Skip to content

Commit fe34460

Browse files
xaionaro@dx.centerxaionaro@dx.center
authored andcommitted
feat: split E2E tests into e2e and e2e_root tiers, fix service names
Split the E2E test suite into two build-tag tiers: - `e2e` — normal tests running as shell (UID 2000) - `e2e_root` — tests requiring root + permissive SELinux Moved 15 root-requiring tests (WiFi scanner, keystore, notifications, device policy, system update, netd OEM network) to usecase_root_test.go with a separate TestMain in root_main_test.go that requires UID 0. Fixed service name constants: DreamService "dream" -> "dreams", EuiccService "euicc" -> "econtroller" (matching actual binder registrations vs incorrect android.content.Context constants). Fixed netd tests to use AIDL HAL name "android.system.net.netd.INetd/default" instead of inaccessible framework "netd" service. Converted sequential method calls in NetworkMonitor and AttestationVerify to subtests so API-36-removed methods skip independently without blocking passing tests. Result: e2e tier drops from 26 skips to 3 (all legitimate: emulator-only factory reset, API 36 removed method, transient BLE). Root tier passes 12/15 tests (3 HAL-level skips on this device).
1 parent c012349 commit fe34460

16 files changed

Lines changed: 476 additions & 289 deletions

servicemanager/service_names_gen.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

specs/servicemanager/spec.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@ services:
168168
- service_name: download
169169
constant_name: DOWNLOAD_SERVICE
170170
descriptor: ""
171-
- service_name: dream
171+
- service_name: dreams
172172
constant_name: DREAM_SERVICE
173-
descriptor: ""
173+
descriptor: android.service.dreams.IDreamManager
174174
- service_name: dropbox
175175
constant_name: DROPBOX_SERVICE
176176
descriptor: com.android.internal.os.IDropBoxManagerService
@@ -183,9 +183,9 @@ services:
183183
- service_name: ethernet
184184
constant_name: ETHERNET_SERVICE
185185
descriptor: ""
186-
- service_name: euicc
186+
- service_name: econtroller
187187
constant_name: EUICC_SERVICE
188-
descriptor: ""
188+
descriptor: com.android.internal.telephony.euicc.IEuiccController
189189
- service_name: euicc_card
190190
constant_name: EUICC_CARD_SERVICE
191191
descriptor: ""

tests/e2e/bindercli_test.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build e2e
1+
//go:build e2e && !e2e_root
22

33
package e2e
44

@@ -37,12 +37,6 @@ var emulatorSerial string
3737
// so cleanup only kills it if we own it.
3838
var emulatorStartedByTest bool
3939

40-
// onDevice reports whether the test binary is running directly on an
41-
// Android device (i.e. /dev/binder is accessible). When true, the
42-
// emulator/adb setup is skipped — on-device tests open /dev/binder
43-
// directly, and bindercli tests exec the binary directly.
44-
var onDevice bool
45-
4640
// bindercliAvailable is true when the bindercli binary exists at
4741
// deviceBinary. On-device, this requires the binary to have been
4842
// pushed separately; on-host it is built and pushed by TestMain.

tests/e2e/bluetooth_gatt_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build e2e
1+
//go:build e2e || e2e_root
22

33
package e2e
44

tests/e2e/camera_capture_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build e2e
1+
//go:build e2e || e2e_root
22

33
package e2e
44

tests/e2e/concurrent_stress_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build e2e
1+
//go:build e2e || e2e_root
22

33
package e2e
44

tests/e2e/e2e_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build e2e
1+
//go:build e2e || e2e_root
22

33
package e2e
44

@@ -22,6 +22,12 @@ import (
2222
"github.com/AndroidGoLab/binder/servicemanager"
2323
)
2424

25+
// onDevice reports whether the test binary is running directly on an
26+
// Android device (i.e. /dev/binder is accessible). When true, the
27+
// emulator/adb setup is skipped — on-device tests open /dev/binder
28+
// directly, and bindercli tests exec the binary directly.
29+
var onDevice bool
30+
2531
// cachedBinder provides a shared binder connection with auto-recovery.
2632
// The connection is refreshed every maxTestsPerConnection tests to
2733
// prevent accumulated state from degrading performance. A watchdog

tests/e2e/exceptions_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build e2e
1+
//go:build e2e || e2e_root
22

33
package e2e
44

