2024-04-20 08:44:13 -07:00
|
|
|
|
local t = require('test.testutil')
|
|
|
|
|
local n = require('test.functional.testnvim')()
|
|
|
|
|
local Screen = require('test.functional.ui.screen')
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local uv = vim.uv
|
2024-04-08 02:03:20 -07:00
|
|
|
|
|
|
|
|
|
local assert_log = t.assert_log
|
|
|
|
|
local assert_nolog = t.assert_nolog
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local clear = n.clear
|
|
|
|
|
local command = n.command
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local eq = t.eq
|
|
|
|
|
local neq = t.neq
|
|
|
|
|
local ok = t.ok
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local feed = n.feed
|
|
|
|
|
local fn = n.fn
|
|
|
|
|
local nvim_prog = n.nvim_prog
|
|
|
|
|
local request = n.request
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local retry = t.retry
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local rmdir = n.rmdir
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local matches = t.matches
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local api = n.api
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local mkdir = t.mkdir
|
2024-01-12 04:41:09 -07:00
|
|
|
|
local sleep = vim.uv.sleep
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local read_file = t.read_file
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local trim = vim.trim
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local currentdir = n.fn.getcwd
|
|
|
|
|
local assert_alive = n.assert_alive
|
|
|
|
|
local check_close = n.check_close
|
|
|
|
|
local expect_exit = n.expect_exit
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local write_file = t.write_file
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local feed_command = n.feed_command
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local skip = t.skip
|
|
|
|
|
local is_os = t.is_os
|
|
|
|
|
local is_ci = t.is_ci
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local spawn = n.spawn
|
|
|
|
|
local set_session = n.set_session
|
2018-04-22 19:43:00 -07:00
|
|
|
|
|
|
|
|
|
describe('fileio', function()
|
|
|
|
|
before_each(function() end)
|
|
|
|
|
after_each(function()
|
2023-01-14 18:34:21 -07:00
|
|
|
|
check_close()
|
2018-04-22 19:43:00 -07:00
|
|
|
|
os.remove('Xtest_startup_shada')
|
|
|
|
|
os.remove('Xtest_startup_file1')
|
2019-03-23 16:21:26 -07:00
|
|
|
|
os.remove('Xtest_startup_file1~')
|
2018-04-22 19:43:00 -07:00
|
|
|
|
os.remove('Xtest_startup_file2')
|
2023-10-02 21:13:04 -07:00
|
|
|
|
os.remove('Xtest_startup_file2~')
|
2019-07-23 11:56:27 -07:00
|
|
|
|
os.remove('Xtest_тест.md')
|
2021-11-23 21:07:47 -07:00
|
|
|
|
os.remove('Xtest-u8-int-max')
|
2022-09-24 18:57:10 -07:00
|
|
|
|
os.remove('Xtest-overwrite-forced')
|
2018-04-22 19:43:00 -07:00
|
|
|
|
rmdir('Xtest_startup_swapdir')
|
2019-11-18 00:38:27 -07:00
|
|
|
|
rmdir('Xtest_backupdir')
|
2023-07-17 06:27:21 -07:00
|
|
|
|
rmdir('Xtest_backupdir with spaces')
|
2018-04-22 19:43:00 -07:00
|
|
|
|
end)
|
|
|
|
|
|
test: 'nofsync' with deadly signal #26415
Problem:
The test for 'nofsync' swapfile preservation on a deadly signal, does
not actually assert anything.
followup to 1fd29a28841dee3d25ff079eb24fc160eb02cb3c
Solution:
Check that swapfile contents are present after getting SIGTERM.
TODO: this doesn't really verify that 'fsync' was called; it still
passes with this patch:
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 216e39f3e81c..7a635520401d 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -838,7 +838,7 @@ void preserve_exit(const char *errmsg)
if (errmsg != NULL) {
os_errmsg("Vim: preserving files...\r\n");
}
- ml_sync_all(false, false, true); // preserve all swap files
+ ml_sync_all(false, false, false); // preserve all swap files
break;
}
}
However it correctly fails with this patch, at least:
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 216e39f3e81c..f2306c310ddc 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -838,7 +838,6 @@ void preserve_exit(const char *errmsg)
if (errmsg != NULL) {
os_errmsg("Vim: preserving files...\r\n");
}
- ml_sync_all(false, false, true); // preserve all swap files
break;
}
}
2023-12-06 08:11:36 -07:00
|
|
|
|
local args = { nvim_prog, '--clean', '--cmd', 'set nofsync directory=Xtest_startup_swapdir' }
|
|
|
|
|
--- Starts a new nvim session and returns an attached screen.
|
|
|
|
|
local function startup(extra_args)
|
|
|
|
|
extra_args = extra_args or {}
|
2024-04-21 15:58:48 -07:00
|
|
|
|
local argv = vim.iter({ args, '--embed', extra_args }):flatten():totable()
|
test: 'nofsync' with deadly signal #26415
Problem:
The test for 'nofsync' swapfile preservation on a deadly signal, does
not actually assert anything.
followup to 1fd29a28841dee3d25ff079eb24fc160eb02cb3c
Solution:
Check that swapfile contents are present after getting SIGTERM.
TODO: this doesn't really verify that 'fsync' was called; it still
passes with this patch:
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 216e39f3e81c..7a635520401d 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -838,7 +838,7 @@ void preserve_exit(const char *errmsg)
if (errmsg != NULL) {
os_errmsg("Vim: preserving files...\r\n");
}
- ml_sync_all(false, false, true); // preserve all swap files
+ ml_sync_all(false, false, false); // preserve all swap files
break;
}
}
However it correctly fails with this patch, at least:
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 216e39f3e81c..f2306c310ddc 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -838,7 +838,6 @@ void preserve_exit(const char *errmsg)
if (errmsg != NULL) {
os_errmsg("Vim: preserving files...\r\n");
}
- ml_sync_all(false, false, true); // preserve all swap files
break;
}
}
2023-12-06 08:11:36 -07:00
|
|
|
|
local screen_nvim = spawn(argv)
|
|
|
|
|
set_session(screen_nvim)
|
|
|
|
|
local screen = Screen.new(70, 10)
|
|
|
|
|
screen:set_default_attr_ids({
|
|
|
|
|
[1] = { foreground = Screen.colors.NvimDarkGrey4 },
|
|
|
|
|
[2] = { background = Screen.colors.NvimDarkGrey1, foreground = Screen.colors.NvimLightGrey3 },
|
|
|
|
|
[3] = { foreground = Screen.colors.NvimLightCyan },
|
|
|
|
|
})
|
|
|
|
|
return screen
|
|
|
|
|
end
|
|
|
|
|
|
2023-12-05 13:52:06 -07:00
|
|
|
|
it("fsync() with 'nofsync' #8304", function()
|
|
|
|
|
clear({ args = { '--cmd', 'set nofsync directory=Xtest_startup_swapdir' } })
|
2018-04-22 19:43:00 -07:00
|
|
|
|
|
|
|
|
|
-- These cases ALWAYS force fsync (regardless of 'fsync' option):
|
|
|
|
|
|
|
|
|
|
-- 1. Idle (CursorHold) with modified buffers (+ 'swapfile').
|
|
|
|
|
command('write Xtest_startup_file1')
|
2023-12-05 13:52:06 -07:00
|
|
|
|
feed('Afoo<esc>h')
|
2018-04-23 15:27:09 -07:00
|
|
|
|
command('write')
|
2023-12-05 13:52:06 -07:00
|
|
|
|
eq(0, request('nvim__stats').fsync)
|
2018-04-23 15:27:09 -07:00
|
|
|
|
command('set swapfile')
|
|
|
|
|
command('set updatetime=1')
|
2023-12-05 13:52:06 -07:00
|
|
|
|
feed('Azub<esc>h') -- File is 'modified'.
|
2018-04-23 15:27:09 -07:00
|
|
|
|
sleep(3) -- Allow 'updatetime' to expire.
|
|
|
|
|
retry(3, nil, function()
|
|
|
|
|
eq(1, request('nvim__stats').fsync)
|
|
|
|
|
end)
|
2023-12-05 13:52:06 -07:00
|
|
|
|
command('set updatetime=100000 updatecount=100000')
|
|
|
|
|
|
|
|
|
|
-- 2. Explicit :preserve command.
|
|
|
|
|
command('preserve')
|
2023-12-06 09:26:30 -07:00
|
|
|
|
-- TODO: should be exactly 2; where is the extra fsync() is coming from? #26404
|
|
|
|
|
ok(request('nvim__stats').fsync == 2 or request('nvim__stats').fsync == 3)
|
2023-12-05 13:52:06 -07:00
|
|
|
|
|
|
|
|
|
-- 3. Enable 'fsync' option, write file.
|
|
|
|
|
command('set fsync')
|
|
|
|
|
feed('Abaz<esc>h')
|
|
|
|
|
command('write')
|
2023-12-06 09:26:30 -07:00
|
|
|
|
-- TODO: should be exactly 4; where is the extra fsync() is coming from? #26404
|
|
|
|
|
ok(request('nvim__stats').fsync == 4 or request('nvim__stats').fsync == 5)
|
2023-12-05 13:52:06 -07:00
|
|
|
|
eq('foozubbaz', trim(read_file('Xtest_startup_file1')))
|
2018-04-22 19:43:00 -07:00
|
|
|
|
|
2023-12-05 13:52:06 -07:00
|
|
|
|
-- 4. Exit caused by deadly signal (+ 'swapfile').
|
2024-04-21 15:58:48 -07:00
|
|
|
|
local j = fn.jobstart(vim.iter({ args, '--embed' }):flatten():totable(), { rpc = true })
|
2024-01-12 10:59:57 -07:00
|
|
|
|
fn.rpcrequest(
|
test: 'nofsync' with deadly signal #26415
Problem:
The test for 'nofsync' swapfile preservation on a deadly signal, does
not actually assert anything.
followup to 1fd29a28841dee3d25ff079eb24fc160eb02cb3c
Solution:
Check that swapfile contents are present after getting SIGTERM.
TODO: this doesn't really verify that 'fsync' was called; it still
passes with this patch:
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 216e39f3e81c..7a635520401d 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -838,7 +838,7 @@ void preserve_exit(const char *errmsg)
if (errmsg != NULL) {
os_errmsg("Vim: preserving files...\r\n");
}
- ml_sync_all(false, false, true); // preserve all swap files
+ ml_sync_all(false, false, false); // preserve all swap files
break;
}
}
However it correctly fails with this patch, at least:
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 216e39f3e81c..f2306c310ddc 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -838,7 +838,6 @@ void preserve_exit(const char *errmsg)
if (errmsg != NULL) {
os_errmsg("Vim: preserving files...\r\n");
}
- ml_sync_all(false, false, true); // preserve all swap files
break;
}
}
2023-12-06 08:11:36 -07:00
|
|
|
|
j,
|
|
|
|
|
'nvim_exec2',
|
|
|
|
|
[[
|
|
|
|
|
set nofsync directory=Xtest_startup_swapdir
|
|
|
|
|
edit Xtest_startup_file2
|
|
|
|
|
write
|
|
|
|
|
put ='fsyncd text'
|
|
|
|
|
]],
|
|
|
|
|
{}
|
|
|
|
|
)
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq('Xtest_startup_swapdir', fn.rpcrequest(j, 'nvim_eval', '&directory'))
|
|
|
|
|
fn.jobstop(j) -- Send deadly signal.
|
2018-04-22 19:43:00 -07:00
|
|
|
|
|
test: 'nofsync' with deadly signal #26415
Problem:
The test for 'nofsync' swapfile preservation on a deadly signal, does
not actually assert anything.
followup to 1fd29a28841dee3d25ff079eb24fc160eb02cb3c
Solution:
Check that swapfile contents are present after getting SIGTERM.
TODO: this doesn't really verify that 'fsync' was called; it still
passes with this patch:
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 216e39f3e81c..7a635520401d 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -838,7 +838,7 @@ void preserve_exit(const char *errmsg)
if (errmsg != NULL) {
os_errmsg("Vim: preserving files...\r\n");
}
- ml_sync_all(false, false, true); // preserve all swap files
+ ml_sync_all(false, false, false); // preserve all swap files
break;
}
}
However it correctly fails with this patch, at least:
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 216e39f3e81c..f2306c310ddc 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -838,7 +838,6 @@ void preserve_exit(const char *errmsg)
if (errmsg != NULL) {
os_errmsg("Vim: preserving files...\r\n");
}
- ml_sync_all(false, false, true); // preserve all swap files
break;
}
}
2023-12-06 08:11:36 -07:00
|
|
|
|
local screen = startup()
|
|
|
|
|
feed(':recover Xtest_startup_file2<cr>')
|
|
|
|
|
screen:expect({ any = [[Using swap file "Xtest_startup_swapdir[/\]Xtest_startup_file2%.swp"]] })
|
|
|
|
|
feed('<cr>')
|
|
|
|
|
screen:expect({ any = 'fsyncd text' })
|
|
|
|
|
|
2023-12-05 13:52:06 -07:00
|
|
|
|
-- 5. SIGPWR signal.
|
test: 'nofsync' with deadly signal #26415
Problem:
The test for 'nofsync' swapfile preservation on a deadly signal, does
not actually assert anything.
followup to 1fd29a28841dee3d25ff079eb24fc160eb02cb3c
Solution:
Check that swapfile contents are present after getting SIGTERM.
TODO: this doesn't really verify that 'fsync' was called; it still
passes with this patch:
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 216e39f3e81c..7a635520401d 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -838,7 +838,7 @@ void preserve_exit(const char *errmsg)
if (errmsg != NULL) {
os_errmsg("Vim: preserving files...\r\n");
}
- ml_sync_all(false, false, true); // preserve all swap files
+ ml_sync_all(false, false, false); // preserve all swap files
break;
}
}
However it correctly fails with this patch, at least:
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 216e39f3e81c..f2306c310ddc 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -838,7 +838,6 @@ void preserve_exit(const char *errmsg)
if (errmsg != NULL) {
os_errmsg("Vim: preserving files...\r\n");
}
- ml_sync_all(false, false, true); // preserve all swap files
break;
}
}
2023-12-06 08:11:36 -07:00
|
|
|
|
-- oldtest: Test_signal_PWR()
|
2018-04-22 19:43:00 -07:00
|
|
|
|
end)
|
2019-03-23 16:21:26 -07:00
|
|
|
|
|
2019-05-20 13:33:19 -07:00
|
|
|
|
it('backup #9709', function()
|
2022-11-21 17:13:30 -07:00
|
|
|
|
skip(is_ci('cirrus'))
|
2019-03-23 16:21:26 -07:00
|
|
|
|
clear({
|
|
|
|
|
args = {
|
|
|
|
|
'-i',
|
|
|
|
|
'Xtest_startup_shada',
|
|
|
|
|
'--cmd',
|
|
|
|
|
'set directory=Xtest_startup_swapdir',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
command('write Xtest_startup_file1')
|
|
|
|
|
feed('ifoo<esc>')
|
|
|
|
|
command('set backup')
|
|
|
|
|
command('set backupcopy=yes')
|
|
|
|
|
command('write')
|
|
|
|
|
feed('Abar<esc>')
|
|
|
|
|
command('write')
|
|
|
|
|
|
2019-03-30 10:14:20 -07:00
|
|
|
|
local foobar_contents = trim(read_file('Xtest_startup_file1'))
|
|
|
|
|
local bar_contents = trim(read_file('Xtest_startup_file1~'))
|
2019-03-23 16:21:26 -07:00
|
|
|
|
|
2019-03-30 10:14:20 -07:00
|
|
|
|
eq('foobar', foobar_contents)
|
|
|
|
|
eq('foo', bar_contents)
|
2019-07-23 11:56:27 -07:00
|
|
|
|
end)
|
2019-03-23 16:21:26 -07:00
|
|
|
|
|
2019-11-18 00:38:27 -07:00
|
|
|
|
it('backup with full path #11214', function()
|
2022-11-21 17:13:30 -07:00
|
|
|
|
skip(is_ci('cirrus'))
|
2019-11-18 00:38:27 -07:00
|
|
|
|
clear()
|
|
|
|
|
mkdir('Xtest_backupdir')
|
|
|
|
|
command('set backup')
|
|
|
|
|
command('set backupdir=Xtest_backupdir//')
|
|
|
|
|
command('write Xtest_startup_file1')
|
|
|
|
|
feed('ifoo<esc>')
|
|
|
|
|
command('write')
|
|
|
|
|
feed('Abar<esc>')
|
|
|
|
|
command('write')
|
|
|
|
|
|
|
|
|
|
-- Backup filename = fullpath, separators replaced with "%".
|
|
|
|
|
local backup_file_name = string.gsub(
|
|
|
|
|
currentdir() .. '/Xtest_startup_file1',
|
2022-11-21 17:13:30 -07:00
|
|
|
|
is_os('win') and '[:/\\]' or '/',
|
|
|
|
|
'%%'
|
|
|
|
|
) .. '~'
|
2019-11-18 00:38:27 -07:00
|
|
|
|
local foo_contents = trim(read_file('Xtest_backupdir/' .. backup_file_name))
|
|
|
|
|
local foobar_contents = trim(read_file('Xtest_startup_file1'))
|
|
|
|
|
|
|
|
|
|
eq('foobar', foobar_contents)
|
|
|
|
|
eq('foo', foo_contents)
|
|
|
|
|
end)
|
|
|
|
|
|
2023-07-17 06:27:21 -07:00
|
|
|
|
it('backup with full path with spaces', function()
|
|
|
|
|
skip(is_ci('cirrus'))
|
|
|
|
|
clear()
|
2023-10-02 21:13:04 -07:00
|
|
|
|
mkdir('Xtest_backupdir with spaces')
|
2023-07-17 06:27:21 -07:00
|
|
|
|
command('set backup')
|
|
|
|
|
command('set backupdir=Xtest_backupdir\\ with\\ spaces//')
|
|
|
|
|
command('write Xtest_startup_file1')
|
|
|
|
|
feed('ifoo<esc>')
|
|
|
|
|
command('write')
|
|
|
|
|
feed('Abar<esc>')
|
|
|
|
|
command('write')
|
|
|
|
|
|
|
|
|
|
-- Backup filename = fullpath, separators replaced with "%".
|
|
|
|
|
local backup_file_name = string.gsub(
|
|
|
|
|
currentdir() .. '/Xtest_startup_file1',
|
|
|
|
|
is_os('win') and '[:/\\]' or '/',
|
|
|
|
|
'%%'
|
|
|
|
|
) .. '~'
|
|
|
|
|
local foo_contents = trim(read_file('Xtest_backupdir with spaces/' .. backup_file_name))
|
|
|
|
|
local foobar_contents = trim(read_file('Xtest_startup_file1'))
|
|
|
|
|
|
|
|
|
|
eq('foobar', foobar_contents)
|
|
|
|
|
eq('foo', foo_contents)
|
|
|
|
|
end)
|
|
|
|
|
|
2022-11-04 18:24:34 -07:00
|
|
|
|
it('backup symlinked files #11349', function()
|
2022-11-21 17:13:30 -07:00
|
|
|
|
skip(is_ci('cirrus'))
|
2022-11-04 18:24:34 -07:00
|
|
|
|
clear()
|
|
|
|
|
|
|
|
|
|
local initial_content = 'foo'
|
|
|
|
|
local link_file_name = 'Xtest_startup_file2'
|
|
|
|
|
local backup_file_name = link_file_name .. '~'
|
|
|
|
|
|
|
|
|
|
write_file('Xtest_startup_file1', initial_content, false)
|
2024-01-12 04:28:20 -07:00
|
|
|
|
uv.fs_symlink('Xtest_startup_file1', link_file_name)
|
2022-11-04 18:24:34 -07:00
|
|
|
|
command('set backup')
|
|
|
|
|
command('set backupcopy=yes')
|
|
|
|
|
command('edit ' .. link_file_name)
|
|
|
|
|
feed('Abar<esc>')
|
|
|
|
|
command('write')
|
|
|
|
|
|
|
|
|
|
local backup_raw = read_file(backup_file_name)
|
|
|
|
|
neq(nil, backup_raw, 'Expected backup file ' .. backup_file_name .. 'to exist but did not')
|
|
|
|
|
eq(initial_content, trim(backup_raw), 'Expected backup to contain original contents')
|
|
|
|
|
end)
|
|
|
|
|
|
2022-11-28 18:45:48 -07:00
|
|
|
|
it('backup symlinked files in first available backupdir #11349', function()
|
2022-11-21 17:13:30 -07:00
|
|
|
|
skip(is_ci('cirrus'))
|
2022-11-04 18:24:34 -07:00
|
|
|
|
clear()
|
|
|
|
|
|
|
|
|
|
local initial_content = 'foo'
|
|
|
|
|
local backup_dir = 'Xtest_backupdir'
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local sep = n.get_pathsep()
|
2022-11-04 18:24:34 -07:00
|
|
|
|
local link_file_name = 'Xtest_startup_file2'
|
|
|
|
|
local backup_file_name = backup_dir .. sep .. link_file_name .. '~'
|
|
|
|
|
|
|
|
|
|
write_file('Xtest_startup_file1', initial_content, false)
|
2024-01-12 04:28:20 -07:00
|
|
|
|
uv.fs_symlink('Xtest_startup_file1', link_file_name)
|
2022-11-04 18:24:34 -07:00
|
|
|
|
mkdir(backup_dir)
|
|
|
|
|
command('set backup')
|
|
|
|
|
command('set backupcopy=yes')
|
|
|
|
|
command('set backupdir=.__this_does_not_exist__,' .. backup_dir)
|
|
|
|
|
command('edit ' .. link_file_name)
|
|
|
|
|
feed('Abar<esc>')
|
|
|
|
|
command('write')
|
|
|
|
|
|
|
|
|
|
local backup_raw = read_file(backup_file_name)
|
|
|
|
|
neq(nil, backup_raw, 'Expected backup file ' .. backup_file_name .. ' to exist but did not')
|
|
|
|
|
eq(initial_content, trim(backup_raw), 'Expected backup to contain original contents')
|
|
|
|
|
end)
|
|
|
|
|
|
2019-07-23 11:56:27 -07:00
|
|
|
|
it('readfile() on multibyte filename #10586', function()
|
|
|
|
|
clear()
|
|
|
|
|
local text = {
|
|
|
|
|
'line1',
|
|
|
|
|
' ...line2... ',
|
|
|
|
|
'',
|
|
|
|
|
'line3!',
|
|
|
|
|
'тест yay тест.',
|
|
|
|
|
'',
|
|
|
|
|
}
|
|
|
|
|
local fname = 'Xtest_тест.md'
|
2024-01-12 10:59:57 -07:00
|
|
|
|
fn.writefile(text, fname, 's')
|
2019-07-23 11:56:27 -07:00
|
|
|
|
table.insert(text, '')
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq(text, fn.readfile(fname, 'b'))
|
2019-03-23 16:21:26 -07:00
|
|
|
|
end)
|
2021-11-23 21:07:47 -07:00
|
|
|
|
it("read invalid u8 over INT_MAX doesn't segfault", function()
|
|
|
|
|
clear()
|
|
|
|
|
command('call writefile(0zFFFFFFFF, "Xtest-u8-int-max")')
|
|
|
|
|
-- This should not segfault
|
|
|
|
|
command('edit ++enc=utf32 Xtest-u8-int-max')
|
|
|
|
|
assert_alive()
|
|
|
|
|
end)
|
2022-09-24 18:57:10 -07:00
|
|
|
|
|
|
|
|
|
it(':w! does not show "file has been changed" warning', function()
|
|
|
|
|
clear()
|
|
|
|
|
write_file('Xtest-overwrite-forced', 'foobar')
|
|
|
|
|
command('set nofixendofline')
|
|
|
|
|
local screen = Screen.new(40, 4)
|
2022-09-27 07:19:15 -07:00
|
|
|
|
command('set shortmess-=F')
|
2022-09-24 18:57:10 -07:00
|
|
|
|
|
|
|
|
|
command('e Xtest-overwrite-forced')
|
|
|
|
|
screen:expect([[
|
|
|
|
|
^foobar |
|
2023-12-09 05:42:00 -07:00
|
|
|
|
{1:~ }|*2
|
2022-09-24 18:57:10 -07:00
|
|
|
|
"Xtest-overwrite-forced" [noeol] 1L, 6B |
|
|
|
|
|
]])
|
|
|
|
|
|
|
|
|
|
-- Get current unix time.
|
|
|
|
|
local cur_unix_time = os.time(os.date('!*t'))
|
|
|
|
|
local future_time = cur_unix_time + 999999
|
|
|
|
|
-- Set the file's access/update time to be
|
|
|
|
|
-- greater than the time at which it was created.
|
|
|
|
|
uv.fs_utime('Xtest-overwrite-forced', future_time, future_time)
|
|
|
|
|
-- use async feed_command because nvim basically hangs on the prompt
|
|
|
|
|
feed_command('w')
|
|
|
|
|
screen:expect([[
|
2024-05-26 00:34:29 -07:00
|
|
|
|
{9:WARNING: The file has been changed since}|
|
|
|
|
|
{9: reading it!!!} |
|
|
|
|
|
{6:Do you really want to write to it (y/n)?}|
|
2023-09-30 01:31:55 -07:00
|
|
|
|
^ |
|
2022-09-24 18:57:10 -07:00
|
|
|
|
]])
|
|
|
|
|
|
|
|
|
|
feed('n')
|
|
|
|
|
feed('<cr>')
|
|
|
|
|
screen:expect([[
|
|
|
|
|
^foobar |
|
2023-12-09 05:42:00 -07:00
|
|
|
|
{1:~ }|*2
|
2022-09-24 18:57:10 -07:00
|
|
|
|
|
|
|
|
|
|
]])
|
|
|
|
|
-- Use a screen test because the warning does not set v:errmsg.
|
|
|
|
|
command('w!')
|
|
|
|
|
screen:expect([[
|
|
|
|
|
^foobar |
|
2023-12-09 05:42:00 -07:00
|
|
|
|
{1:~ }|*2
|
2022-09-24 18:57:10 -07:00
|
|
|
|
<erwrite-forced" [noeol] 1L, 6B written |
|
|
|
|
|
]])
|
|
|
|
|
end)
|
2018-04-22 19:43:00 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2022-06-30 04:16:46 -07:00
|
|
|
|
describe('tmpdir', function()
|
|
|
|
|
local tmproot_pat = [=[.*[/\\]nvim%.[^/\\]+]=]
|
|
|
|
|
local testlog = 'Xtest_tmpdir_log'
|
2024-09-08 12:48:32 -07:00
|
|
|
|
local os_tmpdir ---@type string
|
2022-06-30 04:16:46 -07:00
|
|
|
|
|
|
|
|
|
before_each(function()
|
|
|
|
|
-- Fake /tmp dir so that we can mess it up.
|
2024-09-08 12:48:32 -07:00
|
|
|
|
os_tmpdir = assert(vim.uv.fs_mkdtemp(vim.fs.dirname(t.tmpname(false)) .. '/nvim_XXXXXXXXXX'))
|
2022-06-30 04:16:46 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
after_each(function()
|
2023-01-14 18:34:21 -07:00
|
|
|
|
check_close()
|
2022-06-30 04:16:46 -07:00
|
|
|
|
os.remove(testlog)
|
|
|
|
|
end)
|
|
|
|
|
|
2023-03-09 06:07:36 -07:00
|
|
|
|
local function get_tmproot()
|
2022-06-30 04:16:46 -07:00
|
|
|
|
-- Tempfiles typically look like: "…/nvim.<user>/xxx/0".
|
|
|
|
|
-- - "…/nvim.<user>/xxx/" is the per-process tmpdir, not shared with other Nvims.
|
|
|
|
|
-- - "…/nvim.<user>/" is the tmpdir root, shared by all Nvims (normally).
|
2024-01-12 10:59:57 -07:00
|
|
|
|
local tmproot = (fn.tempname()):match(tmproot_pat)
|
2022-06-30 04:16:46 -07:00
|
|
|
|
ok(tmproot:len() > 4, 'tmproot like "nvim.foo"', tmproot)
|
2023-03-09 06:07:36 -07:00
|
|
|
|
return tmproot
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it('failure modes', function()
|
|
|
|
|
clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } })
|
|
|
|
|
assert_nolog('tempdir is not a directory', testlog)
|
|
|
|
|
assert_nolog('tempdir has invalid permissions', testlog)
|
|
|
|
|
|
|
|
|
|
local tmproot = get_tmproot()
|
2022-06-30 04:16:46 -07:00
|
|
|
|
|
|
|
|
|
-- Test how Nvim handles invalid tmpdir root (by hostile users or accidents).
|
|
|
|
|
--
|
|
|
|
|
-- "…/nvim.<user>/" is not a directory:
|
|
|
|
|
expect_exit(command, ':qall!')
|
|
|
|
|
rmdir(tmproot)
|
|
|
|
|
write_file(tmproot, '') -- Not a directory, vim_mktempdir() should skip it.
|
2023-03-09 06:07:36 -07:00
|
|
|
|
clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } })
|
2024-01-12 10:59:57 -07:00
|
|
|
|
matches(tmproot_pat, fn.stdpath('run')) -- Tickle vim_mktempdir().
|
2022-06-30 04:16:46 -07:00
|
|
|
|
-- Assert that broken tmpdir root was handled.
|
2023-01-16 16:12:59 -07:00
|
|
|
|
assert_log('tempdir root not a directory', testlog, 100)
|
2022-06-30 04:16:46 -07:00
|
|
|
|
|
|
|
|
|
-- "…/nvim.<user>/" has wrong permissions:
|
2022-11-21 17:13:30 -07:00
|
|
|
|
skip(is_os('win'), 'TODO(justinmk): need setfperm/getfperm on Windows. #8244')
|
2022-06-30 04:16:46 -07:00
|
|
|
|
os.remove(testlog)
|
|
|
|
|
os.remove(tmproot)
|
|
|
|
|
mkdir(tmproot)
|
2024-01-12 10:59:57 -07:00
|
|
|
|
fn.setfperm(tmproot, 'rwxr--r--') -- Invalid permissions, vim_mktempdir() should skip it.
|
2023-03-09 06:07:36 -07:00
|
|
|
|
clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } })
|
2024-01-12 10:59:57 -07:00
|
|
|
|
matches(tmproot_pat, fn.stdpath('run')) -- Tickle vim_mktempdir().
|
2022-06-30 04:16:46 -07:00
|
|
|
|
-- Assert that broken tmpdir root was handled.
|
2023-01-16 16:12:59 -07:00
|
|
|
|
assert_log('tempdir root has invalid permissions', testlog, 100)
|
2022-06-30 04:16:46 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('too long', function()
|
2023-03-09 06:07:36 -07:00
|
|
|
|
local bigname = ('%s/%s'):format(os_tmpdir, ('x'):rep(666))
|
2022-06-30 04:16:46 -07:00
|
|
|
|
mkdir(bigname)
|
|
|
|
|
clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = bigname } })
|
2024-01-12 10:59:57 -07:00
|
|
|
|
matches(tmproot_pat, fn.stdpath('run')) -- Tickle vim_mktempdir().
|
|
|
|
|
local len = (fn.tempname()):len()
|
2022-06-30 04:16:46 -07:00
|
|
|
|
ok(len > 4 and len < 256, '4 < len < 256', tostring(len))
|
|
|
|
|
end)
|
2023-03-09 06:07:36 -07:00
|
|
|
|
|
|
|
|
|
it('disappeared #1432', function()
|
|
|
|
|
clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } })
|
|
|
|
|
assert_nolog('tempdir disappeared', testlog)
|
|
|
|
|
|
|
|
|
|
local function rm_tmpdir()
|
2024-01-12 10:59:57 -07:00
|
|
|
|
local tmpname1 = fn.tempname()
|
|
|
|
|
local tmpdir1 = fn.fnamemodify(tmpname1, ':h')
|
|
|
|
|
eq(fn.stdpath('run'), tmpdir1)
|
2023-03-09 06:07:36 -07:00
|
|
|
|
|
|
|
|
|
rmdir(tmpdir1)
|
|
|
|
|
retry(nil, 1000, function()
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq(0, fn.isdirectory(tmpdir1))
|
2023-03-09 06:07:36 -07:00
|
|
|
|
end)
|
2024-01-12 10:59:57 -07:00
|
|
|
|
local tmpname2 = fn.tempname()
|
|
|
|
|
local tmpdir2 = fn.fnamemodify(tmpname2, ':h')
|
2023-03-09 06:07:36 -07:00
|
|
|
|
neq(tmpdir1, tmpdir2)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Your antivirus hates you...
|
|
|
|
|
rm_tmpdir()
|
|
|
|
|
assert_log('tempdir disappeared', testlog, 100)
|
2024-01-12 10:59:57 -07:00
|
|
|
|
fn.tempname()
|
|
|
|
|
fn.tempname()
|
|
|
|
|
fn.tempname()
|
|
|
|
|
eq('', api.nvim_get_vvar('errmsg'))
|
2023-03-09 06:07:36 -07:00
|
|
|
|
rm_tmpdir()
|
2024-01-12 10:59:57 -07:00
|
|
|
|
fn.tempname()
|
|
|
|
|
fn.tempname()
|
|
|
|
|
fn.tempname()
|
|
|
|
|
eq('E5431: tempdir disappeared (2 times)', api.nvim_get_vvar('errmsg'))
|
2023-03-09 06:07:36 -07:00
|
|
|
|
rm_tmpdir()
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq('E5431: tempdir disappeared (3 times)', api.nvim_get_vvar('errmsg'))
|
2023-03-09 06:07:36 -07:00
|
|
|
|
end)
|
2022-06-30 04:16:46 -07:00
|
|
|
|
end)
|