Skip to content

fix(tests): a fixture must not inherit a previous run - #89

Merged
ciresnave merged 1 commit into
mainfrom
fix/82-fixture-inherits-a-previous-run
Sep 11, 2026
Merged

ciresnave merged 1 commit into
mainfrom
fix/82-fixture-inherits-a-previous-run

Conversation

@ciresnave-bot

@ciresnave-bot ciresnave-bot commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Closes #82.

tokenizer_config_wins_over_registry failed once during a full cargo test --tests and never reproduced:

assertion `left == right` failed: tier 3 does not fire for this fixture
  left: TokenizerConfig
 right: Registry

⚠️ The issue I filed ruled out the actual mechanism

It said: "Concurrent test binaries have distinct pids, so two fixtures cannot collide on a name by that route."

That is a correct argument aimed at the wrong question. It answers can two live processes collide — and I used it to answer can two fixtures collide, which is larger. I never considered sequential collision across runs.

The mechanism

  • CARGO_TARGET_TMPDIR is never cleaned between runs
  • create_dir_all succeeds on an existing directory and does not clear it
  • the nonce is pid + atomic counter: unique within a run, and it recurs across runs, because pids are recycled and the counter restarts at 0

Measured on disk before the fix:

14183  stale fixture directories under target/tmp
  393  distinct pids represented
 6389  already holding a tokenizer_config.json
  347  stale dirs for THIS test's own fixture name
  343  of those 347 already poisoned

The test writes tokenizer_config.json at its last step while asserting tier 3 fires at its first. On a name+pid+counter recurrence it reads the previous run's tier-1 file and fails exactly as recorded.

⚠️ Every observation is explained, including the one that misled me. "Only under a full cargo test --tests" is real, but it is a correlate, not the mechanism — more binaries means more pids consumed, which raises the chance of drawing one a previous run used. A condition that raises the probability of a collision looks exactly like the cause of it.

Fix

fresh_dir removes before it creates and asserts the directory is empty afterwards. Extracted as a named helper deliberately: a helper that promises "the directory exists" is indistinguishable from one that promises "the directory is yours" until something asserts the difference.

Detector

a_fixture_directory_does_not_inherit_a_previous_run poisons a directory exactly as a previous run would, asserts the poisoning took (a probe that failed to poison would make the check below pass for the wrong reason), then asserts the fixture comes back clean.

⚠️ Born-red, and the first attempt fired the wrong arm:

M1  remove deleted only       -> fresh_dir's OWN emptiness guard fired
                                 "fixture ... is not empty at creation"
M2  remove AND guard deleted  -> the regression test's named assertion fired
                                 "the fixture inherited a previous run's
                                  tier-1 file -- this is issue #82"

Two independent guards, each firing on its own arm. M1 alone would have let me claim the regression test works when it had not run.

Not done, deliberately

The 14183 stale directories are not deleted. The fix makes them harmless, and deleting is a destructive act on a shared checkout for a benefit the fix already provides.

Verification

chat_template_render: 75 passed, 0 failed. Eleven-step chain green at exit 0 — fmt, lockfile, doc, test, featgate, clippy, spm, sweep, e2e, census, dtype.

⚠️ That chain is my own instrument on this machine and it is not the forge's verdict.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JtTf3315ahKPPyBiYugnPh

Summary by Sourcery

Ensure temporary test fixtures are recreated cleanly so prior runs cannot affect current test results.

Bug Fixes:

  • Prevent test fixtures from inheriting files left by previous test runs, eliminating intermittent configuration-resolution failures.

Enhancements:

  • Add explicit directory freshness and emptiness guarantees for temporary model fixtures.
  • Add a regression test that verifies stale fixture files are removed before reuse.

Tests:

  • Add coverage for fixture isolation across sequential test runs, including independent checks that stale data is created and then removed.

Closes #82.

`tokenizer_config_wins_over_registry` failed once during a full
`cargo test --tests` and never reproduced:

    assertion `left == right` failed: tier 3 does not fire for this fixture
      left: TokenizerConfig
     right: Registry

⚠️ AND THE ISSUE I FILED RULED OUT THE ACTUAL MECHANISM, IN WRITING, WITH A
CORRECT ARGUMENT AIMED AT THE WRONG QUESTION. It said: "Concurrent test binaries
have distinct pids, so two fixtures cannot collide on a name by that route."
That answers CAN TWO LIVE PROCESSES COLLIDE. I used it to answer CAN TWO
FIXTURES COLLIDE, which is a larger question, and never considered SEQUENTIAL
collision across runs.

