mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
Inspector parses uses-permission entries from `aapt dump permissions` and the granter shells out to `adb shell pm grant`. Both are pluggable so tests can drive logic without aapt or a device. Granter failures become warnings rather than errors — Android refuses non-runtime permissions and we'd rather keep going than abort the run.
128 lines
3.9 KiB
Go
128 lines
3.9 KiB
Go
package permissions
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"slices"
|
|
"testing"
|
|
)
|
|
|
|
func TestGrantDangerous_FiltersAndCallsGranter(t *testing.T) {
|
|
declared := []string{
|
|
"android.permission.INTERNET", // not dangerous
|
|
"android.permission.CAMERA", // dangerous
|
|
"android.permission.WAKE_LOCK", // not dangerous
|
|
"android.permission.ACCESS_FINE_LOCATION", // dangerous
|
|
"android.permission.READ_EXTERNAL_STORAGE", // dangerous
|
|
"android.permission.SYSTEM_ALERT_WINDOW", // not dangerous
|
|
}
|
|
inspector := func(_ context.Context, _ string) ([]string, error) { return declared, nil }
|
|
var requested []string
|
|
granter := func(_ context.Context, packageName, permission string) error {
|
|
if packageName != "com.example" {
|
|
t.Errorf("granter received wrong package: %q", packageName)
|
|
}
|
|
requested = append(requested, permission)
|
|
return nil
|
|
}
|
|
|
|
granted, warnings, err := GrantDangerous(context.Background(), "/path/to/apk", "com.example", inspector, granter)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := []string{
|
|
"android.permission.CAMERA",
|
|
"android.permission.ACCESS_FINE_LOCATION",
|
|
"android.permission.READ_EXTERNAL_STORAGE",
|
|
}
|
|
if !slices.Equal(granted, want) {
|
|
t.Errorf("granted permissions: got %v, want %v", granted, want)
|
|
}
|
|
if !slices.Equal(requested, want) {
|
|
t.Errorf("granter calls: got %v, want %v", requested, want)
|
|
}
|
|
if len(warnings) != 0 {
|
|
t.Errorf("expected no warnings, got %v", warnings)
|
|
}
|
|
}
|
|
|
|
func TestGrantDangerous_CollectsGranterFailuresAsWarnings(t *testing.T) {
|
|
declared := []string{"android.permission.CAMERA", "android.permission.RECORD_AUDIO"}
|
|
inspector := func(_ context.Context, _ string) ([]string, error) { return declared, nil }
|
|
granter := func(_ context.Context, _, permission string) error {
|
|
if permission == "android.permission.CAMERA" {
|
|
return errors.New("device denied")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
granted, warnings, err := GrantDangerous(context.Background(), "/x", "com.example", inspector, granter)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !slices.Equal(granted, []string{"android.permission.RECORD_AUDIO"}) {
|
|
t.Errorf("granted: %v", granted)
|
|
}
|
|
if len(warnings) != 1 || warnings[0] != "android.permission.CAMERA: device denied" {
|
|
t.Errorf("warnings: %v", warnings)
|
|
}
|
|
}
|
|
|
|
func TestGrantDangerous_InspectorErrorBubbles(t *testing.T) {
|
|
inspector := func(_ context.Context, _ string) ([]string, error) {
|
|
return nil, errors.New("aapt missing")
|
|
}
|
|
_, _, err := GrantDangerous(context.Background(), "/x", "com.example", inspector, nil)
|
|
if err == nil || err.Error() == "" {
|
|
t.Errorf("expected wrapped inspector error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestIsDangerous_KnownPermissions(t *testing.T) {
|
|
dangerous := []string{
|
|
"android.permission.CAMERA",
|
|
"android.permission.RECORD_AUDIO",
|
|
"android.permission.POST_NOTIFICATIONS",
|
|
}
|
|
for _, permission := range dangerous {
|
|
if !IsDangerous(permission) {
|
|
t.Errorf("expected %q to be dangerous", permission)
|
|
}
|
|
}
|
|
|
|
normal := []string{
|
|
"android.permission.INTERNET",
|
|
"android.permission.WAKE_LOCK",
|
|
"android.permission.SYSTEM_ALERT_WINDOW",
|
|
}
|
|
for _, permission := range normal {
|
|
if IsDangerous(permission) {
|
|
t.Errorf("expected %q not to be dangerous", permission)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAaptInspector_ParsesFixtureOutput(t *testing.T) {
|
|
// Direct test of the regex; avoids spawning aapt.
|
|
output := `
|
|
package: com.example
|
|
sdkVersion:'24'
|
|
uses-permission: name='android.permission.INTERNET'
|
|
uses-permission: name='android.permission.CAMERA'
|
|
uses-permission: name='android.permission.WAKE_LOCK'
|
|
`
|
|
matches := aaptPermissionPattern.FindAllStringSubmatch(output, -1)
|
|
got := make([]string, 0, len(matches))
|
|
for _, match := range matches {
|
|
got = append(got, match[1])
|
|
}
|
|
want := []string{
|
|
"android.permission.INTERNET",
|
|
"android.permission.CAMERA",
|
|
"android.permission.WAKE_LOCK",
|
|
}
|
|
if !slices.Equal(got, want) {
|
|
t.Errorf("got %v, want %v", got, want)
|
|
}
|
|
}
|