mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-25 06:24:27 +08:00
Key the differential oracle cache on the inherited environment (#1266)
This commit is contained in:
@@ -22,6 +22,7 @@ import { describe, expect, test } from "vitest";
|
||||
import ts5 from "typescript";
|
||||
import { compile } from "@scriptc/compiler";
|
||||
import { corpusSelect, shardSuffix } from "./shard.js";
|
||||
import { oracleEnvKey } from "./oracle-env.js";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
const repoRoot = join(import.meta.dirname, "../..");
|
||||
@@ -238,8 +239,8 @@ function programInputs(file: string): string[] {
|
||||
// Node's verdict for a corpus program is a pure function of the program bytes,
|
||||
// the shims, and the Node build (corpus stdout is deterministic by
|
||||
// construction — it must be identical to a non-Node native binary's output). So
|
||||
// cache it, keyed by all of those plus the invocation shape (SCRIPTC_TEST_ENV
|
||||
// and the cwd). Only the SPAWN is skipped: the native side always runs live
|
||||
// cache it, keyed by all of those plus the invocation shape (the inherited
|
||||
// environment, see oracle-env.ts, and the cwd). Only the SPAWN is skipped: the native side always runs live
|
||||
// and the comparison itself never changes. SCRIPTC_NO_CACHE=1 (or an unset
|
||||
// SCRIPTC_CACHE_DIR) disables the cache in both directions — no reads, no writes.
|
||||
// Storage shares the compile cache's root and its LRU sweep (see native-toolchain.ts).
|
||||
@@ -265,7 +266,7 @@ function oracleKeyBase(): Promise<string> {
|
||||
.update(readFileSync(fileURLToPath(comptimeShim)))
|
||||
.update("\0")
|
||||
.update("\0")
|
||||
.update(process.env["SCRIPTC_TEST_ENV"] ?? "")
|
||||
.update(oracleEnvKey(process.env))
|
||||
.update("\0")
|
||||
.update(process.cwd())
|
||||
.update("\0")
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { expect, test } from "vitest";
|
||||
import { oracleEnvKey } from "./oracle-env.js";
|
||||
|
||||
test("the oracle key changes with any inherited variable", () => {
|
||||
const base = { PATH: "/bin", SCRIPTC_TEST_ENV: "from-harness" };
|
||||
expect(oracleEnvKey({ ...base, NODE_ENV: "production" })).not.toBe(
|
||||
oracleEnvKey({ ...base, NODE_ENV: "test" }),
|
||||
);
|
||||
expect(oracleEnvKey({ ...base, NODE_ENV: "test" })).not.toBe(oracleEnvKey(base));
|
||||
expect(oracleEnvKey({ ...base, FOO: "a=b" })).not.toBe(
|
||||
oracleEnvKey({ ...base, FOO: "a", B: "" }),
|
||||
);
|
||||
});
|
||||
|
||||
test("the oracle key ignores the runner's worker numbers and variable order", () => {
|
||||
expect(oracleEnvKey({ A: "1", B: "2", VITEST_WORKER_ID: "1", VITEST_POOL_ID: "1" })).toBe(
|
||||
oracleEnvKey({
|
||||
VITEST_POOL_ID: "7",
|
||||
B: "2",
|
||||
TINYPOOL_WORKER_ID: "3",
|
||||
A: "1",
|
||||
VITEST_WORKER_ID: "9",
|
||||
}),
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
/* The environment part of the differential oracle cache key. The Node
|
||||
* oracle runs with the harness's inherited environment, so a program whose
|
||||
* output reads a variable (NODE_ENV, SCRIPTC_TEST_ENV, ...) must not reuse a
|
||||
* verdict recorded under a different value. The variables that number the
|
||||
* test runner's own workers differ between workers of one run and are left
|
||||
* out, so every worker shares the cache. */
|
||||
const WORKER_VARIABLES = new Set(["VITEST_POOL_ID", "VITEST_WORKER_ID", "TINYPOOL_WORKER_ID"]);
|
||||
|
||||
export function oracleEnvKey(env: NodeJS.ProcessEnv): string {
|
||||
return Object.keys(env)
|
||||
.filter((name) => !WORKER_VARIABLES.has(name) && env[name] !== undefined)
|
||||
.sort()
|
||||
.map((name) => `${name}=${env[name]}\0`)
|
||||
.join("");
|
||||
}
|
||||
Reference in New Issue
Block a user