lib/std/testing.rad 2.4 KiB raw
1
//! Test utilities for the Radiance testing framework.
2
3
use std::mem;
4
use std::io;
5
6
/// Internal state for tracking test pass/fail counts.
7
record Ctx {
8
    passed: u32,
9
    failed: u32,
10
}
11
12
/// Error thrown when a test assertion fails.
13
pub union TestError {
14
    Failed,
15
}
16
17
/// Descriptor for a single test case, holding its module path, name, and entry point.
18
pub record TestInfo {
19
    module: *[u8],
20
    name: *[u8],
21
    func: fn() -> void throws (TestError),
22
}
23
24
/// Construct a [`TestInfo`]. Used by the compiler's synthetic test harness.
25
pub fn test(module: *[u8], name: *[u8], func: fn() -> void throws (TestError)) -> TestInfo {
26
    return TestInfo { module, name, func };
27
}
28
29
/// Run all tests and return `0` on success or `1` if any test failed.
30
pub fn runAllTests(tests: *[TestInfo]) -> i32 {
31
    let mut ctx: Ctx = Ctx { passed: 0, failed: 0 };
32
33
    io::print("Running ");
34
    io::printU32(tests.len);
35
    io::print(" test(s)...\n\n");
36
37
    for t in tests {
38
        runTest(&mut ctx, t.module, t.name, t.func);
39
    }
40
    printTestSummary(&ctx);
41
42
    if ctx.failed > 0 {
43
        return 1;
44
    }
45
    return 0;
46
}
47
48
fn runTest(
49
    ctx: *mut Ctx,
50
    module: *[u8],
51
    name: *[u8],
52
    testFn: fn () -> void throws (TestError)
53
) {
54
    io::print("test ");
55
    io::print(module);
56
    io::print("::");
57
    io::print(name);
58
    io::print(" ... ");
59
60
    let mut success = true;
61
    try testFn() catch {
62
        success = false;
63
    };
64
    if success {
65
        io::printLn("ok");
66
        ctx.passed += 1;
67
    } else {
68
        io::printLn("FAILED");
69
        ctx.failed += 1;
70
    }
71
}
72
73
fn printTestSummary(ctx: *Ctx) {
74
    if (ctx.failed > 0) {
75
        io::print("\ntest result: FAILED. ");
76
        io::printU32(ctx.passed);
77
        io::print(" passed; ");
78
        io::printU32(ctx.failed);
79
        io::printLn(" failed");
80
    } else {
81
        io::print("\ntest result: ok. ");
82
        io::printU32(ctx.passed);
83
        io::printLn(" passed; 0 failed");
84
    }
85
}
86
87
/// Assert that two byte slices are equal.
88
pub fn expectBytesEq(left: *[u8], right: *[u8])
89
    throws (TestError)
90
{
91
    try expect(mem::eq(left, right));
92
}
93
94
/// Assert that a boolean condition is true.
95
pub fn expect(cond: bool)
96
    throws (TestError)
97
{
98
    if not cond {
99
        throw TestError::Failed;
100
    }
101
}
102
103
/// Assert that a boolean condition is false.
104
pub fn expectNot(cond: bool)
105
    throws (TestError)
106
{
107
    if cond {
108
        throw TestError::Failed;
109
    }
110
}