test: prove package initialization semantics

This commit is contained in:
2026-08-14 19:02:49 +09:00
parent c6bec0914d
commit 763bbc8f25
24 changed files with 2243 additions and 349 deletions

View File

@@ -75,31 +75,6 @@ fn astrow(label: str, src: str, needles: []str) void = {
testenv.clean(td);
};
fn rejectrow(label: str, src: str, needle: str) void = {
let td: str = testenv.fresh();
testenv.writefile(strings.concat(td, "/a.ww"), src);
let tools: []str = ["wwdump", "wwdump_ww"];
let stages: []str = ["cstage", "wwstage"];
let errors: []str = ["", ""];
let i: i32 = 0;
for (i < tools.len) {
let av: []str = [testenv.driver(tools[i]), "-a",
strings.concat(td, "/a.ww")];
let co: testenv.commandout;
testenv.runcommand(td, td, stages[i], av, tmo(), &co);
if (co.termination != exec.termination.EXIT || co.code == 0
|| !testenv.has(co.stderr, needle)) {
fail(label, strings.concat(stages[i], " accepted rejected import"));
};
errors[i] = strings.dup(co.stderr);
i += 1;
};
if (!testenv.same(errors[0], errors[1])) {
fail(label, "cs/ww parse diagnostics DIFFER");
};
testenv.clean(td);
};
@test fn astproof() void = {
let trailing: []str = ["(dot \"x\"", "(structlit",
"(tname \"pkg.point\""];
@@ -127,9 +102,11 @@ fn rejectrow(label: str, src: str, needle: str) void = {
"package main;\n",
"import stable acme.codec;\n",
"fn main() i32 = { return 0; };\n"), aliased);
rejectrow("blank-alias", strings.concat(
// A blank N_USE deliberately has no `.str` qualifier, so astprint's
// `(use` line has no quoted binding while remaining a real use node.
let blank: []str = ["(use\n"];
astrow("blank-import", strings.concat(
"package main;\n",
"import _ acme.codec;\n",
"fn main() i32 = { return 0; };\n"),
"blank import alias _ is not implemented");
"fn main() i32 = { return 0; };\n"), blank);
};

View File

