wwtest: native package-test coordinator

Single-directory package-test planner: discovers *.ww, groups white-box
and external <pkg>_test sources, composes the combined test package,
builds it through the sibling ww driver, and runs it with the runtime's
-package/-list/-timeout-ms contract. test/package holds its E2E corpus
and the manual runtime fixture set.
This commit is contained in:
2026-08-07 23:01:03 +09:00
parent ff042df937
commit 7a2c21acfb
34 changed files with 1598 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
package bad_external;
export fn value() int = { return 1; };

View File

@@ -0,0 +1,3 @@
package unrelated_test;
@test fn wrong_external_name() void = { assert(true); };

View File

@@ -0,0 +1,5 @@
package assert_failure_test;
@test fn assertion_failure() void = {
assert(false, "synthetic assertion failure");
};

View File

@@ -0,0 +1,25 @@
package descendant_test;
import os;
@test fn normal_return_clears_descendant() void = {
let ready: [2]i32;
assert(os.pipe(&ready) == 0);
let pid: i32 = os.fork();
assert(pid >= 0);
if (pid == 0) {
os.close(ready[0]);
let mask: u64 = 1u64 << ((os.SIGTERM - 1): u64);
if (os.sigprocmask(os.SIG_BLOCK, &mask, nil: *u64) != 0) {
os.exit(120);
};
let b: [1]u8 = [1u8];
if (os.write(ready[1], &b[0], 1u64) != 1i64) { os.exit(121); };
os.close(ready[1]);
for (true) { };
};
os.close(ready[1]);
let b: [1]u8;
assert(os.read(ready[0], &b[0], 1u64) == 1i64);
os.close(ready[0]);
};

View File

@@ -0,0 +1,5 @@
package multi_fail_test;
@test fn first_failure() void = { assert(false); };
@test fn second_failure() void = { assert(false); };
@test fn continuation_after_failures() void = { assert(true); };

View File

@@ -0,0 +1,5 @@
package nonzero_test;
import os;
@test fn deliberate_nonzero_exit() void = { os.exit(7); };

View File

@@ -0,0 +1,18 @@
package pass_test;
import test;
@test fn alpha_pass() void = {
assert(test.current() == "pass_test.alpha_pass");
};
@test fn beta_skip() void = {
test.skip("synthetic unavailable feature");
};
@test fn gamma_expected_abort() void = {
test.expectabort();
abort();
};
@test fn delta_pass() void = { assert(6 * 7 == 42); };

View File

@@ -0,0 +1,5 @@
package premature_test;
import os;
@test fn clean_exit_without_completion() void = { os.exit(0); };

View File

@@ -0,0 +1,7 @@
package signal_test;
import os;
@test fn signal_is_not_exit() void = {
os.kill(os.getpid(), os.SIGTERM);
};

View File

@@ -0,0 +1,16 @@
package timeout_test;
import os;
@test fn timeout_clears_term_resistant_descendant() void = {
let pid: i32 = os.fork();
assert(pid >= 0);
if (pid == 0) {
let mask: u64 = 1u64 << ((os.SIGTERM - 1): u64);
if (os.sigprocmask(os.SIG_BLOCK, &mask, nil: *u64) != 0) {
os.exit(120);
};
for (true) { };
};
for (true) { };
};

View File

@@ -0,0 +1,4 @@
package dep;
// A production filename ending in "test.ww" is not a test by itself.
export fn bonus() int = { return 2; };

View File

@@ -0,0 +1,3 @@
package dep;
export fn value() int = { return 40; };

View File

@@ -0,0 +1,7 @@
package dep;
// Noncanonical migration spelling: the actual line-leading @test makes this
// test-only. It must be excluded when dep is imported by the root package.
@test fn imported_dependency_test_must_not_leak() void = {
assert(false);
};

View File

@@ -0,0 +1,5 @@
package root;
import dep;
fn answer() int = { return dep.value() + dep.bonus(); };

View File

@@ -0,0 +1,5 @@
package root;
@test fn imported_production_only() void = {
assert(answer() == 42);
};

View File

@@ -0,0 +1,3 @@
package no_tests;
export fn value() int = { return 1; };

View File

