Make local graph execution optional across composed packages
This commit is contained in:
@@ -3,7 +3,7 @@ import { test } from "node:test";
|
||||
import { compileCapabilityResourceSource } from "../src/capability-language/index.js";
|
||||
|
||||
const source = { repository: "https://example.test/execution.git", commit: "a".repeat(40) };
|
||||
const data = (execution = "snapshot targets [browser, server]") =>
|
||||
const data = (execution = "snapshot") =>
|
||||
compileCapabilityResourceSource(
|
||||
`
|
||||
interface Data id "interface:data" revision "interface:data@1" {
|
||||
@@ -14,13 +14,14 @@ interface Data id "interface:data" revision "interface:data@1" {
|
||||
}`,
|
||||
{ source },
|
||||
);
|
||||
const program = (selection: string, execution = "snapshot targets [browser, server]") => {
|
||||
const program = (selection: string, execution = "snapshot targets [JavaScript, server]") => {
|
||||
const contract = data();
|
||||
assert.ok(contract.ok, JSON.stringify(contract.diagnostics));
|
||||
assert.equal(contract.resource.kind, "interface");
|
||||
if (contract.resource.kind !== "interface") throw new Error("Expected interface");
|
||||
return compileCapabilityResourceSource(
|
||||
`
|
||||
`symbol JavaScript id "target:org.quixos.execution.javascript@1";
|
||||
|
||||
import interface Data;
|
||||
package Reader id "package:reader" revision "package:reader@1" {
|
||||
function label id "export:label" : unit -> string execution ${execution} requires {
|
||||
@@ -43,7 +44,10 @@ test("portable contracts preserve exact selected operations and targets", () =>
|
||||
assert.equal(result.resource.kind, "package");
|
||||
if (result.resource.kind !== "package") return;
|
||||
const entry = result.resource.revision.exports[0]!;
|
||||
assert.deepEqual(entry.execution, { kind: "snapshot", targets: ["browser", "server"] });
|
||||
assert.deepEqual(entry.execution, {
|
||||
kind: "snapshot",
|
||||
targets: ["target:org.quixos.execution.javascript@1", "server"],
|
||||
});
|
||||
assert.deepEqual(entry.dependencyPorts[0]!.requirement, {
|
||||
kind: "interface",
|
||||
interfaceRevisionId: "interface:data@1",
|
||||
@@ -53,10 +57,10 @@ test("portable contracts preserve exact selected operations and targets", () =>
|
||||
|
||||
test("portable dependency diagnostics reject remote defaults and broad acquisition", () => {
|
||||
for (const [selection, execution, message] of [
|
||||
["using [refresh.call]", "snapshot targets [browser]", "remote-only"],
|
||||
["", "snapshot targets [browser]", "select"],
|
||||
["using [label.get, label.get]", "snapshot targets [browser]", "duplicates"],
|
||||
["using [label.set]", "snapshot targets [browser]", "Unknown"],
|
||||
["using [refresh.call]", "snapshot targets [JavaScript, server]", "remote-only"],
|
||||
["", "snapshot targets [JavaScript, server]", "select"],
|
||||
["using [label.get, label.get]", "snapshot targets [JavaScript, server]", "duplicates"],
|
||||
["using [label.set]", "snapshot targets [JavaScript, server]", "Unknown"],
|
||||
]) {
|
||||
const result = program(selection!, execution);
|
||||
assert.equal(result.ok, false);
|
||||
@@ -64,11 +68,26 @@ test("portable dependency diagnostics reject remote defaults and broad acquisiti
|
||||
}
|
||||
});
|
||||
|
||||
test("package code targets may exceed a dependency's public minimum", () => {
|
||||
test("execution targets must resolve nominal declarations", () => {
|
||||
const result = program("using [label.get]", "snapshot targets [arduino]");
|
||||
assert.ok(result.ok, JSON.stringify(result.diagnostics));
|
||||
// A workspace still has to provide the full installed closure before an
|
||||
// operation can promise this target; package code alone is insufficient.
|
||||
assert.equal(result.ok, false);
|
||||
assert.match(JSON.stringify(result.diagnostics), /Unknown nominal execution target arduino/);
|
||||
});
|
||||
|
||||
test("nominal targets are identified by symbols rather than platform spellings or interfaces", () => {
|
||||
const compile = (alias: string, identity: string) =>
|
||||
compileCapabilityResourceSource(
|
||||
`symbol ${alias} id "${identity}"; package P id "p" revision "p@1" { function f id "f" : unit -> unit execution transaction targets [${alias},server]; }`,
|
||||
{ source },
|
||||
);
|
||||
const device = compile("ESP32", "target:example.device@1");
|
||||
const renamed = compile("MyController", "target:example.device@1");
|
||||
assert.ok(device.ok && device.resource.kind === "package");
|
||||
assert.ok(renamed.ok && renamed.resource.kind === "package");
|
||||
assert.deepEqual(device.resource.revision.exports[0]!.execution, renamed.resource.revision.exports[0]!.execution);
|
||||
assert.deepEqual(device.resource.externalInterfaces, [], "A target identity has no interface definition dependency");
|
||||
assert.equal(compile("server", "target:example.device@1").ok, false);
|
||||
assert.equal(compile("Alias", "server").ok, false);
|
||||
});
|
||||
|
||||
test("portable query getters and target declarations are checked", () => {
|
||||
@@ -80,9 +99,10 @@ test("portable query getters and target declarations are checked", () => {
|
||||
test("snapshot exports reject mutable state ports but transactions admit them", () => {
|
||||
const compile = (effect: string) =>
|
||||
compileCapabilityResourceSource(
|
||||
`
|
||||
`symbol JavaScript id "target:org.quixos.execution.javascript@1";
|
||||
|
||||
package Reader id "package:reader" revision "package:reader@1" {
|
||||
function update id "export:update" : string -> unit execution ${effect} targets [browser, server] requires {
|
||||
function update id "export:update" : string -> unit execution ${effect} targets [JavaScript, server] requires {
|
||||
state storage id "port:value" : string [read, write];
|
||||
};
|
||||
}`,
|
||||
@@ -137,7 +157,7 @@ package Reader id "package:reader" revision "package:reader@1" {
|
||||
delete remote.members[0]!.operations[0]!.execution;
|
||||
await assert.rejects(
|
||||
compileQuery(local, [remote], async () => document("Presentation", "availableObjects")),
|
||||
/browser snapshot getter/,
|
||||
/graph snapshot getter/,
|
||||
);
|
||||
const { capabilityId } = await import("../src/capability-model/index.js");
|
||||
const linked = linkQueries({
|
||||
@@ -200,15 +220,16 @@ test("generic selected ports preserve operation identities and execution through
|
||||
const { specializePackageExport, capabilityId } = await import("../src/capability-model/index.js");
|
||||
const iface = compileCapabilityResourceSource(
|
||||
`interface Cell<value T> id "cell" revision "cell@1" {
|
||||
value content id "content" : T { get id "content:get" execution snapshot targets [browser, server]; }
|
||||
value content id "content" : T { get id "content:get" execution snapshot; }
|
||||
}`,
|
||||
{ source },
|
||||
);
|
||||
assert.ok(iface.ok && iface.resource.kind === "interface", JSON.stringify(iface.diagnostics));
|
||||
const pkg = compileCapabilityResourceSource(
|
||||
`import interface Cell;
|
||||
`symbol JavaScript id "target:org.quixos.execution.javascript@1";
|
||||
import interface Cell;
|
||||
package P id "p" revision "p@1" {
|
||||
function load<value T> id "read" : unit -> T execution snapshot targets [browser, server] requires {
|
||||
function load<value T> id "read" : unit -> T execution snapshot targets [JavaScript, server] requires {
|
||||
interface cell id "cell" : Cell<T> using [content.get];
|
||||
};
|
||||
}`,
|
||||
@@ -236,7 +257,10 @@ test("generic selected ports preserve operation identities and execution through
|
||||
implementsInterface: () => false,
|
||||
},
|
||||
);
|
||||
assert.deepEqual(specialized.execution, { kind: "snapshot", targets: ["browser", "server"] });
|
||||
assert.deepEqual(specialized.execution, {
|
||||
kind: "snapshot",
|
||||
targets: ["target:org.quixos.execution.javascript@1", "server"],
|
||||
});
|
||||
assert.deepEqual(specialized.dependencyPorts[0]!.requirement.kind, "interface");
|
||||
const requirement = specialized.dependencyPorts[0]!.requirement;
|
||||
if (requirement.kind === "interface")
|
||||
|
||||
Reference in New Issue
Block a user