zig/test/stack_traces.zig
2025-10-29 06:20:50 -07:00

225 lines
6.5 KiB
Zig

pub fn addCases(cases: *@import("tests.zig").StackTracesContext) void {
cases.addCase(.{
.name = "simple panic",
.source =
\\pub fn main() void {
\\ foo();
\\}
\\fn foo() void {
\\ @panic("oh no");
\\}
\\
,
.unwind = .any,
.expect_panic = true,
.expect =
\\panic: oh no
\\source.zig:5:5: [address] in foo
\\ @panic("oh no");
\\ ^
\\source.zig:2:8: [address] in main
\\ foo();
\\ ^
\\
,
.expect_strip =
\\panic: oh no
\\???:?:?: [address] in source.foo
\\???:?:?: [address] in source.main
\\
,
});
cases.addCase(.{
.name = "simple panic with no unwind strategy",
.source =
\\pub fn main() void {
\\ foo();
\\}
\\fn foo() void {
\\ @panic("oh no");
\\}
\\
,
.unwind = .none,
.expect_panic = true,
.expect = "panic: oh no",
.expect_strip = "panic: oh no",
});
cases.addCase(.{
.name = "dump current trace",
.source =
\\pub fn main() void {
\\ foo(bar());
\\}
\\fn bar() void {
\\ qux(123);
\\}
\\fn foo(_: void) void {}
\\fn qux(x: u32) void {
\\ std.debug.dumpCurrentStackTrace(.{});
\\ _ = x;
\\}
\\const std = @import("std");
\\
,
.unwind = .safe,
.expect_panic = false,
.expect =
\\source.zig:9:36: [address] in qux
\\ std.debug.dumpCurrentStackTrace(.{});
\\ ^
\\source.zig:5:8: [address] in bar
\\ qux(123);
\\ ^
\\source.zig:2:12: [address] in main
\\ foo(bar());
\\ ^
\\
,
.expect_strip =
\\???:?:?: [address] in source.qux
\\???:?:?: [address] in source.bar
\\???:?:?: [address] in source.main
\\
,
});
cases.addCase(.{
.name = "dump current trace with no unwind strategy",
.source =
\\pub fn main() void {
\\ foo(bar());
\\}
\\fn bar() void {
\\ qux(123);
\\}
\\fn foo(_: void) void {}
\\fn qux(x: u32) void {
\\ std.debug.print("pre\n", .{});
\\ std.debug.dumpCurrentStackTrace(.{});
\\ std.debug.print("post\n", .{});
\\ _ = x;
\\}
\\const std = @import("std");
\\
,
.unwind = .no_safe,
.expect_panic = false,
.expect = "pre\npost\n",
.expect_strip = "pre\npost\n",
});
cases.addCase(.{
.name = "dump captured trace",
.source =
\\pub fn main() void {
\\ var stack_trace_buf: [8]usize = undefined;
\\ dumpIt(captureIt(&stack_trace_buf));
\\}
\\fn captureIt(buf: []usize) std.builtin.StackTrace {
\\ return captureItInner(buf);
\\}
\\fn dumpIt(st: std.builtin.StackTrace) void {
\\ std.debug.dumpStackTrace(st);
\\}
\\fn captureItInner(buf: []usize) std.builtin.StackTrace {
\\ return std.debug.captureCurrentStackTrace(.{}, buf);
\\}
\\const std = @import("std");
\\
,
.unwind = .safe,
.expect_panic = false,
.expect =
\\source.zig:12:46: [address] in captureItInner
\\ return std.debug.captureCurrentStackTrace(.{}, buf);
\\ ^
\\source.zig:6:26: [address] in captureIt
\\ return captureItInner(buf);
\\ ^
\\source.zig:3:22: [address] in main
\\ dumpIt(captureIt(&stack_trace_buf));
\\ ^
\\
,
.expect_strip =
\\???:?:?: [address] in source.captureItInner
\\???:?:?: [address] in source.captureIt
\\???:?:?: [address] in source.main
\\
,
});
cases.addCase(.{
.name = "dump captured trace with no unwind strategy",
.source =
\\pub fn main() void {
\\ var stack_trace_buf: [8]usize = undefined;
\\ dumpIt(captureIt(&stack_trace_buf));
\\}
\\fn captureIt(buf: []usize) std.builtin.StackTrace {
\\ return captureItInner(buf);
\\}
\\fn dumpIt(st: std.builtin.StackTrace) void {
\\ std.debug.dumpStackTrace(st);
\\}
\\fn captureItInner(buf: []usize) std.builtin.StackTrace {
\\ return std.debug.captureCurrentStackTrace(.{}, buf);
\\}
\\const std = @import("std");
\\
,
.unwind = .no_safe,
.expect_panic = false,
.expect = "(empty stack trace)\n",
.expect_strip = "(empty stack trace)\n",
});
cases.addCase(.{
.name = "dump captured trace on thread",
.source =
\\pub fn main() !void {
\\ var stack_trace_buf: [8]usize = undefined;
\\ const t = try std.Thread.spawn(.{}, threadMain, .{&stack_trace_buf});
\\ t.join();
\\}
\\fn threadMain(stack_trace_buf: []usize) void {
\\ dumpIt(captureIt(stack_trace_buf));
\\}
\\fn captureIt(buf: []usize) std.builtin.StackTrace {
\\ return captureItInner(buf);
\\}
\\fn dumpIt(st: std.builtin.StackTrace) void {
\\ std.debug.dumpStackTrace(st);
\\}
\\fn captureItInner(buf: []usize) std.builtin.StackTrace {
\\ return std.debug.captureCurrentStackTrace(.{}, buf);
\\}
\\const std = @import("std");
\\
,
.unwind = .safe,
.expect_panic = false,
.expect =
\\source.zig:16:46: [address] in captureItInner
\\ return std.debug.captureCurrentStackTrace(.{}, buf);
\\ ^
\\source.zig:10:26: [address] in captureIt
\\ return captureItInner(buf);
\\ ^
\\source.zig:7:22: [address] in threadMain
\\ dumpIt(captureIt(stack_trace_buf));
\\ ^
\\
,
.expect_strip =
\\???:?:?: [address] in source.captureItInner
\\???:?:?: [address] in source.captureIt
\\???:?:?: [address] in source.threadMain
\\
,
});
}