| author | |
| committer | |
| log | 047640383e5e635ffe52ab360e03dbe08e73d025 |
| tree | 47b7062d2f80b34655481bf91f06bef4d132cfe7 |
| parent | 6f3767862d6886d5fde7e3734455a30f168ba80b |
This flag makes the build runner rebuild unit tests after the pipeline
finishes, if it finds any unit tests.
I did not make this integrate with file system watching yet.
The test runner is updated to detect which tests are fuzz tests.
Run step is updated to track which test indexes are fuzz tests.5 files changed, 97 insertions(+), 17 deletions(-)
lib/compiler/build_runner.zig+56-5| ... | @@ -10,7 +10,8 @@ const File = std.fs.File; | ... | @@ -10,7 +10,8 @@ const File = std.fs.File; |
| 10 | const Step = std.Build.Step; | 10 | const Step = std.Build.Step; |
| 11 | const Watch = std.Build.Watch; | 11 | const Watch = std.Build.Watch; |
| 12 | const Allocator = std.mem.Allocator; | 12 | const Allocator = std.mem.Allocator; |
| 13 | const fatal = std.zig.fatal; | 13 | const fatal = std.process.fatal; |
| 14 | const runner = @This(); | ||
| 14 | 15 | ||
| 15 | pub const root = @import("@build"); | 16 | pub const root = @import("@build"); |
| 16 | pub const dependencies = @import("@dependencies"); | 17 | pub const dependencies = @import("@dependencies"); |
| ... | @@ -102,6 +103,7 @@ pub fn main() !void { | ... | @@ -102,6 +103,7 @@ pub fn main() !void { |
| 102 | var steps_menu = false; | 103 | var steps_menu = false; |
| 103 | var output_tmp_nonce: ?[16]u8 = null; | 104 | var output_tmp_nonce: ?[16]u8 = null; |
| 104 | var watch = false; | 105 | var watch = false; |
| 106 | var fuzz = false; | ||
| 105 | var debounce_interval_ms: u16 = 50; | 107 | var debounce_interval_ms: u16 = 50; |
| 106 | 108 | ||
| 107 | while (nextArg(args, &arg_idx)) |arg| { | 109 | while (nextArg(args, &arg_idx)) |arg| { |
| ... | @@ -234,6 +236,8 @@ pub fn main() !void { | ... | @@ -234,6 +236,8 @@ pub fn main() !void { |
| 234 | prominent_compile_errors = true; | 236 | prominent_compile_errors = true; |
| 235 | } else if (mem.eql(u8, arg, "--watch")) { | 237 | } else if (mem.eql(u8, arg, "--watch")) { |
| 236 | watch = true; | 238 | watch = true; |
| 239 | } else if (mem.eql(u8, arg, "--fuzz")) { | ||
| 240 | fuzz = true; | ||
| 237 | } else if (mem.eql(u8, arg, "-fincremental")) { | 241 | } else if (mem.eql(u8, arg, "-fincremental")) { |
| 238 | graph.incremental = true; | 242 | graph.incremental = true; |
| 239 | } else if (mem.eql(u8, arg, "-fno-incremental")) { | 243 | } else if (mem.eql(u8, arg, "-fno-incremental")) { |
| ... | @@ -353,6 +357,7 @@ pub fn main() !void { | ... | @@ -353,6 +357,7 @@ pub fn main() !void { |
| 353 | .max_rss_mutex = .{}, | 357 | .max_rss_mutex = .{}, |
| 354 | .skip_oom_steps = skip_oom_steps, | 358 | .skip_oom_steps = skip_oom_steps, |
| 355 | .watch = watch, | 359 | .watch = watch, |
| 360 | .fuzz = fuzz, | ||
| 356 | .memory_blocked_steps = std.ArrayList(*Step).init(arena), | 361 | .memory_blocked_steps = std.ArrayList(*Step).init(arena), |
| 357 | .step_stack = .{}, | 362 | .step_stack = .{}, |
| 358 | .prominent_compile_errors = prominent_compile_errors, | 363 | .prominent_compile_errors = prominent_compile_errors, |
| ... | @@ -394,6 +399,10 @@ pub fn main() !void { | ... | @@ -394,6 +399,10 @@ pub fn main() !void { |
| 394 | }, | 399 | }, |
| 395 | else => return err, | 400 | else => return err, |
| 396 | }; | 401 | }; |
| 402 | if (fuzz) { | ||
| 403 | startFuzzing(&run.thread_pool, run.step_stack.keys(), main_progress_node); | ||
| 404 | } | ||
| 405 | |||
| 397 | if (!watch) return cleanExit(); | 406 | if (!watch) return cleanExit(); |
| 398 | 407 | ||
| 399 | switch (builtin.os.tag) { | 408 | switch (builtin.os.tag) { |
| ... | @@ -430,6 +439,43 @@ pub fn main() !void { | ... | @@ -430,6 +439,43 @@ pub fn main() !void { |
| 430 | } | 439 | } |
| 431 | } | 440 | } |
| 432 | 441 | ||
| 442 | fn startFuzzing(thread_pool: *std.Thread.Pool, all_steps: []const *Step, prog_node: std.Progress.Node) void { | ||
| 443 | { | ||
| 444 | const rebuild_node = prog_node.start("Rebuilding Unit Tests", 0); | ||
| 445 | defer rebuild_node.end(); | ||
| 446 | var count: usize = 0; | ||
| 447 | var wait_group: std.Thread.WaitGroup = .{}; | ||
| 448 | defer wait_group.wait(); | ||
| 449 | for (all_steps) |step| { | ||
| 450 | const run = step.cast(Step.Run) orelse continue; | ||
| 451 | if (run.fuzz_tests.items.len > 0 and run.producer != null) { | ||
| 452 | thread_pool.spawnWg(&wait_group, rebuildTestsWorkerRun, .{ run, prog_node }); | ||
| 453 | count += 1; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | if (count == 0) { | ||
| 457 | std.debug.lockStdErr(); | ||
| 458 | std.debug.print("no fuzz tests found\n", .{}); | ||
| 459 | process.exit(2); | ||
| 460 | } | ||
| 461 | rebuild_node.setEstimatedTotalItems(count); | ||
| 462 | } | ||
| 463 | @panic("TODO do something with the rebuilt unit tests"); | ||
| 464 | } | ||
| 465 | |||
| 466 | fn rebuildTestsWorkerRun(run: *Step.Run, parent_prog_node: std.Progress.Node) void { | ||
| 467 | const compile_step = run.producer.?; | ||
| 468 | const prog_node = parent_prog_node.start(compile_step.step.name, 0); | ||
| 469 | defer prog_node.end(); | ||
| 470 | const rebuilt_bin_path = compile_step.rebuildInFuzzMode(prog_node) catch |err| { | ||
| 471 | std.debug.print("failed to rebuild {s} in fuzz mode: {s}", .{ | ||
| 472 | compile_step.step.name, @errorName(err), | ||
| 473 | }); | ||
| 474 | return; | ||
| 475 | }; | ||
| 476 | std.debug.print("rebuilt binary: '{s}'\n", .{rebuilt_bin_path}); | ||
| 477 | } | ||
| 478 | |||
| 433 | fn markFailedStepsDirty(gpa: Allocator, all_steps: []const *Step) void { | 479 | fn markFailedStepsDirty(gpa: Allocator, all_steps: []const *Step) void { |
| 434 | for (all_steps) |step| switch (step.state) { | 480 | for (all_steps) |step| switch (step.state) { |
| 435 | .dependency_failure, .failure, .skipped => step.recursiveReset(gpa), | 481 | .dependency_failure, .failure, .skipped => step.recursiveReset(gpa), |
| ... | @@ -457,6 +503,7 @@ const Run = struct { | ... | @@ -457,6 +503,7 @@ const Run = struct { |
| 457 | max_rss_mutex: std.Thread.Mutex, | 503 | max_rss_mutex: std.Thread.Mutex, |
| 458 | skip_oom_steps: bool, | 504 | skip_oom_steps: bool, |
| 459 | watch: bool, | 505 | watch: bool, |
| 506 | fuzz: bool, | ||
| 460 | memory_blocked_steps: std.ArrayList(*Step), | 507 | memory_blocked_steps: std.ArrayList(*Step), |
| 461 | step_stack: std.AutoArrayHashMapUnmanaged(*Step, void), | 508 | step_stack: std.AutoArrayHashMapUnmanaged(*Step, void), |
| 462 | prominent_compile_errors: bool, | 509 | prominent_compile_errors: bool, |
| ... | @@ -466,6 +513,11 @@ const Run = struct { | ... | @@ -466,6 +513,11 @@ const Run = struct { |
| 466 | summary: Summary, | 513 | summary: Summary, |
| 467 | ttyconf: std.io.tty.Config, | 514 | ttyconf: std.io.tty.Config, |
| 468 | stderr: File, | 515 | stderr: File, |
| 516 | |||
| 517 | fn cleanExit(run: Run) void { | ||
| 518 | if (run.watch or run.fuzz) return; | ||
| 519 | return runner.cleanExit(); | ||
| 520 | } | ||
| 469 | }; | 521 | }; |
| 470 | 522 | ||
| 471 | fn prepare( | 523 | fn prepare( |
| ... | @@ -614,8 +666,7 @@ fn runStepNames( | ... | @@ -614,8 +666,7 @@ fn runStepNames( |
| 614 | else => false, | 666 | else => false, |
| 615 | }; | 667 | }; |
| 616 | if (failure_count == 0 and failures_only) { | 668 | if (failure_count == 0 and failures_only) { |
| 617 | if (!run.watch) cleanExit(); | 669 | return run.cleanExit(); |
| 618 | return; | ||
| 619 | } | 670 | } |
| 620 | 671 | ||
| 621 | const ttyconf = run.ttyconf; | 672 | const ttyconf = run.ttyconf; |
| ... | @@ -672,8 +723,7 @@ fn runStepNames( | ... | @@ -672,8 +723,7 @@ fn runStepNames( |
| 672 | } | 723 | } |
| 673 | 724 | ||
| 674 | if (failure_count == 0) { | 725 | if (failure_count == 0) { |
| 675 | if (!run.watch) cleanExit(); | 726 | return run.cleanExit(); |
| 676 | return; | ||
| 677 | } | 727 | } |
| 678 | 728 | ||
| 679 | // Finally, render compile errors at the bottom of the terminal. | 729 | // Finally, render compile errors at the bottom of the terminal. |
| ... | @@ -1226,6 +1276,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void { | ... | @@ -1226,6 +1276,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void { |
| 1226 | \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss | 1276 | \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss |
| 1227 | \\ --fetch Exit after fetching dependency tree | 1277 | \\ --fetch Exit after fetching dependency tree |
| 1228 | \\ --watch Continuously rebuild when source files are modified | 1278 | \\ --watch Continuously rebuild when source files are modified |
| 1279 | \\ --fuzz Continuously search for unit test failures | ||
| 1229 | \\ --debounce <ms> Delay before rebuilding after changed file detected | 1280 | \\ --debounce <ms> Delay before rebuilding after changed file detected |
| 1230 | \\ -fincremental Enable incremental compilation | 1281 | \\ -fincremental Enable incremental compilation |
| 1231 | \\ -fno-incremental Disable incremental compilation | 1282 | \\ -fno-incremental Disable incremental compilation |
lib/compiler/test_runner.zig+6-1| ... | @@ -143,6 +143,7 @@ fn mainTerminal() void { | ... | @@ -143,6 +143,7 @@ fn mainTerminal() void { |
| 143 | var ok_count: usize = 0; | 143 | var ok_count: usize = 0; |
| 144 | var skip_count: usize = 0; | 144 | var skip_count: usize = 0; |
| 145 | var fail_count: usize = 0; | 145 | var fail_count: usize = 0; |
| 146 | var fuzz_count: usize = 0; | ||
| 146 | const root_node = std.Progress.start(.{ | 147 | const root_node = std.Progress.start(.{ |
| 147 | .root_name = "Test", | 148 | .root_name = "Test", |
| 148 | .estimated_total_items = test_fn_list.len, | 149 | .estimated_total_items = test_fn_list.len, |
| ... | @@ -168,7 +169,7 @@ fn mainTerminal() void { | ... | @@ -168,7 +169,7 @@ fn mainTerminal() void { |
| 168 | if (!have_tty) { | 169 | if (!have_tty) { |
| 169 | std.debug.print("{d}/{d} {s}...", .{ i + 1, test_fn_list.len, test_fn.name }); | 170 | std.debug.print("{d}/{d} {s}...", .{ i + 1, test_fn_list.len, test_fn.name }); |
| 170 | } | 171 | } |
| 171 | // Track in a global variable so that `fuzzInput` can see it. | 172 | is_fuzz_test = false; |
| 172 | if (test_fn.func()) |_| { | 173 | if (test_fn.func()) |_| { |
| 173 | ok_count += 1; | 174 | ok_count += 1; |
| 174 | test_node.end(); | 175 | test_node.end(); |
| ... | @@ -198,6 +199,7 @@ fn mainTerminal() void { | ... | @@ -198,6 +199,7 @@ fn mainTerminal() void { |
| 198 | test_node.end(); | 199 | test_node.end(); |
| 199 | }, | 200 | }, |
| 200 | } | 201 | } |
| 202 | fuzz_count += @intFromBool(is_fuzz_test); | ||
| 201 | } | 203 | } |
| 202 | root_node.end(); | 204 | root_node.end(); |
| 203 | if (ok_count == test_fn_list.len) { | 205 | if (ok_count == test_fn_list.len) { |
| ... | @@ -211,6 +213,9 @@ fn mainTerminal() void { | ... | @@ -211,6 +213,9 @@ fn mainTerminal() void { |
| 211 | if (leaks != 0) { | 213 | if (leaks != 0) { |
| 212 | std.debug.print("{d} tests leaked memory.\n", .{leaks}); | 214 | std.debug.print("{d} tests leaked memory.\n", .{leaks}); |
| 213 | } | 215 | } |
| 216 | if (fuzz_count != 0) { | ||
| 217 | std.debug.print("{d} fuzz tests found.\n", .{fuzz_count}); | ||
| 218 | } | ||
| 214 | if (leaks != 0 or log_err_count != 0 or fail_count != 0) { | 219 | if (leaks != 0 or log_err_count != 0 or fail_count != 0) { |
| 215 | std.process.exit(1); | 220 | std.process.exit(1); |
| 216 | } | 221 | } |
lib/std/Build.zig+1| ... | @@ -977,6 +977,7 @@ pub fn addRunArtifact(b: *Build, exe: *Step.Compile) *Step.Run { | ... | @@ -977,6 +977,7 @@ pub fn addRunArtifact(b: *Build, exe: *Step.Compile) *Step.Run { |
| 977 | // Consider that this is declarative; the run step may not be run unless a user | 977 | // Consider that this is declarative; the run step may not be run unless a user |
| 978 | // option is supplied. | 978 | // option is supplied. |
| 979 | const run_step = Step.Run.create(b, b.fmt("run {s}", .{exe.name})); | 979 | const run_step = Step.Run.create(b, b.fmt("run {s}", .{exe.name})); |
| 980 | run_step.producer = exe; | ||
| 980 | if (exe.kind == .@"test") { | 981 | if (exe.kind == .@"test") { |
| 981 | if (exe.exec_cmd_args) |exec_cmd_args| { | 982 | if (exe.exec_cmd_args) |exec_cmd_args| { |
| 982 | for (exec_cmd_args) |cmd_arg| { | 983 | for (exec_cmd_args) |cmd_arg| { |
lib/std/Build/Step/Compile.zig+21-11| ... | @@ -1004,7 +1004,7 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking | ... | @@ -1004,7 +1004,7 @@ fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking |
| 1004 | return path; | 1004 | return path; |
| 1005 | } | 1005 | } |
| 1006 | 1006 | ||
| 1007 | fn getZigArgs(compile: *Compile) ![][]const u8 { | 1007 | fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 1008 | const step = &compile.step; | 1008 | const step = &compile.step; |
| 1009 | const b = step.owner; | 1009 | const b = step.owner; |
| 1010 | const arena = b.allocator; | 1010 | const arena = b.allocator; |
| ... | @@ -1055,6 +1055,10 @@ fn getZigArgs(compile: *Compile) ![][]const u8 { | ... | @@ -1055,6 +1055,10 @@ fn getZigArgs(compile: *Compile) ![][]const u8 { |
| 1055 | try zig_args.append(try std.fmt.allocPrint(arena, "{}", .{stack_size})); | 1055 | try zig_args.append(try std.fmt.allocPrint(arena, "{}", .{stack_size})); |
| 1056 | } | 1056 | } |
| 1057 | 1057 | ||
| 1058 | if (fuzz) { | ||
| 1059 | try zig_args.append("-ffuzz"); | ||
| 1060 | } | ||
| 1061 | |||
| 1058 | { | 1062 | { |
| 1059 | // Stores system libraries that have already been seen for at least one | 1063 | // Stores system libraries that have already been seen for at least one |
| 1060 | // module, along with any arguments that need to be passed to the | 1064 | // module, along with any arguments that need to be passed to the |
| ... | @@ -1757,7 +1761,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -1757,7 +1761,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 1757 | const b = step.owner; | 1761 | const b = step.owner; |
| 1758 | const compile: *Compile = @fieldParentPtr("step", step); | 1762 | const compile: *Compile = @fieldParentPtr("step", step); |
| 1759 | 1763 | ||
| 1760 | const zig_args = try getZigArgs(compile); | 1764 | const zig_args = try getZigArgs(compile, false); |
| 1761 | 1765 | ||
| 1762 | const maybe_output_bin_path = step.evalZigProcess( | 1766 | const maybe_output_bin_path = step.evalZigProcess( |
| 1763 | zig_args, | 1767 | zig_args, |
| ... | @@ -1835,6 +1839,12 @@ fn make(step: *Step, options: Step.MakeOptions) !void { | ... | @@ -1835,6 +1839,12 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 1835 | } | 1839 | } |
| 1836 | } | 1840 | } |
| 1837 | 1841 | ||
| 1842 | pub fn rebuildInFuzzMode(c: *Compile, progress_node: std.Progress.Node) ![]const u8 { | ||
| 1843 | const zig_args = try getZigArgs(c, true); | ||
| 1844 | const maybe_output_bin_path = try c.step.evalZigProcess(zig_args, progress_node, false); | ||
| 1845 | return maybe_output_bin_path.?; | ||
| 1846 | } | ||
| 1847 | |||
| 1838 | pub fn doAtomicSymLinks( | 1848 | pub fn doAtomicSymLinks( |
| 1839 | step: *Step, | 1849 | step: *Step, |
| 1840 | output_path: []const u8, | 1850 | output_path: []const u8, |
| ... | @@ -1861,10 +1871,10 @@ pub fn doAtomicSymLinks( | ... | @@ -1861,10 +1871,10 @@ pub fn doAtomicSymLinks( |
| 1861 | }; | 1871 | }; |
| 1862 | } | 1872 | } |
| 1863 | 1873 | ||
| 1864 | fn execPkgConfigList(compile: *std.Build, out_code: *u8) (PkgConfigError || RunError)![]const PkgConfigPkg { | 1874 | fn execPkgConfigList(b: *std.Build, out_code: *u8) (PkgConfigError || RunError)![]const PkgConfigPkg { |
| 1865 | const pkg_config_exe = compile.graph.env_map.get("PKG_CONFIG") orelse "pkg-config"; | 1875 | const pkg_config_exe = b.graph.env_map.get("PKG_CONFIG") orelse "pkg-config"; |
| 1866 | const stdout = try compile.runAllowFail(&[_][]const u8{ pkg_config_exe, "--list-all" }, out_code, .Ignore); | 1876 | const stdout = try b.runAllowFail(&[_][]const u8{ pkg_config_exe, "--list-all" }, out_code, .Ignore); |
| 1867 | var list = ArrayList(PkgConfigPkg).init(compile.allocator); | 1877 | var list = ArrayList(PkgConfigPkg).init(b.allocator); |
| 1868 | errdefer list.deinit(); | 1878 | errdefer list.deinit(); |
| 1869 | var line_it = mem.tokenizeAny(u8, stdout, "\r\n"); | 1879 | var line_it = mem.tokenizeAny(u8, stdout, "\r\n"); |
| 1870 | while (line_it.next()) |line| { | 1880 | while (line_it.next()) |line| { |
| ... | @@ -1878,13 +1888,13 @@ fn execPkgConfigList(compile: *std.Build, out_code: *u8) (PkgConfigError || RunE | ... | @@ -1878,13 +1888,13 @@ fn execPkgConfigList(compile: *std.Build, out_code: *u8) (PkgConfigError || RunE |
| 1878 | return list.toOwnedSlice(); | 1888 | return list.toOwnedSlice(); |
| 1879 | } | 1889 | } |
| 1880 | 1890 | ||
| 1881 | fn getPkgConfigList(compile: *std.Build) ![]const PkgConfigPkg { | 1891 | fn getPkgConfigList(b: *std.Build) ![]const PkgConfigPkg { |
| 1882 | if (compile.pkg_config_pkg_list) |res| { | 1892 | if (b.pkg_config_pkg_list) |res| { |
| 1883 | return res; | 1893 | return res; |
| 1884 | } | 1894 | } |
| 1885 | var code: u8 = undefined; | 1895 | var code: u8 = undefined; |
| 1886 | if (execPkgConfigList(compile, &code)) |list| { | 1896 | if (execPkgConfigList(b, &code)) |list| { |
| 1887 | compile.pkg_config_pkg_list = list; | 1897 | b.pkg_config_pkg_list = list; |
| 1888 | return list; | 1898 | return list; |
| 1889 | } else |err| { | 1899 | } else |err| { |
| 1890 | const result = switch (err) { | 1900 | const result = switch (err) { |
| ... | @@ -1896,7 +1906,7 @@ fn getPkgConfigList(compile: *std.Build) ![]const PkgConfigPkg { | ... | @@ -1896,7 +1906,7 @@ fn getPkgConfigList(compile: *std.Build) ![]const PkgConfigPkg { |
| 1896 | error.PkgConfigInvalidOutput => error.PkgConfigInvalidOutput, | 1906 | error.PkgConfigInvalidOutput => error.PkgConfigInvalidOutput, |
| 1897 | else => return err, | 1907 | else => return err, |
| 1898 | }; | 1908 | }; |
| 1899 | compile.pkg_config_pkg_list = result; | 1909 | b.pkg_config_pkg_list = result; |
| 1900 | return result; | 1910 | return result; |
| 1901 | } | 1911 | } |
| 1902 | } | 1912 | } |
lib/std/Build/Step/Run.zig+13| ... | @@ -86,6 +86,13 @@ dep_output_file: ?*Output, | ... | @@ -86,6 +86,13 @@ dep_output_file: ?*Output, |
| 86 | 86 | ||
| 87 | has_side_effects: bool, | 87 | has_side_effects: bool, |
| 88 | 88 | ||
| 89 | /// If this is a Zig unit test binary, this tracks the indexes of the unit | ||
| 90 | /// tests that are also fuzz tests. | ||
| 91 | fuzz_tests: std.ArrayListUnmanaged(u32), | ||
| 92 | |||
| 93 | /// If this Run step was produced by a Compile step, it is tracked here. | ||
| 94 | producer: ?*Step.Compile, | ||
| 95 | |||
| 89 | pub const StdIn = union(enum) { | 96 | pub const StdIn = union(enum) { |
| 90 | none, | 97 | none, |
| 91 | bytes: []const u8, | 98 | bytes: []const u8, |
| ... | @@ -175,6 +182,8 @@ pub fn create(owner: *std.Build, name: []const u8) *Run { | ... | @@ -175,6 +182,8 @@ pub fn create(owner: *std.Build, name: []const u8) *Run { |
| 175 | .captured_stderr = null, | 182 | .captured_stderr = null, |
| 176 | .dep_output_file = null, | 183 | .dep_output_file = null, |
| 177 | .has_side_effects = false, | 184 | .has_side_effects = false, |
| 185 | .fuzz_tests = .{}, | ||
| 186 | .producer = null, | ||
| 178 | }; | 187 | }; |
| 179 | return run; | 188 | return run; |
| 180 | } | 189 | } |
| ... | @@ -1347,6 +1356,8 @@ fn evalZigTest( | ... | @@ -1347,6 +1356,8 @@ fn evalZigTest( |
| 1347 | var sub_prog_node: ?std.Progress.Node = null; | 1356 | var sub_prog_node: ?std.Progress.Node = null; |
| 1348 | defer if (sub_prog_node) |n| n.end(); | 1357 | defer if (sub_prog_node) |n| n.end(); |
| 1349 | 1358 | ||
| 1359 | run.fuzz_tests.clearRetainingCapacity(); | ||
| 1360 | |||
| 1350 | poll: while (true) { | 1361 | poll: while (true) { |
| 1351 | while (stdout.readableLength() < @sizeOf(Header)) { | 1362 | while (stdout.readableLength() < @sizeOf(Header)) { |
| 1352 | if (!(try poller.poll())) break :poll; | 1363 | if (!(try poller.poll())) break :poll; |
| ... | @@ -1404,6 +1415,8 @@ fn evalZigTest( | ... | @@ -1404,6 +1415,8 @@ fn evalZigTest( |
| 1404 | leak_count +|= @intFromBool(tr_hdr.flags.leak); | 1415 | leak_count +|= @intFromBool(tr_hdr.flags.leak); |
| 1405 | log_err_count +|= tr_hdr.flags.log_err_count; | 1416 | log_err_count +|= tr_hdr.flags.log_err_count; |
| 1406 | 1417 | ||
| 1418 | if (tr_hdr.flags.fuzz) try run.fuzz_tests.append(gpa, tr_hdr.index); | ||
| 1419 | |||
| 1407 | if (tr_hdr.flags.fail or tr_hdr.flags.leak or tr_hdr.flags.log_err_count > 0) { | 1420 | if (tr_hdr.flags.fail or tr_hdr.flags.leak or tr_hdr.flags.log_err_count > 0) { |
| 1408 | const name = std.mem.sliceTo(md.string_bytes[md.names[tr_hdr.index]..], 0); | 1421 | const name = std.mem.sliceTo(md.string_bytes[md.names[tr_hdr.index]..], 0); |
| 1409 | const orig_msg = stderr.readableSlice(0); | 1422 | const orig_msg = stderr.readableSlice(0); |