123 lines
5.3 KiB
TypeScript
123 lines
5.3 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { test } from "node:test";
|
|
import { loadReaderWorkspace } from "./reader-fixture.js";
|
|
import { buildArtifactFixture } from "./artifact-fixture.js";
|
|
import { capabilityId as id, type WorkspaceRevision } from "../src/capability-model/types.js";
|
|
import {
|
|
compileExecutionPlan,
|
|
compileExecutionGroups,
|
|
checkExecutionWorld,
|
|
checkedWorldDigest,
|
|
type ExecutionInstallation,
|
|
type ExecutionEnvironment,
|
|
} from "../src/execution-world/index.js";
|
|
const environment: ExecutionEnvironment = {
|
|
placement: "service",
|
|
hostDigest: "a".repeat(64),
|
|
policyDigest: "b".repeat(64),
|
|
credentialGeneration: "config:1",
|
|
};
|
|
const prepare = async (workspace: WorkspaceRevision) => {
|
|
const plan = compileExecutionPlan(workspace);
|
|
const fixtures = plan.definition.packages.map((pkg) => buildArtifactFixture(plan, pkg.revision));
|
|
const world = await checkExecutionWorld(
|
|
plan,
|
|
fixtures.map((f) => f.manifest),
|
|
fixtures[0]!.read,
|
|
);
|
|
const installation: ExecutionInstallation = {
|
|
codec: "camino-execution-installation-v1",
|
|
plan: plan.digest,
|
|
world: checkedWorldDigest(world),
|
|
routes: {},
|
|
components: [],
|
|
packages: fixtures.map((f) => ({
|
|
revision: f.manifest.packageRevisionId,
|
|
root: "/fixture",
|
|
service: f.manifest.implementations[0]!,
|
|
module: f.manifest.implementations[1]!,
|
|
})),
|
|
};
|
|
const environments = Object.fromEntries(plan.definition.packages.map((pkg) => [pkg.revision, { ...environment }]));
|
|
return { plan, installation, environments, groups: () => compileExecutionGroups(plan, installation, environments) };
|
|
};
|
|
|
|
test("execution reuse ignores world/source/display changes and unrelated packages", async () => {
|
|
const workspace = await loadReaderWorkspace(),
|
|
original = await prepare(workspace);
|
|
const before = (await original.groups())[0]!.executionDigest;
|
|
workspace.sourceRootCommit = "f".repeat(40);
|
|
workspace.packageImports[0]!.displayName = "Renamed";
|
|
workspace.packageImports[0]!.source.commit = "e".repeat(40);
|
|
workspace.packageImports.push({
|
|
packageId: id.package("unrelated"),
|
|
revisionId: id.packageRevision("unrelated@1"),
|
|
displayName: "Other",
|
|
source: workspace.packageImports[0]!.source,
|
|
exports: [],
|
|
});
|
|
const after = await prepare(workspace);
|
|
assert.notEqual(after.plan.digest, original.plan.digest);
|
|
assert.equal(
|
|
(await after.groups()).find((g) => g.logicalId === workspace.packageImports[0]!.packageId)!.executionDigest,
|
|
before,
|
|
);
|
|
original.environments[workspace.packageImports[0]!.revisionId]!.credentialGeneration = "config:2";
|
|
assert.notEqual((await original.groups())[0]!.executionDigest, before);
|
|
original.environments[workspace.packageImports[0]!.revisionId]!.placement = "module";
|
|
assert.notEqual((await original.groups())[0]!.executionDigest, before);
|
|
});
|
|
|
|
test("outbound provider changes invalidate consumers while caller changes preserve providers", async () => {
|
|
const workspace = await loadReaderWorkspace((name, text) =>
|
|
name === "DocumentData.qx" ? text.replace("queryable value content", "queryable portable value content") : text,
|
|
);
|
|
const revision = id.packageRevision("provider@1"),
|
|
exportId = id.packageExport("provider:content"),
|
|
portId = id.dependencyPort("provider:state");
|
|
workspace.packageImports.push({
|
|
packageId: id.package("provider"),
|
|
revisionId: revision,
|
|
displayName: "Provider",
|
|
source: workspace.packageImports[0]!.source,
|
|
exports: [
|
|
{
|
|
kind: "operation",
|
|
id: exportId,
|
|
displayName: "content",
|
|
mode: "call",
|
|
inputType: { kind: "builtin", name: "unit" },
|
|
outputType: { kind: "scalar", name: "string" },
|
|
execution: { kind: "snapshot", targets: ["target:org.quixos.execution.javascript@1", "server"] },
|
|
receiverRequirement: { kind: "exact-atom", atomId: id.atom("atom:reader:document") },
|
|
dependencyPorts: [
|
|
{
|
|
id: portId,
|
|
displayName: "state",
|
|
requirement: { kind: "state", valueType: { kind: "scalar", name: "string" }, primitives: ["read"] },
|
|
},
|
|
],
|
|
},
|
|
],
|
|
});
|
|
const owner = workspace.conformances.find((c) => c.interfaceRevisionId === "interface:reader:document-data@1")!;
|
|
owner.operationBindings.find((b) => b.operationId === "document:content:get")!.binding = {
|
|
kind: "package",
|
|
packageRevisionId: revision,
|
|
exportId,
|
|
dependencies: [{ portId, binding: { kind: "state", slotId: id.slot("slot:document:content") } }],
|
|
};
|
|
const prepared = await prepare(workspace);
|
|
const values = async () => new Map((await prepared.groups()).map((g) => [g.logicalId, g.executionDigest]));
|
|
const before = await values();
|
|
prepared.installation.packages.find((p) => p.revision === "package:reader-runtime@1")!.service!.contentDigest =
|
|
"c".repeat(64);
|
|
const callerChanged = await values();
|
|
assert.equal(callerChanged.get("provider"), before.get("provider"));
|
|
assert.notEqual(callerChanged.get("package:reader-runtime"), before.get("package:reader-runtime"));
|
|
prepared.installation.packages.find((p) => p.revision === revision)!.service!.contentDigest = "d".repeat(64);
|
|
const providerChanged = await values();
|
|
assert.notEqual(providerChanged.get("provider"), callerChanged.get("provider"));
|
|
assert.notEqual(providerChanged.get("package:reader-runtime"), callerChanged.get("package:reader-runtime"));
|
|
});
|