| author | |
| committer | |
| log | 711ed56ce361fd9051fcf6039de48022b8dbc2d1 |
| tree | 856a966ec867171cff804e7a09f8184ca6c3cb9e |
| parent | 047640383e5e635ffe52ab360e03dbe08e73d025 |
4 files changed, 53 insertions(+), 38 deletions(-)
lib/compiler/build_runner.zig+2-38| ... | @@ -9,6 +9,7 @@ const ArrayList = std.ArrayList; | ... | @@ -9,6 +9,7 @@ const ArrayList = std.ArrayList; |
| 9 | const File = std.fs.File; | 9 | 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 Fuzz = std.Build.Fuzz; | ||
| 12 | const Allocator = std.mem.Allocator; | 13 | const Allocator = std.mem.Allocator; |
| 13 | const fatal = std.process.fatal; | 14 | const fatal = std.process.fatal; |
| 14 | const runner = @This(); | 15 | const runner = @This(); |
| ... | @@ -400,7 +401,7 @@ pub fn main() !void { | ... | @@ -400,7 +401,7 @@ pub fn main() !void { |
| 400 | else => return err, | 401 | else => return err, |
| 401 | }; | 402 | }; |
| 402 | if (fuzz) { | 403 | if (fuzz) { |
| 403 | startFuzzing(&run.thread_pool, run.step_stack.keys(), main_progress_node); | 404 | Fuzz.start(&run.thread_pool, run.step_stack.keys(), main_progress_node); |
| 404 | } | 405 | } |
| 405 | 406 | ||
| 406 | if (!watch) return cleanExit(); | 407 | if (!watch) return cleanExit(); |
| ... | @@ -439,43 +440,6 @@ pub fn main() !void { | ... | @@ -439,43 +440,6 @@ pub fn main() !void { |
| 439 | } | 440 | } |
| 440 | } | 441 | } |
| 441 | 442 | ||
| 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 | |||
| 479 | fn markFailedStepsDirty(gpa: Allocator, all_steps: []const *Step) void { | 443 | fn markFailedStepsDirty(gpa: Allocator, all_steps: []const *Step) void { |
| 480 | for (all_steps) |step| switch (step.state) { | 444 | for (all_steps) |step| switch (step.state) { |
| 481 | .dependency_failure, .failure, .skipped => step.recursiveReset(gpa), | 445 | .dependency_failure, .failure, .skipped => step.recursiveReset(gpa), |
lib/std/Build.zig+1| ... | @@ -21,6 +21,7 @@ pub const Cache = @import("Build/Cache.zig"); | ... | @@ -21,6 +21,7 @@ pub const Cache = @import("Build/Cache.zig"); |
| 21 | pub const Step = @import("Build/Step.zig"); | 21 | pub const Step = @import("Build/Step.zig"); |
| 22 | pub const Module = @import("Build/Module.zig"); | 22 | pub const Module = @import("Build/Module.zig"); |
| 23 | pub const Watch = @import("Build/Watch.zig"); | 23 | pub const Watch = @import("Build/Watch.zig"); |
| 24 | pub const Fuzz = @import("Build/Fuzz.zig"); | ||
| 24 | 25 | ||
| 25 | /// Shared state among all Build instances. | 26 | /// Shared state among all Build instances. |
| 26 | graph: *Graph, | 27 | graph: *Graph, |
lib/std/Build/Fuzz.zig created+46| ... | @@ -0,0 +1,46 @@ | ||
| 1 | const std = @import("../std.zig"); | ||
| 2 | const Fuzz = @This(); | ||
| 3 | const Step = std.Build.Step; | ||
| 4 | const assert = std.debug.assert; | ||
| 5 | const fatal = std.process.fatal; | ||
| 6 | |||
| 7 | pub fn start(thread_pool: *std.Thread.Pool, all_steps: []const *Step, prog_node: std.Progress.Node) void { | ||
| 8 | { | ||
| 9 | const rebuild_node = prog_node.start("Rebuilding Unit Tests", 0); | ||
| 10 | defer rebuild_node.end(); | ||
| 11 | var count: usize = 0; | ||
| 12 | var wait_group: std.Thread.WaitGroup = .{}; | ||
| 13 | defer wait_group.wait(); | ||
| 14 | for (all_steps) |step| { | ||
| 15 | const run = step.cast(Step.Run) orelse continue; | ||
| 16 | if (run.fuzz_tests.items.len > 0 and run.producer != null) { | ||
| 17 | thread_pool.spawnWg(&wait_group, rebuildTestsWorkerRun, .{ run, prog_node }); | ||
| 18 | count += 1; | ||
| 19 | } | ||
| 20 | } | ||
| 21 | if (count == 0) fatal("no fuzz tests found", .{}); | ||
| 22 | rebuild_node.setEstimatedTotalItems(count); | ||
| 23 | } | ||
| 24 | |||
| 25 | // Detect failure. | ||
| 26 | for (all_steps) |step| { | ||
| 27 | const run = step.cast(Step.Run) orelse continue; | ||
| 28 | if (run.fuzz_tests.items.len > 0 and run.rebuilt_executable == null) | ||
| 29 | fatal("one or more unit tests failed to be rebuilt in fuzz mode", .{}); | ||
| 30 | } | ||
| 31 | |||
| 32 | @panic("TODO do something with the rebuilt unit tests"); | ||
| 33 | } | ||
| 34 | |||
| 35 | fn rebuildTestsWorkerRun(run: *Step.Run, parent_prog_node: std.Progress.Node) void { | ||
| 36 | const compile_step = run.producer.?; | ||
| 37 | const prog_node = parent_prog_node.start(compile_step.step.name, 0); | ||
| 38 | defer prog_node.end(); | ||
| 39 | const rebuilt_bin_path = compile_step.rebuildInFuzzMode(prog_node) catch |err| { | ||
| 40 | std.debug.print("failed to rebuild {s} in fuzz mode: {s}", .{ | ||
| 41 | compile_step.step.name, @errorName(err), | ||
| 42 | }); | ||
| 43 | return; | ||
| 44 | }; | ||
| 45 | run.rebuilt_executable = rebuilt_bin_path; | ||
| 46 | } | ||
lib/std/Build/Step/Run.zig+4| ... | @@ -89,6 +89,9 @@ has_side_effects: bool, | ... | @@ -89,6 +89,9 @@ has_side_effects: bool, |
| 89 | /// If this is a Zig unit test binary, this tracks the indexes of the unit | 89 | /// If this is a Zig unit test binary, this tracks the indexes of the unit |
| 90 | /// tests that are also fuzz tests. | 90 | /// tests that are also fuzz tests. |
| 91 | fuzz_tests: std.ArrayListUnmanaged(u32), | 91 | fuzz_tests: std.ArrayListUnmanaged(u32), |
| 92 | /// Populated during the fuzz phase if this run step corresponds to a unit test | ||
| 93 | /// executable that contains fuzz tests. | ||
| 94 | rebuilt_executable: ?[]const u8, | ||
| 92 | 95 | ||
| 93 | /// If this Run step was produced by a Compile step, it is tracked here. | 96 | /// If this Run step was produced by a Compile step, it is tracked here. |
| 94 | producer: ?*Step.Compile, | 97 | producer: ?*Step.Compile, |
| ... | @@ -183,6 +186,7 @@ pub fn create(owner: *std.Build, name: []const u8) *Run { | ... | @@ -183,6 +186,7 @@ pub fn create(owner: *std.Build, name: []const u8) *Run { |
| 183 | .dep_output_file = null, | 186 | .dep_output_file = null, |
| 184 | .has_side_effects = false, | 187 | .has_side_effects = false, |
| 185 | .fuzz_tests = .{}, | 188 | .fuzz_tests = .{}, |
| 189 | .rebuilt_executable = null, | ||
| 186 | .producer = null, | 190 | .producer = null, |
| 187 | }; | 191 | }; |
| 188 | return run; | 192 | return run; |