aboutsummaryrefslogtreecommitdiff
path: root/test/functional/lua/watch_spec.lua
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2024-09-30 15:25:44 +0200
committerJustin M. Keyes <justinkz@gmail.com>2024-10-02 16:41:01 +0200
commit9e23b4e1852f9ad6418b45f827d1fb160611d8cf (patch)
tree6b4a20275919f355d3c3bdc3e0d4867da176938e /test/functional/lua/watch_spec.lua
parent391c5084d1181a6742ebd8551efda4db7e8ca46e (diff)
downloadrneovim-9e23b4e1852f9ad6418b45f827d1fb160611d8cf.tar.gz
rneovim-9e23b4e1852f9ad6418b45f827d1fb160611d8cf.tar.bz2
rneovim-9e23b4e1852f9ad6418b45f827d1fb160611d8cf.zip
fix(watch): ignore nonexistent paths (ENOENT)
Problem: The `_watch.watch()` strategy may fail if the given path does not exist: …/vim/_watch.lua:101: ENOENT: no such file or directory stack traceback: [C]: in function 'assert' …/vim/_watch.lua:101: in function <…/vim/_watch.lua:61> [string "<nvim>"]:5: in main chunk - `_watch.watch()` actively asserts any error returned by `handle:start()`. - whereas `_watch.watchdirs()` just ignores the result of `root_handle:start()`. Servers may send "client/registerCapability" with "workspace/didChangeWatchedFiles" item(s) (`baseUri`) which do not actually exist on the filesystem: https://github.com/neovim/neovim/issues/28058#issuecomment-2189929424 { method = "client/registerCapability", params = { registrations = { { method = "workspace/didChangeWatchedFiles", registerOptions = { watchers = { { globPattern = { baseUri = "file:///Users/does/not/exist", pattern = "**/*.{ts,js,mts,mjs,cjs,cts,json,svelte}" } }, ... } Solution: - Remove the assert in `_watch.watch()`. - Show a once-only message for both cases. - More detailed logging is blocked until we have `nvim_log` / `vim.log`. fix #28058
Diffstat (limited to 'test/functional/lua/watch_spec.lua')
-rw-r--r--test/functional/lua/watch_spec.lua92
1 files changed, 64 insertions, 28 deletions
diff --git a/test/functional/lua/watch_spec.lua b/test/functional/lua/watch_spec.lua
index ab6b1416aa..a1e4a42ebe 100644
--- a/test/functional/lua/watch_spec.lua
+++ b/test/functional/lua/watch_spec.lua
@@ -21,16 +21,72 @@ describe('vim._watch', function()
end)
local function run(watchfunc)
- it('detects file changes (watchfunc=' .. watchfunc .. '())', function()
+ -- Monkey-patches vim.notify_once so we can "spy" on it.
+ local function spy_notify_once()
+ exec_lua [[
+ _G.__notify_once_msgs = {}
+ vim.notify_once = (function(overridden)
+ return function(msg, level, opts)
+ table.insert(_G.__notify_once_msgs, msg)
+ return overridden(msg, level, opts)
+ end
+ end)(vim.notify_once)
+ ]]
+ end
+
+ local function last_notify_once_msg()
+ return exec_lua 'return _G.__notify_once_msgs[#_G.__notify_once_msgs]'
+ end
+
+ local function do_watch(root_dir, watchfunc_)
+ exec_lua(
+ [[
+ local root_dir, watchfunc = ...
+
+ _G.events = {}
+
+ _G.stop_watch = vim._watch[watchfunc](root_dir, {
+ debounce = 100,
+ include_pattern = vim.lpeg.P(root_dir) * vim.lpeg.P("/file") ^ -1,
+ exclude_pattern = vim.lpeg.P(root_dir .. '/file.unwatched'),
+ }, function(path, change_type)
+ table.insert(_G.events, { path = path, change_type = change_type })
+ end)
+ ]],
+ root_dir,
+ watchfunc_
+ )
+ end
+
+ it(watchfunc .. '() ignores nonexistent paths', function()
+ if watchfunc == 'inotify' then
+ skip(n.fn.executable('inotifywait') == 0, 'inotifywait not found')
+ skip(is_os('bsd'), 'inotifywait on bsd CI seems to expect path to exist?')
+ end
+
+ local msg = ('watch.%s: ENOENT: no such file or directory'):format(watchfunc)
+
+ spy_notify_once()
+ do_watch('/i am /very/funny.go', watchfunc)
+
+ if watchfunc ~= 'inotify' then -- watch.inotify() doesn't (currently) call vim.notify_once.
+ t.retry(nil, 2000, function()
+ t.eq(msg, last_notify_once_msg())
+ end)
+ end
+ eq(0, exec_lua [[return #_G.events]])
+
+ exec_lua [[_G.stop_watch()]]
+ end)
+
+ it(watchfunc .. '() detects file changes', function()
if watchfunc == 'inotify' then
skip(is_os('win'), 'not supported on windows')
skip(is_os('mac'), 'flaky test on mac')
- skip(
- not is_ci() and n.fn.executable('inotifywait') == 0,
- 'inotify-tools not installed and not on CI'
- )
+ skip(not is_ci() and n.fn.executable('inotifywait') == 0, 'inotifywait not found')
end
+ -- Note: because this is not `elseif`, BSD is skipped for *all* cases...?
if watchfunc == 'watch' then
skip(is_os('mac'), 'flaky test on mac')
skip(is_os('bsd'), 'Stopped working on bsd after 3ca967387c49c754561c3b11a574797504d40f38')
@@ -41,10 +97,8 @@ describe('vim._watch', function()
)
end
- local root_dir = vim.uv.fs_mkdtemp(vim.fs.dirname(t.tmpname(false)) .. '/nvim_XXXXXXXXXX')
-
local expected_events = 0
-
+ --- Waits for a new event, or fails if no events are triggered.
local function wait_for_event()
expected_events = expected_events + 1
exec_lua(
@@ -65,26 +119,11 @@ describe('vim._watch', function()
)
end
+ local root_dir = vim.uv.fs_mkdtemp(vim.fs.dirname(t.tmpname(false)) .. '/nvim_XXXXXXXXXX')
local unwatched_path = root_dir .. '/file.unwatched'
local watched_path = root_dir .. '/file'
- exec_lua(
- [[
- local root_dir, watchfunc = ...
-
- _G.events = {}
-
- _G.stop_watch = vim._watch[watchfunc](root_dir, {
- debounce = 100,
- include_pattern = vim.lpeg.P(root_dir) * vim.lpeg.P("/file") ^ -1,
- exclude_pattern = vim.lpeg.P(root_dir .. '/file.unwatched'),
- }, function(path, change_type)
- table.insert(_G.events, { path = path, change_type = change_type })
- end)
- ]],
- root_dir,
- watchfunc
- )
+ do_watch(root_dir, watchfunc)
if watchfunc ~= 'watch' then
vim.uv.sleep(200)
@@ -92,16 +131,13 @@ describe('vim._watch', function()
touch(watched_path)
touch(unwatched_path)
-
wait_for_event()
os.remove(watched_path)
os.remove(unwatched_path)
-
wait_for_event()
exec_lua [[_G.stop_watch()]]
-
-- No events should come through anymore
vim.uv.sleep(100)