Files
rea/experiments/atomic-codemode/native-parameters.test.mjs
T

172 lines
5.5 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import {
readParameterFacet,
createParameterViews,
} from "./native-parameters.mjs";
import { parseNativeIR } from "./native-ir.mjs";
import { methods, reference } from "./api.mjs";
import Ajv2020 from "ajv/dist/2020.js";
const parameter = (
index,
storage = { space: "register", offset: "0x38", size_bytes: 8 },
) => ({
id: index === null ? "return" : `parameter:${index}`,
native_index: index,
name: "display",
type_name: "unknown8",
size_bytes: 8,
is_void: false,
storage,
type_locked: false,
name_locked: false,
size_locked: false,
this_pointer: false,
indirect_storage: false,
hidden_return: false,
});
const fixture = () => ({
schema_version: 1,
model: "__stdcall",
model_unknown: false,
inputs_locked: false,
output_locked: false,
variadic: false,
input_errors: false,
output_errors: true,
items: [
parameter(0),
parameter(1, { space: "stack", offset: "0x8", size_bytes: 8 }),
],
output: parameter(null, { space: "register", offset: "0x0", size_bytes: 8 }),
});
const read = (raw) => readParameterFacet({ atomic_parameters: raw });
const model = (fn) =>
parseNativeIR(
JSON.stringify({
binary: "/input",
count: 1,
language: "c",
error: null,
functions: [
{ address_hex: "0x1000", error: null, code: "readable", ...fn },
],
}),
"0x1000",
);
test("formal selection preserves native indices, caller order, unknowns and independently selected output", () => {
const parsed = read(fixture());
assert.equal(parsed.ok, true);
const view = createParameterViews(parsed.value);
const first = view.parameters({
indices: [1, 0, 1, 8],
fields: ["storage", "size_bytes"],
limit: 1,
});
assert.deepEqual(
first.items.map((r) => r.id),
["parameter:1"],
);
assert.equal(first.total, 2);
assert.equal(first.next_offset, 1);
assert.deepEqual(first.missing_indices, [8]);
assert.equal(first.output.id, "return");
assert.equal(first.prototype.output_errors, true);
assert.equal(first.coverage.source_signature, "unknown");
const next = view.parameters({ indices: [1, 0], fields: [], offset: 1 });
assert.deepEqual(next.items, [{ id: "parameter:0", native_index: 0 }]);
assert.deepEqual(next.output, { id: "return", native_index: null });
assert.deepEqual(view.parameters({ indices: [] }).items, []);
assert.equal(Object.hasOwn(view.parameters({}).items[0], "type_name"), false);
});
test("cached metadata/storage cannot be changed by SDK callers", () => {
const view = createParameterViews(read(fixture()).value);
const result = view.parameters({});
assert.throws(() => {
result.prototype.model = "changed";
}, TypeError);
assert.throws(() => {
result.items[0].storage.offset = "0x0";
}, TypeError);
result.items.length = 0;
assert.equal(view.parameters({}).total, 2);
assert.equal(view.parameters({}).prototype.model, "__stdcall");
});
test("unknown type/storage is distinct from native void, malformed identities cannot publish partial formals", () => {
const unknown = fixture();
Object.assign(unknown.output, {
type_name: null,
is_void: null,
storage: null,
});
assert.equal(read(unknown).ok, true);
const empty = fixture();
empty.items = [];
Object.assign(empty.output, {
type_name: "void",
is_void: true,
size_bytes: 0,
storage: null,
});
assert.equal(read(empty).ok, true);
for (const change of [
(x) => (x.items[0].id = "parameter:9"),
(x) => (x.items[1].native_index = 0),
(x) => (x.output.native_index = 0),
(x) => (x.items[0].size_bytes = 4),
(x) => (x.output.is_void = true),
(x) => (x.output.type_name = null),
(x) => (x.model_unknown = null),
]) {
const x = fixture();
change(x);
assert.equal(read(x).ok, false);
}
});
test("prototype facet works without graph/calls; unavailable/invalid prototype retains code and reason", () => {
const available = model({
atomic_parameters: fixture(),
atomic_facts_error: { malformed: "not a failure string" },
atomic_calls_error: "capacity",
});
assert.equal(available.facets.parameters.availability, "available");
assert.equal(available.parameters({}).total, 2);
assert.equal(available.facets.recovered_ir.availability, "unavailable");
assert.equal(available.code, "readable");
for (const fn of [
{},
{
atomic_parameters_error: "native function prototype store is unavailable",
},
{ atomic_parameters: { schema_version: 99 } },
]) {
const unavailable = model(fn);
assert.equal(unavailable.code, "readable");
assert.equal(unavailable.facets.parameters.availability, "unavailable");
assert.throws(
() => unavailable.parameters({}),
(e) => e.details.facet === "parameters",
);
}
});
test("parameter input schema matches advertised JSON Schema and rejects guessed keys/indices", () => {
const validate = new Ajv2020({ strict: false }).compile(
reference("parameters").methods[0].input_schema,
);
for (const [request, valid] of [
[{}, true],
[{ indices: [], fields: [] }, true],
[{ indices: [1, 0, 1], fields: ["storage", "type_name"] }, true],
[{ indices: [-1] }, false],
[{ indices: ["0"] }, false],
[{ fields: ["value_id"] }, false],
[{ signature: true }, false],
]) {
const input = { snapshot: "snap_test", ...request };
assert.equal(methods.parameters.input.safeParse(input).success, valid);
assert.equal(validate(input), valid);
}
});