test: accept empty skip reasons

This commit is contained in:
2026-08-22 12:59:08 +09:00
parent 78c9eee82d
commit 91fce80b37
5 changed files with 610 additions and 2 deletions

View File

@@ -18689,3 +18689,355 @@ fn runtimepath(relative: str) str = {
&& !directoryhasfragment(root, ".install"));
clean(root);
};
// A skip is an outcome even when it carries no explanatory bytes. Keep that
// boundary identical through every directory-package test descriptor and the
// retained-binary route; an empty payload must not become a harness error.
@test fn empty_skip_reason_is_a_successful_skip() void = {
let root: str = fresh();
let mixed: str = strings.concat(root, "/mixed");
let only: str = strings.concat(root, "/only");
let raw: str = strings.concat(root, "/raw_test.ww");
let oversized: str = strings.concat(root, "/oversized");
let outside: str = strings.concat(root, "/outside");
mkdirall(mixed);
mkdirall(only);
mkdirall(oversized);
mkdirall(outside);
writefile(strings.concat(mixed, "/prod.ww"), strings.concat(
"package skipmix;\n",
"import test;\n",
"export fn value() i32 = { return 7; };\n",
"export fn skip_from_production() never = { test.skip(\"\"); };\n"));
writefile(strings.concat(mixed, "/same_test.ww"), strings.concat(
"package skipmix;\n",
"import test;\n",
"@test fn aa_empty_production() void = { skip_from_production(); };\n",
"@test fn aa_empty_same() void = { test.skip(\"\"); };\n",
"@test fn ab_same_peer() void = { assert(value() == 7); };\n",
"@test fn ac_named_same() void = { test.skip(\"named reason\"); };\n"));
writefile(strings.concat(mixed, "/external_test.ww"), strings.concat(
"package skipmix_test;\n",
"import skipmix;\n",
"import test;\n",
"@test fn ad_empty_external() void = {\n",
" assert(skipmix.value() == 7); test.skip(\"\");\n",
"};\n",
"@test fn ae_external_peer() void = {\n",
" assert(skipmix.value() == 7);\n",
"};\n"));
writefile(strings.concat(only, "/only_test.ww"), strings.concat(
"package skiponly;\n",
"import test;\n",
"@test fn aa_empty_test_only() void = { test.skip(\"\"); };\n",
"@test fn ab_test_only_peer() void = { assert(true); };\n"));
writefile(raw, strings.concat(
"package rawskip;\n",
"import test;\n",
"@test fn aa_empty_raw() void = { test.skip(\"\"); };\n",
"@test fn ab_raw_peer() void = { assert(true); };\n"));
writefile(strings.concat(oversized, "/oversized_test.ww"), strings.concat(
"package skipoversized;\n",
"import strings;\n",
"import test;\n",
"@test fn too_large() void = {\n",
" let reason: []u8 = alloc([], 4094u64)!; reason.len = 4094;\n",
" let i: i32 = 0; for (i < reason.len) { reason[i] = 'x'; i += 1; };\n",
" test.skip(strings.frombytes(reason));\n",
"};\n"));
writefile(strings.concat(outside, "/main.ww"), strings.concat(
"package main;\n",
"import test;\n",
"fn main() void = { test.skip(\"\"); };\n"));
let stages: []str = ["ww", "ww_ww"];
let tags: []str = ["c", "ww"];
let works: []str = [strings.concat(root, "/work-c"),
strings.concat(root, "/work-ww")];
let oversizedworks: []str = [strings.concat(root, "/oversized-work-c"),
strings.concat(root, "/oversized-work-ww")];
let outsideworks: []str = [strings.concat(root, "/outside-work-c"),
strings.concat(root, "/outside-work-ww")];
let outsidebins: []str = [strings.concat(root, "/outside-c"),
strings.concat(root, "/outside-ww")];
let retained: []str = [strings.concat(root, "/retained-c.test"),
strings.concat(root, "/retained-ww.test")];
let runningretained: []str = [strings.concat(root, "/running-c.test"),
strings.concat(root, "/running-ww.test")];
let ordinaryout: []str = ["", ""];
let ordinaryerr: []str = ["", ""];
let emptyout: []str = ["", ""];
let emptyerr: []str = ["", ""];
let passout: []str = ["", ""];
let passerr: []str = ["", ""];
let listout: []str = ["", ""];
let listerr: []str = ["", ""];
let rawout: []str = ["", ""];
let rawerr: []str = ["", ""];
let oversizedout: []str = ["", ""];
let oversizederr: []str = ["", ""];
let runningout: []str = ["", ""];
let runningerr: []str = ["", ""];
let compileout: []str = ["", ""];
let compileerr: []str = ["", ""];
let directout: []str = ["", ""];
let directerr: []str = ["", ""];
let outsideout: []str = ["", ""];
let outsideerr: []str = ["", ""];
let out: commandout;
let si: i32 = 0;
for (si < stages.len) {
mkdirall(outsideworks[si]);
// An ordinary product may import the shared test library. Its artifact
// therefore participates in normal content invalidation, while invoking
// skip without an active test retains the preexisting abort boundary.
let outsidebuildav: []str = [driver(stages[si]), "build", "-w",
outsideworks[si], "-o", outsidebins[si], outside];
runcommand(root, strings.concat("empty-skip-outside-build-", tags[si]),
outsidebuildav, (120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(out.stdout.len == 0 && out.stderr.len == 0
&& os.exists(outsidebins[si]));
let outsiderunav: []str = [outsidebins[si]];
runcommand(root, strings.concat("empty-skip-outside-run-", tags[si]),
outsiderunav, (30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stdout.len == 0
&& same(out.stderr, "test.skip called outside a test"));
outsideout[si] = strings.dup(out.stdout);
outsideerr[si] = strings.dup(out.stderr);
assert(!directoryhasnew(outsideworks[si])
&& !directoryhasfragment(outsideworks[si], ".wwtxn.")
&& !directoryhasfragment(outsideworks[si], ".install"));
let ordinaryav: []str = [driver(stages[si]), "test", "-w",
works[si], "-I", root, mixed, only];
runcommand(root, strings.concat("empty-skip-ordinary-cold-", tags[si]),
ordinaryav, (120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(out.stderr.len == 0);
assert(occurrences(out.stdout,
"skipmix.aa_empty_production ... SKIP: \n") == 1);
assert(occurrences(out.stdout,
"skipmix.aa_empty_same ... SKIP: \n") == 1);
assert(occurrences(out.stdout,
"skipmix.ad_empty_external ... SKIP: \n") == 1);
assert(occurrences(out.stdout,
"skiponly.aa_empty_test_only ... SKIP: \n") == 1);
assert(occurrences(out.stdout,
"skipmix.ac_named_same ... SKIP: named reason\n") == 1);
assert(occurrences(out.stdout,
"skipmix.ab_same_peer ... ok\n") == 1);
assert(occurrences(out.stdout,
"skipmix.ae_external_peer ... ok\n") == 1);
assert(occurrences(out.stdout,
"skiponly.ab_test_only_peer ... ok\n") == 1);
assert(pos(out.stdout, "skipmix.aa_empty_same ... SKIP: \n")
< pos(out.stdout, "skipmix.ab_same_peer ... ok\n"));
assert(occurrences(out.stdout,
"2 passed, 0 failed, 4 skipped, 0 harness errors\n") == 1);
assert(occurrences(out.stdout,
"6 discovered, 6 selected, 6 started, 6 completed\n") == 1);
assert(occurrences(out.stdout,
"1 passed, 0 failed, 1 skipped, 0 harness errors\n") == 1);
assert(occurrences(out.stdout,
"2 discovered, 2 selected, 2 started, 2 completed\n") == 1);
assert(occurrences(out.stdout, strings.concat("ok ", mixed,
" [skipmix]\n")) == 1);
assert(occurrences(out.stdout, strings.concat("ok ", only,
" [skiponly]\n")) == 1);
assert(!has(out.stdout, "HARNESS"));
ordinaryout[si] = strings.dup(out.stdout);
ordinaryerr[si] = strings.dup(out.stderr);
// Exact repetition against persisted work preserves the externally
// visible result and leaves no transactional residue.
runcommand(root, strings.concat("empty-skip-ordinary-warm-", tags[si]),
ordinaryav, (120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(same(out.stdout, ordinaryout[si]));
assert(same(out.stderr, ordinaryerr[si]));
assert(!directoryhasnew(works[si])
&& !directoryhasfragment(works[si], ".wwtxn.")
&& !directoryhasfragment(works[si], ".install"));
let emptyav: []str = [driver(stages[si]), "test", "-w",
works[si], "-I", root, "-run", "aa_empty_same", mixed];
runcommand(root, strings.concat("empty-skip-filter-empty-", tags[si]),
emptyav, (120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(out.stderr.len == 0
&& occurrences(out.stdout,
"skipmix.aa_empty_same ... SKIP: \n") == 1
&& occurrences(out.stdout,
"0 passed, 0 failed, 1 skipped, 0 harness errors\n") == 1
&& occurrences(out.stdout,
"6 discovered, 1 selected, 1 started, 1 completed\n") == 1
&& !has(out.stdout, "ab_same_peer ...")
&& !has(out.stdout, "HARNESS"));
emptyout[si] = strings.dup(out.stdout);
emptyerr[si] = strings.dup(out.stderr);
let passav: []str = [driver(stages[si]), "test", "-w",
works[si], "-I", root, "-run", "ab_same_peer", mixed];
runcommand(root, strings.concat("empty-skip-filter-pass-", tags[si]),
passav, (120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(out.stderr.len == 0
&& occurrences(out.stdout, "skipmix.ab_same_peer ... ok\n") == 1
&& occurrences(out.stdout,
"1 passed, 0 failed, 0 skipped, 0 harness errors\n") == 1
&& occurrences(out.stdout,
"6 discovered, 1 selected, 1 started, 1 completed\n") == 1
&& !has(out.stdout, "SKIP:") && !has(out.stdout, "HARNESS"));
passout[si] = strings.dup(out.stdout);
passerr[si] = strings.dup(out.stderr);
let listav: []str = [driver(stages[si]), "test", "-w", works[si],
"-I", root, "-list", mixed, only];
runcommand(root, strings.concat("empty-skip-list-", tags[si]), listav,
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(out.stderr.len == 0);
assert(occurrences(out.stdout, "skipmix.aa_empty_same\n") == 1
&& occurrences(out.stdout, "skipmix.ad_empty_external\n") == 1
&& occurrences(out.stdout, "skiponly.aa_empty_test_only\n") == 1
&& !has(out.stdout, " ... ") && !has(out.stdout, "SKIP:")
&& !has(out.stdout, " discovered, ") && !has(out.stdout, "HARNESS"));
listout[si] = strings.dup(out.stdout);
listerr[si] = strings.dup(out.stderr);
// The raw single-file compatibility route wraps the same runtime and
// therefore accepts the same zero-byte skip payload before continuing.
let rawav: []str = [driver(stages[si]), "test", raw];
runcommand(root, strings.concat("empty-skip-raw-", tags[si]), rawav,
(120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(out.stderr.len == 0
&& occurrences(out.stdout,
"aa_empty_raw ... SKIP: \n") == 1
&& occurrences(out.stdout, "ab_raw_peer ... ok\n") == 1
&& pos(out.stdout, "aa_empty_raw ... SKIP: \n")
< pos(out.stdout, "ab_raw_peer ... ok\n")
&& occurrences(out.stdout,
"1 passed, 0 failed, 1 skipped, 0 harness errors\n") == 1
&& occurrences(out.stdout,
"2 discovered, 2 selected, 2 started, 2 completed\n") == 1
&& !has(out.stdout, "HARNESS"));
rawout[si] = strings.dup(out.stdout);
rawerr[si] = strings.dup(out.stderr);
// The empty-payload correction does not broaden the framed protocol:
// an oversized reason remains an isolated harness error.
let oversizedav: []str = [driver(stages[si]), "test", "-w",
oversizedworks[si], oversized];
runcommand(root, strings.concat("empty-skip-oversized-", tags[si]),
oversizedav, (120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(out.stderr.len == 0
&& occurrences(out.stdout, strings.concat(
"skipoversized.too_large ... ",
"HARNESS (malformed or contradictory result)\n")) == 1
&& occurrences(out.stdout,
"0 passed, 0 failed, 0 skipped, 1 harness errors\n") == 1
&& occurrences(out.stdout,
"1 discovered, 1 selected, 1 started, 1 completed\n") == 1
&& !has(out.stdout, "SKIP:"));
oversizedout[si] = strings.dup(out.stdout);
oversizederr[si] = strings.dup(out.stderr);
assert(!directoryhasnew(oversizedworks[si])
&& !directoryhasfragment(oversizedworks[si], ".wwtxn.")
&& !directoryhasfragment(oversizedworks[si], ".install"));
// Running retention consumes the same result before guarded publication.
let runningav: []str = [driver(stages[si]), "test", "-w",
works[si], "-o", runningretained[si], "-I", root, mixed];
runcommand(root, strings.concat("empty-skip-running-retained-", tags[si]),
runningav, (120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(out.stderr.len == 0
&& occurrences(out.stdout,
"skipmix.aa_empty_production ... SKIP: \n") == 1
&& occurrences(out.stdout,
"skipmix.aa_empty_same ... SKIP: \n") == 1
&& occurrences(out.stdout,
"skipmix.ad_empty_external ... SKIP: \n") == 1
&& occurrences(out.stdout,
"skipmix.ac_named_same ... SKIP: named reason\n") == 1
&& occurrences(out.stdout,
"2 passed, 0 failed, 4 skipped, 0 harness errors\n") == 1
&& occurrences(out.stdout,
"6 discovered, 6 selected, 6 started, 6 completed\n") == 1
&& !has(out.stdout, "HARNESS")
&& os.exists(runningretained[si])
&& !os.exists(strings.concat(runningretained[si], ".new"))
&& !os.exists(strings.concat(runningretained[si], ".sepwork")));
runningout[si] = strings.dup(out.stdout);
runningerr[si] = strings.dup(out.stderr);
let compileav: []str = [driver(stages[si]), "test", "-c", "-w",
works[si], "-o", retained[si], "-I", root, mixed];
runcommand(root, strings.concat("empty-skip-compile-", tags[si]),
compileav, (120i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(out.stdout.len == 0 && out.stderr.len == 0
&& os.exists(retained[si])
&& !os.exists(strings.concat(retained[si], ".new"))
&& !os.exists(strings.concat(retained[si], ".sepwork")));
compileout[si] = strings.dup(out.stdout);
compileerr[si] = strings.dup(out.stderr);
let directav: []str = [retained[si], "-package=skipmix"];
runcommand(root, strings.concat("empty-skip-direct-", tags[si]),
directav, (30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(out.stderr.len == 0
&& occurrences(out.stdout,
"skipmix.aa_empty_production ... SKIP: \n") == 1
&& occurrences(out.stdout,
"skipmix.aa_empty_same ... SKIP: \n") == 1
&& occurrences(out.stdout,
"skipmix.ad_empty_external ... SKIP: \n") == 1
&& occurrences(out.stdout,
"skipmix.ac_named_same ... SKIP: named reason\n") == 1
&& occurrences(out.stdout,
"2 passed, 0 failed, 4 skipped, 0 harness errors\n") == 1
&& occurrences(out.stdout,
"6 discovered, 6 selected, 6 started, 6 completed\n") == 1
&& !has(out.stdout, "HARNESS"));
directout[si] = strings.dup(out.stdout);
directerr[si] = strings.dup(out.stderr);
assert(!directoryhasnew(works[si])
&& !directoryhasfragment(works[si], ".wwtxn.")
&& !directoryhasfragment(works[si], ".install"));
si += 1;
};
assert(same(ordinaryout[0], ordinaryout[1])
&& same(ordinaryerr[0], ordinaryerr[1]));
assert(same(emptyout[0], emptyout[1])
&& same(emptyerr[0], emptyerr[1]));
assert(same(passout[0], passout[1])
&& same(passerr[0], passerr[1]));
assert(same(listout[0], listout[1])
&& same(listerr[0], listerr[1]));
assert(same(rawout[0], rawout[1])
&& same(rawerr[0], rawerr[1]));
assert(same(oversizedout[0], oversizedout[1])
&& same(oversizederr[0], oversizederr[1]));
assert(same(runningout[0], runningout[1])
&& same(runningerr[0], runningerr[1]));
assert(same(readfile(runningretained[0]), readfile(runningretained[1])));
assert(same(compileout[0], compileout[1])
&& same(compileerr[0], compileerr[1]));
assert(same(readfile(retained[0]), readfile(retained[1])));
assert(same(directout[0], directout[1])
&& same(directerr[0], directerr[1]));
assert(same(outsideout[0], outsideout[1])
&& same(outsideerr[0], outsideerr[1]));
assert(same(readfile(outsidebins[0]), readfile(outsidebins[1])));
assert(!directoryhasnew(root)
&& !directoryhasfragment(root, ".wwtxn.")
&& !directoryhasfragment(root, ".install"));
clean(root);
};