analysis/test-data-manager/README.md
Automated system for managing test data files across multiple test configurations.
It supports only tests which implement ManagedTest interface and are generated (*Generated suffix).
Tests declare TestVariantChain via ManagedTest.variantChain:
[] (empty) — golden configuration, writes to .txt files["js"] — writes to .js.txt files["knm", "wasm"] — writes to .js.txt files (only the last variant determines the output file)Priority rule: Tests are grouped by variant chain depth. Fewer variants = higher priority.
[js], [wasm], [jvm]) runs together[knm, native], [knm, wasm]) runs togetherChose the variant chain that best reuses test data across configurations.
Each test can:
Example for ["knm", "wasm"]:
.txt (golden), .knm.txt, .wasm.txt.wasm.txt onlyThis means:
["knm", "wasm"] can inherit expected output from .knm.txt if no .wasm.txt exists. .txt (golden) will be used only if both .knm.txt and .wasm.txt don't exist.["standalone"] can only inherit from .txt (golden).Within the same variant depth group, tests run in parallel. A conflict occurs when:
This would cause a race condition (A writes, B reads the same file).
Examples:
[a, b, c] and [a, c, b] — CONFLICT (c is last in first, present in second)[x, y, c] and [a, b, c] — CONFLICT (both write to .c.txt)[lib, js] and [lib, wasm] — OK (different last variants, no overlap)Important: The system doesn't resolve conflicts – execution will be terminated with an error in this case.
["knm", "js"] can fall back to .knm.txt → .txt["knm", "js"], ["knm", "wasm"]) share .knm.txt and .txtThe test generates tests for three platforms: JVM, JS, and Common. To properly share the test data, it has such a variant chain:
[] (golden)[knm][knm, js][knm, native] (not supported yet)[knm, js, wasm] (not supported yet)Why this hierarchy?
[knm].[knm]).knm variant, or they are different.
Hence, they represent the next hierarchy level: [knm, js] and [knm, native].js.txt exists, then it will have the same difference with knm.txt.
Hence, it represents the next hierarchy level: [knm, js, wasm].An alternative approach would be to use Common as the golden configuration:
[][jvm] (golden)[js][native] (not supported yet)[js, wasm] (not supported yet)This would result in more efficient parallel execution ([1, 3, 1] grouping instead of [1, 1, 2, 1]) while potentially introducing
more redundant special suffices (jvm.txt). This is because some tests depend on the JVM-only features, so we wouldn't be able to use just .txt
because it won't be available since Common won't be executed, so we would have only .jvm.txt and no .txt.
The test generates tests for:
[] (golden)[lib][knm][kmp.lib]Why this hierarchy?
lib. [kmp] could be used as the shared variant,
but effectively there are no such cases that it would help to deduplicate the data.Within each group, tests may update files that other tests depend on. The runner executes passes until no more updates occur (max 10 passes).
CHECK — fail on mismatch (default, for CI)UPDATE — silently update files on mismatchSet via -Dkotlin.test.data.manager.mode=check|update (managed by Gradle tasks automatically)
Run across all modules with the test-data-manager plugin:
# Check mode (default) - fails if test data doesn't match
./gradlew manageTestDataGlobally
# Update mode - updates test data files
./gradlew manageTestDataGlobally --mode=update
# Run only golden tests (skip all variant-specific tests)
./gradlew manageTestDataGlobally --mode=update --golden-only
# Incremental update — skip variant tests for unchanged golden paths
./gradlew manageTestDataGlobally --mode=update --incremental
Run on a single module:
./gradlew :analysis:analysis-api-fir:manageTestData --mode=update
For full CLI options, see repo/gradle-build-conventions/test-data-manager-convention/README.md.
TestDataManagerRunner — Main entry point. Discovers tests, groups by variant depth, validates for conflicts, runs with convergence.VariantChainComparator — Orders variant chains (empty first, then by depth, then alphabetically).DiscoveredTest — Represents a test with its unique ID, display name, and variant chain.TestGroup — Represents tests with the same variant depth.GroupingResult — Result of grouping, includes groups and any detected conflicts.VariantChainConflict — Describes a conflict between two variant chains.The runner uses pure functions for testability:
discoverTests(testPlan) — Extracts test information from JUnit test plangroupByVariantDepth(tests) — Groups tests by variant chain depth, validates conflictsvalidateConflicts(tests) — Checks for race condition conflicts within a groupThe test data manager has comprehensive test coverage organized by component:
| Component | Test File | Description |
|---|---|---|
VariantChainComparator | VariantChainComparatorTest.kt | Unit tests for variant chain ordering |
groupByVariantDepth() | TestDataManagerGroupingTest.kt | Unit tests for test grouping logic |
validateConflicts() | TestDataManagerGroupingTest.kt | Unit tests for conflict detection |
ManagedTestFilter | ManagedTestFilterTest.kt | Filter for ManagedTest implementations |
TestMetadataFilter | TestMetadataFilterTest.kt | Filter by @TestMetadata paths |
| Discovery + Grouping | TestDiscoveryAndGroupingIntegrationTest.kt | Integration tests for full pipeline |
Located in tests/.../fakes/, these classes simulate real test configurations:
Analysis tests (fakes/analysis/):
FakeGoldenAnalysisApiTestGenerated — golden (no variant)FakeStandaloneAnalysisApiTestGenerated — [standalone]FakeLibrarySourceTestGenerated — [librarySource]Light classes tests (fakes/lightclasses/):
FakeGoldenLightClassesTestGenerated — goldenFakeKnmLightClassesTestGenerated — [knm]FakeLibLightClassesTestGenerated — [lib]FakeLibKmpLightClassesTestGenerated — [lib, kmp.lib]FakeWasmLightClassesTestGenerated — [knm, wasm]Conflict test cases (fakes/conflicts/):
FakeConflictingTestAB — [a, b]FakeConflictingTestBA — [b, a] (conflicts with AB)FakeConflictingTestXB — [x, b] (same last variant as AB)FakeNonConflictingTestXY — [x, y] (no conflict)# Run all tests
./gradlew :analysis:test-data-manager:test -q
# Run specific test class
./gradlew :analysis:test-data-manager:test --tests "*TestDiscoveryAndGroupingIntegrationTest" -q