Java-to-Zig Migration Testing
Prove two separate claims in order:
- the entire source test contract and all test assets were migrated without
loss and Java/Zig observable results match;
- Zig-specific risks have additional valuable tests.
Do not use coverage, target test counts, file counts, or two independently green
suites as proof of migration completion.
Compose with the Zig skill pack
Use $zig-testing for Zig assertions, leak detection, and test syntax;
$zig-build-system for test modules, steps, options, and targets;
$zig-concurrency for deterministic synchronization and race/lifecycle tests;
and $zig-java-migration for the authoritative object and semantic scope. Load
$zig-0.16 or $zig-0.15 according to the pinned repository toolchain.
This skill implements the same source-test contract as
rust-java-migration-testing and future Kotlin/Swift variants. The invariant
portion must remain equivalent; only target syntax, build integration, and
target-specific obligations may differ. Read
Testing adapter contract before
changing dispositions, manifest fields, or completion rules.
Required ledgers
Maintain three logically separate ledgers:
| Ledger |
Denominator |
Completion rule |
SOURCE_PARITY/TEST_CASE |
every Java test method and every concrete generated/parameterized case |
lossless Zig implementation plus per-case MATCH |
SOURCE_PARITY/TEST_ASSET |
every source fixture/resource/script/corpus/golden/data file |
byte-identical target copy and matching SHA-256 |
ZIG_OBLIGATION |
allocator, lifetime, error, target, ABI, build, concurrency and other target risks |
applicable obligation passes |
VALUE_ADD tests may follow, but never replace a missing source row or Zig
obligation.
Inventory the source suite
Pin the Java and Zig baselines, then inventory:
- JUnit 4/5 test methods;
- parameterized, repeated, dynamic, template, nested, inherited, and generated
cases;
- disabled/ignored tests and their reasons;
- setup, teardown, rules, extensions, temporary directories, clocks, random
seeds, environment, system properties, locale, and time zone;
- test-support modules and helper classes;
- every test fixture, resource, script, corpus, snapshot, and golden file;
- external services, containers, native libraries, ports, and host assumptions.
A disabled Java test remains in the denominator. It must be implemented and
enabled for migration completion, or remain an explicit blocker.
Use one row per concrete case. Never map parameterized methods only by method
name or compare aggregate test totals.
Source test dispositions
| Disposition |
Meaning |
Complete only when |
MIRRORED |
one Java case maps to one Zig case |
full contract and MATCH |
ADAPTED |
Zig-native harness represents the same contract |
no weaker input/assertion/effect/cleanup and MATCH |
SPLIT |
one Java case maps to multiple Zig tests |
all assertions and case identity preserved |
MERGED_APPROVED |
cases share a data-driven Zig runner |
every case and assertion remains individually traceable |
NOT_APPLICABLE |
source claim considered target-inapplicable |
blocks lossless completion |
BLOCKED |
dependency/oracle prevents execution |
blocks |
MISSING |
no Zig test implementation |
blocks |
The first four also require all preservation flags true, an existing Zig target
test, retained evidence, and Java/Zig result MATCH.
Copy source assets exactly
Copy every source fixture/resource/script/corpus/golden/data file without
editing bytes. Record Java path, Zig path, mode COPY_EXACT, and SHA-256.
Target-normalized or generated files must be separate derivatives and must cite
the immutable source copy.
Do not silently normalize line endings, encodings, JSON/YAML formatting,
timestamps, ordering, locale data, or snapshots while copying.
Whole-project Zig acceptance module
Every repository/product-level completion claim requires:
<project>-test/
├── src/root.zig # reusable harness only
├── tests/source_parity.zig
├── tests/cross_component.zig
└── suite/source/ # byte-identical Java test assets
Register it in the root build.zig with an explicit migration-test step and
run it with:
zig build migration-test
Keep it out of production installation and build.zig.zon publication paths.
It imports public production modules and owns complete source replay,
cross-module/binding workflows, differential execution, and aggregate artifacts.
Local production-module test blocks remain focused subsystem evidence.
The whole-project gate cannot use “at least N passes”, representative cases,
filters, skipped capabilities, or ignored tests. Require every source case
MATCH and failed/skipped/not-run counts of zero.
Implement Zig test contracts
For each Java case preserve:
- exact inputs and boundary values;
- assertion specificity, including exact error category and structured data;
- fixture setup and state;
- observable output, ordering, state transitions, side effects, and calls;
- cleanup on success, error, cancellation, and partial initialization;
- deterministic clock/random/scheduling behavior;
- environment and host assumptions.
Use std.testing.expectEqual, expectEqualStrings, expectError, or more
specific assertions rather than generic success/failure checks. A compile-only
import or try with no observable assertion does not preserve a source test.
Differential verification
Run the complete pinned Java suite and complete Zig suite, then compare every
source case using either:
- pinned Java golden artifacts consumed by Zig; or
- a live harness that invokes both implementations.
Retain raw Java output, raw Zig output, normalized output, and the comparison
report separately. Normalize only documented nondeterminism. Never normalize
error categories, missing/extra fields, numeric precision, contractual order,
side-effect counts, lifecycle transitions, or security-relevant data.
Required outcome:
matched == source_cases
mismatched == 0
harness_failures == 0
skipped == 0
not_run == 0
Use the source parity manifest and run the
audit script described below.
Zig-specific obligations
After source parity, add tests where applicable for:
- allocator ownership and matching free/deinit;
defer and errdefer behavior under every partial failure point;
- borrowed slice/pointer lifetime and aliasing;
- exact error-set and diagnostic behavior;
- integer width, overflow, alignment, endian, and ABI layout;
- comptime branches and generated declarations;
- Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall differences;
- native, cross-compiled, Wasm/WASI, embedded, or mobile targets claimed;
- thread safety, atomics, cancellation, bounded queues, and shutdown;
- JSON unknown/default/null/numeric behavior;
- malformed input, allocation limits, fuzz/property invariants;
- real C library, service, filesystem, network, or host integration.
These are additive. They do not increase the source parity numerator.
Audit workflow
Resolve SKILL_DIR to this skill directory and run:
python3 "$SKILL_DIR/scripts/audit_java_zig_tests.py" \
--java-root ../agentscope-java \
--zig-root ../agentscope-zig \
--parity-manifest docs/source-test-parity.json \
--fail-on-incomplete
The script verifies baselines, every recorded source case, preservation flags,
existing Zig target files, exact source assets, complete run records,
migration-test module registration, and the full differential counts. Static
extraction is conservative and cannot infer semantic mappings; the manifest and
retained artifacts remain required evidence.
Read Verification SOP for schema,
module layout, evidence, and normalizer rules.
Red lines
- Do not exclude, disable, weaken, or merge away source tests to manufacture
parity.
- Do not accept generic “no error” assertions when Java checks exact values,
state, side effects, or error categories.
- Do not edit source assets in place.
- Do not call mirrored tests differential unless Java output participates.
- Do not use test totals, coverage, sampled cases, or two green suites as parity.
- Do not accept leaks, hidden allocator ownership, skipped targets, broad
anyerror, ignored cleanup, or ABI gaps as language-internal details.
- Do not put missing production logic in
<project>-test.
- Do not let local module tests replace whole-project acceptance.
- Do not claim completion with any failed, skipped, ignored, blocked, missing,
mismatched, harness-failed, or not-run case.
Completion criteria
- Every Java test and concrete generated case has a lossless Zig implementation.
- Every source test asset has a byte-identical Zig repository copy and matching
SHA-256.
- Every mapped case preserves inputs, assertions, fixture state, effects, and
cleanup.
- Complete Java and Zig suites pass from pinned baselines.
- Full Java/Zig differential results are 100%
MATCH.
<project>-test is registered under zig build migration-test, excluded from
production publication, and owns aggregate evidence.
- All applicable Zig obligations pass across claimed targets and modes.
- Object-ledger blockers, host gaps, flakes, warnings, and production-readiness
gaps remain visible.
Resources
- Testing adapter contract
- Verification SOP
- Test categories
- Migration test ledger template
- Source parity manifest template
scripts/audit_java_zig_tests.py
1---2name: zig-java-migration-testing3description: Strict Java-to-Zig migration testing and completion firewall. Use when porting Java JUnit tests, parameterized cases, fixtures, resources, scripts, corpora, and golden data to Zig; building Java/Zig differential harnesses; auditing whether source tests were weakened or skipped; creating a whole-project Zig migration-test module; or adding Zig-specific allocator, error, ABI, target, concurrency, fuzz, load, and host tests after source parity.4---56# Java-to-Zig Migration Testing78Prove two separate claims in order:9101. the entire source test contract and all test assets were migrated without11 loss and Java/Zig observable results match;122. Zig-specific risks have additional valuable tests.1314Do not use coverage, target test counts, file counts, or two independently green15suites as proof of migration completion.1617## Compose with the Zig skill pack1819Use `$zig-testing` for Zig assertions, leak detection, and test syntax;20`$zig-build-system` for test modules, steps, options, and targets;21`$zig-concurrency` for deterministic synchronization and race/lifecycle tests;22and `$zig-java-migration` for the authoritative object and semantic scope. Load23`$zig-0.16` or `$zig-0.15` according to the pinned repository toolchain.2425This skill implements the same source-test contract as26`rust-java-migration-testing` and future Kotlin/Swift variants. The invariant27portion must remain equivalent; only target syntax, build integration, and28target-specific obligations may differ. Read29[Testing adapter contract](references/testing-adapter-contract.md) before30changing dispositions, manifest fields, or completion rules.3132## Required ledgers3334Maintain three logically separate ledgers:3536| Ledger | Denominator | Completion rule |37|---|---|---|38| `SOURCE_PARITY/TEST_CASE` | every Java test method and every concrete generated/parameterized case | lossless Zig implementation plus per-case `MATCH` |39| `SOURCE_PARITY/TEST_ASSET` | every source fixture/resource/script/corpus/golden/data file | byte-identical target copy and matching SHA-256 |40| `ZIG_OBLIGATION` | allocator, lifetime, error, target, ABI, build, concurrency and other target risks | applicable obligation passes |4142`VALUE_ADD` tests may follow, but never replace a missing source row or Zig43obligation.4445## Inventory the source suite4647Pin the Java and Zig baselines, then inventory:4849- JUnit 4/5 test methods;50- parameterized, repeated, dynamic, template, nested, inherited, and generated51 cases;52- disabled/ignored tests and their reasons;53- setup, teardown, rules, extensions, temporary directories, clocks, random54 seeds, environment, system properties, locale, and time zone;55- test-support modules and helper classes;56- every test fixture, resource, script, corpus, snapshot, and golden file;57- external services, containers, native libraries, ports, and host assumptions.5859A disabled Java test remains in the denominator. It must be implemented and60enabled for migration completion, or remain an explicit blocker.6162Use one row per concrete case. Never map parameterized methods only by method63name or compare aggregate test totals.6465## Source test dispositions6667| Disposition | Meaning | Complete only when |68|---|---|---|69| `MIRRORED` | one Java case maps to one Zig case | full contract and `MATCH` |70| `ADAPTED` | Zig-native harness represents the same contract | no weaker input/assertion/effect/cleanup and `MATCH` |71| `SPLIT` | one Java case maps to multiple Zig tests | all assertions and case identity preserved |72| `MERGED_APPROVED` | cases share a data-driven Zig runner | every case and assertion remains individually traceable |73| `NOT_APPLICABLE` | source claim considered target-inapplicable | blocks lossless completion |74| `BLOCKED` | dependency/oracle prevents execution | blocks |75| `MISSING` | no Zig test implementation | blocks |7677The first four also require all preservation flags true, an existing Zig target78test, retained evidence, and Java/Zig result `MATCH`.7980## Copy source assets exactly8182Copy every source fixture/resource/script/corpus/golden/data file without83editing bytes. Record Java path, Zig path, mode `COPY_EXACT`, and SHA-256.84Target-normalized or generated files must be separate derivatives and must cite85the immutable source copy.8687Do not silently normalize line endings, encodings, JSON/YAML formatting,88timestamps, ordering, locale data, or snapshots while copying.8990## Whole-project Zig acceptance module9192Every repository/product-level completion claim requires:9394```text95<project>-test/96├── src/root.zig # reusable harness only97├── tests/source_parity.zig98├── tests/cross_component.zig99└── suite/source/ # byte-identical Java test assets100```101102Register it in the root `build.zig` with an explicit `migration-test` step and103run it with:104105```bash106zig build migration-test107```108109Keep it out of production installation and `build.zig.zon` publication paths.110It imports public production modules and owns complete source replay,111cross-module/binding workflows, differential execution, and aggregate artifacts.112Local production-module `test` blocks remain focused subsystem evidence.113114The whole-project gate cannot use “at least N passes”, representative cases,115filters, skipped capabilities, or ignored tests. Require every source case116`MATCH` and failed/skipped/not-run counts of zero.117118## Implement Zig test contracts119120For each Java case preserve:121122- exact inputs and boundary values;123- assertion specificity, including exact error category and structured data;124- fixture setup and state;125- observable output, ordering, state transitions, side effects, and calls;126- cleanup on success, error, cancellation, and partial initialization;127- deterministic clock/random/scheduling behavior;128- environment and host assumptions.129130Use `std.testing.expectEqual`, `expectEqualStrings`, `expectError`, or more131specific assertions rather than generic success/failure checks. A compile-only132import or `try` with no observable assertion does not preserve a source test.133134## Differential verification135136Run the complete pinned Java suite and complete Zig suite, then compare every137source case using either:138139- pinned Java golden artifacts consumed by Zig; or140- a live harness that invokes both implementations.141142Retain raw Java output, raw Zig output, normalized output, and the comparison143report separately. Normalize only documented nondeterminism. Never normalize144error categories, missing/extra fields, numeric precision, contractual order,145side-effect counts, lifecycle transitions, or security-relevant data.146147Required outcome:148149```text150matched == source_cases151mismatched == 0152harness_failures == 0153skipped == 0154not_run == 0155```156157Use the [source parity manifest](assets/source-test-parity.json) and run the158audit script described below.159160## Zig-specific obligations161162After source parity, add tests where applicable for:163164- allocator ownership and matching free/deinit;165- `defer` and `errdefer` behavior under every partial failure point;166- borrowed slice/pointer lifetime and aliasing;167- exact error-set and diagnostic behavior;168- integer width, overflow, alignment, endian, and ABI layout;169- comptime branches and generated declarations;170- Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall differences;171- native, cross-compiled, Wasm/WASI, embedded, or mobile targets claimed;172- thread safety, atomics, cancellation, bounded queues, and shutdown;173- JSON unknown/default/null/numeric behavior;174- malformed input, allocation limits, fuzz/property invariants;175- real C library, service, filesystem, network, or host integration.176177These are additive. They do not increase the source parity numerator.178179## Audit workflow180181Resolve `SKILL_DIR` to this skill directory and run:182183```bash184python3 "$SKILL_DIR/scripts/audit_java_zig_tests.py" \185 --java-root ../agentscope-java \186 --zig-root ../agentscope-zig \187 --parity-manifest docs/source-test-parity.json \188 --fail-on-incomplete189```190191The script verifies baselines, every recorded source case, preservation flags,192existing Zig target files, exact source assets, complete run records,193`migration-test` module registration, and the full differential counts. Static194extraction is conservative and cannot infer semantic mappings; the manifest and195retained artifacts remain required evidence.196197Read [Verification SOP](references/migration-verification-sop.md) for schema,198module layout, evidence, and normalizer rules.199200## Red lines201202- Do not exclude, disable, weaken, or merge away source tests to manufacture203 parity.204- Do not accept generic “no error” assertions when Java checks exact values,205 state, side effects, or error categories.206- Do not edit source assets in place.207- Do not call mirrored tests differential unless Java output participates.208- Do not use test totals, coverage, sampled cases, or two green suites as parity.209- Do not accept leaks, hidden allocator ownership, skipped targets, broad210 `anyerror`, ignored cleanup, or ABI gaps as language-internal details.211- Do not put missing production logic in `<project>-test`.212- Do not let local module tests replace whole-project acceptance.213- Do not claim completion with any failed, skipped, ignored, blocked, missing,214 mismatched, harness-failed, or not-run case.215216## Completion criteria217218- Every Java test and concrete generated case has a lossless Zig implementation.219- Every source test asset has a byte-identical Zig repository copy and matching220 SHA-256.221- Every mapped case preserves inputs, assertions, fixture state, effects, and222 cleanup.223- Complete Java and Zig suites pass from pinned baselines.224- Full Java/Zig differential results are 100% `MATCH`.225- `<project>-test` is registered under `zig build migration-test`, excluded from226 production publication, and owns aggregate evidence.227- All applicable Zig obligations pass across claimed targets and modes.228- Object-ledger blockers, host gaps, flakes, warnings, and production-readiness229 gaps remain visible.230231## Resources232233- [Testing adapter contract](references/testing-adapter-contract.md)234- [Verification SOP](references/migration-verification-sop.md)235- [Test categories](references/test-categories.md)236- [Migration test ledger template](assets/迁移测试对照表.md)237- [Source parity manifest template](assets/source-test-parity.json)238- `scripts/audit_java_zig_tests.py`