I see a lot of people give in to the temptation to abuse inline for
and write tests like this (real example from the standard library):
test "twos complement limit set" {
const test_types = [_]type{
u64,
i64,
u1,
i1,
u0,
i0,
u65,
i65,
};
inline for (test_types) |T| {
const int_info = @typeInfo(T).Int;
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.setTwosCompIntLimit(.max, int_info.signedness, int_info.bits);
const max: T = maxInt(T);
try testing.expect(max == try a.to(T));
try a.setTwosCompIntLimit(.min, int_info.signedness, int_info.bits);
const min: T = minInt(T);
try testing.expect(min == try a.to(T));
}
}
When a test failure happens, it looks like this:
Test [2213/2751] math.big.int_test.test.twos complement limit set... Segmentation fault at address 0x0
/home/andy/src/zig/lib/libc/musl/arch/i386/atomic_arch.h:83:2: 0x2187b56 in __stack_chk_fail (/home/andy/src/zig/lib/libc/musl/src/env/__stack_chk_fail.c)
__asm__ __volatile__( "hlt" : : : "memory" );
^
Unwind error at address `exe:0x2187b56` (error.AddressOutOfRange), trace may be incomplete
/home/andy/src/zig/lib/std/math/big/int.zig:2761:33: 0x1b691b0 in to__anon_55641 (test)
return self.toConst().to(T);
^
/home/andy/src/zig/lib/std/math/big/int_test.zig:310:43: 0x1b68b8a in test.twos complement limit set (test)
try testing.expect(max == try a.to(T));
^
/home/andy/src/zig/lib/compiler/test_runner.zig:158:25: 0xb89d2b in mainTerminal (test)
if (test_fn.func()) |_| {
^
/home/andy/src/zig/lib/compiler/test_runner.zig:35:28: 0xb37685 in main (test)
return mainTerminal();
^
/home/andy/src/zig/lib/std/start.zig:501:22: 0xb3710f in main (test)
root.main();
^
/home/andy/src/zig/lib/libc/musl/src/env/__libc_start_main.c:95:7: 0x2187890 in libc_start_main_stage2 (/home/andy/src/zig/lib/libc/musl/src/env/__libc_start_main.c)
exit(main(argc, argv, envp));
^
???:?:?: 0xff903d64 in ??? (???)
error: the following test command crashed:
/home/andy/src/zig/zig-cache/o/a15660423f74135612b38da4d3379840/test
Instead, I suggest to make a function call for each type:
test "twos complement limit set" {
try testTwosComplementLimit(u64);
try testTwosComplementLimit(i64);
try testTwosComplementLimit(u1);
try testTwosComplementLimit(i1);
try testTwosComplementLimit(u0);
try testTwosComplementLimit(i0);
try testTwosComplementLimit(u65);
try testTwosComplementLimit(i65);
}
fn testTwosComplementLimit(comptime T: type) !void {
const int_info = @typeInfo(T).Int;
var a = try Managed.init(testing.allocator);
defer a.deinit();
try a.setTwosCompIntLimit(.max, int_info.signedness, int_info.bits);
const max: T = maxInt(T);
try testing.expect(max == try a.to(T));
try a.setTwosCompIntLimit(.min, int_info.signedness, int_info.bits);
const min: T = minInt(T);
try testing.expect(min == try a.to(T));
}
Now the same test failure looks like this:
Test [2213/2751] math.big.int_test.test.twos complement limit set... Segmentation fault at address 0x0
/home/andy/src/zig/lib/libc/musl/arch/i386/atomic_arch.h:83:2: 0x21879b6 in __stack_chk_fail (/home/andy/src/zig/lib/libc/musl/src/env/__stack_chk_fail.c)
__asm__ __volatile__( "hlt" : : : "memory" );
^
Unwind error at address `exe:0x21879b6` (error.AddressOutOfRange), trace may be incomplete
/home/andy/src/zig/lib/std/math/big/int.zig:2761:33: 0x1b68c00 in to__anon_55649 (test)
return self.toConst().to(T);
^
/home/andy/src/zig/lib/std/math/big/int_test.zig:309:39: 0x1b689b4 in testTwosComplementLimit__anon_55648 (test)
try testing.expect(max == try a.to(T));
^
/home/andy/src/zig/lib/std/math/big/int_test.zig:297:32: 0x1b690ff in test.twos complement limit set (test)
try testTwosComplementLimit(u65);
^
/home/andy/src/zig/lib/compiler/test_runner.zig:158:25: 0xb89ebb in mainTerminal (test)
if (test_fn.func()) |_| {
^
/home/andy/src/zig/lib/compiler/test_runner.zig:35:28: 0xb37815 in main (test)
return mainTerminal();
^
/home/andy/src/zig/lib/std/start.zig:501:22: 0xb3729f in main (test)
root.main();
^
/home/andy/src/zig/lib/libc/musl/src/env/__libc_start_main.c:95:7: 0x21876f0 in libc_start_main_stage2 (/home/andy/src/zig/lib/libc/musl/src/env/__libc_start_main.c)
exit(main(argc, argv, envp));
^
???:?:?: 0xffbccd64 in ??? (???)
error: the following test command crashed:
/home/andy/src/zig/zig-cache/o/a15660423f74135612b38da4d3379840/test
Do you see the difference? We get a super helpful clue now, which is that it crashed on the u65
case.
And it’s fewer lines of code!
lib/std/math/big/int_test.zig | 40 +++++++++++++++++++---------------------
1 file changed, 19 insertions(+), 21 deletions(-)