@@ -0,0 +1,444 @@
package package_test;
// Native end-to-end checks for the first single-directory package route.
// Make builds and invokes this one binary; discovery, subprocess ownership,
// output interpretation, and assertions remain WW code.
import os;
import os.exec;
import strings;
import temp;
import time;
type commandout = struct {
termination: exec.termination,
code: i32,
stdout: str,
stderr: str,
};
fn envrequired(name: str) str = {
match (os.getenv(name)) {
case let value: str => {
assert(value.len != 0);
return strings.dup(value);
};
case void => abort("missing package-test environment");
};
};
fn repo() str = { return envrequired("WW_PACKAGE_REPO"); };
fn driver(name: str) str = {
return strings.concat(repo(), "/out/bin/", name);
};
fn readfile(path: str) str = {
let fd: i32 = os.open(path, os.flag.RDONLY, 0i32);
assert(fd >= 0);
let sr: (i64 | os.oserror) = os.filesize(fd);
let n: i64 = -1i64;
match (sr) {
case let v: i64 => n = v;
case let e: os.oserror => abort("filesize failed");
};
assert(n >= 0i64);
let b: []u8 = alloc([], (n + 1i64): u64)!;
b.len = (n + 1i64): i32;
let rr: (i64 | os.oserror) = os.readall(fd, b.ptr, n: u64);
os.close(fd);
let got: i64 = -1i64;
match (rr) {
case let v: i64 => got = v;
case let e: os.oserror => abort("read failed");
};
assert(got == n);
let ni: i32 = n: i32;
b[ni] = 0u8;
let out: str;
out.ptr = b.ptr;
out.len = n: i32;
return out;
};
fn writefile(path: str, content: str) void = {
let fd: i32 = os.open(path,
os.flag.WRONLY | os.flag.CREATE | os.flag.EXCL, 384i32);
assert(fd >= 0);
match (os.writeall(fd, content.ptr, content.len: u64)) {
case let n: i64 => assert(n == content.len: i64);
case let e: os.oserror => abort("write failed");
};
assert(os.close(fd) == 0);
};
fn runcommand(root: str, name: str, argv: []str,
lifetime: time.duration, out: *commandout) void = {
let c: exec.command;
c.path = argv[0];
c.argv = argv;
c.env = os.getenvs();
c.dir = repo();
c.stdoutpath = strings.concat(root, "/", name, ".stdout");
c.stderrpath = strings.concat(root, "/", name, ".stderr");
c.deadline = time.add(time.now(time.clock.monotonic), lifetime);
c.grace = (100i64 * (time.millisecond: i64)): time.duration;
let r: exec.result;
exec.run(&c, &r);
assert(r.errno == 0 && r.cleanuperrno == 0);
out.termination = r.termination;
out.code = r.code;
out.stdout = readfile(c.stdoutpath);
out.stderr = readfile(c.stderrpath);
};
fn clean(root: str) void = {
let av: []str = ["/bin/rm", "-rf", "--", root];
let c: exec.command;
c.path = av[0];
c.argv = av;
c.env = os.getenvs();
c.dir = "/";
c.stdoutpath = strings.concat(root, ".cleanup.stdout");
c.stderrpath = strings.concat(root, ".cleanup.stderr");
c.deadline = time.add(time.now(time.clock.monotonic), time.second);
c.grace = (50i64 * (time.millisecond: i64)): time.duration;
let r: exec.result;
exec.run(&c, &r);
assert(r.termination == exec.termination.EXIT && r.code == 0);
assert(os.remove(c.stdoutpath) == 0);
assert(os.remove(c.stderrpath) == 0);
};
fn fresh() str = { return strings.dup(temp.dir()); };
fn pos(haystack: str, needle: str) i32 = {
match (strings.index(haystack, needle)) {
case let n: i32 => return n;
case void => return -1;
};
};
fn has(haystack: str, needle: str) bool = {
return pos(haystack, needle) >= 0;
};
fn same(a: str, b: str) bool = {
if (a.len != b.len) { return false; };
let i: i32 = 0;
for (i < a.len) {
if (a[i] != b[i]) { return false; };
i += 1;
};
return true;
};
fn occurrences(haystack: str, needle: str) i32 = {
if (needle.len == 0 || haystack.len < needle.len) { return 0; };
let count: i32 = 0;
let i: i32 = 0;
for (i + needle.len <= haystack.len) {
let matches: bool = true;
let j: i32 = 0;
for (j < needle.len) {
if (haystack[i + j] != needle[j]) { matches = false; break; };
j += 1;
};
if (matches) { count += 1; i += needle.len; }
else { i += 1; };
};
return count;
};
fn expectexit(out: *commandout, code: i32) void = {
assert(out.termination == exec.termination.EXIT);
assert(out.code == code);
};
fn packagepath(relative: str) str = {
return strings.concat(repo(), "/test/package/", relative);
};
@test fn deterministic_routing_and_filters() void = {
let root: str = fresh();
let target: str = packagepath("routing");
let av: []str = [driver("ww"), "test", "-list", target];
let out: commandout;
runcommand(root, "list", av, (30i64 * (time.second: i64)): time.duration,
&out);
expectexit(&out, 0);
let first: i32 = pos(out.stdout, "routing.private_helper_first\n");
let second: i32 = pos(out.stdout, "routing.same_package\n");
let third: i32 = pos(out.stdout, "routing_test.external_package\n");
assert(first >= 0 && first < second && second < third);
assert(occurrences(out.stdout, "routing.private_helper_first\n") == 1);
assert(occurrences(out.stdout, "routing.same_package\n") == 1);
assert(occurrences(out.stdout, "routing_test.external_package\n") == 1);
let rav: []str = [driver("ww"), "test", target];
runcommand(root, "run", rav,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(has(out.stdout, "routing.private_helper_first ... ok\n"));
assert(has(out.stdout, "routing.same_package ... ok\n"));
assert(has(out.stdout, "routing_test.external_package ... ok\n"));
assert(has(out.stdout,
"2 passed, 0 failed, 0 skipped, 0 harness errors\n"));
assert(has(out.stdout,
"1 passed, 0 failed, 0 skipped, 0 harness errors\n"));
let fav: []str = [driver("ww"), "test", "-run",
"routing.private_helper_first", "-filter", "external_package",
target];
runcommand(root, "filters", fav,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(has(out.stdout, "routing.private_helper_first ... ok\n"));
assert(!has(out.stdout, "routing.same_package ..."));
assert(has(out.stdout, "routing_test.external_package ... ok\n"));
let nav: []str = [driver("ww"), "test", "-run", "no-such-*", target];
runcommand(root, "nomatch", nav,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(occurrences(out.stdout, "[no matches]\n") == 2);
assert(occurrences(out.stdout,
"1 discovered, 0 selected, 0 started, 0 completed\n") == 1);
assert(occurrences(out.stdout,
"2 discovered, 0 selected, 0 started, 0 completed\n") == 1);
let lnav: []str = [driver("ww"), "test", "-list", "-run",
"no-such-*", target];
runcommand(root, "list-nomatch", lnav,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(occurrences(out.stdout, "[no matches]\n") == 2);
clean(root);
};
@test fn imported_dependency_tests_do_not_leak() void = {
let root: str = fresh();
let base: str = packagepath("dependency");
let av: []str = [driver("ww"), "test", "-I", base,
strings.concat(base, "/root")];
let out: commandout;
runcommand(root, "dependency", av,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(has(out.stdout, "root.imported_production_only ... ok\n"));
assert(!has(out.stdout, "imported_dependency_test_must_not_leak"));
assert(has(out.stdout,
"1 discovered, 1 selected, 1 started, 1 completed\n"));
clean(root);
};
@test fn empty_and_invalid_package_classes() void = {
let root: str = fresh();
let av: []str = [driver("ww"), "test", packagepath("no_tests")];
let out: commandout;
runcommand(root, "notests", av,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(has(out.stdout, " [no tests]\n"));
assert(!has(out.stdout, " ... ok"));
let bad: []str = [driver("ww"), "test", packagepath("bad_external")];
runcommand(root, "badexternal", bad,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stderr,
"test package must match production package or <package>_test"));
let empty: str = strings.concat(root, "/empty");
assert(os.mkdir(empty, 448i32) == 0);
let emptyav: []str = [driver("ww"), "test", empty];
runcommand(root, "emptydir", emptyav,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stderr, "directory contains no WW package sources"));
clean(root);
};
@test fn symlink_package_is_rejected() void = {
let root: str = fresh();
let real: str = strings.concat(root, "/real");
let link: str = strings.concat(root, "/link");
assert(os.mkdir(real, 448i32) == 0);
writefile(strings.concat(real, "/real.ww"),
"package real;\nexport fn value() int = { return 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"));
clean(root);
};
@test fn pass_skip_and_expected_abort() void = {
let root: str = fresh();
let av: []str = [driver("ww"), "test", packagepath("cases/pass")];
let out: commandout;
runcommand(root, "pass", av,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(has(out.stdout, "pass_test.alpha_pass ... ok\n"));
assert(has(out.stdout,
"pass_test.beta_skip ... SKIP: synthetic unavailable feature\n"));
assert(has(out.stdout, "pass_test.gamma_expected_abort ... ok\n"));
assert(has(out.stdout, "pass_test.delta_pass ... ok\n"));
assert(has(out.stdout,
"3 passed, 0 failed, 1 skipped, 0 harness errors\n"));
assert(has(out.stdout,
"4 discovered, 4 selected, 4 started, 4 completed\n"));
clean(root);
};
@test fn failures_are_distinct_and_clamped() void = {
let root: str = fresh();
let out: commandout;
let av: []str = [driver("ww"), "test",
packagepath("cases/assert_failure")];
runcommand(root, "assert", av,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stdout,
"assert_failure_test.assertion_failure ... FAIL (exit 1)\n"));
assert(!has(out.stderr, "captures:"));
let nonzeroav: []str = [driver("ww"), "test",
packagepath("cases/nonzero")];
runcommand(root, "nonzero", nonzeroav,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stdout,
"nonzero_test.deliberate_nonzero_exit ... FAIL (exit 7)\n"));
let prematureav: []str = [driver("ww"), "test",
packagepath("cases/premature")];
runcommand(root, "premature", prematureav,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stdout,
"premature_test.clean_exit_without_completion ... HARNESS (incomplete result)\n"));
let signalav: []str = [driver("ww"), "test",
packagepath("cases/signal")];
runcommand(root, "signal", signalav,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stdout,
"signal_test.signal_is_not_exit ... FAIL (signal 15)\n"));
let multiav: []str = [driver("ww"), "test",
packagepath("cases/multi_fail")];
runcommand(root, "multifail", multiav,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stdout,
"1 passed, 2 failed, 0 skipped, 0 harness errors\n"));
assert(has(out.stdout,
"3 discovered, 3 selected, 3 started, 3 completed\n"));
clean(root);
};
@test fn timeout_and_descendant_cleanup() void = {
let root: str = fresh();
let av: []str = [driver("ww"), "test", "-timeout-ms=100",
packagepath("cases/timeout")];
let out: commandout;
runcommand(root, "timeout", av,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 1);
assert(has(out.stdout,
"timeout_test.timeout_clears_term_resistant_descendant ... FAIL(timeout)\n"));
assert(has(out.stdout,
"1 discovered, 1 selected, 1 started, 1 completed\n"));
let descendantav: []str = [driver("ww"), "test",
packagepath("cases/descendant")];
runcommand(root, "descendant", descendantav,
(30i64 * (time.second: i64)): time.duration, &out);
expectexit(&out, 0);
assert(has(out.stdout,
"descendant_test.normal_return_clears_descendant ... ok\n"));
assert(!has(out.stdout, "HARNESS"));
clean(root);
};
@test fn cstage_wwstage_behavior_and_assembly_match() void = {
let root: str = fresh();
writefile(strings.concat(root, "/route.ww"),
"package route;\nexport fn value() int = { return 7; };\n");
writefile(strings.concat(root, "/a_test.ww"),
"package route;\n@test fn white() void = { assert(value() == 7); };\n");
writefile(strings.concat(root, "/z_test.ww"),
"package route_test;\nimport route;\n@test fn external() void = { assert(route.value() == 7); };\n");
let outc: commandout;
let outw: commandout;
let listc: []str = [driver("ww"), "test", "-list", root];
let listw: []str = [driver("ww_ww"), "test", "-list", root];
runcommand(root, "list-c", listc,
(30i64 * (time.second: i64)): time.duration, &outc);
runcommand(root, "list-ww", listw,
(30i64 * (time.second: i64)): time.duration, &outw);
expectexit(&outc, 0);
expectexit(&outw, 0);
assert(same(outc.stdout, outw.stdout));
assert(same(outc.stderr, outw.stderr));
let misusec: []str = [driver("ww"), "test", "-run"];
let misusew: []str = [driver("ww_ww"), "test", "-run"];
runcommand(root, "misuse-c", misusec, time.second, &outc);
runcommand(root, "misuse-ww", misusew, time.second, &outw);
expectexit(&outc, 2);
expectexit(&outw, 2);
assert(same(outc.stdout, outw.stdout));
assert(same(outc.stderr, outw.stderr));
assert(has(outc.stderr, "ww test: -run needs an argument\n"));
let timeoutc: []str = [driver("ww"), "test",
"-timeout-ms=4000000", root];
let timeoutw: []str = [driver("ww_ww"), "test",
"-timeout-ms=4000000", root];
runcommand(root, "timeout-misuse-c", timeoutc, time.second, &outc);
runcommand(root, "timeout-misuse-ww", timeoutw, time.second, &outw);
expectexit(&outc, 2);
expectexit(&outw, 2);
assert(same(outc.stdout, outw.stdout));
assert(same(outc.stderr, outw.stderr));
assert(has(outc.stderr, "usage: wwtest package"));
let cc: []str = [driver("ww"), "test", "-c", root];
runcommand(root, "compile-c", cc,
(30i64 * (time.second: i64)): time.duration, &outc);
expectexit(&outc, 0);
assert(has(outc.stdout, strings.concat(" -> ", root, "/route.test\n")));
assert(has(outc.stdout,
strings.concat(" -> ", root, "/route_test.test\n")));
let cwhite: str = readfile(strings.concat(root,
"/route.test.sepwork/__root.s"));
let cexternal: str = readfile(strings.concat(root,
"/route_test.test.sepwork/__root.s"));
// The explicit package `-c` outputs are caller-owned artifacts. Release
// the two exact C-stage trees before asking the WW driver to acquire the
// same stems; the driver never deletes a pre-existing `.sepwork` path.
clean(strings.concat(root, "/route.test.sepwork"));
clean(strings.concat(root, "/route_test.test.sepwork"));
let wc: []str = [driver("ww_ww"), "test", "-c", root];
runcommand(root, "compile-ww", wc,
(30i64 * (time.second: i64)): time.duration, &outw);
expectexit(&outw, 0);
assert(same(outc.stdout, outw.stdout));
assert(same(outc.stderr, outw.stderr));
assert(same(cwhite, readfile(strings.concat(root,
"/route.test.sepwork/__root.s"))));
assert(same(cexternal, readfile(strings.concat(root,
"/route_test.test.sepwork/__root.s"))));
clean(root);
};

