Skip to content

Commit a48b69a

Browse files
codeslakeclaude
andcommitted
fix(test): keep the microcompact scratch dirs off /tmp when a case fails
Fourteen cases each made their own `mc-` dir. Thirteen removed it on the last line of the test body, so an assertion that threw skipped the removal; the fourteenth (case 11) never removed it at all, so that one leaked on the green path too. None of the fourteen was inside a try/finally — the file's three `finally` blocks belong to withEnv, silenceStderr and silenceStderrAsync, and restore env and stderr rather than remove anything. Reproduced two ways: a clean run of the parent leaves 1 dir behind (case 11), and one injected assertion failure leaves 2. After this change both are 0. Registering the dir at creation and collecting in after() puts the cleanup in one place instead of fourteen, and covers the paths that were missing rather than the thirteen that already worked. The eager `rm` calls stay: they free disk during a long run, and after() is idempotent with force. after() does not cover SIGINT, SIGKILL, or a throw at import time — measured. The first matters: Ctrl-C on a long suite still leaks. The last is vacuous here, since every mcTemp() call is inside a test body. test/proxy-wrapper.test.mjs already carries this shape; this is that pattern, not a new one. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 78ca948 commit a48b69a

1 file changed

Lines changed: 34 additions & 15 deletions

File tree

test/proxy-microcompact-stability.test.mjs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { test } from "node:test";
1+
import { after, test } from "node:test";
22
import assert from "node:assert/strict";
33
import { mkdtemp, readFile, rm, stat } from "node:fs/promises";
44
import { tmpdir } from "node:os";
@@ -12,6 +12,25 @@ import ext, {
1212
runMicrocompactStability,
1313
} from "../proxy/extensions/microcompact-stability.mjs";
1414

15+
// EVERY SCRATCH DIR, EVEN THE RUNS THAT FAIL. Thirteen cases remove theirs on the
16+
// last line of the test body, so an assertion that throws skips it, and the
17+
// fourteenth removes nothing at all — that one leaked on the green path too.
18+
// Those calls stay as they are, since they free disk during a long run; this
19+
// collects what they miss.
20+
const scratch = [];
21+
async function mcTemp() {
22+
const d = await mkdtemp(join(tmpdir(), "mc-"));
23+
scratch.push(d);
24+
return d;
25+
}
26+
after(async () => {
27+
for (const d of scratch) {
28+
// Per dir, so one refused removal cannot strand the rest. `force` already
29+
// swallows a missing dir; this is for EPERM and EBUSY.
30+
try { await rm(d, { recursive: true, force: true }); } catch { /* see above */ }
31+
}
32+
});
33+
1534
// --- Fixture helpers ---
1635

