jc/+internal/testing.jai
2025-09-07 15:25:57 -06:00

119 lines
2.5 KiB
Text

// Usage:
#if 0 {
#run,stallable {
Test("thing", t => {
Expect(some_condition, "error message: %", value);
});
Test("other thing", t => {
Expect(other_condition, "error message: %", value);
});
// ...
}
}
/// Test defines a new suite to be executed by the test runner.
///
/// See: Expect for more information.
///
/// Test("my_proc does what it should", t => {
/// value1 := my_proc(/* ... */);
/// Expect(value1 != 0, "my_proc returned zero!");
///
/// value2 := my_proc(/* .... */);
/// Expect(value2 > 0, "my_proc returned a negative number!");
/// });
///
Test :: (name: string, proc: (t: *void) -> (), loc := #caller_location) {
// @note(judah): incredibly dumb way to get nicer test runs
WriteString(SmallerPath(loc.fully_pathed_filename), ",");
WriteNumber(loc.line_number);
WriteString(": ", name, "... ");
t: TestRun;
proc(*t);
if t.failed {
WriteString("failed");
}
else {
WriteString("ok");
}
WriteString(" (");
WriteNumber(t.total_ok);
WriteString("/");
WriteNumber(t.total_expects);
WriteString(")\n");
}
/// Expect checks the given condition, failing the current test if it is false.
///
/// Note: Expect must be called within a test. Additionally, it expects the test
/// parameter to be called 't'.
Expect :: (cond: bool, message := "", args: ..Any, loc := #caller_location) #expand {
run := `t.(*TestRun);
run.total_expects += 1;
if cond {
run.total_ok += 1;
return;
}
msg := "expectation failed";
if message.count != 0 {
msg = basic.tprint(message, ..args);
}
run.failed = true;
if #compile_time {
CompileError(msg, loc = loc);
}
else {
WriteStderrLocation(loc);
WriteStderrString(": ", msg, "\n");
}
}
#scope_file
TestRun :: struct {
location: Source_Code_Location;
total_expects: s64;
total_ok: s64;
failed: bool;
}
SmallerPath :: (path: string) -> string {
p := path;
i := p.count - 1;
found_first_slash := false;
while i >= 0 {
if p[i] == "/" {
if found_first_slash {
i += 1;
break;
}
found_first_slash = true;
}
i -= 1;
}
if !found_first_slash {
p = strings.path_filename(path);
}
else {
p.count -= i;
p.data += i;
}
return p;
}
basic :: #import "Basic"; // @future
strings :: #import "String"; // @future
compiler :: #import "Compiler"; // @future