View File

@@ -0,0 +1,5 @@
package routing;
// Canonical test-only helper: no @test declaration in this file. Both
// same-package test files below share it through the single white-box build.
fn privatevalue() int = { return value() + 1; };

View File

@@ -0,0 +1,5 @@
package routing;
@test fn private_helper_first() void = {
assert(privatevalue() == 8);
};

View File

@@ -0,0 +1,7 @@
package routing_test;
import routing;
@test fn external_package() void = {
assert(routing.value() == 7);
};

View File

@@ -0,0 +1,3 @@
package routing;
export fn value() int = { return 7; };

View File

@@ -0,0 +1,6 @@
package routing;
@test fn same_package() void = {
assert(value() == 7);
assert(privatevalue() == 8);
};

View File

@@ -0,0 +1,45 @@
# Native package-runtime fixtures
These fixtures exercise the compiled package test binary, rather than a
subprocess-per-assertion harness. Build the bootstrap tools once with `make all`,
then run the focused cases from the repository root:
```sh
out/bin/ww test test/package/runtime/success_test.ww
out/bin/ww test -c -o /tmp/ww-runtime-test test/package/runtime/success_test.ww
/tmp/ww-runtime-test 'alpha*' 'delta*'
/tmp/ww-runtime-test -list
/tmp/ww-runtime-test -list 'gamma*'
/tmp/ww-runtime-test -timeout-ms=50 'alpha*'
out/bin/ww test test/package/runtime/fail_test.ww
out/bin/ww test test/package/runtime/multiple_fail_test.ww
out/bin/ww test test/package/runtime/expected_abort_return_test.ww
out/bin/ww test test/package/runtime/premature_exit_test.ww
out/bin/ww test test/package/runtime/signal_test.ww
out/bin/ww test -c -o /tmp/ww-runtime-timeout test/package/runtime/timeout_test.ww
/tmp/ww-runtime-timeout -timeout-ms=50
out/bin/ww test -c -o /tmp/ww-runtime-descendant test/package/runtime/lingering_descendant_test.ww
/tmp/ww-runtime-descendant -timeout-ms=250
out/bin/ww test -c -o /tmp/ww-runtime-escaped test/package/runtime/escaped_descendant_test.ww
/tmp/ww-runtime-escaped -timeout-ms=250
```
The success fixture reports two ordinary passes, one expected-abort pass, and
one skip with its reason. The preserved test binary accepts repeated glob
arguments directly. List mode prints selected names without starting tests.
Each test has a 30-second default timeout; `-timeout-ms=N` selects a positive
per-test timeout up to one hour for a direct test-binary invocation.
The current runtime recognizes `expectabort(); os.exit(nonzero)` as an expected
abort because WW's abort primitive itself terminates with a normal exit status;
the ABI cannot distinguish those two paths without a future abort hook.
The assertion, multiple-failure, unmet-expected-abort, premature-exit, and
signal fixtures fail respectively with a normal exit, two failures whose
process status is still clamped to 1, an expected abort that never happens, an
incomplete completion record, and signal 15; none may be mistaken for a pass.
The timeout fixture fails deterministically as `FAIL(timeout)`. The lingering
descendant fixture passes without waiting on the inherited control-pipe writer:
the descendant blocks SIGTERM, so the runner exercises its grace period and
SIGKILL escalation before draining the record.
The escaped-descendant fixture moves its inherited writer into another process
group for one second. The framed nonblocking protocol returns immediately after
the test leader and owned group complete; it never waits for pipe EOF.

