test: prove long package identity semantics
This commit is contained in:
@@ -26,7 +26,8 @@ package wwi_test;
|
||||
// decl-less shapes routing the wwi_emit fallback (empty, comment-only,
|
||||
// nested dotted path a.b.c -> leaf c). Each row drives the REAL
|
||||
// producer->importer flow on BOTH stages: (a) the dep `.wwi` package
|
||||
// line equals the real leaf, (b) the dep `.wwi` is byte-identical
|
||||
// owner marker is the complete path and its package line equals the real leaf,
|
||||
// (b) the dep `.wwi` is byte-identical
|
||||
// across stages, (c) a root importing the dep RESOLVES on both stages
|
||||
// and the two importer `.s` are byte-identical. The owner units and
|
||||
// separate exports are fed straight to w6c / w6c_ww (not `ww build`):
|
||||
@@ -55,13 +56,6 @@ fn runok(dir: str, name: str, argv: []str) bool = {
|
||||
return co.termination == exec.termination.EXIT && co.code == 0;
|
||||
};
|
||||
|
||||
fn firstline(path: str) str = {
|
||||
let body: str = testenv.readfile(path);
|
||||
let nl: i32 = testenv.pos(body, "\n");
|
||||
if (nl < 0) { return body; };
|
||||
return strings.sub(body, 0, nl);
|
||||
};
|
||||
|
||||
// one positive package: build the target as primary, produce the `.wwi`
|
||||
// on both stages, require byte-id + re-parse.
|
||||
fn m2positive(pkg: str) void = {
|
||||
@@ -345,9 +339,10 @@ fn leafrow(tag: str, path: str, leaf: str, body: str, want: str) void = {
|
||||
let wav: []str = [testenv.driver("w6c_ww"), "-c", "-I", wwwwi,
|
||||
"-o", wws, prod];
|
||||
if (!runok(td, "wsprod", wav)) { fail(tag, "w6c_ww producer errored"); };
|
||||
let wantline: str = strings.concat("package ", want, ";");
|
||||
if (!testenv.same(firstline(cswwi), wantline)) {
|
||||
fail(tag, ".wwi package line is not the real leaf (BUG-C)");
|
||||
let wanthead: str = strings.concat(strings.concat(strings.concat(
|
||||
"//ww:module ", path), "\npackage "), strings.concat(want, ";\n"));
|
||||
if (!strings.hasprefix(testenv.readfile(cswwi), wanthead)) {
|
||||
fail(tag, ".wwi owner or package leaf is incomplete (BUG-C)");
|
||||
};
|
||||
|
||||
// Leg b — the dep `.wwi` is byte-identical across stages (rule 10).
|
||||
|
||||
@@ -3,6 +3,8 @@ package package_test;
|
||||
// Make builds and invokes this one binary; discovery, subprocess ownership,
|
||||
// output interpretation, and assertions remain WW code.
|
||||
|
||||
import crypto.sha256;
|
||||
import hash;
|
||||
import os;
|
||||
import os.exec;
|
||||
import strings;
|
||||
@@ -287,6 +289,98 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
return strings.frombytes(out);
|
||||
};
|
||||
|
||||
fn digesthex(h: *hash.hash) str = {
|
||||
let digest: [32]u8;
|
||||
hash.sum(h, digest[0:32]);
|
||||
let out: []u8 = alloc([], 65u64)!;
|
||||
let digits: str = "0123456789abcdef";
|
||||
let i: i32 = 0;
|
||||
for (i < 32) {
|
||||
let high: i32 = (digest[i] / 16u8): i32;
|
||||
let low: i32 = (digest[i] % 16u8): i32;
|
||||
append(out, digits[high]);
|
||||
append(out, digits[low]);
|
||||
i += 1;
|
||||
};
|
||||
return strings.frombytes(out);
|
||||
};
|
||||
|
||||
fn packagestoragekey(path: str, canon: str, variant: i32, role: i32) str = {
|
||||
let state: sha256.state = sha256.sha256();
|
||||
let h: *hash.hash = (&state): *hash.hash;
|
||||
hash.write(h, strings.toutf8("ww-package-storage-v2:"));
|
||||
let tag: [4]u8;
|
||||
tag[0] = ('0': i32 + variant): u8;
|
||||
tag[1] = ':': u8;
|
||||
tag[2] = ('0': i32 + role): u8;
|
||||
tag[3] = ':': u8;
|
||||
hash.write(h, tag[0:4]);
|
||||
hash.write(h, strings.toutf8(path));
|
||||
let zero: [1]u8;
|
||||
zero[0] = 0u8;
|
||||
hash.write(h, zero[0:1]);
|
||||
hash.write(h, strings.toutf8(canon));
|
||||
let out: []u8 = alloc([], 81u64)!;
|
||||
let prefix: str = "__wwpkg.v";
|
||||
let i: i32 = 0;
|
||||
for (i < prefix.len) { append(out, prefix[i]); i += 1; };
|
||||
append(out, tag[0]); append(out, '.'); append(out, 'r');
|
||||
append(out, tag[2]); append(out, '.'); append(out, 'h');
|
||||
let hex: str = digesthex(h);
|
||||
i = 0;
|
||||
for (i < hex.len) { append(out, hex[i]); i += 1; };
|
||||
return strings.frombytes(out);
|
||||
};
|
||||
|
||||
fn requestworkkey(dir: str) str = {
|
||||
let state: sha256.state = sha256.sha256();
|
||||
let h: *hash.hash = (&state): *hash.hash;
|
||||
hash.write(h, strings.toutf8("ww-request-workdir-v1:"));
|
||||
hash.write(h, strings.toutf8(dir));
|
||||
return strings.concat("d_", digesthex(h));
|
||||
};
|
||||
|
||||
fn importrelative(path: str) str = {
|
||||
let out: []u8 = alloc([], (path.len + 1): u64)!;
|
||||
let i: i32 = 0;
|
||||
for (i < path.len) {
|
||||
if (path[i] == '.') { append(out, '/'); }
|
||||
else { append(out, path[i]); };
|
||||
i += 1;
|
||||
};
|
||||
return strings.frombytes(out);
|
||||
};
|
||||
|
||||
fn longidentity(leaf: str) str = {
|
||||
let out: []u8 = alloc([], 384u64)!;
|
||||
let component: str = "segmentabcdefghijklmnop";
|
||||
let n: i32 = 0;
|
||||
for (n < 13) {
|
||||
let i: i32 = 0;
|
||||
for (i < component.len) { append(out, component[i]); i += 1; };
|
||||
append(out, '.');
|
||||
n += 1;
|
||||
};
|
||||
let i: i32 = 0;
|
||||
for (i < leaf.len) { append(out, leaf[i]); i += 1; };
|
||||
return strings.frombytes(out);
|
||||
};
|
||||
|
||||
fn deeppunctuationpath(root: str, branch: str) str = {
|
||||
let out: str = strings.concat(root, "/outside +% @ _/", branch);
|
||||
let component: str = "/punctuation + percent% at@ under_score";
|
||||
let n: i32 = 0;
|
||||
for (n < 9) { out = strings.concat(out, component); n += 1; };
|
||||
return out;
|
||||
};
|
||||
|
||||
fn mkdirall(path: str) void = {
|
||||
match (os.mkdirs(path, 448i32)) {
|
||||
case void => void;
|
||||
case let e: os.oserror => abort("mkdirs failed");
|
||||
};
|
||||
};
|
||||
|
||||
@test fn deterministic_routing_and_filters() void = {
|
||||
let root: str = fresh();
|
||||
let target: str = packagepath("routing");
|
||||
@@ -515,22 +609,97 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
clean(root);
|
||||
};
|
||||
|
||||
@test fn symlink_package_is_rejected() void = {
|
||||
@test fn symlink_package_root_reuses_canonical_directory() void = {
|
||||
let root: str = fresh();
|
||||
let real: str = strings.concat(root, "/real");
|
||||
let real: str = deeppunctuationpath(root, "symlink target");
|
||||
let link: str = strings.concat(root, "/link");
|
||||
assert(os.mkdir(real, 448i32) == 0);
|
||||
let wrapper: str = strings.concat(root, "/compiler wrapper.sh");
|
||||
mkdirall(real);
|
||||
writefile(strings.concat(real, "/real.ww"),
|
||||
"package real;\nexport fn value() int = { return 1; };\n");
|
||||
writefile(strings.concat(real, "/real_test.ww"),
|
||||
"package real;\n@test fn value_is_one() void = { assert(value() == 1); };\n");
|
||||
let lav: []str = ["/bin/ln", "-s", real, link];
|
||||
let out: commandout;
|
||||
runcommand(root, "link", lav, time.second, &out);
|
||||
expectexit(&out, 0);
|
||||
let av: []str = [driver("ww"), "test", link];
|
||||
runcommand(root, "reject", av,
|
||||
(30i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 1);
|
||||
assert(has(out.stderr, "symlink traversal is not allowed"));
|
||||
writeexecutable(wrapper, strings.concat(
|
||||
"#!/bin/sh\n",
|
||||
"printf 'BEGIN' >> \"$WW_SYMLINK_COMPILER_TRACE\"\n",
|
||||
"for arg in \"$@\"; do printf '<%s>' \"$arg\" >> ",
|
||||
"\"$WW_SYMLINK_COMPILER_TRACE\"; done\n",
|
||||
"printf '\\n' >> \"$WW_SYMLINK_COMPILER_TRACE\"\n",
|
||||
"exec \"$WW_SYMLINK_REAL_COMPILER\" \"$@\"\n"));
|
||||
let actionid: str = localidentity(real, "real");
|
||||
assert(actionid.len > 255);
|
||||
let action: str = packagestoragekey(actionid, real, 1, 0);
|
||||
assert(action.len + 9 <= 255);
|
||||
let stages: []str = ["ww", "ww_ww"];
|
||||
let compilers: []str = ["w6c", "w6c_ww"];
|
||||
let references: []str = ["", "", ""];
|
||||
let baseenv: []str = os.getenvs();
|
||||
let si: i32 = 0;
|
||||
for (si < stages.len) {
|
||||
let work: str = strings.concat(root, "/work-", stages[si]);
|
||||
let trace: str = strings.concat(root, "/trace-", stages[si]);
|
||||
assert(os.mkdir(work, 448i32) == 0);
|
||||
writefile(trace, "");
|
||||
let env: []str = alloc([], (baseenv.len + 3): u64)!;
|
||||
let ei: i32 = 0;
|
||||
for (ei < baseenv.len) {
|
||||
if (!strings.hasprefix(baseenv[ei], "WW_W6C=")
|
||||
&& !strings.hasprefix(baseenv[ei],
|
||||
"WW_SYMLINK_COMPILER_TRACE=")
|
||||
&& !strings.hasprefix(baseenv[ei],
|
||||
"WW_SYMLINK_REAL_COMPILER=")) {
|
||||
append(env, baseenv[ei]);
|
||||
};
|
||||
ei += 1;
|
||||
};
|
||||
append(env, strings.concat("WW_W6C=", wrapper));
|
||||
append(env, strings.concat("WW_SYMLINK_COMPILER_TRACE=", trace));
|
||||
append(env, strings.concat("WW_SYMLINK_REAL_COMPILER=",
|
||||
driver(compilers[si])));
|
||||
let av: []str = [driver(stages[si]), "test", "-w", work, real];
|
||||
runcommandenv(root, strings.concat("real-cold-", stages[si]), av, env,
|
||||
(60i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
assert(has(out.stdout, "real.value_is_one ... ok\n"));
|
||||
let coldtrace: str = readfile(trace);
|
||||
assert(coldtrace.len > 0);
|
||||
assert(has(coldtrace, strings.concat("<--import><", actionid, "><")));
|
||||
let key: str = strings.concat(work, "/", requestworkkey(real));
|
||||
assert(os.exists(key));
|
||||
let suffixes: []str = [".unit.ww", ".wwi", ".a"];
|
||||
let xi: i32 = 0;
|
||||
for (xi < suffixes.len) {
|
||||
let artifact: str = readfile(strings.concat(key, "/", action,
|
||||
suffixes[xi]));
|
||||
if (xi == 0) {
|
||||
assert(has(artifact, strings.concat("//ww:module-reset ",
|
||||
actionid, "\n")));
|
||||
} else { if (xi == 1) {
|
||||
assert(strings.hasprefix(artifact, strings.concat("//ww:module ",
|
||||
actionid, "\n")));
|
||||
}; };
|
||||
if (si == 0) { references[xi] = strings.dup(artifact); }
|
||||
else { assert(same(references[xi], artifact)); };
|
||||
xi += 1;
|
||||
};
|
||||
let linkav: []str = [driver(stages[si]), "test", "-w", work, link];
|
||||
runcommandenv(root, strings.concat("symlink-warm-", stages[si]),
|
||||
linkav, env, (60i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
assert(has(out.stdout, "real.value_is_one ... ok\n"));
|
||||
assert(same(coldtrace, readfile(trace)));
|
||||
xi = 0;
|
||||
for (xi < suffixes.len) {
|
||||
assert(same(references[xi], readfile(strings.concat(key, "/",
|
||||
action, suffixes[xi]))));
|
||||
xi += 1;
|
||||
};
|
||||
si += 1;
|
||||
};
|
||||
clean(root);
|
||||
};
|
||||
|
||||
@@ -2606,44 +2775,48 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
let root: str = fresh();
|
||||
let source: str = strings.concat(root, "/source tree");
|
||||
let runtime: str = strings.concat(root, "/runtime library");
|
||||
let base: str = strings.concat(source, "/ww_root_parity_base_7f3");
|
||||
let left: str = strings.concat(source, "/ww_root_parity_left_7f3");
|
||||
let right: str = strings.concat(source, "/ww_root_parity_right_7f3");
|
||||
let rootidentity: str = "ww_root_parity_target_7f3";
|
||||
let target: str = strings.concat(source, "/", rootidentity);
|
||||
let baseidentity: str = longidentity("paritybase");
|
||||
let leftidentity: str = longidentity("parityleft");
|
||||
let rightidentity: str = longidentity("parityright");
|
||||
let rootidentity: str = longidentity("paritycommand");
|
||||
assert(baseidentity.len > 255 && rootidentity.len > 255);
|
||||
let base: str = strings.concat(source, "/", importrelative(baseidentity));
|
||||
let left: str = strings.concat(source, "/", importrelative(leftidentity));
|
||||
let right: str = strings.concat(source, "/", importrelative(rightidentity));
|
||||
let target: str = strings.concat(source, "/", importrelative(rootidentity));
|
||||
let tools: str = strings.concat(root, "/tool wrappers");
|
||||
assert(os.mkdir(source, 448i32) == 0);
|
||||
assert(os.mkdir(runtime, 448i32) == 0);
|
||||
writefile(strings.concat(runtime, "/libwwrt.a"),
|
||||
readfile(strings.concat(repo(), "/out/lib/libwwrt.a")));
|
||||
assert(os.mkdir(base, 448i32) == 0);
|
||||
assert(os.mkdir(left, 448i32) == 0);
|
||||
assert(os.mkdir(right, 448i32) == 0);
|
||||
assert(os.mkdir(target, 448i32) == 0);
|
||||
mkdirall(base);
|
||||
mkdirall(left);
|
||||
mkdirall(right);
|
||||
mkdirall(target);
|
||||
assert(os.mkdir(tools, 448i32) == 0);
|
||||
let basea: str = strings.concat(
|
||||
"package ww_root_parity_base_7f3;\n",
|
||||
"package paritybase;\n",
|
||||
"export fn value() i32 = { return 20; };\n");
|
||||
let basez: str = strings.concat(
|
||||
"package ww_root_parity_base_7f3;\n",
|
||||
"package paritybase;\n",
|
||||
"fn private_value() i32 = { return 99; };\n");
|
||||
let leftbody: str = strings.concat(
|
||||
"package ww_root_parity_left_7f3;\n",
|
||||
"import ww_root_parity_base_7f3;\n",
|
||||
"import ww_root_parity_base_7f3;\n",
|
||||
"package parityleft;\n",
|
||||
"import ", baseidentity, ";\n",
|
||||
"import ", baseidentity, ";\n",
|
||||
"export fn value() i32 = { return ",
|
||||
"ww_root_parity_base_7f3.value(); };\n");
|
||||
"paritybase.value(); };\n");
|
||||
let rightbody: str = strings.concat(
|
||||
"package ww_root_parity_right_7f3;\n",
|
||||
"import ww_root_parity_base_7f3;\n",
|
||||
"package parityright;\n",
|
||||
"import ", baseidentity, ";\n",
|
||||
"export fn value() i32 = { return ",
|
||||
"ww_root_parity_base_7f3.value() + 1; };\n");
|
||||
"paritybase.value() + 1; };\n");
|
||||
let rootbody: str = strings.concat(
|
||||
"package main;\n",
|
||||
"import ww_root_parity_right_7f3;\n",
|
||||
"import ww_root_parity_left_7f3;\n",
|
||||
"fn main() i32 = { return ww_root_parity_left_7f3.value() + ",
|
||||
"ww_root_parity_right_7f3.value() + 1; };\n");
|
||||
"import ", rightidentity, ";\n",
|
||||
"import ", leftidentity, ";\n",
|
||||
"fn main() i32 = { return parityleft.value() + ",
|
||||
"parityright.value() + 1; };\n");
|
||||
writefile(strings.concat(base, "/a.ww"), basea);
|
||||
writefile(strings.concat(base, "/z.ww"), basez);
|
||||
writefile(strings.concat(left, "/left.ww"), leftbody);
|
||||
@@ -2703,18 +2876,25 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
let bin: str = strings.concat(root, "/published binary");
|
||||
let workroot: str = strings.concat(bin, ".sepwork");
|
||||
let work: str = strings.concat(workroot, "/");
|
||||
let artifacts: []str = ["ww_root_parity_base_7f3",
|
||||
"ww_root_parity_left_7f3", "ww_root_parity_right_7f3",
|
||||
rootidentity];
|
||||
let unitartifacts: []str = ["ww_root_parity_base_7f3",
|
||||
"ww_root_parity_left_7f3", "ww_root_parity_right_7f3",
|
||||
let identities: []str = [baseidentity, leftidentity, rightidentity,
|
||||
rootidentity];
|
||||
let artifacts: []str = [packagestoragekey(baseidentity, base, 0, 0),
|
||||
packagestoragekey(leftidentity, left, 0, 0),
|
||||
packagestoragekey(rightidentity, right, 0, 0),
|
||||
packagestoragekey(rootidentity, target, 0, 0)];
|
||||
let unitartifacts: []str = artifacts;
|
||||
let aki: i32 = 0;
|
||||
for (aki < artifacts.len) {
|
||||
assert(strings.hasprefix(artifacts[aki], "__wwpkg.v0.r0.h"));
|
||||
assert(artifacts[aki].len <= 246);
|
||||
aki += 1;
|
||||
};
|
||||
let wantunits: []str = [strings.concat(
|
||||
"//ww:module-reset ww_root_parity_base_7f3\n", basea,
|
||||
"\n//ww:module-reset ww_root_parity_base_7f3\n", basez, "\n"),
|
||||
strings.concat("//ww:module-reset ww_root_parity_left_7f3\n",
|
||||
"//ww:module-reset ", baseidentity, "\n", basea,
|
||||
"\n//ww:module-reset ", baseidentity, "\n", basez, "\n"),
|
||||
strings.concat("//ww:module-reset ", leftidentity, "\n",
|
||||
leftbody, "\n"),
|
||||
strings.concat("//ww:module-reset ww_root_parity_right_7f3\n",
|
||||
strings.concat("//ww:module-reset ", rightidentity, "\n",
|
||||
rightbody, "\n"),
|
||||
strings.concat("//ww:module-reset ", rootidentity, "\n", rootbody,
|
||||
"\n")];
|
||||
@@ -2728,6 +2908,7 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
let referenceout: str = "";
|
||||
let referenceerr: str = "";
|
||||
let referencefailure: str = "";
|
||||
let referencecollision: str = "";
|
||||
let baseenv: []str = os.getenvs();
|
||||
let si: i32 = 0;
|
||||
for (si < stages.len) {
|
||||
@@ -2788,8 +2969,10 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
append(env, strings.concat("WW_ARGV_REAL_LINKER=",
|
||||
driver(linkers[si])));
|
||||
|
||||
let request: str = target;
|
||||
if (si == 1 || si == 3) { request = rootidentity; };
|
||||
let av: []str = [driver(stages[si]), "build", "-o", bin,
|
||||
target];
|
||||
request];
|
||||
let out: commandout;
|
||||
runcommandenv(root, strings.concat("exact-argv-", tags[si]), av, env,
|
||||
(120i64 * (time.second: i64)): time.duration, &out);
|
||||
@@ -2809,12 +2992,19 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
for (ai < artifacts.len) {
|
||||
let exportf: str = readfile(strings.concat(work, artifacts[ai],
|
||||
".wwi"));
|
||||
let assembly: str = readfile(strings.concat(work, artifacts[ai],
|
||||
".s"));
|
||||
let archive: str = readfile(strings.concat(work, artifacts[ai],
|
||||
".a"));
|
||||
assert(strings.hasprefix(exportf, strings.concat("//ww:module ",
|
||||
identities[ai], "\n")));
|
||||
if (ai < 3) {
|
||||
assert(has(assembly, strings.concat(identities[ai], ".value")));
|
||||
};
|
||||
if (ai == 3) {
|
||||
assert(strings.hasprefix(exportf, strings.concat("package ",
|
||||
rootidentity, ";\n")));
|
||||
assert(!strings.hasprefix(exportf, "package main;\n"));
|
||||
assert(has(exportf, strings.concat("\npackage paritycommand",
|
||||
";\n")));
|
||||
assert(!has(exportf, "\npackage main;\n"));
|
||||
};
|
||||
if (si == 0) {
|
||||
referenceexports[ai] = strings.dup(exportf);
|
||||
@@ -2832,48 +3022,62 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
let ltrace: str = readfile(linkertrace);
|
||||
assert(occurrences(ctrace, "\n") == 4);
|
||||
let baseline: str = strings.concat("BEGIN<-c><-I><", work,
|
||||
"ww_root_parity_base_7f3.wwi><-o><", work,
|
||||
"ww_root_parity_base_7f3.s><", work,
|
||||
"ww_root_parity_base_7f3.unit.ww>");
|
||||
artifacts[0], ".wwi><-o><", work,
|
||||
artifacts[0], ".s><", work,
|
||||
artifacts[0], ".unit.ww>");
|
||||
let leftline: str = strings.concat("BEGIN<-c><--import>",
|
||||
"<ww_root_parity_base_7f3><", work,
|
||||
"ww_root_parity_base_7f3.wwi><-I><", work,
|
||||
"ww_root_parity_left_7f3.wwi><-o><", work,
|
||||
"ww_root_parity_left_7f3.s><", work,
|
||||
"ww_root_parity_left_7f3.unit.ww>");
|
||||
"<", baseidentity, "><", work,
|
||||
artifacts[0], ".wwi><-I><", work,
|
||||
artifacts[1], ".wwi><-o><", work,
|
||||
artifacts[1], ".s><", work,
|
||||
artifacts[1], ".unit.ww>");
|
||||
let rightline: str = strings.concat("BEGIN<-c><--import>",
|
||||
"<ww_root_parity_base_7f3><", work,
|
||||
"ww_root_parity_base_7f3.wwi><-I><", work,
|
||||
"ww_root_parity_right_7f3.wwi><-o><", work,
|
||||
"ww_root_parity_right_7f3.s><", work,
|
||||
"ww_root_parity_right_7f3.unit.ww>");
|
||||
"<", baseidentity, "><", work,
|
||||
artifacts[0], ".wwi><-I><", work,
|
||||
artifacts[2], ".wwi><-o><", work,
|
||||
artifacts[2], ".s><", work,
|
||||
artifacts[2], ".unit.ww>");
|
||||
let rootline: str = strings.concat("BEGIN<--entry><-c><--import>",
|
||||
"<ww_root_parity_left_7f3><", work,
|
||||
"ww_root_parity_left_7f3.wwi><--import>",
|
||||
"<ww_root_parity_right_7f3><", work,
|
||||
"ww_root_parity_right_7f3.wwi><-I><", work,
|
||||
rootidentity, ".wwi><-o><", work,
|
||||
rootidentity, ".s><", work, rootidentity, ".unit.ww>");
|
||||
"<", leftidentity, "><", work,
|
||||
artifacts[1], ".wwi><--import>",
|
||||
"<", rightidentity, "><", work,
|
||||
artifacts[2], ".wwi><-I><", work,
|
||||
artifacts[3], ".wwi><-o><", work,
|
||||
artifacts[3], ".s><", work, artifacts[3], ".unit.ww>");
|
||||
assert(same(linecontaining(ctrace,
|
||||
"ww_root_parity_base_7f3.unit.ww"), baseline));
|
||||
strings.concat(artifacts[0], ".unit.ww")), baseline));
|
||||
assert(same(linecontaining(ctrace,
|
||||
"ww_root_parity_left_7f3.unit.ww"), leftline));
|
||||
strings.concat(artifacts[1], ".unit.ww")), leftline));
|
||||
assert(same(linecontaining(ctrace,
|
||||
"ww_root_parity_right_7f3.unit.ww"), rightline));
|
||||
assert(same(linecontaining(ctrace, strings.concat(rootidentity,
|
||||
strings.concat(artifacts[2], ".unit.ww")), rightline));
|
||||
assert(same(linecontaining(ctrace, strings.concat(artifacts[3],
|
||||
".unit.ww")), rootline));
|
||||
assert(!has(rootline, "ww_root_parity_base_7f3.wwi"));
|
||||
assert(!has(rootline, strings.concat(artifacts[0], ".wwi")));
|
||||
// The primary command declaration is accepted only when the compiler
|
||||
// receives command classification from --entry. Imported interfaces and
|
||||
// ordinary package compiles retain strict identity-leaf validation.
|
||||
let rejectwwi: str = strings.concat(root, "/reject-", tags[si], ".wwi");
|
||||
let rejectasm: str = strings.concat(root, "/reject-", tags[si], ".s");
|
||||
let rejectav: []str = [driver(compilers[si]), "-c", "-I", rejectwwi,
|
||||
"-o", rejectasm, strings.concat(work, rootidentity, ".unit.ww")];
|
||||
"-o", rejectasm, strings.concat(work, artifacts[3], ".unit.ww")];
|
||||
runcommand(root, strings.concat("command-without-entry-", tags[si]),
|
||||
rejectav, (60i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 1);
|
||||
assert(has(out.stderr, "does not match import path"));
|
||||
assert(has(out.stderr, rootidentity));
|
||||
let ownerrejectwwi: str = strings.concat(root, "/owner-reject-",
|
||||
tags[si], ".wwi");
|
||||
let ownerrejectasm: str = strings.concat(root, "/owner-reject-",
|
||||
tags[si], ".s");
|
||||
let ownerrejectav: []str = [driver(compilers[si]), "-c", "--import",
|
||||
leftidentity, strings.concat(work, artifacts[0], ".wwi"), "-I",
|
||||
ownerrejectwwi, "-o", ownerrejectasm,
|
||||
strings.concat(work, artifacts[1], ".unit.ww")];
|
||||
runcommand(root, strings.concat("export-owner-reject-", tags[si]),
|
||||
ownerrejectav, (60i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 1);
|
||||
assert(same(out.stderr, strings.concat("w6c: import ", leftidentity,
|
||||
": export owner mismatch in ", work, artifacts[0], ".wwi\n")));
|
||||
assert(occurrences(atrace, "\n") == 4);
|
||||
ai = 0;
|
||||
for (ai < artifacts.len) {
|
||||
@@ -2885,7 +3089,7 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
};
|
||||
assert(occurrences(ltrace, "\n") == 1);
|
||||
assert(has(ltrace, strings.concat("BEGIN<-o><", bin, "><", work,
|
||||
rootidentity, ".a>")));
|
||||
artifacts[3], ".a>")));
|
||||
ai = 0;
|
||||
for (ai < artifacts.len) {
|
||||
assert(occurrences(ltrace, strings.concat("<", work, artifacts[ai],
|
||||
@@ -2917,6 +3121,127 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
assert(same(referenceout, out.stdout));
|
||||
assert(same(referenceerr, out.stderr));
|
||||
};
|
||||
|
||||
// Select the same long ordinary directory as both an explicit product
|
||||
// root and the dependency of another product in one command. Then build
|
||||
// it alone through logical and literal spellings. All routes must intern
|
||||
// one production action and emit the dependency-built bytes above.
|
||||
let combinedbase: str = strings.concat(root, "/combined-base-", tags[si]);
|
||||
let combinedleft: str = strings.concat(root, "/combined-left-", tags[si]);
|
||||
let combinedbasestatus: str = strings.concat(combinedbase, ".status");
|
||||
let combinedleftstatus: str = strings.concat(combinedleft, ".status");
|
||||
clean(compilertrace); writefile(compilertrace, "");
|
||||
clean(assemblertrace); writefile(assemblertrace, "");
|
||||
clean(linkertrace); writefile(linkertrace, "");
|
||||
let combinedav: []str = [driver(stages[si]), "test", "-c", "-I",
|
||||
source,
|
||||
"--ww-package-test", "production", "paritybase", base,
|
||||
combinedbase, combinedbasestatus,
|
||||
"--ww-package-test", "production", "parityleft", left,
|
||||
combinedleft, combinedleftstatus, left];
|
||||
runcommandenv(root, strings.concat("long-combined-", tags[si]),
|
||||
combinedav, env, (120i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
let combinedtrace: str = readfile(compilertrace);
|
||||
assert(occurrences(combinedtrace, strings.concat(artifacts[0],
|
||||
".unit.ww>")) == 1);
|
||||
let combinedwork: str = strings.concat(combinedbase, ".sepwork/");
|
||||
let combinedunit: str = readfile(strings.concat(combinedwork,
|
||||
artifacts[0], ".unit.ww"));
|
||||
let combinedwwi: str = readfile(strings.concat(combinedwork,
|
||||
artifacts[0], ".wwi"));
|
||||
let combinedarchive: str = readfile(strings.concat(combinedwork,
|
||||
artifacts[0], ".a"));
|
||||
assert(same(referenceunits[0], combinedunit));
|
||||
assert(same(referenceexports[0], combinedwwi));
|
||||
assert(same(referencearchives[0], combinedarchive));
|
||||
|
||||
let rootspellings: []str = [baseidentity, base];
|
||||
let rootlabels: []str = ["logical", "literal"];
|
||||
let ri: i32 = 0;
|
||||
for (ri < rootspellings.len) {
|
||||
let rootout: str = strings.concat(root, "/long-root-",
|
||||
rootlabels[ri], "-", tags[si], ".a");
|
||||
clean(compilertrace); writefile(compilertrace, "");
|
||||
let rootav: []str = [driver(stages[si]), "build", "-p", "-I",
|
||||
source, "-o", rootout, rootspellings[ri]];
|
||||
runcommandenv(root, strings.concat("long-root-", rootlabels[ri],
|
||||
"-", tags[si]), rootav, env,
|
||||
(120i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
assert(occurrences(readfile(compilertrace), strings.concat(
|
||||
artifacts[0], ".unit.ww>")) == 1);
|
||||
let rootwork: str = strings.concat(rootout, ".sepwork/");
|
||||
assert(same(combinedunit, readfile(strings.concat(rootwork,
|
||||
artifacts[0], ".unit.ww"))));
|
||||
assert(same(combinedwwi, readfile(strings.concat(rootwork,
|
||||
artifacts[0], ".wwi"))));
|
||||
assert(same(combinedarchive, readfile(strings.concat(rootwork,
|
||||
artifacts[0], ".a"))));
|
||||
clean(strings.concat(rootout, ".sepwork"));
|
||||
clean(rootout); clean(strings.concat(rootout, ".wwi"));
|
||||
ri += 1;
|
||||
};
|
||||
clean(strings.concat(combinedbase, ".sepwork"));
|
||||
clean(combinedbase); clean(combinedleft);
|
||||
clean(combinedbasestatus); clean(combinedleftstatus);
|
||||
let seedav: []str = [driver(stages[si]), "build", "-w", workroot,
|
||||
"-o", bin, request];
|
||||
runcommandenv(root, strings.concat("persistent-seed-", tags[si]),
|
||||
seedav, env, (120i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
assert(os.remove(compilertrace) == 0);
|
||||
assert(os.remove(assemblertrace) == 0);
|
||||
writefile(compilertrace, "");
|
||||
writefile(assemblertrace, "");
|
||||
let equivalent: str = rootidentity;
|
||||
if (same(request, rootidentity)) { equivalent = target; };
|
||||
let warmav: []str = [driver(stages[si]), "build", "-w", workroot,
|
||||
"-o", bin, equivalent];
|
||||
runcommandenv(root, strings.concat("persistent-equivalent-", tags[si]),
|
||||
warmav, env, (120i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
assert(readfile(compilertrace).len == 0);
|
||||
assert(readfile(assemblertrace).len == 0);
|
||||
let baseafile: str = strings.concat(base, "/a.ww");
|
||||
assert(os.remove(baseafile) == 0);
|
||||
writefile(baseafile, strings.concat(basea,
|
||||
"export fn marker() i32 = { return 7; };\n"));
|
||||
runcommandenv(root, strings.concat("persistent-export-", tags[si]),
|
||||
warmav, env, (120i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
let changedtrace: str = readfile(compilertrace);
|
||||
assert(occurrences(changedtrace, "\n") == 3);
|
||||
assert(has(changedtrace, strings.concat(artifacts[0], ".unit.new")));
|
||||
assert(has(changedtrace, strings.concat(artifacts[1], ".unit.new")));
|
||||
assert(has(changedtrace, strings.concat(artifacts[2], ".unit.new")));
|
||||
assert(!has(changedtrace, strings.concat(artifacts[3], ".unit.new")));
|
||||
let badunit: str = strings.concat(work, artifacts[0], ".unit.ww");
|
||||
assert(os.remove(badunit) == 0);
|
||||
writefile(badunit, "//ww:module-reset wrong.owner\n");
|
||||
assert(os.remove(compilertrace) == 0);
|
||||
assert(os.remove(assemblertrace) == 0);
|
||||
assert(os.remove(linkertrace) == 0);
|
||||
writefile(compilertrace, "");
|
||||
writefile(assemblertrace, "");
|
||||
writefile(linkertrace, "");
|
||||
let collisionav: []str = [driver(stages[si]), "build", "-w",
|
||||
workroot, "-o", bin, request];
|
||||
runcommandenv(root, strings.concat("storage-owner-", tags[si]),
|
||||
collisionav, env,
|
||||
(120i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 1);
|
||||
let collisiondiag: str = strings.concat(
|
||||
"ww: package storage owner mismatch at ", artifacts[0],
|
||||
" for ", baseidentity, "\n");
|
||||
assert(same(out.stderr, collisiondiag));
|
||||
assert(readfile(compilertrace).len == 0);
|
||||
assert(readfile(assemblertrace).len == 0);
|
||||
assert(readfile(linkertrace).len == 0);
|
||||
if (si == 0) { referencecollision = strings.dup(out.stderr); }
|
||||
else { assert(same(referencecollision, out.stderr)); };
|
||||
assert(os.remove(baseafile) == 0);
|
||||
writefile(baseafile, basea);
|
||||
clean(workroot);
|
||||
clean(bin);
|
||||
|
||||
@@ -2933,20 +3258,20 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
append(failenv, strings.concat("WW_W6C=", failurewrapper));
|
||||
append(failenv, strings.concat("WW_ARGV_FAILURE_TRACE=", failuretrace));
|
||||
append(failenv, strings.concat("WW_ARGV_MISSING_EXPORT=", work,
|
||||
"ww_root_parity_base_7f3.wwi"));
|
||||
artifacts[0], ".wwi"));
|
||||
append(failenv, strings.concat("WW_ARGV_MISSING_OWNER=", work,
|
||||
"ww_root_parity_left_7f3.unit.ww"));
|
||||
artifacts[1], ".unit.ww"));
|
||||
runcommandenv(root, strings.concat("exact-argv-fail-", tags[si]), av,
|
||||
failenv, (120i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 1);
|
||||
let wantfailure: str = strings.concat(
|
||||
"w6c: import ww_root_parity_base_7f3: cannot read ", work,
|
||||
"ww_root_parity_base_7f3.wwi\n",
|
||||
"ww: w6c failed for ww_root_parity_left_7f3\n");
|
||||
"w6c: import ", baseidentity, ": cannot read ", work,
|
||||
artifacts[0], ".wwi\n",
|
||||
"ww: w6c failed for ", leftidentity, "\n");
|
||||
assert(same(out.stderr, wantfailure));
|
||||
assert(has(readfile(failuretrace), strings.concat(
|
||||
"<--import><ww_root_parity_base_7f3><", work,
|
||||
"ww_root_parity_base_7f3.wwi>")));
|
||||
"<--import><", baseidentity, "><", work,
|
||||
artifacts[0], ".wwi>")));
|
||||
if (si == 0) { referencefailure = strings.dup(out.stderr); }
|
||||
else { assert(same(referencefailure, out.stderr)); };
|
||||
clean(workroot);
|
||||
@@ -2959,11 +3284,13 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
@test fn command_package_test_variants_keep_canonical_identity() void = {
|
||||
let root: str = fresh();
|
||||
let source: str = strings.concat(root, "/source");
|
||||
let target: str = strings.concat(source, "/cmdtool");
|
||||
let commandid: str = longidentity("cmdtool");
|
||||
assert(commandid.len > 255);
|
||||
let target: str = strings.concat(source, "/", importrelative(commandid));
|
||||
let importer: str = strings.concat(source, "/importer");
|
||||
let wrapper: str = strings.concat(root, "/command-w6c.sh");
|
||||
assert(os.mkdir(source, 448i32) == 0);
|
||||
assert(os.mkdir(target, 448i32) == 0);
|
||||
mkdirall(target);
|
||||
assert(os.mkdir(importer, 448i32) == 0);
|
||||
writefile(strings.concat(target, "/main.ww"), strings.concat(
|
||||
"package main;\n",
|
||||
@@ -2974,12 +3301,12 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
"@test fn command_internal() void = { assert(value() == 41); };\n"));
|
||||
writefile(strings.concat(target, "/external_test.ww"), strings.concat(
|
||||
"package main_test;\n",
|
||||
"import cmdtool;\n",
|
||||
"import ", commandid, ";\n",
|
||||
"@test fn command_external() void = { ",
|
||||
"assert(cmdtool.value() == 41); };\n"));
|
||||
writefile(strings.concat(importer, "/importer.ww"), strings.concat(
|
||||
"package importer;\n",
|
||||
"import cmdtool;\n",
|
||||
"import ", commandid, ";\n",
|
||||
"export fn value() i32 = { return cmdtool.value(); };\n"));
|
||||
writeexecutable(wrapper, strings.concat(
|
||||
"#!/bin/sh\n",
|
||||
@@ -2991,17 +3318,33 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
|
||||
let stages: []str = ["ww", "ww_ww"];
|
||||
let compilers: []str = ["w6c", "w6c_ww"];
|
||||
let artifacts: []str = ["cmdtool", "cmdtool-internal-test",
|
||||
"cmdtool_test-external-test"];
|
||||
let internalid: str = commandid;
|
||||
let externalid: str = strings.concat(commandid, "_test");
|
||||
let internalmainid: str = strings.concat("__wwtestmain.", commandid,
|
||||
".internal.main");
|
||||
let externalmainid: str = strings.concat("__wwtestmain.", externalid,
|
||||
".external.main");
|
||||
let actionids: []str = [commandid, internalid, externalid,
|
||||
internalmainid, externalmainid];
|
||||
let artifacts: []str = [packagestoragekey(commandid, target, 0, 0),
|
||||
packagestoragekey(internalid, target, 1, 0),
|
||||
packagestoragekey(externalid, target, 2, 0),
|
||||
packagestoragekey(internalmainid,
|
||||
strings.concat(target, "#internal-test-main"), 3, 2),
|
||||
packagestoragekey(externalmainid,
|
||||
strings.concat(target, "#external-test-main"), 3, 2)];
|
||||
let suffixes: []str = [".unit.ww", ".wwi", ".a"];
|
||||
let reference: []str = ["", "", "", "", "", "", "", "", ""];
|
||||
let reference: []str = ["", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", ""];
|
||||
let samebin: str = strings.concat(target, "/main.test");
|
||||
let externalbin: str = strings.concat(target, "/main_test.test");
|
||||
let workroot: str = strings.concat(samebin, ".sepwork");
|
||||
let work: str = strings.concat(workroot, "/");
|
||||
let baseenv: []str = os.getenvs();
|
||||
let si: i32 = 0;
|
||||
for (si < stages.len) {
|
||||
let workroot: str = strings.concat(root, "/command-work-", stages[si]);
|
||||
assert(os.mkdir(workroot, 448i32) == 0);
|
||||
let work: str = strings.concat(workroot, "/", requestworkkey(target),
|
||||
"/");
|
||||
let trace: str = strings.concat(root, "/", stages[si], ".trace");
|
||||
writefile(trace, "");
|
||||
let env: []str = alloc([], (baseenv.len + 3): u64)!;
|
||||
@@ -3020,24 +3363,34 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
append(env, strings.concat("WW_COMMAND_COMPILER_TRACE=", trace));
|
||||
append(env, strings.concat("WW_COMMAND_REAL_COMPILER=",
|
||||
driver(compilers[si])));
|
||||
let av: []str = [driver(stages[si]), "test", "-c", "-I", source,
|
||||
target];
|
||||
let av: []str = [driver(stages[si]), "test", "-w", workroot,
|
||||
"-I", source, target];
|
||||
let out: commandout;
|
||||
runcommandenv(root, strings.concat("command-variants-", stages[si]), av,
|
||||
env, (120i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
assert(out.stderr.len == 0);
|
||||
assert(has(out.stdout, "main.command_internal ... ok\n"));
|
||||
assert(has(out.stdout, "main_test.command_external ... ok\n"));
|
||||
|
||||
let ctrace: str = readfile(trace);
|
||||
let ai: i32 = 0;
|
||||
for (ai < artifacts.len) {
|
||||
let line: str = linecontaining(ctrace,
|
||||
strings.concat(artifacts[ai], ".unit.ww"));
|
||||
assert(has(line, "<--command-package>"));
|
||||
strings.concat(artifacts[ai], ".unit.new"));
|
||||
if (ai < 3) { assert(has(line, "<--command-package>")); }
|
||||
else { assert(has(line, "<-T><--entry>")); };
|
||||
let sj: i32 = 0;
|
||||
for (sj < suffixes.len) {
|
||||
let body: str = readfile(strings.concat(work, artifacts[ai],
|
||||
suffixes[sj]));
|
||||
if (sj == 0) {
|
||||
assert(has(body, strings.concat("//ww:module-reset ",
|
||||
actionids[ai], "\n")));
|
||||
} else { if (sj == 1) {
|
||||
assert(strings.hasprefix(body, strings.concat("//ww:module ",
|
||||
actionids[ai], "\n")));
|
||||
}; };
|
||||
let ri: i32 = ai * suffixes.len + sj;
|
||||
if (si == 0) { reference[ri] = strings.dup(body); }
|
||||
else { assert(same(reference[ri], body)); };
|
||||
@@ -3045,25 +3398,50 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
};
|
||||
ai += 1;
|
||||
};
|
||||
assert(has(readfile(strings.concat(work, "cmdtool.unit.ww")),
|
||||
"//ww:module-reset cmdtool\n"));
|
||||
assert(has(readfile(strings.concat(work,
|
||||
"cmdtool-internal-test.unit.ww")),
|
||||
"//ww:module-reset cmdtool\n"));
|
||||
assert(has(readfile(strings.concat(work,
|
||||
"cmdtool_test-external-test.unit.ww")),
|
||||
"//ww:module-reset cmdtool_test\n"));
|
||||
|
||||
let runav: []str = [samebin, "-package=main"];
|
||||
runcommand(root, strings.concat("command-internal-run-", stages[si]),
|
||||
runav, (60i64 * (time.second: i64)): time.duration, &out);
|
||||
let externalline: str = linecontaining(ctrace,
|
||||
strings.concat(artifacts[2], ".unit.new"));
|
||||
assert(has(externalline, strings.concat("<--import><", commandid,
|
||||
"><", work, artifacts[0], ".wwi>")));
|
||||
let internalmainline: str = linecontaining(ctrace,
|
||||
strings.concat(artifacts[3], ".unit.new"));
|
||||
let externalmainline: str = linecontaining(ctrace,
|
||||
strings.concat(artifacts[4], ".unit.new"));
|
||||
assert(has(internalmainline, strings.concat("<--import><", internalid,
|
||||
"><", work, artifacts[1], ".wwi>")));
|
||||
assert(has(externalmainline, strings.concat("<--import><", externalid,
|
||||
"><", work, artifacts[2], ".wwi>")));
|
||||
assert(occurrences(ctrace, strings.concat("<", work, artifacts[0],
|
||||
".unit.new>")) == 1);
|
||||
assert(has(readfile(strings.concat(work, artifacts[0], ".s")),
|
||||
strings.concat(commandid, ".value")));
|
||||
let warmrefs: []str = alloc([], reference.len: u64)!;
|
||||
warmrefs.len = reference.len;
|
||||
ai = 0;
|
||||
for (ai < artifacts.len) {
|
||||
let sj: i32 = 0;
|
||||
for (sj < suffixes.len) {
|
||||
warmrefs[ai * suffixes.len + sj] = strings.dup(readfile(
|
||||
strings.concat(work, artifacts[ai], suffixes[sj])));
|
||||
sj += 1;
|
||||
};
|
||||
ai += 1;
|
||||
};
|
||||
runcommandenv(root, strings.concat("command-warm-", stages[si]), av,
|
||||
env, (120i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
assert(has(out.stdout, "command_internal ... ok\n"));
|
||||
let externalav: []str = [externalbin, "-package=main_test"];
|
||||
runcommand(root, strings.concat("command-external-run-", stages[si]),
|
||||
externalav, (60i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
assert(has(out.stdout, "command_external ... ok\n"));
|
||||
assert(has(out.stdout, "main.command_internal ... ok\n"));
|
||||
assert(has(out.stdout, "main_test.command_external ... ok\n"));
|
||||
assert(same(ctrace, readfile(trace)));
|
||||
ai = 0;
|
||||
for (ai < artifacts.len) {
|
||||
let sj: i32 = 0;
|
||||
for (sj < suffixes.len) {
|
||||
assert(same(warmrefs[ai * suffixes.len + sj], readfile(
|
||||
strings.concat(work, artifacts[ai], suffixes[sj]))));
|
||||
sj += 1;
|
||||
};
|
||||
ai += 1;
|
||||
};
|
||||
|
||||
// The same command action is not generally source-importable. It is
|
||||
// classified before leaf validation so this Go-like diagnostic is stable,
|
||||
@@ -3076,8 +3454,8 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
runcommandenv(root, strings.concat("command-import-", stages[si]),
|
||||
importav, env, (60i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 1);
|
||||
assert(has(out.stderr,
|
||||
"package cmdtool is a program, not an importable package\n"));
|
||||
assert(has(out.stderr, strings.concat("package ", commandid,
|
||||
" is a program, not an importable package\n")));
|
||||
assert(readfile(trace).len == 0);
|
||||
|
||||
clean(workroot);
|
||||
@@ -3426,14 +3804,15 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
|
||||
@test fn persistent_package_request_workdir_is_stable() void = {
|
||||
let root: str = fresh();
|
||||
let tree: str = strings.concat(root, "/tree");
|
||||
let tree: str = deeppunctuationpath(root, "request tree");
|
||||
assert(tree.len > 255);
|
||||
let adir: str = strings.concat(tree, "/a");
|
||||
let bdir: str = strings.concat(tree, "/b");
|
||||
let a: str = strings.concat(adir, "/foo");
|
||||
let b: str = strings.concat(bdir, "/foo");
|
||||
let workc: str = strings.concat(root, "/work-c");
|
||||
let workww: str = strings.concat(root, "/work-ww");
|
||||
assert(os.mkdir(tree, 448i32) == 0);
|
||||
mkdirall(tree);
|
||||
assert(os.mkdir(adir, 448i32) == 0);
|
||||
assert(os.mkdir(bdir, 448i32) == 0);
|
||||
assert(os.mkdir(a, 448i32) == 0);
|
||||
@@ -3459,8 +3838,9 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
" [foo, same-package]\n")));
|
||||
assert(has(cold, strings.concat("ok ", b,
|
||||
" [foo, same-package]\n")));
|
||||
let ckey: str = strings.concat(workc, "/d_", workescape(tree));
|
||||
let ckey: str = strings.concat(workc, "/", requestworkkey(tree));
|
||||
assert(os.exists(ckey));
|
||||
assert(requestworkkey(tree).len == 66);
|
||||
let aaction: str = "a.foo-internal-test";
|
||||
let baction: str = "b.foo-internal-test";
|
||||
assert(os.exists(strings.concat(ckey, "/", aaction, ".unit.ww")));
|
||||
@@ -3483,7 +3863,7 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
(60i64 * (time.second: i64)): time.duration, &out);
|
||||
expectexit(&out, 0);
|
||||
assert(same(cold, out.stdout));
|
||||
let wwkey: str = strings.concat(workww, "/d_", workescape(tree));
|
||||
let wwkey: str = strings.concat(workww, "/", requestworkkey(tree));
|
||||
assert(same(aunit, readfile(strings.concat(wwkey, "/", aaction,
|
||||
".unit.ww"))));
|
||||
assert(same(bunit, readfile(strings.concat(wwkey, "/", baction,
|
||||
@@ -3515,10 +3895,10 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
|
||||
// Outside every active import root, equal declaration leaves remain two
|
||||
// deterministic command-local identities derived from canonical dirs.
|
||||
let localleft: str = strings.concat(root, "/local-left");
|
||||
let localright: str = strings.concat(root, "/local-right");
|
||||
assert(os.mkdir(localleft, 448i32) == 0);
|
||||
assert(os.mkdir(localright, 448i32) == 0);
|
||||
let localleft: str = deeppunctuationpath(root, "local left");
|
||||
let localright: str = deeppunctuationpath(root, "local right");
|
||||
mkdirall(localleft);
|
||||
mkdirall(localright);
|
||||
writefile(strings.concat(localleft, "/foo.ww"),
|
||||
"package foo;\nexport fn value() i32 = { return 11; };\n");
|
||||
writefile(strings.concat(localright, "/foo.ww"),
|
||||
@@ -3526,6 +3906,10 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
let localids: []str = [localidentity(localleft, "foo"),
|
||||
localidentity(localright, "foo")];
|
||||
assert(!same(localids[0], localids[1]));
|
||||
assert(localids[0].len > 255 && localids[1].len > 255);
|
||||
let localstorage: []str = [packagestoragekey(localids[0], localleft, 0, 0),
|
||||
packagestoragekey(localids[1], localright, 0, 0)];
|
||||
assert(!same(localstorage[0], localstorage[1]));
|
||||
let stages: []str = ["ww", "ww_ww"];
|
||||
let localrefs: []str = ["", "", "", "", "", ""];
|
||||
let si: i32 = 0;
|
||||
@@ -3550,7 +3934,14 @@ fn localidentity(dir: str, leaf: str) str = {
|
||||
let xi: i32 = 0;
|
||||
for (xi < suffixes.len) {
|
||||
let artifact: str = readfile(strings.concat(localwork,
|
||||
localids[li], suffixes[xi]));
|
||||
localstorage[li], suffixes[xi]));
|
||||
if (xi == 0) {
|
||||
assert(has(artifact, strings.concat("//ww:module-reset ",
|
||||
localids[li], "\n")));
|
||||
} else { if (xi == 1) {
|
||||
assert(strings.hasprefix(artifact, strings.concat(
|
||||
"//ww:module ", localids[li], "\n")));
|
||||
}; };
|
||||
let refi: i32 = li * 3 + xi;
|
||||
if (si == 0) { localrefs[refi] = strings.dup(artifact); }
|
||||
else { assert(same(localrefs[refi], artifact)); };
|
||||
|
||||
@@ -907,7 +907,7 @@ fn writediamond(td: str, reverse: bool) str = {
|
||||
"/.wwtool.w6a")), testenv.readfile(assembler))
|
||||
|| !testenv.same(testenv.readfile(strings.concat(work,
|
||||
"/.wwtool.stamp")),
|
||||
"ww workdir fmt 8 mode build asm 0\n")) {
|
||||
"ww workdir fmt 10 mode build asm 0\n")) {
|
||||
fail("driver-identity", "persistent artifacts or identities are incomplete");
|
||||
};
|
||||
let coldwwi: str = testenv.readfile(strings.concat(work, "/dep.wwi"));
|
||||
|
||||
Reference in New Issue
Block a user