test: env restore runs per-test, not per-suite — the leak that failed 30 strangers

gstack-memory-helpers saved HOME/GSTACK_HOME/PATH in beforeEach but
restored in afterAll, so the last beforeEach's snapshot won and a
gstack-test-engine temp dir leaked into every later file in the same
process: gstack-config read the wrong store, make-pdf's child resolved
Chromium under the temp cache, update-check and artifacts-init lost
their real homes. afterAll is now afterEach; the config and
update-check harnesses also strip GSTACK_HOME/GSTACK_STATE_ROOT from
child env as a belt.
This commit is contained in:
Garry Tan 2026-08-15 10:44:09 -07:00
parent 3fffeab725
commit 7d732020b0
No known key found for this signature in database
GPG Key ID: C1F69E85C74EFE1D
1 changed files with 13 additions and 3 deletions

View File

@ -11,7 +11,7 @@
* Free-tier (~50ms total). Runs in `bun test`.
*/
import { describe, it, expect, beforeEach, afterAll } from "bun:test";
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
import { mkdtempSync, writeFileSync, readFileSync, existsSync, rmSync, mkdirSync, chmodSync } from "fs";
import { tmpdir } from "os";
import { join } from "path";
@ -338,7 +338,11 @@ describe("withErrorContext", () => {
process.env.GSTACK_HOME = testHome;
});
afterAll(() => {
// afterEach, not afterAll: the save happens in beforeEach, so an afterAll
// restore would put back the PREVIOUS test's temp dir (the last beforeEach
// overwrote savedHome) and leak a gstack-test-home-* dir into every test
// file that runs after this one in the same bun process.
afterEach(() => {
if (savedHome === undefined) delete process.env.GSTACK_HOME;
else process.env.GSTACK_HOME = savedHome;
});
@ -414,7 +418,13 @@ describe("detectEngineTier", () => {
process.env.HOME = testHome;
});
afterAll(() => {
// afterEach, not afterAll: the save happens in beforeEach, so an afterAll
// restore would put back the PREVIOUS test's gstack-test-engine-* temp dir
// (the last beforeEach overwrote the saved values). That leaked
// HOME/GSTACK_HOME/PATH into every test file that ran after this one in the
// same bun process — child processes then looked for Playwright's Chromium
// cache and ~/.gstack config under a throwaway temp HOME.
afterEach(() => {
if (savedHome === undefined) delete process.env.GSTACK_HOME;
else process.env.GSTACK_HOME = savedHome;
if (savedGbrainHome === undefined) delete process.env.GBRAIN_HOME;