View File

@@ -0,0 +1,26 @@
package runtime_escaped_descendant_test;
import os;
import time;
@test fn escaped_writer_does_not_hold_runner() void = {
let fds: [2]i32;
assert(os.pipe(&fds) == 0);
let pid: i32 = os.fork();
assert(pid >= 0);
if (pid == 0) {
os.close(fds[0]);
if (os.setpgid(0, 0) != 0) { os.exit(120); };
let ready: u8 = 1u8;
if (os.write(fds[1], &ready, 1u64) != 1i64) { os.exit(121); };
os.close(fds[1]);
time.sleep((time.second: i64): time.duration,
time.clock.monotonic);
os.exit(0);
};
os.close(fds[1]);
let ready: u8 = 0u8;
assert(os.read(fds[0], &ready, 1u64) == 1i64);
os.close(fds[0]);
assert(ready == 1u8);
};

View File

@@ -0,0 +1,7 @@
package runtime_expected_abort_return_test;
import test;
@test fn expected_abort_must_happen() void = {
test.expectabort();
};

View File

@@ -0,0 +1,5 @@
package runtime_fail_test;
@test fn assertion_failure() void = {
assert(false, "synthetic assertion failure");
};

View File

@@ -0,0 +1,26 @@
package runtime_lingering_descendant_test;
import os;
@test fn returning_test_clears_descendant() void = {
let fds: [2]i32;
assert(os.pipe(&fds) == 0);
let pid: i32 = os.fork();
assert(pid >= 0);
if (pid == 0) {
os.close(fds[0]);
let mask: u64 = 1u64 << ((os.SIGTERM - 1): u64);
if (os.sigprocmask(os.SIG_BLOCK, &mask, nil: *u64) != 0) {
os.exit(120);
};
let ready: u8 = 1u8;
if (os.write(fds[1], &ready, 1u64) != 1i64) { os.exit(121); };
os.close(fds[1]);
for (true) { };
};
os.close(fds[1]);
let ready: u8 = 0u8;
assert(os.read(fds[0], &ready, 1u64) == 1i64);
os.close(fds[0]);
assert(ready == 1u8);
};

View File

@@ -0,0 +1,9 @@
package runtime_multiple_fail_test;
@test fn first_failure() void = {
assert(false);
};
@test fn second_failure() void = {
assert(false);
};

View File

@@ -0,0 +1,7 @@
package runtime_premature_exit_test;
import os;
@test fn clean_exit_without_completion() void = {
os.exit(0);
};

View File

@@ -0,0 +1,7 @@
package runtime_signal_test;
import os;
@test fn signal_is_not_exit() void = {
os.kill(os.getpid(), os.SIGTERM);
};

View File

@@ -0,0 +1,20 @@
package runtime_success_test;
import test;
@test fn alpha_pass() void = {
assert(test.current() != "");
};
@test fn beta_skip() void = {
test.skip("synthetic unavailable feature");
};
@test fn gamma_expected_abort() void = {
test.expectabort();
abort();
};
@test fn delta_pass() void = {
assert(6 * 7 == 42);
};

View File

@@ -0,0 +1,5 @@
package runtime_timeout_test;
@test fn hang_times_out() void = {
for (true) { };
};