ww: print final status for explicit test failures

This commit is contained in:
2026-08-21 07:39:54 +09:00
parent b5fb478613
commit 394e46ff2f
7 changed files with 388 additions and 20 deletions

View File

@@ -1159,6 +1159,7 @@ fn cwdwritedata(dir: str, label: str) void = {
assert(outc.stderr.len == 0);
assert(has(outc.stdout, strings.concat("FAIL ", p7,
" [p7] (test exit 1)\n")));
assert(strings.hassuffix(outc.stdout, "\nFAIL\n"));
let timeoutc: []str = [driver("ww"), "test", "-timeout-ms=50", "-I",
tree, "-I", failtree, p8];
@@ -1180,6 +1181,7 @@ fn cwdwritedata(dir: str, label: str) void = {
assert(outc.stderr.len == 0);
assert(has(outc.stdout, strings.concat("FAIL ", p8,
" [p8] (test exit 1)\n")));
assert(strings.hassuffix(outc.stdout, "\nFAIL\n"));
let signalc: []str = [driver("ww"), "test", "-I", tree, "-I",
failtree, p9];
@@ -1199,6 +1201,7 @@ fn cwdwritedata(dir: str, label: str) void = {
assert(outc.stderr.len == 0);
assert(has(outc.stdout, strings.concat("FAIL ", p9,
" [p9] (test exit 1)\n")));
assert(strings.hassuffix(outc.stdout, "\nFAIL\n"));
// Source-class rejection precedes every captured build or test child, so a
// nonempty caller input cannot create a partial persistent generation.
@@ -1216,7 +1219,7 @@ fn cwdwritedata(dir: str, label: str) void = {
stdinpath, (60i64 * (time.second: i64)): time.duration, &outw);
expectexit(&outc, 1);
expectexit(&outw, 1);
assert(outc.stdout.len == 0 && outw.stdout.len == 0);
assert(same(outc.stdout, "FAIL\n") && same(outw.stdout, "FAIL\n"));
assert(same(outc.stderr, outw.stderr));
assert(has(outc.stderr,
"test package must match production package or <package>_test\n"));
@@ -1360,6 +1363,7 @@ fn cwdwritedata(dir: str, label: str) void = {
(90i64 * (time.second: i64)): time.duration, &outc);
expectexit(&outc, 1);
cwdassertpackage(outc.stdout, "p7-fail", p7, "p7-data", "p7-testdata");
assert(strings.hassuffix(outc.stdout, "\nFAIL\n"));
assert(same(retainedbytes, readfile(retained)));
runcommandinputenvdir(root, "path-retain-fail-ww", retainfailw, wenv,
caller, stdinpath,
@@ -1735,6 +1739,7 @@ fn cwdwritedata(dir: str, label: str) void = {
(90i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stderr.len == 0);
assert(strings.hassuffix(out.stdout, "\nFAIL\n"));
assert(has(out.stdout, "partial-success\nok "));
assert(!has(out.stdout, "partial-successok "));
assert(has(out.stdout, "partial-failure\nFAIL "));
@@ -1792,6 +1797,133 @@ fn cwdwritedata(dir: str, label: str) void = {
clean(root);
};
@test fn explicit_test_failure_has_final_status() void = {
let root: str = fresh();
let fail: str = strings.concat(root, "/fail");
let pass: str = strings.concat(root, "/pass");
let setup: str = strings.concat(root, "/setup");
mkdirall(fail); mkdirall(pass); mkdirall(setup);
let failfile: str = strings.concat(fail, "/fail_test.ww");
writefile(failfile, strings.concat(
"package final_fail;\n",
"@test fn fails() void = { assert(false); };\n"));
writefile(strings.concat(pass, "/pass_test.ww"), strings.concat(
"package final_pass;\n",
"@test fn passes() void = { assert(true); };\n"));
writefile(strings.concat(setup, "/bad_test.ww"), strings.concat(
"package final_setup;\nimport nowhere;\n",
"@test fn unreachable() void = { void; };\n"));
let stages: []str = ["ww", "ww_ww"];
let tags: []str = ["c", "ww"];
let multiout: []str = ["", ""];
let multierr: []str = ["", ""];
let rawout: []str = ["", ""];
let setuperr: []str = ["", ""];
let out: commandout;
let i: i32 = 0;
for (i < stages.len) {
let multiav: []str = [driver(stages[i]), "test", "-j", "2",
fail, pass];
runcommand(root, strings.concat("final-multi-", tags[i]), multiav,
(60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stderr.len == 0);
assert(strings.hassuffix(out.stdout, "\nFAIL\n"));
assert(occurrences(out.stdout, "\nFAIL\n") == 1);
assert(has(out.stdout, strings.concat("ok ", pass,
" [final_pass]\nFAIL\n")));
multiout[i] = strings.dup(out.stdout);
multierr[i] = strings.dup(out.stderr);
let filterav: []str = [driver(stages[i]), "test", "-run", "fails",
fail];
runcommand(root, strings.concat("final-filter-", tags[i]), filterav,
(60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stderr.len == 0);
assert(strings.hassuffix(out.stdout, "\nFAIL\n"));
let listav: []str = [driver(stages[i]), "test", "-list", setup];
runcommand(root, strings.concat("final-list-", tags[i]), listav,
(60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(same(out.stdout, "FAIL\n"));
assert(has(out.stderr, "cannot find package nowhere\n"));
let rawav: []str = [driver(stages[i]), "test", failfile];
runcommand(root, strings.concat("final-raw-", tags[i]), rawav,
(60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stderr.len == 0);
assert(strings.hassuffix(out.stdout, "\nFAIL\n"));
assert(!has(out.stdout, strings.concat("FAIL ", fail, " [")));
rawout[i] = strings.dup(out.stdout);
let setupav: []str = [driver(stages[i]), "test", setup];
runcommand(root, strings.concat("final-setup-", tags[i]), setupav,
(60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(same(out.stdout, "FAIL\n"));
assert(has(out.stderr, "cannot find package nowhere\n"));
assert(has(out.stderr, strings.concat("FAIL ", setup,
" [final_setup] (build exit 1)\n")));
setuperr[i] = strings.dup(out.stderr);
let missing: str = strings.concat(root, "/missing");
let missingav: []str = [driver(stages[i]), "test", missing];
runcommand(root, strings.concat("final-missing-", tags[i]), missingav,
(60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(same(out.stdout, "FAIL\n"));
assert(same(out.stderr, strings.concat("ww test: cannot find ",
missing, "\n")));
let implicitav: []str = [driver(stages[i]), "test"];
runcommanddir(root, strings.concat("final-implicit-", tags[i]), fail,
implicitav, (60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stderr.len == 0);
assert(!strings.hassuffix(out.stdout, "\nFAIL\n"));
let compileav: []str = [driver(stages[i]), "test", "-c", setup];
runcommand(root, strings.concat("final-compile-", tags[i]), compileav,
(60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stdout.len == 0);
assert(has(out.stderr, "cannot find package nowhere\n"));
let successav: []str = [driver(stages[i]), "test", pass];
runcommand(root, strings.concat("final-success-", tags[i]), successav,
(60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(out.stderr.len == 0);
assert(!strings.hassuffix(out.stdout, "\nFAIL\n"));
let retained: str = strings.concat(root, "/retained-", tags[i], ".test");
writefile(retained, "prior-test-binary\n");
let retainav: []str = [driver(stages[i]), "test", "-o", retained,
fail];
runcommand(root, strings.concat("final-retained-", tags[i]), retainav,
(60i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stderr.len == 0);
assert(strings.hassuffix(out.stdout, "\nFAIL\n"));
assert(same(readfile(retained), "prior-test-binary\n"));
assert(!os.exists(strings.concat(retained, ".new")));
assert(!directoryhasfragment(root, ".wwtxn."));
i += 1;
};
assert(same(multiout[0], multiout[1]));
assert(same(multierr[0], multierr[1]));
assert(same(rawout[0], rawout[1]));
assert(same(setuperr[0], setuperr[1]));
assert(same(readfile(strings.concat(root, "/retained-c.test")),
readfile(strings.concat(root, "/retained-ww.test"))));
assert(!directoryhasnew(root));
clean(root);
};
@test fn imported_dependency_tests_do_not_leak() void = {
let root: str = fresh();
let base: str = packagepath("dependency");
@@ -4967,7 +5099,7 @@ fn cwdwritedata(dir: str, label: str) void = {
runcommand(root, strings.concat("multidir-failure-", stages[i]), av,
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stdout.len == 0);
assert(same(out.stdout, "FAIL\n"));
assert(has(out.stderr, "has no exported declaration 'hidden'"));
assert(has(out.stderr, strings.concat("FAIL ", alpha,
" [alpha] (build exit 1)\n")));
@@ -5033,7 +5165,7 @@ fn cwdwritedata(dir: str, label: str) void = {
runcommand(root, strings.concat("isolated-external-", tags[i]),
externalav, (120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stdout.len == 0);
assert(same(out.stdout, "FAIL\n"));
assert(has(out.stderr,
"has no exported declaration 'hidden'"));
assert(has(out.stderr,
@@ -5049,7 +5181,7 @@ fn cwdwritedata(dir: str, label: str) void = {
runcommand(root, strings.concat("isolated-same-", tags[i]), sameav,
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stdout.len == 0);
assert(same(out.stdout, "FAIL\n"));
assert(has(out.stderr, "undefined: missing"));
assert(has(out.stderr, strings.concat("FAIL ", badsame,
" [badsame] (build exit 1)\n")));
@@ -8168,12 +8300,15 @@ fn cwdwritedata(dir: str, label: str) void = {
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
let foldfullwant: str = foldwants[fi];
let foldstdoutwant: str = "";
if (same(foldmodes[fi], "test")) {
foldfullwant = strings.concat(foldwants[fi], "FAIL ",
foldtargets[fi], " [", foldpackages[fi],
"] (build exit 1)\n");
foldstdoutwant = "FAIL\n";
};
assert(out.stdout.len == 0 && same(out.stderr, foldfullwant));
assert(same(out.stdout, foldstdoutwant)
&& same(out.stderr, foldfullwant));
assert(readfile(compilertrace).len == 0);
assert(readfile(assemblertrace).len == 0);
assert(readfile(linkertrace).len == 0);