1736
const SENTINEL_BARE = "[Old tool result content cleared]";
@@ -149,7 +168,7 @@ test("4. unrelated truncation message → no match in either mode (rejected from
149168
// --- Mode B ---
150169

151170
test("4a. sentinel + trailing text → Mode B match, body NOT mutated, prefix_64 only in dump", async () => {
152-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
171+
const dir = await mcTemp();
153172
const dumpPath = join(dir, "dump.jsonl");
154173
const body = makeBody([
155174
assistantMsg("t1"),
@@ -182,7 +201,7 @@ test("4a. sentinel + trailing text → Mode B match, body NOT mutated, prefix_64
182201

183202
test("4b. long trailing → prefix_64 captures only first 64 chars, byte_length reports full size", async () => {
184203
const long = SENTINEL_TS + " " + "x".repeat(200);
185-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
204+
const dir = await mcTemp();
186205
const dumpPath = join(dir, "dump.jsonl");
187206
const body = makeBody([
188207
assistantMsg("t1"),
@@ -201,7 +220,7 @@ test("4b. long trailing → prefix_64 captures only first 64 chars, byte_length
201220
});
202221

203222
test("4c. CACHE_FIX_MICROCOMPACT_REDACT_LEN=0 → prefix_64 absent", async () => {
204-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
223+
const dir = await mcTemp();
205224
const dumpPath = join(dir, "dump.jsonl");
206225
const body = makeBody([
207226
assistantMsg("t1"),
@@ -237,7 +256,7 @@ test("5a. CACHE_FIX_MICROCOMPACT_SENTINEL_PATTERN_1 adds custom Mode A pattern",
237256
});
238257

239258
test("5b. custom Mode A regex + custom Mode B prefix → exact match goes to exact_matches", async () => {
240-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
259+
const dir = await mcTemp();
241260
const dumpPath = join(dir, "dump.jsonl");
242261
// Exact match against a custom regex from a sentinel family that does NOT
243262
// share the built-in prefix. Verifies exact-match path for custom families.
@@ -269,7 +288,7 @@ test("5c. custom Mode B prefix → variant-of-custom-family captured redacted in
269288
// EXACTLY normalizes, but its prefix-only variant must also be captured
270289
// in Mode B (redacted) — not silently dropped just because the variant
271290
// doesn't share the built-in `[Old tool result content cleared` prefix.
272-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
291+
const dir = await mcTemp();
273292
const dumpPath = join(dir, "dump.jsonl");
274293
const text = "[CC microcompact rev2 at 2026-04-30T17:00:00Z] (with trailing content)";
275294
const body = makeBody([
@@ -352,7 +371,7 @@ test("8. mixed array (text + image) — only the text matches → image untouche
352371
// --- Diagnostic dump ---
353372

354373
test("9. dump set + sentinel match → JSONL line; session_id is hashed (no plaintext)", async () => {
355-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
374+
const dir = await mcTemp();
356375
const dumpPath = join(dir, "dump.jsonl");
357376
const body = makeBody([
358377
assistantMsg("t1"),
@@ -373,7 +392,7 @@ test("9. dump set + sentinel match → JSONL line; session_id is hashed (no plai
373392
});
374393

375394
test("10. dump unset → no fs activity", async () => {
376-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
395+
const dir = await mcTemp();
377396
const dumpPath = join(dir, "dump.jsonl");
378397
const body = makeBody([
379398
assistantMsg("t1"),
@@ -395,7 +414,7 @@ test("10. dump unset → no fs activity", async () => {
395414
});
396415

397416
test("11. multiple matches in one request → ONE JSONL line with arrays split A/B", async () => {
398-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
417+
const dir = await mcTemp();
399418
const dumpPath = join(dir, "dump.jsonl");
400419
const body = makeBody([
401420
assistantMsg("t1"),
@@ -455,7 +474,7 @@ test("13. normalize on + custom canonical → matched sentinel becomes the custo
455474
});
456475

457476
test("14. normalize disabled, dump enabled → matches recorded in dump but body NOT mutated", async () => {
458-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
477+
const dir = await mcTemp();
459478
const dumpPath = join(dir, "dump.jsonl");
460479
const body = makeBody([
461480
assistantMsg("t1"),
@@ -500,7 +519,7 @@ test("15. two requests with different timestamps → byte-identical bodies after
500519
// --- Activation ---
501520

502521
test("16. both gates unset → extension fires but exits early; no telemetry, no mutation, no fs", async () => {
503-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
522+
const dir = await mcTemp();
504523
const dumpPath = join(dir, "dump.jsonl");
505524
const body = makeBody([
506525
assistantMsg("t1"),
@@ -526,7 +545,7 @@ test("16. both gates unset → extension fires but exits early; no telemetry, no
526545
});
527546

528547
test("17. only diagnostic enabled → telemetry present, JSONL written, no mutation", async () => {
529-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
548+
const dir = await mcTemp();
530549
const dumpPath = join(dir, "dump.jsonl");
531550
const body = makeBody([
532551
assistantMsg("t1"),
@@ -548,7 +567,7 @@ test("17. only diagnostic enabled → telemetry present, JSONL written, no mutat
548567
});
549568

550569
test("18. only normalize enabled → telemetry present, mutation happens, no JSONL", async () => {
551-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
570+
const dir = await mcTemp();
552571
const dumpPath = join(dir, "dump.jsonl");
553572
const body = makeBody([
554573
assistantMsg("t1"),
@@ -568,7 +587,7 @@ test("18. only normalize enabled → telemetry present, mutation happens, no JSO
568587
});
569588

570589
test("19. both enabled → telemetry, mutation, AND JSONL all happen; raw text captured pre-normalization", async () => {
571-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
590+
const dir = await mcTemp();
572591
const dumpPath = join(dir, "dump.jsonl");
573592
const body = makeBody([
574593
assistantMsg("t1"),
@@ -598,7 +617,7 @@ test("19. both enabled → telemetry, mutation, AND JSONL all happen; raw text c
598617
});
599618

600619
test("19a. CACHE_FIX_DUMP_MICROCOMPACT_INCLUDE_NORMALIZED=1 → adds normalized_text alongside raw sentinel_text", async () => {
601-
const dir = await mkdtemp(join(tmpdir(), "mc-"));
620+
const dir = await mcTemp();
602621
const dumpPath = join(dir, "dump.jsonl");
603622
const body = makeBody([
604623
assistantMsg("t1"),

0 commit comments

Comments
 (0)