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
5381 lines
309 KiB
JavaScript
5381 lines
309 KiB
JavaScript
#!/usr/bin/env node
|
|
import { execFile } from "node:child_process";
|
|
import { existsSync } from "node:fs";
|
|
import { access, chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
import { resolve } from "node:path";
|
|
import { createAggregateAssert, describeFailure, finishAggregateAssert } from "../scripts/aggregate-assert.mjs";
|
|
|
|
const assert = createAggregateAssert();
|
|
|
|
if (process.env.ZERO_NATIVE_TEST_SANDBOX !== "1" && process.env.ZERO_NATIVE_TEST_ALLOW_LOCAL !== "1") {
|
|
console.error("conformance emits native test artifacts; run `pnpm run conformance` for Vercel Sandbox execution or set ZERO_NATIVE_TEST_ALLOW_LOCAL=1 to opt into local artifacts.");
|
|
process.exit(1);
|
|
}
|
|
|
|
const execMaxBuffer = 16 * 1024 * 1024;
|
|
const zero = resolve(process.env.ZERO_BIN || (existsSync(".zero/bin/zero") ? ".zero/bin/zero" : "bin/zero"));
|
|
const outDir = process.env.ZERO_CONFORMANCE_OUT_DIR || ".zero/conformance";
|
|
const canRunLinuxMuslX64 = process.platform === "linux" && process.arch === "x64";
|
|
const runnableDirectTarget =
|
|
process.platform === "darwin" && process.arch === "arm64" ? "darwin-arm64" :
|
|
process.platform === "linux" && process.arch === "x64" ? "linux-musl-x64" :
|
|
null;
|
|
const checkTimeoutMs = Number(process.env.ZERO_CHECK_TIMEOUT_MS ?? 2000);
|
|
|
|
function parsePositiveInt(value, fallback) {
|
|
const parsed = Number.parseInt(value ?? "", 10);
|
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
}
|
|
|
|
const defaultCheckJobs = 1;
|
|
const checkJobs = parsePositiveInt(process.env.ZERO_CONFORMANCE_CHECK_JOBS, defaultCheckJobs);
|
|
|
|
function runnableExeArgs(input, out) {
|
|
if (!runnableDirectTarget) return null;
|
|
return ["build", "--emit", "exe", "--target", runnableDirectTarget, compilerInputPath(input), "--out", out];
|
|
}
|
|
|
|
await mkdir(outDir, { recursive: true });
|
|
await mkdir(`${outDir}/check-cache`, { recursive: true });
|
|
|
|
function execFileAsync(file, args = [], options = {}) {
|
|
return new Promise((resolve, reject) => {
|
|
const normalizedArgs = file === zero ? normalizeZeroCompilerArgs(args) : args;
|
|
execFile(file, normalizedArgs, { maxBuffer: execMaxBuffer, ...options }, (error, stdout, stderr) => {
|
|
if (error) {
|
|
error.stdout = stdout;
|
|
error.stderr = stderr;
|
|
reject(error);
|
|
return;
|
|
}
|
|
resolve({ stdout, stderr });
|
|
});
|
|
});
|
|
}
|
|
|
|
function tomlQuote(value) {
|
|
return JSON.stringify(String(value));
|
|
}
|
|
|
|
function tomlArray(values) {
|
|
return `[${values.map(tomlQuote).join(", ")}]`;
|
|
}
|
|
|
|
function appendManifestFields(lines, object, order) {
|
|
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) {
|
|
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, ["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, ["path", "version", "targets", "target"]);
|
|
}
|
|
}
|
|
for (const [name, lib] of Object.entries(manifest.c?.libs ?? {})) {
|
|
lines.push("", `[c.libs.${name}]`);
|
|
appendManifestFields(lines, lib, ["headers", "include", "lib", "link", "mode", "pkg_config", "pkgConfig"]);
|
|
}
|
|
return `${lines.join("\n").replace(/\n{3,}/g, "\n\n")}\n`;
|
|
}
|
|
|
|
async function writeZeroToml(root, manifest) {
|
|
await writeFile(`${root}/zero.toml`, manifestToml(manifest));
|
|
}
|
|
|
|
function graphSidecarPath(sourcePath) {
|
|
if (!sourcePath.endsWith(".0")) throw new Error(`${sourcePath}: expected a .0 projection path`);
|
|
return `${sourcePath.slice(0, -2)}.graph`;
|
|
}
|
|
|
|
const compilerInputCommands = new Set(["check", "build", "run", "test", "size", "mem", "doc", "dev", "time", "fix"]);
|
|
const compilerInputValueFlags = new Set(["--backend", "--emit", "--filter", "--out", "--profile", "--release", "--target"]);
|
|
const abiInputSubcommands = new Set(["check", "dump"]);
|
|
|
|
function compilerInputPath(inputPath) {
|
|
if (typeof inputPath !== "string" || !inputPath.endsWith(".0")) return inputPath;
|
|
const graphPath = graphSidecarPath(inputPath);
|
|
if (!existsSync(graphPath)) {
|
|
throw new Error(`${inputPath}: compiler command requires graph input; missing graph sidecar ${graphPath}`);
|
|
}
|
|
return graphPath;
|
|
}
|
|
|
|
function normalizeZeroCompilerArgs(args) {
|
|
if (!Array.isArray(args)) return args;
|
|
const isCompilerInputCommand = compilerInputCommands.has(args[0]);
|
|
const isAbiInputCommand = args[0] === "abi" && abiInputSubcommands.has(args[1]);
|
|
if (!isCompilerInputCommand && !isAbiInputCommand) return args;
|
|
let afterProgramArgs = false;
|
|
let skipOptionValue = false;
|
|
return args.map((arg) => {
|
|
if (afterProgramArgs) return arg;
|
|
if (arg === "--") afterProgramArgs = true;
|
|
if (skipOptionValue) {
|
|
skipOptionValue = false;
|
|
return arg;
|
|
}
|
|
if (compilerInputValueFlags.has(arg)) {
|
|
skipOptionValue = true;
|
|
return arg;
|
|
}
|
|
return afterProgramArgs ? arg : compilerInputPath(arg);
|
|
});
|
|
}
|
|
|
|
async function writeGraphFixture(sourcePath, source) {
|
|
await writeFile(sourcePath, source);
|
|
const graphPath = graphSidecarPath(sourcePath);
|
|
await execFileAsync(zero, ["import", "--format", "binary", "--out", graphPath, sourcePath]);
|
|
return graphPath;
|
|
}
|
|
|
|
async function importGraphFixtureFailure(sourcePath) {
|
|
const result = await execFileAsync(zero, ["import", "--json", "--format", "binary", "--out", graphSidecarPath(sourcePath), sourcePath]).catch((error) => error);
|
|
assert.notEqual(result.code, 0);
|
|
return JSON.parse(result.stdout);
|
|
}
|
|
|
|
async function writeImportFailureFixture(sourcePath, source) {
|
|
await writeFile(sourcePath, source);
|
|
return importGraphFixtureFailure(sourcePath);
|
|
}
|
|
|
|
async function importPackageGraph(root) {
|
|
await execFileAsync(zero, ["import", root]);
|
|
}
|
|
|
|
function isolatedCacheEnv(workerIndex) {
|
|
return {
|
|
...process.env,
|
|
ZERO_CACHE_DIR: `${outDir}/check-cache/worker-${workerIndex}`,
|
|
};
|
|
}
|
|
|
|
async function mapLimit(items, limit, callback) {
|
|
const results = new Array(items.length);
|
|
let next = 0;
|
|
const workerCount = Math.min(Math.max(1, limit), Math.max(1, items.length));
|
|
async function worker(workerIndex) {
|
|
await mkdir(`${outDir}/check-cache/worker-${workerIndex}`, { recursive: true });
|
|
for (;;) {
|
|
const index = next++;
|
|
if (index >= items.length) return;
|
|
try {
|
|
results[index] = await callback(items[index], index, workerIndex);
|
|
} catch (error) {
|
|
const item = Array.isArray(items[index]) ? items[index][0] : items[index];
|
|
results[index] = { error };
|
|
assert.fail(`parallel conformance item failed: ${item}\n${describeFailure(error)}`);
|
|
}
|
|
}
|
|
}
|
|
await Promise.all(Array.from({ length: workerCount }, (_, index) => worker(index)));
|
|
return results;
|
|
}
|
|
|
|
async function checkFixtureParallel(fixture, workerIndex) {
|
|
const options = checkJobs > 1 ? { env: isolatedCacheEnv(workerIndex) } : {};
|
|
const result = await execFileAsync(zero, ["check", fixture], options).catch((error) => error);
|
|
assert.equal(result.code ?? 0, 0, `${fixture} should check cleanly\n${result.stderr ?? ""}`);
|
|
}
|
|
|
|
async function checkFailureFixtureParallel(fixture, code, workerIndex) {
|
|
const options = checkJobs > 1 ? { env: isolatedCacheEnv(workerIndex) } : {};
|
|
const result = await execFileAsync(zero, ["check", fixture], options).catch((error) => error);
|
|
assert.notEqual(result.code, 0);
|
|
assert.match(result.stderr, code);
|
|
}
|
|
|
|
async function fileExists(path) {
|
|
try {
|
|
await access(path);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function assertRepositoryGraphNativeCheck(body, sourceProjectionState = "clean", options = {}) {
|
|
const graphHirToMirUsed = options.graphHirToMirUsed === false ? false : true;
|
|
const compilerInputReady = body.targetReadiness?.ok === true && graphHirToMirUsed;
|
|
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.semanticDiagnosticsAuthority, "stored-typed-graph-facts");
|
|
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;
|
|
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);
|
|
}
|
|
|
|
function assertSourceGraph(body, artifact, moduleIdentity, lowering = "typed-program-graph-mir", canonicalSource = false, 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(body.compilerCaches.map((cache) => [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", "nodeHashes", "importPaths", "compilerVersion", "packageDependencies"], ["sourceFiles", "targetFacts", "profile"]);
|
|
assertCacheInputs("interface", ["graphHash", "modulePaths", "symbolFacts", "importGraph"], ["targetFacts", "profile", "compilerVersion", "packageDependencies"]);
|
|
assertCacheInputs("checkedBody", ["graphHash", "importPaths", "targetFacts", "compilerVersion", "packageDependencies"], ["sourceFiles", "profile"]);
|
|
assertCacheInputs("specialization", ["graphHash", "importPaths", "targetFacts", "profile", "compilerVersion", "packageDependencies"], ["sourceFiles"]);
|
|
if (body.graph.lowering === "mapped-final-mir") {
|
|
assertCacheInputs("mappedFinalMir", ["graphHash", "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(body.incrementalInvalidation.graphInput.mappedFinalMir.path, mappedMirCache.path);
|
|
assert.equal(body.incrementalInvalidation.graphInput.mappedFinalMir.memoryMapped, true);
|
|
assert.equal(body.incrementalInvalidation.graphInput.mappedFinalMir.borrowedStorage, true);
|
|
}
|
|
assertCacheInputs("emittedObject", ["graphHash", "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 assertLlvmPhiPredecessors(ir) {
|
|
const predecessors = new Map();
|
|
const phiEdges = [];
|
|
let functionIndex = -1;
|
|
let current = "-1:entry";
|
|
const scoped = (label) => `${functionIndex}:${label}`;
|
|
for (const line of ir.split("\n")) {
|
|
if (line.startsWith("define ")) {
|
|
functionIndex++;
|
|
current = scoped("entry");
|
|
continue;
|
|
}
|
|
const label = line.match(/^(L[0-9]+):$/);
|
|
if (label) {
|
|
current = scoped(label[1]);
|
|
continue;
|
|
}
|
|
const branch = line.match(/^ br (?:label %(L[0-9]+)|i1 [^,]+, label %(L[0-9]+), label %(L[0-9]+))$/);
|
|
if (branch) {
|
|
for (const target of branch.slice(1).filter(Boolean)) {
|
|
const key = scoped(target);
|
|
if (!predecessors.has(key)) predecessors.set(key, new Set());
|
|
predecessors.get(key).add(current);
|
|
}
|
|
continue;
|
|
}
|
|
if (!line.includes(" = phi ")) continue;
|
|
for (const match of line.matchAll(/\[[^\]]+, %(L[0-9]+)\]/g)) {
|
|
phiEdges.push({ block: current, predecessor: scoped(match[1]) });
|
|
}
|
|
}
|
|
for (const edge of phiEdges) {
|
|
assert(
|
|
predecessors.get(edge.block)?.has(edge.predecessor),
|
|
`LLVM phi predecessor ${edge.predecessor} must branch to ${edge.block}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
async function buildLlvmIrFixture(fixture, name) {
|
|
const outPath = `${outDir}/${name}.ll`;
|
|
const build = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"llvm-ir",
|
|
"--backend",
|
|
"llvm",
|
|
fixture,
|
|
"--out",
|
|
outPath,
|
|
]);
|
|
const body = JSON.parse(build.stdout);
|
|
assert.equal(body.emit, "llvm-ir");
|
|
assert.equal(body.compiler, "zero-c-llvm-ir");
|
|
assert.equal(body.generatedCBytes, 0);
|
|
return readFile(outPath, "utf8");
|
|
}
|
|
|
|
async function assertLlvmHostExitCode(fixture, name, expectedCode) {
|
|
const readiness = await execFileAsync(zero, ["check", "--json", "--backend", "llvm", fixture]).catch((error) => error);
|
|
if (readiness.code) return;
|
|
const readinessBody = JSON.parse(readiness.stdout);
|
|
if (!readinessBody.targetReadiness?.ok) return;
|
|
|
|
const out = `${outDir}/${name}`;
|
|
const build = await execFileAsync(zero, ["build", "--json", "--backend", "llvm", fixture, "--out", out]);
|
|
const body = JSON.parse(build.stdout);
|
|
assert.equal(body.emit, "exe");
|
|
assert.equal(body.objectBackend.backendFamily, "llvm");
|
|
const run = await execFileAsync(out, []).catch((error) => error);
|
|
assert.equal(run.code ?? 0, expectedCode);
|
|
assert.equal(run.signal ?? null, null);
|
|
}
|
|
|
|
async function assertBoundsTrap(fixture, name) {
|
|
const out = `${outDir}/${name}`;
|
|
const build = await execFileAsync(zero, ["build", "--json", "--emit", "exe", "--target", "linux-musl-x64", fixture, "--out", out]).catch((error) => error);
|
|
if (build.code) {
|
|
const body = JSON.parse(build.stdout);
|
|
assert.equal(body.diagnostics?.[0]?.code, "BLD004");
|
|
return;
|
|
}
|
|
const body = JSON.parse(build.stdout);
|
|
assert.equal(body.generatedCBytes, 0);
|
|
if (!canRunLinuxMuslX64) return;
|
|
const failedRun = await execFileAsync(out, []).catch((error) => error);
|
|
assert.notEqual(failedRun.code ?? (failedRun.signal ? 1 : 0), 0);
|
|
if (failedRun.stderr) assert.match(failedRun.stderr, /zero bounds check failed|trap: index out of bounds/);
|
|
}
|
|
|
|
async function assertDirectRuntimeOrUnsupported(fixture, name, expected) {
|
|
const out = `${outDir}/${name}`;
|
|
const build = await execFileAsync(zero, ["build", "--json", "--emit", "exe", "--target", "linux-musl-x64", fixture, "--out", out]).catch((error) => error);
|
|
if (build.code) {
|
|
const body = JSON.parse(build.stdout);
|
|
assert.equal(body.diagnostics?.[0]?.code, "BLD004");
|
|
return;
|
|
}
|
|
|
|
const body = JSON.parse(build.stdout);
|
|
assert.equal(body.generatedCBytes, 0);
|
|
assert.equal(body.legacy, false);
|
|
if (!canRunLinuxMuslX64) return;
|
|
const run = await execFileAsync(out, expected.args ?? [], expected.env ? { env: { ...process.env, ...expected.env } } : {}).catch((error) => error);
|
|
if (run.code || run.signal) return;
|
|
if (expected.stdout instanceof RegExp) assert.match(run.stdout, expected.stdout);
|
|
else assert.equal(run.stdout, expected.stdout);
|
|
if (expected.stderr !== undefined) assert.equal(run.stderr, expected.stderr);
|
|
if (expected.file) assert.equal(await readFile(`${outDir}/${expected.file.name}`, "utf8"), expected.file.text);
|
|
}
|
|
|
|
async function assertDirectRuntimeRequired(fixture, name, expected) {
|
|
const target = runnableDirectTarget ?? "linux-musl-x64";
|
|
const out = `${outDir}/${name}`;
|
|
const build = await execFileAsync(zero, ["build", "--json", "--emit", "exe", "--target", target, fixture, "--out", out]);
|
|
const body = JSON.parse(build.stdout);
|
|
assert.equal(body.generatedCBytes, 0);
|
|
assert.equal(body.legacy, false);
|
|
if (!runnableDirectTarget) return;
|
|
const run = await execFileAsync(out, expected.args ?? [], expected.env ? { env: { ...process.env, ...expected.env } } : {});
|
|
if (expected.stdout instanceof RegExp) assert.match(run.stdout, expected.stdout);
|
|
else assert.equal(run.stdout, expected.stdout);
|
|
if (expected.stderr !== undefined) assert.equal(run.stderr, expected.stderr);
|
|
}
|
|
|
|
async function assertCommonRuntimeOrUnsupported(fixture, name, expected) {
|
|
const target = runnableDirectTarget ?? "linux-musl-x64";
|
|
const out = `${outDir}/${name}`;
|
|
const build = await execFileAsync(zero, ["build", "--json", "--emit", "exe", "--target", target, fixture, "--out", out]).catch((error) => error);
|
|
if (build.code) {
|
|
const body = JSON.parse(build.stdout);
|
|
assert.equal(body.diagnostics?.[0]?.code, "BLD004");
|
|
return;
|
|
}
|
|
|
|
const body = JSON.parse(build.stdout);
|
|
assert.equal(body.generatedCBytes, 0);
|
|
assert.equal(body.legacy, false);
|
|
if (!runnableDirectTarget) return;
|
|
const run = await execFileAsync(out, expected.args ?? [], expected.env ? { env: { ...process.env, ...expected.env } } : {}).catch((error) => error);
|
|
assert.equal(run.code ?? 0, 0);
|
|
assert.equal(run.signal ?? null, null);
|
|
if (expected.stdout instanceof RegExp) assert.match(run.stdout, expected.stdout);
|
|
else assert.equal(run.stdout, expected.stdout);
|
|
if (expected.stderr !== undefined) assert.equal(run.stderr, expected.stderr);
|
|
if (expected.file) assert.equal(await readFile(`${outDir}/${expected.file.name}`, "utf8"), expected.file.text);
|
|
}
|
|
|
|
async function assertCheckTimeoutOrDiagnostic(fixture, expectedCodes) {
|
|
const result = await execFileAsync(zero, ["check", "--json", fixture], { timeout: checkTimeoutMs }).catch((error) => error);
|
|
if (result.killed || result.signal) {
|
|
assert.equal(result.killed, true);
|
|
return { timedOut: true };
|
|
}
|
|
assert.notEqual(result.code, 0);
|
|
const body = JSON.parse(result.stdout);
|
|
const code = body.diagnostics?.[0]?.code;
|
|
assert(expectedCodes.includes(code), `expected one of ${expectedCodes.join(", ")}, got ${code}`);
|
|
return { timedOut: false, code };
|
|
}
|
|
|
|
async function assertElf64Object(path, exportedName) {
|
|
const bytes = await readFile(path);
|
|
assert.equal(bytes[0], 0x7f);
|
|
assert.equal(bytes[1], 0x45);
|
|
assert.equal(bytes[2], 0x4c);
|
|
assert.equal(bytes[3], 0x46);
|
|
assert.equal(bytes[4], 2);
|
|
assert.equal(bytes[5], 1);
|
|
assert.equal(bytes.readUInt16LE(16), 1);
|
|
assert.equal(bytes.readUInt16LE(18), 62);
|
|
const shoff = Number(bytes.readBigUInt64LE(40));
|
|
const shentsize = bytes.readUInt16LE(58);
|
|
const shnum = bytes.readUInt16LE(60);
|
|
const shstrndx = bytes.readUInt16LE(62);
|
|
const cstr = (offset) => {
|
|
let end = offset;
|
|
while (end < bytes.length && bytes[end] !== 0) end++;
|
|
return bytes.toString("utf8", offset, end);
|
|
};
|
|
const shstrHeader = shoff + shstrndx * shentsize;
|
|
const shstrOffset = Number(bytes.readBigUInt64LE(shstrHeader + 24));
|
|
const sections = new Map();
|
|
for (let i = 0; i < shnum; i++) {
|
|
const header = shoff + i * shentsize;
|
|
sections.set(cstr(shstrOffset + bytes.readUInt32LE(header)), {
|
|
index: i,
|
|
offset: Number(bytes.readBigUInt64LE(header + 24)),
|
|
size: Number(bytes.readBigUInt64LE(header + 32)),
|
|
link: bytes.readUInt32LE(header + 40),
|
|
entsize: Number(bytes.readBigUInt64LE(header + 56)),
|
|
});
|
|
}
|
|
assert(sections.get(".text")?.size > 0);
|
|
const symtab = sections.get(".symtab");
|
|
assert(symtab);
|
|
const strtab = [...sections.values()].find((section) => section.index === symtab.link);
|
|
assert(strtab);
|
|
let sawExport = false;
|
|
for (let offset = symtab.offset; offset < symtab.offset + symtab.size; offset += symtab.entsize) {
|
|
const name = cstr(strtab.offset + bytes.readUInt32LE(offset));
|
|
const info = bytes[offset + 4];
|
|
const shndx = bytes.readUInt16LE(offset + 6);
|
|
const size = Number(bytes.readBigUInt64LE(offset + 16));
|
|
if (name === exportedName && info === 0x12 && shndx === sections.get(".text").index && size > 0) sawExport = true;
|
|
}
|
|
assert(sawExport);
|
|
return { bytes, sections };
|
|
}
|
|
|
|
async function assertElfAarch64Object(path, exportedName) {
|
|
const bytes = await readFile(path);
|
|
assert.equal(bytes[0], 0x7f);
|
|
assert.equal(bytes[1], 0x45);
|
|
assert.equal(bytes[2], 0x4c);
|
|
assert.equal(bytes[3], 0x46);
|
|
assert.equal(bytes[4], 2);
|
|
assert.equal(bytes[5], 1);
|
|
assert.equal(bytes.readUInt16LE(16), 1);
|
|
assert.equal(bytes.readUInt16LE(18), 183);
|
|
assert(bytes.includes(Buffer.concat([Buffer.from(exportedName), Buffer.from([0])])));
|
|
return bytes;
|
|
}
|
|
|
|
function hasAarch64Instruction(bytes, expected) {
|
|
for (let offset = 0; offset + 4 <= bytes.length; offset++) {
|
|
if (bytes.readUInt32LE(offset) === expected) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function countAarch64InstructionSequence(bytes, expected) {
|
|
let count = 0;
|
|
for (let offset = 0; offset + expected.length * 4 <= bytes.length; offset++) {
|
|
let matched = true;
|
|
for (let index = 0; index < expected.length; index++) {
|
|
if (bytes.readUInt32LE(offset + index * 4) !== expected[index]) {
|
|
matched = false;
|
|
break;
|
|
}
|
|
}
|
|
if (matched) count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
function aarch64SpLoad(reg, offset, wide) {
|
|
const scale = wide ? 8 : 4;
|
|
assert.equal(offset % scale, 0);
|
|
return ((wide ? 0xf9400000 : 0xb9400000) + ((offset / scale) << 10) + (31 << 5) + reg) >>> 0;
|
|
}
|
|
|
|
function aarch64ByteViewReloadSequence(count) {
|
|
const sequence = [];
|
|
for (let index = 0; index < count; index++) {
|
|
sequence.push(aarch64SpLoad(index * 2, index * 16, true));
|
|
sequence.push(aarch64SpLoad(index * 2 + 1, index * 16 + 8, false));
|
|
}
|
|
return sequence;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
async function assertElf64Executable(path) {
|
|
const bytes = await readFile(path);
|
|
assert.equal(bytes[0], 0x7f);
|
|
assert.equal(bytes[1], 0x45);
|
|
assert.equal(bytes[2], 0x4c);
|
|
assert.equal(bytes[3], 0x46);
|
|
assert.equal(bytes[4], 2);
|
|
assert.equal(bytes[5], 1);
|
|
assert.equal(bytes.readUInt16LE(16), 2);
|
|
assert.equal(bytes.readUInt16LE(18), 62);
|
|
assert(Number(bytes.readBigUInt64LE(24)) > 0);
|
|
assert.equal(Number(bytes.readBigUInt64LE(32)), 64);
|
|
assert.equal(bytes.readUInt16LE(54), 56);
|
|
assert.equal(bytes.readUInt16LE(56), 1);
|
|
const phoff = Number(bytes.readBigUInt64LE(32));
|
|
assert.equal(bytes.readUInt32LE(phoff), 1);
|
|
assert.equal(bytes.readUInt32LE(phoff + 4), 5);
|
|
assert(Number(bytes.readBigUInt64LE(phoff + 32)) > 0);
|
|
assert.equal(Number(bytes.readBigUInt64LE(phoff + 32)), Number(bytes.readBigUInt64LE(phoff + 40)));
|
|
}
|
|
|
|
async function assertElfAarch64Executable(path) {
|
|
const bytes = await readFile(path);
|
|
assert.equal(bytes[0], 0x7f);
|
|
assert.equal(bytes[1], 0x45);
|
|
assert.equal(bytes[2], 0x4c);
|
|
assert.equal(bytes[3], 0x46);
|
|
assert.equal(bytes[4], 2);
|
|
assert.equal(bytes[5], 1);
|
|
assert.equal(bytes.readUInt16LE(16), 2);
|
|
assert.equal(bytes.readUInt16LE(18), 183);
|
|
assert.equal(bytes.readUInt16LE(54), 56);
|
|
assert.equal(bytes.readUInt16LE(56), 1);
|
|
assert(bytes.includes(Buffer.from([0x40, 0x05, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6])));
|
|
assert(bytes.includes(Buffer.from([0xa8, 0x0b, 0x80, 0xd2, 0x01, 0x00, 0x00, 0xd4])));
|
|
}
|
|
|
|
async function assertMachOArm64Object(path, exportedName) {
|
|
const bytes = await readFile(path);
|
|
assert.equal(bytes.readUInt32LE(0), 0xfeedfacf);
|
|
assert.equal(bytes.readUInt32LE(4), 0x0100000c);
|
|
assert.equal(bytes.readUInt32LE(12), 1);
|
|
assert(bytes.includes(Buffer.concat([Buffer.from(`_${exportedName}`), Buffer.from([0])])));
|
|
return bytes;
|
|
}
|
|
|
|
async function assertMachOX64Object(path, exportedName) {
|
|
const bytes = await readFile(path);
|
|
assert.equal(bytes.readUInt32LE(0), 0xfeedfacf);
|
|
assert.equal(bytes.readUInt32LE(4), 0x01000007);
|
|
assert.equal(bytes.readUInt32LE(12), 1);
|
|
assert(bytes.includes(Buffer.concat([Buffer.from(`_${exportedName}`), Buffer.from([0])])));
|
|
return bytes;
|
|
}
|
|
|
|
function assertX64SliceBoundsTrapBytes(bytes) {
|
|
assert(bytes.includes(Buffer.from([0x0f, 0x86])));
|
|
assert(bytes.includes(Buffer.from([0x0f, 0x0b])));
|
|
}
|
|
|
|
function assertX64U16RecordFieldBytes(bytes) {
|
|
assert(bytes.includes(Buffer.from([0x0f, 0xb7])));
|
|
assert(bytes.includes(Buffer.from([0x66, 0x89])));
|
|
}
|
|
|
|
function isRexW(byte) {
|
|
return (byte & 0xf8) === 0x48;
|
|
}
|
|
|
|
function hasX64MovMemoryToR64(bytes) {
|
|
for (let i = 0; i + 2 < bytes.length; i++) {
|
|
if (!isRexW(bytes[i]) || bytes[i + 1] !== 0x8b) continue;
|
|
const mod = bytes[i + 2] >> 6;
|
|
if (mod !== 3) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function hasX64MovR64ToMemory(bytes) {
|
|
for (let i = 0; i + 2 < bytes.length; i++) {
|
|
if (!isRexW(bytes[i]) || bytes[i + 1] !== 0x89) continue;
|
|
const mod = bytes[i + 2] >> 6;
|
|
if (mod !== 3) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function hasX64CmpR64(bytes) {
|
|
for (let i = 0; i + 2 < bytes.length; i++) {
|
|
if (!isRexW(bytes[i]) || bytes[i + 1] !== 0x39) continue;
|
|
const mod = bytes[i + 2] >> 6;
|
|
if (mod === 3) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
async function assertMachOArm64Executable(path) {
|
|
const bytes = await readFile(path);
|
|
assert.equal(bytes.readUInt32LE(0), 0xfeedfacf);
|
|
assert.equal(bytes.readUInt32LE(4), 0x0100000c);
|
|
assert.equal(bytes.readUInt32LE(12), 2);
|
|
const ncmds = bytes.readUInt32LE(16);
|
|
let sawUuid = false;
|
|
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 === 0x1b) {
|
|
assert.equal(cmdsize, 24);
|
|
assert(!bytes.subarray(offset + 8, offset + 24).every((byte) => byte === 0));
|
|
sawUuid = true;
|
|
}
|
|
offset += cmdsize;
|
|
}
|
|
assert(sawUuid);
|
|
assert(bytes.includes(Buffer.from("/usr/lib/dyld")));
|
|
assert(bytes.includes(Buffer.from("/usr/lib/libSystem.B.dylib")));
|
|
assert(bytes.includes(Buffer.from("zero-direct")));
|
|
return bytes;
|
|
}
|
|
|
|
async function assertCoffX64Object(path, exportedName) {
|
|
const bytes = await readFile(path);
|
|
assert.equal(bytes.readUInt16LE(0), 0x8664);
|
|
assert(bytes.readUInt16LE(2) >= 1);
|
|
assert(bytes.readUInt32LE(8) > 0);
|
|
assert(bytes.includes(Buffer.concat([Buffer.from(exportedName), Buffer.from([0])])));
|
|
return bytes;
|
|
}
|
|
|
|
async function assertPeCoffX64Executable(path) {
|
|
const bytes = await readFile(path);
|
|
assert.equal(bytes[0], 0x4d);
|
|
assert.equal(bytes[1], 0x5a);
|
|
const peOffset = bytes.readUInt32LE(0x3c);
|
|
assert.equal(bytes.toString("ascii", peOffset, peOffset + 4), "PE\u0000\u0000");
|
|
assert.equal(bytes.readUInt16LE(peOffset + 4), 0x8664);
|
|
assert.equal(bytes.readUInt16LE(peOffset + 24), 0x20b);
|
|
assert.equal(bytes.readUInt16LE(peOffset + 92), 3);
|
|
assert(bytes.includes(Buffer.from("KERNEL32.dll")));
|
|
assert(bytes.includes(Buffer.from("ExitProcess")));
|
|
assert(bytes.includes(Buffer.from("WriteFile")));
|
|
return bytes;
|
|
}
|
|
|
|
const passCheckFixtures = [
|
|
"conformance/run/pass/hello.0",
|
|
"conformance/native/pass/params.0",
|
|
"conformance/native/pass/shape.0",
|
|
"conformance/native/pass/mutref-shape-param.0",
|
|
"conformance/native/pass/mutref-shape-param-nested.0",
|
|
"conformance/native/pass/primitive-stdlib.0",
|
|
"conformance/native/pass/break-continue.0",
|
|
"conformance/native/pass/nested-break-continue.0",
|
|
"conformance/native/pass/untyped-literal-adoption.0",
|
|
"conformance/native/pass/for-range.0",
|
|
"conformance/native/pass/choice-payload-reference-return.0",
|
|
"conformance/native/pass/choice-match-payload-reference-origin.0",
|
|
"conformance/native/pass/choice-match-payload-return-origin.0",
|
|
"conformance/native/pass/null-maybe.0",
|
|
"conformance/native/pass/maybe-local-null-init-return.0",
|
|
"conformance/native/pass/meta-typed-target-type.0",
|
|
"conformance/native/pass/std-args.0",
|
|
"conformance/native/pass/std-env.0",
|
|
"conformance/native/pass/std-hosted-cli.0",
|
|
"conformance/native/pass/std-fs.0",
|
|
"conformance/native/pass/std-fs-bytes.0",
|
|
"conformance/native/pass/std-fs-read-chunks.0",
|
|
"conformance/native/pass/frame-large-locals.0",
|
|
"conformance/native/pass/frame-limit-boundary.0",
|
|
"conformance/native/pass/frame-split-helpers.0",
|
|
"conformance/native/pass/fixed-buf-alloc-local.0",
|
|
"conformance/native/pass/std-fs-resource.0",
|
|
"conformance/native/pass/std-fs-readall.0",
|
|
"conformance/native/pass/std-fs-polish.0",
|
|
"conformance/native/pass/std-fs-breadth.0",
|
|
"conformance/native/pass/std-fs-file-helpers.0",
|
|
"conformance/native/pass/std-pty-child.0",
|
|
"conformance/native/pass/std-math-breadth.0",
|
|
"conformance/native/pass/std-numeric-random-time.0",
|
|
"conformance/native/pass/std-regex.0",
|
|
"conformance/native/pass/std-unicode.0",
|
|
"conformance/native/pass/std-inet.0",
|
|
"conformance/native/pass/std-time-rfc3339.0",
|
|
"conformance/native/pass/std-io-lines.0",
|
|
"conformance/native/pass/std-path-io-breadth.0",
|
|
"conformance/native/pass/std-str-breadth.0",
|
|
"conformance/native/pass/std-testing-log.0",
|
|
"conformance/native/pass/std-term-ansi.0",
|
|
"conformance/native/pass/std-testing-helpers-test.0",
|
|
"conformance/native/pass/std-path-helper-name-collision.0",
|
|
"conformance/native/pass/std-net-http-breadth.0",
|
|
"conformance/native/pass/std-http-metadata-neutral.0",
|
|
"conformance/native/pass/std-http-fetch.0",
|
|
"conformance/native/pass/std-http-errors.0",
|
|
"conformance/native/pass/std-http-response-helpers.0",
|
|
"conformance/native/pass/std-http-text-html-response-helpers.0",
|
|
"conformance/native/pass/std-http-redirect-response-helpers.0",
|
|
"conformance/native/pass/std-http-api-helpers.0",
|
|
"conformance/native/pass/std-http-cors-helpers.0",
|
|
"conformance/native/pass/std-http-auth-helpers.0",
|
|
"conformance/native/pass/std-data-formats.0",
|
|
"conformance/native/pass/std-csv.0",
|
|
"conformance/native/pass/std-diag.0",
|
|
"conformance/native/pass/std-codec-json-url.0",
|
|
"conformance/native/pass/std-json-cursors.0",
|
|
"conformance/native/pass/std-json-bytes.0",
|
|
"conformance/native/pass/std-json-inline-bytes.0",
|
|
"conformance/native/pass/std-json-duplicate-keys.0",
|
|
"conformance/native/pass/std-json-allocator-capacity.0",
|
|
"conformance/native/pass/std-platform-basics.0",
|
|
"conformance/native/pass/std-mem-arrays.0",
|
|
"conformance/native/pass/std-mem-generic-items.0",
|
|
"conformance/native/pass/std-mem-field-items.0",
|
|
"conformance/native/pass/std-mem-byte-field-copy.0",
|
|
"conformance/native/pass/std-mem-bool-copy-items.0",
|
|
"conformance/native/pass/std-mem-u64-contains.0",
|
|
"conformance/native/pass/std-mem-u64-copy-items.0",
|
|
"conformance/native/pass/std-mem-local-u64-copy-items.0",
|
|
"conformance/native/pass/array-repeat-literal.0",
|
|
"conformance/native/pass/array-repeat-record-field.0",
|
|
"conformance/native/pass/integer-widths.0",
|
|
"conformance/native/pass/std-codec-widths.0",
|
|
"conformance/native/pass/std-crypto-hmac32.0",
|
|
"conformance/native/pass/std-crypto-sha256.0",
|
|
"conformance/native/pass/parse-integers.0",
|
|
"conformance/native/pass/explicit-casts.0",
|
|
"conformance/native/pass/float-char-casts.0",
|
|
"conformance/native/pass/radix-suffix-literals.0",
|
|
"conformance/native/pass/char-literals.0",
|
|
"conformance/native/pass/float-primitives.0",
|
|
"conformance/native/pass/wrapping-saturating-arithmetic.0",
|
|
"conformance/native/pass/maybe-guard-branch-restore.0",
|
|
"conformance/native/pass/maybe-guard-negated-conjunction.0",
|
|
"conformance/native/pass/maybe-guard-scalar-match.0",
|
|
"conformance/native/pass/maybe-guard-short-circuit-match.0",
|
|
"conformance/native/pass/maybe-guard-static-index-literals.0",
|
|
"conformance/native/pass/maybe-guard-variant-match-after.0",
|
|
"conformance/native/pass/maybe-guard-variant-guard-side-effect.0",
|
|
"conformance/native/pass/match-scalar-guards.0",
|
|
"conformance/native/pass/indexing-primitives.0",
|
|
"conformance/native/pass/checked-bounds-get.0",
|
|
"conformance/native/pass/check-maybe-fallibility.0",
|
|
"conformance/native/pass/fallibility-error-sets.0",
|
|
"conformance/native/pass/checked-fallible-wrapper.0",
|
|
"conformance/native/pass/checked-fallible-static-method.0",
|
|
"conformance/native/pass/checked-fallible-interface-method.0",
|
|
"conformance/native/pass/fallibility-check-value.0",
|
|
"conformance/native/pass/rescue-check.0",
|
|
"conformance/native/pass/std-fs-fallible.0",
|
|
"conformance/native/pass/std-fs-fallible-resources.0",
|
|
"conformance/native/pass/std-cli-helpers.0",
|
|
"conformance/native/pass/std-mem-copy-fill.0",
|
|
"conformance/native/pass/const-layout.0",
|
|
"conformance/native/pass/c-abi-export.0",
|
|
"conformance/native/pass/range-slices.0",
|
|
"conformance/native/pass/byte-view-call-single-eval.0",
|
|
"conformance/native/pass/generic-spans.0",
|
|
"conformance/native/pass/open-ended-slices.0",
|
|
"conformance/native/pass/string-slices.0",
|
|
"conformance/native/pass/string-param-span-slice.0",
|
|
"conformance/native/pass/coff-dynamic-byte-slice.0",
|
|
"conformance/native/pass/macho-large-byte-slice-blocked.0",
|
|
"conformance/native/pass/macho-nested-call-scratch-blocked.0",
|
|
"conformance/native/pass/macho-open-byte-slice.0",
|
|
"conformance/native/pass/string-byte-ergonomics.0",
|
|
"conformance/native/pass/indexed-mutation.0",
|
|
"conformance/native/pass/dynamic-indexed-store-scratch.0",
|
|
"conformance/native/pass/nested-lvalues.0",
|
|
"conformance/native/pass/mutable-spans.0",
|
|
"conformance/native/pass/mutref-indexed-lvalues.0",
|
|
"conformance/native/pass/generic-mem.0",
|
|
"conformance/native/pass/generic-function-basic.0",
|
|
"conformance/native/pass/generic-nested-calls.0",
|
|
"conformance/native/pass/generic-specialization-reuse.0",
|
|
"conformance/native/pass/generic-multi-specialization.0",
|
|
"conformance/native/pass/generic-inferred-specialized-call.0",
|
|
"conformance/native/pass/generic-nested-local-specialization.0",
|
|
"conformance/native/pass/generic-static-array-specialization.0",
|
|
"conformance/native/pass/generic-static-forwarded-array-specialization.0",
|
|
"conformance/native/pass/generic-shape-basic.0",
|
|
"conformance/native/pass/generic-shape-multi.0",
|
|
"conformance/native/pass/generic-shape-methods.0",
|
|
"conformance/native/pass/generic-shape-nested-defaults-alias.0",
|
|
"conformance/native/pass/generic-constructor-expected.0",
|
|
"conformance/native/pass/generic-expected-return.0",
|
|
"conformance/native/pass/generic-literals-arrays.0",
|
|
"conformance/native/pass/receiver-method-calls.0",
|
|
"conformance/native/pass/constructors-defaults.0",
|
|
"conformance/native/pass/static-value-params.0",
|
|
"conformance/native/pass/static-value-types-const-expr.0",
|
|
"conformance/native/pass/compile-time-v1.0",
|
|
"conformance/native/pass/static-interface-basic.0",
|
|
"conformance/native/pass/static-interface-mutref.0",
|
|
"conformance/native/pass/static-interface-static-param.0",
|
|
"conformance/native/pass/top-level-const.0",
|
|
"conformance/native/pass/const-arithmetic.0",
|
|
"conformance/native/pass/type-alias-basic.0",
|
|
"conformance/native/pass/static-method-namespace.0",
|
|
"conformance/native/pass/c-import-type-shadowing.0",
|
|
"conformance/native/pass/c-import-alias-later-local.0",
|
|
"conformance/native/pass/memory-types.0",
|
|
"conformance/native/pass/owned-transfer.0",
|
|
"conformance/native/pass/owned-field-move-return-branch.0",
|
|
"conformance/native/pass/owned-field-reassignment-after-move.0",
|
|
"conformance/native/pass/owned-array-static-index-reassignment.0",
|
|
"conformance/native/pass/owned-mutspan-alias-reassignment-after-move.0",
|
|
"conformance/native/pass/maybe-owned-null-repeat.0",
|
|
"conformance/native/pass/owned-drop-cleanup.0",
|
|
"conformance/native/pass/owned-drop-move-suppressed.0",
|
|
"conformance/native/pass/borrow-primitives.0",
|
|
"conformance/native/pass/borrow-field-independent-assignment.0",
|
|
"conformance/native/pass/borrow-aggregate-reassignment-same-origin.0",
|
|
"conformance/native/pass/receiver-return-field-origin-clears-other-field.0",
|
|
"conformance/native/pass/borrow-return-param-field-subpath.0",
|
|
"conformance/native/pass/borrow-return-explicit-ref-field-origin.0",
|
|
"conformance/native/pass/borrow-unreachable-return-origin.0",
|
|
"conformance/native/pass/borrow-unreachable-loop-return-origin.0",
|
|
"conformance/native/pass/borrow-unreachable-if-return-origin.0",
|
|
"conformance/native/pass/borrow-unreachable-match-return-origin.0",
|
|
"conformance/native/pass/borrow-unreachable-raise-return-origin.0",
|
|
"conformance/native/pass/borrow-return-ref-alias-field.0",
|
|
"conformance/native/pass/assignment-rhs-side-effect-clears-old-origin.0",
|
|
"conformance/native/pass/shadowed-mutref-side-effect-clears-old-origin.0",
|
|
"conformance/native/pass/mutref-alias-assignment-clears-old-origin.0",
|
|
"conformance/native/pass/mutref-alias-assignment-same-origin.0",
|
|
"conformance/native/pass/function-mutref-reference-store.0",
|
|
"conformance/native/pass/generic-mutref-reference-store.0",
|
|
"conformance/native/pass/receiver-method-reference-store.0",
|
|
"conformance/native/pass/static-interface-mutref-reference-store.0",
|
|
"conformance/native/pass/static-interface-return-reference-origin.0",
|
|
"conformance/native/pass/borrow-return-param-ref.0",
|
|
"conformance/native/pass/borrow-assignment-same-origin.0",
|
|
"conformance/native/pass/borrow-shadowed-root-reassignment.0",
|
|
"conformance/native/pass/borrow-branch-reassignment.0",
|
|
"conformance/native/pass/branch-overwrite-away-reference-origin.0",
|
|
"conformance/native/pass/shape-field-reference-reassignment-clears-origin.0",
|
|
"conformance/native/pass/index-reference-assignment-clears-origin.0",
|
|
"conformance/native/pass/allocator-primitives.0",
|
|
"conformance/native/pass/std-mem-arena.0",
|
|
"conformance/native/pass/std-mem-collections.0",
|
|
"conformance/native/pass/std-collections-algorithms.0",
|
|
"conformance/native/pass/std-collections-u8.0",
|
|
"conformance/native/pass/std-collections-mutspan-memory.0",
|
|
"conformance/native/pass/std-collections-usize-memory.0",
|
|
"conformance/native/pass/std-collections-query-memory.0",
|
|
"conformance/native/pass/std-search-sort-widths.0",
|
|
"conformance/native/pass/owned-byte-buffer.0",
|
|
"conformance/check/pass/generic-function-basic.0",
|
|
"conformance/check/pass/generic-array-inference.0",
|
|
"conformance/check/pass/generic-static-explicit-shadowing.0",
|
|
"conformance/check/pass/generic-static-forwarding.0",
|
|
"conformance/check/pass/generic-static-method-forwarding.0",
|
|
"conformance/check/pass/generic-static-return-substitution.0",
|
|
"conformance/check/pass/generic-static-wrapper-type-collision.0",
|
|
"conformance/check/pass/static-interface-return-substitution.0",
|
|
"conformance/check/pass/generic-untyped-static-const-inference.0",
|
|
"conformance/check/pass/generic-const-shadowing.0",
|
|
"conformance/check/pass/generic-const-type-name-collision.0",
|
|
"conformance/check/pass/generic-mixed-const-type-name-collision.0",
|
|
"conformance/check/pass/generic-method-outer-param-inference.0",
|
|
"conformance/native/pass/generic-nested-calls.0",
|
|
"conformance/native/pass/generic-specialization-reuse.0",
|
|
"conformance/native/pass/generic-multi-specialization.0",
|
|
"conformance/native/pass/generic-inferred-specialized-call.0",
|
|
"conformance/native/pass/generic-nested-local-specialization.0",
|
|
"conformance/native/pass/generic-static-array-specialization.0",
|
|
"conformance/native/pass/generic-static-forwarded-array-specialization.0",
|
|
"conformance/check/pass/generic-shape-basic.0",
|
|
"conformance/check/pass/generic-shape-multi.0",
|
|
"conformance/check/pass/generic-shape-methods.0",
|
|
"conformance/native/pass/generic-constructor-expected.0",
|
|
"conformance/native/pass/generic-literals-arrays.0",
|
|
"conformance/check/pass/receiver-method-calls.0",
|
|
"conformance/check/pass/shape-field-defaults.0",
|
|
"conformance/check/pass/static-value-params.0",
|
|
"conformance/check/pass/static-interface-basic.0",
|
|
"conformance/check/pass/call-resolution-edge-cases.0",
|
|
"conformance/native/pass/static-interface-mutref.0",
|
|
"conformance/native/pass/static-interface-static-param.0",
|
|
"conformance/check/pass/top-level-const.0",
|
|
"conformance/check/pass/const-arithmetic.0",
|
|
"conformance/check/pass/type-alias-basic.0",
|
|
"conformance/check/pass/static-method-namespace.0",
|
|
"conformance/check/pass/fmt-core-usability.0",
|
|
"conformance/check/pass/c-header-import.0",
|
|
"conformance/check/pass/c-import-local-shadowing.0",
|
|
"conformance/check/pass/match-fallback.0",
|
|
"conformance/check/pass/memory-types.0",
|
|
"conformance/check/pass/std-mem-field-items.0",
|
|
"conformance/check/pass/std-mem-field-slice.0",
|
|
"conformance/check/pass/fixed-array-length-match.0",
|
|
"conformance/check/pass/imports",
|
|
"examples/memory-package",
|
|
"examples/const-arithmetic.0",
|
|
"examples/generic-pair.0",
|
|
"examples/fixed-vec.0",
|
|
"examples/static-value-params.0",
|
|
"examples/compile-time-v1.0",
|
|
"examples/type-alias.0",
|
|
"examples/static-method.0",
|
|
"examples/static-interface.0",
|
|
"examples/ownership-cleanup.0",
|
|
];
|
|
await mapLimit(passCheckFixtures, checkJobs, (fixture, _index, workerIndex) => checkFixtureParallel(fixture, workerIndex));
|
|
|
|
const stdSortMergeOverlap = await writeImportFailureFixture(`${outDir}/std-sort-merge-overlap.0`, `pub fn main() -> Void {
|
|
var values: [5]i32 = [1, 3, 5, 2, 4]
|
|
let written: usize = std.sort.mergeSortedI32(values, std.mem.prefix(values, 3_usize), std.mem.dropPrefix(values, 3_usize))
|
|
}
|
|
`);
|
|
assert.equal(stdSortMergeOverlap.diagnostics[0].code, "STD003");
|
|
assert.match(stdSortMergeOverlap.diagnostics[0].message, /std\.sort\.mergeSorted source must not overlap destination storage/);
|
|
|
|
const stdMemStartsWithMismatch = await writeImportFailureFixture(`${outDir}/std-mem-startswith-mismatch.0`, `pub fn main() -> Void {
|
|
let left_values: [2]i32 = [1, 2]
|
|
let right_values: [2]u32 = [1_u32, 2_u32]
|
|
let left: Span<i32> = left_values
|
|
let right: Span<u32> = right_values
|
|
let ok: Bool = std.mem.startsWith(left, right)
|
|
}
|
|
`);
|
|
assert.equal(stdMemStartsWithMismatch.diagnostics[0].code, "STD003");
|
|
assert.match(stdMemStartsWithMismatch.diagnostics[0].message, /std\.mem\.startsWith span element types must match/);
|
|
|
|
const stdMemStartsWithUnsupported = await writeImportFailureFixture(`${outDir}/std-mem-startswith-unsupported.0`, `type Point {
|
|
x: i32,
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let points: [1]Point = [Point { x: 1 }]
|
|
let span: Span<Point> = points
|
|
let ok: Bool = std.mem.startsWith(span, span)
|
|
}
|
|
`);
|
|
assert.equal(stdMemStartsWithUnsupported.diagnostics[0].code, "STD003");
|
|
assert.match(stdMemStartsWithUnsupported.diagnostics[0].message, /std\.mem\.startsWith item element type is not supported/);
|
|
|
|
// Fixtures using the gated typed graph MIR constructs fail check with the
|
|
// same BLD004 diagnostics zero build reports for their graph stores.
|
|
const gateBlockedCheckFixtures = [
|
|
"conformance/check/pass/package",
|
|
"conformance/native/pass/variants-defer-stdlib.0",
|
|
"conformance/native/pass/defer-return-raise-nested.0",
|
|
"conformance/native/pass/payload-match.0",
|
|
"conformance/native/pass/match-payload-binding.0",
|
|
"conformance/native/pass/match-choice-fallback.0",
|
|
"conformance/native/pass/maybe-error-flow.0",
|
|
"conformance/native/pass/match-fallback.0",
|
|
"conformance/check/pass/call-resolution-inspection.0",
|
|
"conformance/check/pass/checker-type-forms.0",
|
|
];
|
|
await mapLimit(gateBlockedCheckFixtures, checkJobs, (fixture, _index, workerIndex) => checkFailureFixtureParallel(fixture, /BLD004/, workerIndex));
|
|
|
|
const checkJsonSuccess = await execFileAsync(zero, ["check", "--json", "conformance/native/pass/explicit-casts.0"]);
|
|
const checkJsonSuccessBody = JSON.parse(checkJsonSuccess.stdout);
|
|
assert.equal(checkJsonSuccessBody.ok, true);
|
|
assert.equal(checkJsonSuccessBody.diagnostics.length, 0);
|
|
assert.equal(checkJsonSuccessBody.artifact, "conformance/native/pass/explicit-casts.graph");
|
|
assert.equal(checkJsonSuccessBody.canonicalSource, false);
|
|
assert.equal(checkJsonSuccessBody.moduleIdentity, "module:explicit-casts");
|
|
assert.match(checkJsonSuccessBody.graphHash, /^graph:[0-9a-f]{16}$/);
|
|
assert.equal(checkJsonSuccessBody.check.phase, "typecheck");
|
|
assert.equal(checkJsonSuccessBody.check.lowering, "graph-native-check");
|
|
assert.equal(checkJsonSuccessBody.graphCompiler.input, "program-graph-artifact");
|
|
assert.equal(checkJsonSuccessBody.graphCompiler.graphNativeCheckerUsed, true);
|
|
assert.equal(checkJsonSuccessBody.graphCompiler.graphHirToMirUsed, true);
|
|
|
|
const stdDiagGraphCheck = await execFileAsync(zero, ["check", "--json", "conformance/native/pass/std-diag.graph"]);
|
|
const stdDiagGraphCheckBody = JSON.parse(stdDiagGraphCheck.stdout);
|
|
assert.equal(stdDiagGraphCheckBody.ok, true);
|
|
assert.equal(stdDiagGraphCheckBody.targetReadiness.ok, true);
|
|
assert.equal(stdDiagGraphCheckBody.targetReadiness.buildable, true);
|
|
assert.equal(stdDiagGraphCheckBody.targetReadiness.diagnostics.length, 0);
|
|
|
|
const agentSurfaceClassification = JSON.parse(await readFile("conformance/agent-surface/classification.json", "utf8"));
|
|
assert.equal(agentSurfaceClassification.schema, 1);
|
|
assert.deepEqual(agentSurfaceClassification.fixtures.map((item) => item.id), [
|
|
"interface-method-generic-binding",
|
|
"direct-generic-recursion",
|
|
"direct-generic-specialization-name-collision",
|
|
"stdlib-signature-parity",
|
|
"owned-drop-direct-backend-unsupported",
|
|
]);
|
|
|
|
const agentSurfaceInterfaceMethodGeneric = await execFileAsync(zero, ["check", "--json", "conformance/agent-surface/fixtures/interface-method-generic-binding.0"]);
|
|
const agentSurfaceInterfaceMethodGenericBody = JSON.parse(agentSurfaceInterfaceMethodGeneric.stdout);
|
|
assert.equal(agentSurfaceInterfaceMethodGenericBody.ok, true);
|
|
assert.equal(agentSurfaceInterfaceMethodGenericBody.diagnostics.length, 0);
|
|
|
|
const agentSurfaceDirectGenericCheck = await execFileAsync(zero, ["check", "--json", "conformance/agent-surface/fixtures/direct-generic-recursion.0"]);
|
|
const agentSurfaceDirectGenericCheckBody = JSON.parse(agentSurfaceDirectGenericCheck.stdout);
|
|
assert.equal(agentSurfaceDirectGenericCheckBody.ok, true);
|
|
assert.equal(agentSurfaceDirectGenericCheckBody.diagnostics.length, 0);
|
|
const agentSurfaceDirectGenericReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"linux-musl-x64",
|
|
"conformance/agent-surface/fixtures/direct-generic-recursion.0",
|
|
]);
|
|
const agentSurfaceDirectGenericReadinessBody = JSON.parse(agentSurfaceDirectGenericReadiness.stdout);
|
|
assert.equal(agentSurfaceDirectGenericReadinessBody.ok, true);
|
|
assert.equal(agentSurfaceDirectGenericReadinessBody.targetReadiness.ok, true);
|
|
assert.equal(agentSurfaceDirectGenericReadinessBody.targetReadiness.buildable, true);
|
|
assert.equal(agentSurfaceDirectGenericReadinessBody.targetReadiness.diagnostics.length, 0);
|
|
|
|
const agentSurfaceDirectGenericCollisionReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"linux-musl-x64",
|
|
"conformance/agent-surface/fixtures/direct-generic-specialization-name-collision.0",
|
|
]);
|
|
const agentSurfaceDirectGenericCollisionReadinessBody = JSON.parse(agentSurfaceDirectGenericCollisionReadiness.stdout);
|
|
assert.equal(agentSurfaceDirectGenericCollisionReadinessBody.ok, true);
|
|
assert.equal(agentSurfaceDirectGenericCollisionReadinessBody.targetReadiness.ok, false);
|
|
assert.equal(agentSurfaceDirectGenericCollisionReadinessBody.targetReadiness.buildable, false);
|
|
assert.equal(agentSurfaceDirectGenericCollisionReadinessBody.targetReadiness.diagnostics[0].code, "BLD004");
|
|
assert.match(agentSurfaceDirectGenericCollisionReadinessBody.targetReadiness.diagnostics[0].message, /specialization name collides/);
|
|
|
|
const compilerMetrics = await execFileAsync("node", ["--experimental-strip-types", "--disable-warning=ExperimentalWarning", "scripts/compiler-metrics.mts"]);
|
|
const compilerMetricsBody = JSON.parse(compilerMetrics.stdout);
|
|
assert.equal(compilerMetricsBody.schema, 1);
|
|
assert(compilerMetricsBody.files["native/zero-c/src/checker.c"].lines > 0);
|
|
assert.equal(compilerMetricsBody.files["native/zero-c/src/fs.c"].shellCalls, 0);
|
|
assert.equal(compilerMetricsBody.files["native/zero-c/src/main.c"].shellCalls, 0);
|
|
for (const [path, metrics] of Object.entries(compilerMetricsBody.files)) {
|
|
assert.equal(metrics.shellCalls, 0, `${path} should not introduce shell execution calls`);
|
|
}
|
|
|
|
const relativeToolDir = `${outDir}/relative-tools`;
|
|
await mkdir(relativeToolDir, { recursive: true });
|
|
await writeFile(`${relativeToolDir}/cc`, "#!/bin/sh\nprintf 'fake relative cc\\n'\n");
|
|
await chmod(`${relativeToolDir}/cc`, 0o755);
|
|
const relativePathDoctor = await execFileAsync(zero, ["doctor", "--json"], { env: { ...process.env, PATH: relativeToolDir } }).catch((error) => error);
|
|
assert.notEqual(relativePathDoctor.code, 0);
|
|
const relativePathDoctorBody = JSON.parse(relativePathDoctor.stdout);
|
|
const relativePathNativeCompiler = relativePathDoctorBody.checks.find((check) => check.name === "native-c-compiler");
|
|
assert.equal(relativePathNativeCompiler.status, "error");
|
|
assert.match(relativePathNativeCompiler.message, /no native C compiler found/);
|
|
|
|
assert(Array.isArray(compilerMetricsBody.largeFunctions));
|
|
assert(compilerMetricsBody.stdlib.mainHelperCount > 0);
|
|
assert.equal(compilerMetricsBody.stdlib.mainHelperCount, compilerMetricsBody.stdlib.checkerReturnCount);
|
|
assert.equal(compilerMetricsBody.stdlib.mainHelperCount, compilerMetricsBody.stdlib.checkerArgCountCount);
|
|
assert.deepEqual(compilerMetricsBody.stdlib.duplicateCheckerReturnTypes, []);
|
|
assert.deepEqual(compilerMetricsBody.stdlib.duplicateCheckerArgCounts, []);
|
|
assert.deepEqual(compilerMetricsBody.stdlib.checkerReturnsMissingFromMainHelpers, []);
|
|
assert.deepEqual(compilerMetricsBody.stdlib.mainHelpersMissingFromCheckerReturns, []);
|
|
assert.deepEqual(compilerMetricsBody.stdlib.checkerArgCountsMissingFromMainHelpers, []);
|
|
assert.deepEqual(compilerMetricsBody.stdlib.mainHelpersMissingFromCheckerArgCounts, []);
|
|
assert.deepEqual(compilerMetricsBody.stdlib.argCountMismatches, []);
|
|
assert.equal(compilerMetricsBody.stdlib.sharedSignatureLookup.checkerReturnTypes, true);
|
|
assert.equal(compilerMetricsBody.stdlib.sharedSignatureLookup.checkerArgCounts, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.elf.sharedWriter, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.elf.x86ObjectUsesSharedWriter, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.elf.x86ExecutableUsesSharedWriter, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.elf.aarch64ObjectUsesSharedWriter, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.elf.aarch64ExecutableUsesSharedWriter, true);
|
|
assert.deepEqual(compilerMetricsBody.backendFormats.elf.archFilesWithLocalSectionWriters, []);
|
|
assert.equal(compilerMetricsBody.backendFormats.elf.patchStateModule, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.elf.x86UsesPatchStateModule, true);
|
|
assert.deepEqual(compilerMetricsBody.backendFormats.elf.archFilesWithLocalPatchState, []);
|
|
assert.equal(compilerMetricsBody.backendFormats.coff.sharedWriter, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.coff.objectUsesSharedWriter, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.coff.executableUsesSharedWriter, true);
|
|
assert.deepEqual(compilerMetricsBody.backendFormats.coff.archFilesWithLocalContainerWriters, []);
|
|
assert.equal(compilerMetricsBody.backendFormats.coff.patchStateModule, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.coff.x64UsesPatchStateModule, true);
|
|
assert.deepEqual(compilerMetricsBody.backendFormats.coff.archFilesWithLocalPatchState, []);
|
|
assert.equal(compilerMetricsBody.backendFormats.macho.sharedWriter, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.macho.objectUsesSharedWriter, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.macho.executableUsesSharedWriter, true);
|
|
assert.deepEqual(compilerMetricsBody.backendFormats.macho.archFilesWithLocalContainerWriters, []);
|
|
assert.equal(compilerMetricsBody.backendFormats.macho.patchStateModule, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.macho.archFileUsesPatchStateModule, true);
|
|
assert.deepEqual(compilerMetricsBody.backendFormats.macho.archFilesWithLocalPatchState, []);
|
|
assert.equal(compilerMetricsBody.backendFormats.x64.sharedEncodingPrimitives, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.x64.elfUsesSharedEncodingPrimitives, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.x64.coffUsesSharedEncodingPrimitives, true);
|
|
assert.deepEqual(compilerMetricsBody.backendFormats.x64.formatFilesWithLocalEncodingPrimitives, []);
|
|
assert.equal(compilerMetricsBody.backendFormats.aarch64.sharedEncodingPrimitives, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.aarch64.elfUsesSharedEncodingPrimitives, true);
|
|
assert.equal(compilerMetricsBody.backendFormats.aarch64.machoUsesSharedEncodingPrimitives, true);
|
|
assert.deepEqual(compilerMetricsBody.backendFormats.aarch64.formatFilesWithLocalEncodingPrimitives, []);
|
|
assert.equal(compilerMetricsBody.budget.ok, true);
|
|
assert.deepEqual(compilerMetricsBody.budget.violations, []);
|
|
assert.equal(typeof compilerMetricsBody.budget.reportThreshold, "number");
|
|
for (const item of compilerMetricsBody.largeFunctions) {
|
|
assert.equal(typeof item.path, "string");
|
|
assert.equal(typeof item.signature, "string");
|
|
assert.equal(typeof item.line, "number");
|
|
assert.equal(typeof item.lines, "number");
|
|
assert(item.lines >= compilerMetricsBody.budget.reportThreshold);
|
|
}
|
|
|
|
const unsafeCompilerOverrideBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--out",
|
|
`${outDir}/unsafe-cc-override`,
|
|
"examples/json-api-client.graph",
|
|
], { env: { ...process.env, ZERO_CC: "cc;touch" } }).catch((error) => error);
|
|
assert.notEqual(unsafeCompilerOverrideBuild.code, 0);
|
|
assert.match(unsafeCompilerOverrideBuild.stderr, /compiler override contains unsafe shell characters/);
|
|
const unsafeCompilerOverrideBody = JSON.parse(unsafeCompilerOverrideBuild.stdout);
|
|
assert.equal(unsafeCompilerOverrideBody.ok, false);
|
|
assert.equal(unsafeCompilerOverrideBody.diagnostics[0].code, "BLD003");
|
|
assert.equal(unsafeCompilerOverrideBody.diagnostics[0].actual, "compiler override contains unsafe shell characters");
|
|
assert.match(unsafeCompilerOverrideBody.diagnostics[0].help, /without flags, whitespace, or shell syntax/);
|
|
|
|
const agentSurfaceBorrowExplain = await execFileAsync(zero, ["explain", "--json", "BOR001"]);
|
|
const agentSurfaceBorrowExplainBody = JSON.parse(agentSurfaceBorrowExplain.stdout);
|
|
assert.equal(agentSurfaceBorrowExplainBody.code, "BOR001");
|
|
assert.equal(agentSurfaceBorrowExplainBody.repair.id, "end-conflicting-borrow");
|
|
assert.match(agentSurfaceBorrowExplainBody.summary, /lexical scope/);
|
|
|
|
const agentSurfaceMalformedLocalUseFixture = `${outDir}/malformed-local-use.0`;
|
|
await writeFile(agentSurfaceMalformedLocalUseFixture, 'use local.\n\npub fn main(world: World) -> Void raises {\n check world.out.write("malformed local use parser fixture\\n")\n}\n');
|
|
const agentSurfaceMalformedLocalUse = await execFileAsync(zero, ["parse", "--json", agentSurfaceMalformedLocalUseFixture]).catch((error) => error);
|
|
assert.notEqual(agentSurfaceMalformedLocalUse.code, 0);
|
|
const agentSurfaceMalformedLocalUseBody = JSON.parse(agentSurfaceMalformedLocalUse.stdout);
|
|
assert.equal(agentSurfaceMalformedLocalUseBody.diagnostics[0].code, "PAR100");
|
|
assert.match(agentSurfaceMalformedLocalUseBody.diagnostics[0].message, /expected import module segment/);
|
|
assert.equal(agentSurfaceMalformedLocalUseBody.diagnostics[0].line, 1);
|
|
assert.equal(agentSurfaceMalformedLocalUseBody.diagnostics[0].column, 11);
|
|
|
|
const agentSurfaceSplitUseFixture = `${outDir}/split-use-path.0`;
|
|
await writeFile(agentSurfaceSplitUseFixture, 'use std.\ncodec\n\npub fn main(world: World) -> Void raises {\n check world.out.write("split use parser fixture\\n")\n}\n');
|
|
const agentSurfaceSplitUse = await execFileAsync(zero, ["parse", "--json", agentSurfaceSplitUseFixture]).catch((error) => error);
|
|
assert.notEqual(agentSurfaceSplitUse.code, 0);
|
|
const agentSurfaceSplitUseBody = JSON.parse(agentSurfaceSplitUse.stdout);
|
|
assert.equal(agentSurfaceSplitUseBody.diagnostics[0].code, "PAR100");
|
|
assert.match(agentSurfaceSplitUseBody.diagnostics[0].message, /expected import module segment/);
|
|
assert.equal(agentSurfaceSplitUseBody.diagnostics[0].line, 1);
|
|
assert.equal(agentSurfaceSplitUseBody.diagnostics[0].column, 9);
|
|
|
|
const agentSurfaceKeywordUseFixture = `${outDir}/keyword-use.0`;
|
|
await writeFile(agentSurfaceKeywordUseFixture, 'use pub\n\npub fn main(world: World) -> Void raises {\n check world.out.write("keyword use parser fixture\\n")\n}\n');
|
|
const agentSurfaceKeywordUse = await execFileAsync(zero, ["parse", "--json", agentSurfaceKeywordUseFixture]).catch((error) => error);
|
|
assert.notEqual(agentSurfaceKeywordUse.code, 0);
|
|
const agentSurfaceKeywordUseBody = JSON.parse(agentSurfaceKeywordUse.stdout);
|
|
assert.equal(agentSurfaceKeywordUseBody.diagnostics[0].code, "PAR100");
|
|
assert.match(agentSurfaceKeywordUseBody.diagnostics[0].message, /reserved word cannot be used as an identifier/);
|
|
assert.equal(agentSurfaceKeywordUseBody.diagnostics[0].line, 1);
|
|
assert.equal(agentSurfaceKeywordUseBody.diagnostics[0].column, 5);
|
|
|
|
const agentSurfaceOwnedDropCheck = await execFileAsync(zero, ["check", "--json", "conformance/agent-surface/fixtures/owned-drop-direct-backend-unsupported.0"]);
|
|
const agentSurfaceOwnedDropCheckBody = JSON.parse(agentSurfaceOwnedDropCheck.stdout);
|
|
assert.equal(agentSurfaceOwnedDropCheckBody.ok, true);
|
|
|
|
const agentSurfaceOwnedDropReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"linux-musl-x64",
|
|
"conformance/agent-surface/fixtures/owned-drop-direct-backend-unsupported.0",
|
|
]);
|
|
const agentSurfaceOwnedDropReadinessBody = JSON.parse(agentSurfaceOwnedDropReadiness.stdout);
|
|
assert.equal(agentSurfaceOwnedDropReadinessBody.ok, true);
|
|
assert.equal(agentSurfaceOwnedDropReadinessBody.diagnostics.length, 0);
|
|
assert.equal(agentSurfaceOwnedDropReadinessBody.targetReadiness.ok, false);
|
|
assert.equal(agentSurfaceOwnedDropReadinessBody.targetReadiness.buildable, false);
|
|
assert.equal(agentSurfaceOwnedDropReadinessBody.targetReadiness.languageOk, true);
|
|
assert.equal(agentSurfaceOwnedDropReadinessBody.targetReadiness.diagnostics[0].code, "BLD004");
|
|
assert.deepEqual(agentSurfaceOwnedDropReadinessBody.targetReadiness.diagnostics[0].backendBlocker, {
|
|
target: "linux-musl-x64",
|
|
objectFormat: "elf",
|
|
backend: "zero-elf64",
|
|
stage: "lower",
|
|
unsupportedFeature: "owned<Tracked>",
|
|
});
|
|
|
|
const directCallExeReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"exe",
|
|
"--target",
|
|
"linux-musl-x64",
|
|
"examples/direct-call-add.0",
|
|
]);
|
|
const directCallExeReadinessBody = JSON.parse(directCallExeReadiness.stdout);
|
|
assert.equal(directCallExeReadinessBody.ok, true);
|
|
assert.equal(directCallExeReadinessBody.diagnostics.length, 0);
|
|
assert.equal(directCallExeReadinessBody.targetReadiness.ok, false);
|
|
assert.equal(directCallExeReadinessBody.targetReadiness.buildable, false);
|
|
assert.equal(directCallExeReadinessBody.targetReadiness.diagnostics[0].code, "BLD004");
|
|
assert.equal(directCallExeReadinessBody.targetReadiness.diagnostics[0].backendBlocker.stage, "buildability");
|
|
assert.match(directCallExeReadinessBody.targetReadiness.diagnostics[0].message, /main must not take parameters/);
|
|
const directCallExeBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"exe",
|
|
"--target",
|
|
"linux-musl-x64",
|
|
"examples/direct-call-add.0",
|
|
"--out",
|
|
`${outDir}/direct-call-add-blocked`,
|
|
]).catch((error) => error);
|
|
assert.notEqual(directCallExeBuild.code, 0);
|
|
const directCallExeBuildBody = JSON.parse(directCallExeBuild.stdout);
|
|
const directCallReadinessDiag = directCallExeReadinessBody.targetReadiness.diagnostics[0];
|
|
const directCallBuildDiag = directCallExeBuildBody.diagnostics[0];
|
|
for (const key of ["code", "path", "line", "column", "length", "expected", "actual", "help"]) {
|
|
assert.equal(directCallBuildDiag[key], directCallReadinessDiag[key]);
|
|
}
|
|
assert.equal(directCallBuildDiag.backendBlocker.stage, "buildability");
|
|
const directCallExeGraph = await execFileAsync(zero, [
|
|
"inspect",
|
|
"--json",
|
|
"--emit",
|
|
"exe",
|
|
"--target",
|
|
"linux-musl-x64",
|
|
"examples/direct-call-add.0",
|
|
]);
|
|
const directCallExeGraphBody = JSON.parse(directCallExeGraph.stdout);
|
|
assert.equal(directCallExeGraphBody.targetReadiness.ok, false);
|
|
assert.equal(directCallExeGraphBody.targetReadiness.diagnostics[0].code, "BLD004");
|
|
const directCallGraphDiag = directCallExeGraphBody.targetReadiness.diagnostics[0];
|
|
assert.equal(directCallGraphDiag.path, "direct-call-add.0");
|
|
assert.equal(directCallGraphDiag.expected, "direct ELF64 object subset");
|
|
assert.equal(directCallGraphDiag.actual, "unsupported construct");
|
|
assert.equal(directCallGraphDiag.backendBlocker.backend, "zero-elf64-exe");
|
|
assert.equal(directCallGraphDiag.backendBlocker.stage, "lower");
|
|
|
|
const llvmLoopIrPath = `${outDir}/llvm-direct-while-sum.ll`;
|
|
await execFileAsync(zero, [
|
|
"build",
|
|
"--emit",
|
|
"llvm-ir",
|
|
"--backend",
|
|
"llvm",
|
|
"examples/direct-while-sum.0",
|
|
"--out",
|
|
llvmLoopIrPath,
|
|
]);
|
|
const llvmLoopIr = await readFile(llvmLoopIrPath, "utf8");
|
|
assert.match(llvmLoopIr, /^; zero llvm-ir v1\n/);
|
|
assert.match(llvmLoopIr, /target triple = "/);
|
|
assert.match(llvmLoopIr, /define i32 @main\(\) \{/);
|
|
assert.match(llvmLoopIr, /br label %L0\nL0:\n/);
|
|
assert.match(llvmLoopIr, /icmp slt i32 %v[0-9]+, 5/);
|
|
assert.match(llvmLoopIr, /add i32 %v[0-9]+, %v[0-9]+/);
|
|
assert.match(llvmLoopIr, /ret i32 %v[0-9]+/);
|
|
|
|
const llvmArrayIr = await buildLlvmIrFixture("examples/direct-array-sum.0", "llvm-direct-array-sum");
|
|
assert.match(llvmArrayIr, /alloca \[4 x i32\]/);
|
|
assert.match(llvmArrayIr, /getelementptr inbounds \[4 x i32\], ptr %slot[0-9]+, i64 0, i64 0/);
|
|
assert.match(llvmArrayIr, /getelementptr inbounds \[4 x i32\], ptr %slot[0-9]+, i64 0, i64 %v[0-9]+/);
|
|
assert.match(llvmArrayIr, /store i32 4, ptr %v[0-9]+, align 4/);
|
|
assert.match(llvmArrayIr, /load i32, ptr %v[0-9]+, align 4/);
|
|
assert.match(llvmArrayIr, /call void @llvm\.trap\(\)/);
|
|
await assertLlvmHostExitCode("examples/direct-array-sum.0", "llvm-direct-array-sum", 10);
|
|
|
|
const llvmStringLenIr = await buildLlvmIrFixture("examples/direct-string-len.0", "llvm-direct-string-len");
|
|
assert.match(llvmStringLenIr, /@\.zero\.data\.0 = private unnamed_addr constant \[6 x i8\] c"token\\00", align 1/);
|
|
assert.match(llvmStringLenIr, /insertvalue \{ ptr, i64 \} poison, ptr %v[0-9]+, 0/);
|
|
assert.match(llvmStringLenIr, /insertvalue \{ ptr, i64 \} %v[0-9]+, i64 5, 1/);
|
|
assert.match(llvmStringLenIr, /ret i64 5/);
|
|
await assertLlvmHostExitCode("examples/direct-string-len.0", "llvm-direct-string-len", 5);
|
|
|
|
const llvmByteCopyFillIr = await buildLlvmIrFixture("examples/direct-byte-copy-fill.0", "llvm-direct-byte-copy-fill");
|
|
assert.match(llvmByteCopyFillIr, /declare void @llvm\.memcpy\.p0\.p0\.i64\(ptr, ptr, i64, i1\)/);
|
|
assert.match(llvmByteCopyFillIr, /declare void @llvm\.memset\.p0\.i64\(ptr, i8, i64, i1\)/);
|
|
assert.match(llvmByteCopyFillIr, /alloca \[5 x i8\]/);
|
|
assert.match(llvmByteCopyFillIr, /call void @llvm\.memset\.p0\.i64\(ptr %v[0-9]+, i8 33, i64 (?:5|%v[0-9]+), i1 false\)/);
|
|
assert.match(llvmByteCopyFillIr, /select i1 %v[0-9]+, i64 %v[0-9]+, i64 %v[0-9]+/);
|
|
assert.match(llvmByteCopyFillIr, /call void @llvm\.memcpy\.p0\.p0\.i64\(ptr %v[0-9]+, ptr %v[0-9]+, i64 %v[0-9]+, i1 false\)/);
|
|
await assertLlvmHostExitCode("examples/direct-byte-copy-fill.0", "llvm-direct-byte-copy-fill", 111);
|
|
|
|
const llvmStringEqlIr = await buildLlvmIrFixture("examples/direct-string-eql.0", "llvm-direct-string-eql");
|
|
assertLlvmPhiPredecessors(llvmStringEqlIr);
|
|
assert.match(llvmStringEqlIr, /phi i64 \[0, %L[0-9]+\], \[%v[0-9]+, %L[0-9]+\]/);
|
|
assert.match(llvmStringEqlIr, /icmp eq i8 %v[0-9]+, %v[0-9]+/);
|
|
assert.match(llvmStringEqlIr, /phi i1 \[1, %L[0-9]+\], \[0, %L[0-9]+\]/);
|
|
await assertLlvmHostExitCode("examples/direct-string-eql.0", "llvm-direct-string-eql", 1);
|
|
|
|
const llvmByteViewLocalsIr = await buildLlvmIrFixture("examples/direct-byte-view-locals.0", "llvm-direct-byte-view-locals");
|
|
assertLlvmPhiPredecessors(llvmByteViewLocalsIr);
|
|
assert.match(llvmByteViewLocalsIr, /alloca \{ ptr, i64 \}/);
|
|
assert.match(llvmByteViewLocalsIr, /store \{ ptr, i64 \} %v[0-9]+, ptr %slot[0-9]+, align 8/);
|
|
assert.match(llvmByteViewLocalsIr, /load \{ ptr, i64 \}, ptr %slot[0-9]+, align 8/);
|
|
assert.match(llvmByteViewLocalsIr, /extractvalue \{ ptr, i64 \} %v[0-9]+, 0/);
|
|
assert.match(llvmByteViewLocalsIr, /extractvalue \{ ptr, i64 \} %v[0-9]+, 1/);
|
|
await assertLlvmHostExitCode("examples/direct-byte-view-locals.0", "llvm-direct-byte-view-locals", 107);
|
|
|
|
const llvmSpanReadIr = await buildLlvmIrFixture("examples/direct-span-read.0", "llvm-direct-span-read");
|
|
assert.match(llvmSpanReadIr, /icmp ule i64 %v[0-9]+, %v[0-9]+/);
|
|
assert.match(llvmSpanReadIr, /icmp ult i64 %v[0-9]+, %v[0-9]+/);
|
|
assert.match(llvmSpanReadIr, /getelementptr inbounds i8, ptr %v[0-9]+, i64 %v[0-9]+/);
|
|
assert.match(llvmSpanReadIr, /load i8, ptr %v[0-9]+, align 1/);
|
|
await assertLlvmHostExitCode("examples/direct-span-read.0", "llvm-direct-span-read", 107);
|
|
|
|
const llvmShortCircuitSourcePath = `${outDir}/llvm-short-circuit.0`;
|
|
const llvmShortCircuitIrPath = `${outDir}/llvm-short-circuit.ll`;
|
|
await writeGraphFixture(llvmShortCircuitSourcePath, `fn rhsAnd() -> Bool {
|
|
return true
|
|
}
|
|
|
|
fn rhsOr() -> Bool {
|
|
return false
|
|
}
|
|
|
|
export c fn main() -> i32 {
|
|
if false && rhsAnd() {
|
|
return 1
|
|
}
|
|
if true || rhsOr() {
|
|
return 2
|
|
}
|
|
if true && (false && rhsAnd()) {
|
|
return 3
|
|
}
|
|
if false || (true || rhsOr()) {
|
|
return 4
|
|
}
|
|
return 0
|
|
}
|
|
`);
|
|
await execFileAsync(zero, [
|
|
"build",
|
|
"--emit",
|
|
"llvm-ir",
|
|
"--backend",
|
|
"llvm",
|
|
llvmShortCircuitSourcePath,
|
|
"--out",
|
|
llvmShortCircuitIrPath,
|
|
]);
|
|
const llvmShortCircuitIr = await readFile(llvmShortCircuitIrPath, "utf8");
|
|
assertLlvmPhiPredecessors(llvmShortCircuitIr);
|
|
assert.match(llvmShortCircuitIr, /br i1 0, label %L[0-9]+, label %L[0-9]+\nL[0-9]+:\n %v[0-9]+ = call i1 @\.zero\.fn\.[0-9]+\.rhsAnd\(\)/);
|
|
assert.match(llvmShortCircuitIr, /%v[0-9]+ = phi i1 \[%v[0-9]+, %L[0-9]+\], \[0, %L[0-9]+\]/);
|
|
assert.match(llvmShortCircuitIr, /br i1 1, label %L[0-9]+, label %L[0-9]+\nL[0-9]+:\n %v[0-9]+ = call i1 @\.zero\.fn\.[0-9]+\.rhsOr\(\)/);
|
|
assert.match(llvmShortCircuitIr, /%v[0-9]+ = phi i1 \[%v[0-9]+, %L[0-9]+\], \[1, %L[0-9]+\]/);
|
|
|
|
const llvmAddIrPath = `${outDir}/llvm-add.ll`;
|
|
const llvmAddBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"llvm-ir",
|
|
"--backend",
|
|
"llvm",
|
|
"examples/add.0",
|
|
"--out",
|
|
llvmAddIrPath,
|
|
]);
|
|
const llvmAddBuildBody = JSON.parse(llvmAddBuild.stdout);
|
|
assert.equal(llvmAddBuildBody.objectBackend.linking.targetLibraries, "zero-runtime");
|
|
assert.equal(llvmAddBuildBody.objectBackend.linking.toolchainSource, "textual-llvm-ir-runtime-link-plan");
|
|
assert.deepEqual(llvmAddBuildBody.objectBackend.linkerPlan.staticLibraries, ["zero_runtime.o"]);
|
|
const llvmAddIr = await readFile(llvmAddIrPath, "utf8");
|
|
assert.match(llvmAddIr, /@\.zero\.data\.0 = private unnamed_addr constant \[12 x i8\] c"math works\\0A\\00", align 1/);
|
|
assert.match(llvmAddIr, /declare i32 @zero_world_write\(i32, ptr, i32\)/);
|
|
assert.match(llvmAddIr, /declare void @llvm\.trap\(\)/);
|
|
assert.match(llvmAddIr, /define i32 @\.zero\.fn\.[0-9]+\.answer\(\) \{/);
|
|
assert.match(llvmAddIr, /call i32 @zero_world_write\(i32 1, ptr %v[0-9]+, i32 (?:11|%v[0-9]+)\)/);
|
|
assert.match(llvmAddIr, /%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 llvmSymbolCollisionSourcePath = `${outDir}/llvm-symbol-collision.0`;
|
|
const llvmSymbolCollisionIrPath = `${outDir}/llvm-symbol-collision.ll`;
|
|
await writeGraphFixture(llvmSymbolCollisionSourcePath, `fn foo() -> i32 {
|
|
return 1
|
|
}
|
|
|
|
export c fn z_fn_0_foo() -> i32 {
|
|
return 2
|
|
}
|
|
|
|
export c fn main() -> i32 {
|
|
return foo() + z_fn_0_foo()
|
|
}
|
|
`);
|
|
await execFileAsync(zero, [
|
|
"build",
|
|
"--emit",
|
|
"llvm-ir",
|
|
"--backend",
|
|
"llvm",
|
|
llvmSymbolCollisionSourcePath,
|
|
"--out",
|
|
llvmSymbolCollisionIrPath,
|
|
]);
|
|
const llvmSymbolCollisionIr = await readFile(llvmSymbolCollisionIrPath, "utf8");
|
|
assert.match(llvmSymbolCollisionIr, /define i32 @\.zero\.fn\.[0-9]+\.foo\(\) \{/);
|
|
assert.match(llvmSymbolCollisionIr, /define i32 @z_fn_0_foo\(\) \{/);
|
|
assert.match(llvmSymbolCollisionIr, /call i32 @\.zero\.fn\.[0-9]+\.foo\(\)/);
|
|
assert.equal((llvmSymbolCollisionIr.match(/define i32 @z_fn_0_foo\(\) \{/g) || []).length, 1);
|
|
|
|
const llvmRuntimeCollisionSourcePath = `${outDir}/llvm-runtime-symbol-collision.0`;
|
|
await writeGraphFixture(llvmRuntimeCollisionSourcePath, `export c fn zero_world_write() -> i32 {
|
|
return 7
|
|
}
|
|
|
|
pub fn main(world: World) -> Void raises {
|
|
check world.out.write("hello\\n")
|
|
}
|
|
`);
|
|
const llvmRuntimeCollisionReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"llvm-ir",
|
|
"--backend",
|
|
"llvm",
|
|
llvmRuntimeCollisionSourcePath,
|
|
]);
|
|
const llvmRuntimeCollisionReadinessBody = JSON.parse(llvmRuntimeCollisionReadiness.stdout);
|
|
assert.equal(llvmRuntimeCollisionReadinessBody.ok, true);
|
|
assert.equal(llvmRuntimeCollisionReadinessBody.targetReadiness.ok, false);
|
|
assert.equal(llvmRuntimeCollisionReadinessBody.targetReadiness.diagnostics[0].code, "BLD004");
|
|
assert.equal(llvmRuntimeCollisionReadinessBody.targetReadiness.diagnostics[0].actual, "zero_world_write");
|
|
assert.equal(llvmRuntimeCollisionReadinessBody.targetReadiness.diagnostics[0].backendBlocker.backend, "llvm");
|
|
assert.equal(llvmRuntimeCollisionReadinessBody.targetReadiness.diagnostics[0].backendBlocker.stage, "lower");
|
|
const llvmRuntimeCollisionBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"llvm-ir",
|
|
"--backend",
|
|
"llvm",
|
|
llvmRuntimeCollisionSourcePath,
|
|
"--out",
|
|
`${outDir}/llvm-runtime-symbol-collision.ll`,
|
|
]).catch((error) => error);
|
|
assert.notEqual(llvmRuntimeCollisionBuild.code, 0);
|
|
const llvmRuntimeCollisionBuildBody = JSON.parse(llvmRuntimeCollisionBuild.stdout);
|
|
assert.equal(llvmRuntimeCollisionBuildBody.diagnostics[0].actual, "zero_world_write");
|
|
assert.equal(llvmRuntimeCollisionBuildBody.diagnostics[0].backendBlocker.backend, "llvm");
|
|
|
|
const llvmLongExportName = `llvm_export_${"a".repeat(200)}`;
|
|
const llvmLongExportSourcePath = `${outDir}/llvm-long-export.0`;
|
|
const llvmLongExportIrPath = `${outDir}/llvm-long-export.ll`;
|
|
await writeGraphFixture(llvmLongExportSourcePath, `export c fn ${llvmLongExportName}() -> i32 {
|
|
return 7
|
|
}
|
|
|
|
export c fn main() -> i32 {
|
|
return ${llvmLongExportName}()
|
|
}
|
|
`);
|
|
await execFileAsync(zero, [
|
|
"build",
|
|
"--emit",
|
|
"llvm-ir",
|
|
"--backend",
|
|
"llvm",
|
|
llvmLongExportSourcePath,
|
|
"--out",
|
|
llvmLongExportIrPath,
|
|
]);
|
|
const llvmLongExportIr = await readFile(llvmLongExportIrPath, "utf8");
|
|
assert(llvmLongExportIr.includes(`define i32 @${llvmLongExportName}() {`));
|
|
assert(llvmLongExportIr.includes(`call i32 @${llvmLongExportName}()`));
|
|
|
|
const directStringMachOExe = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"exe",
|
|
"--target",
|
|
"darwin-arm64",
|
|
"examples/direct-string-literal.0",
|
|
"--out",
|
|
`${outDir}/direct-string-literal-darwin`,
|
|
]);
|
|
const directStringMachOExeBody = JSON.parse(directStringMachOExe.stdout);
|
|
assert.equal(directStringMachOExeBody.compiler, "zero-macho64");
|
|
assert.equal(directStringMachOExeBody.generatedCBytes, 0);
|
|
const directStringCoffExe = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"exe",
|
|
"--target",
|
|
"win32-x64.exe",
|
|
"examples/direct-string-literal.0",
|
|
"--out",
|
|
`${outDir}/direct-string-literal-win`,
|
|
]);
|
|
const directStringCoffExeBody = JSON.parse(directStringCoffExe.stdout);
|
|
assert.equal(directStringCoffExeBody.compiler, "zero-coff-x64");
|
|
assert.equal(directStringCoffExeBody.generatedCBytes, 0);
|
|
|
|
const coffDynamicSliceFixture = "conformance/native/pass/coff-dynamic-byte-slice.0";
|
|
const coffDynamicSliceReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"win32-x64.exe",
|
|
coffDynamicSliceFixture,
|
|
]);
|
|
const coffDynamicSliceReadinessBody = JSON.parse(coffDynamicSliceReadiness.stdout);
|
|
assert.equal(coffDynamicSliceReadinessBody.ok, true);
|
|
assert.equal(coffDynamicSliceReadinessBody.diagnostics.length, 0);
|
|
assert.equal(coffDynamicSliceReadinessBody.targetReadiness.ok, true);
|
|
assert.equal(coffDynamicSliceReadinessBody.targetReadiness.buildable, true);
|
|
assert.equal(coffDynamicSliceReadinessBody.targetReadiness.backend, "zero-coff-x64");
|
|
const coffDynamicSliceBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"win32-x64.exe",
|
|
coffDynamicSliceFixture,
|
|
"--out",
|
|
`${outDir}/coff-dynamic-byte-slice.obj`,
|
|
]);
|
|
const coffDynamicSliceBuildBody = JSON.parse(coffDynamicSliceBuild.stdout);
|
|
assert.equal(coffDynamicSliceBuildBody.compiler, "zero-coff-x64");
|
|
assert.equal(coffDynamicSliceBuildBody.generatedCBytes, 0);
|
|
assert.equal(coffDynamicSliceBuildBody.objectBackend.objectEmission.path, "direct-coff-x64-object");
|
|
await assertCoffX64Object(`${outDir}/coff-dynamic-byte-slice.obj`, "main");
|
|
|
|
const coffU64CopyFixture = "conformance/native/pass/std-mem-u64-copy-items.0";
|
|
const coffU64CopyReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"win32-x64.exe",
|
|
coffU64CopyFixture,
|
|
]);
|
|
const coffU64CopyReadinessBody = JSON.parse(coffU64CopyReadiness.stdout);
|
|
assert.equal(coffU64CopyReadinessBody.ok, true);
|
|
assert.equal(coffU64CopyReadinessBody.targetReadiness.ok, true);
|
|
assert.equal(coffU64CopyReadinessBody.targetReadiness.buildable, true);
|
|
assert.equal(coffU64CopyReadinessBody.targetReadiness.backend, "zero-coff-x64");
|
|
const coffU64CopyPath = `${outDir}/coff-u64-copy-items.obj`;
|
|
const coffU64CopyBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"win32-x64.exe",
|
|
coffU64CopyFixture,
|
|
"--out",
|
|
coffU64CopyPath,
|
|
]);
|
|
const coffU64CopyBuildBody = JSON.parse(coffU64CopyBuild.stdout);
|
|
assert.equal(coffU64CopyBuildBody.compiler, "zero-coff-x64");
|
|
assert.equal(coffU64CopyBuildBody.generatedCBytes, 0);
|
|
assert.equal(coffU64CopyBuildBody.objectBackend.objectEmission.path, "direct-coff-x64-object");
|
|
const coffU64CopyBytes = await assertCoffX64Object(coffU64CopyPath, "main");
|
|
assert(hasX64MovMemoryToR64(coffU64CopyBytes));
|
|
assert(hasX64MovR64ToMemory(coffU64CopyBytes));
|
|
|
|
const coffU64ContainsFixture = "conformance/native/pass/std-mem-u64-contains.0";
|
|
const coffU64ContainsReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"win32-x64.exe",
|
|
coffU64ContainsFixture,
|
|
]);
|
|
const coffU64ContainsReadinessBody = JSON.parse(coffU64ContainsReadiness.stdout);
|
|
assert.equal(coffU64ContainsReadinessBody.ok, true);
|
|
assert.equal(coffU64ContainsReadinessBody.targetReadiness.ok, true);
|
|
assert.equal(coffU64ContainsReadinessBody.targetReadiness.buildable, true);
|
|
assert.equal(coffU64ContainsReadinessBody.targetReadiness.backend, "zero-coff-x64");
|
|
const coffU64ContainsPath = `${outDir}/coff-u64-contains.obj`;
|
|
const coffU64ContainsBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"win32-x64.exe",
|
|
coffU64ContainsFixture,
|
|
"--out",
|
|
coffU64ContainsPath,
|
|
]);
|
|
const coffU64ContainsBuildBody = JSON.parse(coffU64ContainsBuild.stdout);
|
|
assert.equal(coffU64ContainsBuildBody.compiler, "zero-coff-x64");
|
|
assert.equal(coffU64ContainsBuildBody.generatedCBytes, 0);
|
|
assert.equal(coffU64ContainsBuildBody.objectBackend.objectEmission.path, "direct-coff-x64-object");
|
|
const coffU64ContainsBytes = await assertCoffX64Object(coffU64ContainsPath, "main");
|
|
assert(coffU64ContainsBytes.includes(Buffer.from([0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00])));
|
|
assert(hasX64MovMemoryToR64(coffU64ContainsBytes));
|
|
assert(hasX64CmpR64(coffU64ContainsBytes));
|
|
|
|
const coffBoolCopyFixture = "conformance/native/pass/std-mem-bool-copy-items.0";
|
|
const coffBoolCopyReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"win32-x64.exe",
|
|
coffBoolCopyFixture,
|
|
]);
|
|
const coffBoolCopyReadinessBody = JSON.parse(coffBoolCopyReadiness.stdout);
|
|
assert.equal(coffBoolCopyReadinessBody.ok, true);
|
|
assert.equal(coffBoolCopyReadinessBody.targetReadiness.ok, true);
|
|
assert.equal(coffBoolCopyReadinessBody.targetReadiness.buildable, true);
|
|
assert.equal(coffBoolCopyReadinessBody.targetReadiness.backend, "zero-coff-x64");
|
|
const coffBoolCopyPath = `${outDir}/coff-bool-copy-items.obj`;
|
|
const coffBoolCopyBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"win32-x64.exe",
|
|
coffBoolCopyFixture,
|
|
"--out",
|
|
coffBoolCopyPath,
|
|
]);
|
|
const coffBoolCopyBuildBody = JSON.parse(coffBoolCopyBuild.stdout);
|
|
assert.equal(coffBoolCopyBuildBody.compiler, "zero-coff-x64");
|
|
assert.equal(coffBoolCopyBuildBody.generatedCBytes, 0);
|
|
assert.equal(coffBoolCopyBuildBody.objectBackend.objectEmission.path, "direct-coff-x64-object");
|
|
await assertCoffX64Object(coffBoolCopyPath, "main");
|
|
|
|
async function assertMachOObjectBuildabilityBlocked(fixture, outName, expectedMessage) {
|
|
const readiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"darwin-arm64",
|
|
fixture,
|
|
]);
|
|
const readinessBody = JSON.parse(readiness.stdout);
|
|
assert.equal(readinessBody.ok, true);
|
|
assert.equal(readinessBody.diagnostics.length, 0);
|
|
assert.equal(readinessBody.targetReadiness.ok, false);
|
|
assert.equal(readinessBody.targetReadiness.buildable, false);
|
|
assert.equal(readinessBody.targetReadiness.languageOk, true);
|
|
assert.equal(readinessBody.targetReadiness.emit, "obj");
|
|
assert.equal(readinessBody.targetReadiness.target, "darwin-arm64");
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].code, "BLD004");
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].backendBlocker.backend, "zero-macho64");
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].backendBlocker.stage, "buildability");
|
|
assert.match(readinessBody.targetReadiness.diagnostics[0].message, expectedMessage);
|
|
const build = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"darwin-arm64",
|
|
fixture,
|
|
"--out",
|
|
`${outDir}/${outName}`,
|
|
]).catch((error) => error);
|
|
assert.notEqual(build.code, 0);
|
|
const buildBody = JSON.parse(build.stdout);
|
|
const readinessDiag = readinessBody.targetReadiness.diagnostics[0];
|
|
const buildDiag = buildBody.diagnostics[0];
|
|
for (const key of ["code", "path", "line", "column", "length", "expected", "actual", "help"]) {
|
|
assert.equal(buildDiag[key], readinessDiag[key]);
|
|
}
|
|
assert.equal(buildDiag.backendBlocker.backend, "zero-macho64");
|
|
assert.equal(buildDiag.backendBlocker.stage, "buildability");
|
|
}
|
|
|
|
await assertMachOObjectBuildabilityBlocked(
|
|
"conformance/native/pass/macho-large-byte-slice-blocked.0",
|
|
"macho-large-byte-slice.o",
|
|
/constant start/,
|
|
);
|
|
await assertMachOObjectBuildabilityBlocked(
|
|
"conformance/native/pass/macho-nested-call-scratch-blocked.0",
|
|
"macho-nested-call-scratch.o",
|
|
/scratch spill capacity/,
|
|
);
|
|
|
|
const machoOpenByteSliceFixture = "conformance/native/pass/macho-open-byte-slice.0";
|
|
const machoOpenByteSliceReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"darwin-arm64",
|
|
machoOpenByteSliceFixture,
|
|
]);
|
|
const machoOpenByteSliceReadinessBody = JSON.parse(machoOpenByteSliceReadiness.stdout);
|
|
assert.equal(machoOpenByteSliceReadinessBody.ok, true);
|
|
assert.equal(machoOpenByteSliceReadinessBody.diagnostics.length, 0);
|
|
assert.equal(machoOpenByteSliceReadinessBody.targetReadiness.ok, true);
|
|
assert.equal(machoOpenByteSliceReadinessBody.targetReadiness.buildable, true);
|
|
assert.equal(machoOpenByteSliceReadinessBody.targetReadiness.backend, "zero-macho64");
|
|
const machoOpenByteSliceBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"darwin-arm64",
|
|
machoOpenByteSliceFixture,
|
|
"--out",
|
|
`${outDir}/macho-open-byte-slice.o`,
|
|
]);
|
|
const machoOpenByteSliceBuildBody = JSON.parse(machoOpenByteSliceBuild.stdout);
|
|
assert.equal(machoOpenByteSliceBuildBody.compiler, "zero-macho64");
|
|
assert.equal(machoOpenByteSliceBuildBody.generatedCBytes, 0);
|
|
assert.equal(machoOpenByteSliceBuildBody.objectBackend.objectEmission.path, "direct-macho64-object");
|
|
await assertMachOArm64Object(`${outDir}/macho-open-byte-slice.o`, "main");
|
|
|
|
const aarch64OpenSliceBoundsFixture = `${outDir}/aarch64-open-byte-slice-bounds.0`;
|
|
await writeGraphFixture(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
|
|
}
|
|
`);
|
|
await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"linux-arm64",
|
|
aarch64OpenSliceBoundsFixture,
|
|
"--out",
|
|
`${outDir}/aarch64-open-byte-slice-bounds.o`,
|
|
]);
|
|
const aarch64OpenSliceBoundsBytes = await assertElfAarch64Object(`${outDir}/aarch64-open-byte-slice-bounds.o`, "main");
|
|
assert(hasAarch64CondBranch(aarch64OpenSliceBoundsBytes, 9));
|
|
assert(hasAarch64Instruction(aarch64OpenSliceBoundsBytes, 0xd4200000));
|
|
await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"darwin-arm64",
|
|
aarch64OpenSliceBoundsFixture,
|
|
"--out",
|
|
`${outDir}/macho-open-byte-slice-bounds.o`,
|
|
]);
|
|
const machoOpenSliceBoundsBytes = await assertMachOArm64Object(`${outDir}/macho-open-byte-slice-bounds.o`, "main");
|
|
assert(hasAarch64CondBranch(machoOpenSliceBoundsBytes, 9));
|
|
assert(hasAarch64Instruction(machoOpenSliceBoundsBytes, 0xd4200000));
|
|
|
|
const trapMessageFixture = `${outDir}/trap-index-message.0`;
|
|
const trapMessageGraph = await writeGraphFixture(trapMessageFixture, `pub fn main(world: World) -> Void raises {
|
|
var values: [4]u32 = [1, 2, 3, 4]
|
|
var index: usize = 4
|
|
index = index + 1000
|
|
let v: u32 = values[index]
|
|
if v == 1 {
|
|
check world.out.write("unreachable\\n")
|
|
}
|
|
}
|
|
`);
|
|
if (runnableDirectTarget) {
|
|
const trapMessageOut = `${outDir}/trap-index-message`;
|
|
await execFileAsync(zero, ["build", "--json", "--emit", "exe", "--target", runnableDirectTarget, trapMessageGraph, "--out", trapMessageOut]);
|
|
const trapMessageRun = await execFileAsync(trapMessageOut, []).catch((error) => error);
|
|
assert.notEqual(trapMessageRun.code ?? (trapMessageRun.signal ? 1 : 0), 0, "deliberate out-of-bounds index must abort");
|
|
assert.match(trapMessageRun.stderr ?? "", /trap: index out of bounds/);
|
|
assert.equal(trapMessageRun.stdout ?? "", "");
|
|
}
|
|
|
|
const x64OpenSliceBoundsFixture = `${outDir}/x64-open-u16-slice-bounds.0`;
|
|
await writeGraphFixture(x64OpenSliceBoundsFixture, `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 x64SliceLenBoundsFixture = `${outDir}/x64-len-u16-slice-bounds.0`;
|
|
await writeGraphFixture(x64SliceLenBoundsFixture, `export c fn main() -> u32 {
|
|
let words: [2]u16 = [1_u16, 2_u16]
|
|
return (std.mem.len(words[..3_usize])) as u32
|
|
}
|
|
`);
|
|
|
|
await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"linux-arm64",
|
|
x64SliceLenBoundsFixture,
|
|
"--out",
|
|
`${outDir}/aarch64-len-u16-slice-bounds.o`,
|
|
]);
|
|
const aarch64LenSliceBoundsBytes = await assertElfAarch64Object(`${outDir}/aarch64-len-u16-slice-bounds.o`, "main");
|
|
assert(hasAarch64CondBranch(aarch64LenSliceBoundsBytes, 9));
|
|
assert(hasAarch64Instruction(aarch64LenSliceBoundsBytes, 0xd4200000));
|
|
await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"darwin-arm64",
|
|
x64SliceLenBoundsFixture,
|
|
"--out",
|
|
`${outDir}/macho-len-u16-slice-bounds.o`,
|
|
]);
|
|
const machoLenSliceBoundsBytes = await assertMachOArm64Object(`${outDir}/macho-len-u16-slice-bounds.o`, "main");
|
|
assert(hasAarch64CondBranch(machoLenSliceBoundsBytes, 9));
|
|
assert(hasAarch64Instruction(machoLenSliceBoundsBytes, 0xd4200000));
|
|
|
|
async function assertX64SliceBoundsObject(fixture, name) {
|
|
const elfPath = `${outDir}/${name}-linux.o`;
|
|
await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", fixture, "--out", elfPath]);
|
|
assertX64SliceBoundsTrapBytes((await assertElf64Object(elfPath, "main")).bytes);
|
|
|
|
const machoPath = `${outDir}/${name}-macho-x64.o`;
|
|
await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", "darwin-x64", fixture, "--out", machoPath]);
|
|
assertX64SliceBoundsTrapBytes(await assertMachOX64Object(machoPath, "main"));
|
|
|
|
const coffPath = `${outDir}/${name}-coff.obj`;
|
|
await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", "win32-x64.exe", fixture, "--out", coffPath]);
|
|
assertX64SliceBoundsTrapBytes(await assertCoffX64Object(coffPath, "main"));
|
|
}
|
|
|
|
await assertX64SliceBoundsObject(x64OpenSliceBoundsFixture, "x64-open-u16-slice-bounds");
|
|
await assertX64SliceBoundsObject(x64SliceLenBoundsFixture, "x64-len-u16-slice-bounds");
|
|
|
|
const x64U16RecordFieldFixture = `${outDir}/x64-u16-record-field.0`;
|
|
await writeGraphFixture(x64U16RecordFieldFixture, `type Holder {
|
|
values: [3]u16,
|
|
}
|
|
|
|
export c fn main() -> u32 {
|
|
var holder: Holder = Holder { values: [10_u16, 20_u16, 30_u16] }
|
|
if holder.values[0] == 10_u16 && holder.values[1] == 20_u16 && holder.values[2] == 30_u16 {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|
|
`);
|
|
const x64U16RecordFieldElfPath = `${outDir}/x64-u16-record-field-linux.o`;
|
|
await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", x64U16RecordFieldFixture, "--out", x64U16RecordFieldElfPath]);
|
|
assertX64U16RecordFieldBytes((await assertElf64Object(x64U16RecordFieldElfPath, "main")).bytes);
|
|
const x64U16RecordFieldMachOPath = `${outDir}/x64-u16-record-field-macho-x64.o`;
|
|
await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", "darwin-x64", x64U16RecordFieldFixture, "--out", x64U16RecordFieldMachOPath]);
|
|
assertX64U16RecordFieldBytes(await assertMachOX64Object(x64U16RecordFieldMachOPath, "main"));
|
|
|
|
async function assertAArch64ObjectBuildabilityBlocked(target, backend, outName, expectedMessage) {
|
|
const fixture = "conformance/native/pass/macho-nested-call-scratch-blocked.0";
|
|
const readiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
target,
|
|
fixture,
|
|
]);
|
|
const readinessBody = JSON.parse(readiness.stdout);
|
|
assert.equal(readinessBody.ok, true);
|
|
assert.equal(readinessBody.diagnostics.length, 0);
|
|
assert.equal(readinessBody.targetReadiness.ok, false);
|
|
assert.equal(readinessBody.targetReadiness.buildable, false);
|
|
assert.equal(readinessBody.targetReadiness.languageOk, true);
|
|
assert.equal(readinessBody.targetReadiness.emit, "obj");
|
|
assert.equal(readinessBody.targetReadiness.target, target);
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].code, "BLD004");
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].backendBlocker.backend, backend);
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].backendBlocker.stage, "buildability");
|
|
assert.match(readinessBody.targetReadiness.diagnostics[0].message, expectedMessage);
|
|
const build = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
target,
|
|
fixture,
|
|
"--out",
|
|
`${outDir}/${outName}`,
|
|
]).catch((error) => error);
|
|
assert.notEqual(build.code, 0);
|
|
const buildBody = JSON.parse(build.stdout);
|
|
const readinessDiag = readinessBody.targetReadiness.diagnostics[0];
|
|
const buildDiag = buildBody.diagnostics[0];
|
|
for (const key of ["code", "path", "line", "column", "length", "expected", "actual", "help"]) {
|
|
assert.equal(buildDiag[key], readinessDiag[key]);
|
|
}
|
|
assert.equal(buildDiag.backendBlocker.backend, backend);
|
|
assert.equal(buildDiag.backendBlocker.stage, "buildability");
|
|
}
|
|
|
|
await assertAArch64ObjectBuildabilityBlocked("linux-arm64", "zero-elf-aarch64", "elf-aarch64-nested-call-scratch.o", /scratch spill capacity/);
|
|
await assertAArch64ObjectBuildabilityBlocked("win32-arm64.exe", "zero-coff-aarch64", "coff-aarch64-nested-call-scratch.obj", /scratch spill capacity/);
|
|
const machoBoolArraysBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"darwin-arm64",
|
|
"conformance/native/pass/bool-arrays.0",
|
|
"--out",
|
|
`${outDir}/macho-bool-arrays.o`,
|
|
]);
|
|
const machoBoolArraysBody = JSON.parse(machoBoolArraysBuild.stdout);
|
|
assert.equal(machoBoolArraysBody.compiler, "zero-macho64");
|
|
assert.equal(machoBoolArraysBody.generatedCBytes, 0);
|
|
assert.equal(machoBoolArraysBody.objectBackend.objectEmission.path, "direct-macho64-object");
|
|
|
|
const directCallArm64ObjReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"linux-arm64",
|
|
"examples/direct-call-add.0",
|
|
]);
|
|
const directCallArm64ObjReadinessBody = JSON.parse(directCallArm64ObjReadiness.stdout);
|
|
assert.equal(directCallArm64ObjReadinessBody.ok, true);
|
|
assert.equal(directCallArm64ObjReadinessBody.diagnostics.length, 0);
|
|
assert.equal(directCallArm64ObjReadinessBody.targetReadiness.ok, true);
|
|
assert.equal(directCallArm64ObjReadinessBody.targetReadiness.buildable, true);
|
|
assert.equal(directCallArm64ObjReadinessBody.targetReadiness.backend, "zero-elf-aarch64");
|
|
const directCallArm64ObjBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"linux-arm64",
|
|
"examples/direct-call-add.0",
|
|
"--out",
|
|
`${outDir}/direct-call-add-arm64.o`,
|
|
]);
|
|
const directCallArm64ObjBuildBody = JSON.parse(directCallArm64ObjBuild.stdout);
|
|
assert.equal(directCallArm64ObjBuildBody.compiler, "zero-elf-aarch64");
|
|
assert.equal(directCallArm64ObjBuildBody.generatedCBytes, 0);
|
|
assert.equal(directCallArm64ObjBuildBody.objectBackend.objectEmission.path, "direct-elf-aarch64-object");
|
|
await assertElfAarch64Object(`${outDir}/direct-call-add-arm64.o`, "main");
|
|
|
|
const arm64ProcDynamicViewsSource = `${outDir}/aarch64-proc-dynamic-byte-view-spawn.0`;
|
|
const arm64ProcDynamicViewsObj = `${outDir}/aarch64-proc-dynamic-byte-view-spawn.o`;
|
|
await writeGraphFixture(arm64ProcDynamicViewsSource, `fn programName() -> String {
|
|
return "sh"
|
|
}
|
|
|
|
fn childArgs() -> Span<u8> {
|
|
return std.mem.span("-c\\ntrue")
|
|
}
|
|
|
|
fn cwdName() -> String {
|
|
return "."
|
|
}
|
|
|
|
fn envBlock() -> Span<u8> {
|
|
return std.mem.span("ZERO_AARCH64_PROC=1")
|
|
}
|
|
|
|
fn childCommand() -> String {
|
|
return "sh -c true"
|
|
}
|
|
|
|
export c fn main() -> i32 {
|
|
let status: ProcStatus = std.proc.spawnInheritArgs(programName(), childArgs(), cwdName(), envBlock())
|
|
let child: ProcChild = std.proc.spawnChildArgs(programName(), childArgs(), cwdName(), envBlock())
|
|
let child_env: ProcChild = std.proc.spawnChildInEnv(childCommand(), cwdName(), envBlock())
|
|
let pty_child: ProcChild = std.pty.spawnArgs(programName(), childArgs(), cwdName(), envBlock())
|
|
return std.proc.exitCode(status) + std.proc.pid(child) + std.proc.pid(child_env) + std.proc.pid(pty_child)
|
|
}
|
|
`);
|
|
const arm64ProcDynamicViewsBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"linux-arm64",
|
|
arm64ProcDynamicViewsSource,
|
|
"--out",
|
|
arm64ProcDynamicViewsObj,
|
|
]);
|
|
const arm64ProcDynamicViewsBuildBody = JSON.parse(arm64ProcDynamicViewsBuild.stdout);
|
|
assert.equal(arm64ProcDynamicViewsBuildBody.compiler, "zero-elf-aarch64");
|
|
assert.equal(arm64ProcDynamicViewsBuildBody.objectBackend.objectEmission.path, "direct-elf-aarch64-object");
|
|
const arm64ProcDynamicViewsBytes = await assertElfAarch64Object(arm64ProcDynamicViewsObj, "main");
|
|
assert(countAarch64InstructionSequence(arm64ProcDynamicViewsBytes, aarch64ByteViewReloadSequence(4)) >= 3);
|
|
|
|
let arm64NestedIndexExpr = "values[idx]";
|
|
for (let i = 0; i < 32; i++) arm64NestedIndexExpr = `(0_u32 + ${arm64NestedIndexExpr})`;
|
|
const arm64NestedIndexFixture = `${outDir}/aarch64-nested-index-scratch-blocked.0`;
|
|
await writeGraphFixture(arm64NestedIndexFixture, `export c fn main() -> u32 {
|
|
let values: [1]u32 = [7]
|
|
let idx: u32 = 0_u32
|
|
return ${arm64NestedIndexExpr}
|
|
}
|
|
`);
|
|
async function assertArm64NestedScratchBlocked(fixture, expectedMessage, outPrefix) {
|
|
for (const blocked of [["linux-arm64", "zero-elf-aarch64", "linux.o"], ["darwin-arm64", "zero-macho64", "macho.o"], ["win32-arm64.exe", "zero-coff-aarch64", "coff.obj"]]) {
|
|
const readiness = await execFileAsync(zero, ["check", "--json", "--emit", "obj", "--target", blocked[0], fixture]);
|
|
const readinessBody = JSON.parse(readiness.stdout);
|
|
assert.equal(readinessBody.ok, true);
|
|
assert.equal(readinessBody.targetReadiness.ok, false);
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].code, "BLD004");
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].backendBlocker.backend, blocked[1]);
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].backendBlocker.stage, "buildability");
|
|
assert.match(readinessBody.targetReadiness.diagnostics[0].message, expectedMessage);
|
|
const build = await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", blocked[0], fixture, "--out", `${outDir}/${outPrefix}-${blocked[2]}`]).catch((error) => error);
|
|
assert.notEqual(build.code, 0);
|
|
assert.equal(JSON.parse(build.stdout).diagnostics[0].backendBlocker.stage, "buildability");
|
|
}
|
|
}
|
|
await assertArm64NestedScratchBlocked(arm64NestedIndexFixture, /indexed load exceeds scratch register spill capacity/, "aarch64-nested-index");
|
|
let arm64NestedLenExpr = "((std.mem.len(text[start..end])) as u32)";
|
|
for (let i = 0; i < 32; i++) arm64NestedLenExpr = `(0_u32 + ${arm64NestedLenExpr})`;
|
|
const arm64NestedLenFixture = `${outDir}/aarch64-nested-len-scratch-blocked.0`;
|
|
await writeGraphFixture(arm64NestedLenFixture, `export c fn main() -> u32 {
|
|
let text: String = "abcdef"
|
|
let start: usize = 1
|
|
let end: usize = 4
|
|
return ${arm64NestedLenExpr}
|
|
}
|
|
`);
|
|
await assertArm64NestedScratchBlocked(arm64NestedLenFixture, /byte-view length exceeds scratch register spill capacity/, "aarch64-nested-len");
|
|
let arm64NestedDynamicStartLenExpr = "((std.mem.len(text[(start + 0_usize)..end])) as u32)";
|
|
for (let i = 0; i < 31; i++) arm64NestedDynamicStartLenExpr = `(0_u32 + ${arm64NestedDynamicStartLenExpr})`;
|
|
const arm64NestedDynamicStartLenFixture = `${outDir}/aarch64-nested-dynamic-start-len-scratch-blocked.0`;
|
|
await writeGraphFixture(arm64NestedDynamicStartLenFixture, `export c fn main() -> u32 {
|
|
let text: String = "abcdef"
|
|
let start: usize = 1
|
|
let end: usize = 4
|
|
return ${arm64NestedDynamicStartLenExpr}
|
|
}
|
|
`);
|
|
await assertArm64NestedScratchBlocked(arm64NestedDynamicStartLenFixture, /byte-view length exceeds scratch register spill capacity/, "aarch64-nested-dynamic-start-len");
|
|
let arm64NestedEndLenExpr = "((std.mem.len(text[1..(end + 0_usize)])) as u32)";
|
|
for (let i = 0; i < 32; i++) arm64NestedEndLenExpr = `(0_u32 + ${arm64NestedEndLenExpr})`;
|
|
const arm64NestedEndLenFixture = `${outDir}/aarch64-nested-end-len-scratch-blocked.0`;
|
|
await writeGraphFixture(arm64NestedEndLenFixture, `export c fn main() -> u32 {
|
|
let text: String = "abcdef"
|
|
let end: usize = 4
|
|
return ${arm64NestedEndLenExpr}
|
|
}
|
|
`);
|
|
await assertArm64NestedScratchBlocked(arm64NestedEndLenFixture, /byte-view length exceeds scratch register spill capacity/, "aarch64-nested-end-len");
|
|
let arm64NestedDynamicEqlExpr = "std.mem.eqlBytes(text[(start + (0_usize + 0_usize))..end], text[(start + (0_usize + 0_usize))..end])";
|
|
for (let i = 0; i < 29; i++) arm64NestedDynamicEqlExpr = `(true == ${arm64NestedDynamicEqlExpr})`;
|
|
const arm64NestedDynamicEqlFixture = `${outDir}/aarch64-nested-dynamic-eql-scratch-blocked.0`;
|
|
await writeGraphFixture(arm64NestedDynamicEqlFixture, `export c fn main() -> Bool {
|
|
let text: String = "abcdef"
|
|
let start: usize = 1
|
|
let end: usize = 4
|
|
return ${arm64NestedDynamicEqlExpr}
|
|
}
|
|
`);
|
|
await assertArm64NestedScratchBlocked(arm64NestedDynamicEqlFixture, /byte-view equality exceeds scratch register spill capacity/, "aarch64-nested-dynamic-eql");
|
|
|
|
let arm64WorldWriteSliceStart = "(start + 0_usize)";
|
|
for (let i = 0; i < 31; i++) arm64WorldWriteSliceStart = `(0_usize + ${arm64WorldWriteSliceStart})`;
|
|
const arm64WorldWriteFixture = `${outDir}/aarch64-world-write-dynamic-slice-scratch-blocked.0`;
|
|
await writeGraphFixture(arm64WorldWriteFixture, `pub fn main(world: World) -> Void raises {
|
|
let text: String = "abcdef"
|
|
let start: usize = 1
|
|
check world.out.write(text[${arm64WorldWriteSliceStart}..6])
|
|
}
|
|
`);
|
|
async function assertArm64WorldWriteScratchBlocked(fixture, expectedMessage, outPrefix) {
|
|
for (const blocked of [["linux-musl-arm64", "zero-elf-aarch64-exe", "linux"], ["win32-arm64.exe", "zero-coff-aarch64-exe", "coff.exe"]]) {
|
|
const readiness = await execFileAsync(zero, ["check", "--json", "--emit", "exe", "--target", blocked[0], fixture]);
|
|
const readinessBody = JSON.parse(readiness.stdout);
|
|
assert.equal(readinessBody.ok, true);
|
|
assert.equal(readinessBody.targetReadiness.ok, false);
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].code, "BLD004");
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].backendBlocker.backend, blocked[1]);
|
|
assert.equal(readinessBody.targetReadiness.diagnostics[0].backendBlocker.stage, "buildability");
|
|
assert.match(readinessBody.targetReadiness.diagnostics[0].message, expectedMessage);
|
|
const build = await execFileAsync(zero, ["build", "--json", "--emit", "exe", "--target", blocked[0], fixture, "--out", `${outDir}/${outPrefix}-${blocked[2]}`]).catch((error) => error);
|
|
assert.notEqual(build.code, 0);
|
|
const buildDiag = JSON.parse(build.stdout).diagnostics[0];
|
|
assert.equal(buildDiag.backendBlocker.backend, blocked[1]);
|
|
assert.equal(buildDiag.backendBlocker.stage, "buildability");
|
|
assert.match(buildDiag.message, expectedMessage);
|
|
}
|
|
}
|
|
await assertArm64WorldWriteScratchBlocked(arm64WorldWriteFixture, /expression nesting exceeds scratch register spill capacity/, "aarch64-world-write-dynamic-slice");
|
|
|
|
let arm64WorldWriteSliceEnd = "(end + 0_usize)";
|
|
for (let i = 0; i < 32; i++) arm64WorldWriteSliceEnd = `(0_usize + ${arm64WorldWriteSliceEnd})`;
|
|
const arm64WorldWriteEndFixture = `${outDir}/aarch64-world-write-dynamic-end-scratch-blocked.0`;
|
|
await writeGraphFixture(arm64WorldWriteEndFixture, `pub fn main(world: World) -> Void raises {
|
|
let text: String = "abcdef"
|
|
let end: usize = 6
|
|
check world.out.write(text[1..${arm64WorldWriteSliceEnd}])
|
|
}
|
|
`);
|
|
await assertArm64WorldWriteScratchBlocked(arm64WorldWriteEndFixture, /expression nesting exceeds scratch register spill capacity/, "aarch64-world-write-dynamic-end");
|
|
|
|
const arm64PrivateHelperObj = `${outDir}/aarch64-private-helper-ignored.o`;
|
|
await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"linux-arm64",
|
|
"conformance/native/pass/aarch64-private-helper-ignored.0",
|
|
"--out",
|
|
arm64PrivateHelperObj,
|
|
]);
|
|
const arm64PrivateHelperBytes = await assertElfAarch64Object(arm64PrivateHelperObj, "main");
|
|
assert(arm64PrivateHelperBytes.includes(Buffer.from([0x40, 0x05, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6])));
|
|
|
|
const arm64CompareSource = `${outDir}/aarch64-typed-compare.0`;
|
|
const arm64CompareObj = `${outDir}/aarch64-typed-compare.o`;
|
|
await writeGraphFixture(arm64CompareSource, `export c fn main() -> u32 {
|
|
let large: u32 = 4294967295
|
|
if large > 0_u32 {
|
|
return 7
|
|
}
|
|
return 3
|
|
}
|
|
|
|
export c fn wide_guard() -> u32 {
|
|
let wide: u64 = 4294967296
|
|
if wide != 0_u64 {
|
|
return 9
|
|
}
|
|
return 4
|
|
}
|
|
`);
|
|
await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"linux-arm64",
|
|
arm64CompareSource,
|
|
"--out",
|
|
arm64CompareObj,
|
|
]);
|
|
const arm64CompareBytes = await readFile(arm64CompareObj);
|
|
assert(hasAarch64CondBranch(arm64CompareBytes, 9));
|
|
assert(hasAarch64Instruction(arm64CompareBytes, 0xeb09011f));
|
|
|
|
const memoryPackageMachOReadiness = await execFileAsync(zero, [
|
|
"check",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"darwin-arm64",
|
|
"examples/memory-package",
|
|
]);
|
|
const memoryPackageMachOReadinessBody = JSON.parse(memoryPackageMachOReadiness.stdout);
|
|
assert.equal(memoryPackageMachOReadinessBody.ok, true);
|
|
assert.equal(memoryPackageMachOReadinessBody.diagnostics.length, 0);
|
|
assert.equal(memoryPackageMachOReadinessBody.targetReadiness.ok, true);
|
|
assert.equal(memoryPackageMachOReadinessBody.targetReadiness.buildable, true);
|
|
assert.equal(memoryPackageMachOReadinessBody.targetReadiness.backend, "zero-macho64");
|
|
assert.equal(memoryPackageMachOReadinessBody.targetReadiness.diagnostics.length, 0);
|
|
const memoryPackageMachOObj = `${outDir}/memory-package-macho.o`;
|
|
const memoryPackageMachOBuild = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"darwin-arm64",
|
|
"examples/memory-package",
|
|
"--out",
|
|
memoryPackageMachOObj,
|
|
]);
|
|
const memoryPackageMachOBuildBody = JSON.parse(memoryPackageMachOBuild.stdout);
|
|
assert.equal(memoryPackageMachOBuildBody.compiler, "zero-macho64");
|
|
assert.equal(memoryPackageMachOBuildBody.generatedCBytes, 0);
|
|
assert.equal(memoryPackageMachOBuildBody.objectBackend.objectEmission.path, "direct-macho64-object");
|
|
await assertMachOArm64Object(memoryPackageMachOObj, "main");
|
|
|
|
async function assertAgentSurfaceOwnedDropUnsupported(target, emit, outName, expectedPattern, expectedObjectFormat, expectedBackend, options = {}) {
|
|
const extraArgs = options.extraArgs ?? [];
|
|
const build = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
emit,
|
|
"--target",
|
|
target,
|
|
...extraArgs,
|
|
"conformance/agent-surface/fixtures/owned-drop-direct-backend-unsupported.0",
|
|
"--out",
|
|
`${outDir}/${outName}`,
|
|
]).catch((error) => error);
|
|
assert.notEqual(build.code, 0);
|
|
const body = JSON.parse(build.stdout);
|
|
const diagnostic = body.diagnostics[0];
|
|
assert.equal(diagnostic.code, "BLD004");
|
|
assert.match(diagnostic.expected, expectedPattern);
|
|
assert.equal(diagnostic.actual, "owned<Tracked>");
|
|
assert.deepEqual(diagnostic.backendBlocker, {
|
|
target,
|
|
objectFormat: expectedObjectFormat,
|
|
backend: expectedBackend,
|
|
stage: "lower",
|
|
unsupportedFeature: "owned<Tracked>",
|
|
});
|
|
}
|
|
|
|
await assertAgentSurfaceOwnedDropUnsupported("linux-musl-x64", "obj", "agent-surface-owned-drop-elf.o", /typed program graph MIR subset/, "elf", "zero-elf64-exe");
|
|
await assertAgentSurfaceOwnedDropUnsupported("darwin-arm64", "obj", "agent-surface-owned-drop-macho.o", /typed program graph MIR subset/, "macho", "zero-macho64-exe");
|
|
await assertAgentSurfaceOwnedDropUnsupported("win32-x64.exe", "obj", "agent-surface-owned-drop-coff.obj", /typed program graph MIR subset/, "coff", "zero-coff-x64-exe");
|
|
|
|
const mismatchedDirectEmitter = await execFileAsync(zero, [
|
|
"build",
|
|
"--json",
|
|
"--emit",
|
|
"obj",
|
|
"--target",
|
|
"darwin-arm64",
|
|
"--backend",
|
|
"zero-elf64",
|
|
"examples/add.0",
|
|
"--out",
|
|
`${outDir}/direct-emitter-mismatch.o`,
|
|
]).catch((error) => error);
|
|
assert.notEqual(mismatchedDirectEmitter.code, 0);
|
|
const mismatchedDirectEmitterBody = JSON.parse(mismatchedDirectEmitter.stdout);
|
|
assert.equal(mismatchedDirectEmitterBody.diagnostics[0].code, "BLD004");
|
|
assert.equal(mismatchedDirectEmitterBody.diagnostics[0].actual, "--backend zero-elf64");
|
|
assert.deepEqual(mismatchedDirectEmitterBody.diagnostics[0].backendBlocker, {
|
|
target: "darwin-arm64",
|
|
objectFormat: "macho",
|
|
backend: "zero-elf64",
|
|
stage: "target-selection",
|
|
unsupportedFeature: "requested direct emitter does not match target",
|
|
});
|
|
|
|
const commonPassFixtures = [
|
|
["conformance/common/pass/array-sum-min-max.0", "common-array-sum-min-max", { stdout: "array sum min max ok\n" }],
|
|
["conformance/common/pass/bytes-reverse.0", "common-bytes-reverse", { stdout: "bytes reverse ok\n" }],
|
|
["conformance/common/pass/cli-args.0", "common-cli-args", { stdout: "alpha\n", args: ["alpha", "beta"] }],
|
|
["conformance/common/pass/count-words-lines.0", "common-count-words-lines", { stdout: "count words lines ok\n" }],
|
|
["conformance/common/pass/factorial.0", "common-factorial", { stdout: "factorial ok\n" }],
|
|
["conformance/common/pass/fib-iterative.0", "common-fib-iterative", { stdout: "fib iterative ok\n" }],
|
|
["conformance/common/pass/fib-recursive.0", "common-fib-recursive", { stdout: "fib recursive ok\n" }],
|
|
["conformance/common/pass/file-copy.0", "common-file-copy", { stdout: "file copy ok\n", file: { name: "common-file-copy-output.txt", text: "zero file copy\n" } }],
|
|
["conformance/common/pass/gcd.0", "common-gcd", { stdout: "gcd ok\n" }],
|
|
["conformance/common/pass/json-roundtrip.0", "common-json-roundtrip", { stdout: "json roundtrip ok\n" }],
|
|
["conformance/common/pass/palindrome.0", "common-palindrome", { stdout: "palindrome ok\n" }],
|
|
["conformance/common/pass/prime.0", "common-prime", { stdout: "prime ok\n" }],
|
|
["conformance/common/pass/sieve-small.0", "common-sieve-small", { stdout: "sieve small ok\n" }],
|
|
["conformance/common/pass/sort-small.0", "common-sort-small", { stdout: "sort small ok\n" }],
|
|
["conformance/common/pass/string-search.0", "common-string-search", { stdout: "string search ok\n" }],
|
|
["conformance/common/pass/word-reverse.0", "common-word-reverse", { stdout: "word reverse ok\n" }],
|
|
];
|
|
|
|
for (const [fixture, name, expected] of commonPassFixtures) {
|
|
const check = await execFileAsync(zero, ["check", "--json", fixture]);
|
|
assert.equal(JSON.parse(check.stdout).ok, true);
|
|
const graph = await execFileAsync(zero, ["inspect", "--json", fixture]);
|
|
const graphBody = JSON.parse(graph.stdout);
|
|
assert.equal(graphBody.graph.artifact, fixture.replace(/\.0$/, ".graph"));
|
|
assert(graphBody.sourceFiles.includes(fixture) || graphBody.sourceFiles.includes(fixture.split("/").at(-1)));
|
|
const size = await execFileAsync(zero, ["size", "--json", fixture]);
|
|
assert.equal(JSON.parse(size.stdout).schemaVersion, 1);
|
|
await assertCommonRuntimeOrUnsupported(fixture, name, expected);
|
|
}
|
|
|
|
const commonUnsupportedTarget = await execFileAsync(zero, ["check", "--json", "--target", "linux-musl-x64", "conformance/common/fail/unsupported-target-feature.0"]).catch((error) => error);
|
|
assert.notEqual(commonUnsupportedTarget.code, 0);
|
|
assert.equal(JSON.parse(commonUnsupportedTarget.stdout).diagnostics[0].code, "TAR002");
|
|
|
|
const compileTimeJson = await execFileAsync(zero, ["check", "--json", "conformance/native/pass/compile-time-v1.0"]);
|
|
const compileTimeBody = JSON.parse(compileTimeJson.stdout);
|
|
assert.equal(compileTimeBody.ok, true);
|
|
assert.equal(compileTimeBody.compileTime.deterministic, true);
|
|
assert.equal(compileTimeBody.compileTime.sandbox.filesystem, "denied");
|
|
assert.equal(compileTimeBody.compileTime.sandbox.network, "denied");
|
|
assert.equal(compileTimeBody.compileTime.limits.maxDepth, 64);
|
|
assert.equal(compileTimeBody.compileTime.limits.maxSteps, 1024);
|
|
assert.equal(compileTimeBody.compileTime.cacheKeyInputs.algorithm, "fnv1a64-zero-meta-v1");
|
|
assert.ok(compileTimeBody.compileTime.cacheKeyInputs.sourceHash);
|
|
assert.ok(compileTimeBody.compileTime.meta.supportedFacts.includes("target.abi"));
|
|
assert.ok(compileTimeBody.compileTime.meta.supportedFacts.includes("fieldType"));
|
|
assert.ok(compileTimeBody.compileTime.meta.supportedFacts.includes("hasEnumCase"));
|
|
assert.ok(compileTimeBody.compileTime.staticValues.supported.includes("Bool"));
|
|
assert.ok(compileTimeBody.compileTime.staticValues.supported.includes("enum"));
|
|
assert.equal(compileTimeBody.compileTime.staticValues.runtimeRegistries, false);
|
|
assert.equal(compileTimeBody.compileTime.staticValues.reflectionTables, false);
|
|
assert.equal(compileTimeBody.compileTime.reflection.compileTimeOnly, true);
|
|
assert.equal(compileTimeBody.compileTime.typedBuilders.status, "limited-v1");
|
|
assert.equal(compileTimeBody.compileTime.typedBuilders.rawTokenStrings, false);
|
|
assert.equal(compileTimeBody.safetyFacts.schemaVersion, 1);
|
|
assert.equal(compileTimeBody.safetyFacts.bounds.runtimeTraps, true);
|
|
assert.equal(compileTimeBody.safetyFacts.bounds.optimizerElision, false);
|
|
assert.equal(compileTimeBody.safetyFacts.overflow.runtimeArithmetic, "unchecked-machine-wrap");
|
|
assert.equal(compileTimeBody.safetyFacts.overflow.unchecked, true);
|
|
assert.equal(compileTimeBody.safetyFacts.initialization.locals, "initializer-required");
|
|
assert.equal(compileTimeBody.safetyFacts.initialization.maybePayloadReads, "guard-checked");
|
|
assert.equal(compileTimeBody.safetyFacts.aliasing.mutableAliases, "diagnostic");
|
|
assert.equal(compileTimeBody.safetyFacts.mir.invalidMemoryContractsBlockEmission, true);
|
|
|
|
const compileTimeGraph = await execFileAsync(zero, ["inspect", "--json", "conformance/native/pass/compile-time-v1.0"]);
|
|
const compileTimeGraphBody = JSON.parse(compileTimeGraph.stdout);
|
|
assert.equal(compileTimeGraphBody.compileTime.deterministic, true);
|
|
assert.equal(compileTimeGraphBody.safetyFacts.profileKey, "small");
|
|
assert.equal(compileTimeGraphBody.safetyFacts.lifetimes.escapedLocalBorrow, "diagnostic");
|
|
const readGateGraph = compileTimeGraphBody.functions.find((item) => item.name === "readGate");
|
|
assert.ok(readGateGraph.staticParams.some((item) => item.name === "enabledFlag" && item.kind === "bool"));
|
|
assert.ok(readGateGraph.staticParams.some((item) => item.name === "selectedMode" && item.kind === "enum"));
|
|
const gateGraph = compileTimeGraphBody.shapes.find((item) => item.name === "Gate");
|
|
assert.ok(gateGraph.staticParams.some((item) => item.name === "enabledFlag" && item.kind === "bool"));
|
|
assert.ok(gateGraph.staticParams.some((item) => item.name === "selectedMode" && item.kind === "enum"));
|
|
|
|
const fastCheck = await execFileAsync(zero, ["check", "--json", "--profile", "fast", "examples/hello.0"]);
|
|
const fastCheckBody = JSON.parse(fastCheck.stdout);
|
|
assert.equal(fastCheckBody.artifact, "examples/hello.graph");
|
|
assert.equal(fastCheckBody.canonicalSource, false);
|
|
assert.equal(fastCheckBody.check.lowering, "graph-native-check");
|
|
assert.equal(fastCheckBody.safetyFacts.profile, "release-fast");
|
|
assert.equal(fastCheckBody.safetyFacts.profileKey, "fast");
|
|
|
|
const fastGraph = await execFileAsync(zero, ["inspect", "--json", "--profile", "fast", "examples/hello.0"]);
|
|
const fastGraphBody = JSON.parse(fastGraph.stdout);
|
|
assert.equal(fastGraphBody.packageCache.profile, "fast");
|
|
assert.equal(fastGraphBody.incrementalInvalidation.profileDependency, "fast");
|
|
assert.equal(fastGraphBody.safetyFacts.profile, "release-fast");
|
|
assert.equal(fastGraphBody.safetyFacts.profileKey, "fast");
|
|
|
|
const buildJsonM6 = await execFileAsync(zero, ["build", "--json", "--emit", "exe", "--target", "linux-musl-x64", "--release", "tiny", "examples/hello.0", "--out", `${outDir}/m6-hello`]);
|
|
const buildJsonM6Body = JSON.parse(buildJsonM6.stdout);
|
|
assert.equal(buildJsonM6Body.legacy, false);
|
|
assert.equal(buildJsonM6Body.legacyBackend, null);
|
|
assert.equal(buildJsonM6Body.generatedCBytes, 0);
|
|
assert.equal(buildJsonM6Body.profileSemantics.canonical, "tiny");
|
|
assert.equal(buildJsonM6Body.profileSemantics.panicPolicy, "abort");
|
|
assert.equal(buildJsonM6Body.profileSemantics.runtimeMetadataPolicy, "minimum");
|
|
assert.equal(buildJsonM6Body.profileSemantics.profileKey, "tiny");
|
|
assert.equal(buildJsonM6Body.profileSemantics.unwindPolicy, "no-unwind-abort");
|
|
assert.equal(buildJsonM6Body.profileSemantics.boundsPolicy, "checked");
|
|
assert.equal(buildJsonM6Body.profileSemantics.overflowPolicy, "literal-range-checked-runtime-unchecked");
|
|
assert.equal(buildJsonM6Body.profileSemantics.profileBudget.generatedCBytes, 0);
|
|
assert.equal(buildJsonM6Body.safetyFacts.profile, "tiny");
|
|
assert.equal(buildJsonM6Body.safetyFacts.bounds.policy, "checked");
|
|
assert.equal(buildJsonM6Body.safetyFacts.bounds.optimizerElision, false);
|
|
assert.equal(buildJsonM6Body.safetyFacts.overflow.policy, "literal-range-checked-runtime-unchecked");
|
|
assert.equal(buildJsonM6Body.safetyFacts.overflow.integerLiterals, "range-checked");
|
|
assert.equal(buildJsonM6Body.safetyFacts.ownership.useAfterMove, "diagnostic");
|
|
assert.equal(buildJsonM6Body.profileBudget.helperBudgetPolicy, "pay-as-used-minimum-runtime");
|
|
assert(buildJsonM6Body.profileCatalog.some((item) => item.canonical === "debug" && item.debugInfo === true));
|
|
assert(buildJsonM6Body.profileCatalog.some((item) => item.canonical === "release-fast" && item.boundsPolicy === "checked"));
|
|
assert(buildJsonM6Body.profileCatalog.some((item) => item.canonical === "audit" && item.runtimeMetadataPolicy === "maximum"));
|
|
assert.equal(buildJsonM6Body.objectBackend.internalIr.callRepresentation, "same-object direct calls for supported direct subsets");
|
|
assert.equal(buildJsonM6Body.objectBackend.objectEmission.path, "direct-elf64-exe");
|
|
assert.equal(buildJsonM6Body.objectBackend.objectEmission.symbols, true);
|
|
assert.ok(buildJsonM6Body.objectBackend.linking.linkerFlavor);
|
|
assert.equal(buildJsonM6Body.objectBackend.linking.stripArtifacts, false);
|
|
|
|
for (const [requestedProfile, canonicalProfile, profileKey] of [
|
|
["debug", "debug", "debug"],
|
|
["fast", "release-fast", "fast"],
|
|
["small", "release-small", "small"],
|
|
]) {
|
|
const profileBuild = await execFileAsync(zero, ["build", "--json", "--profile", requestedProfile, "--target", "linux-musl-x64", "examples/hello.0", "--out", `${outDir}/m25-${requestedProfile}-hello`]);
|
|
const profileBody = JSON.parse(profileBuild.stdout);
|
|
assert.equal(profileBody.generatedCBytes, 0);
|
|
assert.equal(profileBody.profileSemantics.canonical, canonicalProfile);
|
|
assert.equal(profileBody.profileSemantics.profileKey, profileKey);
|
|
assert.equal(profileBody.profileSemantics.boundsPolicy, "checked");
|
|
assert.equal(profileBody.profileSemantics.overflowPolicy, "literal-range-checked-runtime-unchecked");
|
|
assert.equal(profileBody.profileSemantics.profileBudget.generatedCBytes, 0);
|
|
assert.equal(profileBody.safetyFacts.profile, canonicalProfile);
|
|
assert.equal(profileBody.safetyFacts.profileKey, profileKey);
|
|
assert.equal(profileBody.safetyFacts.bounds.optimizerElision, false);
|
|
assert.equal(profileBody.profileBudget.cBridgeFallback, false);
|
|
}
|
|
|
|
const profileSize = await execFileAsync(zero, ["size", "--json", "--profile", "debug", "--target", "linux-musl-x64", "examples/hello.0"]);
|
|
const profileSizeBody = JSON.parse(profileSize.stdout);
|
|
assert.equal(profileSizeBody.generatedCBytes, 0);
|
|
assert.equal(profileSizeBody.graph.artifact, "examples/hello.graph");
|
|
assert.equal(profileSizeBody.graph.lowering, "mapped-final-mir");
|
|
assert.equal(profileSizeBody.profileSemantics.profileKey, "debug");
|
|
assert.equal(profileSizeBody.safetyFacts.profileKey, "debug");
|
|
assert.equal(profileSizeBody.safetyFacts.uncheckedSurfaces[0].surface, "C imports");
|
|
assert.equal(profileSizeBody.sizeBreakdown.profileKey, "debug");
|
|
assert(Array.isArray(profileSizeBody.sizeBreakdown.functions));
|
|
assert(profileSizeBody.sizeBreakdown.sections.some((item) => item.name === "text" && item.retainedBy.includes("retained functions")));
|
|
assert(Array.isArray(profileSizeBody.sizeBreakdown.literals.items));
|
|
assert(Array.isArray(profileSizeBody.sizeBreakdown.stdlibHelpers));
|
|
assert(Array.isArray(profileSizeBody.sizeBreakdown.imports));
|
|
assert(Array.isArray(profileSizeBody.sizeBreakdown.runtimeShims));
|
|
assert(profileSizeBody.sizeBreakdown.debugMetadata.bytes > 0);
|
|
assert(profileSizeBody.compilerCaches.some((item) => item.name === "mappedFinalMir" && item.sourceKind === "program-graph" && item.programReconstructed === false));
|
|
assert(profileSizeBody.retentionReasons.some((item) => item.kind === "debugMetadata"));
|
|
assert(profileSizeBody.optimizationHints.some((item) => item.id === "profile-debug-metadata"));
|
|
assert.equal(profileSizeBody.profileBudget.debugMetadataAllowed, true);
|
|
|
|
const directObjOut = `${outDir}/direct-obj-add.o`;
|
|
const directObjJson = await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/direct-obj-add.0", "--out", directObjOut]);
|
|
const directObjBody = JSON.parse(directObjJson.stdout);
|
|
assert.equal(directObjBody.emit, "obj");
|
|
assert.equal(directObjBody.compiler, "zero-elf64");
|
|
assert.equal(directObjBody.generatedCBytes, 0);
|
|
assert(directObjBody.loweredIrBytes > 0);
|
|
assert.equal(directObjBody.objectBackend.objectEmission.path, "direct-elf64-object");
|
|
await assertElf64Object(directObjOut, "main");
|
|
|
|
const directI64ObjOut = `${outDir}/direct-i64-return.o`;
|
|
const directI64ObjJson = await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", "linux-musl-x64", "examples/direct-i64-return.0", "--out", directI64ObjOut]);
|
|
const directI64ObjBody = JSON.parse(directI64ObjJson.stdout);
|
|
const directI64ObjBytes = await readFile(directI64ObjOut);
|
|
assert.equal(directI64ObjBody.emit, "obj");
|
|
assert.equal(directI64ObjBody.compiler, "zero-elf64");
|
|
assert.equal(directI64ObjBody.generatedCBytes, 0);
|
|
assert.equal(directI64ObjBody.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 directWideMainSource = `${outDir}/direct-exe-wide-main.0`;
|
|
const directWideMainOut = `${outDir}/direct-exe-wide-main`;
|
|
await writeGraphFixture(directWideMainSource, `export c fn main() -> usize {
|
|
return 8589934590
|
|
}
|
|
`);
|
|
const directWideMainJson = await execFileAsync(zero, ["build", "--json", "--emit", "exe", "--target", "linux-musl-x64", directWideMainSource, "--out", directWideMainOut]);
|
|
const directWideMainBody = JSON.parse(directWideMainJson.stdout);
|
|
const directWideMainBytes = await readFile(directWideMainOut);
|
|
assert.equal(directWideMainBody.compiler, "zero-elf64");
|
|
assert.equal(directWideMainBody.objectBackend.objectEmission.path, "direct-elf64-exe");
|
|
assert(!directWideMainBytes.includes(Buffer.from([0x48, 0xc1, 0xe9, 0x20])));
|
|
assert(directWideMainBytes.includes(Buffer.from([0x89, 0xc7, 0xb8, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x05])));
|
|
|
|
const directI64MainSource = `${outDir}/direct-exe-i64-main.0`;
|
|
const directI64MainOut = `${outDir}/direct-exe-i64-main`;
|
|
await writeGraphFixture(directI64MainSource, `export c fn main() -> i64 {
|
|
return 8589934590_i64
|
|
}
|
|
`);
|
|
const directI64MainJson = await execFileAsync(zero, ["build", "--json", "--emit", "exe", "--target", "linux-musl-x64", directI64MainSource, "--out", directI64MainOut]);
|
|
const directI64MainBody = JSON.parse(directI64MainJson.stdout);
|
|
assert.equal(directI64MainBody.compiler, "zero-elf64");
|
|
assert.equal(directI64MainBody.objectBackend.objectEmission.path, "direct-elf64-exe");
|
|
|
|
const directMachOU64LiteralSource = `${outDir}/direct-macho-u64-literal.0`;
|
|
const directMachOU64LiteralOut = `${outDir}/direct-macho-u64-literal.o`;
|
|
await writeGraphFixture(directMachOU64LiteralSource, `export c fn main() -> u64 {
|
|
let value: u64 = 4294967296
|
|
return value
|
|
}
|
|
`);
|
|
const directMachOU64LiteralReadinessJson = await execFileAsync(zero, ["check", "--json", "--emit", "obj", "--target", "darwin-arm64", directMachOU64LiteralSource]);
|
|
const directMachOU64LiteralReadinessBody = JSON.parse(directMachOU64LiteralReadinessJson.stdout);
|
|
assert.equal(directMachOU64LiteralReadinessBody.targetReadiness.buildable, true);
|
|
const directMachOU64LiteralJson = await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", "darwin-arm64", directMachOU64LiteralSource, "--out", directMachOU64LiteralOut]);
|
|
const directMachOU64LiteralBody = JSON.parse(directMachOU64LiteralJson.stdout);
|
|
const directMachOU64LiteralBytes = await readFile(directMachOU64LiteralOut);
|
|
assert.equal(directMachOU64LiteralBody.compiler, "zero-macho64");
|
|
assert.equal(directMachOU64LiteralBody.objectBackend.objectEmission.path, "direct-macho64-object");
|
|
assert(directMachOU64LiteralBytes.includes(Buffer.from([0x28, 0x00, 0xc0, 0xf2])));
|
|
|
|
const directMachOU64DivSource = `${outDir}/direct-macho-u64-div.0`;
|
|
const directMachOU64DivOut = `${outDir}/direct-macho-u64-div.o`;
|
|
await writeGraphFixture(directMachOU64DivSource, `export c fn main(a: u64, b: u64) -> u64 {
|
|
return a / b
|
|
}
|
|
`);
|
|
const directMachOU64DivJson = await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", "darwin-arm64", directMachOU64DivSource, "--out", directMachOU64DivOut]);
|
|
const directMachOU64DivBody = JSON.parse(directMachOU64DivJson.stdout);
|
|
const directMachOU64DivBytes = await readFile(directMachOU64DivOut);
|
|
assert.equal(directMachOU64DivBody.compiler, "zero-macho64");
|
|
assert.equal(directMachOU64DivBody.objectBackend.objectEmission.path, "direct-macho64-object");
|
|
assert(directMachOU64DivBytes.includes(Buffer.from([0x00, 0x09, 0xc9, 0x9a])));
|
|
assert(!directMachOU64DivBytes.includes(Buffer.from([0x00, 0x09, 0xc9, 0x1a])));
|
|
|
|
const directMachOU64ModSource = `${outDir}/direct-macho-u64-mod.0`;
|
|
const directMachOU64ModOut = `${outDir}/direct-macho-u64-mod.o`;
|
|
await writeGraphFixture(directMachOU64ModSource, `export c fn main(a: u64, b: u64) -> u64 {
|
|
return a % b
|
|
}
|
|
`);
|
|
const directMachOU64ModJson = await execFileAsync(zero, ["build", "--json", "--emit", "obj", "--target", "darwin-arm64", directMachOU64ModSource, "--out", directMachOU64ModOut]);
|
|
const directMachOU64ModBody = JSON.parse(directMachOU64ModJson.stdout);
|
|
const directMachOU64ModBytes = await readFile(directMachOU64ModOut);
|
|
assert.equal(directMachOU64ModBody.compiler, "zero-macho64");
|
|
assert.equal(directMachOU64ModBody.objectBackend.objectEmission.path, "direct-macho64-object");
|
|
assert(directMachOU64ModBytes.includes(Buffer.from([0x0a, 0x09, 0xc9, 0x9a])));
|
|
assert(directMachOU64ModBytes.includes(Buffer.from([0x40, 0xa1, 0x09, 0x9b])));
|
|
assert(!directMachOU64ModBytes.includes(Buffer.from([0x0a, 0x09, 0xc9, 0x1a])));
|
|
assert(!directMachOU64ModBytes.includes(Buffer.from([0x40, 0xa1, 0x09, 0x1b])));
|
|
|
|
const metaJsonSuccess = await execFileAsync(zero, ["check", "--json", "conformance/native/pass/meta-typed-target-type.0"]);
|
|
const metaJsonSuccessBody = JSON.parse(metaJsonSuccess.stdout);
|
|
assert.equal(metaJsonSuccessBody.ok, true);
|
|
assert.equal(metaJsonSuccessBody.artifact, "conformance/native/pass/meta-typed-target-type.graph");
|
|
assert.equal(metaJsonSuccessBody.canonicalSource, false);
|
|
assert.equal(metaJsonSuccessBody.check.lowering, "graph-native-check");
|
|
assert.equal(metaJsonSuccessBody.compileTime.deterministic, true);
|
|
|
|
const stdModuleBasenameCollisionDir = `${outDir}/std-module-basename-collision`;
|
|
await mkdir(stdModuleBasenameCollisionDir, { recursive: true });
|
|
const stdModuleBasenameCollisionFixture = `${stdModuleBasenameCollisionDir}/term.0`;
|
|
const stdModuleBasenameCollisionGraph = await writeGraphFixture(stdModuleBasenameCollisionFixture, `pub fn main(world: World) -> Void raises {
|
|
var buffer: [16]u8 = [0_u8; 16]
|
|
let cursor: Maybe<Span<u8>> = std.term.cursorUp(buffer, 1_usize)
|
|
if cursor.has {
|
|
check world.out.write(cursor.value)
|
|
check world.out.write("local term collision ok\\n")
|
|
}
|
|
}
|
|
`);
|
|
const stdModuleBasenameCollisionCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", stdModuleBasenameCollisionGraph])).stdout);
|
|
assert.equal(stdModuleBasenameCollisionCheck.ok, true);
|
|
assert(stdModuleBasenameCollisionCheck.graphCompiler.semanticFacts.functions.some((fn) => fn.name === "main"));
|
|
assert(stdModuleBasenameCollisionCheck.graphCompiler.semanticFacts.functions.some((fn) => fn.name === "term_cursor_up"));
|
|
const stdModuleBasenameCollisionInspect = JSON.parse((await execFileAsync(zero, ["inspect", "--json", stdModuleBasenameCollisionGraph])).stdout);
|
|
assert(stdModuleBasenameCollisionInspect.modules.some((module) => module.name === "term"));
|
|
assert(stdModuleBasenameCollisionInspect.modules.some((module) => module.name === "std.term"));
|
|
if (runnableDirectTarget) {
|
|
const stdModuleBasenameCollisionRun = await execFileAsync(zero, ["run", "--out", `${outDir}/std-module-basename-collision-run`, stdModuleBasenameCollisionGraph]);
|
|
assert.equal(stdModuleBasenameCollisionRun.stdout, "\x1b[1Alocal term collision ok\n");
|
|
}
|
|
|
|
const collectionsUsizeMemory = await execFileAsync(zero, ["mem", "--json", "conformance/native/pass/std-collections-usize-memory.0"]);
|
|
const collectionsUsizeMemoryBody = JSON.parse(collectionsUsizeMemory.stdout);
|
|
assert.equal(collectionsUsizeMemoryBody.graph.artifact, "conformance/native/pass/std-collections-usize-memory.graph");
|
|
assert.equal(collectionsUsizeMemoryBody.graph.canonicalSource, false);
|
|
assert.match(collectionsUsizeMemoryBody.graph.graphHash, /^graph:[0-9a-f]{16}$/);
|
|
assert.equal(collectionsUsizeMemoryBody.compilerCaches.every((item) => item.sourceKind === "program-graph" && item.graphHash === collectionsUsizeMemoryBody.graph.graphHash), true);
|
|
assert.equal(collectionsUsizeMemoryBody.incrementalInvalidation.sourceKind, "program-graph");
|
|
assert.equal(collectionsUsizeMemoryBody.incrementalInvalidation.changedInputs.graphArtifact, "conformance/native/pass/std-collections-usize-memory.graph");
|
|
assert.equal(collectionsUsizeMemoryBody.memoryBudgets.collectionCapacityBytes, 32);
|
|
assert.equal(collectionsUsizeMemoryBody.collectionFacts.FixedStorage.capacityBytes, 32);
|
|
|
|
const collectionsMutspanMemory = await execFileAsync(zero, ["mem", "--json", "conformance/native/pass/std-collections-mutspan-memory.0"]);
|
|
const collectionsMutspanMemoryBody = JSON.parse(collectionsMutspanMemory.stdout);
|
|
assert.equal(collectionsMutspanMemoryBody.memoryBudgets.collectionCapacityBytes, 4);
|
|
assert.equal(collectionsMutspanMemoryBody.collectionFacts.FixedStorage.storageSites, 1);
|
|
assert.equal(collectionsMutspanMemoryBody.collectionFacts.FixedStorage.capacityBytes, 4);
|
|
|
|
const collectionsQueryMemory = await execFileAsync(zero, ["mem", "--json", "conformance/native/pass/std-collections-query-memory.0"]);
|
|
const collectionsQueryMemoryBody = JSON.parse(collectionsQueryMemory.stdout);
|
|
assert.equal(collectionsQueryMemoryBody.memoryBudgets.collectionCapacityBytes, 2);
|
|
assert.equal(collectionsQueryMemoryBody.collectionFacts.FixedStorage.storageSites, 1);
|
|
assert.equal(collectionsQueryMemoryBody.collectionFacts.FixedStorage.capacityBytes, 2);
|
|
assert.equal(collectionsQueryMemoryBody.collectionFacts.FixedStorage.queryCalls, 1);
|
|
|
|
const interfaceStaticUnsupportedTypeFixture = `${outDir}/interface-static-unsupported-type.0`;
|
|
const interfaceStaticUnsupportedTypeBody = await writeImportFailureFixture(interfaceStaticUnsupportedTypeFixture, `interface Bad<static N: String> {
|
|
fn value() -> u8
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`);
|
|
assert.equal(interfaceStaticUnsupportedTypeBody.diagnostics[0].code, "STC001");
|
|
|
|
const interfaceMethodStaticUnsupportedTypeFixture = `${outDir}/interface-method-static-unsupported-type.0`;
|
|
const interfaceMethodStaticUnsupportedTypeBody = await writeImportFailureFixture(interfaceMethodStaticUnsupportedTypeFixture, `interface Bad {
|
|
fn value<static N: String>() -> u8
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`);
|
|
assert.equal(interfaceMethodStaticUnsupportedTypeBody.diagnostics[0].code, "STC001");
|
|
|
|
const shapeMethodStaticUnsupportedTypeFixture = `${outDir}/shape-method-static-unsupported-type.0`;
|
|
const shapeMethodStaticUnsupportedTypeBody = await writeImportFailureFixture(shapeMethodStaticUnsupportedTypeFixture, `type Box {
|
|
value: u8,
|
|
fn value<static N: String>(self: ref<Self>) -> u8 {
|
|
return self.value
|
|
}
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`);
|
|
assert.equal(shapeMethodStaticUnsupportedTypeBody.diagnostics[0].code, "STC001");
|
|
|
|
const methodUnknownConstraintFixtures = [
|
|
{
|
|
name: "interface-method-unknown-constraint",
|
|
source: `interface Bad {
|
|
fn value<T: Missing>() -> u8
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`,
|
|
},
|
|
{
|
|
name: "shape-method-unknown-constraint",
|
|
source: `type Box {
|
|
value: u8,
|
|
|
|
fn value<T: Missing>(self: ref<Self>) -> u8 {
|
|
return self.value
|
|
}
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`,
|
|
},
|
|
];
|
|
|
|
for (const fixtureCase of methodUnknownConstraintFixtures) {
|
|
const fixture = `${outDir}/${fixtureCase.name}.0`;
|
|
const methodUnknownConstraintBody = await writeImportFailureFixture(fixture, fixtureCase.source);
|
|
assert.equal(methodUnknownConstraintBody.diagnostics[0].code, "IFC001");
|
|
}
|
|
|
|
const duplicateStaticGenericFixtures = [
|
|
{
|
|
name: "function-duplicate-static-param",
|
|
message: /duplicate generic parameter/,
|
|
source: `fn id<static N: usize, static N: usize>() -> u8 {
|
|
return 1
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`,
|
|
},
|
|
{
|
|
name: "interface-duplicate-static-param",
|
|
message: /duplicate generic parameter/,
|
|
source: `interface Bad<static N: usize, static N: usize> {
|
|
fn value() -> u8
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`,
|
|
},
|
|
{
|
|
name: "shape-method-duplicate-static-param",
|
|
message: /duplicate generic parameter/,
|
|
source: `type Box {
|
|
value: u8,
|
|
|
|
fn value<static N: usize, static N: usize>(self: ref<Self>) -> u8 {
|
|
return self.value
|
|
}
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`,
|
|
},
|
|
{
|
|
name: "shape-method-static-shadows-shape-static",
|
|
message: /shadows outer generic parameter/,
|
|
source: `type Box<static N: usize> {
|
|
value: [N]u8,
|
|
|
|
fn len<static N: usize>(self: ref<Self>) -> usize {
|
|
return N
|
|
}
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`,
|
|
},
|
|
{
|
|
name: "shape-method-static-self-param",
|
|
message: /generic type parameter shadows Self type/,
|
|
source: `type Box {
|
|
value: u8,
|
|
|
|
fn value<static Self: usize>(self: ref<Self>) -> usize {
|
|
return Self
|
|
}
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`,
|
|
},
|
|
];
|
|
|
|
for (const fixtureCase of duplicateStaticGenericFixtures) {
|
|
const fixture = `${outDir}/${fixtureCase.name}.0`;
|
|
const duplicateStaticBody = await writeImportFailureFixture(fixture, fixtureCase.source);
|
|
assert.equal(duplicateStaticBody.diagnostics[0].code, "NAM004");
|
|
assert.match(duplicateStaticBody.diagnostics[0].message, fixtureCase.message);
|
|
}
|
|
|
|
for (const value of ["4_", "M"]) {
|
|
const fixture = `${outDir}/interface-static-constraint-${value.replace(/[^A-Za-z0-9]/g, "_")}.0`;
|
|
const interfaceStaticConstraintBody = await writeImportFailureFixture(fixture, `interface First<T: Type, static N: usize> {
|
|
fn first(self: ref<T>) -> u8
|
|
}
|
|
|
|
fn readFirst<T: First<T, ${value}>>(value: ref<T>) -> u8 {
|
|
return T.first(value)
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
}
|
|
`);
|
|
assert.equal(interfaceStaticConstraintBody.diagnostics[0].code, "STC002");
|
|
assert.equal(interfaceStaticConstraintBody.diagnostics[0].actual, value);
|
|
}
|
|
|
|
const shapeMethodStaticParamFixture = `${outDir}/shape-method-static-param.0`;
|
|
await writeGraphFixture(shapeMethodStaticParamFixture, `type Box {
|
|
value: u8,
|
|
|
|
fn tag<static N: usize>(self: ref<Self>) -> usize {
|
|
return N
|
|
}
|
|
|
|
fn value<static N: usize>() -> usize {
|
|
return N
|
|
}
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let box: Box = Box { value: 1 }
|
|
let receiverTag: usize = box.tag<4>()
|
|
let namespaceTag: usize = Box.value<8>()
|
|
}
|
|
`);
|
|
const shapeMethodStaticParamJson = await execFileAsync(zero, ["check", "--json", shapeMethodStaticParamFixture]);
|
|
const shapeMethodStaticParamBody = JSON.parse(shapeMethodStaticParamJson.stdout);
|
|
assert.equal(shapeMethodStaticParamBody.ok, true);
|
|
const shapeMethodStaticParamGraph = await execFileAsync(zero, ["inspect", "--json", shapeMethodStaticParamFixture]);
|
|
const shapeMethodStaticParamGraphBody = JSON.parse(shapeMethodStaticParamGraph.stdout);
|
|
const shapeMethodStaticBox = shapeMethodStaticParamGraphBody.shapes.find((item) => item.name === "Box");
|
|
assert(shapeMethodStaticBox);
|
|
const shapeMethodStaticTag = shapeMethodStaticBox.methods.find((item) => item.name === "tag");
|
|
assert(shapeMethodStaticTag);
|
|
assert(shapeMethodStaticTag.staticParams.some((item) => item.name === "N" && item.type === "usize" && item.staticDispatch === true));
|
|
|
|
const shapeMethodStaticCanonicalFixture = `${outDir}/shape-method-static-canonical.0`;
|
|
await writeGraphFixture(shapeMethodStaticCanonicalFixture, `type Box {
|
|
fn take<static N: usize>(a: [N]u8, b: [N]u8) -> usize {
|
|
return N
|
|
}
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let a: [4]u8 = [1, 2, 3, 4]
|
|
let b: [0x4]u8 = [1, 2, 3, 4]
|
|
let inferred: usize = Box.take(a, b)
|
|
let explicit: usize = Box.take<0x4>(a, b)
|
|
}
|
|
`);
|
|
const shapeMethodStaticCanonicalJson = await execFileAsync(zero, ["check", "--json", shapeMethodStaticCanonicalFixture]);
|
|
const shapeMethodStaticCanonicalBody = JSON.parse(shapeMethodStaticCanonicalJson.stdout);
|
|
assert.equal(shapeMethodStaticCanonicalBody.ok, true);
|
|
|
|
const interfaceMethodStaticParamFixture = `${outDir}/interface-method-static-param.0`;
|
|
await writeGraphFixture(interfaceMethodStaticParamFixture, `interface Width<T: Type> {
|
|
fn width<static N: usize>(self: ref<T>) -> usize
|
|
}
|
|
|
|
type Bytes {
|
|
value: u8,
|
|
|
|
fn width<static N: usize>(self: ref<Self>) -> usize {
|
|
return N
|
|
}
|
|
}
|
|
|
|
fn readWidth<T: Width<T>>(value: ref<T>) -> usize {
|
|
return T.width<4>(value)
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let bytes: Bytes = Bytes { value: 1 }
|
|
let width: usize = readWidth<Bytes>(&bytes)
|
|
}
|
|
`);
|
|
const interfaceMethodStaticParamJson = await execFileAsync(zero, ["check", "--json", interfaceMethodStaticParamFixture]);
|
|
const interfaceMethodStaticParamBody = JSON.parse(interfaceMethodStaticParamJson.stdout);
|
|
assert.equal(interfaceMethodStaticParamBody.ok, true);
|
|
const interfaceMethodStaticParamGraph = await execFileAsync(zero, ["inspect", "--json", interfaceMethodStaticParamFixture]);
|
|
const interfaceMethodStaticParamGraphBody = JSON.parse(interfaceMethodStaticParamGraph.stdout);
|
|
const interfaceMethodStaticWidth = interfaceMethodStaticParamGraphBody.interfaces.find((item) => item.name === "Width");
|
|
assert(interfaceMethodStaticWidth);
|
|
const interfaceMethodStaticWidthMethod = interfaceMethodStaticWidth.methods.find((item) => item.name === "width");
|
|
assert(interfaceMethodStaticWidthMethod);
|
|
assert(interfaceMethodStaticWidthMethod.staticParams.some((item) => item.name === "N" && item.type === "usize" && item.staticDispatch === true));
|
|
const interfaceMethodStaticBytes = interfaceMethodStaticParamGraphBody.shapes.find((item) => item.name === "Bytes");
|
|
assert(interfaceMethodStaticBytes);
|
|
const interfaceMethodStaticBytesWidth = interfaceMethodStaticBytes.methods.find((item) => item.name === "width");
|
|
assert(interfaceMethodStaticBytesWidth);
|
|
assert(interfaceMethodStaticBytesWidth.staticParams.some((item) => item.name === "N" && item.type === "usize" && item.staticDispatch === true));
|
|
|
|
const interfaceMethodStaticRenamedParamFixture = `${outDir}/interface-method-static-renamed-param.0`;
|
|
await writeGraphFixture(interfaceMethodStaticRenamedParamFixture, `interface Width<T: Type> {
|
|
fn width<static N: usize>(self: ref<T>, bytes: [N]u8) -> [N]u8
|
|
}
|
|
|
|
type Bytes {
|
|
value: u8,
|
|
|
|
fn width<static M: usize>(self: ref<Self>, bytes: [M]u8) -> [M]u8 {
|
|
return bytes
|
|
}
|
|
}
|
|
|
|
fn readWidth<T: Width<T>>(value: ref<T>, bytes: [4]u8) -> [4]u8 {
|
|
return T.width<4>(value, bytes)
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let bytes: Bytes = Bytes { value: 1 }
|
|
let output: [4]u8 = readWidth<Bytes>(&bytes, [1, 2, 3, 4])
|
|
}
|
|
`);
|
|
const interfaceMethodStaticRenamedParamJson = await execFileAsync(zero, ["check", "--json", interfaceMethodStaticRenamedParamFixture]);
|
|
const interfaceMethodStaticRenamedParamBody = JSON.parse(interfaceMethodStaticRenamedParamJson.stdout);
|
|
assert.equal(interfaceMethodStaticRenamedParamBody.ok, true);
|
|
const interfaceMethodStaticRenamedParamGraph = await execFileAsync(zero, ["inspect", "--json", interfaceMethodStaticRenamedParamFixture]);
|
|
const interfaceMethodStaticRenamedParamGraphBody = JSON.parse(interfaceMethodStaticRenamedParamGraph.stdout);
|
|
const interfaceMethodStaticRenamedWidth = interfaceMethodStaticRenamedParamGraphBody.interfaces.find((item) => item.name === "Width");
|
|
assert(interfaceMethodStaticRenamedWidth);
|
|
const interfaceMethodStaticRenamedWidthMethod = interfaceMethodStaticRenamedWidth.methods.find((item) => item.name === "width");
|
|
assert(interfaceMethodStaticRenamedWidthMethod);
|
|
assert(interfaceMethodStaticRenamedWidthMethod.staticParams.some((item) => item.name === "N" && item.type === "usize" && item.staticDispatch === true));
|
|
const interfaceMethodStaticRenamedBytes = interfaceMethodStaticRenamedParamGraphBody.shapes.find((item) => item.name === "Bytes");
|
|
assert(interfaceMethodStaticRenamedBytes);
|
|
const interfaceMethodStaticRenamedBytesWidth = interfaceMethodStaticRenamedBytes.methods.find((item) => item.name === "width");
|
|
assert(interfaceMethodStaticRenamedBytesWidth);
|
|
assert(interfaceMethodStaticRenamedBytesWidth.staticParams.some((item) => item.name === "M" && item.type === "usize" && item.staticDispatch === true));
|
|
|
|
const staticInterfaceReturnMismatchFixture = `${outDir}/static-interface-return-mismatch.0`;
|
|
const staticInterfaceReturnMismatchBody = await writeImportFailureFixture(staticInterfaceReturnMismatchFixture, `interface Sized<T: Type, static N: usize> {
|
|
fn bytes(self: ref<T>) -> [N]u8
|
|
}
|
|
|
|
type Bytes<static N: usize> {
|
|
items: [N]u8,
|
|
|
|
fn bytes(self: ref<Self>) -> [N]u8 {
|
|
return self.items
|
|
}
|
|
}
|
|
|
|
fn read<T: Sized<T, N>, static N: usize>(value: ref<T>) -> [N]u8 {
|
|
return T.bytes(value)
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let bytes: Bytes<4> = Bytes { items: [1, 2, 3, 4] }
|
|
let out: [3]u8 = read<Bytes<4>, 3>(&bytes)
|
|
}
|
|
`);
|
|
assert.equal(staticInterfaceReturnMismatchBody.diagnostics[0].code, "IFC004");
|
|
assert.match(staticInterfaceReturnMismatchBody.diagnostics[0].expected, /\[3\]u8/);
|
|
assert.match(staticInterfaceReturnMismatchBody.diagnostics[0].actual, /\[4\]u8/);
|
|
|
|
const shapeMethodGenericConstraintFixture = `${outDir}/shape-method-generic-constraint.0`;
|
|
const shapeMethodGenericConstraintBody = await writeImportFailureFixture(shapeMethodGenericConstraintFixture, `interface NeedsMethod<T: Type> {
|
|
fn need(self: ref<T>) -> u8
|
|
}
|
|
|
|
type Box {
|
|
value: u8,
|
|
|
|
fn accept<T: NeedsMethod<T>>(self: ref<Self>, item: T) -> u8 {
|
|
return self.value
|
|
}
|
|
}
|
|
|
|
type Plain {
|
|
value: u8,
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let box: Box = Box { value: 1 }
|
|
let plain: Plain = Plain { value: 2 }
|
|
let out: u8 = box.accept<Plain>(plain)
|
|
}
|
|
`);
|
|
assert.equal(shapeMethodGenericConstraintBody.diagnostics[0].code, "IFC002");
|
|
|
|
const interfaceMethodGenericConstraintFixture = `${outDir}/interface-method-generic-constraint.0`;
|
|
const interfaceMethodGenericConstraintBody = await writeImportFailureFixture(interfaceMethodGenericConstraintFixture, `interface NeedsMethod<T: Type> {
|
|
fn need(self: ref<T>) -> u8
|
|
}
|
|
|
|
interface Caller<T: Type> {
|
|
fn accept<U: NeedsMethod<U>>(self: ref<T>, item: U) -> u8
|
|
}
|
|
|
|
type Box {
|
|
value: u8,
|
|
|
|
fn accept<U: NeedsMethod<U>>(self: ref<Self>, item: U) -> u8 {
|
|
return self.value
|
|
}
|
|
}
|
|
|
|
type Plain {
|
|
value: u8,
|
|
}
|
|
|
|
fn read<T: Caller<T>>(value: ref<T>, plain: Plain) -> u8 {
|
|
return T.accept<Plain>(value, plain)
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let box: Box = Box { value: 1 }
|
|
let plain: Plain = Plain { value: 2 }
|
|
let out: u8 = read<Box>(&box, plain)
|
|
}
|
|
`);
|
|
assert.equal(interfaceMethodGenericConstraintBody.diagnostics[0].code, "IFC002");
|
|
|
|
const interfaceMethodGenericMismatchFixtures = [
|
|
{
|
|
name: "interface-method-generic-constraint-mismatch",
|
|
code: "IFC005",
|
|
message: /constraint does not match/,
|
|
source: `interface NeedsA<T: Type> {
|
|
fn needA(self: ref<T>) -> u8
|
|
}
|
|
|
|
interface NeedsB<T: Type> {
|
|
fn needB(self: ref<T>) -> u8
|
|
}
|
|
|
|
interface Caller<T: Type> {
|
|
fn accept<U: NeedsA<U>>(self: ref<T>, item: U) -> u8
|
|
}
|
|
|
|
type Box {
|
|
value: u8,
|
|
|
|
fn accept<U: NeedsB<U>>(self: ref<Self>, item: U) -> u8 {
|
|
return self.value
|
|
}
|
|
}
|
|
|
|
type A {
|
|
value: u8,
|
|
|
|
fn needA(self: ref<Self>) -> u8 {
|
|
return self.value
|
|
}
|
|
}
|
|
|
|
fn read<T: Caller<T>>(value: ref<T>, item: A) -> u8 {
|
|
return T.accept<A>(value, item)
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let box: Box = Box { value: 1 }
|
|
let a: A = A { value: 2 }
|
|
let out: u8 = read<Box>(&box, a)
|
|
}
|
|
`,
|
|
},
|
|
{
|
|
name: "interface-method-missing-static-param",
|
|
code: "IFC003",
|
|
source: `interface Width<T: Type> {
|
|
fn width<static N: usize>(self: ref<T>) -> usize
|
|
}
|
|
|
|
type Bytes {
|
|
value: u8,
|
|
|
|
fn width(self: ref<Self>) -> usize {
|
|
return 1
|
|
}
|
|
}
|
|
|
|
fn readWidth<T: Width<T>>(value: ref<T>) -> usize {
|
|
return T.width<4>(value)
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let bytes: Bytes = Bytes { value: 1 }
|
|
let width: usize = readWidth<Bytes>(&bytes)
|
|
}
|
|
`,
|
|
},
|
|
{
|
|
name: "interface-method-extra-static-param",
|
|
code: "IFC003",
|
|
source: `interface Width<T: Type> {
|
|
fn width(self: ref<T>) -> usize
|
|
}
|
|
|
|
type Bytes {
|
|
value: u8,
|
|
|
|
fn width<static N: usize>(self: ref<Self>) -> usize {
|
|
return N
|
|
}
|
|
}
|
|
|
|
fn readWidth<T: Width<T>>(value: ref<T>) -> usize {
|
|
return T.width(value)
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let bytes: Bytes = Bytes { value: 1 }
|
|
let width: usize = readWidth<Bytes>(&bytes)
|
|
}
|
|
`,
|
|
},
|
|
{
|
|
name: "interface-method-static-param-type-mismatch",
|
|
code: "IFC005",
|
|
source: `interface Width<T: Type> {
|
|
fn width<static N: usize>(self: ref<T>) -> usize
|
|
}
|
|
|
|
type Bytes {
|
|
value: u8,
|
|
|
|
fn width<static N: Bool>(self: ref<Self>) -> usize {
|
|
return 1
|
|
}
|
|
}
|
|
|
|
fn readWidth<T: Width<T>>(value: ref<T>) -> usize {
|
|
return T.width<4>(value)
|
|
}
|
|
|
|
pub fn main() -> Void {
|
|
let bytes: Bytes = Bytes { value: 1 }
|
|
let width: usize = readWidth<Bytes>(&bytes)
|
|
}
|
|
`,
|
|
},
|
|
];
|
|
|
|
for (const fixtureCase of interfaceMethodGenericMismatchFixtures) {
|
|
const fixture = `${outDir}/${fixtureCase.name}.0`;
|
|
const interfaceMethodGenericMismatchBody = await writeImportFailureFixture(fixture, fixtureCase.source);
|
|
assert.equal(interfaceMethodGenericMismatchBody.diagnostics[0].code, fixtureCase.code);
|
|
if (fixtureCase.message) assert.match(interfaceMethodGenericMismatchBody.diagnostics[0].message, fixtureCase.message);
|
|
}
|
|
|
|
const badTargetNameJson = await execFileAsync(zero, ["check", "--json", "--target", "not-a-target", "examples/hello.0"]).catch((error) => error);
|
|
assert.notEqual(badTargetNameJson.code, 0);
|
|
const badTargetNameBody = JSON.parse(badTargetNameJson.stdout);
|
|
assert.equal(badTargetNameBody.diagnostics[0].code, "TAR001");
|
|
assert.match(badTargetNameBody.diagnostics[0].message, /unknown target/);
|
|
assert.match(badTargetNameBody.diagnostics[0].expected, /zero targets/);
|
|
assert.equal(badTargetNameBody.diagnostics[0].actual, "not-a-target");
|
|
assert.match(badTargetNameBody.diagnostics[0].help, /zero targets/);
|
|
assert.equal(badTargetNameBody.diagnostics[0].fixSafety, "requires-human-review");
|
|
assert.equal(badTargetNameBody.diagnostics[0].repair.id, "manual-review");
|
|
assert.match(badTargetNameBody.diagnostics[0].related[0].message, /not-a-target/);
|
|
|
|
const explainTar002 = await execFileAsync(zero, ["explain", "--json", "TAR002"]);
|
|
const explainTar002Body = JSON.parse(explainTar002.stdout);
|
|
assert.equal(explainTar002Body.schemaVersion, 1);
|
|
assert.equal(explainTar002Body.code, "TAR002");
|
|
assert.equal(explainTar002Body.repair.id, "choose-target-with-required-capability");
|
|
|
|
const explainText = await execFileAsync(zero, ["explain", "TYP009"]);
|
|
assert.match(explainText.stdout, /Mutable storage required/);
|
|
|
|
const importGraph = await execFileAsync(zero, ["inspect", "--json", "conformance/check/pass/imports"]);
|
|
const importGraphBody = JSON.parse(importGraph.stdout);
|
|
assert.deepEqual(importGraphBody.imports, []);
|
|
assert.equal(importGraphBody.sourceFiles.length, 3);
|
|
assert.equal(importGraphBody.sourceMaps.length, 3);
|
|
assert(importGraphBody.sourceMaps.every((item) => item.columnUnit === "utf8-byte"));
|
|
assert.deepEqual(importGraphBody.targets.map((item) => item.name), ["cli"]);
|
|
assert.deepEqual(importGraphBody.modules.map((item) => item.name), ["math", "types", "main"]);
|
|
assert.deepEqual(importGraphBody.importEdges.map((item) => `${item.from}->${item.to}`), ["main->math", "main->types"]);
|
|
assert.deepEqual(importGraphBody.importEdges.map((item) => `${item.from}->${item.to}:${item.sourceRange.path}:${item.sourceRange.start.line}:${item.sourceRange.start.column}:${item.sourceRange.end.column}`), [
|
|
"main->math:src/main.0:1:1:9",
|
|
"main->types:src/main.0:3:1:10",
|
|
]);
|
|
assert.deepEqual(importGraphBody.useImports.map((item) => `${item.from}->${item.to}:${item.kind}:${item.line}:${item.column}`), [
|
|
"main->math:package-local:1:1",
|
|
"main->types:package-local:3:1",
|
|
]);
|
|
assert.deepEqual(importGraphBody.useImports.map((item) => item.resolvedPath), [
|
|
"src/math.0",
|
|
"src/types.0",
|
|
]);
|
|
assert(importGraphBody.useImports.every((item) => item.sourceRange.columnUnit === "utf8-byte"));
|
|
assert(importGraphBody.functions.some((item) => item.name === "add_one" && item.returnType === "i32"));
|
|
assert(importGraphBody.functions.some((item) => item.name === "main" && item.returnType === "Void" && item.effects.includes("world")));
|
|
|
|
const whitespaceUsePackage = `${outDir}/use-whitespace-package`;
|
|
await mkdir(`${whitespaceUsePackage}/src`, { recursive: true });
|
|
await writeZeroToml(whitespaceUsePackage, {
|
|
package: { name: "use-whitespace-package", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "src/main.0" } },
|
|
deps: {},
|
|
});
|
|
await mkdir(`${whitespaceUsePackage}/src/math`, { recursive: true });
|
|
await writeFile(`${whitespaceUsePackage}/src/math.0`, 'fn add_one(value: i32) -> i32 {\n return value + 1\n}\n');
|
|
await writeFile(`${whitespaceUsePackage}/src/math/util.0`, 'fn add_two(value: i32) -> i32 {\n return value + 2\n}\n');
|
|
await writeFile(`${whitespaceUsePackage}/src/types.0`, 'type Point {\n value: i32,\n}\n');
|
|
await writeFile(`${whitespaceUsePackage}/src/main.0`, 'use math\nuse math . util\nuse types as model\n\npub fn main(world: World) -> Void raises {\n let point: Point = Point { value: add_two(40) }\n if point.value == add_one(41) {\n check world.out.write("whitespace imports pass\\n")\n }\n}\n');
|
|
await importPackageGraph(whitespaceUsePackage);
|
|
const whitespaceUseCheck = await execFileAsync(zero, ["check", "--json", whitespaceUsePackage]);
|
|
assert.equal(JSON.parse(whitespaceUseCheck.stdout).ok, true);
|
|
const whitespaceUseGraph = await execFileAsync(zero, ["inspect", "--json", whitespaceUsePackage]);
|
|
const whitespaceUseGraphBody = JSON.parse(whitespaceUseGraph.stdout);
|
|
assert.deepEqual(whitespaceUseGraphBody.useImports.map((item) => `${item.from}->${item.to}:${item.kind}:${item.alias ?? "null"}:${item.sourceRange.end.column}`), [
|
|
"main->math:package-local:null:9",
|
|
"main->math.util:package-local:null:14",
|
|
"main->types:package-local:model:10",
|
|
]);
|
|
assert.deepEqual(whitespaceUseGraphBody.importEdges.map((item) => `${item.from}->${item.to}`), ["main->math", "main->math.util", "main->types"]);
|
|
|
|
const packageUseGraph = await execFileAsync(zero, ["inspect", "--json", "conformance/check/pass/package"]);
|
|
const packageUseGraphBody = JSON.parse(packageUseGraph.stdout);
|
|
assert.deepEqual(packageUseGraphBody.useImports.map((item) => `${item.from}->${item.to}:${item.kind}:${item.resolvedPath ?? "null"}`), [
|
|
"main->std.codec:stdlib:null",
|
|
"main->std.parse:stdlib:null",
|
|
"main->std.time:stdlib:null",
|
|
"main->types:package-local:src/types.0",
|
|
]);
|
|
|
|
const resourceGraph = await execFileAsync(zero, ["inspect", "--json", "examples/resource-cli"]);
|
|
const resourceGraphBody = JSON.parse(resourceGraph.stdout);
|
|
assert(resourceGraphBody.targets.some((item) => item.name === "cli" && item.kind === "exe"));
|
|
assert.deepEqual(resourceGraphBody.importEdges.map((item) => `${item.from}->${item.to}`), ["main->config", "main->payload"]);
|
|
assert(resourceGraphBody.requiresCapabilities.includes("fs"));
|
|
assert(resourceGraphBody.functions.some((item) => item.name === "outputDir" && item.effects.includes("env")));
|
|
const resourceMainFunction = resourceGraphBody.functions.find((item) => item.name === "main");
|
|
assert(resourceMainFunction.effects.includes("fs"));
|
|
assert.equal(resourceMainFunction.allocationBehavior, "no heap allocation");
|
|
assert.equal(resourceMainFunction.ownership.params[0].type, "World");
|
|
|
|
const memoryGraph = await execFileAsync(zero, ["inspect", "--json", "--target", "linux-musl-x64", "examples/memory-package"]);
|
|
const memoryGraphBody = JSON.parse(memoryGraph.stdout);
|
|
assert.deepEqual(memoryGraphBody.importEdges.map((item) => `${item.from}->${item.to}`), ["main->buffer", "main->checksum"]);
|
|
assert(memoryGraphBody.requiresCapabilities.includes("memory"));
|
|
assert(!memoryGraphBody.requiresCapabilities.includes("fs"));
|
|
assert.equal(memoryGraphBody.targetSupport.fsAvailable, true);
|
|
assert.equal(memoryGraphBody.targetSupport.requiredCapabilitySupport.status, "supported");
|
|
assert.equal(memoryGraphBody.functions.filter((item) => item.public).length, 5);
|
|
assert(memoryGraphBody.stdlibHelpers.some((helper) => helper.name === "std.mem.copy" && helper.targetSupport === "target-neutral"));
|
|
assert(memoryGraphBody.stdlibHelpers.some((helper) => helper.name === "std.fs.createOrRaise" && helper.targetSupport === "host"));
|
|
const memCopyHelper = memoryGraphBody.stdlibHelpers.find((helper) => helper.name === "std.mem.copy");
|
|
assert.equal(memCopyHelper.module, "std.mem");
|
|
assert(memCopyHelper.effects.includes("memory"));
|
|
assert.equal(memCopyHelper.errorBehavior, "infallible");
|
|
assert.match(memCopyHelper.ownershipNotes, /caller-owned storage/);
|
|
assert.equal(memCopyHelper.example, "examples/memory-primitives.0");
|
|
assert.equal(memCopyHelper.apiStability, "bootstrap-stable");
|
|
|
|
const lexerTokens = await execFileAsync(zero, ["tokens", "--json", "conformance/lexer/compiler-smoke.0"]);
|
|
const lexerTokensBody = JSON.parse(lexerTokens.stdout);
|
|
assert.equal(lexerTokensBody.schemaVersion, 1);
|
|
assert.equal(lexerTokensBody.syntax, "canonical");
|
|
assert.deepEqual(lexerTokensBody.tokens.slice(0, 4).map((token) => `${token.kind}:${token.text}`), [
|
|
"word:use",
|
|
"word:std",
|
|
"symbol:.",
|
|
"word:mem",
|
|
]);
|
|
assert.deepEqual(lexerTokensBody.tokens.filter((token) => token.kind === "number").map((token) => token.text), ["123", "0xff", "0b101", "42_u8"]);
|
|
assert.deepEqual(lexerTokensBody.tokens.filter((token) => token.kind === "string" || token.kind === "char").map((token) => `${token.kind}:${token.text}`), [
|
|
'string:"hi"',
|
|
"char:'x'",
|
|
]);
|
|
assert.equal(lexerTokensBody.tokens[0].line, 1);
|
|
assert.equal(lexerTokensBody.tokens[0].column, 1);
|
|
assert.equal(lexerTokensBody.tokens[0].offset, 0);
|
|
assert.equal(lexerTokensBody.tokens[0].length, 3);
|
|
assert.equal(lexerTokensBody.tokens[5].offset, 12);
|
|
assert.equal(lexerTokensBody.tokens[5].length, 1);
|
|
assert.equal(lexerTokensBody.tokens[8].kind, "word");
|
|
assert.equal(lexerTokensBody.tokens[8].text, "main");
|
|
assert.equal(lexerTokensBody.tokens[8].line, 3);
|
|
assert.equal(lexerTokensBody.tokens[8].column, 8);
|
|
assert.equal(lexerTokensBody.tokens.at(-1).kind, "eof");
|
|
assert.equal(lexerTokensBody.tokens.at(-1).length, 0);
|
|
|
|
const parseTree = await execFileAsync(zero, ["parse", "--json", "conformance/format/functions-blocks.0"]);
|
|
const parseTreeBody = JSON.parse(parseTree.stdout);
|
|
assert.equal(parseTreeBody.schemaVersion, 1);
|
|
assert.equal(parseTreeBody.root.kind, "module");
|
|
assert.equal(parseTreeBody.root.shapeCount, 0);
|
|
assert.equal(parseTreeBody.root.enumCount, 0);
|
|
assert.equal(parseTreeBody.root.choiceCount, 0);
|
|
assert.equal(parseTreeBody.root.functionCount, 2);
|
|
assert.equal(parseTreeBody.functions[0].name, "helper");
|
|
assert.equal(parseTreeBody.functions[0].paramCount, 1);
|
|
assert.deepEqual(parseTreeBody.functions[0].bodyKinds, ["if"]);
|
|
assert.equal(parseTreeBody.functions[1].name, "main");
|
|
assert.equal(parseTreeBody.functions[1].paramCount, 0);
|
|
assert.deepEqual(parseTreeBody.functions[1].bodyKinds, ["let", "while"]);
|
|
|
|
const constGraph = await execFileAsync(zero, ["inspect", "--json", "examples/const-arithmetic.0"]);
|
|
const constGraphBody = JSON.parse(constGraph.stdout);
|
|
assert(constGraphBody.consts.some((item) => item.name === "answer" && item.type === "i32"));
|
|
|
|
const genericPairGraph = await execFileAsync(zero, ["inspect", "--json", "conformance/check/pass/generic-shape-multi.0"]);
|
|
const genericPairGraphBody = JSON.parse(genericPairGraph.stdout);
|
|
assert(genericPairGraphBody.functions.some((item) => item.name === "makePair" && item.generic === true && item.returnType === "Pair<T, U>"));
|
|
assert(genericPairGraphBody.shapes.some((item) => item.name === "Pair" && item.generic === true && item.typeParams.join(",") === "T,U"));
|
|
|
|
const staticValueGraph = await execFileAsync(zero, ["inspect", "--json", "examples/static-value-params.0"]);
|
|
const staticValueGraphBody = JSON.parse(staticValueGraph.stdout);
|
|
const fixedVecShape = staticValueGraphBody.shapes.find((item) => item.name === "FixedVec");
|
|
assert(fixedVecShape);
|
|
assert(fixedVecShape.staticParams.some((item) => item.name === "N" && item.type === "usize" && item.staticDispatch === true));
|
|
assert(staticValueGraphBody.functions.some((item) => item.name === "first" && item.staticParams.some((param) => param.name === "N")));
|
|
|
|
const fixedVecGraph = await execFileAsync(zero, ["inspect", "--json", "examples/fixed-vec.0"]);
|
|
const fixedVecGraphBody = JSON.parse(fixedVecGraph.stdout);
|
|
const fixedVecMethodsShape = fixedVecGraphBody.shapes.find((item) => item.name === "FixedVec");
|
|
assert(fixedVecMethodsShape);
|
|
const pushMethod = fixedVecMethodsShape.methods.find((item) => item.name === "push");
|
|
assert(pushMethod);
|
|
assert.equal(pushMethod.inheritedShapeParams, true);
|
|
assert.deepEqual(pushMethod.shapeTypeParams, ["T", "N"]);
|
|
assert(pushMethod.shapeStaticParams.some((item) => item.name === "N" && item.staticDispatch === true));
|
|
|
|
const aliasGraph = await execFileAsync(zero, ["inspect", "--json", "examples/type-alias.0"]);
|
|
const aliasGraphBody = JSON.parse(aliasGraph.stdout);
|
|
assert(aliasGraphBody.aliases.some((item) => item.name === "BytePair" && item.target === "Pair<u8, u8>"));
|
|
|
|
const staticMethodGraph = await execFileAsync(zero, ["inspect", "--json", "examples/static-method.0"]);
|
|
const staticMethodGraphBody = JSON.parse(staticMethodGraph.stdout);
|
|
const counterShape = staticMethodGraphBody.shapes.find((item) => item.name === "Counter");
|
|
assert(counterShape);
|
|
assert(counterShape.methods.some((item) => item.name === "add" && item.staticDispatch === true && item.returnType === "i32"));
|
|
|
|
const staticInterfaceGraph = await execFileAsync(zero, ["inspect", "--json", "examples/static-interface.0"]);
|
|
const staticInterfaceGraphBody = JSON.parse(staticInterfaceGraph.stdout);
|
|
assert(staticInterfaceGraphBody.interfaces.some((item) => item.name === "Readable" && item.staticOnly === true));
|
|
assert(staticInterfaceGraphBody.functions.some((item) => item.name === "readValue" && item.constraints.some((constraint) => constraint.interface === "Readable<T>" && constraint.staticDispatch === true)));
|
|
|
|
const callResolutionGraph = await execFileAsync(zero, ["inspect", "--json", "conformance/check/pass/call-resolution-inspection.0"]);
|
|
const callResolutionGraphBody = JSON.parse(callResolutionGraph.stdout);
|
|
const callFacts = callResolutionGraphBody.callResolution;
|
|
assert.equal(callFacts.schemaVersion, 1);
|
|
for (const kind of ["function", "stdlib", "receiver", "shape_namespace", "constrained_interface", "concrete_constrained_shape", "choice_constructor"]) {
|
|
assert(callFacts.supportedKinds.includes(kind));
|
|
assert(callFacts.calls.some((item) => item.kind === kind), `missing call-resolution fact for ${kind}`);
|
|
}
|
|
assert(callFacts.calls.some((item) => item.kind === "function" && item.calleeName === "add" && item.returnType === "i32" && item.expectedArgCount === 2));
|
|
assert(callFacts.calls.some((item) => item.kind === "function" && item.calleeName === "id" && item.bindings.some((binding) => binding.name === "T" && binding.type === "i32")));
|
|
assert(callFacts.calls.some((item) => item.kind === "function" && item.calleeName === "id" && item.owner === "wrap" && item.instantiationDepth === 1 && item.instantiatedBy === "main" && item.returnType === "i32"));
|
|
assert(callFacts.calls.some((item) => item.kind === "stdlib" && item.calleeName === "std.mem.len" && item.returnType === "usize" && item.args.some((arg) => arg.actualType === "String")));
|
|
assert(callFacts.calls.some((item) => item.kind === "choice_constructor" && item.calleeName === "Event.key" && item.choice === "Event" && item.choiceCase === "key"));
|
|
assert(callFacts.calls.some((item) => item.kind === "shape_namespace" && item.calleeName === "read" && item.shape === "Counter"));
|
|
assert(callFacts.calls.some((item) => item.kind === "receiver" && item.calleeName === "bump" && item.shape === "Counter" && item.paramOffset === 1));
|
|
assert(callFacts.calls.some((item) => item.kind === "constrained_interface" && item.calleeName === "read" && item.interface === "Readable" && item.owner === "readValue"));
|
|
assert(callFacts.calls.some((item) => item.kind === "concrete_constrained_shape" && item.calleeName === "read" && item.shape === "Counter" && item.instantiatedBy === "main"));
|
|
assert(callFacts.calls.some((item) => item.calleeName === "add" && item.path === "call-resolution-inspection.0"));
|
|
assert(callFacts.calls.some((item) => item.kind === "function" && item.calleeName === "defaultCount" && item.owner === "Counter.value" && item.returnType === "i32"));
|
|
assert(callFacts.calls.some((item) => item.kind === "function" && item.calleeName === "risky" && item.fallible === true && item.errors.includes("BadInput")));
|
|
assert(callFacts.calls.some((item) => item.kind === "receiver" && item.calleeName === "checkedRead" && item.fallible === true && item.errors.includes("EmptyCounter")));
|
|
|
|
const callResolutionMemGetGraph = await execFileAsync(zero, ["inspect", "--json", "conformance/native/pass/checked-bounds-get.0"]);
|
|
const callResolutionMemGetFacts = JSON.parse(callResolutionMemGetGraph.stdout).callResolution;
|
|
assert(callResolutionMemGetFacts.calls.some((item) => item.kind === "stdlib" && item.calleeName === "std.mem.get" && item.returnType === "Maybe<u8>" && item.args.some((arg) => arg.paramIndex === 0 && arg.actualType === "[3]u8")));
|
|
|
|
const callResolutionGenericShapeGraph = await execFileAsync(zero, ["inspect", "--json", "conformance/check/pass/generic-shape-methods.0"]);
|
|
const callResolutionGenericShapeFacts = JSON.parse(callResolutionGenericShapeGraph.stdout).callResolution;
|
|
assert(callResolutionGenericShapeFacts.calls.some((item) =>
|
|
item.kind === "stdlib" &&
|
|
item.calleeName === "std.mem.get" &&
|
|
item.owner === "FixedVec.get" &&
|
|
item.instantiationDepth === 1 &&
|
|
item.instantiatedBy === "main" &&
|
|
item.returnType === "Maybe<u8>" &&
|
|
item.args.some((arg) => arg.paramIndex === 0 && arg.actualType === "[4]u8")
|
|
));
|
|
|
|
const callResolutionFsReadGraph = await execFileAsync(zero, ["inspect", "--json", "conformance/native/pass/std-fs-resource.0"]);
|
|
const callResolutionFsReadFacts = JSON.parse(callResolutionFsReadGraph.stdout).callResolution;
|
|
assert(callResolutionFsReadFacts.calls.some((item) => item.kind === "stdlib" && item.calleeName === "std.fs.read" && item.returnType === "Maybe<usize>" && item.args.some((arg) => arg.paramIndex === 0 && arg.expectedType === "mutref<File>" && arg.actualType === "mutref<File>")));
|
|
|
|
const callResolutionPackageGraph = await execFileAsync(zero, ["inspect", "--json", "examples/systems-package"]);
|
|
const callResolutionPackageFacts = JSON.parse(callResolutionPackageGraph.stdout).callResolution;
|
|
assert(callResolutionPackageFacts.calls.some((item) => item.calleeName === "cleanup" && item.path === "src/main.0" && item.line === 18));
|
|
|
|
const callResolutionEdgeGraph = await execFileAsync(zero, ["inspect", "--json", "conformance/check/pass/call-resolution-edge-cases.0"]);
|
|
const callResolutionEdgeFacts = JSON.parse(callResolutionEdgeGraph.stdout).callResolution;
|
|
assert(callResolutionEdgeFacts.calls.some((item) => item.kind === "function" && item.calleeName === "add" && item.owner === "constTotal" && item.returnType === "i32"));
|
|
assert(callResolutionEdgeFacts.calls.some((item) => item.kind === "stdlib" && item.calleeName === "std.mem.len" && item.owner === "main" && item.args.some((arg) => arg.paramIndex === 0 && arg.actualType === "String")));
|
|
|
|
const programGraphBody = JSON.parse((await execFileAsync(zero, ["inspect", "--json", "examples/hello.0"])).stdout).programGraph;
|
|
const programGraphBodyAgain = JSON.parse((await execFileAsync(zero, ["inspect", "--json", "examples/hello.0"])).stdout).programGraph;
|
|
const programGraphDump = (await execFileAsync(zero, ["dump", "examples/hello.0"])).stdout;
|
|
const programGraphDumpAgain = (await execFileAsync(zero, ["dump", "examples/hello.0"])).stdout;
|
|
const programGraphDumpJson = JSON.parse((await execFileAsync(zero, ["dump", "--json", "examples/hello.0"])).stdout);
|
|
const programGraphDumpPath = `${outDir}/hello.program-graph`;
|
|
const programGraphDumpJsonPath = `${outDir}/hello.dump-json.program-graph`;
|
|
const programGraphCanonicalPath = `${outDir}/hello.canonical.program-graph`;
|
|
const programGraphViewPath = `${outDir}/hello.graph-view.0`;
|
|
const programGraphArtifactRoundtripPath = `${outDir}/hello.roundtrip.program-graph`;
|
|
const programGraphSourceFixturePath = "conformance/program-graph/hello.0";
|
|
const programGraphSourceFixturePackage = "conformance/program-graph";
|
|
const programGraphSourceFixtureStorePath = "conformance/program-graph/zero.graph";
|
|
const programGraphSourceFixtureRunPath = `${outDir}/program-graph-fixture-run`;
|
|
const programGraphSourceFreePackage = `${outDir}/program-graph-source-free`;
|
|
const programGraphSourceFreeBuildPath = `${outDir}/program-graph-source-free-build`;
|
|
const programGraphSourceFreeRunPath = `${outDir}/program-graph-source-free-run`;
|
|
const programGraphSourceFreeStdStrPackage = `${outDir}/program-graph-source-free-std-str`;
|
|
const programGraphCrmApiBuildPath = `${outDir}/program-graph-crm-api-build`;
|
|
const programGraphAuthoringPackage = `${outDir}/program-graph-authoring`;
|
|
const programGraphAuthoringRunPath = `${outDir}/program-graph-authoring-run`;
|
|
const programGraphAuthoringRunAfterHumanEditPath = `${outDir}/program-graph-authoring-run-human-edit`;
|
|
const programGraphBuilderOpsPackage = `${outDir}/program-graph-builder-ops`;
|
|
const programGraphBuilderOpsRunPath = `${outDir}/program-graph-builder-ops-run`;
|
|
const programGraphLoopTestPackage = `${outDir}/program-graph-loop-test`;
|
|
const programGraphArrayLengthPackage = `${outDir}/program-graph-array-length-mismatch`;
|
|
const programGraphBlockBodyPackage = `${outDir}/program-graph-block-body`;
|
|
const programGraphBlockBodyRunPath = `${outDir}/program-graph-block-body-run`;
|
|
const programGraphAuthoringCliPackage = `${outDir}/program-graph-authoring-cli`;
|
|
const programGraphAuthoringCliGraphBuildPath = `${outDir}/program-graph-authoring-cli-graph-build`;
|
|
const programGraphAuthoringCliBuildPath = `${outDir}/program-graph-authoring-cli-build`;
|
|
const programGraphAuthoringCliRunPath = `${outDir}/program-graph-authoring-cli-run`;
|
|
const programGraphAuthoringCliRunAfterHumanEditPath = `${outDir}/program-graph-authoring-cli-run-human-edit`;
|
|
const programGraphSourceFreeCImportPackage = `${outDir}/program-graph-source-free-c-import`;
|
|
const programGraphSourceFreeCImportRunPath = `${outDir}/program-graph-source-free-c-import-run`;
|
|
const programGraphSourceFreeCImportCwdPackage = `${outDir}/program-graph-source-free-c-import-cwd`;
|
|
const programGraphSourceFreeCImportCwdBuildPath = `${outDir}/program-graph-source-free-c-import-cwd-build`;
|
|
const programGraphIdentityMismatchPackage = `${outDir}/program-graph-identity-mismatch`;
|
|
const programGraphMissingPackageNamePackage = `${outDir}/program-graph-missing-package-name`;
|
|
const programGraphBadProjectionPackage = `${outDir}/program-graph-bad-projection`;
|
|
const programGraphSourceFixtureDriftPackage = `${outDir}/program-graph-fixture-drift`;
|
|
const programGraphMissingStorePackage = `${outDir}/program-graph-missing-store`;
|
|
const programGraphInvalidStorePackage = `${outDir}/program-graph-invalid-store`;
|
|
const programGraphTargetWebbitsPackage = `${outDir}/program-graph-target-webbits`;
|
|
const programGraphTargetIncompatiblePackage = `${outDir}/program-graph-target-incompatible`;
|
|
const programGraphTargetCapabilityPackage = `${outDir}/program-graph-target-capability`;
|
|
const programGraphRichPath = `${outDir}/open-ended-slices.program-graph`;
|
|
const programGraphRichViewPath = `${outDir}/open-ended-slices.graph-view.0`;
|
|
const programGraphCharPath = `${outDir}/float-char-casts.program-graph`;
|
|
const programGraphCharViewPath = `${outDir}/float-char-casts.graph-view.0`;
|
|
await rm(programGraphDumpPath, { force: true });
|
|
await rm(programGraphDumpJsonPath, { force: true });
|
|
await rm(programGraphCanonicalPath, { force: true });
|
|
await rm(programGraphViewPath, { force: true });
|
|
await rm(programGraphArtifactRoundtripPath, { force: true });
|
|
await rm(programGraphSourceFixtureRunPath, { force: true });
|
|
await rm(programGraphSourceFreePackage, { recursive: true, force: true });
|
|
await rm(programGraphSourceFreeBuildPath, { force: true });
|
|
await rm(programGraphSourceFreeRunPath, { force: true });
|
|
await rm(programGraphSourceFreeStdStrPackage, { recursive: true, force: true });
|
|
await rm(programGraphCrmApiBuildPath, { force: true });
|
|
await rm(programGraphAuthoringPackage, { recursive: true, force: true });
|
|
await rm(programGraphAuthoringRunPath, { force: true });
|
|
await rm(programGraphAuthoringRunAfterHumanEditPath, { force: true });
|
|
await rm(programGraphBuilderOpsPackage, { recursive: true, force: true });
|
|
await rm(programGraphBuilderOpsRunPath, { force: true });
|
|
await rm(programGraphLoopTestPackage, { recursive: true, force: true });
|
|
await rm(programGraphArrayLengthPackage, { recursive: true, force: true });
|
|
await rm(programGraphBlockBodyPackage, { recursive: true, force: true });
|
|
await rm(programGraphBlockBodyRunPath, { force: true });
|
|
await rm(programGraphAuthoringCliPackage, { recursive: true, force: true });
|
|
await rm(programGraphAuthoringCliGraphBuildPath, { force: true });
|
|
await rm(programGraphAuthoringCliBuildPath, { force: true });
|
|
await rm(programGraphAuthoringCliRunPath, { force: true });
|
|
await rm(programGraphAuthoringCliRunAfterHumanEditPath, { force: true });
|
|
await rm(programGraphSourceFreeCImportPackage, { recursive: true, force: true });
|
|
await rm(programGraphSourceFreeCImportRunPath, { force: true });
|
|
await rm(programGraphSourceFreeCImportCwdPackage, { recursive: true, force: true });
|
|
await rm(programGraphSourceFreeCImportCwdBuildPath, { force: true });
|
|
await rm(programGraphIdentityMismatchPackage, { recursive: true, force: true });
|
|
await rm(programGraphMissingPackageNamePackage, { recursive: true, force: true });
|
|
await rm(programGraphBadProjectionPackage, { recursive: true, force: true });
|
|
await rm(programGraphSourceFixtureDriftPackage, { recursive: true, force: true });
|
|
await rm(programGraphMissingStorePackage, { recursive: true, force: true });
|
|
await rm(programGraphInvalidStorePackage, { recursive: true, force: true });
|
|
await rm(programGraphTargetWebbitsPackage, { recursive: true, force: true });
|
|
await rm(programGraphTargetIncompatiblePackage, { recursive: true, force: true });
|
|
await rm(programGraphTargetCapabilityPackage, { recursive: true, force: true });
|
|
await rm(programGraphRichPath, { force: true });
|
|
await rm(programGraphRichViewPath, { force: true });
|
|
await rm(programGraphCharPath, { force: true });
|
|
await rm(programGraphCharViewPath, { force: true });
|
|
const programGraphDumpOut = await execFileAsync(zero, ["dump", "--out", programGraphDumpPath, "examples/hello.0"]);
|
|
const programGraphDumpOutJson = JSON.parse((await execFileAsync(zero, ["dump", "--json", "--out", programGraphDumpJsonPath, "examples/hello.0"])).stdout);
|
|
const programGraphDumpFile = await readFile(programGraphDumpPath, "utf8");
|
|
const programGraphDumpJsonFile = await readFile(programGraphDumpJsonPath, "utf8");
|
|
const programGraphValidate = await execFileAsync(zero, ["validate", programGraphDumpPath]);
|
|
const programGraphDumpJsonValidate = await execFileAsync(zero, ["validate", programGraphDumpJsonPath]);
|
|
const programGraphValidateJson = JSON.parse((await execFileAsync(zero, ["validate", "--json", "--out", programGraphCanonicalPath, programGraphDumpPath])).stdout);
|
|
const programGraphCanonicalFile = await readFile(programGraphCanonicalPath, "utf8");
|
|
const programGraphView = (await execFileAsync(zero, ["view", programGraphDumpPath])).stdout;
|
|
const programGraphViewAgain = (await execFileAsync(zero, ["view", programGraphDumpPath])).stdout;
|
|
const programGraphViewJson = JSON.parse((await execFileAsync(zero, ["view", "--json", programGraphDumpPath])).stdout);
|
|
const programGraphViewOut = await execFileAsync(zero, ["view", "--out", programGraphViewPath, programGraphDumpPath]);
|
|
const programGraphViewFile = await readFile(programGraphViewPath, "utf8");
|
|
const programGraphViewOutJson = JSON.parse((await execFileAsync(zero, ["view", "--json", "--out", programGraphViewPath, programGraphDumpPath])).stdout);
|
|
const programGraphRoundtrip = await execFileAsync(zero, ["roundtrip", "examples/hello.0"]);
|
|
const programGraphRoundtripJson = JSON.parse((await execFileAsync(zero, ["roundtrip", "--json", "examples/hello.0"])).stdout);
|
|
const programGraphArtifactRoundtrip = await execFileAsync(zero, ["roundtrip", programGraphDumpPath]);
|
|
const programGraphArtifactRoundtripJson = JSON.parse((await execFileAsync(zero, ["roundtrip", "--json", "--out", programGraphArtifactRoundtripPath, programGraphDumpPath])).stdout);
|
|
const programGraphSourceFixtureText = await readFile(programGraphSourceFixturePath, "utf8");
|
|
const programGraphSourceFixtureStoreBytes = await readFile(programGraphSourceFixtureStorePath);
|
|
const programGraphSourceFixturePackageCheckJson = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphSourceFixturePackage])).stdout);
|
|
const programGraphSourceFixturePackageStatusJson = JSON.parse((await execFileAsync(zero, ["status", "--json", programGraphSourceFixturePackage])).stdout);
|
|
const programGraphSourceFixturePackageRun = await execFileAsync(zero, ["run", "--out", programGraphSourceFixtureRunPath, programGraphSourceFixturePackage]);
|
|
await mkdir(programGraphSourceFreePackage, { recursive: true });
|
|
await writeFile(`${programGraphSourceFreePackage}/zero.toml`, await readFile(`${programGraphSourceFixturePackage}/zero.toml`, "utf8"));
|
|
await writeFile(`${programGraphSourceFreePackage}/zero.graph`, programGraphSourceFixtureStoreBytes);
|
|
const programGraphSourceFreeCheckJson = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphSourceFreePackage])).stdout);
|
|
const programGraphSourceFreeSizeJson = JSON.parse((await execFileAsync(zero, ["size", "--json", "--target", "linux-musl-x64", programGraphSourceFreePackage])).stdout);
|
|
const programGraphSourceFreeBuildJson = JSON.parse((await execFileAsync(zero, ["build", "--json", "--target", "linux-musl-x64", "--out", programGraphSourceFreeBuildPath, programGraphSourceFreePackage])).stdout);
|
|
const programGraphSourceFreeMappedMirCache = programGraphSourceFreeBuildJson.graphBuild?.mappedFinalMir;
|
|
const programGraphSourceFreeMappedMirCachePath = programGraphSourceFreeMappedMirCache?.path ?? "";
|
|
const programGraphSourceFreeRun = await execFileAsync(zero, ["run", "--out", programGraphSourceFreeRunPath, programGraphSourceFreePackage]);
|
|
const programGraphSourceFreeTestJson = JSON.parse((await execFileAsync(zero, ["test", "--json", programGraphSourceFreePackage])).stdout);
|
|
const programGraphSourceFreeMemJson = JSON.parse((await execFileAsync(zero, ["mem", "--json", programGraphSourceFreePackage])).stdout);
|
|
const programGraphSourceFreeVerify = await execFileAsync(zero, ["verify-projection", "--json", programGraphSourceFreePackage]).catch((error) => error);
|
|
const programGraphSourceFreeExport = JSON.parse((await execFileAsync(zero, ["export", "--json", programGraphSourceFreePackage])).stdout);
|
|
const programGraphSourceFreeVerifyAfter = JSON.parse((await execFileAsync(zero, ["verify-projection", "--json", programGraphSourceFreePackage])).stdout);
|
|
await mkdir(programGraphSourceFreeStdStrPackage, { recursive: true });
|
|
await writeZeroToml(programGraphSourceFreeStdStrPackage, {
|
|
package: { name: "program-graph-source-free-std-str", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "main.0" } },
|
|
});
|
|
await writeFile(`${programGraphSourceFreeStdStrPackage}/main.0`, await readFile("examples/std-str.0", "utf8"));
|
|
const programGraphSourceFreeStdStrSync = JSON.parse((await execFileAsync(zero, ["import", "--json", programGraphSourceFreeStdStrPackage])).stdout);
|
|
await rm(`${programGraphSourceFreeStdStrPackage}/main.0`, { force: true });
|
|
const programGraphSourceFreeStdStrCheckJson = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphSourceFreeStdStrPackage])).stdout);
|
|
const programGraphCrmApiCheckJson = JSON.parse((await execFileAsync(zero, ["check", "--json", "examples/crm-api"])).stdout);
|
|
const programGraphCrmApiStatusJson = JSON.parse((await execFileAsync(zero, ["status", "--json", "examples/crm-api"])).stdout);
|
|
const programGraphCrmApiBuildJson = JSON.parse((await execFileAsync(zero, ["build", "--json", "--out", programGraphCrmApiBuildPath, "examples/crm-api"])).stdout);
|
|
const programGraphCrmApiHealth = await execFileAsync(programGraphCrmApiBuildPath, ["GET /health\n\n"]);
|
|
const programGraphCrmApiAccounts = await execFileAsync(programGraphCrmApiBuildPath, ["GET /crm/accounts?tenant=demo\n\n"]);
|
|
const programGraphCrmApiDealUpdate = await execFileAsync(programGraphCrmApiBuildPath, ["POST /crm/deals/42/update\ncontent-type: application/json\n\n{\"stage\":\"won\"}"]);
|
|
const programGraphCrmApiMissing = await execFileAsync(programGraphCrmApiBuildPath, ["GET /missing\n\n"]);
|
|
const programGraphAuthoringInit = JSON.parse((await execFileAsync(zero, ["init", "--json", programGraphAuthoringPackage])).stdout);
|
|
const programGraphAuthoringProjectionExistsAfterInit = await fileExists(`${programGraphAuthoringPackage}/src/main.0`);
|
|
const programGraphAuthoringPatch = JSON.parse((await execFileAsync(zero, [
|
|
"patch",
|
|
"--json",
|
|
"--op",
|
|
"addMain",
|
|
"--op",
|
|
"addFunction name=\"add\" ret=\"i32\"",
|
|
"--op",
|
|
"addParam fn=\"add\" name=\"left\" type=\"i32\"",
|
|
"--op",
|
|
"addParam fn=\"add\" name=\"right\" type=\"i32\"",
|
|
"--op",
|
|
"addReturnBinary fn=\"add\" name=\"+\" left=\"left\" right=\"right\" type=\"i32\"",
|
|
"--op",
|
|
"addCheckWrite fn=\"main\" text=\"graph authoring ok\\n\"",
|
|
"--op",
|
|
"addTest name=\"addition works\" call=\"add\" arg0=\"40\" arg1=\"2\" expect=\"42\" type=\"i32\"",
|
|
], { cwd: programGraphAuthoringPackage })).stdout);
|
|
const programGraphAuthoringProjectionExistsAfterPatch = await fileExists(`${programGraphAuthoringPackage}/src/main.0`);
|
|
const programGraphAuthoringStatusMissing = JSON.parse((await execFileAsync(zero, ["status", "--json", programGraphAuthoringPackage])).stdout);
|
|
const programGraphAuthoringVerifyMissing = await execFileAsync(zero, ["verify-projection", "--json", programGraphAuthoringPackage]).catch((error) => error);
|
|
const programGraphAuthoringCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphAuthoringPackage])).stdout);
|
|
const programGraphAuthoringRun = await execFileAsync(zero, ["run", "--out", programGraphAuthoringRunPath, programGraphAuthoringPackage]);
|
|
const programGraphAuthoringTest = JSON.parse((await execFileAsync(zero, ["test", "--json", programGraphAuthoringPackage])).stdout);
|
|
const programGraphAuthoringExport = JSON.parse((await execFileAsync(zero, ["export", "--json", programGraphAuthoringPackage])).stdout);
|
|
const programGraphAuthoringProjectionText = await readFile(`${programGraphAuthoringPackage}/src/main.0`, "utf8");
|
|
const programGraphAuthoringVerifyAfter = JSON.parse((await execFileAsync(zero, ["verify-projection", "--json", programGraphAuthoringPackage])).stdout);
|
|
const programGraphAuthoringCheckAfter = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphAuthoringPackage])).stdout);
|
|
const programGraphAuthoringEditedText = programGraphAuthoringProjectionText.replace("graph authoring ok", "human edit ok");
|
|
await writeFile(`${programGraphAuthoringPackage}/src/main.0`, programGraphAuthoringEditedText);
|
|
const programGraphAuthoringStatusAfterHumanEdit = JSON.parse((await execFileAsync(zero, ["status", "--json", programGraphAuthoringPackage])).stdout);
|
|
const programGraphAuthoringImport = JSON.parse((await execFileAsync(zero, ["import", "--json", programGraphAuthoringPackage])).stdout);
|
|
const programGraphAuthoringCheckAfterHumanEdit = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphAuthoringPackage])).stdout);
|
|
const programGraphAuthoringRunAfterHumanEdit = await execFileAsync(zero, ["run", "--out", programGraphAuthoringRunAfterHumanEditPath, programGraphAuthoringPackage]);
|
|
const programGraphBuilderOpsInit = JSON.parse((await execFileAsync(zero, ["init", "--json", programGraphBuilderOpsPackage])).stdout);
|
|
const programGraphBuilderOpsPatch = JSON.parse((await execFileAsync(zero, [
|
|
"patch",
|
|
"--json",
|
|
"--op",
|
|
"addMain",
|
|
"--op",
|
|
"addLetLiteral fn=\"main\" name=\"message\" type=\"String\" value=\"graph value write ok\\n\"",
|
|
"--op",
|
|
"addCheckWriteValue fn=\"main\" value=\"message\" type=\"String\"",
|
|
"--op",
|
|
"addFunction name=\"add_twice\" ret=\"u32\"",
|
|
"--op",
|
|
"addParam fn=\"add_twice\" name=\"x\" type=\"u32\"",
|
|
"--op",
|
|
"addParam fn=\"add_twice\" name=\"y\" type=\"u32\"",
|
|
"--op",
|
|
"addLetBinary fn=\"add_twice\" name=\"first\" type=\"u32\" operator=\"+\" left=\"x\" right=\"y\"",
|
|
"--op",
|
|
"addLetBinary fn=\"add_twice\" name=\"total\" type=\"u32\" operator=\"+\" left=\"first\" right=\"y\"",
|
|
"--op",
|
|
"addReturnValue fn=\"add_twice\" value=\"total\" type=\"u32\"",
|
|
"--op",
|
|
"addTest name=\"add twice\" call=\"add_twice\" arg0=\"3\" arg1=\"2\" expect=\"7\" type=\"u32\"",
|
|
], { cwd: programGraphBuilderOpsPackage })).stdout);
|
|
const programGraphBuilderOpsProjectionExistsAfterPatch = await fileExists(`${programGraphBuilderOpsPackage}/src/main.0`);
|
|
const programGraphBuilderOpsQuery = JSON.parse((await execFileAsync(zero, ["query", "--json", programGraphBuilderOpsPackage])).stdout);
|
|
const programGraphBuilderOpsView = (await execFileAsync(zero, ["view", programGraphBuilderOpsPackage])).stdout;
|
|
const programGraphBuilderOpsCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphBuilderOpsPackage])).stdout);
|
|
const programGraphBuilderOpsTest = JSON.parse((await execFileAsync(zero, ["test", "--json", programGraphBuilderOpsPackage])).stdout);
|
|
const programGraphBuilderOpsRun = await execFileAsync(zero, ["run", "--out", programGraphBuilderOpsRunPath, programGraphBuilderOpsPackage]);
|
|
const programGraphBuilderOpsSync = JSON.parse((await execFileAsync(zero, ["export", "--json", programGraphBuilderOpsPackage])).stdout);
|
|
const programGraphBuilderOpsProjectionText = await readFile(`${programGraphBuilderOpsPackage}/src/main.0`, "utf8");
|
|
const programGraphLoopTestInit = JSON.parse((await execFileAsync(zero, ["init", "--json", programGraphLoopTestPackage])).stdout);
|
|
const programGraphLoopTestPatch = JSON.parse((await execFileAsync(zero, [
|
|
"patch",
|
|
"--json",
|
|
"--op",
|
|
"addMain",
|
|
"--op",
|
|
"addFunction name=\"count_to\" ret=\"u32\"",
|
|
"--op",
|
|
"addParam fn=\"count_to\" name=\"n\" type=\"u32\"",
|
|
"--op",
|
|
"addParam fn=\"count_to\" name=\"start\" type=\"u32\"",
|
|
"--op",
|
|
"addReturnBinary fn=\"count_to\" name=\"+\" left=\"n\" right=\"start\" type=\"u32\"",
|
|
], { cwd: programGraphLoopTestPackage })).stdout);
|
|
const programGraphLoopTestBodyQuery = JSON.parse((await execFileAsync(zero, ["query", "--json", programGraphLoopTestPackage])).stdout);
|
|
const programGraphLoopTestBodyPatchText = [
|
|
"zero-program-graph-patch v1",
|
|
`expect graphHash "${programGraphLoopTestBodyQuery.graphHash}"`,
|
|
"replaceFunctionBody count_to",
|
|
" var i u32 = start",
|
|
" while i < n",
|
|
" i = i + 1",
|
|
" return i",
|
|
"end",
|
|
"",
|
|
].join("\n");
|
|
const programGraphLoopTestBodyPatch = JSON.parse((await execFileAsync(zero, ["patch", "--json", programGraphLoopTestPackage, "--patch-text", programGraphLoopTestBodyPatchText])).stdout);
|
|
const programGraphLoopTestAddTest = JSON.parse((await execFileAsync(zero, [
|
|
"patch",
|
|
"--json",
|
|
"--op",
|
|
"addTest name=\"graph while assignment\" call=\"count_to\" arg0=\"4\" arg1=\"0\" expect=\"4\" type=\"u32\"",
|
|
], { cwd: programGraphLoopTestPackage })).stdout);
|
|
const programGraphLoopTestCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphLoopTestPackage])).stdout);
|
|
const programGraphLoopTestRun = JSON.parse((await execFileAsync(zero, ["test", "--json", programGraphLoopTestPackage])).stdout);
|
|
const programGraphLoopTestView = (await execFileAsync(zero, ["view", programGraphLoopTestPackage])).stdout;
|
|
const programGraphArrayLengthInit = JSON.parse((await execFileAsync(zero, ["init", "--json", programGraphArrayLengthPackage])).stdout);
|
|
const programGraphArrayLengthMainPatch = JSON.parse((await execFileAsync(zero, ["patch", "--json", "--op", "addMain", programGraphArrayLengthPackage])).stdout);
|
|
const programGraphArrayLengthRepeatBodyPath = `${outDir}/program-graph-array-length-repeat-body.0`;
|
|
await writeFile(programGraphArrayLengthRepeatBodyPath, 'var b: [64]u8 = [0_u8; 32]\ncheck world.out.write("unreachable\\n")\n');
|
|
const programGraphArrayLengthRepeatPatch = JSON.parse((await execFileAsync(zero, ["patch", "--json", "--replace-fn", "main", "--body-file", programGraphArrayLengthRepeatBodyPath, programGraphArrayLengthPackage]).catch((error) => error)).stdout);
|
|
const programGraphArrayLengthListBodyPath = `${outDir}/program-graph-array-length-list-body.0`;
|
|
await writeFile(programGraphArrayLengthListBodyPath, 'var b: [4]u8 = [1, 2]\ncheck world.out.write("unreachable\\n")\n');
|
|
const programGraphArrayLengthListPatch = JSON.parse((await execFileAsync(zero, ["patch", "--json", "--replace-fn", "main", "--body-file", programGraphArrayLengthListBodyPath, programGraphArrayLengthPackage]).catch((error) => error)).stdout);
|
|
const programGraphArrayLengthMatchingBodyPath = `${outDir}/program-graph-array-length-matching-body.0`;
|
|
await writeFile(programGraphArrayLengthMatchingBodyPath, 'var b: [4]u8 = [0_u8; 4]\nb[0] = 1\ncheck world.out.write("lengths agree\\n")\n');
|
|
const programGraphArrayLengthMatchingPatch = JSON.parse((await execFileAsync(zero, ["patch", "--json", "--replace-fn", "main", "--body-file", programGraphArrayLengthMatchingBodyPath, programGraphArrayLengthPackage])).stdout);
|
|
const programGraphArrayLengthCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphArrayLengthPackage])).stdout);
|
|
const programGraphBlockBodyInit = JSON.parse((await execFileAsync(zero, ["init", "--json", programGraphBlockBodyPackage])).stdout);
|
|
const programGraphBlockBodyMainPatch = JSON.parse((await execFileAsync(zero, [
|
|
"patch",
|
|
"--json",
|
|
"--op",
|
|
"addMain",
|
|
], { cwd: programGraphBlockBodyPackage })).stdout);
|
|
const programGraphBlockBodyMainQuery = JSON.parse((await execFileAsync(zero, ["query", "--json", programGraphBlockBodyPackage])).stdout);
|
|
const programGraphBlockBodyGreetingPatchText = [
|
|
"zero-program-graph-patch v1",
|
|
`expect graphHash "${programGraphBlockBodyMainQuery.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 programGraphBlockBodyGreetingPatch = JSON.parse((await execFileAsync(zero, ["patch", "--json", programGraphBlockBodyPackage, "--patch-text", programGraphBlockBodyGreetingPatchText])).stdout);
|
|
const programGraphBlockBodyBlocks = JSON.parse((await execFileAsync(zero, ["query", "--json", "--find", "Block", programGraphBlockBodyPackage])).stdout);
|
|
const programGraphBlockBodyThen = programGraphBlockBodyBlocks.matches.find((node) => node.kind === "Block" && node.name === "then");
|
|
assert(programGraphBlockBodyThen, "expected row-patched greeting body to expose a then block handle");
|
|
const programGraphBlockBodyPatchText = [
|
|
"zero-program-graph-patch v1",
|
|
`expect graphHash "${programGraphBlockBodyBlocks.graphHash}"`,
|
|
`replaceBlockBody ${programGraphBlockBodyThen.id}`,
|
|
" check world.out.write \"name + value: \"",
|
|
" check world.out.write name.value",
|
|
" check world.out.write \"\\n\"",
|
|
"end",
|
|
"",
|
|
].join("\n");
|
|
const programGraphBlockBodyDryRun = JSON.parse((await execFileAsync(zero, ["patch", "--json", "--check-only", programGraphBlockBodyPackage, "--patch-text", programGraphBlockBodyPatchText])).stdout);
|
|
const programGraphBlockBodyPatch = JSON.parse((await execFileAsync(zero, ["patch", "--json", programGraphBlockBodyPackage, "--patch-text", programGraphBlockBodyPatchText])).stdout);
|
|
const programGraphBlockBodyView = (await execFileAsync(zero, ["view", programGraphBlockBodyPackage])).stdout;
|
|
const programGraphBlockBodyCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphBlockBodyPackage])).stdout);
|
|
const programGraphBlockBodyRun = await execFileAsync(zero, ["run", "--out", programGraphBlockBodyRunPath, programGraphBlockBodyPackage, "--", "Ada"]);
|
|
const programGraphAuthoringCliInit = JSON.parse((await execFileAsync(zero, ["init", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliProjectionExistsAfterInit = await fileExists(`${programGraphAuthoringCliPackage}/src/main.0`);
|
|
const programGraphAuthoringCliPatch = JSON.parse((await execFileAsync(zero, [
|
|
"patch",
|
|
"--json",
|
|
"--op",
|
|
"addMain",
|
|
"--op",
|
|
"addFunction name=\"add_u32\" ret=\"u32\"",
|
|
"--op",
|
|
"addParam fn=\"add_u32\" name=\"x\" type=\"u32\"",
|
|
"--op",
|
|
"addParam fn=\"add_u32\" name=\"y\" type=\"u32\"",
|
|
"--op",
|
|
"addReturnBinary fn=\"add_u32\" name=\"+\" left=\"x\" right=\"y\" type=\"u32\"",
|
|
], { cwd: programGraphAuthoringCliPackage })).stdout);
|
|
const programGraphAuthoringCliBodyQuery = JSON.parse((await execFileAsync(zero, ["query", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliBodyPatchText = [
|
|
"zero-program-graph-patch v1",
|
|
`expect graphHash "${programGraphAuthoringCliBodyQuery.graphHash}"`,
|
|
"replaceFunctionBody main",
|
|
" let x Maybe<u32> = std.args.parseU32 1",
|
|
" let y Maybe<u32> = std.args.parseU32 2",
|
|
" if x.has && y.has",
|
|
" let result u32 = add_u32 x.value y.value",
|
|
" var out [10]u8 = repeat 0_u8 10",
|
|
" let text Maybe<Span<u8>> = std.fmt.u32 out result",
|
|
" if text.has",
|
|
" check world.out.write text.value",
|
|
" check world.out.write \"\\n\"",
|
|
" else",
|
|
" check world.err.write \"usage: zero run . -- <x> <y>\\n\"",
|
|
"end",
|
|
"",
|
|
].join("\n");
|
|
const programGraphAuthoringCliBodyPatch = JSON.parse((await execFileAsync(zero, ["patch", "--json", programGraphAuthoringCliPackage, "--patch-text", programGraphAuthoringCliBodyPatchText])).stdout);
|
|
const programGraphAuthoringCliProjectionExistsAfterPatch = await fileExists(`${programGraphAuthoringCliPackage}/src/main.0`);
|
|
const programGraphAuthoringCliStaleAddPatch = JSON.parse((await execFileAsync(zero, [
|
|
"patch",
|
|
"--json",
|
|
"--op",
|
|
"addFunction name=\"add\" ret=\"i32\"",
|
|
"--op",
|
|
"addParam fn=\"add\" name=\"x\" type=\"i32\"",
|
|
"--op",
|
|
"addParam fn=\"add\" name=\"y\" type=\"i32\"",
|
|
"--op",
|
|
"addReturnBinary fn=\"add\" name=\"+\" left=\"x\" right=\"y\" type=\"i32\"",
|
|
"--op",
|
|
"addTest name=\"add works\" call=\"add\" arg0=\"40\" arg1=\"2\" expect=\"42\" type=\"i32\"",
|
|
], { cwd: programGraphAuthoringCliPackage })).stdout);
|
|
const programGraphAuthoringCliFindAdd = JSON.parse((await execFileAsync(zero, ["query", "--json", "--find", "add", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliNodeAdd = JSON.parse((await execFileAsync(zero, ["query", "--json", "--node", "#fn_add", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliCleanupPatch = JSON.parse((await execFileAsync(zero, [
|
|
"patch",
|
|
"--json",
|
|
"--op",
|
|
"delete node=\"#fn___zero_test_0\"",
|
|
"--op",
|
|
"delete node=\"#fn_add\"",
|
|
"--op",
|
|
"addTest name=\"add_u32 works\" call=\"add_u32\" arg0=\"40\" arg1=\"2\" expect=\"42\" type=\"u32\"",
|
|
], { cwd: programGraphAuthoringCliPackage })).stdout);
|
|
const programGraphAuthoringCliCallsText = (await execFileAsync(zero, ["query", "--fn", "main", "--calls", "std", programGraphAuthoringCliPackage])).stdout;
|
|
const programGraphAuthoringCliRefsText = (await execFileAsync(zero, ["query", "--refs", "add_u32", programGraphAuthoringCliPackage])).stdout;
|
|
const programGraphAuthoringCliQuery = JSON.parse((await execFileAsync(zero, ["query", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliGraphBuild = await execFileAsync(zero, ["build", "--out", programGraphAuthoringCliGraphBuildPath, programGraphAuthoringCliPackage]);
|
|
const programGraphAuthoringCliBuild = await execFileAsync(zero, ["build", "--out", programGraphAuthoringCliBuildPath, programGraphAuthoringCliPackage]);
|
|
const programGraphAuthoringCliTest = JSON.parse((await execFileAsync(zero, ["test", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliGraphTest = await execFileAsync(zero, ["test", programGraphAuthoringCliPackage]);
|
|
const programGraphAuthoringCliRun = await execFileAsync(zero, ["run", "--out", programGraphAuthoringCliRunPath, programGraphAuthoringCliPackage, "--", "40", "2"]);
|
|
const programGraphAuthoringCliGraphRun = await execFileAsync(zero, ["run", programGraphAuthoringCliPackage, "--", "7", "8"]);
|
|
const programGraphAuthoringCliSize = JSON.parse((await execFileAsync(zero, ["size", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliSync = JSON.parse((await execFileAsync(zero, ["export", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliProjectionText = await readFile(`${programGraphAuthoringCliPackage}/src/main.0`, "utf8");
|
|
const programGraphAuthoringCliEditedProjectionText = programGraphAuthoringCliProjectionText.replace("usage: zero run . -- <x> <y>\\n", "usage: zero run . -- <left> <right>\\n");
|
|
await writeFile(`${programGraphAuthoringCliPackage}/src/main.0`, programGraphAuthoringCliEditedProjectionText);
|
|
const programGraphAuthoringCliStatusAfterHumanEdit = JSON.parse((await execFileAsync(zero, ["status", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliImport = JSON.parse((await execFileAsync(zero, ["import", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliQueryAfterHumanEdit = JSON.parse((await execFileAsync(zero, ["query", "--json", "--calls", "std", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliFindUsageText = (await execFileAsync(zero, ["query", "--find", "usage", programGraphAuthoringCliPackage])).stdout;
|
|
const programGraphAuthoringCliVerifyAfterHumanEdit = JSON.parse((await execFileAsync(zero, ["verify-projection", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliCheckAfterHumanEdit = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliTestAfterHumanEdit = JSON.parse((await execFileAsync(zero, ["test", "--json", programGraphAuthoringCliPackage])).stdout);
|
|
const programGraphAuthoringCliRunAfterHumanEdit = await execFileAsync(zero, ["run", "--out", programGraphAuthoringCliRunAfterHumanEditPath, programGraphAuthoringCliPackage, "--", "5", "6"]);
|
|
await mkdir(`${programGraphSourceFreeCImportPackage}/src`, { recursive: true });
|
|
await mkdir(`${programGraphSourceFreeCImportPackage}/vendor/include`, { recursive: true });
|
|
await writeZeroToml(programGraphSourceFreeCImportPackage, {
|
|
package: { name: "program-graph-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" },
|
|
},
|
|
},
|
|
});
|
|
await writeFile(`${programGraphSourceFreeCImportPackage}/vendor/include/zero_ext.h`, "int zero_ext_add(int a, int b);\n");
|
|
await writeFile(`${programGraphSourceFreeCImportPackage}/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 programGraphSourceFreeCImportSync = JSON.parse((await execFileAsync(zero, ["import", "--json", programGraphSourceFreeCImportPackage])).stdout);
|
|
await rm(`${programGraphSourceFreeCImportPackage}/src`, { recursive: true, force: true });
|
|
const programGraphSourceFreeCImportCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphSourceFreeCImportPackage])).stdout);
|
|
const programGraphSourceFreeCImportRun = await execFileAsync(zero, ["run", "--out", programGraphSourceFreeCImportRunPath, programGraphSourceFreeCImportPackage]);
|
|
await mkdir(programGraphSourceFreeCImportCwdPackage, { recursive: true });
|
|
await writeZeroToml(programGraphSourceFreeCImportCwdPackage, {
|
|
package: { name: "program-graph-source-free-c-import-cwd", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "src/main.0" } },
|
|
});
|
|
const programGraphSourceFreeCImportCwdBuild = JSON.parse((await execFileAsync(resolve(zero), [
|
|
"build",
|
|
"--json",
|
|
"--out",
|
|
resolve(programGraphSourceFreeCImportCwdBuildPath),
|
|
resolve(programGraphSourceFreeCImportPackage),
|
|
], { cwd: programGraphSourceFreeCImportCwdPackage })).stdout);
|
|
await mkdir(programGraphIdentityMismatchPackage, { recursive: true });
|
|
await writeZeroToml(programGraphIdentityMismatchPackage, {
|
|
package: { name: "program-graph-wrong-package", version: "9.9.9" },
|
|
targets: { cli: { kind: "exe", main: "hello.0" } },
|
|
});
|
|
await writeFile(`${programGraphIdentityMismatchPackage}/zero.graph`, programGraphSourceFixtureStoreBytes);
|
|
const programGraphIdentityMismatchCheck = await execFileAsync(zero, ["check", "--json", programGraphIdentityMismatchPackage]).catch((error) => error);
|
|
const programGraphIdentityMismatchSize = await execFileAsync(zero, ["size", "--json", programGraphIdentityMismatchPackage]).catch((error) => error);
|
|
await mkdir(programGraphMissingPackageNamePackage, { recursive: true });
|
|
await writeZeroToml(programGraphMissingPackageNamePackage, {
|
|
targets: { cli: { kind: "exe", main: "hello.0" } },
|
|
});
|
|
await writeFile(`${programGraphMissingPackageNamePackage}/zero.graph`, programGraphSourceFixtureStoreBytes);
|
|
const programGraphMissingPackageNameCheck = await execFileAsync(zero, ["check", "--json", programGraphMissingPackageNamePackage]).catch((error) => error);
|
|
await mkdir(programGraphBadProjectionPackage, { recursive: true });
|
|
await writeFile(`${programGraphBadProjectionPackage}/zero.toml`, await readFile(`${programGraphSourceFixturePackage}/zero.toml`, "utf8"));
|
|
await writeFile(`${programGraphBadProjectionPackage}/hello.0`, programGraphSourceFixtureText);
|
|
await execFileAsync(zero, ["import", "--format", "text", programGraphBadProjectionPackage]);
|
|
const programGraphBadProjectionStoreText = await readFile(`${programGraphBadProjectionPackage}/zero.graph`, "utf8");
|
|
await writeFile(`${programGraphBadProjectionPackage}/zero.graph`, programGraphBadProjectionStoreText.replace(
|
|
/^projection path:"hello\.0" text:.*$/m,
|
|
`projection path:"hello.0" text:${JSON.stringify("pub fn broken( {\n")}`,
|
|
));
|
|
const programGraphBadProjectionStatus = JSON.parse((await execFileAsync(zero, ["status", "--json", programGraphBadProjectionPackage])).stdout);
|
|
const programGraphBadProjectionCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphBadProjectionPackage])).stdout);
|
|
const programGraphBadProjectionSync = await execFileAsync(zero, ["export", "--json", programGraphBadProjectionPackage]).catch((error) => error);
|
|
await mkdir(programGraphMissingStorePackage, { recursive: true });
|
|
await writeZeroToml(programGraphMissingStorePackage, {
|
|
package: { name: "program-graph-missing-store", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "main.0" } },
|
|
});
|
|
await writeFile(`${programGraphMissingStorePackage}/main.0`, "pub fn main() -> i32 { return 0 }\n");
|
|
const programGraphMissingStoreCheck = await execFileAsync(zero, ["check", "--json", programGraphMissingStorePackage]).catch((error) => error);
|
|
await mkdir(programGraphInvalidStorePackage, { recursive: true });
|
|
await writeZeroToml(programGraphInvalidStorePackage, {
|
|
package: { name: "program-graph-invalid-store", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "main.0" } },
|
|
});
|
|
await writeFile(`${programGraphInvalidStorePackage}/main.0`, "pub fn main() -> i32 { return 0 }\n");
|
|
await writeFile(`${programGraphInvalidStorePackage}/zero.graph`, "not a repository graph\n");
|
|
const programGraphInvalidStoreCheck = await execFileAsync(zero, ["check", "--json", programGraphInvalidStorePackage]).catch((error) => error);
|
|
await mkdir(programGraphSourceFixtureDriftPackage, { recursive: true });
|
|
await writeFile(`${programGraphSourceFixtureDriftPackage}/zero.toml`, await readFile(`${programGraphSourceFixturePackage}/zero.toml`, "utf8"));
|
|
await writeFile(`${programGraphSourceFixtureDriftPackage}/zero.graph`, programGraphSourceFixtureStoreBytes);
|
|
await writeFile(`${programGraphSourceFixtureDriftPackage}/hello.0`, programGraphSourceFixtureText.replace("hello from zero", "hello from drift"));
|
|
const programGraphSourceFixtureDriftVerify = await execFileAsync(zero, ["verify-projection", "--json", programGraphSourceFixtureDriftPackage]).catch((error) => error);
|
|
const programGraphSourceFixtureDriftCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", programGraphSourceFixtureDriftPackage])).stdout);
|
|
const programGraphSourceFixtureDriftVerifyAfterRefresh = JSON.parse((await execFileAsync(zero, ["verify-projection", "--json", programGraphSourceFixtureDriftPackage])).stdout);
|
|
await mkdir(programGraphTargetWebbitsPackage, { recursive: true });
|
|
await writeFile(`${programGraphTargetWebbitsPackage}/zero.toml`, await readFile("conformance/packages/target-webbits/zero.toml", "utf8"));
|
|
await mkdir(`${programGraphTargetIncompatiblePackage}/src`, { recursive: true });
|
|
await writeZeroToml(programGraphTargetIncompatiblePackage, {
|
|
package: { name: "program-graph-target-incompatible", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "src/main.0" } },
|
|
dependencies: { "target-webbits": { path: "../program-graph-target-webbits", version: "0.1.0", targets: ["win32-x64.exe"] } },
|
|
});
|
|
await writeFile(`${programGraphTargetIncompatiblePackage}/src/main.0`, `pub fn main(world: World) -> Void raises {
|
|
check world.out.write("target incompatible\\n")
|
|
}
|
|
`);
|
|
const programGraphTargetIncompatibleSync = JSON.parse((await execFileAsync(zero, ["import", "--json", programGraphTargetIncompatiblePackage])).stdout);
|
|
const programGraphTargetIncompatibleCheck = await execFileAsync(zero, ["check", "--json", "--target", "linux-musl-x64", programGraphTargetIncompatiblePackage]).catch((error) => error);
|
|
await mkdir(programGraphTargetCapabilityPackage, { recursive: true });
|
|
await writeZeroToml(programGraphTargetCapabilityPackage, {
|
|
package: { name: "program-graph-target-capability", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "main.0" } },
|
|
});
|
|
await writeFile(`${programGraphTargetCapabilityPackage}/main.0`, `pub fn main(world: World) -> Void raises {
|
|
let fs: Fs = std.fs.host()
|
|
if std.fs.writeFile(fs, ".zero/out/program-graph-target-capability.txt", "ok\\n") {
|
|
check world.out.write("ok\\n")
|
|
}
|
|
}
|
|
`);
|
|
const programGraphTargetCapabilitySync = JSON.parse((await execFileAsync(zero, ["import", "--json", programGraphTargetCapabilityPackage])).stdout);
|
|
const programGraphTargetCapabilityCheck = await execFileAsync(zero, ["check", "--json", "--target", "linux-arm64", programGraphTargetCapabilityPackage]).catch((error) => error);
|
|
await execFileAsync(zero, ["dump", "--out", programGraphRichPath, "conformance/native/pass/open-ended-slices.0"]);
|
|
await execFileAsync(zero, ["view", "--out", programGraphRichViewPath, programGraphRichPath]);
|
|
const programGraphRichView = await readFile(programGraphRichViewPath, "utf8");
|
|
await execFileAsync(zero, ["dump", "--out", programGraphCharPath, "conformance/native/pass/float-char-casts.0"]);
|
|
await execFileAsync(zero, ["view", "--out", programGraphCharViewPath, programGraphCharPath]);
|
|
const programGraphCharView = await readFile(programGraphCharViewPath, "utf8");
|
|
const programGraphViewCoverage = [
|
|
["compile-time-v1", "examples/compile-time-v1.0", [/const field_type: String = meta fieldType\(Point, "x"\)/, /readGate<enabled, selected>\(&gate\)/]],
|
|
["array-repeat-literal", "conformance/native/pass/array-repeat-literal.0", [/\[7_u8; 8\]/, /\[0_u8; 16\]/]],
|
|
["explicit-casts", "conformance/native/pass/explicit-casts.0", [/let byte: u8 = big as u8/, /let offset: isize = small as isize/]],
|
|
["generic-multi-specialization", "conformance/native/pass/generic-multi-specialization.0", [/first<i32, u8>\(21, 7\)/, /second<i32, u8>\(a, 6\)/]],
|
|
["generic-shape-nested-defaults-alias", "conformance/native/pass/generic-shape-nested-defaults-alias.0", [/Box \{ value: 42 \}/, /Slot \{ item: 7_u8 \}/]],
|
|
["float-primitives", "conformance/native/pass/float-primitives.0", [/let precise: f64 = 1\.0e-3/]],
|
|
["meta-typed-target-type", "conformance/native/pass/meta-typed-target-type.0", [/const computed: usize = meta 2 \+ 2/]],
|
|
["nested-lvalues", "conformance/native/pass/nested-lvalues.0", [/Point \{ x: 3, y: 4 \}/, /Point \{ x: 5, y: 6 \}/]],
|
|
["radix-suffix-literals", "conformance/native/pass/radix-suffix-literals.0", [/return 0x20_usize/, /1_024_usize/, /0x2a_u8/]],
|
|
["test-blocks", "conformance/native/pass/test-blocks.0", [/test "addition works"/]],
|
|
["type-alias-basic", "conformance/native/pass/type-alias-basic.0", [/let count: ByteCount = 4_usize/]],
|
|
["c-abi-export", "conformance/native/pass/c-abi-export.0", [/extern type CPoint/, /export c fn zero_add\(a: i32, b: i32\) -> i32/]],
|
|
["const-layout", "conformance/native/pass/const-layout.0", [/extern type CPoint/, /packed type Header/]],
|
|
["c-header-import", "conformance/check/pass/c-header-import.0", [/extern c "conformance\/c\/simple\.h" as c/]],
|
|
["constructors-defaults", "conformance/native/pass/constructors-defaults.0", [/FixedVec\.init<u8, 4>/]],
|
|
["direct-call-add", "examples/direct-call-add.0", [/export c fn main\(a: i32, b: i32\) -> i32/]],
|
|
["generic-static-explicit-shadowing", "conformance/check/pass/generic-static-explicit-shadowing.0", [/Helper\.needsSame<N>\(left, right\)/]],
|
|
["systems-package", "examples/systems-package", [/use std\.codec/, /pub fn main\(world: World\) -> Void raises/]],
|
|
["std-math", "examples/std-math.0", [/pub fn main\(world: World\) -> Void raises/, /std\.math\.minU32\(8, 3\)/]],
|
|
];
|
|
for (const [name, fixture, patterns] of programGraphViewCoverage) {
|
|
const graphPath = `${outDir}/${name}.program-graph`;
|
|
const viewPath = `${outDir}/${name}.graph-view.0`;
|
|
await rm(graphPath, { force: true });
|
|
await rm(viewPath, { force: true });
|
|
await execFileAsync(zero, ["dump", "--out", graphPath, fixture]);
|
|
await execFileAsync(zero, ["view", "--out", viewPath, graphPath]);
|
|
const view = await readFile(viewPath, "utf8");
|
|
for (const pattern of patterns) assert.match(view, pattern);
|
|
assert.doesNotMatch(view, /fn __zero_test_/);
|
|
if (name === "systems-package") {
|
|
assert.doesNotMatch(view, /^use (helpers|types)$/m);
|
|
await execFileAsync(zero, ["import", "--format", "binary", "--out", graphSidecarPath(viewPath), viewPath]);
|
|
assert.equal((await execFileAsync(zero, ["check", viewPath])).stdout, "ok\n");
|
|
}
|
|
if (name === "std-math") assert.doesNotMatch(view, /fn __zero_std_/);
|
|
}
|
|
for (const fixture of [
|
|
"conformance/native/pass/open-ended-slices.0",
|
|
"conformance/native/pass/float-char-casts.0",
|
|
"conformance/check/pass/call-resolution-edge-cases.0",
|
|
"conformance/native/pass/match-payload-binding.0",
|
|
"conformance/native/pass/match-scalar-guards.0",
|
|
"conformance/native/pass/rescue-check.0",
|
|
"examples/result-choice.0",
|
|
"examples/compile-time-v1.0",
|
|
"examples/config-shape.0",
|
|
"examples/direct-enum-match.0",
|
|
"conformance/native/pass/test-blocks.0",
|
|
"examples/std-math.0",
|
|
"examples/systems-package",
|
|
"std/math.0",
|
|
"std/path.0",
|
|
"std/str.0",
|
|
]) {
|
|
const roundtrip = JSON.parse((await execFileAsync(zero, ["roundtrip", "--json", fixture])).stdout);
|
|
assert.equal(roundtrip.ok, true);
|
|
assert.equal(roundtrip.semanticStable, true);
|
|
assert.equal(roundtrip.roundtripModuleIdentity, roundtrip.moduleIdentity);
|
|
assert.equal(roundtrip.comparison.ok, true);
|
|
assert.deepEqual(roundtrip.semanticCounts.original, roundtrip.semanticCounts.roundtrip);
|
|
}
|
|
const stdPathRecursiveView = (await execFileAsync(zero, ["view", "conformance/native/pass/std-path-io-breadth.0"])).stdout;
|
|
assert.match(stdPathRecursiveView, /std\.path\.relative\(rel_buf, "src", "src\/main\.0"\)/);
|
|
assert.doesNotMatch(stdPathRecursiveView, /__zero_std_/);
|
|
assert.equal(programGraphBody.schemaVersion, 1);
|
|
assert.equal(programGraphBody.canonicalSource, false);
|
|
assert.equal(programGraphBody.moduleIdentity, "module:hello");
|
|
assert.deepEqual(programGraphBodyAgain, programGraphBody);
|
|
assert.equal(programGraphBody.resolution.state, "resolved");
|
|
assert.equal(programGraphBody.resolution.ok, true);
|
|
assert(programGraphBody.resolution.scopes.some((scope) => scope.kind === "module" && scope.name === "hello" && scope.bindings.some((binding) => binding.kind === "function" && binding.name === "main")));
|
|
assert(programGraphBody.resolution.references.some((reference) => reference.kind === "identifier" && reference.name === "world" && reference.targetKind === "param" && reference.symbolId === "symbol:hello::value.main/param.world"));
|
|
assert(programGraphBody.resolution.references.some((reference) => reference.kind === "call" && reference.qualifiedName === "world.out.write" && reference.targetKind === "member"));
|
|
assert.equal(programGraphBody.semantics.state, "typed-facts");
|
|
assert.equal(programGraphBody.semantics.ok, true);
|
|
assert(programGraphBody.semantics.functions.some((item) => item.name === "main" && item.returnType === "Void" && item.fallible === true && item.sourceRange.path === "hello.0" && item.params.some((param) => param.name === "world" && param.type === "World" && param.sourceRange.path === "hello.0")));
|
|
assert(programGraphBody.semantics.calls.some((item) => item.qualifiedName === "world.out.write" && item.returnType === "Void" && item.fallible === true && item.checked === true && item.sourceRange.path === "hello.0" && item.contract.kind === "worldStreamWrite" && item.contract.capability === "io" && item.contract.targetSupport === "world-io" && item.contract.repair?.id === "check-fallible-call" && item.resolution.targetKind === "member" && item.resolution.symbolId === "symbol:hello::value.main/param.world"));
|
|
assert(programGraphBody.semantics.ownership.some((item) => item.name === "world" && item.ownership === "resource-handle" && item.resource === true));
|
|
assert(programGraphBody.semantics.resources.some((item) => item.kind === "capabilityUse" && item.resourceKind === "world-io" && item.qualifiedName === "world.out.write"));
|
|
assert(programGraphBody.semantics.targetRequirements.some((item) => item.qualifiedName === "world.out.write" && item.capability === "io" && item.targetSupport === "world-io"));
|
|
assert(programGraphBody.semantics.repairs.some((item) => item.qualifiedName === "world.out.write" && item.requiresCheck === false && item.repair.id === "check-fallible-call"));
|
|
assert.equal(programGraphDumpAgain, programGraphDump);
|
|
assert.equal(programGraphDumpOut.stdout, "");
|
|
assert.equal(programGraphDumpFile, programGraphDump);
|
|
assert.deepEqual(programGraphDumpOutJson, programGraphDumpJson);
|
|
assert.equal(programGraphDumpJsonFile, programGraphDump);
|
|
assert.equal(programGraphValidate.stdout, "program graph ok\n");
|
|
assert.equal(programGraphDumpJsonValidate.stdout, "program graph ok\n");
|
|
assert.equal(programGraphCanonicalFile, programGraphDump);
|
|
assert.equal(programGraphValidateJson.ok, true);
|
|
assert.equal(programGraphValidateJson.moduleIdentity, "module:hello");
|
|
assert.equal(programGraphValidateJson.graphHash, programGraphBody.graphHash);
|
|
assert.equal(programGraphValidateJson.saved.path, programGraphCanonicalPath);
|
|
assert.equal(programGraphViewAgain, programGraphView);
|
|
assert.equal(programGraphViewOut.stdout, "");
|
|
assert.equal(programGraphViewFile, programGraphView);
|
|
assert.equal(programGraphViewJson.ok, true);
|
|
assert.equal(programGraphViewJson.canonicalSource, false);
|
|
assert.equal(programGraphViewJson.moduleIdentity, "module:hello");
|
|
assert.equal(programGraphViewJson.graphHash, programGraphBody.graphHash);
|
|
assert.equal(programGraphViewJson.view, programGraphView);
|
|
assert.equal(programGraphViewOutJson.ok, true);
|
|
assert.equal(programGraphViewOutJson.saved.path, programGraphViewPath);
|
|
assert.equal(programGraphViewOutJson.view, null);
|
|
assert.equal(programGraphRoundtrip.stdout, "program graph roundtrip ok\n");
|
|
assert.equal(programGraphRoundtripJson.ok, true);
|
|
assert.equal(programGraphRoundtripJson.canonicalSource, false);
|
|
assert.equal(programGraphRoundtripJson.semanticStable, true);
|
|
assert.equal(programGraphRoundtripJson.lowering, "direct-program-graph");
|
|
assert.equal(programGraphRoundtripJson.moduleIdentity, "module:hello");
|
|
assert.equal(programGraphRoundtripJson.roundtripModuleIdentity, "module:hello");
|
|
assert.equal(programGraphRoundtripJson.originalGraphHash, programGraphBody.graphHash);
|
|
assert.equal(programGraphRoundtripJson.roundtripGraphHash, programGraphBody.graphHash);
|
|
assert.deepEqual(programGraphRoundtripJson.semanticCounts.original, programGraphRoundtripJson.semanticCounts.roundtrip);
|
|
assert.equal(programGraphRoundtripJson.comparison.ok, true);
|
|
assert.equal(programGraphRoundtripJson.view, null);
|
|
assert.equal(programGraphArtifactRoundtrip.stdout, "program graph roundtrip ok\n");
|
|
assert.equal(programGraphArtifactRoundtripJson.ok, true);
|
|
assert.equal(programGraphArtifactRoundtripJson.artifact, programGraphDumpPath);
|
|
assert.equal(programGraphArtifactRoundtripJson.semanticStable, true);
|
|
assert.equal(programGraphArtifactRoundtripJson.lowering, "direct-program-graph");
|
|
assert.equal(programGraphArtifactRoundtripJson.originalGraphHash, programGraphBody.graphHash);
|
|
assert.equal(programGraphArtifactRoundtripJson.roundtripGraphHash, programGraphBody.graphHash);
|
|
assert.equal(programGraphArtifactRoundtripJson.saved.path, programGraphArtifactRoundtripPath);
|
|
assert.equal(programGraphArtifactRoundtripJson.saved.kind, "program-graph");
|
|
assert.equal(programGraphArtifactRoundtripJson.view, null);
|
|
assert.equal(await readFile(programGraphArtifactRoundtripPath, "utf8"), programGraphDump);
|
|
assert.equal(programGraphSourceFixtureText, await readFile("examples/hello.0", "utf8"));
|
|
assert.equal(programGraphSourceFixturePackageCheckJson.ok, true);
|
|
assert.equal(programGraphSourceFixturePackageCheckJson.sourceFile, programGraphSourceFixtureStorePath);
|
|
assert.equal(programGraphSourceFixturePackageCheckJson.package.name, "program-graph-fixture");
|
|
assert.equal(programGraphSourceFixturePackageCheckJson.graph.artifact, programGraphSourceFixtureStorePath);
|
|
assert.equal(programGraphSourceFixturePackageCheckJson.graph.canonicalSource, false);
|
|
assert.equal(programGraphSourceFixturePackageCheckJson.graph.moduleIdentity, "package:program-graph-fixture@0.1.0");
|
|
assert.match(programGraphSourceFixturePackageCheckJson.graph.graphHash, /^graph:[0-9a-f]{16}$/);
|
|
assert.equal(programGraphSourceFixturePackageCheckJson.graph.lowering, "graph-native-check");
|
|
assert.equal(programGraphSourceFixturePackageStatusJson.store.encoding, "binary");
|
|
assert.equal(programGraphSourceFixturePackageStatusJson.storage.encoding, "single-file-binary");
|
|
assertRepositoryGraphNativeCheck(programGraphSourceFixturePackageCheckJson);
|
|
assert.equal(programGraphSourceFixturePackageRun.stdout, "hello from zero\n");
|
|
assert.equal(programGraphSourceFreeCheckJson.ok, true);
|
|
assert.equal(programGraphSourceFreeCheckJson.sourceFile, `${programGraphSourceFreePackage}/zero.graph`);
|
|
assert.equal(programGraphSourceFreeCheckJson.graph.artifact, `${programGraphSourceFreePackage}/zero.graph`);
|
|
assert.equal(programGraphSourceFreeCheckJson.graph.sourceProjectionState, "missing");
|
|
assertRepositoryGraphNativeCheck(programGraphSourceFreeCheckJson, "missing");
|
|
assertProgramGraphCompilerInput(programGraphSourceFreeCheckJson, `${programGraphSourceFreePackage}/zero.graph`);
|
|
assertSourceGraph(programGraphSourceFreeSizeJson, `${programGraphSourceFreePackage}/zero.graph`, "package:program-graph-fixture@0.1.0", "mapped-final-mir", false, "missing");
|
|
assertProgramGraphCompilerInput(programGraphSourceFreeSizeJson, `${programGraphSourceFreePackage}/zero.graph`);
|
|
assert.equal(programGraphSourceFreeBuildJson.sourceFile, `${programGraphSourceFreePackage}/zero.graph`);
|
|
assertSourceGraph(programGraphSourceFreeBuildJson, `${programGraphSourceFreePackage}/zero.graph`, "package:program-graph-fixture@0.1.0", "mapped-final-mir", false, "missing");
|
|
assertProgramGraphCompilerInput(programGraphSourceFreeBuildJson, `${programGraphSourceFreePackage}/zero.graph`);
|
|
assert(programGraphSourceFreeMappedMirCachePath.endsWith(".zmir"), "repository graph build should report a mapped MIR cache path");
|
|
assert.equal(existsSync(programGraphSourceFreeMappedMirCachePath), true, "repository graph build should write a mapped MIR cache");
|
|
assert.equal(programGraphSourceFreeRun.stdout, "hello from zero\n");
|
|
assert.equal(programGraphSourceFreeTestJson.ok, true);
|
|
assertSourceGraph(programGraphSourceFreeTestJson, `${programGraphSourceFreePackage}/zero.graph`, "package:program-graph-fixture@0.1.0", "direct-program-graph", false, "missing");
|
|
assert.equal(programGraphSourceFreeTestJson.testBackend, "direct-program-graph");
|
|
assert.equal(programGraphSourceFreeTestJson.testDiscovery.mode, "package-graph");
|
|
assertSourceGraph(programGraphSourceFreeMemJson, `${programGraphSourceFreePackage}/zero.graph`, "package:program-graph-fixture@0.1.0", "mapped-final-mir", false, "missing");
|
|
assertProgramGraphCompilerInput(programGraphSourceFreeMemJson, `${programGraphSourceFreePackage}/zero.graph`);
|
|
assert.notEqual(programGraphSourceFreeVerify.code, 0);
|
|
const programGraphSourceFreeVerifyBody = JSON.parse(programGraphSourceFreeVerify.stdout);
|
|
assert.equal(programGraphSourceFreeVerifyBody.diagnostics[0].code, "RGP006");
|
|
assert.equal(programGraphSourceFreeVerifyBody.diagnostics[0].actual, "missing source projection file");
|
|
assert.match(programGraphSourceFreeVerifyBody.repairCommands.join("\n"), /zero export/);
|
|
assert.equal(programGraphSourceFreeExport.ok, true);
|
|
assert.deepEqual(programGraphSourceFreeExport.changedPaths, [`${programGraphSourceFreePackage}/hello.0`]);
|
|
assert.equal(await readFile(`${programGraphSourceFreePackage}/hello.0`, "utf8"), programGraphSourceFixtureText);
|
|
assert.equal(programGraphSourceFreeVerifyAfter.ok, true);
|
|
assert.equal(programGraphSourceFreeVerifyAfter.repositoryGraph.projectionValidity, "clean");
|
|
assert.equal(programGraphSourceFreeStdStrSync.ok, true);
|
|
assert.equal(programGraphSourceFreeStdStrCheckJson.ok, true);
|
|
assertSourceGraph(programGraphSourceFreeStdStrCheckJson, `${programGraphSourceFreeStdStrPackage}/zero.graph`, "package:program-graph-source-free-std-str@0.1.0", "graph-native-check", false, "missing");
|
|
assertProgramGraphCompilerInput(programGraphSourceFreeStdStrCheckJson, `${programGraphSourceFreeStdStrPackage}/zero.graph`);
|
|
assertRepositoryGraphNativeCheck(programGraphSourceFreeStdStrCheckJson, "missing");
|
|
assert.equal(programGraphSourceFreeStdStrCheckJson.targetReadiness.ok, true);
|
|
assert.equal(programGraphSourceFreeStdStrCheckJson.targetReadiness.diagnostics.length, 0);
|
|
assert(programGraphSourceFreeStdStrCheckJson.graphCompiler.semanticFacts.calls.some((call) => call.qualifiedName === "std.str.reverse" && call.contract.kind === "stdlib" && call.resolution.targetKind === "stdlib" && call.returnType === "Maybe<Span<u8>>"));
|
|
assert.equal(programGraphCrmApiCheckJson.ok, true);
|
|
assert.equal(programGraphCrmApiStatusJson.store.encoding, "binary");
|
|
assert.equal(programGraphCrmApiStatusJson.storage.encoding, "single-file-binary");
|
|
assert.equal(programGraphCrmApiStatusJson.repositoryGraph.projectionValidity, "clean");
|
|
assert.equal(programGraphCrmApiCheckJson.sourceFile, "examples/crm-api/zero.graph");
|
|
assertSourceGraph(programGraphCrmApiCheckJson, "examples/crm-api/zero.graph", "package:crm-api@0.1.0", "graph-native-check", false, "clean");
|
|
assertRepositoryGraphNativeCheck(programGraphCrmApiCheckJson, "clean");
|
|
assert.equal(programGraphCrmApiBuildJson.sourceFile, "examples/crm-api/zero.graph");
|
|
assertSourceGraph(programGraphCrmApiBuildJson, "examples/crm-api/zero.graph", "package:crm-api@0.1.0", "mapped-final-mir", false, "clean");
|
|
assert.equal(programGraphCrmApiBuildJson.generatedCBytes, 0);
|
|
assert.equal(programGraphCrmApiBuildJson.incrementalInvalidation.sourceKind, "program-graph");
|
|
assert.equal(programGraphCrmApiBuildJson.incrementalInvalidation.graphInput.parserArtifactsInKey, false);
|
|
assert.equal(programGraphCrmApiHealth.stdout, "HTTP/1.1 200 OK\r\ncontent-type: application/json\r\nconnection: close\r\ncontent-length: 27\r\n\r\n{\"ok\":true,\"service\":\"crm\"}");
|
|
assert.match(programGraphCrmApiAccounts.stdout, /"accounts":\[/);
|
|
assert.match(programGraphCrmApiDealUpdate.stdout, /"updated":true/);
|
|
assert.match(programGraphCrmApiMissing.stdout, /^HTTP\/1\.1 404 Not Found\r\n/);
|
|
assert.equal(programGraphAuthoringInit.ok, true);
|
|
assert.equal(programGraphAuthoringInit.compilerInput, "repository-graph");
|
|
assert.equal(programGraphAuthoringInit.sourceProjection.path, "src/main.0");
|
|
assert.equal(programGraphAuthoringInit.sourceProjection.materialized, false);
|
|
assert.equal(programGraphAuthoringProjectionExistsAfterInit, false);
|
|
assert.equal(programGraphAuthoringPatch.ok, true);
|
|
assert.equal(programGraphAuthoringPatch.operationCount, 7);
|
|
assert.equal(programGraphAuthoringPatch.artifact, "./zero.graph");
|
|
assert.equal(programGraphAuthoringPatch.saved.path, "./zero.graph");
|
|
assert.equal(programGraphAuthoringProjectionExistsAfterPatch, false);
|
|
assert.equal(programGraphAuthoringStatusMissing.repositoryGraph.projectionState, "source-missing");
|
|
assert.equal(programGraphAuthoringStatusMissing.repositoryGraph.projectionValidity, "missing");
|
|
assert.notEqual(programGraphAuthoringVerifyMissing.code, 0);
|
|
const programGraphAuthoringVerifyMissingBody = JSON.parse(programGraphAuthoringVerifyMissing.stdout);
|
|
assert.equal(programGraphAuthoringVerifyMissingBody.diagnostics[0].code, "RGP006");
|
|
assert.equal(programGraphAuthoringVerifyMissingBody.diagnostics[0].actual, "missing source projection file");
|
|
assert.match(programGraphAuthoringVerifyMissingBody.repairCommands.join("\n"), /zero export/);
|
|
assert.equal(programGraphAuthoringCheck.ok, true);
|
|
assert.equal(programGraphAuthoringCheck.sourceFile, `${programGraphAuthoringPackage}/zero.graph`);
|
|
assert.equal(programGraphAuthoringCheck.graph.sourceProjectionState, "missing");
|
|
assertRepositoryGraphNativeCheck(programGraphAuthoringCheck, "missing");
|
|
assertProgramGraphCompilerInput(programGraphAuthoringCheck, `${programGraphAuthoringPackage}/zero.graph`);
|
|
assert.equal(programGraphAuthoringRun.stdout, "graph authoring ok\n");
|
|
assert.equal(programGraphAuthoringTest.ok, true);
|
|
assert.equal(programGraphAuthoringTest.testDiscovery.mode, "package-graph");
|
|
assert.equal(programGraphAuthoringTest.passedTests, 1);
|
|
assert.equal(programGraphAuthoringExport.ok, true);
|
|
assert.equal(programGraphAuthoringExport.repositoryGraph.projectionState, "clean");
|
|
assert.deepEqual(programGraphAuthoringExport.changedPaths, [`${programGraphAuthoringPackage}/src/main.0`]);
|
|
assert.match(programGraphAuthoringProjectionText, /pub fn main\(world: World\) -> Void raises \{/);
|
|
assert.match(programGraphAuthoringProjectionText, /fn add\(left: i32, right: i32\) -> i32/);
|
|
assert.match(programGraphAuthoringProjectionText, /test "addition works"/);
|
|
assert.equal(programGraphAuthoringVerifyAfter.ok, true);
|
|
assert.equal(programGraphAuthoringVerifyAfter.repositoryGraph.projectionState, "clean");
|
|
assert.equal(programGraphAuthoringCheckAfter.ok, true);
|
|
assert.equal(programGraphAuthoringCheckAfter.graph.sourceProjectionState, "clean");
|
|
assert.equal(programGraphAuthoringStatusAfterHumanEdit.repositoryGraph.projectionState, "source-stale");
|
|
assert.equal(programGraphAuthoringImport.ok, true);
|
|
assert.equal(programGraphAuthoringImport.repositoryGraph.projectionState, "clean");
|
|
assert.deepEqual(programGraphAuthoringImport.changedPaths, [`${programGraphAuthoringPackage}/zero.graph`]);
|
|
assert.equal(programGraphAuthoringCheckAfterHumanEdit.ok, true);
|
|
assert.equal(programGraphAuthoringCheckAfterHumanEdit.graph.sourceProjectionState, "clean");
|
|
assert.equal(programGraphAuthoringRunAfterHumanEdit.stdout, "human edit ok\n");
|
|
assert.equal(programGraphBuilderOpsInit.ok, true);
|
|
assert.equal(programGraphBuilderOpsInit.sourceProjection.materialized, false);
|
|
assert.equal(programGraphBuilderOpsPatch.ok, true);
|
|
assert.equal(programGraphBuilderOpsPatch.operationCount, 10);
|
|
assert.equal(programGraphBuilderOpsProjectionExistsAfterPatch, false);
|
|
assert.equal(programGraphBuilderOpsQuery.ok, true);
|
|
assert(programGraphBuilderOpsQuery.functions.some((fun) => fun.name === "add_twice" && fun.returnType === "u32"));
|
|
assert(programGraphBuilderOpsQuery.patchOperations.includes("addLetLiteral fn=\"main\" name=\"count\" type=\"u32\" value=\"0\""));
|
|
assert(programGraphBuilderOpsQuery.patchOperations.includes("addLetBinary fn=\"add\" name=\"sum\" type=\"i32\" operator=\"+\" left=\"left\" right=\"right\""));
|
|
assert(programGraphBuilderOpsQuery.patchOperations.includes("addReturnValue fn=\"identity\" value=\"input\" type=\"i32\""));
|
|
assert(programGraphBuilderOpsQuery.patchOperations.includes("addCheckWriteValue fn=\"main\" value=\"message\" type=\"String\""));
|
|
assert.match(programGraphBuilderOpsView, /let message: String = "graph value write ok\\n"/);
|
|
assert.match(programGraphBuilderOpsView, /check world\.out\.write\(message\)/);
|
|
assert.match(programGraphBuilderOpsView, /let first: u32 = x \+ y/);
|
|
assert.match(programGraphBuilderOpsView, /let total: u32 = first \+ y/);
|
|
assert.match(programGraphBuilderOpsView, /return total/);
|
|
assert.equal(programGraphBuilderOpsCheck.ok, true);
|
|
assert.equal(programGraphBuilderOpsCheck.graph.sourceProjectionState, "missing");
|
|
assertRepositoryGraphNativeCheck(programGraphBuilderOpsCheck, "missing");
|
|
assert.equal(programGraphBuilderOpsTest.ok, true);
|
|
assert.equal(programGraphBuilderOpsTest.passedTests, 1);
|
|
assert.equal(programGraphBuilderOpsRun.stdout, "graph value write ok\n");
|
|
assert.equal(programGraphBuilderOpsSync.ok, true);
|
|
assert.deepEqual(programGraphBuilderOpsSync.changedPaths, [`${programGraphBuilderOpsPackage}/src/main.0`]);
|
|
assert.equal(programGraphBuilderOpsProjectionText, programGraphBuilderOpsView);
|
|
assert.equal(programGraphLoopTestInit.ok, true);
|
|
assert.equal(programGraphLoopTestPatch.ok, true);
|
|
assert.equal(programGraphLoopTestBodyPatch.ok, true);
|
|
assert.equal(programGraphLoopTestBodyPatch.operations[0].op, "replaceFunctionBody");
|
|
assert.equal(programGraphLoopTestAddTest.ok, true);
|
|
assert.equal(programGraphLoopTestCheck.ok, true);
|
|
assert.equal(programGraphLoopTestCheck.sourceFile, `${programGraphLoopTestPackage}/zero.graph`);
|
|
assertRepositoryGraphNativeCheck(programGraphLoopTestCheck, "missing");
|
|
assert.equal(programGraphLoopTestRun.ok, true);
|
|
assert.equal(programGraphLoopTestRun.testBackend, "direct-program-graph");
|
|
assert.equal(programGraphLoopTestRun.passedTests, 1);
|
|
assert.match(programGraphLoopTestView, /while i < n \{/);
|
|
assert.match(programGraphLoopTestView, /i = i \+ 1/);
|
|
assert.equal(programGraphArrayLengthInit.ok, true);
|
|
assert.equal(programGraphArrayLengthMainPatch.ok, true);
|
|
assert.equal(programGraphArrayLengthRepeatPatch.ok, false);
|
|
assert.equal(programGraphArrayLengthRepeatPatch.diagnostics[0].code, "TYP002");
|
|
assert.equal(programGraphArrayLengthRepeatPatch.diagnostics[0].expected, "[64]u8");
|
|
assert.equal(programGraphArrayLengthRepeatPatch.diagnostics[0].actual, "repeat count 32");
|
|
assert.match(programGraphArrayLengthRepeatPatch.diagnostics[0].help, /make the lengths agree/);
|
|
assert.equal(programGraphArrayLengthListPatch.ok, false);
|
|
assert.equal(programGraphArrayLengthListPatch.diagnostics[0].code, "TYP002");
|
|
assert.equal(programGraphArrayLengthListPatch.diagnostics[0].expected, "[4]u8");
|
|
assert.equal(programGraphArrayLengthListPatch.diagnostics[0].actual, "2 element(s)");
|
|
assert.equal(programGraphArrayLengthMatchingPatch.ok, true);
|
|
assert.equal(programGraphArrayLengthCheck.ok, true);
|
|
assertRepositoryGraphNativeCheck(programGraphArrayLengthCheck, "missing");
|
|
assert.equal(programGraphBlockBodyInit.ok, true);
|
|
assert.equal(programGraphBlockBodyMainPatch.ok, true);
|
|
assert.equal(programGraphBlockBodyMainPatch.operationCount, 1);
|
|
assert.equal(programGraphBlockBodyGreetingPatch.ok, true);
|
|
assert.equal(programGraphBlockBodyGreetingPatch.operationCount, 1);
|
|
assert.equal(programGraphBlockBodyGreetingPatch.operations[0].op, "replaceFunctionBody");
|
|
assert.equal(programGraphBlockBodyBlocks.ok, true);
|
|
assert(programGraphBlockBodyBlocks.patchOperations.some((op) => op.startsWith("replaceBlockBody #block_id\n")));
|
|
assert.equal(programGraphBlockBodyDryRun.ok, true);
|
|
assert.equal(programGraphBlockBodyDryRun.checkOnly, true);
|
|
assert.equal(programGraphBlockBodyDryRun.saved, null);
|
|
assert.equal(programGraphBlockBodyPatch.ok, true);
|
|
assert.equal(programGraphBlockBodyPatch.operationCount, 1);
|
|
assert.equal(programGraphBlockBodyPatch.operations[0].op, "replaceBlockBody");
|
|
assert.match(programGraphBlockBodyView, /if name\.has \{/);
|
|
assert.match(programGraphBlockBodyView, /check world\.out\.write\("name \+ value: "\)/);
|
|
assert.match(programGraphBlockBodyView, /check world\.out\.write\("hello anonymous\\n"\)/);
|
|
assert.equal(programGraphBlockBodyCheck.ok, true);
|
|
assert.equal(programGraphBlockBodyCheck.graph.sourceProjectionState, "missing");
|
|
assertRepositoryGraphNativeCheck(programGraphBlockBodyCheck, "missing");
|
|
assert.equal(programGraphBlockBodyRun.stdout, "name + value: Ada\n");
|
|
assert.equal(programGraphAuthoringCliInit.ok, true);
|
|
assert.equal(programGraphAuthoringCliInit.sourceProjection.materialized, false);
|
|
assert.equal(programGraphAuthoringCliPatch.ok, true);
|
|
assert.equal(programGraphAuthoringCliPatch.operationCount, 5);
|
|
assert.equal(programGraphAuthoringCliBodyPatch.ok, true);
|
|
assert.equal(programGraphAuthoringCliBodyPatch.operationCount, 1);
|
|
assert.equal(programGraphAuthoringCliBodyPatch.operations[0].op, "replaceFunctionBody");
|
|
assert.equal(programGraphAuthoringCliProjectionExistsAfterInit, false);
|
|
assert.equal(programGraphAuthoringCliProjectionExistsAfterPatch, false);
|
|
assert.equal(programGraphAuthoringCliStaleAddPatch.ok, true);
|
|
assert.equal(programGraphAuthoringCliStaleAddPatch.operationCount, 5);
|
|
assert.equal(programGraphAuthoringCliFindAdd.ok, true);
|
|
assert(programGraphAuthoringCliFindAdd.matches.some((node) => node.id === "#fn_add" && node.kind === "Function"));
|
|
assert(programGraphAuthoringCliFindAdd.matches.some((node) => node.id === "#fn___zero_test_0" && node.kind === "Function" && node.value === "add works"));
|
|
assert.equal(programGraphAuthoringCliNodeAdd.ok, true);
|
|
assert.equal(programGraphAuthoringCliNodeAdd.query.node, "#fn_add");
|
|
assert.equal(programGraphAuthoringCliNodeAdd.node.selected.id, "#fn_add");
|
|
assert(programGraphAuthoringCliNodeAdd.node.parents.some((edge) => edge.kind === "function" && edge.from === "#mod_main"));
|
|
assert(programGraphAuthoringCliNodeAdd.node.children.some((edge) => edge.kind === "body" && edge.to === "#block_add_body"));
|
|
assert(programGraphAuthoringCliNodeAdd.node.children.some((edge) => edge.kind === "param" && edge.to === "#param_add_x"));
|
|
assert.equal(programGraphAuthoringCliCleanupPatch.ok, true);
|
|
assert.equal(programGraphAuthoringCliCleanupPatch.operationCount, 3);
|
|
assert.match(programGraphAuthoringCliCallsText, /query: fn:main calls:std/);
|
|
assert.match(programGraphAuthoringCliCallsText, /qualified:std\.args\.parseU32/);
|
|
assert.match(programGraphAuthoringCliCallsText, /qualified:std\.fmt\.u32/);
|
|
assert.match(programGraphAuthoringCliCallsText, /resolved:true/);
|
|
assert.match(programGraphAuthoringCliRefsText, /query: refs:add_u32/);
|
|
assert.match(programGraphAuthoringCliRefsText, /target:function node:#fn_add_u32/);
|
|
assert.match(programGraphAuthoringCliRefsText, /fn:main name:add_u32/);
|
|
assert.equal(programGraphAuthoringCliQuery.ok, true);
|
|
assert.equal(programGraphAuthoringCliQuery.inputKind, "repository-graph");
|
|
assert(programGraphAuthoringCliQuery.functions.some((fun) => fun.name === "main" && fun.public && fun.fallible));
|
|
assert(programGraphAuthoringCliQuery.functions.some((fun) => fun.name === "add_u32" && fun.returnType === "u32" && fun.params.length === 2));
|
|
assert(!programGraphAuthoringCliQuery.functions.some((fun) => fun.name === "add"));
|
|
assert(programGraphAuthoringCliQuery.functions.some((fun) => fun.test === "add_u32 works"));
|
|
assert(!programGraphAuthoringCliQuery.patchOperations.some((op) => op.includes("setMain")));
|
|
assert(programGraphAuthoringCliQuery.patchOperations.some((op) => op.startsWith("replaceFunctionBody main\n")));
|
|
assert.equal(programGraphAuthoringCliCheck.ok, true);
|
|
assert.equal(programGraphAuthoringCliCheck.sourceFile, `${programGraphAuthoringCliPackage}/zero.graph`);
|
|
assert.equal(programGraphAuthoringCliCheck.graph.sourceProjectionState, "missing");
|
|
assertRepositoryGraphNativeCheck(programGraphAuthoringCliCheck, "missing");
|
|
assert.match(programGraphAuthoringCliGraphBuild.stdout, /program-graph-authoring-cli-graph-build/);
|
|
assert.match(programGraphAuthoringCliBuild.stdout, /program-graph-authoring-cli-build/);
|
|
assert.equal(programGraphAuthoringCliTest.ok, true);
|
|
assert.equal(programGraphAuthoringCliTest.passedTests, 1);
|
|
assert.equal(programGraphAuthoringCliGraphTest.stdout, "1 test(s) ok\n");
|
|
assert.equal(programGraphAuthoringCliRun.stdout, "42\n");
|
|
assert.equal(programGraphAuthoringCliGraphRun.stdout, "15\n");
|
|
assertSourceGraph(programGraphAuthoringCliSize, `${programGraphAuthoringCliPackage}/zero.graph`, "package:program-graph-authoring-cli@0.1.0", "mapped-final-mir", false, "missing");
|
|
assert(programGraphAuthoringCliSize.sizeBreakdown.stdlibHelpers.some((helper) => helper.name === "std.args.parseU32"));
|
|
assert(programGraphAuthoringCliSize.sizeBreakdown.stdlibHelpers.some((helper) => helper.name === "std.fmt.u32"));
|
|
assert.equal(programGraphAuthoringCliSync.ok, true);
|
|
assert.deepEqual(programGraphAuthoringCliSync.changedPaths, [`${programGraphAuthoringCliPackage}/src/main.0`]);
|
|
assert.match(programGraphAuthoringCliProjectionText, /fn add_u32\(x: u32, y: u32\) -> u32/);
|
|
assert.match(programGraphAuthoringCliProjectionText, /test "add_u32 works"/);
|
|
assert.doesNotMatch(programGraphAuthoringCliProjectionText, /fn add\(x: i32, y: i32\) -> i32/);
|
|
assert.equal(programGraphAuthoringCliStatusAfterHumanEdit.repositoryGraph.projectionState, "source-stale");
|
|
assert.equal(programGraphAuthoringCliImport.ok, true);
|
|
assert.deepEqual(programGraphAuthoringCliImport.changedPaths, [`${programGraphAuthoringCliPackage}/zero.graph`]);
|
|
assert.equal(programGraphAuthoringCliImport.store.nodes, 96);
|
|
assert.equal(programGraphAuthoringCliImport.store.sources, 1);
|
|
assert.equal(programGraphAuthoringCliQueryAfterHumanEdit.ok, true);
|
|
assert.equal(programGraphAuthoringCliQueryAfterHumanEdit.counts.nodes, 96);
|
|
assert.deepEqual(programGraphAuthoringCliQueryAfterHumanEdit.modules.map((module) => module.name), ["main"]);
|
|
assert(programGraphAuthoringCliQueryAfterHumanEdit.calls.some((call) => call.qualifiedName === "std.args.parseU32" && call.targetKind === "stdlib"));
|
|
assert(programGraphAuthoringCliQueryAfterHumanEdit.calls.some((call) => call.qualifiedName === "std.fmt.u32" && call.targetKind === "stdlib"));
|
|
assert(!programGraphAuthoringCliQueryAfterHumanEdit.calls.some((call) => call.targetKind === "graphBackedStdlib"));
|
|
assert.match(programGraphAuthoringCliFindUsageText, /value:usage: zero run \. -- <left> <right>\\n path:/);
|
|
assert.equal(programGraphAuthoringCliVerifyAfterHumanEdit.ok, true);
|
|
assert.equal(programGraphAuthoringCliVerifyAfterHumanEdit.repositoryGraph.projectionState, "clean");
|
|
assert.equal(programGraphAuthoringCliCheckAfterHumanEdit.ok, true);
|
|
assert.equal(programGraphAuthoringCliCheckAfterHumanEdit.sourceFile, `${programGraphAuthoringCliPackage}/zero.graph`);
|
|
assertRepositoryGraphNativeCheck(programGraphAuthoringCliCheckAfterHumanEdit, "clean");
|
|
assert.equal(programGraphAuthoringCliTestAfterHumanEdit.ok, true);
|
|
assert.equal(programGraphAuthoringCliTestAfterHumanEdit.passedTests, 1);
|
|
assert.equal(programGraphAuthoringCliRunAfterHumanEdit.stdout, "11\n");
|
|
assert.equal(programGraphSourceFreeCImportSync.ok, true);
|
|
assert.equal(programGraphSourceFreeCImportSync.repositoryGraph.projectionValidity, "clean");
|
|
assert.equal(programGraphSourceFreeCImportCheck.ok, true);
|
|
assert.equal(programGraphSourceFreeCImportCheck.graph.sourceProjectionState, "missing");
|
|
assertRepositoryGraphNativeCheck(programGraphSourceFreeCImportCheck, "missing");
|
|
assert.equal(programGraphSourceFreeCImportRun.stdout, "source-free c import ok\n");
|
|
assert.equal(programGraphSourceFreeCImportCwdBuild.sourceFile, resolve(`${programGraphSourceFreeCImportPackage}/zero.graph`));
|
|
assert.equal(programGraphSourceFreeCImportCwdBuild.graph.artifact, resolve(`${programGraphSourceFreeCImportPackage}/zero.graph`));
|
|
assert.equal(programGraphSourceFreeCImportCwdBuild.graph.sourceProjectionState, "missing");
|
|
assert.notEqual(programGraphIdentityMismatchCheck.code, 0);
|
|
const programGraphIdentityMismatchCheckBody = JSON.parse(programGraphIdentityMismatchCheck.stdout);
|
|
assert.equal(programGraphIdentityMismatchCheckBody.diagnostics[0].code, "RGP007");
|
|
assert.equal(programGraphIdentityMismatchCheckBody.diagnostics[0].expected, "package:program-graph-wrong-package@9.9.9");
|
|
assert.equal(programGraphIdentityMismatchCheckBody.diagnostics[0].actual, "package:program-graph-fixture@0.1.0");
|
|
assert.notEqual(programGraphIdentityMismatchSize.code, 0);
|
|
assert.equal(JSON.parse(programGraphIdentityMismatchSize.stdout).diagnostics[0].code, "RGP007");
|
|
assert.notEqual(programGraphMissingPackageNameCheck.code, 0);
|
|
const programGraphMissingPackageNameBody = JSON.parse(programGraphMissingPackageNameCheck.stdout);
|
|
assert.equal(programGraphMissingPackageNameBody.diagnostics[0].code, "RGP007");
|
|
assert.equal(programGraphMissingPackageNameBody.diagnostics[0].message, "repository graph compiler input requires package.name");
|
|
assert.match(programGraphMissingPackageNameBody.diagnostics[0].actual, /package:program-graph-fixture@0\.1\.0/);
|
|
assert.equal(programGraphBadProjectionStatus.repositoryGraph.projectionState, "conflict");
|
|
assert.equal(programGraphBadProjectionStatus.repositoryGraph.projectionValidity, "conflict");
|
|
assert.equal(programGraphBadProjectionCheck.ok, true);
|
|
assert.equal(programGraphBadProjectionCheck.graph.sourceProjectionState, "conflict");
|
|
assert.notEqual(programGraphBadProjectionSync.code, 0);
|
|
assert.equal(JSON.parse(programGraphBadProjectionSync.stdout).diagnostics[0].code, "RGP004");
|
|
assert.notEqual(programGraphMissingStoreCheck.code, 0);
|
|
const programGraphMissingStoreBody = JSON.parse(programGraphMissingStoreCheck.stdout);
|
|
assert.equal(programGraphMissingStoreBody.ok, false);
|
|
assert.equal(programGraphMissingStoreBody.mode, "compiler-input");
|
|
assert.equal(programGraphMissingStoreBody.repositoryGraph.storePresent, false);
|
|
assert.equal(programGraphMissingStoreBody.diagnostics[0].code, "RGP001");
|
|
assert.equal(programGraphMissingStoreBody.diagnostics[0].path, programGraphMissingStorePackage);
|
|
assert.match(programGraphMissingStoreBody.repairCommands.join("\n"), /zero import/);
|
|
assert.notEqual(programGraphInvalidStoreCheck.code, 0);
|
|
const programGraphInvalidStoreBody = JSON.parse(programGraphInvalidStoreCheck.stdout);
|
|
assert.equal(programGraphInvalidStoreBody.ok, false);
|
|
assert.equal(programGraphInvalidStoreBody.mode, "compiler-input");
|
|
assert.equal(programGraphInvalidStoreBody.repositoryGraph.storePresent, true);
|
|
assert.equal(programGraphInvalidStoreBody.repositoryGraph.storeValid, false);
|
|
assert.equal(programGraphInvalidStoreBody.diagnostics[0].code, "RGP003");
|
|
assert.equal(programGraphInvalidStoreBody.diagnostics[0].path, programGraphInvalidStorePackage);
|
|
assert.match(programGraphInvalidStoreBody.repairCommands.join("\n"), /zero import/);
|
|
assert.equal(programGraphSourceFixtureDriftCheck.ok, true);
|
|
assert.equal(programGraphSourceFixtureDriftCheck.graph.lowering, "graph-native-check");
|
|
assert.equal(programGraphSourceFixtureDriftCheck.graph.sourceProjectionState, "clean");
|
|
assertRepositoryGraphNativeCheck(programGraphSourceFixtureDriftCheck, "clean");
|
|
assert.equal(programGraphSourceFixtureDriftVerifyAfterRefresh.ok, true);
|
|
assert.notEqual(programGraphSourceFixtureDriftVerify.code, 0);
|
|
const programGraphSourceFixtureDriftBody = JSON.parse(programGraphSourceFixtureDriftVerify.stdout);
|
|
assert.equal(programGraphSourceFixtureDriftBody.ok, false);
|
|
assert.equal(programGraphSourceFixtureDriftBody.mode, "verify-projection");
|
|
assert.equal(programGraphSourceFixtureDriftBody.repositoryGraph.compilerInput, "repository-graph");
|
|
assert.equal(programGraphSourceFixtureDriftBody.diagnostics[0].code, "RGP006");
|
|
assert.match(programGraphSourceFixtureDriftBody.repairCommands.join("\n"), /zero import/);
|
|
assert.match(programGraphSourceFixtureDriftBody.repairCommands.join("\n"), /zero export/);
|
|
assert.equal(programGraphTargetIncompatibleSync.ok, true);
|
|
assert.notEqual(programGraphTargetIncompatibleCheck.code, 0);
|
|
const programGraphTargetIncompatibleBody = JSON.parse(programGraphTargetIncompatibleCheck.stdout);
|
|
assert.equal(programGraphTargetIncompatibleBody.ok, false);
|
|
assert.equal(programGraphTargetIncompatibleBody.diagnostics[0].code, "PKG004");
|
|
assert.match(programGraphTargetIncompatibleBody.diagnostics[0].actual, /target-webbits targets/);
|
|
assert.equal(programGraphTargetCapabilitySync.ok, true);
|
|
assert.notEqual(programGraphTargetCapabilityCheck.code, 0);
|
|
const programGraphTargetCapabilityBody = JSON.parse(programGraphTargetCapabilityCheck.stdout);
|
|
assert.equal(programGraphTargetCapabilityBody.ok, false);
|
|
assert.equal(programGraphTargetCapabilityBody.diagnostics[0].code, "TAR002");
|
|
assert.match(programGraphTargetCapabilityBody.diagnostics[0].actual, /lacks Fs/);
|
|
const programGraphBackendMismatchCheck = JSON.parse((await execFileAsync(zero, ["check", "--json", "--backend", "zero-coff-x64", "--target", "linux-musl-x64", programGraphSourceFixturePackage])).stdout);
|
|
assert.equal(programGraphBackendMismatchCheck.ok, true);
|
|
assert.equal(programGraphBackendMismatchCheck.targetReadiness.ok, false);
|
|
assert.equal(programGraphBackendMismatchCheck.targetReadiness.diagnostics[0].code, "BLD004");
|
|
assert.equal(programGraphBackendMismatchCheck.targetReadiness.diagnostics[0].backendBlocker.backend, "zero-coff-x64");
|
|
const programGraphRepositoryStatus = JSON.parse((await execFileAsync(zero, ["status", "--json", "--target", "linux-musl-x64", programGraphSourceFixturePackage])).stdout);
|
|
assert.equal(programGraphRepositoryStatus.repositoryGraph.storePresent, true);
|
|
assert.equal(programGraphRepositoryStatus.repositoryGraph.storeValid, true);
|
|
assert.equal(programGraphRepositoryStatus.repositoryGraph.projectionState, "clean");
|
|
assert.equal(programGraphRepositoryStatus.repositoryGraph.compilerInput, "repository-graph");
|
|
const programGraphRepositoryVerify = JSON.parse((await execFileAsync(zero, ["verify-projection", "--json", "--target", "linux-musl-x64", programGraphSourceFixturePackage])).stdout);
|
|
assert.equal(programGraphRepositoryVerify.ok, true);
|
|
assert.equal(programGraphRepositoryVerify.writes, false);
|
|
assert.deepEqual(programGraphDumpJson, programGraphBody);
|
|
assert.match(programGraphDump, /^zero-graph v1\n/);
|
|
assert.match(programGraphDump, /origin source-text/);
|
|
assert.match(programGraphDump, /module "hello"/);
|
|
assert.match(programGraphDump, /hash "graph:[0-9a-f]{16}"/);
|
|
assert.doesNotMatch(programGraphDump, /validation "shape-valid" ok/);
|
|
assert.doesNotMatch(programGraphDump, /idStrategy/);
|
|
assert.doesNotMatch(programGraphDump, /canonicalSource/);
|
|
assert.doesNotMatch(programGraphDump, /moduleIdentity/);
|
|
assert.doesNotMatch(programGraphDump, /graphHash/);
|
|
assert.doesNotMatch(programGraphDump, /counts nodes=/);
|
|
assert.doesNotMatch(programGraphDump, /node id=/);
|
|
assert.match(programGraphDump, /node #mod_[0-9a-f]{8} Module name:"hello"/);
|
|
assert.match(programGraphDump, /edge #mod_[0-9a-f]{8} function #decl_[0-9a-f]{8} order:0/);
|
|
assert.match(programGraphView, /^pub fn main\(world: World\) -> Void raises \{\n/);
|
|
assert.match(programGraphView, /check world\.out\.write\("hello from zero\\n"\)/);
|
|
assert.match(programGraphRichView, /bytesTail\(bytesSpan\)\[1\]/);
|
|
assert.match(programGraphRichView, /numbers\[2\.\.\]/);
|
|
assert.match(programGraphCharView, /again == 'A'/);
|
|
assert.match(programGraphBody.graphHash, /^graph:[0-9a-f]{16}$/);
|
|
assert.equal(programGraphBody.validation.ok, true);
|
|
assert.equal(programGraphBody.validation.state, "shape-valid");
|
|
assert(programGraphBody.counts.nodes > 0);
|
|
assert(programGraphBody.counts.edges > 0);
|
|
assert(programGraphBody.nodes.every((item) => /^#[a-z][a-z0-9]*_[0-9a-f]{8}(-[0-9a-f]{4}(-[0-9]+)?)?$/.test(item.id) && /^nodehash:[0-9a-f]{16}$/.test(item.nodeHash)));
|
|
assert(programGraphBody.edges.every((item) => item.target === "node"));
|
|
assert(programGraphBody.nodes.some((item) => item.kind === "Module" && item.name === "hello" && item.symbolId === "symbol:hello::module"));
|
|
assert(programGraphBody.nodes.some((item) => item.kind === "Function" && item.name === "main" && item.public === true && item.fallible === true && item.symbolId === "symbol:hello::value.main" && /^type:[0-9a-f]{16}$/.test(item.typeId)));
|
|
assert(programGraphBody.nodes.some((item) => item.kind === "Param" && item.name === "world" && item.type === "World" && item.symbolId === "symbol:hello::value.main/param.world"));
|
|
assert(programGraphBody.nodes.some((item) => item.kind === "EffectRef" && item.name === "error" && /^effect:[0-9a-f]{16}$/.test(item.effectId)));
|
|
assert(programGraphBody.nodes.some((item) => item.kind === "Check"));
|
|
assert(programGraphBody.nodes.some((item) => item.kind === "MethodCall"));
|
|
assert(programGraphBody.edges.some((item) => item.kind === "body"));
|
|
const programGraphWrongSchemaPath = `${outDir}/wrong-schema.program-graph`;
|
|
await writeFile(programGraphWrongSchemaPath, "zero-graph v2\n");
|
|
const programGraphWrongSchema = await execFileAsync(zero, ["validate", "--json", programGraphWrongSchemaPath]).catch((error) => error);
|
|
assert(programGraphWrongSchema.code);
|
|
assert.equal(JSON.parse(programGraphWrongSchema.stdout).diagnostics[0].message, "unknown program graph schema version");
|
|
const programGraphFailedArtifactPath = `${outDir}/failed-validation.program-graph`;
|
|
await writeFile(programGraphFailedArtifactPath, [
|
|
"zero-graph v1",
|
|
"origin source-text",
|
|
"module \"main\"",
|
|
"hash \"\"",
|
|
"validation \"decoded\" failed",
|
|
"diagnostic code:\"GRF001\" message:\"program graph construction failed\"",
|
|
"",
|
|
].join("\n"));
|
|
const programGraphFailedArtifact = await execFileAsync(zero, ["validate", "--json", programGraphFailedArtifactPath]).catch((error) => error);
|
|
assert(programGraphFailedArtifact.code);
|
|
assert.equal(JSON.parse(programGraphFailedArtifact.stdout).diagnostics[0].message, "program graph input reports failed validation");
|
|
const programGraphTrailingArtifactPath = `${outDir}/trailing-content.program-graph`;
|
|
await writeFile(programGraphTrailingArtifactPath, `${programGraphDump}\nextra\n`);
|
|
const programGraphTrailingArtifact = await execFileAsync(zero, ["validate", "--json", programGraphTrailingArtifactPath]).catch((error) => error);
|
|
assert(programGraphTrailingArtifact.code);
|
|
assert.equal(JSON.parse(programGraphTrailingArtifact.stdout).diagnostics[0].message, "unexpected content after graph header");
|
|
assert(programGraphBody.edges.some((item) => item.kind === "statement" && item.order === 0));
|
|
|
|
const programGraphDuplicateIdFixture = `${outDir}/program-graph-duplicate-id-stress.0`;
|
|
const programGraphDuplicateIdPath = `${outDir}/program-graph-duplicate-id-stress.program-graph`;
|
|
await writeFile(programGraphDuplicateIdFixture, [
|
|
"pub fn main() -> Void {",
|
|
...Array.from({ length: 700 }, (_, index) => ` let x${index}: i32 = 1`),
|
|
"}",
|
|
"",
|
|
].join("\n"));
|
|
const programGraphDuplicateIdDump = await execFileAsync(zero, ["import", "--format", "text", "--out", programGraphDuplicateIdPath, programGraphDuplicateIdFixture]);
|
|
assert.equal(programGraphDuplicateIdDump.stdout, "");
|
|
assert.equal((await execFileAsync(zero, ["validate", programGraphDuplicateIdPath])).stdout, "program graph ok\n");
|
|
const programGraphDuplicateIdText = await readFile(programGraphDuplicateIdPath, "utf8");
|
|
const programGraphDuplicateIds = [...programGraphDuplicateIdText.matchAll(/^node (#[^ ]+)/gm)].map((match) => match[1]);
|
|
assert.equal(new Set(programGraphDuplicateIds).size, programGraphDuplicateIds.length);
|
|
assert(programGraphDuplicateIds.some((id) => /^#[a-z][a-z0-9]*_[0-9a-f]{8}-[0-9a-f]{4}(-[0-9]+)?$/.test(id)));
|
|
|
|
const programGraphControlFixture = `${outDir}/program-graph-control.0`;
|
|
const programGraphControlPath = await writeGraphFixture(programGraphControlFixture, "pub fn main(world: World) -> Void raises {\n check world.out.write(\"\\x01 ok\\n\")\n}\n");
|
|
const programGraphControl = JSON.parse((await execFileAsync(zero, ["inspect", "--json", programGraphControlPath])).stdout).programGraph;
|
|
assert(programGraphControl.nodes.some((item) => item.kind === "Literal" && item.value === "\u0001 ok\n"));
|
|
|
|
const programGraphMatchRanges = JSON.parse((await execFileAsync(zero, ["inspect", "--json", "conformance/native/pass/match-scalar-guards.0"])).stdout).programGraph;
|
|
const programGraphRangeArm = programGraphMatchRanges.nodes.find((item) => item.kind === "MatchArm" && item.name === "1");
|
|
assert(programGraphRangeArm);
|
|
const programGraphRangeEdge = programGraphMatchRanges.edges.find((item) => item.from === programGraphRangeArm.id && item.kind === "rangeEnd");
|
|
assert(programGraphRangeEdge);
|
|
assert(programGraphMatchRanges.nodes.some((item) => item.id === programGraphRangeEdge.to && item.kind === "Literal" && item.value === "3"));
|
|
|
|
const programGraphShapeDefaults = JSON.parse((await execFileAsync(zero, ["inspect", "--json", "conformance/check/pass/shape-field-defaults.0"])).stdout).programGraph;
|
|
const programGraphDefaultField = programGraphShapeDefaults.nodes.find((item) => item.kind === "Field" && item.name === "left");
|
|
assert(programGraphDefaultField);
|
|
const programGraphDefaultEdge = programGraphShapeDefaults.edges.find((item) => item.from === programGraphDefaultField.id && item.kind === "default");
|
|
assert(programGraphDefaultEdge);
|
|
assert(programGraphShapeDefaults.nodes.some((item) => item.id === programGraphDefaultEdge.to && item.kind === "Literal" && item.value === "1"));
|
|
|
|
const memorySize = await execFileAsync(zero, ["size", "--json", "--target", "linux-musl-x64", "examples/memory-package"]);
|
|
const memorySizeBody = JSON.parse(memorySize.stdout);
|
|
assert.equal(memorySizeBody.target, "linux-musl-x64");
|
|
assert.equal(memorySizeBody.targetSupport.fsAvailable, true);
|
|
assert(memorySizeBody.requiresCapabilities.includes("memory"));
|
|
assert(!memorySizeBody.requiresCapabilities.includes("fs"));
|
|
assert.equal(memorySizeBody.generatedCBytes, 0);
|
|
assert.equal(memorySizeBody.cBridgeFallback, false);
|
|
assert(memorySizeBody.loweredIrBytes > 0);
|
|
assert(memorySizeBody.sections.some((section) => section.name === "direct-size-metadata" && section.kind === "metadata"));
|
|
assert(memorySizeBody.objectBackend.objectEmission.path.includes("direct-"));
|
|
assert.equal(memorySizeBody.objectBackend.emitKind, "size");
|
|
assert(memorySizeBody.stdlibHelpers.some((helper) => helper.name === "std.mem.copy"));
|
|
assert(memorySizeBody.stdlibHelperAttribution.some((helper) => helper.name === "std.mem.copy" && helper.estimatedDirectBytes > 0));
|
|
assert(memorySizeBody.usedStdlibHelpers.every((helper) => helper.module && helper.effects?.length && helper.errorBehavior && helper.ownershipNotes && helper.example));
|
|
assert(memorySizeBody.runtimeShims.some((shim) => shim.name === "stdio-world" && shim.payAsUsed === true));
|
|
|
|
const genericPairSize = await execFileAsync(zero, ["size", "--json", "examples/generic-pair.0"]);
|
|
const genericPairSizeBody = JSON.parse(genericPairSize.stdout);
|
|
assert.equal(genericPairSizeBody.graph.artifact, "examples/generic-pair.graph");
|
|
assert.equal(genericPairSizeBody.graph.lowering, "mapped-final-mir");
|
|
assert.equal(genericPairSizeBody.cBridgeFallback, false);
|
|
assert(genericPairSizeBody.loweredIrBytes > 0);
|
|
|
|
const genericInferredSize = await execFileAsync(zero, ["size", "--json", "conformance/native/pass/generic-inferred-specialized-call.0"]);
|
|
const genericInferredSizeBody = JSON.parse(genericInferredSize.stdout);
|
|
assert.equal(genericInferredSizeBody.graph.artifact, "conformance/native/pass/generic-inferred-specialized-call.graph");
|
|
assert.equal(genericInferredSizeBody.graph.lowering, "mapped-final-mir");
|
|
assert.equal(genericInferredSizeBody.cBridgeFallback, false);
|
|
assert(genericInferredSizeBody.loweredIrBytes > 0);
|
|
|
|
const genericStaticForwardedSize = await execFileAsync(zero, ["size", "--json", "conformance/native/pass/generic-static-forwarded-array-specialization.0"]);
|
|
const genericStaticForwardedSizeBody = JSON.parse(genericStaticForwardedSize.stdout);
|
|
assert.equal(genericStaticForwardedSizeBody.graph.artifact, "conformance/native/pass/generic-static-forwarded-array-specialization.graph");
|
|
assert.equal(genericStaticForwardedSizeBody.graph.lowering, "mapped-final-mir");
|
|
assert.equal(genericStaticForwardedSizeBody.cBridgeFallback, false);
|
|
assert(genericStaticForwardedSizeBody.loweredIrBytes > 0);
|
|
|
|
const targetsJson = await execFileAsync(zero, ["targets"]);
|
|
const targetsBody = JSON.parse(targetsJson.stdout);
|
|
const linuxMuslTarget = targetsBody.targets.find((item) => item.name === "linux-musl-x64");
|
|
const windowsMsvcTarget = targetsBody.targets.find((item) => item.aliases.includes("x86_64-windows-msvc"));
|
|
const linuxGnuTarget = targetsBody.targets.find((item) => item.name === "linux-x64");
|
|
const darwinArm64Target = targetsBody.targets.find((item) => item.name === "darwin-arm64");
|
|
const darwinX64Target = targetsBody.targets.find((item) => item.name === "darwin-x64");
|
|
const linuxArm64Target = targetsBody.targets.find((item) => item.name === "linux-arm64");
|
|
assert(linuxMuslTarget.capabilityFacts.some((item) => item.name === "fs" && item.available === true));
|
|
assert.equal(linuxMuslTarget.abi, "musl");
|
|
assert.equal(linuxMuslTarget.objectFormat, "elf");
|
|
assert.equal(linuxMuslTarget.toolchain.crossCompiler, "target-capable C compiler");
|
|
assert.equal(linuxMuslTarget.libcFacts.mode, "bundled-libc");
|
|
assert.equal(linuxMuslTarget.directBackend.status, "native-exe");
|
|
assert.equal(linuxMuslTarget.directBackend.objectSupported, true);
|
|
assert.equal(linuxMuslTarget.directBackend.exeSupported, true);
|
|
assert.equal(linuxMuslTarget.directBackend.objectEmitter, "zero-elf64");
|
|
assert.equal(linuxMuslTarget.directBackend.exeEmitter, "zero-elf64-exe");
|
|
assert.equal(linuxMuslTarget.directBackend.explicitDirectFallback, "never-c-bridge");
|
|
assert.equal(linuxMuslTarget.httpRuntime.status, "unsupported");
|
|
assert.equal(linuxMuslTarget.httpRuntime.provider, null);
|
|
assert.match(linuxMuslTarget.httpRuntime.reason, /lacks net/i);
|
|
assert.equal(windowsMsvcTarget.objectFormat, "coff");
|
|
assert.equal(windowsMsvcTarget.libcFacts.mode, "sysroot");
|
|
assert.equal(windowsMsvcTarget.libcFacts.sysrootStatus, "missing");
|
|
assert.equal(windowsMsvcTarget.directBackend.objectSupported, true);
|
|
assert.equal(windowsMsvcTarget.directBackend.exeSupported, true);
|
|
assert.equal(windowsMsvcTarget.directBackend.objectEmitter, "zero-coff-x64");
|
|
assert.equal(windowsMsvcTarget.directBackend.exeEmitter, "zero-coff-x64-exe");
|
|
assert.equal(linuxGnuTarget.directBackend.objectEmitter, "zero-elf64");
|
|
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(darwinArm64Target.httpRuntime.provider, targetsBody.host === "darwin-arm64" ? "curl" : null);
|
|
assert.equal(darwinArm64Target.httpRuntime.tlsVerification, targetsBody.host === "darwin-arm64");
|
|
if (targetsBody.host === "darwin-arm64") {
|
|
assert.equal(darwinArm64Target.httpRuntime.customCa.env, "ZERO_HTTP_TEST_CA_BUNDLE");
|
|
}
|
|
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 zlsSelfTest = await execFileAsync("node", [
|
|
"--experimental-strip-types",
|
|
"--disable-warning=ExperimentalWarning",
|
|
"scripts/zls.mts",
|
|
"--self-test",
|
|
]);
|
|
assert.match(zlsSelfTest.stdout, /zls self-test ok/);
|
|
|
|
const cHeaderGraph = await execFileAsync(zero, ["inspect", "--json", "conformance/check/pass/c-header-import.0"]);
|
|
const cHeaderGraphBody = JSON.parse(cHeaderGraph.stdout);
|
|
assert(cHeaderGraphBody.cImports.some((item) => item.header === "conformance/c/simple.h" && item.imports.functions >= 1 && item.cacheKey));
|
|
const simpleHeaderImport = cHeaderGraphBody.cImports.find((item) => item.header === "conformance/c/simple.h");
|
|
assert(simpleHeaderImport.typedModel.functions.some((item) => item.name === "zero_c_add" && item.params.length === 2));
|
|
assert(simpleHeaderImport.typedModel.constants.some((item) => item.name === "ZERO_C_ANSWER" && item.value === "42"));
|
|
assert(simpleHeaderImport.typedModel.structs.some((item) => item.name === "zero_c_point" && item.fields.some((field) => field.name === "y")));
|
|
assert(simpleHeaderImport.typedModel.enums.some((item) => item.name === "zero_c_color" && item.cases.some((entry) => entry.name === "ZERO_C_BLUE")));
|
|
assert(simpleHeaderImport.typedModel.typedefs.some((item) => item.name === "zero_c_int" && item.target === "int"));
|
|
assert.equal(typeof simpleHeaderImport.cache.target, "string");
|
|
|
|
const cImportTargetLinux = await execFileAsync(zero, ["check", "--json", "--emit", "obj", "--target", "linux-musl-x64", "conformance/check/pass/c-import-target-linux.0"]);
|
|
const cImportTargetLinuxBody = JSON.parse(cImportTargetLinux.stdout);
|
|
assert.equal(cImportTargetLinuxBody.ok, true);
|
|
assert.equal(cImportTargetLinuxBody.targetReadiness.ok, true);
|
|
assert.equal(cImportTargetLinuxBody.targetReadiness.buildable, true);
|
|
const cImportTargetWin = await execFileAsync(zero, ["check", "--json", "--emit", "obj", "--target", "win32-x64.exe", "conformance/check/pass/c-import-target-win.0"]);
|
|
const cImportTargetWinBody = JSON.parse(cImportTargetWin.stdout);
|
|
assert.equal(cImportTargetWinBody.ok, true);
|
|
assert.equal(cImportTargetWinBody.targetReadiness.ok, true);
|
|
assert.equal(cImportTargetWinBody.targetReadiness.buildable, true);
|
|
const cImportTargetLinuxGraph = await execFileAsync(zero, ["inspect", "--json", "--target", "linux-musl-x64", "conformance/check/pass/c-import-target-linux.0"]);
|
|
const cImportTargetLinuxModel = JSON.parse(cImportTargetLinuxGraph.stdout).cImports.find((item) => item.header === "conformance/c/target-conditional.h").typedModel;
|
|
assert(cImportTargetLinuxModel.functions.some((item) => item.name === "zero_c_linux_add"));
|
|
assert(cImportTargetLinuxModel.functions.some((item) => item.name === "zero_c_not_windows"));
|
|
assert(!cImportTargetLinuxModel.functions.some((item) => item.name === "zero_c_windows_add"));
|
|
const cImportTargetWinGraph = await execFileAsync(zero, ["inspect", "--json", "--target", "win32-x64.exe", "conformance/check/pass/c-import-target-win.0"]);
|
|
const cImportTargetWinModel = JSON.parse(cImportTargetWinGraph.stdout).cImports.find((item) => item.header === "conformance/c/target-conditional.h").typedModel;
|
|
assert(cImportTargetWinModel.functions.some((item) => item.name === "zero_c_windows_add"));
|
|
assert(!cImportTargetWinModel.functions.some((item) => item.name === "zero_c_linux_add"));
|
|
assert(!cImportTargetWinModel.functions.some((item) => item.name === "zero_c_not_windows"));
|
|
|
|
const cImportTypeShadowReadiness = await execFileAsync(zero, ["check", "--json", "--emit", "obj", "conformance/native/pass/c-import-type-shadowing.0"]);
|
|
const cImportTypeShadowReadinessBody = JSON.parse(cImportTypeShadowReadiness.stdout);
|
|
assert.equal(cImportTypeShadowReadinessBody.ok, true);
|
|
assert.equal(cImportTypeShadowReadinessBody.targetReadiness.buildable, false);
|
|
assert.equal(cImportTypeShadowReadinessBody.targetReadiness.diagnostics[0].backendBlocker.unsupportedFeature, "ref<Self>");
|
|
const cImportLaterLocalReadiness = await execFileAsync(zero, ["check", "--json", "--emit", "obj", "conformance/native/pass/c-import-alias-later-local.0"]);
|
|
const cImportLaterLocalReadinessBody = JSON.parse(cImportLaterLocalReadiness.stdout);
|
|
assert.equal(cImportLaterLocalReadinessBody.ok, true);
|
|
assert.equal(cImportLaterLocalReadinessBody.targetReadiness.ok, true);
|
|
assert.equal(cImportLaterLocalReadinessBody.targetReadiness.buildable, true);
|
|
assert.equal(cImportLaterLocalReadinessBody.targetReadiness.diagnostics.length, 0);
|
|
const cImportMissingLinkReadiness = await execFileAsync(zero, ["check", "--json", "conformance/native/pass/c-import-alias-later-local.0"]);
|
|
const cImportMissingLinkReadinessBody = JSON.parse(cImportMissingLinkReadiness.stdout);
|
|
assert.equal(cImportMissingLinkReadinessBody.ok, true);
|
|
assert.equal(cImportMissingLinkReadinessBody.targetReadiness.ok, false);
|
|
assert.equal(cImportMissingLinkReadinessBody.targetReadiness.buildable, false);
|
|
assert.equal(cImportMissingLinkReadinessBody.targetReadiness.diagnostics[0].code, "CIMP005");
|
|
const cImportMissingLinkBuild = await execFileAsync(zero, ["build", "--json", "conformance/native/pass/c-import-alias-later-local.0", "--out", `.zero/out/c-import-missing-link-${process.pid}`]).catch((error) => error);
|
|
assert.notEqual(cImportMissingLinkBuild.code, 0);
|
|
assert.equal(JSON.parse(cImportMissingLinkBuild.stdout).diagnostics[0].code, "CIMP005");
|
|
|
|
const cImportPartialLinkRoot = `/tmp/zero-c-import-partial-link-${process.pid}`;
|
|
await rm(cImportPartialLinkRoot, { recursive: true, force: true });
|
|
await mkdir(`${cImportPartialLinkRoot}/src`, { recursive: true });
|
|
await mkdir(`${cImportPartialLinkRoot}/vendor/include`, { recursive: true });
|
|
await writeFile(`${cImportPartialLinkRoot}/vendor/include/a.h`, "int zero_a_add(int left, int right);\n");
|
|
await writeFile(`${cImportPartialLinkRoot}/vendor/include/b.h`, "int zero_b_add(int left, int right);\n");
|
|
await writeZeroToml(cImportPartialLinkRoot, {
|
|
package: { name: "c-import-partial-link", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "src/main.0" } },
|
|
c: { libs: {
|
|
a: { headers: ["vendor/include/a.h"], include: ["vendor/include"], lib: ["vendor/lib/a.o"], link: [], mode: "static" },
|
|
b: { headers: ["vendor/include/b.h"], include: ["vendor/include"], lib: [], link: [], mode: "static" }
|
|
} }
|
|
});
|
|
await writeFile(`${cImportPartialLinkRoot}/src/main.0`, `extern c "vendor/include/a.h" as a
|
|
extern c "vendor/include/b.h" as b
|
|
|
|
export c fn main() -> i32 {
|
|
return a.zero_a_add(1, 2) + b.zero_b_add(3, 4)
|
|
}
|
|
`);
|
|
await importPackageGraph(cImportPartialLinkRoot);
|
|
const cImportPartialLinkReadiness = await execFileAsync(zero, ["check", "--json", cImportPartialLinkRoot]);
|
|
const cImportPartialLinkReadinessBody = JSON.parse(cImportPartialLinkReadiness.stdout);
|
|
assert.equal(cImportPartialLinkReadinessBody.ok, true);
|
|
assert.equal(cImportPartialLinkReadinessBody.targetReadiness.ok, false);
|
|
assert.equal(cImportPartialLinkReadinessBody.targetReadiness.buildable, false);
|
|
assert.equal(cImportPartialLinkReadinessBody.targetReadiness.diagnostics[0].code, "CIMP005");
|
|
assert.match(cImportPartialLinkReadinessBody.targetReadiness.diagnostics[0].actual, /b\.h/);
|
|
const cImportPartialLinkBuild = await execFileAsync(zero, ["build", "--json", cImportPartialLinkRoot, "--out", `${cImportPartialLinkRoot}/partial-link`]).catch((error) => error);
|
|
assert.notEqual(cImportPartialLinkBuild.code, 0);
|
|
const cImportPartialLinkBuildBody = JSON.parse(cImportPartialLinkBuild.stdout);
|
|
assert.equal(cImportPartialLinkBuildBody.diagnostics[0].code, "CIMP005");
|
|
assert.match(cImportPartialLinkBuildBody.diagnostics[0].actual, /b\.h/);
|
|
await rm(cImportPartialLinkRoot, { recursive: true, force: true });
|
|
|
|
const externCallRoot = `/tmp/zero-extern-c-call-${process.pid}`;
|
|
const externCallShadowRoot = `/tmp/zero-extern-c-shadow-${process.pid}`;
|
|
const externCallScalarRoot = `/tmp/zero-extern-c-scalar-${process.pid}`;
|
|
await rm(externCallRoot, { recursive: true, force: true });
|
|
await rm(externCallShadowRoot, { recursive: true, force: true });
|
|
await rm(externCallScalarRoot, { recursive: true, force: true });
|
|
await mkdir(`${externCallRoot}/src`, { recursive: true });
|
|
await mkdir(`${externCallRoot}/vendor/include`, { recursive: true });
|
|
await mkdir(`${externCallRoot}/vendor/lib`, { recursive: true });
|
|
await mkdir(`${externCallShadowRoot}/vendor/include`, { recursive: true });
|
|
await mkdir(`${externCallScalarRoot}/src`, { recursive: true });
|
|
const externCallObjectRel = "vendor/lib/zero ext's.o";
|
|
const externCallDirtyObjectRel = "vendor/lib/zero_ext_dirty.o";
|
|
const externCallSymbolPrefix = process.platform === "darwin" ? "_" : "";
|
|
let externCallDirtyAsm = "";
|
|
if (process.arch === "x64") {
|
|
externCallDirtyAsm = `.text
|
|
.globl ${externCallSymbolPrefix}zero_ext_dirty_u8
|
|
${externCallSymbolPrefix}zero_ext_dirty_u8:
|
|
movq $257, %rax
|
|
ret
|
|
`;
|
|
} else if (process.arch === "arm64") {
|
|
externCallDirtyAsm = `.text
|
|
.globl ${externCallSymbolPrefix}zero_ext_dirty_u8
|
|
${externCallSymbolPrefix}zero_ext_dirty_u8:
|
|
movz x0, #257
|
|
ret
|
|
`;
|
|
}
|
|
await writeFile(`${externCallRoot}/vendor/include/zero_ext.h`, `#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
int
|
|
zero_ext_add(
|
|
int left,
|
|
int right
|
|
);
|
|
// int zero_ext_commented(int value);
|
|
/*
|
|
int zero_ext_block_commented(int value);
|
|
*/
|
|
#if 0
|
|
int zero_ext_disabled(int value);
|
|
#endif
|
|
int zero_ext_inline_left(int value); int zero_ext_inline_right(int value);
|
|
unsigned char zero_ext_dirty_u8(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
`);
|
|
await writeFile(`${externCallShadowRoot}/vendor/include/zero_ext.h`, "int zero_ext_wrong(int, int);\n");
|
|
await writeFile(`${externCallRoot}/vendor/lib/zero_ext.c`, '#include "zero_ext.h"\nint zero_ext_add(int a, int b) { return a + b; }\nint zero_ext_inline_left(int value) { return value + 1; }\nint zero_ext_inline_right(int value) { return value + 2; }\n');
|
|
await execFileAsync("cc", ["-I", `${externCallRoot}/vendor/include`, "-c", `${externCallRoot}/vendor/lib/zero_ext.c`, "-o", `${externCallRoot}/${externCallObjectRel}`]);
|
|
if (externCallDirtyAsm) {
|
|
await writeFile(`${externCallRoot}/vendor/lib/zero_ext_dirty.S`, externCallDirtyAsm);
|
|
await execFileAsync("cc", ["-c", `${externCallRoot}/vendor/lib/zero_ext_dirty.S`, "-o", `${externCallRoot}/${externCallDirtyObjectRel}`]);
|
|
}
|
|
await writeZeroToml(externCallRoot, {
|
|
package: { name: "extern-c-call", 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: [externCallObjectRel, ...(externCallDirtyAsm ? [externCallDirtyObjectRel] : [])], link: [], mode: "static" },
|
|
unused: { headers: ["vendor/include/unused.h"], include: ["vendor/include"], lib: ["vendor/lib/missing-unused.o"], link: [], mode: "static" }
|
|
} }
|
|
});
|
|
await writeZeroToml(externCallScalarRoot, {
|
|
package: { name: "extern-c-scalar", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "src/main.0" } },
|
|
c: { libs: { ext: { headers: [`${externCallRoot}/vendor/include/zero_ext.h`], include: [`${externCallRoot}/vendor/include`], lib: [`${externCallRoot}/${externCallObjectRel}`], link: [], mode: "static" } } }
|
|
});
|
|
await writeFile(`${externCallRoot}/src/main.0`, `extern c "vendor/include/zero_ext.h" as c
|
|
|
|
pub fn main(world: World) -> Void raises {
|
|
let total: i32 = c.zero_ext_add(20, 20) + c.zero_ext_inline_right(0)
|
|
if total == 42${externCallDirtyAsm ? " && c.zero_ext_dirty_u8() == 1_u8" : ""} {
|
|
check world.out.write("extern c call ok\\n")
|
|
} else {
|
|
check world.out.write("extern c call failed\\n")
|
|
}
|
|
}
|
|
`);
|
|
await writeFile(`${externCallRoot}/src/disabled.0`, `extern c "vendor/include/zero_ext.h" as c
|
|
|
|
pub fn main() -> i32 {
|
|
return c.zero_ext_disabled(1)
|
|
}
|
|
`);
|
|
await writeFile(`${externCallRoot}/src/commented.0`, `extern c "vendor/include/zero_ext.h" as c
|
|
|
|
pub fn main() -> i32 {
|
|
return c.zero_ext_commented(1)
|
|
}
|
|
`);
|
|
await writeFile(`${externCallScalarRoot}/src/main.0`, `extern c "${externCallRoot}/vendor/include/zero_ext.h" as c
|
|
|
|
export c fn main() -> i32 {
|
|
return c.zero_ext_add(20, 22)
|
|
}
|
|
`);
|
|
await importPackageGraph(externCallRoot);
|
|
await importPackageGraph(externCallScalarRoot);
|
|
const externCallShadowCheck = await execFileAsync(zero, ["check", "--json", externCallRoot], { cwd: externCallShadowRoot });
|
|
const externCallShadowCheckBody = JSON.parse(externCallShadowCheck.stdout);
|
|
assert.equal(externCallShadowCheckBody.ok, true);
|
|
const externCallDisabledCheck = await execFileAsync(zero, ["import", "--json", "--format", "binary", "--out", "src/disabled.graph", "src/disabled.0"], { cwd: externCallRoot }).catch((error) => error);
|
|
assert.notEqual(externCallDisabledCheck.code, 0);
|
|
const externCallDisabledCheckBody = JSON.parse(externCallDisabledCheck.stdout);
|
|
assert.equal(externCallDisabledCheckBody.diagnostics[0].code, "CIMP004");
|
|
const externCallCommentedCheck = await execFileAsync(zero, ["import", "--json", "--format", "binary", "--out", "src/commented.graph", "src/commented.0"], { cwd: externCallRoot }).catch((error) => error);
|
|
assert.notEqual(externCallCommentedCheck.code, 0);
|
|
const externCallCommentedCheckBody = JSON.parse(externCallCommentedCheck.stdout);
|
|
assert.equal(externCallCommentedCheckBody.diagnostics[0].code, "CIMP004");
|
|
assert.match(externCallCommentedCheckBody.diagnostics[0].message, /not declared/);
|
|
const externCallScalarCrossReadiness = await execFileAsync(zero, ["check", "--json", "--target", "linux-musl-arm64", externCallScalarRoot]);
|
|
const externCallScalarCrossReadinessBody = JSON.parse(externCallScalarCrossReadiness.stdout);
|
|
assert.equal(externCallScalarCrossReadinessBody.ok, true);
|
|
assert.equal(externCallScalarCrossReadinessBody.targetReadiness.ok, true);
|
|
assert.equal(externCallScalarCrossReadinessBody.targetReadiness.buildable, true);
|
|
assert.equal(externCallScalarCrossReadinessBody.targetReadiness.diagnostics.length, 0);
|
|
const externCallGraph = await execFileAsync(zero, ["inspect", "--json", externCallRoot]);
|
|
const externCallGraphBody = JSON.parse(externCallGraph.stdout);
|
|
const externCallImport = externCallGraphBody.cImports.find((item) => item.header === "vendor/include/zero_ext.h");
|
|
assert(externCallImport);
|
|
assert.equal(externCallImport.alias, "c");
|
|
assert.match(externCallImport.cache.headerHash, /^[0-9a-f]{16}$/);
|
|
assert(Array.isArray(externCallImport.typedModel.functions));
|
|
assert(!externCallImport.typedModel.functions.some((item) => item.name === "zero_ext_commented"));
|
|
assert(!externCallImport.typedModel.functions.some((item) => item.name === "zero_ext_block_commented"));
|
|
assert(!externCallImport.typedModel.functions.some((item) => item.name === "zero_ext_disabled"));
|
|
const externCallGraphSizeArtifact = `${externCallRoot}/extern-call-size-metadata.json`;
|
|
const externCallGraphSize = await execFileAsync(zero, ["size", "--json", "--out", externCallGraphSizeArtifact, externCallRoot]);
|
|
assert.equal(JSON.parse(externCallGraphSize.stdout).graph.moduleIdentity, "package:extern-c-call@0.1.0");
|
|
const externCallBuildOut = `${externCallRoot}/extern-call`;
|
|
const externCallBuild = await execFileAsync(zero, ["build", "--json", externCallRoot, "--out", externCallBuildOut]);
|
|
const externCallBuildBody = JSON.parse(externCallBuild.stdout);
|
|
assert.equal(externCallBuildBody.emit, "exe");
|
|
assert.notEqual(externCallBuildBody.objectBackend.objectEmission.path, "none");
|
|
assert.notEqual(externCallBuildBody.objectBackend.linking.externalToolchain, "none");
|
|
assert.match(externCallBuildBody.objectBackend.linking.targetLibraries, /zero-runtime/);
|
|
assert.match(externCallBuildBody.objectBackend.linking.targetLibraries, /c-imports/);
|
|
assert(externCallBuildBody.objectBackend.linkerPlan.staticLibraries.some((item) => item.endsWith(externCallObjectRel)));
|
|
if (externCallDirtyAsm) assert(externCallBuildBody.objectBackend.linkerPlan.staticLibraries.some((item) => item.endsWith(externCallDirtyObjectRel)));
|
|
assert(!externCallBuildBody.objectBackend.linkerPlan.staticLibraries.some((item) => item.endsWith("vendor/lib/missing-unused.o")));
|
|
const externCallObjectOverhead = externCallBuildBody.objectBackend.linking.objectFormat === "coff"
|
|
? (externCallBuildBody.objectBackend.objectEmission.dataSections ? 2 : 1)
|
|
: (externCallBuildBody.objectBackend.objectEmission.dataSections ? 1 : 0);
|
|
const externCallExpectedExternalSymbols = externCallDirtyAsm ? 3 : 2;
|
|
assert.equal(
|
|
externCallBuildBody.objectBackend.objectEmission.symbolCount,
|
|
externCallBuildBody.objectBackend.directFacts.functionCount +
|
|
externCallBuildBody.objectBackend.directFacts.runtimeHelperCount +
|
|
externCallExpectedExternalSymbols +
|
|
externCallObjectOverhead
|
|
);
|
|
assert.equal(externCallBuildBody.releaseTargetContract.selectedEmitter, externCallBuildBody.releaseTargetContract.directObjectEmitter);
|
|
assert.equal(externCallBuildBody.releaseTargetContract.libc.artifactMode, externCallBuildBody.releaseTargetContract.libc.targetMode);
|
|
const externCallRun = await execFileAsync(zero, ["run", externCallRoot]);
|
|
assert.equal(externCallRun.stdout, "extern c call ok\n");
|
|
const externCallScalarBuildOut = `${externCallScalarRoot}/extern-scalar`;
|
|
const externCallScalarBuild = await execFileAsync(zero, ["build", "--json", externCallScalarRoot, "--out", externCallScalarBuildOut]);
|
|
const externCallScalarBuildBody = JSON.parse(externCallScalarBuild.stdout);
|
|
assert.equal(externCallScalarBuildBody.emit, "exe");
|
|
assert.match(externCallScalarBuildBody.objectBackend.linking.targetLibraries, /c-imports/);
|
|
assert.doesNotMatch(externCallScalarBuildBody.objectBackend.linking.targetLibraries, /zero-runtime/);
|
|
assert.notEqual(externCallScalarBuildBody.objectBackend.linking.externalToolchain, "none");
|
|
assert(!externCallScalarBuildBody.objectBackend.linkerPlan.staticLibraries.some((item) => item === "zero_runtime.o"));
|
|
assert(externCallScalarBuildBody.objectBackend.linkerPlan.staticLibraries.some((item) => item.endsWith(externCallObjectRel)));
|
|
assert.equal(externCallScalarBuildBody.releaseTargetContract.selectedEmitter, externCallScalarBuildBody.releaseTargetContract.directObjectEmitter);
|
|
assert.equal(externCallScalarBuildBody.releaseTargetContract.libc.artifactMode, externCallScalarBuildBody.releaseTargetContract.libc.targetMode);
|
|
await rm(externCallRoot, { recursive: true, force: true });
|
|
await rm(externCallShadowRoot, { recursive: true, force: true });
|
|
await rm(externCallScalarRoot, { recursive: true, force: true });
|
|
|
|
const unsafeExternLinkRoot = `/tmp/zero-extern-c-unsafe-link-${process.pid}`;
|
|
await rm(unsafeExternLinkRoot, { recursive: true, force: true });
|
|
await mkdir(`${unsafeExternLinkRoot}/src`, { recursive: true });
|
|
await mkdir(`${unsafeExternLinkRoot}/vendor/include`, { recursive: true });
|
|
await writeFile(`${unsafeExternLinkRoot}/vendor/include/zero_ext.h`, "int zero_ext_add(int left, int right);\n");
|
|
await writeZeroToml(unsafeExternLinkRoot, {
|
|
package: { name: "extern-c-unsafe-link", 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: ["zero_ext;touch"], mode: "static" } } }
|
|
});
|
|
await writeFile(`${unsafeExternLinkRoot}/src/main.0`, `extern c "vendor/include/zero_ext.h" as c
|
|
|
|
pub fn main() -> i32 {
|
|
return c.zero_ext_add(20, 22)
|
|
}
|
|
`);
|
|
await importPackageGraph(unsafeExternLinkRoot);
|
|
const unsafeExternLinkReadiness = await execFileAsync(zero, ["check", "--json", unsafeExternLinkRoot]);
|
|
const unsafeExternLinkReadinessBody = JSON.parse(unsafeExternLinkReadiness.stdout);
|
|
assert.equal(unsafeExternLinkReadinessBody.ok, true);
|
|
assert.equal(unsafeExternLinkReadinessBody.targetReadiness.buildable, false);
|
|
assert.equal(unsafeExternLinkReadinessBody.targetReadiness.diagnostics[0].code, "CIMP005");
|
|
assert.match(unsafeExternLinkReadinessBody.targetReadiness.diagnostics[0].actual, /unsafe library name/);
|
|
const unsafeExternLinkBuild = await execFileAsync(zero, ["build", "--json", unsafeExternLinkRoot, "--out", `${unsafeExternLinkRoot}/extern-link`]).catch((error) => error);
|
|
assert.notEqual(unsafeExternLinkBuild.code, 0);
|
|
assert.equal(JSON.parse(unsafeExternLinkBuild.stdout).diagnostics[0].code, "CIMP005");
|
|
await rm(unsafeExternLinkRoot, { recursive: true, force: true });
|
|
|
|
const runtimeManifestRoot = `/tmp/zero-runtime-manifest-link-${process.pid}`;
|
|
await rm(runtimeManifestRoot, { recursive: true, force: true });
|
|
await mkdir(`${runtimeManifestRoot}/src`, { recursive: true });
|
|
await writeZeroToml(runtimeManifestRoot, {
|
|
package: { name: "runtime-manifest-link", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "src/main.0" } },
|
|
c: { libs: { unused: { headers: ["vendor/include/unused.h"], include: ["vendor/include"], lib: ["vendor/lib/missing.o"], link: ["zero_missing_system"], mode: "static" } } }
|
|
});
|
|
await writeFile(`${runtimeManifestRoot}/src/main.0`, `pub fn main(world: World) -> Void raises {
|
|
check world.out.write("runtime manifest ignored\\n")
|
|
}
|
|
`);
|
|
await importPackageGraph(runtimeManifestRoot);
|
|
const runtimeManifestBuildOut = `${runtimeManifestRoot}/runtime-manifest`;
|
|
const runtimeManifestBuild = await execFileAsync(zero, ["build", "--json", runtimeManifestRoot, "--out", runtimeManifestBuildOut]);
|
|
const runtimeManifestBuildBody = JSON.parse(runtimeManifestBuild.stdout);
|
|
assert(!runtimeManifestBuildBody.objectBackend.linkerPlan.staticLibraries.some((item) => item.endsWith("vendor/lib/missing.o")));
|
|
assert(!runtimeManifestBuildBody.objectBackend.linkerPlan.systemLibraries.includes("zero_missing_system"));
|
|
const runtimeManifestRun = await execFileAsync(zero, ["run", runtimeManifestRoot]);
|
|
assert.equal(runtimeManifestRun.stdout, "runtime manifest ignored\n");
|
|
await rm(runtimeManifestRoot, { recursive: true, force: true });
|
|
|
|
const cInteropGraph = await execFileAsync(zero, ["inspect", "--json", "examples/c-interop"]);
|
|
const cInteropGraphBody = JSON.parse(cInteropGraph.stdout);
|
|
const mathLib = cInteropGraphBody.cLibraries.find((item) => item.name === "math");
|
|
assert(mathLib);
|
|
assert.equal(mathLib.linkMode, "static");
|
|
assert.equal(mathLib.targetValidation.vendoredLibraries, true);
|
|
assert.equal(mathLib.targetValidation.vendoredHeaders, true);
|
|
assert.equal(mathLib.targetValidation.pkgConfigTargetSafe, true);
|
|
const cInteropCrossGraph = await execFileAsync(zero, ["inspect", "--json", "--target", "linux-musl-x64", "examples/c-interop"]);
|
|
const cInteropCrossGraphBody = JSON.parse(cInteropCrossGraph.stdout);
|
|
assert.equal(cInteropCrossGraphBody.cLibraries[0].targetValidation.pkgConfigTargetSafe, true);
|
|
assert.equal(cInteropCrossGraphBody.cLibraries[0].targetValidation.implicitHostDiscovery, false);
|
|
assert.equal(cInteropCrossGraphBody.cLibraries[0].linkPlan.hostDiscovery, "none");
|
|
const hostLeakGraph = await execFileAsync(zero, ["inspect", "--json", "--target", "linux-musl-x64", "conformance/c/host-leak-package"]);
|
|
const hostLeakGraphBody = JSON.parse(hostLeakGraph.stdout);
|
|
assert.equal(hostLeakGraphBody.cLibraries[0].targetValidation.hostHeaderLeakage, true);
|
|
assert.equal(hostLeakGraphBody.cLibraries[0].targetValidation.implicitHostDiscovery, true);
|
|
assert.equal(hostLeakGraphBody.cLibraries[0].targetValidation.status, "blocked");
|
|
const hostLeakReadiness = await execFileAsync(zero, ["check", "--json", "--target", "linux-musl-x64", "conformance/c/host-leak-package"]);
|
|
const hostLeakReadinessBody = JSON.parse(hostLeakReadiness.stdout);
|
|
assert.equal(hostLeakReadinessBody.ok, true);
|
|
assert.equal(hostLeakReadinessBody.diagnostics.length, 0);
|
|
assert.equal(hostLeakReadinessBody.targetReadiness.ok, false);
|
|
assert.equal(hostLeakReadinessBody.targetReadiness.buildable, false);
|
|
assert.equal(hostLeakReadinessBody.targetReadiness.diagnostics[0].code, "CIMP003");
|
|
assert.match(hostLeakReadinessBody.targetReadiness.diagnostics[0].help, /target sysroot|vendored/);
|
|
const hostLeakBuild = await execFileAsync(zero, ["build", "--json", "--target", "linux-musl-x64", "conformance/c/host-leak-package", "--out", ".zero/out/host-leak-package"], { encoding: "utf8" }).catch((error) => error);
|
|
assert.notEqual(hostLeakBuild.code, 0);
|
|
const hostLeakBuildBody = JSON.parse(hostLeakBuild.stdout);
|
|
assert.equal(hostLeakBuildBody.diagnostics[0].code, "CIMP003");
|
|
assert.match(hostLeakBuildBody.diagnostics[0].help, /target sysroot|vendored/);
|
|
|
|
const depGraph = await execFileAsync(zero, ["inspect", "--json", "--target", "linux-musl-x64", "conformance/packages/dep-app"]);
|
|
const depGraphBody = JSON.parse(depGraph.stdout);
|
|
assert.equal(depGraphBody.package.name, "dep-app");
|
|
assert.equal(depGraphBody.package.version, "0.1.0");
|
|
assert.equal(depGraphBody.package.resolver.deterministic, true);
|
|
assert.match(depGraphBody.package.lockfile.path, /\.zero\/package-locks\/[0-9a-f]+\.lock\.json/);
|
|
assert(depGraphBody.package.dependencies.some((item) => item.name === "dep-lib" && item.status === "path-resolved" && item.targetCompatible === true));
|
|
assert(depGraphBody.package.dependencies.some((item) => item.name === "remote-tools" && item.status === "registry-reference" && item.version === "1.2.3"));
|
|
assert.equal(depGraphBody.packageCache.cacheKeyInputs.compilerVersion, "0.3.4");
|
|
assert.equal(depGraphBody.packageCache.cacheKeyInputs.packageVersion, "0.1.0");
|
|
assert.match(depGraphBody.packageCache.cacheKeyInputs.dependencyGraphHash, /^[0-9a-f]{16}$/);
|
|
const depDoc = await execFileAsync(zero, ["doc", "--json", "conformance/packages/dep-app"]);
|
|
const depDocBody = JSON.parse(depDoc.stdout);
|
|
assert.equal(depDocBody.package.name, "dep-app");
|
|
assert.equal(depDocBody.publicationGate.requiresExamplesForPublicApi, true);
|
|
assert.equal(depDocBody.packageCache.cacheKeyInputs.packageVersion, "0.1.0");
|
|
const depBuild = await execFileAsync(zero, ["build", "--json", "--target", "linux-musl-x64", "conformance/packages/dep-app", "--out", ".zero/out/dep-app"]);
|
|
const depBuildBody = JSON.parse(depBuild.stdout);
|
|
assert.equal(depBuildBody.package.dependencies.length, 2);
|
|
assert.equal(depBuildBody.packageCache.invalidationReasons.includes("dependency graph changed"), true);
|
|
assert.match(depBuildBody.compilerCaches[0].dependencyGraphHash, /^[0-9a-f]{16}$/);
|
|
|
|
const malformedTomlArrayRoot = `${outDir}/malformed-toml-array`;
|
|
await rm(malformedTomlArrayRoot, { recursive: true, force: true });
|
|
await mkdir(malformedTomlArrayRoot, { recursive: true });
|
|
await writeFile(`${malformedTomlArrayRoot}/zero.toml`, `[package]
|
|
name = "malformed-toml-array"
|
|
version = "0.1.0"
|
|
|
|
[targets.cli]
|
|
kind = "exe"
|
|
main = "src/main.0"
|
|
|
|
[c.libs.demo]
|
|
headers = ["unterminated]
|
|
`);
|
|
const malformedTomlArrayStatus = await execFileAsync(zero, ["status", "--json", malformedTomlArrayRoot]);
|
|
const malformedTomlArrayBody = JSON.parse(malformedTomlArrayStatus.stdout);
|
|
assert.equal(malformedTomlArrayBody.ok, true);
|
|
assert.equal(malformedTomlArrayBody.repositoryGraph.storePresent, false);
|
|
assert.deepEqual(malformedTomlArrayBody.diagnostics, []);
|
|
|
|
const zeroTestRun = await execFileAsync(zero, ["test", "conformance/native/pass/test-blocks.0"]);
|
|
assert.equal(zeroTestRun.stdout, "1 test(s) ok\n");
|
|
|
|
const zeroTestingHelpersRun = await execFileAsync(zero, ["test", "conformance/native/pass/std-testing-helpers-test.0"]);
|
|
assert.equal(zeroTestingHelpersRun.stdout, "1 test(s) ok\n");
|
|
|
|
const zeroTestJsonRun = await execFileAsync(zero, ["test", "--json", "--filter", "addition", "conformance/native/pass/test-blocks.0"]);
|
|
const zeroTestJsonBody = JSON.parse(zeroTestJsonRun.stdout);
|
|
assert.equal(zeroTestJsonBody.ok, true);
|
|
assert.equal(zeroTestJsonBody.discoveredTests, 1);
|
|
assert.equal(zeroTestJsonBody.selectedTests, 1);
|
|
assert.equal(zeroTestJsonBody.passedTests, 1);
|
|
assert.equal(zeroTestJsonBody.graph.artifact, "conformance/native/pass/test-blocks.graph");
|
|
assert.equal(zeroTestJsonBody.graph.canonicalSource, false);
|
|
assert.equal(zeroTestJsonBody.graph.moduleIdentity, "module:test-blocks");
|
|
assert.equal(zeroTestJsonBody.graph.lowering, "direct-program-graph");
|
|
assert.equal(zeroTestJsonBody.testDiscovery.mode, "program-graph");
|
|
assert.equal(zeroTestJsonBody.testDiscovery.filter, "addition");
|
|
assert.equal(zeroTestJsonBody.fixtures.snapshotKey, "zero-test-graph-native-v1");
|
|
assert.equal(zeroTestJsonBody.results[0].status, "passed");
|
|
|
|
const zeroPtyTargetCapTest = await execFileAsync(zero, ["test", "--json", "--filter", "pty target", "--target", "linux-arm64", "conformance/check/pass/test-target-proc-caps.graph"]).catch((error) => error);
|
|
assert.notEqual(zeroPtyTargetCapTest.code, 0);
|
|
const zeroPtyTargetCapBody = JSON.parse(zeroPtyTargetCapTest.stdout);
|
|
assert.equal(zeroPtyTargetCapBody.ok, false);
|
|
assert.equal(zeroPtyTargetCapBody.diagnostics[0].code, "PAR100");
|
|
assert.match(zeroPtyTargetCapBody.diagnostics[0].actual, /lacks proc/);
|
|
|
|
const zeroTermTargetCapTest = await execFileAsync(zero, ["test", "--json", "--filter", "term target", "--target", "linux-arm64", "conformance/check/pass/test-target-proc-caps.graph"]).catch((error) => error);
|
|
assert.notEqual(zeroTermTargetCapTest.code, 0);
|
|
const zeroTermTargetCapBody = JSON.parse(zeroTermTargetCapTest.stdout);
|
|
assert.equal(zeroTermTargetCapBody.ok, false);
|
|
assert.equal(zeroTermTargetCapBody.diagnostics[0].code, "PAR100");
|
|
assert.match(zeroTermTargetCapBody.diagnostics[0].actual, /lacks proc/);
|
|
|
|
const zeroPackageTestJsonRun = await execFileAsync(zero, ["test", "--json", "conformance/packages/test-app"]);
|
|
const zeroPackageTestBody = JSON.parse(zeroPackageTestJsonRun.stdout);
|
|
assert.equal(zeroPackageTestBody.ok, true);
|
|
assert.equal(zeroPackageTestBody.graph.artifact, "conformance/packages/test-app/zero.graph");
|
|
assert.equal(zeroPackageTestBody.graph.canonicalSource, false);
|
|
assert.equal(zeroPackageTestBody.graph.moduleIdentity, "package:test-app@0.1.0");
|
|
assert.equal(zeroPackageTestBody.graph.lowering, "direct-program-graph");
|
|
assert.equal(zeroPackageTestBody.testDiscovery.mode, "package-graph");
|
|
assert.equal(zeroPackageTestBody.discoveredTests, 3);
|
|
assert.equal(zeroPackageTestBody.selectedTests, 3);
|
|
assert.equal(zeroPackageTestBody.expectedFailures, 1);
|
|
assert(zeroPackageTestBody.fixtures.sourceFiles.some((path) => path.endsWith("helper.0")));
|
|
|
|
const zeroExpectedFailJsonRun = await execFileAsync(zero, ["test", "--json", "conformance/native/pass/test-expected-fail.0"]);
|
|
const zeroExpectedFailBody = JSON.parse(zeroExpectedFailJsonRun.stdout);
|
|
assert.equal(zeroExpectedFailBody.ok, true);
|
|
assert.equal(zeroExpectedFailBody.expectedFailures, 1);
|
|
assert.equal(zeroExpectedFailBody.failedTests, 0);
|
|
assert.equal(zeroExpectedFailBody.results[0].status, "expected-fail");
|
|
|
|
const fmtRun = await execFileAsync(zero, ["fmt", "conformance/native/pass/test-blocks.0"]);
|
|
assert.equal(fmtRun.stdout, await readFile("conformance/native/pass/test-blocks.0", "utf8"));
|
|
|
|
const fmtFallibilityRun = await execFileAsync(zero, ["fmt", "conformance/native/pass/fallibility-check-value.0"]);
|
|
assert.equal(fmtFallibilityRun.stdout, await readFile("conformance/native/pass/fallibility-check-value.0", "utf8"));
|
|
|
|
const fmtImportsRun = await execFileAsync(zero, ["fmt", "conformance/check/pass/imports/src/main.0"]);
|
|
assert.match(fmtImportsRun.stdout, /use math/);
|
|
assert.match(fmtImportsRun.stdout, /use types/);
|
|
|
|
const fmtCoreRun = await execFileAsync(zero, ["fmt", "conformance/check/pass/fmt-core-usability.0"]);
|
|
assert.equal(fmtCoreRun.stdout, await readFile("conformance/check/pass/fmt-core-usability.0", "utf8"));
|
|
|
|
const fmtMessyRun = await execFileAsync(zero, ["fmt", "conformance/format/messy.0"]);
|
|
assert.equal(fmtMessyRun.stdout, await readFile("conformance/format/messy.0", "utf8"));
|
|
|
|
const fmtIdempotentPath = `${outDir}/fmt-idempotent.0`;
|
|
await writeFile(fmtIdempotentPath, fmtMessyRun.stdout);
|
|
const fmtIdempotentRun = await execFileAsync(zero, ["fmt", fmtIdempotentPath]);
|
|
assert.equal(fmtIdempotentRun.stdout, fmtMessyRun.stdout);
|
|
|
|
const fmtFunctionsBlocksRun = await execFileAsync(zero, ["fmt", "conformance/format/functions-blocks.0"]);
|
|
assert.equal(fmtFunctionsBlocksRun.stdout, await readFile("conformance/format/functions-blocks.0", "utf8"));
|
|
|
|
const fmtGenericsStaticRun = await execFileAsync(zero, ["fmt", "conformance/format/generics-static.0"]);
|
|
assert.equal(fmtGenericsStaticRun.stdout, await readFile("conformance/format/generics-static.0", "utf8"));
|
|
|
|
const fmtMatchRun = await execFileAsync(zero, ["fmt", "conformance/format/match-expressions.0"]);
|
|
assert.equal(fmtMatchRun.stdout, await readFile("conformance/format/match-expressions.0", "utf8"));
|
|
|
|
const helloRunArgs = runnableExeArgs("conformance/run/pass/hello.0", `${outDir}/hello`);
|
|
if (helloRunArgs) {
|
|
await rm(`${outDir}/hello`, { force: true });
|
|
await execFileAsync(zero, helloRunArgs);
|
|
const run = await execFileAsync(`${outDir}/hello`, []);
|
|
assert.match(run.stdout, /hello conformance/);
|
|
}
|
|
|
|
const packageGraphJson = await execFileAsync(zero, ["inspect", "--json", "conformance/check/pass/package"]);
|
|
const packageGraph = JSON.parse(packageGraphJson.stdout);
|
|
assert.deepEqual(packageGraph.sourceFiles.sort(), [
|
|
"src/main.0",
|
|
"src/types.0",
|
|
"std/codec.0",
|
|
]);
|
|
assert(packageGraph.requiresCapabilities.includes("codec"));
|
|
assert(packageGraph.requiresCapabilities.includes("parse"));
|
|
assert(packageGraph.requiresCapabilities.includes("time"));
|
|
assert.equal(packageGraph.selfHostRouting.cBridge.policy, "removed");
|
|
|
|
for (const runtimeFixture of [
|
|
["conformance/native/pass/break-continue.0", "break-continue", { stdout: "loop tick\nloop tick\n" }],
|
|
["conformance/native/pass/nested-break-continue.0", "nested-break-continue", { stdout: "inner tick\ninner tick\nouter tick\ninner tick\ninner tick\nnested break continue ok\n" }],
|
|
["conformance/native/pass/mutref-shape-param.0", "mutref-shape-param", { stdout: "mutref x ok\nmutref y ok\nref sum ok\n" }],
|
|
["conformance/native/pass/mutref-shape-param-nested.0", "mutref-shape-param-nested", { stdout: "nested count ok\nnested total ok\nnested flag ok\nnested copy ok\nnested bytes ok\ngeneric mutref ok\n" }],
|
|
["conformance/native/pass/untyped-literal-adoption.0", "untyped-literal-adoption", { stdout: "usize literal adoption ok\nflipped literal adoption ok\nliteral arithmetic adoption ok\nu8 literal adoption ok\n" }],
|
|
["conformance/native/pass/for-range.0", "for-range", { stdout: "range tick\nrange tick\nrange tick\n" }],
|
|
["conformance/native/pass/match-payload-binding.0", "match-payload-binding", { stdout: /payload binding ok/ }],
|
|
["conformance/native/pass/match-fallback.0", "match-fallback", { stdout: "match fallback ok\n" }],
|
|
["conformance/native/pass/match-choice-fallback.0", "match-choice-fallback", { stdout: "choice fallback ok\n" }],
|
|
["conformance/native/pass/null-maybe.0", "null-maybe", { stdout: /null maybe ok/ }],
|
|
["conformance/native/pass/maybe-local-null-init-return.0", "maybe-local-null-init-return", { stdout: "maybe local found 42\nmaybe local none\nmaybe local sum 5\n" }],
|
|
["conformance/native/pass/top-level-const.0", "top-level-const", { stdout: "const ok\n" }],
|
|
["conformance/native/pass/const-arithmetic.0", "const-arithmetic", { stdout: "const arithmetic ok\n" }],
|
|
["conformance/native/pass/std-args.0", "std-args", { stdout: "alpha\n", args: ["alpha", "beta"] }],
|
|
["conformance/native/pass/std-env.0", "std-env", { stdout: "env ok\n", env: { ZERO_CONFORMANCE_ENV: "agent-env", ZERO_CONFORMANCE_ENV_DELTA: "-3", ZERO_CONFORMANCE_ENV_WORKERS: "5" } }],
|
|
["conformance/native/pass/std-hosted-cli.0", "std-hosted-cli", { stdout: "std hosted cli ok\n", args: ["run", "7", "--json", "--name", "agent", "--count", "3", "--enabled", "false", "--delta", "-5", "--size", "9"], env: { ZERO_CONFORMANCE_MODE: "test", ZERO_CONFORMANCE_VERBOSE: "true", ZERO_CONFORMANCE_LIMIT: "9" } }],
|
|
["conformance/native/pass/std-proc-helpers.0", "std-proc-helpers", { stdout: "std proc helpers ok\n" }],
|
|
["conformance/native/pass/std-proc-capture.0", "std-proc-capture", { stdout: "std proc capture ok\n" }],
|
|
["conformance/native/pass/std-proc-capture-files.0", "std-proc-capture-files", { stdout: "std proc capture files ok\n" }],
|
|
["conformance/native/pass/std-proc-child.0", "std-proc-child", { stdout: "std proc child ok\n" }],
|
|
["conformance/native/pass/std-pty-child.0", "std-pty-child", { stdout: "std pty child ok\n" }],
|
|
["conformance/native/pass/std-proc-child-cwd.0", "std-proc-child-cwd", { stdout: "std proc child cwd ok\n" }],
|
|
["conformance/native/pass/std-proc-spawn-inherit.0", "std-proc-spawn-inherit", { stdout: "inherit-out status-ok\n" }],
|
|
["conformance/native/pass/std-fs.0", "std-fs", { stdout: "fs ok\n", file: { name: "std-fs-write.txt", text: "zero write\n" } }],
|
|
["conformance/native/pass/std-fs-bytes.0", "std-fs-bytes", { stdout: "fs bytes ok\n", stderr: "fs bytes err ok\n" }],
|
|
["conformance/native/pass/std-fs-write-file-bool.0", "std-fs-write-file-bool", { stdout: "fs write file bool ok\n" }],
|
|
["conformance/native/pass/std-fs-append-bytes.0", "std-fs-append-bytes", { stdout: "fs append ok\n" }],
|
|
["conformance/native/pass/std-fs-direct-return.0", "std-fs-direct-return", { stdout: "fs direct return ok\n" }],
|
|
["conformance/native/pass/std-fs-read-chunks.0", "std-fs-read-chunks", { stdout: "fs read chunks ok\n" }],
|
|
["conformance/native/pass/frame-large-locals.0", "frame-large-locals", { stdout: "frame large locals ok alpha\n", args: ["alpha"] }],
|
|
["conformance/native/pass/frame-limit-boundary.0", "frame-limit-boundary", { stdout: "frame limit boundary ok\n" }],
|
|
["conformance/native/pass/frame-split-helpers.0", "frame-split-helpers", { stdout: "frame split helpers ok\n" }],
|
|
["conformance/native/pass/fixed-buf-alloc-local.0", "fixed-buf-alloc-local", { stdout: "fixed buf alloc local ok\n" }],
|
|
["conformance/native/pass/std-fs-resource.0", "std-fs-resource", { stdout: "fs resource ok\n", file: { name: "std-fs-resource.txt", text: "zero file\n" } }],
|
|
["conformance/native/pass/std-fs-file-helpers.0", "std-fs-file-helpers", { stdout: "std fs file helpers ok\n" }],
|
|
["conformance/native/pass/std-io-lines.0", "std-io-lines", { stdout: "std io lines ok\n" }],
|
|
["conformance/native/pass/integer-widths.0", "integer-widths", { stdout: "integer widths ok\n" }],
|
|
["conformance/native/pass/std-codec-widths.0", "std-codec-widths", { stdout: "codec widths ok\n" }],
|
|
["conformance/native/pass/std-csv.0", "std-csv", { stdout: "std csv ok\n" }],
|
|
["conformance/native/pass/std-diag.0", "std-diag", { stdout: "std diag ok\n" }],
|
|
["conformance/native/pass/std-codec-json-url.0", "std-codec-json-url", { stdout: "std codec json url ok\n" }],
|
|
["conformance/native/pass/std-json-cursors.0", "std-json-cursors", { stdout: "std json cursors ok\n" }],
|
|
["conformance/native/pass/std-crypto-hmac32.0", "std-crypto-hmac32", { stdout: "crypto hmac32 ok\n" }],
|
|
["conformance/native/pass/std-crypto-sha256.0", "std-crypto-sha256", { stdout: "crypto sha256 ok\n" }],
|
|
["conformance/native/pass/parse-integers.0", "parse-integers", { stdout: "parse integers ok\n" }],
|
|
["conformance/native/pass/std-parse-text.0", "std-parse-text", { stdout: "std parse text ok\n" }],
|
|
["conformance/native/pass/explicit-casts.0", "explicit-casts", { stdout: "explicit casts ok\n" }],
|
|
["conformance/native/pass/float-char-casts.0", "float-char-casts", { stdout: "float char casts ok\n" }],
|
|
["conformance/native/pass/radix-suffix-literals.0", "radix-suffix-literals", { stdout: "radix suffix literals ok\n" }],
|
|
["conformance/native/pass/char-literals.0", "char-literals", { stdout: "char literals ok\n" }],
|
|
["conformance/native/pass/float-primitives.0", "float-primitives", { stdout: "float primitives ok\n" }],
|
|
["conformance/native/pass/recursive-fibonacci.0", "recursive-fibonacci", { stdout: "recursive fibonacci ok\n" }],
|
|
["conformance/native/pass/mutual-recursion.0", "mutual-recursion", { stdout: "mutual recursion ok\n" }],
|
|
["conformance/native/pass/scratch-nested-index.0", "scratch-nested-index", { stdout: "scratch nested index ok\n" }],
|
|
["conformance/native/pass/checked-bounds-get.0", "checked-bounds-get", { stdout: "checked bounds get ok\n" }],
|
|
["conformance/native/pass/check-maybe-fallibility.0", "check-maybe-fallibility", { stdout: "check maybe fallibility ok\n" }],
|
|
["conformance/native/pass/fallibility-error-sets.0", "fallibility-error-sets", { stdout: "fallibility error sets ok\n" }],
|
|
["conformance/native/pass/rescue-check.0", "rescue-check", { stdout: "rescue ok\n" }],
|
|
["conformance/native/pass/std-fs-fallible.0", "std-fs-fallible", { stdout: "fs named errors ok\n" }],
|
|
["conformance/native/pass/std-fs-fallible-resources.0", "std-fs-fallible-resources", { stdout: "fs fallible resources ok\n" }],
|
|
["conformance/native/pass/std-cli-helpers.0", "std-cli-helpers", { stdout: "cli helpers ok\n" }],
|
|
["conformance/native/pass/std-mem-copy-fill.0", "std-mem-copy-fill", { stdout: "mem copy fill ok\n" }],
|
|
["conformance/native/pass/const-layout.0", "const-layout", { stdout: "const layout ok\n" }],
|
|
["conformance/native/pass/c-abi-export.0", "c-abi-export", { stdout: "c abi export ok\n" }],
|
|
]) {
|
|
await assertDirectRuntimeOrUnsupported(...runtimeFixture);
|
|
}
|
|
|
|
await assertDirectRuntimeRequired("conformance/native/pass/untyped-literal-adoption.0", "untyped-literal-adoption-required", { stdout: "usize literal adoption ok\nflipped literal adoption ok\nliteral arithmetic adoption ok\nu8 literal adoption ok\n" });
|
|
|
|
await assertDirectRuntimeRequired("conformance/native/pass/recursive-multi-call-let.0", "recursive-multi-call-let-required", { stdout: "recursive multi call ok\n" });
|
|
|
|
const literalAdoptionInitOverflowFixture = `${outDir}/untyped-literal-adoption-init-overflow.0`;
|
|
const literalAdoptionInitOverflowBody = await writeImportFailureFixture(literalAdoptionInitOverflowFixture, `pub fn main(world: World) -> Void raises {
|
|
var small: u8 = 300
|
|
check world.out.write("unreachable\\n")
|
|
}
|
|
`);
|
|
assert.equal(literalAdoptionInitOverflowBody.diagnostics[0].code, "TYP016");
|
|
assert.equal(literalAdoptionInitOverflowBody.diagnostics[0].expected, "u8");
|
|
assert.equal(literalAdoptionInitOverflowBody.diagnostics[0].actual, "300 overflows u8");
|
|
|
|
const literalAdoptionCompareOverflowFixture = `${outDir}/untyped-literal-adoption-compare-overflow.0`;
|
|
const literalAdoptionCompareOverflowBody = await writeImportFailureFixture(literalAdoptionCompareOverflowFixture, `pub fn main(world: World) -> Void raises {
|
|
var small: u8 = 7
|
|
if 300 > small {
|
|
check world.out.write("unreachable\\n")
|
|
}
|
|
}
|
|
`);
|
|
assert.equal(literalAdoptionCompareOverflowBody.diagnostics[0].code, "TYP016");
|
|
assert.equal(literalAdoptionCompareOverflowBody.diagnostics[0].expected, "u8");
|
|
assert.equal(literalAdoptionCompareOverflowBody.diagnostics[0].actual, "300 overflows u8");
|
|
assert.match(literalAdoptionCompareOverflowBody.diagnostics[0].help, /smaller literal or a wider integer type/);
|
|
|
|
const fixedArrayRepeatLengthFixture = `${outDir}/fixed-array-repeat-length-mismatch.0`;
|
|
const fixedArrayRepeatLengthBody = await writeImportFailureFixture(fixedArrayRepeatLengthFixture, `pub fn main(world: World) -> Void raises {
|
|
var b: [64]u8 = [0_u8; 32]
|
|
b[0] = 1
|
|
check world.out.write("unreachable\\n")
|
|
}
|
|
`);
|
|
assert.equal(fixedArrayRepeatLengthBody.diagnostics[0].code, "TYP002");
|
|
assert.equal(fixedArrayRepeatLengthBody.diagnostics[0].expected, "[64]u8");
|
|
assert.equal(fixedArrayRepeatLengthBody.diagnostics[0].actual, "repeat count 32");
|
|
assert.match(fixedArrayRepeatLengthBody.diagnostics[0].help, /make the lengths agree/);
|
|
|
|
const fixedArrayListLengthFixture = `${outDir}/fixed-array-list-length-mismatch.0`;
|
|
const fixedArrayListLengthBody = await writeImportFailureFixture(fixedArrayListLengthFixture, `pub fn main(world: World) -> Void raises {
|
|
var b: [4]u8 = [1, 2]
|
|
b[0] = 1
|
|
check world.out.write("unreachable\\n")
|
|
}
|
|
`);
|
|
assert.equal(fixedArrayListLengthBody.diagnostics[0].code, "TYP002");
|
|
assert.equal(fixedArrayListLengthBody.diagnostics[0].expected, "[4]u8");
|
|
assert.equal(fixedArrayListLengthBody.diagnostics[0].actual, "2 element(s)");
|
|
assert.match(fixedArrayListLengthBody.diagnostics[0].help, /annotate the intended array length/);
|
|
|
|
await assertDirectRuntimeRequired("conformance/native/pass/break-continue.0", "break-continue-required", { stdout: "loop tick\nloop tick\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/maybe-local-null-init-return.0", "maybe-local-null-init-return-required", { stdout: "maybe local found 42\nmaybe local none\nmaybe local sum 5\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/top-level-const.0", "top-level-const-required", { stdout: "const ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/const-arithmetic.0", "const-arithmetic-required", { stdout: "const arithmetic ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/nested-break-continue.0", "nested-break-continue-required", { stdout: "inner tick\ninner tick\nouter tick\ninner tick\ninner tick\nnested break continue ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/mutref-shape-param.0", "mutref-shape-param-required", { stdout: "mutref x ok\nmutref y ok\nref sum ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/mutref-shape-param-nested.0", "mutref-shape-param-nested-required", { stdout: "nested count ok\nnested total ok\nnested flag ok\nnested copy ok\nnested bytes ok\ngeneric mutref ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/generic-function-basic.0", "generic-function-basic-required", { stdout: "generic function ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/generic-nested-calls.0", "generic-nested-calls-required", { stdout: "generic nested calls ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/generic-inferred-specialized-call.0", "generic-inferred-specialized-call-required", { stdout: "generic inferred specialized call ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/generic-nested-local-specialization.0", "generic-nested-local-specialization-required", { stdout: "generic nested local specialization ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/generic-static-array-specialization.0", "generic-static-array-specialization-required", { stdout: "generic static array specialization ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/generic-static-forwarded-array-specialization.0", "generic-static-forwarded-array-specialization-required", { stdout: "generic static forwarded array specialization ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/explicit-cast-narrow-direct.0", "explicit-cast-narrow-direct-required", { stdout: "explicit cast narrow direct ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/frame-large-locals.0", "frame-large-locals-required", { stdout: "frame large locals ok alpha\n", args: ["alpha"] });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/frame-limit-boundary.0", "frame-limit-boundary-required", { stdout: "frame limit boundary ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/frame-split-helpers.0", "frame-split-helpers-required", { stdout: "frame split helpers ok\n" });
|
|
await assertDirectRuntimeRequired("conformance/native/pass/fixed-buf-alloc-local.0", "fixed-buf-alloc-local-required", { stdout: "fixed buf alloc local ok\n" });
|
|
|
|
const frameLimitOverFixture = `${outDir}/frame-limit-over.0`;
|
|
const frameLimitOverBody = await writeImportFailureFixture(frameLimitOverFixture, `pub fn main(world: World) -> Void raises {
|
|
var buffer: [262144]u8 = [0; 262144]
|
|
buffer[0] = 1
|
|
check world.out.write("unreachable\\n")
|
|
}
|
|
`);
|
|
assert.equal(frameLimitOverBody.diagnostics[0].code, "MEM003");
|
|
assert.match(frameLimitOverBody.diagnostics[0].expected, /131072 bytes of locals/);
|
|
assert.match(frameLimitOverBody.diagnostics[0].actual, /262144 bytes of locals/);
|
|
assert.match(frameLimitOverBody.diagnostics[0].help, /smaller buffers in helper functions/);
|
|
|
|
// Typed graph MIR constructs outside the buildable subset fail at import
|
|
// time with the same BLD004 diagnostics zero build would report later.
|
|
const pageAllocLocalBody = await writeImportFailureFixture(`${outDir}/page-alloc-local.0`, `pub fn main(world: World) -> Void raises {
|
|
let page: PageAlloc = std.mem.pageAlloc()
|
|
let bytes: Maybe<MutSpan<u8>> = std.mem.allocBytes(page, 4096)
|
|
if bytes.has {
|
|
check world.out.write("unreachable\\n")
|
|
}
|
|
}
|
|
`);
|
|
assert.equal(pageAllocLocalBody.diagnostics[0].code, "BLD004");
|
|
assert.match(pageAllocLocalBody.diagnostics[0].message, /allocator local requires FixedBufAlloc/);
|
|
assert.equal(pageAllocLocalBody.diagnostics[0].actual, "PageAlloc");
|
|
assert.equal(pageAllocLocalBody.diagnostics[0].line, 2);
|
|
assert.match(pageAllocLocalBody.diagnostics[0].help, /std\.mem\.fixedBufAlloc/);
|
|
assert.match(pageAllocLocalBody.diagnostics[0].help, /do not lower to direct backends yet/);
|
|
|
|
const generalAllocLocalBody = await writeImportFailureFixture(`${outDir}/general-alloc-local.0`, `pub fn main(world: World) -> Void raises {
|
|
let general: GeneralAlloc = std.mem.generalAlloc()
|
|
let bytes: Maybe<MutSpan<u8>> = std.mem.allocBytes(general, 64)
|
|
if bytes.has {
|
|
check world.out.write("unreachable\\n")
|
|
}
|
|
}
|
|
`);
|
|
assert.equal(generalAllocLocalBody.diagnostics[0].code, "BLD004");
|
|
assert.equal(generalAllocLocalBody.diagnostics[0].actual, "GeneralAlloc");
|
|
assert.equal(generalAllocLocalBody.diagnostics[0].line, 2);
|
|
|
|
const deferStatementBody = await writeImportFailureFixture(`${outDir}/defer-statement-gate.0`, `pub fn main(world: World) -> Void raises {
|
|
defer check world.out.write("bye\\n")
|
|
check world.out.write("hi\\n")
|
|
}
|
|
`);
|
|
assert.equal(deferStatementBody.diagnostics[0].code, "BLD004");
|
|
assert.match(deferStatementBody.diagnostics[0].message, /statement kind is unsupported/);
|
|
assert.equal(deferStatementBody.diagnostics[0].actual, "Defer");
|
|
assert.equal(deferStatementBody.diagnostics[0].line, 2);
|
|
assert.equal(deferStatementBody.diagnostics[0].column, 5);
|
|
|
|
const rescueNonPrimitiveBody = await writeImportFailureFixture(`${outDir}/rescue-non-primitive-gate.0`, `fn label(ok: Bool) -> String raises [Invalid] {
|
|
if ok {
|
|
return "primary"
|
|
}
|
|
raise Invalid
|
|
}
|
|
|
|
pub fn main(world: World) -> Void raises {
|
|
let value: String = rescue label(false) err "fallback"
|
|
check world.out.write(value)
|
|
}
|
|
`);
|
|
assert.equal(rescueNonPrimitiveBody.diagnostics[0].code, "BLD004");
|
|
assert.equal(rescueNonPrimitiveBody.diagnostics[0].actual, "String");
|
|
assert.equal(rescueNonPrimitiveBody.diagnostics[0].line, 1);
|
|
|
|
const refByteBufParamBody = await writeImportFailureFixture(`${outDir}/ref-bytebuf-param-gate.0`, `fn buffered(buf: ref<ByteBuf>) -> usize {
|
|
return std.mem.bufLen(buf)
|
|
}
|
|
|
|
pub fn main(world: World) -> Void raises {
|
|
var storage: [8]u8 = [0, 0, 0, 0, 0, 0, 0, 0]
|
|
var alloc: FixedBufAlloc = std.mem.fixedBufAlloc(storage)
|
|
let maybe: Maybe<owned<ByteBuf>> = std.mem.byteBuf(alloc, 4)
|
|
if !maybe.has {
|
|
return
|
|
}
|
|
let buf: owned<ByteBuf> = maybe.value
|
|
if buffered(&buf) == 4 {
|
|
check world.out.write("buffered\\n")
|
|
}
|
|
}
|
|
`);
|
|
assert.equal(refByteBufParamBody.diagnostics[0].code, "BLD004");
|
|
assert.equal(refByteBufParamBody.diagnostics[0].actual, "ref<ByteBuf>");
|
|
assert.equal(refByteBufParamBody.diagnostics[0].line, 1);
|
|
|
|
await assertDirectRuntimeRequired("conformance/run/pass/world-output-helper.0", "world-output-helper-required", { stdout: "world helper ok\n" });
|
|
|
|
const codecReadU32Body = await writeImportFailureFixture(`${outDir}/codec-readu32-gate.0`, `use std.codec
|
|
|
|
pub fn main(world: World) -> Void raises {
|
|
let value: u32 = std.codec.readU32("abcd")
|
|
if value > 0 {
|
|
check world.out.write("read\\n")
|
|
}
|
|
}
|
|
`);
|
|
assert.equal(codecReadU32Body.diagnostics[0].code, "STD002");
|
|
assert.match(codecReadU32Body.diagnostics[0].message, /unknown std helper/);
|
|
assert.equal(codecReadU32Body.diagnostics[0].actual, "unknown std helper");
|
|
assert.equal(codecReadU32Body.diagnostics[0].line, 4);
|
|
|
|
const enumLocalPackage = `${outDir}/enum-local-package`;
|
|
await mkdir(`${enumLocalPackage}/src`, { recursive: true });
|
|
await writeZeroToml(enumLocalPackage, {
|
|
package: { name: "enum-local-package", version: "0.1.0" },
|
|
targets: { cli: { kind: "exe", main: "src/main.0" } },
|
|
deps: {},
|
|
});
|
|
await writeFile(`${enumLocalPackage}/src/main.0`, `enum Status {
|
|
ready,
|
|
failed,
|
|
}
|
|
|
|
choice Outcome {
|
|
ok,
|
|
failed: i32,
|
|
}
|
|
|
|
pub fn main(world: World) -> Void raises {
|
|
let status: Status = Status.ready
|
|
let outcome: Outcome = Outcome.ok
|
|
if status == Status.ready {
|
|
check world.out.write("ready\\n")
|
|
}
|
|
}
|
|
`);
|
|
const enumLocalImport = await execFileAsync(zero, ["import", "--json", enumLocalPackage]).catch((error) => error);
|
|
assert.notEqual(enumLocalImport.code, 0);
|
|
const enumLocalImportBody = JSON.parse(enumLocalImport.stdout);
|
|
assert.equal(enumLocalImportBody.diagnostics[0].code, "BLD004");
|
|
assert.match(enumLocalImportBody.diagnostics[0].message, /local type is unsupported/);
|
|
assert.equal(enumLocalImportBody.diagnostics[0].actual, "Status");
|
|
assert.match(enumLocalImportBody.diagnostics[0].path, /src\/main\.0$/);
|
|
assert.equal(enumLocalImportBody.diagnostics[0].line, 12);
|
|
|
|
const abiDump = await execFileAsync(zero, ["abi", "dump", "--json", "conformance/native/pass/const-layout.0"]);
|
|
const abiDumpBody = JSON.parse(abiDump.stdout);
|
|
assert.equal(abiDumpBody.schemaVersion, 1);
|
|
assert.equal(abiDumpBody.pointerSize, 8);
|
|
assert(abiDumpBody.externShapes.some((item) => item.name === "CPoint" && item.size === 8 && item.fields[1].offset === 4));
|
|
assert(abiDumpBody.primitiveLayouts.some((item) => item.name === "usize" && item.size === 8));
|
|
const cAbiDump = await execFileAsync(zero, ["abi", "dump", "--json", "conformance/native/pass/c-abi-export.0"]);
|
|
const cAbiDumpBody = JSON.parse(cAbiDump.stdout);
|
|
assert(cAbiDumpBody.cExports.some((item) => item.name === "zero_add" && item.cReturnType === "int32_t"));
|
|
assert.equal(cAbiDumpBody.generatedHeader.available, true);
|
|
assert.match(cAbiDumpBody.generatedHeader.text, /int32_t zero_add\(int32_t a, int32_t b\);/);
|
|
const abiCheck = await execFileAsync(zero, ["abi", "check", "--json", "conformance/native/pass/const-layout.0"]);
|
|
assert.equal(JSON.parse(abiCheck.stdout).ok, true);
|
|
|
|
for (const runtimeFixture of [
|
|
["conformance/native/pass/indexing-primitives.0", "indexing-primitives", { stdout: "indexing primitives ok\n" }],
|
|
["conformance/native/pass/range-slices.0", "range-slices", { stdout: "range slices ok\n" }],
|
|
["conformance/native/pass/byte-view-call-single-eval.0", "byte-view-call-single-eval", { stdout: "byte view call single eval ok\n" }],
|
|
["conformance/native/pass/std-math-breadth.0", "std-math-breadth", { stdout: "std math breadth ok\n" }],
|
|
["conformance/native/pass/std-numeric-random-time.0", "std-numeric-random-time", { stdout: "std numeric random time ok\n" }],
|
|
["conformance/native/pass/std-regex.0", "std-regex", { stdout: "std regex ok\n" }],
|
|
["conformance/native/pass/std-unicode.0", "std-unicode", { stdout: "std unicode ok\n" }],
|
|
["conformance/native/pass/std-inet.0", "std-inet", { stdout: "std inet ok\n" }],
|
|
["conformance/native/pass/std-time-rfc3339.0", "std-time-rfc3339", { stdout: "std time rfc3339 ok\n" }],
|
|
["conformance/native/pass/std-str-breadth.0", "std-str-breadth", { stdout: "std str breadth ok\n" }],
|
|
["conformance/native/pass/std-mem-generic-items.0", "std-mem-generic-items", { stdout: "std mem generic items ok\n" }],
|
|
["conformance/native/pass/std-mem-field-items.0", "std-mem-field-items", { stdout: "std mem field items ok\n" }],
|
|
["conformance/native/pass/std-mem-byte-field-copy.0", "std-mem-byte-field-copy", { stdout: "std mem byte field copy ok\n" }],
|
|
["conformance/native/pass/std-mem-bool-copy-items.0", "std-mem-bool-copy-items", { stdout: "std mem bool copy items ok\n" }],
|
|
["conformance/native/pass/std-mem-u64-contains.0", "std-mem-u64-contains", { stdout: "std mem u64 contains ok\n" }],
|
|
["conformance/native/pass/std-mem-u64-copy-items.0", "std-mem-u64-copy-items", { stdout: "std mem u64 copy items ok\n" }],
|
|
["conformance/native/pass/std-mem-local-u64-copy-items.0", "std-mem-local-u64-copy-items", { stdout: "std mem local u64 copy items ok\n" }],
|
|
["conformance/native/pass/std-path-helper-name-collision.0", "std-path-helper-name-collision", { stdout: "std path helper collision ok\n" }],
|
|
["conformance/native/pass/byte-view-params.0", "byte-view-params", { stdout: "byte view params ok\n" }],
|
|
["conformance/native/pass/bool-arrays.0", "bool-arrays", { stdout: "bool arrays ok\n" }],
|
|
["conformance/native/pass/generic-spans.0", "generic-spans", { stdout: "generic spans ok\n" }],
|
|
["conformance/native/pass/open-ended-slices.0", "open-ended-slices", { stdout: "open ended slices ok\n" }],
|
|
["conformance/native/pass/string-slices.0", "string-slices", { stdout: "string slices ok\n" }],
|
|
["conformance/native/pass/indexed-mutation.0", "indexed-mutation", { stdout: "indexed mutation ok\n" }],
|
|
["conformance/native/pass/dynamic-indexed-store-scratch.0", "dynamic-indexed-store-scratch", { stdout: "dynamic indexed store ok\n" }],
|
|
["conformance/native/pass/nested-lvalues.0", "nested-lvalues", { stdout: "nested lvalues ok\n" }],
|
|
["conformance/native/pass/mutable-spans.0", "mutable-spans", { stdout: "mutable spans ok\n" }],
|
|
["conformance/native/pass/mutref-indexed-lvalues.0", "mutref-indexed-lvalues", { stdout: "mutref indexed lvalues ok\n" }],
|
|
["conformance/native/pass/generic-mem.0", "generic-mem", { stdout: "generic mem ok\n" }],
|
|
["conformance/native/pass/generic-nested-calls.0", "generic-nested-calls", { stdout: "generic nested calls ok\n" }],
|
|
["conformance/native/pass/generic-multi-specialization.0", "generic-multi-specialization", { stdout: "generic multi specialization ok\n" }],
|
|
["conformance/native/pass/generic-inferred-specialized-call.0", "generic-inferred-specialized-call", { stdout: "generic inferred specialized call ok\n" }],
|
|
["conformance/native/pass/generic-nested-local-specialization.0", "generic-nested-local-specialization", { stdout: "generic nested local specialization ok\n" }],
|
|
["conformance/native/pass/generic-static-array-specialization.0", "generic-static-array-specialization", { stdout: "generic static array specialization ok\n" }],
|
|
["conformance/native/pass/generic-static-forwarded-array-specialization.0", "generic-static-forwarded-array-specialization", { stdout: "generic static forwarded array specialization ok\n" }],
|
|
["conformance/native/pass/static-interface-mutref.0", "static-interface-mutref", { stdout: "static interface mutref ok\n" }],
|
|
["conformance/native/pass/owned-transfer.0", "owned-transfer", { stdout: "owned transfer ok\n" }],
|
|
["conformance/native/pass/owned-drop-cleanup.0", "owned-drop-cleanup", { stdout: "owned drop cleanup ok\n" }],
|
|
["conformance/native/pass/owned-drop-move-suppressed.0", "owned-drop-move-suppressed", { stdout: "owned drop move suppressed ok\n" }],
|
|
["conformance/native/pass/borrow-primitives.0", "borrow-primitives", { stdout: "borrow primitives ok\n" }],
|
|
["conformance/native/pass/allocator-primitives.0", "allocator-primitives", { stdout: "allocator primitives ok\n" }],
|
|
["conformance/native/pass/owned-byte-buffer.0", "owned-byte-buffer", { stdout: "owned byte buffer ok\n" }],
|
|
]) {
|
|
await assertDirectRuntimeOrUnsupported(...runtimeFixture);
|
|
}
|
|
|
|
finishAggregateAssert(assert, { suite: "conformance", reportPath: `${outDir}/failures.json` });
|
|
console.log("conformance ok");
|