aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorFeoramund <161657516+Feoramund@users.noreply.github.com>2024-05-29 18:04:59 -0400
committerFeoramund <161657516+Feoramund@users.noreply.github.com>2024-06-02 14:47:07 -0400
commit1f6a6f2cd367aec2e506ae8d5fafcb34d4b2a0e3 (patch)
treef7b377de19693f1ab649946f267c437e99ed59fe /core
parenta27b16721893f78f1788c4f8a7a952d65f7799c3 (diff)
Support deterministic random seeding of tests
Add a new option `ODIN_TEST_RANDOM_SEED` which is picked from the cycle counter at startup, if it's not specified by the user. This number is sent to every test in the `T` struct and reset every test (just in case).
Diffstat (limited to 'core')
-rw-r--r--core/testing/runner.odin14
-rw-r--r--core/testing/testing.odin10
2 files changed, 24 insertions, 0 deletions
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,