tests/e2e/root_main_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//go:build e2e_root
2+
3+
package e2e
4+
5+
import (
6+
"os"
7+
"testing"
8+
)
9+
10+
func TestMain(m *testing.M) {
11+
// Root tests REQUIRE UID 0 (adb root) and permissive SELinux
12+
// (setenforce 0) to bypass service_manager restrictions for HALs
13+
// and privileged system services.
14+
//
15+
// WARNING: These tests intentionally skip the root-refusal guard in
16+
// bindercli_test.go. Only read-only queries are performed — no
17+
// destructive operations (e.g. DeleteAllKeys, WipeData) are called.
18+
// Review every new root test for safety before adding it here.
19+
if os.Getuid() != 0 {
20+
os.Stderr.WriteString("FATAL: e2e_root tests require root (UID 0).\n")
21+
os.Stderr.WriteString("Run: adb root && adb shell setenforce 0\n")
22+
os.Stderr.WriteString("Then push and execute the e2e_root binary.\n")
23+
os.Exit(1)
24+
}
25+
26+
if _, err := os.Stat("/dev/binder"); err != nil {
27+
os.Stderr.WriteString("FATAL: /dev/binder not found — must run on device.\n")
28+
os.Exit(1)
29+
}
30+
31+
onDevice = true
32+
os.Exit(m.Run())
33+
}

tests/e2e/usecase_camera_bluetooth_test.go

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build e2e
1+
//go:build e2e || e2e_root
22

33
package e2e
44

@@ -30,7 +30,6 @@ import (
3030
genLE "github.com/AndroidGoLab/binder/android/bluetooth/le"
3131
"github.com/AndroidGoLab/binder/android/content"
3232
fwkService "github.com/AndroidGoLab/binder/android/frameworks/cameraservice/service"
33-
"github.com/AndroidGoLab/binder/android/hardware"
3433
genOs "github.com/AndroidGoLab/binder/android/os"
3534
"github.com/AndroidGoLab/binder/binder"
3635
"github.com/AndroidGoLab/binder/binder/versionaware"
@@ -110,25 +109,8 @@ func TestUseCase22_FlashlightTorch(t *testing.T) {
110109
// Clean up listener registration.
111110
_ = fwkCam.RemoveListener(ctx, listener)
112111

113-
t.Run("SetTorchMode", func(t *testing.T) {
114-
// Torch control requires the media.camera service. Create a
115-
// properly registered client token (same pattern as the
116-
// flashlight_torch example).
117-
mediaSvc, err := sm.GetService(ctx, servicemanager.MediaCameraService)
118-
requireOrSkip(t, err)
119-
cam := hardware.NewCameraServiceProxy(mediaSvc)
120-
121-
token := binder.NewStubBinder(&torchClientToken{})
122-
token.RegisterWithTransport(ctx, transport)
123-
124-
err = cam.SetTorchMode(ctx, cameras[0].CameraId, true, token)
125-
requireOrSkip(t, err)
126-
t.Log("Torch ON")
127-
128-
err = cam.SetTorchMode(ctx, cameras[0].CameraId, false, token)
129-
requireOrSkip(t, err)
130-
t.Log("Torch OFF")
131-
})
112+
// SetTorchMode subtest moved to usecase_root_test.go — requires root
113+
// to bypass media.camera SELinux restrictions (kernel status -61).
132114
}
133115

134116
// torchClientToken is a minimal TransactionReceiver used as the client
@@ -205,22 +187,8 @@ func TestUseCase23_CameraAvailability(t *testing.T) {
205187
}
206188
})
207189

208-
t.Run("GetCameraCharacteristics", func(t *testing.T) {
209-
listener := fwkService.NewCameraServiceListenerStub(&noopCameraServiceListener{})
210-
cameras, err := fwkCam.AddListener(ctx, listener)
211-
requireOrSkip(t, err)
212-
defer func() { _ = fwkCam.RemoveListener(ctx, listener) }()
213-
214-
if len(cameras) == 0 {
215-
t.Skip("no cameras available")
216-
}
217-
218-
chars, err := fwkCam.GetCameraCharacteristics(ctx, cameras[0].CameraId)
219-
requireOrSkip(t, err)
220-
t.Logf("Camera %q characteristics: %d bytes of metadata",
221-
cameras[0].CameraId, len(chars.Metadata))
222-
assert.Greater(t, len(chars.Metadata), 0, "expected non-empty camera metadata")
223-
})
190+
// GetCameraCharacteristics subtest moved to usecase_root_test.go —
191+
// returns HAL ServiceSpecific error as shell.
224192
}
225193

226194
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)