Files
zig/test/stack_traces.zig
T
Mason Remaley 94ff38af87 Separates error return traces from stack traces
Doesn't commit the changes to stage1, we can generate those at the end
once we're not making any more changes to it to avoid wasting storage.
2026-04-12 04:01:29 -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.debug.StackTrace {
\\ return captureItInner(buf);
\\}
\\fn dumpIt(st: *const std.debug.StackTrace) void {
\\ std.debug.dumpStackTrace(st);
\\}
\\fn captureItInner(buf: []usize) std.debug.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.debug.StackTrace {
\\ return captureItInner(buf);
\\}
\\fn dumpIt(st: *const std.debug.StackTrace) void {
\\ std.debug.dumpStackTrace(st);
\\}
\\fn captureItInner(buf: []usize) std.debug.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.debug.StackTrace {
\\ return captureItInner(buf);
\\}
\\fn dumpIt(st: *const std.debug.StackTrace) void {
\\ std.debug.dumpStackTrace(st);
\\}
\\fn captureItInner(buf: []usize) std.debug.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
\\
,
});
}