From 2b7e722f4d060f26b7883d7697b3a9f294ebdbeb Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Mon, 16 Mar 2026 20:56:11 -0400 Subject: [PATCH] fix(test): resolve trash_spec.lua flakes from leaked mutation state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: `mutation_in_progress` and `buffers_locked` are module-level locals in `mutator/init.lua` and `view.lua`. When a trash test times out mid-mutation, these flags stay true and `reset_editor()` never clears them. Subsequent tests' `save()` calls bail on `mutation_in_progress`, silently skipping mutations so `OilMutationComplete` never fires — causing cascading 10s timeouts. Solution: Add `mutator.reset()` to clear leaked mutation state, and call it from `reset_editor()` when `is_mutating()` is true. A 50ms event loop drain lets in-flight libuv callbacks settle before the reset. Baseline: 4/10 sequential passes. After fix: 49/50 parallel passes with zero timing overhead on the happy path (~2.4s). --- lua/oil/mutator/init.lua | 4 ++++ spec/test_util.lua | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/lua/oil/mutator/init.lua b/lua/oil/mutator/init.lua index 5a36a63..4170398 100644 --- a/lua/oil/mutator/init.lua +++ b/lua/oil/mutator/init.lua @@ -510,6 +510,10 @@ M.is_mutating = function() return mutation_in_progress end +M.reset = function() + mutation_in_progress = false +end + ---@param confirm nil|boolean ---@param cb? fun(err: nil|string) M.try_write_changes = function(confirm, cb) diff --git a/spec/test_util.lua b/spec/test_util.lua index 57f81b1..f5dd94a 100644 --- a/spec/test_util.lua +++ b/spec/test_util.lua @@ -17,6 +17,14 @@ M.reset_editor = function() for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do vim.api.nvim_buf_delete(bufnr, { force = true }) end + local mutator = require('oil.mutator') + if mutator.is_mutating() then + vim.wait(50, function() + return not mutator.is_mutating() + end, 10) + mutator.reset() + require('oil.view').unlock_buffers() + end cache.clear_everything() test_adapter.test_clear() end