Skip to content

Reproducer for #335 fix #2: parse-asymmetry should fall back to simple hash diff#352

Open
tinder-maxwellelliott wants to merge 1 commit into
masterfrom
claude/reproducer-issue-335-fallback
Open

Reproducer for #335 fix #2: parse-asymmetry should fall back to simple hash diff#352
tinder-maxwellelliott wants to merge 1 commit into
masterfrom
claude/reproducer-issue-335-fallback

Conversation

@tinder-maxwellelliott
Copy link
Copy Markdown
Collaborator

Summary

Adds two @Ignored reproducer tests for #335 fix #2 (the "fall back to computeSimpleImpactedTargets when parse asymmetry is detected" proposal in the issue body).

Today, when the two module-graph JSON payloads passed to get-impacted-targets differ but one of them fails to parse, CalculateImpactedTargetsInteractor.detectChangedModules returns the full set of modules from the parseable side via findChangedModules(emptyMap, fullMap). Every module is then treated as "added". The impacted set explodes in one of two ways:

Both outcomes are far worse than the per-target hash diff that would have run if no module graph had been supplied. PR #336 made the parser tolerant of stderr-polluted JSON, which covers the historical 18.0.x base graph case, but the asymmetry remains a real failure mode for any genuinely unparseable input (corrupted base graphs pulled from object storage, truncation, a future bazel mod graph serialisation change).

The reproducer

Two @Ignored tests in cli/src/test/kotlin/com/bazel_diff/interactor/CalculateImpactedTargetsInteractorTest.kt cover both code paths that branch on changedModules.isNotEmpty():

  • execute_parseAsymmetryFallsBackToSimpleHashDiff_reproducerForIssue335Fix2 — exercises execute() (the default get-impacted-targets path).
  • executeWithDistances_parseAsymmetryFallsBackToSimpleHashDiff_reproducerForIssue335Fix2 — exercises executeWithDistances() (the --depsFile path).

Both feed:

  • A fromModuleGraphJson with no { at all ("garbage-non-json-payload") so ModuleGraphParser.parseModuleGraph falls through to if (start < 0) return emptyMap().
  • A toModuleGraphJson that parses cleanly to one or two modules.
  • A startHashes / endHashes pair where only //:changed has actually changed.

Each test asserts that the impacted set is exactly {//:changed}. Today both fail with:

expected to contain only:<["//:changed"]>
 but was:<["//:changed", "//:unchanged_a", "//:unchanged_b"]>

The @Ignored state keeps CI green; the annotations document the issue. Drop @Ignore once an asymmetry-detection fallback lands (e.g. "if parseModuleGraph returns an empty map for one side and a non-empty map for the other, skip queryTargetsDependingOnModules and fall through to computeSimpleImpactedTargets").

Verification

  • bazel test //cli:CalculateImpactedTargetsInteractorTestPASSED (new tests are @Ignored and skipped; existing 19 tests still pass).
  • Temporarily dropped the @Ignore annotations and re-ran — FAILED with the assertion above, confirming the reproducer catches the bug.

Test plan

  • bazel test //cli:CalculateImpactedTargetsInteractorTest — passes with @Ignored.
  • Manually un-@Ignore'd and re-ran — both tests fail with the expected "every target reported" assertion error.
  • After the asymmetry fallback lands, drop @Ignore from both tests and re-run — both should pass.

Generated with Claude Code (https://claude.com/claude-code)

When the two module-graph JSON payloads passed to get-impacted-targets are
not byte-equal but one of them fails to parse, findChangedModules(emptyMap,
fullMap) reports every module in the populated graph as "added". The
impacted set then explodes -- either fanning out into one rdeps subprocess
per matched repo (the multi-hour fan-out in #335) or, when no
BazelQueryService is bound, falling through to allTargets.keys so every
hashed label is reported as impacted.

Both outcomes are far worse than a per-target hash diff. PR #336 made the
parser tolerant of stderr-polluted JSON, which covers the historical
18.0.x base graph case, but the asymmetry remains a real failure mode for
genuinely unparseable input (corrupted base graphs, truncation, future
serialization format changes).

The reproducer adds two @ignore'd tests in CalculateImpactedTargetsInteractorTest
covering both code paths that branch on changedModules.isNotEmpty():
execute() and executeWithDistances(). Both feed a non-JSON fromGraph and a
parseable toGraph and assert that only the actually-hash-changed target
appears in the impacted set. Today both tests fail (every target is
reported); the @ignore'd state keeps CI green until fix #2 lands.

Generated with Claude Code (https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant