authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-22 16:03:11-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-23 11:43:12-07:00
log33c79841832b575c2dacc7ec07ac9536798be4e3
treec7cf048b70a09f3e365ac0d36828b4653cc6d457
parent6f3e9939d0389539570d4a7cad95b1e96bc8f0d4

add std.testing.random_seed

closes #17609

13 files changed, 35 insertions(+), 18 deletions(-)

lib/compiler/build_runner.zig+2-3
...@@ -97,7 +97,6 @@ pub fn main() !void {...@@ -97,7 +97,6 @@ pub fn main() !void {
97 var max_rss: u64 = 0;97 var max_rss: u64 = 0;
98 var skip_oom_steps = false;98 var skip_oom_steps = false;
99 var color: Color = .auto;99 var color: Color = .auto;
100 var seed: u32 = 0;
101 var prominent_compile_errors = false;100 var prominent_compile_errors = false;
102 var help_menu = false;101 var help_menu = false;
103 var steps_menu = false;102 var steps_menu = false;
...@@ -188,7 +187,7 @@ pub fn main() !void {...@@ -188,7 +187,7 @@ pub fn main() !void {
188 } else if (mem.eql(u8, arg, "--seed")) {187 } else if (mem.eql(u8, arg, "--seed")) {
189 const next_arg = nextArg(args, &arg_idx) orelse188 const next_arg = nextArg(args, &arg_idx) orelse
190 fatalWithHint("expected u32 after '{s}'", .{arg});189 fatalWithHint("expected u32 after '{s}'", .{arg});
191 seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| {190 graph.random_seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| {
192 fatal("unable to parse seed '{s}' as unsigned 32-bit integer: {s}\n", .{191 fatal("unable to parse seed '{s}' as unsigned 32-bit integer: {s}\n", .{
193 next_arg, @errorName(err),192 next_arg, @errorName(err),
194 });193 });
...@@ -371,7 +370,7 @@ pub fn main() !void {...@@ -371,7 +370,7 @@ pub fn main() !void {
371 }370 }
372371
373 const gpa = arena;372 const gpa = arena;
374 prepare(gpa, arena, builder, targets.items, &run, seed) catch |err| switch (err) {373 prepare(gpa, arena, builder, targets.items, &run, graph.random_seed) catch |err| switch (err) {
375 error.UncleanExit => process.exit(1),374 error.UncleanExit => process.exit(1),
376 else => return err,375 else => return err,
377 };376 };
lib/compiler/test_runner.zig+3
...@@ -24,6 +24,9 @@ pub fn main() void {...@@ -24,6 +24,9 @@ pub fn main() void {
24 for (args[1..]) |arg| {24 for (args[1..]) |arg| {
25 if (std.mem.eql(u8, arg, "--listen=-")) {25 if (std.mem.eql(u8, arg, "--listen=-")) {
26 listen = true;26 listen = true;
27 } else if (std.mem.startsWith(u8, arg, "--seed=")) {
28 std.testing.random_seed = std.fmt.parseUnsigned(u32, arg["--seed=".len..], 0) catch
29 @panic("unable to parse --seed command line argument");
27 } else {30 } else {
28 @panic("unrecognized command line argument");31 @panic("unrecognized command line argument");
29 }32 }
lib/std/Build.zig+1
...@@ -121,6 +121,7 @@ pub const Graph = struct {...@@ -121,6 +121,7 @@ pub const Graph = struct {
121 /// Information about the native target. Computed before build() is invoked.121 /// Information about the native target. Computed before build() is invoked.
122 host: ResolvedTarget,122 host: ResolvedTarget,
123 incremental: ?bool = null,123 incremental: ?bool = null,
124 random_seed: u32 = 0,
124};125};
125126
126const AvailableDeps = []const struct { []const u8, []const u8 };127const AvailableDeps = []const struct { []const u8, []const u8 };
lib/std/Build/Step/Run.zig+6-1
...@@ -185,8 +185,13 @@ pub fn setName(run: *Run, name: []const u8) void {...@@ -185,8 +185,13 @@ pub fn setName(run: *Run, name: []const u8) void {
185}185}
186186
187pub fn enableTestRunnerMode(run: *Run) void {187pub fn enableTestRunnerMode(run: *Run) void {
188 const b = run.step.owner;
189 const arena = b.allocator;
188 run.stdio = .zig_test;190 run.stdio = .zig_test;
189 run.addArgs(&.{"--listen=-"});191 run.addArgs(&.{
192 std.fmt.allocPrint(arena, "--seed=0x{x}", .{b.graph.random_seed}) catch @panic("OOM"),
193 "--listen=-",
194 });
190}195}
191196
192pub fn addArtifactArg(run: *Run, artifact: *Step.Compile) void {197pub fn addArtifactArg(run: *Run, artifact: *Step.Compile) void {
lib/std/Random/ziggurat.zig+3-1
...@@ -126,7 +126,9 @@ pub fn norm_zero_case(random: Random, u: f64) f64 {...@@ -126,7 +126,9 @@ pub fn norm_zero_case(random: Random, u: f64) f64 {
126 }126 }
127}127}
128128
129test "normal dist sanity" {129test "normal dist smoke test" {
130 // Hardcode 0 as the seed because it's possible a seed exists that fails
131 // this test.
130 var prng = Random.DefaultPrng.init(0);132 var prng = Random.DefaultPrng.init(0);
131 const random = prng.random();133 const random = prng.random();
132134
lib/std/hash_map.zig+2-2
...@@ -1935,7 +1935,7 @@ test "put and remove loop in random order" {...@@ -1935,7 +1935,7 @@ test "put and remove loop in random order" {
1935 while (i < size) : (i += 1) {1935 while (i < size) : (i += 1) {
1936 try keys.append(i);1936 try keys.append(i);
1937 }1937 }
1938 var prng = std.Random.DefaultPrng.init(0);1938 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
1939 const random = prng.random();1939 const random = prng.random();
19401940
1941 while (i < iterations) : (i += 1) {1941 while (i < iterations) : (i += 1) {
...@@ -1967,7 +1967,7 @@ test "remove one million elements in random order" {...@@ -1967,7 +1967,7 @@ test "remove one million elements in random order" {
1967 keys.append(i) catch unreachable;1967 keys.append(i) catch unreachable;
1968 }1968 }
19691969
1970 var prng = std.Random.DefaultPrng.init(0);1970 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
1971 const random = prng.random();1971 const random = prng.random();
1972 random.shuffle(u32, keys.items);1972 random.shuffle(u32, keys.items);
19731973
lib/std/heap/arena_allocator.zig+1-1
...@@ -250,7 +250,7 @@ test "reset with preheating" {...@@ -250,7 +250,7 @@ test "reset with preheating" {
250 var arena_allocator = ArenaAllocator.init(std.testing.allocator);250 var arena_allocator = ArenaAllocator.init(std.testing.allocator);
251 defer arena_allocator.deinit();251 defer arena_allocator.deinit();
252 // provides some variance in the allocated data252 // provides some variance in the allocated data
253 var rng_src = std.Random.DefaultPrng.init(19930913);253 var rng_src = std.Random.DefaultPrng.init(std.testing.random_seed);
254 const random = rng_src.random();254 const random = rng_src.random();
255 var rounds: usize = 25;255 var rounds: usize = 25;
256 while (rounds > 0) {256 while (rounds > 0) {
lib/std/math/big/rational.zig+1-1
...@@ -594,7 +594,7 @@ test "toFloat" {...@@ -594,7 +594,7 @@ test "toFloat" {
594test "set/to Float round-trip" {594test "set/to Float round-trip" {
595 var a = try Rational.init(testing.allocator);595 var a = try Rational.init(testing.allocator);
596 defer a.deinit();596 defer a.deinit();
597 var prng = std.Random.DefaultPrng.init(0x5EED);597 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
598 const random = prng.random();598 const random = prng.random();
599 var i: usize = 0;599 var i: usize = 0;
600 while (i < 512) : (i += 1) {600 while (i < 512) : (i += 1) {
lib/std/os/linux/IoUring.zig+2-2
...@@ -3995,7 +3995,7 @@ test "ring mapped buffers recv" {...@@ -3995,7 +3995,7 @@ test "ring mapped buffers recv" {
3995 defer fds.close();3995 defer fds.close();
39963996
3997 // for random user_data in sqe/cqe3997 // for random user_data in sqe/cqe
3998 var Rnd = std.Random.DefaultPrng.init(0);3998 var Rnd = std.Random.DefaultPrng.init(std.testing.random_seed);
3999 var rnd = Rnd.random();3999 var rnd = Rnd.random();
40004000
4001 var round: usize = 4; // repeat send/recv cycle round times4001 var round: usize = 4; // repeat send/recv cycle round times
...@@ -4081,7 +4081,7 @@ test "ring mapped buffers multishot recv" {...@@ -4081,7 +4081,7 @@ test "ring mapped buffers multishot recv" {
4081 defer fds.close();4081 defer fds.close();
40824082
4083 // for random user_data in sqe/cqe4083 // for random user_data in sqe/cqe
4084 var Rnd = std.Random.DefaultPrng.init(0);4084 var Rnd = std.Random.DefaultPrng.init(std.testing.random_seed);
4085 var rnd = Rnd.random();4085 var rnd = Rnd.random();
40864086
4087 var round: usize = 4; // repeat send/recv cycle round times4087 var round: usize = 4; // repeat send/recv cycle round times
lib/std/priority_dequeue.zig+3-3
...@@ -866,7 +866,7 @@ test "shrinkAndFree" {...@@ -866,7 +866,7 @@ test "shrinkAndFree" {
866}866}
867867
868test "fuzz testing min" {868test "fuzz testing min" {
869 var prng = std.Random.DefaultPrng.init(0x12345678);869 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
870 const random = prng.random();870 const random = prng.random();
871871
872 const test_case_count = 100;872 const test_case_count = 100;
...@@ -895,7 +895,7 @@ fn fuzzTestMin(rng: std.Random, comptime queue_size: usize) !void {...@@ -895,7 +895,7 @@ fn fuzzTestMin(rng: std.Random, comptime queue_size: usize) !void {
895}895}
896896
897test "fuzz testing max" {897test "fuzz testing max" {
898 var prng = std.Random.DefaultPrng.init(0x87654321);898 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
899 const random = prng.random();899 const random = prng.random();
900900
901 const test_case_count = 100;901 const test_case_count = 100;
...@@ -924,7 +924,7 @@ fn fuzzTestMax(rng: std.Random, queue_size: usize) !void {...@@ -924,7 +924,7 @@ fn fuzzTestMax(rng: std.Random, queue_size: usize) !void {
924}924}
925925
926test "fuzz testing min and max" {926test "fuzz testing min and max" {
927 var prng = std.Random.DefaultPrng.init(0x87654321);927 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
928 const random = prng.random();928 const random = prng.random();
929929
930 const test_case_count = 100;930 const test_case_count = 100;
lib/std/sort.zig+2-2
...@@ -223,7 +223,7 @@ test "stable sort" {...@@ -223,7 +223,7 @@ test "stable sort" {
223}223}
224224
225test "stable sort fuzz testing" {225test "stable sort fuzz testing" {
226 var prng = std.Random.DefaultPrng.init(0x12345678);226 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
227 const random = prng.random();227 const random = prng.random();
228 const test_case_count = 10;228 const test_case_count = 10;
229229
...@@ -408,7 +408,7 @@ test "sort with context in the middle of a slice" {...@@ -408,7 +408,7 @@ test "sort with context in the middle of a slice" {
408}408}
409409
410test "sort fuzz testing" {410test "sort fuzz testing" {
411 var prng = std.Random.DefaultPrng.init(0x12345678);411 var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
412 const random = prng.random();412 const random = prng.random();
413 const test_case_count = 10;413 const test_case_count = 10;
414414
lib/std/testing.zig+5-1
...@@ -1,8 +1,12 @@...@@ -1,8 +1,12 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33const assert = std.debug.assert;
4const math = std.math;4const math = std.math;
55
6/// Provides deterministic randomness in unit tests.
7/// Initialized on startup. Read-only after that.
8pub var random_seed: u32 = 0;
9
6pub const FailingAllocator = @import("testing/failing_allocator.zig").FailingAllocator;10pub const FailingAllocator = @import("testing/failing_allocator.zig").FailingAllocator;
711
8/// This should only be used in temporary test programs.12/// This should only be used in temporary test programs.
src/main.zig+4-1
...@@ -4282,7 +4282,10 @@ fn runOrTest(...@@ -4282,7 +4282,10 @@ fn runOrTest(
4282 defer argv.deinit();4282 defer argv.deinit();
42834283
4284 if (test_exec_args.len == 0) {4284 if (test_exec_args.len == 0) {
4285 try argv.append(exe_path);4285 try argv.appendSlice(&.{
4286 exe_path,
4287 try std.fmt.allocPrint(arena, "--seed=0x{x}", .{std.crypto.random.int(u32)}),
4288 });
4286 } else {4289 } else {
4287 for (test_exec_args) |arg| {4290 for (test_exec_args) |arg| {
4288 try argv.append(arg orelse exe_path);4291 try argv.append(arg orelse exe_path);