mirror of https://github.com/garrytan/gstack.git
test: cover fail-closed GBrain maintenance
Co-Authored-By: OpenAI Codex <noreply@openai.com>
This commit is contained in:
parent
fcdfeadd72
commit
0ba7300a30
|
|
@ -1,7 +1,7 @@
|
||||||
import { describe, expect, test } from "bun:test";
|
import { describe, expect, test } from "bun:test";
|
||||||
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
|
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
|
||||||
import { tmpdir } from "os";
|
import { tmpdir } from "os";
|
||||||
import { dirname, join, resolve } from "path";
|
import { delimiter, dirname, join, resolve } from "path";
|
||||||
import { spawnSync } from "child_process";
|
import { spawnSync } from "child_process";
|
||||||
|
|
||||||
import codex from "../hosts/codex";
|
import codex from "../hosts/codex";
|
||||||
|
|
@ -106,6 +106,18 @@ describe("DEV-206 Windows Codex runtime and GBrain regressions", () => {
|
||||||
expect(plan.shell).toBe(false);
|
expect(plan.shell).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Windows source registration rejects shell-only launchers", () => {
|
||||||
|
for (const extension of ["cmd", "bat", "ps1"]) {
|
||||||
|
expect(() =>
|
||||||
|
planGbrainSpawn(
|
||||||
|
["sources", "list", "--json"],
|
||||||
|
`C:\\Program Files\\GBrain\\gbrain.${extension}`,
|
||||||
|
"win32",
|
||||||
|
),
|
||||||
|
).toThrow("unsafe Windows gbrain launcher");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test("dream capability planning refuses a brain-wide fallback", () => {
|
test("dream capability planning refuses a brain-wide fallback", () => {
|
||||||
const supported = planSourceScopedDream(
|
const supported = planSourceScopedDream(
|
||||||
"gstack-code-test",
|
"gstack-code-test",
|
||||||
|
|
@ -125,4 +137,85 @@ describe("DEV-206 Windows Codex runtime and GBrain regressions", () => {
|
||||||
expect(brainWideOnly.error).toContain("refusing to widen scope");
|
expect(brainWideOnly.error).toContain("refusing to widen scope");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("dream execution probes capability and never launches a brain-wide fallback", () => {
|
||||||
|
const tmp = mkdtempSync(join(tmpdir(), "gstack-dev-206-dream-"));
|
||||||
|
try {
|
||||||
|
const binDir = join(tmp, "bin");
|
||||||
|
const gbrainHome = join(tmp, ".gbrain");
|
||||||
|
const gstackHome = join(tmp, ".gstack");
|
||||||
|
const logPath = join(tmp, "gbrain-calls.jsonl");
|
||||||
|
mkdirSync(binDir, { recursive: true });
|
||||||
|
mkdirSync(gbrainHome, { recursive: true });
|
||||||
|
mkdirSync(gstackHome, { recursive: true });
|
||||||
|
writeFileSync(
|
||||||
|
join(gbrainHome, "config.json"),
|
||||||
|
JSON.stringify({ engine: "pglite", database_url: "pglite:///synthetic" }),
|
||||||
|
);
|
||||||
|
|
||||||
|
const fakeSource = join(tmp, "fake-gbrain.ts");
|
||||||
|
const fakeBinary = join(binDir, process.platform === "win32" ? "gbrain.exe" : "gbrain");
|
||||||
|
writeFileSync(
|
||||||
|
fakeSource,
|
||||||
|
`import { appendFileSync } from "fs";
|
||||||
|
const args = process.argv.slice(2);
|
||||||
|
appendFileSync(process.env.FAKE_GBRAIN_LOG!, JSON.stringify(args) + "\\n");
|
||||||
|
if (args.join(" ") === "--version") { console.log("gbrain 0.41.0"); process.exit(0); }
|
||||||
|
if (args.join(" ") === "sources list --json") { console.log('{"sources":[]}'); process.exit(0); }
|
||||||
|
if (args.join(" ") === "dream --help") { console.log("Usage: gbrain dream"); process.exit(0); }
|
||||||
|
process.exit(91);
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
const built = spawnSync(
|
||||||
|
process.execPath,
|
||||||
|
["build", fakeSource, "--compile", "--outfile", fakeBinary],
|
||||||
|
{ encoding: "utf-8", timeout: 30_000 },
|
||||||
|
);
|
||||||
|
expect(built.status).toBe(0);
|
||||||
|
chmodSync(fakeBinary, 0o755);
|
||||||
|
|
||||||
|
const childEnv: NodeJS.ProcessEnv = { ...process.env };
|
||||||
|
for (const key of Object.keys(childEnv)) {
|
||||||
|
if (key.toUpperCase() === "PATH") delete childEnv[key];
|
||||||
|
}
|
||||||
|
Object.assign(childEnv, {
|
||||||
|
HOME: tmp,
|
||||||
|
GBRAIN_HOME: gbrainHome,
|
||||||
|
GSTACK_HOME: gstackHome,
|
||||||
|
PATH: `${binDir}${delimiter}${process.env.PATH || ""}`,
|
||||||
|
FAKE_GBRAIN_LOG: logPath,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = spawnSync(
|
||||||
|
process.execPath,
|
||||||
|
[
|
||||||
|
join(ROOT, "bin", "gstack-gbrain-sync.ts"),
|
||||||
|
"--dream",
|
||||||
|
"--no-code",
|
||||||
|
"--no-memory",
|
||||||
|
"--no-brain-sync",
|
||||||
|
],
|
||||||
|
{
|
||||||
|
cwd: ROOT,
|
||||||
|
encoding: "utf-8",
|
||||||
|
timeout: 15_000,
|
||||||
|
env: childEnv,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const output = `${result.stdout || ""}${result.stderr || ""}`;
|
||||||
|
expect(result.status).toBe(1);
|
||||||
|
expect(output).toContain("does not support --source");
|
||||||
|
expect(output).toContain("refusing to widen scope");
|
||||||
|
|
||||||
|
const calls = readFileSync(logPath, "utf-8")
|
||||||
|
.trim()
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => JSON.parse(line) as string[]);
|
||||||
|
expect(calls).toContainEqual(["dream", "--help"]);
|
||||||
|
expect(calls).not.toContainEqual(["dream"]);
|
||||||
|
expect(calls.some((call) => call[0] === "dream" && call[1] !== "--help")).toBe(false);
|
||||||
|
} finally {
|
||||||
|
rmSync(tmp, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue