test(native): host CMake build + CI for native C++ engine tests (#78)#81
Merged
Conversation
) The native engine (app/src/main/jni) does the real gesture/dictionary/geometry work, but its gtest suite (tests/) only had an AOSP-platform-build runner (run-tests.sh / HostUnitTests.mk via mmm/lunch/BUILD_HOST_NATIVE_TEST) that cannot run in gradle/NDK CI. So the engine had ZERO automated coverage — only on-device manual testing caught a recognizer/dictionary regression. Add a standalone host build: - app/src/main/jni/CMakeLists.txt — compiles the engine core + the existing gtest suite + GoogleTest (FetchContent) into a host executable. Excludes the JNI bridge (needs jni.h at link); pulls JDK jni.h headers via find_package(JNI) (or -DLATINIME_JNI_INCLUDE for local builds). No AOSP tree needed. - host_test_compat.h — force-included for the host build only, supplying the few standard headers (climits/cstdint/...) modern g++ wants but the AOSP clang pulled transitively. Shared sources untouched (they build fine under the NDK). - .github/workflows/native-tests.yml — ubuntu + setup-java + cmake + ctest, run on changes to app/src/main/jni/**. Verified locally (WSL g++13): 66 tests build and run, 65 pass. The 1 failure (FormatUtilsTest.TestDetectFormatVersion) is a host-toolchain anomaly in code that works on-device, quarantined from the gate and tracked in #80 — the harness catching it on first run is the point: it reaches code the JVM tests cannot. Deliverable 1 of #78 (native engine tests in CI). Deliverable 2 (gesture-replay test over recorded TraceRecorder fixtures) follows — it needs on-device-recorded trace fixtures.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #78 (deliverable 1: native engine tests in CI).
Problem
The native C++ engine (
app/src/main/jni) does the real gesture / dictionary / geometry work, but its existing gtest suite (tests/, ~20 files) only had an AOSP-platform-build runner (run-tests.sh/HostUnitTests.mkviammm/lunch/BUILD_HOST_NATIVE_TEST) that needs a full Android platform checkout — it cannot run in gradle/NDK CI. Result: the engine had zero automated coverage; only on-device manual testing caught a recognizer/dictionary regression. This is the long-standing gap from AGENTS.md.Change — a standalone host build (no AOSP tree)
app/src/main/jni/CMakeLists.txt— compiles the engine core + the existing gtest suite + GoogleTest (FetchContent) into a host executable. Excludes the JNI bridge (com_android_*/jni_common); getsjni.hfrom a JDK viafind_package(JNI)(CI usessetup-java; local builds can pass-DLATINIME_JNI_INCLUDE).host_test_compat.h— force-included for the host build only, supplying the standard headers (climits/cstdint/…) modern g++ wants but AOSP's older clang pulled transitively. Shared sources untouched (they compile fine under the NDK for the app)..github/workflows/native-tests.yml— ubuntu + setup-java + cmake + ctest, triggered on changes toapp/src/main/jni/**. (This PR touchesjni/**, so the workflow runs here — watch it go green.)Verification
Built + ran locally (WSL, g++ 13): 66 tests build and run, 65 pass.
The 1 failure —
FormatUtilsTest.TestDetectFormatVersion— is a host-toolchain anomaly in code that works on-device (the suite had never run in CI, so it was latently host-incompatible). It's quarantined from the gate (ctest -E) and tracked in #80. The harness catching it on first run is exactly the point — it reaches engine code the JVM/Robolectric tests cannot.Follow-up (deliverable 2 of #78)
The gesture-replay test — load recorded
TraceRecorder(#20) fixtures, feed theInputPointers+geometry through the recognizer, assert top suggestion == recorded word — is the next piece. It needs on-device-recorded trace fixtures first, so it's a natural follow-up.