diff --git a/core/testing/runner.odin b/core/testing/runner.odin index 759b23b0f..faba54286 100644 --- a/core/testing/runner.odin +++ b/core/testing/runner.odin @@ -9,6 +9,7 @@ import "core:encoding/base64" import "core:fmt" import "core:io" import pkg_log "core:log" +import "core:math/rand" import "core:mem" import "core:os" import "core:slice" @@ -38,6 +39,9 @@ FANCY_OUTPUT : bool : #config(ODIN_TEST_FANCY, true) USE_CLIPBOARD : bool : #config(ODIN_TEST_CLIPBOARD, false) // How many test results to show at a time per package. PROGRESS_WIDTH : int : #config(ODIN_TEST_PROGRESS_WIDTH, 24) +// This is the random seed that will be sent to each test. +// If it is unspecified, it will be set to the system cycle counter at startup. +SHARED_RANDOM_SEED : u64 : #config(ODIN_TEST_RANDOM_SEED, 0) end_t :: proc(t: ^T) { @@ -333,6 +337,12 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { defer bytes.buffer_destroy(&clipboard_buffer) } + when SHARED_RANDOM_SEED == 0 { + shared_random_seed := cast(u64)intrinsics.read_cycle_counter() + } else { + shared_random_seed := SHARED_RANDOM_SEED + } + // -- Setup initial tasks. // NOTE(Feoramund): This is the allocator that will be used by threads to @@ -356,6 +366,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { defer run_index += 1 data.it = it + data.t.seed = shared_random_seed #no_bounds_check data.t.channel = chan.as_send(task_channels[task_index].channel) data.t._log_allocator = shared_log_allocator data.allocator_index = task_index @@ -383,6 +394,8 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { draw_status_bar(stdout, thread_count_status_string, total_done_count, total_test_count) } + pkg_log.infof("The random seed sent to every test is: %v", shared_random_seed) + when TRACKING_MEMORY { when ALWAYS_REPORT_MEMORY { pkg_log.info("Memory tracking is enabled. Tests will log their memory usage when complete.") @@ -428,6 +441,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool { defer run_index += 1 data.it = it + data.t.seed = shared_random_seed data.t.error_count = 0 thread.pool_add_task(&pool, task.allocator, run_test_task, data, run_index) diff --git a/core/testing/testing.odin b/core/testing/testing.odin index 30109304d..92b4d391d 100644 --- a/core/testing/testing.odin +++ b/core/testing/testing.odin @@ -29,6 +29,16 @@ Internal_Cleanup :: struct { T :: struct { error_count: int, + // If your test needs to perform random operations, it's advised to use + // this value to seed a local random number generator rather than relying + // on the non-thread-safe global one. + // + // This way, your results will be deterministic. + // + // This value is chosen at startup of the test runner, logged, and may be + // specified by the user. It is the same for all tests of a single run. + seed: u64, + channel: Update_Channel_Sender, cleanups: [dynamic]Internal_Cleanup,