From dcb99857ca72702ee4bb9d8a120a360fb21269f2 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Thu, 26 Feb 2026 22:54:06 -0500 Subject: [PATCH] feat(runner): run test cases in parallel Problem: test cases were executed sequentially, each waiting for the previous process to finish before starting the next. On problems with many test cases this meant wall-clock run time scaled linearly. Solution: fan out all test case processes simultaneously. A remaining counter fires on_done once all callbacks have returned. on_each is called per completion as before; callers that pass on_each ignore its arguments so the index semantics change is non-breaking. --- lua/cp/runner/run.lua | 45 ++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/lua/cp/runner/run.lua b/lua/cp/runner/run.lua index 36a560c..4e4a8f6 100644 --- a/lua/cp/runner/run.lua +++ b/lua/cp/runner/run.lua @@ -276,26 +276,35 @@ function M.run_all_test_cases(indices, debug, on_each, on_done) end end - local function run_next(pos) - if pos > #to_run then - logger.log( - ('Finished %s %d test cases.'):format(debug and 'debugging' or 'running', #to_run), - vim.log.levels.INFO, - true - ) - on_done(panel_state.test_cases) - return - end - - M.run_test_case(to_run[pos], debug, function() - if on_each then - on_each(pos, #to_run) - end - run_next(pos + 1) - end) + if #to_run == 0 then + logger.log( + ('Finished %s %d test cases.'):format(debug and 'debugging' or 'running', 0), + vim.log.levels.INFO, + true + ) + on_done(panel_state.test_cases) + return end - run_next(1) + local total = #to_run + local remaining = total + + for _, idx in ipairs(to_run) do + M.run_test_case(idx, debug, function() + if on_each then + on_each(idx, total) + end + remaining = remaining - 1 + if remaining == 0 then + logger.log( + ('Finished %s %d test cases.'):format(debug and 'debugging' or 'running', total), + vim.log.levels.INFO, + true + ) + on_done(panel_state.test_cases) + end + end) + end end ---@return PanelState