lib/io tests: hand-main plumbing -> assert (@test conversion B5)

This commit is contained in:
2026-06-10 18:52:53 +09:00
parent 612e6d149c
commit e8096e68e1
5 changed files with 492 additions and 531 deletions

View File

@@ -14,20 +14,6 @@ import encoding.utf8;
import io; import io;
import memio; import memio;
// Direct exit(2) binding rather than `use os;` — os exports
// read/write/close, which collide with io.read/write/close under
// the driver's flat-scope concat.
@symbol("rt_syscall") fn syscall1ww(num: i64, a: i64) i64;
fn doexit(code: i32) void = {
syscall1ww(60i64, code: i64);
};
// signalled — bumped by main before each test so a failing exit code
// pinpoints the offending case.
let signalled: i32 = 0;
fn fail() void = { doexit(signalled + 10); };
// putstr — copy the bytes of `s` into `into` starting at `off`, // putstr — copy the bytes of `s` into `into` starting at `off`,
// returning the new offset. // returning the new offset.
fn putstr(s: str, into: []u8, off: i32) i32 = { fn putstr(s: str, into: []u8, off: i32) i32 = {
@@ -83,11 +69,11 @@ fn errsource() io.stream = {
let r: (u8 | io.eof | io.error) = bufio.scanbyte(&sc); let r: (u8 | io.eof | io.error) = bufio.scanbyte(&sc);
match (r) { match (r) {
case let b: u8 => { case let b: u8 => {
if (weof[i] != 0) { fail(); }; assert(!(weof[i] != 0));
if (b != want[i]) { fail(); }; assert(!(b != want[i]));
}; };
case io.eof => { if (weof[i] == 0) { fail(); }; }; case io.eof => { assert(!(weof[i] == 0)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
i += 1; i += 1;
}; };
@@ -122,14 +108,14 @@ fn errsource() io.stream = {
let r: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc); let r: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);
match (r) { match (r) {
case let v: str => { case let v: str => {
if (weof[i] != 0) { fail(); }; assert(!(weof[i] != 0));
if (wovr[i] != 0) { fail(); }; assert(!(wovr[i] != 0));
if (v.len != wl[i]) { fail(); }; assert(!(v.len != wl[i]));
if (v.len > 0 && v[0] != wf[i]) { fail(); }; assert(!(v.len > 0 && v[0] != wf[i]));
}; };
case io.eof => { if (weof[i] == 0) { fail(); }; }; case io.eof => { assert(!(weof[i] == 0)); };
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => { if (wovr[i] == 0) { fail(); }; }; case bufio.overflow => { assert(!(wovr[i] == 0)); };
}; };
i += 1; i += 1;
}; };
@@ -152,9 +138,9 @@ fn errsource() io.stream = {
let r: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc); let r: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);
match (r) { match (r) {
case let v: str => fail(); case let v: str => abort();
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => { }; case bufio.overflow => { };
}; };
@@ -188,13 +174,13 @@ fn errsource() io.stream = {
let r: ([]u8 | io.eof | io.error | bufio.overflow) = bufio.scanbytes(&sc, 44u8); // ',' let r: ([]u8 | io.eof | io.error | bufio.overflow) = bufio.scanbytes(&sc, 44u8); // ','
match (r) { match (r) {
case let v: []u8 => { case let v: []u8 => {
if (weof[i] != 0) { fail(); }; assert(!(weof[i] != 0));
if (v.len != wl[i]) { fail(); }; assert(!(v.len != wl[i]));
if (v.len > 0 && v[0] != wf[i]) { fail(); }; assert(!(v.len > 0 && v[0] != wf[i]));
}; };
case io.eof => { if (weof[i] == 0) { fail(); }; }; case io.eof => { assert(!(weof[i] == 0)); };
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
i += 1; i += 1;
}; };
@@ -213,25 +199,25 @@ fn errsource() io.stream = {
let r1: (u8 | io.eof | io.error) = bufio.scanbyte(&sc); let r1: (u8 | io.eof | io.error) = bufio.scanbyte(&sc);
match (r1) { match (r1) {
case let b: u8 => fail(); case let b: u8 => abort();
case io.eof => { }; case io.eof => { };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let r2: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc); let r2: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);
match (r2) { match (r2) {
case let v: str => fail(); case let v: str => abort();
case io.eof => { }; case io.eof => { };
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
let r3: ([]u8 | io.eof | io.error | bufio.overflow) = bufio.scanbytes(&sc, 10u8); let r3: ([]u8 | io.eof | io.error | bufio.overflow) = bufio.scanbytes(&sc, 10u8);
match (r3) { match (r3) {
case let v: []u8 => fail(); case let v: []u8 => abort();
case io.eof => { }; case io.eof => { };
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
bufio.finish(&sc); bufio.finish(&sc);
@@ -246,25 +232,25 @@ fn errsource() io.stream = {
let r1: (u8 | io.eof | io.error) = bufio.scanbyte(&sc); let r1: (u8 | io.eof | io.error) = bufio.scanbyte(&sc);
match (r1) { match (r1) {
case let b: u8 => fail(); case let b: u8 => abort();
case io.eof => fail(); case io.eof => abort();
case let e: io.error => { }; case let e: io.error => { };
}; };
let r2: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc); let r2: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);
match (r2) { match (r2) {
case let v: str => fail(); case let v: str => abort();
case io.eof => fail(); case io.eof => abort();
case let e: io.error => { }; case let e: io.error => { };
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
let r3: ([]u8 | io.eof | io.error | bufio.overflow) = bufio.scanbytes(&sc, 32u8); let r3: ([]u8 | io.eof | io.error | bufio.overflow) = bufio.scanbytes(&sc, 32u8);
match (r3) { match (r3) {
case let v: []u8 => fail(); case let v: []u8 => abort();
case io.eof => fail(); case io.eof => abort();
case let e: io.error => { }; case let e: io.error => { };
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
bufio.finish(&sc); bufio.finish(&sc);
@@ -283,20 +269,20 @@ fn errsource() io.stream = {
let r1: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc1); let r1: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc1);
match (r1) { match (r1) {
case let v: str => { if (v.len != 0) { fail(); }; }; case let v: str => { assert(!(v.len != 0)); };
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
let r2: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc1); let r2: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc1);
match (r2) { match (r2) {
case let v: str => { case let v: str => {
if (v.len != 3) { fail(); }; assert(!(v.len != 3));
if (v[0] != 102u8) { fail(); }; // 'f' assert(!(v[0] != 102u8)); // 'f'
}; };
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
bufio.finish(&sc1); bufio.finish(&sc1);
@@ -310,17 +296,17 @@ fn errsource() io.stream = {
let t1: ([]u8 | io.eof | io.error | bufio.overflow) = bufio.scanbytes(&sc2, 44u8); let t1: ([]u8 | io.eof | io.error | bufio.overflow) = bufio.scanbytes(&sc2, 44u8);
match (t1) { match (t1) {
case let v: []u8 => fail(); case let v: []u8 => abort();
case io.eof => { }; case io.eof => { };
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
let t2: ([]u8 | io.eof | io.error | bufio.overflow) = bufio.scanbytes(&sc2, 44u8); let t2: ([]u8 | io.eof | io.error | bufio.overflow) = bufio.scanbytes(&sc2, 44u8);
match (t2) { match (t2) {
case let v: []u8 => fail(); case let v: []u8 => abort();
case io.eof => { }; case io.eof => { };
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
bufio.finish(&sc2); bufio.finish(&sc2);
}; };
@@ -349,13 +335,13 @@ fn errsource() io.stream = {
let r: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc); let r: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);
match (r) { match (r) {
case let v: str => { case let v: str => {
if (weof[i] != 0) { fail(); }; assert(!(weof[i] != 0));
if (v.len != wl[i]) { fail(); }; assert(!(v.len != wl[i]));
if (v.len > 0 && v[0] != wf[i]) { fail(); }; assert(!(v.len > 0 && v[0] != wf[i]));
}; };
case io.eof => { if (weof[i] == 0) { fail(); }; }; case io.eof => { assert(!(weof[i] == 0)); };
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
i += 1; i += 1;
}; };
@@ -380,19 +366,19 @@ fn errsource() io.stream = {
let p: io.stream = &b.vt; let p: io.stream = &b.vt;
let r: (size | io.error) = io.write(p, buf[0:5]); let r: (size | io.error) = io.write(p, buf[0:5]);
match (r) { match (r) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (mem.pos != 0) { fail(); }; assert(!(mem.pos != 0));
let fr: (void | io.error) = bufio.flush(&b); let fr: (void | io.error) = bufio.flush(&b);
match (fr) { match (fr) {
case void => { }; case void => { };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (mem.pos != 5) { fail(); }; assert(!(mem.pos != 5));
if (raw[0] != 104u8) { fail(); }; assert(!(raw[0] != 104u8));
if (raw[4] != 111u8) { fail(); }; assert(!(raw[4] != 111u8));
}; };
// ---- write larger than wbuf → auto-flush ----------------------------- // ---- write larger than wbuf → auto-flush -----------------------------
@@ -412,20 +398,20 @@ fn errsource() io.stream = {
let p: io.stream = &b.vt; let p: io.stream = &b.vt;
let r: (size | io.error) = io.write(p, buf[0:10]); let r: (size | io.error) = io.write(p, buf[0:10]);
match (r) { match (r) {
case let n: size => { if (n: i32 != 10) { fail(); }; }; case let n: size => { assert(!(n: i32 != 10)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
// Two full flushes happened (8B); 2B still pending. // Two full flushes happened (8B); 2B still pending.
if (mem.pos != 8) { fail(); }; assert(!(mem.pos != 8));
let fr: (void | io.error) = bufio.flush(&b); let fr: (void | io.error) = bufio.flush(&b);
match (fr) { match (fr) {
case void => { }; case void => { };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (mem.pos != 10) { fail(); }; assert(!(mem.pos != 10));
if (raw[0] != 97u8) { fail(); }; // 'a' assert(!(raw[0] != 97u8)); // 'a'
if (raw[9] != 106u8) { fail(); }; // 'j' assert(!(raw[9] != 106u8)); // 'j'
}; };
// ---- default flush byte-set: '\n' in payload triggers flush --------- // ---- default flush byte-set: '\n' in payload triggers flush ---------
@@ -446,22 +432,22 @@ fn errsource() io.stream = {
let zh: i32 = putstr("hello", h[0:5], 0); let zh: i32 = putstr("hello", h[0:5], 0);
let r1: (size | io.error) = io.write(p, h[0:5]); let r1: (size | io.error) = io.write(p, h[0:5]);
match (r1) { match (r1) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (mem.pos != 0) { fail(); }; assert(!(mem.pos != 0));
// Second write: '\n' present, triggers flush of everything (6B). // Second write: '\n' present, triggers flush of everything (6B).
let nl: [1]u8; let nl: [1]u8;
nl[0] = 10u8; nl[0] = 10u8;
let r2: (size | io.error) = io.write(p, nl[0:1]); let r2: (size | io.error) = io.write(p, nl[0:1]);
match (r2) { match (r2) {
case let n: size => { if (n: i32 != 1) { fail(); }; }; case let n: size => { assert(!(n: i32 != 1)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (mem.pos != 6) { fail(); }; assert(!(mem.pos != 6));
if (raw[0] != 104u8) { fail(); }; assert(!(raw[0] != 104u8));
if (raw[5] != 10u8) { fail(); }; assert(!(raw[5] != 10u8));
}; };
// ---- explicit-flush-per-write: caller drives the drain --------------- // ---- explicit-flush-per-write: caller drives the drain ---------------
@@ -482,29 +468,29 @@ fn errsource() io.stream = {
h[0] = 65u8; h[1] = 66u8; // "AB" h[0] = 65u8; h[1] = 66u8; // "AB"
let r1: (size | io.error) = io.write(p, h[0:2]); let r1: (size | io.error) = io.write(p, h[0:2]);
match (r1) { match (r1) {
case let n: size => { if (n: i32 != 2) { fail(); }; }; case let n: size => { assert(!(n: i32 != 2)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let f1: (void | io.error) = bufio.flush(&b); let f1: (void | io.error) = bufio.flush(&b);
match (f1) { match (f1) {
case void => { }; case void => { };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (mem.pos != 2) { fail(); }; assert(!(mem.pos != 2));
if (raw[0] != 65u8) { fail(); }; assert(!(raw[0] != 65u8));
let r2: (size | io.error) = io.write(p, h[0:1]); let r2: (size | io.error) = io.write(p, h[0:1]);
match (r2) { match (r2) {
case let n: size => { if (n: i32 != 1) { fail(); }; }; case let n: size => { assert(!(n: i32 != 1)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let f2: (void | io.error) = bufio.flush(&b); let f2: (void | io.error) = bufio.flush(&b);
match (f2) { match (f2) {
case void => { }; case void => { };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (mem.pos != 3) { fail(); }; assert(!(mem.pos != 3));
if (raw[2] != 65u8) { fail(); }; assert(!(raw[2] != 65u8));
}; };
// ---- isbuffered: stream → true, plain memio → false ----------------- // ---- isbuffered: stream → true, plain memio → false -----------------
@@ -518,8 +504,8 @@ fn errsource() io.stream = {
let wb: [4]u8; let wb: [4]u8;
let b: bufio.stream = bufio.init(m, rb[0:4], wb[0:4]); let b: bufio.stream = bufio.init(m, rb[0:4], wb[0:4]);
if (!bufio.isbuffered(&b.vt)) { fail(); }; assert(!(!bufio.isbuffered(&b.vt)));
if (bufio.isbuffered(m)) { fail(); }; assert(!(bufio.isbuffered(m)));
}; };
// ---- bread + unread: pushed-back bytes come out first ---------------- // ---- bread + unread: pushed-back bytes come out first ----------------
@@ -541,12 +527,12 @@ fn errsource() io.stream = {
let out: [4]u8; let out: [4]u8;
let r1: (size | io.eof | io.error) = io.read(p, out[0:3]); let r1: (size | io.eof | io.error) = io.read(p, out[0:3]);
match (r1) { match (r1) {
case let z: size => { if (z: i32 != 3) { fail(); }; }; case let z: size => { assert(!(z: i32 != 3)); };
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (out[0] != 65u8) { fail(); }; // 'A' assert(!(out[0] != 65u8)); // 'A'
if (out[2] != 67u8) { fail(); }; // 'C' assert(!(out[2] != 67u8)); // 'C'
// Push back 2 bytes; next read returns them first. // Push back 2 bytes; next read returns them first.
let push: [2]u8; let push: [2]u8;
@@ -555,22 +541,22 @@ fn errsource() io.stream = {
let r2: (size | io.eof | io.error) = io.read(p, out[0:2]); let r2: (size | io.eof | io.error) = io.read(p, out[0:2]);
match (r2) { match (r2) {
case let z: size => { if (z: i32 != 2) { fail(); }; }; case let z: size => { assert(!(z: i32 != 2)); };
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (out[0] != 88u8) { fail(); }; // 'X' assert(!(out[0] != 88u8)); // 'X'
if (out[1] != 89u8) { fail(); }; // 'Y' assert(!(out[1] != 89u8)); // 'Y'
// Subsequent read returns the original tail. // Subsequent read returns the original tail.
let r3: (size | io.eof | io.error) = io.read(p, out[0:4]); let r3: (size | io.eof | io.error) = io.read(p, out[0:4]);
match (r3) { match (r3) {
case let z: size => { if (z: i32 != 4) { fail(); }; }; case let z: size => { assert(!(z: i32 != 4)); };
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (out[0] != 68u8) { fail(); }; // 'D' assert(!(out[0] != 68u8)); // 'D'
if (out[3] != 71u8) { fail(); }; // 'G' assert(!(out[3] != 71u8)); // 'G'
}; };
// ---- scanner over a stream-wrapped src: pre-read unread + scanline -- // ---- scanner over a stream-wrapped src: pre-read unread + scanline --
@@ -597,13 +583,13 @@ fn errsource() io.stream = {
let lr: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc); let lr: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);
match (lr) { match (lr) {
case let v: str => { case let v: str => {
if (v.len != 8) { fail(); }; // "XYZhello" assert(!(v.len != 8)); // "XYZhello"
if (v[0] != 88u8) { fail(); }; // 'X' assert(!(v[0] != 88u8)); // 'X'
if (v[7] != 111u8) { fail(); }; // 'o' assert(!(v[7] != 111u8)); // 'o'
}; };
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
bufio.finish(&sc); bufio.finish(&sc);
}; };
@@ -622,9 +608,9 @@ fn errsource() io.stream = {
let r: (void | io.error) = bufio.flush(&b); let r: (void | io.error) = bufio.flush(&b);
match (r) { match (r) {
case void => { }; case void => { };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (mem.pos != 0) { fail(); }; assert(!(mem.pos != 0));
}; };
// ---- bclose drains pending wbuf then forwards close to src ---------- // ---- bclose drains pending wbuf then forwards close to src ----------
@@ -645,19 +631,19 @@ fn errsource() io.stream = {
h[0] = 80u8; h[1] = 81u8; // "PQ" h[0] = 80u8; h[1] = 81u8; // "PQ"
let r: (size | io.error) = io.write(p, h[0:2]); let r: (size | io.error) = io.write(p, h[0:2]);
match (r) { match (r) {
case let n: size => { if (n: i32 != 2) { fail(); }; }; case let n: size => { assert(!(n: i32 != 2)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (mem.pos != 0) { fail(); }; // still buffered assert(!(mem.pos != 0)); // still buffered
let cr: (void | io.error) = io.close(p); let cr: (void | io.error) = io.close(p);
match (cr) { match (cr) {
case void => { }; case void => { };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (mem.pos != 2) { fail(); }; assert(!(mem.pos != 2));
if (raw[0] != 80u8) { fail(); }; assert(!(raw[0] != 80u8));
if (raw[1] != 81u8) { fail(); }; assert(!(raw[1] != 81u8));
}; };
// ---- setflush with a custom non-empty byte-set ----------------------- // ---- setflush with a custom non-empty byte-set -----------------------
@@ -679,13 +665,13 @@ fn errsource() io.stream = {
let z: i32 = putstr("ab cd", buf[0:5], 0); let z: i32 = putstr("ab cd", buf[0:5], 0);
let r: (size | io.error) = io.write(p, buf[0:5]); let r: (size | io.error) = io.write(p, buf[0:5]);
match (r) { match (r) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
// Space at index 2 triggers post-copy flush of all 5 bytes. // Space at index 2 triggers post-copy flush of all 5 bytes.
if (mem.pos != 5) { fail(); }; assert(!(mem.pos != 5));
if (raw[2] != 32u8) { fail(); }; assert(!(raw[2] != 32u8));
if (raw[4] != 100u8) { fail(); }; // 'd' assert(!(raw[4] != 100u8)); // 'd'
}; };
// ---- scanrune: ASCII + 2/3/4-byte UTF-8 + idempotent EOF -------------- // ---- scanrune: ASCII + 2/3/4-byte UTF-8 + idempotent EOF --------------
@@ -720,12 +706,12 @@ fn errsource() io.stream = {
let r: (rune | io.eof | io.error | utf8.invalid) = bufio.scanrune(&sc); let r: (rune | io.eof | io.error | utf8.invalid) = bufio.scanrune(&sc);
match (r) { match (r) {
case let rn: rune => { case let rn: rune => {
if (weof[i] != 0) { fail(); }; assert(!(weof[i] != 0));
if (rn: u32 != want[i]) { fail(); }; assert(!(rn: u32 != want[i]));
}; };
case io.eof => { if (weof[i] == 0) { fail(); }; }; case io.eof => { assert(!(weof[i] == 0)); };
case let e: io.error => fail(); case let e: io.error => abort();
case utf8.invalid => fail(); case utf8.invalid => abort();
}; };
i += 1; i += 1;
}; };
@@ -745,9 +731,9 @@ fn errsource() io.stream = {
let sc1: bufio.scanner = bufio.newscannerbuf(m1, b1[0:8]); let sc1: bufio.scanner = bufio.newscannerbuf(m1, b1[0:8]);
let r1: (rune | io.eof | io.error | utf8.invalid) = bufio.scanrune(&sc1); let r1: (rune | io.eof | io.error | utf8.invalid) = bufio.scanrune(&sc1);
match (r1) { match (r1) {
case let rn: rune => fail(); case let rn: rune => abort();
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
case utf8.invalid => { }; case utf8.invalid => { };
}; };
bufio.finish(&sc1); bufio.finish(&sc1);
@@ -762,9 +748,9 @@ fn errsource() io.stream = {
let sc2: bufio.scanner = bufio.newscannerbuf(m2, b2[0:8]); let sc2: bufio.scanner = bufio.newscannerbuf(m2, b2[0:8]);
let r2: (rune | io.eof | io.error | utf8.invalid) = bufio.scanrune(&sc2); let r2: (rune | io.eof | io.error | utf8.invalid) = bufio.scanrune(&sc2);
match (r2) { match (r2) {
case let rn: rune => fail(); case let rn: rune => abort();
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
case utf8.invalid => { }; case utf8.invalid => { };
}; };
bufio.finish(&sc2); bufio.finish(&sc2);
@@ -779,9 +765,9 @@ fn errsource() io.stream = {
let sc3: bufio.scanner = bufio.newscannerbuf(m3, b3[0:8]); let sc3: bufio.scanner = bufio.newscannerbuf(m3, b3[0:8]);
let r3: (rune | io.eof | io.error | utf8.invalid) = bufio.scanrune(&sc3); let r3: (rune | io.eof | io.error | utf8.invalid) = bufio.scanrune(&sc3);
match (r3) { match (r3) {
case let rn: rune => fail(); case let rn: rune => abort();
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
case utf8.invalid => { }; case utf8.invalid => { };
}; };
bufio.finish(&sc3); bufio.finish(&sc3);
@@ -811,13 +797,13 @@ fn errsource() io.stream = {
let r: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc); let r: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);
match (r) { match (r) {
case let v: str => { case let v: str => {
if (weof[i] != 0) { fail(); }; assert(!(weof[i] != 0));
if (v.len != wl[i]) { fail(); }; assert(!(v.len != wl[i]));
if (v.len > 0 && v[0] != wf[i]) { fail(); }; assert(!(v.len > 0 && v[0] != wf[i]));
}; };
case io.eof => { if (weof[i] == 0) { fail(); }; }; case io.eof => { assert(!(weof[i] == 0)); };
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => fail(); case bufio.overflow => abort();
}; };
i += 1; i += 1;
}; };
@@ -842,12 +828,12 @@ fn errsource() io.stream = {
let r: (rune | io.eof | io.error | utf8.invalid) = bufio.scanrune(&sc2); let r: (rune | io.eof | io.error | utf8.invalid) = bufio.scanrune(&sc2);
match (r) { match (r) {
case let rn: rune => { case let rn: rune => {
if (weof2[i] != 0) { fail(); }; assert(!(weof2[i] != 0));
if (rn: u32 != want[i]) { fail(); }; assert(!(rn: u32 != want[i]));
}; };
case io.eof => { if (weof2[i] == 0) { fail(); }; }; case io.eof => { assert(!(weof2[i] == 0)); };
case let e: io.error => fail(); case let e: io.error => abort();
case utf8.invalid => fail(); case utf8.invalid => abort();
}; };
i += 1; i += 1;
}; };
@@ -866,36 +852,36 @@ fn errsource() io.stream = {
let r: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc); let r: (str | io.eof | io.error | bufio.overflow) = bufio.scanline(&sc);
match (r) { match (r) {
case let v: str => fail(); case let v: str => abort();
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
case bufio.overflow => { }; case bufio.overflow => { };
}; };
bufio.finish(&sc); bufio.finish(&sc);
}; };
export fn main() i32 = { export fn main() i32 = {
signalled = 1; scanbytecases(); scanbytecases();
signalled = 2; scanlinecases(); scanlinecases();
signalled = 3; scanlineoverflow(); scanlineoverflow();
signalled = 4; scanbytescases(); scanbytescases();
signalled = 5; emptystream(); emptystream();
signalled = 6; errorsource(); errorsource();
signalled = 7; boundarycases(); boundarycases();
signalled = 8; multifill(); multifill();
signalled = 9; streamsmallwrite(); streamsmallwrite();
signalled = 10; streamautoflush(); streamautoflush();
signalled = 11; streamlineflush(); streamlineflush();
signalled = 12; streamflushonwrite(); streamflushonwrite();
signalled = 13; streamisbuffered(); streamisbuffered();
signalled = 14; streamunread(); streamunread();
signalled = 15; streamscannerunread(); streamscannerunread();
signalled = 16; streamflushempty(); streamflushempty();
signalled = 17; streamcloseflushes(); streamcloseflushes();
signalled = 18; streamsetflushcustom(); streamsetflushcustom();
signalled = 19; scanrunecases(); scanrunecases();
signalled = 20; scanruneinvalid(); scanruneinvalid();
signalled = 21; newscannergrow(); newscannergrow();
signalled = 22; newscanneroverflow(); newscanneroverflow();
return 0; return 0;
}; };

View File

@@ -11,11 +11,6 @@ package errors_test;
import errors; import errors;
import os; import os;
// signalled — bumped by main before each test so a failing exit code
// pinpoints the offending case.
let signalled: i32 = 0;
fn fail() void = { os.exit(signalled + 10); };
fn streq(a: str, b: str) bool = { fn streq(a: str, b: str) bool = {
if (a.len != b.len) { return false; }; if (a.len != b.len) { return false; };
let i: i32 = 0; let i: i32 = 0;
@@ -85,7 +80,7 @@ fn errtag(e: errors.error) int = {
// regardless — it is how errno is actually used (cf // regardless — it is how errno is actually used (cf
// lib/io/stream.ww:53, and Hare's errors/rt.ha callers). // lib/io/stream.ww:53, and Hare's errors/rt.ha callers).
let er: errors.error = errors.errno(ins[i]); let er: errors.error = errors.errno(ins[i]);
if (errtag(er) != exp[i]) { fail(); }; assert(!(errtag(er) != exp[i]));
i += 1; i += 1;
}; };
}; };
@@ -94,25 +89,25 @@ fn errtag(e: errors.error) int = {
@test fn opaquetail() void = { @test fn opaquetail() void = {
// EIO (5) is outside the mapped set, so it wraps opaque_. // EIO (5) is outside the mapped set, so it wraps opaque_.
let e: errors.error = errors.errno(5); let e: errors.error = errors.errno(5);
if (errtag(e) != 99) { fail(); }; assert(!(errtag(e) != 99));
match (e) { match (e) {
case let o: errors.opaque_ => case let o: errors.opaque_ =>
if (!streq((*o.strerror)(&o.data), "Unknown error")) { fail(); }; assert(!(!streq((*o.strerror)(&o.data), "Unknown error")));
case => case =>
fail(); abort();
}; };
}; };
// ---- os.strerror mapped path -------------------------------------- // ---- os.strerror mapped path --------------------------------------
@test fn strerrortext() void = { @test fn strerrortext() void = {
if (!streq(os.strerror(os.ENOENT), "No such file or directory")) { fail(); }; assert(!(!streq(os.strerror(os.ENOENT), "No such file or directory")));
if (!streq(os.strerror(os.EINVAL), "Invalid argument")) { fail(); }; assert(!(!streq(os.strerror(os.EINVAL), "Invalid argument")));
if (!streq(os.strerror(5), "Unknown error")) { fail(); }; assert(!(!streq(os.strerror(5), "Unknown error")));
}; };
export fn main() i32 = { export fn main() i32 = {
signalled = 1; mapping(); mapping();
signalled = 2; opaquetail(); opaquetail();
signalled = 3; strerrortext(); strerrortext();
return 0; return 0;
}; };

View File

@@ -14,12 +14,6 @@ import io;
import memio; import memio;
import os; import os;
// signalled — bumped before each scenario so a failing exit code
// pinpoints the offending case.
let signalled: i32 = 0;
fn fail() void = { os.exit(signalled + 10); };
fn streq(a: str, b: str) bool = { fn streq(a: str, b: str) bool = {
if (a.len != b.len) { return false; }; if (a.len != b.len) { return false; };
let i: i32 = 0; let i: i32 = 0;
@@ -56,13 +50,13 @@ fn errsource() io.stream = {
let r: (size | io.error) = fmt.fprint(s, "hello"); let r: (size | io.error) = fmt.fprint(s, "hello");
match (r) { match (r) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "hello")) { fail(); }; assert(!(!streq(memio.string(&mem), "hello")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// ---- fprint: int + str mix, space-separated ---------------------------- // ---- fprint: int + str mix, space-separated ----------------------------
@@ -73,13 +67,13 @@ fn errsource() io.stream = {
let r: (size | io.error) = fmt.fprint(s, 42i64, "x"); let r: (size | io.error) = fmt.fprint(s, 42i64, "x");
match (r) { match (r) {
case let n: size => { if (n: i32 != 4) { fail(); }; }; // "42 x" case let n: size => { assert(!(n: i32 != 4)); }; // "42 x"
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "42 x")) { fail(); }; assert(!(!streq(memio.string(&mem), "42 x")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// ---- fprint: bool + rune renders as "true A" -------------------------- // ---- fprint: bool + rune renders as "true A" --------------------------
@@ -90,13 +84,13 @@ fn errsource() io.stream = {
let r: (size | io.error) = fmt.fprint(s, true, 'A': rune); let r: (size | io.error) = fmt.fprint(s, true, 'A': rune);
match (r) { match (r) {
case let n: size => { if (n: i32 != 6) { fail(); }; }; // "true A" case let n: size => { assert(!(n: i32 != 6)); }; // "true A"
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "true A")) { fail(); }; assert(!(!streq(memio.string(&mem), "true A")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// ---- fprint: zero args returns 0, no bytes written -------------------- // ---- fprint: zero args returns 0, no bytes written --------------------
@@ -107,13 +101,13 @@ fn errsource() io.stream = {
let r: (size | io.error) = fmt.fprint(s); let r: (size | io.error) = fmt.fprint(s);
match (r) { match (r) {
case let n: size => { if (n: i32 != 0) { fail(); }; }; case let n: size => { assert(!(n: i32 != 0)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (memio.string(&mem).len != 0) { fail(); }; assert(!(memio.string(&mem).len != 0));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// ---- fprintln: multi-arg, trailing '\n' -------------------------------- // ---- fprintln: multi-arg, trailing '\n' --------------------------------
@@ -124,13 +118,13 @@ fn errsource() io.stream = {
let r: (size | io.error) = fmt.fprintln(s, "a", 1i64, false); let r: (size | io.error) = fmt.fprintln(s, "a", 1i64, false);
match (r) { match (r) {
case let n: size => { if (n: i32 != 10) { fail(); }; }; // "a 1 false\n" case let n: size => { assert(!(n: i32 != 10)); }; // "a 1 false\n"
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "a 1 false\n")) { fail(); }; assert(!(!streq(memio.string(&mem), "a 1 false\n")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// ---- fprintln: zero args writes just the newline ---------------------- // ---- fprintln: zero args writes just the newline ----------------------
@@ -141,13 +135,13 @@ fn errsource() io.stream = {
let r: (size | io.error) = fmt.fprintln(s); let r: (size | io.error) = fmt.fprintln(s);
match (r) { match (r) {
case let n: size => { if (n: i32 != 1) { fail(); }; }; case let n: size => { assert(!(n: i32 != 1)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "\n")) { fail(); }; assert(!(!streq(memio.string(&mem), "\n")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// ---- fprint over a fixed stream: short writes return partial count ---- // ---- fprint over a fixed stream: short writes return partial count ----
@@ -163,13 +157,13 @@ fn errsource() io.stream = {
let r: (size | io.error) = fmt.fprint(s, "hello"); let r: (size | io.error) = fmt.fprint(s, "hello");
match (r) { match (r) {
case let n: size => { if (n: i32 != 3) { fail(); }; }; case let n: size => { assert(!(n: i32 != 3)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "hel")) { fail(); }; assert(!(!streq(memio.string(&mem), "hel")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// ---- fprint over a closed stream surfaces io.error ------------------- // ---- fprint over a closed stream surfaces io.error -------------------
@@ -183,7 +177,7 @@ fn errsource() io.stream = {
let r: (size | io.error) = fmt.fprint(s, "x"); let r: (size | io.error) = fmt.fprint(s, "x");
match (r) { match (r) {
case let n: size => fail(); case let n: size => abort();
case let eioe: io.error => {}; case let eioe: io.error => {};
}; };
}; };
@@ -198,12 +192,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "hello {} {}", "world", 42i64); let r: (size | io.error) = fmt.fprintf(s, "hello {} {}", "world", 42i64);
match (r) { match (r) {
case let n: size => { if (n: i32 != 14) { fail(); }; }; case let n: size => { assert(!(n: i32 != 14)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "hello world 42")) { fail(); }; assert(!(!streq(memio.string(&mem), "hello world 42")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_indexed() void = { @test fn fprintf_indexed() void = {
@@ -211,12 +205,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{1} {0} {1}", "hello", "world"); let r: (size | io.error) = fmt.fprintf(s, "{1} {0} {1}", "hello", "world");
match (r) { match (r) {
case let n: size => { if (n: i32 != 17) { fail(); }; }; case let n: size => { assert(!(n: i32 != 17)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "world hello world")) { fail(); }; assert(!(!streq(memio.string(&mem), "world hello world")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_literal_braces() void = { @test fn fprintf_literal_braces() void = {
@@ -224,12 +218,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{{ {} }}", 1i64); let r: (size | io.error) = fmt.fprintf(s, "{{ {} }}", 1i64);
match (r) { match (r) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "{ 1 }")) { fail(); }; assert(!(!streq(memio.string(&mem), "{ 1 }")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_width_right() void = { @test fn fprintf_width_right() void = {
@@ -237,12 +231,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:5}", 42i64); let r: (size | io.error) = fmt.fprintf(s, "{:5}", 42i64);
match (r) { match (r) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), " 42")) { fail(); }; assert(!(!streq(memio.string(&mem), " 42")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_width_left() void = { @test fn fprintf_width_left() void = {
@@ -250,12 +244,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:-5}", 42i64); let r: (size | io.error) = fmt.fprintf(s, "{:-5}", 42i64);
match (r) { match (r) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "42 ")) { fail(); }; assert(!(!streq(memio.string(&mem), "42 ")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_width_center() void = { @test fn fprintf_width_center() void = {
@@ -263,12 +257,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:=5}", "hi"); let r: (size | io.error) = fmt.fprintf(s, "{:=5}", "hi");
match (r) { match (r) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), " hi ")) { fail(); }; assert(!(!streq(memio.string(&mem), " hi ")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_pad_underscore() void = { @test fn fprintf_pad_underscore() void = {
@@ -276,12 +270,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:_05}", "hi"); let r: (size | io.error) = fmt.fprintf(s, "{:_05}", "hi");
match (r) { match (r) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "000hi")) { fail(); }; assert(!(!streq(memio.string(&mem), "000hi")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_base_hex() void = { @test fn fprintf_base_hex() void = {
@@ -289,12 +283,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:x} {:X}", 48879i64, 61453i64); let r: (size | io.error) = fmt.fprintf(s, "{:x} {:X}", 48879i64, 61453i64);
match (r) { match (r) {
case let n: size => { if (n: i32 != 9) { fail(); }; }; case let n: size => { assert(!(n: i32 != 9)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "beef F00D")) { fail(); }; assert(!(!streq(memio.string(&mem), "beef F00D")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_base_oct_bin() void = { @test fn fprintf_base_oct_bin() void = {
@@ -302,12 +296,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:o} {:b}", 493i64, 27i64); let r: (size | io.error) = fmt.fprintf(s, "{:o} {:b}", 493i64, 27i64);
match (r) { match (r) {
case let n: size => { if (n: i32 != 9) { fail(); }; }; // "755 11011" case let n: size => { assert(!(n: i32 != 9)); }; // "755 11011"
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "755 11011")) { fail(); }; assert(!(!streq(memio.string(&mem), "755 11011")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_prec_int() void = { @test fn fprintf_prec_int() void = {
@@ -315,12 +309,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:.5}", 42i64); let r: (size | io.error) = fmt.fprintf(s, "{:.5}", 42i64);
match (r) { match (r) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "00042")) { fail(); }; assert(!(!streq(memio.string(&mem), "00042")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_prec_str_trunc() void = { @test fn fprintf_prec_str_trunc() void = {
@@ -328,12 +322,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:.3}", "hello"); let r: (size | io.error) = fmt.fprintf(s, "{:.3}", "hello");
match (r) { match (r) {
case let n: size => { if (n: i32 != 3) { fail(); }; }; case let n: size => { assert(!(n: i32 != 3)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "hel")) { fail(); }; assert(!(!streq(memio.string(&mem), "hel")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_sign_neg() void = { @test fn fprintf_sign_neg() void = {
@@ -341,12 +335,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{} {:+} {: }", -7i64, 7i64, 7i64); let r: (size | io.error) = fmt.fprintf(s, "{} {:+} {: }", -7i64, 7i64, 7i64);
match (r) { match (r) {
case let n: size => { if (n: i32 != 8) { fail(); }; }; // "-7 +7 7" case let n: size => { assert(!(n: i32 != 8)); }; // "-7 +7 7"
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "-7 +7 7")) { fail(); }; assert(!(!streq(memio.string(&mem), "-7 +7 7")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintfln_basic() void = { @test fn fprintfln_basic() void = {
@@ -354,19 +348,19 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintfln(s, "x={}", 9i64); let r: (size | io.error) = fmt.fprintfln(s, "x={}", 9i64);
match (r) { match (r) {
case let n: size => { if (n: i32 != 4) { fail(); }; }; // "x=9\n" case let n: size => { assert(!(n: i32 != 4)); }; // "x=9\n"
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "x=9\n")) { fail(); }; assert(!(!streq(memio.string(&mem), "x=9\n")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_closed() void = { @test fn fprintf_closed() void = {
let s: io.stream = errsource(); let s: io.stream = errsource();
let r: (size | io.error) = fmt.fprintf(s, "hello {}", 1i64); let r: (size | io.error) = fmt.fprintf(s, "hello {}", 1i64);
match (r) { match (r) {
case let n: size => fail(); case let n: size => abort();
case let eioe: io.error => {}; case let eioe: io.error => {};
}; };
}; };
@@ -375,8 +369,8 @@ fn errsource() io.stream = {
let buf: [16]u8; let buf: [16]u8;
let r: (str | io.error) = fmt.bsprintf(buf[0:16], "{} {}", "hi", 42i64); let r: (str | io.error) = fmt.bsprintf(buf[0:16], "{} {}", "hi", 42i64);
match (r) { match (r) {
case let s: str => { if (!streq(s, "hi 42")) { fail(); }; }; case let s: str => { assert(!(!streq(s, "hi 42"))); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
}; };
@@ -390,12 +384,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{} {}", true, 'A': rune); let r: (size | io.error) = fmt.fprintf(s, "{} {}", true, 'A': rune);
match (r) { match (r) {
case let n: size => { if (n: i32 != 6) { fail(); }; }; // "true A" case let n: size => { assert(!(n: i32 != 6)); }; // "true A"
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "true A")) { fail(); }; assert(!(!streq(memio.string(&mem), "true A")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// Verifies bsprintf's documented truncation contract — short writes // Verifies bsprintf's documented truncation contract — short writes
@@ -406,8 +400,8 @@ fn errsource() io.stream = {
let buf: [3]u8; let buf: [3]u8;
let r: (str | io.error) = fmt.bsprintf(buf[0:3], "{} {}", "hi", 42i64); let r: (str | io.error) = fmt.bsprintf(buf[0:3], "{} {}", "hi", 42i64);
match (r) { match (r) {
case let s: str => { if (!streq(s, "hi ")) { fail(); }; }; case let s: str => { assert(!(!streq(s, "hi "))); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
}; };
@@ -420,8 +414,8 @@ fn errsource() io.stream = {
let buf: [3]u8; let buf: [3]u8;
let r: (str | io.error) = fmt.bsprintf(buf[0:3], "{:5}", 42i64); let r: (str | io.error) = fmt.bsprintf(buf[0:3], "{:5}", 42i64);
match (r) { match (r) {
case let s: str => { if (!streq(s, " ")) { fail(); }; }; case let s: str => { assert(!(!streq(s, " "))); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
}; };
@@ -430,7 +424,7 @@ fn errsource() io.stream = {
@test fn asprintf_basic() void = { @test fn asprintf_basic() void = {
let r: str = fmt.asprintf("{} {}", "hi", 42i64); let r: str = fmt.asprintf("{} {}", "hi", 42i64);
if (!streq(r, "hi 42")) { fail(); }; assert(!(!streq(r, "hi 42")));
os.free(r.ptr: *void, r.len: u64); os.free(r.ptr: *void, r.len: u64);
}; };
@@ -438,7 +432,7 @@ fn errsource() io.stream = {
// double-and-copy grow path; 34B target traverses 8→16→32→64. // double-and-copy grow path; 34B target traverses 8→16→32→64.
@test fn asprintf_growth() void = { @test fn asprintf_growth() void = {
let r: str = fmt.asprintf("hello {} world {} value {}", "alpha", "beta", "gamma"); let r: str = fmt.asprintf("hello {} world {} value {}", "alpha", "beta", "gamma");
if (!streq(r, "hello alpha world beta value gamma")) { fail(); }; assert(!(!streq(r, "hello alpha world beta value gamma")));
os.free(r.ptr: *void, r.len: u64); os.free(r.ptr: *void, r.len: u64);
}; };
@@ -448,7 +442,7 @@ fn errsource() io.stream = {
// strings.dup empty-input contract. // strings.dup empty-input contract.
@test fn asprintf_empty() void = { @test fn asprintf_empty() void = {
let r: str = fmt.asprintf(""); let r: str = fmt.asprintf("");
if (r.len != 0) { fail(); }; assert(!(r.len != 0));
}; };
// Indexed placeholder + modifier through asprintf — confirms the full // Indexed placeholder + modifier through asprintf — confirms the full
@@ -456,7 +450,7 @@ fn errsource() io.stream = {
// the memio.fixed (bsprintf) and memio.dynamic-via-fprintf paths. // the memio.fixed (bsprintf) and memio.dynamic-via-fprintf paths.
@test fn asprintf_indexed_mods() void = { @test fn asprintf_indexed_mods() void = {
let r: str = fmt.asprintf("{1:_05}", "zzz", 42i64); let r: str = fmt.asprintf("{1:_05}", "zzz", 42i64);
if (!streq(r, "00042")) { fail(); }; assert(!(!streq(r, "00042")));
os.free(r.ptr: *void, r.len: u64); os.free(r.ptr: *void, r.len: u64);
}; };
@@ -476,12 +470,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{}", 1.5); let r: (size | io.error) = fmt.fprintf(s, "{}", 1.5);
match (r) { match (r) {
case let n: size => { if (n: i32 != 3) { fail(); }; }; case let n: size => { assert(!(n: i32 != 3)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "1.5")) { fail(); }; assert(!(!streq(memio.string(&mem), "1.5")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_f64_int_valued() void = { @test fn fprintf_f64_int_valued() void = {
@@ -489,12 +483,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{}", 1.0); let r: (size | io.error) = fmt.fprintf(s, "{}", 1.0);
match (r) { match (r) {
case let n: size => { if (n: i32 != 1) { fail(); }; }; case let n: size => { assert(!(n: i32 != 1)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "1")) { fail(); }; assert(!(!streq(memio.string(&mem), "1")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_f64_neg() void = { @test fn fprintf_f64_neg() void = {
@@ -502,12 +496,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{}", -2.5); let r: (size | io.error) = fmt.fprintf(s, "{}", -2.5);
match (r) { match (r) {
case let n: size => { if (n: i32 != 4) { fail(); }; }; case let n: size => { assert(!(n: i32 != 4)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "-2.5")) { fail(); }; assert(!(!streq(memio.string(&mem), "-2.5")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_f64_zero() void = { @test fn fprintf_f64_zero() void = {
@@ -515,12 +509,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{}", 0.0); let r: (size | io.error) = fmt.fprintf(s, "{}", 0.0);
match (r) { match (r) {
case let n: size => { if (n: i32 != 1) { fail(); }; }; case let n: size => { assert(!(n: i32 != 1)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "0")) { fail(); }; assert(!(!streq(memio.string(&mem), "0")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_f64_small_frac() void = { @test fn fprintf_f64_small_frac() void = {
@@ -528,12 +522,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{}", 0.05); let r: (size | io.error) = fmt.fprintf(s, "{}", 0.05);
match (r) { match (r) {
case let n: size => { if (n: i32 != 4) { fail(); }; }; case let n: size => { assert(!(n: i32 != 4)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "0.05")) { fail(); }; assert(!(!streq(memio.string(&mem), "0.05")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// Pins a large magnitude through the fmt dispatch — post-Ryū-graduation // Pins a large magnitude through the fmt dispatch — post-Ryū-graduation
@@ -544,12 +538,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{}", 9.5e18); let r: (size | io.error) = fmt.fprintf(s, "{}", 9.5e18);
match (r) { match (r) {
case let n: size => { if (n: i32 != 6) { fail(); }; }; // "9.5e18" case let n: size => { assert(!(n: i32 != 6)); }; // "9.5e18"
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "9.5e18")) { fail(); }; assert(!(!streq(memio.string(&mem), "9.5e18")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// Sign-mod fold: '+' on positive, '-' still wins on negative (the // Sign-mod fold: '+' on positive, '-' still wins on negative (the
@@ -559,12 +553,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:+} {:+}", 1.5, -1.5); let r: (size | io.error) = fmt.fprintf(s, "{:+} {:+}", 1.5, -1.5);
match (r) { match (r) {
case let n: size => { if (n: i32 != 9) { fail(); }; }; // "+1.5 -1.5" case let n: size => { assert(!(n: i32 != 9)); }; // "+1.5 -1.5"
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "+1.5 -1.5")) { fail(); }; assert(!(!streq(memio.string(&mem), "+1.5 -1.5")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_f64_sign_space() void = { @test fn fprintf_f64_sign_space() void = {
@@ -572,12 +566,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{: }", 1.5); let r: (size | io.error) = fmt.fprintf(s, "{: }", 1.5);
match (r) { match (r) {
case let n: size => { if (n: i32 != 4) { fail(); }; }; case let n: size => { assert(!(n: i32 != 4)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), " 1.5")) { fail(); }; assert(!(!streq(memio.string(&mem), " 1.5")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// Width + alignment round-trip through rawlenf64 (sign-aware len count). // Width + alignment round-trip through rawlenf64 (sign-aware len count).
@@ -586,12 +580,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:8}", 1.5); let r: (size | io.error) = fmt.fprintf(s, "{:8}", 1.5);
match (r) { match (r) {
case let n: size => { if (n: i32 != 8) { fail(); }; }; case let n: size => { assert(!(n: i32 != 8)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), " 1.5")) { fail(); }; assert(!(!streq(memio.string(&mem), " 1.5")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn fprintf_f64_width_left() void = { @test fn fprintf_f64_width_left() void = {
@@ -599,12 +593,12 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprintf(s, "{:-8}", 1.5); let r: (size | io.error) = fmt.fprintf(s, "{:-8}", 1.5);
match (r) { match (r) {
case let n: size => { if (n: i32 != 8) { fail(); }; }; case let n: size => { assert(!(n: i32 != 8)); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "1.5 ")) { fail(); }; assert(!(!streq(memio.string(&mem), "1.5 ")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
// Legacy fprint variadic — covers the non-printf surface arm (where // Legacy fprint variadic — covers the non-printf surface arm (where
@@ -614,73 +608,73 @@ fn errsource() io.stream = {
let s: io.stream = &mem.vt; let s: io.stream = &mem.vt;
let r: (size | io.error) = fmt.fprint(s, 1.5, "x"); let r: (size | io.error) = fmt.fprint(s, 1.5, "x");
match (r) { match (r) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; // "1.5 x" case let n: size => { assert(!(n: i32 != 5)); }; // "1.5 x"
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
if (!streq(memio.string(&mem), "1.5 x")) { fail(); }; assert(!(!streq(memio.string(&mem), "1.5 x")));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let eioe: io.error => fail(); }; match (c) { case void => {}; case let eioe: io.error => abort(); };
}; };
@test fn bsprintf_f64() void = { @test fn bsprintf_f64() void = {
let buf: [16]u8; let buf: [16]u8;
let r: (str | io.error) = fmt.bsprintf(buf[0:16], "x={}", 1.5); let r: (str | io.error) = fmt.bsprintf(buf[0:16], "x={}", 1.5);
match (r) { match (r) {
case let s: str => { if (!streq(s, "x=1.5")) { fail(); }; }; case let s: str => { assert(!(!streq(s, "x=1.5"))); };
case let eioe: io.error => fail(); case let eioe: io.error => abort();
}; };
}; };
// Heap sink + both signs. // Heap sink + both signs.
@test fn asprintf_f64() void = { @test fn asprintf_f64() void = {
let r: str = fmt.asprintf("{} {}", 1.5, -2.5); let r: str = fmt.asprintf("{} {}", 1.5, -2.5);
if (!streq(r, "1.5 -2.5")) { fail(); }; assert(!(!streq(r, "1.5 -2.5")));
os.free(r.ptr: *void, r.len: u64); os.free(r.ptr: *void, r.len: u64);
}; };
export fn main() i32 = { export fn main() i32 = {
signalled = 1; fprintbarestr(); fprintbarestr();
signalled = 2; fprintintstr(); fprintintstr();
signalled = 3; fprintboolrune(); fprintboolrune();
signalled = 4; fprintempty(); fprintempty();
signalled = 5; fprintlnmulti(); fprintlnmulti();
signalled = 6; fprintlnempty(); fprintlnempty();
signalled = 7; fprintfixedshort(); fprintfixedshort();
signalled = 8; fprintclosed(); fprintclosed();
signalled = 9; fprintf_implicit(); fprintf_implicit();
signalled = 10; fprintf_indexed(); fprintf_indexed();
signalled = 11; fprintf_literal_braces(); fprintf_literal_braces();
signalled = 12; fprintf_width_right(); fprintf_width_right();
signalled = 13; fprintf_width_left(); fprintf_width_left();
signalled = 14; fprintf_width_center(); fprintf_width_center();
signalled = 15; fprintf_pad_underscore(); fprintf_pad_underscore();
signalled = 16; fprintf_base_hex(); fprintf_base_hex();
signalled = 17; fprintf_base_oct_bin(); fprintf_base_oct_bin();
signalled = 18; fprintf_prec_int(); fprintf_prec_int();
signalled = 19; fprintf_prec_str_trunc(); fprintf_prec_str_trunc();
signalled = 20; fprintf_sign_neg(); fprintf_sign_neg();
signalled = 21; fprintfln_basic(); fprintfln_basic();
signalled = 22; fprintf_closed(); fprintf_closed();
signalled = 23; bsprintf_basic(); bsprintf_basic();
signalled = 24; fprintf_bool_rune(); fprintf_bool_rune();
signalled = 25; bsprintf_trunc(); bsprintf_trunc();
signalled = 26; bsprintf_width_trunc(); bsprintf_width_trunc();
signalled = 27; asprintf_basic(); asprintf_basic();
signalled = 28; asprintf_growth(); asprintf_growth();
signalled = 29; asprintf_empty(); asprintf_empty();
signalled = 30; asprintf_indexed_mods(); asprintf_indexed_mods();
signalled = 31; fprintf_f64_basic(); fprintf_f64_basic();
signalled = 32; fprintf_f64_int_valued(); fprintf_f64_int_valued();
signalled = 33; fprintf_f64_neg(); fprintf_f64_neg();
signalled = 34; fprintf_f64_zero(); fprintf_f64_zero();
signalled = 35; fprintf_f64_small_frac(); fprintf_f64_small_frac();
signalled = 36; fprintf_f64_huge(); fprintf_f64_huge();
signalled = 37; fprintf_f64_sign_plus(); fprintf_f64_sign_plus();
signalled = 38; fprintf_f64_sign_space(); fprintf_f64_sign_space();
signalled = 39; fprintf_f64_width_right(); fprintf_f64_width_right();
signalled = 40; fprintf_f64_width_left(); fprintf_f64_width_left();
signalled = 41; fprint_f64_variadic(); fprint_f64_variadic();
signalled = 42; bsprintf_f64(); bsprintf_f64();
signalled = 43; asprintf_f64(); asprintf_f64();
return 0; return 0;
}; };

View File

@@ -15,13 +15,6 @@ import fmt;
import io; import io;
import log; import log;
import memio; import memio;
import os;
// signalled — bumped before each scenario so a failing exit code
// pinpoints the offending case.
let signalled: i32 = 0;
fn fail() void = { os.exit(signalled + 10); };
fn streq(a: str, b: str) bool = { fn streq(a: str, b: str) bool = {
if (a.len != b.len) { return false; }; if (a.len != b.len) { return false; };
@@ -48,10 +41,10 @@ fn streq(a: str, b: str) bool = {
let s = &mem.vt; let s = &mem.vt;
let sl = log.new(s); // triggers ensureinit let sl = log.new(s); // triggers ensureinit
if (log.silent == nil) { fail(); }; assert(!(log.silent == nil));
if (log.default == nil) { fail(); }; assert(!(log.default == nil));
if (log.global == nil) { fail(); }; assert(!(log.global == nil));
if (log.global != log.default) { fail(); }; assert(!(log.global != log.default));
}; };
// ---- lprintln to a memio sink: exact-byte assertion ------------------- // ---- lprintln to a memio sink: exact-byte assertion -------------------
@@ -65,7 +58,7 @@ fn streq(a: str, b: str) bool = {
log.lprintln(&sl.logger, "hello", 42i64); log.lprintln(&sl.logger, "hello", 42i64);
if (!streq(memio.string(&mem), "hello 42\n")) { fail(); }; assert(!(!streq(memio.string(&mem), "hello 42\n")));
}; };
// ---- lprintln single-arg: no leading space, just trailing newline ----- // ---- lprintln single-arg: no leading space, just trailing newline -----
@@ -79,7 +72,7 @@ fn streq(a: str, b: str) bool = {
log.lprintln(&sl.logger, "only"); log.lprintln(&sl.logger, "only");
if (!streq(memio.string(&mem), "only\n")) { fail(); }; assert(!(!streq(memio.string(&mem), "only\n")));
}; };
// ---- lprintln zero args: bare newline --------------------------------- // ---- lprintln zero args: bare newline ---------------------------------
@@ -93,7 +86,7 @@ fn streq(a: str, b: str) bool = {
log.lprintln(&sl.logger); log.lprintln(&sl.logger);
if (!streq(memio.string(&mem), "\n")) { fail(); }; assert(!(!streq(memio.string(&mem), "\n")));
}; };
// ---- silent: lprintln through log.silent writes no bytes -------------- // ---- silent: lprintln through log.silent writes no bytes --------------
@@ -111,11 +104,11 @@ fn streq(a: str, b: str) bool = {
let sl = log.new(s); // triggers log.ensureinit; populates log.silent let sl = log.new(s); // triggers log.ensureinit; populates log.silent
if (log.silent == nil) { fail(); }; assert(!(log.silent == nil));
log.lprintln(log.silent, "ignored", 1i64, true); log.lprintln(log.silent, "ignored", 1i64, true);
if (mem.pos != 0) { fail(); }; assert(!(mem.pos != 0));
}; };
// ---- setlogger swap: global redirects to a new sink, then to silent -- // ---- setlogger swap: global redirects to a new sink, then to silent --
@@ -137,20 +130,20 @@ fn streq(a: str, b: str) bool = {
log.setlogger(&sl1.logger); log.setlogger(&sl1.logger);
log.println("first"); log.println("first");
if (!streq(memio.string(&mem1), "first\n")) { fail(); }; assert(!(!streq(memio.string(&mem1), "first\n")));
if (mem2.pos != 0) { fail(); }; assert(!(mem2.pos != 0));
log.setlogger(&sl2.logger); log.setlogger(&sl2.logger);
log.println("second"); log.println("second");
if (!streq(memio.string(&mem2), "second\n")) { fail(); }; assert(!(!streq(memio.string(&mem2), "second\n")));
// mem1 must be unchanged. // mem1 must be unchanged.
if (!streq(memio.string(&mem1), "first\n")) { fail(); }; assert(!(!streq(memio.string(&mem1), "first\n")));
log.setlogger(log.silent); log.setlogger(log.silent);
log.println("dropped"); log.println("dropped");
// Both sinks unchanged. // Both sinks unchanged.
if (!streq(memio.string(&mem1), "first\n")) { fail(); }; assert(!(!streq(memio.string(&mem1), "first\n")));
if (!streq(memio.string(&mem2), "second\n")) { fail(); }; assert(!(!streq(memio.string(&mem2), "second\n")));
}; };
// ---- lprintfln: {n}-placeholder render into a memio sink ------------- // ---- lprintfln: {n}-placeholder render into a memio sink -------------
@@ -164,7 +157,7 @@ fn streq(a: str, b: str) bool = {
log.lprintfln(&sl.logger, "x={} y={}", 42i64, "hi"); log.lprintfln(&sl.logger, "x={} y={}", 42i64, "hi");
if (!streq(memio.string(&mem), "x=42 y=hi\n")) { fail(); }; assert(!(!streq(memio.string(&mem), "x=42 y=hi\n")));
}; };
// ---- printfln through global: setlogger then dispatch --------------- // ---- printfln through global: setlogger then dispatch ---------------
@@ -184,8 +177,8 @@ fn streq(a: str, b: str) bool = {
log.setlogger(&sl1.logger); log.setlogger(&sl1.logger);
log.printfln("v={}", 7i64); log.printfln("v={}", 7i64);
if (!streq(memio.string(&mem1), "v=7\n")) { fail(); }; assert(!(!streq(memio.string(&mem1), "v=7\n")));
if (mem2.pos != 0) { fail(); }; assert(!(mem2.pos != 0));
}; };
// ---- silent.printfln writes nothing --------------------------------- // ---- silent.printfln writes nothing ---------------------------------
@@ -200,11 +193,11 @@ fn streq(a: str, b: str) bool = {
let sl = log.new(s); // triggers log.ensureinit; populates log.silent let sl = log.new(s); // triggers log.ensureinit; populates log.silent
if (log.silent == nil) { fail(); }; assert(!(log.silent == nil));
log.lprintfln(log.silent, "ignored={}", 1i64); log.lprintfln(log.silent, "ignored={}", 1i64);
if (mem.pos != 0) { fail(); }; assert(!(mem.pos != 0));
}; };
// ---- lprintfln: indexed {N} placeholder across log → fmt seam ------- // ---- lprintfln: indexed {N} placeholder across log → fmt seam -------
@@ -221,7 +214,7 @@ fn streq(a: str, b: str) bool = {
log.lprintfln(&sl.logger, "{1} {0}", "a", "b"); log.lprintfln(&sl.logger, "{1} {0}", "a", "b");
if (!streq(memio.string(&mem), "b a\n")) { fail(); }; assert(!(!streq(memio.string(&mem), "b a\n")));
}; };
// ---- lprintfln: {:mods} modifier across log → fmt seam -------------- // ---- lprintfln: {:mods} modifier across log → fmt seam --------------
@@ -237,7 +230,7 @@ fn streq(a: str, b: str) bool = {
log.lprintfln(&sl.logger, "{:5}", 42i64); log.lprintfln(&sl.logger, "{:5}", 42i64);
if (!streq(memio.string(&mem), " 42\n")) { fail(); }; assert(!(!streq(memio.string(&mem), " 42\n")));
}; };
// TODO subprocess: log.fatal / log.lfatal / log.fatalf / log.lfatalf // TODO subprocess: log.fatal / log.lfatal / log.fatalf / log.lfatalf
@@ -247,16 +240,16 @@ fn streq(a: str, b: str) bool = {
// when that lands. // when that lands.
export fn main() i32 = { export fn main() i32 = {
signalled = 1; defaultwiredtoglobal(); defaultwiredtoglobal();
signalled = 2; lprintlnbasic(); lprintlnbasic();
signalled = 3; lprintlnsingle(); lprintlnsingle();
signalled = 4; lprintlnempty(); lprintlnempty();
signalled = 5; silentwritesnothing(); silentwritesnothing();
signalled = 6; setloggerswap(); setloggerswap();
signalled = 7; lprintflnbasic(); lprintflnbasic();
signalled = 8; printflnglobal(); printflnglobal();
signalled = 9; silentignoresprintfln(); silentignoresprintfln();
signalled = 10; lprintflnindexed(); lprintflnindexed();
signalled = 11; lprintflnmods(); lprintflnmods();
return 0; return 0;
}; };

View File

@@ -13,13 +13,6 @@ import bytes;
import errors; import errors;
import io; import io;
import memio; import memio;
import os;
// signalled — bumped by main before each test so a failing exit code
// pinpoints the offending case.
let signalled: i32 = 0;
fn fail() void = { os.exit(signalled + 10); };
fn putstr(s: str, into: []u8, off: i32) i32 = { fn putstr(s: str, into: []u8, off: i32) i32 = {
let i: i32 = 0; let i: i32 = 0;
@@ -64,20 +57,20 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
match (r) { match (r) {
case let nz: size => { case let nz: size => {
let n: i32 = nz: i32; let n: i32 = nz: i32;
if (weof[i] != 0) { fail(); }; assert(!(weof[i] != 0));
if (n != wantn[i]) { fail(); }; assert(!(n != wantn[i]));
if (n > 0 && out[0] != wantf[i]) { fail(); }; assert(!(n > 0 && out[0] != wantf[i]));
if (n > 0 && out[n - 1] != wantl[i]) { fail(); }; assert(!(n > 0 && out[n - 1] != wantl[i]));
}; };
case io.eof => { if (weof[i] == 0) { fail(); }; }; case io.eof => { assert(!(weof[i] == 0)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
i += 1; i += 1;
}; };
// fixed stream has no closer → io.close returns void. // fixed stream has no closer → io.close returns void.
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let e: io.error => fail(); }; match (c) { case void => {}; case let e: io.error => abort(); };
}; };
// ---- fixedwritecases: full-fit / exact-fill / partial / overflow ------------- // ---- fixedwritecases: full-fit / exact-fill / partial / overflow -------------
@@ -108,25 +101,25 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
let hi: i32 = lo + ln[i]; let hi: i32 = lo + ln[i];
let r: (size | io.error) = io.write(s, src[lo:hi]); let r: (size | io.error) = io.write(s, src[lo:hi]);
match (r) { match (r) {
case let n: size => { if (n: i32 != wantn[i]) { fail(); }; }; case let n: size => { assert(!(n: i32 != wantn[i])); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
i += 1; i += 1;
}; };
let want: [16]u8; let want: [16]u8;
let _: i32 = putstr("hello world!!XXX", want[0:16], 0); let _: i32 = putstr("hello world!!XXX", want[0:16], 0);
if (!bytes.equal(dst[0:16], want[0:16])) { fail(); }; assert(!(!bytes.equal(dst[0:16], want[0:16])));
// 0-byte write is always 0 with no side effects. // 0-byte write is always 0 with no side effects.
let r0: (size | io.error) = io.write(s, src[0:0]); let r0: (size | io.error) = io.write(s, src[0:0]);
match (r0) { match (r0) {
case let n: size => { if (n != 0: size) { fail(); }; }; case let n: size => { assert(!(n != 0: size)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let e: io.error => fail(); }; match (c) { case void => {}; case let e: io.error => abort(); };
}; };
// ---- dynamicgrowcases: every cap doubling exercised --------------------- // ---- dynamicgrowcases: every cap doubling exercised ---------------------
@@ -157,18 +150,18 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
let hi: i32 = lo + chunk[i]; let hi: i32 = lo + chunk[i];
let r: (size | io.error) = io.write(s, src[lo:hi]); let r: (size | io.error) = io.write(s, src[lo:hi]);
match (r) { match (r) {
case let n: size => { if (n: i32 != chunk[i]) { fail(); }; }; case let n: size => { assert(!(n: i32 != chunk[i])); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
if (memio.buffer(&st).len != total[i]) { fail(); }; assert(!(memio.buffer(&st).len != total[i]));
off += chunk[i]; off += chunk[i];
i += 1; i += 1;
}; };
if (!bytes.equal(memio.buffer(&st), src[0:26])) { fail(); }; assert(!(!bytes.equal(memio.buffer(&st), src[0:26])));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let e: io.error => fail(); }; match (c) { case void => {}; case let e: io.error => abort(); };
}; };
// ---- dynamicreset: write / reset / write cycles ------------------------- // ---- dynamicreset: write / reset / write cycles -------------------------
@@ -204,19 +197,19 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
let hi: i32 = lo + ln[i]; let hi: i32 = lo + ln[i];
let r: (size | io.error) = io.write(s, src[lo:hi]); let r: (size | io.error) = io.write(s, src[lo:hi]);
match (r) { match (r) {
case let n: size => { if (n: i32 != ln[i]) { fail(); }; }; case let n: size => { assert(!(n: i32 != ln[i])); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
off += ln[i]; off += ln[i];
}; };
if (memio.buffer(&st).len != want[i]) { fail(); }; assert(!(memio.buffer(&st).len != want[i]));
i += 1; i += 1;
}; };
if (!bytes.equal(memio.buffer(&st), src[0:8])) { fail(); }; assert(!(!bytes.equal(memio.buffer(&st), src[0:8])));
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let e: io.error => fail(); }; match (c) { case void => {}; case let e: io.error => abort(); };
}; };
// ---- borrowedread: under / exact / over / 0-byte ------------------------ // ---- borrowedread: under / exact / over / 0-byte ------------------------
@@ -242,12 +235,12 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
let r: ([]u8 | io.eof) = memio.borrowedread(&st, amt[i]); let r: ([]u8 | io.eof) = memio.borrowedread(&st, amt[i]);
match (r) { match (r) {
case let v: []u8 => { case let v: []u8 => {
if (weof[i] != 0) { fail(); }; assert(!(weof[i] != 0));
if (v.len != amt[i]) { fail(); }; assert(!(v.len != amt[i]));
if (v.len > 0 && v[0] != wf[i]) { fail(); }; assert(!(v.len > 0 && v[0] != wf[i]));
if (v.len > 0 && v[v.len - 1] != wl[i]) { fail(); }; assert(!(v.len > 0 && v[v.len - 1] != wl[i]));
}; };
case io.eof => { if (weof[i] == 0) { fail(); }; }; case io.eof => { assert(!(weof[i] == 0)); };
}; };
i += 1; i += 1;
}; };
@@ -259,7 +252,7 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
let st: memio.stream = memio.dynamic(); let st: memio.stream = memio.dynamic();
let s: io.stream = &st.vt; let s: io.stream = &st.vt;
if (memio.string(&st).len != 0) { fail(); }; assert(!(memio.string(&st).len != 0));
let src: [32]u8; let src: [32]u8;
let _: i32 = putstr("hello world!!", src[0:32], 0); let _: i32 = putstr("hello world!!", src[0:32], 0);
@@ -279,16 +272,16 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
let lo: i32 = off[i]; let lo: i32 = off[i];
let hi: i32 = lo + ln[i]; let hi: i32 = lo + ln[i];
let r: (size | io.error) = io.write(s, src[lo:hi]); let r: (size | io.error) = io.write(s, src[lo:hi]);
match (r) { case let n: size => {}; case let e: io.error => fail(); }; match (r) { case let n: size => {}; case let e: io.error => abort(); };
let v: str = memio.string(&st); let v: str = memio.string(&st);
if (v.len != want[i]) { fail(); }; assert(!(v.len != want[i]));
if (v[0] != wf[i]) { fail(); }; assert(!(v[0] != wf[i]));
if (v[v.len - 1] != wl[i]) { fail(); }; assert(!(v[v.len - 1] != wl[i]));
i += 1; i += 1;
}; };
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let e: io.error => fail(); }; match (c) { case void => {}; case let e: io.error => abort(); };
}; };
// ---- dynamicfromseed: ownership-transferred seed, read then write ------- // ---- dynamicfromseed: ownership-transferred seed, read then write -------
@@ -321,12 +314,12 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
match (r) { match (r) {
case let nz: size => { case let nz: size => {
let n: i32 = nz: i32; let n: i32 = nz: i32;
if (weof[i] != 0) { fail(); }; assert(!(weof[i] != 0));
if (n != rn[i]) { fail(); }; assert(!(n != rn[i]));
if (out[0] != want[i]) { fail(); }; assert(!(out[0] != want[i]));
}; };
case io.eof => { if (weof[i] == 0) { fail(); }; }; case io.eof => { assert(!(weof[i] == 0)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
i += 1; i += 1;
}; };
@@ -337,12 +330,12 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
extra[0]=200u8; extra[1]=201u8; extra[2]=202u8; extra[3]=203u8; extra[0]=200u8; extra[1]=201u8; extra[2]=202u8; extra[3]=203u8;
let w: (size | io.error) = io.write(s, extra[0:4]); let w: (size | io.error) = io.write(s, extra[0:4]);
match (w) { match (w) {
case let n: size => { if (n: i32 != 4) { fail(); }; }; case let n: size => { assert(!(n: i32 != 4)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let e: io.error => fail(); }; match (c) { case void => {}; case let e: io.error => abort(); };
}; };
// ---- seekcases: SET/CUR/END × in-bounds/OOB over one fixed stream -------- // ---- seekcases: SET/CUR/END × in-bounds/OOB over one fixed stream --------
@@ -385,22 +378,22 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
let r: (io.off | io.error) = io.seek(s, off[i], w); let r: (io.off | io.error) = io.seek(s, off[i], w);
match (r) { match (r) {
case let o: io.off => { case let o: io.off => {
if (want[i] < 0) { fail(); }; assert(!(want[i] < 0));
if ((o: i64) != want[i]) { fail(); }; assert(!((o: i64) != want[i]));
pos = o: i64; pos = o: i64;
}; };
case let e: io.error => { case let e: io.error => {
if (want[i] >= 0) { fail(); }; assert(!(want[i] >= 0));
match (e) { match (e) {
case errors.invalid => {}; case errors.invalid => {};
case => fail(); case => abort();
}; };
}; };
}; };
let t: (io.off | io.error) = io.tell(s); let t: (io.off | io.error) = io.tell(s);
match (t) { match (t) {
case let o: io.off => { if ((o: i64) != pos) { fail(); }; }; case let o: io.off => { assert(!((o: i64) != pos)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
i += 1; i += 1;
}; };
@@ -409,25 +402,25 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
// drains bytes 5..7, then eof. // drains bytes 5..7, then eof.
let r: (io.off | io.error) = io.seek(s, 5, io.whence.SET); let r: (io.off | io.error) = io.seek(s, 5, io.whence.SET);
match (r) { match (r) {
case let o: io.off => { if ((o: i64) != 5) { fail(); }; }; case let o: io.off => { assert(!((o: i64) != 5)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let out: [8]u8; let out: [8]u8;
let rd: (size | io.eof | io.error) = io.read(s, out[0:8]); let rd: (size | io.eof | io.error) = io.read(s, out[0:8]);
match (rd) { match (rd) {
case let nz: size => { case let nz: size => {
if (nz: i32 != 3) { fail(); }; assert(!(nz: i32 != 3));
if (out[0] != 15u8) { fail(); }; assert(!(out[0] != 15u8));
if (out[2] != 17u8) { fail(); }; assert(!(out[2] != 17u8));
}; };
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let rd2: (size | io.eof | io.error) = io.read(s, out[0:8]); let rd2: (size | io.eof | io.error) = io.read(s, out[0:8]);
match (rd2) { match (rd2) {
case io.eof => {}; case io.eof => {};
case let nz: size => fail(); case let nz: size => abort();
case let e: io.error => fail(); case let e: io.error => abort();
}; };
}; };
@@ -454,14 +447,14 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
let r: (io.off | io.error) = io.seek(s, off[i], w); let r: (io.off | io.error) = io.seek(s, off[i], w);
match (r) { match (r) {
case let o: io.off => { case let o: io.off => {
if (want[i] < 0) { fail(); }; assert(!(want[i] < 0));
if ((o: i64) != want[i]) { fail(); }; assert(!((o: i64) != want[i]));
}; };
case let e: io.error => { case let e: io.error => {
if (want[i] >= 0) { fail(); }; assert(!(want[i] >= 0));
match (e) { match (e) {
case errors.invalid => {}; case errors.invalid => {};
case => fail(); case => abort();
}; };
}; };
}; };
@@ -482,24 +475,24 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
src[0]=30u8; src[1]=31u8; src[2]=32u8; src[3]=33u8; src[4]=34u8; src[0]=30u8; src[1]=31u8; src[2]=32u8; src[3]=33u8; src[4]=34u8;
let wr: (size | io.error) = io.write(s, src[0:5]); let wr: (size | io.error) = io.write(s, src[0:5]);
match (wr) { match (wr) {
case let n: size => { if (n: i32 != 5) { fail(); }; }; case let n: size => { assert(!(n: i32 != 5)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
// END 0 → 5 (logical length); cap is 8 post-grow, so END 1 must // END 0 → 5 (logical length); cap is 8 post-grow, so END 1 must
// still be invalid even though capacity would fit it. // still be invalid even though capacity would fit it.
let r: (io.off | io.error) = io.seek(s, 0, io.whence.END); let r: (io.off | io.error) = io.seek(s, 0, io.whence.END);
match (r) { match (r) {
case let o: io.off => { if ((o: i64) != 5) { fail(); }; }; case let o: io.off => { assert(!((o: i64) != 5)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let r1: (io.off | io.error) = io.seek(s, 1, io.whence.END); let r1: (io.off | io.error) = io.seek(s, 1, io.whence.END);
match (r1) { match (r1) {
case let o: io.off => fail(); case let o: io.off => abort();
case let e: io.error => { case let e: io.error => {
match (e) { match (e) {
case errors.invalid => {}; case errors.invalid => {};
case => fail(); case => abort();
}; };
}; };
}; };
@@ -507,41 +500,41 @@ fn putstr(s: str, into: []u8, off: i32) i32 = {
// CUR -2 → 3; read drains 33,34 then eof. // CUR -2 → 3; read drains 33,34 then eof.
let r2: (io.off | io.error) = io.seek(s, -2, io.whence.CUR); let r2: (io.off | io.error) = io.seek(s, -2, io.whence.CUR);
match (r2) { match (r2) {
case let o: io.off => { if ((o: i64) != 3) { fail(); }; }; case let o: io.off => { assert(!((o: i64) != 3)); };
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let out: [4]u8; let out: [4]u8;
let rd: (size | io.eof | io.error) = io.read(s, out[0:4]); let rd: (size | io.eof | io.error) = io.read(s, out[0:4]);
match (rd) { match (rd) {
case let nz: size => { case let nz: size => {
if (nz: i32 != 2) { fail(); }; assert(!(nz: i32 != 2));
if (out[0] != 33u8) { fail(); }; assert(!(out[0] != 33u8));
if (out[1] != 34u8) { fail(); }; assert(!(out[1] != 34u8));
}; };
case io.eof => fail(); case io.eof => abort();
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let rd2: (size | io.eof | io.error) = io.read(s, out[0:4]); let rd2: (size | io.eof | io.error) = io.read(s, out[0:4]);
match (rd2) { match (rd2) {
case io.eof => {}; case io.eof => {};
case let nz: size => fail(); case let nz: size => abort();
case let e: io.error => fail(); case let e: io.error => abort();
}; };
let c: (void | io.error) = io.close(s); let c: (void | io.error) = io.close(s);
match (c) { case void => {}; case let e: io.error => fail(); }; match (c) { case void => {}; case let e: io.error => abort(); };
}; };
export fn main() i32 = { export fn main() i32 = {
signalled = 1; fixedread(); fixedread();
signalled = 2; fixedwritecases(); fixedwritecases();
signalled = 3; dynamicgrowcases(); dynamicgrowcases();
signalled = 4; dynamicreset(); dynamicreset();
signalled = 5; borrowedreadcases(); borrowedreadcases();
signalled = 6; stringview(); stringview();
signalled = 7; dynamicfromseed(); dynamicfromseed();
signalled = 8; seekcases(); seekcases();
signalled = 9; emptyseek(); emptyseek();
signalled = 10; dynamicseek(); dynamicseek();
return 0; return 0;
}; };