Skip to content

Commit a16fa0d

Browse files
xaionaro@dx.centerxaionaro@dx.center
authored andcommitted
tests: add E2E tests for all ndkcli commands
35 test functions that execute ndkcli subcommands on an Android device and verify output. Covers: camera, audio record/play, sensors, thermal, EGL, GLES2/3, media codecs, config, font, permission, trace, log, NNAPI, looper, window, storage, binder. The runner script now also builds and pushes the ndkcli binary.
1 parent 86fb55a commit a16fa0d

2 files changed

Lines changed: 226 additions & 2 deletions

File tree

tests/e2e/ndkcli_test.go

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
//go:build e2e
2+
3+
// E2E tests for ndkcli commands running on an Android device.
4+
//
5+
// These tests execute ndkcli subcommands as subprocesses and verify
6+
// their output. The ndkcli binary must be pre-built and available
7+
// at the path specified by the NDKCLI_BIN environment variable
8+
// (default: /data/local/tmp/ndkcli).
9+
package main
10+
11+
import (
12+
"os"
13+
"os/exec"
14+
"strings"
15+
"testing"
16+
17+
"github.com/stretchr/testify/assert"
18+
"github.com/stretchr/testify/require"
19+
)
20+
21+
func ndkcliBin() string {
22+
if bin := os.Getenv("NDKCLI_BIN"); bin != "" {
23+
return bin
24+
}
25+
return "/data/local/tmp/ndkcli"
26+
}
27+
28+
func runNdkcli(
29+
t *testing.T,
30+
args ...string,
31+
) (string, error) {
32+
t.Helper()
33+
cmd := exec.Command(ndkcliBin(), args...)
34+
out, err := cmd.CombinedOutput()
35+
return string(out), err
36+
}
37+
38+
func requireNdkcli(
39+
t *testing.T,
40+
args ...string,
41+
) string {
42+
t.Helper()
43+
out, err := runNdkcli(t, args...)
44+
require.NoError(t, err, "ndkcli %s failed: %s", strings.Join(args, " "), out)
45+
return out
46+
}
47+
48+
func TestNdkcli_Help(t *testing.T) {
49+
out := requireNdkcli(t, "--help")
50+
assert.Contains(t, out, "ndkcli")
51+
assert.Contains(t, out, "camera")
52+
assert.Contains(t, out, "audio")
53+
assert.Contains(t, out, "sensor")
54+
}
55+
56+
func TestNdkcli_CameraManagerCameraIDList(t *testing.T) {
57+
out, err := runNdkcli(t, "camera", "manager", "camera-id-list")
58+
// May fail on emulator without camera permission, but should not crash.
59+
t.Logf("camera manager camera-id-list: err=%v output=%q", err, out)
60+
}
61+
62+
func TestNdkcli_CameraListDetails(t *testing.T) {
63+
out, err := runNdkcli(t, "camera", "list-details")
64+
t.Logf("camera list-details: err=%v output=%q", err, out)
65+
}
66+
67+
func TestNdkcli_AudioStreamBuilderNew(t *testing.T) {
68+
out := requireNdkcli(t, "audio", "stream-builder", "new")
69+
assert.Contains(t, out, "created successfully")
70+
}
71+
72+
func TestNdkcli_AudioRecord(t *testing.T) {
73+
out, err := runNdkcli(t, "audio", "record",
74+
"--output", "/data/local/tmp/ndkcli_test.pcm",
75+
"--duration", "1s",
76+
"--sample-rate", "44100",
77+
"--channels", "1",
78+
)
79+
t.Logf("audio record: err=%v output=%q", err, out)
80+
// Cleanup.
81+
os.Remove("/data/local/tmp/ndkcli_test.pcm")
82+
}
83+
84+
func TestNdkcli_SensorRead(t *testing.T) {
85+
out, err := runNdkcli(t, "sensor", "read", "--type", "1", "--duration", "1s")
86+
t.Logf("sensor read: err=%v output=%q", err, out)
87+
}
88+
89+
func TestNdkcli_SensorManagerDefaultSensor(t *testing.T) {
90+
out, err := runNdkcli(t, "sensor", "manager", "default-sensor", "--value", "1")
91+
t.Logf("sensor manager default-sensor: err=%v output=%q", err, out)
92+
}
93+
94+
func TestNdkcli_ThermalManagerCurrentStatus(t *testing.T) {
95+
out := requireNdkcli(t, "thermal", "manager", "current-status")
96+
t.Logf("thermal status: %q", out)
97+
}
98+
99+
func TestNdkcli_ThermalMonitor(t *testing.T) {
100+
out, err := runNdkcli(t, "thermal", "monitor", "--interval", "500ms", "--duration", "1s")
101+
t.Logf("thermal monitor: err=%v output=%q", err, out)
102+
}
103+
104+
func TestNdkcli_EGLInfo(t *testing.T) {
105+
out := requireNdkcli(t, "egl", "info")
106+
assert.Contains(t, out, "Vendor", "EGL info should contain Vendor")
107+
t.Logf("egl info:\n%s", out)
108+
}
109+
110+
func TestNdkcli_EGLConfigs(t *testing.T) {
111+
out, err := runNdkcli(t, "egl", "configs")
112+
t.Logf("egl configs: err=%v output=%q", err, out)
113+
}
114+
115+
func TestNdkcli_GLES2Info(t *testing.T) {
116+
out := requireNdkcli(t, "gles2", "info")
117+
assert.Contains(t, out, "GL_VERSION", "gles2 info should contain GL_VERSION")
118+
t.Logf("gles2 info:\n%s", out)
119+
}
120+
121+
func TestNdkcli_GLES3Info(t *testing.T) {
122+
out, err := runNdkcli(t, "gles3", "info")
123+
t.Logf("gles3 info: err=%v output=%q", err, out)
124+
}
125+
126+
func TestNdkcli_MediaCodecs(t *testing.T) {
127+
out := requireNdkcli(t, "media", "codecs")
128+
assert.Contains(t, out, "video/avc", "should probe H.264")
129+
t.Logf("media codecs:\n%s", out)
130+
}
131+
132+
func TestNdkcli_MediaNewEncoder(t *testing.T) {
133+
out, err := runNdkcli(t, "media", "new-encoder", "--mime_type", "video/avc")
134+
t.Logf("media new-encoder: err=%v output=%q", err, out)
135+
}
136+
137+
func TestNdkcli_MediaNewDecoder(t *testing.T) {
138+
out, err := runNdkcli(t, "media", "new-decoder", "--mime_type", "video/avc")
139+
t.Logf("media new-decoder: err=%v output=%q", err, out)
140+
}
141+
142+
func TestNdkcli_ConfigShow(t *testing.T) {
143+
out := requireNdkcli(t, "config", "show")
144+
assert.Contains(t, out, "Density", "config show should contain Density")
145+
t.Logf("config show:\n%s", out)
146+
}
147+
148+
func TestNdkcli_ConfigDensity(t *testing.T) {
149+
out := requireNdkcli(t, "config", "config", "density")
150+
t.Logf("config density: %q", out)
151+
}
152+
153+
func TestNdkcli_ConfigSdkVersion(t *testing.T) {
154+
out := requireNdkcli(t, "config", "config", "sdk-version")
155+
t.Logf("config sdk-version: %q", out)
156+
}
157+
158+
func TestNdkcli_FontMatch(t *testing.T) {
159+
out, err := runNdkcli(t, "font", "match", "--family", "sans-serif", "--weight", "400")
160+
t.Logf("font match: err=%v output=%q", err, out)
161+
}
162+
163+
func TestNdkcli_PermissionCheck(t *testing.T) {
164+
out, err := runNdkcli(t, "permission", "check",
165+
"--name", "android.permission.CAMERA",
166+
"--pid", "1000", "--uid", "1000",
167+
)
168+
t.Logf("permission check: err=%v output=%q", err, out)
169+
}
170+
171+
func TestNdkcli_TraceIsEnabled(t *testing.T) {
172+
out := requireNdkcli(t, "trace", "is-enabled")
173+
t.Logf("trace is-enabled: %q", out)
174+
}
175+
176+
func TestNdkcli_TraceBeginEndSection(t *testing.T) {
177+
out := requireNdkcli(t, "trace", "begin-section", "--section-name", "test_section")
178+
t.Logf("trace begin-section: %q", out)
179+
180+
out = requireNdkcli(t, "trace", "end-section")
181+
t.Logf("trace end-section: %q", out)
182+
}
183+
184+
func TestNdkcli_TraceSetCounter(t *testing.T) {
185+
out := requireNdkcli(t, "trace", "set-counter", "--counter-name", "test_counter", "--counter-value", "42")
186+
t.Logf("trace set-counter: %q", out)
187+
}
188+
189+
func TestNdkcli_LogWrite(t *testing.T) {
190+
out := requireNdkcli(t, "log", "write", "--tag", "ndktest", "--message", "e2e test", "--priority", "4")
191+
t.Logf("log write: %q", out)
192+
}
193+
194+
func TestNdkcli_NnapiProbe(t *testing.T) {
195+
out, err := runNdkcli(t, "nnapi", "probe")
196+
t.Logf("nnapi probe: err=%v output=%q", err, out)
197+
}
198+
199+
func TestNdkcli_LooperTest(t *testing.T) {
200+
out, err := runNdkcli(t, "looper", "test")
201+
t.Logf("looper test: err=%v output=%q", err, out)
202+
}
203+
204+
func TestNdkcli_WindowQuery(t *testing.T) {
205+
out, err := runNdkcli(t, "window", "query")
206+
t.Logf("window query: err=%v output=%q", err, out)
207+
}
208+
209+
func TestNdkcli_StorageObb(t *testing.T) {
210+
out, err := runNdkcli(t, "storage", "obb", "--file", "/nonexistent.obb")
211+
t.Logf("storage obb: err=%v output=%q", err, out)
212+
}
213+
214+
func TestNdkcli_BinderprocessStartThreadPool(t *testing.T) {
215+
out, err := runNdkcli(t, "binderprocess", "start-thread-pool")
216+
t.Logf("binderprocess start-thread-pool: err=%v output=%q", err, out)
217+
}

tests/e2e/run-examples-test.sh

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,21 @@ fi
4040
cd "$PROJECT_DIR"
4141

4242
BIN="/tmp/examples_e2e.test"
43+
NDKCLI_BIN="/tmp/ndkcli"
4344

4445
echo "=== Cross-compiling examples E2E test binary (android/amd64) ==="
4546
CGO_ENABLED=1 GOOS=android GOARCH=amd64 CC="$CC" \
4647
go test -c -tags e2e -o "$BIN" ./tests/e2e/
4748

49+
echo "=== Cross-compiling ndkcli (android/amd64) ==="
50+
CGO_ENABLED=1 GOOS=android GOARCH=amd64 CC="$CC" \
51+
go build -o "$NDKCLI_BIN" ./cmd/ndkcli/
52+
4853
echo "=== Pushing to device ==="
4954
"$ADB" push "$BIN" /data/local/tmp/examples_e2e.test >/dev/null 2>&1
55+
"$ADB" push "$NDKCLI_BIN" /data/local/tmp/ndkcli >/dev/null 2>&1
5056
"$ADB" shell chmod 755 /data/local/tmp/examples_e2e.test
57+
"$ADB" shell chmod 755 /data/local/tmp/ndkcli
5158

5259
echo "=== Running tests ==="
5360
OUTPUT=$("$ADB" shell "timeout $TIMEOUT /data/local/tmp/examples_e2e.test -test.v 2>&1; echo EXIT=\$?" 2>&1)
@@ -56,8 +63,8 @@ echo "$OUTPUT"
5663
EXIT_CODE=$(echo "$OUTPUT" | grep -oP 'EXIT=\K\d+' | tail -1)
5764

5865
# Cleanup.
59-
"$ADB" shell rm -f /data/local/tmp/examples_e2e.test 2>/dev/null || true
60-
rm -f "$BIN" 2>/dev/null || true
66+
"$ADB" shell rm -f /data/local/tmp/examples_e2e.test /data/local/tmp/ndkcli 2>/dev/null || true
67+
rm -f "$BIN" "$NDKCLI_BIN" 2>/dev/null || true
6168

6269
if [ "${EXIT_CODE:-1}" = "0" ]; then
6370
echo "=== PASS: examples E2E tests ==="

0 commit comments

Comments
 (0)