Files
quixos-protocol/test/build-contract.test.ts
T

79 lines
3.8 KiB
TypeScript
Raw Normal View History

import assert from "node:assert/strict";
import { test } from "node:test";
import { compileCapabilityResourceSource } from "../src/capability-language/index.js";
import { packageBuildContract } from "../src/execution-world/build-contract.js";
import { generatePortableTypeScriptBindings } from "../src/bindings/portable.js";
import type { BindingSchema } from "../src/bindings/index.js";
import type { InterfaceRevision } from "../src/capability-model/types.js";
function fixture() {
const source = { repository: "https://example.test/source", commit: "1".repeat(40) };
const interfaces = new Map<string, InterfaceRevision>();
for (const name of ["Value", "Unrelated"]) {
const result = compileCapabilityResourceSource(
`interface ${name} id "${name}" revision "${name}@1" {
value text id "text" : string { get id "text:get" execution snapshot; }
}`,
{ source },
);
assert.ok(result.ok && result.resource.kind === "interface", JSON.stringify(result.diagnostics));
interfaces.set(name, result.resource.revision);
}
const result = compileCapabilityResourceSource(
`import interface Value;
package Adapter id "adapter" revision "adapter@1" {
operation fetchText id "read" : unit -> string mode call execution snapshot targets [server]
receiver any requires { interface data id "value" : Value using [text.get]; };
}`,
{ source, environment: { interfaces, interfaceClosure: [...interfaces.values()] } },
);
assert.ok(result.ok && result.resource.kind === "package", JSON.stringify(result.diagnostics));
return {
format: "quixos-bindings",
version: 1,
interfaces: [...interfaces.values()],
packages: [result.resource.revision],
} satisfies BindingSchema;
}
test("package builds ignore exact pins and unrelated declarations, and preserve generated port types", () => {
const schema = fixture();
const original = packageBuildContract(schema, "adapter@1");
const changed = structuredClone(schema);
changed.interfaces.forEach((iface) => {
iface.source.commit = "2".repeat(40);
});
changed.packages[0]!.source.commit = "3".repeat(40);
changed.interfaces.find((iface) => iface.displayName === "Unrelated")!.members = [];
assert.deepEqual(packageBuildContract(changed, "adapter@1"), original);
assert.equal(JSON.stringify(original).includes("https://example.test/source"), false);
assert.equal(
generatePortableTypeScriptBindings(original.definition.bindings, "adapter@1", { target: "server" }),
generatePortableTypeScriptBindings(schema, "adapter@1", { target: "server" }),
);
});
test("changing a consumed interface or an owned port contract invalidates the build", () => {
const schema = fixture();
const original = packageBuildContract(schema, "adapter@1");
const changed = structuredClone(schema);
changed.interfaces[0]!.members[0]!.operations[0]!.outputType = { kind: "scalar", name: "bool" };
assert.notEqual(packageBuildContract(changed, "adapter@1").digest, original.digest);
const own = structuredClone(schema);
own.packages[0]!.exports[0]!.outputType = { kind: "scalar", name: "bool" };
assert.notEqual(packageBuildContract(own, "adapter@1").digest, original.digest);
});
test("a nominal reference does not import the referenced interface's entire dependency graph", () => {
const schema = fixture();
schema.packages[0]!.exports[0]!.inputType = {
kind: "object-ref",
expectation: { kind: "interface", interfaceRevisionId: schema.interfaces[1]!.revisionId },
};
const original = packageBuildContract(schema, "adapter@1");
schema.interfaces[1]!.members = [];
assert.deepEqual(packageBuildContract(schema, "adapter@1"), original);
schema.packages[0]!.exports[0]!.inputType = { kind: "scalar", name: "string" };
assert.notEqual(packageBuildContract(schema, "adapter@1").digest, original.digest);
});