Files
rea/experiments/atomic-codemode/reference-ranges.test.mjs
T

144 lines
4.1 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import { referencesMethod } from "./reference-contracts.mjs";
import { methods } from "./api.mjs";
import { NativeReferenceReads } from "./reference-reads.mjs";
test("range selectors preserve old inputs and reject ambiguous/directional/malformed choices", () => {
assert.equal(methods.references, referencesMethod);
const schema = methods.references.input;
assert.deepEqual(schema.parse({ addresses: ["0x1"] }).addresses, ["0x1"]);
assert.equal(
schema.parse({
addresses: ["0x1"],
direction: "outgoing",
scope: "function",
}).scope,
"function",
);
const ranges = [{ start: "0x0", end_inclusive: "0xffffffffffffffff" }];
assert.equal(schema.parse({ ranges }).scope, "range");
for (const input of [
{ ranges, addresses: ["0x0"] },
{ addresses: ["0x1"], scope: "function", direction: "incoming" },
{ addresses: ["0x1"], scope: "function" },
{ ranges, scope: "function" },
{ ranges, direction: "outgoing" },
{ ranges: [] },
{ ranges: [{ start: "0x2", end_inclusive: "0x1" }] },
{ ranges: [{ start: "0xg", end_inclusive: "0x1" }] },
{ ranges: [{ start: "0x0", end_inclusive: "0x10000000000000000" }] },
{ ranges, limit: 129 },
{ ranges, offset: -1 },
])
assert.equal(schema.safeParse(input).success, false, JSON.stringify(input));
});
const range = { start: "0x100", end_inclusive: "0x10d" };
const wire = JSON.stringify({
schema_version: 1,
binary: "/input",
direction: "to",
count: 1,
ranges: [
{
...range,
index: 0,
offset: 0,
limit: 20,
total: 1,
count: 1,
next_offset: null,
},
],
xrefs: [
{
range_index: 0,
address: 8,
address_hex: "0x8",
kind: "data",
from_address: 8,
from_address_hex: "0x8",
to_address: 264,
to_address_hex: "0x108",
from_function: null,
to_function: null,
instruction: "LEA pointer",
},
],
});
const source = {
evidence_id: "ev_page",
sha256: "owned-sha",
bytes: Buffer.byteLength(wire),
elapsed_ms: 1,
};
test("range pages reuse one immutable parsed source across fields and expire on clear", async () => {
let reads = 0;
const invocations = [];
const reader = new NativeReferenceReads(
async (key, args) => {
invocations.push({ key, args: args("/input") });
return { input: "/input", source };
},
async () => {
reads++;
return wire;
},
() => {},
);
const input = referencesMethod.input.parse({ ranges: [range] });
const first = await reader.read(input);
const selected = await reader.read({ ...input, fields: [] });
assert.equal(reads, 1);
assert.equal(invocations[0].key, invocations[1].key);
assert.deepEqual(Object.keys(selected.results[0].items[0]), [
"source_row",
"from",
"to",
"kind",
]);
assert.throws(() => {
first.results[0].items[0].instruction = "corrupt";
}, TypeError);
first.results[0].items.length = 0;
assert.equal((await reader.read(input)).results[0].items.length, 1);
assert.equal(
selected.results[0].coverage.whole_string_use,
"not-established",
);
reader.clear();
await reader.read(input);
assert.equal(reads, 2);
});
test("unavailable and malformed ranges cannot masquerade as empty observations", async () => {
const input = referencesMethod.input.parse({ ranges: [range] });
const unavailable = new NativeReferenceReads(
() => {
throw Error("must not launch");
},
() => {},
() => {
throw Object.assign(Error("requires native"), {
code: "capability_unavailable",
});
},
);
await assert.rejects(
unavailable.read(input),
(e) => e.code === "capability_unavailable",
);
const malformed = new NativeReferenceReads(
async () => ({ input: "/input", source }),
async () => "{}",
() => {},
);
await assert.rejects(
malformed.read(input),
(e) =>
e.code === "invalid_provider_output" &&
e.details.evidence_id === source.evidence_id &&
e.details.source_retained === true,
);
});