Migration contract: Phase-1 test suite + CI (issues #7, #8) - #20
Merged
Conversation
…oved, NDK 27.0, build-tools 36.1.0, Java 11)
…EADME build guide + local.properties.example
…ative lib loads in-place from APK on-device
…) + native running-flag race fix - spa2/build.gradle: testInstrumentationRunner, unit testOptions (includeAndroidResources, maxHeapSize), junit/robolectric/androidx-test deps. Robolectric pinned to 4.17-beta-4 (bundles ASM 9.10.1) so unit tests run under JDK 26 without 'Unsupported class file major version 70'. - regrep.cpp: Context::start() now sets running=true under the mutex before spawning the worker (and clears it if thread creation throws). Previously report() could briefly return 'not running' with stale matchCount=0 after startThread(), racing the UI/test threads.
…tive tests green)
- Robolectric unit tests under spa2/src/test: InfraSmokeTest, Alphabet,
StringDecoder, StatefulDecoder, CislaConv, Morse, Mobil, PolskyKriz,
SubstituceAdapters, FrekvExpListAdapter. Corrected expectations to
spec behavior where noted in-test (PismenaC zero-count merge, DelkyC
'2, 4' merge, semafor 48/80 with pref_sem_num off, roman zero).
- Instrumented RegExpNativeTest under spa2/src/androidTest: matchesWord
on raw/en.canon ('^aardvark:'), noMatches, missingAssetFails
('Can't open asset'). Uses decompressed asset name (packaging strips
.gz); pattern must resolve exactly one line.
- Verified: testDebugUnitTest 68/0, connectedDebugAndroidTest 3/0 on
Pixel 9 Pro XL - 17.
…rumented tests green) - AppSmokeTest: SplashActivity→MainActivity transition (startActivitySync + ActivityMonitor) + each of the 12 cipher activities reaches RESUMED. - RegExpNativeTest.switchDictionaryReplacesResults: run '^aardvark:' on en.canon (1 match) then '^sifry:' on cs.canon (2 matches: sifry/Sifry), proving the startThread(fn) dict switch replaces prior results. - moveToState(RESUMED) after ActivityScenario.launch to avoid the CREATED->RESUMED race; splash covered via startActivitySync since it self-stops when MainActivity opens on top. - Verified on-device: 6/6 green, 0 failures, 0 errors.
- .github/workflows/build.yml: JDK 17 matrix, Android SDK (android-35, build-tools 36.1.0, ndk 27.0.12077973, cmake 3.22.1), runs :spa2:testDebugUnitTest (Tier 1+2) and :spa2:assembleDebug (native libregrep) on every push/PR; NDK/CMake + Gradle cached; uploads test reports. Robolectric 4.17-beta-4 pin is the AGP/JDK-sensitive checkpoint. - README: document the 3-tier split — Tier 3 instrumented tests stay on the physical Pixel locally (no managed device / Firebase Test Lab yet).
There was a problem hiding this comment.
🟡 Changes recommended
CI workflow error-masking and an instrumented test flakiness risk should be addressed to keep the “migration contract” reliable.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Implements the “migration contract” for SPA2 by introducing a tiered Phase-1 test suite (JVM + Robolectric + on-device instrumented) and adding GitHub Actions CI to run Tier 1+2 plus assembleDebug with a pinned Android toolchain, while also addressing a native regrep running-flag race.
Changes:
- Added Tier-1/2 JVM+Robolectric tests across multiple cipher/decoder components, plus Tier-3 instrumented tests for native PCRE-backed regex search and app activity smoke coverage.
- Added GitHub Actions workflow to run unit tests and build APK on every push/PR using the pinned SDK/NDK/CMake toolchain.
- Updated module build configuration/toolchain settings and bumped app versionCode/versionName in the manifest.
File summaries
| File | Description |
|---|---|
spa2/src/test/java/cz/absolutno/sifry/tabulky/polsky/PolskyKrizDecoderTest.java |
Adds JVM coverage for Polish cross-table decoder variants and locale behavior. |
spa2/src/test/java/cz/absolutno/sifry/tabulky/mobil/MobilDecoderTest.java |
Adds JVM tests for mobile keypad decoder encode/decode and accessors. |
spa2/src/test/java/cz/absolutno/sifry/substituce/SubstituceAdaptersTest.java |
Adds Robolectric tests for substitution cipher adapters. |
spa2/src/test/java/cz/absolutno/sifry/morse/MorseDecoderTest.java |
Adds Robolectric tests for Morse decoder mappings and encode/decode tuples. |
spa2/src/test/java/cz/absolutno/sifry/InfraSmokeTest.java |
Adds Robolectric smoke tests for App initialization and resource-backed decoding. |
spa2/src/test/java/cz/absolutno/sifry/frekvence/FrekvExpListAdapterTest.java |
Adds Robolectric tests for frequency adapter grouping/child structure. |
spa2/src/test/java/cz/absolutno/sifry/common/decoder/StringDecoderTest.java |
Adds Robolectric tests for resource-driven string decoder parsing/behavior. |
spa2/src/test/java/cz/absolutno/sifry/common/decoder/StatefulDecoderTest.java |
Adds Robolectric tests for stateful decoders (semafor/braille) including prefs-driven paths. |
spa2/src/test/java/cz/absolutno/sifry/common/alphabet/AlphabetTest.java |
Adds JVM tests for alphabet variants and locale-sensitive digraph parsing (CH). |
spa2/src/test/java/cz/absolutno/sifry/cisla/CislaConvTest.java |
Adds JVM tests for numeric conversion utilities (perm/roman/binary/ternary). |
spa2/src/main/cpp/regrep.cpp |
Fixes native running-flag synchronization around worker thread spawn. |
spa2/src/main/AndroidManifest.xml |
Updates app versionCode/versionName to 40000 / 4.0.0. |
spa2/src/androidTest/java/cz/absolutno/sifry/regexp/RegExpNativeTest.java |
Adds instrumented tests for native regex search and dictionary switching. |
spa2/src/androidTest/java/cz/absolutno/sifry/AppSmokeTest.java |
Adds instrumented smoke coverage for Splash→Main and cipher activity rendering. |
spa2/build.gradle |
Adds test dependencies/options, pins build tools/NDK/CMake, configures instrumentation runner. |
README.md |
Documents build requirements, tiered testing strategy, and CI scope/toolchain. |
local.properties.example |
Provides an example SDK path configuration file for local builds. |
gradle/wrapper/gradle-wrapper.properties |
Bumps Gradle wrapper distribution to 9.7.1. |
gradle.properties |
Removes android.enableJetifier setting; keeps non-transitive R classes. |
build.gradle |
Updates AGP version to 9.4.0. |
.github/workflows/build.yml |
Adds CI workflow for Tier 1+2 unit tests and debug APK build with pinned SDK components. |
Review details
- Files reviewed: 20/21 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
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.
Migration contract — Phase-1 test suite + CI (issues #7, #8)
Brings
masterforward from the pre-migration (new-regex) state throughthe migration steps to the current stack (app 4.0.0 / 40000, Gradle
9.7.1, AGP 9.4, JDK 17+ validated on 17/26, compileSdk/targetSdk 35,
NDK 27.0.12077973, CMake 3.22.1, build-tools 36.1.0).
What this adds
Tiered test suite — issue #7
decoders, converter, adapters, state machine (incl. spec-corrected
expectations). Robolectric pinned
4.17-beta-4(ASM 9.10.1) so it runson JDK 26; verified green on JDK 17 and 26.
RegExpNativeTest(4 — nativePCRE-backed search incl. new cs↔en
switchDictionaryReplacesResults)and
AppSmokeTest(2 — splash→main, all 12 cipher activities reachRESUMED). Ran on physical Pixel: 6 tests / 0 failures / 0 errors.
regrep.cpp:runningflag set under the progressmutex before thread spawn (spawn failure resets it) — removes the
race where a completed search left
getRunning()true.CI — issue #8
.github/workflows/build.yml: every push/PR runs Tier 1+2 +assembleDebugunder JDK 17 with the exact pinned SDK toolchain(platform android-35, build-tools 36.1.0, ndk 27.0.12077973,
cmake 3.22.1); Gradle + NDK/CMake cached; test reports uploaded.
52141FDAS001QF):GitHub runners can't host devices; Managed/Firebase Test Lab deferred.
as later steps land.
Verification
adb install -r+ launch:topResumedActivity=...#MainActivity,0 FATAL.
phase-1-tests@49b0c0cpush-top.Expected noise
Master and this branch diverged before the migration began (
new-regex),so the PR diff is large by design: it is the whole migration applied.