From: Brendan Hansen Date: Fri, 3 Dec 2021 04:45:28 +0000 (-0600) Subject: multi-threaded the test runner X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=3cecfbb2367006057b5af2c65f6abdf391fefe3b;p=onyx.git multi-threaded the test runner --- diff --git a/scripts/run_tests.onyx b/scripts/run_tests.onyx index 4cda81e9..73c88d97 100644 --- a/scripts/run_tests.onyx +++ b/scripts/run_tests.onyx @@ -85,34 +85,98 @@ find_onyx_files :: (root: str, cases: ^[..] str) { return; } +#if false { + divide_array :: (arr: [] $T, divisions: [] [] T) { + if divisions.count == 0 do return; + + chunk_size := arr.count / divisions.count; + + i := 0; + for ^ divisions { + low := i*chunk_size; + high := (i+1)*chunk_size; + if i == divisions.count - 1 do high = divisions.count; + *it = arr[low .. high]; + i += 1; + } + } +} + +distributor :: (arr: [] $T) -> Iterator(T) { + Context :: struct (T: type_expr) { + mutex: sync.Mutex; + arr: [] T; + curr_pos: i32; + } + + next :: (use c: ^Context($T)) -> (T, bool) { + sync.scoped_mutex(^mutex); + + use package core.intrinsics.onyx {__zero_value} + if curr_pos >= arr.count do return __zero_value(T), false; + + defer curr_pos += 1; + return arr[curr_pos], true; + } + + close :: (use c: ^Context($T)) { + // This will leak because it shouldn't be freed. + } + + c := new(Context(T)); + sync.mutex_init(^c.mutex); + c.arr = arr; + c.curr_pos = 0; + + return .{ c, #solidify next {T=T}, #solidify close {T=T}}; +} + main :: (args) => { test_folder := "./tests"; - onyx_cmd: str; + #persist onyx_cmd: str; switch runtime.OS { - case runtime.OS_Linux do onyx_cmd = "./bin/onyx"; + case runtime.OS_Linux { + onyx_cmd = "./bin/onyx"; + if args.count > 1 { + if string.from_cstr(args[1]) == "debug" do onyx_cmd = "./bin/onyx-debug"; + } + } case runtime.OS_Windows do onyx_cmd = "onyx.exe"; } + test_cases :: (cases) => { + for *cases { + printf("[{}] Running test {}...\n", context.thread_id, it); + + proc := io.process_spawn(onyx_cmd, .["run", it]); + defer io.process_destroy(^proc); + + proc_reader := io.reader_make(^proc); + output := io.read_all(^proc_reader); + defer memory.free_slice(^output); + + if exit := io.process_wait(^proc); exit != .Success { + // Error running the test case + println(exit); + println(output); + } + } + } + cases := array.make(str); find_onyx_files(test_folder, ^cases); - for cases { - printf("Running test {}...\n", it); - proc := io.process_spawn(onyx_cmd, .["run", it]); - defer io.process_destroy(^proc); + Thread_Count :: 3 + #persist threads: [Thread_Count] thread.Thread; - proc_reader := io.reader_make(^proc); - output := io.read_all(^proc_reader); - defer memory.free_slice(^output); + case_iterator := distributor(cases); - if exit := io.process_wait(^proc); exit != .Success { - // Error running the test case - println(exit); - println(output); - } + for Thread_Count { + thread.spawn(^threads[it], ^case_iterator, test_cases); } - // Ensure the corresponding correct output file present - // Run tests, checking their output + test_cases(^case_iterator); + for ^ threads do thread.join(it); + println("Done"); } \ No newline at end of file