aboutsummaryrefslogtreecommitdiff
path: root/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
commit931bffbda3668ddc609fc1da8f9eb576b170aa52 (patch)
treed8c1843a95da5ea0bb4acc09f7e37843d9995c86 /test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
parent142d9041391780ac15b89886a54015fdc5c73995 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-userreg.tar.gz
rneovim-userreg.tar.bz2
rneovim-userreg.zip
Merge remote-tracking branch 'upstream/master' into userreguserreg
Diffstat (limited to 'test/functional/ex_cmds/swapfile_preserve_recover_spec.lua')
-rw-r--r--test/functional/ex_cmds/swapfile_preserve_recover_spec.lua235
1 files changed, 199 insertions, 36 deletions
diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
index 8eed00c973..436873b464 100644
--- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
+++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
@@ -1,6 +1,5 @@
local Screen = require('test.functional.ui.screen')
local helpers = require('test.functional.helpers')(after_each)
-local lfs = require('lfs')
local luv = require('luv')
local eq, eval, expect, exec =
helpers.eq, helpers.eval, helpers.expect, helpers.exec
@@ -13,13 +12,19 @@ local nvim_prog = helpers.nvim_prog
local ok = helpers.ok
local rmdir = helpers.rmdir
local new_argv = helpers.new_argv
+local new_pipename = helpers.new_pipename
local pesc = helpers.pesc
local os_kill = helpers.os_kill
local set_session = helpers.set_session
local spawn = helpers.spawn
-local nvim_async = helpers.nvim_async
+local async_meths = helpers.async_meths
local expect_msg_seq = helpers.expect_msg_seq
local pcall_err = helpers.pcall_err
+local mkdir = helpers.mkdir
+local poke_eventloop = helpers.poke_eventloop
+local meths = helpers.meths
+local retry = helpers.retry
+local write_file = helpers.write_file
describe(':recover', function()
before_each(clear)
@@ -37,40 +42,40 @@ describe(':recover', function()
end)
-describe(':preserve', function()
- local swapdir = lfs.currentdir()..'/Xtest_recover_dir'
+describe("preserve and (R)ecover with custom 'directory'", function()
+ local swapdir = luv.cwd()..'/Xtest_recover_dir'
+ local testfile = 'Xtest_recover_file1'
+ -- Put swapdir at the start of the 'directory' list. #1836
+ -- Note: `set swapfile` *must* go after `set directory`: otherwise it may
+ -- attempt to create a swapfile in different directory.
+ local init = [[
+ set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[//
+ set swapfile fileformat=unix undolevels=-1
+ ]]
+
+ local nvim0
before_each(function()
- clear()
+ nvim0 = spawn(new_argv())
+ set_session(nvim0)
rmdir(swapdir)
- lfs.mkdir(swapdir)
+ mkdir(swapdir)
end)
after_each(function()
command('%bwipeout!')
rmdir(swapdir)
end)
- it("saves to custom 'directory' and (R)ecovers #1836", function()
- local testfile = 'Xtest_recover_file1'
- -- Put swapdir at the start of the 'directory' list. #1836
- -- Note: `set swapfile` *must* go after `set directory`: otherwise it may
- -- attempt to create a swapfile in different directory.
- local init = [[
- set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[//
- set swapfile fileformat=unix undolevels=-1
- ]]
-
+ local function setup_swapname()
exec(init)
command('edit! '..testfile)
feed('isometext<esc>')
- command('preserve')
exec('redir => g:swapname | silent swapname | redir END')
+ return eval('g:swapname')
+ end
- local swappath1 = eval('g:swapname')
-
- os_kill(eval('getpid()'))
+ local function test_recover(swappath1)
-- Start another Nvim instance.
- local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'},
- true)
+ local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'}, true)
set_session(nvim2)
exec(init)
@@ -90,12 +95,41 @@ describe(':preserve', function()
-- Verify that :swapname was not truncated (:help 'shortmess').
ok(nil == string.find(swappath1, '%.%.%.'))
ok(nil == string.find(swappath2, '%.%.%.'))
+ end
+
+ it('with :preserve and SIGKILL', function()
+ local swappath1 = setup_swapname()
+ command('preserve')
+ os_kill(eval('getpid()'))
+ test_recover(swappath1)
+ end)
+
+ it('closing stdio channel without :preserve #22096', function()
+ local swappath1 = setup_swapname()
+ nvim0:close()
+ test_recover(swappath1)
+ end)
+
+ it('killing TUI process without :preserve #22096', function()
+ helpers.skip(helpers.is_os('win'))
+ local screen0 = Screen.new()
+ screen0:attach()
+ local child_server = new_pipename()
+ funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--listen', child_server})
+ screen0:expect({any = pesc('[No Name]')}) -- Wait for the child process to start.
+ local child_session = helpers.connect(child_server)
+ set_session(child_session)
+ local swappath1 = setup_swapname()
+ set_session(nvim0)
+ command('call chanclose(&channel)') -- Kill the child process.
+ screen0:expect({any = pesc('[Process exited 1]')}) -- Wait for the child process to stop.
+ test_recover(swappath1)
end)
end)
describe('swapfile detection', function()
- local swapdir = lfs.currentdir()..'/Xtest_swapdialog_dir'
+ local swapdir = luv.cwd()..'/Xtest_swapdialog_dir'
local nvim0
-- Put swapdir at the start of the 'directory' list. #1836
-- Note: `set swapfile` *must* go after `set directory`: otherwise it may
@@ -108,7 +142,7 @@ describe('swapfile detection', function()
nvim0 = spawn(new_argv())
set_session(nvim0)
rmdir(swapdir)
- lfs.mkdir(swapdir)
+ mkdir(swapdir)
end)
after_each(function()
set_session(nvim0)
@@ -137,6 +171,7 @@ describe('swapfile detection', function()
local screen2 = Screen.new(256, 40)
screen2:attach()
exec(init)
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
-- With shortmess+=F
command('set shortmess+=F')
@@ -160,7 +195,7 @@ describe('swapfile detection', function()
feed('e') -- Chose "Edit" at the swap dialog.
screen2:expect(expected_no_dialog)
- -- With API (via eval/VimL) call and shortmess+=F
+ -- With API (via eval/Vimscript) call and shortmess+=F
feed(':call nvim_command("edit %")<CR>')
screen2:expect{any=[[Found a swap file by the name ".*]]
..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]}
@@ -169,7 +204,7 @@ describe('swapfile detection', function()
screen2:expect(expected_no_dialog)
-- With API call and shortmess+=F
- nvim_async('command', 'edit %')
+ async_meths.command('edit %')
screen2:expect{any=[[Found a swap file by the name ".*]]
..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]}
feed('e') -- Chose "Edit" at the swap dialog.
@@ -185,11 +220,29 @@ describe('swapfile detection', function()
nvim2:close()
end)
+ it('default SwapExists handler selects "(E)dit" and skips prompt', function()
+ exec(init)
+ command('edit Xfile1')
+ command("put ='some text...'")
+ command('preserve') -- Make sure the swap file exists.
+ local nvimpid = funcs.getpid()
+
+ local nvim1 = spawn(new_argv(), true, nil, true)
+ set_session(nvim1)
+ local screen = Screen.new(75, 18)
+ screen:attach()
+ exec(init)
+ feed(':edit Xfile1\n')
+
+ screen:expect({ any = ('W325: Ignoring swapfile from Nvim process %d'):format(nvimpid) })
+ nvim1:close()
+ end)
+
-- oldtest: Test_swap_prompt_splitwin()
it('selecting "q" in the attention prompt', function()
exec(init)
command('edit Xfile1')
- command('preserve') -- should help to make sure the swap file exists
+ command('preserve') -- Make sure the swap file exists.
local screen = Screen.new(75, 18)
screen:set_default_attr_ids({
@@ -201,7 +254,9 @@ describe('swapfile detection', function()
set_session(nvim1)
screen:attach()
exec(init)
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
feed(':split Xfile1\n')
+ -- The default SwapExists handler does _not_ skip this prompt.
screen:expect({
any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^')
})
@@ -233,6 +288,7 @@ describe('swapfile detection', function()
set_session(nvim2)
screen:attach()
exec(init)
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
command('set more')
command('au bufadd * let foo_w = wincol()')
feed(':e Xfile1<CR>')
@@ -266,8 +322,9 @@ describe('swapfile detection', function()
nvim2:close()
end)
- -- oldtest: Test_nocatch_process_still_running()
- it('allows deleting swapfile created before boot vim-patch:8.2.2586', function()
+ --- @param swapexists boolean Enable the default SwapExists handler.
+ --- @param on_swapfile_running fun(screen: any) Called after swapfile ("STILL RUNNING") prompt.
+ local function test_swapfile_after_reboot(swapexists, on_swapfile_running)
local screen = Screen.new(75, 30)
screen:set_default_attr_ids({
[0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
@@ -277,6 +334,9 @@ describe('swapfile detection', function()
screen:attach()
exec(init)
+ if not swapexists then
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
+ end
command('set nohidden')
exec([=[
@@ -313,12 +373,7 @@ describe('swapfile detection', function()
os.rename('Xswap', swname)
feed(':edit Xswaptest<CR>')
- screen:expect({any = table.concat({
- pesc('{2:E325: ATTENTION}'),
- 'file name: .*Xswaptest',
- 'process ID: %d* %(STILL RUNNING%)',
- pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'),
- }, '.*')})
+ on_swapfile_running(screen)
feed('e')
@@ -330,7 +385,8 @@ describe('swapfile detection', function()
]])
-- pretend that the swapfile was created before boot
- lfs.touch(swname, os.time() - luv.uptime() - 10)
+ local atime = os.time() - luv.uptime() - 10
+ luv.fs_utime(swname, atime, atime)
feed(':edit Xswaptest<CR>')
screen:expect({any = table.concat({
@@ -339,5 +395,112 @@ describe('swapfile detection', function()
}, '.*')})
feed('e')
+ end
+
+ -- oldtest: Test_nocatch_process_still_running()
+ it('swapfile created before boot vim-patch:8.2.2586', function()
+ test_swapfile_after_reboot(false, function(screen)
+ screen:expect({any = table.concat({
+ pesc('{2:E325: ATTENTION}'),
+ 'file name: .*Xswaptest',
+ 'process ID: %d* %(STILL RUNNING%)',
+ pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'),
+ }, '.*')})
+ end)
+ end)
+
+ it('swapfile created before boot + default SwapExists handler', function()
+ test_swapfile_after_reboot(true, function(screen)
+ screen:expect({ any = 'W325: Ignoring swapfile from Nvim process' })
+ end)
+ end)
+
+end)
+
+describe('quitting swapfile dialog on startup stops TUI properly', function()
+ local swapdir = luv.cwd()..'/Xtest_swapquit_dir'
+ local testfile = 'Xtest_swapquit_file1'
+ local otherfile = 'Xtest_swapquit_file2'
+ -- Put swapdir at the start of the 'directory' list. #1836
+ -- Note: `set swapfile` *must* go after `set directory`: otherwise it may
+ -- attempt to create a swapfile in different directory.
+ local init_dir = [[set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[//]]
+ local init_set = [[set swapfile fileformat=unix nomodified undolevels=-1 nohidden]]
+
+ before_each(function()
+ clear({args = {'--cmd', init_dir, '--cmd', init_set}})
+ rmdir(swapdir)
+ mkdir(swapdir)
+ write_file(testfile, [[
+ first
+ second
+ third
+
+ ]])
+ command('edit! '..testfile)
+ feed('Gisometext<esc>')
+ poke_eventloop()
+ clear() -- Leaves a swap file behind
+ meths.ui_attach(80, 30, {})
+ end)
+ after_each(function()
+ rmdir(swapdir)
+ os.remove(testfile)
+ os.remove(otherfile)
+ end)
+
+ it('(Q)uit at first file argument', function()
+ local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE',
+ '--cmd', init_dir, '--cmd', init_set,
+ testfile})
+ retry(nil, nil, function()
+ eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
+ eval("getline('$')->trim(' ', 2)"))
+ end)
+ meths.chan_send(chan, 'q')
+ retry(nil, nil, function()
+ eq({'', '[Process exited 1]', ''},
+ eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})"))
+ end)
+ end)
+
+ it('(A)bort at second file argument with -p', function()
+ local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE',
+ '--cmd', init_dir, '--cmd', init_set,
+ '-p', otherfile, testfile})
+ retry(nil, nil, function()
+ eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
+ eval("getline('$')->trim(' ', 2)"))
+ end)
+ meths.chan_send(chan, 'a')
+ retry(nil, nil, function()
+ eq({'', '[Process exited 1]', ''},
+ eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})"))
+ end)
+ end)
+
+ it('(Q)uit at file opened by -t', function()
+ write_file(otherfile, ([[
+ !_TAG_FILE_ENCODING utf-8 //
+ first %s /^ \zsfirst$/
+ second %s /^ \zssecond$/
+ third %s /^ \zsthird$/]]):format(testfile, testfile, testfile))
+ local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE',
+ '--cmd', init_dir, '--cmd', init_set,
+ '--cmd', 'set tags='..otherfile, '-tsecond'})
+ retry(nil, nil, function()
+ eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
+ eval("getline('$')->trim(' ', 2)"))
+ end)
+ meths.chan_send(chan, 'q')
+ retry(nil, nil, function()
+ eq('Press ENTER or type command to continue',
+ eval("getline('$')->trim(' ', 2)"))
+ end)
+ meths.chan_send(chan, '\r')
+ retry(nil, nil, function()
+ eq({'', '[Process exited 1]', ''},
+ eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})"))
+ end)
end)
end)