Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deno-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ jobs:
shell: bash
run: |
set -euo pipefail
bun --no-env-file --no-install run test tests/gpg-dsh.test.ts "--native-kv-binding=$(cat "$RUNNER_TEMP/uos-native-kv/receipt.json")"
bun --no-env-file --no-install scripts/test-runner.ts darwin "--native-kv-binding=$(cat "$RUNNER_TEMP/uos-native-kv/receipt.json")"

verify-artifact:
needs: [scope, validate, native, mac-containment, darwin-native]
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
.env
.env.*
!.env.example
!.env.sample
!.env.template
!.env.*.example
!.env.*.sample
!.env.*.template
.data/
.codex-worktrees/
.kv-migration/
Expand Down
120 changes: 120 additions & 0 deletions scripts/responses-conformance-codex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import assert from "node:assert/strict";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { isAbsolute, join } from "node:path";
import { fileURLToPath } from "node:url";
import { runCodexConformance } from "../tests/helpers/responses-conformance-client.ts";
import { initializeTestNativeKv, verifiedTestNativeKvBinding, type TestNativeKvBinding } from "./test-native-kv.ts";
import { testNetworkArgv } from "./test-network.ts";

type Options = Readonly<{
executable: string;
expectedSha256: string;
expectedVersion: string;
captureDirectory: string;
nativeBinding: TestNativeKvBinding;
}>;

const parseOptions = (args: readonly string[]): Options => {
const names = ["codex-executable", "codex-sha256", "codex-version", "capture-directory", "native-kv-binding"];
const values = new Map<string, string>();
for (const argument of args) {
const match = /^--([^=]+)=(.+)$/.exec(argument);
if (!match || !names.includes(match[1]) || values.has(match[1])) throw new Error("Pass each supported --name=value option exactly once");
values.set(match[1], match[2]);
}
const required = (name: string): string => {
const value = values.get(name);
if (!value) throw new Error("Missing --" + name);
return value;
};
const executable = required("codex-executable");
const captureDirectory = required("capture-directory");
assert(isAbsolute(executable) && isAbsolute(captureDirectory), "Executable and fresh capture directory must be absolute");
const expectedSha256 = required("codex-sha256");
const expectedVersion = required("codex-version");
assert(/^[a-f0-9]{64}$/.test(expectedSha256), "An independently pinned Codex SHA256 is required");
assert(/^\d+\.\d+\.\d+$/.test(expectedVersion), "An exact Codex CLI version is required");
return { executable, expectedSha256, expectedVersion, captureDirectory, nativeBinding: verifiedTestNativeKvBinding(required("native-kv-binding")) };
};

async function replay(options: Options): Promise<void> {
initializeTestNativeKv(options.nativeBinding);
const { startResponsesConformanceFixture } = await import("../tests/helpers/responses-conformance-fixture.ts");
const fixture = await startResponsesConformanceFixture({ holdToolDelta: false, captureDirectory: join(options.captureDirectory, "gateway") });
try {
const native = await runCodexConformance({
executable: options.executable,
expectedSha256: options.expectedSha256,
expectedVersion: options.expectedVersion,
endpoint: fixture.endpoint,
token: fixture.token,
captureDirectory: join(options.captureDirectory, "native"),
onTextDelta: (event) => {
fixture.acknowledge(2, event);
},
});
if (fixture.terminals.length < 2) await fixture.journal.wait((entry) => entry.kind === "request_terminal" && fixture.terminals.length === 2);
assert.equal(fixture.calls.length, 2, "One tool turn and one coherent continuation must dispatch exactly twice");
assert.equal(fixture.terminals.length, 2);
await fixture.save(native);
} finally {
await fixture.stop();
}
const reopened = fixture.verifyReopenedLedger();
assert.equal(reopened.outcome, "verified");
console.log(
JSON.stringify({
kind: "responses_conformance_codex",
status: "passed",
captureDirectory: options.captureDirectory,
dispatches: fixture.calls.length,
durableReopen: reopened.outcome,
})
);
}

