Files
vercel-labs--zerolang/scripts/snapshot-command-contracts.mts
wehub-resource-sync e7738de6d2
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
chore: import upstream snapshot with attribution
2026-07-13 12:29:30 +08:00

8691 lines
554 KiB
TypeScript
Executable File

#!/usr/bin/env -S node --experimental-strip-types --disable-warning=ExperimentalWarning
import { execFileSync, spawnSync } from "node:child_process";
import { createHash } from "node:crypto";
import { chmodSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, symlinkSync, utimesSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { createAggregateAssert, finishAggregateAssert } from "./aggregate-assert.mjs";
const assert = createAggregateAssert();
if (process.env.ZERO_NATIVE_TEST_SANDBOX !== "1" && process.env.ZERO_NATIVE_TEST_ALLOW_LOCAL !== "1") {
console.error("command contract snapshots emit native test artifacts; run `pnpm run command-contracts` for Vercel Sandbox execution or set ZERO_NATIVE_TEST_ALLOW_LOCAL=1 to opt into local artifacts.");
process.exit(1);
}
const outDir = ".zero/command-contracts";
const execMaxBuffer = 64 * 1024 * 1024;
const zeroBin = process.env.ZERO_BIN || (existsSync(".zero/bin/zero") ? resolve(".zero/bin/zero") : resolve("bin/zero"));
mkdirSync(outDir, { recursive: true });
function graphSidecarPath(sourcePath: string) {
return `${sourcePath.slice(0, -2)}.graph`;
}
function zero(args, options: { allowFailure?: boolean; env?: Record<string, string> } = {}) {
try {
const stdout = execFileSync(zeroBin, args, { encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"], env: options.env ? { ...process.env, ...options.env } : process.env });
return { code: 0, stdout };
} catch (error) {
if (!options.allowFailure) throw error;
return {
code: error.status ?? 1,
stdout: error.stdout?.toString() ?? "",
stderr: error.stderr?.toString() ?? "",
};
}
}
function zeroWithStderr(args, options: { cwd?: string } = {}) {
const result = spawnSync(zeroBin, args, { encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"], cwd: options.cwd });
if (result.error) throw result.error;
return { code: result.status ?? 1, stdout: result.stdout ?? "", stderr: result.stderr ?? "" };
}
function zeroWithInput(args, input: string, options: { allowFailure?: boolean } = {}) {
const result = spawnSync(zeroBin, args, { encoding: "utf8", maxBuffer: execMaxBuffer, input, stdio: ["pipe", "pipe", "pipe"] });
if (result.error) throw result.error;
const code = result.status ?? 1;
if (code !== 0 && !options.allowFailure) {
throw new Error(`zero ${args.join(" ")} exited ${code}: ${result.stderr ?? ""}`);
}
return { code, stdout: result.stdout ?? "", stderr: result.stderr ?? "" };
}
function zeroRaw(args, options: { allowFailure?: boolean; env?: Record<string, string> } = {}) {
try {
const stdout = execFileSync(zeroBin, args, { encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"], env: options.env ? { ...process.env, ...options.env } : process.env });
return { code: 0, stdout };
} catch (error) {
if (!options.allowFailure) throw error;
return {
code: error.status ?? 1,
stdout: error.stdout?.toString() ?? "",
stderr: error.stderr?.toString() ?? "",
};
}
}
function assertPatchOkOutput(stdout: string, expectedSaved?: string) {
assert.match(stdout, /^program graph patch ok\n/);
if (expectedSaved) {
assert.match(stdout, new RegExp(`saved: ${expectedSaved.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\n`));
}
assert.match(stdout, /graphHash: graph:[0-9a-f]{16}\n/);
assert.match(stdout, /applied: \d+ ops?, \d+ nodes? touched\n/);
}
function json(args, options = {}) {
const result = zero(args, options);
return { ...result, body: JSON.parse(result.stdout) };
}
function jsonRaw(args, options = {}) {
const result = zeroRaw(args, options);
return { ...result, body: JSON.parse(result.stdout) };
}
function projectionSidecarGraphPath(sourcePath: string) {
assert(sourcePath.endsWith(".0"), `projection path must end in .0: ${sourcePath}`);
return graphSidecarPath(sourcePath);
}
function importProjectionSidecar(sourcePath: string) {
const graphPath = projectionSidecarGraphPath(sourcePath);
assert.equal(zero(["import", "--format", "binary", "--out", graphPath, sourcePath]).stdout, "");
return graphPath;
}
function assertProjectionCheckOk(sourcePath: string) {
const graphPath = importProjectionSidecar(sourcePath);
assert.equal(zero(["check", graphPath]).stdout, "ok\n");
}
function writeProjectionFile(sourcePath: string, contents: string) {
rmSync(projectionSidecarGraphPath(sourcePath), { force: true });
writeFileSync(sourcePath, contents);
}
function repositoryGraphVerifyScript(root, options: { allowFailure?: boolean; target?: string } = {}) {
const args = [
"--experimental-strip-types",
"--disable-warning=ExperimentalWarning",
"scripts/repository-graph-verify-projection.mts",
"--root",
root,
];
if (options.target) args.push("--target", options.target);
try {
const stdout = execFileSync(
process.execPath,
args,
{ encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"] },
);
return { code: 0, stdout, stderr: "" };
} catch (error) {
if (!options.allowFailure) throw error;
return {
code: error.status ?? 1,
stdout: error.stdout?.toString() ?? "",
stderr: error.stderr?.toString() ?? "",
};
}
}
function sha256File(path) {
return createHash("sha256").update(readFileSync(path)).digest("hex");
}
function assertSourceGraph(body, artifact, moduleIdentity, lowering = "typed-program-graph-mir", canonicalSource = true, sourceProjectionState = undefined) {
assert.equal(body.graph.artifact, artifact);
assert.equal(body.graph.canonicalSource, canonicalSource);
assert.equal(body.graph.moduleIdentity, moduleIdentity);
assert.match(body.graph.graphHash, /^graph:[0-9a-f]{16}$/);
assert.equal(body.graph.lowering, lowering);
if (sourceProjectionState !== undefined) assert.equal(body.graph.sourceProjectionState, sourceProjectionState);
}
const programGraphParseTreeKeys = new Map();
function assertProgramGraphCompilerInput(body, artifact) {
assert(body.compilerCaches.every((cache) => cache.sourceKind === "program-graph" && cache.graphHash === body.graph.graphHash));
assert(body.compilerCaches.every((cache) => cache.parserArtifactsInKey === false));
const caches = new Map<string, any>();
for (const cache of body.compilerCaches) caches.set(cache.name, cache);
const assertCacheInputs = (name, includes, excludes = []) => {
const cache = caches.get(name);
assert(cache, `missing compiler cache ${name}`);
for (const key of includes) assert(cache.graphKeyInputs.includes(key), `${name} cache key inputs should include ${key}`);
for (const key of excludes) assert(!cache.graphKeyInputs.includes(key), `${name} cache key inputs should not include ${key}`);
};
assertCacheInputs("parseTree", ["graphHash", "stdlibGraph", "nodeHashes", "importPaths", "compilerVersion", "packageDependencies"], ["sourceFiles", "targetFacts", "profile"]);
assertCacheInputs("interface", ["graphHash", "modulePaths", "symbolFacts", "importGraph"], ["targetFacts", "profile", "compilerVersion", "packageDependencies"]);
assertCacheInputs("checkedBody", ["graphHash", "stdlibGraph", "importPaths", "targetFacts", "compilerVersion", "packageDependencies"], ["sourceFiles", "profile"]);
assertCacheInputs("specialization", ["graphHash", "stdlibGraph", "importPaths", "targetFacts", "profile", "compilerVersion", "packageDependencies"], ["sourceFiles"]);
if (body.graph.lowering === "mapped-final-mir") {
assertCacheInputs("mappedFinalMir", ["graphHash", "stdlibGraph", "importPaths", "targetFacts", "compilerVersion", "packageDependencies", "emitKind", "backend"], ["sourceFiles", "profile"]);
const mappedMirCache = caches.get("mappedFinalMir");
assert.match(mappedMirCache.path, /\.zero\/cache\/native\/mir-[0-9a-f]+\.zmir$/);
assert.equal(mappedMirCache.memoryMapped, true);
assert.equal(mappedMirCache.borrowedStorage, true);
assert.equal(mappedMirCache.byteLength > 0, true);
assert.equal(typeof mappedMirCache.codegenImmediate, "boolean");
assert.equal(typeof mappedMirCache.programReconstructed, "boolean");
assert.equal(body.incrementalInvalidation.graphInput.mappedFinalMir.path, mappedMirCache.path);
assert.equal(body.incrementalInvalidation.graphInput.mappedFinalMir.memoryMapped, true);
assert.equal(body.incrementalInvalidation.graphInput.mappedFinalMir.borrowedStorage, true);
assert.equal(body.incrementalInvalidation.graphInput.mappedFinalMir.codegenImmediate, mappedMirCache.codegenImmediate);
assert.equal(body.incrementalInvalidation.graphInput.mappedFinalMir.programReconstructed, mappedMirCache.programReconstructed);
}
assertCacheInputs("emittedObject", ["graphHash", "stdlibGraph", "importPaths", "targetFacts", "profile", "compilerVersion", "packageDependencies"], ["sourceFiles"]);
const parseTreeCache = caches.get("parseTree");
assert.equal(parseTreeCache.invalidatesOn, "ProgramGraph input");
if (programGraphParseTreeKeys.has(artifact)) assert.equal(parseTreeCache.key, programGraphParseTreeKeys.get(artifact));
else programGraphParseTreeKeys.set(artifact, parseTreeCache.key);
assert.equal(body.incrementalInvalidation.sourceKind, "program-graph");
assert.equal(body.incrementalInvalidation.graphInput.artifact, artifact);
assert.equal(body.incrementalInvalidation.graphInput.graphHash, body.graph.graphHash);
assert.equal(body.incrementalInvalidation.graphInput.parserArtifactsInKey, false);
assert(body.incrementalInvalidation.graphInput.keyedBy.includes("graphHash"));
assert(body.incrementalInvalidation.graphInput.keyedBy.includes("nodeHashes"));
assert(body.incrementalInvalidation.graphInput.keyedBy.includes("typeFacts"));
assert(body.incrementalInvalidation.graphInput.keyedBy.includes("symbolFacts"));
assert(body.incrementalInvalidation.graphInput.keyedBy.includes("modulePaths"));
assert(body.incrementalInvalidation.graphInput.keyedBy.includes("importPaths"));
assert.equal(body.incrementalInvalidation.changedInputs.graphArtifact, artifact);
assert.equal(body.incrementalInvalidation.interfaceFingerprints.sourceKind, "program-graph");
assert.equal(body.incrementalInvalidation.interfaceFingerprints.graphHash, body.graph.graphHash);
}
function assertRepositoryGraphNativeCheck(body, sourceProjectionState = "clean", options: { graphHirToMirUsed?: boolean } = {}) {
const graphHirToMirUsed = options.graphHirToMirUsed === false ? false : true;
assert.equal(body.graphCompiler.input, "repository-graph-store");
assert.equal(body.graphCompiler.graphStoreLoaded, true);
assert.equal(body.graphCompiler.sourceProjectionRequiredForCompilerInput, false);
assert.equal(body.graphCompiler.sourceProjectionState, sourceProjectionState);
assert.equal(body.graphCompiler.graphNativeCheckerUsed, true);
assert.equal(body.graphCompiler.graphHirToMirUsed, graphHirToMirUsed);
assert.equal(body.graphCompiler.unsupportedGraphFacts.count, 0);
assert.equal(body.graphCompiler.resolution.ok, true);
assert.equal(body.graphCompiler.resolution.state, "resolved-graph-facts");
assert.equal(body.graphCompiler.checking.ok, true);
assert.equal(body.graphCompiler.checking.state, "checked-graph-readiness-facts");
assert.equal(body.graphCompiler.checking.scope, "resolution-package-target-and-graph-mir-readiness");
assert.equal(body.graphCompiler.checking.semanticDiagnosticsEnforced, false);
assert.equal(body.graphCompiler.checking.authority, "ProgramGraphStore");
assert.equal(body.graphCompiler.checking.sourceTextAuthority, false);
assert.equal(body.graphCompiler.semanticFacts.state, "typed-facts");
assert.equal(body.graphCompiler.semanticFacts.ok, true);
const targetReady = body.targetReadiness?.ok === true;
const compilerInputReady = targetReady && graphHirToMirUsed;
assert.equal(body.graphCompiler.defaultReadiness.compilerInputReady, compilerInputReady);
assert.equal(body.graphCompiler.defaultReadiness.claim, compilerInputReady ? "ready-for-repository-graph-input" : "blocked");
assert.equal(body.graphCompiler.defaultReadiness.sourceFreeCompile, compilerInputReady);
assert.equal(body.graphCompiler.defaultReadiness.sourceProjectionRequired, false);
assert.equal(body.graphCompiler.defaultReadiness.sourceProjectionState, sourceProjectionState);
assert.equal(body.graphCompiler.defaultReadiness.graphMir.used, graphHirToMirUsed);
assert.equal(Object.hasOwn(body.graphCompiler.defaultReadiness, "fallback"), false);
assert.equal(body.graphCompiler.defaultReadiness.performance.validationInLoad, true);
assert.equal(body.graphCompiler.defaultReadiness.cacheInvalidation.parserArtifactsInKey, false);
assert(body.graphCompiler.defaultReadiness.cacheInvalidation.keyedBy.includes("nodeHashes"));
assert(body.graphCompiler.defaultReadiness.cacheInvalidation.keyedBy.includes("symbolFacts"));
assert(body.graphCompiler.defaultReadiness.cacheInvalidation.keyedBy.includes("modulePaths"));
assert(body.graphCompiler.defaultReadiness.cacheInvalidation.keyedBy.includes("importPaths"));
assert.equal(body.graphCompiler.defaultReadiness.targetReadinessOk, targetReady);
assert.equal(body.compileTime.deterministic, true);
assert.equal(body.targetReadiness.languageOk, true);
assert.equal(body.safetyFacts.schemaVersion, 1);
}
const graphHashPrime = 1099511628211n;
const graphHashMask = (1n << 64n) - 1n;
function graphHashText(hash, text) {
for (const byte of Buffer.from(text ?? "")) {
hash ^= BigInt(byte);
hash = (hash * graphHashPrime) & graphHashMask;
}
hash ^= 0xffn;
return (hash * graphHashPrime) & graphHashMask;
}
function graphHashU64(hash, value) {
let item = BigInt(value);
for (let i = 0n; i < 8n; i++) {
hash ^= (item >> (i * 8n)) & 0xffn;
hash = (hash * graphHashPrime) & graphHashMask;
}
return hash;
}
function graphQuotedField(line, field) {
const match = line.match(new RegExp(`(?:^| )${field}:"((?:\\\\.|[^"])*)"`));
return match ? JSON.parse(`"${match[1]}"`) : "";
}
function graphBareField(line, field, fallback = "") {
const match = line.match(new RegExp(`(?:^| )${field}:([^ ]+)`));
return match ? match[1] : fallback;
}
function graphTopLevelQuoted(line, field) {
const match = line.match(new RegExp(`^${field} "([^"]*)"$`));
return match ? match[1] : "";
}
function graphNodeHandle(line) {
const match = line.match(/^node (#[A-Za-z0-9_.-]+)/);
return match ? match[1] : "";
}
function graphNodeKind(line) {
const match = line.match(/^node #[A-Za-z0-9_.-]+ ([A-Za-z_][A-Za-z0-9_-]*)/);
return match ? match[1] : "";
}
function graphStoredModuleIdentity(text) {
if (!text) return "module:main";
if (text.startsWith("module:") || text.startsWith("package:")) return text;
return `module:${text}`;
}
function graphEdgeRecord(line) {
const match = line.match(/^edge (#[A-Za-z0-9_.-]+) ([A-Za-z_][A-Za-z0-9_-]*) ([^ ]+)/);
return {
line,
from: match?.[1] ?? "",
kind: match?.[2] ?? "",
to: match?.[3] ?? "",
target: graphBareField(line, "target", "node"),
order: graphBareField(line, "order", "0"),
};
}
function graphDomainId(domain, hash) {
return `${domain}:${hash.toString(16).padStart(16, "0")}`;
}
function graphNodeDeclaresSymbol(node) {
if (!node?.name) return false;
return [
"Module",
"Const",
"CImport",
"TypeAlias",
"Shape",
"Interface",
"Enum",
"Choice",
"Function",
"Param",
"Field",
"EnumCase",
"ChoiceCase",
"Let",
"ErrorVariant",
].includes(node.kind);
}
function graphNodeHash(line) {
let hash = 1469598103934665603n;
hash = graphHashText(hash, graphNodeKind(line));
hash = graphHashText(hash, graphQuotedField(line, "name"));
hash = graphHashText(hash, graphQuotedField(line, "type"));
hash = graphHashText(hash, graphQuotedField(line, "value"));
hash = graphHashU64(hash, graphBareField(line, "public", "false") === "true" ? 1n : 0n);
hash = graphHashU64(hash, graphBareField(line, "mutable", "false") === "true" ? 1n : 0n);
hash = graphHashU64(hash, graphBareField(line, "static", "false") === "true" ? 1n : 0n);
hash = graphHashU64(hash, graphBareField(line, "fallible", "false") === "true" ? 1n : 0n);
hash = graphHashU64(hash, graphBareField(line, "exportC", "false") === "true" ? 1n : 0n);
return graphDomainId("nodehash", hash);
}
function graphSymbolComponent(text) {
let out = "";
for (const ch of text ?? "") out += /^[A-Za-z0-9._@/-]$/.test(ch) ? ch : "_";
return out || "main";
}
function graphIdentityName(identity) {
if (identity?.startsWith("module:")) return identity.slice("module:".length);
if (identity?.startsWith("package:")) return identity.slice("package:".length);
return identity || "main";
}
function graphModuleScopeName(moduleIdentity, moduleNode) {
const moduleName = moduleNode?.name || graphIdentityName(moduleIdentity);
if (moduleIdentity?.startsWith("package:")) return `${graphSymbolComponent(graphIdentityName(moduleIdentity))}/${graphSymbolComponent(moduleName)}`;
return graphSymbolComponent(moduleName);
}
function graphImportBindingName(node) {
if (node.value) return node.value;
const parts = (node.name ?? "").split(".");
return parts.at(-1) || node.name || "";
}
function graphSymbolName(node) {
return node.kind === "Import" ? graphImportBindingName(node) : (node.name ?? "");
}
const graphOwnerKinds = new Set([
"alias",
"arg",
"arm",
"body",
"cImport",
"case",
"choice",
"const",
"constraint",
"declaredType",
"default",
"effect",
"else",
"enum",
"error",
"expr",
"field",
"function",
"guard",
"import",
"interface",
"left",
"method",
"param",
"rangeEnd",
"returnType",
"right",
"shape",
"statement",
"target",
"then",
"type",
"typeArg",
"typeParam",
"value",
"variant",
]);
function graphOwnerEdgeForNode(edges, nodeId) {
return edges.find((edge) => edge.target === "node" && edge.to === nodeId && graphOwnerKinds.has(edge.kind)) ?? null;
}
function graphSymbolOwner(nodesById, edges, node) {
let current = node?.id ?? "";
for (let depth = 0; current && depth < nodesById.size; depth++) {
const ownerEdge = graphOwnerEdgeForNode(edges, current);
if (!ownerEdge) return null;
const owner = nodesById.get(ownerEdge.from);
if (!owner) return null;
if (owner.kind === "Module" || graphNodeDeclaresSymbol(owner)) return owner;
current = owner.id;
}
return null;
}
function graphNodeSymbolNamespace(node, ownerEdge) {
switch (node.kind) {
case "Module": return "module";
case "Import": return "import";
case "CImport": return "c-import";
case "Const": return "value";
case "Function": return ownerEdge?.kind === "method" ? "method" : "value";
case "TypeAlias":
case "Shape":
case "Interface":
case "Enum":
case "Choice":
return "type";
case "Param": return "param";
case "Field": return "field";
case "EnumCase":
case "ChoiceCase":
case "ErrorVariant":
return "variant";
case "Let": return "local";
default: return "";
}
}
function graphLocalSymbolSuffix(node) {
if (node.kind !== "Let") return "";
const suffix = node.id.split(".").at(-1) || node.id;
return suffix ? `@${graphSymbolComponent(suffix)}` : "";
}
function graphNodeSymbolIdFromGraph(moduleIdentity, nodesById, edges, node, depth = 0) {
if (!graphNodeDeclaresSymbol(node) || depth > nodesById.size) return "";
const name = graphSymbolName(node);
if (!name) return "";
if (node.kind === "Module") return `symbol:${graphModuleScopeName(moduleIdentity, node)}::module`;
const ownerEdge = graphOwnerEdgeForNode(edges, node.id);
const owner = graphSymbolOwner(nodesById, edges, node);
const namespace = graphNodeSymbolNamespace(node, ownerEdge);
if (!namespace) return "";
if (owner?.kind === "Module") {
return `symbol:${graphModuleScopeName(moduleIdentity, owner)}::${graphSymbolComponent(namespace)}.${graphSymbolComponent(name)}${graphLocalSymbolSuffix(node)}`;
}
if (owner) {
const ownerSymbol = graphNodeSymbolIdFromGraph(moduleIdentity, nodesById, edges, owner, depth + 1);
if (ownerSymbol) return `${ownerSymbol}/${graphSymbolComponent(namespace)}.${graphSymbolComponent(name)}${graphLocalSymbolSuffix(node)}`;
}
return `symbol:${graphSymbolComponent(graphIdentityName(moduleIdentity))}::${graphSymbolComponent(namespace)}.${graphSymbolComponent(name)}${graphLocalSymbolSuffix(node)}`;
}
function graphNodeTypeId(line) {
const type = graphQuotedField(line, "type");
return type ? graphDomainId("type", graphHashText(1469598103934665603n, type)) : "";
}
function graphNodeEffectId(line) {
const kind = graphNodeKind(line);
const name = graphQuotedField(line, "name");
return kind === "EffectRef" && name ? graphDomainId("effect", graphHashText(1469598103934665603n, name)) : "";
}
function recomputeGraphHash(text) {
const lines = text.trimEnd().split("\n");
const moduleIdentity = graphStoredModuleIdentity(graphTopLevelQuoted(lines.find((line) => line.startsWith("module ")) ?? "", "module"));
const nodeRecords = lines.filter((item) => item.startsWith("node ")).map((line) => ({
line,
id: graphNodeHandle(line),
kind: graphNodeKind(line),
name: graphQuotedField(line, "name"),
type: graphQuotedField(line, "type"),
value: graphQuotedField(line, "value"),
}));
const edgeRecords = lines.filter((item) => item.startsWith("edge ")).map(graphEdgeRecord);
const nodesById = new Map(nodeRecords.map((node) => [node.id, node]));
let hash = 1469598103934665603n;
hash = graphHashU64(hash, 1n);
hash = graphHashText(hash, moduleIdentity);
for (const node of nodeRecords) {
const line = node.line;
hash = graphHashText(hash, node.id);
hash = graphHashText(hash, graphQuotedField(line, "nodeHash") || graphNodeHash(line));
hash = graphHashText(hash, graphQuotedField(line, "symbolId") || graphNodeSymbolIdFromGraph(moduleIdentity, nodesById, edgeRecords, node));
hash = graphHashText(hash, graphQuotedField(line, "typeId") || graphNodeTypeId(line));
hash = graphHashText(hash, graphQuotedField(line, "effectId") || graphNodeEffectId(line));
}
for (const edge of edgeRecords) {
hash = graphHashText(hash, edge.from);
hash = graphHashText(hash, edge.to);
hash = graphHashText(hash, edge.kind);
hash = graphHashText(hash, edge.target);
hash = graphHashU64(hash, edge.order);
}
return `graph:${hash.toString(16).padStart(16, "0")}`;
}
function repositoryGraphPayload(storeText) {
const marker = "\ngraph\n";
const start = storeText.indexOf(marker);
assert.notEqual(start, -1);
return storeText.slice(start + marker.length);
}
function repositoryGraphModuleIdentity(storeText, graphText) {
const stored = storeText.match(/^moduleIdentity "([^"]+)"$/m)?.[1];
if (stored) return stored;
const moduleLine = graphText.split("\n").find((line) => line.startsWith("module ")) ?? "";
return graphStoredModuleIdentity(graphTopLevelQuoted(moduleLine, "module"));
}
function graphNodeHasSourceMap(line) {
return graphQuotedField(line, "path") !== "" ||
Number.parseInt(graphBareField(line, "line", "0"), 10) > 0 ||
Number.parseInt(graphBareField(line, "column", "0"), 10) > 0;
}
function graphNodeIsDeclaration(kind) {
return [
"Import",
"CImport",
"Const",
"TypeAlias",
"Shape",
"Interface",
"Enum",
"Choice",
"Function",
"Param",
"Field",
"EnumCase",
"ChoiceCase",
"Let",
"ErrorVariant",
].includes(kind);
}
function graphNodeIsScope(kind) {
return [
"Module",
"Function",
"Block",
"Shape",
"Interface",
"Enum",
"Choice",
].includes(kind);
}
function graphTypeIsCapability(type) {
return ["World", "Fs", "File", "Net", "HttpClient"].includes(type);
}
function graphTypeIsOwnership(type) {
return type.includes("owned<") || type.includes("MutSpan<") || type.includes("mutref<");
}
function graphTypeIsResource(type) {
return ["World", "Fs", "File"].includes(type) || type.includes("owned<File>");
}
function repositoryGraphCompilerTableCounts(storeText) {
const graphText = repositoryGraphPayload(storeText);
const moduleIdentity = repositoryGraphModuleIdentity(storeText, graphText);
const nodeLines = graphText.split("\n").filter((line) => line.startsWith("node "));
const edgeLines = graphText.split("\n").filter((line) => line.startsWith("edge "));
const projection = storeText.match(/^projection path:/gm)?.length ?? 0;
const counts = {
schema: 1,
package: moduleIdentity.startsWith("package:") ? 1 : 0,
module: 0,
declaration: 0,
scope: 0,
import: 0,
symbol: 0,
type: 0,
effect: 0,
capability: 0,
ownership: 0,
resource: 0,
node: nodeLines.length,
edge: edgeLines.length,
projection,
sourceMap: 0,
};
for (const line of nodeLines) {
const kind = graphNodeKind(line);
const type = graphQuotedField(line, "type");
const fallible = graphBareField(line, "fallible", "false") === "true";
const mutable = graphBareField(line, "mutable", "false") === "true";
const node = {
id: graphNodeHandle(line),
kind,
name: graphQuotedField(line, "name"),
type,
value: graphQuotedField(line, "value"),
};
if (kind === "Module") counts.module++;
if (graphNodeIsDeclaration(kind)) counts.declaration++;
if (graphNodeIsScope(kind)) counts.scope++;
if (kind === "Import" || kind === "CImport") counts.import++;
if (graphQuotedField(line, "symbolId") || graphNodeDeclaresSymbol(node)) counts.symbol++;
if (graphQuotedField(line, "typeId") || type) counts.type++;
if (graphQuotedField(line, "effectId") || kind === "EffectRef" || fallible) counts.effect++;
if (fallible || graphTypeIsCapability(type)) counts.capability++;
if (mutable || graphTypeIsOwnership(type)) counts.ownership++;
if (graphTypeIsResource(type)) counts.resource++;
if (graphNodeHasSourceMap(line)) counts.sourceMap++;
}
return counts;
}
function repositoryGraphCompilerTablesLine(storeText) {
const counts = repositoryGraphCompilerTableCounts(storeText);
return `compilerTables schema:${counts.schema} package:${counts.package} module:${counts.module} declaration:${counts.declaration} scope:${counts.scope} import:${counts.import} symbol:${counts.symbol} type:${counts.type} effect:${counts.effect} capability:${counts.capability} ownership:${counts.ownership} resource:${counts.resource} node:${counts.node} edge:${counts.edge} projection:${counts.projection} sourceMap:${counts.sourceMap}`;
}
function refreshRepositoryGraphCompilerMetadata(storeText) {
const compilerStoreLine = 'compilerStore schemaVersion:1 shape:"compiler-oriented-tables" semanticOk:true semanticValidity:"shape-valid" sourceProjectionRequired:false sourceMapRequired:false storageInterface:"ProgramGraphStore"';
const compilerHashInputsLine = 'compilerHashInputs graphHashExcludes:"source-path,line,column,projection-text" nodeHashExcludes:"source-path,line,column,projection-text" idCollisionFallbackMayUse:"source-path,line,column"';
return storeText
.replace(/^compilerStore .*$/m, compilerStoreLine)
.replace(/^compilerTables .*$/m, repositoryGraphCompilerTablesLine(storeText))
.replace(/^compilerHashInputs .*$/m, compilerHashInputsLine);
}
function repeatBuildHash(args, firstPath, repeatOut, repeatPath = repeatOut) {
const repeatArgs = [...args];
const outIndex = repeatArgs.indexOf("--out");
assert(outIndex >= 0, "repeat build args should include --out");
repeatArgs[outIndex + 1] = repeatOut;
rmSync(repeatPath, { force: true, recursive: true });
rmSync(`${repeatOut}.exe`, { force: true });
const repeatReport = json(repeatArgs).body;
assert.equal(repeatReport.generatedCBytes, 0);
assert.equal(repeatReport.cBridgeFallback ?? false, false);
assert.equal(sha256File(repeatPath), sha256File(firstPath));
return repeatReport;
}
function hasAarch64Instruction(bytes, expected) {
for (let offset = 0; offset + 4 <= bytes.length; offset++) {
if (bytes.readUInt32LE(offset) === expected) return true;
}
return false;
}
function hasAarch64CondBranch(bytes, cond) {
for (let offset = 0; offset + 4 <= bytes.length; offset++) {
const instruction = bytes.readUInt32LE(offset);
if ((instruction & 0xff000010) === 0x54000000 && (instruction & 0xf) === cond) return true;
}
return false;
}
function hasAarch64VoidReturnEpilogue(bytes) {
for (let offset = 0; offset + 12 <= bytes.length; offset++) {
if (bytes.readUInt32LE(offset) !== 0x52800000) continue;
let cursor = offset + 4;
const maybeAddSp = bytes.readUInt32LE(cursor);
if (((maybeAddSp & 0xffc003ff) >>> 0) === 0x910003ff) cursor += 4;
if (cursor + 8 <= bytes.length &&
bytes.readUInt32LE(cursor) === 0xa8c17bfd &&
bytes.readUInt32LE(cursor + 4) === 0xd65f03c0) return true;
}
return false;
}
function assertMachOLoadCommand(bytes, expectedCommand, expectedSize) {
const ncmds = bytes.readUInt32LE(16);
for (let offset = 32, i = 0; i < ncmds; i++) {
const cmd = bytes.readUInt32LE(offset);
const cmdsize = bytes.readUInt32LE(offset + 4);
assert(cmdsize >= 8);
assert(offset + cmdsize <= bytes.length);
if (cmd === expectedCommand) {
if (expectedSize !== undefined) assert.equal(cmdsize, expectedSize);
return bytes.subarray(offset, offset + cmdsize);
}
offset += cmdsize;
}
assert.fail(`missing Mach-O load command 0x${expectedCommand.toString(16)}`);
}
function elfPackedErrorBytes(code, flagged = false) {
// Raises functions pack (code << 32); world-main envelopes fold the error
// flag into the same movabs as (code << 32) | 1, since a separate 32-bit
// flag mov would zero-extend over the code.
const bytes = Buffer.alloc(10);
bytes[0] = 0x48;
bytes[1] = 0xb8;
bytes.writeBigUInt64LE((BigInt(code) << 32n) | (flagged ? 1n : 0n), 2);
return bytes;
}
function hasAnsiControlBytes(text) {
return /\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b\][^\x07]*(?:\x07|\x1b\\)/.test(text);
}
function removeInlineTests(path) {
if (!existsSync(path)) return;
const source = readFileSync(path, "utf8");
const testStart = source.indexOf("\n\ntest ");
if (testStart >= 0) writeFileSync(path, `${source.slice(0, testStart)}\n`);
}
function tomlQuote(value: unknown) {
return JSON.stringify(String(value));
}
function tomlArray(values: unknown[]) {
return `[${values.map(tomlQuote).join(", ")}]`;
}
function appendManifestFields(lines: string[], object: Record<string, unknown>, order: string[]) {
for (const key of order) {
if (!(key in object)) continue;
const value = object[key];
if (Array.isArray(value)) lines.push(`${key} = ${tomlArray(value)}`);
else if (typeof value === "boolean") lines.push(`${key} = ${value ? "true" : "false"}`);
else lines.push(`${key} = ${tomlQuote(value)}`);
}
}
function manifestToml(manifest: Record<string, any>) {
const lines = ["[package]"];
appendManifestFields(lines, manifest.package ?? {}, ["name", "version", "license"]);
for (const [targetName, target] of Object.entries(manifest.targets ?? {})) {
lines.push("", `[targets.${targetName}]`);
appendManifestFields(lines, target as Record<string, unknown>, ["kind", "main", "graph", "defaultTarget", "devTarget", "releaseProfile"]);
}
if (manifest.repositoryGraph) {
lines.push("", "[repositoryGraph]");
appendManifestFields(lines, manifest.repositoryGraph, ["compilerInput"]);
}
for (const sectionName of ["deps", "dependencies"]) {
if (!manifest[sectionName]) continue;
lines.push("", `[${sectionName}]`);
for (const [name, value] of Object.entries(manifest[sectionName])) {
if (typeof value === "string") lines.push(`${name} = ${tomlQuote(value)}`);
}
for (const [name, value] of Object.entries(manifest[sectionName])) {
if (typeof value === "string") continue;
lines.push("", `[${sectionName}.${name}]`);
appendManifestFields(lines, value as Record<string, unknown>, ["path", "version", "targets", "target"]);
}
}
for (const [name, lib] of Object.entries(manifest.c?.libs ?? {})) {
lines.push("", `[c.libs.${name}]`);
appendManifestFields(lines, lib as Record<string, unknown>, ["headers", "include", "lib", "link", "mode", "pkg_config", "pkgConfig"]);
}
return `${lines.join("\n").replace(/\n{3,}/g, "\n\n")}\n`;
}
function writeZeroTomlSync(root: string, manifest: Record<string, any>) {
writeFileSync(join(root, "zero.toml"), manifestToml(manifest));
}
function parseSimpleTomlManifest(text: string) {
const manifest: Record<string, any> = {};
let section: string[] = [];
for (const rawLine of text.split(/\r?\n/)) {
const line = rawLine.trim();
if (!line || line.startsWith("#")) continue;
const sectionMatch = line.match(/^\[([A-Za-z0-9_.-]+)\]$/);
if (sectionMatch) {
section = sectionMatch[1].split(".");
let cursor = manifest;
for (const part of section) cursor = cursor[part] ??= {};
continue;
}
const valueMatch = line.match(/^([A-Za-z0-9_.-]+)\s*=\s*"([^"]*)"$/);
if (!valueMatch) continue;
let cursor = manifest;
for (const part of section) cursor = cursor[part] ??= {};
cursor[valueMatch[1]] = valueMatch[2];
}
return manifest;
}
function readGeneratedManifest(root: string) {
const tomlPath = join(root, "zero.toml");
if (existsSync(tomlPath)) return parseSimpleTomlManifest(readFileSync(tomlPath, "utf8"));
return JSON.parse(readFileSync(join(root, "zero.json"), "utf8"));
}
function assertTemplateManifest(kind, manifest, readme) {
assert.equal(manifest.package.version, "0.1.0");
assert.equal(manifest.targets.cli.defaultTarget, "linux-musl-x64");
assert.equal(manifest.targets.cli.devTarget, "host");
assert.equal(manifest.targets.cli.releaseProfile, "release-small");
if (manifest.docs) {
assert.equal(manifest.docs.readme, "README.md");
assert.deepEqual(manifest.docs.examples, [manifest.targets.cli.main]);
}
assert.match(readme, /zero check/);
assert.match(readme, /zero test/);
assert.match(readme, /zero dev --json/);
if (kind === "lib") {
assert.equal(manifest.targets.cli.main, "src/lib.0");
assert.match(readme, /zero doc --json/);
} else {
assert.equal(manifest.targets.cli.main, "src/main.0");
assert.match(readme, /zero run/);
assert.match(readme, /zero build --target linux-musl-x64/);
}
}
function assertDevReport(report, kind) {
assert.equal(report.schemaVersion, 1);
assert.equal(report.ok, true);
assert.equal(report.mode, "watch-plan");
assert.equal(report.generatedCBytes, 0);
assert.equal(report.cBridgeFallback, false);
assert.equal(report.watch.planOnly, true);
assert.equal(report.watch.manifest, "zero.toml");
assert.deepEqual(report.watch.rerun, ["check", "test", "examples"]);
assert(Array.isArray(report.watch.packageLocks));
assert(Array.isArray(report.watch.generatedBindingInputs));
assert.equal(report.watch.restartOnSuccess, kind !== "lib");
assert.equal(report.restart.runnableCli, kind !== "lib");
assert.equal(report.trace.enabled, true);
assert.equal(report.trace.requested, false);
assert.equal(report.trace.phaseTiming, true);
assert.equal(report.trace.cacheFacts, true);
assert.equal(report.trace.diagnosticsPassthrough, true);
assert.equal(report.partialDiagnostics.stable, true);
assert.equal(report.partialDiagnostics.whileCodegenPending, true);
assert.equal(report.interfaceFingerprints.algorithm, "fnv1a64-zero-interface-v1");
assert.match(report.interfaceFingerprints.targetFactsHash, /^[0-9a-f]{16}$/);
assert(report.interfaceFingerprints.modules.length >= 1);
assert.equal(report.incrementalInvalidation.partialDiagnosticsStable, true);
assert.match(String(report.incrementalInvalidation.cacheHits), /^\d+$/);
assert.match(String(report.incrementalInvalidation.cacheMisses), /^\d+$/);
assert(report.actions.some((action) => action.kind === "check"));
assert(report.actions.some((action) => action.kind === "test"));
assert(report.actions.some((action) => action.kind === "examples"));
assert(report.actions.some((action) => action.kind === "restart" && action.enabled === (kind !== "lib")));
}
function assertReleaseTargetContract(report, expected) {
const contract = report.releaseTargetContract;
assert(contract, "release target contract should be present");
assert.equal(contract.schemaVersion, 1);
assert.equal(contract.target, expected.target);
assert.equal(contract.emit, expected.emit);
assert.equal(contract.artifactKind, expected.artifactKind);
assert.equal(contract.objectFormat, expected.objectFormat);
assert.equal(contract.linkerFlavor, expected.linkerFlavor);
assert.equal(contract.libc.targetMode, expected.targetLibcMode);
assert.equal(contract.libc.artifactMode, "none");
assert.equal(contract.generatedCBytes, 0);
assert.equal(contract.cBridgeFallback, false);
assert.equal(contract.fallbackPolicy, "explicit-direct-never-c-bridge");
assert.equal(contract.readiness.status, "supported");
assert.equal(contract.readiness.directArtifact, true);
assert.equal(contract.sysroot.requiredByArtifact, false);
assert.equal(contract.determinism.repeatBuildHash, "checked-by-command-contracts");
assert(contract.capabilityFacts.some((capability) => capability.name === "memory" && capability.available === true));
}
function directExeEmitterForTarget(target: string) {
if (target.startsWith("linux") && target.includes("arm64")) return "zero-elf-aarch64-exe";
if (target.startsWith("linux")) return "zero-elf64-exe";
if (target === "darwin-x64") return "zero-macho-x64-exe";
if (target.startsWith("darwin")) return "zero-macho64-exe";
if (target === "win32-arm64.exe") return "zero-coff-aarch64-exe";
if (target.startsWith("win32")) return "zero-coff-x64-exe";
return "direct";
}
const generatedCBytesBeforeReadOnlyCommands = json(["size", "--json", "examples/memory-package"]).body.generatedCBytes;
assert.match(zero(["--version"]).stdout, /^zero 0\.3\.4 \(build (?:[0-9a-f]{7,40}|unknown)\)\n$/);
const version = json(["--version", "--json"]).body;
assert.equal(version.schemaVersion, 1);
assert.equal(version.version, "0.3.4");
assert.match(version.commit, /^(?:[0-9a-f]{7,40}|unknown)$/);
assert.equal(version.backend, "zero-c");
assert.equal(typeof version.host, "string");
assert(version.targets.includes("darwin-arm64"));
assert(version.targets.includes("linux-musl-x64"));
assert(version.targets.includes("win32-x64.exe"));
assert.equal(typeof version.targetCompiler.available, "boolean");
const doctor = json(["doctor", "--json"]).body;
assert.equal(doctor.schemaVersion, 1);
assert(["ok", "warning", "error"].includes(doctor.status));
assert(doctor.checks.some((check) => check.name === "native-c-compiler"));
assert(doctor.checks.some((check) => check.name === "target-c-compiler"));
assert(doctor.checks.some((check) => check.name === "llvm-toolchain"));
assert(["ready", "tool-missing", "unsupported-target"].includes(doctor.llvmToolchain.status));
assert.equal(typeof doctor.llvmToolchain.compiler, "string");
assert.equal(doctor.llvmToolchain.backendLifecycle.stability, "experimental");
assert.equal(doctor.llvmToolchain.backendLifecycle.defaultEligible, false);
assert.equal(doctor.llvmToolchain.backendLifecycle.releaseEligible, false);
assert(doctor.checks.some((check) => check.name === "cross-executable-builds" && /non-host executable builds|target-capable C compiler available/.test(check.message)));
assert(doctor.checks.some((check) => check.name === "path" && /PATH/.test(check.message)));
assert(doctor.checks.some((check) => check.name === "host-target" && /host target/.test(check.message)));
assert(doctor.checks.some((check) => check.name === "target-sdk-sysroot" && /sysroot|target-capable C compiler/.test(check.message)));
assert(doctor.checks.some((check) => check.name === "docs-examples"));
for (const [command, expected] of [
[["--help"], /zero init --template cli hello/],
[["check", "--help"], /Usage: zero check/],
[["build", "--help"], /Usage: zero build/],
[["run", "--help"], /Usage: zero run/],
[["test", "--help"], /Usage: zero test/],
[["fmt", "--help"], /Usage: zero fmt/],
[["init", "--help"], /--template cli\|lib\|package/],
[["skills", "--help"], /Usage: zero skills/],
[["targets", "--help"], /Usage: zero targets/],
[["tokens", "--help"], /Usage: zero tokens/],
[["parse", "--help"], /Usage: zero parse/],
[["query", "--help"], /Usage: zero query \[--json\] \[--fn <name>\] \[--find <text>\] \[--refs <name>\] \[--calls <name>\] \[--node <id>\] \[--depth <n>\] \[--full\] \[--handles\] \[--no-help\] \[graph-input\|name\]/],
[["inspect", "--help"], /Usage: zero init \[--template cli\|lib\|package\] \[project-path\]; zero query\|view\|diff\|dump\|inspect\|validate\|source-map\|roundtrip \[--json\] \[graph-input\]/],
[["diff", "--help"], /Usage: zero diff \[--fn <name>\] \[graph-input\]/],
[["size", "--help"], /Usage: zero size/],
[["explain", "--help"], /Usage: zero explain/],
[["fix", "--help"], /Usage: zero fix/],
] as Array<[string[], RegExp]>) {
assert.match(zero(command).stdout, expected);
}
const removedNewCommand = zero(["new", "--help"], { allowFailure: true });
assert.notEqual(removedNewCommand.code, 0);
assert.match(removedNewCommand.stdout, /zero init --template cli hello/);
const tomlInitRoot = join(outDir, "init-toml-manifest");
rmSync(tomlInitRoot, { recursive: true, force: true });
const tomlInit = json(["init", "--json", "--manifest", "toml", tomlInitRoot]).body;
assert.equal(tomlInit.ok, true);
assert(tomlInit.writes.includes(join(tomlInitRoot, "zero.toml")));
assert(tomlInit.writes.includes(join(tomlInitRoot, "zero.graph")));
assert(existsSync(join(tomlInitRoot, "zero.toml")));
assert(!existsSync(join(tomlInitRoot, "zero.json")));
assert.match(readFileSync(join(tomlInitRoot, "zero.toml"), "utf8"), /\[package\]/);
const defaultInitRoot = join(outDir, "init-default-manifest");
rmSync(defaultInitRoot, { recursive: true, force: true });
const defaultInit = json(["init", "--json", defaultInitRoot]).body;
assert.equal(defaultInit.ok, true);
assert(defaultInit.writes.includes(join(defaultInitRoot, "zero.toml")));
assert(!existsSync(join(defaultInitRoot, "zero.json")));
for (const [code, goodExample, stalePattern] of [
["STD003", "var bytes: [4]u8 = [0, 0, 0, 0]", /\bmut bytes\b|std\.mem\.fill bytes/],
["TYP026", "alias Bytes = Span<u8>", /\btype [A-Z][A-Za-z0-9_]* =/],
["PUB001", "pub const answer: i32 = 42", /pub const answer (42|i32 42)/],
["IFC002", "fn describe(self: ref<Self>) -> String", /type Person\n|fn describe (String|i32)|ret self/],
["IFC003", "fn describe(self: ref<Self>) -> String", /fn describe (String|i32)|ret self/],
["IFC004", "fn describe(self: ref<Self>) -> String", /fn describe (String|i32)|ret self/],
["IFC005", "fn describe(self: ref<Self>) -> String", /fn describe (String|i32)|ret self/],
["STC001", "type Buf<static N: usize> {", /type Buf<static N: usize>\n|len usize/],
["RCV002", "var vec: FixedVec<u8, 4>", /\bmut vec\b|vec\.push 1|use `mut`/],
] as Array<[string, string, RegExp]>) {
const explanation = json(["explain", "--json", code]).body;
assert.equal(explanation.code, code);
assert(explanation.examples.good.includes(goodExample), `${code} explain good example should use canonical source`);
assert.doesNotMatch(
`${explanation.repair.summary}\n${explanation.examples.bad}\n${explanation.examples.good}`,
stalePattern,
`${code} explain examples should use canonical source syntax`,
);
}
// Every diagnostic code the compiler can emit must resolve in `zero explain`.
const compilerSourceDir = "native/zero-c/src";
const emittableDiagnosticCodes = new Set<string>();
for (const entry of readdirSync(compilerSourceDir)) {
if (!entry.endsWith(".c")) continue;
const source = readFileSync(join(compilerSourceDir, entry), "utf8");
for (const match of source.matchAll(/"([A-Z]{3,4}[0-9]{3})"/g)) emittableDiagnosticCodes.add(match[1]);
}
assert(emittableDiagnosticCodes.size > 100, "expected to discover the compiler diagnostic code catalog");
for (const code of [...emittableDiagnosticCodes].sort()) {
const explained = json(["explain", "--json", code], { allowFailure: true });
assert.equal(explained.code, 0, `zero explain ${code} must have an explain entry`);
assert.equal(explained.body.code, code, `zero explain ${code} must explain the requested code`);
}
const graphHelp = zero(["inspect", "--help"]).stdout;
assert.match(graphHelp, /zero dump\|validate\|roundtrip \[--json\] \[--format text\|binary\] --out <program-graph-artifact> \[graph-input\]; zero import \[--json\] \[--format text\|binary\] --out <program-graph-artifact> \[project\|zero\.toml\|zero\.json\|file\.0\]/);
assert.match(graphHelp, /zero view \[--json\] \[--fn <name> \[--around <text>\|--handles\]\] \[--outline <module-or-file>\] \[--out <file\.0>\] \[graph-input\]/);
assert.match(graphHelp, /zero diff \[--fn <name>\] \[graph-input\]/);
assert.match(graphHelp, /zero source-map \[--json\] \[graph-input\]/);
assert.match(graphHelp, /zero query \[--json\] \[--fn <name>\] \[--find <text>\] \[--refs <name>\] \[--calls <name>\] \[--node <id>\] \[--depth <n>\] \[--full\] \[--handles\] \[--no-help\] \[graph-input\|name\]/);
assert.match(graphHelp, /zero reconcile \[--json\] <base-graph-input> --source <edited-file\.0\|project\|zero\.toml\|zero\.json>/);
assert.match(graphHelp, /zero status\|verify-projection \[--json\] \[project\|zero\.toml\|zero\.json\|file\.0\|zero\.graph\]/);
assert.match(graphHelp, /zero import \[--json\] \[--format text\|binary\] \[project\|zero\.toml\|zero\.json\|file\.0\]/);
assert.match(graphHelp, /zero export \[--json\] \[project\|zero\.toml\|zero\.json\|file\.0\]/);
assert.match(graphHelp, /zero merge --base <base-zero\.graph> --left <left-zero\.graph> --right <right-zero\.graph> \[--json\] \[project\|zero\.toml\|zero\.json\|file\.0\]/);
assert.match(graphHelp, /zero size \[--json\] \[--target <target>\] \[--out <artifact>\] \[graph-input\]/);
assert.match(graphHelp, /Patch usage: zero patch \[--json\] \[--check-only\|--dry-run\] \[--format text\|binary\] \[--out <program-graph-artifact>\] \[graph-input\] \(<patch-file>\|--op <operation>\|--replace-fn <name> --body-file <file\|->\|--replace-in-fn <name> --old <text> --new <text>\|--rewrite <pattern> --to <template> \[--fn <name>\] \[--apply\]\)/);
assert.match(graphHelp, /Patch operation help: zero patch --op help/);
assert.match(graphHelp, /binary is the default zero\.graph encoding/);
assert.match(graphHelp, /--format text writes readable repository stores when explicitly requested/);
assert.match(graphHelp, /--format binary opts explicit graph artifact outputs into binary storage/);
assert.doesNotMatch(graphHelp, /setMain[A-Za-z]+Cli/);
assert.match(graphHelp, /replaceFunctionBody main \.\.\. end/);
assert.match(graphHelp, /replaceBlockBody #block_id \.\.\. end/);
assert.match(graphHelp, /addLetBinary fn="add" name="sum" type="i32" operator="\+"/);
assert.match(graphHelp, /addReturnExpr fn="maybe" expr="null"/);
assert.match(graphHelp, /appendStmt fn="main" stmt="check std\.http\.listen\(world, 3000_u16\)"/);
assert.match(graphHelp, /addTestBody name="api add"/);
assert.match(graphHelp, /renameTest name="api add" value="api add route"/);
assert.match(graphHelp, /deleteTest name="api add"/);
assert.match(graphHelp, /upsertFunction handle/);
assert.match(graphHelp, /zero build \[--json\] \[--emit exe\|obj\|llvm-ir\].*\[graph-input\]/);
assert.match(graphHelp, /zero run \[--target <host-target>\].*\[graph-input\] \[-- args\.\.\.\]/);
assert.match(graphHelp, /zero test \[--json\] \[--filter <name>\] \[--target <target>\] \[graph-input\]/);
assert.doesNotMatch(graphHelp, /zero graph (check|patch|size|build|run|test)/);
assert.doesNotMatch(graphHelp, /zero sync/);
const runHelp = zero(["run", "--help"]).stdout;
assert.match(runHelp, /Usage: zero run \[--backend direct\|llvm\|<direct-emitter>\]/);
assert.match(runHelp, /LLVM is explicit and requires clang/);
const rootHelp = zero(["--help"]).stdout;
assert.match(rootHelp, /zero run \[--backend direct\|llvm\|<direct-emitter>\].*\[graph-input\] \[-- args\.\.\.\]/);
assert.match(rootHelp, /zero build \[--json\] \[--emit exe\|obj\|llvm-ir\].*\[graph-input\]/);
assert.match(rootHelp, /zero test \[graph-input\]/);
assert.match(rootHelp, /zero check \[--json\] \[--target <target>\] \[--emit exe\|obj\|llvm-ir\] \[graph-input\]/);
assert.match(rootHelp, /zero fix --plan --json \[graph-input\]/);
assert.match(rootHelp, /zero patch \[--json\] \[--check-only\|--dry-run\] \[--format text\|binary\] \[--out <program-graph-artifact>\] \[graph-input\] \(<patch-file>\|--op <operation>\|--replace-fn <name> --body-file <file\|->\|--replace-in-fn <name> --old <text> --new <text>\|--rewrite <pattern> --to <template> \[--fn <name>\] \[--apply\]\)/);
assert.match(rootHelp, /zero dump\|validate\|roundtrip \[--json\] \[--format text\|binary\] \[--out <program-graph-artifact>\] \[graph-input\]/);
assert.match(rootHelp, /zero view \[--json\] \[--fn <name> \[--around <text>\|--handles\]\] \[--outline <module-or-file>\] \[--out <file\.0>\] \[graph-input\]/);
assert.match(rootHelp, /zero diff \[--fn <name>\] \[graph-input\]/);
assert.match(rootHelp, /zero source-map \[--json\] \[graph-input\]/);
assert.match(rootHelp, /zero query \[--json\] \[--fn <name>\] \[--find <text>\] \[--refs <name>\] \[--calls <name>\] \[--node <id>\] \[--depth <n>\] \[--full\] \[--handles\] \[--no-help\] \[graph-input\|name\]/);
assert.match(rootHelp, /zero reconcile \[--json\] <base-graph-input> --source <edited-file\.0\|project\|zero\.toml\|zero\.json>/);
assert.match(rootHelp, /zero status\|verify-projection \[--json\] \[project\|zero\.toml\|zero\.json\|file\.0\|zero\.graph\]/);
assert.match(rootHelp, /zero import \[--json\] \[--format text\|binary\] \[--out <program-graph-artifact>\] \[project\|zero\.toml\|zero\.json\|file\.0\]/);
assert.match(rootHelp, /zero export \[--json\] \[project\|zero\.toml\|zero\.json\|file\.0\]/);
assert.match(rootHelp, /zero merge --base <base-zero\.graph> --left <left-zero\.graph> --right <right-zero\.graph> \[--json\] \[--format text\|binary\] <project\|zero\.toml\|zero\.json\|file\.0>/);
assert.doesNotMatch(rootHelp, /zero graph (check|patch|size|build|run|test)/);
assert.doesNotMatch(rootHelp, /zero sync/);
const graphPatchHelp = zero(["patch", "--op", "help"]).stdout;
assert.match(graphPatchHelp, /program graph patch operations/);
assert.match(graphPatchHelp, /accepted by zero patch --op, --patch-text, and zero-program-graph-patch v1 files/);
assert.match(graphPatchHelp, /insert node="#id" kind="Literal"/);
assert.match(graphPatchHelp, /insertEdge from="#from" to="#to"/);
assert.match(graphPatchHelp, /replace node="#id" expect="nodehash:abc123"/);
assert.doesNotMatch(graphPatchHelp, /setMain[A-Za-z]+Cli/);
assert.match(graphPatchHelp, /replaceFunctionBody main/);
assert.match(graphPatchHelp, /replaceBlockBody #block_id/);
assert.match(graphPatchHelp, /use --replace-fn with --body-file/);
assert.match(graphPatchHelp, /--body-file - reads the body rows from stdin, so a heredoc does the whole edit in one call/);
assert.match(graphPatchHelp, /zero patch \. --replace-fn greet --body-file - <<'EOF'/);
assert.match(graphPatchHelp, /Alternative: write the rows to a file and pass its path/);
assert.match(graphPatchHelp, /zero patch \. --replace-fn greet --body-file \/tmp\/greet\.body/);
assert(graphPatchHelp.indexOf("--body-file - <<'EOF'") < graphPatchHelp.indexOf("/tmp/greet.body"), "patch help should show the stdin heredoc form before the temp-file form");
assert.match(graphPatchHelp, /--replace-in-fn/);
assert.match(graphPatchHelp, /zero patch \. --replace-in-fn greet --old 'return 1' --new 'return 2'/);
assert.match(graphPatchHelp, /--old must match the body text zero view --fn <name> prints exactly once/);
assert.match(graphPatchHelp, /advanced: node-level ops \(see zero view --fn <name> --handles\)/);
assert.match(graphPatchHelp, /replaceExpr node="#id" with="left \+ 1"/);
assert.match(graphPatchHelp, /--patch-text - reads a complete patch from stdin/);
const patchHelpInFnIdx = graphPatchHelp.indexOf("--replace-in-fn greet");
const patchHelpReplaceFnIdx = graphPatchHelp.indexOf("--replace-fn greet --body-file - <<'EOF'");
const patchHelpGrammarIdx = graphPatchHelp.indexOf("zero-program-graph-patch v1 files");
const patchHelpAdvancedIdx = graphPatchHelp.indexOf("advanced: node-level ops");
assert(patchHelpInFnIdx >= 0 && patchHelpInFnIdx < patchHelpReplaceFnIdx, "patch help leads with --replace-in-fn");
assert(patchHelpReplaceFnIdx < patchHelpGrammarIdx, "the --replace-fn heredoc precedes the op grammar reference");
assert(patchHelpGrammarIdx < patchHelpAdvancedIdx, "the op grammar precedes the advanced node-level section");
assert(graphPatchHelp.indexOf('set node="#id"') > patchHelpAdvancedIdx, "node-handle ops sit under the advanced header");
assert(graphPatchHelp.indexOf("addMain") < patchHelpAdvancedIdx, "authoring ops print before node-level ops");
assert.match(graphPatchHelp, /addLetLiteral fn="main" name="count" type="u32" value="0"/);
assert.match(graphPatchHelp, /addReturnValue fn="identity" value="input" type="i32"/);
assert.match(graphPatchHelp, /addReturnExpr fn="maybe" expr="null"/);
assert.match(graphPatchHelp, /appendStmt fn="main" stmt="check std\.http\.listen\(world, 3000_u16\)"/);
assert.match(graphPatchHelp, /addTestBody name="api add"/);
assert.match(graphPatchHelp, /renameTest name="api add" value="api add route"/);
assert.match(graphPatchHelp, /deleteTest name="api add"/);
assert.match(graphPatchHelp, /upsertFunction handle/);
const graphPatchHelpJson = json(["patch", "--op", "help", "--json"]).body;
assert.equal(graphPatchHelpJson.ok, true);
assert.equal(graphPatchHelpJson.command, "zero patch");
assert.equal(graphPatchHelpJson.operations.includes("insert node=\"#id\" kind=\"Literal\" parent=\"#parent\" edge=\"arg\" order=\"0\" type=\"String\" value=\"text\""), true);
assert.equal(graphPatchHelpJson.operations.includes("insertEdge from=\"#from\" to=\"#to\" edge=\"arg\" target=\"node\" order=\"0\""), true);
assert.equal(graphPatchHelpJson.operations.includes("replace node=\"#id\" expect=\"nodehash:abc123\" kind=\"Literal\" type=\"String\" value=\"text\""), true);
assert.equal(graphPatchHelpJson.operations.some((op) => op.includes("setMain")), false);
assert.equal(graphPatchHelpJson.operations.some((op) => op.startsWith("replaceFunctionBody main\n")), true);
assert.equal(graphPatchHelpJson.operations.some((op) => op.startsWith("replaceBlockBody #block_id\n")), true);
assert.equal(graphPatchHelpJson.operations.includes("addLetBinary fn=\"add\" name=\"sum\" type=\"i32\" operator=\"+\" left=\"left\" right=\"right\""), true);
assert.equal(graphPatchHelpJson.operations.includes("addCheckWriteValue fn=\"main\" value=\"message\" type=\"String\""), true);
assert.equal(graphPatchHelpJson.operations.includes("addReturnExpr fn=\"maybe\" expr=\"null\""), true);
assert.equal(graphPatchHelpJson.operations.includes("appendStmt fn=\"main\" stmt=\"check std.http.listen(world, 3000_u16)\""), true);
assert.equal(graphPatchHelpJson.operations.some((op) => op.startsWith("addTestBody name=\"api add\"\n")), true);
assert.equal(graphPatchHelpJson.operations.includes("renameTest name=\"api add\" value=\"api add route\""), true);
assert.equal(graphPatchHelpJson.operations.includes("deleteTest name=\"api add\""), true);
assert.equal(graphPatchHelpJson.operations.some((op) => op.startsWith("upsertFunction handle\n")), true);
const retiredGraphCheckJson = json(["graph", "check", "--json", "examples/hello.0"], { allowFailure: true });
assert.equal(retiredGraphCheckJson.code, 1);
assert.equal(retiredGraphCheckJson.body.diagnostics[0].message, "zero graph check is not supported");
assert.equal(retiredGraphCheckJson.body.diagnostics[0].expected, "zero check [graph-input]");
const retiredGraphPatchJson = json(["graph", "patch", "--json", "--op", "help"], { allowFailure: true });
assert.equal(retiredGraphPatchJson.code, 1);
assert.equal(retiredGraphPatchJson.body.diagnostics[0].message, "zero graph patch is not supported");
assert.match(retiredGraphPatchJson.body.diagnostics[0].expected, /zero patch/);
const retiredGraphDumpJson = json(["graph", "dump", "--json", "examples/hello.0"], { allowFailure: true });
assert.equal(retiredGraphDumpJson.code, 1);
assert.equal(retiredGraphDumpJson.body.diagnostics[0].message, "zero graph dump is not supported");
assert.equal(retiredGraphDumpJson.body.diagnostics[0].expected, "zero dump [graph-input]");
const retiredGraphDefaultJson = json(["graph", "--json", "examples/hello.0"], { allowFailure: true });
assert.equal(retiredGraphDefaultJson.code, 1);
assert.equal(retiredGraphDefaultJson.body.diagnostics[0].message, "zero graph is not supported");
assert.equal(retiredGraphDefaultJson.body.diagnostics[0].expected, "zero inspect [graph-input]");
const retiredGraphHelpJson = json(["graph", "--help", "--json"], { allowFailure: true });
assert.equal(retiredGraphHelpJson.code, 1);
assert.equal(retiredGraphHelpJson.body.diagnostics[0].message, "zero graph is not supported");
assert.equal(retiredGraphHelpJson.body.diagnostics[0].expected, "zero inspect [graph-input]");
const graphDump = zero(["dump", "examples/hello.0"]).stdout;
const graphDumpAgain = zero(["dump", "examples/hello.0"]).stdout;
assert.equal(graphDumpAgain, graphDump);
assert.equal(zero(["dump", "examples/hello.0"]).stdout, graphDump);
assert.match(graphDump, /^zero-graph v1\n/);
assert.match(graphDump, /origin source-text/);
assert.match(graphDump, /module "hello"/);
assert.match(graphDump, /hash "graph:[0-9a-f]{16}"/);
assert.doesNotMatch(graphDump, /idStrategy/);
assert.doesNotMatch(graphDump, /canonicalSource/);
assert.doesNotMatch(graphDump, /moduleIdentity/);
assert.doesNotMatch(graphDump, /graphHash/);
assert.doesNotMatch(graphDump, /counts nodes=/);
assert.doesNotMatch(graphDump, /validation "shape-valid" ok/);
assert.doesNotMatch(graphDump, / nodeHash:/);
assert.match(graphDump, / path:"hello\.0"/);
assert.match(graphDump, / line:1 column:1/);
assert.match(graphDump, / line:2 column:27/);
assert.doesNotMatch(graphDump, / public:false/);
assert.doesNotMatch(graphDump, / target:node order:0/);
const rootQueryHello = json(["query", "--json", "--fn", "main", "examples/hello.0"]).body;
assert.equal(rootQueryHello.ok, true);
assert.equal(rootQueryHello.query.function, "main");
assert.equal(rootQueryHello.functions.some((fun: any) => fun.name === "main"), true);
assert.equal(zero(["view", "examples/hello.0"]).stdout, readFileSync("examples/hello.0", "utf8"));
const queryScopeRoot = join("/tmp", `zero-query-scope-${process.pid}`);
rmSync(queryScopeRoot, { force: true, recursive: true });
assert.equal(json(["init", "--json", queryScopeRoot]).body.ok, true);
mkdirSync(join(queryScopeRoot, "src"), { recursive: true });
writeFileSync(
join(queryScopeRoot, "src", "main.0"),
'fn dealsTotal(amount: usize) -> usize {\n return amount + 1\n}\n\npub fn main(world: World) -> Void raises {\n let total: usize = dealsTotal(41)\n if total == 42 {\n check world.out.write("query scope\\n")\n }\n}\n',
);
assert.equal(json(["import", "--json", join(queryScopeRoot, "src", "main.0")]).body.ok, true);
const queryScopeFind = json(["query", "--json", "--find", "dealsTotal", queryScopeRoot]).body;
assert.equal(queryScopeFind.ok, true);
const queryScopeFunctionId = queryScopeFind.matches.find((match: any) => match.kind === "Function")?.id;
assert(queryScopeFunctionId);
const queryScopeWholeModule = zero(["query", "--json", queryScopeRoot]);
const queryScopeNode = json(["query", "--json", "--node", queryScopeFunctionId, queryScopeRoot]);
assert.equal(queryScopeNode.body.ok, true);
assert.equal(queryScopeNode.body.query.scope, "node");
assert.equal(queryScopeNode.body.query.depth, 1);
assert.equal(queryScopeNode.body.node.selected.id, queryScopeFunctionId);
assert.equal(queryScopeNode.body.node.span.path, "src/main.0");
assert(queryScopeNode.body.node.parents.length >= 1);
assert(queryScopeNode.body.node.children.length >= 1);
assert.equal(queryScopeNode.body.node.children.every((edge: any) => edge.children === undefined), true);
assert.match(queryScopeNode.body.hint, /--depth <n>.*--full.*zero view --fn <name>/);
assert(queryScopeNode.stdout.length < 4096, `node-scoped query output should stay within a few KB, got ${queryScopeNode.stdout.length}`);
assert(queryScopeNode.stdout.length < queryScopeWholeModule.stdout.length, "node-scoped query output should be smaller than the whole-module report");
const queryScopeDepthTwo = json(["query", "--json", "--node", queryScopeFunctionId, "--depth", "2", queryScopeRoot]).body;
assert.equal(queryScopeDepthTwo.query.depth, 2);
assert.equal(queryScopeDepthTwo.node.children.some((edge: any) => Array.isArray(edge.children)), true);
const queryScopeFullModule = json(["query", "--json", "--node", queryScopeFunctionId, "--full", queryScopeRoot]).body;
assert.equal(queryScopeFullModule.ok, true);
assert(queryScopeFullModule.counts.nodes > 0);
assert.equal(queryScopeFullModule.node.selected.id, queryScopeFunctionId);
assert(Array.isArray(queryScopeFullModule.functions));
const queryScopeBadDepth = json(["query", "--json", "--node", queryScopeFunctionId, "--depth", "0", queryScopeRoot], { allowFailure: true });
assert.notEqual(queryScopeBadDepth.code, 0);
assert.match(queryScopeBadDepth.body.diagnostics[0].message, /invalid query depth '0'/);
const queryBareName = JSON.parse(execFileSync(zeroBin, ["query", "--json", "dealsTotal"], { cwd: queryScopeRoot, encoding: "utf8", maxBuffer: execMaxBuffer }));
assert.equal(queryBareName.ok, true);
assert.equal(queryBareName.query.find, "dealsTotal");
assert.equal(queryBareName.argument.value, "dealsTotal");
assert.equal(queryBareName.argument.resolvedAs, "find");
assert.match(queryBareName.argument.hint, /zero view --fn <name>/);
assert.equal(queryBareName.matches.some((match: any) => match.kind === "Function" && match.name === "dealsTotal"), true);
const queryBareNameText = execFileSync(zeroBin, ["query", "dealsTotal"], { cwd: queryScopeRoot, encoding: "utf8", maxBuffer: execMaxBuffer });
assert.match(queryBareNameText, /argument: dealsTotal is not an existing path; treated as --find dealsTotal/);
assert.match(queryBareNameText, /zero view --fn <name> prints one function's source/);
assert.doesNotMatch(queryBareNameText, /modules:/, "scoped query text output must not repeat the module list");
assert.doesNotMatch(queryBareNameText, /patch help:/, "scoped query text output must not repeat the patch footer");
const queryOverviewText = execFileSync(zeroBin, ["query"], { cwd: queryScopeRoot, encoding: "utf8", maxBuffer: execMaxBuffer });
assert.match(queryOverviewText, /modules:/);
assert.match(queryOverviewText, /main path:src\/main\.0 functions:2 \(entry\)/);
assert.match(queryOverviewText, /functions \(module main\):/);
assert.match(queryOverviewText, /dealsTotal\(amount: usize\) -> usize #decl_/);
assert.doesNotMatch(queryOverviewText, /stmt\[0\]/, "overview hides stmt handle inventories unless --handles is set");
assert.doesNotMatch(queryOverviewText, /resolution:/, "overview omits resolution facts");
assert.match(queryOverviewText, /tips: zero query --fn <name> \| --find <text> \| --calls <name> \| --refs <name>/);
assert.match(queryOverviewText, /zero view --fn <name>.*zero view --outline/);
assert(queryOverviewText.length < 3072, `bare query overview should stay compact, got ${queryOverviewText.length}`);
const queryFnText = execFileSync(zeroBin, ["query", "--fn", "dealsTotal"], { cwd: queryScopeRoot, encoding: "utf8", maxBuffer: execMaxBuffer });
assert.match(queryFnText, /query: fn:dealsTotal/);
assert.match(queryFnText, /dealsTotal\(amount: usize\) -> usize #decl_/);
assert.doesNotMatch(queryFnText, /stmt\[0\]/);
assert.match(queryFnText, /add --handles/);
const queryFnHandlesText = execFileSync(zeroBin, ["query", "--fn", "dealsTotal", "--handles"], { cwd: queryScopeRoot, encoding: "utf8", maxBuffer: execMaxBuffer });
assert.match(queryFnHandlesText, /param\[0\] amount: usize #param_/);
assert.match(queryFnHandlesText, /stmt\[0\] Return #stmt_/);
assert.match(queryFnHandlesText, /patch help:/);
const queryFnHandlesNoHelpText = execFileSync(zeroBin, ["query", "--fn", "dealsTotal", "--handles", "--no-help"], { cwd: queryScopeRoot, encoding: "utf8", maxBuffer: execMaxBuffer });
assert.match(queryFnHandlesNoHelpText, /param\[0\] amount: usize #param_/);
assert.match(queryFnHandlesNoHelpText, /stmt\[0\] Return #stmt_/);
assert.doesNotMatch(queryFnHandlesNoHelpText, /patch help:/, "--handles --no-help keeps handles without the operation footer");
assert(queryFnText.length < queryFnHandlesText.length, "default --fn output must be smaller than the --handles report");
const queryMissingPathInput = zero(["query", "no-such-dir/no-such-input"], { allowFailure: true });
assert.notEqual(queryMissingPathInput.code, 0, "path-shaped query arguments must keep file input semantics");
const viewFunction = zero(["view", "--fn", "dealsTotal", queryScopeRoot]).stdout;
assert.match(viewFunction, /^fn dealsTotal\(amount: usize\) -> usize \{\n/);
assert.match(viewFunction, /return amount \+ 1/);
assert.doesNotMatch(viewFunction, /fn main/);
const viewFunctionMiss = zero(["view", "--fn", "dealsTotle", queryScopeRoot], { allowFailure: true });
assert.notEqual(viewFunctionMiss.code, 0);
const viewFunctionMissOutput = `${viewFunctionMiss.stdout}${viewFunctionMiss.stderr}`;
assert.match(viewFunctionMissOutput, /function 'dealsTotle' not found in graph view/);
assert.match(viewFunctionMissOutput, /close matches: dealsTotal/);
assert.match(viewFunctionMissOutput, /zero query --find dealsTotle/);
const viewOutline = zero(["view", "--outline", "main", queryScopeRoot]).stdout;
assert.match(viewOutline, /module main path:src\/main\.0/);
assert.match(viewOutline, /fn dealsTotal\(amount: usize\) -> usize/);
assert.match(viewOutline, /pub fn main\(world: World\) -> Void raises/);
assert.doesNotMatch(viewOutline, /return amount/, "outline must not print function bodies");
assert.equal(zero(["view", "--outline", ".", queryScopeRoot]).stdout, viewOutline);
const viewOutlineMiss = zero(["view", "--outline", "nosuch", queryScopeRoot], { allowFailure: true });
assert.notEqual(viewOutlineMiss.code, 0);
assert.match(`${viewOutlineMiss.stdout}${viewOutlineMiss.stderr}`, /no module matches --outline nosuch/);
assert.match(`${viewOutlineMiss.stdout}${viewOutlineMiss.stderr}`, /modules in this graph: main/);
const viewAround = zero(["view", "--fn", "main", "--around", "total == 42", queryScopeRoot]).stdout;
assert.match(viewAround, /pub fn main\(world: World\) -> Void raises \{/);
assert.match(viewAround, /if total == 42 \{/);
assert.match(viewAround, /query scope/);
assert.match(viewAround, /\n \.\.\.\n/, "around output elides lines outside the enclosing block");
assert.doesNotMatch(viewAround, /let total/, "around output keeps only the enclosing block");
const viewAroundNoFn = zero(["view", "--around", "total", queryScopeRoot], { allowFailure: true });
assert.notEqual(viewAroundNoFn.code, 0);
assert.match(`${viewAroundNoFn.stdout}${viewAroundNoFn.stderr}`, /--around requires --fn <name>/);
const viewAroundMiss = zero(["view", "--fn", "main", "--around", "zzz-not-here", queryScopeRoot], { allowFailure: true });
assert.notEqual(viewAroundMiss.code, 0);
assert.match(`${viewAroundMiss.stdout}${viewAroundMiss.stderr}`, /text 'zzz-not-here' not found in function 'main'/);
const diffFunction = zero(["diff", "--fn", "dealsTotal", queryScopeRoot]).stdout;
assert.equal(diffFunction, viewFunction);
const diffFunctionMiss = zero(["diff", "--fn", "dealsTotle", queryScopeRoot], { allowFailure: true });
assert.notEqual(diffFunctionMiss.code, 0);
assert.match(`${diffFunctionMiss.stdout}${diffFunctionMiss.stderr}`, /close matches: dealsTotal/);
const diffHelp = zero(["diff", "--help"]).stdout;
assert.match(diffHelp, /Usage: zero diff \[--fn <name>\] \[graph-input\]/);
assert.match(diffHelp, /zero diff --fn handleLine \./);
assert.doesNotMatch(diffHelp, /Patch usage:/);
const queryHelp = zero(["query", "--help"]).stdout;
assert.match(queryHelp, /Usage: zero query .*\[--node <id>\] \[--depth <n>\] \[--full\] \[--handles\] \[--no-help\] \[graph-input\|name\]/);
assert.match(queryHelp, /--handles adds stmt and param patch handles/);
assert.match(queryHelp, /--no-help suppresses the long patch-operation footer/);
assert.match(queryHelp, /zero query userTotals/);
assert.match(queryHelp, /zero query --json --node '#decl_12ab34cd' --depth 2/);
assert.match(queryHelp, /zero view --fn <name>/);
const reconcileHelp = zero(["reconcile", "--help"]).stdout;
assert.match(reconcileHelp, /Usage: zero reconcile \[--json\] <base-graph-input> --source/);
assert.match(reconcileHelp, /zero reconcile zero\.graph --source src\/main\.0/);
assert.match(reconcileHelp, /zero reconcile --json \. --source src\/main\.0/);
assert.match(reconcileHelp, /zero reconcile --json baseline\.graph --source \./);
const viewHelp = zero(["view", "--help"]).stdout;
assert.match(viewHelp, /Usage: zero view \[--json\] \[--fn <name> \[--around <text>\|--handles\]\] \[--outline <module-or-file>\] \[--out <file\.0>\] \[graph-input\]/);
assert.match(viewHelp, /zero view --fn handleLine \./);
assert.match(viewHelp, /--outline <module-or-file> prints function signatures/);
assert.match(viewHelp, /--around <text> prints only the enclosing block/);
assert.match(viewHelp, /close matches/);
// --- think-in-graph addressing: zero view --fn <name> --handles ---
const viewPlainMain = zero(["view", "--fn", "main", queryScopeRoot]).stdout;
const viewHandlesMain = zero(["view", "--fn", "main", "--handles", queryScopeRoot]).stdout;
assert.equal(viewHandlesMain.replace(/ \/\/ [^\n]*$/gm, ""), viewPlainMain, "--handles must only add margin comments");
assert.match(viewHandlesMain, /let total: usize = dealsTotal\(41\) \/\/ #\S+\n/, "every statement line gains a trailing handle comment");
assert.match(viewHandlesMain, /if total == 42 \{ \/\/ #\S+ #\S+\n/, "compound headers show the stmt handle and the clause block handle");
assert(viewHandlesMain.length <= viewPlainMain.length * 1.3, `--handles annotation overhead must stay under 30%, got ${Math.round((viewHandlesMain.length / viewPlainMain.length - 1) * 1000) / 10}%`);
const viewHandlesNoFn = zero(["view", "--handles", queryScopeRoot], { allowFailure: true });
assert.notEqual(viewHandlesNoFn.code, 0);
assert.match(`${viewHandlesNoFn.stdout}${viewHandlesNoFn.stderr}`, /--handles requires --fn <name>/);
// refs and find rows gain the enclosing statement handle with --handles
const refsHandlesText = execFileSync(zeroBin, ["query", "--refs", "dealsTotal", "--handles"], { cwd: queryScopeRoot, encoding: "utf8", maxBuffer: execMaxBuffer });
assert.match(refsHandlesText, /call #expr_\S+ fn:main stmt:#stmt_\S+/, "--refs --handles rows show the enclosing statement handle");
const refsPlainText = execFileSync(zeroBin, ["query", "--refs", "dealsTotal"], { cwd: queryScopeRoot, encoding: "utf8", maxBuffer: execMaxBuffer });
assert.doesNotMatch(refsPlainText, / stmt:#/, "--refs without --handles stays unchanged");
const refsHandlesJson = json(["query", "--json", "--refs", "dealsTotal", queryScopeRoot]).body;
assert(refsHandlesJson.references.some((ref: any) => typeof ref.stmt === "string" && ref.stmt.startsWith("#stmt_")), "refs JSON rows carry the enclosing statement handle");
const findHandlesText = execFileSync(zeroBin, ["query", "--find", "dealsTotal", "--handles"], { cwd: queryScopeRoot, encoding: "utf8", maxBuffer: execMaxBuffer });
assert.match(findHandlesText, /Identifier #expr_\S+ name:dealsTotal stmt:#stmt_\S+/, "--find --handles match rows show the enclosing statement handle");
// the printed handles are the identifiers zero patch accepts: set-by-handle round trip
const letHandle = viewHandlesMain.match(/let total[^\n]* \/\/ (#\S+)$/m)?.[1];
assert(letHandle, "let statement line carries a handle");
const letNode = json(["query", "--json", "--node", letHandle, "--depth", "2", queryScopeRoot]).body;
assert.equal(letNode.node.selected.kind, "Let", "short handles resolve in zero query --node");
const letCall = letNode.node.children.find((edge: any) => edge.kind === "expr");
const letLiteralId = letCall?.children?.find((edge: any) => edge.kind === "arg")?.node?.id;
assert(letLiteralId, "literal argument node is reachable from the statement handle");
const setByHandle = zero(["patch", queryScopeRoot, "--op", `set node="${letLiteralId}" field="value" expect="41" value="43"`]);
assert.equal(setByHandle.code, 0);
const viewAfterSet = zero(["view", "--fn", "main", "--handles", queryScopeRoot]).stdout;
assert.match(viewAfterSet, /let total: usize = dealsTotal\(43\) \/\/ #\S+\n/, "set-by-handle edit shows up in the handles view");
// clause block handles drive replaceBlockBody directly from the view output
const ifClause = viewAfterSet.match(/if total == 42 \{ \/\/ (#\S+) (#\S+)$/m);
assert(ifClause, "if header carries stmt and clause block handles");
const clausePatch = zero(["patch", queryScopeRoot, "--patch-text", `zero-program-graph-patch v1\nreplaceBlockBody ${ifClause[2]}\n check world.out.write "clause by handle\\n"\nend\n`]);
assert.equal(clausePatch.code, 0);
assert.match(zero(["view", "--fn", "main", queryScopeRoot]).stdout, /clause by handle/, "replaceBlockBody accepts the clause handle printed by --handles");
// replaceExpr: one-line micro edits by handle (value, condition, subexpression)
const viewDealsHandles = zero(["view", "--fn", "dealsTotal", "--handles", queryScopeRoot]).stdout;
const returnHandle = viewDealsHandles.match(/return amount \+ 1 \/\/ (#\S+)$/m)?.[1];
assert(returnHandle, "return statement carries a handle");
const exprBadText = zero(["patch", queryScopeRoot, "--op", `replaceExpr node="${returnHandle}" with="amount ) 2"`], { allowFailure: true });
assert.notEqual(exprBadText.code, 0);
assert.match(exprBadText.stderr, /replaceExpr text did not parse as a Zero expression/);
const exprEdit = zero(["patch", queryScopeRoot, "--op", `replaceExpr node="${returnHandle}" with="amount * 2 + 1"`]);
assert.equal(exprEdit.code, 0);
assert.match(zero(["view", "--fn", "dealsTotal", queryScopeRoot]).stdout, /return amount \* 2 \+ 1/, "replaceExpr on a statement handle replaces its expression");
// micro-op batch: three --op edits, one patch, one revalidation pass
const viewMainBatch = zero(["view", "--fn", "main", "--handles", queryScopeRoot]).stdout;
const batchLetHandle = viewMainBatch.match(/let total[^\n]* \/\/ (#\S+)$/m)?.[1];
const batchIfHandle = viewMainBatch.match(/if total == 42 \{ \/\/ (#\S+) #\S+$/m)?.[1];
assert(batchLetHandle && batchIfHandle, "main handles for batch edit");
const batchPatch = zero(["patch", queryScopeRoot,
"--op", `replaceExpr node="${batchLetHandle}" with="dealsTotal(20) + 1"`,
"--op", `replaceExpr node="${batchIfHandle}" with="total != 0"`,
"--op", `set node="${batchLetHandle}" field="mutable" value="true"`,
]);
assert.equal(batchPatch.code, 0);
assert.match(batchPatch.stdout, /applied: 3 ops/, "batched --op edits apply as one patch");
const viewMainAfterBatch = zero(["view", "--fn", "main", queryScopeRoot]).stdout;
assert.match(viewMainAfterBatch, /var total: usize = dealsTotal\(20\) \+ 1/);
assert.match(viewMainAfterBatch, /if total != 0 \{/);
// structural rewrite by example: zero patch --rewrite '<pattern>' --to '<template>'
const rewriteRoot = join("/tmp", `zero-rewrite-scope-${process.pid}`);
rmSync(rewriteRoot, { force: true, recursive: true });
assert.equal(json(["init", "--json", rewriteRoot]).body.ok, true);
mkdirSync(join(rewriteRoot, "src"), { recursive: true });
writeFileSync(
join(rewriteRoot, "src", "main.0"),
'fn calc(a: usize) -> usize {\n let x: usize = a + 1\n let y: usize = a + 1\n return x + y\n}\n\nfn calc2(b: usize) -> usize {\n return b + 1\n}\n\npub fn main(world: World) -> Void raises {\n let t: usize = calc(1) + calc2(2)\n if t == t {\n check world.out.write("rewrite scope\\n")\n }\n}\n',
);
assert.equal(json(["import", "--json", join(rewriteRoot, "src", "main.0")]).body.ok, true);
// dry run is the default: each site lists file, fn, handle, and rendered before/after
const rewriteDry = zero(["patch", rewriteRoot, "--rewrite", "$A + 1", "--to", "$A + 2"]);
assert.equal(rewriteDry.code, 0);
assert.match(rewriteDry.stdout, /rewrite: \$A \+ 1 -> \$A \+ 2/);
assert.match(rewriteDry.stdout, /matches: 3/, "package-wide rewrite matches all three sites");
assert.match(rewriteDry.stdout, /src\/main\.0 fn:calc #\S+/);
assert.match(rewriteDry.stdout, /- a \+ 1/);
assert.match(rewriteDry.stdout, /\+ a \+ 2/);
assert.match(rewriteDry.stdout, /- b \+ 1/);
assert.match(rewriteDry.stdout, /dry run: pass --apply/);
assert.equal(zero(["view", "--fn", "calc", rewriteRoot]).stdout.includes("a + 2"), false, "dry run leaves the store untouched");
// --fn scopes matching to one function
const rewriteScoped = zero(["patch", rewriteRoot, "--rewrite", "$A + 1", "--to", "$A + 2", "--fn", "calc"]);
assert.match(rewriteScoped.stdout, /matches: 2/, "--fn calc scopes the rewrite to two sites");
assert.doesNotMatch(rewriteScoped.stdout, /fn:calc2/);
// the same metavariable twice must match equal subtrees
const rewriteEquality = zero(["patch", rewriteRoot, "--rewrite", "$A == $A", "--to", "true"]);
assert.match(rewriteEquality.stdout, /matches: 1/, "$A == $A matches t == t and nothing else");
assert.match(rewriteEquality.stdout, /- t == t/);
// JSON dry run carries the match list
const rewriteJson = json(["patch", "--json", rewriteRoot, "--rewrite", "$A + 1", "--to", "$A + 2"]).body;
assert.equal(rewriteJson.ok, true);
assert.equal(rewriteJson.matchCount, 3);
assert.equal(rewriteJson.matches.length, 3);
assert.equal(rewriteJson.matches[0].before, "a + 1");
assert.equal(rewriteJson.matches[0].after, "a + 2");
assert.equal(rewriteJson.rewrite.apply, false);
// revalidation failure rolls the whole batch back
const rewriteRollback = zero(["patch", rewriteRoot, "--rewrite", "$A + 1", "--to", "$A + nosuchconst", "--apply"], { allowFailure: true });
assert.notEqual(rewriteRollback.code, 0);
assert.match(`${rewriteRollback.stdout}${rewriteRollback.stderr}`, /revalidation/);
assert.equal(zero(["view", "--fn", "calc", rewriteRoot]).stdout.includes("nosuchconst"), false, "failed rewrite leaves the store untouched");
// metavar capture reuse on both sides, applied in one batch
const rewriteApply = zero(["patch", rewriteRoot, "--rewrite", "$A + 1", "--to", "$A + 1 + ($A - $A)", "--apply"]);
assert.equal(rewriteApply.code, 0);
assert.match(rewriteApply.stdout, /matches: 3/);
assert.match(rewriteApply.stdout, /applied: 3 ops/, "apply rewrites every site in one batch with one revalidation");
const rewriteCalcView = zero(["view", "--fn", "calc", rewriteRoot]).stdout;
assert.match(rewriteCalcView, /let x: usize = a \+ 1 \+ \(a - a\)/, "applied rewrite matches the dry-run rendering");
assert.match(rewriteCalcView, /let y: usize = a \+ 1 \+ \(a - a\)/);
assert.match(zero(["view", "--fn", "calc2", rewriteRoot]).stdout, /return b \+ 1 \+ \(b - b\)/);
// rewrite needs both halves and a real function for --fn
const rewriteMissingTo = zero(["patch", rewriteRoot, "--rewrite", "$A + 1"], { allowFailure: true });
assert.notEqual(rewriteMissingTo.code, 0);
assert.match(rewriteMissingTo.stderr, /graph rewrite needs both --rewrite and --to/);
const rewriteBadFn = zero(["patch", rewriteRoot, "--rewrite", "$A + 1", "--to", "$A", "--fn", "nosuchfn"], { allowFailure: true });
assert.notEqual(rewriteBadFn.code, 0);
assert.match(rewriteBadFn.stderr, /rewrite --fn function 'nosuchfn' was not found/);
const rewriteUnboundVar = zero(["patch", rewriteRoot, "--rewrite", "$A + 1", "--to", "$B + 1"], { allowFailure: true });
assert.notEqual(rewriteUnboundVar.code, 0);
assert.match(rewriteUnboundVar.stderr, /template uses \$B which the pattern does not bind/);
rmSync(rewriteRoot, { force: true, recursive: true });
// GPH004 with a near-miss handle names the nearest existing handle
const nearMiss = `${letHandle.slice(0, -1)}${letHandle.endsWith("z") ? "y" : "z"}`;
const nearMissPatch = zero(["patch", queryScopeRoot, "--op", `set node="${nearMiss}" field="value" value="9"`], { allowFailure: true });
assert.notEqual(nearMissPatch.code, 0);
assert.match(nearMissPatch.stderr, /patch node was not found; nearest: #/, "GPH004 suggests the nearest handle");
rmSync(queryScopeRoot, { force: true, recursive: true });
const repoGraphStatus = json(["status", "--json", "."]).body;
assert.equal(repoGraphStatus.ok, true);
assert.equal(repoGraphStatus.mode, "status");
assert.equal(repoGraphStatus.writes, false);
assert.equal(repoGraphStatus.repositoryGraph.storePath, "./zero.graph");
assert.equal(repoGraphStatus.repositoryGraph.storePresent, false);
assert.equal(repoGraphStatus.repositoryGraph.storeValid, false);
assert.equal(repoGraphStatus.repositoryGraph.enabled, true);
assert.equal(repoGraphStatus.repositoryGraph.projectionState, "store-missing");
assert.equal(repoGraphStatus.repositoryGraph.semanticValidity, "unavailable");
assert.equal(repoGraphStatus.repositoryGraph.projectionValidity, "unavailable");
assert.equal(repoGraphStatus.contract.artifact, "zero.graph");
assert.equal(repoGraphStatus.contract.compilerInput, "manifest package plus checked-in zero.graph repository store");
assert.equal(repoGraphStatus.contract.commands.status.writes, false);
assert.equal(repoGraphStatus.contract.commands.verifyProjection.writes, false);
assert.equal(repoGraphStatus.contract.commands.verifyProjection.available, false);
assert.equal(repoGraphStatus.contract.commands.import.writes, true);
assert.equal(repoGraphStatus.contract.commands.import.available, true);
assert.equal(repoGraphStatus.contract.commands.export.writes, true);
assert.equal(repoGraphStatus.contract.commands.export.available, false);
assert.equal(repoGraphStatus.contract.commands.merge.writes, true);
assert.equal(repoGraphStatus.contract.commands.merge.available, true);
assert.deepEqual(repoGraphStatus.contract.commands.merge.requires, ["--base", "--left", "--right"]);
assert.equal(repoGraphStatus.storage.encoding, "single-file-binary");
assert.equal(repoGraphStatus.storage.defaultEncoding, "binary");
assert.equal(repoGraphStatus.storage.interface, "ProgramGraphStore");
assert.equal(repoGraphStatus.storage.evolvable, true);
assert.equal(repoGraphStatus.scale.nodes, 0);
assert.equal(repoGraphStatus.scale.edges, 0);
assert.deepEqual(repoGraphStatus.repairCommands, []);
const invalidRepoGraphCompilerInputRoot = join("/tmp", `zero-repo-graph-invalid-compiler-input-${process.pid}`);
rmSync(invalidRepoGraphCompilerInputRoot, { force: true, recursive: true });
mkdirSync(invalidRepoGraphCompilerInputRoot, { recursive: true });
writeFileSync(join(invalidRepoGraphCompilerInputRoot, "zero.toml"), `[package]
name = "invalid-repo-graph-compiler-input"
version = "0.1.0"
[targets.cli]
kind = "exe"
main = "main.0"
[repositoryGraph]
compilerInput = "true"
`);
const invalidRepoGraphCompilerInputStatus = json(["status", "--json", invalidRepoGraphCompilerInputRoot], { allowFailure: true });
assert.notEqual(invalidRepoGraphCompilerInputStatus.code, 0);
assert.equal(invalidRepoGraphCompilerInputStatus.body.ok, false);
assert.equal(invalidRepoGraphCompilerInputStatus.body.repositoryGraph.compilerInput, "invalid");
assert.equal(invalidRepoGraphCompilerInputStatus.body.diagnostics[0].code, "BLD002");
assert.equal(invalidRepoGraphCompilerInputStatus.body.diagnostics[0].path, join(invalidRepoGraphCompilerInputRoot, "zero.toml"));
assert.equal(invalidRepoGraphCompilerInputStatus.body.diagnostics[0].message, "repositoryGraph.compilerInput must be a boolean");
const standaloneRepoGraphRoot = join("/tmp", `zero-repo-graph-contract-${process.pid}`);
const standaloneRepoGraphSource = join(standaloneRepoGraphRoot, "standalone.0");
const standaloneRepoGraphStore = join(standaloneRepoGraphRoot, "zero.graph");
rmSync(standaloneRepoGraphRoot, { force: true, recursive: true });
mkdirSync(standaloneRepoGraphRoot, { recursive: true });
const standaloneRepoGraphComment = "// repository graph projection comment\n";
writeFileSync(standaloneRepoGraphSource, standaloneRepoGraphComment + readFileSync("examples/hello.0", "utf8"));
const standaloneRepoGraphStatus = json(["status", "--json", resolve(standaloneRepoGraphSource)]).body;
assert.equal(standaloneRepoGraphStatus.repositoryGraph.root, resolve(standaloneRepoGraphRoot));
assert.equal(standaloneRepoGraphStatus.repositoryGraph.storePath, standaloneRepoGraphStore);
const nestedRelativeRepoGraphStatus = JSON.parse(execFileSync(zeroBin, ["status", "--json", "main.0"], { cwd: "examples/systems-package/src", encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"] }));
assert.equal(nestedRelativeRepoGraphStatus.repositoryGraph.root, "..");
assert.equal(nestedRelativeRepoGraphStatus.repositoryGraph.storePath, "../zero.graph");
writeFileSync(standaloneRepoGraphStore, "");
const standaloneRepoGraphInvalidStatus = json(["status", "--json", resolve(standaloneRepoGraphSource)], { allowFailure: true });
assert.notEqual(standaloneRepoGraphInvalidStatus.code, 0);
assert.equal(standaloneRepoGraphInvalidStatus.body.repositoryGraph.storePresent, true);
assert.equal(standaloneRepoGraphInvalidStatus.body.repositoryGraph.storeValid, false);
assert.equal(standaloneRepoGraphInvalidStatus.body.repositoryGraph.projectionState, "store-invalid");
assert.equal(standaloneRepoGraphInvalidStatus.body.diagnostics[0].code, "RGP003");
rmSync(standaloneRepoGraphStore, { force: true });
const repoGraphImport = json(["import", "--format", "text", "--json", resolve(standaloneRepoGraphSource)]);
assert.equal(repoGraphImport.code, 0);
assert.equal(repoGraphImport.body.ok, true);
assert.equal(repoGraphImport.body.mode, "import");
assert.equal(repoGraphImport.body.writes, true);
assert.equal(repoGraphImport.body.repositoryGraph.storePresent, true);
assert.equal(repoGraphImport.body.repositoryGraph.storeValid, true);
assert.equal(repoGraphImport.body.repositoryGraph.enabled, true);
assert.equal(repoGraphImport.body.repositoryGraph.projectionState, "clean");
assert.equal(repoGraphImport.body.repositoryGraph.semanticValidity, "shape-valid");
assert.equal(repoGraphImport.body.repositoryGraph.projectionValidity, "clean");
assert.equal(repoGraphImport.body.compilerStore.shape, "compiler-oriented-tables");
assert.equal(repoGraphImport.body.compilerStore.sourceFreeInspection, true);
assert.equal(repoGraphImport.body.compilerStore.sourceProjectionRequiredForSemanticFacts, false);
assert.equal(repoGraphImport.body.compilerStore.semanticValidity.state, "shape-valid");
assert.equal(repoGraphImport.body.compilerStore.projectionValidity.state, "clean");
assert.equal(repoGraphImport.body.compilerStore.tables.node, repoGraphImport.body.store.nodes);
assert.deepEqual(repoGraphImport.body.compilerStore.hashInputs.graphHashExcludes, ["sourcePath", "line", "column", "projectionText"]);
assert(repoGraphImport.body.repositoryGraph.possibleProjectionStates.includes("source-stale"));
assert(repoGraphImport.body.repositoryGraph.possibleProjectionStates.includes("conflict"));
assert.equal(repoGraphImport.body.contract.commands.export.available, true);
assert.equal(repoGraphImport.body.changedPaths[0], standaloneRepoGraphStore);
assert(existsSync(standaloneRepoGraphStore));
const storeText = readFileSync(standaloneRepoGraphStore, "utf8");
assert.match(storeText, /^zero-repository-graph v1\n/);
assert.match(storeText, /^sourceProjection "\.0"$/m);
assert.match(storeText, /^compilerStore schemaVersion:1 shape:"compiler-oriented-tables"/m);
assert.match(storeText, /^compilerTables schema:1 package:/m);
assert.match(storeText, /^compilerHashInputs graphHashExcludes:"source-path,line,column,projection-text"/m);
assert.match(storeText, /^source path:"standalone\.0"$/m);
assert.match(storeText, /^projection path:"standalone\.0" text:"\/\/ repository graph projection comment\\n/m);
assert.match(storeText, /^nodeHash node:"#/m);
assert.match(storeText, /^graph\nzero-graph v1\n/m);
assert(!storeText.includes(standaloneRepoGraphRoot));
const firstStoreHash = sha256File(standaloneRepoGraphStore);
writeFileSync(standaloneRepoGraphStore, storeText.replace('sourceProjection ".0"\n', 'sourceProjection ".0"\n\n'));
const standaloneRepoGraphNonCanonicalStatus = json(["status", "--json", resolve(standaloneRepoGraphSource)], { allowFailure: true });
assert.notEqual(standaloneRepoGraphNonCanonicalStatus.code, 0);
assert.equal(standaloneRepoGraphNonCanonicalStatus.body.repositoryGraph.storePresent, true);
assert.equal(standaloneRepoGraphNonCanonicalStatus.body.repositoryGraph.storeValid, false);
assert.equal(standaloneRepoGraphNonCanonicalStatus.body.diagnostics[0].code, "RGP003");
assert.match(standaloneRepoGraphNonCanonicalStatus.body.diagnostics[0].actual, /byte-stable/);
writeFileSync(standaloneRepoGraphStore, storeText);
const standaloneRepoGraphStatusWithStore = json(["status", "--json", resolve(standaloneRepoGraphSource)]).body;
assert.equal(standaloneRepoGraphStatusWithStore.repositoryGraph.storePresent, true);
assert.equal(standaloneRepoGraphStatusWithStore.repositoryGraph.storeValid, true);
assert.equal(standaloneRepoGraphStatusWithStore.repositoryGraph.enabled, true);
assert.equal(standaloneRepoGraphStatusWithStore.repositoryGraph.projectionState, "clean");
assert.equal(standaloneRepoGraphStatusWithStore.repositoryGraph.semanticValidity, "shape-valid");
assert.equal(standaloneRepoGraphStatusWithStore.repositoryGraph.projectionValidity, "clean");
assert.equal(standaloneRepoGraphStatusWithStore.store.format, "zero-repository-graph");
assert.equal(standaloneRepoGraphStatusWithStore.store.encoding, "text");
assert.equal(standaloneRepoGraphStatusWithStore.store.graphHash, repoGraphImport.body.store.graphHash);
assert.equal(standaloneRepoGraphStatusWithStore.compilerStore.tables.sourceMap, standaloneRepoGraphStatusWithStore.store.nodes);
const binaryRepoGraphRoot = join("/tmp", `zero-repo-graph-binary-contract-${process.pid}`);
rmSync(binaryRepoGraphRoot, { force: true, recursive: true });
mkdirSync(binaryRepoGraphRoot, { recursive: true });
assert.match(zero(["init", binaryRepoGraphRoot]).stdout, /graph project init ok/);
let binaryRepoGraphStore = readFileSync(join(binaryRepoGraphRoot, "zero.graph"));
assert.equal(binaryRepoGraphStore.subarray(0, 8).toString("binary"), "ZRGBIN1\0");
assertPatchOkOutput(zero(["patch", binaryRepoGraphRoot, "--op", "addMain", "--op", 'addCheckWrite fn="main" text="hello binary\\n"']).stdout, join(binaryRepoGraphRoot, "zero.graph"));
binaryRepoGraphStore = readFileSync(join(binaryRepoGraphRoot, "zero.graph"));
assert.equal(binaryRepoGraphStore.subarray(0, 8).toString("binary"), "ZRGBIN1\0");
const binaryRepoGraphStatus = json(["status", "--json", binaryRepoGraphRoot]).body;
assert.equal(binaryRepoGraphStatus.repositoryGraph.storeValid, true);
assert.equal(binaryRepoGraphStatus.store.format, "zero-repository-graph");
assert.equal(binaryRepoGraphStatus.store.encoding, "binary");
assert.equal(binaryRepoGraphStatus.storage.encoding, "single-file-binary");
assert.equal(binaryRepoGraphStatus.storage.defaultEncoding, "binary");
assert.equal(binaryRepoGraphStatus.storage.binaryAvailable, true);
assert.equal(zero(["check", binaryRepoGraphRoot]).stdout, "ok\n");
assert.equal(zero(["run", binaryRepoGraphRoot]).stdout, "hello binary\n");
assert.match(zero(["export", binaryRepoGraphRoot]).stdout, /repository graph export ok/);
assert.equal(zero(["verify-projection", binaryRepoGraphRoot]).stdout, "repository graph verify-projection ok\n");
const invalidBinaryFormatSync = zero(["import", "--format", "pickle", binaryRepoGraphRoot], { allowFailure: true });
assert.notEqual(invalidBinaryFormatSync.code, 0);
assert.match(invalidBinaryFormatSync.stderr, /repository graph store format is not supported/);
const standaloneRepoGraphVerifyWithStore = json(["verify-projection", "--json", resolve(standaloneRepoGraphSource)]);
assert.equal(standaloneRepoGraphVerifyWithStore.code, 0);
assert.equal(standaloneRepoGraphVerifyWithStore.body.ok, true);
assert.equal(standaloneRepoGraphVerifyWithStore.body.writes, false);
const repositoryGraphVerifyCleanScript = repositoryGraphVerifyScript(standaloneRepoGraphRoot);
assert.equal(repositoryGraphVerifyCleanScript.code, 0);
assert.match(repositoryGraphVerifyCleanScript.stdout, /repository graph verify-projection ok \(1 store\)/);
const repositoryGraphVerifyNoStoresRoot = join("/tmp", `zero-repo-graph-no-stores-${process.pid}`);
rmSync(repositoryGraphVerifyNoStoresRoot, { force: true, recursive: true });
mkdirSync(repositoryGraphVerifyNoStoresRoot, { recursive: true });
const repositoryGraphVerifyNoStoresScript = repositoryGraphVerifyScript(repositoryGraphVerifyNoStoresRoot);
assert.equal(repositoryGraphVerifyNoStoresScript.code, 0);
assert.match(repositoryGraphVerifyNoStoresScript.stdout, /repository graph verify-projection ok \(0 stores\)/);
const repositoryGraphVerifyRedirectRoot = join("/tmp", `zero-repo-graph-redirect-${process.pid}`);
const repositoryGraphVerifyRedirectGood = join(repositoryGraphVerifyRedirectRoot, "good");
const repositoryGraphVerifyRedirectBad = join(repositoryGraphVerifyRedirectRoot, "bad");
rmSync(repositoryGraphVerifyRedirectRoot, { force: true, recursive: true });
mkdirSync(repositoryGraphVerifyRedirectGood, { recursive: true });
mkdirSync(repositoryGraphVerifyRedirectBad, { recursive: true });
writeFileSync(join(repositoryGraphVerifyRedirectGood, "main.0"), readFileSync("examples/hello.0", "utf8"));
json(["import", "--format", "text", "--json", join(repositoryGraphVerifyRedirectGood, "main.0")]);
writeFileSync(join(repositoryGraphVerifyRedirectBad, "zero.graph"), 'invalid repository graph store\nprojection path:"../good/main.0" text:""\n');
const repositoryGraphVerifyRedirectScript = repositoryGraphVerifyScript(repositoryGraphVerifyRedirectRoot, { allowFailure: true });
assert.notEqual(repositoryGraphVerifyRedirectScript.code, 0);
assert.match(repositoryGraphVerifyRedirectScript.stderr, /repository graph verify-projection failed/);
assert.match(repositoryGraphVerifyRedirectScript.stderr, /zero-repo-graph-redirect-[0-9]+\/bad/);
const standaloneRepoGraphVerifyRelative = JSON.parse(execFileSync(zeroBin, ["verify-projection", "--json", "standalone.0"], { cwd: standaloneRepoGraphRoot, encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"] }));
assert.equal(standaloneRepoGraphVerifyRelative.ok, true);
const repoGraphImportAgain = json(["import", "--format", "text", "--json", resolve(standaloneRepoGraphSource)]);
assert.equal(repoGraphImportAgain.code, 0);
assert.equal(sha256File(standaloneRepoGraphStore), firstStoreHash);
writeFileSync(standaloneRepoGraphSource, readFileSync(standaloneRepoGraphSource, "utf8").replace("hello from zero", "hello from graph projection"));
const standaloneRepoGraphProjectionStale = json(["status", "--json", resolve(standaloneRepoGraphSource)]);
assert.equal(standaloneRepoGraphProjectionStale.body.repositoryGraph.projectionState, "source-stale");
assert.equal(standaloneRepoGraphProjectionStale.body.repositoryGraph.projectionValidity, "stale");
const standaloneRepoGraphExport = json(["export", "--json", resolve(standaloneRepoGraphSource)]);
assert.equal(standaloneRepoGraphExport.code, 0);
assert.equal(standaloneRepoGraphExport.body.mode, "export");
assert.equal(standaloneRepoGraphExport.body.writes, true);
assert.deepEqual(standaloneRepoGraphExport.body.changedPaths, [standaloneRepoGraphSource]);
const restoredRepoGraphSource = readFileSync(standaloneRepoGraphSource, "utf8");
assert.match(restoredRepoGraphSource, /hello from zero/);
assert.equal(restoredRepoGraphSource.startsWith(standaloneRepoGraphComment), true);
const standaloneRepoGraphExportAgain = json(["export", "--json", resolve(standaloneRepoGraphSource)]);
assert.equal(standaloneRepoGraphExportAgain.code, 0);
assert.deepEqual(standaloneRepoGraphExportAgain.body.changedPaths, []);
const standaloneRepoGraphVerifyAfterProjection = json(["verify-projection", "--json", resolve(standaloneRepoGraphSource)]);
assert.equal(standaloneRepoGraphVerifyAfterProjection.body.ok, true);
const standaloneRepoGraphSourceMapAfterProjection = json(["source-map", "--json", resolve(standaloneRepoGraphSource)]).body;
assert.equal(standaloneRepoGraphSourceMapAfterProjection.ok, true);
assert(standaloneRepoGraphSourceMapAfterProjection.files.some((file: any) => file.path.endsWith("standalone.0") && file.nodeCount > 0));
assert(standaloneRepoGraphSourceMapAfterProjection.mappings.some((mapping: any) => mapping.sourceAvailable === false && mapping.sourceRange?.path.endsWith("standalone.0")));
const invalidProjectionText = readFileSync(standaloneRepoGraphSource, "utf8").replace("hello from zero", "projection row changed graph");
writeFileSync(standaloneRepoGraphStore, storeText.replace(/^projection path:"standalone\.0" text:.*$/m, `projection path:"standalone.0" text:${JSON.stringify(invalidProjectionText)}`));
const invalidProjectionStatus = json(["status", "--json", resolve(standaloneRepoGraphSource)]);
assert.equal(invalidProjectionStatus.body.repositoryGraph.projectionState, "conflict");
const invalidProjectionVerify = json(["verify-projection", "--json", resolve(standaloneRepoGraphSource)], { allowFailure: true });
assert.notEqual(invalidProjectionVerify.code, 0);
assert.equal(invalidProjectionVerify.body.diagnostics[0].code, "RGP006");
assert.deepEqual(invalidProjectionVerify.body.repairCommands, [`zero import ${resolve(standaloneRepoGraphSource)}`, `zero export ${resolve(standaloneRepoGraphSource)}`]);
const invalidProjectionVerifyText = zero(["verify-projection", resolve(standaloneRepoGraphSource)], { allowFailure: true });
assert.notEqual(invalidProjectionVerifyText.code, 0);
assert.match(invalidProjectionVerifyText.stderr, new RegExp(`repair: zero import ${resolve(standaloneRepoGraphSource).replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`));
assert.match(invalidProjectionVerifyText.stderr, new RegExp(`repair: zero export ${resolve(standaloneRepoGraphSource).replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`));
const invalidProjectionSync = json(["export", "--json", resolve(standaloneRepoGraphSource)], { allowFailure: true });
assert.notEqual(invalidProjectionSync.code, 0);
assert.equal(invalidProjectionSync.body.diagnostics[0].code, "RGP004");
assert(!readFileSync(standaloneRepoGraphSource, "utf8").includes("projection row changed graph"));
writeFileSync(standaloneRepoGraphStore, storeText);
const graphMarker = "\ngraph\n";
const standaloneRepoGraphGraphStart = storeText.indexOf(graphMarker);
assert.notEqual(standaloneRepoGraphGraphStart, -1);
const standaloneRepoGraphBaseArtifact = join(standaloneRepoGraphRoot, "base.program-graph");
const standaloneRepoGraphPatchedArtifact = join(standaloneRepoGraphRoot, "graph-only-drift.program-graph");
const standaloneRepoGraphBaseGraphText = storeText.slice(standaloneRepoGraphGraphStart + graphMarker.length);
writeFileSync(standaloneRepoGraphBaseArtifact, standaloneRepoGraphBaseGraphText);
const standaloneRepoGraphModule = standaloneRepoGraphBaseGraphText.match(/^node (#[^ ]+) Module /m)?.[1];
assert(standaloneRepoGraphModule);
const voidTypeId = graphDomainId("type", graphHashText(1469598103934665603n, "Void"));
const graphOnlyDriftPatch = `insertEdge from="${standaloneRepoGraphModule}" to="${voidTypeId}" edge="projectionDrift" target="type" order="0"`;
const graphOnlyDriftPatchResult = json(["patch", "--json", "--out", standaloneRepoGraphPatchedArtifact, standaloneRepoGraphBaseArtifact, "--op", graphOnlyDriftPatch]);
assert.equal(graphOnlyDriftPatchResult.body.ok, true);
const standaloneRepoGraphPatchedGraphText = readFileSync(standaloneRepoGraphPatchedArtifact, "utf8");
const standaloneRepoGraphPatchedHash = standaloneRepoGraphPatchedGraphText.match(/^hash "([^"]+)"$/m)?.[1];
assert(standaloneRepoGraphPatchedHash);
const graphOnlyDriftStoreText = refreshRepositoryGraphCompilerMetadata(storeText
.slice(0, standaloneRepoGraphGraphStart + graphMarker.length)
.replace(/^graphHash "[^"]+"$/m, `graphHash "${standaloneRepoGraphPatchedHash}"`)
.replace(/^moduleHash "[^"]+"$/m, `moduleHash "${standaloneRepoGraphPatchedHash}"`) +
standaloneRepoGraphPatchedGraphText);
writeFileSync(standaloneRepoGraphStore, graphOnlyDriftStoreText);
const graphOnlyDriftStatus = json(["status", "--json", resolve(standaloneRepoGraphSource)]);
assert.equal(graphOnlyDriftStatus.body.repositoryGraph.projectionState, "conflict");
const graphOnlyDriftSync = json(["export", "--json", resolve(standaloneRepoGraphSource)], { allowFailure: true });
assert.notEqual(graphOnlyDriftSync.code, 0);
assert.equal(graphOnlyDriftSync.body.diagnostics[0].code, "RGP004");
writeFileSync(standaloneRepoGraphStore, storeText);
const typeErasedBaseLiteralLine = standaloneRepoGraphBaseGraphText.match(/^node (#[^ ]+) Literal [^\n]*value:"hello from zero[^\n]*$/m);
assert(typeErasedBaseLiteralLine);
assert(typeErasedBaseLiteralLine[0].includes(' type:"String"'));
const typeErasedLiteralText = typeErasedBaseLiteralLine[0].replace(' type:"String"', "");
const typeErasedGraphText = standaloneRepoGraphBaseGraphText.replace(typeErasedBaseLiteralLine[0], typeErasedLiteralText);
assert.notEqual(typeErasedGraphText, standaloneRepoGraphBaseGraphText);
const typeErasedLiteralLine = typeErasedGraphText.match(/^node (#[^ ]+) Literal [^\n]*value:"hello from zero\\n"[^\n]*$/m);
assert(typeErasedLiteralLine);
const typeErasedGraphHash = recomputeGraphHash(typeErasedGraphText);
const typeErasedStoredGraphText = typeErasedGraphText.replace(/^hash "graph:[0-9a-f]{16}"$/m, `hash "${typeErasedGraphHash}"`);
const typeErasedStoreText = refreshRepositoryGraphCompilerMetadata(storeText
.slice(0, standaloneRepoGraphGraphStart + graphMarker.length)
.replace(/^graphHash "[^"]+"$/m, `graphHash "${typeErasedGraphHash}"`)
.replace(/^moduleHash "[^"]+"$/m, `moduleHash "${typeErasedGraphHash}"`)
.replace(
new RegExp(`^nodeHash node:${JSON.stringify(typeErasedLiteralLine[1])} hash:"[^"]+"$`, "m"),
`nodeHash node:${JSON.stringify(typeErasedLiteralLine[1])} hash:${JSON.stringify(graphNodeHash(typeErasedLiteralLine[0]))}`,
) +
typeErasedStoredGraphText);
writeFileSync(standaloneRepoGraphStore, typeErasedStoreText);
const typeErasedProjectionStatus = json(["status", "--json", resolve(standaloneRepoGraphSource)]);
assert.equal(typeErasedProjectionStatus.body.repositoryGraph.projectionState, "conflict");
const typeErasedProjectionSync = json(["export", "--json", resolve(standaloneRepoGraphSource)], { allowFailure: true });
assert.notEqual(typeErasedProjectionSync.code, 0);
assert.equal(typeErasedProjectionSync.body.diagnostics[0].code, "RGP004");
writeFileSync(standaloneRepoGraphStore, storeText);
const relativePackageRoot = join("/tmp", `zero-repo-graph-relative-package-${process.pid}`);
const relativePackageSource = join(relativePackageRoot, "src", "main.0");
const relativePackageStore = join(relativePackageRoot, "zero.graph");
rmSync(relativePackageRoot, { force: true, recursive: true });
mkdirSync(join(relativePackageRoot, "src"), { recursive: true });
writeFileSync(join(relativePackageRoot, "zero.toml"), readFileSync("examples/systems-package/zero.toml", "utf8"));
writeFileSync(relativePackageSource, readFileSync("examples/hello.0", "utf8"));
json(["import", "--format", "text", "--json", relativePackageRoot]);
const relativePackageStoreText = readFileSync(relativePackageStore, "utf8");
assert.match(relativePackageStoreText, /^source path:"src\/main\.0"$/m);
assert(!relativePackageStoreText.includes(relativePackageRoot));
const relativePackageStoreHash = sha256File(relativePackageStore);
const relativePackageVerifyDot = JSON.parse(execFileSync(zeroBin, ["verify-projection", "--json", "."], { cwd: relativePackageRoot, encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"] }));
assert.equal(relativePackageVerifyDot.ok, true);
const relativePackageSyncDot = JSON.parse(execFileSync(zeroBin, ["import", "--format", "text", "--json", "."], { cwd: relativePackageRoot, encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"] }));
assert.equal(relativePackageSyncDot.ok, true);
assert.equal(sha256File(relativePackageStore), relativePackageStoreHash);
const relativePackageVerifyAbsolute = json(["verify-projection", "--json", relativePackageRoot]);
assert.equal(relativePackageVerifyAbsolute.body.ok, true);
const relativePackageManifest = join(relativePackageRoot, "zero.toml");
writeFileSync(relativePackageManifest, manifestToml({ package: { name: "systems-package-renamed", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "src/main.0" } } }));
const relativePackageManifestStatus = json(["status", "--json", relativePackageRoot]);
assert.equal(relativePackageManifestStatus.body.repositoryGraph.projectionState, "conflict");
const relativePackageManifestVerify = json(["verify-projection", "--json", relativePackageRoot], { allowFailure: true });
assert.notEqual(relativePackageManifestVerify.code, 0);
assert.equal(relativePackageManifestVerify.body.repositoryGraph.projectionState, "conflict");
assert.equal(relativePackageManifestVerify.body.diagnostics[0].code, "RGP007");
const relativePackageManifestExport = json(["export", "--json", relativePackageRoot], { allowFailure: true });
assert.notEqual(relativePackageManifestExport.code, 0);
assert.equal(relativePackageManifestExport.body.repositoryGraph.projectionState, "conflict");
assert.equal(relativePackageManifestExport.body.diagnostics[0].code, "RGP007");
writeFileSync(relativePackageManifest, manifestToml({ package: { name: "systems-package", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "src/missing.0" } } }));
const relativePackageBrokenManifestStatus = json(["status", "--json", relativePackageRoot]);
assert.equal(relativePackageBrokenManifestStatus.code, 0);
assert.equal(relativePackageBrokenManifestStatus.body.ok, true);
assert.equal(relativePackageBrokenManifestStatus.body.mode, "status");
assert.equal(relativePackageBrokenManifestStatus.body.repositoryGraph.projectionState, "conflict");
assert.deepEqual(relativePackageBrokenManifestStatus.body.diagnostics, []);
const relativePackageBrokenManifestVerify = json(["verify-projection", "--json", relativePackageRoot], { allowFailure: true });
assert.notEqual(relativePackageBrokenManifestVerify.code, 0);
const packageRefreshRoot = join("/tmp", `zero-repo-graph-package-refresh-${process.pid}`);
const packageRefreshSource = join(packageRefreshRoot, "src", "main.0");
const packageRefreshStore = join(packageRefreshRoot, "zero.graph");
rmSync(packageRefreshRoot, { force: true, recursive: true });
const packageRefreshInit = json(["init", "--json", packageRefreshRoot]);
assert.equal(packageRefreshInit.body.ok, true);
const packageRefreshName = readFileSync(join(packageRefreshRoot, "zero.toml"), "utf8").match(/^name = "([^"]+)"$/m)?.[1];
assert(packageRefreshName);
mkdirSync(join(packageRefreshRoot, "src"), { recursive: true });
writeFileSync(packageRefreshSource, 'pub fn main(world: World) -> Void raises {\n check world.out.write("package refresh one\\n")\n}\n');
const packageRefreshImport = json(["import", "--json", packageRefreshSource]);
assert.equal(packageRefreshImport.code, 0);
assert.equal(packageRefreshImport.body.ok, true);
const packageRefreshQuery = json(["query", "--json", "--fn", "main", packageRefreshRoot]);
assert.equal(packageRefreshQuery.body.moduleIdentity, `package:${packageRefreshName}@0.1.0`);
const packageRefreshMainId = packageRefreshQuery.body.functions[0].id;
assert(packageRefreshMainId);
assert.equal(zero(["run", packageRefreshRoot]).stdout, "package refresh one\n");
writeFileSync(packageRefreshSource, 'pub fn main(world: World) -> Void raises {\n check world.out.write("package refresh two\\n")\n}\n');
const packageRefreshReimport = json(["import", "--json", packageRefreshSource]);
assert.equal(packageRefreshReimport.body.ok, true);
assert.equal(zero(["run", packageRefreshRoot]).stdout, "package refresh two\n");
assert.equal(json(["query", "--json", "--fn", "main", packageRefreshRoot]).body.functions[0].id, packageRefreshMainId);
writeFileSync(packageRefreshSource, 'pub fn main(world: World) -> Void raises {\n check world.out.write("package refresh three\\n")\n}\n');
const packageRefreshRootReimport = json(["import", "--json", packageRefreshRoot]);
assert.equal(packageRefreshRootReimport.body.ok, true);
assert.equal(zero(["run", packageRefreshRoot]).stdout, "package refresh three\n");
const packageRefreshStoreHash = sha256File(packageRefreshStore);
const packageRefreshOutRejected = json(["import", "--json", "--format", "binary", "--out", packageRefreshStore, packageRefreshSource], { allowFailure: true });
assert.notEqual(packageRefreshOutRejected.code, 0);
assert.equal(packageRefreshOutRejected.body.diagnostics[0].code, "RGP002");
assert.deepEqual(packageRefreshOutRejected.body.repairCommands, [`zero import ${packageRefreshSource}`]);
assert.equal(sha256File(packageRefreshStore), packageRefreshStoreHash);
const packageRefreshManifestText = readFileSync(join(packageRefreshRoot, "zero.toml"), "utf8");
writeFileSync(join(packageRefreshRoot, "zero.toml"), packageRefreshManifestText.replace('version = "0.1.0"', 'version = "0.2.0"'));
const packageRefreshBumpImport = json(["import", "--json", packageRefreshRoot]);
assert.equal(packageRefreshBumpImport.body.ok, true);
assert.equal(json(["query", "--json", packageRefreshRoot]).body.moduleIdentity, `package:${packageRefreshName}@0.2.0`);
assert.equal(zero(["run", packageRefreshRoot]).stdout, "package refresh three\n");
writeFileSync(join(packageRefreshRoot, "zero.toml"), packageRefreshManifestText);
assert.equal(json(["import", "--json", packageRefreshRoot]).body.ok, true);
const packageRefreshBareRoot = join("/tmp", `zero-repo-graph-package-refresh-bare-${process.pid}`);
rmSync(packageRefreshBareRoot, { force: true, recursive: true });
mkdirSync(packageRefreshBareRoot, { recursive: true });
writeFileSync(join(packageRefreshBareRoot, "main.0"), readFileSync(packageRefreshSource, "utf8"));
assert.equal(json(["import", "--json", "--format", "binary", join(packageRefreshBareRoot, "main.0")]).body.ok, true);
writeFileSync(packageRefreshStore, readFileSync(join(packageRefreshBareRoot, "zero.graph")));
const packageRefreshPoisonedCheck = json(["check", "--json", packageRefreshRoot], { allowFailure: true });
assert.notEqual(packageRefreshPoisonedCheck.code, 0);
assert.equal(packageRefreshPoisonedCheck.body.diagnostics[0].code, "RGP007");
assert.equal(packageRefreshPoisonedCheck.body.diagnostics[0].actual, "module:main");
assert.match(packageRefreshPoisonedCheck.body.diagnostics[0].help, /run zero import to refresh zero\.graph/);
assert.deepEqual(packageRefreshPoisonedCheck.body.repairCommands, [`zero import ${packageRefreshRoot}`]);
const packageRefreshHealImport = json(["import", "--json", packageRefreshRoot]);
assert.equal(packageRefreshHealImport.body.ok, true);
assert.equal(zero(["run", packageRefreshRoot]).stdout, "package refresh three\n");
const packageForeignRoot = join("/tmp", `zero-repo-graph-package-foreign-${process.pid}`);
rmSync(packageForeignRoot, { force: true, recursive: true });
assert.equal(json(["init", "--json", packageForeignRoot]).body.ok, true);
mkdirSync(join(packageForeignRoot, "src"), { recursive: true });
writeFileSync(join(packageForeignRoot, "src", "main.0"), readFileSync(packageRefreshSource, "utf8"));
assert.equal(json(["import", "--json", packageForeignRoot]).body.ok, true);
writeFileSync(packageRefreshStore, readFileSync(join(packageForeignRoot, "zero.graph")));
const packageForeignStoreHash = sha256File(packageRefreshStore);
const packageForeignImport = json(["import", "--json", packageRefreshRoot], { allowFailure: true });
assert.notEqual(packageForeignImport.code, 0);
assert.equal(packageForeignImport.body.diagnostics[0].code, "RGP007");
assert.equal(packageForeignImport.body.diagnostics[0].message, "repository graph source identity has a different module identity");
assert.equal(sha256File(packageRefreshStore), packageForeignStoreHash);
const packageForeignCheck = json(["check", "--json", packageRefreshRoot], { allowFailure: true });
assert.notEqual(packageForeignCheck.code, 0);
assert.equal(packageForeignCheck.body.diagnostics[0].code, "RGP007");
rmSync(packageRefreshStore, { force: true });
assert.equal(json(["import", "--json", packageRefreshRoot]).body.ok, true);
assert.equal(zero(["run", packageRefreshRoot]).stdout, "package refresh three\n");
const staleRunRoot = join("/tmp", `zero-repo-graph-stale-run-${process.pid}`);
const staleRunSource = join(staleRunRoot, "src", "main.0");
const staleRunStore = join(staleRunRoot, "zero.graph");
rmSync(staleRunRoot, { force: true, recursive: true });
assert.equal(json(["init", "--json", staleRunRoot]).body.ok, true);
mkdirSync(join(staleRunRoot, "src"), { recursive: true });
writeFileSync(staleRunSource, 'pub fn main(world: World) -> Void raises {\n check world.out.write("stale run one\\n")\n}\n');
assert.equal(json(["import", "--json", staleRunRoot]).body.ok, true);
assert.equal(zero(["run", staleRunRoot]).stdout, "stale run one\n");
writeFileSync(staleRunSource, 'pub fn main(world: World) -> Void raises {\n check world.out.write("stale run two\\n")\n}\n');
assert.equal(json(["status", "--json", staleRunRoot]).body.repositoryGraph.projectionState, "source-stale");
const staleRunStoreHashBefore = sha256File(staleRunStore);
assert.equal(zero(["run", staleRunRoot]).stdout, "stale run two\n");
assert.notEqual(sha256File(staleRunStore), staleRunStoreHashBefore);
assert.equal(json(["status", "--json", staleRunRoot]).body.repositoryGraph.projectionState, "clean");
writeFileSync(staleRunSource, 'pub fn main(world: World) -> Void raises {\n check world.out.write("stale run three\\n")\n}\n');
assert.equal(zero(["check", staleRunRoot]).stdout, "ok\n");
assert.equal(json(["status", "--json", staleRunRoot]).body.repositoryGraph.projectionState, "clean");
assert.equal(zero(["run", staleRunRoot]).stdout, "stale run three\n");
const staleRunGoodSource = readFileSync(staleRunSource, "utf8");
writeFileSync(staleRunSource, `${staleRunGoodSource}fn broken( {\n`);
const staleRunBrokenCheck = zero(["check", staleRunRoot], { allowFailure: true });
assert.notEqual(staleRunBrokenCheck.code, 0);
const staleRunBrokenRun = zero(["run", staleRunRoot], { allowFailure: true });
assert.notEqual(staleRunBrokenRun.code, 0);
writeFileSync(staleRunSource, staleRunGoodSource);
assert.equal(zero(["run", staleRunRoot]).stdout, "stale run three\n");
writeFileSync(staleRunSource, 'pub fn main(world: World) -> Void raises {\n check world.out.write("stale run four\\n")\n}\n');
const staleRunStrictHash = sha256File(staleRunStore);
const staleRunStrict = json(["build", "--json", staleRunRoot], { allowFailure: true, env: { ZERO_STALE: "fail" } });
assert.notEqual(staleRunStrict.code, 0);
assert.equal(staleRunStrict.body.diagnostics[0].code, "RGP008");
assert.deepEqual(staleRunStrict.body.repairCommands, [`zero import ${staleRunRoot}`]);
assert.equal(sha256File(staleRunStore), staleRunStrictHash);
const staleRunStrictRun = zero(["run", staleRunRoot], { allowFailure: true, env: { ZERO_STALE: "fail" } });
assert.notEqual(staleRunStrictRun.code, 0);
assert.equal(zero(["run", staleRunRoot]).stdout, "stale run four\n");
assert.equal(zero(["run", staleRunSource]).stdout, "stale run four\n");
assert.equal(zero(["check", staleRunSource]).stdout, "ok\n");
writeFileSync(staleRunSource, 'pub fn main(world: World) -> Void raises {\n check world.out.write("stale run five\\n")\n}\n');
assert.equal(zero(["run", staleRunSource]).stdout, "stale run five\n");
assert.equal(json(["status", "--json", staleRunRoot]).body.repositoryGraph.projectionState, "clean");
const cachedArgvRoot = join("/tmp", `zero-repo-graph-cached-argv-${process.pid}`);
const cachedArgvSource = join(cachedArgvRoot, "src", "main.0");
rmSync(cachedArgvRoot, { force: true, recursive: true });
assert.equal(json(["init", "--json", cachedArgvRoot]).body.ok, true);
mkdirSync(join(cachedArgvRoot, "src"), { recursive: true });
writeFileSync(cachedArgvSource, 'pub fn main(world: World) -> Void raises {\n let self: Maybe<String> = std.args.get(0)\n if self.has {\n check world.out.write(self.value)\n check world.out.write("\\n")\n }\n}\n');
assert.equal(json(["import", "--json", cachedArgvRoot]).body.ok, true);
assert.match(zero(["run", cachedArgvRoot]).stdout, /\.run-/);
const cachedArgvSecondRun = zero(["run", cachedArgvRoot]).stdout.trim();
assert.match(cachedArgvSecondRun, /\.run-/);
assert.doesNotMatch(cachedArgvSecondRun, /linked-exe-/);
const procFdRoot = join("/tmp", `zero-proc-child-fd-inherit-${process.pid}`);
const procFdSource = join(procFdRoot, "src", "main.0");
rmSync(procFdRoot, { force: true, recursive: true });
assert.equal(json(["init", "--json", procFdRoot]).body.ok, true);
mkdirSync(join(procFdRoot, "src"), { recursive: true });
writeFileSync(procFdSource, `pub fn main(world: World) -> Void raises {
let first: ProcChild = std.proc.spawnChild("sh -c 'cat >/dev/null; printf first-done'")
let second: ProcChild = std.proc.spawnChild("sleep 5")
let closed: Bool = std.proc.closeStdin(first)
let status: ProcStatus = std.proc.wait(first)
var output: [64]u8 = [0_u8; 64]
let read: Maybe<usize> = std.proc.readStdout(first, output)
if closed && std.proc.succeeded(status) && read.has {
let bytes: Span<u8> = std.io.written(output, read.value)
check world.out.write(bytes)
check world.out.write("\\n")
}
let killed: Bool = std.proc.kill(second)
let second_status: ProcStatus = std.proc.wait(second)
let closed_first: Bool = std.proc.close(first)
let closed_second: Bool = std.proc.close(second)
}
`);
assert.equal(json(["import", "--json", procFdRoot]).body.ok, true);
const procFdRun = spawnSync(zeroBin, ["run", procFdRoot], { encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"], timeout: 1800 });
assert.equal(procFdRun.error, undefined);
assert.equal(procFdRun.status, 0);
assert.equal(procFdRun.stdout, "first-done\n");
const staleMultiRoot = join("/tmp", `zero-repo-graph-stale-multi-${process.pid}`);
const staleMultiStore = join(staleMultiRoot, "zero.graph");
const staleMultiHelper = join(staleMultiRoot, "src", "math.0");
rmSync(staleMultiRoot, { force: true, recursive: true });
assert.equal(json(["init", "--json", staleMultiRoot]).body.ok, true);
mkdirSync(join(staleMultiRoot, "src"), { recursive: true });
writeFileSync(
join(staleMultiRoot, "src", "main.0"),
'use math\n\npub fn main(world: World) -> Void raises {\n if add_one(41) == 42 {\n check world.out.write("stale multi one\\n")\n }\n if add_one(41) == 43 {\n check world.out.write("stale multi two\\n")\n }\n}\n',
);
writeFileSync(staleMultiHelper, "pub fn add_one(value: i32) -> i32 {\n return value + 1\n}\n");
assert.equal(json(["import", "--json", staleMultiRoot]).body.ok, true);
assert.equal(zero(["run", staleMultiRoot]).stdout, "stale multi one\n");
const staleMultiOverview = zero(["query", staleMultiRoot]).stdout;
assert.match(staleMultiOverview, /math path:src\/math\.0 functions:1\n/);
assert.match(staleMultiOverview, /main path:src\/main\.0 functions:1 \(entry\)/);
assert.match(staleMultiOverview, /functions \(module main\):/);
assert.doesNotMatch(staleMultiOverview, /add_one\(value: i32\)/, "the bare overview lists only entry-module signatures");
writeFileSync(staleMultiHelper, "pub fn add_one(value: i32) -> i32 {\n return value + 2\n}\n");
const staleMultiCheck = zeroWithStderr(["check"], { cwd: staleMultiRoot });
assert.equal(staleMultiCheck.code, 0);
assert.equal(staleMultiCheck.stdout, "ok\n");
assert.match(staleMultiCheck.stderr, /note: zero check refreshed zero\.graph from the edited package source projection; tip: zero patch --replace-fn <fn> --body-file - edits the graph directly and skips this reconcile/);
assert.equal((staleMultiCheck.stderr.match(/\n/g) ?? []).length, 1, "graph refresh note plus tip should stay on one stderr line");
assert.equal(json(["status", "--json", staleMultiRoot]).body.repositoryGraph.projectionState, "clean");
assert.equal(zero(["run", staleMultiRoot]).stdout, "stale multi two\n");
// Context-aware refresh tips: a signature-changing source edit teaches the
// declaration-level patch ops at the moment of fallback, a const initializer
// edit teaches setConst, and the refreshed (clean) state stays quiet.
const refreshTipRoot = join("/tmp", `zero-repo-graph-refresh-tip-${process.pid}`);
const refreshTipMain = join(refreshTipRoot, "src", "main.0");
const refreshTipMath = join(refreshTipRoot, "src", "math.0");
rmSync(refreshTipRoot, { force: true, recursive: true });
assert.equal(json(["init", "--json", refreshTipRoot]).body.ok, true);
mkdirSync(join(refreshTipRoot, "src"), { recursive: true });
writeFileSync(refreshTipMain, 'use math\n\nconst limit: i32 = 42\n\npub fn main(world: World) -> Void raises {\n if add_one(41) == limit {\n check world.out.write("tip one\\n")\n }\n}\n');
writeFileSync(refreshTipMath, "pub fn add_one(value: i32) -> i32 {\n return value + 1\n}\n");
assert.equal(json(["import", "--json", refreshTipRoot]).body.ok, true);
writeFileSync(refreshTipMath, "pub fn add_one(value: i32, bias: i32) -> i32 {\n return value + bias\n}\n");
writeFileSync(refreshTipMain, 'use math\n\nconst limit: i32 = 42\n\npub fn main(world: World) -> Void raises {\n if add_one(41, 1) == limit {\n check world.out.write("tip one\\n")\n }\n}\n');
const refreshTipSignature = zeroWithStderr(["check", refreshTipRoot]);
assert.equal(refreshTipSignature.code, 0);
assert.match(refreshTipSignature.stderr, /note: zero check refreshed zero\.graph from the edited package source projection; tip: zero patch --op 'addParamTo fn=\.\.\. name=\.\.\. type=\.\.\. default=\.\.\.' threads a new parameter through every call site in one step; setReturnType changes return types/);
assert.equal((refreshTipSignature.stderr.match(/\n/g) ?? []).length, 1, "signature refresh note plus tip should stay on one stderr line");
const refreshTipQuiet = zeroWithStderr(["check", refreshTipRoot]);
assert.equal(refreshTipQuiet.code, 0);
assert.doesNotMatch(refreshTipQuiet.stderr, /refreshed zero\.graph/, "the refresh note prints once per stale state");
writeFileSync(refreshTipMain, 'use math\n\nconst limit: i32 = 43\n\npub fn main(world: World) -> Void raises {\n if add_one(41, 1) == limit {\n check world.out.write("tip one\\n")\n }\n}\n');
const refreshTipConst = zeroWithStderr(["check", refreshTipRoot]);
assert.equal(refreshTipConst.code, 0);
assert.match(refreshTipConst.stderr, /note: zero check refreshed zero\.graph from the edited package source projection; tip: zero patch --op 'setConst name=\.\.\. value=\.\.\.' replaces a top-level const initializer directly and skips this reconcile/);
assert.equal(json(["status", "--json", refreshTipRoot]).body.repositoryGraph.projectionState, "clean");
writeFileSync(staleMultiHelper, "pub fn add_one(value: i32) -> i32 {\n return value + 1\n}\n");
const staleMultiStoreCheck = zeroWithStderr(["check", staleMultiStore]);
assert.equal(staleMultiStoreCheck.code, 0);
assert.equal(staleMultiStoreCheck.stdout, "ok\n");
assert.match(staleMultiStoreCheck.stderr, /note: zero check refreshed zero\.graph from the edited package source projection/);
assert.equal(json(["status", "--json", staleMultiRoot]).body.repositoryGraph.projectionState, "clean");
writeFileSync(staleMultiHelper, "pub fn add_one(value: i32) -> i32 {\n return value + 2\n}\n");
const staleMultiBuild = zeroWithStderr(["build", staleMultiStore]);
assert.equal(staleMultiBuild.code, 0);
assert.match(staleMultiBuild.stderr, /note: zero build refreshed zero\.graph from the edited package source projection/);
assert.equal(zero(["run", staleMultiRoot]).stdout, "stale multi two\n");
writeFileSync(staleMultiHelper, "pub fn add_one(value: i32) -> i32 {\n return value + 1\n}\n");
const staleMultiView = zeroWithStderr(["view", "--fn", "add_one", staleMultiRoot]);
assert.equal(staleMultiView.code, 0);
assert.match(staleMultiView.stdout, /return value \+ 1/);
assert.match(staleMultiView.stderr, /note: zero view refreshed zero\.graph from the edited package source projection/);
assert.equal(json(["status", "--json", staleMultiRoot]).body.repositoryGraph.projectionState, "clean");
const staleMultiPatch = json(["patch", "--json", staleMultiRoot, "--op", 'addLetLiteral fn="main" name="patched" type="u32" value="7"']);
assert.equal(staleMultiPatch.body.ok, true);
const staleMultiGraphNewerBuild = zeroWithStderr(["build", staleMultiRoot]);
assert.equal(staleMultiGraphNewerBuild.code, 0);
assert.match(staleMultiGraphNewerBuild.stderr, /note: zero build is using zero\.graph, which is newer than the \.0 source projection/);
// the store-newer note is once-per-state: a second command on the same store
// stays quiet until the store or source state changes
const staleMultiGraphNewerRepeat = zeroWithStderr(["check", staleMultiRoot]);
assert.equal(staleMultiGraphNewerRepeat.code, 0);
assert.doesNotMatch(staleMultiGraphNewerRepeat.stderr, /is using zero\.graph/, "two consecutive commands print the store-newer note once");
writeFileSync(staleMultiHelper, "pub fn add_one(value: i32) -> i32 {\n return value + 2\n}\n");
const staleMultiDiverged = json(["check", "--json", staleMultiRoot], { allowFailure: true });
assert.notEqual(staleMultiDiverged.code, 0);
assert.equal(staleMultiDiverged.body.diagnostics[0].code, "RGP006");
assert.match(staleMultiDiverged.body.diagnostics[0].message, /have diverged/);
assert.match(staleMultiDiverged.body.repairCommands.join("\n"), /zero import/);
assert.match(staleMultiDiverged.body.repairCommands.join("\n"), /zero export/);
const staleMultiDivergedBuild = json(["build", "--json", staleMultiRoot], { allowFailure: true });
assert.notEqual(staleMultiDivergedBuild.code, 0);
assert.equal(staleMultiDivergedBuild.body.diagnostics[0].code, "RGP006");
assert.equal(json(["import", "--json", staleMultiRoot]).body.ok, true);
assert.equal(zero(["run", staleMultiRoot]).stdout, "stale multi two\n");
assert.equal(json(["status", "--json", staleMultiRoot]).body.repositoryGraph.projectionState, "clean");
// Content-based store/source sync classification: a freshly staged workspace
// with an edited source projection classifies source-newer and runs the
// edited behavior with the store mtime newest, oldest, or tied, because the
// store records a hash of the source projection at every write and mtimes
// never decide the state.
const stagedSyncBase = join("/tmp", `zero-staged-sync-base-${process.pid}`);
rmSync(stagedSyncBase, { force: true, recursive: true });
mkdirSync(join(stagedSyncBase, "src"), { recursive: true });
writeFileSync(join(stagedSyncBase, "zero.toml"), '[package]\nname = "staged-sync"\nversion = "0.1.0"\n\n[targets.cli]\nkind = "exe"\nmain = "src/main.0"\n');
writeFileSync(join(stagedSyncBase, "src", "main.0"), 'pub fn main(world: World) -> Void raises {\n check world.out.write("staged one\\n")\n}\n');
assert.equal(json(["import", "--json", stagedSyncBase]).body.ok, true);
assert.equal(zero(["run", stagedSyncBase]).stdout, "staged one\n");
const stagedSyncEpoch = new Date("2026-01-01T00:00:00Z");
for (const order of ["store-newest", "store-oldest", "tied"]) {
const stagedRoot = join("/tmp", `zero-staged-sync-${order}-${process.pid}`);
rmSync(stagedRoot, { force: true, recursive: true });
cpSync(stagedSyncBase, stagedRoot, { recursive: true });
writeFileSync(join(stagedRoot, "src", "main.0"), 'pub fn main(world: World) -> Void raises {\n check world.out.write("staged two\\n")\n}\n');
const stagedNow = new Date();
const storeTime = order === "store-newest" ? stagedNow : stagedSyncEpoch;
const sourceTime = order === "store-oldest" ? stagedNow : stagedSyncEpoch;
utimesSync(join(stagedRoot, "zero.graph"), storeTime, storeTime);
utimesSync(join(stagedRoot, "src", "main.0"), sourceTime, sourceTime);
const stagedRun = zeroWithStderr(["run", stagedRoot]);
assert.equal(stagedRun.code, 0, `staged ${order} run exits 0`);
assert.equal(stagedRun.stdout, "staged two\n", `staged ${order} runs the edited behavior`);
assert.match(stagedRun.stderr, /refreshed zero\.graph from the edited package source projection/, `staged ${order} classifies source-newer`);
rmSync(stagedRoot, { force: true, recursive: true });
}
// A patched store stays authoritative by content even when its mtime is the
// oldest file in the workspace.
const stagedPatch = json(["patch", "--json", stagedSyncBase, "--op", 'addCheckWrite fn="main" text="staged patched\\n"']);
assert.equal(stagedPatch.body.ok, true);
utimesSync(join(stagedSyncBase, "zero.graph"), stagedSyncEpoch, stagedSyncEpoch);
const stagedStoreNewer = zeroWithStderr(["run", stagedSyncBase]);
assert.equal(stagedStoreNewer.code, 0);
assert.equal(stagedStoreNewer.stdout, "staged one\nstaged patched\n");
assert.match(stagedStoreNewer.stderr, /is using zero\.graph, which is newer than the \.0 source projection/);
// zero export refreshes the recorded source projection hash so a source edit
// after the export classifies source-newer instead of diverged.
const stagedExport = json(["export", "--json", stagedSyncBase]);
assert.equal(stagedExport.body.ok, true);
assert.equal(stagedExport.body.changedPaths.includes(join(stagedSyncBase, "zero.graph")), true);
writeFileSync(join(stagedSyncBase, "src", "main.0"), 'pub fn main(world: World) -> Void raises {\n check world.out.write("staged three\\n")\n}\n');
utimesSync(join(stagedSyncBase, "src", "main.0"), stagedSyncEpoch, stagedSyncEpoch);
const stagedAfterExport = zeroWithStderr(["run", stagedSyncBase]);
assert.equal(stagedAfterExport.code, 0);
assert.equal(stagedAfterExport.stdout, "staged three\n");
assert.match(stagedAfterExport.stderr, /refreshed zero\.graph from the edited package source projection/);
// Editing the source while the store holds unexported patches is a genuine
// divergence regardless of mtimes.
assert.equal(json(["patch", "--json", stagedSyncBase, "--op", 'addCheckWrite fn="main" text="staged patched again\\n"']).body.ok, true);
writeFileSync(join(stagedSyncBase, "src", "main.0"), 'pub fn main(world: World) -> Void raises {\n check world.out.write("staged four\\n")\n}\n');
const stagedDiverged = json(["check", "--json", stagedSyncBase], { allowFailure: true });
assert.notEqual(stagedDiverged.code, 0);
assert.equal(stagedDiverged.body.diagnostics[0].code, "RGP006");
rmSync(stagedSyncBase, { force: true, recursive: true });
// Stores written before the recorded source projection hash existed degrade
// to one reconciling source refresh instead of an error wall, and the
// refresh records the hash.
const legacySyncRoot = join("/tmp", `zero-legacy-sync-${process.pid}`);
rmSync(legacySyncRoot, { force: true, recursive: true });
mkdirSync(join(legacySyncRoot, "src"), { recursive: true });
writeFileSync(join(legacySyncRoot, "zero.toml"), '[package]\nname = "legacy-sync"\nversion = "0.1.0"\n\n[targets.cli]\nkind = "exe"\nmain = "src/main.0"\n');
writeFileSync(join(legacySyncRoot, "src", "main.0"), 'pub fn main(world: World) -> Void raises {\n check world.out.write("legacy one\\n")\n}\n');
assert.equal(json(["import", "--json", "--format", "text", legacySyncRoot]).body.ok, true);
const legacyStorePath = join(legacySyncRoot, "zero.graph");
const legacyStoreText = readFileSync(legacyStorePath, "utf8");
assert.match(legacyStoreText, /\nsourceHash "src:[0-9a-f]{16}"\n/);
writeFileSync(legacyStorePath, legacyStoreText.replace(/\nsourceHash "[^"]*"/, ""));
writeFileSync(join(legacySyncRoot, "src", "main.0"), 'pub fn main(world: World) -> Void raises {\n check world.out.write("legacy two\\n")\n}\n');
utimesSync(join(legacySyncRoot, "src", "main.0"), stagedSyncEpoch, stagedSyncEpoch);
const legacyRun = zeroWithStderr(["run", legacySyncRoot]);
assert.equal(legacyRun.code, 0);
assert.equal(legacyRun.stdout, "legacy two\n");
assert.match(legacyRun.stderr, /refreshed zero\.graph from the edited package source projection/);
assert.match(readFileSync(legacyStorePath, "utf8"), /\nsourceHash "src:[0-9a-f]{16}"\n/);
rmSync(legacySyncRoot, { force: true, recursive: true });
// One diagnostic oracle for the sync verbs: zero check, zero import, and
// zero patch revalidation accept the same code (Span<T> helpers through
// std.mem.prefix, integer-literal returns in plain helpers, and ref<shape>
// parameters), revalidation reports every introduced diagnostic in one
// shot, and pre-existing diagnostics print as notes instead of walls.
const oracleAlignRoot = join("/tmp", `zero-oracle-align-${process.pid}`);
rmSync(oracleAlignRoot, { force: true, recursive: true });
mkdirSync(join(oracleAlignRoot, "src"), { recursive: true });
writeFileSync(join(oracleAlignRoot, "zero.toml"), '[package]\nname = "oracle-align"\nversion = "0.1.0"\n\n[targets.cli]\nkind = "exe"\nmain = "src/main.0"\n');
const oracleAlignSource = [
"pub type Pair {",
" left: u64,",
" right: u64,",
"}",
"",
"fn headBytes(bytes: Span<u8>, len: usize) -> Span<u8> {",
" return std.mem.prefix(bytes, len)",
"}",
"",
"fn limit() -> usize {",
" return 5",
"}",
"",
"pub fn pairLeft(p: ref<Pair>) -> u64 {",
" return p.left",
"}",
"",
"pub fn main(world: World) -> Void raises {",
' let text: String = "alignment"',
" let head: Span<u8> = headBytes(text, limit())",
" if std.mem.len(head) == 5 {",
' check world.out.write("aligned\\n")',
" }",
"}",
"",
].join("\n");
writeFileSync(join(oracleAlignRoot, "src", "main.0"), oracleAlignSource);
assert.equal(json(["import", "--json", oracleAlignRoot]).body.ok, true);
assert.equal(zero(["check", oracleAlignRoot]).stdout, "ok\n");
assert.equal(zero(["run", oracleAlignRoot]).stdout, "aligned\n");
const oracleAlignPatch = json(["patch", "--json", oracleAlignRoot, "--op", 'addLetLiteral fn="main" name="probe" type="u32" value="1"']);
assert.equal(oracleAlignPatch.body.ok, true);
// a deliberate bad payload still fails with the diagnostic list and leaves
// the store untouched
const oracleHashBefore = json(["status", "--json", oracleAlignRoot]).body.store.graphHash;
const oracleBadPatch = json(["patch", "--json", oracleAlignRoot, "--op", 'addReturnValue fn="limit" value="no_such_binding" type="usize"'], { allowFailure: true });
assert.notEqual(oracleBadPatch.code, 0);
assert.equal(oracleBadPatch.body.ok, false);
assert.equal(oracleBadPatch.body.diagnostics[0].code, "NAM003");
assert.equal(json(["status", "--json", oracleAlignRoot]).body.store.graphHash, oracleHashBefore);
// an import that introduces two diagnostics reports both in one shot
assert.equal(json(["export", "--json", oracleAlignRoot]).body.ok, true);
writeFileSync(join(oracleAlignRoot, "src", "main.0"), oracleAlignSource.replace(' if std.mem.len(head) == 5 {', " check world.out.write(missing_one)\n check world.out.write(missing_two)\n if std.mem.len(head) == 5 {"));
const oracleMultiImport = json(["import", "--json", oracleAlignRoot], { allowFailure: true });
assert.notEqual(oracleMultiImport.code, 0);
assert.equal(oracleMultiImport.body.diagnostics.length, 2);
assert.equal(oracleMultiImport.body.diagnostics[0].code, "NAM003");
assert.equal(oracleMultiImport.body.diagnostics[1].code, "NAM003");
rmSync(oracleAlignRoot, { force: true, recursive: true });
// pre-existing diagnostics report as notes, not walls: the TAR002 a
// capability-less target reports in zero check predates the patch, so a
// valid op still applies and the note points back at zero check
const oraclePreRoot = join("/tmp", `zero-oracle-preexisting-${process.pid}`);
rmSync(oraclePreRoot, { force: true, recursive: true });
mkdirSync(join(oraclePreRoot, "src"), { recursive: true });
writeFileSync(join(oraclePreRoot, "zero.toml"), '[package]\nname = "oracle-preexisting"\nversion = "0.1.0"\n\n[targets.cli]\nkind = "exe"\nmain = "src/main.0"\n');
writeFileSync(join(oraclePreRoot, "src", "main.0"), 'pub fn main(world: World) -> Void raises {\n let a1: Maybe<String> = std.args.get(1)\n if a1.has {\n check world.out.write(a1.value)\n }\n check world.out.write("done\\n")\n}\n');
assert.equal(json(["import", "--json", oraclePreRoot]).body.ok, true);
// win32-x64.exe is a direct-backend cross target on every CI host, so the
// Args-capability gap is host-independent (linux-x64 resolves to the hosted
// backend on linux runners and reports nothing).
const oraclePreCheck = json(["check", "--json", "--target", "win32-x64.exe", oraclePreRoot], { allowFailure: true });
assert.notEqual(oraclePreCheck.code, 0);
assert.equal(oraclePreCheck.body.diagnostics[0].code, "TAR002");
const oraclePrePatch = zeroWithStderr(["patch", "--target", "win32-x64.exe", oraclePreRoot, "--op", 'addLetLiteral fn="main" name="probe" type="u32" value="1"']);
assert.equal(oraclePrePatch.code, 0);
assert.match(oraclePrePatch.stdout, /program graph patch ok/);
assert.match(oraclePrePatch.stderr, /pre-existing diagnostic predates this patch and did not block it/);
assert.match(oraclePrePatch.stderr, /TAR002: target does not provide required Args capability/);
// the pre-existing note is once-per-state as well: the next patch against the
// same unchanged diagnostic set stays quiet
const oraclePrePatchRepeat = zeroWithStderr(["patch", "--target", "win32-x64.exe", oraclePreRoot, "--op", 'addLetLiteral fn="main" name="probe2" type="u32" value="2"']);
assert.equal(oraclePrePatchRepeat.code, 0);
assert.match(oraclePrePatchRepeat.stdout, /program graph patch ok/);
assert.doesNotMatch(oraclePrePatchRepeat.stderr, /pre-existing diagnostic/, "the pre-existing diagnostics note prints once per diagnostic state");
rmSync(oraclePreRoot, { force: true, recursive: true });
// a store whose recorded projection already fails the compiler typecheck
// (checker drift, stores written by older compilers) does not wall the
// import of unchanged files: the failure prints as a note and the refresh
// proceeds, so one pre-existing diagnostic never costs a whack-a-mole round
const oracleDriftRoot = join("/tmp", `zero-oracle-drift-${process.pid}`);
rmSync(oracleDriftRoot, { force: true, recursive: true });
mkdirSync(join(oracleDriftRoot, "src"), { recursive: true });
writeFileSync(join(oracleDriftRoot, "zero.toml"), '[package]\nname = "oracle-drift"\nversion = "0.1.0"\n\n[targets.cli]\nkind = "exe"\nmain = "src/main.0"\n');
writeFileSync(join(oracleDriftRoot, "src", "main.0"), 'fn want(v: u32) -> u32 {\n return v\n}\n\npub fn main(world: World) -> Void raises {\n let r: u32 = want(1_u32)\n if r == 1 {\n check world.out.write("drift ok\\n")\n }\n}\n');
assert.equal(json(["import", "--json", "--format", "text", oracleDriftRoot]).body.ok, true);
const oracleDriftStorePath = join(oracleDriftRoot, "zero.graph");
writeFileSync(oracleDriftStorePath, readFileSync(oracleDriftStorePath, "utf8").replace("want(1_u32)", 'want(\\"text\\")'));
writeFileSync(join(oracleDriftRoot, "src", "main.0"), readFileSync(join(oracleDriftRoot, "src", "main.0"), "utf8").replace("want(1_u32)", 'want("text")'));
const oracleDriftImport = zeroWithStderr(["import", oracleDriftRoot]);
assert.equal(oracleDriftImport.code, 0);
assert.match(oracleDriftImport.stdout, /repository graph import ok/);
assert.match(oracleDriftImport.stderr, /note: a pre-existing diagnostic predates this import and did not block it \(the file is unchanged since the last sync\)/);
assert.equal(json(["status", "--json", oracleDriftRoot]).body.repositoryGraph.projectionState, "clean");
assert.equal(zero(["check", oracleDriftRoot]).stdout, "ok\n");
rmSync(oracleDriftRoot, { force: true, recursive: true });
const reconcileScaleRoot = join("/tmp", `zero-reconcile-scale-${process.pid}`);
const reconcileScaleSource = join(reconcileScaleRoot, "src", "main.0");
rmSync(reconcileScaleRoot, { force: true, recursive: true });
assert.equal(json(["init", "--json", reconcileScaleRoot]).body.ok, true);
mkdirSync(join(reconcileScaleRoot, "src"), { recursive: true });
const reconcileScaleFunctions: string[] = [];
for (let i = 0; i < 240; i++) {
reconcileScaleFunctions.push([
`fn helper${i}(x: usize) -> usize {`,
" var a: usize = x",
...Array.from({ length: 8 }, (_, j) => ` a = a + ${i * 8 + j + 1}_usize`),
" return a",
"}",
].join("\n"));
}
const reconcileScaleMain = 'pub fn main(world: World) -> Void raises {\n check world.out.write("reconcile scale\\n")\n}';
writeFileSync(reconcileScaleSource, `${reconcileScaleFunctions.join("\n\n")}\n\n${reconcileScaleMain}\n`);
assert.equal(json(["import", "--json", reconcileScaleRoot]).body.ok, true);
const reconcileScaleNeedle = "fn helper120(x: usize) -> usize {\n var a: usize = x";
const reconcileScaleText = readFileSync(reconcileScaleSource, "utf8");
assert(reconcileScaleText.includes(reconcileScaleNeedle));
writeFileSync(reconcileScaleSource, reconcileScaleText.replace(reconcileScaleNeedle, `${reconcileScaleNeedle}\n var inserted: usize = a + 7001_usize\n inserted = inserted + 7003_usize\n a = a + inserted`));
const reconcileScaleStarted = Date.now();
let reconcileScaleStdout = "";
try {
reconcileScaleStdout = execFileSync(zeroBin, ["reconcile", "--json", reconcileScaleRoot, "--source", reconcileScaleSource], { encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"], timeout: 120000 });
} catch (error) {
assert(false, `zero reconcile on a multi-statement insertion into a large package did not complete: ${error.signal ?? error.status}`);
}
const reconcileScaleElapsed = Date.now() - reconcileScaleStarted;
assert(reconcileScaleElapsed < 60000, `zero reconcile on a large package took ${reconcileScaleElapsed}ms`);
if (reconcileScaleStdout) {
const reconcileScale = JSON.parse(reconcileScaleStdout);
assert.equal(reconcileScale.ok, true);
assert.equal(reconcileScale.identity.moduleIdentityChanged, false);
assert.equal(reconcileScale.identity.ambiguous, 0);
assert(reconcileScale.identity.inserted > 0);
assert(reconcileScale.identity.unchanged > 0);
}
assert.equal(zero(["run", reconcileScaleRoot]).stdout, "reconcile scale\n");
assert.equal(json(["status", "--json", reconcileScaleRoot]).body.repositoryGraph.projectionState, "clean");
const postCheckWriteFailureRoot = join("/tmp", `zero-repo-graph-post-check-write-${process.pid}`);
const postCheckWriteFailureHelper = join(postCheckWriteFailureRoot, "src", "helper.0");
rmSync(postCheckWriteFailureRoot, { force: true, recursive: true });
mkdirSync(join(postCheckWriteFailureRoot, "src"), { recursive: true });
writeFileSync(join(postCheckWriteFailureRoot, "zero.toml"), readFileSync("conformance/packages/test-app/zero.toml", "utf8"));
writeFileSync(join(postCheckWriteFailureRoot, "src", "main.0"), readFileSync("conformance/packages/test-app/src/main.0", "utf8"));
writeFileSync(postCheckWriteFailureHelper, readFileSync("conformance/packages/test-app/src/helper.0", "utf8"));
json(["import", "--format", "text", "--json", postCheckWriteFailureRoot]);
const postCheckWriteFailureOriginalHelper = readFileSync(postCheckWriteFailureHelper, "utf8");
writeFileSync(postCheckWriteFailureHelper, postCheckWriteFailureOriginalHelper.replace("return value + value", "return value + value + 0"));
writeZeroTomlSync(postCheckWriteFailureRoot, { package: { name: "test-app", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "src/missing.0" } } });
const postCheckWriteFailure = json(["export", "--json", postCheckWriteFailureRoot], { allowFailure: true });
assert.notEqual(postCheckWriteFailure.code, 0);
assert.equal(postCheckWriteFailure.body.diagnostics[0].code, "RGP006");
assert.equal(postCheckWriteFailure.body.writes, true);
assert.deepEqual(postCheckWriteFailure.body.changedPaths, [postCheckWriteFailureHelper]);
assert.equal(readFileSync(postCheckWriteFailureHelper, "utf8"), postCheckWriteFailureOriginalHelper);
const targetProjectionRoot = join("/tmp", `zero-repo-graph-target-projection-${process.pid}`);
const targetProjectionSource = join(targetProjectionRoot, "main.0");
rmSync(targetProjectionRoot, { force: true, recursive: true });
mkdirSync(targetProjectionRoot, { recursive: true });
writeFileSync(targetProjectionSource, readFileSync("conformance/native/pass/meta-typed-target-type.0", "utf8"));
const targetProjectionSync = json(["import", "--format", "text", "--json", "--target", "linux-musl-x64", targetProjectionSource]);
assert.equal(targetProjectionSync.code, 0);
assert.equal(targetProjectionSync.body.repositoryGraph.projectionState, "clean");
const targetProjectionStatus = json(["status", "--json", "--target", "linux-musl-x64", targetProjectionSource]);
assert.equal(targetProjectionStatus.code, 0);
assert.equal(targetProjectionStatus.body.repositoryGraph.projectionState, "clean");
const targetProjectionVerify = json(["verify-projection", "--json", "--target", "linux-musl-x64", targetProjectionSource]);
assert.equal(targetProjectionVerify.code, 0);
assert.equal(targetProjectionVerify.body.ok, true);
const targetProjectionVerifyScript = repositoryGraphVerifyScript(targetProjectionRoot, { target: "linux-musl-x64" });
assert.equal(targetProjectionVerifyScript.code, 0);
assert.match(targetProjectionVerifyScript.stdout, /repository graph verify-projection ok \(1 store\)/);
const targetProjectionExport = json(["export", "--json", "--target", "linux-musl-x64", targetProjectionSource]);
assert.equal(targetProjectionExport.code, 0);
assert.equal(targetProjectionExport.body.repositoryGraph.projectionState, "clean");
assert.deepEqual(targetProjectionExport.body.changedPaths, []);
const typeInvalidRepoGraphRoot = join("/tmp", `zero-repo-graph-type-invalid-${process.pid}`);
const typeInvalidRepoGraphSource = join(typeInvalidRepoGraphRoot, "main.0");
const typeInvalidRepoGraphStore = join(typeInvalidRepoGraphRoot, "zero.graph");
rmSync(typeInvalidRepoGraphRoot, { force: true, recursive: true });
mkdirSync(typeInvalidRepoGraphRoot, { recursive: true });
writeFileSync(typeInvalidRepoGraphSource, "pub fn main() -> i32 {\n return true\n}\n");
const typeInvalidRepoGraphSync = json(["import", "--format", "text", "--json", typeInvalidRepoGraphSource], { allowFailure: true });
assert.notEqual(typeInvalidRepoGraphSync.code, 0);
assert.equal(typeInvalidRepoGraphSync.body.diagnostics[0].code, "TYP003");
assert(!existsSync(typeInvalidRepoGraphStore));
const stdProjectionRoot = join("/tmp", `zero-repo-graph-std-projection-${process.pid}`);
const stdProjectionSource = join(stdProjectionRoot, "std-path-io.0");
const stdProjectionStore = join(stdProjectionRoot, "zero.graph");
rmSync(stdProjectionRoot, { force: true, recursive: true });
mkdirSync(stdProjectionRoot, { recursive: true });
writeFileSync(stdProjectionSource, readFileSync("examples/std-path-io.0", "utf8"));
const stdProjectionSync = json(["import", "--format", "text", "--json", stdProjectionSource]);
assert.equal(stdProjectionSync.code, 0);
assert.equal(stdProjectionSync.body.repositoryGraph.projectionState, "clean");
const stdProjectionStoreText = readFileSync(stdProjectionStore, "utf8");
assert.match(stdProjectionStoreText, /^source path:"std-path-io\.0"$/m);
assert.doesNotMatch(stdProjectionStoreText, /^source path:"std\//m);
assert.match(stdProjectionStoreText, /^projection path:"std-path-io\.0" text:/m);
assert.doesNotMatch(stdProjectionStoreText, /^projection path:"std\//m);
const stdProjectionVerify = json(["verify-projection", "--json", stdProjectionSource]);
assert.equal(stdProjectionVerify.body.ok, true);
const embeddedStdMainRoot = join("/tmp", `zero-repo-graph-embedded-std-main-${process.pid}`);
const embeddedStdMainStore = join(embeddedStdMainRoot, "zero.graph");
rmSync(embeddedStdMainRoot, { force: true, recursive: true });
mkdirSync(join(embeddedStdMainRoot, "std"), { recursive: true });
writeZeroTomlSync(embeddedStdMainRoot, { package: { name: "embedded-std-main", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "std/path.0" } } });
writeFileSync(join(embeddedStdMainRoot, "std", "path.0"), readFileSync("std/path.0", "utf8"));
const embeddedStdMainSync = json(["import", "--format", "text", "--json", embeddedStdMainRoot]);
assert.equal(embeddedStdMainSync.code, 0);
assert.equal(embeddedStdMainSync.body.ok, true);
assert.equal(embeddedStdMainSync.body.repositoryGraph.projectionState, "clean");
const embeddedStdMainStoreText = readFileSync(embeddedStdMainStore, "utf8");
assert.match(embeddedStdMainStoreText, /^projection path:"std\/path\.0" text:/m);
const embeddedStdMainVerify = json(["verify-projection", "--json", embeddedStdMainRoot]);
assert.equal(embeddedStdMainVerify.body.ok, true);
const embeddedStdRelativeRoot = join("/tmp", `zero-repo-graph-embedded-std-relative-${process.pid}`);
const embeddedStdRelativeSource = join(embeddedStdRelativeRoot, "std", "path.0");
rmSync(embeddedStdRelativeRoot, { force: true, recursive: true });
mkdirSync(join(embeddedStdRelativeRoot, "std"), { recursive: true });
writeFileSync(embeddedStdRelativeSource, readFileSync("std/path.0", "utf8"));
writeFileSync(join(embeddedStdRelativeRoot, "std", "str.0"), readFileSync("std/str.0", "utf8"));
const embeddedStdRelativeSync = json(["import", "--format", "text", "--json", embeddedStdRelativeSource]);
assert.equal(embeddedStdRelativeSync.code, 0);
assert.equal(embeddedStdRelativeSync.body.repositoryGraph.projectionState, "clean");
const embeddedStdRelativeVerify = json(["verify-projection", "--json", embeddedStdRelativeSource]);
assert.equal(embeddedStdRelativeVerify.body.ok, true);
writeFileSync(stdProjectionStore, refreshRepositoryGraphCompilerMetadata(stdProjectionStoreText.replace(/^nodeHash /m, `projection path:"std/path.0" text:${JSON.stringify("// embedded std projection should be rejected\\n")}\nnodeHash `)));
const embeddedStdProjectionStatus = json(["status", "--json", stdProjectionSource], { allowFailure: true });
assert.notEqual(embeddedStdProjectionStatus.code, 0);
assert.equal(embeddedStdProjectionStatus.body.diagnostics[0].code, "RGP003");
assert.match(embeddedStdProjectionStatus.body.diagnostics[0].actual, /unknown source path/);
const partialProjectionRoot = join("/tmp", `zero-repo-graph-partial-projection-${process.pid}`);
const partialProjectionStore = join(partialProjectionRoot, "zero.graph");
rmSync(partialProjectionRoot, { force: true, recursive: true });
mkdirSync(join(partialProjectionRoot, "src"), { recursive: true });
writeFileSync(join(partialProjectionRoot, "zero.toml"), readFileSync("conformance/packages/test-app/zero.toml", "utf8"));
writeFileSync(join(partialProjectionRoot, "src", "main.0"), readFileSync("conformance/packages/test-app/src/main.0", "utf8"));
writeFileSync(join(partialProjectionRoot, "src", "helper.0"), readFileSync("conformance/packages/test-app/src/helper.0", "utf8"));
json(["import", "--format", "text", "--json", partialProjectionRoot]);
const partialProjectionStoreText = readFileSync(partialProjectionStore, "utf8");
assert.match(partialProjectionStoreText, /^source path:"src\/helper\.0"$/m);
assert.match(partialProjectionStoreText, /^projection path:"src\/helper\.0" text:/m);
const swappedProjectionStoreText = partialProjectionStoreText.replace(
/^(projection path:"src\/helper\.0" text:[^\n]*\n)(projection path:"src\/main\.0" text:[^\n]*\n)/m,
"$2$1",
);
writeFileSync(partialProjectionStore, swappedProjectionStoreText);
const swappedProjectionStatus = json(["status", "--json", partialProjectionRoot], { allowFailure: true });
assert.notEqual(swappedProjectionStatus.code, 0);
assert.equal(swappedProjectionStatus.body.diagnostics[0].code, "RGP003");
assert.match(swappedProjectionStatus.body.diagnostics[0].actual, /byte-stable/);
writeFileSync(partialProjectionStore, partialProjectionStoreText);
writeFileSync(partialProjectionStore, refreshRepositoryGraphCompilerMetadata(partialProjectionStoreText.replace(/^projection path:"src\/helper\.0" text:[^\n]*\n/m, "")));
const partialProjectionStatus = json(["status", "--json", partialProjectionRoot], { allowFailure: true });
assert.notEqual(partialProjectionStatus.code, 0);
assert.equal(partialProjectionStatus.body.diagnostics[0].code, "RGP003");
assert.match(partialProjectionStatus.body.diagnostics[0].actual, /projection table is missing a source path/);
const partialProjectionWriteRoot = join("/tmp", `zero-repo-graph-partial-write-${process.pid}`);
const partialProjectionWriteMain = join(partialProjectionWriteRoot, "src", "main.0");
const partialProjectionWriteHelper = join(partialProjectionWriteRoot, "src", "helper.0");
rmSync(partialProjectionWriteRoot, { force: true, recursive: true });
mkdirSync(join(partialProjectionWriteRoot, "src"), { recursive: true });
writeFileSync(join(partialProjectionWriteRoot, "zero.toml"), readFileSync("conformance/packages/test-app/zero.toml", "utf8"));
writeFileSync(partialProjectionWriteMain, readFileSync("conformance/packages/test-app/src/main.0", "utf8"));
writeFileSync(partialProjectionWriteHelper, readFileSync("conformance/packages/test-app/src/helper.0", "utf8"));
json(["import", "--format", "text", "--json", partialProjectionWriteRoot]);
const partialProjectionOriginalHelper = readFileSync(partialProjectionWriteHelper, "utf8");
const partialProjectionDriftedHelper = partialProjectionOriginalHelper.replace("return value + value", "return value + value + 0");
writeFileSync(partialProjectionWriteHelper, partialProjectionDriftedHelper);
writeFileSync(partialProjectionWriteMain, readFileSync(partialProjectionWriteMain, "utf8").replace("package tests", "package tests drift"));
rmSync(partialProjectionWriteMain, { force: true });
mkdirSync(partialProjectionWriteMain);
const partialProjectionWriteFailure = json(["export", "--json", partialProjectionWriteRoot], { allowFailure: true });
assert.notEqual(partialProjectionWriteFailure.code, 0);
assert.equal(partialProjectionWriteFailure.body.diagnostics[0].code, "RGP004");
assert.equal(partialProjectionWriteFailure.body.writes, false);
assert.equal(readFileSync(partialProjectionWriteHelper, "utf8"), partialProjectionDriftedHelper);
const unsafeProjectionRoot = join("/tmp", `zero-repo-graph-unsafe-projection-${process.pid}`);
const unsafeProjectionSource = join(unsafeProjectionRoot, "outside.0");
const unsafeProjectionArtifact = join(unsafeProjectionRoot, "outside.program-graph");
const unsafeProjectionStoreRoot = join(unsafeProjectionRoot, "repo");
const unsafeProjectionStore = join(unsafeProjectionStoreRoot, "zero.graph");
const unsafeProjectionText = "// should not be written outside the repository graph root\n";
rmSync(unsafeProjectionRoot, { force: true, recursive: true });
mkdirSync(unsafeProjectionStoreRoot, { recursive: true });
writeFileSync(unsafeProjectionSource, readFileSync("examples/hello.0", "utf8"));
assert.equal(zero(["import", "--out", unsafeProjectionArtifact, unsafeProjectionSource]).stdout, "");
const unsafeProjectionGraph = zero(["dump", unsafeProjectionArtifact]).stdout;
const unsafeProjectionGraphJson = json(["dump", "--json", unsafeProjectionArtifact]).body;
const unsafeProjectionQuote = JSON.stringify;
const unsafeProjectionStoreLines = [
"zero-repository-graph v1",
`sourceProjection ${unsafeProjectionQuote(".0")}`,
`moduleIdentity ${unsafeProjectionQuote(unsafeProjectionGraphJson.moduleIdentity)}`,
`graphHash ${unsafeProjectionQuote(unsafeProjectionGraphJson.graphHash)}`,
`moduleHash ${unsafeProjectionQuote(unsafeProjectionGraphJson.graphHash)}`,
`source path:${unsafeProjectionQuote(unsafeProjectionSource)}`,
`projection path:${unsafeProjectionQuote(unsafeProjectionSource)} text:${unsafeProjectionQuote(unsafeProjectionText)}`,
...unsafeProjectionGraphJson.nodes.map((node) => `nodeHash node:${unsafeProjectionQuote(node.id)} hash:${unsafeProjectionQuote(node.nodeHash)}`),
];
writeFileSync(unsafeProjectionStore, `${unsafeProjectionStoreLines.join("\n")}\n\ngraph\n${unsafeProjectionGraph}`);
const unsafeProjectionStatus = json(["status", "--json", unsafeProjectionStoreRoot], { allowFailure: true });
assert.notEqual(unsafeProjectionStatus.code, 0);
assert.equal(unsafeProjectionStatus.body.diagnostics[0].code, "RGP003");
assert.match(unsafeProjectionStatus.body.diagnostics[0].actual, /invalid repository graph store/);
const unsafeProjectionSync = json(["export", "--json", unsafeProjectionStoreRoot], { allowFailure: true });
assert.notEqual(unsafeProjectionSync.code, 0);
assert.notEqual(readFileSync(unsafeProjectionSource, "utf8"), unsafeProjectionText);
if (process.platform !== "win32") {
const symlinkProjectionParent = join("/tmp", `zero-repo-graph-symlink-projection-${process.pid}`);
const symlinkProjectionRoot = join(symlinkProjectionParent, "repo");
const symlinkProjectionOutside = join(symlinkProjectionParent, "outside");
const symlinkProjectionRootSourceDir = join(symlinkProjectionRoot, "src");
const symlinkProjectionRootSource = join(symlinkProjectionRootSourceDir, "main.0");
const symlinkProjectionOutsideSource = join(symlinkProjectionOutside, "main.0");
rmSync(symlinkProjectionParent, { force: true, recursive: true });
mkdirSync(symlinkProjectionRoot, { recursive: true });
mkdirSync(symlinkProjectionRootSourceDir, { recursive: true });
mkdirSync(symlinkProjectionOutside, { recursive: true });
writeZeroTomlSync(symlinkProjectionRoot, { package: { name: "symlink-projection", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "src/main.0" } } });
writeFileSync(symlinkProjectionRootSource, readFileSync("examples/hello.0", "utf8"));
json(["import", "--format", "text", "--json", symlinkProjectionRoot]);
rmSync(symlinkProjectionRootSourceDir, { force: true, recursive: true });
symlinkSync(symlinkProjectionOutside, symlinkProjectionRootSourceDir, "dir");
writeFileSync(symlinkProjectionOutsideSource, readFileSync("examples/hello.0", "utf8"));
const symlinkProjectionDriftedSource = readFileSync(symlinkProjectionOutsideSource, "utf8").replace("hello from zero", "changed outside projection root");
writeFileSync(symlinkProjectionOutsideSource, symlinkProjectionDriftedSource);
const symlinkProjectionSync = json(["export", "--json", symlinkProjectionRoot], { allowFailure: true });
assert.notEqual(symlinkProjectionSync.code, 0);
assert.equal(symlinkProjectionSync.body.diagnostics[0].code, "RGP004");
assert.equal(symlinkProjectionSync.body.writes, false);
assert.equal(readFileSync(symlinkProjectionOutsideSource, "utf8"), symlinkProjectionDriftedSource);
}
const repoGraphArtifactInputRoot = join("/tmp", `zero-repo-graph-artifact-input-${process.pid}`);
const repoGraphArtifactInputPath = join(repoGraphArtifactInputRoot, "hello.program-graph");
rmSync(repoGraphArtifactInputRoot, { force: true, recursive: true });
mkdirSync(repoGraphArtifactInputRoot, { recursive: true });
zero(["dump", "--out", repoGraphArtifactInputPath, "examples/hello.0"]);
const repoGraphStatusArtifactNoStore = json(["status", "--json", repoGraphArtifactInputPath], { allowFailure: true });
assert.notEqual(repoGraphStatusArtifactNoStore.code, 0);
assert.equal(repoGraphStatusArtifactNoStore.body.diagnostics[0].message, "expected Zero source file or package");
const repoGraphVerifyArtifactNoStore = json(["verify-projection", "--json", repoGraphArtifactInputPath], { allowFailure: true });
assert.notEqual(repoGraphVerifyArtifactNoStore.code, 0);
assert.equal(repoGraphVerifyArtifactNoStore.body.diagnostics[0].message, "expected Zero source file or package");
assert(!existsSync(join(repoGraphArtifactInputRoot, "zero.graph")));
const repoGraphSyncFromArtifact = json(["import", "--format", "text", "--json", repoGraphArtifactInputPath], { allowFailure: true });
assert.notEqual(repoGraphSyncFromArtifact.code, 0);
assert.equal(repoGraphSyncFromArtifact.body.diagnostics[0].message, "expected Zero source file or package");
assert(!existsSync(join(repoGraphArtifactInputRoot, "zero.graph")));
writeFileSync(join(repoGraphArtifactInputRoot, "zero.graph"), readFileSync(standaloneRepoGraphStore));
const repoGraphVerifyArtifactWithStore = json(["verify-projection", "--json", repoGraphArtifactInputPath], { allowFailure: true });
assert.notEqual(repoGraphVerifyArtifactWithStore.code, 0);
assert.equal(repoGraphVerifyArtifactWithStore.body.diagnostics[0].message, "expected Zero source file or package");
const copiedRepoGraphRootA = join("/tmp", `zero-repo-graph-copied-a-${process.pid}`);
const copiedRepoGraphRootB = join("/tmp", `zero-repo-graph-copied-b-${process.pid}`);
rmSync(copiedRepoGraphRootA, { force: true, recursive: true });
rmSync(copiedRepoGraphRootB, { force: true, recursive: true });
mkdirSync(copiedRepoGraphRootA, { recursive: true });
mkdirSync(copiedRepoGraphRootB, { recursive: true });
const copiedRepoGraphSourceText = `pub fn main(world: World) -> Void raises {
let total: i32 = 41 + 1
if total == 42 {
check world.out.write("copied graph source ok\\n")
}
}
`;
writeFileSync(join(copiedRepoGraphRootA, "main.0"), copiedRepoGraphSourceText);
writeFileSync(join(copiedRepoGraphRootB, "main.0"), copiedRepoGraphSourceText);
const copiedRepoGraphSourceA = join(copiedRepoGraphRootA, "main.0");
const copiedRepoGraphSourceB = join(copiedRepoGraphRootB, "main.0");
json(["import", "--format", "text", "--json", copiedRepoGraphSourceA]);
writeFileSync(join(copiedRepoGraphRootB, "zero.graph"), readFileSync(join(copiedRepoGraphRootA, "zero.graph")));
const copiedRepoGraphVerify = json(["verify-projection", "--json", copiedRepoGraphSourceB]);
assert.equal(copiedRepoGraphVerify.code, 0);
assert.equal(copiedRepoGraphVerify.body.ok, true);
writeFileSync(copiedRepoGraphSourceB, readFileSync(copiedRepoGraphSourceB, "utf8").replace("copied graph source ok", "checker copied graph store"));
const copiedRepoGraphVerifyDrift = json(["verify-projection", "--json", copiedRepoGraphSourceB], { allowFailure: true });
assert.notEqual(copiedRepoGraphVerifyDrift.code, 0);
assert.equal(copiedRepoGraphVerifyDrift.body.diagnostics[0].code, "RGP006");
const identityRepoGraphRoot = join("/tmp", `zero-repo-graph-identity-${process.pid}`);
const identityRepoGraphSource = join(identityRepoGraphRoot, "main.0");
const identityRepoGraphStore = join(identityRepoGraphRoot, "zero.graph");
rmSync(identityRepoGraphRoot, { force: true, recursive: true });
mkdirSync(identityRepoGraphRoot, { recursive: true });
writeFileSync(
identityRepoGraphSource,
`use std.mem
pub fn main(world: World) -> Void raises {
let text: String = "zero"
if std.mem.len(text) == 4 {
check world.out.write("identity ok\\n")
}
}
`,
);
json(["import", "--format", "text", "--json", identityRepoGraphSource]);
const identityRepoGraphStoreText = readFileSync(identityRepoGraphStore, "utf8");
const identityRepoGraphMainId = identityRepoGraphStoreText.match(/^node (#[^ ]+) Function name:"main"/m)?.[1];
const identityRepoGraphMemImportId = identityRepoGraphStoreText.match(/^node (#[^ ]+) Import name:"std\.mem"/m)?.[1];
const identityRepoGraphLiteralId = identityRepoGraphStoreText.match(/^node (#[^ ]+) Literal [^\n]*value:"identity ok\\n"/m)?.[1];
assert(identityRepoGraphMainId);
assert(identityRepoGraphMemImportId);
assert(identityRepoGraphLiteralId);
writeFileSync(
identityRepoGraphSource,
`// human source edit
use std.str
use std.mem
pub fn main(world: World) -> Void raises {
let label: String = "zero"
let count: usize = std.mem.len(label)
if count == 4 {
// projection comment
check world.out.write("identity updated\\n")
}
}
`,
);
const identityRepoGraphSyncEdited = json(["import", "--format", "text", "--json", identityRepoGraphSource]);
assert.equal(identityRepoGraphSyncEdited.code, 0);
assert.equal(identityRepoGraphSyncEdited.body.repositoryGraph.projectionState, "clean");
const identityRepoGraphEditedStoreText = readFileSync(identityRepoGraphStore, "utf8");
assert(identityRepoGraphEditedStoreText.includes(`node ${identityRepoGraphMainId} Function name:"main"`));
assert(identityRepoGraphEditedStoreText.includes(`node ${identityRepoGraphMemImportId} Import name:"std.mem"`));
assert(identityRepoGraphEditedStoreText.includes(`node ${identityRepoGraphLiteralId} Literal type:"String" value:"identity updated\\n"`));
assert.match(identityRepoGraphEditedStoreText, /^node #[^ ]+ Import name:"std\.str"/m);
assert.match(identityRepoGraphEditedStoreText, /^projection path:"main\.0" text:"\/\/ human source edit\\n/m);
assert(identityRepoGraphEditedStoreText.includes("// projection comment"));
const identityRepoGraphSourceAfterSync = readFileSync(identityRepoGraphSource, "utf8");
const identityRepoGraphSyncProjection = json(["export", "--json", identityRepoGraphSource]);
assert.equal(identityRepoGraphSyncProjection.code, 0);
assert.deepEqual(identityRepoGraphSyncProjection.body.changedPaths, []);
assert.equal(readFileSync(identityRepoGraphSource, "utf8"), identityRepoGraphSourceAfterSync);
const deleteRepoGraphRoot = join("/tmp", `zero-repo-graph-delete-${process.pid}`);
const deleteRepoGraphSource = join(deleteRepoGraphRoot, "main.0");
const deleteRepoGraphStore = join(deleteRepoGraphRoot, "zero.graph");
rmSync(deleteRepoGraphRoot, { force: true, recursive: true });
mkdirSync(deleteRepoGraphRoot, { recursive: true });
const deleteRepoGraphOriginal = `fn alpha() -> i32 {
return 1
}
fn beta() -> i32 {
return 2
}
fn gamma() -> i32 {
return 3
}
pub fn main(world: World) -> Void raises {
check world.out.write("delete ok\\n")
}
`;
writeFileSync(deleteRepoGraphSource, deleteRepoGraphOriginal);
json(["import", "--format", "text", "--json", deleteRepoGraphSource]);
const deleteRepoGraphStoreBefore = readFileSync(deleteRepoGraphStore, "utf8");
const deleteRepoGraphAlphaId = deleteRepoGraphStoreBefore.match(/^node (#[^ ]+) Function name:"alpha"/m)?.[1];
const deleteRepoGraphBetaId = deleteRepoGraphStoreBefore.match(/^node (#[^ ]+) Function name:"beta"/m)?.[1];
const deleteRepoGraphGammaId = deleteRepoGraphStoreBefore.match(/^node (#[^ ]+) Function name:"gamma"/m)?.[1];
assert(deleteRepoGraphAlphaId);
assert(deleteRepoGraphBetaId);
assert(deleteRepoGraphGammaId);
writeFileSync(
deleteRepoGraphSource,
deleteRepoGraphOriginal.replace(
`\nfn beta() -> i32 {
return 2
}
`,
"",
),
);
const deleteRepoGraphSync = json(["import", "--format", "text", "--json", deleteRepoGraphSource]);
assert.equal(deleteRepoGraphSync.code, 0);
assert.equal(deleteRepoGraphSync.body.repositoryGraph.projectionState, "clean");
const deleteRepoGraphStoreAfter = readFileSync(deleteRepoGraphStore, "utf8");
assert(deleteRepoGraphStoreAfter.includes(`node ${deleteRepoGraphAlphaId} Function name:"alpha"`));
assert(deleteRepoGraphStoreAfter.includes(`node ${deleteRepoGraphGammaId} Function name:"gamma"`));
assert(!deleteRepoGraphStoreAfter.includes(`node ${deleteRepoGraphBetaId} Function name:"beta"`));
const renameRepoGraphRoot = join("/tmp", `zero-repo-graph-rename-${process.pid}`);
const renameRepoGraphSource = join(renameRepoGraphRoot, "main.0");
const renameRepoGraphStore = join(renameRepoGraphRoot, "zero.graph");
rmSync(renameRepoGraphRoot, { force: true, recursive: true });
mkdirSync(renameRepoGraphRoot, { recursive: true });
const renameRepoGraphOriginal = `fn alpha() -> i32 {
return 1
}
fn beta() -> i32 {
return 2
}
pub fn main(world: World) -> Void raises {
check world.out.write("rename ok\\n")
}
`;
writeFileSync(renameRepoGraphSource, renameRepoGraphOriginal);
json(["import", "--format", "text", "--json", renameRepoGraphSource]);
const renameRepoGraphStoreBefore = readFileSync(renameRepoGraphStore, "utf8");
const renameRepoGraphBetaId = renameRepoGraphStoreBefore.match(/^node (#[^ ]+) Function name:"beta"/m)?.[1];
assert(renameRepoGraphBetaId);
writeFileSync(renameRepoGraphSource, renameRepoGraphOriginal.replace("fn beta()", "fn gamma()"));
const renameRepoGraphSync = json(["import", "--format", "text", "--json", renameRepoGraphSource]);
assert.equal(renameRepoGraphSync.code, 0);
assert.equal(renameRepoGraphSync.body.repositoryGraph.projectionState, "clean");
assert(readFileSync(renameRepoGraphStore, "utf8").includes(`node ${renameRepoGraphBetaId} Function name:"gamma"`));
const moduleIdentityRepoGraphRoot = join("/tmp", `zero-repo-graph-module-identity-${process.pid}`);
const moduleIdentityRepoGraphSourceOne = join(moduleIdentityRepoGraphRoot, "one.0");
const moduleIdentityRepoGraphSourceTwo = join(moduleIdentityRepoGraphRoot, "two.0");
const moduleIdentityRepoGraphStore = join(moduleIdentityRepoGraphRoot, "zero.graph");
rmSync(moduleIdentityRepoGraphRoot, { force: true, recursive: true });
mkdirSync(moduleIdentityRepoGraphRoot, { recursive: true });
writeFileSync(
moduleIdentityRepoGraphSourceOne,
`pub fn main(world: World) -> Void raises {
check world.out.write("module one\\n")
}
`,
);
json(["import", "--format", "text", "--json", moduleIdentityRepoGraphSourceOne]);
const moduleIdentityRepoGraphStoreBefore = readFileSync(moduleIdentityRepoGraphStore, "utf8");
renameSync(moduleIdentityRepoGraphSourceOne, moduleIdentityRepoGraphSourceTwo);
const moduleIdentityRepoGraphSync = json(["import", "--format", "text", "--json", moduleIdentityRepoGraphSourceTwo], { allowFailure: true });
assert.notEqual(moduleIdentityRepoGraphSync.code, 0);
assert.equal(moduleIdentityRepoGraphSync.body.diagnostics[0].code, "RGP007");
assert.equal(moduleIdentityRepoGraphSync.body.diagnostics[0].message, "repository graph source identity has a different module identity");
assert.equal(moduleIdentityRepoGraphSync.body.diagnostics[0].expected, "module:one");
assert.equal(moduleIdentityRepoGraphSync.body.diagnostics[0].actual, "module:two");
assert.match(moduleIdentityRepoGraphSync.body.diagnostics[0].help, /module rename/);
assert.equal(readFileSync(moduleIdentityRepoGraphStore, "utf8"), moduleIdentityRepoGraphStoreBefore);
const ambiguousRepoGraphRoot = join("/tmp", `zero-repo-graph-ambiguous-${process.pid}`);
const ambiguousRepoGraphSource = join(ambiguousRepoGraphRoot, "main.0");
const ambiguousRepoGraphStore = join(ambiguousRepoGraphRoot, "zero.graph");
rmSync(ambiguousRepoGraphRoot, { force: true, recursive: true });
mkdirSync(ambiguousRepoGraphRoot, { recursive: true });
writeFileSync(
ambiguousRepoGraphSource,
`fn add(a: i32, b: i32) -> i32 {
return a + b
}
pub fn main(world: World) -> Void raises {
let total: i32 = add(1, 2)
if total == 3 {
check world.out.write("ambiguous ok\\n")
}
}
`,
);
json(["import", "--format", "text", "--json", ambiguousRepoGraphSource]);
const ambiguousRepoGraphStoreBefore = readFileSync(ambiguousRepoGraphStore, "utf8");
writeFileSync(ambiguousRepoGraphSource, readFileSync(ambiguousRepoGraphSource, "utf8").replace("add(1, 2)", "add(2, 1)"));
// The argument swap ties structurally, but it is a single-file edit whose
// function set still matches by name and signature, so import accepts the
// rewrite wholesale with regenerated node identities instead of RGP007.
const ambiguousRepoGraphSync = zeroWithStderr(["import", "--format", "text", "--json", ambiguousRepoGraphSource]);
assert.equal(ambiguousRepoGraphSync.code, 0);
assert.match(ambiguousRepoGraphSync.stderr, /note: file-scope rewrite accepted; node identities regenerated for main\.0/);
assert.equal(JSON.parse(ambiguousRepoGraphSync.stdout).repositoryGraph.projectionState, "clean");
assert.notEqual(readFileSync(ambiguousRepoGraphStore, "utf8"), ambiguousRepoGraphStoreBefore);
const rotatedRepoGraphRoot = join("/tmp", `zero-repo-graph-rotated-${process.pid}`);
const rotatedRepoGraphSource = join(rotatedRepoGraphRoot, "main.0");
const rotatedRepoGraphStore = join(rotatedRepoGraphRoot, "zero.graph");
rmSync(rotatedRepoGraphRoot, { force: true, recursive: true });
mkdirSync(rotatedRepoGraphRoot, { recursive: true });
writeFileSync(
rotatedRepoGraphSource,
`fn sum3(a: i32, b: i32, c: i32) -> i32 {
return a + b + c
}
pub fn main(world: World) -> Void raises {
let total: i32 = sum3(1, 2, 3)
if total == 6 {
check world.out.write("rotated ok\\n")
}
}
`,
);
json(["import", "--format", "text", "--json", rotatedRepoGraphSource]);
const rotatedRepoGraphStoreBefore = readFileSync(rotatedRepoGraphStore, "utf8");
writeFileSync(rotatedRepoGraphSource, readFileSync(rotatedRepoGraphSource, "utf8").replace("sum3(1, 2, 3)", "sum3(2, 3, 1)"));
// Rotated identical arguments tie structurally; the single-file rewrite is
// accepted wholesale with regenerated identities instead of RGP007.
const rotatedRepoGraphSync = zeroWithStderr(["import", "--format", "text", "--json", rotatedRepoGraphSource]);
assert.equal(rotatedRepoGraphSync.code, 0);
assert.match(rotatedRepoGraphSync.stderr, /note: file-scope rewrite accepted; node identities regenerated for main\.0/);
assert.equal(JSON.parse(rotatedRepoGraphSync.stdout).repositoryGraph.projectionState, "clean");
assert.notEqual(readFileSync(rotatedRepoGraphStore, "utf8"), rotatedRepoGraphStoreBefore);
const ambiguousSiblingRepoGraphRoot = join("/tmp", `zero-repo-graph-ambiguous-sibling-${process.pid}`);
const ambiguousSiblingRepoGraphSource = join(ambiguousSiblingRepoGraphRoot, "main.0");
const ambiguousSiblingRepoGraphStore = join(ambiguousSiblingRepoGraphRoot, "zero.graph");
rmSync(ambiguousSiblingRepoGraphRoot, { force: true, recursive: true });
mkdirSync(ambiguousSiblingRepoGraphRoot, { recursive: true });
const ambiguousSiblingRepoGraphOriginal = `fn helper() -> i32 {
return 1
}
pub fn main(world: World) -> Void raises {
check world.out.write("sibling ok\\n")
}
`;
writeFileSync(ambiguousSiblingRepoGraphSource, ambiguousSiblingRepoGraphOriginal);
json(["import", "--format", "text", "--json", ambiguousSiblingRepoGraphSource]);
const ambiguousSiblingRepoGraphStoreBefore = readFileSync(ambiguousSiblingRepoGraphStore, "utf8");
const ambiguousSiblingRepoGraphHelperId = ambiguousSiblingRepoGraphStoreBefore.match(/^node (#[^ ]+) Function name:"helper"/m)?.[1];
assert(ambiguousSiblingRepoGraphHelperId);
writeFileSync(
ambiguousSiblingRepoGraphSource,
ambiguousSiblingRepoGraphOriginal.replace(
"\npub fn main",
"\nfn appendedHelper() -> i32 {\n return 2\n}\n\npub fn main",
),
);
const ambiguousSiblingRepoGraphSync = json(["import", "--format", "text", "--json", ambiguousSiblingRepoGraphSource], { allowFailure: true });
assert.equal(ambiguousSiblingRepoGraphSync.code, 0);
assert.equal(ambiguousSiblingRepoGraphSync.body.repositoryGraph.projectionState, "clean");
const ambiguousSiblingRepoGraphStoreAfter = readFileSync(ambiguousSiblingRepoGraphStore, "utf8");
assert(ambiguousSiblingRepoGraphStoreAfter.includes(`node ${ambiguousSiblingRepoGraphHelperId} Function name:"helper"`));
const ambiguousSiblingRepoGraphAppendedId = ambiguousSiblingRepoGraphStoreAfter.match(/^node (#[^ ]+) Function name:"appendedHelper"/m)?.[1];
assert(ambiguousSiblingRepoGraphAppendedId);
assert.notEqual(ambiguousSiblingRepoGraphAppendedId, ambiguousSiblingRepoGraphHelperId);
const insertRunRepoGraphRoot = join("/tmp", `zero-repo-graph-insert-run-${process.pid}`);
const insertRunRepoGraphSource = join(insertRunRepoGraphRoot, "main.0");
const insertRunRepoGraphStore = join(insertRunRepoGraphRoot, "zero.graph");
rmSync(insertRunRepoGraphRoot, { force: true, recursive: true });
mkdirSync(insertRunRepoGraphRoot, { recursive: true });
const insertRunRepoGraphOriginal = `fn fill(out: MutSpan<u8>, n: usize) -> usize {
var i: usize = 0
var p: usize = 0
while i < n {
p = p + 1_usize
i = i + 1_usize
}
return p
}
pub fn main(world: World) -> Void raises {
check world.out.write("insert run ok\\n")
}
`;
writeFileSync(insertRunRepoGraphSource, insertRunRepoGraphOriginal);
json(["import", "--format", "text", "--json", insertRunRepoGraphSource]);
const insertRunRepoGraphStoreBefore = readFileSync(insertRunRepoGraphStore, "utf8");
const insertRunRepoGraphWhileId = insertRunRepoGraphStoreBefore.match(/^node (#[^ ]+) While/m)?.[1];
const insertRunRepoGraphReturnId = insertRunRepoGraphStoreBefore.match(/^node (#[^ ]+) Return path:"main\.0" line:8/m)?.[1];
assert(insertRunRepoGraphWhileId);
assert(insertRunRepoGraphReturnId);
assert(!insertRunRepoGraphWhileId.includes("-"));
writeFileSync(
insertRunRepoGraphSource,
insertRunRepoGraphOriginal.replace(
" while i < n {",
" var padded: usize = 0\n while padded < n {\n padded = padded + 1_usize\n }\n var spill: usize = padded\n while i < n {",
),
);
const insertRunRepoGraphSync = json(["import", "--format", "text", "--json", insertRunRepoGraphSource]);
assert.equal(insertRunRepoGraphSync.code, 0);
assert.equal(insertRunRepoGraphSync.body.repositoryGraph.projectionState, "clean");
const insertRunRepoGraphStoreAfter = readFileSync(insertRunRepoGraphStore, "utf8");
assert(insertRunRepoGraphStoreAfter.includes(`node ${insertRunRepoGraphWhileId} While`));
assert(insertRunRepoGraphStoreAfter.includes(`node ${insertRunRepoGraphReturnId} Return`));
const insertRunRepoGraphWhileIds = [...insertRunRepoGraphStoreAfter.matchAll(/^node (#[^ ]+) While/gm)].map((m) => m[1]);
assert.equal(insertRunRepoGraphWhileIds.length, 2);
assert(insertRunRepoGraphWhileIds.includes(insertRunRepoGraphWhileId));
const ambiguousRunRepoGraphRoot = join("/tmp", `zero-repo-graph-ambiguous-run-${process.pid}`);
const ambiguousRunRepoGraphSource = join(ambiguousRunRepoGraphRoot, "main.0");
const ambiguousRunRepoGraphStore = join(ambiguousRunRepoGraphRoot, "zero.graph");
rmSync(ambiguousRunRepoGraphRoot, { force: true, recursive: true });
mkdirSync(ambiguousRunRepoGraphRoot, { recursive: true });
writeFileSync(ambiguousRunRepoGraphSource, insertRunRepoGraphOriginal);
json(["import", "--format", "text", "--json", ambiguousRunRepoGraphSource]);
const ambiguousRunRepoGraphStoreBefore = readFileSync(ambiguousRunRepoGraphStore, "utf8");
const ambiguousRunRepoGraphWhileId = ambiguousRunRepoGraphStoreBefore.match(/^node (#[^ ]+) While/m)?.[1];
assert(ambiguousRunRepoGraphWhileId);
writeFileSync(
ambiguousRunRepoGraphSource,
insertRunRepoGraphOriginal.replace(
" while i < n {",
" var padded: usize = 0\n while padded < n {\n padded = padded + 1_usize\n }\n while i <= n {",
),
);
// An inserted sibling plus an edit to the original statement used to fail RGP007;
// import now disambiguates by structural similarity and keeps the original handle
// on the statement that shares its body.
const ambiguousRunRepoGraphSync = zeroWithStderr(["import", "--format", "text", "--json", ambiguousRunRepoGraphSource]);
assert.equal(ambiguousRunRepoGraphSync.code, 0);
assert.match(ambiguousRunRepoGraphSync.stderr, /note: import matched 1 edited node to existing graph identities by structure/);
const ambiguousRunRepoGraphStoreAfter = readFileSync(ambiguousRunRepoGraphStore, "utf8");
const ambiguousRunRepoGraphResolvedLine = ambiguousRunRepoGraphStoreAfter
.split("\n")
.find((line) => line.startsWith(`node ${ambiguousRunRepoGraphWhileId} While`));
assert(ambiguousRunRepoGraphResolvedLine, "original while handle survives the auto-resolved import");
assert.match(ambiguousRunRepoGraphResolvedLine, /line:8/, "original while handle follows the statement that kept its body");
// Identical edited candidates at shifted orders stay genuinely ambiguous; the
// same edit also widens fill's signature, so the file-scope rewrite escape
// stays closed (function set changed) and the import keeps RGP007.
const tieRunRepoGraphRoot = join("/tmp", `zero-repo-graph-tie-run-${process.pid}`);
const tieRunRepoGraphSource = join(tieRunRepoGraphRoot, "main.0");
const tieRunRepoGraphStore = join(tieRunRepoGraphRoot, "zero.graph");
rmSync(tieRunRepoGraphRoot, { force: true, recursive: true });
mkdirSync(tieRunRepoGraphRoot, { recursive: true });
writeFileSync(tieRunRepoGraphSource, insertRunRepoGraphOriginal);
json(["import", "--format", "text", "--json", tieRunRepoGraphSource]);
const tieRunRepoGraphStoreBefore = readFileSync(tieRunRepoGraphStore, "utf8");
writeFileSync(
tieRunRepoGraphSource,
insertRunRepoGraphOriginal.replace(
" while i < n {\n p = p + 1_usize\n i = i + 1_usize\n }\n",
" var shift: usize = 0\n while i <= n {\n p = p + 2_usize\n i = i + 1_usize\n }\n while i <= n {\n p = p + 2_usize\n i = i + 1_usize\n }\n",
).replace(
"fn fill(out: MutSpan<u8>, n: usize) -> usize {",
"fn fill(out: MutSpan<u8>, n: usize, pad: usize) -> usize {",
),
);
const tieRunRepoGraphSync = json(["import", "--format", "text", "--json", tieRunRepoGraphSource], { allowFailure: true });
assert.notEqual(tieRunRepoGraphSync.code, 0);
assert.equal(tieRunRepoGraphSync.body.diagnostics[0].code, "RGP007");
assert.equal(tieRunRepoGraphSync.body.diagnostics[0].message, "repository graph source identity is ambiguous");
assert.match(tieRunRepoGraphSync.body.diagnostics[0].actual, /matches 2 edited candidates at main\.0:\d+-\d+/);
assert.match(tieRunRepoGraphSync.body.diagnostics[0].help, /split the text edit: import the change touching main\.0:\d+-\d+ on its own first/);
assert.equal(readFileSync(tieRunRepoGraphStore, "utf8"), tieRunRepoGraphStoreBefore);
rmSync(tieRunRepoGraphRoot, { force: true, recursive: true });
// Whole-file rewrite escape: a single-file rewrite of a multi-function module
// whose function set still matches by name and signature imports in one pass;
// the file's node identities are regenerated and other files keep theirs.
const fileScopeRoot = join(outDir, "repository-graph-file-scope-rewrite");
const fileScopeStore = join(fileScopeRoot, "zero.graph");
rmSync(fileScopeRoot, { recursive: true, force: true });
mkdirSync(join(fileScopeRoot, "src"), { recursive: true });
writeZeroTomlSync(fileScopeRoot, { package: { name: "file-scope", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "src/main.0" } } });
const fileScopeUtilOriginal = [
"pub fn fill(n: usize) -> usize {",
" var i: usize = 0",
" var p: usize = 0",
" while i < n {",
" p = p + 1_usize",
" i = i + 1_usize",
" }",
" return p",
"}",
"",
"pub fn cap(n: usize) -> usize {",
" return n",
"}",
"",
].join("\n");
const fileScopeUtilRewrite = [
"pub fn fill(n: usize) -> usize {",
" var i: usize = 0",
" var p: usize = 0",
" var shift: usize = 0",
" while i <= n {",
" p = p + 2_usize",
" i = i + 1_usize",
" }",
" while i <= n {",
" p = p + 2_usize",
" i = i + 1_usize",
" }",
" return p + shift",
"}",
"",
"pub fn cap(n: usize) -> usize {",
" return n + 0_usize",
"}",
"",
].join("\n");
const fileScopeMainOriginal = [
"use util",
"",
"pub fn main(world: World) -> Void raises {",
" if fill(2) >= cap(1) {",
' check world.out.write("file scope ok\\n")',
" }",
"}",
"",
].join("\n");
writeFileSync(join(fileScopeRoot, "src", "util.0"), fileScopeUtilOriginal);
writeFileSync(join(fileScopeRoot, "src", "main.0"), fileScopeMainOriginal);
assert.equal(json(["import", "--format", "text", "--json", fileScopeRoot]).code, 0);
assert.equal(zero(["check", fileScopeRoot]).stdout, "ok\n");
const fileScopeStoreBefore = readFileSync(fileScopeStore, "utf8");
const fileScopeMainId = fileScopeStoreBefore.match(/^node (#[^ ]+) Function name:"main"/m)?.[1];
assert(fileScopeMainId, "expected a main Function node in the file-scope store");
writeFileSync(join(fileScopeRoot, "src", "util.0"), fileScopeUtilRewrite);
const fileScopeSync = zeroWithStderr(["import", "--format", "text", "--json", fileScopeRoot]);
assert.equal(fileScopeSync.code, 0);
assert.match(fileScopeSync.stderr, /note: file-scope rewrite accepted; node identities regenerated for src\/util\.0/);
assert.equal(JSON.parse(fileScopeSync.stdout).repositoryGraph.projectionState, "clean");
const fileScopeStoreAfter = readFileSync(fileScopeStore, "utf8");
assert(fileScopeStoreAfter.includes(`node ${fileScopeMainId} Function name:"main"`), "untouched files keep their node identities");
assert.equal(zero(["check", fileScopeRoot]).stdout, "ok\n");
// Handles and queries resolve against the regenerated identities in one pass.
const fileScopeHandlesView = zero(["view", "--fn", "fill", "--handles", fileScopeRoot]).stdout;
const fileScopeReturnLine = fileScopeHandlesView.split("\n").find((line) => line.includes("return p + shift"));
assert(fileScopeReturnLine, "expected the rewritten return row in the handles view");
const fileScopeHandle = fileScopeReturnLine.match(/\/\/ (#[0-9a-z_.]+)/)?.[1];
assert(fileScopeHandle, "expected a patch handle on the rewritten return row");
const fileScopeQueryHandles = json(["query", "--json", "--fn", "fill", "--handles", fileScopeRoot]).body;
assert.equal(fileScopeQueryHandles.ok, true);
const fileScopePatch = json(["patch", "--json", fileScopeRoot, "--op", `replaceExpr node="${fileScopeHandle}" with="p + shift + 0_usize"`]).body;
assert.equal(fileScopePatch.ok, true);
assert.match(zero(["view", "--fn", "fill", fileScopeRoot]).stdout, /return p \+ shift \+ 0_usize/);
// Cross-file ambiguity keeps RGP007: the same tie-producing rewrite plus an
// edit in a second file is not a file-scope rewrite.
writeFileSync(join(fileScopeRoot, "src", "util.0"), fileScopeUtilOriginal);
writeFileSync(join(fileScopeRoot, "src", "main.0"), fileScopeMainOriginal);
assert.equal(json(["import", "--format", "text", "--json", fileScopeRoot]).code, 0);
const crossFileStoreBefore = readFileSync(fileScopeStore, "utf8");
writeFileSync(join(fileScopeRoot, "src", "util.0"), fileScopeUtilRewrite);
writeFileSync(join(fileScopeRoot, "src", "main.0"), fileScopeMainOriginal.replace("file scope ok", "cross file ok"));
const crossFileSync = json(["import", "--format", "text", "--json", fileScopeRoot], { allowFailure: true });
assert.notEqual(crossFileSync.code, 0);
assert.equal(crossFileSync.body.diagnostics[0].code, "RGP007");
assert.equal(crossFileSync.body.diagnostics[0].message, "repository graph source identity is ambiguous");
assert.equal(readFileSync(fileScopeStore, "utf8"), crossFileStoreBefore);
const mergeRepoGraphRoot = join("/tmp", `zero-repo-graph-merge-${process.pid}`);
const mergeRepoGraphSource = join(mergeRepoGraphRoot, "main.0");
const mergeRepoGraphStore = join(mergeRepoGraphRoot, "zero.graph");
rmSync(mergeRepoGraphRoot, { force: true, recursive: true });
mkdirSync(mergeRepoGraphRoot, { recursive: true });
const mergeRepoGraphOriginal = `fn alpha() -> i32 {
return 1
}
fn beta() -> i32 {
return 2
}
pub fn main(world: World) -> Void raises {
check world.out.write("merge ok\\n")
}
`;
writeFileSync(mergeRepoGraphSource, mergeRepoGraphOriginal);
json(["import", "--format", "text", "--json", mergeRepoGraphSource]);
writeFileSync(join(mergeRepoGraphRoot, "base.graph"), readFileSync(mergeRepoGraphStore, "utf8"));
writeFileSync(mergeRepoGraphSource, mergeRepoGraphOriginal.replace("return 1", "return 10"));
json(["import", "--format", "text", "--json", mergeRepoGraphSource]);
writeFileSync(join(mergeRepoGraphRoot, "left.graph"), readFileSync(mergeRepoGraphStore, "utf8"));
writeFileSync(mergeRepoGraphStore, readFileSync(join(mergeRepoGraphRoot, "base.graph"), "utf8"));
writeFileSync(mergeRepoGraphSource, mergeRepoGraphOriginal.replace("return 2", "return 20"));
json(["import", "--format", "text", "--json", mergeRepoGraphSource]);
writeFileSync(join(mergeRepoGraphRoot, "right.graph"), readFileSync(mergeRepoGraphStore, "utf8"));
const mergeRepoGraphResult = json([
"merge",
"--json",
"--base",
join(mergeRepoGraphRoot, "base.graph"),
"--left",
join(mergeRepoGraphRoot, "left.graph"),
"--right",
join(mergeRepoGraphRoot, "right.graph"),
mergeRepoGraphRoot,
]);
assert.equal(mergeRepoGraphResult.code, 0);
assert.equal(mergeRepoGraphResult.body.mode, "merge");
assert.equal(mergeRepoGraphResult.body.writes, true);
assert.equal(mergeRepoGraphResult.body.repositoryGraph.projectionState, "source-stale");
assert.equal(mergeRepoGraphResult.body.merge.conflicts, 0);
assert.equal(mergeRepoGraphResult.body.merge.leftChanges, 1);
assert.equal(mergeRepoGraphResult.body.merge.rightChanges, 1);
assert.equal(mergeRepoGraphResult.body.merge.target, mergeRepoGraphStore);
assert.deepEqual(mergeRepoGraphResult.body.changedPaths, [mergeRepoGraphStore]);
const mergeRepoGraphText = readFileSync(mergeRepoGraphStore, "utf8");
assert(mergeRepoGraphText.includes('value:"10"'));
assert(mergeRepoGraphText.includes('value:"20"'));
const mergeRepoGraphSyncProjection = json(["export", "--json", mergeRepoGraphSource]);
assert.equal(mergeRepoGraphSyncProjection.body.repositoryGraph.projectionState, "clean");
assert(readFileSync(mergeRepoGraphSource, "utf8").includes("return 10"));
assert(readFileSync(mergeRepoGraphSource, "utf8").includes("return 20"));
const mergeStaleProjectionRoot = join("/tmp", `zero-repo-graph-merge-stale-projection-${process.pid}`);
const mergeStaleProjectionSource = join(mergeStaleProjectionRoot, "main.0");
const mergeStaleProjectionStore = join(mergeStaleProjectionRoot, "zero.graph");
rmSync(mergeStaleProjectionRoot, { force: true, recursive: true });
mkdirSync(mergeStaleProjectionRoot, { recursive: true });
writeFileSync(mergeStaleProjectionSource, mergeRepoGraphOriginal);
json(["import", "--format", "text", "--json", mergeStaleProjectionSource]);
writeFileSync(join(mergeStaleProjectionRoot, "base.graph"), readFileSync(mergeStaleProjectionStore, "utf8"));
writeFileSync(join(mergeStaleProjectionRoot, "right.graph"), readFileSync(mergeStaleProjectionStore, "utf8"));
writeFileSync(mergeStaleProjectionSource, mergeRepoGraphOriginal.replace("return 1", "return 10"));
json(["import", "--format", "text", "--json", mergeStaleProjectionSource]);
writeFileSync(
join(mergeStaleProjectionRoot, "left.graph"),
readFileSync(mergeStaleProjectionStore, "utf8").replace("return 10", "return 999"),
);
writeFileSync(mergeStaleProjectionStore, readFileSync(join(mergeStaleProjectionRoot, "base.graph"), "utf8"));
const mergeStaleProjection = json([
"merge",
"--json",
"--base",
join(mergeStaleProjectionRoot, "base.graph"),
"--left",
join(mergeStaleProjectionRoot, "left.graph"),
"--right",
join(mergeStaleProjectionRoot, "right.graph"),
mergeStaleProjectionRoot,
]);
assert.equal(mergeStaleProjection.code, 0);
assert.equal(mergeStaleProjection.body.merge.conflicts, 0);
const mergeStaleProjectionText = readFileSync(mergeStaleProjectionStore, "utf8");
assert(mergeStaleProjectionText.includes('value:"10"'));
assert(!mergeStaleProjectionText.includes('value:"999"'));
const mergeProjectionOnlyConflictRoot = join("/tmp", `zero-repo-graph-merge-projection-only-conflict-${process.pid}`);
const mergeProjectionOnlyConflictSource = join(mergeProjectionOnlyConflictRoot, "main.0");
const mergeProjectionOnlyConflictStore = join(mergeProjectionOnlyConflictRoot, "zero.graph");
rmSync(mergeProjectionOnlyConflictRoot, { force: true, recursive: true });
mkdirSync(mergeProjectionOnlyConflictRoot, { recursive: true });
const mergeProjectionOnlyConflictOriginal = `// base comment
fn alpha() -> i32 {
return 1
}
pub fn main(world: World) -> Void raises {
check world.out.write("merge projection-only conflict ok\\n")
}
`;
writeFileSync(mergeProjectionOnlyConflictSource, mergeProjectionOnlyConflictOriginal);
json(["import", "--format", "text", "--json", mergeProjectionOnlyConflictSource]);
writeFileSync(join(mergeProjectionOnlyConflictRoot, "base.graph"), readFileSync(mergeProjectionOnlyConflictStore, "utf8"));
writeFileSync(mergeProjectionOnlyConflictSource, mergeProjectionOnlyConflictOriginal.replace("return 1", "return 10"));
json(["import", "--format", "text", "--json", mergeProjectionOnlyConflictSource]);
writeFileSync(join(mergeProjectionOnlyConflictRoot, "left.graph"), readFileSync(mergeProjectionOnlyConflictStore, "utf8"));
writeFileSync(mergeProjectionOnlyConflictStore, readFileSync(join(mergeProjectionOnlyConflictRoot, "base.graph"), "utf8"));
writeFileSync(mergeProjectionOnlyConflictSource, mergeProjectionOnlyConflictOriginal.replace("base comment", "right comment"));
json(["import", "--format", "text", "--json", mergeProjectionOnlyConflictSource]);
writeFileSync(join(mergeProjectionOnlyConflictRoot, "right.graph"), readFileSync(mergeProjectionOnlyConflictStore, "utf8"));
writeFileSync(mergeProjectionOnlyConflictStore, readFileSync(join(mergeProjectionOnlyConflictRoot, "base.graph"), "utf8"));
const mergeProjectionOnlyConflict = json([
"merge",
"--json",
"--base",
join(mergeProjectionOnlyConflictRoot, "base.graph"),
"--left",
join(mergeProjectionOnlyConflictRoot, "left.graph"),
"--right",
join(mergeProjectionOnlyConflictRoot, "right.graph"),
mergeProjectionOnlyConflictRoot,
], { allowFailure: true });
assert.notEqual(mergeProjectionOnlyConflict.code, 0);
assert.equal(mergeProjectionOnlyConflict.body.writes, false);
assert.equal(mergeProjectionOnlyConflict.body.diagnostics[0].code, "RGM005");
assert.equal(mergeProjectionOnlyConflict.body.diagnostics[0].message, "repository graph projection-only edit conflicts with graph changes");
assert.equal(mergeProjectionOnlyConflict.body.merge.conflicts, 1);
const mergeProjectionOnlyConflictText = readFileSync(mergeProjectionOnlyConflictStore, "utf8");
assert(mergeProjectionOnlyConflictText.includes("base comment"));
assert(!mergeProjectionOnlyConflictText.includes("right comment"));
assert(!mergeProjectionOnlyConflictText.includes('value:"10"'));
const mergeDeleteShiftRoot = join("/tmp", `zero-repo-graph-merge-delete-shift-${process.pid}`);
const mergeDeleteShiftSource = join(mergeDeleteShiftRoot, "main.0");
const mergeDeleteShiftStore = join(mergeDeleteShiftRoot, "zero.graph");
rmSync(mergeDeleteShiftRoot, { force: true, recursive: true });
mkdirSync(mergeDeleteShiftRoot, { recursive: true });
const mergeDeleteShiftOriginal = `fn alpha() -> i32 {
return 1
}
fn beta() -> i32 {
return 2
}
pub fn main(world: World) -> Void raises {
check world.out.write("merge delete shift ok\\n")
}
`;
writeFileSync(mergeDeleteShiftSource, mergeDeleteShiftOriginal);
json(["import", "--format", "text", "--json", mergeDeleteShiftSource]);
writeFileSync(join(mergeDeleteShiftRoot, "base.graph"), readFileSync(mergeDeleteShiftStore, "utf8"));
writeFileSync(mergeDeleteShiftSource, mergeDeleteShiftOriginal.replace(/fn alpha\(\) -> i32 \{\n return 1\n\}\n\n/, ""));
json(["import", "--format", "text", "--json", mergeDeleteShiftSource]);
writeFileSync(join(mergeDeleteShiftRoot, "left.graph"), readFileSync(mergeDeleteShiftStore, "utf8"));
writeFileSync(mergeDeleteShiftStore, readFileSync(join(mergeDeleteShiftRoot, "base.graph"), "utf8"));
writeFileSync(mergeDeleteShiftSource, mergeDeleteShiftOriginal.replace("return 2", "return 20"));
json(["import", "--format", "text", "--json", mergeDeleteShiftSource]);
writeFileSync(join(mergeDeleteShiftRoot, "right.graph"), readFileSync(mergeDeleteShiftStore, "utf8"));
writeFileSync(mergeDeleteShiftStore, readFileSync(join(mergeDeleteShiftRoot, "base.graph"), "utf8"));
writeFileSync(mergeDeleteShiftSource, mergeDeleteShiftOriginal);
const mergeDeleteShift = json([
"merge",
"--json",
"--base",
join(mergeDeleteShiftRoot, "base.graph"),
"--left",
join(mergeDeleteShiftRoot, "left.graph"),
"--right",
join(mergeDeleteShiftRoot, "right.graph"),
mergeDeleteShiftRoot,
]);
assert.equal(mergeDeleteShift.code, 0);
assert.equal(mergeDeleteShift.body.merge.conflicts, 0);
const mergeDeleteShiftText = readFileSync(mergeDeleteShiftStore, "utf8");
assert(!mergeDeleteShiftText.includes('name:"alpha"'));
assert(mergeDeleteShiftText.includes('name:"beta"'));
assert(mergeDeleteShiftText.includes('value:"20"'));
const mergeDeleteShiftSyncProjection = json(["export", "--json", mergeDeleteShiftSource]);
assert.equal(mergeDeleteShiftSyncProjection.body.repositoryGraph.projectionState, "clean");
assert(!readFileSync(mergeDeleteShiftSource, "utf8").includes("fn alpha"));
assert(readFileSync(mergeDeleteShiftSource, "utf8").includes("return 20"));
const mergeBothDeleteRoot = join("/tmp", `zero-repo-graph-merge-both-delete-${process.pid}`);
const mergeBothDeleteSource = join(mergeBothDeleteRoot, "main.0");
const mergeBothDeleteStore = join(mergeBothDeleteRoot, "zero.graph");
rmSync(mergeBothDeleteRoot, { force: true, recursive: true });
mkdirSync(mergeBothDeleteRoot, { recursive: true });
writeFileSync(mergeBothDeleteSource, mergeDeleteShiftOriginal);
json(["import", "--format", "text", "--json", mergeBothDeleteSource]);
writeFileSync(join(mergeBothDeleteRoot, "base.graph"), readFileSync(mergeBothDeleteStore, "utf8"));
const mergeBothDeleteEdited = mergeDeleteShiftOriginal.replace(/fn alpha\(\) -> i32 \{\n return 1\n\}\n\n/, "");
writeFileSync(mergeBothDeleteSource, mergeBothDeleteEdited);
json(["import", "--format", "text", "--json", mergeBothDeleteSource]);
writeFileSync(join(mergeBothDeleteRoot, "left.graph"), readFileSync(mergeBothDeleteStore, "utf8"));
writeFileSync(mergeBothDeleteStore, readFileSync(join(mergeBothDeleteRoot, "base.graph"), "utf8"));
writeFileSync(mergeBothDeleteSource, mergeBothDeleteEdited);
json(["import", "--format", "text", "--json", mergeBothDeleteSource]);
writeFileSync(join(mergeBothDeleteRoot, "right.graph"), readFileSync(mergeBothDeleteStore, "utf8"));
writeFileSync(mergeBothDeleteStore, readFileSync(join(mergeBothDeleteRoot, "base.graph"), "utf8"));
const mergeBothDelete = json([
"merge",
"--json",
"--base",
join(mergeBothDeleteRoot, "base.graph"),
"--left",
join(mergeBothDeleteRoot, "left.graph"),
"--right",
join(mergeBothDeleteRoot, "right.graph"),
mergeBothDeleteRoot,
]);
assert.equal(mergeBothDelete.code, 0);
assert.equal(mergeBothDelete.body.merge.conflicts, 0);
const mergeBothDeleteText = readFileSync(mergeBothDeleteStore, "utf8");
assert(!mergeBothDeleteText.includes('name:"alpha"'));
assert(mergeBothDeleteText.includes('name:"beta"'));
const mergeBothDeleteSyncProjection = json(["export", "--json", mergeBothDeleteSource]);
assert.equal(mergeBothDeleteSyncProjection.body.repositoryGraph.projectionState, "clean");
assert(!readFileSync(mergeBothDeleteSource, "utf8").includes("fn alpha"));
const mergeNoopProjectionRoot = join("/tmp", `zero-repo-graph-merge-noop-projection-${process.pid}`);
const mergeNoopProjectionSource = join(mergeNoopProjectionRoot, "main.0");
const mergeNoopProjectionStore = join(mergeNoopProjectionRoot, "zero.graph");
rmSync(mergeNoopProjectionRoot, { force: true, recursive: true });
mkdirSync(mergeNoopProjectionRoot, { recursive: true });
writeFileSync(
mergeNoopProjectionSource,
`// keep projection comment
fn alpha() -> i32 {
return 1
}
pub fn main(world: World) -> Void raises {
check world.out.write("merge no-op projection ok\\n")
}
`,
);
json(["import", "--format", "text", "--json", mergeNoopProjectionSource]);
writeFileSync(join(mergeNoopProjectionRoot, "base.graph"), readFileSync(mergeNoopProjectionStore, "utf8"));
writeFileSync(join(mergeNoopProjectionRoot, "left.graph"), readFileSync(mergeNoopProjectionStore, "utf8"));
writeFileSync(join(mergeNoopProjectionRoot, "right.graph"), readFileSync(mergeNoopProjectionStore, "utf8"));
const mergeNoopProjection = json([
"merge",
"--json",
"--base",
join(mergeNoopProjectionRoot, "base.graph"),
"--left",
join(mergeNoopProjectionRoot, "left.graph"),
"--right",
join(mergeNoopProjectionRoot, "right.graph"),
mergeNoopProjectionRoot,
]);
assert.equal(mergeNoopProjection.code, 0);
assert.equal(mergeNoopProjection.body.repositoryGraph.projectionState, "clean");
assert(readFileSync(mergeNoopProjectionStore, "utf8").includes("keep projection comment"));
const mergeNoopProjectionVerify = json(["verify-projection", "--json", mergeNoopProjectionSource]);
assert.equal(mergeNoopProjectionVerify.body.ok, true);
const mergeTargetRoot = join("/tmp", `zero-repo-graph-merge-target-${process.pid}`);
const mergeTargetSource = join(mergeTargetRoot, "main.0");
const mergeTargetStore = join(mergeTargetRoot, "zero.graph");
rmSync(mergeTargetRoot, { force: true, recursive: true });
mkdirSync(mergeTargetRoot, { recursive: true });
writeFileSync(mergeTargetSource, readFileSync("conformance/native/pass/meta-typed-target-type.0", "utf8"));
json(["import", "--format", "text", "--json", "--target", "linux-musl-x64", mergeTargetSource]);
const mergeTargetBefore = readFileSync(mergeTargetStore, "utf8");
writeFileSync(join(mergeTargetRoot, "base.graph"), mergeTargetBefore);
writeFileSync(join(mergeTargetRoot, "left.graph"), mergeTargetBefore);
writeFileSync(join(mergeTargetRoot, "right.graph"), mergeTargetBefore);
const mergeTarget = json([
"merge",
"--json",
"--target",
"linux-musl-x64",
"--base",
join(mergeTargetRoot, "base.graph"),
"--left",
join(mergeTargetRoot, "left.graph"),
"--right",
join(mergeTargetRoot, "right.graph"),
mergeTargetRoot,
]);
assert.equal(mergeTarget.code, 0);
assert.equal(mergeTarget.body.merge.conflicts, 0);
assert.equal(readFileSync(mergeTargetStore, "utf8"), mergeTargetBefore);
const mergeTargetVerify = json(["verify-projection", "--json", "--target", "linux-musl-x64", mergeTargetSource]);
assert.equal(mergeTargetVerify.body.ok, true);
const mergePathMoveRoot = join("/tmp", `zero-repo-graph-merge-path-move-${process.pid}`);
const mergePathMoveSource = join(mergePathMoveRoot, "main.0");
const mergePathMoveRenamedSource = join(mergePathMoveRoot, "renamed.0");
const mergePathMoveStore = join(mergePathMoveRoot, "zero.graph");
rmSync(mergePathMoveRoot, { force: true, recursive: true });
mkdirSync(mergePathMoveRoot, { recursive: true });
writeZeroTomlSync(mergePathMoveRoot, { package: { name: "merge-path-move", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "main.0" } } });
writeFileSync(
mergePathMoveSource,
`fn alpha() -> i32 {
return 1
}
pub fn main(world: World) -> Void raises {
check world.out.write("merge path move ok\\n")
}
`,
);
json(["import", "--format", "text", "--json", mergePathMoveRoot]);
writeFileSync(join(mergePathMoveRoot, "base.graph"), readFileSync(mergePathMoveStore, "utf8"));
writeFileSync(join(mergePathMoveRoot, "right.graph"), readFileSync(mergePathMoveStore, "utf8"));
renameSync(mergePathMoveSource, mergePathMoveRenamedSource);
writeZeroTomlSync(mergePathMoveRoot, { package: { name: "merge-path-move", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "renamed.0" } } });
json(["import", "--format", "text", "--json", mergePathMoveRoot]);
writeFileSync(join(mergePathMoveRoot, "left.graph"), readFileSync(mergePathMoveStore, "utf8"));
const mergePathMove = json([
"merge",
"--json",
"--base",
join(mergePathMoveRoot, "base.graph"),
"--left",
join(mergePathMoveRoot, "left.graph"),
"--right",
join(mergePathMoveRoot, "right.graph"),
mergePathMoveRoot,
]);
assert.equal(mergePathMove.code, 0);
const mergePathMoveText = readFileSync(mergePathMoveStore, "utf8");
assert(mergePathMoveText.includes('source path:"renamed.0"'));
assert(mergePathMoveText.includes('projection path:"renamed.0"'));
assert(!mergePathMoveText.includes('source path:"main.0"'));
assert(!mergePathMoveText.includes('projection path:"main.0"'));
const mergePathMoveVerify = json(["verify-projection", "--json", mergePathMoveRoot]);
assert.equal(mergePathMoveVerify.body.ok, true);
const mergeMissingInput = json(["merge", "--json", "--base", join(mergeRepoGraphRoot, "base.graph"), "--left", join(mergeRepoGraphRoot, "left.graph"), mergeRepoGraphRoot], { allowFailure: true });
assert.notEqual(mergeMissingInput.code, 0);
assert.equal(mergeMissingInput.body.diagnostics[0].code, "RGM001");
assert.equal(mergeMissingInput.body.diagnostics[0].actual, "missing --right");
const mergeConflictRepoGraphRoot = join("/tmp", `zero-repo-graph-merge-conflict-${process.pid}`);
const mergeConflictRepoGraphSource = join(mergeConflictRepoGraphRoot, "main.0");
const mergeConflictRepoGraphStore = join(mergeConflictRepoGraphRoot, "zero.graph");
rmSync(mergeConflictRepoGraphRoot, { force: true, recursive: true });
mkdirSync(mergeConflictRepoGraphRoot, { recursive: true });
const mergeConflictOriginal = `fn alpha() -> i32 {
return 1
}
pub fn main(world: World) -> Void raises {
check world.out.write("merge conflict ok\\n")
}
`;
writeFileSync(mergeConflictRepoGraphSource, mergeConflictOriginal);
json(["import", "--format", "text", "--json", mergeConflictRepoGraphSource]);
writeFileSync(join(mergeConflictRepoGraphRoot, "base.graph"), readFileSync(mergeConflictRepoGraphStore, "utf8"));
writeFileSync(mergeConflictRepoGraphSource, mergeConflictOriginal.replace("return 1", "return 10"));
json(["import", "--format", "text", "--json", mergeConflictRepoGraphSource]);
writeFileSync(join(mergeConflictRepoGraphRoot, "left.graph"), readFileSync(mergeConflictRepoGraphStore, "utf8"));
writeFileSync(mergeConflictRepoGraphStore, readFileSync(join(mergeConflictRepoGraphRoot, "base.graph"), "utf8"));
writeFileSync(mergeConflictRepoGraphSource, mergeConflictOriginal.replace("return 1", "return 20"));
json(["import", "--format", "text", "--json", mergeConflictRepoGraphSource]);
writeFileSync(join(mergeConflictRepoGraphRoot, "right.graph"), readFileSync(mergeConflictRepoGraphStore, "utf8"));
const mergeConflict = json([
"merge",
"--json",
"--base",
join(mergeConflictRepoGraphRoot, "base.graph"),
"--left",
join(mergeConflictRepoGraphRoot, "left.graph"),
"--right",
join(mergeConflictRepoGraphRoot, "right.graph"),
mergeConflictRepoGraphRoot,
], { allowFailure: true });
assert.notEqual(mergeConflict.code, 0);
assert.equal(mergeConflict.body.mode, "merge");
assert.equal(mergeConflict.body.writes, false);
assert.equal(mergeConflict.body.diagnostics[0].code, "RGM002");
assert.equal(mergeConflict.body.diagnostics[0].message, "repository graph node was changed on both sides");
assert.equal(mergeConflict.body.diagnostics[0].related[0].kind, "graphNode");
assert.equal(mergeConflict.body.diagnostics[0].related[1].kind, "semanticObject");
assert.equal(mergeConflict.body.diagnostics[0].related[2].kind, "field");
assert.equal(mergeConflict.body.merge.conflicts, 1);
assert(readFileSync(mergeConflictRepoGraphStore, "utf8").includes('value:"20"'));
writeFileSync(standaloneRepoGraphSource, readFileSync(standaloneRepoGraphSource, "utf8").replace("hello from zero", "hello from graph store"));
const standaloneRepoGraphVerifyDrift = json(["verify-projection", "--json", resolve(standaloneRepoGraphSource)], { allowFailure: true });
assert.notEqual(standaloneRepoGraphVerifyDrift.code, 0);
assert.equal(standaloneRepoGraphVerifyDrift.body.diagnostics[0].code, "RGP006");
assert.deepEqual(standaloneRepoGraphVerifyDrift.body.repairCommands, [`zero import ${resolve(standaloneRepoGraphSource)}`, `zero export ${resolve(standaloneRepoGraphSource)}`]);
const standaloneRepoGraphVerifyDriftText = zero(["verify-projection", resolve(standaloneRepoGraphSource)], { allowFailure: true });
assert.notEqual(standaloneRepoGraphVerifyDriftText.code, 0);
assert.match(standaloneRepoGraphVerifyDriftText.stderr, new RegExp(`repair: zero import ${resolve(standaloneRepoGraphSource).replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`));
assert.match(standaloneRepoGraphVerifyDriftText.stderr, new RegExp(`repair: zero export ${resolve(standaloneRepoGraphSource).replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`));
const repositoryGraphVerifyDriftScript = repositoryGraphVerifyScript(standaloneRepoGraphRoot, { allowFailure: true });
assert.notEqual(repositoryGraphVerifyDriftScript.code, 0);
assert.match(repositoryGraphVerifyDriftScript.stderr, /repository graph verify-projection failed/);
assert.match(repositoryGraphVerifyDriftScript.stderr, /repair: zero import/);
assert.match(repositoryGraphVerifyDriftScript.stderr, /repair: zero export/);
const repoGraphVerify = json(["verify-projection", "--json", "."], { allowFailure: true });
assert.notEqual(repoGraphVerify.code, 0);
assert.equal(repoGraphVerify.body.ok, false);
assert.equal(repoGraphVerify.body.mode, "verify-projection");
assert.equal(repoGraphVerify.body.writes, false);
assert.equal(repoGraphVerify.body.diagnostics[0].code, "RGP001");
assert.equal(repoGraphVerify.body.diagnostics[0].actual, "missing zero.graph");
assert(repoGraphVerify.body.repairCommands.includes("zero import ."));
assert(!repoGraphVerify.body.repairCommands.includes("zero export ."));
const repoGraphExport = json(["export", "--json", "."], { allowFailure: true });
assert.notEqual(repoGraphExport.code, 0);
assert.equal(repoGraphExport.body.mode, "export");
assert.equal(repoGraphExport.body.writes, false);
assert.equal(repoGraphExport.body.diagnostics[0].code, "RGP001");
assert.doesNotMatch(graphDump, /node id=/);
const graphDumpJson = json(["dump", "--json", "examples/hello.0"]).body;
assert.equal(graphDumpJson.schemaVersion, 1);
assert.equal(graphDumpJson.moduleIdentity, "module:hello");
assert.equal(graphDumpJson.validation.ok, true);
assert.match(graphDumpJson.graphHash, /^graph:[0-9a-f]{16}$/);
const graphNodeBy = (predicate) => {
const node = graphDumpJson.nodes.find(predicate);
assert(node);
return node;
};
const graphModuleNode = graphNodeBy((node) => node.kind === "Module" && node.name === "hello");
const graphMainFunctionNode = graphNodeBy((node) => node.kind === "Function" && node.name === "main");
const graphMainBodyNode = graphNodeBy((node) => node.kind === "Block" && node.name === "body");
const graphHelloLiteralNode = graphNodeBy((node) => node.kind === "Literal" && node.type === "String" && node.value === "hello from zero\n");
assert.match(graphModuleNode.id, /^#mod_[0-9a-f]{8}$/);
assert.equal(graphModuleNode.symbolId, "symbol:hello::module");
assert.equal(graphMainFunctionNode.symbolId, "symbol:hello::value.main");
assert.doesNotMatch(graphDump, /node #000001/);
assert(graphDumpJson.edges.some((edge) => edge.from === graphModuleNode.id && edge.to === graphMainFunctionNode.id && edge.kind === "function" && edge.order === 0));
const graphDumpPath = join(outDir, "hello.program-graph");
const graphDumpBinaryPath = join(outDir, "hello.binary.graph");
const graphDumpJsonPath = join(outDir, "hello.dump-json.program-graph");
const graphStableSiblingSourcePath = join(outDir, "hello-stable-sibling.0");
const graphImportPath = join(outDir, "hello.imported.program-graph");
const graphImportJsonPath = join(outDir, "hello.imported-json.program-graph");
const graphImportDirectorySourcePath = join(outDir, "hello-source-directory.0");
const graphImportDirectoryOutPath = join(outDir, "hello-source-directory.program-graph");
const graphInspectOutPath = join(outDir, "hello.inspect.json");
const graphSourceMapOutPath = join(outDir, "hello.source-map.json");
const graphReconcileBasePath = join(outDir, "hello.reconcile-base.program-graph");
const graphReconcileSourcePath = join(outDir, "hello.0");
const graphCanonicalPath = join(outDir, "hello.canonical.program-graph");
const graphSourceTextOutPath = join(outDir, "hello.source-output.0");
const graphValidateSourceTextOutPath = join(outDir, "hello.validate-source-output.0");
const checkedInGraphSourcePath = "conformance/program-graph/hello.0";
const checkedInGraphPackageDir = "conformance/program-graph";
const checkedInGraphDefaultBuildPath = ".zero/out/hello";
const checkedInGraphBuildPath = join(outDir, "checked-in-graph-build");
const checkedInGraphRunPath = join(outDir, "checked-in-graph-run");
const graphRecordRoot = join(outDir, "repository-graph-record");
const graphRecordBuildPath = join(outDir, "repository-graph-record-build");
const graphRecordObjPath = join(outDir, "repository-graph-record.o");
const graphRecordDirectLlvmIrPath = join(outDir, "repository-graph-record-direct.ll");
const graphRecordLlvmIrPath = join(outDir, "repository-graph-record.ll");
const graphViewPath = join(outDir, "hello.graph-view.0");
const graphViewWrongOutPath = join(outDir, "hello.program-graph.txt");
const graphViewParentFilePath = join(outDir, "hello.graph-view-parent-file");
const graphViewParentFileOutPath = join(graphViewParentFilePath, "out.0");
const graphCheckViewPath = join(outDir, "hello.checked.graph-view.0");
const graphSizePath = join(outDir, "hello.program-graph.size.json");
const graphBuildPath = join(outDir, "hello.program-graph-build");
const graphObjPath = join(outDir, "hello.program-graph.o");
const graphRunPath = join(outDir, "hello.program-graph-run");
const graphArgsDumpPath = join(outDir, "std-args.program-graph");
const graphArgsRunPath = join(outDir, "std-args.program-graph-run");
const graphTestDumpPath = join(outDir, "test-blocks.program-graph");
const graphPackageTestDumpPath = join(outDir, "test-app.program-graph");
const graphManifestPackageDir = join(outDir, "graph-manifest-package");
const graphManifestSourcePath = join(graphManifestPackageDir, "src", "main.0");
const graphManifestStorePath = join(graphManifestPackageDir, "zero.graph");
const graphManifestArtifactPath = join(graphManifestPackageDir, "artifacts", "test-app.program-graph");
const graphManifestBuildPath = join(outDir, "graph-manifest-package-build");
const graphManifestRunPath = join(outDir, "graph-manifest-package-run");
const directGraphManifestBuildPath = join(outDir, "direct-graph-manifest-package-build");
const directGraphManifestRunPath = join(outDir, "direct-graph-manifest-package-run");
const directGraphTargetGateRoot = join(outDir, "direct-graph-target-gate");
const directGraphTargetGatePackageDir = join(directGraphTargetGateRoot, "app");
const directGraphTargetGateDepDir = join(directGraphTargetGateRoot, "target-webbits");
const directGraphTargetGateArtifactPath = join(directGraphTargetGatePackageDir, "artifacts", "app.program-graph");
const directGraphHostLeakPackageDir = join(outDir, "direct-graph-host-leak-package");
const directGraphHostLeakArtifactPath = join(directGraphHostLeakPackageDir, "artifacts", "app.program-graph");
const directGraphHostLeakBuildPath = join(outDir, "direct-graph-host-leak-build");
const graphSizeNoisePatchPath = join(outDir, "hello.program-graph.size-noise.patch");
const graphSizeNoisePath = join(outDir, "hello.program-graph.size-noise.program-graph");
const graphSourceRoundtripPath = join(outDir, "hello.source-roundtrip.program-graph");
const graphSourceRoundtripSourceTextPath = join(outDir, "hello.source-roundtrip.0");
const graphArtifactRoundtripPath = join(outDir, "hello.roundtrip.program-graph");
const graphArtifactRoundtripSourceTextPath = join(outDir, "hello.roundtrip.0");
const graphPatchPath = join(outDir, "hello.program-graph.patch");
const graphPatchDirectoryPath = join(outDir, "hello.program-graph.patch-directory");
const graphPatchDirectoryOutPath = join(outDir, "hello.directory-patch.program-graph");
const graphPatchedPath = join(outDir, "hello.patched.program-graph");
const graphInlinePatchedPath = join(outDir, "hello.inline-patched.program-graph");
const graphPatchInsertPath = join(outDir, "hello.insert.program-graph.patch");
const graphInsertedPath = join(outDir, "hello.insert.program-graph");
const graphPatchDeletePath = join(outDir, "hello.delete.program-graph.patch");
const graphDeletedPath = join(outDir, "hello.delete.program-graph");
const graphPatchDeleteThenInsertPath = join(outDir, "hello.delete-then-insert.program-graph.patch");
const graphDeleteThenInsertedPath = join(outDir, "hello.delete-then-insert.program-graph");
const graphPatchDeleteNodeFactPath = join(outDir, "hello.delete-node-fact.program-graph.patch");
const graphDeletedNodeFactPath = join(outDir, "hello.delete-node-fact.program-graph");
const graphRepositoryPatchPackageDir = join(outDir, "repository-graph-patch-package");
const graphRepositoryNewOpsPackageDir = join(outDir, "repository-graph-new-patch-ops");
const graphRepositoryBodyPatchPath = join(outDir, "repository-graph.replace-body.patch");
const graphRepositoryNewOpsPatchPath = join(outDir, "repository-graph.new-ops.patch");
const graphRepositoryBlockPatchPath = join(outDir, "repository-graph.replace-block.patch");
const graphRepositoryInvalidBlockRowsPatchPath = join(outDir, "repository-graph.invalid-block-rows.patch");
const graphRepositoryCheckExprPatchPath = join(outDir, "repository-graph.check-expr.patch");
const graphRepositoryRowErgonomicsPatchPath = join(outDir, "repository-graph.row-ergonomics.patch");
const graphRepositoryInvalidRowsPatchPath = join(outDir, "repository-graph.invalid-rows.patch");
const graphRepositoryInvalidBodyPatchPath = join(outDir, "repository-graph.invalid-body.patch");
const graphPatchDeleteExternalRootRefPath = join(outDir, "hello.delete-external-root-ref.program-graph.patch");
const graphPatchDeleteExtraOwnerPath = join(outDir, "hello.delete-extra-owner.program-graph.patch");
const graphPatchReplacePath = join(outDir, "hello.replace.program-graph.patch");
const graphReplacedPath = join(outDir, "hello.replace.program-graph");
const graphPatchStaleReplacePath = join(outDir, "hello.stale-replace.program-graph.patch");
const graphPatchInsertEdgePath = join(outDir, "hello.insert-edge.program-graph.patch");
const graphInsertedEdgePath = join(outDir, "hello.insert-edge.program-graph");
const graphPatchEmptyTypeEdgePath = join(outDir, "hello.empty-type-edge.program-graph.patch");
const graphPatchRenamePath = join(outDir, "hello.rename.program-graph.patch");
const graphRenamedPath = join(outDir, "hello.rename.program-graph");
const graphPatchInvalidRenamePath = join(outDir, "hello.invalid-rename.program-graph.patch");
const graphUncheckedPatchPath = join(outDir, "hello.unchecked.program-graph.patch");
const graphUncheckedPath = join(outDir, "hello.unchecked.program-graph");
const graphBorrowDumpPath = join(outDir, "borrow.program-graph");
const graphBorrowConflictPatchPath = join(outDir, "borrow-conflict.program-graph.patch");
const graphBorrowConflictPath = join(outDir, "borrow-conflict.program-graph");
const graphPatchEmptyPath = join(outDir, "hello.empty.program-graph.patch");
const graphPatchControlPath = join(outDir, "hello.control.program-graph.patch");
const graphPatchHighBytePath = join(outDir, "hello.high-byte.program-graph.patch");
const graphPatchBadEscapePath = join(outDir, "hello.bad-escape.program-graph.patch");
const graphPatchNullEscapePath = join(outDir, "hello.null-escape.program-graph.patch");
const graphPatchRawNullPath = join(outDir, "hello.raw-null.program-graph.patch");
const graphPatchInvalidNamePath = join(outDir, "hello.invalid-name.program-graph.patch");
const graphPatchInvalidTypePath = join(outDir, "hello.invalid-type.program-graph.patch");
const graphPatchReservedParamPath = join(outDir, "hello.reserved-param.program-graph.patch");
const graphReservedParamPath = join(outDir, "hello.reserved-param.program-graph");
const graphPatchInternalFunctionPath = join(outDir, "hello.internal-function.program-graph.patch");
const graphInternalFunctionPath = join(outDir, "hello.internal-function.program-graph");
const graphPayloadDumpPath = join(outDir, "payload-match.program-graph");
const graphPatchInvalidMatchReplacePath = join(outDir, "payload-match.invalid-replace.program-graph.patch");
const graphPatchInvalidMatchInsertPath = join(outDir, "payload-match.invalid-insert.program-graph.patch");
const graphPackageDumpPath = join(outDir, "systems-package.program-graph");
const graphPackageViewPath = join(outDir, "systems-package.graph-view.0");
const graphPackagePathMismatchPatchPath = join(outDir, "systems-package.path-mismatch.program-graph.patch");
const graphPackagePathMismatchPath = join(outDir, "systems-package.path-mismatch.program-graph");
const graphPatchInvalidImportAliasPath = join(outDir, "systems-package.invalid-import-alias.program-graph.patch");
const graphPatchInvalidImportNamePath = join(outDir, "systems-package.invalid-import-name.program-graph.patch");
const graphInvalidImportNamePath = join(outDir, "systems-package.invalid-import-name.program-graph");
const graphPatchMissingImportPath = join(outDir, "systems-package.missing-import.program-graph.patch");
const graphMissingImportPath = join(outDir, "systems-package.missing-import.program-graph");
const graphPatchMismatchPath = join(outDir, "hello.mismatch.program-graph.patch");
const graphPatchBadHashPath = join(outDir, "hello.bad-hash.program-graph.patch");
const graphSparseOrderPath = join(outDir, "hello.sparse-order.program-graph");
const graphSparseArgPath = join(outDir, "hello.sparse-arg.program-graph");
rmSync(graphDumpPath, { force: true });
rmSync(graphDumpJsonPath, { force: true });
rmSync(graphStableSiblingSourcePath, { force: true });
rmSync(graphImportPath, { force: true });
rmSync(graphImportJsonPath, { force: true });
rmSync(graphImportDirectorySourcePath, { recursive: true, force: true });
rmSync(graphImportDirectoryOutPath, { force: true });
rmSync(graphCanonicalPath, { force: true });
rmSync(graphSourceTextOutPath, { force: true });
rmSync(graphValidateSourceTextOutPath, { force: true });
rmSync(checkedInGraphDefaultBuildPath, { force: true });
rmSync(checkedInGraphBuildPath, { force: true });
rmSync(checkedInGraphRunPath, { force: true });
rmSync(graphRecordRoot, { force: true, recursive: true });
rmSync(graphRecordBuildPath, { force: true });
rmSync(graphRecordObjPath, { force: true });
rmSync(graphRecordDirectLlvmIrPath, { force: true });
rmSync(graphRecordLlvmIrPath, { force: true });
rmSync(graphViewPath, { force: true });
rmSync(graphViewWrongOutPath, { force: true });
rmSync(graphViewParentFilePath, { force: true, recursive: true });
rmSync(graphCheckViewPath, { force: true });
rmSync(graphSizePath, { force: true });
rmSync(graphBuildPath, { force: true });
rmSync(graphObjPath, { force: true });
rmSync(graphRunPath, { force: true });
rmSync(graphArgsDumpPath, { force: true });
rmSync(graphArgsRunPath, { force: true });
rmSync(graphTestDumpPath, { force: true });
rmSync(graphPackageTestDumpPath, { force: true });
rmSync(graphManifestPackageDir, { force: true, recursive: true });
rmSync(graphManifestBuildPath, { force: true });
rmSync(graphManifestRunPath, { force: true });
rmSync(directGraphManifestBuildPath, { force: true });
rmSync(directGraphManifestRunPath, { force: true });
rmSync(directGraphTargetGateRoot, { force: true, recursive: true });
rmSync(directGraphHostLeakPackageDir, { force: true, recursive: true });
rmSync(directGraphHostLeakBuildPath, { force: true });
rmSync(graphSizeNoisePatchPath, { force: true });
rmSync(graphSizeNoisePath, { force: true });
rmSync(graphSourceRoundtripPath, { force: true });
rmSync(graphSourceRoundtripSourceTextPath, { force: true });
rmSync(graphArtifactRoundtripPath, { force: true });
rmSync(graphArtifactRoundtripSourceTextPath, { force: true });
rmSync(graphPatchPath, { force: true });
rmSync(graphPatchDirectoryPath, { recursive: true, force: true });
rmSync(graphPatchDirectoryOutPath, { force: true });
rmSync(graphPatchedPath, { force: true });
rmSync(graphInlinePatchedPath, { force: true });
rmSync(graphPatchInsertPath, { force: true });
rmSync(graphInsertedPath, { force: true });
rmSync(graphPatchDeletePath, { force: true });
rmSync(graphDeletedPath, { force: true });
rmSync(graphPatchDeleteThenInsertPath, { force: true });
rmSync(graphDeleteThenInsertedPath, { force: true });
rmSync(graphPatchDeleteNodeFactPath, { force: true });
rmSync(graphDeletedNodeFactPath, { force: true });
rmSync(graphPatchDeleteExternalRootRefPath, { force: true });
rmSync(graphPatchDeleteExtraOwnerPath, { force: true });
rmSync(graphPatchReplacePath, { force: true });
rmSync(graphReplacedPath, { force: true });
rmSync(graphPatchStaleReplacePath, { force: true });
rmSync(graphPatchInsertEdgePath, { force: true });
rmSync(graphInsertedEdgePath, { force: true });
rmSync(graphPatchEmptyTypeEdgePath, { force: true });
rmSync(graphPatchRenamePath, { force: true });
rmSync(graphRenamedPath, { force: true });
rmSync(graphPatchInvalidRenamePath, { force: true });
rmSync(graphUncheckedPatchPath, { force: true });
rmSync(graphUncheckedPath, { force: true });
rmSync(graphBorrowDumpPath, { force: true });
rmSync(graphBorrowConflictPatchPath, { force: true });
rmSync(graphBorrowConflictPath, { force: true });
rmSync(graphPatchEmptyPath, { force: true });
rmSync(graphPatchControlPath, { force: true });
rmSync(graphPatchHighBytePath, { force: true });
rmSync(graphPatchBadEscapePath, { force: true });
rmSync(graphPatchNullEscapePath, { force: true });
rmSync(graphPatchRawNullPath, { force: true });
rmSync(graphPatchInvalidNamePath, { force: true });
rmSync(graphPatchInvalidTypePath, { force: true });
rmSync(graphPatchReservedParamPath, { force: true });
rmSync(graphReservedParamPath, { force: true });
rmSync(graphPatchInternalFunctionPath, { force: true });
rmSync(graphInternalFunctionPath, { force: true });
rmSync(graphPayloadDumpPath, { force: true });
rmSync(graphPatchInvalidMatchReplacePath, { force: true });
rmSync(graphPatchInvalidMatchInsertPath, { force: true });
rmSync(graphPackageDumpPath, { force: true });
rmSync(graphPackagePathMismatchPatchPath, { force: true });
rmSync(graphPackagePathMismatchPath, { force: true });
rmSync(graphPatchInvalidImportAliasPath, { force: true });
rmSync(graphPatchInvalidImportNamePath, { force: true });
rmSync(graphInvalidImportNamePath, { force: true });
rmSync(graphPatchMissingImportPath, { force: true });
rmSync(graphMissingImportPath, { force: true });
rmSync(graphPatchMismatchPath, { force: true });
rmSync(graphPatchBadHashPath, { force: true });
rmSync(graphSparseOrderPath, { force: true });
rmSync(graphSparseArgPath, { force: true });
writeFileSync(graphStableSiblingSourcePath, readFileSync("examples/hello.0", "utf8"));
importProjectionSidecar(graphStableSiblingSourcePath);
const graphStableBaseJson = json(["dump", "--json", graphStableSiblingSourcePath]).body;
const graphStableBaseMain = graphStableBaseJson.nodes.find((node) => node.kind === "Function" && node.name === "main");
const graphStableBaseLiteral = graphStableBaseJson.nodes.find((node) => node.kind === "Literal" && node.type === "String" && node.value === "hello from zero\n");
assert(graphStableBaseMain);
assert(graphStableBaseLiteral);
writeFileSync(graphStableSiblingSourcePath, `fn helper() -> u32 {\n return 1\n}\n\n${readFileSync("examples/hello.0", "utf8")}`);
importProjectionSidecar(graphStableSiblingSourcePath);
const graphStableSiblingJson = json(["dump", "--json", graphStableSiblingSourcePath]).body;
assert.equal(graphStableSiblingJson.nodes.find((node) => node.kind === "Function" && node.name === "main")?.id, graphStableBaseMain.id);
assert.equal(graphStableSiblingJson.nodes.find((node) => node.kind === "Literal" && node.type === "String" && node.value === "hello from zero\n")?.id, graphStableBaseLiteral.id);
assert.equal(zero(["dump", "--out", graphDumpPath, "examples/hello.0"]).stdout, "");
assert.equal(readFileSync(graphDumpPath, "utf8"), graphDump);
assert.equal(zero(["dump", "--format", "binary", "--out", graphDumpBinaryPath, "examples/hello.0"]).stdout, "");
assert.equal(readFileSync(graphDumpBinaryPath).subarray(0, 8).toString("latin1"), "ZRGBIN1\0");
assert.equal(zero(["validate", graphDumpBinaryPath]).stdout, "program graph ok\n");
assert.equal(zero(["view", graphDumpBinaryPath]).stdout, zero(["view", graphDumpPath]).stdout);
const graphDumpOutJson = json(["dump", "--json", "--out", graphDumpJsonPath, "examples/hello.0"]).body;
assert.deepEqual(graphDumpOutJson, graphDumpJson);
assert.equal(readFileSync(graphDumpJsonPath, "utf8"), graphDump);
assert.equal(zero(["validate", graphDumpJsonPath]).stdout, "program graph ok\n");
assert.equal(zero(["dump", "--out", graphDumpPath, "examples/hello.0"]).stdout, "");
assert.equal(readFileSync(graphDumpPath, "utf8"), graphDump);
const graphImportText = zero(["import", "examples/hello.0"]).stdout;
assert.match(graphImportText, / path:"examples\/hello\.0"/);
assert.match(graphImportText, /hash "graph:[0-9a-f]{16}"/);
assert.equal(zero(["import", "--out", graphImportPath, "examples/hello.0"]).stdout, "");
assert.equal(readFileSync(graphImportPath, "utf8"), graphImportText);
const graphImportJson = json(["import", "--json", "examples/hello.0"]).body;
assert.equal(graphImportJson.moduleIdentity, graphDumpJson.moduleIdentity);
assert.equal(graphImportJson.graphHash, graphDumpJson.graphHash);
assert.equal(graphImportJson.validation.ok, true);
const graphImportOutJson = json(["import", "--json", "--out", graphImportJsonPath, "examples/hello.0"]).body;
assert.equal(graphImportOutJson.ok, true);
assert.equal(graphImportOutJson.moduleIdentity, graphDumpJson.moduleIdentity);
assert.equal(graphImportOutJson.graphHash, graphDumpJson.graphHash);
assert.equal(graphImportOutJson.validation.ok, true);
assert.equal(graphImportOutJson.saved.path, graphImportJsonPath);
assert.equal(readFileSync(graphImportJsonPath, "utf8"), graphImportText);
assert.equal(zero(["validate", graphImportJsonPath]).stdout, "program graph ok\n");
mkdirSync(graphImportDirectorySourcePath, { recursive: true });
const graphImportDirectoryJson = json(["import", "--json", "--out", graphImportDirectoryOutPath, graphImportDirectorySourcePath], { allowFailure: true });
assert.notEqual(graphImportDirectoryJson.code, 0);
assert.equal(graphImportDirectoryJson.body.diagnostics[0].path, graphImportDirectorySourcePath);
assert.match(graphImportDirectoryJson.body.diagnostics[0].message, /^failed to read '.+hello-source-directory\.0': /);
assert.equal(existsSync(graphImportDirectoryOutPath), false);
const graphInspectJson = json(["inspect", "--json", "examples/hello.0"]).body;
assert.equal(graphInspectJson.schemaVersion, 1);
assert.match(graphInspectJson.programGraph.graphHash, /^graph:[0-9a-f]{16}$/);
assert.equal(graphInspectJson.programGraph.moduleIdentity, graphDumpJson.moduleIdentity);
assert.equal(graphInspectJson.programGraph.canonicalSource, false);
assert.equal(graphInspectJson.programGraph.validation.ok, true);
assert.equal(graphInspectJson.callResolution.schemaVersion, 1);
const graphStdIoLinesInspectJson = json(["inspect", "--json", "conformance/native/pass/std-io-lines.graph"]).body;
assert.equal(graphStdIoLinesInspectJson.targetReadiness.ok, true);
assert.equal(graphStdIoLinesInspectJson.targetReadiness.buildable, true);
assert.deepEqual(graphStdIoLinesInspectJson.targetReadiness.diagnostics, []);
const graphInspectText = zero(["inspect", "examples/hello.0"]).stdout;
assert.match(graphInspectText, /^program graph inspect\n/);
assert.match(graphInspectText, /graph: module:hello graph:[0-9a-f]{16} \(13 nodes, 12 edges, shape-valid\)/);
assert.match(graphInspectText, /capabilities: world/);
assert.match(graphInspectText, /next: use `zero query examples\/hello\.0` for patch-ready node handles/);
const graphInspectOutJson = json(["inspect", "--json", "--out", graphInspectOutPath, "examples/hello.0"], { allowFailure: true });
assert.notEqual(graphInspectOutJson.code, 0);
assert.equal(graphInspectOutJson.body.diagnostics[0].message, "inspect does not support --out");
assert.equal(graphInspectOutJson.body.diagnostics[0].expected, "zero inspect [--json] [graph-input]");
assert.equal(zero(["validate", graphDumpPath]).stdout, "program graph ok\n");
const graphSourceMapJson = json(["source-map", "--json", "examples/hello.0"]).body;
assert.equal(graphSourceMapJson.ok, true);
assert.match(graphSourceMapJson.graphHash, /^graph:[0-9a-f]{16}$/);
const graphMainSourceMapping = graphSourceMapJson.mappings.find((mapping) => mapping.nodeId === graphMainFunctionNode.id);
assert(graphMainSourceMapping && graphMainSourceMapping.sourceRange.path === "hello.0");
assert.equal(graphMainSourceMapping.sourceAvailable, false);
assert.deepEqual(graphMainSourceMapping.sourceRange.start, { line: 1, column: 1 });
assert.deepEqual(graphMainSourceMapping.sourceRange.end, { line: 1, column: 2 });
assert.equal(zero(["source-map", "examples/hello.0"]).stdout, `program graph source map ok: ${graphSourceMapJson.counts.mappings} mappings\n`);
const graphSourceMapOutJson = json(["source-map", "--json", "--out", graphSourceMapOutPath, "examples/hello.0"], { allowFailure: true });
assert.notEqual(graphSourceMapOutJson.code, 0);
assert.equal(graphSourceMapOutJson.body.diagnostics[0].message, "source-map does not support --out");
assert.equal(graphSourceMapOutJson.body.diagnostics[0].expected, "zero source-map [--json] [graph-input]");
assert.equal(existsSync(graphSourceMapOutPath), false);
writeFileSync(graphReconcileSourcePath, readFileSync("examples/hello.0", "utf8"));
const graphReconcileBaseJson = json(["import", "--json", "--out", graphReconcileBasePath, graphReconcileSourcePath]).body;
assert.equal(graphReconcileBaseJson.saved.path, graphReconcileBasePath);
writeFileSync(graphReconcileSourcePath, readFileSync(graphReconcileSourcePath, "utf8").replace("hello from zero\\n", "hello from reconcile\\n"));
const graphReconcileJson = json(["reconcile", "--json", graphReconcileBasePath, "--source", graphReconcileSourcePath]).body;
assert.equal(graphReconcileJson.ok, true);
assert.equal(graphReconcileJson.base.graphHash, graphReconcileBaseJson.graphHash);
assert.equal(graphReconcileJson.identity.ambiguous, 0);
assert.equal(graphReconcileJson.graphPatch.available, true);
assert.match(graphReconcileJson.graphPatch.text, /set node="#expr_[^"]+" field="value"/);
const graphReconcileLiteralDecision = graphReconcileJson.decisions.find((decision) => decision.status === "edited" && decision.kind === "Literal");
assert.deepEqual(graphReconcileLiteralDecision?.sourceRange.start, { line: 2, column: 27 });
assert.deepEqual(graphReconcileLiteralDecision?.sourceRange.end, { line: 2, column: 51 });
assert.equal(zero(["reconcile", graphReconcileBasePath, "--source", graphReconcileSourcePath]).stdout, "program graph reconcile ok\n");
const graphReconcileMissingSource = json(["reconcile", "--json", graphReconcileBasePath], { allowFailure: true });
assert.notEqual(graphReconcileMissingSource.code, 0);
assert.equal(graphReconcileMissingSource.body.diagnostics[0].message, "graph reconcile requires edited source input");
assert.equal(graphReconcileMissingSource.body.diagnostics[0].actual, "missing --source");
const graphValidateJson = json(["validate", "--json", "--out", graphCanonicalPath, graphDumpPath]).body;
assert.equal(graphValidateJson.ok, true);
assert.equal(graphValidateJson.moduleIdentity, "module:hello");
assert.equal(graphValidateJson.graphHash, graphDumpJson.graphHash);
assert.equal(graphValidateJson.saved.path, graphCanonicalPath);
assert.equal(readFileSync(graphCanonicalPath, "utf8"), graphDump);
const graphSourceTextOutJson = json(["dump", "--json", "--out", graphSourceTextOutPath, "examples/hello.0"], { allowFailure: true });
assert.notEqual(graphSourceTextOutJson.code, 0);
assert.equal(graphSourceTextOutJson.body.diagnostics[0].message, "program graph output must not use source text extension");
assert.equal(graphSourceTextOutJson.body.diagnostics[0].expected, "zero dump --out <program-graph-artifact> [graph-input]");
assert.equal(graphSourceTextOutJson.body.diagnostics[0].help, ".0 files are canonical source text; write derived ProgramGraph artifacts to a non-source path");
assert.equal(existsSync(graphSourceTextOutPath), false);
const graphValidateSourceTextOutJson = json(["validate", "--json", "--out", graphValidateSourceTextOutPath, graphDumpPath], { allowFailure: true });
assert.notEqual(graphValidateSourceTextOutJson.code, 0);
assert.equal(graphValidateSourceTextOutJson.body.diagnostics[0].message, "program graph output must not use source text extension");
assert.equal(graphValidateSourceTextOutJson.body.diagnostics[0].expected, "zero validate --out <program-graph-artifact> [graph-input]");
assert.equal(existsSync(graphValidateSourceTextOutPath), false);
const checkedInGraphSource = readFileSync(checkedInGraphSourcePath, "utf8");
assert.equal(checkedInGraphSource, readFileSync("examples/hello.0", "utf8"));
const checkedInRepositoryGraphStorePath = join(checkedInGraphPackageDir, "zero.graph");
const checkedInGraphValidateJson = json(["validate", "--json", checkedInGraphSourcePath]).body;
assert.equal(checkedInGraphValidateJson.ok, true);
assert.equal(checkedInGraphValidateJson.artifact, checkedInRepositoryGraphStorePath);
assert.equal(checkedInGraphValidateJson.moduleIdentity, "package:program-graph-fixture@0.1.0");
const checkedInGraphViewJson = json(["view", "--json", checkedInGraphPackageDir]).body;
assert.equal(checkedInGraphViewJson.ok, true);
assert.equal(checkedInGraphViewJson.canonicalSource, true);
assert.match(checkedInGraphViewJson.view, /pub fn main\(world: World\) -> Void raises/);
const checkedInGraphQueryJson = json(["query", "--json", checkedInGraphPackageDir]).body;
assert.equal(checkedInGraphQueryJson.ok, true);
assert.equal(checkedInGraphQueryJson.inputKind, "repository-graph");
assert.equal(checkedInGraphQueryJson.functions.some((fun) => fun.name === "main" && fun.public === true), true);
assert.equal(checkedInGraphQueryJson.patchOperations.includes("insert node=\"#id\" kind=\"Literal\" parent=\"#parent\" edge=\"arg\" order=\"0\" type=\"String\" value=\"text\""), true);
assert.equal(checkedInGraphQueryJson.patchOperations.includes("replace node=\"#id\" expect=\"nodehash:abc123\" kind=\"Literal\" type=\"String\" value=\"text\""), true);
assert.equal(checkedInGraphQueryJson.patchOperations.some((op) => op.includes("setMain")), false);
assert.equal(checkedInGraphQueryJson.patchOperations.some((op) => op.startsWith("replaceFunctionBody main\n")), true);
assert.equal(checkedInGraphQueryJson.patchOperations.some((op) => op.startsWith("replaceBlockBody #block_id\n")), true);
assert.equal(checkedInGraphQueryJson.patchOperations.includes("addLetLiteral fn=\"main\" name=\"count\" type=\"u32\" value=\"0\""), true);
assert.equal(checkedInGraphQueryJson.patchOperations.includes("addReturnValue fn=\"identity\" value=\"input\" type=\"i32\""), true);
assert.equal(checkedInGraphQueryJson.patchOperations.includes("addReturnExpr fn=\"maybe\" expr=\"null\""), true);
assert.equal(checkedInGraphQueryJson.patchOperations.includes("appendStmt fn=\"main\" stmt=\"check std.http.listen(world, 3000_u16)\""), true);
assert.equal(checkedInGraphQueryJson.patchOperations.some((op) => op.startsWith("addTestBody name=\"api add\"\n")), true);
assert.equal(checkedInGraphQueryJson.patchOperations.includes("renameTest name=\"api add\" value=\"api add route\""), true);
assert.equal(checkedInGraphQueryJson.patchOperations.includes("deleteTest name=\"api add\""), true);
assert.equal(checkedInGraphQueryJson.patchOperations.some((op) => op.startsWith("upsertFunction handle\n")), true);
rmSync(graphRepositoryNewOpsPackageDir, { recursive: true, force: true });
mkdirSync(graphRepositoryNewOpsPackageDir, { recursive: true });
writeFileSync(join(graphRepositoryNewOpsPackageDir, "zero.toml"), readFileSync(join(checkedInGraphPackageDir, "zero.toml"), "utf8"));
writeFileSync(join(graphRepositoryNewOpsPackageDir, "zero.graph"), readFileSync(checkedInRepositoryGraphStorePath));
writeFileSync(join(graphRepositoryNewOpsPackageDir, "hello.0"), checkedInGraphSource);
const repositoryNewOpsHash = json(["query", "--json", graphRepositoryNewOpsPackageDir]).body.graphHash;
writeFileSync(graphRepositoryNewOpsPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${repositoryNewOpsHash}"`,
"upsertFunction main",
"pub fn main(world: World) -> Void raises {",
"}",
"end",
'appendStmt fn="main" stmt="check world.out.write(\\"new ops ok\\")"',
'addFunction name="answer" ret="i32"',
'addReturnExpr fn="answer" expr="42"',
'addTestBody name="answer works"',
" expect (answer() == 42)",
"end",
"",
].join("\n"));
const repositoryNewOpsDryRunJson = json(["patch", "--json", "--check-only", graphRepositoryNewOpsPackageDir, graphRepositoryNewOpsPatchPath]).body;
assert.equal(repositoryNewOpsDryRunJson.ok, true);
assert.equal(repositoryNewOpsDryRunJson.checkOnly, true);
assert.equal(repositoryNewOpsDryRunJson.saved, null);
assert.deepEqual(repositoryNewOpsDryRunJson.operations.map((operation) => operation.op), ["upsertFunction", "appendStmt", "addFunction", "addReturnExpr", "addTestBody"]);
assert.equal(zero(["view", graphRepositoryNewOpsPackageDir]).stdout, checkedInGraphSource);
const repositoryNewOpsPatchJson = json(["patch", "--json", graphRepositoryNewOpsPackageDir, graphRepositoryNewOpsPatchPath]).body;
assert.equal(repositoryNewOpsPatchJson.ok, true);
assert.deepEqual(repositoryNewOpsPatchJson.operations.map((operation) => operation.op), ["upsertFunction", "appendStmt", "addFunction", "addReturnExpr", "addTestBody"]);
assert.equal(repositoryNewOpsPatchJson.saved.path, join(graphRepositoryNewOpsPackageDir, "zero.graph"));
assert.match(zero(["view", "--fn", "main", graphRepositoryNewOpsPackageDir]).stdout, /check world\.out\.write\("new ops ok"\)/);
assert.match(zero(["view", "--fn", "answer", graphRepositoryNewOpsPackageDir]).stdout, /return 42/);
assert.equal(zero(["check", graphRepositoryNewOpsPackageDir]).stdout, "ok\n");
assert.equal(zero(["run", graphRepositoryNewOpsPackageDir]).stdout, "new ops ok");
assert.equal(zero(["test", graphRepositoryNewOpsPackageDir]).stdout, "1 test(s) ok\n");
const repositoryRenameTestJson = json(["patch", "--json", graphRepositoryNewOpsPackageDir, "--op", 'renameTest name="answer works" value="answer route works"']).body;
assert.equal(repositoryRenameTestJson.ok, true);
assert.equal(repositoryRenameTestJson.operations[0].op, "renameTest");
assert.equal(repositoryRenameTestJson.operations[0].actual, "answer works");
assert.equal(zero(["test", graphRepositoryNewOpsPackageDir]).stdout, "1 test(s) ok\n");
const repositoryUnsupportedTestPatch = zeroWithInput(["patch", graphRepositoryNewOpsPackageDir, "--patch-text", "-"], [
"zero-program-graph-patch v1",
'addTestBody name="unsupported buffer test"',
" var response: [16]u8 = [0_u8; 16]",
" expect true",
"end",
"",
].join("\n"));
assertPatchOkOutput(repositoryUnsupportedTestPatch.stdout, join(graphRepositoryNewOpsPackageDir, "zero.graph"));
const repositoryUnsupportedTestRun = zero(["test", graphRepositoryNewOpsPackageDir], { allowFailure: true });
assert.notEqual(repositoryUnsupportedTestRun.code, 0);
assert.match(repositoryUnsupportedTestRun.stderr, /zero graph test runner does not support .* expression yet/);
assert.match(repositoryUnsupportedTestRun.stderr, /supported graph tests are pure locals/);
const repositoryDeleteUnsupportedTestJson = json(["patch", "--json", graphRepositoryNewOpsPackageDir, "--op", 'deleteTest name="unsupported buffer test"']).body;
assert.equal(repositoryDeleteUnsupportedTestJson.ok, true);
assert.equal(repositoryDeleteUnsupportedTestJson.operations[0].op, "deleteTest");
assert.equal(zero(["test", graphRepositoryNewOpsPackageDir]).stdout, "1 test(s) ok\n");
const repositoryDeleteTestJson = json(["patch", "--json", graphRepositoryNewOpsPackageDir, "--op", 'deleteTest name="answer route works"']).body;
assert.equal(repositoryDeleteTestJson.ok, true);
assert.equal(repositoryDeleteTestJson.operations[0].op, "deleteTest");
const repositoryNoTests = zero(["test", graphRepositoryNewOpsPackageDir]).stdout;
assert.match(repositoryNoTests, /0 test\(s\) ok/);
assert.match(repositoryNoTests, /note: no test blocks found/);
assert.match(zero(["export", graphRepositoryNewOpsPackageDir]).stdout, /repository graph export ok/);
assert.equal(zero(["verify-projection", graphRepositoryNewOpsPackageDir]).stdout, "repository graph verify-projection ok\n");
rmSync(graphRepositoryPatchPackageDir, { recursive: true, force: true });
mkdirSync(graphRepositoryPatchPackageDir, { recursive: true });
writeFileSync(join(graphRepositoryPatchPackageDir, "zero.toml"), readFileSync(join(checkedInGraphPackageDir, "zero.toml"), "utf8"));
writeFileSync(join(graphRepositoryPatchPackageDir, "zero.graph"), readFileSync(checkedInRepositoryGraphStorePath));
writeFileSync(join(graphRepositoryPatchPackageDir, "hello.0"), checkedInGraphSource);
const repositoryPatchQueryJson = json(["query", "--json", graphRepositoryPatchPackageDir]).body;
writeFileSync(graphRepositoryBodyPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${repositoryPatchQueryJson.graphHash}"`,
"replaceFunctionBody main",
" let name Maybe<String> = std.args.get 1",
" if name.has",
" check world.out.write \"hello \"",
" check world.out.write name.value",
" check world.out.write \"\\n\"",
" else",
" check world.out.write \"hello anonymous\\n\"",
"end",
"",
].join("\n"));
const repositoryPatchDryRunJson = json(["patch", "--json", "--check-only", graphRepositoryPatchPackageDir, graphRepositoryBodyPatchPath]).body;
assert.equal(repositoryPatchDryRunJson.ok, true);
assert.equal(repositoryPatchDryRunJson.checkOnly, true);
assert.equal(repositoryPatchDryRunJson.saved, null);
assert.equal(zero(["view", graphRepositoryPatchPackageDir]).stdout, checkedInGraphSource);
const repositoryBodyPatchJson = json(["patch", "--json", graphRepositoryPatchPackageDir, graphRepositoryBodyPatchPath]).body;
assert.equal(repositoryBodyPatchJson.ok, true);
assert.equal(repositoryBodyPatchJson.checkOnly, false);
assert.equal(repositoryBodyPatchJson.operations[0].op, "replaceFunctionBody");
assert.equal(repositoryBodyPatchJson.saved.path, join(graphRepositoryPatchPackageDir, "zero.graph"));
assert.match(zero(["view", graphRepositoryPatchPackageDir]).stdout, /let name: Maybe<String> = std\.args\.get\(1\)/);
assert.equal(zero(["check", graphRepositoryPatchPackageDir]).stdout, "ok\n");
assert.equal(zero(["run", graphRepositoryPatchPackageDir, "--", "Ada"]).stdout, "hello Ada\n");
const repositoryBlockQueryJson = json(["query", "--json", "--find", "Block", graphRepositoryPatchPackageDir]).body;
const repositoryThenBlock = repositoryBlockQueryJson.matches.find((node) => node.kind === "Block" && node.name === "then");
assert(repositoryThenBlock, "expected replaceFunctionBody patch to expose a then block handle");
writeFileSync(graphRepositoryInvalidBlockRowsPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${repositoryBlockQueryJson.graphHash}"`,
`replaceBlockBody ${repositoryThenBlock.id}`,
" check world.out.write \"name: \"",
" let same Bool = std.mem.eql (std.mem.span name \"Ada\"",
"end",
"",
].join("\n"));
const repositoryInvalidBlockRowsDryRun = json(["patch", "--json", "--check-only", graphRepositoryPatchPackageDir, graphRepositoryInvalidBlockRowsPatchPath], { allowFailure: true });
assert.notEqual(repositoryInvalidBlockRowsDryRun.code, 0);
assert.equal(repositoryInvalidBlockRowsDryRun.body.diagnostic.code, "GPH001");
assert.match(repositoryInvalidBlockRowsDryRun.body.diagnostic.actual, /row 2: let same Bool = std\.mem\.eql/);
writeFileSync(graphRepositoryBlockPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${repositoryBlockQueryJson.graphHash}"`,
`replaceBlockBody ${repositoryThenBlock.id}`,
" check world.out.write \"name: \"",
" check world.out.write name.value",
" check world.out.write \"\\n\"",
"end",
"",
].join("\n"));
const repositoryBlockPatchDryRunJson = json(["patch", "--json", "--check-only", graphRepositoryPatchPackageDir, graphRepositoryBlockPatchPath]).body;
assert.equal(repositoryBlockPatchDryRunJson.ok, true);
assert.equal(repositoryBlockPatchDryRunJson.checkOnly, true);
assert.equal(repositoryBlockPatchDryRunJson.saved, null);
const repositoryBlockPatchJson = json(["patch", "--json", graphRepositoryPatchPackageDir, graphRepositoryBlockPatchPath]).body;
assert.equal(repositoryBlockPatchJson.ok, true);
assert.equal(repositoryBlockPatchJson.operations[0].op, "replaceBlockBody");
assert.equal(repositoryBlockPatchJson.saved.path, join(graphRepositoryPatchPackageDir, "zero.graph"));
const repositoryBlockView = zero(["view", graphRepositoryPatchPackageDir]).stdout;
assert.match(repositoryBlockView, /check world\.out\.write\("name: "\)/);
assert.match(repositoryBlockView, /check world\.out\.write\("hello anonymous\\n"\)/);
assert.equal(zero(["check", graphRepositoryPatchPackageDir]).stdout, "ok\n");
assert.equal(zero(["run", graphRepositoryPatchPackageDir, "--", "Ada"]).stdout, "name: Ada\n");
assert.match(zero(["status", graphRepositoryPatchPackageDir]).stdout, /source-stale/);
const statusStorePathStdout = zero(["status", join(graphRepositoryPatchPackageDir, "zero.graph")]).stdout;
assert.match(statusStorePathStdout, /repository graph status: source-stale/);
assert.match(statusStorePathStdout, new RegExp(`root: ${graphRepositoryPatchPackageDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\n`));
assert.match(zero(["export", graphRepositoryPatchPackageDir]).stdout, /repository graph export ok/);
assert.equal(zero(["verify-projection", graphRepositoryPatchPackageDir]).stdout, "repository graph verify-projection ok\n");
assert.equal(zero(["verify-projection", join(graphRepositoryPatchPackageDir, "zero.graph")]).stdout, "repository graph verify-projection ok\n");
const repositoryRowQueryJson = json(["query", "--json", graphRepositoryPatchPackageDir]).body;
writeFileSync(graphRepositoryCheckExprPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${repositoryRowQueryJson.graphHash}"`,
"replaceFunctionBody main",
" var path_storage [32]u8 = repeat 0_u8 32",
" let name String = check std.path.join path_storage \".zero\" \"row-ergonomics\"",
" if !std.mem.eql name \".zero/row-ergonomics\"",
" check world.err.write \"wrong name\\n\"",
"end",
"",
].join("\n"));
const repositoryCheckExprDryRunJson = json(["patch", "--json", "--check-only", graphRepositoryPatchPackageDir, graphRepositoryCheckExprPatchPath]).body;
assert.equal(repositoryCheckExprDryRunJson.ok, true);
assert.equal(repositoryCheckExprDryRunJson.checkOnly, true);
assert.equal(repositoryCheckExprDryRunJson.saved, null);
assert.equal(repositoryCheckExprDryRunJson.operations[0].op, "replaceFunctionBody");
writeFileSync(graphRepositoryRowErgonomicsPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${repositoryRowQueryJson.graphHash}"`,
"replaceFunctionBody main",
" let name String = \".zero/row-ergonomics\"",
" let same Bool = std.mem.eql (std.mem.span name) \".zero/row-ergonomics\"",
" let status i32 = 200_u16 as i32",
" let count i32 = 2",
" let math Bool = count + 1 > 2",
" if !same || status != 200",
" check world.err.write \"wrong name\\n\"",
" else if math || status == 200",
" check world.out.write \"row ergonomics ok\\n\"",
" return",
" else",
" return",
"end",
"",
].join("\n"));
const repositoryRowErgonomicsDryRunJson = json(["patch", "--json", "--check-only", graphRepositoryPatchPackageDir, graphRepositoryRowErgonomicsPatchPath]).body;
assert.equal(repositoryRowErgonomicsDryRunJson.ok, true);
assert.equal(repositoryRowErgonomicsDryRunJson.checkOnly, true);
assert.equal(repositoryRowErgonomicsDryRunJson.saved, null);
const repositoryRowErgonomicsPatchJson = json(["patch", "--json", graphRepositoryPatchPackageDir, graphRepositoryRowErgonomicsPatchPath]).body;
assert.equal(repositoryRowErgonomicsPatchJson.ok, true);
assert.equal(repositoryRowErgonomicsPatchJson.operations[0].op, "replaceFunctionBody");
const repositoryRowErgonomicsView = zero(["view", graphRepositoryPatchPackageDir]).stdout;
assert.match(repositoryRowErgonomicsView, /let name: String = "\.zero\/row-ergonomics"/);
assert.match(repositoryRowErgonomicsView, /let same: Bool = std\.mem\.eql\(std\.mem\.span\(name\), "\.zero\/row-ergonomics"\)/);
assert.match(repositoryRowErgonomicsView, /let status: i32 = 200_u16 as i32/);
assert.match(repositoryRowErgonomicsView, /let math: Bool = count \+ 1 > 2/);
assert.match(repositoryRowErgonomicsView, /if !same \|\| status != 200/);
assert.match(repositoryRowErgonomicsView, /else if math \|\| status == 200/);
assert.match(repositoryRowErgonomicsView, /return/);
assert.equal(zero(["check", graphRepositoryPatchPackageDir]).stdout, "ok\n");
assert.equal(zero(["run", graphRepositoryPatchPackageDir]).stdout, "row ergonomics ok\n");
assert.match(zero(["export", graphRepositoryPatchPackageDir]).stdout, /repository graph export ok/);
assert.equal(zero(["verify-projection", graphRepositoryPatchPackageDir]).stdout, "repository graph verify-projection ok\n");
const repositorySyncedQueryJson = json(["query", "--json", graphRepositoryPatchPackageDir]).body;
writeFileSync(graphRepositoryInvalidRowsPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${repositorySyncedQueryJson.graphHash}"`,
"replaceFunctionBody main",
" let name String = \"Ada\"",
" let same Bool = std.mem.eql (std.mem.span name \"Ada\"",
"end",
"",
].join("\n"));
const repositoryInvalidRowsDryRun = json(["patch", "--json", "--check-only", graphRepositoryPatchPackageDir, graphRepositoryInvalidRowsPatchPath], { allowFailure: true });
assert.notEqual(repositoryInvalidRowsDryRun.code, 0);
assert.equal(repositoryInvalidRowsDryRun.body.diagnostic.code, "GPH001");
assert.match(repositoryInvalidRowsDryRun.body.diagnostic.actual, /row 2: let same Bool = std\.mem\.eql/);
writeFileSync(graphRepositoryInvalidBodyPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${repositorySyncedQueryJson.graphHash}"`,
"replaceFunctionBody main",
" world.out.write \"bad\\n\"",
"end",
"",
].join("\n"));
const repositoryInvalidBodyDryRun = json(["patch", "--json", "--check-only", graphRepositoryPatchPackageDir, graphRepositoryInvalidBodyPatchPath], { allowFailure: true });
assert.notEqual(repositoryInvalidBodyDryRun.code, 0);
assert.equal(repositoryInvalidBodyDryRun.body.diagnostics[0].code, "ERR003");
assert.equal(repositoryInvalidBodyDryRun.body.diagnostics[0].message, "fallible function call must be checked");
assert.equal(repositoryInvalidBodyDryRun.body.diagnostics[0].path, "hello.0");
const repositoryInvalidBodyPatch = json(["patch", "--json", graphRepositoryPatchPackageDir, graphRepositoryInvalidBodyPatchPath], { allowFailure: true });
assert.notEqual(repositoryInvalidBodyPatch.code, 0);
assert.equal(repositoryInvalidBodyPatch.body.diagnostics[0].code, "ERR003");
assert.equal(json(["query", "--json", graphRepositoryPatchPackageDir]).body.graphHash, repositorySyncedQueryJson.graphHash);
const replaceFnBodyPath = join(outDir, "repository-graph.replace-fn.body");
writeFileSync(replaceFnBodyPath, [
" let name: Maybe<String> = std.args.get(1)",
" if name.has {",
" check world.out.write(\"hi \")",
" check world.out.write(name.value)",
" check world.out.write(\"\\n\")",
" } else {",
" check world.out.write(\"hi anonymous\\n\")",
" }",
"",
].join("\n"));
const replaceFnPatchJson = json(["patch", "--json", graphRepositoryPatchPackageDir, "--expect-graph-hash", repositorySyncedQueryJson.graphHash, "--replace-fn", "main", "--body-file", replaceFnBodyPath]).body;
assert.equal(replaceFnPatchJson.ok, true);
assert.equal(replaceFnPatchJson.patch, replaceFnBodyPath);
assert.equal(replaceFnPatchJson.operationCount, 1);
assert.equal(replaceFnPatchJson.operations[0].op, "replaceFunctionBody");
assert.equal(replaceFnPatchJson.saved.path, join(graphRepositoryPatchPackageDir, "zero.graph"));
assert.match(zero(["view", "--fn", "main", graphRepositoryPatchPackageDir]).stdout, /check world\.out\.write\("hi "\)/);
assert.equal(zero(["run", graphRepositoryPatchPackageDir, "--", "Ada"]).stdout, "hi Ada\n");
const replaceFnStaleHash = json(["patch", "--json", graphRepositoryPatchPackageDir, "--expect-graph-hash", repositorySyncedQueryJson.graphHash, "--replace-fn", "main", "--body-file", replaceFnBodyPath], { allowFailure: true });
assert.notEqual(replaceFnStaleHash.code, 0);
assert.equal(replaceFnStaleHash.body.diagnostic.code, "GPH002");
const replaceFnInvalidBodyPath = join(outDir, "repository-graph.replace-fn.invalid.body");
writeFileSync(replaceFnInvalidBodyPath, " let same Bool = std.mem.eql (std.mem.span name \"Ada\"\n");
const replaceFnInvalidText = zero(["patch", graphRepositoryPatchPackageDir, "--replace-fn", "main", "--body-file", replaceFnInvalidBodyPath], { allowFailure: true });
assert.notEqual(replaceFnInvalidText.code, 0);
assert.match(replaceFnInvalidText.stderr, /replaceFunctionBody rows did not parse as a Zero function body/);
assert.match(replaceFnInvalidText.stderr, /row 1: let same Bool = std\.mem\.eql \(std\.mem\.span name "Ada"/);
const replaceFnInvalidJson = json(["patch", "--json", graphRepositoryPatchPackageDir, "--replace-fn", "main", "--body-file", replaceFnInvalidBodyPath], { allowFailure: true });
assert.notEqual(replaceFnInvalidJson.code, 0);
assert.equal(replaceFnInvalidJson.body.diagnostic.code, "GPH001");
assert.match(replaceFnInvalidJson.body.diagnostic.actual, /row 1: let same Bool = std\.mem\.eql/);
const replaceFnEmptyBodyPath = join(outDir, "repository-graph.replace-fn.empty.body");
writeFileSync(replaceFnEmptyBodyPath, "\n");
const replaceFnEmptyJson = json(["patch", "--json", graphRepositoryPatchPackageDir, "--replace-fn", "main", "--body-file", replaceFnEmptyBodyPath], { allowFailure: true });
assert.notEqual(replaceFnEmptyJson.code, 0);
assert.equal(replaceFnEmptyJson.body.diagnostic.code, "GPH001");
assert.equal(replaceFnEmptyJson.body.diagnostic.message, "function body file is empty");
const replaceFnMissingBodyFlag = json(["patch", "--json", graphRepositoryPatchPackageDir, "--replace-fn", "main"], { allowFailure: true });
assert.notEqual(replaceFnMissingBodyFlag.code, 0);
assert.match(replaceFnMissingBodyFlag.body.diagnostics[0].message, /needs both --replace-fn and --body-file/);
assert.equal(replaceFnMissingBodyFlag.body.diagnostics[0].actual, "missing --body-file");
const replaceFnAmbiguousSource = json(["patch", "--json", graphRepositoryPatchPackageDir, graphRepositoryBodyPatchPath, "--replace-fn", "main", "--body-file", replaceFnBodyPath], { allowFailure: true });
assert.notEqual(replaceFnAmbiguousSource.code, 0);
assert.match(replaceFnAmbiguousSource.body.diagnostics[0].message, /graph patch source is ambiguous/);
const replaceFnStdinHash = json(["query", "--json", graphRepositoryPatchPackageDir]).body.graphHash;
const replaceFnStdinBody = ' check world.out.write("quoted \\"rows\\" with $HOME and C:\\\\path\\n")\n';
const replaceFnStdinText = zeroWithInput(["patch", graphRepositoryPatchPackageDir, "--expect-graph-hash", replaceFnStdinHash, "--replace-fn", "main", "--body-file", "-"], replaceFnStdinBody);
assertPatchOkOutput(replaceFnStdinText.stdout, join(graphRepositoryPatchPackageDir, "zero.graph"));
assert.match(zero(["view", "--fn", "main", graphRepositoryPatchPackageDir]).stdout, /quoted \\"rows\\" with \$HOME and C:\\\\path/);
assert.equal(zero(["run", graphRepositoryPatchPackageDir]).stdout, 'quoted "rows" with $HOME and C:\\path\n');
const replaceFnStdinJsonHash = json(["query", "--json", graphRepositoryPatchPackageDir]).body.graphHash;
const replaceFnStdinJsonRun = zeroWithInput(["patch", "--json", graphRepositoryPatchPackageDir, "--expect-graph-hash", replaceFnStdinJsonHash, "--replace-fn", "main", "--body-file", "-"], ' check world.out.write("stdin body update\\n")\n');
const replaceFnStdinJson = JSON.parse(replaceFnStdinJsonRun.stdout);
assert.equal(replaceFnStdinJson.ok, true);
assert.equal(replaceFnStdinJson.patch, "<stdin>");
assert.equal(replaceFnStdinJson.operationCount, 1);
assert.equal(replaceFnStdinJson.operations[0].op, "replaceFunctionBody");
assert.equal(replaceFnStdinJson.saved.path, join(graphRepositoryPatchPackageDir, "zero.graph"));
assert.equal(zero(["run", graphRepositoryPatchPackageDir]).stdout, "stdin body update\n");
const replaceFnStdinEmpty = zeroWithInput(["patch", "--json", graphRepositoryPatchPackageDir, "--replace-fn", "main", "--body-file", "-"], "\n", { allowFailure: true });
assert.notEqual(replaceFnStdinEmpty.code, 0);
const replaceFnStdinEmptyBody = JSON.parse(replaceFnStdinEmpty.stdout);
assert.equal(replaceFnStdinEmptyBody.diagnostic.code, "GPH001");
assert.equal(replaceFnStdinEmptyBody.diagnostic.message, "function body file is empty");
assert.equal(replaceFnStdinEmptyBody.diagnostic.actual, "<stdin>");
// Surgical in-function replacement: --replace-in-fn finds --old as a literal
// substring of the canonical body projection (the text zero view --fn prints),
// requires it unique within the function, and revalidates exactly like
// --replace-fn, all in one call.
const replaceInFnHash = json(["query", "--json", graphRepositoryPatchPackageDir]).body.graphHash;
const replaceInFnSingle = zero(["patch", graphRepositoryPatchPackageDir, "--expect-graph-hash", replaceInFnHash, "--replace-in-fn", "main", "--old", "stdin body update\\n", "--new", "surgical update\\n"]);
assertPatchOkOutput(replaceInFnSingle.stdout, join(graphRepositoryPatchPackageDir, "zero.graph"));
assert.equal(zero(["run", graphRepositoryPatchPackageDir]).stdout, "surgical update\n");
const replaceInFnBodyRows = [
' let name: Maybe<String> = std.args.get(1)',
' if name.has {',
' check world.out.write("hey ")',
' check world.out.write(name.value)',
' check world.out.write("\\n")',
' } else {',
' check world.out.write("hey anonymous\\n")',
' }',
'',
].join("\n");
zeroWithInput(["patch", graphRepositoryPatchPackageDir, "--replace-fn", "main", "--body-file", "-"], replaceInFnBodyRows);
const replaceInFnView = zero(["view", "--fn", "main", graphRepositoryPatchPackageDir]).stdout;
const replaceInFnViewLines = replaceInFnView.split("\n");
const replaceInFnHeyIndex = replaceInFnViewLines.findIndex((line) => line.includes('"hey "'));
assert(replaceInFnHeyIndex > 0, "expected the replaced body in zero view --fn main");
// multi-line --old/--new through inline \n escapes, exactly as view prints the rows
const replaceInFnMultiOld = `${replaceInFnViewLines[replaceInFnHeyIndex]}\\n${replaceInFnViewLines[replaceInFnHeyIndex + 1]}`;
const replaceInFnMultiNew = replaceInFnMultiOld.replace('"hey "', '"hi "');
const replaceInFnMulti = zero(["patch", graphRepositoryPatchPackageDir, "--replace-in-fn", "main", "--old", replaceInFnMultiOld, "--new", replaceInFnMultiNew]);
assertPatchOkOutput(replaceInFnMulti.stdout, join(graphRepositoryPatchPackageDir, "zero.graph"));
assert.equal(zero(["run", graphRepositoryPatchPackageDir, "--", "Ada"]).stdout, "hi Ada\n");
// non-unique --old fails with the occurrence count and a view-oriented hint
const replaceInFnAmbiguous = zero(["patch", graphRepositoryPatchPackageDir, "--replace-in-fn", "main", "--old", "check world.out.write(", "--new", "check world.err.write("], { allowFailure: true });
assert.notEqual(replaceInFnAmbiguous.code, 0);
assert.match(replaceInFnAmbiguous.stderr, /replace-in-fn --old text matches 4 places in function 'main'/);
assert.match(replaceInFnAmbiguous.stderr, /zero view --fn main/);
// missing --old fails without touching the store
const replaceInFnMissBefore = json(["query", "--json", graphRepositoryPatchPackageDir]).body.graphHash;
const replaceInFnMiss = zero(["patch", graphRepositoryPatchPackageDir, "--replace-in-fn", "main", "--old", "zzz-not-here", "--new", "anything"], { allowFailure: true });
assert.notEqual(replaceInFnMiss.code, 0);
assert.match(replaceInFnMiss.stderr, /replace-in-fn --old text was not found in function 'main'/);
assert.match(replaceInFnMiss.stderr, /zero view --fn main/);
assert.equal(json(["query", "--json", graphRepositoryPatchPackageDir]).body.graphHash, replaceInFnMissBefore);
// stdin variants: --old-file - and --new-file - read the text verbatim
const replaceInFnStdinOld = zeroWithInput(["patch", graphRepositoryPatchPackageDir, "--replace-in-fn", "main", "--old-file", "-", "--new", replaceInFnViewLines[replaceInFnHeyIndex].replace('"hey "', '"hello "')], replaceInFnViewLines[replaceInFnHeyIndex].replace('"hey "', '"hi "'));
assertPatchOkOutput(replaceInFnStdinOld.stdout, join(graphRepositoryPatchPackageDir, "zero.graph"));
assert.equal(zero(["run", graphRepositoryPatchPackageDir, "--", "Ada"]).stdout, "hello Ada\n");
const replaceInFnStdinNew = zeroWithInput(["patch", "--json", graphRepositoryPatchPackageDir, "--replace-in-fn", "main", "--old", '"hello "', "--new-file", "-"], '"howdy "');
const replaceInFnStdinNewBody = JSON.parse(replaceInFnStdinNew.stdout);
assert.equal(replaceInFnStdinNewBody.ok, true);
assert.equal(replaceInFnStdinNewBody.patch, "<replace-in-fn>");
assert.equal(replaceInFnStdinNewBody.operationCount, 1);
assert.equal(replaceInFnStdinNewBody.operations[0].op, "replaceFunctionBody");
assert.equal(zero(["run", graphRepositoryPatchPackageDir, "--", "Ada"]).stdout, "howdy Ada\n");
// a replacement that introduces a diagnostic fails revalidation with
// baseline-diff behavior and leaves the store untouched
const replaceInFnInvalidBefore = json(["query", "--json", graphRepositoryPatchPackageDir]).body.graphHash;
const replaceInFnInvalid = zero(["patch", graphRepositoryPatchPackageDir, "--replace-in-fn", "main", "--old", 'check world.out.write("howdy ")', "--new", 'world.out.write("howdy ")'], { allowFailure: true });
assert.notEqual(replaceInFnInvalid.code, 0);
assert.match(replaceInFnInvalid.stderr, /ERR003: fallible function call must be checked/);
assert.match(replaceInFnInvalid.stderr, /program graph patch failed revalidation: 1 diagnostic introduced by this patch/);
assert.equal(json(["query", "--json", graphRepositoryPatchPackageDir]).body.graphHash, replaceInFnInvalidBefore);
// incomplete or doubled flag sets fail with actionable diagnostics
const replaceInFnMissingNew = json(["patch", "--json", graphRepositoryPatchPackageDir, "--replace-in-fn", "main", "--old", "x"], { allowFailure: true });
assert.notEqual(replaceInFnMissingNew.code, 0);
assert.match(replaceInFnMissingNew.body.diagnostics[0].message, /needs --replace-in-fn, --old, and --new/);
assert.equal(replaceInFnMissingNew.body.diagnostics[0].actual, "missing --new");
const replaceInFnDoubleStdin = json(["patch", "--json", graphRepositoryPatchPackageDir, "--replace-in-fn", "main", "--old-file", "-", "--new-file", "-"], { allowFailure: true });
assert.notEqual(replaceInFnDoubleStdin.code, 0);
assert.match(replaceInFnDoubleStdin.body.diagnostics[0].message, /cannot read both texts from stdin/);
const replaceInFnMixedSource = json(["patch", "--json", graphRepositoryPatchPackageDir, "--replace-in-fn", "main", "--old", "x", "--new", "y", "--replace-fn", "main", "--body-file", "-"], { allowFailure: true });
assert.notEqual(replaceInFnMixedSource.code, 0);
assert.match(replaceInFnMixedSource.body.diagnostics[0].message, /graph patch source is ambiguous/);
const genericPatchRoot = join(outDir, "repository-graph-generic-patch");
rmSync(genericPatchRoot, { recursive: true, force: true });
mkdirSync(join(genericPatchRoot, "src"), { recursive: true });
writeZeroTomlSync(genericPatchRoot, { package: { name: "generic-patch", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "src/main.0" } } });
writeFileSync(join(genericPatchRoot, "src", "main.0"), [
"fn tail(data: Span<u8>, offset: usize) -> Span<u8> {",
" return std.mem.dropPrefix(data, offset)",
"}",
"",
"fn pick(data: Span<u8>, limit: usize) -> usize {",
" var i: usize = 0",
" var total: usize = 0",
" while i < limit {",
" total = total + std.mem.len(tail(data, i))",
" i = i + 1_usize",
" }",
" return total",
"}",
"",
"pub fn main(world: World) -> Void raises {",
" let bytes: Span<u8> = \"abc\"",
" if pick(bytes, 2) > 0 {",
" check world.out.write(\"generic patch ok\\n\")",
" }",
"}",
"",
].join("\n"));
assert.equal(json(["import", "--format", "text", "--json", genericPatchRoot]).code, 0);
assert.equal(zero(["check", genericPatchRoot]).stdout, "ok\n");
const genericPatchDump = zero(["dump", genericPatchRoot]).stdout;
const genericComparisonNode = genericPatchDump.match(/node (#\S+) Call name:"<"/);
assert(genericComparisonNode, "expected a comparison Call node in the generic-bearing package dump");
const genericOperatorFlip = json(["patch", "--json", genericPatchRoot, "--op", `set node="${genericComparisonNode[1]}" field="name" expect="<" value="<="`]).body;
assert.equal(genericOperatorFlip.ok, true);
assert.equal(genericOperatorFlip.operations[0].ok, true);
assert.equal(zero(["check", genericPatchRoot]).stdout, "ok\n");
assert.match(zero(["view", genericPatchRoot]).stdout, /while i <= limit/);
assert.equal(zero(["run", genericPatchRoot]).stdout, "generic patch ok\n");
const genericViewBodyQuery = json(["query", "--json", genericPatchRoot]).body;
const genericViewSource = zero(["view", genericPatchRoot]).stdout.split("\n");
const genericPickStart = genericViewSource.findIndex((line) => line.startsWith("fn pick("));
assert(genericPickStart >= 0, "expected zero view to print fn pick");
const genericPickBody: string[] = [];
let genericPickDepth = 0;
for (const line of genericViewSource.slice(genericPickStart)) {
genericPickDepth += (line.match(/\{/g) ?? []).length - (line.match(/\}/g) ?? []).length;
genericPickBody.push(line);
if (genericPickDepth === 0 && genericPickBody.length > 1) break;
}
const genericVerbatimPatchPath = join(outDir, "repository-graph-generic-verbatim.patch");
writeFileSync(genericVerbatimPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${genericViewBodyQuery.graphHash}"`,
"replaceFunctionBody pick",
...genericPickBody.slice(1, -1).map((line) => ` ${line}`),
"end",
"",
].join("\n"));
const genericVerbatimPatch = json(["patch", "--json", genericPatchRoot, genericVerbatimPatchPath]).body;
assert.equal(genericVerbatimPatch.ok, true);
assert.equal(genericVerbatimPatch.operations[0].op, "replaceFunctionBody");
assert.equal(zero(["check", genericPatchRoot]).stdout, "ok\n");
assert.equal(zero(["run", genericPatchRoot]).stdout, "generic patch ok\n");
const genericTypedRowsQuery = json(["query", "--json", genericPatchRoot]).body;
const genericTypedRowsPatchPath = join(outDir, "repository-graph-generic-typed-rows.patch");
writeFileSync(genericTypedRowsPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${genericTypedRowsQuery.graphHash}"`,
"replaceFunctionBody pick",
" let n: usize = std.mem.len(tail(data, 0))",
" var total: usize = 0",
" if n > 0 && limit > 0 {",
" total = n + limit",
" } else {",
" total = limit",
" }",
" return total",
"end",
"",
].join("\n"));
const genericTypedRowsPatch = json(["patch", "--json", genericPatchRoot, genericTypedRowsPatchPath]).body;
assert.equal(genericTypedRowsPatch.ok, true);
assert.equal(genericTypedRowsPatch.operations[0].op, "replaceFunctionBody");
const genericTypedRowsView = zero(["view", genericPatchRoot]).stdout;
assert.match(genericTypedRowsView, /let n: usize = std\.mem\.len\(tail\(data, 0\)\)/);
assert.match(genericTypedRowsView, /if n > 0 && limit > 0/);
assert.equal(zero(["check", genericPatchRoot]).stdout, "ok\n");
const genericUnknownOpPatchPath = join(outDir, "repository-graph-generic-unknown-op.patch");
writeFileSync(genericUnknownOpPatchPath, [
"zero-program-graph-patch v1",
'setNodeField node="#missing" value="oops"',
"",
].join("\n"));
const genericUnknownOp = json(["patch", "--json", "--check-only", genericPatchRoot, genericUnknownOpPatchPath], { allowFailure: true });
assert.notEqual(genericUnknownOp.code, 0);
assert.equal(genericUnknownOp.body.diagnostic.code, "GPH001");
assert.match(genericUnknownOp.body.diagnostic.message, /unknown program graph patch operation/);
assert.match(genericUnknownOp.body.diagnostic.message, /zero patch --op help/);
assert.match(genericUnknownOp.body.diagnostic.expected, /set, insert, insertEdge, replace, replaceExpr, delete, rename/);
assert.match(genericUnknownOp.body.diagnostic.expected, /replaceFunctionBody/);
assert.equal(genericUnknownOp.body.diagnostic.line, 2);
const genericUnknownOpText = zero(["patch", "--check-only", genericPatchRoot, genericUnknownOpPatchPath], { allowFailure: true });
assert.notEqual(genericUnknownOpText.code, 0);
assert.match(genericUnknownOpText.stderr, /unknown program graph patch operation/);
assert.match(genericUnknownOpText.stderr, new RegExp(`${genericUnknownOpPatchPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}:2: setNodeField`));
assert.match(genericUnknownOpText.stderr, /help: a minimal complete patch file looks exactly like this:\nzero-program-graph-patch v1\nreplaceFunctionBody main\n {2}check world\.out\.write "hello\\n"\nend\n/);
const genericMissingHeaderPatchPath = join(outDir, "repository-graph-generic-missing-header.patch");
writeFileSync(genericMissingHeaderPatchPath, [
"replaceFunctionBody main",
' check world.out.write("missing header\\n")',
"end",
"",
].join("\n"));
const genericMissingHeader = zero(["patch", "--check-only", genericPatchRoot, genericMissingHeaderPatchPath], { allowFailure: true });
assert.notEqual(genericMissingHeader.code, 0);
assert.match(genericMissingHeader.stderr, /unknown program graph patch schema/);
assert.match(genericMissingHeader.stderr, new RegExp(`${genericMissingHeaderPatchPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}:1: replaceFunctionBody main`));
assert.match(genericMissingHeader.stderr, /expected: zero-program-graph-patch v1/);
assert.match(genericMissingHeader.stderr, /help: a minimal complete patch file looks exactly like this:/);
const genericMissingEndPatchPath = join(outDir, "repository-graph-generic-missing-end.patch");
writeFileSync(genericMissingEndPatchPath, [
"zero-program-graph-patch v1",
"replaceFunctionBody main",
' check world.out.write("missing end\\n")',
"",
].join("\n"));
const genericMissingEnd = zero(["patch", "--check-only", genericPatchRoot, genericMissingEndPatchPath], { allowFailure: true });
assert.notEqual(genericMissingEnd.code, 0);
assert.match(genericMissingEnd.stderr, /body patch is missing end marker/);
assert.match(genericMissingEnd.stderr, new RegExp(`${genericMissingEndPatchPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}:2: replaceFunctionBody main`));
assert.match(genericMissingEnd.stderr, /help: a minimal complete patch file looks exactly like this:/);
const genericIndentedHeaderPatchPath = join(outDir, "repository-graph-generic-indented-header.patch");
writeFileSync(genericIndentedHeaderPatchPath, [
" zero-program-graph-patch v1",
" replaceFunctionBody main",
' check world.out.write("indented header ok\\n")',
" end",
"",
].join("\n"));
const genericIndentedHeaderCheckOnly = zero(["patch", "--check-only", genericPatchRoot, genericIndentedHeaderPatchPath]).stdout;
assert.match(genericIndentedHeaderCheckOnly, /^program graph patch ok \(check-only\)\n/);
assert.match(genericIndentedHeaderCheckOnly, /validated: check-equivalent\n$/);
const headerlessOpsRoot = join(outDir, "repository-graph-headerless-ops");
rmSync(headerlessOpsRoot, { recursive: true, force: true });
mkdirSync(join(headerlessOpsRoot, "src"), { recursive: true });
writeZeroTomlSync(headerlessOpsRoot, { package: { name: "headerless-ops", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "src/main.0" } } });
writeFileSync(join(headerlessOpsRoot, "src", "main.0"), [
"const LIMIT: usize = 4",
"",
"fn bump(value: usize) -> usize {",
" return value + LIMIT",
"}",
"",
"fn answer() -> usize {",
" return LIMIT",
"}",
"",
"pub fn main(world: World) -> Void raises {",
" if bump(1) == answer() + 1 {",
" check world.out.write(\"headerless ops ok\\n\")",
" }",
"}",
"",
"test \"answer works\" {",
" expect (answer() == 4)",
"}",
"",
].join("\n"));
assert.equal(json(["import", "--format", "text", "--json", headerlessOpsRoot]).code, 0);
const headerlessAnswerHandles = zero(["view", "--fn", "answer", "--handles", headerlessOpsRoot]).stdout;
const headerlessReturnHandle = headerlessAnswerHandles.match(/return LIMIT\s+\/\/ (#\S+)/);
assert(headerlessReturnHandle, "expected answer return handle for headerless replaceExpr detection");
function assertHeaderlessPatchFileDetected(name: string, rows: string[]) {
const patchPath = join(headerlessOpsRoot, `${name}.patch`);
writeFileSync(patchPath, [...rows, ""].join("\n"));
const result = zeroWithStderr(["patch", "--check-only", `${name}.patch`], { cwd: headerlessOpsRoot });
assert.notEqual(result.code, 0);
assert.match(result.stderr, /unknown program graph patch schema/);
assert.match(result.stderr, new RegExp(`${name}\\.patch:1: ${rows[0].replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`));
assert.match(result.stderr, /expected: zero-program-graph-patch v1/);
}
assertHeaderlessPatchFileDetected("set-const", ['setConst name="LIMIT" value="5"']);
assertHeaderlessPatchFileDetected("set-return-type", [
'setReturnType fn="answer" type="i64"',
"replaceFunctionBody answer",
" return 4 as i64",
"end",
]);
assertHeaderlessPatchFileDetected("replace-expr", [`replaceExpr node="${headerlessReturnHandle[1]}" with="LIMIT + 0"`]);
assertHeaderlessPatchFileDetected("delete-test", ['deleteTest name="answer works"']);
assertHeaderlessPatchFileDetected("rename-test", ['renameTest name="answer works" value="answer still works"']);
assertHeaderlessPatchFileDetected("add-param-to", ['addParamTo fn="bump" name="bias" type="usize" default="0"']);
// Declaration-level patch ops: setConst, addParamTo, setReturnType.
const declOpsRoot = join(outDir, "repository-graph-decl-ops");
rmSync(declOpsRoot, { recursive: true, force: true });
mkdirSync(join(declOpsRoot, "src"), { recursive: true });
writeZeroTomlSync(declOpsRoot, { package: { name: "decl-ops", version: "0.1.0" }, targets: { cli: { kind: "exe", main: "src/main.0" } } });
writeFileSync(join(declOpsRoot, "src", "main.0"), [
"const LIMIT: usize = 4",
"",
"fn bump(value: usize) -> usize {",
" return value + LIMIT",
"}",
"",
"fn twice(value: usize) -> usize {",
" return bump(bump(value))",
"}",
"",
"fn answer() -> usize {",
" return LIMIT",
"}",
"",
"fn wide(a: Span<u8>, b: Span<u8>, c: Span<u8>, d: usize) -> usize {",
" return std.mem.len(a) + std.mem.len(b) + std.mem.len(c) + d",
"}",
"",
"pub fn main(world: World) -> Void raises {",
" let start: usize = bump(1)",
" let total: usize = twice(start)",
" let padding: usize = wide(\"a\", \"b\", \"c\", 0)",
" if total + padding > answer() {",
" check world.out.write(\"decl ops ok\\n\")",
" }",
"}",
"",
].join("\n"));
assert.equal(json(["import", "--format", "text", "--json", declOpsRoot]).code, 0);
assert.equal(zero(["check", declOpsRoot]).stdout, "ok\n");
const declOpsViewBefore = zero(["view", declOpsRoot]).stdout;
assert.match(declOpsViewBefore, /const LIMIT: usize = 4/);
// setConst round trip: change the initializer, then restore it.
const declOpsSetConst = zero(["patch", declOpsRoot, "--op", 'setConst name="LIMIT" value="8"']);
assertPatchOkOutput(declOpsSetConst.stdout, join(declOpsRoot, "zero.graph"));
assert.match(declOpsSetConst.stdout, /validated: check-equivalent\n$/);
assert.match(zero(["view", declOpsRoot]).stdout, /const LIMIT: usize = 8/);
assert.equal(zero(["check", declOpsRoot]).stdout, "ok\n");
const declOpsSetConstBack = json(["patch", "--json", declOpsRoot, "--op", 'setConst name="LIMIT" value="4"']).body;
assert.equal(declOpsSetConstBack.ok, true);
assert.equal(declOpsSetConstBack.operations[0].op, "setConst");
assert.equal(zero(["view", declOpsRoot]).stdout, declOpsViewBefore);
// setConst revalidation failure rolls the store back untouched.
const declOpsStoreBefore = readFileSync(join(declOpsRoot, "zero.graph"), "utf8");
const declOpsBadConst = zero(["patch", declOpsRoot, "--op", 'setConst name="LIMIT" value="missingName"'], { allowFailure: true });
assert.notEqual(declOpsBadConst.code, 0);
assert.match(declOpsBadConst.stderr, /program graph patch failed revalidation: 1 diagnostic introduced by this patch/);
assert.equal(readFileSync(join(declOpsRoot, "zero.graph"), "utf8"), declOpsStoreBefore);
assert.match(zero(["view", declOpsRoot]).stdout, /const LIMIT: usize = 4/);
// setConst misses fail with the nearest const name.
const declOpsConstMiss = zero(["patch", declOpsRoot, "--op", 'setConst name="LIMTI" value="8"'], { allowFailure: true });
assert.notEqual(declOpsConstMiss.code, 0);
assert.match(declOpsConstMiss.stderr, /setConst const was not found; nearest: LIMIT/);
// addParamTo without default fails with the call-site count.
const declOpsNoDefault = zero(["patch", declOpsRoot, "--op", 'addParamTo fn="bump" name="bias" type="usize"'], { allowFailure: true });
assert.notEqual(declOpsNoDefault.code, 0);
assert.match(declOpsNoDefault.stderr, /addParamTo needs a default to update existing call sites/);
assert.match(declOpsNoDefault.stderr, /3 call sites call bump/);
// addParamTo with default appends the parameter and updates every call site,
// including the nested bump(bump(value)) calls inside twice.
const declOpsAddParam = zero(["patch", declOpsRoot, "--op", 'addParamTo fn="bump" name="bias" type="usize" default="0"']);
assertPatchOkOutput(declOpsAddParam.stdout, join(declOpsRoot, "zero.graph"));
assert.match(declOpsAddParam.stdout, /updated 3 call sites\n/);
const declOpsAddParamView = zero(["view", declOpsRoot]).stdout;
assert.match(declOpsAddParamView, /fn bump\(value: usize, bias: usize\) -> usize/);
assert.match(declOpsAddParamView, /return bump\(bump\(value, 0\), 0\)/);
assert.match(declOpsAddParamView, /let start: usize = bump\(1, 0\)/);
assert.equal(zero(["check", declOpsRoot]).stdout, "ok\n");
const declOpsAddParamJson = json(["patch", "--json", declOpsRoot, "--op", 'addParamTo fn="answer" name="extra" type="usize" default="1"']).body;
assert.equal(declOpsAddParamJson.ok, true);
assert.equal(declOpsAddParamJson.operations[0].op, "addParamTo");
assert.equal(declOpsAddParamJson.operations[0].callSites, 1);
// The direct backends cap signatures at 8 ABI argument slots (byte views take
// 2); addParamTo rejects an over-cap signature at patch time.
const declOpsAbiCap = zero(["patch", declOpsRoot, "--op", 'addParamTo fn="wide" name="e" type="Span<u8>"'], { allowFailure: true });
assert.notEqual(declOpsAbiCap.code, 0);
assert.match(declOpsAbiCap.stderr, /direct backend object buildability has too many ABI argument slots/);
assert.match(declOpsAbiCap.stderr, /wide would have 9 ABI argument slot\(s\)/);
// Signature ops compose with other ops in one batched patch.
const declOpsBatchPath = join(outDir, "repository-graph-decl-ops-batch.patch");
writeFileSync(declOpsBatchPath, [
"zero-program-graph-patch v1",
'setConst name="LIMIT" value="6"',
'setReturnType fn="answer" type="i64"',
"replaceFunctionBody answer",
" return 9 as i64",
"end",
"",
].join("\n"));
const declOpsBatch = json(["patch", "--json", declOpsRoot, declOpsBatchPath]).body;
assert.equal(declOpsBatch.ok, true);
assert.equal(declOpsBatch.operationCount, 3);
assert.equal(declOpsBatch.operations[0].op, "setConst");
assert.equal(declOpsBatch.operations[1].op, "setReturnType");
assert.equal(declOpsBatch.operations[2].op, "replaceFunctionBody");
const declOpsBatchView = zero(["view", declOpsRoot]).stdout;
assert.match(declOpsBatchView, /const LIMIT: usize = 6/);
assert.match(declOpsBatchView, /fn answer\(extra: usize\) -> i64/);
assert.equal(zero(["check", declOpsRoot]).stdout, "ok\n");
const checkedInGraphCallsJson = json(["query", "--json", "--fn", "main", "--calls", "write", checkedInGraphPackageDir]).body;
assert.equal(checkedInGraphCallsJson.ok, true);
assert.equal(checkedInGraphCallsJson.query.function, "main");
assert.equal(checkedInGraphCallsJson.query.calls, "write");
assert.equal(checkedInGraphCallsJson.references.length, 0);
assert.equal(checkedInGraphCallsJson.calls.some((call) => call.function === "main" && call.name === "write" && call.resolved === true), true);
const checkedInGraphPackageCheckJson = json(["check", "--json", checkedInGraphPackageDir]).body;
assert.equal(checkedInGraphPackageCheckJson.ok, true);
assert.equal(checkedInGraphPackageCheckJson.sourceFile, checkedInRepositoryGraphStorePath);
assert.equal(checkedInGraphPackageCheckJson.package.name, "program-graph-fixture");
assert.equal(checkedInGraphPackageCheckJson.package.manifestPath, join(checkedInGraphPackageDir, "zero.toml"));
assertSourceGraph(checkedInGraphPackageCheckJson, checkedInRepositoryGraphStorePath, "package:program-graph-fixture@0.1.0", "graph-native-check", false);
assertProgramGraphCompilerInput(checkedInGraphPackageCheckJson, checkedInRepositoryGraphStorePath);
assertRepositoryGraphNativeCheck(checkedInGraphPackageCheckJson);
const sourceFreeCopiedGraphRoot = join(outDir, "source-free-program-graph");
const sourceFreeCopiedGraphStorePath = join(sourceFreeCopiedGraphRoot, "zero.graph");
const sourceFreeCopiedGraphBuildPath = join(outDir, "source-free-program-graph-build");
const sourceFreeCopiedGraphRunPath = join(outDir, "source-free-program-graph-run");
const sourceFreeCImportRoot = join(outDir, "source-free-c-import");
const sourceFreeCImportStorePath = join(sourceFreeCImportRoot, "zero.graph");
const sourceFreeCImportRunPath = join(outDir, "source-free-c-import-run");
const sourceFreeCImportCwdRoot = join(outDir, "source-free-c-import-unrelated-cwd");
const sourceFreeCImportCwdBuildPath = join(outDir, "source-free-c-import-cwd-build");
const sourceFreeIdentityMismatchRoot = join(outDir, "source-free-identity-mismatch");
const sourceFreeMissingPackageNameRoot = join(outDir, "source-free-missing-package-name");
const sourceFreeBadProjectionRoot = join(outDir, "source-free-bad-projection");
rmSync(sourceFreeCopiedGraphRoot, { recursive: true, force: true });
rmSync(sourceFreeCImportRoot, { recursive: true, force: true });
rmSync(sourceFreeCImportRunPath, { recursive: true, force: true });
rmSync(sourceFreeCImportCwdRoot, { recursive: true, force: true });
rmSync(sourceFreeCImportCwdBuildPath, { recursive: true, force: true });
rmSync(sourceFreeIdentityMismatchRoot, { recursive: true, force: true });
rmSync(sourceFreeMissingPackageNameRoot, { recursive: true, force: true });
rmSync(sourceFreeBadProjectionRoot, { recursive: true, force: true });
mkdirSync(sourceFreeCopiedGraphRoot, { recursive: true });
writeFileSync(join(sourceFreeCopiedGraphRoot, "zero.toml"), readFileSync(join(checkedInGraphPackageDir, "zero.toml"), "utf8"));
writeFileSync(sourceFreeCopiedGraphStorePath, readFileSync(checkedInRepositoryGraphStorePath));
const sourceFreeCopiedGraphCheckJson = json(["check", "--json", sourceFreeCopiedGraphRoot]).body;
assert.equal(sourceFreeCopiedGraphCheckJson.ok, true);
assert.equal(sourceFreeCopiedGraphCheckJson.sourceFile, sourceFreeCopiedGraphStorePath);
assertSourceGraph(sourceFreeCopiedGraphCheckJson, sourceFreeCopiedGraphStorePath, "package:program-graph-fixture@0.1.0", "graph-native-check", false, "missing");
assertProgramGraphCompilerInput(sourceFreeCopiedGraphCheckJson, sourceFreeCopiedGraphStorePath);
assertRepositoryGraphNativeCheck(sourceFreeCopiedGraphCheckJson, "missing");
const sourceFreeCopiedGraphSizeJson = json(["size", "--json", "--target", "linux-musl-x64", sourceFreeCopiedGraphRoot]).body;
assertSourceGraph(sourceFreeCopiedGraphSizeJson, sourceFreeCopiedGraphStorePath, "package:program-graph-fixture@0.1.0", "mapped-final-mir", false, "missing");
assertProgramGraphCompilerInput(sourceFreeCopiedGraphSizeJson, sourceFreeCopiedGraphStorePath);
const sourceFreeCopiedGraphBuildJson = json(["build", "--json", "--target", "linux-musl-x64", "--out", sourceFreeCopiedGraphBuildPath, sourceFreeCopiedGraphRoot]).body;
assert.equal(sourceFreeCopiedGraphBuildJson.sourceFile, sourceFreeCopiedGraphStorePath);
assertSourceGraph(sourceFreeCopiedGraphBuildJson, sourceFreeCopiedGraphStorePath, "package:program-graph-fixture@0.1.0", "mapped-final-mir", false, "missing");
assertProgramGraphCompilerInput(sourceFreeCopiedGraphBuildJson, sourceFreeCopiedGraphStorePath);
assert.equal(zero(["run", "--out", sourceFreeCopiedGraphRunPath, sourceFreeCopiedGraphRoot]).stdout, "hello from zero\n");
const sourceFreeCopiedGraphTestJson = json(["test", "--json", sourceFreeCopiedGraphRoot]).body;
assert.equal(sourceFreeCopiedGraphTestJson.ok, true);
assertSourceGraph(sourceFreeCopiedGraphTestJson, sourceFreeCopiedGraphStorePath, "package:program-graph-fixture@0.1.0", "direct-program-graph", false, "missing");
assert.equal(sourceFreeCopiedGraphTestJson.testBackend, "direct-program-graph");
assert.equal(sourceFreeCopiedGraphTestJson.testDiscovery.mode, "package-graph");
const sourceFreeCopiedGraphMemJson = json(["mem", "--json", sourceFreeCopiedGraphRoot]).body;
assertSourceGraph(sourceFreeCopiedGraphMemJson, sourceFreeCopiedGraphStorePath, "package:program-graph-fixture@0.1.0", "mapped-final-mir", false, "missing");
assertProgramGraphCompilerInput(sourceFreeCopiedGraphMemJson, sourceFreeCopiedGraphStorePath);
const sourceFreeCopiedGraphVerify = json(["verify-projection", "--json", sourceFreeCopiedGraphRoot], { allowFailure: true });
assert.notEqual(sourceFreeCopiedGraphVerify.code, 0);
assert.equal(sourceFreeCopiedGraphVerify.body.diagnostics[0].code, "RGP006");
assert.equal(sourceFreeCopiedGraphVerify.body.diagnostics[0].actual, "missing source projection file");
const sourceFreeCopiedGraphExport = json(["export", "--json", sourceFreeCopiedGraphRoot]).body;
assert.equal(sourceFreeCopiedGraphExport.ok, true);
assert.deepEqual(sourceFreeCopiedGraphExport.changedPaths, [join(sourceFreeCopiedGraphRoot, "hello.0")]);
assert.equal(readFileSync(join(sourceFreeCopiedGraphRoot, "hello.0"), "utf8"), readFileSync(checkedInGraphSourcePath, "utf8"));
const sourceFreeCopiedGraphVerifyAfter = json(["verify-projection", "--json", sourceFreeCopiedGraphRoot]).body;
assert.equal(sourceFreeCopiedGraphVerifyAfter.ok, true);
assert.equal(sourceFreeCopiedGraphVerifyAfter.repositoryGraph.projectionValidity, "clean");
assert.deepEqual(json(["export", "--json", sourceFreeCopiedGraphRoot]).body.changedPaths, []);
mkdirSync(join(sourceFreeCImportRoot, "src"), { recursive: true });
mkdirSync(join(sourceFreeCImportRoot, "vendor/include"), { recursive: true });
writeZeroTomlSync(sourceFreeCImportRoot, {
package: { name: "source-free-c-import", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "src/main.0" } },
c: {
libs: {
ext: { headers: ["vendor/include/zero_ext.h"], include: ["vendor/include"], lib: [], link: [], mode: "static" },
},
},
});
writeFileSync(join(sourceFreeCImportRoot, "vendor/include/zero_ext.h"), "int zero_ext_add(int a, int b);\n");
writeFileSync(join(sourceFreeCImportRoot, "src/main.0"), `extern c "vendor/include/zero_ext.h" as c
pub fn main(world: World) -> Void raises {
check world.out.write("source-free c import ok\\n")
}
`);
const sourceFreeCImportSync = json(["import", "--format", "text", "--json", sourceFreeCImportRoot]).body;
assert.equal(sourceFreeCImportSync.ok, true);
assert.equal(sourceFreeCImportSync.repositoryGraph.projectionValidity, "clean");
rmSync(join(sourceFreeCImportRoot, "src"), { recursive: true, force: true });
const sourceFreeCImportCheck = json(["check", "--json", sourceFreeCImportRoot]).body;
assert.equal(sourceFreeCImportCheck.ok, true);
assertSourceGraph(sourceFreeCImportCheck, sourceFreeCImportStorePath, "package:source-free-c-import@0.1.0", "graph-native-check", false, "missing");
assertProgramGraphCompilerInput(sourceFreeCImportCheck, sourceFreeCImportStorePath);
assertRepositoryGraphNativeCheck(sourceFreeCImportCheck, "missing");
assert.equal(zero(["run", "--out", sourceFreeCImportRunPath, sourceFreeCImportRoot]).stdout, "source-free c import ok\n");
mkdirSync(sourceFreeCImportCwdRoot, { recursive: true });
writeZeroTomlSync(sourceFreeCImportCwdRoot, {
package: { name: "unrelated-cwd-package", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "src/main.0" } },
});
const sourceFreeCImportCwdBuild = JSON.parse(execFileSync(zeroBin, [
"build",
"--json",
"--out",
resolve(sourceFreeCImportCwdBuildPath),
resolve(sourceFreeCImportRoot),
], { cwd: sourceFreeCImportCwdRoot, encoding: "utf8", maxBuffer: execMaxBuffer, stdio: ["ignore", "pipe", "pipe"] }));
assertSourceGraph(sourceFreeCImportCwdBuild, resolve(sourceFreeCImportStorePath), "package:source-free-c-import@0.1.0", "mapped-final-mir", false, "missing");
assertProgramGraphCompilerInput(sourceFreeCImportCwdBuild, resolve(sourceFreeCImportStorePath));
mkdirSync(sourceFreeIdentityMismatchRoot, { recursive: true });
writeZeroTomlSync(sourceFreeIdentityMismatchRoot, {
package: { name: "wrong-program-graph-fixture", version: "9.9.9" },
targets: { cli: { kind: "exe", main: "hello.0" } },
});
writeFileSync(join(sourceFreeIdentityMismatchRoot, "zero.graph"), readFileSync(checkedInRepositoryGraphStorePath));
const sourceFreeIdentityMismatchCheck = json(["check", "--json", sourceFreeIdentityMismatchRoot], { allowFailure: true });
assert.notEqual(sourceFreeIdentityMismatchCheck.code, 0);
assert.equal(sourceFreeIdentityMismatchCheck.body.diagnostics[0].code, "RGP007");
assert.equal(sourceFreeIdentityMismatchCheck.body.diagnostics[0].expected, "package:wrong-program-graph-fixture@9.9.9");
assert.equal(sourceFreeIdentityMismatchCheck.body.diagnostics[0].actual, "package:program-graph-fixture@0.1.0");
const sourceFreeIdentityMismatchSize = json(["size", "--json", sourceFreeIdentityMismatchRoot], { allowFailure: true });
assert.notEqual(sourceFreeIdentityMismatchSize.code, 0);
assert.equal(sourceFreeIdentityMismatchSize.body.diagnostics[0].code, "RGP007");
mkdirSync(sourceFreeMissingPackageNameRoot, { recursive: true });
writeZeroTomlSync(sourceFreeMissingPackageNameRoot, {
targets: { cli: { kind: "exe", main: "hello.0" } },
});
writeFileSync(join(sourceFreeMissingPackageNameRoot, "zero.graph"), readFileSync(checkedInRepositoryGraphStorePath));
const sourceFreeMissingPackageNameCheck = json(["check", "--json", sourceFreeMissingPackageNameRoot], { allowFailure: true });
assert.notEqual(sourceFreeMissingPackageNameCheck.code, 0);
assert.equal(sourceFreeMissingPackageNameCheck.body.diagnostics[0].code, "RGP007");
assert.equal(sourceFreeMissingPackageNameCheck.body.diagnostics[0].message, "repository graph compiler input requires package.name");
assert.match(sourceFreeMissingPackageNameCheck.body.diagnostics[0].actual, /package:program-graph-fixture@0\.1\.0/);
mkdirSync(sourceFreeBadProjectionRoot, { recursive: true });
writeFileSync(join(sourceFreeBadProjectionRoot, "zero.toml"), readFileSync(join(checkedInGraphPackageDir, "zero.toml"), "utf8"));
writeFileSync(join(sourceFreeBadProjectionRoot, "hello.0"), checkedInGraphSource);
zero(["import", "--format", "text", sourceFreeBadProjectionRoot]);
const sourceFreeBadProjectionStoreText = readFileSync(join(sourceFreeBadProjectionRoot, "zero.graph"), "utf8");
writeFileSync(join(sourceFreeBadProjectionRoot, "zero.graph"), sourceFreeBadProjectionStoreText.replace(
/^projection path:"hello\.0" text:.*$/m,
`projection path:"hello.0" text:${JSON.stringify("pub fn broken( {\n")}`,
));
const sourceFreeBadProjectionStatus = json(["status", "--json", sourceFreeBadProjectionRoot]).body;
assert.equal(sourceFreeBadProjectionStatus.repositoryGraph.projectionState, "conflict");
assert.equal(sourceFreeBadProjectionStatus.repositoryGraph.projectionValidity, "conflict");
const sourceFreeBadProjectionCheck = json(["check", "--json", sourceFreeBadProjectionRoot]).body;
assert.equal(sourceFreeBadProjectionCheck.ok, true);
assertSourceGraph(sourceFreeBadProjectionCheck, join(sourceFreeBadProjectionRoot, "zero.graph"), "package:program-graph-fixture@0.1.0", "graph-native-check", false, "conflict");
assertRepositoryGraphNativeCheck(sourceFreeBadProjectionCheck, "conflict");
const sourceFreeBadProjectionSync = json(["export", "--json", sourceFreeBadProjectionRoot], { allowFailure: true });
assert.notEqual(sourceFreeBadProjectionSync.code, 0);
assert.equal(sourceFreeBadProjectionSync.body.diagnostics[0].code, "RGP004");
const missingRepoGraphStoreRoot = join(outDir, "repository-graph-missing-store");
rmSync(missingRepoGraphStoreRoot, { recursive: true, force: true });
mkdirSync(missingRepoGraphStoreRoot, { recursive: true });
writeZeroTomlSync(missingRepoGraphStoreRoot, {
package: { name: "repository-graph-missing-store", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "main.0" } },
});
writeFileSync(join(missingRepoGraphStoreRoot, "main.0"), "pub fn main() -> i32 { return 0 }\n");
const missingRepoGraphStoreCheck = json(["check", "--json", missingRepoGraphStoreRoot], { allowFailure: true });
assert.notEqual(missingRepoGraphStoreCheck.code, 0);
assert.equal(missingRepoGraphStoreCheck.body.ok, false);
assert.equal(missingRepoGraphStoreCheck.body.mode, "compiler-input");
assert.equal(missingRepoGraphStoreCheck.body.repositoryGraph.storePresent, false);
assert.equal(missingRepoGraphStoreCheck.body.diagnostics[0].code, "RGP001");
assert.equal(missingRepoGraphStoreCheck.body.diagnostics[0].path, missingRepoGraphStoreRoot);
assert.match(missingRepoGraphStoreCheck.body.repairCommands.join("\n"), /zero import/);
const invalidRepoGraphStoreRoot = join(outDir, "repository-graph-invalid-store");
rmSync(invalidRepoGraphStoreRoot, { recursive: true, force: true });
mkdirSync(invalidRepoGraphStoreRoot, { recursive: true });
writeZeroTomlSync(invalidRepoGraphStoreRoot, {
package: { name: "repository-graph-invalid-store", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "main.0" } },
});
writeFileSync(join(invalidRepoGraphStoreRoot, "main.0"), "pub fn main() -> i32 { return 0 }\n");
writeFileSync(join(invalidRepoGraphStoreRoot, "zero.graph"), "not a repository graph\n");
const invalidRepoGraphStoreCheck = json(["check", "--json", invalidRepoGraphStoreRoot], { allowFailure: true });
assert.notEqual(invalidRepoGraphStoreCheck.code, 0);
assert.equal(invalidRepoGraphStoreCheck.body.ok, false);
assert.equal(invalidRepoGraphStoreCheck.body.mode, "compiler-input");
assert.equal(invalidRepoGraphStoreCheck.body.repositoryGraph.storePresent, true);
assert.equal(invalidRepoGraphStoreCheck.body.repositoryGraph.storeValid, false);
assert.equal(invalidRepoGraphStoreCheck.body.diagnostics[0].code, "RGP003");
assert.equal(invalidRepoGraphStoreCheck.body.diagnostics[0].path, invalidRepoGraphStoreRoot);
assert.match(invalidRepoGraphStoreCheck.body.repairCommands.join("\n"), /zero import/);
const directoryRepoGraphStoreRoot = join(outDir, "repository-graph-directory-store");
rmSync(directoryRepoGraphStoreRoot, { recursive: true, force: true });
mkdirSync(join(directoryRepoGraphStoreRoot, "zero.graph"), { recursive: true });
writeZeroTomlSync(directoryRepoGraphStoreRoot, {
package: { name: "repository-graph-directory-store", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "main.0" } },
});
writeFileSync(join(directoryRepoGraphStoreRoot, "main.0"), "pub fn main() -> i32 { return 0 }\n");
const directoryRepoGraphStoreCheck = json(["check", "--json", directoryRepoGraphStoreRoot], { allowFailure: true });
assert.notEqual(directoryRepoGraphStoreCheck.code, 0);
assert.equal(directoryRepoGraphStoreCheck.body.ok, false);
assert.equal(directoryRepoGraphStoreCheck.body.repositoryGraph.storePresent, true);
assert.equal(directoryRepoGraphStoreCheck.body.repositoryGraph.projectionState, "store-invalid");
assert.equal(directoryRepoGraphStoreCheck.body.diagnostics[0].code, "RGP003");
assert.equal(directoryRepoGraphStoreCheck.body.diagnostics[0].actual, "failed to read repository graph store");
const sourceFreeGraphPackageRoot = join(outDir, "source-free-graph-package");
rmSync(sourceFreeGraphPackageRoot, { recursive: true, force: true });
mkdirSync(join(sourceFreeGraphPackageRoot, "src"), { recursive: true });
writeZeroTomlSync(sourceFreeGraphPackageRoot, {
package: { name: "source-free-graph-package", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "src/main.0" } },
});
writeFileSync(join(sourceFreeGraphPackageRoot, "src", "main.0"), readFileSync("conformance/packages/test-app/src/main.0", "utf8"));
writeFileSync(join(sourceFreeGraphPackageRoot, "src", "helper.0"), readFileSync("conformance/packages/test-app/src/helper.0", "utf8"));
const sourceFreeGraphPackageSync = json(["import", "--format", "text", "--json", sourceFreeGraphPackageRoot]);
assert.equal(sourceFreeGraphPackageSync.body.ok, true);
rmSync(join(sourceFreeGraphPackageRoot, "src"), { recursive: true, force: true });
const sourceFreeGraphPackageStorePath = join(sourceFreeGraphPackageRoot, "zero.graph");
const sourceFreeGraphPackageCheckJson = json(["check", "--json", sourceFreeGraphPackageRoot]).body;
assert.equal(sourceFreeGraphPackageCheckJson.ok, true);
assertSourceGraph(sourceFreeGraphPackageCheckJson, sourceFreeGraphPackageStorePath, "package:source-free-graph-package@0.1.0", "graph-native-check", false, "missing");
assertProgramGraphCompilerInput(sourceFreeGraphPackageCheckJson, sourceFreeGraphPackageStorePath);
assertRepositoryGraphNativeCheck(sourceFreeGraphPackageCheckJson, "missing");
assert(sourceFreeGraphPackageCheckJson.interfaceFingerprints.modules.some((module) => module.name === "main"));
assert(sourceFreeGraphPackageCheckJson.interfaceFingerprints.modules.some((module) => module.name === "main" && module.imports.some((entry) => entry.module === "helper")));
const sourceFreeGraphPackageSizeJson = json(["size", "--json", "--target", "linux-musl-x64", sourceFreeGraphPackageRoot]).body;
assertSourceGraph(sourceFreeGraphPackageSizeJson, sourceFreeGraphPackageStorePath, "package:source-free-graph-package@0.1.0", "mapped-final-mir", false, "missing");
assertProgramGraphCompilerInput(sourceFreeGraphPackageSizeJson, sourceFreeGraphPackageStorePath);
const sourceFreeGraphPackageSizeMir = sourceFreeGraphPackageSizeJson.compilerCaches.find((cache) => cache.name === "mappedFinalMir");
assert.equal(sourceFreeGraphPackageSizeMir.codegenImmediate, sourceFreeGraphPackageSizeMir.hit === true);
assert.equal(sourceFreeGraphPackageSizeMir.programReconstructed, false);
const sourceFreeGraphPackageBuildPath = join(outDir, "source-free-graph-package-build");
const sourceFreeGraphPackageBuildJson = json(["build", "--json", "--target", "linux-musl-x64", "--out", sourceFreeGraphPackageBuildPath, sourceFreeGraphPackageRoot]).body;
assert.equal(sourceFreeGraphPackageBuildJson.sourceFile, sourceFreeGraphPackageStorePath);
assertSourceGraph(sourceFreeGraphPackageBuildJson, sourceFreeGraphPackageStorePath, "package:source-free-graph-package@0.1.0", "mapped-final-mir", false, "missing");
assertProgramGraphCompilerInput(sourceFreeGraphPackageBuildJson, sourceFreeGraphPackageStorePath);
const sourceFreeGraphPackageBuildMir = sourceFreeGraphPackageBuildJson.compilerCaches.find((cache) => cache.name === "mappedFinalMir");
assert.equal(sourceFreeGraphPackageBuildMir.hit, true);
assert.equal(sourceFreeGraphPackageBuildMir.codegenImmediate, true);
assert.equal(sourceFreeGraphPackageBuildMir.programReconstructed, false);
const sourceFreeGraphPackageRunPath = join(outDir, "source-free-graph-package-run");
assert.equal(zero(["run", "--out", sourceFreeGraphPackageRunPath, sourceFreeGraphPackageRoot]).stdout, "package tests\n");
const sourceFreeGraphPackageTestJson = json(["test", "--json", sourceFreeGraphPackageRoot]).body;
assert.equal(sourceFreeGraphPackageTestJson.ok, true);
assertSourceGraph(sourceFreeGraphPackageTestJson, sourceFreeGraphPackageStorePath, "package:source-free-graph-package@0.1.0", "direct-program-graph", false, "missing");
assert.equal(sourceFreeGraphPackageTestJson.testBackend, "direct-program-graph");
assert.equal(sourceFreeGraphPackageTestJson.selectedTests, 3);
const sourceFreeGraphPackageMemJson = json(["mem", "--json", sourceFreeGraphPackageRoot]).body;
assertSourceGraph(sourceFreeGraphPackageMemJson, sourceFreeGraphPackageStorePath, "package:source-free-graph-package@0.1.0", "mapped-final-mir", false, "missing");
assertProgramGraphCompilerInput(sourceFreeGraphPackageMemJson, sourceFreeGraphPackageStorePath);
const sourceFreeGraphPackageStatus = json(["status", "--json", sourceFreeGraphPackageRoot]).body;
assert.equal(sourceFreeGraphPackageStatus.repositoryGraph.semanticValidity, "shape-valid");
assert.equal(sourceFreeGraphPackageStatus.repositoryGraph.projectionValidity, "missing");
const sourceFreeGraphPackageVerify = json(["verify-projection", "--json", sourceFreeGraphPackageRoot], { allowFailure: true });
assert.notEqual(sourceFreeGraphPackageVerify.code, 0);
assert.equal(sourceFreeGraphPackageVerify.body.ok, false);
assert.equal(sourceFreeGraphPackageVerify.body.diagnostics[0].code, "RGP006");
assert.equal(sourceFreeGraphPackageVerify.body.diagnostics[0].actual, "missing source projection file");
const sourceFreeGraphPackageExport = json(["export", "--json", sourceFreeGraphPackageRoot]).body;
assert.equal(sourceFreeGraphPackageExport.ok, true);
assert.deepEqual(sourceFreeGraphPackageExport.changedPaths, [
join(sourceFreeGraphPackageRoot, "src", "helper.0"),
join(sourceFreeGraphPackageRoot, "src", "main.0"),
]);
assert.equal(readFileSync(join(sourceFreeGraphPackageRoot, "src", "main.0"), "utf8"), readFileSync("conformance/packages/test-app/src/main.0", "utf8"));
assert.equal(readFileSync(join(sourceFreeGraphPackageRoot, "src", "helper.0"), "utf8"), readFileSync("conformance/packages/test-app/src/helper.0", "utf8"));
const sourceFreeGraphPackageVerifyAfter = json(["verify-projection", "--json", sourceFreeGraphPackageRoot]).body;
assert.equal(sourceFreeGraphPackageVerifyAfter.ok, true);
assert.equal(sourceFreeGraphPackageVerifyAfter.repositoryGraph.projectionValidity, "clean");
assert.deepEqual(json(["export", "--json", sourceFreeGraphPackageRoot]).body.changedPaths, []);
const graphTargetWebbitsRoot = join(outDir, "repo-graph-target-webbits");
const graphTargetIncompatibleRoot = join(outDir, "repo-graph-target-incompatible-app");
rmSync(graphTargetWebbitsRoot, { recursive: true, force: true });
rmSync(graphTargetIncompatibleRoot, { recursive: true, force: true });
mkdirSync(join(graphTargetIncompatibleRoot, "src"), { recursive: true });
mkdirSync(graphTargetWebbitsRoot, { recursive: true });
writeFileSync(join(graphTargetWebbitsRoot, "zero.toml"), readFileSync("conformance/packages/target-webbits/zero.toml", "utf8"));
writeZeroTomlSync(graphTargetIncompatibleRoot, {
package: { name: "repo-graph-target-incompatible-app", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "src/main.0" } },
dependencies: { "target-webbits": { path: "../repo-graph-target-webbits", version: "0.1.0", targets: ["win32-x64.exe"] } },
});
writeFileSync(join(graphTargetIncompatibleRoot, "src", "main.0"), `pub fn main(world: World) -> Void raises {
check world.out.write("target incompatible\\n")
}
`);
assert.equal(json(["import", "--format", "text", "--json", graphTargetIncompatibleRoot]).body.ok, true);
const graphTargetIncompatibleCheck = json(["check", "--json", "--target", "linux-musl-x64", graphTargetIncompatibleRoot], { allowFailure: true });
assert.notEqual(graphTargetIncompatibleCheck.code, 0);
assert.equal(graphTargetIncompatibleCheck.body.diagnostics[0].code, "PKG004");
assert.match(graphTargetIncompatibleCheck.body.diagnostics[0].actual, /target-webbits targets/);
const graphTargetCapabilityRoot = join(outDir, "repo-graph-target-capability-app");
rmSync(graphTargetCapabilityRoot, { recursive: true, force: true });
mkdirSync(graphTargetCapabilityRoot, { recursive: true });
writeZeroTomlSync(graphTargetCapabilityRoot, {
package: { name: "repo-graph-target-capability-app", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "main.0" } },
});
writeFileSync(join(graphTargetCapabilityRoot, "main.0"), `pub fn main(world: World) -> Void raises {
let fs: Fs = std.fs.host()
if std.fs.writeFile(fs, ".zero/out/repo-graph-target-capability.txt", "ok\\n") {
check world.out.write("ok\\n")
}
}
`);
assert.equal(json(["import", "--format", "text", "--json", graphTargetCapabilityRoot]).body.ok, true);
const graphTargetCapabilityCheck = json(["check", "--json", "--target", "linux-arm64", graphTargetCapabilityRoot], { allowFailure: true });
assert.notEqual(graphTargetCapabilityCheck.code, 0);
assert.equal(graphTargetCapabilityCheck.body.diagnostics[0].code, "TAR002");
assert.match(graphTargetCapabilityCheck.body.diagnostics[0].actual, /lacks Fs/);
const graphTargetBackendMismatchCheck = json(["check", "--json", "--backend", "zero-coff-x64", "--target", "linux-musl-x64", checkedInGraphPackageDir]);
assert.equal(graphTargetBackendMismatchCheck.body.ok, true);
assert.equal(graphTargetBackendMismatchCheck.body.targetReadiness.ok, false);
assert.equal(graphTargetBackendMismatchCheck.body.targetReadiness.diagnostics[0].code, "BLD004");
assert.equal(graphTargetBackendMismatchCheck.body.targetReadiness.diagnostics[0].backendBlocker.backend, "zero-coff-x64");
const sourceFreeStdGraphRoot = join(outDir, "source-free-std-str");
rmSync(sourceFreeStdGraphRoot, { recursive: true, force: true });
mkdirSync(sourceFreeStdGraphRoot, { recursive: true });
writeZeroTomlSync(sourceFreeStdGraphRoot, {
package: { name: "source-free-std-str", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "main.0" } },
});
writeFileSync(join(sourceFreeStdGraphRoot, "main.0"), readFileSync("examples/std-str.0", "utf8"));
const sourceFreeStdGraphSync = json(["import", "--format", "text", "--json", sourceFreeStdGraphRoot]);
assert.equal(sourceFreeStdGraphSync.body.ok, true);
rmSync(join(sourceFreeStdGraphRoot, "main.0"), { force: true });
const sourceFreeStdGraphCheckJson = json(["check", "--json", sourceFreeStdGraphRoot]).body;
assert.equal(sourceFreeStdGraphCheckJson.ok, true);
assertSourceGraph(sourceFreeStdGraphCheckJson, join(sourceFreeStdGraphRoot, "zero.graph"), "package:source-free-std-str@0.1.0", "graph-native-check", false, "missing");
assertProgramGraphCompilerInput(sourceFreeStdGraphCheckJson, join(sourceFreeStdGraphRoot, "zero.graph"));
assertRepositoryGraphNativeCheck(sourceFreeStdGraphCheckJson, "missing");
assert.equal(sourceFreeStdGraphCheckJson.targetReadiness.ok, true);
assert.equal(sourceFreeStdGraphCheckJson.targetReadiness.diagnostics.length, 0);
assert(sourceFreeStdGraphCheckJson.graphCompiler.semanticFacts.calls.some((call) => call.qualifiedName === "std.str.reverse" && call.contract.kind === "stdlib" && call.resolution.targetKind === "stdlib" && call.returnType === "Maybe<Span<u8>>"));
assert(sourceFreeStdGraphCheckJson.graphCompiler.tables.capability > 0);
const checkedInGraphPackageSizeJson = json(["size", "--json", "--target", "linux-musl-x64", checkedInGraphPackageDir]).body;
assert.equal(checkedInGraphPackageSizeJson.sourceFile, checkedInRepositoryGraphStorePath);
assertSourceGraph(checkedInGraphPackageSizeJson, checkedInRepositoryGraphStorePath, "package:program-graph-fixture@0.1.0", "mapped-final-mir", false);
assertProgramGraphCompilerInput(checkedInGraphPackageSizeJson, checkedInRepositoryGraphStorePath);
const checkedInGraphPackageSizeMir = checkedInGraphPackageSizeJson.compilerCaches.find((cache) => cache.name === "mappedFinalMir");
assert.equal(checkedInGraphPackageSizeMir.codegenImmediate, checkedInGraphPackageSizeMir.hit === true);
assert.equal(checkedInGraphPackageSizeMir.programReconstructed, false);
const checkedInGraphPackageBuildJson = json(["build", "--json", "--target", "linux-musl-x64", "--out", checkedInGraphBuildPath, checkedInGraphPackageDir]).body;
assert.equal(checkedInGraphPackageBuildJson.sourceFile, checkedInRepositoryGraphStorePath);
assertSourceGraph(checkedInGraphPackageBuildJson, checkedInRepositoryGraphStorePath, "package:program-graph-fixture@0.1.0", "mapped-final-mir", false);
assertProgramGraphCompilerInput(checkedInGraphPackageBuildJson, checkedInRepositoryGraphStorePath);
const checkedInGraphPackageBuildMir = checkedInGraphPackageBuildJson.compilerCaches.find((cache) => cache.name === "mappedFinalMir");
assert.equal(checkedInGraphPackageBuildMir.hit, true);
assert.equal(checkedInGraphPackageBuildMir.codegenImmediate, true);
assert.equal(checkedInGraphPackageBuildMir.programReconstructed, false);
assert.equal(checkedInGraphPackageBuildJson.artifactPath, checkedInGraphBuildPath);
mkdirSync(graphRecordRoot, { recursive: true });
writeZeroTomlSync(graphRecordRoot, {
package: { name: "repository-graph-record", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "main.0" } },
});
writeFileSync(join(graphRecordRoot, "main.0"), [
"type Point {",
" x: i32,",
" y: i32,",
"}",
"",
"pub fn main(world: World) -> Void raises {",
" let point: Point = Point { x: 40, y: 2 }",
" if point.x == 40 {",
" check world.out.write(\"ok\\n\")",
" }",
"}",
].join("\n") + "\n");
assert.equal(json(["import", "--format", "text", "--json", graphRecordRoot]).body.ok, true);
const graphRecordCheckJson = json(["check", "--json", graphRecordRoot]).body;
assert.equal(graphRecordCheckJson.ok, true);
assertRepositoryGraphNativeCheck(graphRecordCheckJson);
assert.equal(graphRecordCheckJson.targetReadiness.ok, true);
assert.equal(graphRecordCheckJson.targetReadiness.diagnostics.length, 0);
assert.equal(graphRecordCheckJson.graphCompiler.defaultReadiness.compilerInputReady, true);
assert.equal(graphRecordCheckJson.graphCompiler.defaultReadiness.claim, "ready-for-repository-graph-input");
const graphRecordBuildJson = json(["build", "--json", "--target", "linux-musl-x64", "--out", graphRecordBuildPath, graphRecordRoot]).body;
assertSourceGraph(graphRecordBuildJson, join(graphRecordRoot, "zero.graph"), "package:repository-graph-record@0.1.0", "mapped-final-mir", false, "clean");
assert.equal(graphRecordBuildJson.artifactPath, graphRecordBuildPath);
assert.equal(existsSync(graphRecordBuildPath), true);
const graphRecordObjJson = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "--out", graphRecordObjPath, graphRecordRoot]).body;
assertSourceGraph(graphRecordObjJson, join(graphRecordRoot, "zero.graph"), "package:repository-graph-record@0.1.0", "mapped-final-mir", false, "clean");
assert.equal(graphRecordObjJson.artifactPath, graphRecordObjPath);
assert.equal(existsSync(graphRecordObjPath), true);
const graphRecordDirectLlvmIrJson = json(["build", "--json", "--emit", "llvm-ir", "--target", "linux-musl-x64", "--out", graphRecordDirectLlvmIrPath, graphRecordRoot], { allowFailure: true });
assert.notEqual(graphRecordDirectLlvmIrJson.code, 0);
assert.equal(graphRecordDirectLlvmIrJson.body.diagnostics[0].message, "direct backend does not support --emit llvm-ir");
assert.equal(graphRecordDirectLlvmIrJson.body.diagnostics[0].path, join(graphRecordRoot, "zero.graph"));
assert.equal(graphRecordDirectLlvmIrJson.body.diagnostics[0].backendBlocker.backend, "direct");
assert.equal(graphRecordDirectLlvmIrJson.body.diagnostics[0].backendBlocker.stage, "buildability");
assert.equal(graphRecordDirectLlvmIrJson.body.diagnostics[0].backendBlocker.unsupportedFeature, "llvm-ir");
assert.equal(existsSync(graphRecordDirectLlvmIrPath), false);
const graphRecordLlvmIrJson = json(["build", "--json", "--backend", "llvm", "--emit", "llvm-ir", "--target", "linux-musl-x64", "--out", graphRecordLlvmIrPath, graphRecordRoot], { allowFailure: true });
assert.notEqual(graphRecordLlvmIrJson.code, 0);
assert.equal(graphRecordLlvmIrJson.body.diagnostics[0].path, join(graphRecordRoot, "zero.graph"));
assert.equal(graphRecordLlvmIrJson.body.diagnostics[0].message, "LLVM IR backend local type is unsupported");
assert.equal(graphRecordLlvmIrJson.body.diagnostics[0].backendBlocker.backend, "llvm");
assert.equal(graphRecordLlvmIrJson.body.diagnostics[0].backendBlocker.stage, "lower");
assert.equal(graphRecordLlvmIrJson.body.diagnostics[0].backendBlocker.unsupportedFeature, "unsupported local type");
assert.equal(existsSync(graphRecordLlvmIrPath), false);
const checkedInGraphPackageDefaultBuildJson = json(["build", "--json", "--target", "linux-musl-x64", checkedInGraphPackageDir]).body;
assert.equal(checkedInGraphPackageDefaultBuildJson.artifactPath, checkedInGraphDefaultBuildPath);
assert.equal(zero(["run", "--out", checkedInGraphRunPath, checkedInGraphPackageDir]).stdout, "hello from zero\n");
const checkedInGraphPackageTestJson = json(["test", "--json", checkedInGraphPackageDir]).body;
assert.equal(checkedInGraphPackageTestJson.ok, true);
assert.equal(checkedInGraphPackageTestJson.sourceFile, checkedInRepositoryGraphStorePath);
assertSourceGraph(checkedInGraphPackageTestJson, checkedInRepositoryGraphStorePath, "package:program-graph-fixture@0.1.0", "direct-program-graph", false);
assert.equal(checkedInGraphPackageTestJson.testBackend, "direct-program-graph");
assert.equal(checkedInGraphPackageTestJson.testDiscovery.mode, "package-graph");
assert.equal(checkedInGraphPackageTestJson.selectedTests, 0);
const checkedInRepositoryGraphStoreBytes = readFileSync(checkedInRepositoryGraphStorePath);
assert.equal(checkedInRepositoryGraphStoreBytes.subarray(0, 8).toString("binary"), "ZRGBIN1\0");
const sourceLocationOnlyGraphRoot = join(outDir, "repository-graph-source-location-only");
rmSync(sourceLocationOnlyGraphRoot, { recursive: true, force: true });
mkdirSync(sourceLocationOnlyGraphRoot, { recursive: true });
writeFileSync(join(sourceLocationOnlyGraphRoot, "zero.toml"), readFileSync(join(checkedInGraphPackageDir, "zero.toml"), "utf8"));
writeFileSync(join(sourceLocationOnlyGraphRoot, "hello.0"), checkedInGraphSource);
zero(["import", "--format", "text", sourceLocationOnlyGraphRoot]);
const sourceLocationOnlyStoreText = readFileSync(join(sourceLocationOnlyGraphRoot, "zero.graph"), "utf8");
writeFileSync(join(sourceLocationOnlyGraphRoot, "zero.graph"), sourceLocationOnlyStoreText.replace("line:1 column:1", "line:99 column:77"));
const sourceLocationOnlyVerify = json(["verify-projection", "--json", sourceLocationOnlyGraphRoot]).body;
assert.equal(sourceLocationOnlyVerify.ok, true);
assert.equal(sourceLocationOnlyVerify.repositoryGraph.projectionState, "clean");
const checkedInRepositoryGraphStatus = json(["status", "--json", "--target", "linux-musl-x64", checkedInGraphPackageDir]).body;
assert.equal(checkedInRepositoryGraphStatus.repositoryGraph.storePresent, true);
assert.equal(checkedInRepositoryGraphStatus.repositoryGraph.storeValid, true);
assert.equal(checkedInRepositoryGraphStatus.repositoryGraph.projectionState, "clean");
assert.equal(checkedInRepositoryGraphStatus.repositoryGraph.compilerInput, "repository-graph");
const checkedInRepositoryGraphVerify = json(["verify-projection", "--json", "--target", "linux-musl-x64", checkedInGraphPackageDir]);
assert.equal(checkedInRepositoryGraphVerify.body.ok, true);
assert.equal(checkedInRepositoryGraphVerify.body.writes, false);
const checkedInRepositoryGraphExport = json(["export", "--json", "--target", "linux-musl-x64", checkedInGraphPackageDir]);
assert.equal(checkedInRepositoryGraphExport.body.ok, true);
assert.deepEqual(checkedInRepositoryGraphExport.body.changedPaths, []);
assert.equal(readFileSync(checkedInGraphSourcePath, "utf8"), checkedInGraphSource);
assert.equal(Buffer.compare(readFileSync(checkedInRepositoryGraphStorePath), checkedInRepositoryGraphStoreBytes), 0);
const checkedInRepositoryGraphScript = repositoryGraphVerifyScript(checkedInGraphPackageDir, { target: "linux-musl-x64" });
assert.equal(checkedInRepositoryGraphScript.code, 0);
assert.match(checkedInRepositoryGraphScript.stdout, /repository graph verify-projection ok \(1 store\)/);
const checkedInGraphDriftRoot = join(outDir, "repository-graph-drift-package");
rmSync(checkedInGraphDriftRoot, { recursive: true, force: true });
mkdirSync(checkedInGraphDriftRoot, { recursive: true });
writeFileSync(join(checkedInGraphDriftRoot, "zero.toml"), readFileSync(join(checkedInGraphPackageDir, "zero.toml"), "utf8"));
writeFileSync(join(checkedInGraphDriftRoot, "zero.graph"), checkedInRepositoryGraphStoreBytes);
writeFileSync(join(checkedInGraphDriftRoot, "hello.0"), checkedInGraphSource.replace("hello from zero", "hello from drift"));
const checkedInGraphDriftVerify = json(["verify-projection", "--json", checkedInGraphDriftRoot], { allowFailure: true });
assert.notEqual(checkedInGraphDriftVerify.code, 0);
assert.equal(checkedInGraphDriftVerify.body.ok, false);
assert.equal(checkedInGraphDriftVerify.body.mode, "verify-projection");
assert.equal(checkedInGraphDriftVerify.body.repositoryGraph.compilerInput, "repository-graph");
assert.equal(checkedInGraphDriftVerify.body.diagnostics[0].code, "RGP006");
assert.match(checkedInGraphDriftVerify.body.repairCommands.join("\n"), /zero import/);
assert.match(checkedInGraphDriftVerify.body.repairCommands.join("\n"), /zero export/);
const checkedInGraphDriftCheck = json(["check", "--json", checkedInGraphDriftRoot]);
assert.equal(checkedInGraphDriftCheck.body.ok, true);
assertSourceGraph(checkedInGraphDriftCheck.body, join(checkedInGraphDriftRoot, "zero.graph"), "package:program-graph-fixture@0.1.0", "graph-native-check", false, "clean");
assertProgramGraphCompilerInput(checkedInGraphDriftCheck.body, join(checkedInGraphDriftRoot, "zero.graph"));
assertRepositoryGraphNativeCheck(checkedInGraphDriftCheck.body, "clean");
assert.match(zero(["view", join(checkedInGraphDriftRoot, "zero.graph")]).stdout, /hello from drift/);
const checkedInGraphDriftVerifyAfterRefresh = json(["verify-projection", "--json", checkedInGraphDriftRoot]);
assert.equal(checkedInGraphDriftVerifyAfterRefresh.body.ok, true);
const graphView = zero(["view", graphDumpPath]).stdout;
assert.equal(zero(["view", graphDumpPath]).stdout, graphView);
assert.equal(zero(["diff", graphDumpPath]).stdout, graphView);
assert.match(graphView, /^pub fn main\(world: World\) -> Void raises \{\n/);
assert.match(graphView, /check world\.out\.write\("hello from zero\\n"\)/);
const graphViewJson = json(["view", "--json", graphDumpPath]).body;
assert.equal(graphViewJson.ok, true);
assert.equal(graphViewJson.canonicalSource, false);
assert.equal(graphViewJson.moduleIdentity, "module:hello");
assert.equal(graphViewJson.graphHash, graphDumpJson.graphHash);
assert.equal(graphViewJson.view, graphView);
assert.equal(zero(["view", "--out", graphViewPath, graphDumpPath]).stdout, "");
assert.equal(readFileSync(graphViewPath, "utf8"), graphView);
const graphViewOutJson = json(["view", "--json", "--out", graphViewPath, graphDumpPath]).body;
assert.equal(graphViewOutJson.ok, true);
assert.equal(graphViewOutJson.saved.path, graphViewPath);
assert.equal(graphViewOutJson.view, null);
assert.equal(readFileSync(graphViewPath, "utf8"), graphView);
const graphViewWrongOutJson = json(["view", "--json", "--out", graphViewWrongOutPath, graphDumpPath], { allowFailure: true });
assert.notEqual(graphViewWrongOutJson.code, 0);
assert.equal(graphViewWrongOutJson.body.diagnostics[0].message, "graph view output must use .0 extension");
assert.equal(graphViewWrongOutJson.body.diagnostics[0].expected, "zero view --out <file.0> [graph-input]");
assert.equal(existsSync(graphViewWrongOutPath), false);
writeFileSync(graphViewParentFilePath, "");
const graphViewParentFileJson = json(["view", "--json", "--out", graphViewParentFileOutPath, graphDumpPath], { allowFailure: true });
assert.notEqual(graphViewParentFileJson.code, 0);
assert.equal(graphViewParentFileJson.body.diagnostics[0].path, graphViewParentFileOutPath);
assert.equal(graphViewParentFileJson.body.diagnostics[0].message, `path component is not a directory: '${graphViewParentFilePath}'`);
assert.equal(existsSync(graphViewParentFileOutPath), false);
const graphDiffOutJson = json(["diff", "--json", "--out", graphViewPath, graphDumpPath], { allowFailure: true });
assert.notEqual(graphDiffOutJson.code, 0);
assert.equal(graphDiffOutJson.body.diagnostics[0].message, "diff textconv output does not support --out");
assert.equal(graphDiffOutJson.body.diagnostics[0].expected, "zero diff [--fn <name>] [graph-input]");
assert.equal(zero(["check", graphDumpPath]).stdout, "ok\n");
const graphCheckJson = json(["check", "--json", graphDumpPath]).body;
assert.equal(graphCheckJson.ok, true);
assert.equal(graphCheckJson.canonicalSource, false);
assert.equal(graphCheckJson.moduleIdentity, "module:hello");
assert.equal(graphCheckJson.graphHash, graphDumpJson.graphHash);
assert.equal(graphCheckJson.check.ok, true);
assert.equal(graphCheckJson.check.phase, "typecheck");
assert.match(graphCheckJson.check.target, /^(darwin|linux|win32)-/);
assert.equal(graphCheckJson.check.lowering, "graph-native-check");
assert.equal(graphCheckJson.check.sourcePath, null);
assert.equal(graphCheckJson.targetReadiness.ok, true);
assert.equal(graphCheckJson.targetReadiness.languageOk, true);
assert.equal(graphCheckJson.targetReadiness.buildable, true);
assert.equal(graphCheckJson.graphCompiler.graphNativeCheckerUsed, true);
assert.equal(graphCheckJson.graphCompiler.graphHirToMirUsed, true);
assert.equal(graphCheckJson.graphCompiler.input, "program-graph-artifact");
assert.equal(graphCheckJson.safetyFacts.schemaVersion, 1);
assert.equal(graphCheckJson.safetyFacts.bounds.runtimeTraps, true);
assert.equal(graphCheckJson.safetyFacts.bounds.optimizerElision, false);
assert.equal(graphCheckJson.safetyFacts.overflow.runtimeArithmetic, "unchecked-machine-wrap");
assert.equal(graphCheckJson.safetyFacts.overflow.unchecked, true);
assert.equal(graphCheckJson.safetyFacts.initialization.maybePayloadReads, "guard-checked");
assert.equal(graphCheckJson.safetyFacts.mir.invalidMemoryContractsBlockEmission, true);
assert.deepEqual(graphCheckJson.diagnostics, []);
assert.equal(graphCheckJson.saved, null);
assert.equal(graphCheckJson.view, null);
const graphDirectImportCheckJson = json(["check", "--json", "examples/direct-package-arrays"]).body;
assert.equal(graphDirectImportCheckJson.ok, true);
assert.equal(graphDirectImportCheckJson.graph.canonicalSource, false);
assert.equal(graphDirectImportCheckJson.graph.lowering, "graph-native-check");
assert.equal(graphDirectImportCheckJson.graphCompiler.input, "repository-graph-store");
assert.equal(graphDirectImportCheckJson.targetReadiness.ok, true);
assert.equal(graphDirectImportCheckJson.safetyFacts.initialization.locals, "initializer-required");
assert.deepEqual(graphDirectImportCheckJson.diagnostics, []);
const graphDirectImportView = zero(["view", "examples/direct-package-arrays"]).stdout;
assert.match(graphDirectImportView, /fn package_sum\(\) -> i32/);
assert.match(graphDirectImportView, /export c fn main\(\) -> i32/);
const graphDirectStdCheckJson = json(["check", "--json", "examples/std-str.graph"]).body;
assert.equal(graphDirectStdCheckJson.ok, true);
assert.equal(graphDirectStdCheckJson.artifact, "examples/std-str.graph");
assert.equal(graphDirectStdCheckJson.canonicalSource, false);
assert.equal(graphDirectStdCheckJson.check.lowering, "graph-native-check");
assert.equal(graphDirectStdCheckJson.graphCompiler.input, "program-graph-artifact");
assert.equal(graphDirectStdCheckJson.targetReadiness.ok, true);
assert.deepEqual(graphDirectStdCheckJson.diagnostics, []);
const graphCheckOutJson = json(["check", "--json", "--out", graphCheckViewPath, graphDumpPath], { allowFailure: true });
assert.notEqual(graphCheckOutJson.code, 0);
assert.equal(graphCheckOutJson.body.diagnostics[0].message, "zero check does not support --out");
assert.equal(graphCheckOutJson.body.diagnostics[0].expected, "zero view --out <file.0> [graph-input]");
const graphSizeJson = json(["size", "--json", "--target", "linux-musl-x64", graphDumpPath]).body;
assert.equal(graphSizeJson.schemaVersion, 1);
assert.equal(graphSizeJson.sourceFile, graphDumpPath);
assert.equal(graphSizeJson.graph.artifact, graphDumpPath);
assert.equal(graphSizeJson.graph.canonicalSource, false);
assert.equal(graphSizeJson.graph.moduleIdentity, "module:hello");
assert.equal(graphSizeJson.graph.graphHash, graphInspectJson.programGraph.graphHash);
assert.equal(graphSizeJson.graph.graphHash, graphDumpJson.graphHash);
assert.equal(graphSizeJson.graph.lowering, "mapped-final-mir");
assert.equal(graphSizeJson.target, "linux-musl-x64");
assert.equal(graphSizeJson.generatedCBytes, 0);
assert.equal(graphSizeJson.cBridgeFallback, false);
assert.equal(graphSizeJson.sizeBreakdown.target, "linux-musl-x64");
assert.equal(graphSizeJson.objectBackend.objectEmission.path, "direct-elf64-object");
assert.equal(graphSizeJson.artifactPath, null);
assertProgramGraphCompilerInput(graphSizeJson, graphDumpPath);
const graphSizeMirCache = graphSizeJson.compilerCaches.find((cache) => cache.name === "mappedFinalMir");
assert.equal(graphSizeMirCache.codegenImmediate, graphSizeMirCache.hit === true);
assert.equal(graphSizeMirCache.programReconstructed, false);
assert.equal(graphSizeJson.incrementalInvalidation.changedInputs.graphArtifact, graphDumpPath);
assert.equal(graphSizeJson.incrementalInvalidation.interfaceFingerprints.sourceKind, "program-graph");
assert.equal(graphSizeJson.incrementalInvalidation.interfaceFingerprints.graphHash, graphSizeJson.graph.graphHash);
const graphSizeHelloInterface = graphSizeJson.incrementalInvalidation.interfaceFingerprints.modules.find((item) => item.name === "hello");
assert(graphSizeHelloInterface);
assert.equal(graphSizeHelloInterface.publicSymbolCount, 1);
assert.deepEqual(graphSizeHelloInterface.publicSymbols, [{ name: "main", kind: "function" }]);
const graphSizeOutJson = json(["size", "--json", "--target", "linux-musl-x64", "--out", graphSizePath, graphDumpPath]).body;
assert.equal(graphSizeOutJson.graph.graphHash, graphSizeJson.graph.graphHash);
assert.equal(graphSizeOutJson.artifactPath, graphSizePath);
assert.equal(graphSizeOutJson.artifactBytes, statSync(graphSizePath).size);
assert.match(readFileSync(graphSizePath, "utf8"), /"kind": "zero-size-metadata"/);
const graphBuildJson = json(["build", "--json", "--target", "linux-musl-x64", "--out", graphBuildPath, graphDumpPath]).body;
assert.equal(graphBuildJson.schemaVersion, 1);
assert.equal(graphBuildJson.sourceFile, graphDumpPath);
assert.equal(graphBuildJson.graph.artifact, graphDumpPath);
assert.equal(graphBuildJson.graph.canonicalSource, false);
assert.equal(graphBuildJson.graph.moduleIdentity, "module:hello");
assert.equal(graphBuildJson.graph.graphHash, graphDumpJson.graphHash);
assert.equal(graphBuildJson.graph.lowering, "mapped-final-mir");
assert.equal(graphBuildJson.emit, "exe");
assert.equal(graphBuildJson.target, "linux-musl-x64");
assert.equal(graphBuildJson.generatedCBytes, 0);
assert.equal(graphBuildJson.artifactPath, graphBuildPath);
assert.equal(graphBuildJson.artifactBytes, statSync(graphBuildPath).size);
assertProgramGraphCompilerInput(graphBuildJson, graphDumpPath);
const graphBuildMirCache = graphBuildJson.compilerCaches.find((cache) => cache.name === "mappedFinalMir");
assert.equal(graphBuildMirCache.hit, true);
assert.equal(graphBuildMirCache.codegenImmediate, true);
assert.equal(graphBuildMirCache.programReconstructed, false);
const graphObjJson = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "--out", graphObjPath, graphDumpPath]).body;
assert.equal(graphObjJson.sourceFile, graphDumpPath);
assert.equal(graphObjJson.graph.graphHash, graphDumpJson.graphHash);
assert.equal(graphObjJson.graph.lowering, "mapped-final-mir");
assert.equal(graphObjJson.emit, "obj");
assert.equal(graphObjJson.target, "linux-musl-x64");
assert.equal(graphObjJson.generatedCBytes, 0);
assert.equal(graphObjJson.artifactPath, graphObjPath);
assert.equal(graphObjJson.artifactBytes, statSync(graphObjPath).size);
assertProgramGraphCompilerInput(graphObjJson, graphDumpPath);
assert.equal(zero(["run", "--out", graphRunPath, graphDumpPath]).stdout, "hello from zero\n");
assert.equal(existsSync(graphRunPath), true);
assert.equal(zero(["dump", "--out", graphArgsDumpPath, "conformance/native/pass/std-args.0"]).stdout, "");
assert.equal(zero(["run", "--out", graphArgsRunPath, graphArgsDumpPath, "--", "alpha", "beta"]).stdout, "alpha\n");
assert.equal(existsSync(graphArgsRunPath), true);
const graphRunJson = json(["run", "--json", graphDumpPath], { allowFailure: true });
assert.equal(graphRunJson.code, 1);
assert.equal(graphRunJson.body.diagnostics[0].message, "zero run does not support --json");
assert.equal(zero(["dump", "--out", graphTestDumpPath, "conformance/native/pass/test-blocks.0"]).stdout, "");
assert.equal(zero(["test", graphTestDumpPath]).stdout, "1 test(s) ok\n");
const graphTestOutJson = json(["test", "--json", "--out", graphCheckViewPath, graphTestDumpPath], { allowFailure: true });
assert.notEqual(graphTestOutJson.code, 0);
assert.equal(graphTestOutJson.body.diagnostics[0].message, "zero test does not support --out");
assert.equal(graphTestOutJson.body.diagnostics[0].expected, "zero test [--json] [--filter <name>] [--target <target>] [graph-input]");
const graphTestJson = json(["test", "--json", "--filter", "addition", graphTestDumpPath]).body;
assert.equal(graphTestJson.ok, true);
assert.equal(graphTestJson.sourceFile, graphTestDumpPath);
assert.equal(graphTestJson.graph.artifact, graphTestDumpPath);
assert.equal(graphTestJson.graph.canonicalSource, false);
assert.equal(graphTestJson.graph.lowering, "direct-program-graph");
assert.match(graphTestJson.graph.graphHash, /^graph:[0-9a-f]{16}$/);
assert.equal(graphTestJson.testBackend, "direct-program-graph");
assert.equal(graphTestJson.fixtures.snapshotKey, "zero-test-graph-native-v1");
assert.equal(graphTestJson.testDiscovery.mode, "program-graph");
assert.equal(graphTestJson.testDiscovery.filter, "addition");
assert.equal(graphTestJson.selectedTests, 1);
assert.equal(graphTestJson.results[0].status, "passed");
assert.equal(graphTestJson.results[0].location.sourceFile, "test-blocks.0");
assert.equal(graphTestJson.results[0].location.line, 5);
assert.equal(zero(["dump", "--out", graphPackageTestDumpPath, "conformance/packages/test-app"]).stdout, "");
const graphPackageTestJson = json(["test", "--json", graphPackageTestDumpPath]).body;
assert.equal(graphPackageTestJson.ok, true);
assert.equal(graphPackageTestJson.graph.artifact, graphPackageTestDumpPath);
assert.equal(graphPackageTestJson.graph.moduleIdentity, "package:test-app@0.1.0");
assert.equal(graphPackageTestJson.testDiscovery.mode, "package-graph");
assert.equal(graphPackageTestJson.testDiscovery.sourceFileCount, 2);
assert.equal(graphPackageTestJson.selectedTests, 3);
assert(graphPackageTestJson.fixtures.sourceFiles.includes("src/helper.0"));
assert(graphPackageTestJson.fixtures.sourceFiles.includes("src/main.0"));
const graphPackageHelperTest = graphPackageTestJson.results.find((item) => item.name === "package helper double");
assert(graphPackageHelperTest);
assert.equal(graphPackageHelperTest.location.sourceFile, "src/helper.0");
assert.equal(graphPackageHelperTest.location.line, 5);
const graphPackageExpectedFail = graphPackageTestJson.results.find((item) => item.status === "expected-fail");
assert(graphPackageExpectedFail);
assert.equal(graphPackageExpectedFail.location.sourceFile, "src/helper.0");
assert.equal(graphPackageExpectedFail.location.line, 9);
assert.equal(graphPackageExpectedFail.failure.sourceFile, "src/helper.0");
assert.equal(graphPackageExpectedFail.failure.line, 10);
mkdirSync(join(graphManifestPackageDir, "src"), { recursive: true });
mkdirSync(join(graphManifestPackageDir, "artifacts"), { recursive: true });
writeFileSync(join(graphManifestPackageDir, "src", "main.0"), readFileSync("conformance/packages/test-app/src/main.0", "utf8"));
writeFileSync(join(graphManifestPackageDir, "src", "helper.0"), readFileSync("conformance/packages/test-app/src/helper.0", "utf8"));
writeZeroTomlSync(graphManifestPackageDir, {
package: { name: "graph-manifest-package", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "src/main.0", graph: "artifacts/test-app.program-graph" } },
});
assert.equal(zero(["dump", "--out", graphManifestArtifactPath, "conformance/packages/test-app"]).stdout, "");
assert.equal(zero(["import", graphManifestPackageDir]).stdout, `repository graph import ok\nwrote: ${graphManifestStorePath}\n`);
assert.equal(zero(["validate", graphManifestPackageDir]).stdout, "program graph ok\n");
const graphManifestCheckJson = json(["check", "--json", graphManifestPackageDir]).body;
assert.equal(graphManifestCheckJson.ok, true);
assert.equal(graphManifestCheckJson.graph.artifact, graphManifestStorePath);
assert.equal(graphManifestCheckJson.graph.moduleIdentity, "package:graph-manifest-package@0.1.0");
assert.equal(graphManifestCheckJson.graph.lowering, "graph-native-check");
const graphManifestSizeJson = json(["size", "--json", "--target", "linux-musl-x64", graphManifestPackageDir]).body;
assertSourceGraph(graphManifestSizeJson, graphManifestStorePath, "package:graph-manifest-package@0.1.0", "mapped-final-mir", false, "clean");
assertProgramGraphCompilerInput(graphManifestSizeJson, graphManifestStorePath);
assert.equal(graphManifestSizeJson.sourceFile, graphManifestStorePath);
const graphManifestBuildJson = json(["build", "--json", "--target", "linux-musl-x64", "--out", graphManifestBuildPath, graphManifestPackageDir]).body;
assertSourceGraph(graphManifestBuildJson, graphManifestStorePath, "package:graph-manifest-package@0.1.0", "mapped-final-mir", false, "clean");
assertProgramGraphCompilerInput(graphManifestBuildJson, graphManifestStorePath);
assert.equal(graphManifestBuildJson.sourceFile, graphManifestStorePath);
assert.equal(zero(["run", "--out", graphManifestRunPath, graphManifestPackageDir]).stdout, "package tests\n");
const graphManifestTestJson = json(["test", "--json", graphManifestPackageDir]).body;
assert.equal(graphManifestTestJson.ok, true);
assertSourceGraph(graphManifestTestJson, graphManifestStorePath, "package:graph-manifest-package@0.1.0", "direct-program-graph", false, "clean");
assert.equal(graphManifestTestJson.testDiscovery.mode, "package-graph");
const graphManifestRoundtripJson = json(["roundtrip", "--json", graphManifestPackageDir]).body;
assert.equal(graphManifestRoundtripJson.ok, true);
assert.equal(graphManifestRoundtripJson.artifact, graphManifestStorePath);
assert.equal(graphManifestRoundtripJson.semanticStable, true);
assert.equal(graphManifestRoundtripJson.lowering, "direct-program-graph");
assert.equal(graphManifestRoundtripJson.moduleIdentity, "package:graph-manifest-package@0.1.0");
assert.equal(graphManifestRoundtripJson.roundtripModuleIdentity, "package:graph-manifest-package@0.1.0");
assert.equal(graphManifestRoundtripJson.view, null);
const directGraphManifestCheckJson = json(["check", "--json", graphManifestPackageDir]).body;
assert.equal(directGraphManifestCheckJson.ok, true);
assertSourceGraph(directGraphManifestCheckJson, graphManifestStorePath, "package:graph-manifest-package@0.1.0", "graph-native-check", false, "clean");
assert.equal(directGraphManifestCheckJson.sourceFile, graphManifestStorePath);
assert.equal(directGraphManifestCheckJson.package.name, "graph-manifest-package");
assert.equal(directGraphManifestCheckJson.package.manifestPath, join(graphManifestPackageDir, "zero.toml"));
assert.notEqual(directGraphManifestCheckJson.package.manifestHash, "0000000000000000");
assertProgramGraphCompilerInput(directGraphManifestCheckJson, graphManifestStorePath);
assert.equal(directGraphManifestCheckJson.incrementalInvalidation.changedInputs.manifestPath, join(graphManifestPackageDir, "zero.toml"));
const directGraphManifestSizeJson = json(["size", "--json", "--target", "linux-musl-x64", graphManifestPackageDir]).body;
assertSourceGraph(directGraphManifestSizeJson, graphManifestStorePath, "package:graph-manifest-package@0.1.0", "mapped-final-mir", false, "clean");
assertProgramGraphCompilerInput(directGraphManifestSizeJson, graphManifestStorePath);
assert.equal(directGraphManifestSizeJson.sourceFile, graphManifestStorePath);
const directGraphManifestMemJson = json(["mem", "--json", graphManifestPackageDir]).body;
assertSourceGraph(directGraphManifestMemJson, graphManifestStorePath, "package:graph-manifest-package@0.1.0", "mapped-final-mir", false, "clean");
assertProgramGraphCompilerInput(directGraphManifestMemJson, graphManifestStorePath);
assert.equal(directGraphManifestMemJson.sourceFile, graphManifestStorePath);
const directGraphManifestBuildJson = json(["build", "--json", "--target", "linux-musl-x64", "--out", directGraphManifestBuildPath, graphManifestPackageDir]).body;
assertSourceGraph(directGraphManifestBuildJson, graphManifestStorePath, "package:graph-manifest-package@0.1.0", "mapped-final-mir", false, "clean");
assertProgramGraphCompilerInput(directGraphManifestBuildJson, graphManifestStorePath);
assert.equal(directGraphManifestBuildJson.sourceFile, graphManifestStorePath);
assert.equal(zero(["run", "--out", directGraphManifestRunPath, graphManifestPackageDir]).stdout, "package tests\n");
const directGraphManifestTestJson = json(["test", "--json", graphManifestPackageDir]).body;
assert.equal(directGraphManifestTestJson.ok, true);
assertSourceGraph(directGraphManifestTestJson, graphManifestStorePath, "package:graph-manifest-package@0.1.0", "direct-program-graph", false, "clean");
assert.equal(directGraphManifestTestJson.testDiscovery.mode, "package-graph");
const sourcePackageCheckJson = json(["check", "--json", "conformance/packages/test-app"]).body;
assert.equal(sourcePackageCheckJson.ok, true);
assertSourceGraph(sourcePackageCheckJson, "conformance/packages/test-app/zero.graph", "package:test-app@0.1.0", "graph-native-check", false);
mkdirSync(join(directGraphTargetGatePackageDir, "src"), { recursive: true });
mkdirSync(join(directGraphTargetGatePackageDir, "artifacts"), { recursive: true });
mkdirSync(join(directGraphTargetGateDepDir, "src"), { recursive: true });
writeFileSync(join(directGraphTargetGatePackageDir, "src", "main.0"), "pub fn main(world: World) -> Void raises {\n check world.out.write(\"target gate\\n\")\n}\n");
writeFileSync(join(directGraphTargetGateDepDir, "src", "main.0"), "pub fn main(world: World) -> Void raises {\n check world.out.write(\"webbits\\n\")\n}\n");
writeZeroTomlSync(directGraphTargetGateDepDir, {
package: { name: "target-webbits", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "src/main.0" } },
});
writeZeroTomlSync(directGraphTargetGatePackageDir, {
package: { name: "direct-graph-target-gate", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "src/main.0", graph: "artifacts/app.program-graph" } },
dependencies: {
"target-webbits": {
path: "../target-webbits",
version: "0.1.0",
targets: ["win32-x64.exe"],
},
},
});
assert.equal(zero(["import", directGraphTargetGateDepDir]).stdout, `repository graph import ok\nwrote: ${join(directGraphTargetGateDepDir, "zero.graph")}\n`);
assert.equal(zero(["import", directGraphTargetGatePackageDir]).stdout, `repository graph import ok\nwrote: ${join(directGraphTargetGatePackageDir, "zero.graph")}\n`);
assert.equal(zero(["dump", "--out", directGraphTargetGateArtifactPath, directGraphTargetGatePackageDir]).stdout, "");
const directGraphTargetGateJson = json(["check", "--json", "--target", "linux-musl-x64", directGraphTargetGatePackageDir], { allowFailure: true });
assert.equal(directGraphTargetGateJson.code, 1);
assert.equal(directGraphTargetGateJson.body.diagnostics[0].code, "PKG004");
assert.equal(directGraphTargetGateJson.body.diagnostics[0].message, "package dependency is not compatible with target");
mkdirSync(join(directGraphHostLeakPackageDir, "src"), { recursive: true });
mkdirSync(join(directGraphHostLeakPackageDir, "artifacts"), { recursive: true });
writeFileSync(join(directGraphHostLeakPackageDir, "src", "main.0"), "pub fn main(world: World) -> Void raises {\n check world.out.write(\"host leak\\n\")\n}\n");
writeZeroTomlSync(directGraphHostLeakPackageDir, {
package: { name: "direct-graph-host-leak", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "src/main.0", graph: "artifacts/app.program-graph" } },
c: {
libs: {
hostonly: {
headers: ["hostonly.h"],
include: ["/usr/include"],
lib: ["/usr/lib"],
link: ["hostonly"],
pkg_config: "hostonly",
},
},
},
});
assert.equal(zero(["import", directGraphHostLeakPackageDir]).stdout, `repository graph import ok\nwrote: ${join(directGraphHostLeakPackageDir, "zero.graph")}\n`);
assert.equal(zero(["dump", "--out", directGraphHostLeakArtifactPath, directGraphHostLeakPackageDir]).stdout, "");
const directGraphHostLeakJson = json(["build", "--json", "--target", "linux-musl-x64", "--out", directGraphHostLeakBuildPath, directGraphHostLeakPackageDir], { allowFailure: true });
assert.equal(directGraphHostLeakJson.code, 1);
assert.equal(directGraphHostLeakJson.body.diagnostics[0].code, "CIMP003");
assert.equal(directGraphHostLeakJson.body.diagnostics[0].message, "foreign target C dependency would use host discovery");
const graphPackageSourceCheckJson = json(["check", "--json", "conformance/packages/test-app"]).body;
assert.equal(graphPackageSourceCheckJson.ok, true);
assert.equal(graphPackageSourceCheckJson.graph.moduleIdentity, "package:test-app@0.1.0");
assert.equal(graphPackageSourceCheckJson.graph.lowering, "graph-native-check");
writeFileSync(graphSizeNoisePatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`insertEdge from="${graphHelloLiteralNode.id}" to="${graphHelloLiteralNode.typeId}" edge="sizeProbeType" target="type" order="0"`,
"",
].join("\n"));
const graphSizeNoisePatchJson = json(["patch", "--json", "--out", graphSizeNoisePath, graphDumpPath, graphSizeNoisePatchPath]).body;
assert.equal(graphSizeNoisePatchJson.ok, true);
assert.equal(zero(["check", graphSizeNoisePath]).stdout, "ok\n");
const graphSizeNoiseJson = json(["size", "--json", "--target", "linux-musl-x64", graphSizeNoisePath]).body;
const graphSizeNoiseInterface = graphSizeNoiseJson.incrementalInvalidation.interfaceFingerprints.modules.find((item) => item.name === "hello");
assert(graphSizeNoiseInterface);
assert.deepEqual(graphSizeNoiseInterface.publicSymbols, [{ name: "main", kind: "function" }]);
writeFileSync(graphPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphHelloLiteralNode.id}" field="value" expect="hello from zero\\n" value="hello patched\\n"`,
"",
].join("\n"));
assertPatchOkOutput(zero(["patch", "--out", graphPatchedPath, graphDumpPath, graphPatchPath]).stdout, graphPatchedPath);
const graphPatchedStdout = zero(["patch", graphDumpPath, graphPatchPath]).stdout;
assert.match(graphPatchedStdout, /^zero-graph v1\n/);
assert.match(graphPatchedStdout, /value:"hello patched\\n"/);
assert.equal(readFileSync(graphPatchedPath, "utf8"), graphPatchedStdout);
const graphPatchJson = json(["patch", "--json", "--out", graphPatchedPath, graphDumpPath, graphPatchPath]).body;
assert.equal(graphPatchJson.ok, true);
assert.equal(graphPatchJson.canonicalSource, false);
assert.equal(graphPatchJson.patch, graphPatchPath);
assert.equal(graphPatchJson.originalGraphHash, graphDumpJson.graphHash);
assert.match(graphPatchJson.patchedGraphHash, /^graph:[0-9a-f]{16}$/);
assert.notEqual(graphPatchJson.patchedGraphHash, graphDumpJson.graphHash);
assert.equal(graphPatchJson.operationCount, 1);
assert.equal(graphPatchJson.operations[0].ok, true);
assert.equal(graphPatchJson.operations[0].node, graphHelloLiteralNode.id);
assert.equal(graphPatchJson.operations[0].field, "value");
assert.equal(graphPatchJson.operations[0].actual, "hello from zero\n");
assert.equal(graphPatchJson.operations[0].value, "hello patched\n");
assert.equal(graphPatchJson.diagnostic, null);
assert.equal(graphPatchJson.saved.path, graphPatchedPath);
mkdirSync(graphPatchDirectoryPath, { recursive: true });
const graphPatchDirectoryJson = json(["patch", "--json", "--out", graphPatchDirectoryOutPath, graphDumpPath, graphPatchDirectoryPath], { allowFailure: true });
assert.notEqual(graphPatchDirectoryJson.code, 0);
assert.equal(graphPatchDirectoryJson.body.diagnostics[0].path, graphPatchDirectoryPath);
assert.match(graphPatchDirectoryJson.body.diagnostics[0].message, /^failed to read '.+hello\.program-graph\.patch-directory': /);
assert.equal(existsSync(graphPatchDirectoryOutPath), false);
assert.equal(zero(["validate", graphPatchedPath]).stdout, "program graph ok\n");
assert.match(zero(["view", graphPatchedPath]).stdout, /check world\.out\.write\("hello patched\\n"\)/);
assert.equal(zero(["check", graphPatchedPath]).stdout, "ok\n");
const graphSourcePatchPath = join(outDir, "hello.graph-sidecar.0");
writeProjectionFile(graphSourcePatchPath, graphView);
const graphSourcePatchSidecar = importProjectionSidecar(graphSourcePatchPath);
const graphSourcePatchDumpJson = json(["dump", "--json", graphSourcePatchPath]).body;
assert.equal(graphSourcePatchDumpJson.canonicalSource, false);
const graphSourceLiteralNode = graphSourcePatchDumpJson.nodes.find((node) => node.kind === "Literal" && node.type === "String" && node.value === "hello from zero\n");
assert(graphSourceLiteralNode);
const graphSourcePatchJson = json([
"patch",
"--json",
"--out",
graphSourcePatchSidecar,
graphSourcePatchSidecar,
"--expect-graph-hash",
graphSourcePatchDumpJson.graphHash,
"--op",
`set node="${graphSourceLiteralNode.id}" field="value" expect="hello from zero\\n" value="hello sidecar graph\\n"`,
]).body;
assert.equal(graphSourcePatchJson.ok, true);
assert.equal(graphSourcePatchJson.canonicalSource, false);
assert.equal(graphSourcePatchJson.saved.path, graphSourcePatchSidecar);
zero(["view", "--out", graphSourcePatchPath, graphSourcePatchSidecar]);
assert.match(readFileSync(graphSourcePatchPath, "utf8"), /hello sidecar graph\\n/);
assertProjectionCheckOk(graphSourcePatchPath);
const graphSourceProjectionPatchRejected = json(["patch", "--json", graphSourcePatchPath, "--op", "addMain"], { allowFailure: true });
assert.notEqual(graphSourceProjectionPatchRejected.code, 0);
assert.equal(graphSourceProjectionPatchRejected.body.diagnostics[0].code, "BLD002");
assert.equal(graphSourceProjectionPatchRejected.body.diagnostics[0].message, "graph patch requires graph input");
assert.equal(graphSourceProjectionPatchRejected.body.diagnostics[0].expected, "package zero.graph store, .graph store, or ProgramGraph artifact");
const graphSourcePackageDir = join(outDir, "graph-source-package");
const graphSourcePackageMain = join(graphSourcePackageDir, "src", "main.0");
const graphSourcePackageHelper = join(graphSourcePackageDir, "src", "helper.0");
rmSync(graphSourcePackageDir, { recursive: true, force: true });
mkdirSync(join(graphSourcePackageDir, "src"), { recursive: true });
writeZeroTomlSync(graphSourcePackageDir, {
package: { name: "graph-source-package", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "src/main.0" } },
});
writeProjectionFile(
graphSourcePackageHelper,
"pub fn value() -> i32 {\n" +
" return 41\n" +
"}\n",
);
writeProjectionFile(
graphSourcePackageMain,
"use helper\n\n" +
"pub fn main() -> i32 {\n" +
" return value() + 1\n" +
"}\n",
);
assert.match(zero(["import", graphSourcePackageDir]).stdout, /^repository graph import ok\n/);
const graphSourcePackageDumpJson = json(["dump", "--json", graphSourcePackageMain]).body;
const graphSourcePackageLiteralNode = graphSourcePackageDumpJson.nodes.find(
(node) => node.kind === "Literal" && node.value === "1",
);
assert(graphSourcePackageLiteralNode);
const graphSourcePackagePatchJson = json([
"patch",
"--json",
graphSourcePackageDir,
"--expect-graph-hash",
graphSourcePackageDumpJson.graphHash,
"--op",
`set node="${graphSourcePackageLiteralNode.id}" field="value" expect="1" value="2"`,
]).body;
assert.equal(graphSourcePackagePatchJson.ok, true);
assert.equal(graphSourcePackagePatchJson.saved.path, join(graphSourcePackageDir, "zero.graph"));
assert.match(zero(["export", graphSourcePackageDir]).stdout, /^repository graph export ok\n/);
const graphSourcePackageMainText = readFileSync(graphSourcePackageMain, "utf8");
assert.match(graphSourcePackageMainText, /^use helper\n\n/);
assert.match(graphSourcePackageMainText, /return value\(\) \+ 2/);
assert.doesNotMatch(graphSourcePackageMainText, /pub fn value/);
assert.equal(readFileSync(graphSourcePackageHelper, "utf8"), "pub fn value() -> i32 {\n return 41\n}\n");
assert.equal(zero(["check", graphSourcePackageDir]).stdout, "ok\n");
const graphUserDerefSourcePath = join(outDir, "deref-member.0");
const graphUserDerefViewPath = join(outDir, "deref-member.view.0");
const graphPrefixDerefSourcePath = join(outDir, "prefix-deref-member.0");
const graphNestedCastSourcePath = join(outDir, "nested-cast.0");
const graphNestedCastViewPath = join(outDir, "nested-cast.view.0");
const graphPublicExportSourcePath = join(outDir, "public-export-c.0");
const graphPublicExportViewPath = join(outDir, "public-export-c.view.0");
const graphPublicInterfaceSourcePath = join(outDir, "public-interface-method.0");
const graphPublicInterfaceViewPath = join(outDir, "public-interface-method.view.0");
const graphPublicSumsSourcePath = join(outDir, "public-sums.0");
const graphExternFieldsSourcePath = join(outDir, "extern-fields.0");
const graphCommentsSourcePath = join(outDir, "comments.0");
const graphDerefMemberSource = [
"type Point {",
" x: i32,",
"}",
"",
"type Wrapper {",
" x: Point,",
"}",
"",
"fn deref(value: Wrapper) -> Point {",
" return value.x",
"}",
"",
"pub fn main() -> i32 {",
" let wrapped: Wrapper = Wrapper { x: Point { x: 7 } }",
" return deref(wrapped).x",
"}",
"",
].join("\n");
writeProjectionFile(graphUserDerefSourcePath, graphDerefMemberSource);
assertProjectionCheckOk(graphUserDerefSourcePath);
const graphUserDerefView = zero(["view", graphUserDerefSourcePath]).stdout;
assert.match(graphUserDerefView, /return deref\(wrapped\)\.x/);
assert.doesNotMatch(graphUserDerefView, /return \*wrapped\.x/);
assert.equal(zero(["view", "--out", graphUserDerefViewPath, graphUserDerefSourcePath]).stdout, "");
assertProjectionCheckOk(graphUserDerefViewPath);
writeProjectionFile(graphPrefixDerefSourcePath, graphDerefMemberSource.replace("return deref(wrapped).x", "return (*wrapped).x"));
assertProjectionCheckOk(graphPrefixDerefSourcePath);
const graphPrefixDerefView = zero(["view", graphPrefixDerefSourcePath]).stdout;
assert.match(graphPrefixDerefView, /return \(\*wrapped\)\.x/);
assert.equal(zero(["check", projectionSidecarGraphPath(graphPrefixDerefSourcePath)]).stdout, "ok\n");
writeProjectionFile(graphNestedCastSourcePath, [
"pub fn main() -> u32 {",
" let x: i32 = 1",
" return (x as u16) as u32",
"}",
"",
].join("\n"));
assertProjectionCheckOk(graphNestedCastSourcePath);
const graphNestedCastView = zero(["view", graphNestedCastSourcePath]).stdout;
assert.match(graphNestedCastView, /return \(x as u16\) as u32/);
assert.equal(zero(["view", "--out", graphNestedCastViewPath, graphNestedCastSourcePath]).stdout, "");
assertProjectionCheckOk(graphNestedCastViewPath);
assert.equal(json(["roundtrip", "--json", graphNestedCastSourcePath]).body.view, null);
writeProjectionFile(graphPublicExportSourcePath, [
"pub export c fn main() -> i32 {",
" return 1",
"}",
"",
].join("\n"));
assertProjectionCheckOk(graphPublicExportSourcePath);
assert.equal(zero(["view", "--out", graphPublicExportViewPath, graphPublicExportSourcePath]).stdout, "");
assertProjectionCheckOk(graphPublicExportViewPath);
assert.equal(json(["roundtrip", "--json", graphPublicExportSourcePath]).body.view, null);
writeProjectionFile(graphPublicInterfaceSourcePath, [
"interface Reader {",
" pub fn read() -> i32",
"}",
"",
"pub fn main() -> i32 {",
" return 1",
"}",
"",
].join("\n"));
assertProjectionCheckOk(graphPublicInterfaceSourcePath);
assert.equal(zero(["view", "--out", graphPublicInterfaceViewPath, graphPublicInterfaceSourcePath]).stdout, "");
assertProjectionCheckOk(graphPublicInterfaceViewPath);
assert.equal(json(["roundtrip", "--json", graphPublicInterfaceSourcePath]).body.view, null);
writeProjectionFile(graphPublicSumsSourcePath, [
"pub enum Mode: u8 {",
" ready,",
"}",
"",
"pub choice Result {",
" ok: i32,",
" err: String,",
"}",
"",
"pub fn main() -> i32 {",
" return 1",
"}",
"",
].join("\n"));
const graphPublicSumsSidecar = importProjectionSidecar(graphPublicSumsSourcePath);
const graphPublicSumsDumpJson = json(["dump", "--json", graphPublicSumsSourcePath]).body;
const graphPublicEnumNode = graphPublicSumsDumpJson.nodes.find((node) => node.kind === "Enum" && node.name === "Mode");
const graphPublicChoiceNode = graphPublicSumsDumpJson.nodes.find((node) => node.kind === "Choice" && node.name === "Result");
const graphPublicLiteralNode = graphPublicSumsDumpJson.nodes.find((node) => node.kind === "Literal" && node.value === "1");
assert.equal(graphPublicEnumNode?.public, true);
assert.equal(graphPublicChoiceNode?.public, true);
assert(graphPublicLiteralNode);
const graphPublicSumsPatchJson = json([
"patch",
"--json",
"--out",
graphPublicSumsSidecar,
graphPublicSumsSidecar,
"--expect-graph-hash",
graphPublicSumsDumpJson.graphHash,
"--op",
`set node="${graphPublicLiteralNode.id}" field="value" expect="1" value="2"`,
]).body;
assert.equal(graphPublicSumsPatchJson.ok, true);
assert.equal(graphPublicSumsPatchJson.canonicalSource, false);
assert.equal(graphPublicSumsPatchJson.saved.path, graphPublicSumsSidecar);
zero(["view", "--out", graphPublicSumsSourcePath, graphPublicSumsSidecar]);
const graphPublicSumsText = readFileSync(graphPublicSumsSourcePath, "utf8");
assert.match(graphPublicSumsText, /^pub enum Mode/m);
assert.match(graphPublicSumsText, /^pub choice Result/m);
assert.match(graphPublicSumsText, /return 2/);
assertProjectionCheckOk(graphPublicSumsSourcePath);
writeProjectionFile(graphExternFieldsSourcePath, [
"extern type CPoint {",
" x: i32,",
" y: i32,",
"}",
"",
"pub fn main() -> i32 {",
" return 1",
"}",
"",
].join("\n"));
const graphExternFieldsSidecar = importProjectionSidecar(graphExternFieldsSourcePath);
const graphExternFieldsDumpJson = json(["dump", "--json", graphExternFieldsSourcePath]).body;
const graphExternFieldsLiteralNode = graphExternFieldsDumpJson.nodes.find((node) => node.kind === "Literal" && node.value === "1");
assert(graphExternFieldsLiteralNode);
const graphExternFieldsPatchJson = json([
"patch",
"--json",
"--out",
graphExternFieldsSidecar,
graphExternFieldsSidecar,
"--expect-graph-hash",
graphExternFieldsDumpJson.graphHash,
"--op",
`set node="${graphExternFieldsLiteralNode.id}" field="value" expect="1" value="2"`,
]).body;
assert.equal(graphExternFieldsPatchJson.ok, true);
assert.equal(graphExternFieldsPatchJson.canonicalSource, false);
assert.equal(graphExternFieldsPatchJson.saved.path, graphExternFieldsSidecar);
zero(["view", "--out", graphExternFieldsSourcePath, graphExternFieldsSidecar]);
const graphExternFieldsText = readFileSync(graphExternFieldsSourcePath, "utf8");
assert.match(graphExternFieldsText, /^extern type CPoint \{/m);
assert.match(graphExternFieldsText, /^\s+x: i32,/m);
assert.match(graphExternFieldsText, /^\s+y: i32,/m);
assert.match(graphExternFieldsText, /return 2/);
assertProjectionCheckOk(graphExternFieldsSourcePath);
writeProjectionFile(graphCommentsSourcePath, [
"// module comment",
"",
"pub fn main() -> i32 {",
" // keep this comment",
" return 1",
"}",
"",
].join("\n"));
const graphCommentsOriginal = readFileSync(graphCommentsSourcePath, "utf8");
const graphCommentsPatchJson = json([
"patch",
"--json",
graphCommentsSourcePath,
"--op",
"addMain",
], { allowFailure: true });
assert.notEqual(graphCommentsPatchJson.code, 0);
assert.equal(graphCommentsPatchJson.body.diagnostics[0].code, "BLD002");
assert.equal(graphCommentsPatchJson.body.diagnostics[0].message, "graph patch requires graph input");
assert.equal(readFileSync(graphCommentsSourcePath, "utf8"), graphCommentsOriginal);
const graphInlinePatchJson = json([
"patch",
"--json",
"--out",
graphInlinePatchedPath,
graphDumpPath,
"--expect-graph-hash",
graphDumpJson.graphHash,
"--op",
`set node="${graphHelloLiteralNode.id}" field="value" expect="hello from zero\\n" value="hello inline\\n"`,
]).body;
assert.equal(graphInlinePatchJson.ok, true);
assert.equal(graphInlinePatchJson.patch, "<inline>");
assert.equal(graphInlinePatchJson.originalGraphHash, graphDumpJson.graphHash);
assert.equal(graphInlinePatchJson.operationCount, 1);
assert.equal(graphInlinePatchJson.operations[0].node, graphHelloLiteralNode.id);
assert.equal(graphInlinePatchJson.operations[0].value, "hello inline\n");
assert.equal(graphInlinePatchJson.saved.path, graphInlinePatchedPath);
assert.match(zero(["view", graphInlinePatchedPath]).stdout, /check world\.out\.write\("hello inline\\n"\)/);
writeFileSync(graphPatchInsertPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`insert node="#patch_check" kind="Check" parent="${graphMainBodyNode.id}" edge="statement" order="1" path="examples/hello.0" line="3" column="3"`,
`insert node="#patch_call" kind="MethodCall" parent="#patch_check" edge="expr" name="write" type="Void" path="examples/hello.0" line="3" column="25"`,
`insert node="#patch_write" kind="FieldAccess" parent="#patch_call" edge="left" order="0" name="write" path="examples/hello.0" line="3" column="18"`,
`insert node="#patch_out" kind="FieldAccess" parent="#patch_write" edge="left" order="0" name="out" path="examples/hello.0" line="3" column="14"`,
`insert node="#patch_world" kind="Identifier" parent="#patch_out" edge="left" order="0" name="world" path="examples/hello.0" line="3" column="9"`,
`insert node="#patch_lit" kind="Literal" parent="#patch_call" edge="arg" order="0" type="String" value="second line\\n" path="examples/hello.0" line="3" column="25"`,
"",
].join("\n"));
const graphInsertPatchJson = json(["patch", "--json", "--out", graphInsertedPath, graphDumpPath, graphPatchInsertPath]).body;
assert.equal(graphInsertPatchJson.ok, true);
assert.equal(graphInsertPatchJson.operationCount, 6);
assert.equal(graphInsertPatchJson.operations[0].op, "insert");
assert.equal(graphInsertPatchJson.operations[0].parent, graphMainBodyNode.id);
assert.equal(graphInsertPatchJson.operations[0].edge, "statement");
assert.equal(graphInsertPatchJson.operations[0].order, 1);
assert.equal(graphInsertPatchJson.operations[1].order, 0);
assert.equal(graphInsertPatchJson.operations[5].kind, "Literal");
assert.equal(graphInsertPatchJson.operations[5].type, "String");
assert.equal(graphInsertPatchJson.operations[5].value, "second line\n");
assert.equal(graphInsertPatchJson.saved.path, graphInsertedPath);
const graphInsertedView = zero(["view", graphInsertedPath]).stdout;
assert.match(graphInsertedView, /check world\.out\.write\("hello from zero\\n"\)\n check world\.out\.write\("second line\\n"\)/);
assert.equal(zero(["check", graphInsertedPath]).stdout, "ok\n");
assert.equal(zero(["roundtrip", graphInsertedPath]).stdout, "program graph roundtrip ok\n");
const graphInsertedText = readFileSync(graphInsertedPath, "utf8");
const graphInsertedCheckLine = graphInsertedText.split("\n").find((line) => line.startsWith("node #patch_check ")) ?? "";
const graphInsertedCheckHash = graphQuotedField(graphInsertedCheckLine, "nodeHash") || graphNodeHash(graphInsertedCheckLine);
assert.match(graphInsertedCheckHash, /^nodehash:[0-9a-f]{16}$/);
writeFileSync(graphPatchDeletePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphInsertPatchJson.patchedGraphHash}"`,
`delete node="#patch_check" expect="${graphInsertedCheckHash}"`,
"",
].join("\n"));
const graphDeletePatchJson = json(["patch", "--json", "--out", graphDeletedPath, graphInsertedPath, graphPatchDeletePath]).body;
assert.equal(graphDeletePatchJson.ok, true);
assert.equal(graphDeletePatchJson.operations[0].op, "delete");
assert.equal(graphDeletePatchJson.operations[0].actual, graphInsertedCheckHash);
assert.equal(readFileSync(graphDeletedPath, "utf8"), graphDump);
const graphOriginalCheckNode = graphDumpJson.nodes.find((node) => node.kind === "Check");
assert(graphOriginalCheckNode);
writeFileSync(graphPatchDeleteThenInsertPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphInsertPatchJson.patchedGraphHash}"`,
`delete node="${graphOriginalCheckNode.id}" expect="${graphOriginalCheckNode.nodeHash}"`,
`insert node="#patch_replacement_check" kind="Check" parent="${graphMainBodyNode.id}" edge="statement" order="0" path="examples/hello.0" line="2" column="3"`,
`insert node="#patch_replacement_call" kind="MethodCall" parent="#patch_replacement_check" edge="expr" order="0" name="write" type="Void" path="examples/hello.0" line="2" column="25"`,
`insert node="#patch_replacement_write" kind="FieldAccess" parent="#patch_replacement_call" edge="left" order="0" name="write" path="examples/hello.0" line="2" column="18"`,
`insert node="#patch_replacement_out" kind="FieldAccess" parent="#patch_replacement_write" edge="left" order="0" name="out" path="examples/hello.0" line="2" column="14"`,
`insert node="#patch_replacement_world" kind="Identifier" parent="#patch_replacement_out" edge="left" order="0" name="world" path="examples/hello.0" line="2" column="9"`,
`insert node="#patch_replacement_lit" kind="Literal" parent="#patch_replacement_call" edge="arg" order="0" type="String" value="replacement line\\n" path="examples/hello.0" line="2" column="25"`,
"",
].join("\n"));
const graphDeleteThenInsertPatchJson = json(["patch", "--json", "--out", graphDeleteThenInsertedPath, graphInsertedPath, graphPatchDeleteThenInsertPath]).body;
assert.equal(graphDeleteThenInsertPatchJson.ok, true);
assert.equal(graphDeleteThenInsertPatchJson.operations[0].op, "delete");
assert.equal(graphDeleteThenInsertPatchJson.operations[1].op, "insert");
const graphDeleteThenInsertedView = zero(["view", graphDeleteThenInsertedPath]).stdout;
assert.match(graphDeleteThenInsertedView, /check world\.out\.write\("replacement line\\n"\)\n check world\.out\.write\("second line\\n"\)/);
assert.equal(zero(["check", graphDeleteThenInsertedPath]).stdout, "ok\n");
assert.equal(zero(["roundtrip", graphDeleteThenInsertedPath]).stdout, "program graph roundtrip ok\n");
writeFileSync(graphPatchDeleteNodeFactPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`insert node="#patch_node_fact" kind="Check" parent="${graphMainBodyNode.id}" edge="statement" order="1"`,
`insertEdge from="#patch_node_fact" to="${graphModuleNode.id}" edge="backlink" target="node" order="0"`,
`delete node="#patch_node_fact"`,
"",
].join("\n"));
const graphDeleteNodeFactPatchJson = json(["patch", "--json", "--out", graphDeletedNodeFactPath, graphDumpPath, graphPatchDeleteNodeFactPath]).body;
assert.equal(graphDeleteNodeFactPatchJson.ok, true);
assert.equal(graphDeleteNodeFactPatchJson.operationCount, 3);
assert.equal(graphDeleteNodeFactPatchJson.operations[1].op, "insertEdge");
assert.equal(graphDeleteNodeFactPatchJson.operations[1].target, "node");
assert.equal(graphDeleteNodeFactPatchJson.operations[2].op, "delete");
assert.equal(readFileSync(graphDeletedNodeFactPath, "utf8"), graphDump);
writeFileSync(graphPatchDeleteExternalRootRefPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`insert node="#patch_external_root_ref" kind="Check" parent="${graphMainBodyNode.id}" edge="statement" order="1"`,
`insertEdge from="${graphModuleNode.id}" to="#patch_external_root_ref" edge="backlink" target="node" order="0"`,
`delete node="#patch_external_root_ref"`,
"",
].join("\n"));
const graphDeleteExternalRootRefPatchJson = json(["patch", "--json", graphDumpPath, graphPatchDeleteExternalRootRefPath], { allowFailure: true });
assert.notEqual(graphDeleteExternalRootRefPatchJson.code, 0);
assert.equal(graphDeleteExternalRootRefPatchJson.body.ok, false);
assert.equal(graphDeleteExternalRootRefPatchJson.body.operations[0].ok, true);
assert.equal(graphDeleteExternalRootRefPatchJson.body.operations[1].ok, true);
assert.equal(graphDeleteExternalRootRefPatchJson.body.operations[2].ok, false);
assert.equal(graphDeleteExternalRootRefPatchJson.body.operations[2].code, "GPH005");
assert.equal(graphDeleteExternalRootRefPatchJson.body.operations[2].actual, "#patch_external_root_ref");
assert.equal(graphDeleteExternalRootRefPatchJson.body.saved, null);
writeFileSync(graphPatchDeleteExtraOwnerPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`insert node="#patch_extra_owner" kind="Check" parent="${graphMainBodyNode.id}" edge="statement" order="1"`,
`insertEdge from="${graphModuleNode.id}" to="#patch_extra_owner" edge="function" target="node" order="1"`,
`delete node="#patch_extra_owner"`,
"",
].join("\n"));
const graphDeleteExtraOwnerPatchJson = json(["patch", "--json", graphDumpPath, graphPatchDeleteExtraOwnerPath], { allowFailure: true });
assert.notEqual(graphDeleteExtraOwnerPatchJson.code, 0);
assert.equal(graphDeleteExtraOwnerPatchJson.body.ok, false);
assert.equal(graphDeleteExtraOwnerPatchJson.body.operations[0].ok, true);
assert.equal(graphDeleteExtraOwnerPatchJson.body.operations[1].ok, true);
assert.equal(graphDeleteExtraOwnerPatchJson.body.operations[2].ok, false);
assert.equal(graphDeleteExtraOwnerPatchJson.body.operations[2].code, "GPH005");
assert.equal(graphDeleteExtraOwnerPatchJson.body.operations[2].actual, "#patch_extra_owner");
assert.equal(graphDeleteExtraOwnerPatchJson.body.saved, null);
const graphLiteralNode = graphDumpJson.nodes.find((node) => node.kind === "Literal" && node.type === "String");
assert(graphLiteralNode);
writeFileSync(graphPatchReplacePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`replace node="${graphLiteralNode.id}" expect="${graphLiteralNode.nodeHash}" kind="Literal" type="String" value="hello replaced structurally\\n" public="true"`,
"",
].join("\n"));
const graphReplacePatchJson = json(["patch", "--json", "--out", graphReplacedPath, graphDumpPath, graphPatchReplacePath]).body;
assert.equal(graphReplacePatchJson.ok, true);
assert.equal(graphReplacePatchJson.operations[0].op, "replace");
assert.equal(graphReplacePatchJson.operations[0].actual, graphLiteralNode.nodeHash);
assert.equal(graphReplacePatchJson.operations[0].value, "hello replaced structurally\n");
assert.equal(graphReplacePatchJson.operations[0].public, true);
assert.match(zero(["view", graphReplacedPath]).stdout, /check world\.out\.write\("hello replaced structurally\\n"\)/);
writeFileSync(graphPatchStaleReplacePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`replace node="${graphLiteralNode.id}" expect="${graphLiteralNode.nodeHash}" kind="Literal" type="String" value="first structural value\\n"`,
`replace node="${graphLiteralNode.id}" expect="${graphLiteralNode.nodeHash}" kind="Literal" type="String" value="second structural value\\n"`,
"",
].join("\n"));
const graphStaleReplacePatchJson = json(["patch", "--json", graphDumpPath, graphPatchStaleReplacePath], { allowFailure: true });
assert.notEqual(graphStaleReplacePatchJson.code, 0);
assert.equal(graphStaleReplacePatchJson.body.ok, false);
assert.equal(graphStaleReplacePatchJson.body.operations[0].ok, true);
assert.equal(graphStaleReplacePatchJson.body.operations[1].ok, false);
assert.equal(graphStaleReplacePatchJson.body.operations[1].code, "GPH005");
assert.notEqual(graphStaleReplacePatchJson.body.operations[1].actual, graphLiteralNode.nodeHash);
writeFileSync(graphPatchInsertEdgePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`insertEdge from="${graphLiteralNode.id}" to="${graphLiteralNode.typeId}" edge="resolvedType" target="type" order="0"`,
"",
].join("\n"));
const graphInsertEdgePatchJson = json(["patch", "--json", "--out", graphInsertedEdgePath, graphDumpPath, graphPatchInsertEdgePath]).body;
assert.equal(graphInsertEdgePatchJson.ok, true);
assert.equal(graphInsertEdgePatchJson.operations[0].op, "insertEdge");
assert.equal(graphInsertEdgePatchJson.operations[0].from, graphLiteralNode.id);
assert.equal(graphInsertEdgePatchJson.operations[0].to, graphLiteralNode.typeId);
assert.equal(graphInsertEdgePatchJson.operations[0].target, "type");
assert.equal(zero(["validate", graphInsertedEdgePath]).stdout, "program graph ok\n");
writeFileSync(graphPatchEmptyTypeEdgePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`insertEdge from="${graphModuleNode.id}" to="" edge="resolvedType" target="type" order="0"`,
"",
].join("\n"));
const graphEmptyTypeEdgePatchJson = json(["patch", "--json", graphDumpPath, graphPatchEmptyTypeEdgePath], { allowFailure: true });
assert.notEqual(graphEmptyTypeEdgePatchJson.code, 0);
assert.equal(graphEmptyTypeEdgePatchJson.body.ok, false);
assert.equal(graphEmptyTypeEdgePatchJson.body.diagnostic.code, "GPH004");
assert.equal(graphEmptyTypeEdgePatchJson.body.operations[0].ok, false);
assert.equal(graphEmptyTypeEdgePatchJson.body.operations[0].code, "GPH004");
assert.equal(graphEmptyTypeEdgePatchJson.body.operations[0].to, "");
assert.equal(graphEmptyTypeEdgePatchJson.body.saved, null);
const graphEmptyTypeEdgePatchText = zeroWithStderr(["patch", graphDumpPath, graphPatchEmptyTypeEdgePath]);
assert.notEqual(graphEmptyTypeEdgePatchText.code, 0);
assert.match(graphEmptyTypeEdgePatchText.stderr, /zero query --fn <name> --handles to list stmt and param patch handles/);
writeFileSync(graphPatchRenamePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`rename node="${graphMainFunctionNode.id}" expect="main" value="start"`,
"",
].join("\n"));
const graphRenamePatchJson = json(["patch", "--json", "--out", graphRenamedPath, graphDumpPath, graphPatchRenamePath]).body;
assert.equal(graphRenamePatchJson.ok, true);
assert.equal(graphRenamePatchJson.operations[0].op, "rename");
assert.equal(graphRenamePatchJson.operations[0].actual, "main");
assert.match(zero(["view", graphRenamedPath]).stdout, /pub fn start\(world: World\) -> Void raises/);
const graphRenamedCheck = json(["check", "--json", graphRenamedPath]);
assert.equal(graphRenamedCheck.body.ok, true);
assert.equal(graphRenamedCheck.body.check.lowering, "graph-native-check");
assert.equal(graphRenamedCheck.body.targetReadiness.ok, false);
assert.equal(graphRenamedCheck.body.targetReadiness.diagnostics[0].message, "typed graph MIR requires at least one exported C ABI entry function");
writeFileSync(graphPatchInvalidRenamePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`rename node="${graphMainFunctionNode.id}" expect="main" value="bad\\nname"`,
"",
].join("\n"));
const graphInvalidRenamePatchJson = json(["patch", "--json", graphDumpPath, graphPatchInvalidRenamePath], { allowFailure: true });
assert.notEqual(graphInvalidRenamePatchJson.code, 0);
assert.equal(graphInvalidRenamePatchJson.body.ok, false);
assert.equal(graphInvalidRenamePatchJson.body.diagnostic.code, "GPH003");
assert.equal(graphInvalidRenamePatchJson.body.operations[0].actual, "bad\nname");
assert.equal(graphInvalidRenamePatchJson.body.saved, null);
writeFileSync(graphUncheckedPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphMainFunctionNode.id}" field="type" expect="Void" value="u32"`,
"",
].join("\n"));
assertPatchOkOutput(zero(["patch", "--out", graphUncheckedPath, graphDumpPath, graphUncheckedPatchPath]).stdout, graphUncheckedPath);
const graphUncheckedInline = json(["check", "--json", graphUncheckedPath], { allowFailure: true });
assert.equal(graphUncheckedInline.code, 0);
assert.equal(graphUncheckedInline.body.ok, true);
assert.equal(graphUncheckedInline.body.canonicalSource, false);
assert.equal(graphUncheckedInline.body.check.ok, true);
assert.equal(graphUncheckedInline.body.check.phase, "typecheck");
assert.equal(graphUncheckedInline.body.check.lowering, "graph-native-check");
assert.equal(graphUncheckedInline.body.check.sourcePath, null);
assert.equal(graphUncheckedInline.body.targetReadiness.ok, false);
assert.equal(graphUncheckedInline.body.targetReadiness.diagnostics[0].code, "BLD004");
assert.equal(graphUncheckedInline.body.targetReadiness.diagnostics[0].actual, "no exported function");
assert.equal(graphUncheckedInline.body.saved, null);
assert.deepEqual(graphUncheckedInline.body.diagnostics, []);
assert.equal(graphUncheckedInline.body.view, null);
assert.doesNotMatch(JSON.stringify(graphUncheckedInline.body), /<generated-graph-view>|zero-graph-check/);
assert.equal(zero(["dump", "--out", graphBorrowDumpPath, "conformance/native/pass/borrow-field-independent-assignment.0"]).stdout, "");
const graphBorrowDumpJson = json(["dump", "--json", "conformance/native/pass/borrow-field-independent-assignment.0"]).body;
assert.match(graphBorrowDumpJson.graphHash, /^graph:[0-9a-f]{16}$/);
const graphBorrowRightFieldAccess = graphBorrowDumpJson.nodes.filter((node) => node.kind === "FieldAccess" && node.name === "right").at(-1);
assert(graphBorrowRightFieldAccess);
writeFileSync(graphBorrowConflictPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphBorrowDumpJson.graphHash}"`,
`set node="${graphBorrowRightFieldAccess.id}" field="name" expect="right" value="left"`,
"",
].join("\n"));
assertPatchOkOutput(zero(["patch", "--out", graphBorrowConflictPath, graphBorrowDumpPath, graphBorrowConflictPatchPath]).stdout, graphBorrowConflictPath);
const graphBorrowConflictInline = json(["check", "--json", graphBorrowConflictPath], { allowFailure: true });
assert.equal(graphBorrowConflictInline.code, 0);
assert.equal(graphBorrowConflictInline.body.ok, true);
assert.equal(graphBorrowConflictInline.body.check.ok, true);
assert.equal(graphBorrowConflictInline.body.targetReadiness.ok, false);
assert.equal(graphBorrowConflictInline.body.targetReadiness.diagnostics[0].code, "BLD004");
assert.deepEqual(graphBorrowConflictInline.body.diagnostics, []);
assert.equal(graphBorrowConflictInline.body.view, null);
assert.doesNotMatch(JSON.stringify(graphBorrowConflictInline.body), /<generated-graph-view>|zero-graph-check/);
writeFileSync(graphPatchEmptyPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphHelloLiteralNode.id}" field="value" expect="hello from zero\\n" value=""`,
"",
].join("\n"));
const graphPatchEmpty = json(["patch", "--json", graphDumpPath, graphPatchEmptyPath]).body;
assert.equal(graphPatchEmpty.ok, true);
assert.equal(graphPatchEmpty.operations[0].value, "");
writeFileSync(graphPatchControlPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphHelloLiteralNode.id}" field="value" expect="hello from zero\\n" value="\\u0001"`,
"",
].join("\n"));
const graphPatchControl = json(["patch", "--json", graphDumpPath, graphPatchControlPath]).body;
assert.equal(graphPatchControl.ok, true);
assert.equal(graphPatchControl.operations[0].value, "\u0001");
writeFileSync(graphPatchHighBytePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphHelloLiteralNode.id}" field="value" expect="hello from zero\\n" value="\\u0080"`,
"",
].join("\n"));
const graphPatchHighByteStdout = execFileSync(zeroBin, ["patch", "--json", graphDumpPath, graphPatchHighBytePath], { stdio: ["ignore", "pipe", "pipe"] });
assert.equal(graphPatchHighByteStdout.includes(Buffer.from([0x80])), false);
const graphPatchHighByteText = graphPatchHighByteStdout.toString("utf8");
assert.match(graphPatchHighByteText, /"value": "\\u0080"/);
const graphPatchHighByte = JSON.parse(graphPatchHighByteText);
assert.equal(graphPatchHighByte.ok, true);
assert.equal(graphPatchHighByte.operations[0].value.charCodeAt(0), 0x80);
writeFileSync(graphPatchBadEscapePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphHelloLiteralNode.id}" field="value" expect="hello from zero\\n" value="\\q"`,
"",
].join("\n"));
const graphPatchBadEscape = json(["patch", "--json", graphDumpPath, graphPatchBadEscapePath], { allowFailure: true });
assert.notEqual(graphPatchBadEscape.code, 0);
assert.equal(graphPatchBadEscape.body.ok, false);
assert.equal(graphPatchBadEscape.body.diagnostic.code, "GPH001");
writeFileSync(graphPatchNullEscapePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphHelloLiteralNode.id}" field="value" expect="hello from zero\\n" value="\\u0000x"`,
"",
].join("\n"));
const graphPatchNullEscape = json(["patch", "--json", graphDumpPath, graphPatchNullEscapePath], { allowFailure: true });
assert.notEqual(graphPatchNullEscape.code, 0);
assert.equal(graphPatchNullEscape.body.ok, false);
assert.equal(graphPatchNullEscape.body.diagnostic.code, "GPH001");
writeFileSync(graphPatchRawNullPath, Buffer.concat([
Buffer.from([
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphHelloLiteralNode.id}" field="value" expect="hello from zero\\n" value="raw nul prefix"`,
"",
].join("\n")),
Buffer.from([0]),
Buffer.from(`set node="${graphHelloLiteralNode.id}" field="value" value="ignored"\n`),
]));
const graphPatchRawNull = json(["patch", "--json", graphDumpPath, graphPatchRawNullPath], { allowFailure: true });
assert.notEqual(graphPatchRawNull.code, 0);
assert.equal(graphPatchRawNull.body.ok, false);
assert.equal(graphPatchRawNull.body.diagnostic.code, "GPH001");
assert.equal(graphPatchRawNull.body.diagnostic.message, "program graph patch contains NUL byte");
writeFileSync(graphPatchInvalidNamePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphMainFunctionNode.id}" field="name" expect="main" value="main\\npub fn injected Void"`,
"",
].join("\n"));
const graphPatchInvalidName = json(["patch", "--json", graphDumpPath, graphPatchInvalidNamePath], { allowFailure: true });
assert.notEqual(graphPatchInvalidName.code, 0);
assert.equal(graphPatchInvalidName.body.ok, false);
assert.equal(graphPatchInvalidName.body.diagnostic.code, "GPH003");
assert.equal(graphPatchInvalidName.body.operations[0].field, "name");
assert.equal(graphPatchInvalidName.body.operations[0].value, "main\npub fn injected Void");
writeFileSync(graphPatchInvalidTypePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphMainFunctionNode.id}" field="type" expect="Void" value="Void\\npub fn injected Void"`,
"",
].join("\n"));
const graphPatchInvalidType = json(["patch", "--json", graphDumpPath, graphPatchInvalidTypePath], { allowFailure: true });
assert.notEqual(graphPatchInvalidType.code, 0);
assert.equal(graphPatchInvalidType.body.ok, false);
assert.equal(graphPatchInvalidType.body.diagnostic.code, "GPH003");
assert.equal(graphPatchInvalidType.body.operations[0].field, "type");
assert.equal(graphPatchInvalidType.body.operations[0].value, "Void\npub fn injected Void");
assert.equal(zero(["dump", "--out", graphPayloadDumpPath, "conformance/check/pass/payload-match.0"]).stdout, "");
const graphPayloadDumpJson = json(["dump", "--json", "conformance/check/pass/payload-match.0"]).body;
const graphMatchNode = graphPayloadDumpJson.nodes.find((node) => node.kind === "Match");
const graphMatchArmNode = graphPayloadDumpJson.nodes.find((node) => node.kind === "MatchArm" && node.name === "ok");
assert(graphMatchNode);
assert(graphMatchArmNode);
writeFileSync(graphPatchInvalidMatchReplacePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphPayloadDumpJson.graphHash}"`,
`replace node="${graphMatchArmNode.id}" expect="${graphMatchArmNode.nodeHash}" kind="MatchArm" value="payload\\nname"`,
"",
].join("\n"));
const graphPatchInvalidMatchReplace = json(["patch", "--json", graphPayloadDumpPath, graphPatchInvalidMatchReplacePath], { allowFailure: true });
assert.notEqual(graphPatchInvalidMatchReplace.code, 0);
assert.equal(graphPatchInvalidMatchReplace.body.ok, false);
assert.equal(graphPatchInvalidMatchReplace.body.diagnostic.code, "GPH003");
assert.equal(graphPatchInvalidMatchReplace.body.diagnostic.message, "patch match payload value must be a Zero identifier path or operator");
assert.equal(graphPatchInvalidMatchReplace.body.operations[0].op, "replace");
assert.equal(graphPatchInvalidMatchReplace.body.operations[0].value, "payload\nname");
assert.equal(graphPatchInvalidMatchReplace.body.saved, null);
writeFileSync(graphPatchInvalidMatchInsertPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphPayloadDumpJson.graphHash}"`,
`insert node="#patch_bad_match_arm" kind="MatchArm" parent="${graphMatchNode.id}" edge="arm" order="2" name="ok" value="payload\\nname"`,
"",
].join("\n"));
const graphPatchInvalidMatchInsert = json(["patch", "--json", graphPayloadDumpPath, graphPatchInvalidMatchInsertPath], { allowFailure: true });
assert.notEqual(graphPatchInvalidMatchInsert.code, 0);
assert.equal(graphPatchInvalidMatchInsert.body.ok, false);
assert.equal(graphPatchInvalidMatchInsert.body.diagnostic.code, "GPH003");
assert.equal(graphPatchInvalidMatchInsert.body.diagnostic.message, "patch match payload value must be a Zero identifier path or operator");
assert.equal(graphPatchInvalidMatchInsert.body.operations[0].op, "insert");
assert.equal(graphPatchInvalidMatchInsert.body.operations[0].value, "payload\nname");
assert.equal(graphPatchInvalidMatchInsert.body.saved, null);
const graphWorldParamNode = graphDumpJson.nodes.find((node) => node.kind === "Param" && node.name === "world");
assert(graphWorldParamNode);
writeFileSync(graphPatchReservedParamPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphWorldParamNode.id}" field="name" expect="world" value="pub"`,
"",
].join("\n"));
assertPatchOkOutput(zero(["patch", "--out", graphReservedParamPath, graphDumpPath, graphPatchReservedParamPath]).stdout, graphReservedParamPath);
const graphReservedParam = json(["check", "--json", graphReservedParamPath], { allowFailure: true });
assert.notEqual(graphReservedParam.code, 0);
assert.equal(graphReservedParam.body.ok, false);
assert.equal(graphReservedParam.body.check.phase, "lower");
assert.equal(graphReservedParam.body.check.lowering, "graph-native-check");
assert.equal(graphReservedParam.body.diagnostics[0].message, "program graph parameter name is not valid Zero identifier syntax");
writeFileSync(graphPatchInternalFunctionPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphMainFunctionNode.id}" field="name" expect="main" value="__zero_bad"`,
"",
].join("\n"));
assertPatchOkOutput(zero(["patch", "--out", graphInternalFunctionPath, graphDumpPath, graphPatchInternalFunctionPath]).stdout, graphInternalFunctionPath);
const graphInternalFunction = json(["check", "--json", graphInternalFunctionPath], { allowFailure: true });
assert.notEqual(graphInternalFunction.code, 0);
assert.equal(graphInternalFunction.body.ok, false);
assert.equal(graphInternalFunction.body.check.phase, "lower");
assert.equal(graphInternalFunction.body.check.lowering, "graph-native-check");
assert.equal(graphInternalFunction.body.diagnostics[0].message, "program graph declaration uses a reserved compiler-internal symbol name");
assert.equal(zero(["dump", "--out", graphPackageDumpPath, "examples/direct-package-call-order"]).stdout, "");
assert.equal(zero(["view", "--out", graphPackageViewPath, "examples/direct-package-call-order"]).stdout, "");
const graphPackageView = readFileSync(graphPackageViewPath, "utf8");
assert.match(graphPackageView, /fn right_score/);
assert.match(graphPackageView, /fn left_score/);
assert.doesNotMatch(graphPackageView, /^use (helpers|types)$/m);
assertProjectionCheckOk(graphPackageViewPath);
const graphPackageDumpJson = json(["dump", "--json", "examples/direct-package-call-order"]).body;
const graphStatusFunctionNode = graphPackageDumpJson.nodes.find((node) => node.kind === "Function" && node.name === "right_score");
assert(graphStatusFunctionNode);
writeFileSync(graphPackagePathMismatchPatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphPackageDumpJson.graphHash}"`,
`replace node="${graphStatusFunctionNode.id}" expect="${graphStatusFunctionNode.nodeHash}" path="examples/direct-package-call-order/src/main.0" public="true"`,
"",
].join("\n"));
assertPatchOkOutput(zero(["patch", "--out", graphPackagePathMismatchPath, graphPackageDumpPath, graphPackagePathMismatchPatchPath]).stdout, graphPackagePathMismatchPath);
assert.equal(zero(["check", graphPackagePathMismatchPath]).stdout, "ok\n");
const graphPackagePathMismatchSize = json(["size", "--json", "--target", "linux-musl-x64", graphPackagePathMismatchPath]).body;
const graphHelpersInterface = graphPackagePathMismatchSize.incrementalInvalidation.interfaceFingerprints.modules.find((item) => item.name === "right");
assert(graphHelpersInterface);
assert(graphHelpersInterface.publicSymbols.some((item) => item.name === "right_score" && item.kind === "function"));
const graphMainInterface = graphPackagePathMismatchSize.incrementalInvalidation.interfaceFingerprints.modules.find((item) => item.name === "main");
assert(graphMainInterface);
assert(!graphMainInterface.publicSymbols.some((item) => item.name === "right_score"));
const graphImportNode = graphPackageDumpJson.nodes.find((node) => node.kind === "Import");
assert(graphImportNode);
writeFileSync(graphPatchInvalidImportAliasPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphPackageDumpJson.graphHash}"`,
`set node="${graphImportNode.id}" field="value" value="alias\\npub fn injected Void\\n"`,
"",
].join("\n"));
const graphPatchInvalidImportAlias = json(["patch", "--json", graphPackageDumpPath, graphPatchInvalidImportAliasPath], { allowFailure: true });
assert.notEqual(graphPatchInvalidImportAlias.code, 0);
assert.equal(graphPatchInvalidImportAlias.body.ok, false);
assert.equal(graphPatchInvalidImportAlias.body.diagnostic.code, "GPH003");
assert.equal(graphPatchInvalidImportAlias.body.diagnostic.message, "patch import alias value must be a Zero identifier");
assert.equal(graphPatchInvalidImportAlias.body.operations[0].field, "value");
assert.equal(graphPatchInvalidImportAlias.body.operations[0].value, "alias\npub fn injected Void\n");
assert.equal(graphPatchInvalidImportAlias.body.saved, null);
writeFileSync(graphPatchInvalidImportNamePath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphPackageDumpJson.graphHash}"`,
`set node="${graphImportNode.id}" field="name" value="+"`,
"",
].join("\n"));
assertPatchOkOutput(zero(["patch", "--out", graphInvalidImportNamePath, graphPackageDumpPath, graphPatchInvalidImportNamePath]).stdout, graphInvalidImportNamePath);
const graphInvalidImportName = json(["check", "--json", graphInvalidImportNamePath], { allowFailure: true });
assert.notEqual(graphInvalidImportName.code, 0);
assert.equal(graphInvalidImportName.body.ok, false);
assert.equal(graphInvalidImportName.body.check.phase, "lower");
assert.equal(graphInvalidImportName.body.check.lowering, "graph-native-check");
assert.equal(graphInvalidImportName.body.diagnostics[0].message, "program graph import module is not valid Zero import syntax");
writeFileSync(graphPatchMissingImportPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphPackageDumpJson.graphHash}"`,
`set node="${graphImportNode.id}" field="name" value="missing"`,
"",
].join("\n"));
assertPatchOkOutput(zero(["patch", "--out", graphMissingImportPath, graphPackageDumpPath, graphPatchMissingImportPath]).stdout, graphMissingImportPath);
const graphMissingImport = json(["check", "--json", graphMissingImportPath], { allowFailure: true });
assert.notEqual(graphMissingImport.code, 0);
assert.equal(graphMissingImport.body.ok, false);
assert.equal(graphMissingImport.body.check.phase, "lower");
assert.equal(graphMissingImport.body.check.lowering, "graph-native-check");
assert.equal(graphMissingImport.body.diagnostics[0].message, "program graph import target module is missing");
writeFileSync(graphPatchBadHashPath, [
"zero-program-graph-patch v1",
`expect graphHash "graph:0000000000000000"`,
`set node="${graphHelloLiteralNode.id}" field="value" value="unreachable\\n"`,
"",
].join("\n"));
const graphPatchBadHash = json(["patch", "--json", graphDumpPath, graphPatchBadHashPath], { allowFailure: true });
assert.notEqual(graphPatchBadHash.code, 0);
assert.equal(graphPatchBadHash.body.ok, false);
assert.equal(graphPatchBadHash.body.diagnostic.code, "GPH002");
assert.equal(graphPatchBadHash.body.patchedGraphHash, null);
assert.equal(graphPatchBadHash.body.saved, null);
writeFileSync(graphPatchMismatchPath, [
"zero-program-graph-patch v1",
`expect graphHash "${graphDumpJson.graphHash}"`,
`set node="${graphHelloLiteralNode.id}" field="value" expect="not this" value="unreachable\\n"`,
"",
].join("\n"));
const graphPatchMismatch = json(["patch", "--json", graphDumpPath, graphPatchMismatchPath], { allowFailure: true });
assert.notEqual(graphPatchMismatch.code, 0);
assert.equal(graphPatchMismatch.body.ok, false);
assert.equal(graphPatchMismatch.body.diagnostic.code, "GPH005");
assert.equal(graphPatchMismatch.body.operations[0].ok, false);
assert.equal(graphPatchMismatch.body.operations[0].actual, "hello from zero\n");
assert.equal(graphPatchMismatch.body.saved, null);
assert.equal(zero(["roundtrip", "examples/hello.0"]).stdout, "program graph roundtrip ok\n");
const graphRoundtripJson = json(["roundtrip", "--json", "examples/hello.0"]).body;
assert.equal(graphRoundtripJson.ok, true);
assert.equal(graphRoundtripJson.canonicalSource, false);
assert.equal(graphRoundtripJson.semanticStable, true);
assert.equal(graphRoundtripJson.lowering, "direct-program-graph");
assert.equal(graphRoundtripJson.moduleIdentity, "module:hello");
assert.equal(graphRoundtripJson.roundtripModuleIdentity, "module:hello");
assert.match(graphRoundtripJson.originalGraphHash, /^graph:[0-9a-f]{16}$/);
assert.equal(graphRoundtripJson.roundtripGraphHash, graphRoundtripJson.originalGraphHash);
assert.deepEqual(graphRoundtripJson.counts.original, { nodes: 13, edges: 12 });
assert.deepEqual(graphRoundtripJson.counts.roundtrip, { nodes: 13, edges: 12 });
assert.deepEqual(graphRoundtripJson.semanticCounts.original, { nodes: 13, edges: 12 });
assert.deepEqual(graphRoundtripJson.semanticCounts.roundtrip, { nodes: 13, edges: 12 });
assert.equal(graphRoundtripJson.comparison.ok, true);
assert.equal(graphRoundtripJson.saved, null);
assert.equal(graphRoundtripJson.view, null);
assert.equal(zero(["roundtrip", graphDumpPath]).stdout, "program graph roundtrip ok\n");
const graphArtifactRoundtripJson = json(["roundtrip", "--json", graphDumpPath]).body;
assert.equal(graphArtifactRoundtripJson.ok, true);
assert.equal(graphArtifactRoundtripJson.artifact, graphDumpPath);
assert.equal(graphArtifactRoundtripJson.canonicalSource, false);
assert.equal(graphArtifactRoundtripJson.semanticStable, true);
assert.equal(graphArtifactRoundtripJson.lowering, "direct-program-graph");
assert.equal(graphArtifactRoundtripJson.moduleIdentity, "module:hello");
assert.equal(graphArtifactRoundtripJson.roundtripModuleIdentity, "module:hello");
assert.equal(graphArtifactRoundtripJson.originalGraphHash, graphDumpJson.graphHash);
assert.equal(graphArtifactRoundtripJson.roundtripGraphHash, graphDumpJson.graphHash);
assert.deepEqual(graphArtifactRoundtripJson.semanticCounts.original, graphArtifactRoundtripJson.semanticCounts.roundtrip);
assert.equal(graphArtifactRoundtripJson.comparison.ok, true);
assert.equal(graphArtifactRoundtripJson.view, null);
assert.equal(zero(["roundtrip", "--out", graphArtifactRoundtripPath, graphDumpPath]).stdout, "program graph roundtrip ok\n");
assert.equal(readFileSync(graphArtifactRoundtripPath, "utf8"), graphDump);
const graphArtifactRoundtripOutJson = json(["roundtrip", "--json", "--out", graphArtifactRoundtripPath, graphDumpPath]).body;
assert.equal(graphArtifactRoundtripOutJson.ok, true);
assert.equal(graphArtifactRoundtripOutJson.saved.path, graphArtifactRoundtripPath);
assert.equal(graphArtifactRoundtripOutJson.saved.kind, "program-graph");
assert.equal(graphArtifactRoundtripOutJson.view, null);
assert.equal(readFileSync(graphArtifactRoundtripPath, "utf8"), graphDump);
const graphArtifactRoundtripSourceTextJson = json(["roundtrip", "--json", "--out", graphArtifactRoundtripSourceTextPath, graphDumpPath], { allowFailure: true });
assert.notEqual(graphArtifactRoundtripSourceTextJson.code, 0);
assert.equal(graphArtifactRoundtripSourceTextJson.body.diagnostics[0].message, "program graph output must not use source text extension");
assert.equal(graphArtifactRoundtripSourceTextJson.body.diagnostics[0].expected, "zero roundtrip --out <program-graph-artifact> [graph-input]");
assert.equal(existsSync(graphArtifactRoundtripSourceTextPath), false);
assert.equal(zero(["roundtrip", "--out", graphSourceRoundtripPath, "examples/hello.0"]).stdout, "program graph roundtrip ok\n");
assert.match(readFileSync(graphSourceRoundtripPath, "utf8"), /^zero-graph v1\n/);
assert.equal(zero(["validate", graphSourceRoundtripPath]).stdout, "program graph ok\n");
const graphRoundtripOutJson = json(["roundtrip", "--json", "--out", graphSourceRoundtripPath, "examples/hello.0"]).body;
assert.equal(graphRoundtripOutJson.ok, true);
assert.equal(graphRoundtripOutJson.saved.path, graphSourceRoundtripPath);
assert.equal(graphRoundtripOutJson.saved.kind, "program-graph");
assert.equal(graphRoundtripOutJson.view, null);
assert.match(readFileSync(graphSourceRoundtripPath, "utf8"), /^zero-graph v1\n/);
assert.equal(zero(["validate", graphSourceRoundtripPath]).stdout, "program graph ok\n");
const graphRoundtripSourceTextOutJson = json(["roundtrip", "--json", "--out", graphSourceRoundtripSourceTextPath, "examples/hello.0"], { allowFailure: true });
assert.notEqual(graphRoundtripSourceTextOutJson.code, 0);
assert.equal(graphRoundtripSourceTextOutJson.body.diagnostics[0].message, "program graph output must not use source text extension");
assert.equal(graphRoundtripSourceTextOutJson.body.diagnostics[0].expected, "zero roundtrip --out <program-graph-artifact> [graph-input]");
assert.equal(existsSync(graphSourceRoundtripSourceTextPath), false);
const graphPackageRoundtripJson = json(["roundtrip", "--json", "examples/systems-package"]).body;
assert.equal(graphPackageRoundtripJson.ok, true);
assert.equal(graphPackageRoundtripJson.semanticStable, true);
assert.equal(graphPackageRoundtripJson.moduleIdentity, "package:systems-package@0.1.0");
assert.equal(graphPackageRoundtripJson.roundtripModuleIdentity, graphPackageRoundtripJson.moduleIdentity);
assert.equal(graphPackageRoundtripJson.comparison.ok, true);
assert.deepEqual(graphPackageRoundtripJson.semanticCounts.original, graphPackageRoundtripJson.semanticCounts.roundtrip);
const graphTestBlockRoundtripJson = json(["roundtrip", "--json", "conformance/native/pass/test-blocks.0"]).body;
assert.equal(graphTestBlockRoundtripJson.ok, true);
assert.equal(graphTestBlockRoundtripJson.semanticStable, true);
assert.equal(graphTestBlockRoundtripJson.roundtripModuleIdentity, graphTestBlockRoundtripJson.moduleIdentity);
assert.equal(graphTestBlockRoundtripJson.comparison.ok, true);
let sparseOrderGraph = graphDump.replace(`edge ${graphModuleNode.id} function ${graphMainFunctionNode.id} order:0`, `edge ${graphModuleNode.id} function ${graphMainFunctionNode.id} order:1000000000000`);
sparseOrderGraph = sparseOrderGraph.replace(/hash "graph:[0-9a-f]{16}"/, `hash "${recomputeGraphHash(sparseOrderGraph)}"`);
writeFileSync(graphSparseOrderPath, sparseOrderGraph);
const sparseOrderValidate = json(["validate", "--json", graphSparseOrderPath], { allowFailure: true });
assert.notEqual(sparseOrderValidate.code, 0);
assert.match(sparseOrderValidate.body.diagnostics[0].actual, /^GRF013\b/);
assert.match(sparseOrderValidate.body.diagnostics[0].message, /ordered edge group is sparse/);
let sparseArgGraph = graphDump.replace(/edge (#[^ ]+) arg (#[^ ]+) order:0/, "edge $1 arg $2 order:1000000000000");
sparseArgGraph = sparseArgGraph.replace(/hash "graph:[0-9a-f]{16}"/, `hash "${recomputeGraphHash(sparseArgGraph)}"`);
writeFileSync(graphSparseArgPath, sparseArgGraph);
const sparseArgValidate = json(["validate", "--json", graphSparseArgPath], { allowFailure: true });
assert.notEqual(sparseArgValidate.code, 0);
assert.match(sparseArgValidate.body.diagnostics[0].actual, /^GRF013\b/);
assert.match(sparseArgValidate.body.diagnostics[0].message, /ordered edge group is sparse/);
const graphWrongSchemaPath = join(outDir, "wrong-schema.program-graph");
writeFileSync(graphWrongSchemaPath, "zero-graph v2\n");
const graphWrongSchema = json(["validate", "--json", graphWrongSchemaPath], { allowFailure: true });
assert(graphWrongSchema.code);
assert.equal(graphWrongSchema.body.diagnostics[0].message, "unknown program graph schema version");
const graphFailedArtifactPath = join(outDir, "failed-validation.program-graph");
writeFileSync(graphFailedArtifactPath, [
"zero-graph v1",
"origin source-text",
"module \"main\"",
"hash \"\"",
"validation \"decoded\" failed",
"diagnostic code:\"GRF001\" message:\"program graph construction failed\"",
"",
].join("\n"));
const graphFailedArtifact = json(["validate", "--json", graphFailedArtifactPath], { allowFailure: true });
assert(graphFailedArtifact.code);
assert.equal(graphFailedArtifact.body.diagnostics[0].message, "program graph input reports failed validation");
const graphTrailingArtifactPath = join(outDir, "trailing-content.program-graph");
writeFileSync(graphTrailingArtifactPath, `${graphDump}\nextra\n`);
const graphTrailingArtifact = json(["validate", "--json", graphTrailingArtifactPath], { allowFailure: true });
assert(graphTrailingArtifact.code);
assert.equal(graphTrailingArtifact.body.diagnostics[0].message, "unexpected content after graph header");
const skillsList = json(["skills", "list", "--json"]).body;
assert.equal(skillsList.success, true);
assert(skillsList.data.some((skill) => skill.name === "zero" && /Zero/.test(skill.description)));
const skillNames = new Set(skillsList.data.map((skill) => skill.name));
for (const name of [
"zero",
"agent",
"builds",
"diagnostics",
"graph",
"language",
"packages",
"stdlib",
"testing",
]) {
assert(skillNames.has(name), `missing bundled skill ${name}`);
}
const zeroSkill = json(["skills", "get", "zero", "--full", "--json"]).body;
assert.equal(zeroSkill.success, true);
assert.match(zeroSkill.data[0].content, /# Zero/);
assert.match(zeroSkill.data[0].content, /zero skills get zero --full/);
assert.match(zeroSkill.data[0].content, /zero check \[graph-or-package\]/);
assert.doesNotMatch(zeroSkill.data[0].content, /<file-or-package>/);
assert.equal(zeroSkill.data[0].files, undefined);
assert.match(zeroSkill.data[0].content, /at most once per session/);
for (const skillName of skillsList.data.map((skill) => skill.name)) {
assert(zeroSkill.data[0].content.includes(`\`${skillName}\` (~`), `zero stub should index topic ${skillName} with a size`);
}
const agentSkill = json(["skills", "get", "agent", "--json"]).body;
assert.equal(agentSkill.success, true);
assert.match(agentSkill.data[0].content, /zero query --fn <name> --handles/);
assert.match(agentSkill.data[0].content, /--replace-in-fn handleLine/);
assert.match(agentSkill.data[0].content, /addParamTo fn="scan" name="bias" type="i32" default="0"/);
assert.match(agentSkill.data[0].content, /setConst name="limit" value="64"/);
assert.match(agentSkill.data[0].content, /upsertFunction handle/);
assert.match(agentSkill.data[0].content, /addReturnExpr fn="maybe" expr="null"/);
assert.match(agentSkill.data[0].content, /appendStmt fn="main" stmt="check std\.http\.listen\(world, 3000_u16\)"/);
assert.match(agentSkill.data[0].content, /addTestBody name="api add"/);
assert.match(agentSkill.data[0].content, /deleteTest name="api add"/);
assert.match(agentSkill.data[0].content, /--patch-text -/);
assert.match(agentSkill.data[0].content, /--no-help/);
assert.match(agentSkill.data[0].content, /validated: check-equivalent/);
assert.match(agentSkill.data[0].content, /zero skills get graph/);
assert.doesNotMatch(agentSkill.data[0].content, /--rewrite/);
const agentReplaceInFnIdx = agentSkill.data[0].content.indexOf("--replace-in-fn");
const agentReplaceFnIdx = agentSkill.data[0].content.indexOf("--replace-fn greet");
const agentDeclOpsIdx = agentSkill.data[0].content.indexOf("setConst");
assert(agentReplaceInFnIdx >= 0 && agentReplaceInFnIdx < agentReplaceFnIdx && agentReplaceFnIdx < agentDeclOpsIdx, "agent topic leads with --replace-in-fn, then --replace-fn, then decl ops");
assert.match(agentSkill.data[0].content, /Use JSON only when another tool must parse stable fields/);
assert.match(agentSkill.data[0].content, /zero skills get stdlib --topic std\.time/);
assert.match(agentSkill.data[0].content, /zero view --outline <module-or-file>/);
assert.doesNotMatch(agentSkill.data[0].content, /<file-or-package>/);
assert(agentSkill.data[0].content.length < 4096, `agent topic should stay compact, got ${agentSkill.data[0].content.length}`);
const languageSkill = json(["skills", "get", "language", "--json"]).body;
assert.equal(languageSkill.success, true);
assert.match(languageSkill.data[0].content, /# zerolang Language/);
assert.match(languageSkill.data[0].content, /pub fn main/);
assert.match(languageSkill.data[0].content, /human-readable projection syntax/);
assert.match(languageSkill.data[0].content, /not the package compiler input/);
assert.doesNotMatch(languageSkill.data[0].content, /\.0 source is canonical text/);
for (const typeName of [
"Bool",
"Void",
"String",
"Type",
"World",
"Maybe<T>",
"Span<T>",
"MutSpan<T>",
"ref<T>",
"mutref<T>",
"owned<T>",
]) {
assert.match(languageSkill.data[0].content, new RegExp(typeName.replace(/[<>]/g, "\\$&")));
}
const graphSkill = json(["skills", "get", "graph", "--json"]).body;
assert.equal(graphSkill.success, true);
assert.match(graphSkill.data[0].content, /# Zero Graph Authoring/);
assert.match(graphSkill.data[0].content, /primary agent authoring surface/);
assert.match(graphSkill.data[0].content, /zero query --find Block/);
assert.match(graphSkill.data[0].content, /zero dump --out \.zero\/agent\/app\.program-graph/);
assert.doesNotMatch(graphSkill.data[0].content, /<file-or-package>/);
for (const op of graphPatchHelpJson.operations) {
assert(graphSkill.data[0].content.includes(op), `graph skill should include patch operation ${op}`);
}
for (const lowLevelOp of [
"expect graphHash",
"insert node=",
"insertEdge from=",
"replace node=",
]) {
assert(graphSkill.data[0].content.includes(lowLevelOp), `graph skill should include low-level operation ${lowLevelOp}`);
}
const stdlibSkill = json(["skills", "get", "stdlib", "--json"]).body;
assert.equal(stdlibSkill.success, true);
assert.match(stdlibSkill.data[0].content, /std\.str/);
assert.match(stdlibSkill.data[0].content, /non-overlapping reverse/);
assert.match(stdlibSkill.data[0].content, /## Function Signatures/);
const stdSigText = readFileSync("native/zero-c/src/std_sig.c", "utf8");
const stdHelperNames = [...stdSigText.matchAll(/\{"(std\.[^"]+)",/g)].map((match) => match[1]);
const stdlibCatalog = stdlibSkill.data[0].content.split("## Function Signatures")[1].split("## Maybe Pattern")[0];
assert.equal((stdlibCatalog.match(/^[A-Za-z_][A-Za-z0-9_]*\(.*\) -> /gm) ?? []).length, stdHelperNames.length);
for (const helperName of stdHelperNames) {
const moduleName = helperName.split(".").slice(0, 2).join(".");
const shortName = helperName.slice(moduleName.length + 1);
assert(stdlibCatalog.includes(`### ${moduleName}`), `stdlib skill should include module ${moduleName}`);
assert(stdlibCatalog.includes(`${shortName}(`), `stdlib skill should include helper ${helperName}`);
}
const stdlibTopicSkill = json(["skills", "get", "stdlib", "--topic", "std.time", "--json"]).body;
assert.equal(stdlibTopicSkill.success, true);
assert.equal(stdlibTopicSkill.data[0].topic, "std.time");
assert.match(stdlibTopicSkill.data[0].content, /^### std\.time/);
assert.match(stdlibTopicSkill.data[0].content, /isRfc3339DateTime/);
assert.doesNotMatch(stdlibTopicSkill.data[0].content, /### std\.args/);
assert(stdlibTopicSkill.data[0].content.length < 4096, `stdlib --topic std.time should serve one section, got ${stdlibTopicSkill.data[0].content.length}`);
assert.equal(zero(["skills", "get", "stdlib", "--topic", "std.time"]).stdout, stdlibTopicSkill.data[0].content);
const stdlibTopicMiss = zero(["skills", "get", "stdlib", "--topic", "std.nosuch"], { allowFailure: true });
assert.notEqual(stdlibTopicMiss.code, 0);
assert.match(stdlibTopicMiss.stderr, /No section in skill 'stdlib' matches --topic std\.nosuch/);
assert.match(stdlibTopicMiss.stderr, /std\.time/);
assert.match(zeroSkill.data[0].content, /zero skills get stdlib --topic std\.time/);
const diagnosticSkill = json(["skills", "get", "diagnostics", "--json"]).body;
assert.equal(diagnosticSkill.success, true);
assert.match(diagnosticSkill.data[0].content, /fixSafety/);
const missingSkill = zero(["skills", "get", "missing", "--json"], { allowFailure: true });
assert.notEqual(missingSkill.code, 0);
assert.equal(JSON.parse(missingSkill.stdout).success, false);
const removedSkillsPath = zero(["skills", "path", "zero", "--json"], { allowFailure: true });
assert.notEqual(removedSkillsPath.code, 0);
assert.match(JSON.parse(removedSkillsPath.stdout).error, /Unknown skills subcommand: path/);
const badSkillsFlag = zero(["skills", "-x"], { allowFailure: true });
assert.notEqual(badSkillsFlag.code, 0);
assert.match(badSkillsFlag.stderr, /Unknown skills flag: -x/);
const badSkillsListFlag = zero(["skills", "list", "--unknown", "--json"], { allowFailure: true });
assert.notEqual(badSkillsListFlag.code, 0);
assert.match(JSON.parse(badSkillsListFlag.stdout).error, /Unknown skills flag: --unknown/);
const badSkillsGetFlag = zero(["skills", "get", "language", "--unknown", "--json"], { allowFailure: true });
assert.notEqual(badSkillsGetFlag.code, 0);
assert.match(JSON.parse(badSkillsGetFlag.stdout).error, /Unknown skills flag: --unknown/);
const lexerTokens = json(["tokens", "--json", "conformance/lexer/compiler-smoke.0"]).body;
assert.equal(lexerTokens.schemaVersion, 1);
assert.equal(lexerTokens.syntax, "canonical");
assert.match(lexerTokens.sourceFile, /compiler-smoke\.0$/);
assert.deepEqual(lexerTokens.tokens.slice(0, 4).map((token) => `${token.kind}:${token.text}`), [
"word:use",
"word:std",
"symbol:.",
"word:mem",
]);
assert.deepEqual(lexerTokens.tokens.filter((token) => token.kind === "number").map((token) => token.text), ["123", "0xff", "0b101", "42_u8"]);
assert.deepEqual(lexerTokens.tokens.filter((token) => token.kind === "string" || token.kind === "char").map((token) => `${token.kind}:${token.text}`), [
'string:"hi"',
"char:'x'",
]);
assert.equal(lexerTokens.tokens[0].line, 1);
assert.equal(lexerTokens.tokens[0].column, 1);
assert.equal(lexerTokens.tokens[0].offset, 0);
assert.equal(lexerTokens.tokens[0].length, 3);
assert.equal(lexerTokens.tokens[5].offset, 12);
assert.equal(lexerTokens.tokens[5].length, 1);
assert.equal(lexerTokens.tokens[8].kind, "word");
assert.equal(lexerTokens.tokens[8].text, "main");
assert.equal(lexerTokens.tokens[8].line, 3);
assert.equal(lexerTokens.tokens[8].column, 8);
assert.equal(lexerTokens.tokens.at(-1).kind, "eof");
assert.equal(lexerTokens.tokens.at(-1).length, 0);
const parseTree = json(["parse", "--json", "conformance/format/functions-blocks.0"]).body;
assert.equal(parseTree.schemaVersion, 1);
assert.equal(parseTree.root.kind, "module");
assert.equal(parseTree.root.shapeCount, 0);
assert.equal(parseTree.root.enumCount, 0);
assert.equal(parseTree.root.choiceCount, 0);
assert.equal(parseTree.root.functionCount, 2);
assert.equal(parseTree.functions[0].name, "helper");
assert.equal(parseTree.functions[0].paramCount, 1);
assert.deepEqual(parseTree.functions[0].bodyKinds, ["if"]);
assert.equal(parseTree.functions[1].name, "main");
assert.equal(parseTree.functions[1].paramCount, 0);
assert.deepEqual(parseTree.functions[1].bodyKinds, ["let", "while"]);
const unsupportedSourceFixture = join(outDir, "unsupported-source.txt");
const unsupportedSourceText =
"# command fixture\n" +
"fn inc i32 value i32\n" +
" ret + value 1\n" +
"\n" +
"pub fn main Void\n" +
" let total i32 inc 41\n";
rmSync(unsupportedSourceFixture, { force: true });
writeFileSync(unsupportedSourceFixture, unsupportedSourceText);
for (const args of [
["check", "--json", unsupportedSourceFixture],
["build", "--json", unsupportedSourceFixture],
["fix", "--plan", "--json", unsupportedSourceFixture],
] as string[][]) {
const rejected = json(args, { allowFailure: true });
assert.notEqual(rejected.code, 0);
assert.equal(rejected.body.diagnostics[0].code, "BLD002");
assert.equal(rejected.body.diagnostics[0].message, "compiler command requires graph input");
assert.equal(rejected.body.diagnostics[0].expected, "package zero.graph store, .graph store, or ProgramGraph artifact");
}
const rawProjectionWithGraph = join(outDir, "raw-projection-with-graph.0");
writeProjectionFile(rawProjectionWithGraph, "pub fn main() -> Void { }\n");
importProjectionSidecar(rawProjectionWithGraph);
const rawProjectionWithGraphRejected = jsonRaw(["check", "--json", rawProjectionWithGraph], { allowFailure: true });
assert.notEqual(rawProjectionWithGraphRejected.code, 0);
assert.equal(rawProjectionWithGraphRejected.body.diagnostics[0].code, "BLD002");
assert.equal(rawProjectionWithGraphRejected.body.diagnostics[0].message, "compiler command requires graph input");
assert.equal(rawProjectionWithGraphRejected.body.diagnostics[0].expected, "package zero.graph store, .graph store, or ProgramGraph artifact");
const rawProjectionNoGraph = join(outDir, "raw-projection-no-graph.0");
rmSync(rawProjectionNoGraph, { force: true });
writeFileSync(rawProjectionNoGraph, "pub fn main() -> Void { }\n");
for (const args of [
["check", "--json", rawProjectionNoGraph],
["build", "--json", rawProjectionNoGraph],
["test", "--json", rawProjectionNoGraph],
["size", "--json", rawProjectionNoGraph],
["doc", "--json", rawProjectionNoGraph],
["dev", "--json", rawProjectionNoGraph],
["abi", "dump", "--json", rawProjectionNoGraph],
["fix", "--plan", "--json", rawProjectionNoGraph],
] as string[][]) {
const rejected = jsonRaw(args, { allowFailure: true });
assert.notEqual(rejected.code, 0);
assert.equal(rejected.body.diagnostics[0].code, "BLD002");
assert.equal(rejected.body.diagnostics[0].message, "compiler command requires graph input");
assert.equal(rejected.body.diagnostics[0].expected, "package zero.graph store, .graph store, or ProgramGraph artifact");
}
const rawProjectionRunRejected = zeroRaw(["run", rawProjectionNoGraph], { allowFailure: true });
assert.notEqual(rawProjectionRunRejected.code, 0);
assert.match(rawProjectionRunRejected.stderr, /compiler command requires graph input/);
assert.match(rawProjectionRunRejected.stderr, /package zero\.graph store, \.graph store, or ProgramGraph artifact/);
for (const args of [
["tokens", "--json", unsupportedSourceFixture],
["parse", "--json", unsupportedSourceFixture],
] as string[][]) {
const rejected = json(args, { allowFailure: true });
assert.notEqual(rejected.code, 0);
assert.equal(rejected.body.diagnostics[0].code, "BLD002");
assert.equal(rejected.body.diagnostics[0].message, "expected Zero source file or package");
assert.equal(rejected.body.diagnostics[0].expected, ".0 source file, zero.toml, zero.json, or package directory");
}
for (const args of [
["view", "--json", unsupportedSourceFixture],
] as string[][]) {
const rejected = json(args, { allowFailure: true });
assert.notEqual(rejected.code, 0);
assert.equal(rejected.body.diagnostics[0].code, "PAR100");
assert.equal(rejected.body.diagnostics[0].message, "expected zero-graph v1 header");
}
const unsupportedFmtRejected = zero(["fmt", "--check", unsupportedSourceFixture], { allowFailure: true });
assert.notEqual(unsupportedFmtRejected.code, 0);
assert.match(unsupportedFmtRejected.stderr, /expected Zero source file or package/);
assert.match(unsupportedFmtRejected.stderr, /\.0 source file, zero\.toml, zero\.json, or package directory/);
const unsupportedSourcePackage = join(outDir, "unsupported-source-package");
rmSync(unsupportedSourcePackage, { recursive: true, force: true });
mkdirSync(join(unsupportedSourcePackage, "src"), { recursive: true });
writeZeroTomlSync(unsupportedSourcePackage, {
package: { name: "unsupported-source-package", version: "0.1.0" },
targets: { cli: { kind: "exe", main: "src/main.txt" } },
});
writeFileSync(join(unsupportedSourcePackage, "src", "main.txt"), unsupportedSourceText);
const unsupportedPackageRejected = json(["check", "--json", unsupportedSourcePackage], { allowFailure: true });
assert.notEqual(unsupportedPackageRejected.code, 0);
assert.equal(unsupportedPackageRejected.body.diagnostics[0].code, "RGP001");
assert.equal(unsupportedPackageRejected.body.diagnostics[0].message, "repository graph store is missing");
assert.equal(unsupportedPackageRejected.body.diagnostics[0].expected, "checked-in zero.graph repository graph store");
const testJson = json(["test", "--json", "--filter", "addition", "conformance/native/pass/test-blocks.graph"]).body;
assert.equal(testJson.schemaVersion, 1);
assert.equal(testJson.ok, true);
assert.match(testJson.stdout, /1 test\(s\) ok/);
assert.equal(testJson.testBackend, "direct-program-graph");
assertSourceGraph(testJson, "conformance/native/pass/test-blocks.graph", "module:test-blocks", "direct-program-graph", false);
assert.equal(testJson.testDiscovery.mode, "program-graph");
assert.equal(testJson.testDiscovery.filter, "addition");
assert.equal(testJson.fixtures.snapshotKey, "zero-test-graph-native-v1");
assert.equal(testJson.targetFacts.capabilitySupport.status, "supported");
assert.equal(testJson.results[0].status, "passed");
const packageTestJson = json(["test", "--json", "conformance/packages/test-app"]).body;
assert.equal(packageTestJson.ok, true);
assertSourceGraph(packageTestJson, "conformance/packages/test-app/zero.graph", "package:test-app@0.1.0", "direct-program-graph", false);
assert.equal(packageTestJson.testDiscovery.mode, "package-graph");
assert.equal(packageTestJson.discoveredTests, 3);
assert.equal(packageTestJson.expectedFailures, 1);
assert(packageTestJson.fixtures.sourceFiles.some((path) => path.endsWith("helper.0")));
const expectedFailTestJson = json(["test", "--json", "conformance/native/pass/test-expected-fail.graph"]).body;
assert.equal(expectedFailTestJson.ok, true);
assert.equal(expectedFailTestJson.expectedFailures, 1);
assert.equal(expectedFailTestJson.results[0].status, "expected-fail");
assert.match(zero(["fmt", "--check", "conformance/native/pass/test-blocks.0"]).stdout, /fmt ok/);
const unknownFlag = zero(["check", "--jsoon", "examples/hello.graph"], { allowFailure: true });
assert.notEqual(unknownFlag.code, 0);
assert.match(unknownFlag.stderr, /unknown flag: --jsoon/);
assert.match(unknownFlag.stderr, /--json/);
assert.equal(hasAnsiControlBytes(unknownFlag.stderr), false);
const cleanProbe = join(".zero", "out", "contract-clean", "tmp.txt");
mkdirSync(join(".zero", "out", "contract-clean"), { recursive: true });
writeFileSync(cleanProbe, "tmp");
assert(existsSync(cleanProbe));
const clean = zero(["clean"]).stdout;
assert.match(clean, /removed:/);
assert(!existsSync(cleanProbe));
for (const kind of ["cli", "lib", "package"]) {
const project = join(outDir, `init-template-${kind}`);
rmSync(project, { recursive: true, force: true });
const created = zero(["init", "--template", kind, project]).stdout;
assert.match(created, /graph template init ok/);
assert.match(created, new RegExp(`template: ${kind}`));
assert(existsSync(join(project, "zero.toml")));
assert(!existsSync(join(project, "zero.json")));
const manifest = readGeneratedManifest(project);
const readme = readFileSync(join(project, "README.md"), "utf8");
readFileSync(join(project, ".gitignore"), "utf8");
assertTemplateManifest(kind, manifest, readme);
zero(["check", project]);
zero(["test", project]);
assert.match(zero(["fmt", "--check", project]).stdout, /fmt ok/);
if (kind !== "lib") {
const templateRun = zero(["run", "--out", join(project, "run-app"), project]).stdout;
assert.match(templateRun, kind === "cli" ? /hello from zero\n/ : /package ok\n/);
}
const devReport = json(["dev", "--json", "--target", "linux-musl-x64", project]).body;
assertDevReport(devReport, kind);
if (kind === "lib") {
const docReport = json(["doc", "--json", project]).body;
assert.equal(docReport.schemaVersion, 1);
assert.equal(docReport.generatedCBytes, 0);
}
if (kind === "lib") {
removeInlineTests(join(project, "src", "lib.0"));
zero(["parse", "--json", join(project, "src", "lib.0")]);
} else {
const buildOut = join(project, "app");
const templateBuild = json(["build", "--json", "--emit", "exe", "--target", "linux-musl-x64", project, "--out", buildOut]).body;
assert.equal(templateBuild.generatedCBytes, 0);
assert.equal(templateBuild.objectBackend.objectEmission.path, "direct-elf64-exe");
}
}
const tinyHello = join(outDir, "tiny-hello");
rmSync(tinyHello, { force: true });
zero(["build", "--release", "tiny", "--target", "linux-musl-x64", "examples/hello.graph", "--out", tinyHello]);
assert(statSync(tinyHello).size < 10 * 1024);
const profileCacheCheckSource = join(outDir, "profile-cache-check.0");
writeProjectionFile(profileCacheCheckSource, `pub fn main(world: World) -> Void raises {
check world.out.write("profile cache ${process.pid}\\n")
}
`);
const profileCacheCheckGraph = importProjectionSidecar(profileCacheCheckSource);
const profileCacheCheck = json(["size", "--json", "--profile", "fast", profileCacheCheckGraph]).body;
assert.equal(profileCacheCheck.graph.artifact, profileCacheCheckGraph);
const profileCacheSpecialization = profileCacheCheck.compilerCaches.find((cache) => cache.name === "specialization");
assert(profileCacheSpecialization);
assert.equal(profileCacheCheck.incrementalInvalidation.profileDependency, "fast");
assert.equal(existsSync(join(".zero", "cache", "native", `specialization-${profileCacheSpecialization.key}.cache`)), true);
const buildReport = json(["build", "--json", "--target", "linux-musl-x64", "examples/hello.graph", "--out", join(outDir, "hello-linux-report")]).body;
assert.equal(buildReport.schemaVersion, 1);
assert.equal(buildReport.emit, "exe");
assert.equal(buildReport.hostTarget, version.host);
assert.equal(buildReport.target, "linux-musl-x64");
assert.equal(buildReport.compiler, "zero-elf64");
assert(buildReport.artifactBytes > 0);
assert.equal(buildReport.generatedCBytes, 0);
assert(buildReport.loweredIrBytes > 0);
assert.equal(buildReport.targetSupport.fsAvailable, true);
assert.equal(buildReport.profileSemantics.profileKey, "small");
assert.equal(buildReport.profileSemantics.profileBudget.generatedCBytes, 0);
assert.equal(buildReport.safetyFacts.profileKey, "small");
assert.equal(buildReport.safetyFacts.bounds.policy, "checked");
assert.equal(buildReport.safetyFacts.bounds.optimizerElision, false);
assert.equal(buildReport.safetyFacts.overflow.policy, "literal-range-checked-runtime-unchecked");
assert.equal(buildReport.safetyFacts.initialization.locals, "initializer-required");
assert.equal(buildReport.safetyFacts.initialization.maybePayloadReads, "guard-checked");
assert.equal(buildReport.safetyFacts.aliasing.mutableAliases, "diagnostic");
assert.equal(buildReport.safetyFacts.mir.invalidMemoryContractsBlockEmission, true);
assert.equal(buildReport.profileBudget.cBridgeFallback, false);
assert.equal(buildReport.objectBackend.objectEmission.path, "direct-elf64-exe");
assert.equal(buildReport.objectBackend.linking.externalToolchain, "none");
assertReleaseTargetContract(buildReport, {
target: "linux-musl-x64",
emit: "exe",
objectFormat: "elf",
artifactKind: "native-executable",
linkerFlavor: "elf64",
targetLibcMode: "bundled-libc",
});
repeatBuildHash(["build", "--json", "--target", "linux-musl-x64", "examples/hello.graph", "--out", join(outDir, "hello-linux-report")], join(outDir, "hello-linux-report"), join(outDir, "hello-linux-report.repeat"));
const runArtifact = join(outDir, "run-add");
rmSync(runArtifact, { force: true });
rmSync(`${runArtifact}.exe`, { force: true });
rmSync(`${runArtifact}.c`, { force: true });
const runResult = zero(["run", "--out", runArtifact, "examples/add.graph"]);
assert.match(runResult.stdout, /math works\n/);
assert(existsSync(version.host.startsWith("win32") ? `${runArtifact}.exe` : runArtifact));
assert.equal(existsSync(`${runArtifact}.c`), false);
for (const [requestedProfile, canonicalProfile, profileKey] of [
["debug", "debug", "debug"],
["fast", "release-fast", "fast"],
["small", "release-small", "small"],
["tiny", "tiny", "tiny"],
]) {
const profileOut = join(outDir, `profile-${requestedProfile}-hello`);
const profileReport = json(["build", "--json", "--profile", requestedProfile, "--target", "linux-musl-x64", "examples/hello.graph", "--out", profileOut]).body;
assert.equal(profileReport.generatedCBytes, 0);
assert.equal(profileReport.profileSemantics.canonical, canonicalProfile);
assert.equal(profileReport.profileSemantics.profileKey, profileKey);
assert.equal(profileReport.profileSemantics.boundsPolicy, "checked");
assert.equal(profileReport.profileSemantics.overflowPolicy, "literal-range-checked-runtime-unchecked");
assert.equal(profileReport.profileSemantics.profileBudget.generatedCBytes, 0);
assert.equal(profileReport.safetyFacts.profile, canonicalProfile);
assert.equal(profileReport.safetyFacts.profileKey, profileKey);
assert.equal(profileReport.profileBudget.helperBudgetPolicy, profileReport.profileSemantics.profileBudget.helperBudgetPolicy);
repeatBuildHash(["build", "--json", "--profile", requestedProfile, "--target", "linux-musl-x64", "examples/hello.graph", "--out", profileOut], profileOut, `${profileOut}.repeat`);
}
const profileSizeReport = json(["size", "--json", "--profile", "debug", "--target", "linux-musl-x64", "examples/hello.graph"]).body;
assert.equal(profileSizeReport.generatedCBytes, 0);
assert.equal(profileSizeReport.graph.artifact, "examples/hello.graph");
assert.equal(profileSizeReport.graph.lowering, "mapped-final-mir");
assert.equal(profileSizeReport.profileSemantics.profileKey, "debug");
assert.equal(profileSizeReport.safetyFacts.profileKey, "debug");
assert.equal(profileSizeReport.safetyFacts.uncheckedSurfaces[0].policy, "externally-trusted");
assert.equal(profileSizeReport.sizeBreakdown.profileKey, "debug");
assert(Array.isArray(profileSizeReport.sizeBreakdown.functions));
assert(profileSizeReport.sizeBreakdown.sections.some((item) => item.name === "debug-metadata"));
assert(Array.isArray(profileSizeReport.sizeBreakdown.stdlibHelpers));
assert(Array.isArray(profileSizeReport.sizeBreakdown.imports));
assert(Array.isArray(profileSizeReport.sizeBreakdown.runtimeShims));
assert(profileSizeReport.sizeBreakdown.debugMetadata.bytes > 0);
assert(profileSizeReport.compilerCaches.some((item) => item.name === "mappedFinalMir" && item.sourceKind === "program-graph" && item.programReconstructed === false));
assert(profileSizeReport.retentionReasons.some((item) => item.kind === "debugMetadata"));
assert(profileSizeReport.optimizationHints.some((item) => item.id === "profile-debug-metadata"));
assert.equal(profileSizeReport.profileBudget.debugMetadataAllowed, true);
const directObjPath = join(outDir, "direct-obj-add.o");
rmSync(directObjPath, { force: true });
const directObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/direct-obj-add.graph", "--out", directObjPath]).body;
const directObjBytes = readFileSync(directObjPath);
assert.equal(directObjReport.emit, "obj");
assert.equal(directObjReport.compiler, "zero-elf64");
assert.equal(directObjReport.generatedCBytes, 0);
assert(directObjReport.loweredIrBytes > 0);
assert.equal(directObjReport.objectBackend.objectEmission.path, "direct-elf64-object");
assert.equal(directObjReport.objectBackend.linking.externalToolchain, "none");
assert.equal(directObjBytes[0], 0x7f);
assert.equal(directObjBytes[1], 0x45);
assert.equal(directObjBytes[2], 0x4c);
assert.equal(directObjBytes[3], 0x46);
assert.equal(directObjBytes.readUInt16LE(16), 1);
assert.equal(directObjBytes.readUInt16LE(18), 62);
const directI64ObjPath = join(outDir, "direct-i64-return.o");
rmSync(directI64ObjPath, { force: true });
const directI64ObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/direct-i64-return.graph", "--out", directI64ObjPath]).body;
const directI64ObjBytes = readFileSync(directI64ObjPath);
assert.equal(directI64ObjReport.emit, "obj");
assert.equal(directI64ObjReport.compiler, "zero-elf64");
assert.equal(directI64ObjReport.generatedCBytes, 0);
assert.equal(directI64ObjReport.objectBackend.objectEmission.path, "direct-elf64-object");
assert(directI64ObjBytes.includes(Buffer.from([0x48, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f])));
assert(directI64ObjBytes.includes(Buffer.from([0x48, 0x01, 0xc8])));
const directShapeObjPath = join(outDir, "direct-token-shape.o");
rmSync(directShapeObjPath, { force: true });
const directShapeObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/direct-token-shape.graph", "--out", directShapeObjPath]).body;
const directShapeObjBytes = readFileSync(directShapeObjPath);
assert.equal(directShapeObjReport.emit, "obj");
assert.equal(directShapeObjReport.compiler, "zero-elf64");
assert.equal(directShapeObjReport.generatedCBytes, 0);
assert.equal(directShapeObjReport.objectBackend.objectEmission.path, "direct-elf64-object");
assert.equal(directShapeObjBytes[0], 0x7f);
assert.equal(directShapeObjBytes[1], 0x45);
const directSpanReadObjPath = join(outDir, "direct-span-read.o");
rmSync(directSpanReadObjPath, { force: true });
const directSpanReadObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/direct-span-read.graph", "--out", directSpanReadObjPath]).body;
const directSpanReadObjBytes = readFileSync(directSpanReadObjPath);
assert.equal(directSpanReadObjReport.emit, "obj");
assert.equal(directSpanReadObjReport.compiler, "zero-elf64");
assert.equal(directSpanReadObjReport.generatedCBytes, 0);
assert.equal(directSpanReadObjReport.objectBackend.objectEmission.path, "direct-elf64-object");
assert.equal(directSpanReadObjReport.objectBackend.objectEmission.dataSections, true);
assert.equal(directSpanReadObjReport.objectBackend.directFacts.readonlyDataBytes, 6);
assert.equal(directSpanReadObjBytes[0], 0x7f);
assert.equal(directSpanReadObjBytes[1], 0x45);
const directByteViewLocalsObjPath = join(outDir, "direct-byte-view-reloc.o");
rmSync(directByteViewLocalsObjPath, { force: true });
const directByteViewLocalsObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/direct-byte-view-reloc.graph", "--out", directByteViewLocalsObjPath]).body;
const directByteViewLocalsObjBytes = readFileSync(directByteViewLocalsObjPath);
assert.equal(directByteViewLocalsObjReport.emit, "obj");
assert.equal(directByteViewLocalsObjReport.compiler, "zero-elf64");
assert.equal(directByteViewLocalsObjReport.generatedCBytes, 0);
assert.equal(directByteViewLocalsObjReport.objectBackend.objectEmission.path, "direct-elf64-object");
assert.equal(directByteViewLocalsObjReport.objectBackend.objectEmission.dataSections, true);
assert.equal(directByteViewLocalsObjReport.objectBackend.directFacts.readonlyDataBytes, 6);
assert(directByteViewLocalsObjBytes.includes(Buffer.from(".rodata\0")));
assert(directByteViewLocalsObjBytes.includes(Buffer.from(".rela.text\0")));
const directRescueObjPath = join(outDir, "direct-rescue-basic.o");
rmSync(directRescueObjPath, { force: true });
const directRescueObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/direct-rescue-basic.graph", "--out", directRescueObjPath]).body;
const directRescueObjBytes = readFileSync(directRescueObjPath);
assert.equal(directRescueObjReport.emit, "obj");
assert.equal(directRescueObjReport.compiler, "zero-elf64");
assert.equal(directRescueObjReport.generatedCBytes, 0);
assert.equal(directRescueObjReport.objectBackend.objectEmission.path, "direct-elf64-object");
assert.equal(directRescueObjBytes[0], 0x7f);
assert.equal(directRescueObjBytes[1], 0x45);
const directExePath = join(outDir, "direct-exe-return");
rmSync(directExePath, { force: true });
const directExeReport = json(["build", "--json", "--emit", "exe", "--target", "linux-musl-x64", "examples/direct-exe-return.graph", "--out", directExePath]).body;
const directExeBytes = readFileSync(directExePath);
assert.equal(directExeReport.emit, "exe");
assert.equal(directExeReport.compiler, "zero-elf64");
assert.equal(directExeReport.generatedCBytes, 0);
assert(directExeReport.loweredIrBytes > 0);
assert(directExeReport.artifactBytes < 512);
assert.equal(directExeReport.objectBackend.objectEmission.path, "direct-elf64-exe");
assert.equal(directExeReport.objectBackend.objectEmission.dataSections, false);
assert.equal(directExeReport.objectBackend.linking.externalToolchain, "none");
assert.equal(directExeBytes[0], 0x7f);
assert.equal(directExeBytes[1], 0x45);
assert.equal(directExeBytes[2], 0x4c);
assert.equal(directExeBytes[3], 0x46);
assert.equal(directExeBytes.readUInt16LE(16), 2);
assert.equal(directExeBytes.readUInt16LE(18), 62);
assert.equal(directExeBytes.readUInt16LE(54), 56);
assert.equal(directExeBytes.readUInt16LE(56), 1);
const removedEmitC = json(["build", "--json", "--emit", "c", "--target", "linux-musl-x64", "examples/direct-exe-return.graph", "--out", join(outDir, "removed-c-backend.c")], { allowFailure: true });
assert.notEqual(removedEmitC.code, 0);
assert.equal(removedEmitC.body.diagnostics[0].code, "BLD003");
assert.equal(removedEmitC.body.diagnostics[0].repair.id, "use-direct-emitter");
const removedLegacyFlag = json(["build", "--json", "--legacy-backend", "--target", "linux-musl-x64", "examples/direct-exe-return.graph", "--out", join(outDir, "removed-legacy-flag")], { allowFailure: true });
assert.notEqual(removedLegacyFlag.code, 0);
assert.equal(removedLegacyFlag.body.diagnostics[0].code, "BLD003");
assert.equal(removedLegacyFlag.body.diagnostics[0].repair.id, "use-direct-emitter");
const directMachOExePath = join(outDir, "direct-macho-exe-return");
rmSync(directMachOExePath, { force: true });
const directMachOExeReport = json(["build", "--json", "--emit", "exe", "--backend", "zero-macho64", "--target", "darwin-arm64", "examples/direct-exe-return.graph", "--out", directMachOExePath]).body;
const directMachOExeBytes = readFileSync(directMachOExePath);
assert.equal(directMachOExeReport.emit, "exe");
assert.equal(directMachOExeReport.compiler, "zero-macho64");
assert.equal(directMachOExeReport.generatedCBytes, 0);
assert.equal(directMachOExeReport.objectBackend.objectEmission.path, "direct-macho64-exe");
assert.equal(directMachOExeReport.objectBackend.targetFacts.status, "native-exe");
assertReleaseTargetContract(directMachOExeReport, {
target: "darwin-arm64",
emit: "exe",
objectFormat: "macho",
artifactKind: "native-executable",
linkerFlavor: "macho64",
targetLibcMode: "host-default",
});
repeatBuildHash(["build", "--json", "--emit", "exe", "--backend", "zero-macho64", "--target", "darwin-arm64", "examples/direct-exe-return.graph", "--out", directMachOExePath], directMachOExePath, `${directMachOExePath}.repeat`);
assert.equal(directMachOExeBytes.readUInt32LE(0), 0xfeedfacf);
assert.equal(directMachOExeBytes.readUInt32LE(12), 2);
const directMachOExeUuid = assertMachOLoadCommand(directMachOExeBytes, 0x1b, 24);
assert(!directMachOExeUuid.subarray(8, 24).every((byte) => byte === 0));
assert(directMachOExeBytes.includes(Buffer.from("/usr/lib/dyld")));
assert(directMachOExeBytes.includes(Buffer.from("zero-direct")));
const directMachOX64ExePath = join(outDir, "direct-macho-x64-hello");
rmSync(directMachOX64ExePath, { force: true });
const directMachOX64ExeReport = json(["build", "--json", "--emit", "exe", "--target", "darwin-x64", "examples/hello.graph", "--out", directMachOX64ExePath]).body;
const directMachOX64ExeBytes = readFileSync(directMachOX64ExePath);
assert.equal(directMachOX64ExeReport.emit, "exe");
assert.equal(directMachOX64ExeReport.compiler, "zero-macho-x64");
assert.equal(directMachOX64ExeReport.generatedCBytes, 0);
assert.equal(directMachOX64ExeReport.objectBackend.objectEmission.path, "direct-macho-x64-exe");
assert.equal(directMachOX64ExeReport.objectBackend.targetFacts.status, "native-exe");
assertReleaseTargetContract(directMachOX64ExeReport, {
target: "darwin-x64",
emit: "exe",
objectFormat: "macho",
artifactKind: "native-executable",
linkerFlavor: "macho64",
targetLibcMode: "sysroot",
});
repeatBuildHash(["build", "--json", "--emit", "exe", "--target", "darwin-x64", "examples/hello.graph", "--out", directMachOX64ExePath], directMachOX64ExePath, `${directMachOX64ExePath}.repeat`);
assert.equal(directMachOX64ExeBytes.readUInt32LE(0), 0xfeedfacf);
assert.equal(directMachOX64ExeBytes.readUInt32LE(4), 0x01000007);
assert.equal(directMachOX64ExeBytes.readUInt32LE(8), 3);
assert.equal(directMachOX64ExeBytes.readUInt32LE(12), 2);
const directMachOX64ExeUuid = assertMachOLoadCommand(directMachOX64ExeBytes, 0x1b, 24);
assert(!directMachOX64ExeUuid.subarray(8, 24).every((byte) => byte === 0));
assert(directMachOX64ExeBytes.includes(Buffer.from("/usr/lib/dyld")));
assert(directMachOX64ExeBytes.includes(Buffer.from("zero-direct-x64")));
assert(directMachOX64ExeBytes.includes(Buffer.from("hello from zero")));
const directMachOX64UnhandledPath = join(outDir, "direct-macho-x64-unhandled-error");
rmSync(directMachOX64UnhandledPath, { force: true });
const directMachOX64UnhandledReport = json(["build", "--json", "--emit", "exe", "--target", "darwin-x64", "examples/direct-unhandled-error-exit.graph", "--out", directMachOX64UnhandledPath]).body;
const directMachOX64UnhandledBytes = readFileSync(directMachOX64UnhandledPath);
assert.equal(directMachOX64UnhandledReport.emit, "exe");
assert.equal(directMachOX64UnhandledReport.compiler, "zero-macho-x64");
assert.equal(directMachOX64UnhandledReport.generatedCBytes, 0);
assert.equal(directMachOX64UnhandledReport.objectBackend.objectEmission.path, "direct-macho-x64-exe");
assert.equal(directMachOX64UnhandledReport.objectBackend.directFacts.runtimeHelperCount, 0);
assertReleaseTargetContract(directMachOX64UnhandledReport, {
target: "darwin-x64",
emit: "exe",
objectFormat: "macho",
artifactKind: "native-executable",
linkerFlavor: "macho64",
targetLibcMode: "sysroot",
});
assert.equal(directMachOX64UnhandledBytes.readUInt32LE(0), 0xfeedfacf);
assert.equal(directMachOX64UnhandledBytes.readUInt32LE(4), 0x01000007);
assert.equal(directMachOX64UnhandledBytes.readUInt32LE(8), 3);
assert.equal(directMachOX64UnhandledBytes.readUInt32LE(12), 2);
assert(directMachOX64UnhandledBytes.includes(Buffer.from("/usr/lib/dyld")));
assert(directMachOX64UnhandledBytes.includes(Buffer.from("zero-direct-x64")));
const directMachOU8ExePath = join(outDir, "direct-macho-u8-return");
rmSync(directMachOU8ExePath, { force: true });
const directMachOU8ExeReport = json(["build", "--json", "--emit", "exe", "--target", "darwin-arm64", "examples/direct-string-literal.graph", "--out", directMachOU8ExePath]).body;
assert.equal(directMachOU8ExeReport.emit, "exe");
assert.equal(directMachOU8ExeReport.compiler, "zero-macho64");
assert.equal(directMachOU8ExeReport.generatedCBytes, 0);
assert.equal(directMachOU8ExeReport.objectBackend.objectEmission.path, "direct-macho64-exe");
const directCoffExePath = join(outDir, "direct-coff-exe-return");
rmSync(`${directCoffExePath}.exe`, { force: true });
const directCoffExeReport = json(["build", "--json", "--emit", "exe", "--backend", "zero-coff-x64", "--target", "win32-x64.exe", "examples/direct-exe-return.graph", "--out", directCoffExePath]).body;
const directCoffExeBytes = readFileSync(`${directCoffExePath}.exe`);
const directCoffPeOffset = directCoffExeBytes.readUInt32LE(0x3c);
assert.equal(directCoffExeReport.emit, "exe");
assert.equal(directCoffExeReport.compiler, "zero-coff-x64");
assert.equal(directCoffExeReport.generatedCBytes, 0);
assert.equal(directCoffExeReport.objectBackend.objectEmission.path, "direct-coff-x64-exe");
assert.equal(directCoffExeReport.objectBackend.targetFacts.status, "native-exe");
assertReleaseTargetContract(directCoffExeReport, {
target: "win32-x64.exe",
emit: "exe",
objectFormat: "coff",
artifactKind: "native-executable",
linkerFlavor: "coff",
targetLibcMode: "sysroot",
});
assert.equal(directCoffExeReport.releaseTargetContract.sysroot.requiredByTarget, true);
assert.equal(directCoffExeReport.releaseTargetContract.sysroot.status, "not-used-by-direct-artifact");
repeatBuildHash(["build", "--json", "--emit", "exe", "--backend", "zero-coff-x64", "--target", "win32-x64.exe", "examples/direct-exe-return.graph", "--out", directCoffExePath], `${directCoffExePath}.exe`, `${directCoffExePath}.repeat`, `${directCoffExePath}.repeat.exe`);
assert.equal(directCoffExeBytes.toString("ascii", directCoffPeOffset, directCoffPeOffset + 4), "PE\u0000\u0000");
assert.equal(directCoffExeBytes.readUInt16LE(directCoffPeOffset + 4), 0x8664);
assert(directCoffExeBytes.includes(Buffer.from("KERNEL32.dll")));
const directCoffArm64ExePath = join(outDir, "direct-coff-arm64-exe-return");
rmSync(`${directCoffArm64ExePath}.exe`, { force: true });
const directCoffArm64ExeReport = json(["build", "--json", "--emit", "exe", "--backend", "zero-coff-aarch64", "--target", "win32-arm64.exe", "examples/direct-exe-return.graph", "--out", directCoffArm64ExePath]).body;
const directCoffArm64ExeBytes = readFileSync(`${directCoffArm64ExePath}.exe`);
const directCoffArm64PeOffset = directCoffArm64ExeBytes.readUInt32LE(0x3c);
assert.equal(directCoffArm64ExeReport.emit, "exe");
assert.equal(directCoffArm64ExeReport.compiler, "zero-coff-aarch64");
assert.equal(directCoffArm64ExeReport.generatedCBytes, 0);
assert.equal(directCoffArm64ExeReport.objectBackend.objectEmission.path, "direct-coff-aarch64-exe");
assert.equal(directCoffArm64ExeReport.objectBackend.targetFacts.status, "native-exe");
assertReleaseTargetContract(directCoffArm64ExeReport, {
target: "win32-arm64.exe",
emit: "exe",
objectFormat: "coff",
artifactKind: "native-executable",
linkerFlavor: "coff",
targetLibcMode: "sysroot",
});
assert.equal(directCoffArm64ExeReport.releaseTargetContract.sysroot.requiredByTarget, true);
assert.equal(directCoffArm64ExeReport.releaseTargetContract.sysroot.status, "not-used-by-direct-artifact");
assert.equal(directCoffArm64ExeBytes.toString("ascii", directCoffArm64PeOffset, directCoffArm64PeOffset + 4), "PE\u0000\u0000");
assert.equal(directCoffArm64ExeBytes.readUInt16LE(directCoffArm64PeOffset + 4), 0xaa64);
assert(directCoffArm64ExeBytes.includes(Buffer.from("KERNEL32.dll")));
const directCoffArm64HelloPath = join(outDir, "direct-coff-arm64-hello");
rmSync(`${directCoffArm64HelloPath}.exe`, { force: true });
const directCoffArm64HelloReport = json(["build", "--json", "--emit", "exe", "--target", "win32-arm64.exe", "examples/hello.graph", "--out", directCoffArm64HelloPath]).body;
const directCoffArm64HelloBytes = readFileSync(`${directCoffArm64HelloPath}.exe`);
assert.equal(directCoffArm64HelloReport.compiler, "zero-coff-aarch64");
assert.equal(directCoffArm64HelloReport.generatedCBytes, 0);
assert.equal(directCoffArm64HelloReport.objectBackend.objectEmission.path, "direct-coff-aarch64-exe");
assert.equal(directCoffArm64HelloReport.objectBackend.directFacts.runtimeHelperCount, 1);
assert(directCoffArm64HelloBytes.includes(Buffer.from("hello from zero")));
assert(hasAarch64Instruction(directCoffArm64HelloBytes, 0xf90017fe));
assert(hasAarch64Instruction(directCoffArm64HelloBytes, 0xf94017fe));
const directCoffU8ExePath = join(outDir, "direct-coff-u8-return");
rmSync(`${directCoffU8ExePath}.exe`, { force: true });
const directCoffU8ExeReport = json(["build", "--json", "--emit", "exe", "--target", "win32-x64.exe", "examples/direct-string-literal.graph", "--out", directCoffU8ExePath]).body;
assert.equal(directCoffU8ExeReport.emit, "exe");
assert.equal(directCoffU8ExeReport.compiler, "zero-coff-x64");
assert.equal(directCoffU8ExeReport.generatedCBytes, 0);
assert.equal(directCoffU8ExeReport.objectBackend.objectEmission.path, "direct-coff-x64-exe");
const directAarch64ExePath = join(outDir, "direct-aarch64-exe-return");
rmSync(directAarch64ExePath, { force: true });
const directAarch64ExeReport = json(["build", "--json", "--emit", "exe", "--backend", "zero-elf-aarch64", "--target", "linux-musl-arm64", "examples/direct-exe-return.graph", "--out", directAarch64ExePath]).body;
const directAarch64ExeBytes = readFileSync(directAarch64ExePath);
assert.equal(directAarch64ExeReport.emit, "exe");
assert.equal(directAarch64ExeReport.compiler, "zero-elf-aarch64");
assert.equal(directAarch64ExeReport.generatedCBytes, 0);
assert(directAarch64ExeReport.artifactBytes < 512);
assert.equal(directAarch64ExeReport.objectBackend.objectEmission.path, "direct-elf-aarch64-exe");
const directAarch64HelloPath = join(outDir, "direct-aarch64-hello");
rmSync(directAarch64HelloPath, { force: true });
const directAarch64HelloReport = json(["build", "--json", "--emit", "exe", "--target", "linux-musl-arm64", "examples/hello.graph", "--out", directAarch64HelloPath]).body;
const directAarch64HelloBytes = readFileSync(directAarch64HelloPath);
assert.equal(directAarch64HelloReport.compiler, "zero-elf-aarch64");
assert.equal(directAarch64HelloReport.generatedCBytes, 0);
assert.equal(directAarch64HelloReport.objectBackend.objectEmission.path, "direct-elf-aarch64-exe");
assert.equal(directAarch64HelloReport.objectBackend.directFacts.runtimeHelperCount, 1);
assert(directAarch64HelloBytes.includes(Buffer.from("hello from zero")));
assert(hasAarch64VoidReturnEpilogue(directAarch64HelloBytes));
const directAarch64VoidImplicitSource = join(outDir, "direct-aarch64-void-implicit.0");
const directAarch64VoidImplicitPath = join(outDir, "direct-aarch64-void-implicit");
writeProjectionFile(directAarch64VoidImplicitSource, `export c fn main() -> Void {
let ok: Bool = true
}
`);
const directAarch64VoidImplicitGraph = importProjectionSidecar(directAarch64VoidImplicitSource);
rmSync(directAarch64VoidImplicitPath, { force: true });
const directAarch64VoidImplicitReport = json(["build", "--json", "--emit", "exe", "--target", "linux-musl-arm64", directAarch64VoidImplicitGraph, "--out", directAarch64VoidImplicitPath]).body;
const directAarch64VoidImplicitBytes = readFileSync(directAarch64VoidImplicitPath);
assert.equal(directAarch64VoidImplicitReport.compiler, "zero-elf-aarch64");
assert.equal(directAarch64VoidImplicitReport.generatedCBytes, 0);
assert(hasAarch64VoidReturnEpilogue(directAarch64VoidImplicitBytes));
assert.equal(directAarch64ExeReport.objectBackend.targetFacts.status, "native-exe");
assert.equal(directAarch64ExeBytes.readUInt16LE(16), 2);
assert.equal(directAarch64ExeBytes.readUInt16LE(18), 183);
assert(directAarch64ExeBytes.includes(Buffer.from([0x40, 0x05, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6])));
assert(directAarch64ExeBytes.includes(Buffer.from([0xa8, 0x0b, 0x80, 0xd2, 0x01, 0x00, 0x00, 0xd4])));
const directCallObjPath = join(outDir, "direct-call-add.o");
rmSync(directCallObjPath, { force: true });
const directCallObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/direct-call-add.graph", "--out", directCallObjPath]).body;
const directCallObjBytes = readFileSync(directCallObjPath);
assert.equal(directCallObjReport.emit, "obj");
assert.equal(directCallObjReport.generatedCBytes, 0);
assert.equal(directCallObjReport.objectBackend.objectEmission.path, "direct-elf64-object");
assert.equal(directCallObjBytes.readUInt16LE(16), 1);
assert.equal(directCallObjBytes.readUInt16LE(18), 62);
const directArrayObjPath = join(outDir, "direct-array-fill.o");
rmSync(directArrayObjPath, { force: true });
const directArrayObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/direct-array-fill.graph", "--out", directArrayObjPath]).body;
const directArrayObjBytes = readFileSync(directArrayObjPath);
assert.equal(directArrayObjReport.emit, "obj");
assert.equal(directArrayObjReport.generatedCBytes, 0);
assert(directArrayObjReport.objectBackend.directFacts.maxFrameBytes > 0);
assert.equal(directArrayObjReport.objectBackend.objectEmission.path, "direct-elf64-object");
assert.equal(directArrayObjBytes.readUInt16LE(16), 1);
assert.equal(directArrayObjBytes.readUInt16LE(18), 62);
const directArm64ObjPath = join(outDir, "direct-arm64-return.o");
rmSync(directArm64ObjPath, { force: true });
const directArm64ObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-arm64", "examples/direct-exe-return.graph", "--out", directArm64ObjPath]).body;
const directArm64ObjBytes = readFileSync(directArm64ObjPath);
assert.equal(directArm64ObjReport.emit, "obj");
assert.equal(directArm64ObjReport.compiler, "zero-elf-aarch64");
assert.equal(directArm64ObjReport.generatedCBytes, 0);
assert.equal(directArm64ObjReport.objectBackend.objectEmission.path, "direct-elf-aarch64-object");
assert.equal(directArm64ObjReport.objectBackend.targetFacts.status, "native-exe");
assert.equal(directArm64ObjBytes.readUInt16LE(16), 1);
assert.equal(directArm64ObjBytes.readUInt16LE(18), 183);
assert(directArm64ObjBytes.includes(Buffer.from([0x40, 0x05, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6])));
const directArm64IndexStoreSource = join(outDir, "direct-arm64-index-store-scratch.0");
const directArm64IndexStoreObjPath = join(outDir, "direct-arm64-index-store-scratch.o");
writeProjectionFile(directArm64IndexStoreSource, `export c fn main() -> u32 {
var values: [4]u32 = [0, 0, 0, 0]
values[5_u32 % 4_u32] = 7_u32
return values[1]
}
`);
const directArm64IndexStoreGraph = importProjectionSidecar(directArm64IndexStoreSource);
rmSync(directArm64IndexStoreObjPath, { force: true });
const directArm64IndexStoreObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-arm64", directArm64IndexStoreGraph, "--out", directArm64IndexStoreObjPath]).body;
const directArm64IndexStoreObjBytes = readFileSync(directArm64IndexStoreObjPath);
assert.equal(directArm64IndexStoreObjReport.compiler, "zero-elf-aarch64");
assert.equal(directArm64IndexStoreObjReport.generatedCBytes, 0);
assert(hasAarch64Instruction(directArm64IndexStoreObjBytes, 0xb90003ea));
assert(hasAarch64Instruction(directArm64IndexStoreObjBytes, 0xb94003ea));
const directWhilePath = join(outDir, "direct-while-sum");
rmSync(directWhilePath, { force: true });
const directWhileReport = json(["build", "--json", "--emit", "exe", "--backend", "zero-elf64", "--target", "linux-musl-x64", "examples/direct-while-sum.graph", "--out", directWhilePath]).body;
const directWhileBytes = readFileSync(directWhilePath);
assert.equal(directWhileReport.emit, "exe");
assert.equal(directWhileReport.compiler, "zero-elf64");
assert.equal(directWhileReport.generatedCBytes, 0);
assert.equal(directWhileReport.objectBackend.objectEmission.path, "direct-elf64-exe");
assert.equal(directWhileBytes.readUInt16LE(16), 2);
assert.equal(directWhileBytes.readUInt16LE(18), 62);
const directCallLoopPath = join(outDir, "direct-call-loop");
rmSync(directCallLoopPath, { force: true });
const directCallLoopReport = json(["build", "--json", "--emit", "exe", "--backend", "zero-elf64", "--target", "linux-musl-x64", "examples/direct-call-loop.graph", "--out", directCallLoopPath]).body;
const directCallLoopBytes = readFileSync(directCallLoopPath);
assert.equal(directCallLoopReport.emit, "exe");
assert.equal(directCallLoopReport.compiler, "zero-elf64");
assert.equal(directCallLoopReport.generatedCBytes, 0);
assert.equal(directCallLoopReport.objectBackend.objectEmission.path, "direct-elf64-exe");
assert.equal(directCallLoopBytes.readUInt16LE(16), 2);
assert.equal(directCallLoopBytes.readUInt16LE(18), 62);
const directPackagePath = join(outDir, "direct-package-arrays");
rmSync(directPackagePath, { force: true });
const directPackageReport = json(["build", "--json", "--emit", "exe", "--backend", "zero-elf64", "--target", "linux-musl-x64", "examples/direct-package-arrays", "--out", directPackagePath]).body;
const directPackageBytes = readFileSync(directPackagePath);
assert.equal(directPackageReport.emit, "exe");
assert.equal(directPackageReport.compiler, "zero-elf64");
assert.equal(directPackageReport.generatedCBytes, 0);
assert.equal(directPackageReport.objectBackend.directFacts.moduleCount, 2);
assert.equal(directPackageReport.objectBackend.objectEmission.path, "direct-elf64-exe");
assert.equal(directPackageBytes.readUInt16LE(16), 2);
assert.equal(directPackageBytes.readUInt16LE(18), 62);
const directLinuxGnuObjPath = join(outDir, "direct-linux-gnu.o");
rmSync(directLinuxGnuObjPath, { force: true });
const directLinuxGnuObjReport = json(["build", "--json", "--emit", "obj", "--target", "linux-x64", "examples/direct-call-add.graph", "--out", directLinuxGnuObjPath]).body;
const directLinuxGnuObjBytes = readFileSync(directLinuxGnuObjPath);
assert.equal(directLinuxGnuObjReport.target, "linux-x64");
assert.equal(directLinuxGnuObjReport.compiler, "zero-elf64");
assert.equal(directLinuxGnuObjReport.generatedCBytes, 0);
assert.equal(directLinuxGnuObjReport.objectBackend.targetFacts.selectedEmitter, "zero-elf64");
assert.equal(directLinuxGnuObjBytes[0], 0x7f);
assert.equal(directLinuxGnuObjBytes[1], 0x45);
assert.equal(directLinuxGnuObjBytes.readUInt16LE(16), 1);
assert.equal(directLinuxGnuObjBytes.readUInt16LE(18), 62);
const directStringEqlTargets: Array<{ target: string; outName: string; compiler: string; emissionPath: string; magic: Buffer }> = [
{ target: "linux-musl-x64", outName: "direct-string-eql-linux-musl.o", compiler: "zero-elf64", emissionPath: "direct-elf64-object", magic: Buffer.from([0x7f, 0x45, 0x4c, 0x46]) },
{ target: "linux-x64", outName: "direct-string-eql-linux-gnu.o", compiler: "zero-elf64", emissionPath: "direct-elf64-object", magic: Buffer.from([0x7f, 0x45, 0x4c, 0x46]) },
{ target: "linux-arm64", outName: "direct-string-eql-linux-arm64.o", compiler: "zero-elf-aarch64", emissionPath: "direct-elf-aarch64-object", magic: Buffer.from([0x7f, 0x45, 0x4c, 0x46]) },
{ target: "linux-musl-arm64", outName: "direct-string-eql-linux-musl-arm64.o", compiler: "zero-elf-aarch64", emissionPath: "direct-elf-aarch64-object", magic: Buffer.from([0x7f, 0x45, 0x4c, 0x46]) },
{ target: "darwin-arm64", outName: "direct-string-eql-darwin-arm64.o", compiler: "zero-macho64", emissionPath: "direct-macho64-object", magic: Buffer.from([0xcf, 0xfa, 0xed, 0xfe]) },
{ target: "darwin-x64", outName: "direct-string-eql-darwin-x64.o", compiler: "zero-macho-x64", emissionPath: "direct-macho-x64-object", magic: Buffer.from([0xcf, 0xfa, 0xed, 0xfe]) },
{ target: "win32-x64.exe", outName: "direct-string-eql-win-x64.obj", compiler: "zero-coff-x64", emissionPath: "direct-coff-x64-object", magic: Buffer.from([0x64, 0x86]) },
{ target: "win32-arm64.exe", outName: "direct-string-eql-win-arm64.obj", compiler: "zero-coff-aarch64", emissionPath: "direct-coff-aarch64-object", magic: Buffer.from([0x64, 0xaa]) },
];
for (const { target, outName, compiler, emissionPath, magic } of directStringEqlTargets) {
const directStringEqlPath = join(outDir, outName);
rmSync(directStringEqlPath, { force: true });
const directStringEqlReport = json(["build", "--json", "--emit", "obj", "--target", target, "examples/direct-string-eql.graph", "--out", directStringEqlPath]).body;
const directStringEqlBytes = readFileSync(directStringEqlPath);
assert.equal(directStringEqlReport.compiler, compiler);
assert.equal(directStringEqlReport.generatedCBytes, 0);
assert.equal(directStringEqlReport.objectBackend.objectEmission.path, emissionPath);
assert(directStringEqlBytes.subarray(0, magic.length).equals(magic));
assert(directStringEqlBytes.includes(Buffer.from("token")));
}
const directArm64DynamicStringEqlSource = join(outDir, "direct-arm64-dynamic-string-eql.0");
writeProjectionFile(directArm64DynamicStringEqlSource, `export c fn main() -> u8 {
let text: String = "token"
let start: usize = 0
let end: usize = 5
if std.mem.eqlBytes(text[(start % 1_usize)..end], "token"[(start % 1_usize)..end]) {
return 1_u8
}
return 0_u8
}
`);
const directArm64DynamicStringEqlGraph = importProjectionSidecar(directArm64DynamicStringEqlSource);
for (const { target, outName, compiler, emissionPath, magic } of [
{ target: "linux-arm64", outName: "direct-dynamic-string-eql-linux-arm64.o", compiler: "zero-elf-aarch64", emissionPath: "direct-elf-aarch64-object", magic: Buffer.from([0x7f, 0x45, 0x4c, 0x46]) },
{ target: "darwin-arm64", outName: "direct-dynamic-string-eql-darwin-arm64.o", compiler: "zero-macho64", emissionPath: "direct-macho64-object", magic: Buffer.from([0xcf, 0xfa, 0xed, 0xfe]) },
{ target: "win32-arm64.exe", outName: "direct-dynamic-string-eql-win-arm64.obj", compiler: "zero-coff-aarch64", emissionPath: "direct-coff-aarch64-object", magic: Buffer.from([0x64, 0xaa]) },
]) {
const directArm64DynamicStringEqlPath = join(outDir, outName);
rmSync(directArm64DynamicStringEqlPath, { force: true });
const directArm64DynamicStringEqlReport = json(["build", "--json", "--emit", "obj", "--target", target, directArm64DynamicStringEqlGraph, "--out", directArm64DynamicStringEqlPath]).body;
const directArm64DynamicStringEqlBytes = readFileSync(directArm64DynamicStringEqlPath);
assert.equal(directArm64DynamicStringEqlReport.compiler, compiler);
assert.equal(directArm64DynamicStringEqlReport.generatedCBytes, 0);
assert.equal(directArm64DynamicStringEqlReport.objectBackend.objectEmission.path, emissionPath);
assert(directArm64DynamicStringEqlBytes.subarray(0, magic.length).equals(magic));
assert(hasAarch64Instruction(directArm64DynamicStringEqlBytes, 0xb94003ea));
}
const directByteCopyFillTargets: Array<{ target: string; outName: string; compiler: string; emissionPath: string; magic: Buffer }> = [
{ target: "linux-musl-x64", outName: "direct-byte-copy-fill-linux-musl.o", compiler: "zero-elf64", emissionPath: "direct-elf64-object", magic: Buffer.from([0x7f, 0x45, 0x4c, 0x46]) },
{ target: "linux-x64", outName: "direct-byte-copy-fill-linux-gnu.o", compiler: "zero-elf64", emissionPath: "direct-elf64-object", magic: Buffer.from([0x7f, 0x45, 0x4c, 0x46]) },
{ target: "linux-arm64", outName: "direct-byte-copy-fill-linux-arm64.o", compiler: "zero-elf-aarch64", emissionPath: "direct-elf-aarch64-object", magic: Buffer.from([0x7f, 0x45, 0x4c, 0x46]) },
{ target: "linux-musl-arm64", outName: "direct-byte-copy-fill-linux-musl-arm64.o", compiler: "zero-elf-aarch64", emissionPath: "direct-elf-aarch64-object", magic: Buffer.from([0x7f, 0x45, 0x4c, 0x46]) },
{ target: "darwin-arm64", outName: "direct-byte-copy-fill-darwin-arm64.o", compiler: "zero-macho64", emissionPath: "direct-macho64-object", magic: Buffer.from([0xcf, 0xfa, 0xed, 0xfe]) },
{ target: "darwin-x64", outName: "direct-byte-copy-fill-darwin-x64.o", compiler: "zero-macho-x64", emissionPath: "direct-macho-x64-object", magic: Buffer.from([0xcf, 0xfa, 0xed, 0xfe]) },
{ target: "win32-x64.exe", outName: "direct-byte-copy-fill-win-x64.obj", compiler: "zero-coff-x64", emissionPath: "direct-coff-x64-object", magic: Buffer.from([0x64, 0x86]) },
{ target: "win32-arm64.exe", outName: "direct-byte-copy-fill-win-arm64.obj", compiler: "zero-coff-aarch64", emissionPath: "direct-coff-aarch64-object", magic: Buffer.from([0x64, 0xaa]) },
];
for (const { target, outName, compiler, emissionPath, magic } of directByteCopyFillTargets) {
const directByteCopyFillPath = join(outDir, outName);
rmSync(directByteCopyFillPath, { force: true });
const directByteCopyFillReport = json(["build", "--json", "--emit", "obj", "--target", target, "examples/direct-byte-copy-fill.graph", "--out", directByteCopyFillPath]).body;
const directByteCopyFillBytes = readFileSync(directByteCopyFillPath);
assert.equal(directByteCopyFillReport.compiler, compiler);
assert.equal(directByteCopyFillReport.generatedCBytes, 0);
assert.equal(directByteCopyFillReport.objectBackend.objectEmission.path, emissionPath);
assert(directByteCopyFillBytes.subarray(0, magic.length).equals(magic));
assert(directByteCopyFillBytes.includes(Buffer.from("token")));
}
const directStdPathSource = join(outDir, "direct-std-path-matrix.0");
writeProjectionFile(directStdPathSource, `export c fn main() -> u8 {
var norm: [32]u8 = [0_u8; 32]
let normalized: Maybe<String> = std.path.normalize(norm, "src//./main.0/")
var parent: [32]u8 = [0_u8; 32]
let parent_normalized: Maybe<String> = std.path.normalize(parent, "src/a/../main.0")
var joined_buf: [32]u8 = [0_u8; 32]
let joined: Maybe<String> = std.path.join(joined_buf, "src/", "/main.0")
let root_expected: Span<u8> = "/x"[..1]
var empty_abs_join_buf: [32]u8 = [0_u8; 32]
let empty_abs_joined: Maybe<String> = std.path.join(empty_abs_join_buf, "", "/main.0")
var rel: [32]u8 = [0_u8; 32]
let relative: Maybe<String> = std.path.relative(rel, "src", "src/main.0")
var fallback_buf: [32]u8 = [0_u8; 32]
let fallback: Maybe<String> = std.path.relative(fallback_buf, "other", "src/main.0")
var small: [3]u8 = [0_u8; 3]
let overflow: Maybe<String> = std.path.normalize(small, "abcd")
var root: [32]u8 = [0_u8; 32]
let root_normalized: Maybe<String> = std.path.normalize(root, "/src//./main.0/")
var root_parent_buf: [32]u8 = [0_u8; 32]
let root_parent: Maybe<String> = std.path.normalize(root_parent_buf, "/../src")
var leading_parent_buf: [32]u8 = [0_u8; 32]
let leading_parent: Maybe<String> = std.path.normalize(leading_parent_buf, "../src")
var nested_parent_buf: [32]u8 = [0_u8; 32]
let nested_parent: Maybe<String> = std.path.normalize(nested_parent_buf, "a/../../b")
var trim_fit_buf: [1]u8 = [0_u8; 1]
let trim_fit: Maybe<String> = std.path.normalize(trim_fit_buf, "a/")
var ok: Bool = true
if !normalized.has {
ok = false
}
if normalized.has {
if !std.mem.eql(normalized.value, "src/main.0") {
ok = false
}
}
if !parent_normalized.has {
ok = false
}
if parent_normalized.has {
if !std.mem.eql(parent_normalized.value, "src/main.0") {
ok = false
}
}
if !joined.has {
ok = false
}
if joined.has {
if !std.mem.eql(joined.value, "src/main.0") {
ok = false
}
}
if !empty_abs_joined.has {
ok = false
}
if empty_abs_joined.has {
if !std.mem.eql(empty_abs_joined.value, "/main.0") {
ok = false
}
}
if !relative.has {
ok = false
}
if relative.has {
if !std.mem.eql(relative.value, "main.0") {
ok = false
}
}
if !fallback.has {
ok = false
}
if fallback.has {
if !std.mem.eql(fallback.value, "src/main.0") {
ok = false
}
}
if overflow.has {
ok = false
}
if !root_normalized.has {
ok = false
}
if root_normalized.has {
if !std.mem.eql(root_normalized.value, "/src/main.0") {
ok = false
}
}
if !root_parent.has {
ok = false
}
if root_parent.has {
if !std.mem.eql(root_parent.value, "/src") {
ok = false
}
}
if !leading_parent.has {
ok = false
}
if leading_parent.has {
if !std.mem.eql(leading_parent.value, "../src") {
ok = false
}
}
if !nested_parent.has {
ok = false
}
if nested_parent.has {
if !std.mem.eql(nested_parent.value, "../b") {
ok = false
}
}
if !trim_fit.has {
ok = false
}
if trim_fit.has {
if !std.mem.eql(trim_fit.value, "a") {
ok = false
}
}
if normalized.has {
if !std.mem.eql(std.path.basename(normalized.value), "main.0") {
ok = false
}
if !std.mem.eql(std.path.dirname(normalized.value), "src") {
ok = false
}
}
if !std.mem.eql(std.path.dirname("/main.0"), root_expected) {
ok = false
}
if !std.mem.eql(std.path.dirname(root_expected), root_expected) {
ok = false
}
if normalized.has {
if !std.mem.eql(std.path.extension(normalized.value), "0") {
ok = false
}
}
if ok {
return 1_u8
}
return 0_u8
}
`);
const directStdPathGraph = importProjectionSidecar(directStdPathSource);
for (const { target, compiler, emissionPath, magic } of directByteCopyFillTargets) {
const directStdPathPath = join(outDir, `direct-std-path-${target.replace(/[^a-z0-9]+/gi, "-")}.o`);
rmSync(directStdPathPath, { force: true });
const directStdPathReport = json(["build", "--json", "--emit", "obj", "--target", target, directStdPathGraph, "--out", directStdPathPath]).body;
const directStdPathBytes = readFileSync(directStdPathPath);
assert.equal(directStdPathReport.compiler, compiler);
assert.equal(directStdPathReport.generatedCBytes, 0);
assert.equal(directStdPathReport.objectBackend.objectEmission.path, emissionPath);
assert(directStdPathBytes.subarray(0, magic.length).equals(magic));
assert(directStdPathBytes.includes(Buffer.from("src/main.0")));
}
const directStdStrSource = join(outDir, "direct-std-str-matrix.0");
writeProjectionFile(directStdStrSource, `export c fn main() -> u8 {
var reversed_buf: [6]u8 = [0_u8; 6]
let reversed: Maybe<Span<u8>> = std.str.reverse(reversed_buf, "drawer")
let trimmed: Span<u8> = std.str.trimAscii(" zero text ")
var small: [3]u8 = [0_u8; 3]
let overflow: Maybe<Span<u8>> = std.str.reverse(small, "drawer")
var ok: Bool = true
if !reversed.has {
ok = false
}
if reversed.has {
if !std.mem.eql(reversed.value, "reward") {
ok = false
}
}
if overflow.has {
ok = false
}
if std.str.countByte("banana", 97_u8) != 3 {
ok = false
}
if !std.str.startsWith("zero text syntax", "zero") {
ok = false
}
if !std.str.endsWith("zero text syntax", "syntax") {
ok = false
}
if !std.str.contains("zero text syntax", "text") {
ok = false
}
if std.str.contains("zero text syntax", "column") {
ok = false
}
if !std.str.contains("zero", "") {
ok = false
}
if !std.mem.eql(trimmed, "zero text") {
ok = false
}
if std.str.wordCountAscii("zero text syntax") != 3 {
ok = false
}
if ok {
return 1_u8
}
return 0_u8
}
`);
const directStdStrGraph = importProjectionSidecar(directStdStrSource);
for (const { target, compiler, emissionPath, magic } of directByteCopyFillTargets) {
const directStdStrPath = join(outDir, `direct-std-str-${target.replace(/[^a-z0-9]+/gi, "-")}.o`);
rmSync(directStdStrPath, { force: true });
const directStdStrReport = json(["build", "--json", "--emit", "obj", "--target", target, directStdStrGraph, "--out", directStdStrPath]).body;
const directStdStrBytes = readFileSync(directStdStrPath);
assert.equal(directStdStrReport.compiler, compiler);
assert.equal(directStdStrReport.generatedCBytes, 0);
assert.equal(directStdStrReport.objectBackend.objectEmission.path, emissionPath);
assert(directStdStrBytes.subarray(0, magic.length).equals(magic));
assert(directStdStrBytes.includes(Buffer.from("zero text syntax")));
}
const directStdMathSource = join(outDir, "direct-std-math-matrix.0");
writeProjectionFile(directStdMathSource, `export c fn main() -> u8 {
var ok: Bool = true
if std.math.minU32(8, 3) != 3 {
ok = false
}
if std.math.minU32(4000000000_u32, 3) != 3 {
ok = false
}
if std.math.minI32(0_i32 - 8_i32, 3) != 0_i32 - 8_i32 {
ok = false
}
if std.math.minUsize(8_usize, 3_usize) != 3_usize {
ok = false
}
if std.math.minI64(8_i64, 3_i64) != 3_i64 {
ok = false
}
if std.math.minU64(8_u64, 3_u64) != 3_u64 {
ok = false
}
if std.math.maxU32(8, 3) != 8 {
ok = false
}
if std.math.maxU32(4000000000_u32, 3) != 4000000000_u32 {
ok = false
}
if std.math.maxI32(0_i32 - 8_i32, 3) != 3 {
ok = false
}
if std.math.maxUsize(8_usize, 3_usize) != 8_usize {
ok = false
}
if std.math.maxI64(8_i64, 3_i64) != 8_i64 {
ok = false
}
if std.math.maxU64(8_u64, 3_u64) != 8_u64 {
ok = false
}
if std.math.clampU32(10, 2, 7) != 7 {
ok = false
}
if std.math.clampU32(4000000000_u32, 2, 7) != 7 {
ok = false
}
if std.math.clampU32(1, 7, 2) != 2 {
ok = false
}
if std.math.clampI32(0_i32 - 10_i32, 0_i32 - 5_i32, 7) != 0_i32 - 5_i32 {
ok = false
}
if std.math.clampUsize(1_usize, 7_usize, 2_usize) != 2_usize {
ok = false
}
if std.math.clampI64(10_i64, 2_i64, 7_i64) != 7_i64 {
ok = false
}
if std.math.clampU64(1_u64, 7_u64, 2_u64) != 2_u64 {
ok = false
}
if std.math.absI32(0_i32 - 7_i32) != 7_u32 {
ok = false
}
if std.math.absI64(0_i64 - 9_i64) != 9_u64 {
ok = false
}
let checked_add_u32: Maybe<u32> = std.math.checkedAddU32(40_u32, 2_u32)
let checked_sub_u32: Maybe<u32> = std.math.checkedSubU32(44_u32, 2_u32)
let checked_mul_u32: Maybe<u32> = std.math.checkedMulU32(6_u32, 7_u32)
let checked_add_usize: Maybe<usize> = std.math.checkedAddUsize(40_usize, 2_usize)
let checked_sub_usize: Maybe<usize> = std.math.checkedSubUsize(44_usize, 2_usize)
let checked_mul_usize: Maybe<usize> = std.math.checkedMulUsize(6_usize, 7_usize)
let checked_add_i32: Maybe<i32> = std.math.checkedAddI32(40, 2)
let checked_sub_i32: Maybe<i32> = std.math.checkedSubI32(40, 0_i32 - 2_i32)
let checked_mul_i32: Maybe<i32> = std.math.checkedMulI32(6, 7)
if !checked_add_u32.has || !checked_sub_u32.has || !checked_mul_u32.has || !checked_add_usize.has || !checked_sub_usize.has || !checked_mul_usize.has || !checked_add_i32.has || !checked_sub_i32.has || !checked_mul_i32.has {
ok = false
}
let checked_add_u32_overflow: Maybe<u32> = std.math.checkedAddU32(4294967295_u32, 1_u32)
let checked_sub_u32_overflow: Maybe<u32> = std.math.checkedSubU32(1_u32, 2_u32)
let checked_mul_u32_overflow: Maybe<u32> = std.math.checkedMulU32(4000000000_u32, 2_u32)
if checked_add_u32_overflow.has || checked_sub_u32_overflow.has || checked_mul_u32_overflow.has {
ok = false
}
if std.math.saturatingAddU32(4294967295_u32, 1_u32) != 4294967295_u32 || std.math.saturatingSubU32(1_u32, 2_u32) != 0_u32 || std.math.saturatingMulU32(4000000000_u32, 2_u32) != 4294967295_u32 {
ok = false
}
if std.math.saturatingAddUsize(18446744073709551615_usize, 1_usize) != 18446744073709551615_usize || std.math.saturatingSubUsize(1_usize, 2_usize) != 0_usize || std.math.saturatingMulUsize(18446744073709551615_usize, 2_usize) != 18446744073709551615_usize {
ok = false
}
if std.math.saturatingAddI32(2147483647, 1) != 2147483647 || std.math.saturatingSubI32(0_i32 - 2147483647_i32 - 1_i32, 1) != 0_i32 - 2147483647_i32 - 1_i32 || std.math.saturatingMulI32(2147483647, 2) != 2147483647 {
ok = false
}
if std.math.gcdU32(84, 30) != 6 {
ok = false
}
if std.math.lcmU32(21, 6) != 42 {
ok = false
}
let checked_lcm: Maybe<u32> = std.math.checkedLcmU32(21_u32, 6_u32)
if !checked_lcm.has {
ok = false
}
if std.math.powU32(3, 4) != 81 {
ok = false
}
let checked_pow: Maybe<u32> = std.math.checkedPowU32(2_u32, 10_u32)
if !checked_pow.has {
ok = false
}
if std.math.modPowU32(4, 13, 497) != 445 {
ok = false
}
if std.math.modPowU32(65536_u32, 2_u32, 4294967295_u32) != 1_u32 {
ok = false
}
if std.math.modPowU32(9, 0, 1) != 0 {
ok = false
}
if !std.math.isPrimeU32(31) {
ok = false
}
if std.math.isPrimeU32(33) {
ok = false
}
if !std.math.isEvenU32(42) || !std.math.isOddU32(41) {
ok = false
}
if std.math.sqrtFloorU32(99) != 9 {
ok = false
}
let factorial: Maybe<u32> = std.math.factorialU32(5_u32)
let binomial: Maybe<u32> = std.math.binomialU32(5_u32, 2_u32)
if !factorial.has || !binomial.has {
ok = false
}
let larger_binomial: Maybe<u32> = std.math.binomialU32(31_u32, 15_u32)
if !larger_binomial.has {
ok = false
} else {
if larger_binomial.value != 300540195_u32 {
ok = false
}
}
if std.math.divisorCountU32(28) != 6 {
ok = false
}
if std.math.properDivisorSumU32(28) != 28 {
ok = false
}
if ok {
return 1_u8
}
return 0_u8
}
`);
const directStdMathGraph = importProjectionSidecar(directStdMathSource);
for (const { target, compiler, emissionPath, magic } of directByteCopyFillTargets) {
const directStdMathPath = join(outDir, `direct-std-math-${target.replace(/[^a-z0-9]+/gi, "-")}.o`);
rmSync(directStdMathPath, { force: true });
const directStdMathReport = json(["build", "--json", "--emit", "obj", "--target", target, directStdMathGraph, "--out", directStdMathPath]).body;
const directStdMathBytes = readFileSync(directStdMathPath);
assert.equal(directStdMathReport.compiler, compiler);
assert.equal(directStdMathReport.generatedCBytes, 0);
assert.equal(directStdMathReport.objectBackend.objectEmission.path, emissionPath);
assert(directStdMathBytes.subarray(0, magic.length).equals(magic));
if (compiler === "zero-coff-x64") {
assert(directStdMathBytes.includes(Buffer.from("zero_math_op")));
assert(directStdMathBytes.includes(Buffer.from("zero_math_usize_op")));
}
}
const directStdTimeRandSource = join(outDir, "direct-std-time-rand-matrix.0");
writeProjectionFile(directStdTimeRandSource, `export c fn main() -> u8 {
var ok: Bool = true
let duration: Duration = std.time.add(std.time.us(2500_i64), std.time.ms(1))
let window: Duration = std.time.add(std.time.minutes(1), std.time.seconds(30))
let clamped: Duration = std.time.clamp(std.time.hours(2), std.time.seconds(1), std.time.minutes(10))
let zero: Duration = std.time.zero()
if std.time.asNs(std.time.ns(42_i64)) != 42_i64 {
ok = false
}
if std.time.asUsFloor(std.time.ns(1999_i64)) != 1_i64 {
ok = false
}
if std.time.asMsFloor(duration) != 3 {
ok = false
}
if std.time.asSecondsFloor(window) != 90_i64 {
ok = false
}
if std.time.asSecondsFloor(clamped) != 600_i64 {
ok = false
}
let negative_tick: Duration = std.time.sub(std.time.zero(), std.time.ns(1_i64))
if std.time.asUsFloor(negative_tick) != 0_i64 - 1_i64 {
ok = false
}
if std.time.asMsFloor(negative_tick) != 0 - 1 {
ok = false
}
if std.time.asSecondsFloor(negative_tick) != 0_i64 - 1_i64 {
ok = false
}
if !std.time.lessThan(zero, duration) || !std.time.isZero(zero) {
ok = false
}
if std.time.asSecondsFloor(std.time.max(duration, window)) != 90_i64 {
ok = false
}
if std.time.asNs(std.time.min(duration, window)) != 3500000_i64 {
ok = false
}
var rng: RandSource = std.rand.seed(7_u32)
let first: u32 = std.rand.nextU32(&mut rng)
let bit: Bool = std.rand.nextBool(&mut rng)
let third: u32 = std.rand.nextU32(&mut rng)
if first != 1025555898_u32 || !bit || third != 2630631676_u32 {
ok = false
}
var bool_rng: RandSource = std.rand.seed(7_u32)
let bit_one: Bool = std.rand.nextBool(&mut bool_rng)
let bit_two: Bool = std.rand.nextBool(&mut bool_rng)
let bit_three: Bool = std.rand.nextBool(&mut bool_rng)
if bit_one || !bit_two || !bit_three {
ok = false
}
if ok {
return 1_u8
}
return 0_u8
}
`);
const directStdTimeRandGraph = importProjectionSidecar(directStdTimeRandSource);
for (const { target, compiler, emissionPath, magic } of directByteCopyFillTargets) {
const directStdTimeRandPath = join(outDir, `direct-std-time-rand-${target.replace(/[^a-z0-9]+/gi, "-")}.o`);
rmSync(directStdTimeRandPath, { force: true });
const directStdTimeRandReport = json(["build", "--json", "--emit", "obj", "--target", target, directStdTimeRandGraph, "--out", directStdTimeRandPath]).body;
const directStdTimeRandBytes = readFileSync(directStdTimeRandPath);
assert.equal(directStdTimeRandReport.compiler, compiler);
assert.equal(directStdTimeRandReport.generatedCBytes, 0);
assert.equal(directStdTimeRandReport.objectBackend.objectEmission.path, emissionPath);
assert(directStdTimeRandBytes.subarray(0, magic.length).equals(magic));
}
const directStdDataSource = join(outDir, "direct-std-codec-json-url-matrix.0");
writeProjectionFile(directStdDataSource, `export c fn main() -> u8 {
var ok: Bool = true
var b64_buf: [4]u8 = [0_u8; 4]
let b64: Maybe<Span<u8>> = std.codec.base64Decode(b64_buf, "emVybw==")
if !b64.has || !std.mem.eql(b64.value, "zero") {
ok = false
}
var hex_buf: [2]u8 = [0_u8; 2]
let hex: Maybe<Span<u8>> = std.codec.hexDecode(hex_buf, "417a")
if !hex.has || !std.mem.eql(hex.value, "Az") {
ok = false
}
var word_buf: [4]u8 = [0_u8; 4]
let word: Maybe<Span<u8>> = std.codec.writeU32Be(word_buf, 0x41424344_u32)
if !word.has {
ok = false
}
if word.has {
let read_word: Maybe<u32> = std.codec.readU32Be(word.value)
if !read_word.has || read_word.value != 0x41424344_u32 {
ok = false
}
}
let json: Span<u8> = "{\\"name\\":\\"zero\\",\\"count\\":42,\\"ok\\":true}"
var name_buf: [8]u8 = [0_u8; 8]
let name: Maybe<Span<u8>> = std.json.string(name_buf, json, "name")
let count: Maybe<u32> = std.json.u32(json, "count")
let flag: Maybe<Bool> = std.json.bool(json, "ok")
var json_out_buf: [16]u8 = [0_u8; 16]
let json_out: Maybe<Span<u8>> = std.json.writeObject1U32(json_out_buf, "count", 42_u32)
if !name.has || !std.mem.eql(name.value, "zero") || !count.has || count.value != 42_u32 || !flag.has || !flag.value || !json_out.has || std.json.validateError(json_out.value) != std.json.errorNone() {
ok = false
}
var query_param_buf: [16]u8 = [0_u8; 16]
let query_param: Maybe<Span<u8>> = std.url.writeQueryParam(query_param_buf, "q", "zero lang")
var url_buf: [48]u8 = [0_u8; 48]
var url: Maybe<Span<u8>> = null
if query_param.has {
url = std.url.appendQuery(url_buf, "https://example.com/path", query_param.value)
}
if !url.has || !std.mem.eql(url.value, "https://example.com/path?q=zero+lang") {
ok = false
}
if ok {
return 1_u8
}
return 0_u8
}
`);
const directStdDataGraph = importProjectionSidecar(directStdDataSource);
for (const { target, compiler, emissionPath, magic } of directByteCopyFillTargets) {
const directStdDataPath = join(outDir, `direct-std-codec-json-url-${target.replace(/[^a-z0-9]+/gi, "-")}.o`);
rmSync(directStdDataPath, { force: true });
const directStdDataReport = json(["build", "--json", "--emit", "obj", "--target", target, directStdDataGraph, "--out", directStdDataPath]).body;
const directStdDataBytes = readFileSync(directStdDataPath);
assert.equal(directStdDataReport.compiler, compiler);
assert.equal(directStdDataReport.generatedCBytes, 0);
assert.equal(directStdDataReport.objectBackend.objectEmission.path, emissionPath);
assert(directStdDataBytes.subarray(0, magic.length).equals(magic));
assert(directStdDataBytes.includes(Buffer.from("zero+lang")));
}
const directMachOPath = join(outDir, "direct-darwin-arm64.o");
rmSync(directMachOPath, { force: true });
const directMachOReport = json(["build", "--json", "--emit", "obj", "--target", "darwin-arm64", "examples/direct-call-add.graph", "--out", directMachOPath]).body;
const directMachOBytes = readFileSync(directMachOPath);
assert.equal(directMachOReport.compiler, "zero-macho64");
assert.equal(directMachOReport.objectBackend.objectEmission.path, "direct-macho64-object");
assert.equal(directMachOReport.objectBackend.linking.objectFormat, "macho");
assert.equal(directMachOReport.objectBackend.directFacts.stackBytes, 544);
assert.equal(directMachOReport.objectBackend.directFacts.maxFrameBytes, 272);
assert.equal(directMachOBytes.readUInt32LE(0), 0xfeedfacf);
assert.equal(directMachOBytes.readUInt32LE(4), 0x0100000c);
assert.equal(directMachOBytes.readUInt32LE(12), 1);
assert(directMachOBytes.includes(Buffer.concat([Buffer.from("_main"), Buffer.from([0])])));
assert(directMachOBytes.includes(Buffer.concat([Buffer.from("_add"), Buffer.from([0])])));
assert(directMachOBytes.includes(Buffer.from([0x00, 0x01, 0x09, 0x0b])));
const directMachOSection = 32 + 72;
const directMachORelocOffset = directMachOBytes.readUInt32LE(directMachOSection + 56);
assert(directMachORelocOffset > 0);
assert(directMachOBytes.readUInt32LE(directMachOSection + 60) > 0);
assert.equal((directMachOBytes.readUInt32LE(directMachORelocOffset + 4) >>> 28) & 15, 2);
const directMachODataPath = join(outDir, "direct-darwin-arm64-data.o");
rmSync(directMachODataPath, { force: true });
const directMachODataReport = json(["build", "--json", "--emit", "obj", "--target", "darwin-arm64", "examples/direct-byte-view-reloc.graph", "--out", directMachODataPath]).body;
const directMachODataBytes = readFileSync(directMachODataPath);
assert.equal(directMachODataReport.compiler, "zero-macho64");
assert.equal(directMachODataReport.objectBackend.objectEmission.path, "direct-macho64-object");
assert.equal(directMachODataReport.objectBackend.objectEmission.dataSections, true);
assert.equal(directMachODataReport.objectBackend.directFacts.readonlyDataBytes, 6);
assert(directMachODataBytes.includes(Buffer.from("__const\0")));
assert(directMachODataBytes.includes(Buffer.from("l_.zero_rodata\0")));
assert(directMachODataBytes.includes(Buffer.from("token")));
const directMachODataSection = 32 + 72;
const directMachODataRelocOffset = directMachODataBytes.readUInt32LE(directMachODataSection + 56);
const directMachODataRelocCount = directMachODataBytes.readUInt32LE(directMachODataSection + 60);
assert(directMachODataRelocOffset > 0);
assert(directMachODataRelocCount > 0);
let sawMachOPageReloc = false;
let sawMachOPageoffReloc = false;
for (let i = 0; i < directMachODataRelocCount; i++) {
const info = directMachODataBytes.readUInt32LE(directMachODataRelocOffset + i * 8 + 4);
sawMachOPageReloc ||= ((info >>> 28) & 15) === 3;
sawMachOPageoffReloc ||= ((info >>> 28) & 15) === 4;
}
assert.equal(sawMachOPageReloc, true);
assert.equal(sawMachOPageoffReloc, true);
const directMachOWorldPath = join(outDir, "direct-darwin-arm64-world.o");
rmSync(directMachOWorldPath, { force: true });
const directMachOWorldReport = json(["build", "--json", "--emit", "obj", "--target", "darwin-arm64", "examples/hello.graph", "--out", directMachOWorldPath]).body;
const directMachOWorldBytes = readFileSync(directMachOWorldPath);
assert.equal(directMachOWorldReport.compiler, "zero-macho64");
assert.equal(directMachOWorldReport.generatedCBytes, 0);
assert.equal(directMachOWorldReport.objectBackend.objectEmission.path, "direct-macho64-object");
assert.equal(directMachOWorldReport.objectBackend.objectEmission.symbolCount, 3);
assert.equal(directMachOWorldReport.objectBackend.directFacts.runtimeHelperCount, 1);
assert.equal(directMachOWorldBytes.readUInt32LE(0), 0xfeedfacf);
assert.equal(directMachOWorldBytes.readUInt32LE(4), 0x0100000c);
assert.equal(directMachOWorldBytes.readUInt32LE(12), 1);
assert(directMachOWorldBytes.includes(Buffer.from("hello from zero")));
assert(directMachOWorldBytes.includes(Buffer.from("_zero_world_write")));
const directMachOWorldSection = 32 + 72;
const directMachOWorldRelocOffset = directMachOWorldBytes.readUInt32LE(directMachOWorldSection + 56);
const directMachOWorldRelocCount = directMachOWorldBytes.readUInt32LE(directMachOWorldSection + 60);
assert(directMachOWorldRelocOffset > 0);
assert(directMachOWorldRelocCount >= 2);
let sawMachOWorldBranchReloc = false;
for (let i = 0; i < directMachOWorldRelocCount; i++) {
const info = directMachOWorldBytes.readUInt32LE(directMachOWorldRelocOffset + i * 8 + 4);
sawMachOWorldBranchReloc ||= ((info >>> 28) & 15) === 2;
}
assert.equal(sawMachOWorldBranchReloc, true);
const directMachOX64WorldPath = join(outDir, "direct-darwin-x64-world.o");
rmSync(directMachOX64WorldPath, { force: true });
const directMachOX64WorldReport = json(["build", "--json", "--emit", "obj", "--target", "darwin-x64", "examples/hello.graph", "--out", directMachOX64WorldPath]).body;
const directMachOX64WorldBytes = readFileSync(directMachOX64WorldPath);
assert.equal(directMachOX64WorldReport.compiler, "zero-macho-x64");
assert.equal(directMachOX64WorldReport.generatedCBytes, 0);
assert.equal(directMachOX64WorldReport.objectBackend.objectEmission.path, "direct-macho-x64-object");
assert.equal(directMachOX64WorldReport.objectBackend.objectEmission.symbolCount, 3);
assert.equal(directMachOX64WorldReport.objectBackend.directFacts.runtimeHelperCount, 1);
assert.equal(directMachOX64WorldBytes.readUInt32LE(0), 0xfeedfacf);
assert.equal(directMachOX64WorldBytes.readUInt32LE(4), 0x01000007);
assert.equal(directMachOX64WorldBytes.readUInt32LE(8), 3);
assert.equal(directMachOX64WorldBytes.readUInt32LE(12), 1);
assert(directMachOX64WorldBytes.includes(Buffer.from("hello from zero")));
assert(directMachOX64WorldBytes.includes(Buffer.from("_zero_world_write")));
const directMachOX64WorldSection = 32 + 72;
const directMachOX64WorldRelocOffset = directMachOX64WorldBytes.readUInt32LE(directMachOX64WorldSection + 56);
const directMachOX64WorldRelocCount = directMachOX64WorldBytes.readUInt32LE(directMachOX64WorldSection + 60);
assert(directMachOX64WorldRelocOffset > 0);
assert(directMachOX64WorldRelocCount >= 2);
let sawMachOX64SignedReloc = false;
let sawMachOX64BranchReloc = false;
for (let i = 0; i < directMachOX64WorldRelocCount; i++) {
const info = directMachOX64WorldBytes.readUInt32LE(directMachOX64WorldRelocOffset + i * 8 + 4);
sawMachOX64SignedReloc ||= ((info >>> 28) & 15) === 1;
sawMachOX64BranchReloc ||= ((info >>> 28) & 15) === 2;
}
assert.equal(sawMachOX64SignedReloc, true);
assert.equal(sawMachOX64BranchReloc, true);
const directCoffPath = join(outDir, "direct-win-x64.obj");
rmSync(directCoffPath, { force: true });
const directCoffReport = json(["build", "--json", "--emit", "obj", "--target", "win32-x64.exe", "examples/direct-call-add.graph", "--out", directCoffPath]).body;
const directCoffBytes = readFileSync(directCoffPath);
assert.equal(directCoffReport.compiler, "zero-coff-x64");
assert.equal(directCoffReport.objectBackend.objectEmission.path, "direct-coff-x64-object");
assert.equal(directCoffReport.objectBackend.linking.objectFormat, "coff");
assert.equal(directCoffBytes.readUInt16LE(0), 0x8664);
assert.equal(directCoffBytes.readUInt16LE(2), 1);
assert(directCoffBytes.includes(Buffer.concat([Buffer.from("main"), Buffer.from([0])])));
assert(directCoffBytes.includes(Buffer.concat([Buffer.from("add"), Buffer.from([0])])));
assert(directCoffBytes.includes(Buffer.from([0xe8])));
const directCoffRelocOffset = directCoffBytes.readUInt32LE(20 + 24);
const directCoffRelocCount = directCoffBytes.readUInt16LE(20 + 32);
assert(directCoffRelocOffset > 0);
assert(directCoffRelocCount > 0);
assert.equal(directCoffBytes.readUInt16LE(directCoffRelocOffset + 8), 4);
const directCoffDataPath = join(outDir, "direct-win-x64-data.obj");
rmSync(directCoffDataPath, { force: true });
const directCoffDataReport = json(["build", "--json", "--emit", "obj", "--target", "win32-x64.exe", "examples/direct-byte-view-reloc.graph", "--out", directCoffDataPath]).body;
const directCoffDataBytes = readFileSync(directCoffDataPath);
assert.equal(directCoffDataReport.compiler, "zero-coff-x64");
assert.equal(directCoffDataReport.objectBackend.objectEmission.path, "direct-coff-x64-object");
assert.equal(directCoffDataReport.objectBackend.objectEmission.dataSections, true);
assert.equal(directCoffDataReport.objectBackend.directFacts.readonlyDataBytes, 6);
assert.equal(directCoffDataBytes.readUInt16LE(0), 0x8664);
assert.equal(directCoffDataBytes.readUInt16LE(2), 2);
assert(directCoffDataBytes.includes(Buffer.from(".rdata\0")));
assert(directCoffDataBytes.includes(Buffer.from("token")));
const directCoffDataRelocOffset = directCoffDataBytes.readUInt32LE(20 + 24);
const directCoffDataRelocCount = directCoffDataBytes.readUInt16LE(20 + 32);
assert(directCoffDataRelocOffset > 0);
assert(directCoffDataRelocCount > 0);
let sawCoffAddr64Reloc = false;
for (let i = 0; i < directCoffDataRelocCount; i++) {
sawCoffAddr64Reloc ||= directCoffDataBytes.readUInt16LE(directCoffDataRelocOffset + i * 10 + 8) === 1;
}
assert.equal(sawCoffAddr64Reloc, true);
const directCoffArm64DataPath = join(outDir, "direct-win-arm64-data.obj");
rmSync(directCoffArm64DataPath, { force: true });
const directCoffArm64DataReport = json(["build", "--json", "--emit", "obj", "--target", "win32-arm64.exe", "examples/direct-byte-view-reloc.graph", "--out", directCoffArm64DataPath]).body;
const directCoffArm64DataBytes = readFileSync(directCoffArm64DataPath);
assert.equal(directCoffArm64DataReport.compiler, "zero-coff-aarch64");
assert.equal(directCoffArm64DataReport.objectBackend.objectEmission.path, "direct-coff-aarch64-object");
assert.equal(directCoffArm64DataReport.objectBackend.objectEmission.dataSections, true);
assert.equal(directCoffArm64DataReport.objectBackend.directFacts.readonlyDataBytes, 6);
assert.equal(directCoffArm64DataBytes.readUInt16LE(0), 0xaa64);
assert.equal(directCoffArm64DataBytes.readUInt16LE(2), 2);
assert(directCoffArm64DataBytes.includes(Buffer.from(".rdata\0")));
assert(directCoffArm64DataBytes.includes(Buffer.from("token")));
const directCoffArm64DataRelocOffset = directCoffArm64DataBytes.readUInt32LE(20 + 24);
const directCoffArm64DataRelocCount = directCoffArm64DataBytes.readUInt16LE(20 + 32);
assert(directCoffArm64DataRelocOffset > 0);
assert(directCoffArm64DataRelocCount > 0);
let sawCoffArm64Addr64Reloc = false;
for (let i = 0; i < directCoffArm64DataRelocCount; i++) {
sawCoffArm64Addr64Reloc ||= directCoffArm64DataBytes.readUInt16LE(directCoffArm64DataRelocOffset + i * 10 + 8) === 0x000e;
}
assert.equal(sawCoffArm64Addr64Reloc, true);
const directCoffWorldPath = join(outDir, "direct-win-x64-world.obj");
rmSync(directCoffWorldPath, { force: true });
const directCoffWorldReport = json(["build", "--json", "--emit", "obj", "--target", "win32-x64.exe", "examples/hello.graph", "--out", directCoffWorldPath]).body;
const directCoffWorldBytes = readFileSync(directCoffWorldPath);
assert.equal(directCoffWorldReport.compiler, "zero-coff-x64");
assert.equal(directCoffWorldReport.generatedCBytes, 0);
assert.equal(directCoffWorldReport.objectBackend.objectEmission.path, "direct-coff-x64-object");
assert.equal(directCoffWorldReport.objectBackend.objectEmission.symbolCount, 4);
assert.equal(directCoffWorldReport.objectBackend.directFacts.runtimeHelperCount, 1);
assert.equal(directCoffWorldBytes.readUInt16LE(0), 0x8664);
assert.equal(directCoffWorldBytes.readUInt16LE(2), 2);
assert(directCoffWorldBytes.includes(Buffer.from("hello from zero")));
assert(directCoffWorldBytes.includes(Buffer.from("zero_world_write")));
const directCoffWorldRelocOffset = directCoffWorldBytes.readUInt32LE(20 + 24);
const directCoffWorldRelocCount = directCoffWorldBytes.readUInt16LE(20 + 32);
assert(directCoffWorldRelocOffset > 0);
assert(directCoffWorldRelocCount >= 2);
let sawCoffWorldRel32Reloc = false;
for (let i = 0; i < directCoffWorldRelocCount; i++) {
sawCoffWorldRel32Reloc ||= directCoffWorldBytes.readUInt16LE(directCoffWorldRelocOffset + i * 10 + 8) === 4;
}
assert.equal(sawCoffWorldRel32Reloc, true);
const directElfFsFallibleResourcesPath = join(outDir, "direct-std-fs-fallible-resources");
rmSync(directElfFsFallibleResourcesPath, { force: true });
const directElfFsFallibleResourcesReport = json(["build", "--json", "--emit", "exe", "--backend", "zero-elf64", "--target", "linux-musl-x64", "conformance/native/pass/std-fs-fallible-resources.graph", "--out", directElfFsFallibleResourcesPath]).body;
const directElfFsFallibleResourcesBytes = readFileSync(directElfFsFallibleResourcesPath);
assert.equal(directElfFsFallibleResourcesReport.generatedCBytes, 0);
assert.equal(directElfFsFallibleResourcesReport.objectBackend.objectEmission.path, "direct-elf64-exe");
assert(directElfFsFallibleResourcesBytes.includes(elfPackedErrorBytes(2)));
assert(directElfFsFallibleResourcesBytes.includes(elfPackedErrorBytes(4)));
const directElfFsFalliblePath = join(outDir, "direct-std-fs-fallible");
rmSync(directElfFsFalliblePath, { force: true });
const directElfFsFallibleReport = json(["build", "--json", "--emit", "exe", "--backend", "zero-elf64", "--target", "linux-musl-x64", "conformance/native/pass/std-fs-fallible.graph", "--out", directElfFsFalliblePath]).body;
const directElfFsFallibleBytes = readFileSync(directElfFsFalliblePath);
assert.equal(directElfFsFallibleReport.generatedCBytes, 0);
assert.equal(directElfFsFallibleReport.objectBackend.objectEmission.path, "direct-elf64-exe");
assert(directElfFsFallibleBytes.includes(elfPackedErrorBytes(2, true)));
assert(directElfFsFallibleBytes.includes(elfPackedErrorBytes(3, true)));
assert(directElfFsFallibleBytes.includes(elfPackedErrorBytes(4, true)));
const directArm64ElfPath = join(outDir, "direct-arm64.o");
rmSync(directArm64ElfPath, { force: true });
const directArm64ElfReport = json(["build", "--json", "--emit", "obj", "--target", "linux-arm64", "examples/direct-call-add.graph", "--out", directArm64ElfPath]).body;
const directArm64ElfBytes = readFileSync(directArm64ElfPath);
assert.equal(directArm64ElfReport.compiler, "zero-elf-aarch64");
assert.equal(directArm64ElfReport.generatedCBytes, 0);
assert.equal(directArm64ElfReport.objectBackend.objectEmission.path, "direct-elf-aarch64-object");
assert(directArm64ElfReport.objectBackend.directFacts.functionCount >= 2);
assert(directArm64ElfBytes.subarray(0, 4).equals(Buffer.from([0x7f, 0x45, 0x4c, 0x46])));
assert(directArm64ElfBytes.includes(Buffer.from("main")));
const hostLeakGraph = json(["inspect", "--json", "--target", "linux-musl-x64", "conformance/c/host-leak-package"]).body;
assert.equal(hostLeakGraph.cLibraries[0].targetValidation.status, "blocked");
assert.equal(hostLeakGraph.cLibraries[0].linkPlan.hostDiscovery, "blocked");
const hostLeakReadiness = json(["check", "--json", "--target", "linux-musl-x64", "conformance/c/host-leak-package"]).body;
assert.equal(hostLeakReadiness.ok, true);
assert.equal(hostLeakReadiness.diagnostics.length, 0);
assert.equal(hostLeakReadiness.targetReadiness.ok, false);
assert.equal(hostLeakReadiness.targetReadiness.buildable, false);
assert.equal(hostLeakReadiness.targetReadiness.diagnostics[0].code, "CIMP003");
assert.match(hostLeakReadiness.targetReadiness.diagnostics[0].help, /target sysroot|vendored/);
const hostLeakBuild = json(["build", "--json", "--target", "linux-musl-x64", "conformance/c/host-leak-package", "--out", join(outDir, "host-leak-package")], { allowFailure: true });
assert.notEqual(hostLeakBuild.code, 0);
assert.equal(hostLeakBuild.body.diagnostics[0].code, "CIMP003");
const depGraph = json(["inspect", "--json", "--target", "linux-musl-x64", "conformance/packages/dep-app"]).body;
assert.equal(depGraph.package.name, "dep-app");
assert.equal(depGraph.package.resolver.deterministic, true);
assert(depGraph.package.dependencies.some((item) => item.name === "dep-lib" && item.status === "path-resolved"));
assert(depGraph.package.dependencies.some((item) => item.name === "remote-tools" && item.status === "registry-reference"));
assert.match(depGraph.package.lockfile.path, /\.zero\/package-locks\/[0-9a-f]+\.lock\.json/);
assert.match(depGraph.packageCache.cacheKeyInputs.dependencyGraphHash, /^[0-9a-f]{16}$/);
const depDoc = json(["doc", "--json", "conformance/packages/dep-app"]).body;
assert.equal(depDoc.package.name, "dep-app");
assert.equal(depDoc.publicationGate.requiresExamplesForPublicApi, true);
const depBuild = json(["build", "--json", "--target", "linux-musl-x64", "conformance/packages/dep-app", "--out", join(outDir, "dep-app")]).body;
assert.equal(depBuild.packageCache.invalidationReasons.includes("dependency graph changed"), true);
assert.equal(depBuild.compilerCaches.every((item) => item.compilerVersion === "0.3.4" && item.packageVersion === "0.1.0"), true);
const depDevTrace = json(["dev", "--json", "--trace", "--target", "linux-musl-x64", "conformance/packages/dep-app"]).body;
assert.equal(depDevTrace.trace.requested, true);
assert.equal(depDevTrace.partialDiagnostics.stable, true);
assert(depDevTrace.watch.files.some((item) => item.endsWith("src/main.0")));
assert.match(depDevTrace.watch.packageLocks[0], /\.zero\/package-locks\/[0-9a-f]+\.lock\.json/);
assert.equal(depDevTrace.interfaceFingerprints.algorithm, "fnv1a64-zero-interface-v1");
assert(depDevTrace.interfaceFingerprints.modules.some((item) => item.name === "main" && /^[0-9a-f]{16}$/.test(item.publicInterfaceHash)));
assert.equal(depDevTrace.incrementalInvalidation.partialDiagnosticsStable, true);
assert.equal(depDevTrace.incrementalInvalidation.interfaceFingerprints.importedPackageMetadataHash, depDevTrace.interfaceFingerprints.importedPackageMetadataHash);
const depTime = json(["time", "--json", "--target", "linux-musl-x64", "conformance/packages/dep-app"]).body;
assert.equal(depTime.interfaceFingerprints.algorithm, "fnv1a64-zero-interface-v1");
assert.match(depTime.interfaceFingerprints.targetFactsHash, /^[0-9a-f]{16}$/);
assert(depTime.cacheSummary.entries >= 5);
assert(depTime.incrementalInvalidation.changedInputs.sourceFiles.some((item) => item.endsWith("src/main.0")));
if (process.getuid?.() !== 0) {
const unreadableDepRoot = join("/tmp", `zero-unreadable-dep-manifest-${process.pid}`);
const unreadableDepManifest = join(unreadableDepRoot, "dep-lib", "zero.toml");
rmSync(unreadableDepRoot, { force: true, recursive: true });
cpSync("conformance/packages/dep-app", join(unreadableDepRoot, "dep-app"), { recursive: true });
cpSync("conformance/packages/dep-lib", join(unreadableDepRoot, "dep-lib"), { recursive: true });
rmSync(join(unreadableDepRoot, "dep-app", ".zero"), { force: true, recursive: true });
rmSync(join(unreadableDepRoot, "dep-lib", ".zero"), { force: true, recursive: true });
chmodSync(unreadableDepManifest, 0o000);
const unreadableDepCheck = json(["check", "--json", join(unreadableDepRoot, "dep-app")], { allowFailure: true });
assert.equal(unreadableDepCheck.code, 1);
assert.equal(unreadableDepCheck.body.ok, false);
assert.equal(unreadableDepCheck.body.diagnostics[0].code, "PAR100");
assert.equal(unreadableDepCheck.body.diagnostics[0].path, unreadableDepManifest);
assert.match(unreadableDepCheck.body.diagnostics[0].message, /failed to read '.*dep-lib\/zero\.toml'/);
chmodSync(unreadableDepManifest, 0o644);
rmSync(unreadableDepRoot, { force: true, recursive: true });
}
const zeroHashSize = json(["size", "--json", "--target", "linux-musl-x64", "examples/zero-hash", "--out", join(outDir, "zero-hash-sized")]).body;
assert.equal(zeroHashSize.generatedCBytes, 0);
assert(zeroHashSize.usedStdlibHelpers.some((helper) => helper.name === "std.codec.crc32Bytes"));
assert(zeroHashSize.artifactBytes < 100 * 1024);
const invalidCheckEmit = json(["check", "--json", "--emit", "bogus", "examples/hello.graph"], { allowFailure: true });
assert.equal(invalidCheckEmit.code, 1);
assert.equal(invalidCheckEmit.body.ok, false);
assert.equal(invalidCheckEmit.body.diagnostics[0].code, "BLD002");
assert.equal(invalidCheckEmit.body.diagnostics[0].actual, "--emit bogus");
assert.equal(invalidCheckEmit.body.targetReadiness, undefined);
const unknownBackend = json(["check", "--json", "--backend", "bogus", "examples/hello.graph"], { allowFailure: true });
assert.equal(unknownBackend.code, 1);
assert.equal(unknownBackend.body.diagnostics[0].code, "BLD002");
assert.equal(unknownBackend.body.diagnostics[0].actual, "--backend bogus");
assert.match(unknownBackend.body.diagnostics[0].expected, /direct, llvm/);
const unknownBackendWithLlvmEmit = json(["check", "--json", "--emit", "llvm-ir", "--backend", "bogus", "examples/hello.graph"], { allowFailure: true });
assert.equal(unknownBackendWithLlvmEmit.code, 1);
assert.equal(unknownBackendWithLlvmEmit.body.diagnostics[0].code, "BLD002");
assert.equal(unknownBackendWithLlvmEmit.body.diagnostics[0].actual, "--backend bogus");
const llvmReadiness = json(["check", "--json", "--backend", "llvm", "examples/add.graph"]).body;
assert.equal(llvmReadiness.ok, true);
const llvmHostReady = llvmReadiness.targetReadiness.ok;
assert.equal(llvmReadiness.targetReadiness.backend, "llvm");
assert.equal(llvmReadiness.targetReadiness.emit, "exe");
assert.equal(llvmReadiness.targetReadiness.backendLifecycle.stability, "experimental");
assert.equal(llvmReadiness.targetReadiness.backendLifecycle.defaultEligible, false);
assert.equal(llvmReadiness.targetReadiness.backendLifecycle.releaseEligible, false);
if (llvmHostReady) {
assert.equal(llvmReadiness.targetReadiness.stage, "ready");
assert.equal(llvmReadiness.targetReadiness.diagnostics.length, 0);
} else {
assert.equal(llvmReadiness.targetReadiness.diagnostics[0].code, "BLD004");
assert.equal(llvmReadiness.targetReadiness.diagnostics[0].backendBlocker.backend, "llvm");
assert(["toolchain", "target-selection"].includes(llvmReadiness.targetReadiness.stage));
}
const llvmMissingToolReadiness = json(["check", "--json", "--backend", "llvm", "examples/add.graph"], { env: { ZERO_LLVM_CLANG: "/tmp/zero-missing-clang" } }).body;
assert.equal(llvmMissingToolReadiness.ok, true);
assert.equal(llvmMissingToolReadiness.targetReadiness.ok, false);
assert.equal(llvmMissingToolReadiness.targetReadiness.backend, "llvm");
assert.equal(llvmMissingToolReadiness.targetReadiness.stage, "toolchain");
assert.equal(llvmMissingToolReadiness.targetReadiness.diagnostics[0].code, "BLD004");
assert.equal(llvmMissingToolReadiness.targetReadiness.diagnostics[0].backendBlocker.unsupportedFeature, "clang");
const llvmNonExecutableToolPath = join(outDir, "not-executable-clang");
writeFileSync(llvmNonExecutableToolPath, "");
chmodSync(llvmNonExecutableToolPath, 0o644);
const llvmNonExecutableToolReadiness = json(["check", "--json", "--backend", "llvm", "examples/add.graph"], { env: { ZERO_LLVM_CLANG: llvmNonExecutableToolPath } }).body;
assert.equal(llvmNonExecutableToolReadiness.ok, true);
assert.equal(llvmNonExecutableToolReadiness.targetReadiness.ok, false);
assert.equal(llvmNonExecutableToolReadiness.targetReadiness.backend, "llvm");
assert.equal(llvmNonExecutableToolReadiness.targetReadiness.stage, "toolchain");
assert.equal(llvmNonExecutableToolReadiness.targetReadiness.diagnostics[0].code, "BLD004");
assert.match(llvmNonExecutableToolReadiness.targetReadiness.diagnostics[0].actual, /not executable or not found/);
assert.equal(llvmNonExecutableToolReadiness.targetReadiness.diagnostics[0].backendBlocker.unsupportedFeature, "clang");
const llvmIrReadiness = json(["check", "--json", "--emit", "llvm-ir", "--backend", "llvm", "examples/add.graph"]).body;
assert.equal(llvmIrReadiness.ok, true);
assert.equal(llvmIrReadiness.targetReadiness.ok, true);
assert.equal(llvmIrReadiness.targetReadiness.backend, "llvm");
assert.equal(llvmIrReadiness.targetReadiness.emit, "llvm-ir");
assert.equal(llvmIrReadiness.targetReadiness.stage, "ready");
assert.equal(llvmIrReadiness.targetReadiness.diagnostics.length, 0);
const llvmPracticalSubsetExpected = "LLVM IR scalar, fixed-array, and byte-view MIR subset";
for (const fixture of [
"examples/direct-array-sum.graph",
"examples/direct-string-len.graph",
"examples/direct-byte-copy-fill.graph",
"examples/direct-string-eql.graph",
"examples/direct-byte-view-locals.graph",
"examples/direct-span-read.graph",
]) {
const readiness = json(["check", "--json", "--emit", "llvm-ir", "--backend", "llvm", fixture]).body;
assert.equal(readiness.ok, true);
assert.equal(readiness.targetReadiness.ok, true);
assert.equal(readiness.targetReadiness.backend, "llvm");
assert.equal(readiness.targetReadiness.stage, "ready");
assert.equal(readiness.targetReadiness.diagnostics.length, 0);
}
const llvmIrLoweringBlockedReadiness = json(["check", "--json", "--emit", "llvm-ir", "--backend", "llvm", "conformance/agent-surface/fixtures/owned-drop-direct-backend-unsupported.graph"]).body;
assert.equal(llvmIrLoweringBlockedReadiness.ok, true);
assert.equal(llvmIrLoweringBlockedReadiness.targetReadiness.ok, false);
assert.equal(llvmIrLoweringBlockedReadiness.targetReadiness.backend, "llvm");
assert.equal(llvmIrLoweringBlockedReadiness.targetReadiness.stage, "lower");
assert.equal(llvmIrLoweringBlockedReadiness.targetReadiness.diagnostics[0].code, "BLD004");
assert.equal(llvmIrLoweringBlockedReadiness.targetReadiness.diagnostics[0].expected, "typed program graph MIR subset");
assert.equal(llvmIrLoweringBlockedReadiness.targetReadiness.diagnostics[0].actual, "owned<Tracked>");
assert.deepEqual(llvmIrLoweringBlockedReadiness.targetReadiness.diagnostics[0].backendBlocker, {
target: version.host,
objectFormat: version.host.startsWith("win32") ? "coff" : (version.host.startsWith("linux") ? "elf" : "macho"),
backend: "llvm",
stage: "lower",
unsupportedFeature: "owned<Tracked>",
});
const llvmNativeLoweringBlockedReadiness = json(["check", "--json", "--backend", "llvm", "conformance/agent-surface/fixtures/owned-drop-direct-backend-unsupported.graph"]).body;
assert.equal(llvmNativeLoweringBlockedReadiness.ok, true);
assert.equal(llvmNativeLoweringBlockedReadiness.targetReadiness.ok, false);
assert.equal(llvmNativeLoweringBlockedReadiness.targetReadiness.backend, "llvm");
assert.equal(llvmNativeLoweringBlockedReadiness.targetReadiness.stage, "lower");
assert.equal(llvmNativeLoweringBlockedReadiness.targetReadiness.diagnostics[0].code, "BLD004");
assert.equal(llvmNativeLoweringBlockedReadiness.targetReadiness.diagnostics[0].expected, "typed program graph MIR subset");
assert.equal(llvmNativeLoweringBlockedReadiness.targetReadiness.diagnostics[0].actual, "owned<Tracked>");
assert.doesNotMatch(llvmNativeLoweringBlockedReadiness.targetReadiness.diagnostics[0].message, /direct backend/);
const llvmBuild = json(["build", "--json", "--backend", "llvm", "examples/add.graph", "--out", join(outDir, "add-llvm")], { allowFailure: !llvmHostReady });
if (llvmHostReady) {
assert.equal(llvmBuild.code, 0);
assert.equal(llvmBuild.body.emit, "exe");
assert.equal(llvmBuild.body.compiler, llvmBuild.body.toolchain.compiler);
assert.equal(llvmBuild.body.toolchain.driverKind, "clang");
assert.equal(llvmBuild.body.toolchain.status, "ready");
assert.equal(llvmBuild.body.toolchain.backendLifecycle.releaseEligible, false);
assert.equal(llvmBuild.body.releaseTargetContract.backendFamily, "llvm");
assert.equal(llvmBuild.body.releaseTargetContract.backendLifecycle.releaseEligible, false);
assert.equal(llvmBuild.body.releaseTargetContract.artifactKind, "native-executable");
assert.equal(llvmBuild.body.releaseTargetContract.selectedEmitter, "llvm-clang-exe");
assert.equal(llvmBuild.body.releaseTargetContract.fallbackPolicy, "none");
assert.equal(llvmBuild.body.releaseTargetContract.readiness.llvmArtifact, true);
assert.equal(llvmBuild.body.releaseTargetContract.readiness.releaseEligible, false);
assert.equal(llvmBuild.body.releaseTargetContract.determinism.reproducible, false);
assert.equal(llvmBuild.body.releaseTargetContract.determinism.repeatBuildHash, "external-toolchain-not-claimed");
assert.equal(llvmBuild.body.objectBackend.backendFamily, "llvm");
assert.equal(llvmBuild.body.objectBackend.backendLifecycle.releaseEligible, false);
assert.equal(llvmBuild.body.objectBackend.targetFacts.status, "ready");
assert.equal(llvmBuild.body.objectBackend.linking.externalToolchain, llvmBuild.body.toolchain.compiler);
assert.equal(llvmBuild.body.objectBackend.linking.toolchainSource, "llvm-ir-clang-link-plan");
assert.deepEqual(llvmBuild.body.objectBackend.linkerPlan.staticLibraries, ["zero_runtime.o"]);
assert.equal(llvmBuild.body.objectBackend.linkerPlan.reproducible, false);
assert.equal(llvmBuild.body.targetSupport.backendFamily, "llvm");
assert.equal(llvmBuild.body.targetSupport.fallbackPolicy, "none");
assert.equal(llvmBuild.body.targetSupport.backendLifecycle.releaseEligible, false);
assert(llvmBuild.body.artifactBytes > 0);
assert.equal(execFileSync(llvmBuild.body.artifactPath, [], { encoding: "utf8" }), "math works\n");
} else {
assert.notEqual(llvmBuild.code, 0);
assert.equal(llvmBuild.body.diagnostics[0].code, "BLD004");
assert.equal(llvmBuild.body.diagnostics[0].backendBlocker.backend, "llvm");
}
const llvmMissingToolBuild = json(["build", "--json", "--backend", "llvm", "examples/add.graph", "--out", join(outDir, "add-llvm-missing")], { allowFailure: true, env: { ZERO_LLVM_CLANG: "/tmp/zero-missing-clang" } });
assert.notEqual(llvmMissingToolBuild.code, 0);
assert.equal(llvmMissingToolBuild.body.diagnostics[0].code, "BLD004");
assert.equal(llvmMissingToolBuild.body.diagnostics[0].backendBlocker.stage, "toolchain");
assert.equal(llvmMissingToolBuild.body.diagnostics[0].backendBlocker.unsupportedFeature, "clang");
const llvmNativeLoweringBlockedBuild = json(["build", "--json", "--backend", "llvm", "conformance/agent-surface/fixtures/owned-drop-direct-backend-unsupported.graph", "--out", join(outDir, "owned-drop-llvm")], { allowFailure: true });
assert.notEqual(llvmNativeLoweringBlockedBuild.code, 0);
assert.equal(llvmNativeLoweringBlockedBuild.body.diagnostics[0].code, "BLD004");
assert.equal(llvmNativeLoweringBlockedBuild.body.diagnostics[0].expected, "typed program graph MIR subset");
assert.equal(llvmNativeLoweringBlockedBuild.body.diagnostics[0].actual, "owned<Tracked>");
assert.doesNotMatch(llvmNativeLoweringBlockedBuild.body.diagnostics[0].message, /direct backend/);
assert.equal(llvmNativeLoweringBlockedBuild.body.diagnostics[0].backendBlocker.backend, directExeEmitterForTarget(version.host));
assert.equal(llvmNativeLoweringBlockedBuild.body.diagnostics[0].backendBlocker.stage, "lower");
const llvmFailingToolPath = join(outDir, "failing-clang");
writeFileSync(llvmFailingToolPath, "#!/bin/sh\nexit 1\n");
chmodSync(llvmFailingToolPath, 0o755);
const llvmFailingToolRuntimeBuild = json(["build", "--json", "--backend", "llvm", "examples/hello.graph", "--out", join(outDir, "hello-llvm-failing-tool")], { allowFailure: true, env: { ZERO_LLVM_CLANG: llvmFailingToolPath } });
assert.notEqual(llvmFailingToolRuntimeBuild.code, 0);
assert.equal(llvmFailingToolRuntimeBuild.body.diagnostics[0].code, "BLD004");
assert.match(llvmFailingToolRuntimeBuild.body.diagnostics[0].message, /LLVM runtime object build failed/);
assert.equal(llvmFailingToolRuntimeBuild.body.diagnostics[0].backendBlocker.backend, "llvm");
assert.equal(llvmFailingToolRuntimeBuild.body.diagnostics[0].backendBlocker.stage, "toolchain");
assert.equal(llvmFailingToolRuntimeBuild.body.diagnostics[0].backendBlocker.unsupportedFeature, "clang");
const llvmFailingToolLinkBuild = json(["build", "--json", "--backend", "llvm", "examples/direct-exe-return.graph", "--out", join(outDir, "return-llvm-failing-tool")], { allowFailure: true, env: { ZERO_LLVM_CLANG: llvmFailingToolPath } });
assert.notEqual(llvmFailingToolLinkBuild.code, 0);
assert.equal(llvmFailingToolLinkBuild.body.diagnostics[0].code, "BLD004");
assert.match(llvmFailingToolLinkBuild.body.diagnostics[0].message, /LLVM executable link failed/);
assert.equal(llvmFailingToolLinkBuild.body.diagnostics[0].backendBlocker.backend, "llvm");
assert.equal(llvmFailingToolLinkBuild.body.diagnostics[0].backendBlocker.stage, "toolchain");
assert.equal(llvmFailingToolLinkBuild.body.diagnostics[0].backendBlocker.unsupportedFeature, "clang");
const llvmNoOutputToolPath = join(outDir, "no-output-clang");
const llvmNoOutputArtifactPath = join(outDir, "return-llvm-no-output-tool");
writeFileSync(llvmNoOutputToolPath, "#!/bin/sh\nexit 0\n");
chmodSync(llvmNoOutputToolPath, 0o755);
writeFileSync(llvmNoOutputArtifactPath, "stale executable\n");
const llvmNoOutputToolBuild = json(["build", "--json", "--backend", "llvm", "examples/direct-exe-return.graph", "--out", llvmNoOutputArtifactPath], { allowFailure: true, env: { ZERO_LLVM_CLANG: llvmNoOutputToolPath } });
assert.notEqual(llvmNoOutputToolBuild.code, 0);
assert.equal(llvmNoOutputToolBuild.body.diagnostics[0].code, "BLD004");
assert.match(llvmNoOutputToolBuild.body.diagnostics[0].message, /LLVM executable link failed/);
assert.equal(llvmNoOutputToolBuild.body.diagnostics[0].backendBlocker.backend, "llvm");
assert.equal(llvmNoOutputToolBuild.body.diagnostics[0].backendBlocker.stage, "toolchain");
assert.equal(llvmNoOutputToolBuild.body.diagnostics[0].backendBlocker.unsupportedFeature, "clang");
assert.equal(existsSync(llvmNoOutputArtifactPath), false);
const llvmIrBuild = json(["build", "--json", "--emit", "llvm-ir", "examples/add.graph", "--out", join(outDir, "add.ll")], { allowFailure: true });
assert.notEqual(llvmIrBuild.code, 0);
assert.equal(llvmIrBuild.body.diagnostics[0].code, "BLD004");
assert.equal(llvmIrBuild.body.diagnostics[0].actual, "backend=direct emit=llvm-ir");
const explicitLlvmIrBuild = json(["build", "--json", "--emit", "llvm-ir", "--backend", "llvm", "examples/add.graph", "--out", join(outDir, "add-explicit.ll")]);
assert.equal(explicitLlvmIrBuild.code, 0);
assert.equal(explicitLlvmIrBuild.body.emit, "llvm-ir");
assert.equal(explicitLlvmIrBuild.body.compiler, "zero-c-llvm-ir");
assert.equal(explicitLlvmIrBuild.body.generatedCBytes, 0);
assert.equal(explicitLlvmIrBuild.body.toolchain.driverKind, "none");
assert.equal(explicitLlvmIrBuild.body.toolchain.selectionSource, "not-required");
assert.equal(explicitLlvmIrBuild.body.targetSupport.backendFamily, "llvm");
assert.equal(explicitLlvmIrBuild.body.targetSupport.llvmStatus, "ir-only");
assert.equal(explicitLlvmIrBuild.body.targetSupport.backendLifecycle.releaseEligible, false);
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.backendFamily, "llvm");
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.backendLifecycle.releaseEligible, false);
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.artifactKind, "llvm-ir");
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.selectedEmitter, "llvm-ir");
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.linkerFlavor, "none");
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.targetLinker, "none");
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.fallbackPolicy, "none");
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.libc.artifactMode, "none");
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.sysroot.requiredByArtifact, false);
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.readiness.status, "supported");
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.readiness.directArtifact, false);
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.readiness.llvmArtifact, true);
assert.equal(explicitLlvmIrBuild.body.releaseTargetContract.readiness.releaseEligible, false);
assert.equal(explicitLlvmIrBuild.body.objectBackend.backendFamily, "llvm");
assert.equal(explicitLlvmIrBuild.body.objectBackend.backendLifecycle.releaseEligible, false);
assert.equal(explicitLlvmIrBuild.body.objectBackend.targetFacts.status, "ir-only");
assert.equal(explicitLlvmIrBuild.body.objectBackend.linking.targetLibraries, "zero-runtime");
assert.equal(explicitLlvmIrBuild.body.objectBackend.linking.externalToolchain, "none");
assert.equal(explicitLlvmIrBuild.body.objectBackend.linking.toolchainSource, "textual-llvm-ir-runtime-link-plan");
assert.deepEqual(explicitLlvmIrBuild.body.objectBackend.linkerPlan.staticLibraries, ["zero_runtime.o"]);
assert.match(explicitLlvmIrBuild.body.objectBackend.targetFacts.reason, /native host executable output/);
assert.equal(explicitLlvmIrBuild.body.artifactPath, join(outDir, "add-explicit.ll"));
assert(explicitLlvmIrBuild.body.artifactBytes > 0);
const explicitLlvmIrText = readFileSync(explicitLlvmIrBuild.body.artifactPath, "utf8");
assert.match(explicitLlvmIrText, /^; zero llvm-ir v1\n/);
assert.match(explicitLlvmIrText, /target triple = "/);
assert.match(explicitLlvmIrText, /define i32 @main\(\)/);
assert.match(explicitLlvmIrText, /declare i32 @zero_world_write\(i32, ptr, i32\)/);
assert.match(explicitLlvmIrText, /declare void @llvm\.trap\(\)/);
assert.match(explicitLlvmIrText, /call i32 @zero_world_write\(i32 1, ptr %v[0-9]+, i32 (?:11|%v[0-9]+)\)/);
assert.match(explicitLlvmIrText, /%v[0-9]+ = call i32 @zero_world_write\(i32 1, ptr %v[0-9]+, i32 (?:11|%v[0-9]+)\)\n %v[0-9]+ = icmp eq i32 %v[0-9]+, 0\n br i1 %v[0-9]+, label %L[0-9]+, label %L[0-9]+\nL[0-9]+:\n call void @llvm\.trap\(\)\n unreachable\nL[0-9]+:/);
const llvmIrLoweringBlockedBuild = json(["build", "--json", "--emit", "llvm-ir", "--backend", "llvm", "conformance/agent-surface/fixtures/owned-drop-direct-backend-unsupported.graph", "--out", join(outDir, "owned-drop.ll")], { allowFailure: true });
assert.notEqual(llvmIrLoweringBlockedBuild.code, 0);
assert.equal(llvmIrLoweringBlockedBuild.body.diagnostics[0].code, "BLD004");
assert.equal(llvmIrLoweringBlockedBuild.body.diagnostics[0].expected, "typed program graph MIR subset");
assert.equal(llvmIrLoweringBlockedBuild.body.diagnostics[0].actual, "owned<Tracked>");
assert.equal(llvmIrLoweringBlockedBuild.body.diagnostics[0].backendBlocker.backend, directExeEmitterForTarget(version.host));
assert.equal(llvmIrLoweringBlockedBuild.body.diagnostics[0].backendBlocker.stage, "lower");
assert.equal(llvmIrLoweringBlockedBuild.body.diagnostics[0].backendBlocker.unsupportedFeature, "owned<Tracked>");
const directLlvmIrReadiness = json(["check", "--json", "--emit", "llvm-ir", "--backend", "direct", "examples/add.graph"]).body;
assert.equal(directLlvmIrReadiness.ok, true);
assert.equal(directLlvmIrReadiness.targetReadiness.ok, false);
assert.equal(directLlvmIrReadiness.targetReadiness.diagnostics[0].actual, "backend=direct emit=llvm-ir");
assert.equal(directLlvmIrReadiness.targetReadiness.diagnostics[0].backendBlocker.backend, "direct");
assert.equal(directLlvmIrReadiness.targetReadiness.diagnostics[0].backendBlocker.stage, "buildability");
const directLlvmIrBuild = json(["build", "--json", "--emit", "llvm-ir", "--backend", "direct", "examples/add.graph", "--out", join(outDir, "add-direct.ll")], { allowFailure: true });
assert.notEqual(directLlvmIrBuild.code, 0);
assert.equal(directLlvmIrBuild.body.diagnostics[0].actual, "backend=direct emit=llvm-ir");
const llvmGraphCheck = json(["check", "--json", "--backend", "llvm", "examples/add.graph"]).body;
assert.equal(llvmGraphCheck.ok, true);
assert.equal(llvmGraphCheck.targetReadiness.ok, llvmHostReady);
assert.equal(llvmGraphCheck.targetReadiness.backend, "llvm");
if (llvmHostReady) {
assert.equal(llvmGraphCheck.targetReadiness.stage, "ready");
assert.equal(llvmGraphCheck.targetReadiness.diagnostics.length, 0);
} else {
assert.equal(llvmGraphCheck.targetReadiness.diagnostics[0].backendBlocker.backend, "llvm");
}
const llvmIrGraphCheck = json(["check", "--json", "--emit", "llvm-ir", "--backend", "llvm", "examples/add.graph"]).body;
assert.equal(llvmIrGraphCheck.ok, true);
assert.equal(llvmIrGraphCheck.targetReadiness.ok, true);
assert.equal(llvmIrGraphCheck.targetReadiness.backend, "llvm");
assert.equal(llvmIrGraphCheck.targetReadiness.stage, "ready");
const directLlvmIrGraphCheck = json(["check", "--json", "--emit", "llvm-ir", "--backend", "direct", "examples/add.graph"]).body;
assert.equal(directLlvmIrGraphCheck.ok, true);
assert.equal(directLlvmIrGraphCheck.targetReadiness.ok, false);
assert.equal(directLlvmIrGraphCheck.targetReadiness.diagnostics[0].backendBlocker.backend, "direct");
const llvmSize = json(["size", "--json", "--backend", "llvm", "examples/add.graph"]);
assert.equal(llvmSize.body.targetSupport.backendFamily, "llvm");
assert.equal(llvmSize.body.targetSupport.fallbackPolicy, "none");
assert.equal(llvmSize.body.targetSupport.backendLifecycle.releaseEligible, false);
assert.equal(llvmSize.body.backendProfile.backendFamily, "llvm");
assert.equal(llvmSize.body.backendProfile.backendLifecycle.releaseEligible, false);
assert.equal(llvmSize.body.backendProfile.selectedEmitter, "llvm-clang-exe");
assert.equal(llvmSize.body.backendProfile.targetTriple, llvmSize.body.targetSupport.llvmTargetTriple);
assert.equal(llvmSize.body.backendProfile.optimizationLevel, "-Oz");
assert.equal(llvmSize.body.backendProfile.retained.functionCount + llvmSize.body.backendProfile.retained.runtimeHelperCount, llvmSize.body.objectBackend.objectEmission.symbolCount);
assert.equal(llvmSize.body.objectBackend.backendFamily, "llvm");
assert.equal(llvmSize.body.objectBackend.backendLifecycle.releaseEligible, false);
assert.equal(llvmSize.body.objectBackend.targetFacts.fallbackPolicy, "none");
assert.equal(llvmSize.body.backendComparison.rows.length, 4);
assert(llvmSize.body.backendComparison.rows.some((row) => row.id === "direct-debug" && row.backendFamily === "direct"));
assert(llvmSize.body.backendComparison.rows.some((row) => row.id === "llvm-no-opt" && row.backendFamily === "llvm" && row.optimizationLevel === "-O0"));
const llvmGraphSize = json(["size", "--json", "--backend", "llvm", graphDumpPath]);
assert.equal(llvmGraphSize.body.graph.artifact, graphDumpPath);
assert.equal(llvmGraphSize.body.targetSupport.backendFamily, "llvm");
assert.equal(llvmGraphSize.body.backendProfile.backendFamily, "llvm");
const llvmIrSize = json(["size", "--json", "--emit", "llvm-ir", "--backend", "llvm", "examples/add.graph"], { allowFailure: true });
assert.notEqual(llvmIrSize.code, 0);
assert.equal(llvmIrSize.body.diagnostics[0].code, "BLD004");
assert.match(llvmIrSize.body.diagnostics[0].message, /writes artifacts only through zero build/);
assert.equal(llvmIrSize.body.diagnostics[0].actual, "size --backend llvm --emit llvm-ir");
assert.equal(llvmIrSize.body.diagnostics[0].backendBlocker.unsupportedFeature, "llvm-ir command");
const llvmIrGraphSize = json(["size", "--json", "--emit", "llvm-ir", "--backend", "llvm", graphDumpPath], { allowFailure: true });
assert.notEqual(llvmIrGraphSize.code, 0);
assert.equal(llvmIrGraphSize.body.diagnostics[0].code, "BLD004");
assert.equal(llvmIrGraphSize.body.diagnostics[0].actual, "size --backend llvm --emit llvm-ir");
assert.equal(llvmIrGraphSize.body.diagnostics[0].backendBlocker.unsupportedFeature, "llvm-ir command");
const directLlvmIrSize = json(["size", "--json", "--emit", "llvm-ir", "--backend", "direct", "examples/add.graph"], { allowFailure: true });
assert.notEqual(directLlvmIrSize.code, 0);
assert.equal(directLlvmIrSize.body.diagnostics[0].actual, "backend=direct emit=llvm-ir");
const llvmMem = json(["mem", "--json", "--backend", "llvm", "examples/add.graph"], { allowFailure: true });
assert.notEqual(llvmMem.code, 0);
assert.equal(llvmMem.body.diagnostics[0].code, "BLD004");
assert.equal(llvmMem.body.diagnostics[0].backendBlocker.backend, "llvm");
assert.equal(llvmMem.body.diagnostics[0].backendBlocker.stage, "buildability");
const llvmIrMem = json(["mem", "--json", "--emit", "llvm-ir", "--backend", "llvm", "examples/add.graph"], { allowFailure: true });
assert.notEqual(llvmIrMem.code, 0);
assert.equal(llvmIrMem.body.diagnostics[0].code, "BLD004");
assert.equal(llvmIrMem.body.diagnostics[0].actual, "mem --backend llvm --emit llvm-ir");
assert.equal(llvmIrMem.body.diagnostics[0].backendBlocker.unsupportedFeature, "llvm-ir command");
const directLlvmIrMem = json(["mem", "--json", "--emit", "llvm-ir", "--backend", "direct", "examples/add.graph"], { allowFailure: true });
assert.notEqual(directLlvmIrMem.code, 0);
assert.equal(directLlvmIrMem.body.diagnostics[0].actual, "backend=direct emit=llvm-ir");
const llvmIrRun = zero(["run", "--emit", "llvm-ir", "--backend", "llvm", "examples/add.graph"], { allowFailure: true });
assert.notEqual(llvmIrRun.code, 0);
assert.match(llvmIrRun.stderr, /BLD004: LLVM IR emission writes artifacts only through zero build/);
assert.match(llvmIrRun.stderr, /actual: run --backend llvm --emit llvm-ir/);
const directLlvmIrRun = zero(["run", "--emit", "llvm-ir", "--backend", "direct", "examples/add.graph"], { allowFailure: true });
assert.notEqual(directLlvmIrRun.code, 0);
assert.match(directLlvmIrRun.stderr, /BLD004: direct backend does not support --emit llvm-ir/);
assert.match(directLlvmIrRun.stderr, /actual: backend=direct emit=llvm-ir/);
const llvmIrGraphRun = zero(["run", "--emit", "llvm-ir", "--backend", "llvm", graphDumpPath], { allowFailure: true });
assert.notEqual(llvmIrGraphRun.code, 0);
assert.match(llvmIrGraphRun.stderr, /BLD004: LLVM IR emission writes artifacts only through zero build/);
assert.match(llvmIrGraphRun.stderr, /actual: run --backend llvm --emit llvm-ir/);
const llvmTest = json(["test", "--json", "--backend", "llvm", "conformance/native/pass/test-blocks.graph"], { allowFailure: true });
assert.equal(llvmTest.code, 0);
assert.equal(llvmTest.body.ok, true);
assert.equal(llvmTest.body.graph.artifact, "conformance/native/pass/test-blocks.graph");
assert.equal(llvmTest.body.testBackend, "direct-program-graph");
const llvmIrTest = json(["test", "--json", "--emit", "llvm-ir", "--backend", "llvm", "conformance/native/pass/test-blocks.graph"], { allowFailure: true });
assert.notEqual(llvmIrTest.code, 0);
assert.equal(llvmIrTest.body.diagnostics[0].code, "BLD004");
assert.equal(llvmIrTest.body.diagnostics[0].actual, "test --backend llvm --emit llvm-ir");
assert.equal(llvmIrTest.body.diagnostics[0].backendBlocker.unsupportedFeature, "llvm-ir command");
const directLlvmIrTest = json(["test", "--json", "--emit", "llvm-ir", "--backend", "direct", "conformance/native/pass/test-blocks.graph"], { allowFailure: true });
assert.notEqual(directLlvmIrTest.code, 0);
assert.equal(directLlvmIrTest.body.diagnostics[0].actual, "backend=direct emit=llvm-ir");
const mismatchedDirectSize = json(["size", "--json", "--backend", "zero-coff-x64", "--target", "linux-x64", "examples/add.graph"], { allowFailure: true });
assert.notEqual(mismatchedDirectSize.code, 0);
assert.equal(mismatchedDirectSize.body.diagnostics[0].actual, "--backend zero-coff-x64");
assert.equal(mismatchedDirectSize.body.diagnostics[0].backendBlocker.backend, "zero-coff-x64");
assert.equal(mismatchedDirectSize.body.diagnostics[0].backendBlocker.stage, "target-selection");
const mismatchedDirectMem = json(["mem", "--json", "--backend", "zero-coff-x64", "--target", "linux-x64", "examples/add.graph"], { allowFailure: true });
assert.notEqual(mismatchedDirectMem.code, 0);
assert.equal(mismatchedDirectMem.body.diagnostics[0].actual, "--backend zero-coff-x64");
assert.equal(mismatchedDirectMem.body.diagnostics[0].backendBlocker.backend, "zero-coff-x64");
assert.equal(mismatchedDirectMem.body.diagnostics[0].backendBlocker.stage, "target-selection");
const mismatchedDirectGraphSize = json(["size", "--json", "--backend", "zero-coff-x64", "--target", "linux-x64", graphDumpPath], { allowFailure: true });
assert.notEqual(mismatchedDirectGraphSize.code, 0);
assert.equal(mismatchedDirectGraphSize.body.diagnostics[0].actual, "--backend zero-coff-x64");
assert.equal(mismatchedDirectGraphSize.body.diagnostics[0].backendBlocker.backend, "zero-coff-x64");
assert.equal(mismatchedDirectGraphSize.body.diagnostics[0].backendBlocker.stage, "target-selection");
const mismatchedDirectTest = json(["test", "--json", "--backend", "zero-coff-x64", "--target", "linux-x64", "conformance/native/pass/test-blocks.graph"], { allowFailure: true });
assert.equal(mismatchedDirectTest.code, 0);
assert.equal(mismatchedDirectTest.body.ok, true);
assert.equal(mismatchedDirectTest.body.graph.artifact, "conformance/native/pass/test-blocks.graph");
assert.equal(mismatchedDirectTest.body.testBackend, "direct-program-graph");
const llvmGraphTest = json(["test", "--json", "--backend", "llvm", graphTestDumpPath], { allowFailure: true });
assert.equal(llvmGraphTest.code, 0);
assert.equal(llvmGraphTest.body.ok, true);
assert.equal(llvmGraphTest.body.testBackend, "direct-program-graph");
assert.equal(llvmGraphTest.body.graph.lowering, "direct-program-graph");
const directLlvmIrGraphTest = json(["test", "--json", "--emit", "llvm-ir", "--backend", "direct", graphTestDumpPath], { allowFailure: true });
assert.notEqual(directLlvmIrGraphTest.code, 0);
assert.equal(directLlvmIrGraphTest.body.diagnostics[0].actual, "backend=direct emit=llvm-ir");
const mismatchedDirectObjReadiness = json(["check", "--json", "--emit", "obj", "--backend", "zero-coff-x64", "--target", "linux-x64", "examples/add.graph"]).body;
assert.equal(mismatchedDirectObjReadiness.ok, true);
assert.equal(mismatchedDirectObjReadiness.targetReadiness.ok, false);
assert.equal(mismatchedDirectObjReadiness.targetReadiness.diagnostics[0].actual, "--backend zero-coff-x64");
assert.equal(mismatchedDirectObjReadiness.targetReadiness.diagnostics[0].backendBlocker.backend, "zero-coff-x64");
assert.equal(mismatchedDirectObjReadiness.targetReadiness.diagnostics[0].backendBlocker.stage, "target-selection");
const mismatchedDirectObjBuild = json(["build", "--json", "--emit", "obj", "--backend", "zero-coff-x64", "--target", "linux-x64", "examples/add.graph", "--out", join(outDir, "mismatch.obj")], { allowFailure: true });
assert.notEqual(mismatchedDirectObjBuild.code, 0);
assert.equal(mismatchedDirectObjBuild.body.diagnostics[0].actual, "--backend zero-coff-x64");
assert.equal(mismatchedDirectObjBuild.body.diagnostics[0].backendBlocker.backend, "zero-coff-x64");
assert.equal(mismatchedDirectObjBuild.body.diagnostics[0].backendBlocker.stage, "target-selection");
const mismatchedDirectExeBuild = json(["build", "--json", "--emit", "exe", "--backend", "zero-coff-x64", "--target", "linux-musl-x64", "examples/direct-exe-return.graph", "--out", join(outDir, "mismatch-exe")], { allowFailure: true });
assert.notEqual(mismatchedDirectExeBuild.code, 0);
assert.equal(mismatchedDirectExeBuild.body.diagnostics[0].actual, "--backend zero-coff-x64");
assert.equal(mismatchedDirectExeBuild.body.diagnostics[0].expected, "direct emitter zero-elf64 for target linux-musl-x64");
assert.match(mismatchedDirectExeBuild.body.diagnostics[0].help, /--backend zero-elf64/);
assert.equal(mismatchedDirectExeBuild.body.diagnostics[0].backendBlocker.stage, "target-selection");
const backendBlockedReadiness = json(["check", "--json", "--emit", "obj", "--target", "linux-musl-x64", "conformance/agent-surface/fixtures/owned-drop-direct-backend-unsupported.graph"]).body;
assert.equal(backendBlockedReadiness.ok, true);
assert.equal(backendBlockedReadiness.diagnostics.length, 0);
assert.equal(backendBlockedReadiness.targetReadiness.ok, false);
assert.equal(backendBlockedReadiness.targetReadiness.buildable, false);
assert.equal(backendBlockedReadiness.targetReadiness.languageOk, true);
assert.equal(backendBlockedReadiness.targetReadiness.emit, "obj");
assert.equal(backendBlockedReadiness.targetReadiness.target, "linux-musl-x64");
assert.equal(backendBlockedReadiness.targetReadiness.diagnostics[0].code, "BLD004");
assert.deepEqual(backendBlockedReadiness.targetReadiness.diagnostics[0].backendBlocker, {
target: "linux-musl-x64",
objectFormat: "elf",
backend: "zero-elf64",
stage: "lower",
unsupportedFeature: "owned<Tracked>",
});
const directExeBlockedReadiness = json(["check", "--json", "--emit", "exe", "--target", "linux-musl-x64", "examples/direct-call-add.graph"]).body;
assert.equal(directExeBlockedReadiness.ok, true);
assert.equal(directExeBlockedReadiness.diagnostics.length, 0);
assert.equal(directExeBlockedReadiness.targetReadiness.ok, false);
assert.equal(directExeBlockedReadiness.targetReadiness.buildable, false);
assert.equal(directExeBlockedReadiness.targetReadiness.languageOk, true);
assert.equal(directExeBlockedReadiness.targetReadiness.emit, "exe");
assert.equal(directExeBlockedReadiness.targetReadiness.target, "linux-musl-x64");
assert.equal(directExeBlockedReadiness.targetReadiness.diagnostics[0].code, "BLD004");
assert.equal(directExeBlockedReadiness.targetReadiness.diagnostics[0].backendBlocker.stage, "buildability");
assert.match(directExeBlockedReadiness.targetReadiness.diagnostics[0].message, /main must not take parameters/);
const directExeBlockedBuild = json(["build", "--json", "--emit", "exe", "--target", "linux-musl-x64", "examples/direct-call-add.graph", "--out", join(outDir, "direct-call-add-blocked")], { allowFailure: true });
assert.notEqual(directExeBlockedBuild.code, 0);
for (const key of ["code", "path", "line", "column", "length", "expected", "actual", "help"]) {
assert.equal(directExeBlockedBuild.body.diagnostics[0][key], directExeBlockedReadiness.targetReadiness.diagnostics[0][key]);
}
assert.equal(directExeBlockedBuild.body.diagnostics[0].backendBlocker.stage, "buildability");
const directExeBlockedGraph = json(["inspect", "--json", "--emit", "exe", "--target", "linux-musl-x64", "examples/direct-call-add.0"]).body;
assert.equal(directExeBlockedGraph.targetReadiness.ok, false);
assert.equal(directExeBlockedGraph.targetReadiness.diagnostics[0].code, "BLD004");
assert.equal(directExeBlockedGraph.targetReadiness.diagnostics[0].path, "direct-call-add.0");
assert.equal(directExeBlockedGraph.targetReadiness.diagnostics[0].actual, "unsupported construct");
assert.equal(directExeBlockedGraph.targetReadiness.diagnostics[0].backendBlocker.stage, "lower");
const coffMaybeByteViewFixture = "conformance/native/pass/coff-maybe-byte-view-buildable.graph";
const coffMaybeByteViewReadiness = json(["check", "--json", "--emit", "obj", "--target", "win32-x64.exe", coffMaybeByteViewFixture]).body;
assert.equal(coffMaybeByteViewReadiness.ok, true);
assert.equal(coffMaybeByteViewReadiness.targetReadiness.ok, true);
assert.equal(coffMaybeByteViewReadiness.targetReadiness.buildable, true);
assert.equal(coffMaybeByteViewReadiness.targetReadiness.backend, "zero-coff-x64");
const coffMaybeByteViewBuild = json(["build", "--json", "--emit", "obj", "--target", "win32-x64.exe", coffMaybeByteViewFixture, "--out", join(outDir, "coff-maybe-byte-view.obj")]).body;
assert.equal(coffMaybeByteViewBuild.objectBackend.objectEmission.path, "direct-coff-x64-object");
assert.equal(coffMaybeByteViewBuild.generatedCBytes, 0);
const coffDynamicSliceFixture = "conformance/native/pass/coff-dynamic-byte-slice.graph";
const coffDynamicSliceReadiness = json(["check", "--json", "--emit", "obj", "--target", "win32-x64.exe", coffDynamicSliceFixture]).body;
assert.equal(coffDynamicSliceReadiness.ok, true);
assert.equal(coffDynamicSliceReadiness.diagnostics.length, 0);
assert.equal(coffDynamicSliceReadiness.targetReadiness.ok, true);
assert.equal(coffDynamicSliceReadiness.targetReadiness.buildable, true);
assert.equal(coffDynamicSliceReadiness.targetReadiness.languageOk, true);
assert.equal(coffDynamicSliceReadiness.targetReadiness.emit, "obj");
assert.equal(coffDynamicSliceReadiness.targetReadiness.target, "win32-x64.exe");
assert.equal(coffDynamicSliceReadiness.targetReadiness.backend, "zero-coff-x64");
const coffDynamicSlicePath = join(outDir, "coff-dynamic-byte-slice.obj");
const coffDynamicSliceBuild = json(["build", "--json", "--emit", "obj", "--target", "win32-x64.exe", coffDynamicSliceFixture, "--out", coffDynamicSlicePath]).body;
assert.equal(coffDynamicSliceBuild.objectBackend.objectEmission.path, "direct-coff-x64-object");
assert.equal(coffDynamicSliceBuild.generatedCBytes, 0);
const coffDynamicSliceBytes = readFileSync(coffDynamicSlicePath);
assert.equal(coffDynamicSliceBytes.readUInt16LE(0), 0x8664);
const coffBoolCopyFixture = "conformance/native/pass/std-mem-bool-copy-items.graph";
const coffBoolCopyReadiness = json(["check", "--json", "--emit", "obj", "--target", "win32-x64.exe", coffBoolCopyFixture]).body;
assert.equal(coffBoolCopyReadiness.ok, true);
assert.equal(coffBoolCopyReadiness.targetReadiness.ok, true);
assert.equal(coffBoolCopyReadiness.targetReadiness.buildable, true);
assert.equal(coffBoolCopyReadiness.targetReadiness.backend, "zero-coff-x64");
const coffBoolCopyPath = join(outDir, "coff-bool-copy-items.obj");
const coffBoolCopyBuild = json(["build", "--json", "--emit", "obj", "--target", "win32-x64.exe", coffBoolCopyFixture, "--out", coffBoolCopyPath]).body;
assert.equal(coffBoolCopyBuild.objectBackend.objectEmission.path, "direct-coff-x64-object");
assert.equal(coffBoolCopyBuild.generatedCBytes, 0);
const coffBoolCopyBytes = readFileSync(coffBoolCopyPath);
assert.equal(coffBoolCopyBytes.readUInt16LE(0), 0x8664);
function assertMachOObjectBuildabilityBlocked(fixture: string, outName: string, expectedMessage: RegExp) {
const readiness = json(["check", "--json", "--emit", "obj", "--target", "darwin-arm64", fixture]).body;
assert.equal(readiness.ok, true);
assert.equal(readiness.diagnostics.length, 0);
assert.equal(readiness.targetReadiness.ok, false);
assert.equal(readiness.targetReadiness.buildable, false);
assert.equal(readiness.targetReadiness.languageOk, true);
assert.equal(readiness.targetReadiness.emit, "obj");
assert.equal(readiness.targetReadiness.target, "darwin-arm64");
assert.equal(readiness.targetReadiness.diagnostics[0].code, "BLD004");
assert.equal(readiness.targetReadiness.diagnostics[0].backendBlocker.backend, "zero-macho64");
assert.equal(readiness.targetReadiness.diagnostics[0].backendBlocker.stage, "buildability");
assert.match(readiness.targetReadiness.diagnostics[0].message, expectedMessage);
const build = json(["build", "--json", "--emit", "obj", "--target", "darwin-arm64", fixture, "--out", join(outDir, outName)], { allowFailure: true });
assert.notEqual(build.code, 0);
for (const key of ["code", "path", "line", "column", "length", "expected", "actual", "help"]) {
assert.equal(build.body.diagnostics[0][key], readiness.targetReadiness.diagnostics[0][key]);
}
assert.equal(build.body.diagnostics[0].backendBlocker.backend, "zero-macho64");
assert.equal(build.body.diagnostics[0].backendBlocker.stage, "buildability");
}
assertMachOObjectBuildabilityBlocked(
"conformance/native/pass/macho-large-byte-slice-blocked.graph",
"macho-large-byte-slice.o",
/constant start/,
);
assertMachOObjectBuildabilityBlocked(
"conformance/native/pass/macho-nested-call-scratch-blocked.graph",
"macho-nested-call-scratch.o",
/scratch spill capacity/,
);
const machoOpenByteSliceFixture = "conformance/native/pass/macho-open-byte-slice.graph";
const machoOpenByteSliceReadiness = json(["check", "--json", "--emit", "obj", "--target", "darwin-arm64", machoOpenByteSliceFixture]).body;
assert.equal(machoOpenByteSliceReadiness.ok, true);
assert.equal(machoOpenByteSliceReadiness.diagnostics.length, 0);
assert.equal(machoOpenByteSliceReadiness.targetReadiness.ok, true);
assert.equal(machoOpenByteSliceReadiness.targetReadiness.buildable, true);
assert.equal(machoOpenByteSliceReadiness.targetReadiness.backend, "zero-macho64");
const machoOpenByteSlicePath = join(outDir, "macho-open-byte-slice.o");
const machoOpenByteSliceBuild = json(["build", "--json", "--emit", "obj", "--target", "darwin-arm64", machoOpenByteSliceFixture, "--out", machoOpenByteSlicePath]).body;
const machoOpenByteSliceBytes = readFileSync(machoOpenByteSlicePath);
assert.equal(machoOpenByteSliceBuild.compiler, "zero-macho64");
assert.equal(machoOpenByteSliceBuild.generatedCBytes, 0);
assert.equal(machoOpenByteSliceBuild.objectBackend.objectEmission.path, "direct-macho64-object");
assert.equal(machoOpenByteSliceBytes.readUInt32LE(0), 0xfeedfacf);
const aarch64OpenSliceBoundsFixture = join(outDir, "aarch64-open-byte-slice-bounds.0");
writeProjectionFile(aarch64OpenSliceBoundsFixture, `export c fn main() -> u32 {
let words: [2]u16 = [1_u16, 2_u16]
let suffix: Span<u16> = words[3_usize..]
return (std.mem.len(suffix)) as u32
}
`);
const aarch64OpenSliceBoundsGraph = importProjectionSidecar(aarch64OpenSliceBoundsFixture);
const aarch64OpenSliceBoundsPath = join(outDir, "aarch64-open-byte-slice-bounds.o");
json(["build", "--json", "--emit", "obj", "--target", "linux-arm64", aarch64OpenSliceBoundsGraph, "--out", aarch64OpenSliceBoundsPath]);
const aarch64OpenSliceBoundsBytes = readFileSync(aarch64OpenSliceBoundsPath);
assert.equal(aarch64OpenSliceBoundsBytes.readUInt16LE(16), 1);
assert.equal(aarch64OpenSliceBoundsBytes.readUInt16LE(18), 183);
assert(hasAarch64CondBranch(aarch64OpenSliceBoundsBytes, 9));
assert(hasAarch64Instruction(aarch64OpenSliceBoundsBytes, 0xd4200000));
const machoOpenSliceBoundsPath = join(outDir, "macho-open-byte-slice-bounds.o");
json(["build", "--json", "--emit", "obj", "--target", "darwin-arm64", aarch64OpenSliceBoundsGraph, "--out", machoOpenSliceBoundsPath]);
const machoOpenSliceBoundsBytes = readFileSync(machoOpenSliceBoundsPath);
assert.equal(machoOpenSliceBoundsBytes.readUInt32LE(0), 0xfeedfacf);
assert(hasAarch64CondBranch(machoOpenSliceBoundsBytes, 9));
assert(hasAarch64Instruction(machoOpenSliceBoundsBytes, 0xd4200000));
const machOMemoryPackageReadiness = json(["check", "--json", "--emit", "obj", "--target", "darwin-arm64", "examples/memory-package"]).body;
assert.equal(machOMemoryPackageReadiness.ok, true);
assert.equal(machOMemoryPackageReadiness.diagnostics.length, 0);
assert.equal(machOMemoryPackageReadiness.targetReadiness.ok, true);
assert.equal(machOMemoryPackageReadiness.targetReadiness.buildable, true);
assert.equal(machOMemoryPackageReadiness.targetReadiness.languageOk, true);
assert.equal(machOMemoryPackageReadiness.targetReadiness.emit, "obj");
assert.equal(machOMemoryPackageReadiness.targetReadiness.target, "darwin-arm64");
assert.equal(machOMemoryPackageReadiness.targetReadiness.backend, "zero-macho64");
const machOMemoryPackagePath = join(outDir, "direct-darwin-arm64-memory-package.o");
rmSync(machOMemoryPackagePath, { force: true });
const machOMemoryPackageReport = json(["build", "--json", "--emit", "obj", "--target", "darwin-arm64", "examples/memory-package", "--out", machOMemoryPackagePath]).body;
const machOMemoryPackageBytes = readFileSync(machOMemoryPackagePath);
assert.equal(machOMemoryPackageReport.compiler, "zero-macho64");
assert.equal(machOMemoryPackageReport.generatedCBytes, 0);
assert.equal(machOMemoryPackageReport.objectBackend.objectEmission.path, "direct-macho64-object");
assert.equal(machOMemoryPackageReport.objectBackend.directFacts.moduleCount, 3);
assert.equal(machOMemoryPackageReport.objectBackend.directFacts.runtimeHelperCount, 1);
assert.equal(machOMemoryPackageBytes.readUInt32LE(0), 0xfeedfacf);
assert(machOMemoryPackageBytes.includes(Buffer.from("memory package ok")));
// Package builds must be byte-deterministic: emitting the same package through
// the store-backed manifest pipeline twice must produce identical object bytes,
// so toolchain or allocation randomness can never leak into emitted artifacts.
const crmApiDeterminismPath = join(outDir, "determinism-crm-api.o");
rmSync(crmApiDeterminismPath, { force: true });
const crmApiDeterminismReport = json(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/crm-api", "--out", crmApiDeterminismPath]).body;
assert.equal(crmApiDeterminismReport.generatedCBytes, 0);
assert.equal(crmApiDeterminismReport.cBridgeFallback ?? false, false);
repeatBuildHash(["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/crm-api", "--out", crmApiDeterminismPath], crmApiDeterminismPath, join(outDir, "determinism-crm-api.repeat.o"));
const graph = json(["inspect", "--json", "--target", "linux-musl-x64", "examples/memory-package"]).body;
assert.equal(graph.schemaVersion, 1);
assert.equal(graph.targetSupport.target, "linux-musl-x64");
assert.equal(typeof graph.targetSupport.hostTarget, "string");
assert.equal(graph.targetSupport.fsAvailable, true);
assert(graph.modules.some((module) => module.name === "main"));
assert.equal(graph.imports.length, 0);
assert(graph.importEdges.some((edge) => edge.from === "main" && edge.to === "buffer"));
assert(graph.functions.some((fun) => fun.name === "main"));
assert(graph.functions.some((fun) => fun.name === "prepare" && fun.requiresCapabilities.includes("memory")));
assert(graph.stdlibHelpers.some((helper) => helper.name === "std.mem.copy" && helper.targetSupport === "target-neutral"));
assert(graph.stdlibHelpers.some((helper) => helper.name === "std.mem.byteBuf" && /explicit allocator/.test(helper.allocationBehavior)));
assert(graph.stdlibHelpers.some((helper) => helper.name === "std.fs.createOrRaise" && helper.targetSupport === "host"));
const graphMemCopyHelper = graph.stdlibHelpers.find((helper) => helper.name === "std.mem.copy");
assert.equal(graphMemCopyHelper.module, "std.mem");
assert(graphMemCopyHelper.effects.includes("memory"));
assert.equal(graphMemCopyHelper.errorBehavior, "infallible");
assert.match(graphMemCopyHelper.ownershipNotes, /caller-owned storage/);
assert.equal(graphMemCopyHelper.example, "examples/memory-primitives.0");
assert.equal(graphMemCopyHelper.apiStability, "bootstrap-stable");
const agentToolsGraph = json(["inspect", "--json", "examples/std-testing-log.0"]).body;
const graphTestingHelper = agentToolsGraph.stdlibHelpers.find((helper) => helper.name === "std.testing.equalBytes");
assert.equal(graphTestingHelper.module, "std.testing");
assert.equal(graphTestingHelper.targetSupport, "target-neutral");
assert.equal(graphTestingHelper.errorBehavior, "infallible");
assert.equal(graphTestingHelper.example, "examples/std-testing-log.0");
const graphLogHelper = agentToolsGraph.stdlibHelpers.find((helper) => helper.name === "std.log.keyValue");
assert.equal(graphLogHelper.module, "std.log");
assert(graphLogHelper.effects.includes("memory"));
assert.match(graphLogHelper.allocationBehavior, /caller buffer/);
assert.equal(graphLogHelper.errorBehavior, "returns null on failure");
assert.match(graphLogHelper.ownershipNotes, /caller-owned storage/);
assert.equal(graphLogHelper.example, "examples/std-testing-log.0");
const stdDataSize = json(["size", "--json", "conformance/native/pass/std-codec-json-url.graph"]).body;
const sizeUrlHostHelper = stdDataSize.stdlibHelpers.find((helper) => helper.name === "std.url.host");
assert.equal(sizeUrlHostHelper.module, "std.url");
assert.equal(sizeUrlHostHelper.example, "conformance/native/pass/std-codec-json-url.0");
const agentToolsSize = json(["size", "--json", "examples/std-testing-log.graph"]).body;
assert(agentToolsSize.usedStdlibHelpers.some((helper) => helper.name === "std.log.keyValue" && helper.module === "std.log"));
assert(agentToolsSize.usedStdlibHelpers.some((helper) => helper.name === "std.testing.containsBytes" && helper.module === "std.testing"));
assert(agentToolsSize.usedStdlibHelpers.every((helper) => helper.module && helper.effects && helper.allocationBehavior && helper.targetSupport && helper.errorBehavior && helper.ownershipNotes && helper.example && helper.apiStability));
const stdTestingTestJson = json(["test", "--json", "conformance/native/pass/std-testing-helpers-test.graph"]).body;
assert.equal(stdTestingTestJson.ok, true);
assert.equal(stdTestingTestJson.passedTests, 1);
const crcOnlySource = join(outDir, "std-codec-crc-only.0");
writeProjectionFile(crcOnlySource, `export c fn main() -> u32 {
return std.codec.crc32("zero")
}
`);
const crcOnlySourceGraph = importProjectionSidecar(crcOnlySource);
const crcOnlyGraph = json(["inspect", "--json", crcOnlySource]).body;
assert(!crcOnlyGraph.sourceFiles.some((path) => path.endsWith("std/codec.0")));
assert(!crcOnlyGraph.requiresCapabilities.includes("parse"));
const crcOnlySize = json(["size", "--json", crcOnlySourceGraph]).body;
assert(!crcOnlySize.incrementalInvalidation.changedInputs.sourceFiles.some((path) => path.endsWith("std/codec.0")));
assert(!crcOnlySize.retentionReasons.some((item) => item.name === "__zero_std_codec_hex_decode"));
const codecReadOnlySource = join(outDir, "std-codec-read-only.0");
writeProjectionFile(codecReadOnlySource, `export c fn main() -> i32 {
let value: Maybe<u16> = std.codec.readU16Le("AB")
if value.has {
return 0
}
return 1
}
`);
const codecReadOnlySourceGraph = importProjectionSidecar(codecReadOnlySource);
const codecReadOnlyGraph = json(["inspect", "--json", codecReadOnlySource]).body;
assert(codecReadOnlyGraph.sourceFiles.some((path) => path.endsWith("std/codec.0")));
assert(!codecReadOnlyGraph.sourceFiles.some((path) => path.endsWith("std/ascii.0")));
assert(codecReadOnlyGraph.requiresCapabilities.includes("codec"));
assert(!codecReadOnlyGraph.requiresCapabilities.includes("parse"));
const codecReadOnlySize = json(["size", "--json", codecReadOnlySourceGraph]).body;
assert.equal(codecReadOnlySize.sizeBreakdown.summary.functionCount, 2);
assert.equal(codecReadOnlySize.sizeBreakdown.summary.stdlibHelperCount, 2);
assert(codecReadOnlySize.topLargestEmittedHelpers.some((helper) => helper.name === "std.codec.readU16Le"));
assert(!codecReadOnlySize.retentionReasons.some((item) => item.name === "__zero_std_codec_hex_decode"));
assert(!codecReadOnlySize.retentionReasons.some((item) => item.name === "std.ascii.hexValue"));
assert(!codecReadOnlySize.retentionReasons.some((item) => item.name === "std.url.percentEncode"));
const jsonStatusOnlySource = join(outDir, "std-json-status-only.0");
writeProjectionFile(jsonStatusOnlySource, `export c fn main() -> i32 {
let status: u32 = std.json.errorNone()
if status == 0_u32 {
return 0
}
return 1
}
`);
const jsonStatusOnlySourceGraph = importProjectionSidecar(jsonStatusOnlySource);
const jsonStatusOnlyGraph = json(["inspect", "--json", jsonStatusOnlySource]).body;
assert(!jsonStatusOnlyGraph.sourceFiles.some((path) => path.endsWith("std/json.0")));
assert(!jsonStatusOnlyGraph.sourceFiles.some((path) => path.endsWith("std/ascii.0")));
assert(!jsonStatusOnlyGraph.sourceFiles.some((path) => path.endsWith("std/fmt.0")));
assert(!jsonStatusOnlyGraph.sourceFiles.some((path) => path.endsWith("std/parse.0")));
assert(jsonStatusOnlyGraph.callResolution.calls.some((call) => call.kind === "stdlib" && call.calleeName === "std.json.errorNone"));
const jsonStatusOnlySize = json(["size", "--json", jsonStatusOnlySourceGraph]).body;
assert.equal(jsonStatusOnlySize.objectBackend.directFacts.functionCount, 1);
assert(!jsonStatusOnlySize.retentionReasons.some((item) => item.name === "__zero_std_json_validate_error"));
assert(!jsonStatusOnlySize.retentionReasons.some((item) => item.name === "std.parse.parseU32"));
const httpErrorNameOnlySource = join(outDir, "std-http-error-name-only.0");
writeProjectionFile(httpErrorNameOnlySource, `export c fn main() -> i32 {
let name: String = std.http.errorName(std.http.errorTimeout())
if std.mem.len(name) > 0_usize {
return 0
}
return 1
}
`);
const httpErrorNameOnlyGraphPath = importProjectionSidecar(httpErrorNameOnlySource);
const httpErrorNameOnlyGraph = json(["inspect", "--json", "--target", "linux-musl-x64", httpErrorNameOnlySource]).body;
assert.deepEqual(httpErrorNameOnlyGraph.requiresCapabilities, ["memory"]);
assert.equal(json(["check", "--json", "--target", "linux-musl-x64", httpErrorNameOnlyGraphPath]).body.ok, true);
const testingEqualU32OnlySource = join(outDir, "std-testing-equal-u32-only.0");
writeProjectionFile(testingEqualU32OnlySource, `export c fn main() -> i32 {
if std.testing.equalU32(42_u32, 42_u32) {
return 0
}
return 1
}
`);
importProjectionSidecar(testingEqualU32OnlySource);
const testingEqualU32OnlyGraph = json(["inspect", "--json", testingEqualU32OnlySource]).body;
assert.deepEqual(testingEqualU32OnlyGraph.requiresCapabilities, []);
const logMessageOnlySource = join(outDir, "std-log-message-only.0");
writeProjectionFile(logMessageOnlySource, `export c fn main() -> i32 {
var storage: [64]u8 = [0_u8; 64]
let entry: Maybe<Span<u8>> = std.log.message(storage, "info", "ready")
if entry.has {
return 0
}
return 1
}
`);
importProjectionSidecar(logMessageOnlySource);
const logMessageOnlyGraph = json(["inspect", "--json", logMessageOnlySource]).body;
assert.deepEqual(logMessageOnlyGraph.requiresCapabilities, ["memory"]);
const logMessageFieldSource = join(outDir, "std-log-message-field.0");
writeProjectionFile(logMessageFieldSource, `export c fn main() -> i32 {
var storage: [96]u8 = [0_u8; 96]
let entry: Maybe<Span<u8>> = std.log.messageField(storage, "info", "ready", "\\"event\\":\\"startup\\"")
if entry.has {
return 0
}
return 1
}
`);
importProjectionSidecar(logMessageFieldSource);
const logMessageFieldGraph = json(["inspect", "--json", logMessageFieldSource]).body;
assert.deepEqual(logMessageFieldGraph.requiresCapabilities, ["memory", "parse"]);
const httpErrorsGraph = json(["inspect", "--json", "conformance/native/pass/std-http-errors.0"]).body;
assert.deepEqual(httpErrorsGraph.requiresCapabilities, ["memory"]);
assert.equal(json(["check", "--json", "--target", "linux-musl-x64", "conformance/native/pass/std-http-errors.graph"]).body.ok, true);
const httpTimeoutHelper = httpErrorsGraph.stdlibHelpers.find((helper) => helper.name === "std.http.errorTimeout");
assert.equal(httpTimeoutHelper.returnType, "HttpError");
assert.equal(httpTimeoutHelper.capability, "none");
assert.deepEqual(httpTimeoutHelper.effects, []);
assert.equal(httpTimeoutHelper.allocationBehavior, "no allocation");
assert.equal(httpTimeoutHelper.ownershipNotes, "no ownership transfer");
const httpErrorNameHelper = httpErrorsGraph.stdlibHelpers.find((helper) => helper.name === "std.http.errorName");
assert.equal(httpErrorNameHelper.returnType, "String");
assert.equal(httpErrorNameHelper.capability, "none");
assert.equal(httpErrorNameHelper.targetSupport, "target-neutral");
const coreGraph = json(["inspect", "--json", "examples/static-method.0"]).body;
const counterShape = coreGraph.shapes.find((shape) => shape.name === "Counter");
assert(counterShape);
assert(counterShape.fields.some((field) => field.name === "value" && field.hasDefault === false));
assert(counterShape.methods.some((method) => method.name === "add" && method.staticDispatch === true));
const interfaceGraph = json(["inspect", "--json", "examples/static-interface.0"]).body;
assert(interfaceGraph.interfaces.some((item) => item.name === "Readable" && item.staticOnly === true));
assert(interfaceGraph.functions.some((item) => item.name === "readValue" && item.constraints.some((constraint) => constraint.interface === "Readable<T>")));
const staticValueGraph = json(["inspect", "--json", "examples/static-value-params.0"]).body;
const fixedVecShape = staticValueGraph.shapes.find((shape) => shape.name === "FixedVec");
assert(fixedVecShape);
assert(fixedVecShape.staticParams.some((param) => param.name === "N" && param.type === "usize"));
assert(staticValueGraph.functions.some((fun) => fun.name === "first" && fun.staticParams.some((param) => param.name === "N")));
const fixedVecMethodsGraph = json(["inspect", "--json", "examples/fixed-vec.0"]).body;
const fixedVecMethodsShape = fixedVecMethodsGraph.shapes.find((shape) => shape.name === "FixedVec");
assert(fixedVecMethodsShape);
assert(fixedVecMethodsShape.methods.some((method) => method.name === "push" && method.inheritedShapeParams === true && method.shapeStaticParams.some((param) => param.name === "N")));
assert(fixedVecMethodsShape.methods.some((method) => method.name === "push" && typeof method.doc === "string"));
assert(fixedVecMethodsShape.fields.some((field) => field.name === "len" && field.hasDefault === true));
const aliasGraph = json(["inspect", "--json", "examples/type-alias.0"]).body;
assert(aliasGraph.aliases.some((alias) => alias.name === "BytePair" && alias.target === "Pair<u8, u8>"));
const constGraph = json(["inspect", "--json", "examples/const-arithmetic.0"]).body;
assert(constGraph.consts.some((item) => item.name === "answer" && item.type === "i32"));
const errorGraph = json(["inspect", "--json", "conformance/native/pass/fallibility-error-sets.0"]).body;
const maybeFail = errorGraph.functions.find((item) => item.name === "maybe_fail");
assert(maybeFail);
assert.equal(maybeFail.errorSetKind, "explicit");
assert(maybeFail.errorNames.includes("BadInput"));
const inferredGraph = json(["inspect", "--json", "conformance/native/pass/check-maybe-fallibility.0"]).body;
const inferredPrivate = inferredGraph.functions.find((item) => item.name === "first_or_none");
assert(inferredPrivate);
assert.equal(inferredPrivate.errorSetKind, "inferred");
const size = json(["size", "--json", "--target", "linux-musl-x64", "examples/memory-package"]).body;
assert.equal(size.schemaVersion, 1);
assert(size.stdlibHelpers.some((helper) => helper.name === "std.mem.copy"));
assert(size.usedStdlibHelpers.some((helper) => helper.name === "std.mem.copy"));
assert(size.usedStdlibHelpers.every((helper) => helper.module && helper.effects?.length && helper.errorBehavior && helper.ownershipNotes && helper.example && helper.apiStability));
assert(size.requiresCapabilities.includes("memory"));
assert.equal(size.generatedCBytes, 0);
assert.equal(size.cBridgeFallback, false);
assert(size.loweredIrBytes > 0);
assert(size.sections.some((section) => section.name === "lowered-ir" && section.bytes === size.loweredIrBytes));
assert(size.sections.some((section) => section.name === "direct-size-metadata" && section.kind === "metadata"));
assert(size.topLargestEmittedHelpers.some((helper) => helper.name === "std.mem.copy" && helper.estimatedDirectBytes > 0));
assert.equal(size.objectBackend.objectEmission.path, "direct-elf64-object");
assert(size.compilerRuntimeHelpers.every((helper) => helper.payAsUsed === true && helper.emitted === false));
const sizedArtifact = join(outDir, "sized-memory-package");
rmSync(sizedArtifact, { force: true });
rmSync(`${sizedArtifact}.c`, { force: true });
const sizeWithArtifact = json(["size", "--json", "--out", sizedArtifact, "examples/memory-package"]).body;
assert.equal(sizeWithArtifact.artifactPath, sizedArtifact);
assert(sizeWithArtifact.artifactBytes > 0);
assert(existsSync(sizedArtifact));
const sizeBlockedParent = join(outDir, "size-output-not-dir");
const sizeBlockedOut = join(sizeBlockedParent, "report.json");
rmSync(sizeBlockedParent, { force: true, recursive: true });
writeFileSync(sizeBlockedParent, "not a directory\n");
const sizeBlocked = json(["size", "--json", "--out", sizeBlockedOut, "examples/hello.graph"], { allowFailure: true });
assert.notEqual(sizeBlocked.code, 0);
assert.equal(sizeBlocked.body.diagnostics[0].path, sizeBlockedOut);
const explainRepairId = (code: string) => json(["explain", "--json", code]).body.repair.id;
const explainRepairs = {
ERR001: explainRepairId("ERR001"),
ERR003: explainRepairId("ERR003"),
TYP025: explainRepairId("TYP025"),
TYP009: explainRepairId("TYP009"),
FLD002: explainRepairId("FLD002"),
PUB001: explainRepairId("PUB001"),
};
assert.equal(explainRepairs.ERR001, "add-fallible-marker-or-rescue");
assert.equal(explainRepairs.ERR003, "check-or-rescue-fallible-call");
assert.equal(explainRepairs.TYP025, "add-explicit-generic-type-arguments");
assert.equal(explainRepairs.TYP009, "make-binding-mutable");
assert.equal(explainRepairs.FLD002, "initialize-missing-field");
assert.equal(explainRepairs.PUB001, "add-public-api-type");
const generatedCBytesAfterReadOnlyCommands = json(["size", "--json", "examples/memory-package"]).body.generatedCBytes;
assert.equal(generatedCBytesAfterReadOnlyCommands, generatedCBytesBeforeReadOnlyCommands);
const targets = json(["targets"]).body;
assert.equal(targets.schemaVersion, 1);
assert.equal(typeof targets.host, "string");
const publicTargetNames = ["darwin-arm64", "darwin-x64", "linux-arm64", "linux-musl-arm64", "linux-musl-x64", "linux-x64", "win32-arm64.exe", "win32-x64.exe"];
assert.deepEqual([...targets.targets.map((target) => target.name)].sort(), [...publicTargetNames].sort());
for (const targetName of publicTargetNames) {
assert(targets.targets.some((target) => target.name === targetName), `${targetName} should be listed`);
}
assert(targets.targets.some((target) => target.hosted === true && target.capabilities.includes("fs")));
assert(targets.targets.some((target) => target.hosted === false && !target.capabilities.includes("fs")));
const linuxGnuTarget = targets.targets.find((target) => target.name === "linux-x64");
const linuxMuslTarget = targets.targets.find((target) => target.name === "linux-musl-x64");
const darwinArm64Target = targets.targets.find((target) => target.name === "darwin-arm64");
const darwinX64Target = targets.targets.find((target) => target.name === "darwin-x64");
const winX64Target = targets.targets.find((target) => target.name === "win32-x64.exe");
const winArm64Target = targets.targets.find((target) => target.name === "win32-arm64.exe");
const linuxArm64Target = targets.targets.find((target) => target.name === "linux-arm64");
const hostTarget = targets.targets.find((target) => target.name === targets.host);
assert(hostTarget);
for (const target of targets.targets) {
assert.deepEqual(target.backendFamilies.known, ["direct", "llvm"]);
assert.equal(target.backendFamilies.fallbackPolicy, "none");
assert(target.backendFamilies.llvm.emit.includes("llvm-ir"));
assert(["ready", "tool-missing", "unsupported-target"].includes(target.backendFamilies.llvm.status));
assert.equal(target.backendFamilies.llvm.backendLifecycle.stability, "experimental");
assert.equal(target.backendFamilies.llvm.backendLifecycle.defaultEligible, false);
assert.equal(target.backendFamilies.llvm.backendLifecycle.releaseEligible, false);
}
assert.equal(hostTarget.backendFamilies.llvm.status, doctor.llvmToolchain.status);
assert.equal(hostTarget.backendFamilies.llvm.buildable, doctor.llvmToolchain.nativeExecutable);
if (doctor.llvmToolchain.nativeExecutable) assert(hostTarget.backendFamilies.llvm.emit.includes("exe"));
assert.equal(winX64Target.backendFamilies.llvm.emit.includes("exe"), false);
assert.equal(winArm64Target.backendFamilies.llvm.emit.includes("exe"), false);
assert.equal(linuxMuslTarget.directBackend.exeSupported, true);
assert.equal(linuxMuslTarget.directBackend.exeEmitter, "zero-elf64-exe");
assert.equal(linuxGnuTarget.directBackend.objectEmitter, "zero-elf64");
assert.equal(linuxGnuTarget.directBackend.exeSupported, true);
assert.equal(linuxGnuTarget.directBackend.exeEmitter, "zero-elf64-exe");
assert.equal(darwinArm64Target.directBackend.objectEmitter, "zero-macho64");
assert.equal(darwinArm64Target.directBackend.exeSupported, true);
assert.equal(darwinArm64Target.directBackend.exeEmitter, "zero-macho64-exe");
assert.equal(darwinX64Target.directBackend.objectEmitter, "zero-macho-x64");
assert.equal(darwinX64Target.directBackend.exeSupported, true);
assert.equal(darwinX64Target.directBackend.exeEmitter, "zero-macho-x64-exe");
assert.equal(winX64Target.directBackend.objectEmitter, "zero-coff-x64");
assert.equal(winX64Target.directBackend.objectSupported, true);
assert.equal(winX64Target.directBackend.exeSupported, true);
assert.equal(winX64Target.directBackend.exeEmitter, "zero-coff-x64-exe");
assert.equal(winArm64Target.directBackend.status, "native-exe");
assert.equal(winArm64Target.directBackend.objectEmitter, "zero-coff-aarch64");
assert.equal(winArm64Target.directBackend.exeEmitter, "zero-coff-aarch64-exe");
assert.match(winArm64Target.directBackend.reason, /direct object and executable backend available/);
assert.equal(linuxArm64Target.directBackend.status, "native-exe");
assert.equal(linuxArm64Target.directBackend.objectEmitter, "zero-elf-aarch64");
assert.equal(linuxArm64Target.directBackend.exeEmitter, "zero-elf-aarch64-exe");
assert.match(linuxArm64Target.directBackend.reason, /direct object and executable backend available/);
const cAbiExport = zero(["check", "conformance/native/pass/c-abi-export.graph"]);
assert.match(cAbiExport.stdout, /ok/);
const cAbiDump = json(["abi", "dump", "--json", "conformance/native/pass/c-abi-export.graph"]).body;
assert(cAbiDump.cExports.some((item) => item.name === "zero_add" && item.cReturnType === "int32_t"));
assert.match(cAbiDump.generatedHeader.text, /int32_t zero_add\(int32_t a, int32_t b\);/);
const report = {
generatedAt: new Date().toISOString(),
productShell: {
version: version.version,
host: version.host,
backend: version.backend,
doctorStatus: doctor.status,
cleanRemovedOut: !existsSync(cleanProbe),
},
diagnostics: {
explainRepairs,
},
graph: {
target: graph.targetSupport.target,
requiresCapabilities: graph.requiresCapabilities,
stdlibHelperCount: graph.stdlibHelpers.length,
coreMethodCount: counterShape.methods.length,
interfaceCount: interfaceGraph.interfaces.length,
aliasCount: aliasGraph.aliases.length,
constCount: constGraph.consts.length,
errorFunction: maybeFail.errorNames,
},
size: {
generatedCBytes: size.generatedCBytes,
stdlibHelperCount: size.stdlibHelpers.length,
usedStdlibHelperCount: size.usedStdlibHelpers.length,
artifactBytes: sizeWithArtifact.artifactBytes,
unchangedByReadOnlyCommands: generatedCBytesAfterReadOnlyCommands === generatedCBytesBeforeReadOnlyCommands,
},
noCDefaultRouteSentinels: {
defaultNoC: [
{
id: "direct-linux-exe",
generatedCBytes: directExeReport.generatedCBytes,
cBridgeFallback: directExeReport.selfHostRouting?.cBridge?.required ?? false,
objectEmissionPath: directExeReport.objectBackend.objectEmission.path,
},
],
knownDefaultCGap: {
id: "hello-linux-default",
generatedCBytes: buildReport.generatedCBytes,
cBridgeFallback: buildReport.selfHostRouting?.cBridge?.required ?? false,
objectEmissionPath: buildReport.objectBackend.objectEmission.path,
},
removedGeneratedC: {
emitCDiagnostic: removedEmitC.body.diagnostics[0].code,
legacyFlagDiagnostic: removedLegacyFlag.body.diagnostics[0].code,
repair: removedEmitC.body.diagnostics[0].repair.id,
},
directLinkedExecutables: {
darwin: {
compiler: directMachOExeReport.compiler,
generatedCBytes: directMachOExeReport.generatedCBytes,
objectEmissionPath: directMachOExeReport.objectBackend.objectEmission.path,
},
windows: {
compiler: directCoffExeReport.compiler,
generatedCBytes: directCoffExeReport.generatedCBytes,
objectEmissionPath: directCoffExeReport.objectBackend.objectEmission.path,
},
},
},
targets: {
host: targets.host,
count: targets.targets.length,
},
generatedCAudit: null,
};
writeFileSync(join(outDir, "summary.json"), `${JSON.stringify(report, null, 2)}\n`);
finishAggregateAssert(assert, { suite: "command contract snapshots", reportPath: join(outDir, "failures.json") });
console.log("command contract snapshots ok");