Files
reverse-engineering-anything/tests/boundary/providers/desktopExportPython.test.ts
T
morluto cb4e5cfbff feat(analysis): make resource budgets recoverable across CLI and MCP (#9706)
* refactor(analysis): centralize resource budgets and recovery facts

* feat(analysis): expose ASAR and Ghidra runtime admission controls

* feat(artifacts): expose reader admission and preserve limited recognition

* feat(javascript): expose recoverable semantic precision budgets

* feat(web): add recoverable source-map budgets and compact retained views

* feat(web): make historical capture decoding budgets recoverable

* fix(desktop): enforce selected view policies across capture and export

* feat(runtime): make Frida and LLDB retention budgets selectable

* feat(native): expose diagnostic budgets and preserve exhaustion causes

* feat(managed): expose recoverable snapshot and representation budgets

* feat(metadata): make Go and Rust inspection budgets recoverable

* feat(wasm): expose representation and producer admissions

* feat(evm): expose per-call worker resource budgets

* feat(android): make resource and string-pool omissions recoverable

* feat(producers): expose command and recorded-capture budgets

* docs(analysis): record recovery contracts and integrated validation

* fix(docs): link calibration oracle from published verification pages

* fix(docs): restore desktop task anchors and receipt links

* test(analysis): align fixtures with selectable budget contracts

* fix(analysis): remove source-location projector dependency cycle

* test(analysis): refresh budget recovery and verifier regressions

* test(analysis): preserve format and publication recovery expectations

* test(windows): align conformance with owned runtime admission

* fix(desktop): preserve selected alias kinds in exported state

* test(analysis): align provider fixtures with recoverable budgets

* test(desktop): validate emitted alias metadata structurally

* fix(ghidra): classify bounded Windows endpoint refusals

* test(cli): assert selectable artifact admission recovery

* fix(cli): preserve capture provenance in environment builds
2026-11-10 05:11:20 -05:00

807 lines
27 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
DESKTOP_VIEW_DEFAULTS,
desktopViewPolicy,
type DesktopViewPolicy,
} from "../../../src/domain/desktop/desktopViewPolicy.js";
import {
execFileSync,
type ExecFileSyncOptionsWithStringEncoding,
} from "node:child_process";
import { mkdtempSync, writeFileSync, unlinkSync, rmdirSync } from "node:fs";
import { tmpdir } from "node:os";
import {
chmod,
mkdir,
readFile,
readlink,
stat,
writeFile,
} from "node:fs/promises";
import { join } from "node:path";
import { expect, it } from "vitest";
import {
PYTHON_HELPERS,
renderPythonHelpers,
PYTHON_IMPORTS,
} from "../../../src/domain/desktop/appExportPython.js";
import {
detectStateFormat,
keyfileView,
isJsonText,
jsonView,
textualView,
} from "../../../src/domain/desktop/stateFormats.js";
import { safeParseJson } from "../../../src/domain/safeJson.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
/** Keep the exported Python helpers out of the host command-line size limit. */
const execPython = (
args: string[],
options: ExecFileSyncOptionsWithStringEncoding,
): string => {
const directory = mkdtempSync(join(tmpdir(), "rea-export-python-"));
const script = join(directory, "fixture.py");
const codeIndex = args.indexOf("-c");
try {
writeFileSync(script, args[codeIndex + 1]!, "utf8");
return execFileSync(
process.platform === "win32" ? "python" : "python3",
[
"-X",
"utf8",
...args.slice(0, codeIndex),
script,
...args.slice(codeIndex + 2),
],
options,
);
} finally {
unlinkSync(script);
rmdirSync(directory);
}
};
/** The exported module's view format for each file, run with only its standard library imports. */
const pythonFormats = (files: readonly (readonly [string, string])[]) => {
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}${PYTHON_HELPERS}
for name, text in json.load(sys.stdin):
print(_text_view(name, text, len(text.encode()))["format"])
`;
return execPython(["-I", "-B", "-c", program], {
input: JSON.stringify(files),
encoding: "utf8",
})
.trim()
.split(/\r?\n/u);
};
it("detects Unicode XML names in both state readers while rejecting non-XML text", () => {
const files = [
["map.dat", '<地图 名称="甲"><节点/></地图>'],
["map.dat", '<!DOCTYPE 地图 SYSTEM "map.dtd"><地图/>'],
["map.dat", "<máp/>"],
["map.dat", "<Ϳ>new</Ϳ>"],
["map.xml", "<root><Ϳ/></root>"],
["map.xml", '<root aͿ="x"/>'],
["map.xml", "<𐀀/>"],
["map.dat", "<á/>"],
["map.dat", "<root><?Ϳ value?></root>"],
["map.dat", "<!DOCTYPE Ϳ><root/>"],
["map.dat", "<地图><节点></地图>"],
["note.dat", "<ada@example.test>\nBuy milk"],
] as const;
const expected = [
"xml",
"xml",
"xml",
"text",
"text",
"text",
"text",
"xml",
"text",
"text",
"text",
"text",
];
expect(pythonFormats(files)).toEqual(expected);
expect(
files.map(([name, text]) =>
detectStateFormat(name, new TextEncoder().encode(text)),
),
).toEqual(expected);
});
it("detects key files by the state view's rule rather than a name or any group header", () => {
const files = [
["list.txt", "Groceries\n[x]\nmilk\n"],
["settings.ini", "free text\n"],
["app.conf", "wrap=false\n"],
["settings", "# saved\n[ui]\nwrap=false\n\n; end\n"],
["notes.rc", "[a]\r\nkey = value\r\n"],
] as const;
const formats = pythonFormats(files);
expect(formats).toEqual(["text", "text", "text", "keyfile", "keyfile"]);
expect(formats).toEqual(
files.map(([name, text]) =>
detectStateFormat(name, new TextEncoder().encode(text)),
),
);
});
it("keeps JSON Lines holding a number it cannot read exactly as text, as REA does", () => {
const lines = '{"id":9007199254740993}\n{"id":2}\n';
const files = [
["events.jsonl", lines],
["events.json", lines],
["events.JSON", "42"],
["big.json", '{"id":9007199254740993}'],
["long.json", `{"id":${"9".repeat(5000)}}`],
] as const;
const formats = pythonFormats(files);
expect(formats).toEqual(["text", "text", "json", "json", "json"]);
expect(formats).toEqual(
files.map(([name, text]) =>
detectStateFormat(name, new TextEncoder().encode(text)),
),
);
});
/** The exported module's UTF-16 seed respelling of each file, from /home/ada to /home/user, as hex. */
const pythonUtf16Respelled = (files: readonly string[]) => {
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}
from pathlib import PurePosixPath
SEED_HOME = "/home/ada"
${PYTHON_HELPERS}
for data in json.load(sys.stdin):
print(_respelled_utf16(bytes.fromhex(data), PurePosixPath("/home/user")).hex())
`;
return execPython(["-I", "-B", "-c", program], {
input: JSON.stringify(files),
encoding: "utf8",
})
.trim()
.split(/\r?\n/u);
};
const utf16 = (text: string, order: "le" | "be") => {
const le = Buffer.from(`${text}`, "utf16le");
return order === "le" ? le : Buffer.from(le).swap16();
};
it("respells the captured home in UTF-16 seeds with a byte-order mark, keeping the mark and order", () => {
const work = "# build\n20260216;1;/home/ada/.varicad\n";
const files = [
utf16(work, "le"),
utf16(work, "be"),
utf16("/home/adam/x\n", "le"),
utf16("no home here\n", "le"),
Buffer.from([0xff, 0xfe, 0x41]),
Buffer.from("/home/ada/plain\n"),
];
const respelled = pythonUtf16Respelled(
files.map((file) => file.toString("hex")),
);
const expected = "# build\n20260216;1;/home/user/.varicad\n";
expect(respelled).toEqual([
utf16(expected, "le").toString("hex"),
utf16(expected, "be").toString("hex"),
...files.slice(2).map((file) => file.toString("hex")),
]);
});
it("seeds each file the bundle lists in SEED_MODES with that mode, as a lock whose app checks it stays 0600", async () => {
const root = await createTestTempDirectory("desktop-seed-modes-");
await mkdir(join(root, "seed", ".config", "notes"), { recursive: true });
await writeFile(
join(root, "seed", ".config", "notes", "secret.ini"),
"[s]\n",
);
await writeFile(join(root, "seed", "run.sh"), "#!/bin/sh\n");
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}
SEED_HOME = "/home/ada"
TEXT_SEEDS = frozenset()
SEED_MODES = {".config/notes/secret.ini": 0o600, "run.sh": 0o755}
HERE = Path(sys.argv[1])
${PYTHON_HELPERS}
_seed_home(Path(sys.argv[2]))
`;
execFileSync("python3", [
"-I",
"-B",
"-c",
program,
root,
join(root, "home"),
]);
const mode = async (path: string) =>
(await stat(join(root, "home", path))).mode & 0o777;
expect(await mode(".config/notes/secret.ini")).toBe(0o600);
expect(await mode("run.sh")).toBe(0o755);
});
it.each([true, false])(
"restores nested selected aliases in either selection order (%s)",
async (childFirst) => {
const root = await createTestTempDirectory("desktop-nested-alias-");
const home = join(root, "home");
await mkdir(join(home, ".config", "notes"), { recursive: true });
await writeFile(join(home, ".config", "notes", "profile.ini"), "profile");
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const pairs = childFirst
? '[("settings/profile", ".config/notes", "directory"), ("settings", ".local/share/notes", "directory")]'
: '[("settings", ".local/share/notes", "directory"), ("settings/profile", ".config/notes", "directory")]';
const program = `${imports}
STATE_ALIASES = ${pairs}
${PYTHON_HELPERS}
home = Path(sys.argv[1])
_ensure_state_aliases(home)
_ensure_state_aliases(home)
`;
execPython(["-I", "-B", "-c", program, home], { encoding: "utf8" });
expect(
await readFile(join(home, "settings", "profile", "profile.ini"), "utf8"),
).toBe("profile");
},
);
it("creates a legacy parent alias when a child alias proves it is a directory", async () => {
const root = await createTestTempDirectory("desktop-legacy-parent-alias-");
const home = join(root, "home");
await mkdir(join(home, ".config", "notes"), { recursive: true });
await writeFile(join(home, ".config", "notes", "profile.ini"), "profile");
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}
STATE_ALIASES = [("settings", ".local/share/notes", "unknown"), ("settings/profile", ".config/notes", "directory")]
${PYTHON_HELPERS}
home = Path(sys.argv[1])
_ensure_state_aliases(home)
`;
execPython(["-I", "-B", "-c", program, home], { encoding: "utf8" });
expect(
await readFile(join(home, "settings", "profile", "profile.ini"), "utf8"),
).toBe("profile");
expect(
(await stat(join(home, ".local", "share", "notes"))).isDirectory(),
).toBe(true);
});
it("restores a selected alias to an existing settings file", async () => {
const root = await createTestTempDirectory("desktop-file-alias-");
const home = join(root, "home");
await mkdir(join(home, ".config"), { recursive: true });
await writeFile(join(home, ".config", "tellicorc"), "saved");
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}
STATE_ALIASES = [("settings", ".config/tellicorc", "file")]
${PYTHON_HELPERS}
home = Path(sys.argv[1])
_ensure_state_aliases(home)
_ensure_state_aliases(home)
`;
execPython(["-I", "-B", "-c", program, home], { encoding: "utf8" });
expect(await readFile(join(home, "settings"), "utf8")).toBe("saved");
const absent = join(root, "absent");
await mkdir(join(absent, ".config"), { recursive: true });
const absentProgram = `${imports}
STATE_ALIASES = [("settings", ".config/tellicorc", "file")]
${PYTHON_HELPERS}
home = Path(sys.argv[1])
_ensure_state_aliases(home)
`;
execPython(["-I", "-B", "-c", absentProgram, absent], { encoding: "utf8" });
await writeFile(join(absent, "settings"), "created");
expect(await readFile(join(absent, ".config", "tellicorc"), "utf8")).toBe(
"created",
);
expect((await stat(join(absent, ".config", "tellicorc"))).isFile()).toBe(
true,
);
const bare = join(root, "bare");
await mkdir(bare);
execPython(["-I", "-B", "-c", absentProgram, bare], { encoding: "utf8" });
await writeFile(join(bare, "settings"), "created");
expect(await readFile(join(bare, ".config", "tellicorc"), "utf8")).toBe(
"created",
);
const legacy = join(root, "legacy");
await mkdir(join(legacy, ".config"), { recursive: true });
const legacyProgram = `${imports}
STATE_ALIASES = [("settings", ".config/tellicorc", "unknown")]
${PYTHON_HELPERS}
home = Path(sys.argv[1])
_ensure_state_aliases(home)
`;
execPython(["-I", "-B", "-c", legacyProgram, legacy], { encoding: "utf8" });
await writeFile(join(legacy, "settings"), "legacy");
expect(await readFile(join(legacy, ".config", "tellicorc"), "utf8")).toBe(
"legacy",
);
expect((await stat(join(legacy, ".config", "tellicorc"))).isFile()).toBe(
true,
);
});
it("restores a selected settings alias without replacing an existing path", async () => {
const root = await createTestTempDirectory("desktop-state-alias-");
const home = join(root, "home");
await mkdir(join(root, "seed", ".config", "notes"), { recursive: true });
await writeFile(
join(root, "seed", ".config", "notes", "settings.ini"),
"saved",
);
await mkdir(join(root, "seed", ".config", "notes", "profiles", "work"), {
recursive: true,
});
await writeFile(
join(root, "seed", ".config", "notes", "profiles", "work", "profile.ini"),
"profile",
);
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}
SEED_HOME = "/home/ada"
TEXT_SEEDS = frozenset()
SEED_MODES = {}
STATE_ALIASES = [("settings", ".config/notes", json.loads(sys.argv[3]))]
HERE = Path(sys.argv[1])
${PYTHON_HELPERS}
home = Path(sys.argv[2])
_seed_home(home)
_ensure_state_aliases(home)
_ensure_state_aliases(home)
`;
execPython(
["-I", "-B", "-c", program, root, home, JSON.stringify("directory")],
{ encoding: "utf8" },
);
expect(await readFile(join(home, "settings", "settings.ini"), "utf8")).toBe(
"saved",
);
expect(
await readFile(
join(home, "settings", "profiles", "work", "profile.ini"),
"utf8",
),
).toBe("profile");
const other = join(root, "other-home");
await mkdir(other);
await writeFile(join(other, "settings"), "preserve");
expect(() =>
execPython(
["-I", "-B", "-c", program, root, other, JSON.stringify("directory")],
{
encoding: "utf8",
stdio: "pipe",
},
),
).toThrow();
expect(await readFile(join(other, "settings"), "utf8")).toBe("preserve");
const empty = join(root, "empty-home");
await mkdir(empty);
const emptySeed = join(root, "empty-seed");
await mkdir(emptySeed);
execPython(
["-I", "-B", "-c", program, emptySeed, empty, JSON.stringify("directory")],
{
encoding: "utf8",
},
);
await writeFile(join(empty, "settings", "new.ini"), "new settings");
expect(
await readFile(join(empty, ".config", "notes", "new.ini"), "utf8"),
).toBe("new settings");
// An older capture does not establish the missing target's kind.
const unknown = join(root, "unknown-home");
await mkdir(unknown);
execPython(["-I", "-B", "-c", program, emptySeed, unknown, "null"], {
encoding: "utf8",
});
expect(await readlink(join(unknown, "settings"))).toBe(
join(unknown, ".config", "notes"),
);
await expect(stat(join(unknown, ".config", "notes"))).rejects.toMatchObject({
code: "ENOENT",
});
});
/** A stand-in xprop answering the root window list and each window's class and state from a table. */
const fakeXprop = async (windows: Record<string, string>) => {
const bin = await createTestTempDirectory("desktop-xprop-");
const table = JSON.stringify(windows);
await writeFile(
join(bin, "xprop"),
`#!/usr/bin/env python3
import json, sys
windows = json.loads(${JSON.stringify(table)})
if sys.argv[1:3] == ["-root", "_NET_CLIENT_LIST"]:
print("_NET_CLIENT_LIST(WINDOW): window id # " + ", ".join(windows))
else:
print(windows[sys.argv[2]])
`,
);
await chmod(join(bin, "xprop"), 0o755);
return bin;
};
const taskbarWindow = (bin: string, windowClass: string): string => {
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
return execPython(
[
"-I",
"-B",
"-c",
`${imports}\nfrom pathlib import PurePosixPath
SEED_HOME = "/home/ada"\n${PYTHON_HELPERS}\nprint(_taskbar_window(sys.argv[1]))`,
windowClass,
],
{
encoding: "utf8",
env: { ...process.env, PATH: `${bin}:${process.env.PATH ?? ""}` },
},
).trim();
};
it("holds readiness until a window of the app's class that the taskbar lists is shown, not its splash", async () => {
const splash =
'WM_CLASS(STRING) = "varicad", "varicad"\n_NET_WM_STATE(ATOM) = _NET_WM_STATE_SKIP_PAGER, _NET_WM_STATE_SKIP_TASKBAR, _NET_WM_STATE_ABOVE';
const main =
'WM_CLASS(STRING) = "varicad", "varicad"\n_NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_FOCUSED';
const other =
'WM_CLASS(STRING) = "mousepad", "Mousepad"\n_NET_WM_STATE(ATOM) = ';
expect(taskbarWindow(await fakeXprop({ "0x1": splash }), "varicad")).toBe(
"False",
);
expect(
taskbarWindow(await fakeXprop({ "0x1": splash, "0x2": main }), "varicad"),
).toBe("True");
expect(
taskbarWindow(await fakeXprop({ "0x1": splash, "0x3": other }), "varicad"),
).toBe("False");
expect(taskbarWindow(await fakeXprop({ "0x3": other }), "Mousepad")).toBe(
"True",
);
const typedSplash =
'WM_CLASS(STRING) = "varicad", "varicad"\n_NET_WM_STATE(ATOM) = \n_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_SPLASH';
expect(
taskbarWindow(await fakeXprop({ "0x4": typedSplash }), "varicad"),
).toBe("False");
});
/** The exported module's JSON verdict for each text, with only its standard library imports: its view or its error. */
const pythonJson = (texts: readonly string[]) => {
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}${PYTHON_HELPERS}
for text in json.load(sys.stdin):
print(json.dumps(_text_view("a.json", text, len(text.encode()))))
`;
return execPython(["-I", "-B", "-c", program], {
input: JSON.stringify(texts),
encoding: "utf8",
})
.trim()
.split(/\r?\n/u)
.map((line) => JSON.parse(line) as { view: unknown; error?: string });
};
it("refuses the JSON numbers REA's state view refuses, as JSON with an error rather than an infinity", () => {
const texts = [
'{"a": 1e999}',
'{"a": -1e999}',
'{"a": 12345678901234567890}',
'{"a": -0}',
'{"a": -0.0}',
'{"a": 0.12345678901234567890}',
'{"a": 1e20}',
'{"a": 0.1, "b": 1e21, "c": 42, "d": 9007199254740991}',
'{"a": 9007199254740993, "a": 1}',
'{"a": 1, "a": 9007199254740993}',
];
const python = pythonJson(texts);
texts.forEach((text, index) => {
const typescript = jsonView(text);
const verdict = python[index];
expect(verdict?.error === undefined).toBe(typescript.ok);
if (typescript.ok) expect(verdict?.view).toEqual(typescript.value);
});
});
/** The exported module's format, view and error for each named text, and REA's for the same bytes. */
const textViews = (
files: readonly (readonly [string, string])[],
policy: DesktopViewPolicy = DESKTOP_VIEW_DEFAULTS,
) => {
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}${renderPythonHelpers(policy)}
for name, text in json.load(sys.stdin):
view = _text_view(name, text, len(text.encode()))
print(json.dumps({"format": view["format"], "view": view["view"], "error": view.get("error")}))
`;
const python = execPython(["-I", "-B", "-c", program], {
input: JSON.stringify(files),
encoding: "utf8",
maxBuffer: 64 * 1024 * 1024,
})
.trim()
.split("\n")
.map((line) => JSON.parse(line) as unknown);
const rea = files.map(([name, text]) => {
const bytes = new TextEncoder().encode(text);
const format = detectStateFormat(name, bytes, policy);
if (format !== "text" && format !== "json" && format !== "keyfile")
throw new Error(`${name} reads as ${format}`);
const read = textualView(format, bytes, policy);
return read.ok
? { format, view: read.value, error: null }
: { format, view: null, error: read.error };
});
return { python, rea };
};
it("applies the selected desktop view budgets equally in TypeScript and emitted Python", () => {
const files = [
["lines.txt", "one\ntwo\nthree"],
["value.json", '{"key":"value"}'],
] as const;
const limited = textViews(
files,
desktopViewPolicy({ text_lines: 2, parsed_bytes: 4 }),
);
expect(limited.python).toEqual(limited.rea);
expect(limited.rea[0]?.view).toMatchObject({
lines: ["one", "two"],
truncated: true,
line_count: 3,
});
expect(limited.rea[1]?.error).toContain("limit for JSON");
const recovered = textViews(
files,
desktopViewPolicy({ text_lines: 3, parsed_bytes: 64 }),
);
expect(recovered.python).toEqual(recovered.rea);
expect(recovered.rea[0]?.view).toMatchObject({
lines: ["one", "two", "three"],
truncated: false,
});
expect(recovered.rea[1]).toEqual({
format: "json",
view: { key: "value" },
error: null,
});
});
it("bounds the emitted reader's probe when an app grows a file after its size check", () => {
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}${renderPythonHelpers(desktopViewPolicy({ file_bytes: 4 }))}
read_bytes = 0
class ObservedReader:
def __init__(self, file):
self.file = file
def __enter__(self):
return self
def __exit__(self, *args):
self.file.close()
def read(self, size=-1):
global read_bytes
data = self.file.read(size)
read_bytes += len(data)
return data
class GrowingPath(type(Path())):
def open(self, mode="r", *args, **kwargs):
if mode == "rb":
Path(str(self)).write_bytes(b"x" * 20000)
return ObservedReader(super().open(mode, *args, **kwargs))
return super().open(mode, *args, **kwargs)
with tempfile.TemporaryDirectory() as root:
small = Path(root) / "small.txt"
small.write_bytes(b"abcd")
ordinary = _view(small)
growing = GrowingPath(root) / "growing.txt"
growing.write_bytes(b"abcd")
grown = _view(growing)
print(json.dumps({"ordinary": ordinary, "grown": grown, "read_bytes": read_bytes, "grown_bytes": growing.stat().st_size}))
`;
const result = JSON.parse(
execPython(["-I", "-B", "-c", program], { encoding: "utf8" }),
);
expect(result.ordinary).toMatchObject({
format: "text",
view: { lines: ["abcd"] },
truncated: false,
});
expect(result.grown).toEqual({
format: null,
view: null,
error: "larger than 4 bytes, the most the view reads",
});
expect(result.read_bytes).toBe(5);
expect(result.grown_bytes).toBe(20000);
});
it("reads text nested past Python's recursion limit as JSON only when all of it is, as REA does", () => {
const brackets = (open: number, close: number) =>
`${"[".repeat(open)}${"]".repeat(close)}`;
const files = [
["deep.txt", brackets(1100, 1099)],
["deep.json", brackets(1100, 1099)],
["deep.txt", brackets(1100, 1100)],
["deep.json", `${brackets(1100, 1100)} x`],
] as const;
const { python, rea } = textViews(files);
expect(python).toEqual(rea);
expect(rea.map(({ format, error }) => [format, error])).toEqual([
["text", null],
["text", null],
["json", "nested deeper than the 500 levels a JSON view keeps"],
["text", null],
]);
});
it("refuses JSON and key files over 4 MiB as REA does, telling JSON apart from text without parsing it", () => {
const objects = `[{}${",{}".repeat(1_400_000)}]`;
const files = [
["objects.json", objects],
["objects", `${objects.slice(0, -1)}}`],
["settings", `[ui]\n${"wrap=false\n".repeat(400_000)}`],
["log", `[0] ${"x".repeat(4_200_000)}`],
] as const;
const { python, rea } = textViews(files);
expect(python).toEqual(rea);
const refused = "larger than the 4 MiB limit for JSON and key file views";
expect(rea.map(({ format, error }) => [format, error])).toEqual([
["json", refused],
["text", null],
["keyfile", refused],
["text", null],
]);
});
it("checks text for JSON the way REA does, token by token, without parsing it", () => {
const [bom, nbsp, lineSeparator] = [0xfeff, 0xa0, 0x2028].map((code) =>
String.fromCharCode(code),
);
const texts = [
["-0", "01", "1.", "1E+5", "-", "[1.5e+]", "truex", "[NaN]"],
['"\\u00e9"', '"\\u00g9"', '"\\x"', '"\t"', '"a', '"\\uD800"'],
["", " [1] ", "[1] x", "{}{}", `${bom}[1]`, `[1]${nbsp}`],
[`["${lineSeparator}"]`, "[]", "[1,]", "[,1]", "[1 2]", "[1]]", "[[1]"],
["[}", "{}", '{"a":1}', '{"a" 1}', "{a:1}", '{"a":1,}', '{"a"::1}'],
["{1:2}", '{"a":[1,{"b":null}],"c":-1.5e-3}'],
].flat();
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const python = JSON.parse(
execPython(
[
"-I",
"-B",
"-c",
`${imports}${PYTHON_HELPERS}\ntexts = json.load(sys.stdin)\nprint(json.dumps({"syntax": [_read_json(text, build=False) is not _INVALID_JSON for text in texts], "built": [_read_json(text) is not _INVALID_JSON for text in texts]}))`,
],
{ input: JSON.stringify(texts), encoding: "utf8" },
),
) as { syntax: boolean[]; built: boolean[] };
const parsed = texts.map((text) => safeParseJson(text).ok);
expect(texts.map((text) => isJsonText(text))).toEqual(parsed);
expect(python.syntax).toEqual(parsed);
expect(python.built).toEqual(parsed);
expect(parsed.filter(Boolean)).toHaveLength(10);
});
it("checks JSON depth with one iterator per level, copying no wide list", () => {
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}
import tracemalloc
${PYTHON_HELPERS}
wide = [None] * 800_000
tracemalloc.start()
deep = _deeper_than(wide, 500)
peak = tracemalloc.get_traced_memory()[1]
tracemalloc.stop()
nested = []
for _ in range(501):
nested = [nested]
print(json.dumps({"deep": deep, "peak": peak, "edge": _deeper_than(nested, 501), "over": _deeper_than(nested, 500)}))
`;
const result = JSON.parse(
execPython(["-I", "-B", "-c", program], { encoding: "utf8" }),
) as { deep: boolean; peak: number; edge: boolean; over: boolean };
expect(result).toMatchObject({ deep: false, edge: false, over: true });
// Queuing each member of the 800,000-item list traced about 51 MB.
expect(result.peak).toBeLessThan(1024 * 1024);
});
it("spells infinite and negative-zero SQLite reals as REA's SQLite reader does", () => {
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const cells = execPython(
[
"-I",
"-B",
"-c",
`${imports}${PYTHON_HELPERS}\nprint(json.dumps([_cell(v, "utf-8") for v in (math.inf, -math.inf, -0.0, 0.0, 1.5)]))`,
],
{ encoding: "utf8" },
);
expect(JSON.parse(cells)).toEqual(["Infinity", "-Infinity", "-0", 0, 1.5]);
});
it("keeps the same keyfile whitespace as the retained state view", async () => {
const inputs = [
"[ui]\nsuffix=hello \nunicode=\u00a0hello\u00a0\npadded= hello\n",
"[ui]\r\nsuffix=hello \r\nunicode=\u00a0hello\u00a0\u00a0\r\npadded=\thello\r\n",
];
const imports = PYTHON_IMPORTS.split("\n")
.filter((line) => !line.includes("agentenv_protocol"))
.join("\n");
const program = `${imports}${PYTHON_HELPERS}
print(json.dumps([_text_view("settings.ini", text, len(text.encode()))["view"]["groups"] for text in json.load(sys.stdin)]))
`;
const root = await createTestTempDirectory("rea-keyfile-python-");
const script = join(root, "fixture.py");
await writeFile(script, program, "utf8");
const output = execFileSync(
process.platform === "win32" ? "python" : "python3",
["-I", "-B", "-X", "utf8", script],
{
input: JSON.stringify(inputs),
encoding: "utf8",
},
);
expect(JSON.parse(output)).toEqual(inputs.map(keyfileView));
});