async function isolated(options: Options, args: readonly string[]): Promise<void> {
// mkdir without recursive reuse preserves every earlier transcript and database.
await mkdir(options.captureDirectory, { mode: 0o700 });
const command = testNetworkArgv([process.execPath, "--no-env-file", "--no-install", fileURLToPath(import.meta.url), "--fixture-child", ...args]);
const env: Record<string, string> = { PATH: process.env.PATH ?? "/usr/bin:/bin", TMPDIR: options.captureDirectory, BUN_RUNTIME_TRANSPILER_CACHE_PATH: "0" };
if (process.env.HOME) env.HOME = process.env.HOME;
const child = Bun.spawn(command, { env, stdin: "ignore", stdout: "pipe", stderr: "pipe" });
const stop = (): void => {
if (child.exitCode === null) child.kill("SIGTERM");
};
process.once("SIGINT", stop);
process.once("SIGTERM", stop);
const timer = setTimeout(stop, 60_000);
try {
const [code, stdout, stderr] = await Promise.all([child.exited, new Response(child.stdout).text(), new Response(child.stderr).text()]);
await Promise.all([writeFile(join(options.captureDirectory, "stdout.log"), stdout), writeFile(join(options.captureDirectory, "stderr.log"), stderr)]);
assert.equal(code, 0, "Synthetic native replay failed; inspect its capture directory");
const raw: unknown = JSON.parse(await readFile(join(options.captureDirectory, "gateway/raw.json"), "utf8"));
assert(raw && typeof raw === "object" && "storage" in raw, "Durable source fixture evidence is required");
console.log(stdout.trim());
} finally {
clearTimeout(timer);
process.off("SIGINT", stop);
process.off("SIGTERM", stop);
if (child.exitCode === null) {
child.kill("SIGKILL");
await child.exited;
}
}
}

if (import.meta.main) {
try {
assert.equal(Bun.version, "1.4.0", "Use the prepared pinned Bun runtime");
const args = process.argv.slice(2);
const child = args[0] === "--fixture-child";
if (child) args.shift();
const options = parseOptions(args);
if (child) await replay(options);
else await isolated(options, args);
} catch (error) {
console.error(error instanceof Error ? error.message : String(error));
process.exitCode = 1;
}
}
22 changes: 21 additions & 1 deletion scripts/test-runner-prelaunch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import assert from "node:assert/strict";
import { test } from "bun:test";
import { realpathSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { testFileArgv } from "./test-runner.ts";
import { groupsFor, testFileArgv, testFileSupportsPlatform } from "./test-runner.ts";
import { liveDestination } from "./test-network.ts";

const controller = realpathSync(fileURLToPath(new URL("../tests/private-bun-copy-confinement.test.ts", import.meta.url)));
Expand All @@ -24,3 +24,23 @@ test("a live-policy request cannot opt the trusted controller out of its network
const policy = { live: liveDestination("http://127.0.0.1:12345") };
assert.deepEqual(testFileArgv(controller, command, policy, "darwin", wrapped), wrapped(command));
});

test("the affected Darwin segment retains real private-copy execution without widening named files", () => {
const path = "tests/private-bun-copy-confinement.test.ts";
const selection = { paths: [path], documentationOnly: false, affectedTests: [path], runAll: false, reason: "selected" as const };
assert.equal(testFileSupportsPlatform(path, "linux"), false);
assert.equal(testFileSupportsPlatform(path, "darwin"), true);
assert.deepEqual(groupsFor("darwin", [], "linux", selection), []);
assert.deepEqual(
groupsFor("darwin", [], "darwin", selection).flatMap((group) => group.files),
[path]
);
assert.deepEqual(
groupsFor("main", ["tests/gpg-dsh.test.ts"], "darwin", selection).flatMap((group) => group.files),
["tests/gpg-dsh.test.ts"]
);
assert.equal(
groupsFor("main", [], "linux", selection).some((group) => group.files.includes(path)),
false
);
});
35 changes: 22 additions & 13 deletions scripts/test-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
import { fileURLToPath } from "node:url";
import { LIVE_E2E_DEFAULT_BASE_URL, liveDestination, testNetworkArgv, type TestNetworkPolicy } from "./test-network.ts";
import { createTestNativeKvPreload, prepareTestNativeKv, verifiedTestNativeKvBinding, type TestNativeKvBinding } from "./test-native-kv.ts";
import { detectTestSelection, formatScopeMessage, testRequiresNativeKv } from "./test-scope.ts";
import { detectTestSelection, formatScopeMessage, testRequiresNativeKv, type TestSelection } from "./test-scope.ts";

const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
let interrupted = false;
Expand Down Expand Up @@ -69,6 +69,9 @@ if (!TEST_SELECTION.runAll && TEST_SELECTION.affectedTests.length === 0) {
process.exit(0);
}
type Group = Readonly<{ profile: string; files: readonly string[]; environment: readonly string[]; network?: "live" }>;
export const testFileSupportsPlatform = (path: string, platform: NodeJS.Platform = process.platform): boolean =>
(path !== "tests/private-bun-copy-confinement.test.ts" || platform === "darwin") &&
(path !== "tests/native-authority-workerd.test.ts" || platform === "linux");
const filesBelow = (directory: string): string[] => {
const found: string[] = [];
for (const entry of readdirSync(join(ROOT, directory), { withFileTypes: true })) {
Expand All @@ -94,16 +97,15 @@ const quality = (): Group =>
],
["PATH"]
);
const allGroupsFor = (segment: string, explicitFiles: readonly string[]): Group[] => {
const allGroupsFor = (segment: string, explicitFiles: readonly string[], platform: NodeJS.Platform): Group[] => {
switch (segment) {
case "darwin":
return platform === "darwin" ? [group("main", ["tests/gpg-dsh.test.ts", "tests/private-bun-copy-confinement.test.ts"], PROVIDER_ENV)] : [];
case "main":
return [
group(
"main",
filesBelow("tests").filter(
(path) =>
!SPECIAL_MAIN_FILES.has(path.split("/").at(-1) ?? "") && (path !== "tests/native-authority-workerd.test.ts" || process.platform === "linux")
),
filesBelow("tests").filter((path) => !SPECIAL_MAIN_FILES.has(path.split("/").at(-1) ?? "") && testFileSupportsPlatform(path, platform)),
PROVIDER_ENV
),
group(
Expand All @@ -120,7 +122,7 @@ const allGroupsFor = (segment: string, explicitFiles: readonly string[]): Group[
case "vps":
return [
group("vps", [
...(process.platform === "linux" ? ["ops/tests/vps-release.test.ts"] : []),
...(platform === "linux" ? ["ops/tests/vps-release.test.ts"] : []),
"ops/tests/release-retention.test.ts",
"ops/tests/vps-release-driver.test.ts",
"ops/tests/vps-release-recovery.test.ts",
Expand Down Expand Up @@ -148,7 +150,7 @@ const allGroupsFor = (segment: string, explicitFiles: readonly string[]): Group[
["SENTINEL_REPLAY_KEY"]
),
group("sentinel-upstream", ["tests/sentinel-upstream-providers.test.ts"], ["SENTINEL_REPLAY_KEY"]),
...(process.platform === "linux"
...(platform === "linux"
? [group("sentinel-consumer", ["tests/sentinel-replay-consumer.test.ts"], ["DENO_DIR", "DENO_NO_UPDATE_CHECK", "PATH", "HOME"])]
: []),
];
Expand All @@ -169,10 +171,15 @@ const segmentHints = new Map([
["tests/live-default-model.e2e.ts", "e2e"],
["tests/vps-deploy-guards.test.ts", "deploy-guards"],
]);
export const groupsFor = (segment: string, explicitFiles: readonly string[]): Group[] => {
const groups = allGroupsFor(segment, explicitFiles);
if (explicitFiles.length === 0 && !TEST_SELECTION.runAll) {
const affected = new Set(TEST_SELECTION.affectedTests);
export const groupsFor = (
segment: string,
explicitFiles: readonly string[],
platform: NodeJS.Platform = process.platform,
selection: TestSelection = TEST_SELECTION
): Group[] => {
const groups = allGroupsFor(segment, explicitFiles, platform);
if (explicitFiles.length === 0 && !selection.runAll) {
const affected = new Set(selection.affectedTests);
return groups.map((item) => ({ ...item, files: item.files.filter((path) => affected.has(path)) })).filter((item) => item.files.length !== 0);
}
if (explicitFiles.length === 0 || segment === "files") return groups;
Expand Down Expand Up @@ -361,7 +368,9 @@ const portableGroups = (groups: readonly Group[]): Group[] =>
groups
.map((item) => ({
...item,
files: item.files.filter((path) => !PORTABLE_EXCLUDED.some((pattern) => pattern.test(path)) && !testRequiresNativeKv(path)),
files: item.files.filter(
(path) => testFileSupportsPlatform(path) && !PORTABLE_EXCLUDED.some((pattern) => pattern.test(path)) && !testRequiresNativeKv(path)
),
}))
.filter((item) => item.files.length !== 0);
const resolveNativeTestArtifacts = async (needsNativeKv: boolean, nativeBinding?: string) => {
Expand Down
68 changes: 68 additions & 0 deletions scripts/test-scope.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -880,3 +880,71 @@ describe("private-copy trusted controller source selection", () => {
expect(selectAffectedTestFiles([producer], [controller + ".other"], create())).toEqual([]);
});
});

describe("separate research and CMake component inputs", () => {
const create = (reader?: string) => {
const root = mkdtempSync(join(fixture, "component-scope-"));
for (const path of ["src", "tests", "docs/research", "cpp"]) mkdirSync(join(root, path), { recursive: true });
writeFileSync(join(root, "docs/research/selector-fixture.json"), "{}\n");
writeFileSync(join(root, "docs/research/selector-fixture.py"), "print('fixture')\n");
writeFileSync(join(root, "cpp/selector-fixture.ts"), "export const fixture = 1;\n");
if (reader) writeFileSync(join(root, "src/reader.ts"), reader);
writeFileSync(join(root, "tests/reader.test.ts"), "import '../src/reader.ts';\n");
return root;
};
test("unconsumed research JSON and Python are documentation, while real config stays conservative", () => {
const root = create();
expect(classifyChangedPaths(["docs/research/selector-fixture.json", "docs/research/selector-fixture.py"], root).documentationOnly).toBe(true);
expect(classifyChangedPaths(["package.json"], root).documentationOnly).toBe(false);
expect(classifyChangedPaths(["docs/openapi.json"], root).documentationOnly).toBe(false);
});
test("real imports and literal file reads preserve research runtime inputs, including deleted data", () => {
const json = "../docs/research/selector-fixture.json";
const python = "../docs/research/selector-fixture.py";
const imported = create(`import value from ${JSON.stringify(json)};\nexport {value};\n`);
expect(classifyChangedPaths(["docs/research/selector-fixture.json"], imported).documentationOnly).toBe(false);
const read = create(`import {readFileSync} from 'node:fs';\nreadFileSync(new URL(${JSON.stringify(python)},import.meta.url));\n`);
expect(classifyChangedPaths(["docs/research/selector-fixture.py"], read).documentationOnly).toBe(false);
rmSync(join(read, "docs/research/selector-fixture.py"));
expect(classifyChangedPaths(["docs/research/selector-fixture.py"], read).documentationOnly).toBe(false);
});
test("a quoted fixture program is not an executing runtime reference", () => {
const program = "readFileSync(new URL('../docs/research/selector-fixture.json',import.meta.url));";
const root = create(`export const example = ${JSON.stringify(program)};\n`);
expect(classifyChangedPaths(["docs/research/selector-fixture.json"], root).documentationOnly).toBe(true);
});
test("a repository-root URL is not a component input, while an explicit component directory remains one", () => {
const relativeRoot = "../";
const root = create(`export const root = new URL(${JSON.stringify(relativeRoot)},import.meta.url);\n`);
expect(classifyChangedPaths(["docs/research/selector-fixture.json"], root).documentationOnly).toBe(true);
const directory = "../docs/research/";
const reader = create(`export const data = new URL(${JSON.stringify(directory)},import.meta.url);\n`);
expect(classifyChangedPaths(["docs/research/selector-fixture.json"], reader).documentationOnly).toBe(false);
});
test("standalone CPP stays out of Bun gates until an actual Bun consumer is introduced", () => {
const path = "cpp/selector-fixture.ts";
const native = "cpp/src/selector-fixture.cpp";
const selection: TestSelection = { paths: [native], documentationOnly: false, affectedTests: [], runAll: false, reason: "no-dependent-tests" };
expect(ciScopeForSelection(selection, create(), {}).needsTypeScriptValidate).toBe(false);
expect(formatScopeMessage(selection, "bun test")).toContain("committed CMake/CTest presets");
const adapter = { ...selection, paths: ["cpp/tests/selector-fixture.ts"] };
expect(ciScopeForSelection(adapter, create(), {}).needsTypeScriptValidate).toBe(true);
expect(formatScopeMessage(adapter, "bun test")).toContain("strict no-emit checks");
const specifier = "../cpp/selector-fixture.ts";
const root = create(`import {fixture} from ${JSON.stringify(specifier)};\nexport {fixture};\n`);
const affectedTests = selectAffectedTestFiles([path], ["tests/reader.test.ts"], root);
expect(affectedTests).toEqual(["tests/reader.test.ts"]);
expect(ciScopeForSelection({ ...selection, paths: [path], affectedTests, reason: "selected" }, root, {}).needsTypeScriptValidate).toBe(true);
const literal = create(`import {readFileSync} from 'node:fs';\nreadFileSync(new URL(${JSON.stringify("../" + native)},import.meta.url));\n`);
expect(ciScopeForSelection(selection, literal, {}).needsTypeScriptValidate).toBe(true);
});
test("an affected private-copy controller selects the actual Darwin job", () => {
const path = "tests/private-bun-copy-confinement.test.ts";
expect(
ciScopeForSelection({ paths: [path], documentationOnly: false, affectedTests: [path], runAll: false, reason: "selected" }, create(), {})
).toMatchObject({
needsDarwinTests: true,
needsDarwinNative: true,
});
});
});
Loading
Loading