| author | |
| committer | |
| log | 8b2949e372e615886b9087b06187878452421724 |
| tree | 69109053e156249712255bba6c292f3d7a2eb09c |
| parent | 0f1c478db329c4b91c3a34aed2d48e4cde059eff |
by explicitly listing out the combinations of parameters we would like
to check.5 files changed, 337 insertions(+), 250 deletions(-)
test/error_traces.zig+41-2| ... | @@ -1,7 +1,10 @@ | ... | @@ -1,7 +1,10 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const Context = @import("tests.zig").ErrorTracesContext; | ||
| 2 | 3 | ||
| 3 | pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.Os.Tag) void { | 4 | pub fn addCases(cases: *Context, params: *const Context.CaseParameters, target: *const std.Target) void { |
| 4 | cases.addCase(.{ | 5 | cases.addCase(.{ |
| 6 | .params = params, | ||
| 7 | .target = target, | ||
| 5 | .name = "return", | 8 | .name = "return", |
| 6 | .source = | 9 | .source = |
| 7 | \\pub fn main() !void { | 10 | \\pub fn main() !void { |
| ... | @@ -17,6 +20,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -17,6 +20,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 17 | }); | 20 | }); |
| 18 | 21 | ||
| 19 | cases.addCase(.{ | 22 | cases.addCase(.{ |
| 23 | .params = params, | ||
| 24 | .target = target, | ||
| 20 | .name = "try return", | 25 | .name = "try return", |
| 21 | .source = | 26 | .source = |
| 22 | \\fn foo() !void { | 27 | \\fn foo() !void { |
| ... | @@ -44,6 +49,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -44,6 +49,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 44 | }, | 49 | }, |
| 45 | }); | 50 | }); |
| 46 | cases.addCase(.{ | 51 | cases.addCase(.{ |
| 52 | .params = params, | ||
| 53 | .target = target, | ||
| 47 | .name = "non-error return pops error trace", | 54 | .name = "non-error return pops error trace", |
| 48 | .source = | 55 | .source = |
| 49 | \\fn bar() !void { | 56 | \\fn bar() !void { |
| ... | @@ -70,6 +77,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -70,6 +77,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 70 | }); | 77 | }); |
| 71 | 78 | ||
| 72 | cases.addCase(.{ | 79 | cases.addCase(.{ |
| 80 | .params = params, | ||
| 81 | .target = target, | ||
| 73 | .name = "continue in while loop", | 82 | .name = "continue in while loop", |
| 74 | .source = | 83 | .source = |
| 75 | \\fn foo() !void { | 84 | \\fn foo() !void { |
| ... | @@ -93,6 +102,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -93,6 +102,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 93 | }); | 102 | }); |
| 94 | 103 | ||
| 95 | cases.addCase(.{ | 104 | cases.addCase(.{ |
| 105 | .params = params, | ||
| 106 | .target = target, | ||
| 96 | .name = "for loop pops error return trace", | 107 | .name = "for loop pops error return trace", |
| 97 | .source = | 108 | .source = |
| 98 | \\fn foo() !void { return error.FooError; } | 109 | \\fn foo() !void { return error.FooError; } |
| ... | @@ -123,6 +134,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -123,6 +134,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 123 | }); | 134 | }); |
| 124 | 135 | ||
| 125 | cases.addCase(.{ | 136 | cases.addCase(.{ |
| 137 | .params = params, | ||
| 138 | .target = target, | ||
| 126 | .name = "implicit continue in for loop pops stale error return trace", | 139 | .name = "implicit continue in for loop pops stale error return trace", |
| 127 | .source = | 140 | .source = |
| 128 | \\fn foo() !void { return error.FooError; } | 141 | \\fn foo() !void { return error.FooError; } |
| ... | @@ -154,6 +167,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -154,6 +167,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 154 | }); | 167 | }); |
| 155 | 168 | ||
| 156 | cases.addCase(.{ | 169 | cases.addCase(.{ |
| 170 | .params = params, | ||
| 171 | .target = target, | ||
| 157 | .name = "while loop pops error return trace", | 172 | .name = "while loop pops error return trace", |
| 158 | .source = | 173 | .source = |
| 159 | \\fn foo() !void { return error.FooError; } | 174 | \\fn foo() !void { return error.FooError; } |
| ... | @@ -186,6 +201,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -186,6 +201,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 186 | }); | 201 | }); |
| 187 | 202 | ||
| 188 | cases.addCase(.{ | 203 | cases.addCase(.{ |
| 204 | .params = params, | ||
| 205 | .target = target, | ||
| 189 | .name = "implicit continue in while loop pops stale error return trace", | 206 | .name = "implicit continue in while loop pops stale error return trace", |
| 190 | .source = | 207 | .source = |
| 191 | \\fn foo() !void { return error.FooError; } | 208 | \\fn foo() !void { return error.FooError; } |
| ... | @@ -219,6 +236,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -219,6 +236,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 219 | }); | 236 | }); |
| 220 | 237 | ||
| 221 | cases.addCase(.{ | 238 | cases.addCase(.{ |
| 239 | .params = params, | ||
| 240 | .target = target, | ||
| 222 | .name = "try return + handled catch/if-else", | 241 | .name = "try return + handled catch/if-else", |
| 223 | .source = | 242 | .source = |
| 224 | \\fn foo() !void { | 243 | \\fn foo() !void { |
| ... | @@ -251,6 +270,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -251,6 +270,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 251 | }); | 270 | }); |
| 252 | 271 | ||
| 253 | cases.addCase(.{ | 272 | cases.addCase(.{ |
| 273 | .params = params, | ||
| 274 | .target = target, | ||
| 254 | .name = "break from inline loop pops error return trace", | 275 | .name = "break from inline loop pops error return trace", |
| 255 | .source = | 276 | .source = |
| 256 | \\fn foo() !void { return error.FooBar; } | 277 | \\fn foo() !void { return error.FooBar; } |
| ... | @@ -276,6 +297,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -276,6 +297,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 276 | }); | 297 | }); |
| 277 | 298 | ||
| 278 | cases.addCase(.{ | 299 | cases.addCase(.{ |
| 300 | .params = params, | ||
| 301 | .target = target, | ||
| 279 | .name = "catch and re-throw error", | 302 | .name = "catch and re-throw error", |
| 280 | .source = | 303 | .source = |
| 281 | \\fn foo() !void { | 304 | \\fn foo() !void { |
| ... | @@ -304,6 +327,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -304,6 +327,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 304 | }); | 327 | }); |
| 305 | 328 | ||
| 306 | cases.addCase(.{ | 329 | cases.addCase(.{ |
| 330 | .params = params, | ||
| 331 | .target = target, | ||
| 307 | .name = "errors stored in var do not contribute to error trace", | 332 | .name = "errors stored in var do not contribute to error trace", |
| 308 | .source = | 333 | .source = |
| 309 | \\fn foo() !void { | 334 | \\fn foo() !void { |
| ... | @@ -328,6 +353,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -328,6 +353,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 328 | }); | 353 | }); |
| 329 | 354 | ||
| 330 | cases.addCase(.{ | 355 | cases.addCase(.{ |
| 356 | .params = params, | ||
| 357 | .target = target, | ||
| 331 | .name = "error stored in const has trace preserved for duration of block", | 358 | .name = "error stored in const has trace preserved for duration of block", |
| 332 | .source = | 359 | .source = |
| 333 | \\fn foo() !void { return error.TheSkyIsFalling; } | 360 | \\fn foo() !void { return error.TheSkyIsFalling; } |
| ... | @@ -376,6 +403,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -376,6 +403,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 376 | }); | 403 | }); |
| 377 | 404 | ||
| 378 | cases.addCase(.{ | 405 | cases.addCase(.{ |
| 406 | .params = params, | ||
| 407 | .target = target, | ||
| 379 | .name = "error passed to function has its trace preserved for duration of the call", | 408 | .name = "error passed to function has its trace preserved for duration of the call", |
| 380 | .source = | 409 | .source = |
| 381 | \\pub fn expectError(expected_error: anyerror, actual_error: anyerror!void) !void { | 410 | \\pub fn expectError(expected_error: anyerror, actual_error: anyerror!void) !void { |
| ... | @@ -418,6 +447,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -418,6 +447,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 418 | }); | 447 | }); |
| 419 | 448 | ||
| 420 | cases.addCase(.{ | 449 | cases.addCase(.{ |
| 450 | .params = params, | ||
| 451 | .target = target, | ||
| 421 | .name = "try return from within catch", | 452 | .name = "try return from within catch", |
| 422 | .source = | 453 | .source = |
| 423 | \\fn foo() !void { | 454 | \\fn foo() !void { |
| ... | @@ -455,6 +486,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -455,6 +486,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 455 | }); | 486 | }); |
| 456 | 487 | ||
| 457 | cases.addCase(.{ | 488 | cases.addCase(.{ |
| 489 | .params = params, | ||
| 490 | .target = target, | ||
| 458 | .name = "try return from within if-else", | 491 | .name = "try return from within if-else", |
| 459 | .source = | 492 | .source = |
| 460 | \\fn foo() !void { | 493 | \\fn foo() !void { |
| ... | @@ -492,6 +525,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -492,6 +525,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 492 | }); | 525 | }); |
| 493 | 526 | ||
| 494 | cases.addCase(.{ | 527 | cases.addCase(.{ |
| 528 | .params = params, | ||
| 529 | .target = target, | ||
| 495 | .name = "try try return return", | 530 | .name = "try try return return", |
| 496 | .source = | 531 | .source = |
| 497 | \\fn foo() !void { | 532 | \\fn foo() !void { |
| ... | @@ -534,6 +569,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -534,6 +569,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 534 | }); | 569 | }); |
| 535 | 570 | ||
| 536 | cases.addCase(.{ | 571 | cases.addCase(.{ |
| 572 | .params = params, | ||
| 573 | .target = target, | ||
| 537 | .name = "error union switch with call operand", | 574 | .name = "error union switch with call operand", |
| 538 | .source = | 575 | .source = |
| 539 | \\pub fn main() !void { | 576 | \\pub fn main() !void { |
| ... | @@ -579,6 +616,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -579,6 +616,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 579 | }); | 616 | }); |
| 580 | 617 | ||
| 581 | cases.addCase(.{ | 618 | cases.addCase(.{ |
| 619 | .params = params, | ||
| 620 | .target = target, | ||
| 582 | .name = "trace through inline call", | 621 | .name = "trace through inline call", |
| 583 | // The main function has two inline calls to ensure | 622 | // The main function has two inline calls to ensure |
| 584 | // that inlinees in PDBs are properly deduplicated. | 623 | // that inlinees in PDBs are properly deduplicated. |
| ... | @@ -595,7 +634,7 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. | ... | @@ -595,7 +634,7 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 595 | \\} | 634 | \\} |
| 596 | , | 635 | , |
| 597 | .expect_error = "ThisIsSoSad", | 636 | .expect_error = "ThisIsSoSad", |
| 598 | .expect_trace = switch (os) { | 637 | .expect_trace = switch (target.os.tag) { |
| 599 | // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs, | 638 | // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs, |
| 600 | // so our expected result is slightly different for Windows than on other operating | 639 | // so our expected result is slightly different for Windows than on other operating |
| 601 | // systems. | 640 | // systems. |
test/src/ErrorTrace.zig+117-52| ... | @@ -1,11 +1,81 @@ | ... | @@ -1,11 +1,81 @@ |
| 1 | const ErrorTrace = @This(); | ||
| 2 | |||
| 3 | const builtin = @import("builtin"); | ||
| 4 | |||
| 5 | const std = @import("std"); | ||
| 6 | const Step = std.Build.Step; | ||
| 7 | const OptimizeMode = std.lang.Optimize; | ||
| 8 | const mem = std.mem; | ||
| 9 | |||
| 10 | const error_traces_cases = @import("../error_traces.zig"); | ||
| 11 | |||
| 1 | b: *std.Build, | 12 | b: *std.Build, |
| 2 | step: *Step, | 13 | step: *Step, |
| 3 | test_filters: []const []const u8, | 14 | test_filters: []const []const u8, |
| 4 | targets: []const std.Build.ResolvedTarget, | 15 | skip_non_native: bool, |
| 5 | optimize_modes: []const OptimizeMode, | 16 | optimize_modes: []const OptimizeMode, |
| 6 | convert_exe: *std.Build.Step.Compile, | 17 | convert_exe: *std.Build.Step.Compile, |
| 7 | 18 | ||
| 19 | pub const CaseParameters = @import("StackTrace.zig").CaseParameters; | ||
| 20 | |||
| 21 | const param_sets = [_]CaseParameters{ | ||
| 22 | .{}, | ||
| 23 | .{ | ||
| 24 | .link_libc = true, | ||
| 25 | }, | ||
| 26 | .{ | ||
| 27 | .use_llvm = true, | ||
| 28 | .use_lld = true, | ||
| 29 | }, | ||
| 30 | .{ | ||
| 31 | .pie = true, | ||
| 32 | }, | ||
| 33 | .{ | ||
| 34 | .target = .{ | ||
| 35 | .cpu_arch = .aarch64, | ||
| 36 | .os_tag = .windows, | ||
| 37 | .abi = .msvc, | ||
| 38 | }, | ||
| 39 | }, | ||
| 40 | .{ | ||
| 41 | .target = .{ | ||
| 42 | .cpu_arch = .x86_64, | ||
| 43 | .os_tag = .windows, | ||
| 44 | .abi = .gnu, | ||
| 45 | }, | ||
| 46 | }, | ||
| 47 | .{ | ||
| 48 | .target = .{ | ||
| 49 | .cpu_arch = .x86, | ||
| 50 | .os_tag = .windows, | ||
| 51 | .abi = .msvc, | ||
| 52 | }, | ||
| 53 | }, | ||
| 54 | .{ | ||
| 55 | .target = .{ | ||
| 56 | .cpu_arch = .aarch64, | ||
| 57 | .os_tag = .macos, | ||
| 58 | }, | ||
| 59 | }, | ||
| 60 | .{ | ||
| 61 | .target = .{ | ||
| 62 | .cpu_arch = .s390x, | ||
| 63 | .os_tag = .linux, | ||
| 64 | .abi = .none, | ||
| 65 | }, | ||
| 66 | }, | ||
| 67 | .{ | ||
| 68 | .target = .{ | ||
| 69 | .cpu_arch = .loongarch32, | ||
| 70 | .os_tag = .linux, | ||
| 71 | .abi = .none, | ||
| 72 | }, | ||
| 73 | }, | ||
| 74 | }; | ||
| 75 | |||
| 8 | pub const Case = struct { | 76 | pub const Case = struct { |
| 77 | params: *const CaseParameters, | ||
| 78 | target: *const std.Target, | ||
| 9 | name: []const u8, | 79 | name: []const u8, |
| 10 | source: []const u8, | 80 | source: []const u8, |
| 11 | expect_error: []const u8, | 81 | expect_error: []const u8, |
| ... | @@ -22,50 +92,47 @@ pub const Case = struct { | ... | @@ -22,50 +92,47 @@ pub const Case = struct { |
| 22 | pub const Backend = enum { llvm, selfhosted }; | 92 | pub const Backend = enum { llvm, selfhosted }; |
| 23 | }; | 93 | }; |
| 24 | 94 | ||
| 25 | pub fn addCase(self: *ErrorTrace, case: Case) void { | 95 | pub fn addCases(self: *ErrorTrace) void { |
| 26 | for (self.targets) |*target| { | 96 | const b = self.b; |
| 27 | const triple: ?[]const u8 = if (target.query.isNative()) null else t: { | 97 | |
| 28 | break :t target.query.zigTriple(self.b.graph.arena) catch @panic("OOM"); | 98 | for (&param_sets) |*params| { |
| 29 | }; | 99 | const resolved_target = b.resolveTargetQuery(params.target); |
| 30 | for (self.optimize_modes) |optimize| { | 100 | |
| 31 | self.addCaseConfig(case, target, triple, optimize, .llvm); | 101 | if (self.skip_non_native and !resolved_target.query.isNative()) continue; |
| 32 | } | 102 | |
| 33 | if (shouldTestNonLlvm(&target.result)) { | 103 | // To avoid redundant testing, skip cross-compilation targets matching the host. |
| 34 | for (self.optimize_modes) |optimize| { | 104 | if (resolved_target.result.os.tag == builtin.target.os.tag and |
| 35 | self.addCaseConfig(case, target, triple, optimize, .selfhosted); | 105 | resolved_target.result.cpu.arch == builtin.target.cpu.arch) |
| 36 | } | 106 | { |
| 107 | continue; | ||
| 37 | } | 108 | } |
| 38 | } | ||
| 39 | } | ||
| 40 | 109 | ||
| 41 | fn shouldTestNonLlvm(target: *const std.Target) bool { | 110 | for (self.optimize_modes) |optimize| { |
| 42 | if (comptime builtin.cpu.arch.endian() == .big) return false; // https://github.com/ziglang/zig/issues/25961 | 111 | if (optimize == params.optimize) break; |
| 43 | return switch (target.cpu.arch) { | 112 | } else return; |
| 44 | .x86_64 => switch (target.ofmt) { | 113 | |
| 45 | .elf => !target.os.tag.isBSD() and target.os.tag != .illumos, | 114 | error_traces_cases.addCases(self, params, &resolved_target.result); |
| 46 | else => false, | 115 | } |
| 47 | }, | ||
| 48 | else => false, | ||
| 49 | }; | ||
| 50 | } | 116 | } |
| 51 | 117 | ||
| 52 | fn addCaseConfig( | 118 | /// Called from test/error_traces.zig |
| 53 | self: *ErrorTrace, | 119 | pub fn addCase(self: *ErrorTrace, case: Case) void { |
| 54 | case: Case, | ||
| 55 | target: *const std.Build.ResolvedTarget, | ||
| 56 | triple: ?[]const u8, | ||
| 57 | optimize: OptimizeMode, | ||
| 58 | backend: Case.Backend, | ||
| 59 | ) void { | ||
| 60 | const b = self.b; | 120 | const b = self.b; |
| 121 | const params = case.params; | ||
| 122 | const target = case.target; | ||
| 123 | const target_query = params.target; | ||
| 124 | |||
| 125 | const triple: ?[]const u8 = if (target_query.isNative()) null else t: { | ||
| 126 | break :t target_query.zigTriple(self.b.graph.arena) catch @panic("OOM"); | ||
| 127 | }; | ||
| 61 | 128 | ||
| 62 | const error_tracing: bool = tracing: { | 129 | const error_tracing: bool = tracing: { |
| 63 | if (optimize == .debug) break :tracing true; | 130 | if (params.optimize == .debug) break :tracing true; |
| 64 | if (backend != .llvm) break :tracing true; | 131 | if (params.use_llvm == false) break :tracing true; |
| 65 | if (optimize == .small) break :tracing false; | 132 | if (params.optimize == .small) break :tracing false; |
| 66 | for (case.disable_trace_optimized) |disable| { | 133 | for (case.disable_trace_optimized) |disable| { |
| 67 | const d_arch, const d_os = disable; | 134 | const d_arch, const d_os = disable; |
| 68 | if (target.result.cpu.arch == d_arch and target.result.os.tag == d_os) { | 135 | if (target.cpu.arch == d_arch and target.os.tag == d_os) { |
| 69 | // This particular configuration cannot do error tracing in optimized LLVM builds. | 136 | // This particular configuration cannot do error tracing in optimized LLVM builds. |
| 70 | break :tracing false; | 137 | break :tracing false; |
| 71 | } | 138 | } |
| ... | @@ -73,12 +140,19 @@ fn addCaseConfig( | ... | @@ -73,12 +140,19 @@ fn addCaseConfig( |
| 73 | break :tracing true; | 140 | break :tracing true; |
| 74 | }; | 141 | }; |
| 75 | 142 | ||
| 76 | const annotated_case_name = b.fmt("check {s} ({s}{s}{s} {s})", .{ | 143 | const backend_string = if (params.use_llvm == true) |
| 144 | "-llvm" | ||
| 145 | else if (params.use_llvm == false) | ||
| 146 | "-selfhosted" | ||
| 147 | else | ||
| 148 | ""; | ||
| 149 | |||
| 150 | const annotated_case_name = b.fmt("check {s} ({s}{s}{t}{s})", .{ | ||
| 77 | case.name, | 151 | case.name, |
| 78 | triple orelse "", | 152 | triple orelse "", |
| 79 | if (triple != null) " " else "", | 153 | if (triple != null) " " else "", |
| 80 | @tagName(optimize), | 154 | params.optimize, |
| 81 | @tagName(backend), | 155 | backend_string, |
| 82 | }); | 156 | }); |
| 83 | if (self.test_filters.len > 0) { | 157 | if (self.test_filters.len > 0) { |
| 84 | for (self.test_filters) |test_filter| { | 158 | for (self.test_filters) |test_filter| { |
| ... | @@ -92,15 +166,13 @@ fn addCaseConfig( | ... | @@ -92,15 +166,13 @@ fn addCaseConfig( |
| 92 | .name = "test", | 166 | .name = "test", |
| 93 | .root_module = b.createModule(.{ | 167 | .root_module = b.createModule(.{ |
| 94 | .root_source_file = source_zig, | 168 | .root_source_file = source_zig, |
| 95 | .optimize = optimize, | 169 | .optimize = params.optimize, |
| 96 | .target = target.*, | 170 | .target = .{ .result = target.*, .query = target_query }, |
| 97 | .error_tracing = error_tracing, | 171 | .error_tracing = error_tracing, |
| 98 | .strip = false, | 172 | .strip = false, |
| 99 | }), | 173 | }), |
| 100 | .use_llvm = switch (backend) { | 174 | .use_llvm = params.use_llvm, |
| 101 | .llvm => true, | 175 | .use_lld = params.use_lld, |
| 102 | .selfhosted => false, | ||
| 103 | }, | ||
| 104 | }); | 176 | }); |
| 105 | exe.bundle_ubsan_rt = false; | 177 | exe.bundle_ubsan_rt = false; |
| 106 | 178 | ||
| ... | @@ -124,10 +196,3 @@ fn addCaseConfig( | ... | @@ -124,10 +196,3 @@ fn addCaseConfig( |
| 124 | 196 | ||
| 125 | self.step.dependOn(&check_run.step); | 197 | self.step.dependOn(&check_run.step); |
| 126 | } | 198 | } |
| 127 | |||
| 128 | const ErrorTrace = @This(); | ||
| 129 | const std = @import("std"); | ||
| 130 | const builtin = @import("builtin"); | ||
| 131 | const Step = std.Build.Step; | ||
| 132 | const OptimizeMode = std.builtin.OptimizeMode; | ||
| 133 | const mem = std.mem; |
test/src/StackTrace.zig+146-86| ... | @@ -4,16 +4,88 @@ const builtin = @import("builtin"); | ... | @@ -4,16 +4,88 @@ const builtin = @import("builtin"); |
| 4 | 4 | ||
| 5 | const std = @import("std"); | 5 | const std = @import("std"); |
| 6 | const Step = std.Build.Step; | 6 | const Step = std.Build.Step; |
| 7 | const OptimizeMode = std.lang.OptimizeMode; | 7 | const OptimizeMode = std.lang.Optimize; |
| 8 | const mem = std.mem; | 8 | const mem = std.mem; |
| 9 | 9 | ||
| 10 | const stack_traces_cases = @import("../stack_traces.zig"); | ||
| 11 | |||
| 10 | b: *std.Build, | 12 | b: *std.Build, |
| 11 | step: *Step, | 13 | step: *Step, |
| 12 | test_filters: []const []const u8, | 14 | test_filters: []const []const u8, |
| 13 | targets: []const std.Build.ResolvedTarget, | 15 | skip_non_native: bool, |
| 14 | convert_exe: *std.Build.Step.Compile, | 16 | convert_exe: *std.Build.Step.Compile, |
| 15 | 17 | ||
| 18 | pub const CaseParameters = struct { | ||
| 19 | target: std.Target.Query = .{}, | ||
| 20 | optimize: std.builtin.OptimizeMode = .debug, | ||
| 21 | link_libc: ?bool = null, | ||
| 22 | use_llvm: ?bool = null, | ||
| 23 | use_lld: ?bool = null, | ||
| 24 | pie: ?bool = null, | ||
| 25 | /// To enable this coverage, one of two things needs to happen: | ||
| 26 | /// * The compiler needs to gain the ability to strip only debug info (not symbols) | ||
| 27 | /// * `std.Build.Step.ObjCopy` needs to be un-regressed | ||
| 28 | strip: ?bool = false, | ||
| 29 | }; | ||
| 30 | |||
| 31 | const param_sets = [_]CaseParameters{ | ||
| 32 | .{}, | ||
| 33 | .{ | ||
| 34 | .link_libc = true, | ||
| 35 | }, | ||
| 36 | .{ | ||
| 37 | .use_llvm = true, | ||
| 38 | .use_lld = true, | ||
| 39 | }, | ||
| 40 | .{ | ||
| 41 | .pie = true, | ||
| 42 | }, | ||
| 43 | .{ | ||
| 44 | .target = .{ | ||
| 45 | .cpu_arch = .aarch64, | ||
| 46 | .os_tag = .windows, | ||
| 47 | .abi = .msvc, | ||
| 48 | }, | ||
| 49 | }, | ||
| 50 | .{ | ||
| 51 | .target = .{ | ||
| 52 | .cpu_arch = .x86_64, | ||
| 53 | .os_tag = .windows, | ||
| 54 | .abi = .gnu, | ||
| 55 | }, | ||
| 56 | }, | ||
| 57 | .{ | ||
| 58 | .target = .{ | ||
| 59 | .cpu_arch = .x86, | ||
| 60 | .os_tag = .windows, | ||
| 61 | .abi = .msvc, | ||
| 62 | }, | ||
| 63 | }, | ||
| 64 | .{ | ||
| 65 | .target = .{ | ||
| 66 | .cpu_arch = .aarch64, | ||
| 67 | .os_tag = .macos, | ||
| 68 | }, | ||
| 69 | }, | ||
| 70 | .{ | ||
| 71 | .target = .{ | ||
| 72 | .cpu_arch = .s390x, | ||
| 73 | .os_tag = .linux, | ||
| 74 | .abi = .none, | ||
| 75 | }, | ||
| 76 | }, | ||
| 77 | .{ | ||
| 78 | .target = .{ | ||
| 79 | .cpu_arch = .loongarch32, | ||
| 80 | .os_tag = .linux, | ||
| 81 | .abi = .none, | ||
| 82 | }, | ||
| 83 | }, | ||
| 84 | }; | ||
| 85 | |||
| 16 | const Config = struct { | 86 | const Config = struct { |
| 87 | params: *const CaseParameters, | ||
| 88 | target: *const std.Target, | ||
| 17 | name: []const u8, | 89 | name: []const u8, |
| 18 | source: []const u8, | 90 | source: []const u8, |
| 19 | /// Whether this test case expects to have unwind tables / frame pointers. | 91 | /// Whether this test case expects to have unwind tables / frame pointers. |
| ... | @@ -35,42 +107,37 @@ const Config = struct { | ... | @@ -35,42 +107,37 @@ const Config = struct { |
| 35 | expect_strip: []const u8, | 107 | expect_strip: []const u8, |
| 36 | }; | 108 | }; |
| 37 | 109 | ||
| 38 | pub fn addCase(self: *StackTrace, config: Config) void { | 110 | pub fn addCases(self: *StackTrace) void { |
| 39 | for (self.targets) |*target| { | 111 | const b = self.b; |
| 40 | addCaseTarget( | 112 | |
| 41 | self, | 113 | for (&param_sets) |*params| { |
| 42 | config, | 114 | const resolved_target = b.resolveTargetQuery(params.target); |
| 43 | target, | 115 | |
| 44 | if (target.query.isNative()) null else t: { | 116 | if (self.skip_non_native and !resolved_target.query.isNative()) continue; |
| 45 | break :t target.query.zigTriple(self.b.graph.arena) catch @panic("OOM"); | 117 | |
| 46 | }, | 118 | // To avoid redundant testing, skip cross-compilation targets matching the host. |
| 47 | ); | 119 | if (resolved_target.result.os.tag == builtin.target.os.tag and |
| 120 | resolved_target.result.cpu.arch == builtin.target.cpu.arch) | ||
| 121 | { | ||
| 122 | continue; | ||
| 123 | } | ||
| 124 | |||
| 125 | stack_traces_cases.addCases(self, params, &resolved_target.result); | ||
| 48 | } | 126 | } |
| 49 | } | 127 | } |
| 50 | fn addCaseTarget( | 128 | |
| 51 | self: *StackTrace, | 129 | /// Called from test/stack_traces.zig |
| 52 | config: Config, | 130 | pub fn addCase(self: *StackTrace, config: Config) void { |
| 53 | target: *const std.Build.ResolvedTarget, | 131 | const params = config.params; |
| 54 | triple: ?[]const u8, | 132 | const target = config.target; |
| 55 | ) void { | 133 | const target_query = config.params.target; |
| 56 | const both_backends = b: { | 134 | |
| 57 | if (builtin.cpu.arch.endian() == .big) break :b false; // https://codeberg.org/ziglang/zig/issues/31522 | 135 | const triple: ?[]const u8 = if (target_query.isNative()) null else t: { |
| 58 | break :b switch (target.result.cpu.arch) { | 136 | break :t target_query.zigTriple(self.b.graph.arena) catch @panic("OOM"); |
| 59 | .x86_64 => switch (target.result.ofmt) { | ||
| 60 | .elf => !target.result.os.tag.isBSD() and target.result.os.tag != .illumos, | ||
| 61 | else => false, | ||
| 62 | }, | ||
| 63 | else => false, | ||
| 64 | }; | ||
| 65 | }; | ||
| 66 | const both_pie = switch (target.result.os.tag) { | ||
| 67 | .fuchsia => false, | ||
| 68 | else => true, | ||
| 69 | }; | 137 | }; |
| 70 | const both_libc = !std.os.targetRequiresLibC(&target.result); | ||
| 71 | 138 | ||
| 72 | // See `std.debug.StackIterator.fp_usability` logic. | 139 | // See `std.debug.StackIterator.fp_usability` logic. |
| 73 | const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.result.cpu.arch) { | 140 | const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.cpu.arch) { |
| 74 | .alpha, | 141 | .alpha, |
| 75 | .csky, | 142 | .csky, |
| 76 | .microblaze, | 143 | .microblaze, |
| ... | @@ -92,20 +159,15 @@ fn addCaseTarget( | ... | @@ -92,20 +159,15 @@ fn addCaseTarget( |
| 92 | .sparc, | 159 | .sparc, |
| 93 | .sparc64, | 160 | .sparc64, |
| 94 | => .ideal, | 161 | => .ideal, |
| 95 | .aarch64 => if (target.result.os.tag.isDarwin()) .safe else .unsafe, | 162 | .aarch64 => if (target.os.tag.isDarwin()) .safe else .unsafe, |
| 96 | else => .unsafe, | 163 | else => .unsafe, |
| 97 | }; | 164 | }; |
| 98 | const supports_unwind_tables = switch (target.result.os.tag) { | 165 | const supports_unwind_tables = switch (target.os.tag) { |
| 99 | // x86-windows just has no way to do stack unwinding other then using frame pointers. | 166 | // x86-windows just has no way to do stack unwinding other then using frame pointers. |
| 100 | .windows => target.result.cpu.arch != .x86, | 167 | .windows => target.cpu.arch != .x86, |
| 101 | else => true, | 168 | else => true, |
| 102 | }; | 169 | }; |
| 103 | 170 | ||
| 104 | const use_llvm_vals: []const bool = if (both_backends) &.{ true, false } else &.{true}; | ||
| 105 | const pie_vals: []const ?bool = if (both_pie) &.{ true, false } else &.{null}; | ||
| 106 | const link_libc_vals: []const ?bool = if (both_libc) &.{ true, false } else &.{null}; | ||
| 107 | const strip_debug_vals: []const bool = &.{ true, false }; | ||
| 108 | |||
| 109 | const UnwindInfo = packed struct(u2) { | 171 | const UnwindInfo = packed struct(u2) { |
| 110 | tables: bool, | 172 | tables: bool, |
| 111 | fp: bool, | 173 | fp: bool, |
| ... | @@ -135,43 +197,33 @@ fn addCaseTarget( | ... | @@ -135,43 +197,33 @@ fn addCaseTarget( |
| 135 | }, | 197 | }, |
| 136 | }; | 198 | }; |
| 137 | 199 | ||
| 138 | for (use_llvm_vals) |use_llvm| { | 200 | for (unwind_info_vals) |unwind_info| { |
| 139 | for (pie_vals) |pie| { | 201 | if (unwind_info.tables and !supports_unwind_tables) continue; |
| 140 | for (link_libc_vals) |link_libc| { | 202 | const strip = params.strip orelse switch (params.optimize) { |
| 141 | for (strip_debug_vals) |strip_debug| { | 203 | .debug, .fast, .safe => false, |
| 142 | for (unwind_info_vals) |unwind_info| { | 204 | .small => true, |
| 143 | if (unwind_info.tables and !supports_unwind_tables) continue; | 205 | }; |
| 144 | self.addCaseInstance( | 206 | self.addCaseInstance( |
| 145 | target, | 207 | .{ .result = target.*, .query = target_query }, |
| 146 | triple, | 208 | triple, |
| 147 | config.name, | 209 | config.name, |
| 148 | config.source, | 210 | config.source, |
| 149 | use_llvm, | 211 | params, |
| 150 | pie, | 212 | !unwind_info.tables and supports_unwind_tables, |
| 151 | link_libc, | 213 | !unwind_info.fp, |
| 152 | strip_debug, | 214 | config.expect_panic, |
| 153 | !unwind_info.tables and supports_unwind_tables, | 215 | if (strip) config.expect_strip else config.expect, |
| 154 | !unwind_info.fp, | 216 | ); |
| 155 | config.expect_panic, | ||
| 156 | if (strip_debug) config.expect_strip else config.expect, | ||
| 157 | ); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | } | ||
| 161 | } | ||
| 162 | } | 217 | } |
| 163 | } | 218 | } |
| 164 | 219 | ||
| 165 | fn addCaseInstance( | 220 | fn addCaseInstance( |
| 166 | self: *StackTrace, | 221 | self: *StackTrace, |
| 167 | target: *const std.Build.ResolvedTarget, | 222 | resolved_target: std.Build.ResolvedTarget, |
| 168 | triple: ?[]const u8, | 223 | triple: ?[]const u8, |
| 169 | name: []const u8, | 224 | name: []const u8, |
| 170 | source: []const u8, | 225 | source: []const u8, |
| 171 | use_llvm: bool, | 226 | params: *const CaseParameters, |
| 172 | pie: ?bool, | ||
| 173 | link_libc: ?bool, | ||
| 174 | strip_debug: bool, | ||
| 175 | strip_unwind: bool, | 227 | strip_unwind: bool, |
| 176 | omit_frame_pointer: bool, | 228 | omit_frame_pointer: bool, |
| 177 | expect_panic: bool, | 229 | expect_panic: bool, |
| ... | @@ -179,13 +231,6 @@ fn addCaseInstance( | ... | @@ -179,13 +231,6 @@ fn addCaseInstance( |
| 179 | ) void { | 231 | ) void { |
| 180 | const b = self.b; | 232 | const b = self.b; |
| 181 | 233 | ||
| 182 | if (strip_debug) { | ||
| 183 | // To enable this coverage, one of two things needs to happen: | ||
| 184 | // * The compiler needs to gain the ability to strip only debug info (not symbols) | ||
| 185 | // * `std.Build.Step.ObjCopy` needs to be un-regressed | ||
| 186 | return; | ||
| 187 | } | ||
| 188 | |||
| 189 | if (strip_unwind) { | 234 | if (strip_unwind) { |
| 190 | // To enable this coverage, `std.Build.Step.ObjCopy` needs to be un-regressed and gain the | 235 | // To enable this coverage, `std.Build.Step.ObjCopy` needs to be un-regressed and gain the |
| 191 | // ability to remove individual sections. `-fno-unwind-tables` is insufficient because it | 236 | // ability to remove individual sections. `-fno-unwind-tables` is insufficient because it |
| ... | @@ -196,14 +241,28 @@ fn addCaseInstance( | ... | @@ -196,14 +241,28 @@ fn addCaseInstance( |
| 196 | return; | 241 | return; |
| 197 | } | 242 | } |
| 198 | 243 | ||
| 244 | const backend_string = if (params.use_llvm == true) | ||
| 245 | " llvm" | ||
| 246 | else if (params.use_llvm == false) | ||
| 247 | " selfhosted" | ||
| 248 | else | ||
| 249 | ""; | ||
| 250 | |||
| 251 | const strip_string = if (params.strip == true) | ||
| 252 | " strip" | ||
| 253 | else if (params.strip == false) | ||
| 254 | " unstripped" | ||
| 255 | else | ||
| 256 | ""; | ||
| 257 | |||
| 199 | const annotated_case_name = b.fmt("check {s} ({s}{s}{s}{s}{s}{s}{s}{s})", .{ | 258 | const annotated_case_name = b.fmt("check {s} ({s}{s}{s}{s}{s}{s}{s}{s})", .{ |
| 200 | name, | 259 | name, |
| 201 | triple orelse "", | 260 | triple orelse "", |
| 202 | if (triple != null) " " else "", | 261 | if (triple != null) " " else "", |
| 203 | if (use_llvm) "llvm" else "selfhosted", | 262 | backend_string, |
| 204 | if (pie == true) " pie" else "", | 263 | if (params.pie == true) " pie" else "", |
| 205 | if (link_libc == true) " libc" else "", | 264 | if (params.link_libc == true) " libc" else "", |
| 206 | if (strip_debug) " strip" else "", | 265 | strip_string, |
| 207 | if (strip_unwind) " no_unwind" else "", | 266 | if (strip_unwind) " no_unwind" else "", |
| 208 | if (omit_frame_pointer) " no_fp" else "", | 267 | if (omit_frame_pointer) " no_fp" else "", |
| 209 | }); | 268 | }); |
| ... | @@ -220,16 +279,17 @@ fn addCaseInstance( | ... | @@ -220,16 +279,17 @@ fn addCaseInstance( |
| 220 | .root_module = b.createModule(.{ | 279 | .root_module = b.createModule(.{ |
| 221 | .root_source_file = source_zig, | 280 | .root_source_file = source_zig, |
| 222 | .optimize = .Debug, | 281 | .optimize = .Debug, |
| 223 | .target = target.*, | 282 | .target = resolved_target, |
| 224 | .omit_frame_pointer = omit_frame_pointer, | 283 | .omit_frame_pointer = omit_frame_pointer, |
| 225 | .link_libc = link_libc, | 284 | .link_libc = params.link_libc, |
| 226 | .unwind_tables = if (strip_unwind) .none else null, | 285 | .unwind_tables = if (strip_unwind) .none else null, |
| 227 | // make panics single-threaded so that they don't include a thread ID | 286 | // make panics single-threaded so that they don't include a thread ID |
| 228 | .single_threaded = expect_panic, | 287 | .single_threaded = expect_panic, |
| 229 | }), | 288 | }), |
| 230 | .use_llvm = use_llvm, | 289 | .use_llvm = params.use_llvm, |
| 290 | .use_lld = params.use_lld, | ||
| 231 | }); | 291 | }); |
| 232 | exe.pie = pie; | 292 | exe.pie = params.pie; |
| 233 | exe.bundle_ubsan_rt = false; | 293 | exe.bundle_ubsan_rt = false; |
| 234 | 294 | ||
| 235 | const run = b.addRunArtifact(exe); | 295 | const run = b.addRunArtifact(exe); |
| ... | @@ -238,7 +298,7 @@ fn addCaseInstance( | ... | @@ -238,7 +298,7 @@ fn addCaseInstance( |
| 238 | run.setEnvironmentVariable("NO_COLOR", "1"); | 298 | run.setEnvironmentVariable("NO_COLOR", "1"); |
| 239 | run.addCheck(.{ .expect_term = term: { | 299 | run.addCheck(.{ .expect_term = term: { |
| 240 | if (!expect_panic) break :term .{ .exited = 0 }; | 300 | if (!expect_panic) break :term .{ .exited = 0 }; |
| 241 | if (target.result.os.tag == .windows) break :term .{ .exited = 3 }; | 301 | if (resolved_target.result.os.tag == .windows) break :term .{ .exited = 3 }; |
| 242 | break :term .{ .signal = @fromBackingInt(@intCast(6)) }; | 302 | break :term .{ .signal = @fromBackingInt(@intCast(6)) }; |
| 243 | } }); | 303 | } }); |
| 244 | run.expectStdOutEqual(""); | 304 | run.expectStdOutEqual(""); |
test/stack_traces.zig+24-5| ... | @@ -1,7 +1,10 @@ | ... | @@ -1,7 +1,10 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const Context = @import("tests.zig").StackTracesContext; | ||
| 2 | 3 | ||
| 3 | pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.Os.Tag) void { | 4 | pub fn addCases(cases: *Context, params: *const Context.CaseParameters, target: *const std.Target) void { |
| 4 | cases.addCase(.{ | 5 | cases.addCase(.{ |
| 6 | .params = params, | ||
| 7 | .target = target, | ||
| 5 | .name = "simple panic", | 8 | .name = "simple panic", |
| 6 | .source = | 9 | .source = |
| 7 | \\pub fn main() void { | 10 | \\pub fn main() void { |
| ... | @@ -33,6 +36,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -33,6 +36,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 33 | }); | 36 | }); |
| 34 | 37 | ||
| 35 | cases.addCase(.{ | 38 | cases.addCase(.{ |
| 39 | .params = params, | ||
| 40 | .target = target, | ||
| 36 | .name = "simple panic with no unwind strategy", | 41 | .name = "simple panic with no unwind strategy", |
| 37 | .source = | 42 | .source = |
| 38 | \\pub fn main() void { | 43 | \\pub fn main() void { |
| ... | @@ -50,6 +55,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -50,6 +55,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 50 | }); | 55 | }); |
| 51 | 56 | ||
| 52 | cases.addCase(.{ | 57 | cases.addCase(.{ |
| 58 | .params = params, | ||
| 59 | .target = target, | ||
| 53 | .name = "dump current trace", | 60 | .name = "dump current trace", |
| 54 | .source = | 61 | .source = |
| 55 | \\pub fn main() void { | 62 | \\pub fn main() void { |
| ... | @@ -89,6 +96,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -89,6 +96,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 89 | }); | 96 | }); |
| 90 | 97 | ||
| 91 | cases.addCase(.{ | 98 | cases.addCase(.{ |
| 99 | .params = params, | ||
| 100 | .target = target, | ||
| 92 | .name = "dump current trace with no unwind strategy", | 101 | .name = "dump current trace with no unwind strategy", |
| 93 | .source = | 102 | .source = |
| 94 | \\pub fn main() void { | 103 | \\pub fn main() void { |
| ... | @@ -114,6 +123,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -114,6 +123,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 114 | }); | 123 | }); |
| 115 | 124 | ||
| 116 | cases.addCase(.{ | 125 | cases.addCase(.{ |
| 126 | .params = params, | ||
| 127 | .target = target, | ||
| 117 | .name = "dump captured trace", | 128 | .name = "dump captured trace", |
| 118 | .source = | 129 | .source = |
| 119 | \\pub fn main() void { | 130 | \\pub fn main() void { |
| ... | @@ -155,6 +166,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -155,6 +166,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 155 | }); | 166 | }); |
| 156 | 167 | ||
| 157 | cases.addCase(.{ | 168 | cases.addCase(.{ |
| 169 | .params = params, | ||
| 170 | .target = target, | ||
| 158 | .name = "dump captured trace with no unwind strategy", | 171 | .name = "dump captured trace with no unwind strategy", |
| 159 | .source = | 172 | .source = |
| 160 | \\pub fn main() void { | 173 | \\pub fn main() void { |
| ... | @@ -180,6 +193,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -180,6 +193,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 180 | }); | 193 | }); |
| 181 | 194 | ||
| 182 | cases.addCase(.{ | 195 | cases.addCase(.{ |
| 196 | .params = params, | ||
| 197 | .target = target, | ||
| 183 | .name = "dump captured trace on thread", | 198 | .name = "dump captured trace on thread", |
| 184 | .source = | 199 | .source = |
| 185 | \\pub fn main() !void { | 200 | \\pub fn main() !void { |
| ... | @@ -225,6 +240,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -225,6 +240,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 225 | }); | 240 | }); |
| 226 | 241 | ||
| 227 | cases.addCase(.{ | 242 | cases.addCase(.{ |
| 243 | .params = params, | ||
| 244 | .target = target, | ||
| 228 | .name = "simple inline panic", | 245 | .name = "simple inline panic", |
| 229 | // The main function has two inline calls to ensure | 246 | // The main function has two inline calls to ensure |
| 230 | // that inlinees in PDBs are properly deduplicated. | 247 | // that inlinees in PDBs are properly deduplicated. |
| ... | @@ -240,7 +257,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -240,7 +257,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 240 | , | 257 | , |
| 241 | .unwind = .any, | 258 | .unwind = .any, |
| 242 | .expect_panic = true, | 259 | .expect_panic = true, |
| 243 | .expect = switch (os) { | 260 | .expect = switch (target.os.tag) { |
| 244 | // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs, | 261 | // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs, |
| 245 | // so the first location has only a row. | 262 | // so the first location has only a row. |
| 246 | .windows => | 263 | .windows => |
| ... | @@ -262,7 +279,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -262,7 +279,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 262 | \\ ^ | 279 | \\ ^ |
| 263 | , | 280 | , |
| 264 | }, | 281 | }, |
| 265 | .expect_strip = switch (os) { | 282 | .expect_strip = switch (target.os.tag) { |
| 266 | .windows => | 283 | .windows => |
| 267 | \\panic: oh no | 284 | \\panic: oh no |
| 268 | \\???:?:?: [address] in source.foo | 285 | \\???:?:?: [address] in source.foo |
| ... | @@ -279,6 +296,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -279,6 +296,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 279 | 296 | ||
| 280 | // Make sure all inline calls are resolved and in the right order! | 297 | // Make sure all inline calls are resolved and in the right order! |
| 281 | cases.addCase(.{ | 298 | cases.addCase(.{ |
| 299 | .params = params, | ||
| 300 | .target = target, | ||
| 282 | .name = "nested inline panic", | 301 | .name = "nested inline panic", |
| 283 | .source = | 302 | .source = |
| 284 | \\pub fn main() void { | 303 | \\pub fn main() void { |
| ... | @@ -298,7 +317,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -298,7 +317,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 298 | .unwind = .any, | 317 | .unwind = .any, |
| 299 | .expect_panic = true, | 318 | .expect_panic = true, |
| 300 | // This switch serves a similar purpose as in "inline panic". | 319 | // This switch serves a similar purpose as in "inline panic". |
| 301 | .expect = switch (os) { | 320 | .expect = switch (target.os.tag) { |
| 302 | .windows => | 321 | .windows => |
| 303 | \\panic: oh no | 322 | \\panic: oh no |
| 304 | \\source.zig:11: [address] in baz | 323 | \\source.zig:11: [address] in baz |
| ... | @@ -322,7 +341,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. | ... | @@ -322,7 +341,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 322 | \\ ^ | 341 | \\ ^ |
| 323 | , | 342 | , |
| 324 | }, | 343 | }, |
| 325 | .expect_strip = switch (os) { | 344 | .expect_strip = switch (target.os.tag) { |
| 326 | .windows => | 345 | .windows => |
| 327 | \\panic: oh no | 346 | \\panic: oh no |
| 328 | \\???:?:?: [address] in baz | 347 | \\???:?:?: [address] in baz |
test/tests.zig+9-105| ... | @@ -6,8 +6,6 @@ const OptimizeMode = std.builtin.OptimizeMode; | ... | @@ -6,8 +6,6 @@ const OptimizeMode = std.builtin.OptimizeMode; |
| 6 | const Step = std.Build.Step; | 6 | const Step = std.Build.Step; |
| 7 | 7 | ||
| 8 | // Cases | 8 | // Cases |
| 9 | const error_traces = @import("error_traces.zig"); | ||
| 10 | const stack_traces = @import("stack_traces.zig"); | ||
| 11 | const llvm_ir = @import("llvm_ir.zig"); | 9 | const llvm_ir = @import("llvm_ir.zig"); |
| 12 | const libc = @import("libc.zig"); | 10 | const libc = @import("libc.zig"); |
| 13 | const link = @import("link.zig"); | 11 | const link = @import("link.zig"); |
| ... | @@ -2381,59 +2379,7 @@ pub fn isNative(actual_target: *const std.Build.ResolvedTarget, host: *const std | ... | @@ -2381,59 +2379,7 @@ pub fn isNative(actual_target: *const std.Build.ResolvedTarget, host: *const std |
| 2381 | return true; | 2379 | return true; |
| 2382 | } | 2380 | } |
| 2383 | 2381 | ||
| 2384 | /// For stack trace tests, we only test native by default, because external executors are pretty | 2382 | pub fn addStackTraceTests(b: *std.Build, test_filters: []const []const u8, skip_non_native: bool) *Step { |
| 2385 | /// unreliable at stack tracing. However, if there's a 32-bit equivalent target which the host can | ||
| 2386 | /// trivially run, we may as well at least test that! | ||
| 2387 | fn nativeAndCompatible32bit(b: *std.Build, skip_non_native: bool) []const std.Build.ResolvedTarget { | ||
| 2388 | const host = b.graph.host.result; | ||
| 2389 | const only_native = (&b.graph.host)[0..1]; | ||
| 2390 | if (skip_non_native) return only_native; | ||
| 2391 | const arch32 = compatible32bitArch(&b.graph.host.result) orelse return only_native; | ||
| 2392 | return b.graph.arena.dupe(std.Build.ResolvedTarget, &.{ | ||
| 2393 | b.graph.host, | ||
| 2394 | b.resolveTargetQuery(.{ .cpu_arch = arch32, .os_tag = host.os.tag }), | ||
| 2395 | }) catch @panic("OOM"); | ||
| 2396 | } | ||
| 2397 | |||
| 2398 | fn wineAndCompatible32bit(b: *std.Build, skip_non_native: bool) []const std.Build.ResolvedTarget { | ||
| 2399 | var targets: std.ArrayList(std.Build.ResolvedTarget) = .empty; | ||
| 2400 | |||
| 2401 | const host = b.graph.host.result; | ||
| 2402 | |||
| 2403 | targets.append(b.graph.arena, b.resolveTargetQuery(.{ | ||
| 2404 | .cpu_arch = host.cpu.arch, | ||
| 2405 | .os_tag = .windows, | ||
| 2406 | })) catch @panic("OOM"); | ||
| 2407 | if (!skip_non_native) { | ||
| 2408 | if (compatible32bitArch(&b.graph.host.result)) |arch| { | ||
| 2409 | targets.append(b.graph.arena, b.resolveTargetQuery(.{ | ||
| 2410 | .cpu_arch = arch, | ||
| 2411 | .os_tag = .windows, | ||
| 2412 | })) catch @panic("OOM"); | ||
| 2413 | } | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | return targets.toOwnedSlice(b.graph.arena) catch @panic("OOM"); | ||
| 2417 | } | ||
| 2418 | |||
| 2419 | fn darlingTargets(b: *std.Build) []const std.Build.ResolvedTarget { | ||
| 2420 | var targets: std.ArrayList(std.Build.ResolvedTarget) = .empty; | ||
| 2421 | |||
| 2422 | const host = b.graph.host.result; | ||
| 2423 | |||
| 2424 | targets.append(b.graph.arena, b.resolveTargetQuery(.{ | ||
| 2425 | .cpu_arch = host.cpu.arch, | ||
| 2426 | .os_tag = .macos, | ||
| 2427 | })) catch @panic("OOM"); | ||
| 2428 | |||
| 2429 | return targets.toOwnedSlice(b.graph.arena) catch @panic("OOM"); | ||
| 2430 | } | ||
| 2431 | |||
| 2432 | pub fn addStackTraceTests( | ||
| 2433 | b: *std.Build, | ||
| 2434 | test_filters: []const []const u8, | ||
| 2435 | skip_non_native: bool, | ||
| 2436 | ) *Step { | ||
| 2437 | const step = b.step("test-stack-traces", "Run the stack trace tests"); | 2383 | const step = b.step("test-stack-traces", "Run the stack trace tests"); |
| 2438 | 2384 | ||
| 2439 | const convert_exe = b.addExecutable(.{ | 2385 | const convert_exe = b.addExecutable(.{ |
| ... | @@ -2445,35 +2391,15 @@ pub fn addStackTraceTests( | ... | @@ -2445,35 +2391,15 @@ pub fn addStackTraceTests( |
| 2445 | }), | 2391 | }), |
| 2446 | }); | 2392 | }); |
| 2447 | 2393 | ||
| 2448 | const host_cases = b.allocator.create(StackTracesContext) catch @panic("OOM"); | 2394 | const stack_traces_context = b.allocator.create(StackTracesContext) catch @panic("OOM"); |
| 2449 | host_cases.* = .{ | 2395 | stack_traces_context.* = .{ |
| 2450 | .b = b, | 2396 | .b = b, |
| 2451 | .step = step, | 2397 | .step = step, |
| 2452 | .test_filters = test_filters, | 2398 | .test_filters = test_filters, |
| 2453 | .targets = nativeAndCompatible32bit(b, skip_non_native), | 2399 | .skip_non_native = skip_non_native, |
| 2454 | .convert_exe = convert_exe, | 2400 | .convert_exe = convert_exe, |
| 2455 | }; | 2401 | }; |
| 2456 | stack_traces.addCases(host_cases, b.graph.host.result.os.tag); | 2402 | stack_traces_context.addCases(); |
| 2457 | |||
| 2458 | const wine_cases = b.allocator.create(StackTracesContext) catch @panic("OOM"); | ||
| 2459 | wine_cases.* = .{ | ||
| 2460 | .b = b, | ||
| 2461 | .step = step, | ||
| 2462 | .test_filters = test_filters, | ||
| 2463 | .targets = wineAndCompatible32bit(b, skip_non_native), | ||
| 2464 | .convert_exe = convert_exe, | ||
| 2465 | }; | ||
| 2466 | stack_traces.addCases(wine_cases, .windows); | ||
| 2467 | |||
| 2468 | const darling_cases = b.allocator.create(StackTracesContext) catch @panic("OOM"); | ||
| 2469 | darling_cases.* = .{ | ||
| 2470 | .b = b, | ||
| 2471 | .step = step, | ||
| 2472 | .test_filters = test_filters, | ||
| 2473 | .targets = darlingTargets(b), | ||
| 2474 | .convert_exe = convert_exe, | ||
| 2475 | }; | ||
| 2476 | stack_traces.addCases(darling_cases, .macos); | ||
| 2477 | 2403 | ||
| 2478 | return step; | 2404 | return step; |
| 2479 | } | 2405 | } |
| ... | @@ -2495,38 +2421,16 @@ pub fn addErrorTraceTests( | ... | @@ -2495,38 +2421,16 @@ pub fn addErrorTraceTests( |
| 2495 | }), | 2421 | }), |
| 2496 | }); | 2422 | }); |
| 2497 | 2423 | ||
| 2498 | const host_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM"); | 2424 | const error_traces_context = b.allocator.create(ErrorTracesContext) catch @panic("OOM"); |
| 2499 | host_cases.* = .{ | 2425 | error_traces_context.* = .{ |
| 2500 | .b = b, | ||
| 2501 | .step = step, | ||
| 2502 | .test_filters = test_filters, | ||
| 2503 | .targets = nativeAndCompatible32bit(b, skip_non_native), | ||
| 2504 | .optimize_modes = optimize_modes, | ||
| 2505 | .convert_exe = convert_exe, | ||
| 2506 | }; | ||
| 2507 | error_traces.addCases(host_cases, b.graph.host.result.os.tag); | ||
| 2508 | |||
| 2509 | const wine_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM"); | ||
| 2510 | wine_cases.* = .{ | ||
| 2511 | .b = b, | ||
| 2512 | .step = step, | ||
| 2513 | .test_filters = test_filters, | ||
| 2514 | .targets = wineAndCompatible32bit(b, skip_non_native), | ||
| 2515 | .optimize_modes = optimize_modes, | ||
| 2516 | .convert_exe = convert_exe, | ||
| 2517 | }; | ||
| 2518 | error_traces.addCases(wine_cases, .windows); | ||
| 2519 | |||
| 2520 | const darling_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM"); | ||
| 2521 | darling_cases.* = .{ | ||
| 2522 | .b = b, | 2426 | .b = b, |
| 2523 | .step = step, | 2427 | .step = step, |
| 2524 | .test_filters = test_filters, | 2428 | .test_filters = test_filters, |
| 2525 | .targets = darlingTargets(b), | 2429 | .skip_non_native = skip_non_native, |
| 2526 | .optimize_modes = optimize_modes, | 2430 | .optimize_modes = optimize_modes, |
| 2527 | .convert_exe = convert_exe, | 2431 | .convert_exe = convert_exe, |
| 2528 | }; | 2432 | }; |
| 2529 | error_traces.addCases(darling_cases, .macos); | 2433 | error_traces_context.addCases(); |
| 2530 | 2434 | ||
| 2531 | return step; | 2435 | return step; |
| 2532 | } | 2436 | } |