authorgravatar for michael.dusan@gmail.comMichael Dusan <michael.dusan@gmail.com> 2021-04-10 19:51:27-04:00
committergravatar for michael.dusan@gmail.comMichael Dusan <michael.dusan@gmail.com> 2021-04-10 23:20:06-04:00
logd99dc21b9f00dffcf919188ef6751ee85a2c662e
tree631591c6fda8f4a6bdeccbaf46b6bf1c9814f8b7
parent75f86dab3fba75052da0c7c03d007ff1f20dd154

test: overhaul stack_trace testing

- limit expected-output to main source file; ie. tolerate changes to start.zig - when mode != .Debug the function name is now symbolically represented; ie. tolerate changes in llvm optimizer effects on the callstack - cleanup how test cases are specified - add test case predicates for excluding by arch, os or custom fn

2 files changed, 256 insertions(+), 492 deletions(-)

test/stack_traces.zig+158-459
...@@ -2,18 +2,52 @@ const std = @import("std");...@@ -2,18 +2,52 @@ const std = @import("std");
2const os = std.os;2const os = std.os;
3const tests = @import("tests.zig");3const tests = @import("tests.zig");
44
5// zig fmt: off
6pub fn addCases(cases: *tests.StackTracesContext) void {5pub fn addCases(cases: *tests.StackTracesContext) void {
7 const source_return =6 cases.addCase(.{
8 \\const std = @import("std");7 .name = "return",
9 \\8 .source =
10 \\pub fn main() !void {9 \\pub fn main() !void {
11 \\ return error.TheSkyIsFalling;10 \\ return error.TheSkyIsFalling;
12 \\}11 \\}
13 ;12 ,
14 const source_try_return =13 .Debug = .{
15 \\const std = @import("std");14 .expect =
16 \\15 \\error: TheSkyIsFalling
16 \\source.zig:2:5: [address] in main (test)
17 \\ return error.TheSkyIsFalling;
18 \\ ^
19 \\
20 ,
21 },
22 .ReleaseSafe = .{
23 .exclude_os = .{
24 .windows, // segfault
25 },
26 .expect =
27 \\error: TheSkyIsFalling
28 \\source.zig:2:5: [address] in [function]
29 \\ return error.TheSkyIsFalling;
30 \\ ^
31 \\
32 ,
33 },
34 .ReleaseFast = .{
35 .expect =
36 \\error: TheSkyIsFalling
37 \\
38 ,
39 },
40 .ReleaseSmall = .{
41 .expect =
42 \\error: TheSkyIsFalling
43 \\
44 ,
45 },
46 });
47
48 cases.addCase(.{
49 .name = "try return",
50 .source =
17 \\fn foo() !void {51 \\fn foo() !void {
18 \\ return error.TheSkyIsFalling;52 \\ return error.TheSkyIsFalling;
19 \\}53 \\}
...@@ -21,10 +55,51 @@ pub fn addCases(cases: *tests.StackTracesContext) void {...@@ -21,10 +55,51 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
21 \\pub fn main() !void {55 \\pub fn main() !void {
22 \\ try foo();56 \\ try foo();
23 \\}57 \\}
24 ;58 ,
25 const source_try_try_return_return =59 .Debug = .{
26 \\const std = @import("std");60 .expect =
27 \\61 \\error: TheSkyIsFalling
62 \\source.zig:2:5: [address] in foo (test)
63 \\ return error.TheSkyIsFalling;
64 \\ ^
65 \\source.zig:6:5: [address] in main (test)
66 \\ try foo();
67 \\ ^
68 \\
69 ,
70 },
71 .ReleaseSafe = .{
72 .exclude_os = .{
73 .windows, // segfault
74 },
75 .expect =
76 \\error: TheSkyIsFalling
77 \\source.zig:2:5: [address] in [function]
78 \\ return error.TheSkyIsFalling;
79 \\ ^
80 \\source.zig:6:5: [address] in [function]
81 \\ try foo();
82 \\ ^
83 \\
84 ,
85 },
86 .ReleaseFast = .{
87 .expect =
88 \\error: TheSkyIsFalling
89 \\
90 ,
91 },
92 .ReleaseSmall = .{
93 .expect =
94 \\error: TheSkyIsFalling
95 \\
96 ,
97 },
98 });
99
100 cases.addCase(.{
101 .name = "try try return return",
102 .source =
28 \\fn foo() !void {103 \\fn foo() !void {
29 \\ try bar();104 \\ try bar();
30 \\}105 \\}
...@@ -40,9 +115,66 @@ pub fn addCases(cases: *tests.StackTracesContext) void {...@@ -40,9 +115,66 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
40 \\pub fn main() !void {115 \\pub fn main() !void {
41 \\ try foo();116 \\ try foo();
42 \\}117 \\}
43 ;118 ,
119 .Debug = .{
120 .expect =
121 \\error: TheSkyIsFalling
122 \\source.zig:10:5: [address] in make_error (test)
123 \\ return error.TheSkyIsFalling;
124 \\ ^
125 \\source.zig:6:5: [address] in bar (test)
126 \\ return make_error();
127 \\ ^
128 \\source.zig:2:5: [address] in foo (test)
129 \\ try bar();
130 \\ ^
131 \\source.zig:14:5: [address] in main (test)
132 \\ try foo();
133 \\ ^
134 \\
135 ,
136 },
137 .ReleaseSafe = .{
138 .exclude_os = .{
139 .windows, // segfault
140 },
141 .expect =
142 \\error: TheSkyIsFalling
143 \\source.zig:10:5: [address] in [function]
144 \\ return error.TheSkyIsFalling;
145 \\ ^
146 \\source.zig:6:5: [address] in [function]
147 \\ return make_error();
148 \\ ^
149 \\source.zig:2:5: [address] in [function]
150 \\ try bar();
151 \\ ^
152 \\source.zig:14:5: [address] in [function]
153 \\ try foo();
154 \\ ^
155 \\
156 ,
157 },
158 .ReleaseFast = .{
159 .expect =
160 \\error: TheSkyIsFalling
161 \\
162 ,
163 },
164 .ReleaseSmall = .{
165 .expect =
166 \\error: TheSkyIsFalling
167 \\
168 ,
169 },
170 });
44171
45 const source_dumpCurrentStackTrace =172 cases.addCase(.{
173 .exclude_os = .{
174 .windows,
175 },
176 .name = "dumpCurrentStackTrace",
177 .source =
46 \\const std = @import("std");178 \\const std = @import("std");
47 \\179 \\
48 \\fn bar() void {180 \\fn bar() void {
...@@ -55,450 +187,17 @@ pub fn addCases(cases: *tests.StackTracesContext) void {...@@ -55,450 +187,17 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
55 \\ foo();187 \\ foo();
56 \\ return 1;188 \\ return 1;
57 \\}189 \\}
58 ;190 ,
59191 .Debug = .{
60 switch (std.Target.current.os.tag) {192 .expect =
61 .freebsd => {193 \\source.zig:7:8: [address] in foo (test)
62 cases.addCase(194 \\ bar();
63 "return",195 \\ ^
64 source_return,196 \\source.zig:10:8: [address] in main (test)
65 [_][]const u8{197 \\ foo();
66 // debug198 \\ ^
67 \\error: TheSkyIsFalling199 \\
68 \\source.zig:4:5: [address] in main (test)200 ,
69 \\ return error.TheSkyIsFalling;
70 \\ ^
71 \\
72 ,
73 // release-safe
74 \\error: TheSkyIsFalling
75 \\source.zig:4:5: [address] in std.start.main (test)
76 \\ return error.TheSkyIsFalling;
77 \\ ^
78 \\
79 ,
80 // release-fast
81 \\error: TheSkyIsFalling
82 \\
83 ,
84 // release-small
85 \\error: TheSkyIsFalling
86 \\
87 },
88 );
89 cases.addCase(
90 "try return",
91 source_try_return,
92 [_][]const u8{
93 // debug
94 \\error: TheSkyIsFalling
95 \\source.zig:4:5: [address] in foo (test)
96 \\ return error.TheSkyIsFalling;
97 \\ ^
98 \\source.zig:8:5: [address] in main (test)
99 \\ try foo();
100 \\ ^
101 \\
102 ,
103 // release-safe
104 \\error: TheSkyIsFalling
105 \\source.zig:4:5: [address] in std.start.main (test)
106 \\ return error.TheSkyIsFalling;
107 \\ ^
108 \\source.zig:8:5: [address] in std.start.main (test)
109 \\ try foo();
110 \\ ^
111 \\
112 ,
113 // release-fast
114 \\error: TheSkyIsFalling
115 \\
116 ,
117 // release-small
118 \\error: TheSkyIsFalling
119 \\
120 },
121 );
122 cases.addCase(
123 "try try return return",
124 source_try_try_return_return,
125 [_][]const u8{
126 // debug
127 \\error: TheSkyIsFalling
128 \\source.zig:12:5: [address] in make_error (test)
129 \\ return error.TheSkyIsFalling;
130 \\ ^
131 \\source.zig:8:5: [address] in bar (test)
132 \\ return make_error();
133 \\ ^
134 \\source.zig:4:5: [address] in foo (test)
135 \\ try bar();
136 \\ ^
137 \\source.zig:16:5: [address] in main (test)
138 \\ try foo();
139 \\ ^
140 \\
141 ,
142 // release-safe
143 \\error: TheSkyIsFalling
144 \\source.zig:12:5: [address] in std.start.main (test)
145 \\ return error.TheSkyIsFalling;
146 \\ ^
147 \\source.zig:8:5: [address] in std.start.main (test)
148 \\ return make_error();
149 \\ ^
150 \\source.zig:4:5: [address] in std.start.main (test)
151 \\ try bar();
152 \\ ^
153 \\source.zig:16:5: [address] in std.start.main (test)
154 \\ try foo();
155 \\ ^
156 \\
157 ,
158 // release-fast
159 \\error: TheSkyIsFalling
160 \\
161 ,
162 // release-small
163 \\error: TheSkyIsFalling
164 \\
165 },
166 );
167 },
168 .linux => {
169 cases.addCase(
170 "return",
171 source_return,
172 [_][]const u8{
173 // debug
174 \\error: TheSkyIsFalling
175 \\source.zig:4:5: [address] in main (test)
176 \\ return error.TheSkyIsFalling;
177 \\ ^
178 \\
179 ,
180 // release-safe
181 \\error: TheSkyIsFalling
182 \\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test)
183 \\ return error.TheSkyIsFalling;
184 \\ ^
185 \\
186 ,
187 // release-fast
188 \\error: TheSkyIsFalling
189 \\
190 ,
191 // release-small
192 \\error: TheSkyIsFalling
193 \\
194 },
195 );
196 cases.addCase(
197 "try return",
198 source_try_return,
199 [_][]const u8{
200 // debug
201 \\error: TheSkyIsFalling
202 \\source.zig:4:5: [address] in foo (test)
203 \\ return error.TheSkyIsFalling;
204 \\ ^
205 \\source.zig:8:5: [address] in main (test)
206 \\ try foo();
207 \\ ^
208 \\
209 ,
210 // release-safe
211 \\error: TheSkyIsFalling
212 \\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test)
213 \\ return error.TheSkyIsFalling;
214 \\ ^
215 \\source.zig:8:5: [address] in std.start.posixCallMainAndExit (test)
216 \\ try foo();
217 \\ ^
218 \\
219 ,
220 // release-fast
221 \\error: TheSkyIsFalling
222 \\
223 ,
224 // release-small
225 \\error: TheSkyIsFalling
226 \\
227 },
228 );
229 cases.addCase(
230 "try try return return",
231 source_try_try_return_return,
232 [_][]const u8{
233 // debug
234 \\error: TheSkyIsFalling
235 \\source.zig:12:5: [address] in make_error (test)
236 \\ return error.TheSkyIsFalling;
237 \\ ^
238 \\source.zig:8:5: [address] in bar (test)
239 \\ return make_error();
240 \\ ^
241 \\source.zig:4:5: [address] in foo (test)
242 \\ try bar();
243 \\ ^
244 \\source.zig:16:5: [address] in main (test)
245 \\ try foo();
246 \\ ^
247 \\
248 ,
249 // release-safe
250 \\error: TheSkyIsFalling
251 \\source.zig:12:5: [address] in std.start.posixCallMainAndExit (test)
252 \\ return error.TheSkyIsFalling;
253 \\ ^
254 \\source.zig:8:5: [address] in std.start.posixCallMainAndExit (test)
255 \\ return make_error();
256 \\ ^
257 \\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test)
258 \\ try bar();
259 \\ ^
260 \\source.zig:16:5: [address] in std.start.posixCallMainAndExit (test)
261 \\ try foo();
262 \\ ^
263 \\
264 ,
265 // release-fast
266 \\error: TheSkyIsFalling
267 \\
268 ,
269 // release-small
270 \\error: TheSkyIsFalling
271 \\
272 },
273 );
274 cases.addCase(
275 "dumpCurrentStackTrace",
276 source_dumpCurrentStackTrace,
277 [_][]const u8{
278 // debug
279 \\source.zig:7:8: [address] in foo (test)
280 \\ bar();
281 \\ ^
282 \\source.zig:10:8: [address] in main (test)
283 \\ foo();
284 \\ ^
285 \\start.zig:404:29: [address] in std.start.posixCallMainAndExit (test)
286 \\ return root.main();
287 \\ ^
288 \\start.zig:225:5: [address] in std.start._start (test)
289 \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
290 \\ ^
291 \\
292 ,
293 // release-safe
294 switch (std.Target.current.cpu.arch) {
295 .aarch64 => "", // TODO disabled; results in segfault
296 else =>
297 \\start.zig:225:5: [address] in std.start._start (test)
298 \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
299 \\ ^
300 \\
301 ,
302 },
303 // release-fast
304 \\
305 ,
306 // release-small
307 \\
308 },
309 );
310 },
311 .macos => {
312 cases.addCase(
313 "return",
314 source_return,
315 [_][]const u8{
316 // debug
317 \\error: TheSkyIsFalling
318 \\source.zig:4:5: [address] in main (test)
319 \\ return error.TheSkyIsFalling;
320 \\ ^
321 \\
322 ,
323 // release-safe
324 \\error: TheSkyIsFalling
325 \\source.zig:4:5: [address] in std.start.main (test)
326 \\ return error.TheSkyIsFalling;
327 \\ ^
328 \\
329 ,
330 // release-fast
331 \\error: TheSkyIsFalling
332 \\
333 ,
334 // release-small
335 \\error: TheSkyIsFalling
336 \\
337 },
338 );
339 cases.addCase(
340 "try return",
341 source_try_return,
342 [_][]const u8{
343 // debug
344 \\error: TheSkyIsFalling
345 \\source.zig:4:5: [address] in foo (test)
346 \\ return error.TheSkyIsFalling;
347 \\ ^
348 \\source.zig:8:5: [address] in main (test)
349 \\ try foo();
350 \\ ^
351 \\
352 ,
353 // release-safe
354 \\error: TheSkyIsFalling
355 \\source.zig:4:5: [address] in std.start.main (test)
356 \\ return error.TheSkyIsFalling;
357 \\ ^
358 \\source.zig:8:5: [address] in std.start.main (test)
359 \\ try foo();
360 \\ ^
361 \\
362 ,
363 // release-fast
364 \\error: TheSkyIsFalling
365 \\
366 ,
367 // release-small
368 \\error: TheSkyIsFalling
369 \\
370 },
371 );
372 cases.addCase(
373 "try try return return",
374 source_try_try_return_return,
375 [_][]const u8{
376 // debug
377 \\error: TheSkyIsFalling
378 \\source.zig:12:5: [address] in make_error (test)
379 \\ return error.TheSkyIsFalling;
380 \\ ^
381 \\source.zig:8:5: [address] in bar (test)
382 \\ return make_error();
383 \\ ^
384 \\source.zig:4:5: [address] in foo (test)
385 \\ try bar();
386 \\ ^
387 \\source.zig:16:5: [address] in main (test)
388 \\ try foo();
389 \\ ^
390 \\
391 ,
392 // release-safe
393 \\error: TheSkyIsFalling
394 \\source.zig:12:5: [address] in std.start.main (test)
395 \\ return error.TheSkyIsFalling;
396 \\ ^
397 \\source.zig:8:5: [address] in std.start.main (test)
398 \\ return make_error();
399 \\ ^
400 \\source.zig:4:5: [address] in std.start.main (test)
401 \\ try bar();
402 \\ ^
403 \\source.zig:16:5: [address] in std.start.main (test)
404 \\ try foo();
405 \\ ^
406 \\
407 ,
408 // release-fast
409 \\error: TheSkyIsFalling
410 \\
411 ,
412 // release-small
413 \\error: TheSkyIsFalling
414 \\
415 },
416 );
417 },
418 .windows => {
419 cases.addCase(
420 "return",
421 source_return,
422 [_][]const u8{
423 // debug
424 \\error: TheSkyIsFalling
425 \\source.zig:4:5: [address] in main (test.obj)
426 \\ return error.TheSkyIsFalling;
427 \\ ^
428 \\
429 ,
430 // release-safe
431 // --disabled-- results in segmenetation fault
432 "",
433 // release-fast
434 \\error: TheSkyIsFalling
435 \\
436 ,
437 // release-small
438 \\error: TheSkyIsFalling
439 \\
440 },
441 );
442 cases.addCase(
443 "try return",
444 source_try_return,
445 [_][]const u8{
446 // debug
447 \\error: TheSkyIsFalling
448 \\source.zig:4:5: [address] in foo (test.obj)
449 \\ return error.TheSkyIsFalling;
450 \\ ^
451 \\source.zig:8:5: [address] in main (test.obj)
452 \\ try foo();
453 \\ ^
454 \\
455 ,
456 // release-safe
457 // --disabled-- results in segmenetation fault
458 "",
459 // release-fast
460 \\error: TheSkyIsFalling
461 \\
462 ,
463 // release-small
464 \\error: TheSkyIsFalling
465 \\
466 },
467 );
468 cases.addCase(
469 "try try return return",
470 source_try_try_return_return,
471 [_][]const u8{
472 // debug
473 \\error: TheSkyIsFalling
474 \\source.zig:12:5: [address] in make_error (test.obj)
475 \\ return error.TheSkyIsFalling;
476 \\ ^
477 \\source.zig:8:5: [address] in bar (test.obj)
478 \\ return make_error();
479 \\ ^
480 \\source.zig:4:5: [address] in foo (test.obj)
481 \\ try bar();
482 \\ ^
483 \\source.zig:16:5: [address] in main (test.obj)
484 \\ try foo();
485 \\ ^
486 \\
487 ,
488 // release-safe
489 // --disabled-- results in segmenetation fault
490 "",
491 // release-fast
492 \\error: TheSkyIsFalling
493 \\
494 ,
495 // release-small
496 \\error: TheSkyIsFalling
497 \\
498 },
499 );
500 },201 },
501 else => {},202 });
502 }
503}203}
504// zig fmt: off
test/tests.zig+98-33
...@@ -558,42 +558,87 @@ pub const StackTracesContext = struct {...@@ -558,42 +558,87 @@ pub const StackTracesContext = struct {
558558
559 const Expect = [@typeInfo(Mode).Enum.fields.len][]const u8;559 const Expect = [@typeInfo(Mode).Enum.fields.len][]const u8;
560560
561 pub fn addCase(561 pub fn addCase(self: *StackTracesContext, config: anytype) void {
562 if (@hasField(@TypeOf(config), "exclude")) {
563 if (config.exclude.exclude()) return;
564 }
565 if (@hasField(@TypeOf(config), "exclude_arch")) {
566 const exclude_arch: []const builtin.Cpu.Arch = &config.exclude_arch;
567 for (exclude_arch) |arch| if (arch == builtin.cpu.arch) return;
568 }
569 if (@hasField(@TypeOf(config), "exclude_os")) {
570 const exclude_os: []const builtin.Os.Tag = &config.exclude_os;
571 for (exclude_os) |os| if (os == builtin.os.tag) return;
572 }
573 for (self.modes) |mode| {
574 switch (mode) {
575 .Debug => {
576 if (@hasField(@TypeOf(config), "Debug")) {
577 self.addExpect(config.name, config.source, mode, config.Debug);
578 }
579 },
580 .ReleaseSafe => {
581 if (@hasField(@TypeOf(config), "ReleaseSafe")) {
582 self.addExpect(config.name, config.source, mode, config.ReleaseSafe);
583 }
584 },
585 .ReleaseFast => {
586 if (@hasField(@TypeOf(config), "ReleaseFast")) {
587 self.addExpect(config.name, config.source, mode, config.ReleaseFast);
588 }
589 },
590 .ReleaseSmall => {
591 if (@hasField(@TypeOf(config), "ReleaseSmall")) {
592 self.addExpect(config.name, config.source, mode, config.ReleaseSmall);
593 }
594 },
595 }
596 }
597 }
598
599 fn addExpect(
562 self: *StackTracesContext,600 self: *StackTracesContext,
563 name: []const u8,601 name: []const u8,
564 source: []const u8,602 source: []const u8,
565 expect: Expect,603 mode: Mode,
604 mode_config: anytype,
566 ) void {605 ) void {
567 const b = self.b;606 if (@hasField(@TypeOf(mode_config), "exclude")) {
568607 if (mode_config.exclude.exclude()) return;
569 for (self.modes) |mode| {608 }
570 const expect_for_mode = expect[@enumToInt(mode)];609 if (@hasField(@TypeOf(mode_config), "exclude_arch")) {
571 if (expect_for_mode.len == 0) continue;610 const exclude_arch: []const builtin.Cpu.Arch = &mode_config.exclude_arch;
572611 for (exclude_arch) |arch| if (arch == builtin.cpu.arch) return;
573 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{s} {s} ({s})", .{612 }
574 "stack-trace",613 if (@hasField(@TypeOf(mode_config), "exclude_os")) {
575 name,614 const exclude_os: []const builtin.Os.Tag = &mode_config.exclude_os;
576 @tagName(mode),615 for (exclude_os) |os| if (os == builtin.os.tag) return;
577 }) catch unreachable;616 }
578 if (self.test_filter) |filter| {
579 if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
580 }
581
582 const src_basename = "source.zig";
583 const write_src = b.addWriteFile(src_basename, source);
584 const exe = b.addExecutableFromWriteFileStep("test", write_src, src_basename);
585 exe.setBuildMode(mode);
586
587 const run_and_compare = RunAndCompareStep.create(
588 self,
589 exe,
590 annotated_case_name,
591 mode,
592 expect_for_mode,
593 );
594617
595 self.step.dependOn(&run_and_compare.step);618 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{s} {s} ({s})", .{
619 "stack-trace",
620 name,
621 @tagName(mode),
622 }) catch unreachable;
623 if (self.test_filter) |filter| {
624 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
596 }625 }
626
627 const b = self.b;
628 const src_basename = "source.zig";
629 const write_src = b.addWriteFile(src_basename, source);
630 const exe = b.addExecutableFromWriteFileStep("test", write_src, src_basename);
631 exe.setBuildMode(mode);
632
633 const run_and_compare = RunAndCompareStep.create(
634 self,
635 exe,
636 annotated_case_name,
637 mode,
638 mode_config.expect,
639 );
640
641 self.step.dependOn(&run_and_compare.step);
597 }642 }
598643
599 const RunAndCompareStep = struct {644 const RunAndCompareStep = struct {
...@@ -695,6 +740,7 @@ pub const StackTracesContext = struct {...@@ -695,6 +740,7 @@ pub const StackTracesContext = struct {
695 // process result740 // process result
696 // - keep only basename of source file path741 // - keep only basename of source file path
697 // - replace address with symbolic string742 // - replace address with symbolic string
743 // - replace function name with symbolic string when mode != .Debug
698 // - skip empty lines744 // - skip empty lines
699 const got: []const u8 = got_result: {745 const got: []const u8 = got_result: {
700 var buf = ArrayList(u8).init(b.allocator);746 var buf = ArrayList(u8).init(b.allocator);
...@@ -703,26 +749,45 @@ pub const StackTracesContext = struct {...@@ -703,26 +749,45 @@ pub const StackTracesContext = struct {
703 var it = mem.split(stderr, "\n");749 var it = mem.split(stderr, "\n");
704 process_lines: while (it.next()) |line| {750 process_lines: while (it.next()) |line| {
705 if (line.len == 0) continue;751 if (line.len == 0) continue;
706 const delims = [_][]const u8{ ":", ":", ":", " in " };
707 var marks = [_]usize{0} ** 4;
708 // offset search past `[drive]:` on windows752 // offset search past `[drive]:` on windows
709 var pos: usize = if (std.Target.current.os.tag == .windows) 2 else 0;753 var pos: usize = if (std.Target.current.os.tag == .windows) 2 else 0;
754 // locate delims/anchor
755 const delims = [_][]const u8{ ":", ":", ":", " in ", "(", ")" };
756 var marks = [_]usize{0} ** delims.len;
710 for (delims) |delim, i| {757 for (delims) |delim, i| {
711 marks[i] = mem.indexOfPos(u8, line, pos, delim) orelse {758 marks[i] = mem.indexOfPos(u8, line, pos, delim) orelse {
759 // unexpected pattern: emit raw line and cont
712 try buf.appendSlice(line);760 try buf.appendSlice(line);
713 try buf.appendSlice("\n");761 try buf.appendSlice("\n");
714 continue :process_lines;762 continue :process_lines;
715 };763 };
716 pos = marks[i] + delim.len;764 pos = marks[i] + delim.len;
717 }765 }
766 // locate source basename
718 pos = mem.lastIndexOfScalar(u8, line[0..marks[0]], fs.path.sep) orelse {767 pos = mem.lastIndexOfScalar(u8, line[0..marks[0]], fs.path.sep) orelse {
768 // unexpected pattern: emit raw line and cont
719 try buf.appendSlice(line);769 try buf.appendSlice(line);
720 try buf.appendSlice("\n");770 try buf.appendSlice("\n");
721 continue :process_lines;771 continue :process_lines;
722 };772 };
773 // end processing if source basename changes
774 if (!mem.eql(u8, "source.zig", line[pos + 1 .. marks[0]])) break;
775 // emit substituted line
723 try buf.appendSlice(line[pos + 1 .. marks[2] + delims[2].len]);776 try buf.appendSlice(line[pos + 1 .. marks[2] + delims[2].len]);
724 try buf.appendSlice(" [address]");777 try buf.appendSlice(" [address]");
725 try buf.appendSlice(line[marks[3]..]);778 if (self.mode == .Debug) {
779 if (mem.lastIndexOfScalar(u8, line[marks[4]..marks[5]], '.')) |idot| {
780 // On certain platforms (windows) or possibly depending on how we choose to link main
781 // the object file extension may be present so we simply strip any extension.
782 try buf.appendSlice(line[marks[3] .. marks[4] + idot]);
783 try buf.appendSlice(line[marks[5]..]);
784 } else {
785 try buf.appendSlice(line[marks[3]..]);
786 }
787 } else {
788 try buf.appendSlice(line[marks[3] .. marks[3] + delims[3].len]);
789 try buf.appendSlice("[function]");
790 }
726 try buf.appendSlice("\n");791 try buf.appendSlice("\n");
727 }792 }
728 break :got_result buf.toOwnedSlice();793 break :got_result buf.toOwnedSlice();