THE MECHANISM:
  - `CARGO_TARGET_TMPDIR` is NEVER cleaned between runs
  - `create_dir_all` SUCCEEDS on an existing directory and does NOT clear it
  - the nonce is pid + atomic counter: unique WITHIN a run, and it RECURS
    ACROSS runs, because pids are recycled and the counter restarts at 0

Measured on disk before the fix:

    14183  stale fixture directories under target/tmp
      393  distinct pids represented
     6389  already holding a tokenizer_config.json
      347  stale dirs for THIS test's own fixture name
      343  of those 347 already poisoned

The test writes `tokenizer_config.json` at its LAST step while asserting tier 3
fires at its FIRST. On a name+pid+counter recurrence it reads the PREVIOUS RUN's
tier-1 file and fails exactly as recorded.

⚠️ EVERY OBSERVATION IS EXPLAINED, INCLUDING THE ONE THAT MISLED ME. "Only under
a full `cargo test --tests`" is real, but it is a CORRELATE rather than the
mechanism: more binaries means more pids consumed, which raises the chance of
drawing one a previous run used. A CONDITION THAT RAISES THE PROBABILITY OF A
COLLISION LOOKS EXACTLY LIKE THE CAUSE OF IT.

FIX: `fresh_dir` removes before it creates and asserts the directory is empty
afterwards. Extracted as a named helper deliberately -- a helper that promises
"the directory exists" is indistinguishable from one that promises "the
directory is YOURS" until something asserts the difference.

DETECTOR: `a_fixture_directory_does_not_inherit_a_previous_run` poisons a
directory exactly as a previous run would, ASSERTS THE POISONING TOOK (a probe
that failed to poison would make the check below pass for the wrong reason),
then asserts the fixture comes back clean.

⚠️ BORN-RED, AND THE FIRST ATTEMPT FIRED THE WRONG ARM:

    M1  remove deleted only       -> fresh_dir's OWN emptiness guard fired
                                     "fixture ... is not empty at creation"
    M2  remove AND guard deleted  -> the regression test's named assertion fired
                                     "the fixture inherited a previous run's
                                      tier-1 file -- this is issue #82"

Two independent guards, each firing on its own arm. M1 alone would have let me
claim the regression test works when it had not run.

NOT DONE, deliberately: the 14183 stale directories are NOT deleted. The fix
makes them harmless, and deleting is a destructive act on a shared checkout for
a benefit the fix already provides.

chat_template_render: 75 passed, 0 failed. Eleven-step chain green, exit 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JtTf3315ahKPPyBiYugnPh

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @ciresnave-bot, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 5 days and 2 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR fixes cross-run fixture contamination by replacing create_dir_all with a clean-and-assert directory setup, and adds a regression test that reproduces stale tokenizer configuration inheritance and verifies it is removed.

File-Level Changes

Change Details Files
Ensure fixture directories are recreated from a clean state to prevent stale files from previous test runs affecting test behavior.
  • Added a fresh_dir helper that removes any existing directory, recreates it, and asserts it is empty.
  • Replaced direct directory creation in fixture setup with the clean-state helper.
  • Documented the sequential pid/counter collision mechanism and its impact on fixture isolation.
tests/chat_template_render.rs
Add a regression test that independently verifies stale fixture contents are removed before use.
  • Poisoned a probe directory with the prior run's tokenizer configuration and asserted the poisoning succeeded.
  • Verified the helper removes the stale file while preserving the fixture directory.
  • Used explicit assertions to distinguish failures in the setup guard from failures in the regression check.
tests/chat_template_render.rs

Assessment against linked issues

Issue Objective Addressed Explanation
#82 Ensure fixture directories used by the chat template rendering tests are clean and cannot inherit files from a previous test run.
#82 Prevent the tokenizer_config_wins_over_registry test from falsely observing a stale tokenizer_config.json and incorrectly failing the tier-resolution assertion.
#82 Add regression coverage proving that a previously populated fixture directory is recreated empty while still existing.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 4 complexity · 0 duplication

Metric Results
Complexity 4
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@ciresnave
ciresnave merged commit 29cabf4 into main Sep 11, 2026
3 checks passed
@ciresnave
ciresnave deleted the fix/82-fixture-inherits-a-previous-run branch September 11, 2026 03:36
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.

Flaky: tokenizer_config_wins_over_registry fails rarely under concurrent test binaries (cause unidentified)

2 participants