Skip to content

Commit f511e28

Browse files
oschwaldclaude
andcommitted
test: Add instrumented tests for GPU, Camera, and Font collectors
Add instrumented tests that run on real Android devices/emulators to verify: - GpuCollector: EGL context creation, renderer/vendor info, resource cleanup - CameraCollector: Camera2 API access, facing values, repeated calls - FontCollector: Typeface detection, standard fonts, consistency These tests require actual Android APIs and cannot be mocked in unit tests. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent d5448bc commit f511e28

File tree

3 files changed

+192
-0
lines changed

3 files changed

+192
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.maxmind.device.collector
2+
3+
import android.hardware.camera2.CameraCharacteristics
4+
import androidx.test.ext.junit.runners.AndroidJUnit4
5+
import androidx.test.platform.app.InstrumentationRegistry
6+
import org.junit.Assert.assertNotNull
7+
import org.junit.Assert.assertTrue
8+
import org.junit.Test
9+
import org.junit.runner.RunWith
10+
11+
/**
12+
* Instrumented tests for [CameraCollector].
13+
*
14+
* These tests run on an Android device/emulator to verify camera info collection
15+
* using real Camera2 API.
16+
*/
17+
@RunWith(AndroidJUnit4::class)
18+
public class CameraCollectorInstrumentedTest {
19+
20+
@Test
21+
public fun collect_returnsCameraListOrEmpty() {
22+
val context = InstrumentationRegistry.getInstrumentation().targetContext
23+
val collector = CameraCollector(context)
24+
25+
val result = collector.collect()
26+
27+
assertNotNull("Camera list should not be null", result)
28+
// Most devices have at least one camera, but emulators may not
29+
}
30+
31+
@Test
32+
public fun collect_cameraInfoHasValidFacing() {
33+
val context = InstrumentationRegistry.getInstrumentation().targetContext
34+
val collector = CameraCollector(context)
35+
36+
val result = collector.collect()
37+
38+
result.forEach { cameraInfo ->
39+
assertNotNull("Camera ID should not be null", cameraInfo.cameraID)
40+
assertTrue(
41+
"Facing should be FRONT (0), BACK (1), or EXTERNAL (2)",
42+
cameraInfo.facing in listOf(
43+
CameraCharacteristics.LENS_FACING_FRONT,
44+
CameraCharacteristics.LENS_FACING_BACK,
45+
CameraCharacteristics.LENS_FACING_EXTERNAL,
46+
),
47+
)
48+
}
49+
}
50+
51+
@Test
52+
public fun collect_doesNotCrashOnRepeatedCalls() {
53+
val context = InstrumentationRegistry.getInstrumentation().targetContext
54+
val collector = CameraCollector(context)
55+
56+
// Multiple calls should not crash
57+
repeat(3) {
58+
val result = collector.collect()
59+
assertNotNull(result)
60+
}
61+
}
62+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.maxmind.device.collector
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import org.junit.Assert.assertNotNull
5+
import org.junit.Assert.assertTrue
6+
import org.junit.Test
7+
import org.junit.runner.RunWith
8+
9+
/**
10+
* Instrumented tests for [FontCollector].
11+
*
12+
* These tests run on an Android device/emulator to verify font detection
13+
* using real Android Typeface API.
14+
*/
15+
@RunWith(AndroidJUnit4::class)
16+
public class FontCollectorInstrumentedTest {
17+
18+
@Test
19+
public fun collect_returnsFontInfo() {
20+
val collector = FontCollector()
21+
22+
val result = collector.collect()
23+
24+
assertNotNull("Font info should not be null", result)
25+
assertNotNull("Available fonts list should not be null", result.availableFonts)
26+
}
27+
28+
@Test
29+
public fun collect_detectsRobotoFont() {
30+
val collector = FontCollector()
31+
32+
val result = collector.collect()
33+
34+
// Roboto is always available as the default Android font
35+
// FontCollector only tests fonts from its TEST_FONTS list
36+
assertTrue(
37+
"Roboto font should be available (Android default)",
38+
result.availableFonts.contains("Roboto"),
39+
)
40+
}
41+
42+
@Test
43+
public fun collect_returnsNonEmptyFontList() {
44+
val collector = FontCollector()
45+
46+
val result = collector.collect()
47+
48+
assertTrue(
49+
"Available fonts should not be empty",
50+
result.availableFonts.isNotEmpty(),
51+
)
52+
}
53+
54+
@Test
55+
public fun collect_isConsistentAcrossMultipleCalls() {
56+
val collector = FontCollector()
57+
58+
val result1 = collector.collect()
59+
val result2 = collector.collect()
60+
61+
assertTrue(
62+
"Font list should be consistent across calls",
63+
result1.availableFonts == result2.availableFonts,
64+
)
65+
}
66+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.maxmind.device.collector
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import org.junit.Assert.assertTrue
5+
import org.junit.Test
6+
import org.junit.runner.RunWith
7+
8+
/**
9+
* Instrumented tests for [GpuCollector].
10+
*
11+
* These tests run on an Android device/emulator to verify GPU info collection
12+
* using real EGL contexts.
13+
*/
14+
@RunWith(AndroidJUnit4::class)
15+
public class GpuCollectorInstrumentedTest {
16+
17+
@Test
18+
public fun collect_returnsGpuInfoOrNullGracefully() {
19+
val collector = GpuCollector()
20+
21+
val result = collector.collect()
22+
23+
// On most devices, GPU info should be available
24+
// On emulators without GPU support, null is acceptable
25+
if (result != null) {
26+
// If we got a result, it should have meaningful data
27+
assertTrue(
28+
"Renderer or vendor should be non-null",
29+
result.renderer != null || result.vendor != null,
30+
)
31+
}
32+
// Test passes whether result is null or non-null
33+
// The key is that it doesn't crash
34+
}
35+
36+
@Test
37+
public fun collect_doesNotCrashOnRepeatedCalls() {
38+
val collector = GpuCollector()
39+
40+
// Multiple calls should not leak EGL resources or crash
41+
repeat(5) {
42+
val result = collector.collect()
43+
// Just verify no crash - result can be null or non-null
44+
}
45+
}
46+
47+
@Test
48+
public fun collect_handlesMultipleCollectorInstances() {
49+
// Verify that multiple collector instances don't interfere
50+
val collector1 = GpuCollector()
51+
val collector2 = GpuCollector()
52+
53+
val result1 = collector1.collect()
54+
val result2 = collector2.collect()
55+
56+
// Results should be consistent (both null or both non-null with same values)
57+
if (result1 != null && result2 != null) {
58+
assertTrue(
59+
"Renderer should be consistent across instances",
60+
result1.renderer == result2.renderer,
61+
)
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)