212 lines
6.9 KiB
JavaScript
212 lines
6.9 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { execFile } from "node:child_process";
|
|
import { mkdtemp, readFile, writeFile, rm } from "node:fs/promises";
|
|
import { join, resolve, isAbsolute } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
import { promisify } from "node:util";
|
|
import { Client } from "@modelcontextprotocol/client";
|
|
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
|
import { parseEvidence } from "../dist/domain/evidence.js";
|
|
import { requireMcpOutput } from "./lib/mcp-verifier-results.mjs";
|
|
|
|
const execute = promisify(execFile);
|
|
const bin = process.env.REA_WABT_BIN_DIRECTORY;
|
|
if (!isAbsolute(bin ?? ""))
|
|
throw new Error("Supply absolute REA_WABT_BIN_DIRECTORY with WABT 1.0.42");
|
|
const root = await mkdtemp(join(tmpdir(), "rea-wasm-interface-real-"));
|
|
const cli = resolve("scripts/rea.mjs");
|
|
const environment = { ...process.env };
|
|
const command = async (file, args) =>
|
|
(
|
|
await execute(file, args, {
|
|
env: environment,
|
|
cwd: root,
|
|
timeout: 120000,
|
|
maxBuffer: 64 * 1024 * 1024,
|
|
})
|
|
).stdout;
|
|
const client = new Client({
|
|
name: "wasm-interface-real-verifier",
|
|
version: "1",
|
|
});
|
|
const transport = new StdioClientTransport({
|
|
command: process.execPath,
|
|
args: [cli, "mcp"],
|
|
env: environment,
|
|
stderr: "pipe",
|
|
});
|
|
const source = (parameter) =>
|
|
`(module (type (func (param ${parameter}) (result i64))) (import "env" "f" (func (type 0))) (table 1 3 funcref) (memory 1 2) (global (mut i64) (i64.const 0)) (tag (param i32)) (export "run\\22\\ef\\bb\\bf" (func 0)) (export "table" (table 0)) (export "memory" (memory 0)) (export "global" (global 0)) (export "tag" (tag 0)))`;
|
|
const assemble = async (name, wat) => {
|
|
await writeFile(join(root, `${name}.wat`), wat);
|
|
const path = join(root, `${name}.wasm`);
|
|
await command(join(bin, "wat2wasm"), [
|
|
"--enable-all",
|
|
`${name}.wat`,
|
|
"-o",
|
|
path,
|
|
]);
|
|
return path;
|
|
};
|
|
const inspect = async (path) => {
|
|
const result = await client.callTool({
|
|
name: "inspect_wasm_artifact",
|
|
arguments: { path },
|
|
});
|
|
assert.notEqual(result.isError, true, JSON.stringify(result));
|
|
assert.notEqual(result.structuredContent, undefined);
|
|
return parseEvidence(requireMcpOutput(result, "inspect_wasm_artifact"));
|
|
};
|
|
const compare = async (left, right, scope = "both") => {
|
|
const input = {
|
|
left: { kind: "retained-evidence", evidence_id: left.evidence_id },
|
|
right: { kind: "retained-evidence", evidence_id: right.evidence_id },
|
|
scope,
|
|
};
|
|
const reply = await client.callTool({
|
|
name: "compare_wasm_interfaces",
|
|
arguments: input,
|
|
});
|
|
assert.notEqual(reply.isError, true, JSON.stringify(reply));
|
|
assert.notEqual(reply.structuredContent, undefined);
|
|
const mcp = parseEvidence(requireMcpOutput(reply, "compare_wasm_interfaces"));
|
|
const file = join(root, "comparison.json");
|
|
await writeFile(file, JSON.stringify({ left, right, scope }));
|
|
const local = parseEvidence(
|
|
JSON.parse(
|
|
await command(process.execPath, [
|
|
cli,
|
|
"compare-wasm-interfaces",
|
|
file,
|
|
"--json",
|
|
]),
|
|
),
|
|
);
|
|
assert.deepEqual(local, mcp);
|
|
return mcp.normalized_result;
|
|
};
|
|
try {
|
|
assert.equal(
|
|
(await command(join(bin, "wat2wasm"), ["--version"])).trim(),
|
|
"1.0.42",
|
|
);
|
|
await client.connect(transport);
|
|
const path = await assemble("baseline", source("i32"));
|
|
const original = await readFile(path);
|
|
assert.equal(original[8], 1);
|
|