Skip to content

test(hygiene): stop the suite writing to the operator's real data dir - #87

Merged
Cipher208 merged 2 commits into
masterfrom
fix/tests-must-not-write-to-the-real-data-dir
Oct 7, 2026
Merged

Cipher208 merged 2 commits into
masterfrom
fix/tests-must-not-write-to-the-real-data-dir

Conversation

@Cipher208

Copy link
Copy Markdown
Owner

Several modules resolve their data directory once, at import time, from MCP_MEMORY_DATA_DIR: shared/saga/impl/storage.py (SAGA_DIR), shared/read_only.py (which builds the module-level read_only_replica singleton on import) and features/auth/__init__.py. Importing any of them while the real value was in place was enough to write to the live directory — no test body had to do anything wrong, and hermetic_global_db could not help, because by the time a fixture runs those constants are already resolved.

What the suite was leaving behind

Measured on ~/.mcp-ariel-memory before this change:

path left behind
replica/memory.db 14 MB, rewritten on every run by the lifespan
sagas/ 15875 state files, 63 MB
<repo>/data/auth/keys.enc 704 KB, +~860 B per run

The fix

tests/conftest.py now publishes a session temp dir as MCP_MEMORY_DATA_DIR before pytest imports the first test module, and the session fixture removes it and restores the operator's value on teardown. hermetic_global_db reuses that directory instead of making its own.

After the change, a full run leaves all three paths byte-identical: same mtime, same size, same file count.

Two tests were relying on the variable being unset

  • test_backup_saga_success patched pathlib.Path.home to fake a data dir. That only worked while MCP_MEMORY_DATA_DIR was unset and the fallback was reachable; the variable wins. It now names its own dir through the variable the saga actually reads.
  • test_backup_saga_compensation passed vacuously: with no source database the first step reported skipped_no_source, so backup_path was absent and the assertion that the backup was removed never ran. It now requires the backup to have existed — and finds one.

test_auth_backup.py also constructed APIKeyAuth() / BearerAuth() bare, falling back to the CWD-relative data/auth/*.enc, which no environment variable can redirect — hence the separate fix there. Each test passes its own tmp_path, and test_api_key_list asserts == 2 rather than >= 2: it was being satisfied by the accumulated history, not by itself.

Tests

Full suite: 2087 passed.

Not addressed here, reported instead

  • The same scratch dir holds 1.6 GB of tmp* directories left by tests that call tempfile.mkdtemp() without cleaning up. Different mechanism, own PR.
  • data/auth/keys.enc from earlier runs is still on disk. It is gitignored (*.enc), so nothing was ever committed.

Several modules resolve their data directory ONCE, at import time, from
MCP_MEMORY_DATA_DIR: `shared/saga/impl/storage.py` (SAGA_DIR),
`shared/read_only.py` (which builds the module-level `read_only_replica`
singleton on import) and `features/auth/__init__.py`. Importing any of them
while the real value was in place was enough to write to the live directory —
no test body had to do anything wrong, and `hermetic_global_db` could not help
because by the time a fixture runs those constants are already resolved.

Measured on the operator's `~/.mcp-ariel-memory` before this change:

| path | what the suite left behind |
|---|---|
| `replica/memory.db` | 14 MB, rewritten on every run by the lifespan |
| `sagas/` | 15875 state files, 63 MB |
| `<repo>/data/auth/keys.enc` | 704 KB, +~860 B per run |

`tests/conftest.py` now publishes a session temp dir as MCP_MEMORY_DATA_DIR
before pytest imports the first test module, and the session fixture removes it
and restores the operator's value on teardown. After the change a full run
leaves all three paths byte-identical: same mtime, same size, same file count.

Two tests were relying on the variable being unset and had to stop:

- `test_backup_saga_success` patched `pathlib.Path.home` to fake a data dir,
  which only worked while MCP_MEMORY_DATA_DIR was unset and the fallback was
  reachable. It now names its own dir through the variable, which is what the
  saga actually reads.
- `test_backup_saga_compensation` passed vacuously: with no source database the
  first step reported `skipped_no_source`, so `backup_path` was absent and the
  assertion that the backup was removed never ran. It now requires the backup to
  have existed, and it finds one.

`test_auth_backup.py` also constructed `APIKeyAuth()` / `BearerAuth()` bare,
which fall back to the CWD-relative `data/auth/*.enc` — a fallback no
environment variable can redirect, hence the separate fix there. Each test now
passes its own `tmp_path`, and `test_api_key_list` asserts `== 2` instead of
`>= 2`: it was being satisfied by the accumulated history rather than by itself.

Full suite: 2087 passed. Not addressed here, and reported instead: the same
scratch dir holds 1.6 GB of `tmp*` directories left by tests that call
`tempfile.mkdtemp()` without cleaning up, and `data/auth/keys.enc` from earlier
runs is still on disk (gitignored, nothing was ever committed).
@github-actions github-actions Bot added the test label Oct 7, 2026
@coderabbitai

coderabbitai Bot commented Oct 7, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Repository: Cipher208/a-memory/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c3bca5f4-6d48-4396-a8ec-9276c80c148a
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Cipher208
Cipher208 merged commit fe188e1 into master Oct 7, 2026
19 checks passed
@Cipher208
Cipher208 deleted the fix/tests-must-not-write-to-the-real-data-dir branch October 7, 2026 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant