diff options
author | Josh Rahm <rahm@google.com> | 2022-07-18 19:37:18 +0000 |
---|---|---|
committer | Josh Rahm <rahm@google.com> | 2022-07-18 19:37:18 +0000 |
commit | 308e1940dcd64aa6c344c403d4f9e0dda58d9c5c (patch) | |
tree | 35fe43e01755e0f312650667004487a44d6b7941 /test/functional/autocmd | |
parent | 96a00c7c588b2f38a2424aeeb4ea3581d370bf2d (diff) | |
parent | e8c94697bcbe23a5c7b07c292b90a6b70aadfa87 (diff) | |
download | rneovim-308e1940dcd64aa6c344c403d4f9e0dda58d9c5c.tar.gz rneovim-308e1940dcd64aa6c344c403d4f9e0dda58d9c5c.tar.bz2 rneovim-308e1940dcd64aa6c344c403d4f9e0dda58d9c5c.zip |
Merge remote-tracking branch 'upstream/master' into rahm
Diffstat (limited to 'test/functional/autocmd')
-rw-r--r-- | test/functional/autocmd/autocmd_oldtest_spec.lua | 86 | ||||
-rw-r--r-- | test/functional/autocmd/autocmd_spec.lua | 223 | ||||
-rw-r--r-- | test/functional/autocmd/cursormoved_spec.lua | 1 | ||||
-rw-r--r-- | test/functional/autocmd/dirchanged_spec.lua | 128 | ||||
-rw-r--r-- | test/functional/autocmd/focus_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/autocmd/show_spec.lua | 183 | ||||
-rw-r--r-- | test/functional/autocmd/signal_spec.lua | 6 | ||||
-rw-r--r-- | test/functional/autocmd/termxx_spec.lua | 26 | ||||
-rw-r--r-- | test/functional/autocmd/winscrolled_spec.lua | 103 |
9 files changed, 697 insertions, 61 deletions
diff --git a/test/functional/autocmd/autocmd_oldtest_spec.lua b/test/functional/autocmd/autocmd_oldtest_spec.lua new file mode 100644 index 0000000000..ad3687d7b0 --- /dev/null +++ b/test/functional/autocmd/autocmd_oldtest_spec.lua @@ -0,0 +1,86 @@ +local helpers = require('test.functional.helpers')(after_each) + +local clear = helpers.clear +local eq = helpers.eq +local meths = helpers.meths +local funcs = helpers.funcs + +local exec = function(str) + meths.exec(str, false) +end + +describe('oldtests', function() + before_each(clear) + + local exec_lines = function(str) + return funcs.split(funcs.execute(str), "\n") + end + + local add_an_autocmd = function() + exec [[ + augroup vimBarTest + au BufReadCmd * echo 'hello' + augroup END + ]] + + eq(3, #exec_lines('au vimBarTest')) + eq(1, #meths.get_autocmds({ group = 'vimBarTest' })) + end + + it('should recognize a bar before the {event}', function() + -- Good spacing + add_an_autocmd() + exec [[ augroup vimBarTest | au! | augroup END ]] + eq(1, #exec_lines('au vimBarTest')) + eq({}, meths.get_autocmds({ group = 'vimBarTest' })) + + -- Sad spacing + add_an_autocmd() + exec [[ augroup vimBarTest| au!| augroup END ]] + eq(1, #exec_lines('au vimBarTest')) + + + -- test that a bar is recognized after the {event} + add_an_autocmd() + exec [[ augroup vimBarTest| au!BufReadCmd| augroup END ]] + eq(1, #exec_lines('au vimBarTest')) + + add_an_autocmd() + exec [[ au! vimBarTest|echo 'hello' ]] + eq(1, #exec_lines('au vimBarTest')) + end) + + it('should fire on unload buf', function() + funcs.writefile({'Test file Xxx1'}, 'Xxx1') + funcs.writefile({'Test file Xxx2'}, 'Xxx2') + + local content = [[ + func UnloadAllBufs() + let i = 1 + while i <= bufnr('$') + if i != bufnr('%') && bufloaded(i) + exe i . 'bunload' + endif + let i += 1 + endwhile + endfunc + au BufUnload * call UnloadAllBufs() + au VimLeave * call writefile(['Test Finished'], 'Xout') + set nohidden + edit Xxx1 + split Xxx2 + q + ]] + + funcs.writefile(funcs.split(content, "\n"), 'Xtest') + + funcs.delete('Xout') + funcs.system(meths.get_vvar('progpath') .. ' -u NORC -i NONE -N -S Xtest') + eq(1, funcs.filereadable('Xout')) + + funcs.delete('Xxx1') + funcs.delete('Xxx2') + funcs.delete('Xtest') + funcs.delete('Xout') + end) +end) diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 93d71a9e45..90254b7415 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -2,8 +2,10 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local assert_visible = helpers.assert_visible +local assert_alive = helpers.assert_alive local dedent = helpers.dedent local eq = helpers.eq +local neq = helpers.neq local eval = helpers.eval local feed = helpers.feed local clear = helpers.clear @@ -13,7 +15,9 @@ local funcs = helpers.funcs local expect = helpers.expect local command = helpers.command local exc_exec = helpers.exc_exec +local exec_lua = helpers.exec_lua local curbufmeths = helpers.curbufmeths +local retry = helpers.retry local source = helpers.source describe('autocmd', function() @@ -56,6 +60,23 @@ describe('autocmd', function() eq(expected, eval('g:evs')) end) + it('first edit causes BufUnload on NoName', function() + local expected = { + {'BufUnload', ''}, + {'BufDelete', ''}, + {'BufWipeout', ''}, + {'BufEnter', 'testfile1'}, + } + command('let g:evs = []') + command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("<afile>")])') + command('autocmd BufDelete * :call add(g:evs, ["BufDelete", expand("<afile>")])') + command('autocmd BufLeave * :call add(g:evs, ["BufLeave", expand("<afile>")])') + command('autocmd BufUnload * :call add(g:evs, ["BufUnload", expand("<afile>")])') + command('autocmd BufWipeout * :call add(g:evs, ["BufWipeout", expand("<afile>")])') + command('edit testfile1') + eq(expected, eval('g:evs')) + end) + it('WinClosed is non-recursive', function() command('let g:triggered = 0') command('autocmd WinClosed * :let g:triggered+=1 | :bdelete 2') @@ -333,6 +354,87 @@ describe('autocmd', function() pcall_err(command, "call nvim_set_current_win(g:winid)")) end) + it("`aucmd_win` cannot be changed into a normal window #13699", function() + local screen = Screen.new(50, 10) + screen:attach() + screen:set_default_attr_ids { + [1] = {bold = true, foreground = Screen.colors.Blue1}, + [2] = {reverse = true}, + [3] = {bold = true, reverse = true}, + } + + -- Create specific layout and ensure it's left unchanged. + -- Use nvim_buf_call on a hidden buffer so aucmd_win is used. + exec_lua [[ + vim.cmd "wincmd s | wincmd _" + _G.buf = vim.api.nvim_create_buf(true, true) + vim.api.nvim_buf_call(_G.buf, function() vim.cmd "wincmd J" end) + ]] + screen:expect [[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {3:[No Name] }| + | + {2:[No Name] }| + | + ]] + -- This used to crash after making aucmd_win a normal window via the above. + exec_lua [[ + vim.cmd "tabnew | tabclose # | wincmd s | wincmd _" + vim.api.nvim_buf_call(_G.buf, function() vim.cmd "wincmd K" end) + ]] + assert_alive() + screen:expect_unchanged() + + -- Ensure splitting still works from inside the aucmd_win. + exec_lua [[vim.api.nvim_buf_call(_G.buf, function() vim.cmd "split" end)]] + screen:expect [[ + ^ | + {1:~ }| + {3:[No Name] }| + | + {1:~ }| + {2:[Scratch] }| + | + {1:~ }| + {2:[No Name] }| + | + ]] + + -- After all of our messing around, aucmd_win should still be floating. + -- Use :only to ensure _G.buf is hidden again (so the aucmd_win is used). + eq("editor", exec_lua [[ + vim.cmd "only" + vim.api.nvim_buf_call(_G.buf, function() + _G.config = vim.api.nvim_win_get_config(0) + end) + return _G.config.relative + ]]) + end) + + describe('closing last non-floating window in tab from `aucmd_win`', function() + before_each(function() + command('edit Xa.txt') + command('tabnew Xb.txt') + command('autocmd BufAdd Xa.txt 1close') + end) + + it('gives E814 when there are no other floating windows', function() + eq('Vim(close):E814: Cannot close window, only autocmd window would remain', + pcall_err(command, 'doautoall BufAdd')) + end) + + it('gives E814 when there are other floating windows', function() + meths.open_win(0, true, {width = 10, height = 10, relative = 'editor', row = 10, col = 10}) + eq('Vim(close):E814: Cannot close window, only autocmd window would remain', + pcall_err(command, 'doautoall BufAdd')) + end) + end) + it(':doautocmd does not warn "No matching autocommands" #10689', function() local screen = Screen.new(32, 3) screen:attach() @@ -354,4 +456,125 @@ describe('autocmd', function() :doautocmd SessionLoadPost | ]]} end) + + describe('v:event is readonly #18063', function() + it('during ChanOpen event', function() + command('autocmd ChanOpen * let v:event.info.id = 0') + funcs.jobstart({'cat'}) + retry(nil, nil, function() + eq('E46: Cannot change read-only variable "v:event.info"', meths.get_vvar('errmsg')) + end) + end) + + it('during ChanOpen event', function() + command('autocmd ChanInfo * let v:event.info.id = 0') + meths.set_client_info('foo', {}, 'remote', {}, {}) + retry(nil, nil, function() + eq('E46: Cannot change read-only variable "v:event.info"', meths.get_vvar('errmsg')) + end) + end) + + it('during RecordingLeave event', function() + command([[autocmd RecordingLeave * let v:event.regname = '']]) + eq('Vim(let):E46: Cannot change read-only variable "v:event.regname"', + pcall_err(command, 'normal! qqq')) + end) + + it('during TermClose event', function() + command('autocmd TermClose * let v:event.status = 0') + command('terminal') + eq('Vim(let):E46: Cannot change read-only variable "v:event.status"', + pcall_err(command, 'bdelete!')) + end) + end) + + describe('old_tests', function() + it('vimscript: WinNew ++once', function() + source [[ + " Without ++once WinNew triggers twice + let g:did_split = 0 + augroup Testing + au! + au WinNew * let g:did_split += 1 + augroup END + split + split + call assert_equal(2, g:did_split) + call assert_true(exists('#WinNew')) + close + close + + " With ++once WinNew triggers once + let g:did_split = 0 + augroup Testing + au! + au WinNew * ++once let g:did_split += 1 + augroup END + split + split + call assert_equal(1, g:did_split) + call assert_false(exists('#WinNew')) + close + close + + call assert_fails('au WinNew * ++once ++once echo bad', 'E983:') + ]] + + meths.set_var('did_split', 0) + + source [[ + augroup Testing + au! + au WinNew * let g:did_split += 1 + augroup END + + split + split + ]] + + eq(2, meths.get_var('did_split')) + eq(1, funcs.exists('#WinNew')) + + -- Now with once + meths.set_var('did_split', 0) + + source [[ + augroup Testing + au! + au WinNew * ++once let g:did_split += 1 + augroup END + + split + split + ]] + + eq(1, meths.get_var('did_split')) + eq(0, funcs.exists('#WinNew')) + + -- call assert_fails('au WinNew * ++once ++once echo bad', 'E983:') + local ok, msg = pcall(source, [[ + au WinNew * ++once ++once echo bad + ]]) + + eq(false, ok) + eq(true, not not string.find(msg, 'E983:')) + end) + + it('should have autocmds in filetypedetect group', function() + source [[filetype on]] + neq({}, meths.get_autocmds { group = "filetypedetect" }) + end) + + it('should allow comma-separated patterns', function() + source [[ + augroup TestingPatterns + au! + autocmd BufReadCmd *.shada,*.shada.tmp.[a-z] echo 'hello' + autocmd BufReadCmd *.shada,*.shada.tmp.[a-z] echo 'hello' + augroup END + ]] + + eq(4, #meths.get_autocmds { event = "BufReadCmd", group = "TestingPatterns" }) + end) + end) end) diff --git a/test/functional/autocmd/cursormoved_spec.lua b/test/functional/autocmd/cursormoved_spec.lua index 9641d4b096..85d8628d7e 100644 --- a/test/functional/autocmd/cursormoved_spec.lua +++ b/test/functional/autocmd/cursormoved_spec.lua @@ -35,6 +35,7 @@ describe('CursorMoved', function() it("is not triggered by cursor movement prior to first CursorMoved instantiation", function() source([[ let g:cursormoved = 0 + autocmd! CursorMoved autocmd CursorMoved * let g:cursormoved += 1 ]]) eq(0, eval('g:cursormoved')) diff --git a/test/functional/autocmd/dirchanged_spec.lua b/test/functional/autocmd/dirchanged_spec.lua index f4a1642ebf..45dc06b39b 100644 --- a/test/functional/autocmd/dirchanged_spec.lua +++ b/test/functional/autocmd/dirchanged_spec.lua @@ -8,7 +8,7 @@ local eval = h.eval local request = h.request local iswin = h.iswin -describe('autocmd DirChanged', function() +describe('autocmd DirChanged and DirChangedPre', function() local curdir = string.gsub(lfs.currentdir(), '\\', '/') local dirs = { curdir .. '/Xtest-functional-autocmd-dirchanged.dir1', @@ -26,31 +26,43 @@ describe('autocmd DirChanged', function() before_each(function() clear() + command('autocmd DirChangedPre * let [g:evpre, g:amatchpre, g:cdprecount] ' + ..'= [copy(v:event), expand("<amatch>"), 1 + get(g:, "cdprecount", 0)]') command('autocmd DirChanged * let [g:getcwd, g:ev, g:amatch, g:cdcount] ' - ..' = [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 0)]') + ..'= [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 0)]') -- Normalize path separators. + command([[autocmd DirChangedPre * let g:evpre['directory'] = substitute(g:evpre['directory'], '\\', '/', 'g')]]) command([[autocmd DirChanged * let g:ev['cwd'] = substitute(g:ev['cwd'], '\\', '/', 'g')]]) - command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]]) + command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]]) end) - it('sets v:event and <amatch>', function() + it('set v:event and <amatch>', function() command('lcd '..dirs[1]) + eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev')) + eq('window', eval('g:amatchpre')) eq('window', eval('g:amatch')) + eq(1, eval('g:cdprecount')) eq(1, eval('g:cdcount')) command('tcd '..dirs[2]) + eq({directory=dirs[2], scope='tabpage', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[2], scope='tabpage', changed_window=false}, eval('g:ev')) + eq('tabpage', eval('g:amatchpre')) eq('tabpage', eval('g:amatch')) + eq(2, eval('g:cdprecount')) eq(2, eval('g:cdcount')) command('cd '..dirs[3]) + eq({directory=dirs[3], scope='global', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[3], scope='global', changed_window=false}, eval('g:ev')) + eq('global', eval('g:amatchpre')) eq('global', eval('g:amatch')) + eq(3, eval('g:cdprecount')) eq(3, eval('g:cdcount')) end) - it('sets getcwd() during event #6260', function() + it('DirChanged set getcwd() during event #6260', function() command('lcd '..dirs[1]) eq(dirs[1], eval('g:getcwd')) @@ -61,7 +73,7 @@ describe('autocmd DirChanged', function() eq(dirs[3], eval('g:getcwd')) end) - it('disallows recursion', function() + it('disallow recursion', function() command('set shellslash') -- Set up a _nested_ handler. command('autocmd DirChanged * nested lcd '..dirs[3]) @@ -72,23 +84,36 @@ describe('autocmd DirChanged', function() eq(dirs[3], eval('getcwd()')) end) - it('does not trigger if :cd fails', function() + it('only DirChangedPre is triggered if :cd fails', function() command('let g:ev = {}') + command('let g:cdcount = 0') local status1, err1 = pcall(function() - command('lcd '..dirs[1] .. '/doesnotexist') + command('lcd '..dirs[1]..'/doesnotexist') end) + eq({directory=dirs[1]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre')) eq({}, eval('g:ev')) + eq('window', eval('g:amatchpre')) + eq(1, eval('g:cdprecount')) + eq(0, eval('g:cdcount')) local status2, err2 = pcall(function() - command('lcd '..dirs[2] .. '/doesnotexist') + command('lcd '..dirs[2]..'/doesnotexist') end) + eq({directory=dirs[2]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre')) eq({}, eval('g:ev')) + eq('window', eval('g:amatchpre')) + eq(2, eval('g:cdprecount')) + eq(0, eval('g:cdcount')) local status3, err3 = pcall(function() - command('lcd '..dirs[3] .. '/doesnotexist') + command('lcd '..dirs[3]..'/doesnotexist') end) + eq({directory=dirs[3]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre')) eq({}, eval('g:ev')) + eq('window', eval('g:amatchpre')) + eq(3, eval('g:cdprecount')) + eq(0, eval('g:cdcount')) eq(false, status1) eq(false, status2) @@ -99,85 +124,121 @@ describe('autocmd DirChanged', function() eq('E344:', string.match(err3, "E%d*:")) end) - it("is triggered by 'autochdir'", function() + it("are triggered by 'autochdir'", function() command('set autochdir') command('split '..dirs[1]..'/foo') + eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev')) + eq('auto', eval('g:amatchpre')) eq('auto', eval('g:amatch')) + eq(1, eval('g:cdprecount')) + eq(1, eval('g:cdcount')) command('split '..dirs[2]..'/bar') + eq({directory=dirs[2], scope='window', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[2], scope='window', changed_window=false}, eval('g:ev')) eq('auto', eval('g:amatch')) - + eq(2, eval('g:cdprecount')) eq(2, eval('g:cdcount')) end) - it('does not trigger if directory has not changed', function() + it('do not trigger if directory has not changed', function() command('lcd '..dirs[1]) + eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev')) + eq('window', eval('g:amatchpre')) eq('window', eval('g:amatch')) + eq(1, eval('g:cdprecount')) eq(1, eval('g:cdcount')) + command('let g:evpre = {}') command('let g:ev = {}') command('lcd '..dirs[1]) + eq({}, eval('g:evpre')) eq({}, eval('g:ev')) + eq(1, eval('g:cdprecount')) eq(1, eval('g:cdcount')) if iswin() then command('lcd '..win_dirs[1]) + eq({}, eval('g:evpre')) eq({}, eval('g:ev')) + eq(1, eval('g:cdprecount')) eq(1, eval('g:cdcount')) end command('tcd '..dirs[2]) + eq({directory=dirs[2], scope='tabpage', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[2], scope='tabpage', changed_window=false}, eval('g:ev')) + eq('tabpage', eval('g:amatchpre')) eq('tabpage', eval('g:amatch')) + eq(2, eval('g:cdprecount')) eq(2, eval('g:cdcount')) + command('let g:evpre = {}') command('let g:ev = {}') command('tcd '..dirs[2]) + eq({}, eval('g:evpre')) eq({}, eval('g:ev')) + eq(2, eval('g:cdprecount')) eq(2, eval('g:cdcount')) if iswin() then command('tcd '..win_dirs[2]) + eq({}, eval('g:evpre')) eq({}, eval('g:ev')) + eq(2, eval('g:cdprecount')) eq(2, eval('g:cdcount')) end command('cd '..dirs[3]) + eq({directory=dirs[3], scope='global', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[3], scope='global', changed_window=false}, eval('g:ev')) eq('global', eval('g:amatch')) + eq(3, eval('g:cdprecount')) eq(3, eval('g:cdcount')) + command('let g:evpre = {}') command('let g:ev = {}') command('cd '..dirs[3]) + eq({}, eval('g:evpre')) eq({}, eval('g:ev')) + eq(3, eval('g:cdprecount')) eq(3, eval('g:cdcount')) if iswin() then command('cd '..win_dirs[3]) + eq({}, eval('g:evpre')) eq({}, eval('g:ev')) + eq(3, eval('g:cdprecount')) eq(3, eval('g:cdcount')) end command('set autochdir') command('split '..dirs[1]..'/foo') + eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev')) + eq('auto', eval('g:amatchpre')) eq('auto', eval('g:amatch')) + eq(4, eval('g:cdprecount')) eq(4, eval('g:cdcount')) + command('let g:evpre = {}') command('let g:ev = {}') command('split '..dirs[1]..'/bar') + eq({}, eval('g:evpre')) eq({}, eval('g:ev')) + eq(4, eval('g:cdprecount')) eq(4, eval('g:cdcount')) if iswin() then command('split '..win_dirs[1]..'/baz') + eq({}, eval('g:evpre')) eq({}, eval('g:ev')) + eq(4, eval('g:cdprecount')) eq(4, eval('g:cdcount')) end end) - it("is triggered by switching to win/tab with different CWD #6054", function() + it("are triggered by switching to win/tab with different CWD #6054", function() command('lcd '..dirs[3]) -- window 3 command('split '..dirs[2]..'/foo') -- window 2 command('lcd '..dirs[2]) @@ -185,72 +246,105 @@ describe('autocmd DirChanged', function() command('lcd '..dirs[1]) command('2wincmd w') -- window 2 + eq({directory=dirs[2], scope='window', changed_window=true}, eval('g:evpre')) eq({cwd=dirs[2], scope='window', changed_window=true}, eval('g:ev')) + eq('window', eval('g:amatchpre')) eq('window', eval('g:amatch')) + eq(4, eval('g:cdprecount')) eq(4, eval('g:cdcount')) command('tabnew') -- tab 2 (tab-local CWD) + eq(4, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(4, eval('g:cdcount')) -- same CWD, no DirChanged event command('tcd '..dirs[3]) command('tabnext') -- tab 1 (no tab-local CWD) + eq({directory=dirs[2], scope='window', changed_window=true}, eval('g:evpre')) eq({cwd=dirs[2], scope='window', changed_window=true}, eval('g:ev')) + eq('window', eval('g:amatchpre')) eq('window', eval('g:amatch')) command('tabnext') -- tab 2 + eq({directory=dirs[3], scope='tabpage', changed_window=true}, eval('g:evpre')) eq({cwd=dirs[3], scope='tabpage', changed_window=true}, eval('g:ev')) + eq('tabpage', eval('g:amatchpre')) eq('tabpage', eval('g:amatch')) + eq(7, eval('g:cdprecount')) eq(7, eval('g:cdcount')) command('tabnext') -- tab 1 command('3wincmd w') -- window 3 + eq(9, eval('g:cdprecount')) eq(9, eval('g:cdcount')) command('tabnext') -- tab 2 (has the *same* CWD) + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event if iswin() then command('tabnew') -- tab 3 + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event command('tcd '..win_dirs[3]) + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabnext') -- tab 1 + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabprevious') -- tab 3 + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabprevious') -- tab 2 + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabprevious') -- tab 1 + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event command('lcd '..win_dirs[3]) -- window 3 + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabnext') -- tab 2 + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabnext') -- tab 3 + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabnext') -- tab 1 + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabprevious') -- tab 3 + eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event end end) - it('is triggered by nvim_set_current_dir()', function() + it('are triggered by nvim_set_current_dir()', function() request('nvim_set_current_dir', dirs[1]) + eq({directory=dirs[1], scope='global', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[1], scope='global', changed_window=false}, eval('g:ev')) + eq(1, eval('g:cdprecount')) + eq(1, eval('g:cdcount')) request('nvim_set_current_dir', dirs[2]) + eq({directory=dirs[2], scope='global', changed_window=false}, eval('g:evpre')) eq({cwd=dirs[2], scope='global', changed_window=false}, eval('g:ev')) + eq(2, eval('g:cdprecount')) + eq(2, eval('g:cdcount')) local status, err = pcall(function() request('nvim_set_current_dir', '/doesnotexist') end) eq(false, status) eq('Failed to change directory', string.match(err, ': (.*)')) - eq({cwd=dirs[2], scope='global', changed_window=false}, eval('g:ev')) + eq({directory='/doesnotexist', scope='global', changed_window=false}, eval('g:evpre')) + eq(3, eval('g:cdprecount')) + eq(2, eval('g:cdcount')) end) - it('works when local to buffer', function() + it('work when local to buffer', function() + command('let g:triggeredpre = 0') command('let g:triggered = 0') + command('autocmd DirChangedPre <buffer> let g:triggeredpre = 1') command('autocmd DirChanged <buffer> let g:triggered = 1') command('cd '..dirs[1]) + eq(1, eval('g:triggeredpre')) eq(1, eval('g:triggered')) end) end) diff --git a/test/functional/autocmd/focus_spec.lua b/test/functional/autocmd/focus_spec.lua index 3f9a0ad09b..e3c9e1f9ee 100644 --- a/test/functional/autocmd/focus_spec.lua +++ b/test/functional/autocmd/focus_spec.lua @@ -56,7 +56,7 @@ describe('autoread TUI FocusGained/FocusLost', function() line 3 | line 4 | {5:xtest-foo }| - "xtest-foo" 4L, 28C | + "xtest-foo" 4L, 28B | {3:-- TERMINAL --} | ]]} end) diff --git a/test/functional/autocmd/show_spec.lua b/test/functional/autocmd/show_spec.lua new file mode 100644 index 0000000000..505bed834b --- /dev/null +++ b/test/functional/autocmd/show_spec.lua @@ -0,0 +1,183 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') + +local clear = helpers.clear +local command = helpers.command +local dedent = helpers.dedent +local eq = helpers.eq +local funcs = helpers.funcs +local eval = helpers.eval +local exec = helpers.exec +local feed = helpers.feed + +describe(":autocmd", function() + before_each(function() + clear({'-u', 'NONE'}) + end) + + it("should not segfault when you just do autocmd", function() + command ":autocmd" + end) + + it("should filter based on ++once", function() + command "autocmd! BufEnter" + command "autocmd BufEnter * :echo 'Hello'" + command [[augroup TestingOne]] + command [[ autocmd BufEnter * :echo "Line 1"]] + command [[ autocmd BufEnter * :echo "Line 2"]] + command [[augroup END]] + + eq(dedent([[ + + --- Autocommands --- + BufEnter + * :echo 'Hello' + TestingOne BufEnter + * :echo "Line 1" + :echo "Line 2"]]), + funcs.execute('autocmd BufEnter')) + end) + + it('should not show group information if interrupted', function() + local screen = Screen.new(50, 6) + screen:set_default_attr_ids({ + [1] = {bold = true, foreground = Screen.colors.Blue1}, -- NonText + [2] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg + [3] = {bold = true, foreground = Screen.colors.Magenta}, -- Title + }) + screen:attach() + exec([[ + set more + autocmd! BufEnter + augroup test_1 + autocmd BufEnter A echo 'A' + autocmd BufEnter B echo 'B' + autocmd BufEnter C echo 'C' + autocmd BufEnter D echo 'D' + autocmd BufEnter E echo 'E' + autocmd BufEnter F echo 'F' + augroup END + autocmd! BufLeave + augroup test_1 + autocmd BufLeave A echo 'A' + autocmd BufLeave B echo 'B' + autocmd BufLeave C echo 'C' + autocmd BufLeave D echo 'D' + autocmd BufLeave E echo 'E' + autocmd BufLeave F echo 'F' + augroup END + ]]) + feed(':autocmd<CR>') + screen:expect([[ + :autocmd | + {3:--- Autocommands ---} | + {3:test_1} {3:BufEnter} | + A echo 'A' | + B echo 'B' | + {2:-- More --}^ | + ]]) + feed('q') + screen:expect([[ + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) + end) + + it('should not show group information for deleted pattern', function() + exec([[ + autocmd! BufEnter + augroup test_1 + autocmd BufEnter A echo 'A' + autocmd BufEnter B echo 'B' + autocmd BufEnter C echo 'C' + augroup END + augroup test_2 + autocmd BufEnter foo echo 'foo' + augroup END + augroup test_3 + autocmd BufEnter D echo 'D' + autocmd BufEnter E echo 'E' + autocmd BufEnter F echo 'F' + augroup END + + func Func() + autocmd! test_2 BufEnter + let g:output = execute('autocmd BufEnter') + endfunc + + autocmd User foo call Func() + doautocmd User foo + ]]) + eq(dedent([[ + + --- Autocommands --- + test_1 BufEnter + A echo 'A' + B echo 'B' + C echo 'C' + test_3 BufEnter + D echo 'D' + E echo 'E' + F echo 'F']]), eval('g:output')) + end) + + it('can filter by pattern #17973', function() + exec([[ + autocmd! BufEnter + autocmd! User + augroup test_1 + autocmd BufEnter A echo "A1" + autocmd BufEnter B echo "B1" + autocmd User A echo "A1" + autocmd User B echo "B1" + augroup END + augroup test_2 + autocmd BufEnter A echo "A2" + autocmd BufEnter B echo "B2" + autocmd User A echo "A2" + autocmd User B echo "B2" + augroup END + augroup test_3 + autocmd BufEnter A echo "A3" + autocmd BufEnter B echo "B3" + autocmd User A echo "A3" + autocmd User B echo "B3" + augroup END + ]]) + eq(dedent([[ + + --- Autocommands --- + test_1 User + A echo "A1" + test_2 User + A echo "A2" + test_3 User + A echo "A3"]]), funcs.execute('autocmd User A')) + eq(dedent([[ + + --- Autocommands --- + test_1 BufEnter + B echo "B1" + test_2 BufEnter + B echo "B2" + test_3 BufEnter + B echo "B3" + test_1 User + B echo "B1" + test_2 User + B echo "B2" + test_3 User + B echo "B3"]]), funcs.execute('autocmd * B')) + eq(dedent([[ + + --- Autocommands --- + test_3 BufEnter + B echo "B3" + test_3 User + B echo "B3"]]), funcs.execute('autocmd test_3 * B')) + end) +end) diff --git a/test/functional/autocmd/signal_spec.lua b/test/functional/autocmd/signal_spec.lua index 719adeaf1b..d4f65cc61d 100644 --- a/test/functional/autocmd/signal_spec.lua +++ b/test/functional/autocmd/signal_spec.lua @@ -30,6 +30,12 @@ describe('autocmd Signal', function() eq({'notification', 'foo', {}}, next_msg()) end) + it('matches SIGWINCH', function() + command('autocmd Signal SIGWINCH call rpcnotify(1, "foo")') + posix_kill('WINCH', funcs.getpid()) + eq({'notification', 'foo', {}}, next_msg()) + end) + it('does not match unknown patterns', function() command('autocmd Signal SIGUSR2 call rpcnotify(1, "foo")') posix_kill('USR1', funcs.getpid()) diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua index 1e8f981437..859c2ebf44 100644 --- a/test/functional/autocmd/termxx_spec.lua +++ b/test/functional/autocmd/termxx_spec.lua @@ -1,21 +1,41 @@ local luv = require('luv') local helpers = require('test.functional.helpers')(after_each) -local clear, command, nvim, nvim_dir = - helpers.clear, helpers.command, helpers.nvim, helpers.nvim_dir +local clear, command, nvim, testprg = + helpers.clear, helpers.command, helpers.nvim, helpers.testprg local eval, eq, neq, retry = helpers.eval, helpers.eq, helpers.neq, helpers.retry local ok = helpers.ok local feed = helpers.feed +local pcall_err = helpers.pcall_err +local assert_alive = helpers.assert_alive local iswin = helpers.iswin describe('autocmd TermClose', function() before_each(function() clear() - nvim('set_option', 'shell', nvim_dir .. '/shell-test') + nvim('set_option', 'shell', testprg('shell-test')) command('set shellcmdflag=EXE shellredir= shellpipe= shellquote= shellxquote=') end) + + local function test_termclose_delete_own_buf() + command('autocmd TermClose * bdelete!') + command('terminal') + eq('Vim(bdelete):E937: Attempt to delete a buffer that is in use', pcall_err(command, 'bdelete!')) + assert_alive() + end + + -- TODO: fixed after merging patches for `can_unload_buffer`? + pending('TermClose deleting its own buffer, altbuf = buffer 1 #10386', function() + test_termclose_delete_own_buf() + end) + + it('TermClose deleting its own buffer, altbuf NOT buffer 1 #10386', function() + command('edit foo1') + test_termclose_delete_own_buf() + end) + it('triggers when fast-exiting terminal job stops', function() command('autocmd TermClose * let g:test_termclose = 23') command('terminal') diff --git a/test/functional/autocmd/winscrolled_spec.lua b/test/functional/autocmd/winscrolled_spec.lua index 1ef5a37479..5c1b758961 100644 --- a/test/functional/autocmd/winscrolled_spec.lua +++ b/test/functional/autocmd/winscrolled_spec.lua @@ -3,60 +3,83 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq local eval = helpers.eval -local source = helpers.source +local command = helpers.command +local feed = helpers.feed +local meths = helpers.meths +local assert_alive = helpers.assert_alive + +before_each(clear) describe('WinScrolled', function() - before_each(clear) + local win_id + + before_each(function() + win_id = meths.get_current_win().id + command(string.format('autocmd WinScrolled %d let g:matched = v:true', win_id)) + command('let g:scrolled = 0') + command('autocmd WinScrolled * let g:scrolled += 1') + command([[autocmd WinScrolled * let g:amatch = str2nr(expand('<amatch>'))]]) + command([[autocmd WinScrolled * let g:afile = str2nr(expand('<afile>'))]]) + end) + + after_each(function() + eq(true, eval('g:matched')) + eq(win_id, eval('g:amatch')) + eq(win_id, eval('g:afile')) + end) it('is triggered by scrolling vertically', function() - source([[ - set nowrap - let width = winwidth(0) - let line = '123' . repeat('*', width * 2) - let lines = [line, line] - call nvim_buf_set_lines(0, 0, -1, v:true, lines) - - let g:scrolled = 0 - autocmd WinScrolled * let g:scrolled += 1 - execute "normal! \<C-e>" - ]]) + local lines = {'123', '123'} + meths.buf_set_lines(0, 0, -1, true, lines) + eq(0, eval('g:scrolled')) + feed('<C-E>') eq(1, eval('g:scrolled')) end) it('is triggered by scrolling horizontally', function() - source([[ - set nowrap - let width = winwidth(0) - let line = '123' . repeat('*', width * 2) - let lines = [line, line] - call nvim_buf_set_lines(0, 0, -1, v:true, lines) - - let g:scrolled = 0 - autocmd WinScrolled * let g:scrolled += 1 - execute "normal! zl" - ]]) + command('set nowrap') + local width = meths.win_get_width(0) + local line = '123' .. ('*'):rep(width * 2) + local lines = {line, line} + meths.buf_set_lines(0, 0, -1, true, lines) + eq(0, eval('g:scrolled')) + feed('zl') eq(1, eval('g:scrolled')) end) - it('is triggered when the window scrolls in insert mode', function() - source([[ - let height = winheight(0) - let lines = map(range(height * 2), {_, i -> string(i)}) - call nvim_buf_set_lines(0, 0, -1, v:true, lines) - - let g:scrolled = 0 - autocmd WinScrolled * let g:scrolled += 1 - call feedkeys("LA\<CR><Esc>", "n") - ]]) + it('is triggered by horizontal scrolling from cursor move', function() + command('set nowrap') + local lines = {'', '', 'Foo'} + meths.buf_set_lines(0, 0, -1, true, lines) + meths.win_set_cursor(0, {3, 0}) + eq(0, eval('g:scrolled')) + feed('zl') + eq(1, eval('g:scrolled')) + feed('zl') eq(2, eval('g:scrolled')) + feed('h') + eq(3, eval('g:scrolled')) end) - it('is triggered when the window is resized', function() - source([[ - let g:scrolled = 0 - autocmd WinScrolled * let g:scrolled += 1 - wincmd v - ]]) + it('is triggered when the window scrolls in Insert mode', function() + local height = meths.win_get_height(0) + local lines = {} + for i = 1, height * 2 do + lines[i] = tostring(i) + end + meths.buf_set_lines(0, 0, -1, true, lines) + feed('L') + eq(0, eval('g:scrolled')) + feed('A<CR><Esc>') eq(1, eval('g:scrolled')) end) end) + +it('closing window in WinScrolled does not cause use-after-free #13265', function() + local lines = {'aaa', 'bbb'} + meths.buf_set_lines(0, 0, -1, true, lines) + command('vsplit') + command('autocmd WinScrolled * close') + feed('<C-E>') + assert_alive() +end) |