@@ -1157,12 +1157,16 @@ fn hexbytes(value: str) str = {
assert(!has(externalproduction, "//ww:module "));
assert(!has(externalproduction, "SAME_TEST_SOURCE"));
assert(!has(externalproduction, "EXTERNAL_TEST_SOURCE"));
assert(same(samemainunit, strings.concat(
assert(strings.hasprefix(samemainunit, strings.concat(
"//ww:module-reset __wwtestmain.pkg.internal.main\n",
"package main;\nimport pkg;\nimport test;\n")));
assert(same(externalmainunit, strings.concat(
assert(strings.hasprefix(externalmainunit, strings.concat(
"//ww:module-reset __wwtestmain.pkg_test.external.main\n",
"package main;\nimport pkg_test;\nimport test;\n")));
assert(has(samemainunit, "//ww:direct-export pkg "));
assert(has(samemainunit, "//ww:direct-export test "));
assert(has(externalmainunit, "//ww:direct-export pkg_test "));
assert(has(externalmainunit, "//ww:direct-export test "));
assert(!has(samemainunit, "PACKAGE_PRODUCTION"));
assert(!has(samemainunit, "SAME_TEST_SOURCE"));
assert(!has(externalmainunit, "EXTERNAL_TEST_SOURCE"));
@@ -1221,13 +1225,15 @@ fn hexbytes(value: str) str = {
let productioncompile: str = linecontaining(ctrace,
"/pkg.unit.ww");
assert(same(samecompile, strings.concat(
"--test-package -c --import __same ",
"--test-package --package-init-symbol ",
"__ww..pkg.p.pkg.v1.r0.init -c --import __same ",
sharedwork, "__same.wwi --import api ", sharedwork,
"api.wwi -I ", sharedwork, "pkg-internal-test.wwi -o ",
sharedwork, "pkg-internal-test.s ", sharedwork,
"pkg-internal-test.unit.ww")));
assert(same(externalcompile, strings.concat(
"--test-package -c --import __external ",
"--test-package --package-init-symbol ",
"__ww..pkg.p.pkg_test.v2.r0.init -c --import __external ",
sharedwork, "__external.wwi --import pkg ", sharedwork,
"pkg.wwi -I ", sharedwork,
"pkg_test-external-test.wwi -o ", sharedwork,
@@ -1239,7 +1245,9 @@ fn hexbytes(value: str) str = {
"pkg_test-external-test-main.unit.ww");
assert(same(samemaincompile, strings.concat(
"-T --entry --test-support-module test ",
"--test-target-package pkg -c --import pkg ",
"--test-target-package pkg --package-init-symbol ",
"__ww..pkg.p.__wwtestmain.pkg.internal.main.v3.r2.init ",
"--init-dispatch-symbol __ww..dispatch -c --import pkg ",
sharedwork, "pkg-internal-test.wwi --import test ",
sharedwork, "test.wwi -I ", sharedwork,
"pkg-internal-test-main.wwi -o ", sharedwork,
@@ -1247,22 +1255,25 @@ fn hexbytes(value: str) str = {
"pkg-internal-test-main.unit.ww")));
assert(same(externalmaincompile, strings.concat(
"-T --entry --test-support-module test ",
"--test-target-package pkg_test -c --import pkg_test ",
"--test-target-package pkg_test --package-init-symbol ",
"__ww..pkg.p.__wwtestmain.pkg_test.external.main.v3.r2.init ",
"--init-dispatch-symbol __ww..dispatch -c --import pkg_test ",
sharedwork, "pkg_test-external-test.wwi --import test ",
sharedwork, "test.wwi -I ", sharedwork,
"pkg_test-external-test-main.wwi -o ", sharedwork,
"pkg_test-external-test-main.s ", sharedwork,
"pkg_test-external-test-main.unit.ww")));
assert(same(productioncompile, strings.concat(
"--package-init-symbol __ww..pkg.p.pkg.v0.r0.init ",
"-c --import api ", sharedwork, "api.wwi -I ", sharedwork,
"pkg.wwi -o ", sharedwork,
"pkg.s ", sharedwork, "pkg.unit.ww")));
let ltrace: str = readfile(linkertrace);
assert(occurrences(ltrace, "\n") == 2);
let samelink: str = linecontaining(ltrace,
strings.concat("-o ", samebin, " "));
strings.concat("-o ", samebin, ".new "));
let externallink: str = linecontaining(ltrace,
strings.concat("-o ", externalbin, " "));
strings.concat("-o ", externalbin, ".new "));
assert(has(samelink, strings.concat(sharedwork, "api.a")));
assert(has(samelink,
strings.concat(sharedwork, "implementation.a")));
@@ -1848,7 +1859,7 @@ fn hexbytes(value: str) str = {
ri = 0;
for (ri < bins.len) {
let link: str = linecontaining(ltrace,
strings.concat("-o ", bins[ri], " "));
strings.concat("-o ", bins[ri], ".new "));
assert(has(link, strings.concat(sharedwork, mainkeys[ri], ".a")));
assert(has(link, strings.concat(sharedwork, rootkeys[ri], ".a")));
assert(!has(link, ".wwi"));
@@ -2403,13 +2414,13 @@ fn hexbytes(value: str) str = {
let links: str = readfile(linktrace);
assert(occurrences(links, "\n") == 4);
let namedsame: str = linecontaining(links,
strings.concat("-o ", bins[0], " "));
strings.concat("-o ", bins[0], ".new "));
let namedexternal: str = linecontaining(links,
strings.concat("-o ", bins[1], " "));
strings.concat("-o ", bins[1], ".new "));
let consumersame: str = linecontaining(links,
strings.concat("-o ", bins[2], " "));
strings.concat("-o ", bins[2], ".new "));
let consumerexternal: str = linecontaining(links,
strings.concat("-o ", bins[3], " "));
strings.concat("-o ", bins[3], ".new "));
assert(has(namedsame, strings.concat(work, "__wwtest.a")));
assert(!has(namedsame, strings.concat(work, "test.a")));
assert(has(namedexternal, strings.concat(work, "test.a")));
@@ -2595,19 +2606,22 @@ fn hexbytes(value: str) str = {
let atrace: str = readfile(assemblertraces[si]);
let ltrace: str = readfile(linkertraces[si]);
assert(occurrences(ctrace, "\n") == packagecount + 1);
assert(occurrences(atrace, "\n") == packagecount + 1);
assert(occurrences(atrace, "\n") == packagecount + 2);
assert(occurrences(ltrace, "\n") == 1);
let rootline: str = linecontaining(ctrace,
strings.concat("/", rootaction, ".unit.new"));
assert(occurrences(rootline, "<--import>") == packagecount);
let expectedroot: str = "BEGIN<--entry><-c>";
let expectedroot: str = strings.concat(
"BEGIN<--entry><--package-init-symbol><__ww..pkg.p.",
rootaction, ".v0.r0.init><--init-dispatch-symbol>",
"<__ww..dispatch><-c>");
i = 0;
for (i < packagecount) {
let name: str = boundarypkgname(i);
expectedroot = strings.concat(expectedroot, "<--import><", name,
"><", works[si], "/", name, ".wwi>");
"><", works[si], "/", name, ".wwi.new>");
assert(occurrences(rootline, strings.concat("<", name, "><",
works[si], "/", name, ".wwi>")) == 1);
works[si], "/", name, ".wwi.new>")) == 1);
i += 1;
};
expectedroot = strings.concat(expectedroot, "<-I><", works[si], "/",
@@ -2617,12 +2631,14 @@ fn hexbytes(value: str) str = {
i = 0;
for (i < packagecount) {
let name: str = boundarypkgname(i);
let expectedcompile: str = "BEGIN<-c>";
let expectedcompile: str = strings.concat(
"BEGIN<--package-init-symbol><__ww..pkg.p.", name,
".v0.r0.init><-c>");
if (i + 1 < packagecount) {
let next: str = boundarypkgname(i + 1);
expectedcompile = strings.concat(expectedcompile,
"<--import><", next, "><", works[si], "/", next,
".wwi>");
".wwi.new>");
};
expectedcompile = strings.concat(expectedcompile, "<-I><",
works[si], "/", name, ".wwi.new><-o><", works[si], "/",
@@ -2634,7 +2650,7 @@ fn hexbytes(value: str) str = {
assert(same(linecontaining(atrace,
strings.concat("/", name, ".o.new")), expectedassemble));
assert(occurrences(ltrace, strings.concat("<", works[si], "/",
name, ".a>")) == 1);
name, ".a.new>")) == 1);
assert(os.exists(strings.concat(works[si], "/", name, ".wwi")));
assert(os.exists(strings.concat(works[si], "/", name, ".s")));
assert(os.exists(strings.concat(works[si], "/", name, ".o")));
@@ -2652,35 +2668,47 @@ fn hexbytes(value: str) str = {
};
let z: str = strings.concat("package ", name, ";\n// OWNER_Z_",
name, "\nfn private_value() i32 = { return value(); };\n");
assert(same(readfile(strings.concat(works[si], "/", name,
".unit.ww")), strings.concat("//ww:module-reset ", name,
"\n", a, "\n//ww:module-reset ", name, "\n", z, "\n")));
let unit: str = readfile(strings.concat(works[si], "/", name,
".unit.ww"));
assert(strings.hasprefix(unit, strings.concat("//ww:module-reset ",
name, "\n", a, "\n//ww:module-reset ", name, "\n", z, "\n")));
if (i + 1 < packagecount) {
assert(has(unit, strings.concat("//ww:direct-export ",
boundarypkgname(i + 1), " ")));
};
assert(strings.hasprefix(readfile(strings.concat(works[si], "/",
name, ".wwi")), strings.concat("//ww:module ", name, "\n")));
i += 1;
};
assert(occurrences(ltrace, strings.concat("<", works[si], "/",
rootaction, ".a>")) == 1);
rootaction, ".a.new>")) == 1);
assert(!has(ltrace, ".wwi>"));
let expectedlink: str = strings.concat("BEGIN<-o><", bins[si], "><",
works[si], "/", rootaction, ".a>");
let expectedlink: str = strings.concat("BEGIN<-o><", bins[si], ".new><",
works[si], "/", rootaction, ".a.new>");
i = 0;
for (i < packagecount) {
expectedlink = strings.concat(expectedlink, "<", works[si], "/",
boundarypkgname(i), ".a>");
boundarypkgname(i), ".a.new>");
i += 1;
};
expectedlink = strings.concat(expectedlink, "<", repo(),
"/out/bin/../lib/libwwrt.a>\n");
assert(same(ltrace, expectedlink));
assert(same(readfile(strings.concat(works[si], "/", rootaction,
".unit.ww")),
let rootunit: str = readfile(strings.concat(works[si], "/", rootaction,
".unit.ww"));
assert(strings.hasprefix(rootunit,
strings.concat("//ww:module-reset target\n", roota,
"\n//ww:module-reset target\n", rootz, "\n")));
assert(occurrences(rootunit, "//ww:direct-export p") == packagecount);
let rootassemble: str = strings.concat("BEGIN<-o><", works[si], "/",
rootaction, ".o.new><", works[si], "/", rootaction, ".s.new>");
assert(same(linecontaining(atrace,
strings.concat("/", rootaction, ".o.new")), rootassemble));
let dispatchassemble: str = strings.concat("BEGIN<-o><", works[si],
"/", rootaction, ".init.o.new><", works[si], "/", rootaction,
".init.s.new>");
assert(same(linecontaining(atrace,
strings.concat("/", rootaction, ".init.o.new")), dispatchassemble));
// Repeating the same semantic request in the persistent work root may
// relink the requested binary, but must not compile or assemble any action.
@@ -2711,16 +2739,21 @@ fn hexbytes(value: str) str = {
let adelta: str = strings.sub(chainatrace, chainabefore, chainatrace.len);
let ldelta: str = strings.sub(chainltrace, chainlbefore, chainltrace.len);
assert(occurrences(cdelta, "\n") == 1);
assert(occurrences(adelta, "\n") == 1);
assert(occurrences(adelta, "\n") == 2);
assert(occurrences(ldelta, "\n") == 1);
assert(same(cdelta, strings.concat("BEGIN<--entry><-c><--import><p000><",
assert(same(cdelta, strings.concat(
"BEGIN<--entry><--package-init-symbol><__ww..pkg.p.",
chainaction, ".v0.r0.init><--init-dispatch-symbol>",
"<__ww..dispatch><-c><--import><p000><",
works[si], "/p000.wwi><-I><", works[si], "/", chainaction,
".wwi.new><-o><", works[si], "/", chainaction, ".s.new><",
works[si], "/", chainaction, ".unit.new>\n")));
assert(same(adelta, strings.concat("BEGIN<-o><", works[si], "/",
chainaction, ".o.new><", works[si], "/", chainaction, ".s.new>\n")));
chainaction, ".o.new><", works[si], "/", chainaction, ".s.new>\n",
"BEGIN<-o><", works[si], "/", chainaction, ".init.o.new><",
works[si], "/", chainaction, ".init.s.new>\n")));
let expectedchainlink: str = strings.concat("BEGIN<-o><", chainbins[si],
"><", works[si], "/", chainaction, ".a>");
".new><", works[si], "/", chainaction, ".a.new>");
i = 0;
for (i < packagecount) {
expectedchainlink = strings.concat(expectedchainlink, "<", works[si],
@@ -2731,9 +2764,11 @@ fn hexbytes(value: str) str = {
"/out/bin/../lib/libwwrt.a>\n");
assert(same(ldelta, expectedchainlink));
assert(!has(ldelta, ".wwi>"));
assert(same(readfile(strings.concat(works[si], "/", chainaction,
".unit.ww")), strings.concat("//ww:module-reset chain\n",
chainsource, "\n")));
let chainunit: str = readfile(strings.concat(works[si], "/", chainaction,
".unit.ww"));
assert(strings.hasprefix(chainunit, strings.concat(
"//ww:module-reset chain\n", chainsource, "\n")));
assert(has(chainunit, "//ww:direct-export p000 "));
let chainrun: []str = [chainbins[si]];
runcommand(root, strings.concat("boundary-chain-run-", stages[si]),
chainrun, (60i64 * (time.second: i64)): time.duration, &out);
@@ -3308,26 +3343,20 @@ fn hexbytes(value: str) str = {
runcommand(root, strings.concat("multidir-failure-", stages[i]), av,
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stdout, "alpha_same_survives ... ok\n"));
assert(has(out.stdout, "beta_same_survives ... ok\n"));
assert(has(out.stdout, "beta_external_survives ... ok\n"));
assert(has(out.stdout, strings.concat("ok ", alpha,
" [alpha, same-package]\n")));
assert(has(out.stdout, strings.concat("ok ", beta,
" [beta, same-package]\n")));
assert(has(out.stdout, strings.concat("ok ", beta,
" [beta_test, external]\n")));
assert(!has(out.stdout, "alpha_external_fails ..."));
assert(out.stdout.len == 0);
assert(has(out.stderr, "has no exported declaration 'hidden'"));
assert(has(out.stderr, strings.concat("FAIL ", alpha,
" [alpha] (build exit 1)\n")));
assert(has(out.stderr, strings.concat("FAIL ", alpha,
" [alpha_test] (build exit 1)\n")));
assert(!has(out.stderr, strings.concat("FAIL ", alpha,
" [alpha]")));
assert(!has(out.stderr, strings.concat("FAIL ", beta, " [")));
let alphapos: i32 = pos(out.stdout, strings.concat("ok ", alpha,
" [alpha, same-package]\n"));
let betapos: i32 = pos(out.stdout, strings.concat("ok ", beta,
" [beta, same-package]\n"));
assert(has(out.stderr, strings.concat("FAIL ", beta,
" [beta] (build exit 1)\n")));
assert(has(out.stderr, strings.concat("FAIL ", beta,
" [beta_test] (build exit 1)\n")));
let alphapos: i32 = pos(out.stderr, strings.concat("FAIL ", alpha,
" [alpha] (build exit 1)\n"));
let betapos: i32 = pos(out.stderr, strings.concat("FAIL ", beta,
" [beta] (build exit 1)\n"));
assert(alphapos >= 0 && alphapos < betapos);
diagnostics[i] = strings.dup(primarydiagnostic(out.stderr));
if (i == 0) { referenceout = strings.dup(out.stdout); }
@@ -3338,8 +3367,8 @@ fn hexbytes(value: str) str = {
clean(root);
};
// One failing root is a product failure, not permission for the shared build
// request to suppress an independently compilable sibling root.
// Roots remain independently diagnosed and may be staged in parallel, but one
// failing product rejects publication and execution of the entire request.
@test fn sibling_test_variant_failures_are_isolated() void = {
let root: str = fresh();
let badexternal: str = strings.concat(root, "/badexternal");
@@ -3380,15 +3409,15 @@ fn hexbytes(value: str) str = {
runcommand(root, strings.concat("isolated-external-", tags[i]),
externalav, (120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stdout, "valid_same_runs ... ok\n"));
assert(has(out.stdout, "[badexternal, same-package]\n"));
assert(out.stdout.len == 0);
assert(has(out.stderr,
"has no exported declaration 'hidden'"));
assert(has(out.stderr,
strings.concat("FAIL ", badexternal,
" [badexternal] (build exit 1)\n")));
assert(has(out.stderr,
strings.concat("FAIL ", badexternal,
" [badexternal_test] (build exit 1)\n")));
assert(!has(out.stderr, strings.concat("FAIL ", badexternal,
" [badexternal]")));
externaldiagnostics[i] = strings.dup(primarydiagnostic(out.stderr));
let sameav: []str = [driver(stages[i]), "test", "-I", root,
@@ -3396,23 +3425,20 @@ fn hexbytes(value: str) str = {
runcommand(root, strings.concat("isolated-same-", tags[i]), sameav,
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stdout, "valid_external_runs ... ok\n"));
assert(has(out.stdout, "[badsame_test, external]\n"));
assert(out.stdout.len == 0);
assert(has(out.stderr, "undefined: missing"));
assert(has(out.stderr, strings.concat("FAIL ", badsame,
" [badsame] (build exit 1)\n")));
assert(!has(out.stderr, strings.concat("FAIL ", badsame,
" [badsame_test]")));
assert(has(out.stderr, strings.concat("FAIL ", badsame,
" [badsame_test] (build exit 1)\n")));
samediagnostics[i] = strings.dup(primarydiagnostic(out.stderr));
i += 1;
};
assert(same(externaldiagnostics[0], externaldiagnostics[1]));
assert(same(samediagnostics[0], samediagnostics[1]));
// A first persistent union pass may contain a root-local compiler failure.
// Its successfully committed actions still become reusable: only the
// uncommitted failing root is compiled again on the next request in both
// driver stages.
// A persistent request is one publication transaction. A rejection leaves
// no reusable generation, so every staged action is reconsidered next time.
let warmroot: str = strings.concat(root, "/warm-partial");
assert(os.mkdir(warmroot, 448i32) == 0);
let trace: str = strings.concat(root, "/warm-partial.trace");
@@ -3452,9 +3478,14 @@ fn hexbytes(value: str) str = {
expectexit(&out, 1);
let secondtrace: str = readfile(trace);
assert(occurrences(secondtrace,
"/badexternal-internal-test.unit.new") == 1);
"/badexternal-internal-test.unit.new") == 2);
assert(occurrences(secondtrace,
"/badexternal_test-external-test.unit.new") == 2);
assert(!os.exists(strings.concat(warmroot,
"/badexternal-internal-test.unit.ww")));
assert(!os.exists(strings.concat(warmroot,
"/badexternal_test-external-test.unit.ww")));
assert(!os.exists(strings.concat(warmroot, "/.wwtool.stamp")));
let wwtracebin: str = strings.concat(repo(), "/out/partial-trace-",
workescape(root));
@@ -3502,9 +3533,14 @@ fn hexbytes(value: str) str = {
expectexit(&out, 1);
let wwsecond: str = readfile(wwtrace);
assert(occurrences(wwsecond,
"/badexternal-internal-test.unit.new") == 1);
"/badexternal-internal-test.unit.new") == 2);
assert(occurrences(wwsecond,
"/badexternal_test-external-test.unit.new") == 2);
assert(!os.exists(strings.concat(wwwarmroot,
"/badexternal-internal-test.unit.ww")));
assert(!os.exists(strings.concat(wwwarmroot,
"/badexternal_test-external-test.unit.ww")));
assert(!os.exists(strings.concat(wwwarmroot, "/.wwtool.stamp")));
clean(wwtracebin);
clean(root);
};
@@ -3850,8 +3886,10 @@ fn hexbytes(value: str) str = {
let wantsecret: str = strings.concat(
"//ww:module-reset domain.internal.secret\n", secreta,
"\n//ww:module-reset domain.internal.secret\n", secretz, "\n");
assert(same(readfile(strings.concat(works[si],
"/domain.internal.secret.unit.ww")), wantsecret));
let secretunit: str = readfile(strings.concat(works[si],
"/domain.internal.secret.unit.ww"));
assert(strings.hasprefix(secretunit, wantsecret));
assert(has(secretunit, "//ww:direct-export domain.leaf "));
let ai: i32 = 0;
for (ai < artifacts.len) {
let xi: i32 = 0;
@@ -3869,8 +3907,13 @@ fn hexbytes(value: str) str = {
let atrace: str = readfile(assemblertraces[si]);
let ltrace: str = readfile(linkertraces[si]);
assert(occurrences(ctrace, "\n") == 3);
assert(occurrences(atrace, "\n") == 3);
assert(occurrences(atrace, "\n") == 4);
assert(occurrences(ltrace, "\n") == 1);
let dispatchline: str = strings.concat("BEGIN<-o><", works[si],
"/domain.client.init.o.new><", works[si],
"/domain.client.init.s.new>");
assert(same(linecontaining(atrace, "/domain.client.init.o.new"),
dispatchline));
let secretline: str = linecontaining(ctrace,
"domain.internal.secret.unit.new");
assert(occurrences(secretline, "domain.leaf.wwi") == 1);
@@ -4420,7 +4463,16 @@ fn hexbytes(value: str) str = {
for (ui < unitartifacts.len) {
let unit: str = readfile(strings.concat(work, unitartifacts[ui],
".unit.ww"));
assert(same(unit, wantunits[ui]));
assert(strings.hasprefix(unit, wantunits[ui]));
if (ui == 1 || ui == 2) {
assert(has(unit, strings.concat("//ww:direct-export ",
baseidentity, " ")));
} else { if (ui == 3) {
assert(has(unit, strings.concat("//ww:direct-export ",
leftidentity, " ")));
assert(has(unit, strings.concat("//ww:direct-export ",
rightidentity, " ")));
}; };
assert(!has(unit, "//ww:module "));
if (si == 0) { referenceunits[ui] = strings.dup(unit); }
else { assert(same(referenceunits[ui], unit)); };
@@ -4458,23 +4510,32 @@ fn hexbytes(value: str) str = {
let atrace: str = readfile(assemblertrace);
let ltrace: str = readfile(linkertrace);
assert(occurrences(ctrace, "\n") == 4);
let baseline: str = strings.concat("BEGIN<-c><-I><", work,
let baseline: str = strings.concat(
"BEGIN<--package-init-symbol><__ww..pkg.p.", baseidentity,
".v0.r0.init><-c><-I><", work,
artifacts[0], ".wwi><-o><", work,
artifacts[0], ".s><", work,
artifacts[0], ".unit.ww>");
let leftline: str = strings.concat("BEGIN<-c><--import>",
let leftline: str = strings.concat(
"BEGIN<--package-init-symbol><__ww..pkg.p.", leftidentity,
".v0.r0.init><-c><--import>",
"<", 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>",
let rightline: str = strings.concat(
"BEGIN<--package-init-symbol><__ww..pkg.p.", rightidentity,
".v0.r0.init><-c><--import>",
"<", 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>",
let rootline: str = strings.concat(
"BEGIN<--entry><--package-init-symbol><__ww..pkg.p.",
rootidentity, ".v0.r0.init><--init-dispatch-symbol>",
"<__ww..dispatch><-c><--import>",
"<", leftidentity, "><", work,
artifacts[1], ".wwi><--import>",
"<", rightidentity, "><", work,
@@ -4520,7 +4581,7 @@ fn hexbytes(value: str) str = {
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);
assert(occurrences(atrace, "\n") == 5);
ai = 0;
for (ai < artifacts.len) {
let assemblerline: str = strings.concat("BEGIN<-o><", work,
@@ -4529,8 +4590,12 @@ fn hexbytes(value: str) str = {
artifacts[ai], ".o")), assemblerline));
ai += 1;
};
let dispatcherline: str = strings.concat("BEGIN<-o><", work,
artifacts[3], ".init.o><", work, artifacts[3], ".init.s>");
assert(same(linecontaining(atrace, strings.concat(work,
artifacts[3], ".init.o")), dispatcherline));
assert(occurrences(ltrace, "\n") == 1);
assert(has(ltrace, strings.concat("BEGIN<-o><", bin, "><", work,
assert(has(ltrace, strings.concat("BEGIN<-o><", bin, ".new><", work,
artifacts[3], ".a>")));
ai = 0;
for (ai < artifacts.len) {
@@ -4842,17 +4907,17 @@ fn hexbytes(value: str) str = {
let externalline: str = linecontaining(ctrace,
strings.concat(artifacts[2], ".unit.new"));
assert(has(externalline, strings.concat("<--import><", commandid,
"><", work, artifacts[0], ".wwi>")));
"><", work, artifacts[0], ".wwi.new>")));
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>")));
"><", work, artifacts[1], ".wwi.new>")));
assert(has(internalmainline, strings.concat(
"<--test-target-package><", internalid, ">")));
assert(has(externalmainline, strings.concat("<--import><", externalid,
"><", work, artifacts[2], ".wwi>")));
"><", work, artifacts[2], ".wwi.new>")));
assert(has(externalmainline, strings.concat(
"<--test-target-package><", externalid, ">")));
assert(occurrences(ctrace, strings.concat("<", work, artifacts[0],
@@ -5470,27 +5535,37 @@ fn hexbytes(value: str) str = {
let commandatrace: str = readfile(commandassemblertraces[commandstage]);
let commandltrace: str = readfile(commandlinkertraces[commandstage]);
assert(occurrences(commandctrace, "\n") == 3);
assert(occurrences(commandatrace, "\n") == 3);
assert(occurrences(commandatrace, "\n") == 5);
assert(occurrences(commandltrace, "\n") == 2);
let commandalphacompile: str = linecontaining(commandctrace,
strings.concat(commandalphaid, ".unit.new"));
assert(occurrences(commandalphacompile, strings.concat(
"<--import><library><", commandwork, "library.wwi>")) == 1);
"<--import><library><", commandwork, "library.wwi.new>")) == 1);
assert(!has(commandalphacompile, "cmd-zeta.wwi"));
let alphaassembly: str = strings.concat("BEGIN<-o><", commandwork,
commandalphaid, ".init.o.new><", commandwork, commandalphaid,
".init.s.new>");
let zetaassembly: str = strings.concat("BEGIN<-o><", commandwork,
commandzetaid, ".init.o.new><", commandwork, commandzetaid,
".init.s.new>");
assert(same(linecontaining(commandatrace, strings.concat(commandalphaid,
".init.o.new")), alphaassembly));
assert(same(linecontaining(commandatrace, strings.concat(commandzetaid,
".init.o.new")), zetaassembly));
let commandalphalink: str = linecontaining(commandltrace,
strings.concat("<-o><", commandbins[commandstage], "/cmd-alpha>"));
strings.concat("<-o><", commandbins[commandstage], "/cmd-alpha.new>"));
let commandzetalink: str = linecontaining(commandltrace,
strings.concat("<-o><", commandbins[commandstage], "/cmd-zeta>"));
strings.concat("<-o><", commandbins[commandstage], "/cmd-zeta.new>"));
assert(occurrences(commandalphalink, strings.concat("<", commandwork,
commandalphaid, ".a>")) == 1);
commandalphaid, ".a.new>")) == 1);
assert(occurrences(commandalphalink, strings.concat("<", commandwork,
"library.a>")) == 1);
"library.a.new>")) == 1);
assert(!has(commandalphalink, strings.concat(commandzetaid, ".a")));
assert(!has(commandalphalink, ".wwi>"));
assert(has(commandalphalink, strings.concat("<-L><", repo(),
"/out/lib><-l><wcc>")));
assert(has(commandzetalink, strings.concat("<", commandwork,
commandzetaid, ".a>")));
commandzetaid, ".a.new>")));
assert(!has(commandzetalink, "library.a"));
assert(!has(commandzetalink, ".wwi>"));
let normalizedcommandcompiler: str = normalizedtrace(commandctrace,
@@ -7276,8 +7351,10 @@ fn runtimepath(relative: str) str = {
"//ww:module-reset ", expanded, "\n", neara, "\n",
"//ww:module-reset ", expanded, "\n", nearz, "\n",
"//ww:vendor-dir ", hexbytes(nearest), "\n");
assert(same(readfile(strings.concat(works[si], "/", expanded,
".unit.ww")), wantnear));
let nearunit: str = readfile(strings.concat(works[si], "/", expanded,
".unit.ww"));
assert(strings.hasprefix(nearunit, wantnear));
assert(has(nearunit, "//ww:direct-export lib.leaf "));
let clientunit: str = readfile(strings.concat(works[si],
"/domain.app.client.unit.ww"));
assert(has(clientunit, strings.concat("//ww:import-map lib.math ",
@@ -7299,8 +7376,14 @@ fn runtimepath(relative: str) str = {
let atrace: str = readfile(assemblertraces[si]);
let ltrace: str = readfile(linkertraces[si]);
assert(occurrences(ctrace, "\n") == 3);
assert(occurrences(atrace, "\n") == 3);
assert(occurrences(atrace, "\n") == 4);
assert(occurrences(ltrace, "\n") == 1);
assert(has(ltrace, strings.concat("BEGIN<-o><", bins[si], ".new>")));
let dispatchline: str = strings.concat("BEGIN<-o><", works[si],
"/domain.app.client.init.o.new><", works[si],
"/domain.app.client.init.s.new>");
assert(same(linecontaining(atrace,
"/domain.app.client.init.o.new"), dispatchline));
let nearline: str = linecontaining(ctrace,
strings.concat(expanded, ".unit.new"));
assert(occurrences(nearline, "<--import><lib.leaf>") == 1);
@@ -7308,16 +7391,16 @@ fn runtimepath(relative: str) str = {
let clientline: str = linecontaining(ctrace,
"domain.app.client.unit.new");
assert(occurrences(clientline, strings.concat("<--import><", expanded,
"><", works[si], "/", expanded, ".wwi>")) == 1);
"><", works[si], "/", expanded, ".wwi.new>")) == 1);
assert(occurrences(clientline, strings.concat(
"<--import-map><lib.math><", expanded, ">")) == 1);
assert(!has(clientline, "lib.leaf.wwi"));
assert(occurrences(ltrace, strings.concat("<", works[si],
"/domain.app.client.a>")) == 1);
"/domain.app.client.a.new>")) == 1);
assert(occurrences(ltrace, strings.concat("<", works[si], "/",
expanded, ".a>")) == 1);
expanded, ".a.new>")) == 1);
assert(occurrences(ltrace, strings.concat("<", works[si],
"/lib.leaf.a>")) == 1);
"/lib.leaf.a.new>")) == 1);
assert(!has(ltrace, ".wwi>"));
let nc: str = normalizedtrace(ctrace,
strings.concat(works[si], "/"), bins[si]);
@@ -7732,9 +7815,9 @@ fn runtimepath(relative: str) str = {
let externalline: str = linecontaining(testtrace,
"domain.app.testclient_test-external-test.unit.new");
assert(occurrences(internalline, strings.concat("<--import><", expanded,
"><", testwork, expanded, ".wwi>")) == 1);
"><", testwork, expanded, ".wwi.new>")) == 1);
assert(occurrences(externalline, strings.concat("<--import><", expanded,
"><", testwork, expanded, ".wwi>")) == 1);
"><", testwork, expanded, ".wwi.new>")) == 1);
assert(occurrences(internalline, strings.concat(
"<--import-map><lib.math><", expanded, ">")) == 1);
assert(occurrences(externalline, strings.concat(
@@ -8029,15 +8112,7 @@ fn runtimepath(relative: str) str = {
"for arg in \"$@\"; do printf '<%s>' \"$arg\" >> ",
"\"$WW_NAME_COMPILER_TRACE\"; done\n",
"printf '\\n' >> \"$WW_NAME_COMPILER_TRACE\"\n",
"\"$WW_NAME_REAL_COMPILER\" \"$@\"\n",
"status=$?\n",
"if [ \"$status\" -eq 0 ] && ",
"[ -n \"$WW_COMMIT_BLOCK_STAMP\" ]; then\n",
" mv -- \"$WW_COMMIT_BLOCK_STAMP\" ",
"\"$WW_COMMIT_BLOCK_STAMP.saved\" || exit 97\n",
" mkdir -- \"$WW_COMMIT_BLOCK_STAMP\" || exit 98\n",
"fi\n",
"exit \"$status\"\n"));
"exec \"$WW_NAME_REAL_COMPILER\" \"$@\"\n"));
let stages: []str = ["ww", "ww_ww"];
let compilers: []str = ["w6c", "w6c_ww"];
@@ -8059,8 +8134,6 @@ fn runtimepath(relative: str) str = {
strings.concat(root, "/ww-commit-work")];
let commitcoldbins: []str = [strings.concat(root, "/c-commit-cold"),
strings.concat(root, "/ww-commit-cold")];
let commitblockbins: []str = [strings.concat(root, "/c-commit-block"),
strings.concat(root, "/ww-commit-block")];
let commitrejectbins: []str = [strings.concat(root, "/c-commit-reject"),
strings.concat(root, "/ww-commit-reject")];
let commitfixedbins: []str = [strings.concat(root, "/c-commit-fixed"),
@@ -8087,8 +8160,6 @@ fn runtimepath(relative: str) str = {
let repeatedtraceref: str = "";
let changedtraceref: str = "";
let aliastraceref: str = "";
let commitfailref: str = "";
let commitpreflightref: str = "";
let commitbindingref: str = "";
let commitbinref: str = "";
let initialwwiref: str = "";
@@ -8115,9 +8186,7 @@ fn runtimepath(relative: str) str = {
&& !strings.hasprefix(baseenv[ei],
"WW_NAME_COMPILER_TRACE=")
&& !strings.hasprefix(baseenv[ei],
"WW_NAME_REAL_COMPILER=")
&& !strings.hasprefix(baseenv[ei],
"WW_COMMIT_BLOCK_STAMP=")) {
"WW_NAME_REAL_COMPILER=")) {
append(env, baseenv[ei]);
};
ei += 1;
@@ -8168,11 +8237,10 @@ fn runtimepath(relative: str) str = {
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 42);
// A failed multi-file artifact rename may have published a new
// interface before a later rename fails. It invalidates every old unit
// voucher and the workdir identity, so the next request must reconsider
// an importer even when the regenerated dependency export now compares
// equal to that partially published interface.
// The package and command form one publication transaction. A changed
// declared name is visible to the importer through the staged .wwi, but
// its resulting semantic rejection must preserve the complete prior
// generation and force the next request to reconsider both actions.
let commitcoldav: []str = [driver(stages[si]), "build", "-w",
commitworks[si], "-I", source, "-o", commitcoldbins[si], commitapp];
runcommandenv(root, strings.concat("name-commit-cold-", stages[si]),
@@ -8182,96 +8250,72 @@ fn runtimepath(relative: str) str = {
runcommand(root, strings.concat("name-commit-cold-run-", stages[si]),
commitrun, (30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 42);
let commitpaths: []str = ["/.wwtool.ww", "/.wwtool.w6c",
"/.wwtool.w6a", "/.wwtool.stamp", "/commit.codec.unit.ww",
"/commit.codec.wwi", "/commit.codec.s", "/commit.codec.o",
"/commit.codec.a", "/cmd.commit.unit.ww", "/cmd.commit.wwi",
"/cmd.commit.s", "/cmd.commit.o", "/cmd.commit.a",
"/cmd.commit.init.unit.ww", "/cmd.commit.init.s",
"/cmd.commit.init.o"];
let commitsnapshots: []str = alloc([], commitpaths.len: u64)!;
let cpi: i32 = 0;
for (cpi < commitpaths.len) {
append(commitsnapshots, readfile(strings.concat(commitworks[si],
commitpaths[cpi])));
cpi += 1;
};
let commitcoldbytes: str = readfile(commitcoldbins[si]);
rewritefile(commitcodecfile, cablebody);
let commitstamp: str = strings.concat(commitworks[si],
"/.wwtool.stamp");
let savedstamp: str = strings.concat(commitstamp, ".saved");
let oldcommitwwi: str = readfile(strings.concat(commitworks[si],
"/commit.codec.wwi"));
let oldcommits: str = readfile(strings.concat(commitworks[si],
"/commit.codec.s"));
let oldcommito: str = readfile(strings.concat(commitworks[si],
"/commit.codec.o"));
let oldcommita: str = readfile(strings.concat(commitworks[si],
"/commit.codec.a"));
let blockenv: []str = alloc([], (env.len + 1): u64)!;
let bei: i32 = 0;
for (bei < env.len) { append(blockenv, env[bei]); bei += 1; };
append(blockenv, strings.concat("WW_COMMIT_BLOCK_STAMP=", commitstamp));
let commitblockav: []str = [driver(stages[si]), "build", "-w",
commitworks[si], "-I", source, "-o", commitblockbins[si],
commitapp];
runcommandenv(root, strings.concat("name-commit-preflight-", stages[si]),
commitblockav, blockenv,
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stderr, "ww: cannot invalidate package workdir\n"));
if (si == 0) { commitpreflightref = strings.dup(out.stderr); }
else { assert(same(commitpreflightref, out.stderr)); };
assert(same(oldcommitwwi, readfile(strings.concat(commitworks[si],
"/commit.codec.wwi"))));
assert(same(oldcommits, readfile(strings.concat(commitworks[si],
"/commit.codec.s"))));
assert(same(oldcommito, readfile(strings.concat(commitworks[si],
"/commit.codec.o"))));
assert(same(oldcommita, readfile(strings.concat(commitworks[si],
"/commit.codec.a"))));
assert(!os.exists(strings.concat(commitworks[si],
"/commit.codec.unit.ww")));
assert(!os.exists(commitblockbins[si]));
assert(os.rmdir(commitstamp) == 0);
assert(os.rename(savedstamp, commitstamp) == 0);
// With the stamp preflight restored, force a later artifact rename to
// fail after the changed interface has already been published.
let blockedasm: str = strings.concat(commitworks[si],
"/commit.codec.s");
assert(os.remove(blockedasm) == 0);
assert(os.mkdir(blockedasm, 448i32) == 0);
let commitrejectav: []str = [driver(stages[si]), "build", "-w",
commitworks[si], "-I", source, "-o", commitrejectbins[si],
commitapp];
runcommandenv(root, strings.concat("name-commit-partial-", stages[si]),
commitrejectav, env,
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stderr, "ww: cannot commit commit.codec\n"));
if (si == 0) { commitfailref = strings.dup(out.stderr); }
else { assert(same(commitfailref, out.stderr)); };
assert(has(readfile(strings.concat(commitworks[si],
"/commit.codec.wwi")),
"//ww:module commit.codec\npackage cable;\n"));
assert(!os.exists(strings.concat(commitworks[si],
"/commit.codec.unit.ww")));
assert(!os.exists(strings.concat(commitworks[si],
"/cmd.commit.unit.ww")));
assert(!os.exists(strings.concat(commitworks[si], "/.wwtool.stamp")));
let partialsuffixes: []str = [".unit.new", ".wwi.new", ".s.new",
".o.new", ".a.new"];
let psi: i32 = 0;
for (psi < partialsuffixes.len) {
assert(!os.exists(strings.concat(commitworks[si],
"/commit.codec", partialsuffixes[psi])));
psi += 1;
".o.new", ".a.new", ".init.unit.new", ".init.s.new",
".init.o.new"];
let rejectedactions: []str = ["commit.codec", "cmd.commit"];
let attemptlabels: []str = ["0", "1"];
let attempt: i32 = 0;
for (attempt < 2) {
rewritefile(traces[si], "");
runcommandenv(root, strings.concat("name-commit-reject-",
stages[si], "-", attemptlabels[attempt]),
commitrejectav, env,
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stderr, "imported as cable and not used"));
assert(has(out.stderr, "undefined: wire"));
assert(has(out.stderr, "ww: w6c failed for cmd.commit\n"));
let ncommitbinding: str = normalizedtrace(out.stderr,
strings.concat(commitworks[si], "/"), commitrejectbins[si]);
if (si == 0 && attempt == 0) {
commitbindingref = strings.dup(ncommitbinding);
} else { assert(same(commitbindingref, ncommitbinding)); };
let rejecttrace: str = readfile(traces[si]);
assert(occurrences(rejecttrace,
"/commit.codec.unit.new") == 1);
assert(occurrences(rejecttrace,
"/cmd.commit.unit.new") == 1);
cpi = 0;
for (cpi < commitpaths.len) {
assert(same(commitsnapshots[cpi], readfile(strings.concat(
commitworks[si], commitpaths[cpi]))));
cpi += 1;
};
assert(same(commitcoldbytes, readfile(commitcoldbins[si])));
let rai: i32 = 0;
for (rai < rejectedactions.len) {
let psi: i32 = 0;
for (psi < partialsuffixes.len) {
assert(!os.exists(strings.concat(commitworks[si], "/",
rejectedactions[rai], partialsuffixes[psi])));
psi += 1;
};
rai += 1;
};
assert(!os.exists(commitrejectbins[si]));
assert(!os.exists(strings.concat(commitrejectbins[si], ".new")));
attempt += 1;
};
assert(!os.exists(commitrejectbins[si]));
assert(os.rmdir(blockedasm) == 0);
rewritefile(traces[si], "");
runcommandenv(root, strings.concat("name-commit-reconsider-", stages[si]),
commitrejectav, env,
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stderr, "undefined: wire"));
let ncommitbinding: str = normalizedtrace(out.stderr,
strings.concat(commitworks[si], "/"), commitrejectbins[si]);
if (si == 0) { commitbindingref = strings.dup(ncommitbinding); }
else { assert(same(commitbindingref, ncommitbinding)); };
assert(has(readfile(traces[si]), "/cmd.commit.unit.new"));
assert(os.exists(strings.concat(commitworks[si],
"/commit.codec.unit.ww")));
assert(!os.exists(strings.concat(commitworks[si],
"/cmd.commit.unit.ww")));
assert(!os.exists(commitrejectbins[si]));
rewritefile(commitappfile, strings.concat(
"package main;\nimport commit.codec;\n",
"fn main() i32 = { return cable.value(); };\n"));
@@ -8285,6 +8329,10 @@ fn runtimepath(relative: str) str = {
runcommand(root, strings.concat("name-commit-fixed-run-", stages[si]),
commitfixedrun, (30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 42);
assert(has(readfile(strings.concat(commitworks[si],
"/commit.codec.wwi")),
"//ww:module commit.codec\npackage cable;\n"));
assert(same(commitcoldbytes, readfile(commitcoldbins[si])));
let commitbinbytes: str = readfile(commitfixedbins[si]);
if (si == 0) { commitbinref = strings.dup(commitbinbytes); }
else { assert(same(commitbinref, commitbinbytes)); };
@@ -8614,10 +8662,12 @@ fn runtimepath(relative: str) str = {
let one: str = strings.concat(source, "/pkg/one");
let two: str = strings.concat(source, "/pkg/two");
let positives: []str = ["default", "alias", "reuse", "repeatok",
"repeatedfiles"];
"repeatedfiles", "blankalias", "blankrepeat", "blankdefault",
"blankexplicit", "blankfiles"];
let negatives: []str = ["barefn", "baretype", "baredef", "bareconst",
"barevar", "aliasbad", "aliasleak", "repeatdup", "aliasdup",
"defaultalias", "declcollision", "unusedalias", "blankalias"];
"defaultalias", "declcollision", "unusedalias", "blankqual",
"blankbare", "blankordinaryunused"];
let dirs: []str = [one, two];
let i: i32 = 0;
for (i < positives.len) {
@@ -8673,6 +8723,24 @@ fn runtimepath(relative: str) str = {
"fn second() i32 = { return right.value(); };\n"));
writefile(strings.concat(source, "/cmd/repeatedfiles/main.ww"),
"package main;\nfn main() i32 = { return first() + second(); };\n");
writefile(strings.concat(source, "/cmd/blankalias/main.ww"),
"package main;\nimport _ pkg.one;\nfn main() i32 = { return 0; };\n");
writefile(strings.concat(source, "/cmd/blankrepeat/main.ww"),
strings.concat("package main;\nimport _ pkg.one;\n",
"import _ pkg.one;\nfn main() i32 = { return 0; };\n"));
writefile(strings.concat(source, "/cmd/blankdefault/main.ww"),
strings.concat("package main;\nimport _ pkg.one;\nimport pkg.one;\n",
"fn main() i32 = { return wire.value(); };\n"));
writefile(strings.concat(source, "/cmd/blankexplicit/main.ww"),
strings.concat("package main;\nimport _ pkg.one;\n",
"import stable pkg.one;\n",
"fn main() i32 = { return stable.value(); };\n"));
writefile(strings.concat(source, "/cmd/blankfiles/a.ww"),
"package main;\nimport _ pkg.one;\n");
writefile(strings.concat(source, "/cmd/blankfiles/b.ww"),
"package main;\nimport _ pkg.one;\n");
writefile(strings.concat(source, "/cmd/blankfiles/main.ww"),
"package main;\nfn main() i32 = { return 0; };\n");
let bareexprs: []str = ["value()", "take(7)", "DEFINED", "CONSTANT",
"VARIABLE"];
@@ -8716,22 +8784,29 @@ fn runtimepath(relative: str) str = {
"fn main() i32 = { return stable(); };\n"));
writefile(strings.concat(source, "/cmd/unusedalias/main.ww"),
"package main;\nimport stable pkg.one;\nfn main() i32 = { return 0; };\n");
writefile(strings.concat(source, "/cmd/blankalias/main.ww"),
"package main;\nimport _ pkg.one;\nfn main() i32 = { return 0; };\n");
writefile(strings.concat(source, "/cmd/blankqual/main.ww"),
strings.concat("package main;\nimport _ pkg.one;\n",
"fn main() i32 = { return wire.value(); };\n"));
writefile(strings.concat(source, "/cmd/blankbare/main.ww"),
strings.concat("package main;\nimport _ pkg.one;\n",
"fn main() i32 = { return value(); };\n"));
writefile(strings.concat(source, "/cmd/blankordinaryunused/main.ww"),
strings.concat("package main;\nimport _ pkg.one;\nimport pkg.one;\n",
"fn main() i32 = { return 0; };\n"));
let stages: []str = ["ww", "ww_ww"];
let expected: []i32 = [83, 83, 40, 33, 22];
let binaryrefs: []str = ["", "", "", "", ""];
let expected: []i32 = [83, 83, 40, 33, 22, 0, 0, 11, 11, 0];
let binaryrefs: []str = ["", "", "", "", "", "", "", "", "", ""];
let diagrefs: []str = ["", "", "", "", "", "", "", "", "",
"", "", "", ""];
"", "", "", "", "", ""];
let needles: []str = ["undefined: value", "unknown type 'Thing'",
"undefined: DEFINED", "undefined: CONSTANT", "undefined: VARIABLE",
"unknown type 'wire.Thing'", "package 'stable' is not directly imported",
"wire redeclared in this block", "stable redeclared in this block",
"wire redeclared in this block",
"stable already declared through import of package stable",
"\"pkg.one\" imported as stable and not used",
"blank import alias _ is not implemented"];
"\"pkg.one\" imported as stable and not used", "undefined: wire",
"undefined: value", "\"pkg.one\" imported as wire and not used"];
let exactdiags: []str = [
strings.concat(
"$WORK/cmd.barefn.unit.new:3:1: error: \"pkg.one\" imported as wire and not used\n",
@@ -8777,8 +8852,7 @@ fn runtimepath(relative: str) str = {
strings.concat(
"$WORK/cmd.unusedalias.unit.new:3:1: error: \"pkg.one\" imported as stable and not used\n",
"ww: w6c failed for cmd.unusedalias\n"),
strings.concat(source,
"/cmd/blankalias/main.ww:2:8: error: blank import alias _ is not implemented\n"),
"", "", "",
];
let si: i32 = 0;
for (si < stages.len) {
@@ -8820,6 +8894,26 @@ fn runtimepath(relative: str) str = {
let repeatedunit: str = readfile(strings.concat(work,
"/cmd.repeatedfiles.unit.ww"));
assert(occurrences(repeatedunit, "pkg.one;") == 2);
let blankunit: str = readfile(strings.concat(work,
"/cmd.blankalias.unit.ww"));
assert(has(blankunit, "import _ pkg.one;"));
let blankwwi: str = readfile(strings.concat(work,
"/cmd.blankalias.wwi"));
assert(!has(blankwwi, "import _") && !has(blankwwi, "__ww.."));
let blankrepeat: str = readfile(strings.concat(work,
"/cmd.blankrepeat.unit.ww"));
assert(occurrences(blankrepeat, "import _ pkg.one;") == 2);
assert(occurrences(blankrepeat,
"//ww:direct-export pkg.one ") == 1);
let blankfiles: str = readfile(strings.concat(work,
"/cmd.blankfiles.unit.ww"));
assert(occurrences(blankfiles, "import _ pkg.one;") == 2);
assert(occurrences(blankfiles,
"//ww:direct-export pkg.one ") == 1);
let blankdispatch: str = readfile(strings.concat(work,
"/cmd.blankdefault.init.unit.ww"));
assert(occurrences(blankdispatch,
"//ww:init-call __ww..pkg.p.pkg.one.v0.r0.init") == 1);
i = 0;
for (i < negatives.len) {

36
test/sep/limitexec.c Normal file
View File

@@ -0,0 +1,36 @@
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <unistd.h>
/* Test-only deterministic launcher for allocation-failure observers. Keeping
* setrlimit in a repository-built helper avoids depending on util-linux paths
* or shell-specific ulimit syntax. */
int
main(int argc, char **argv)
{
if (argc < 3) {
fputs("usage: sep-limitexec bytes program [arg ...]\n", stderr);
return 2;
}
errno = 0;
char *end = NULL;
unsigned long long value = strtoull(argv[1], &end, 10);
if (errno != 0 || end == argv[1] || *end != '\0') {
fputs("sep-limitexec: invalid limit\n", stderr);
return 2;
}
struct rlimit limit;
limit.rlim_cur = (rlim_t)value;
limit.rlim_max = (rlim_t)value;
if (setrlimit(RLIMIT_AS, &limit) != 0) {
fputs("sep-limitexec: setrlimit failed\n", stderr);
return 2;
}
execv(argv[2], &argv[2]);
fputs("sep-limitexec: exec failed\n", stderr);
return 127;
}

1421
test/sep/sepinit_test.ww Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -140,6 +140,7 @@ main(void)
"import io;",
"import io.bufio;",
"import stable io.bufio;",
"import _ io.bufio;",
"def MAX: i32 = 4096;",
"export def MAX: i32 = 4096;",
"type point = struct { x: i32, y: i32 };",
@@ -149,6 +150,7 @@ main(void)
"type arr = [16]u8;",
"fn nop() void = {};",
"fn init() void = {}; fn init() void = {};",
"export fn id(x: i32) i32 = { return x; };",
"fn add(a: i32, b: i32) i32 = { return a + b; };",
"@symbol(\"malloc\") fn cmalloc(n: u64) *void;",

View File

@@ -49,6 +49,15 @@ struct row { const char *src, *expect; };
static const struct row rows[] = {
{ "fn main() void = {};", "ok" },
{ "fn init() void = {}; fn init() void = {};", "ok" },
{ "fn init(x: i32) void = {};", "func init must have no arguments and no return values" },
{ "fn init() i32 = { return 1; };", "func init must have no arguments and no return values" },
{ "fn init() void;", "func init must have a body" },
{ "export fn init() void = {};", "func init cannot be exported" },
{ "fn init() void = {}; fn f() void = { init(); };", "undefined: init" },
{ "fn make() i32 = { return 7; }; let state: i32 = make();", "ok" },
{ "fn left() i32 = { return right; }; let first: i32 = left(); let right: i32 = 3;", "ok" },
{ "fn readb() i32 = { return b; }; let a: i32 = readb(); let b: i32 = a;", "initialization cycle for a" },
{ "fn id(x: i32) i32 = { return x; };", "ok" },
{ "fn add(a: i32, b: i32) i32 = { return a + b; };", "ok" },
{ "def MAX: i32 = 4096;", "ok" },

View File

@@ -1,9 +1,9 @@
//ww:run-exit 42
package main;
type bs = struct { rbuf: []u8, mark: i32 };
fn init(b: *bs, rbuf: []u8) void = { b.rbuf = rbuf; b.mark = 9; };
fn setup(b: *bs, rbuf: []u8) void = { b.rbuf = rbuf; b.mark = 9; };
fn main() i32 = {
let raw: [8]u8; raw[0] = 0u8; let b: bs; init(&b, raw[0:5]);
let raw: [8]u8; raw[0] = 0u8; let b: bs; setup(&b, raw[0:5]);
if (b.rbuf.len != 5) { return 1; }; if (b.rbuf.cap != 8) { return 2; };
if (b.mark != 9) { return 3; }; return 42;
};

View File

@@ -16,7 +16,7 @@ export fn main() i32 = {
if (sel == 0) { src = &mstB.vt; };
let rbuf: [4]u8;
let wbuf: [4]u8;
let bc: bufio.stream = bufio.init(src, rbuf[0:4], wbuf[0:4]);
let bc: bufio.stream = bufio.newstream(src, rbuf[0:4], wbuf[0:4]);
let vs: io.stream = &bc.vt;
let out: [4]u8;
let rd = io.read(vs, out[0:4]);

View File

@@ -10,7 +10,7 @@ export fn main() i32 = {
let msrc: io.stream = &mst.vt;
let rbuf: [4]u8;
let wbuf: [4]u8;
let bc: bufio.stream = bufio.init(msrc, rbuf[0:4], wbuf[0:4]);
let bc: bufio.stream = bufio.newstream(msrc, rbuf[0:4], wbuf[0:4]);
let vs: io.stream = &bc.vt;
if (!bufio.isbuffered(vs)) { return 91; };
if (bufio.isbuffered(msrc)) { return 92; };

View File

@@ -10,7 +10,7 @@ export fn main() i32 = {
let msrc: io.stream = &mst.vt;
let rbuf: [4]u8;
let wbuf: [4]u8;
let b: bufio.stream = bufio.init(msrc, rbuf[0:4], wbuf[0:4]);
let b: bufio.stream = bufio.newstream(msrc, rbuf[0:4], wbuf[0:4]);
let vsbuf: io.stream = &b.vt;
let buf2: [4]u8;
let st2: memio.stream = memio.fixed(buf2[0:4]);

View File

@@ -12,7 +12,7 @@ export fn main() i32 = {
let msrc: io.stream = &mst.vt;
let rbuf: [8]u8;
let wbuf: [4]u8;
let b: bufio.stream = bufio.init(msrc, rbuf[0:8], wbuf[0:4]);
let b: bufio.stream = bufio.newstream(msrc, rbuf[0:8], wbuf[0:4]);
let vs: io.stream = &b.vt;
let out: [4]u8;
let rd1 = io.read(vs, out[0:3]);

View File

@@ -10,7 +10,7 @@ export fn main() i32 = {
let sinkvs: io.stream = &sink.vt;
let rb: [4]u8;
let wb: [8]u8;
let b: bufio.stream = bufio.init(sinkvs, rb[0:4], wb[0:8]);
let b: bufio.stream = bufio.newstream(sinkvs, rb[0:4], wb[0:8]);
let bvs: io.stream = &b.vt;
let semi: [1]u8;
semi[0] = 59u8;

View File

@@ -11,7 +11,7 @@ export fn main() i32 = {
let vs: io.stream = &mst.vt;
let rbuf: [4]u8;
let wbuf: [4]u8;
let b: bufio.stream = bufio.init(vs, rbuf[0:4], wbuf[0:4]);
let b: bufio.stream = bufio.newstream(vs, rbuf[0:4], wbuf[0:4]);
let bvs: io.stream = &b.vt;
let out: [4]u8;
let rd = io.read(bvs, out[0:3]);

View File

@@ -10,7 +10,7 @@ export fn main() i32 = {
let msrc: io.stream = &mst.vt;
let rbuf: [8]u8;
let wbuf: [8]u8;
let b: bufio.stream = bufio.init(msrc, rbuf[0:8], wbuf[0:8]);
let b: bufio.stream = bufio.newstream(msrc, rbuf[0:8], wbuf[0:8]);
let vs: io.stream = &b.vt;
let payload: [5]u8;
payload[0] = 104u8; payload[1] = 105u8;

View File

@@ -2,7 +2,7 @@
package main;
import math.random;
export fn main() int = {
let g: random.random = random.init(1u64);
let g: random.random = random.fromseed(1u64);
let x: u32 = random.u32n(&g, 1u32);
if (x >= 1u32) { return 1; };
return 0;

View File

@@ -2,7 +2,7 @@
package main;
import math.random;
export fn main() int = {
let g: random.random = random.init(1u64);
let g: random.random = random.fromseed(1u64);
let x: u32 = random.u32n(&g, 10u32);
if (x >= 10u32) { return 1; };
return 0;

View File

@@ -2,7 +2,7 @@
package main;
import math.random;
export fn main() int = {
let g: random.random = random.init(1u64);
let g: random.random = random.fromseed(1u64);
let x: u64 = random.u64n(&g, 1u64);
if (x >= 1u64) { return 1; };
return 0;

View File

@@ -2,7 +2,7 @@
package main;
import math.random;
export fn main() int = {
let g: random.random = random.init(1u64);
let g: random.random = random.fromseed(1u64);
let x: u64 = random.u64n(&g, 10u64);
if (x >= 10u64) { return 1; };
return 0;