From e3d46a63375c84b7bd409f1f07ef56eb985eae50 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 20 Feb 2026 06:53:33 +0800 Subject: [PATCH] test: start test runners in Xtest_xdg dir (#37964) This is a better way to prevent parallel tests from interfering with each other, as there are many ways files can be created and deleted in tests, so enforcing different file names is hard. Using $TMPDIR can also work in most cases, but 'backipskip' etc. have special defaults for $TMPDIR. Symlink runtime/, src/, test/ and README.md to Xtest_xdg dir to make tests more convenient (and symlinking test/ is required for busted). Also, use README.md instead of test/README.md in the Ex mode inccommand test, as test/README.md no longer contains 'N' char. --- cmake/RunTests.cmake | 21 ++++++++++++------ test/CMakeLists.txt | 2 +- test/functional/core/startup_spec.lua | 2 +- test/functional/editor/ftplugin_spec.lua | 6 ++--- .../legacy/008_autocommands_spec.lua | 2 +- test/functional/options/autochdir_spec.lua | 14 ++++++------ test/functional/plugin/pack_spec.lua | 8 +++---- test/functional/provider/clipboard_spec.lua | 20 +++++++++++++---- test/functional/terminal/ex_terminal_spec.lua | 22 ++++++++++++------- test/functional/treesitter/highlight_spec.lua | 2 +- .../treesitter/inspect_tree_spec.lua | 2 +- test/functional/ui/embed_spec.lua | 1 + test/functional/vimscript/executable_spec.lua | 6 +++++ .../functional/vimscript/fnamemodify_spec.lua | 3 +++ test/functional/vimscript/system_spec.lua | 7 +++++- 15 files changed, 79 insertions(+), 39 deletions(-) diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake index 2885256904..62cff6eebd 100644 --- a/cmake/RunTests.cmake +++ b/cmake/RunTests.cmake @@ -11,7 +11,7 @@ endif() set(ENV{NVIM_TEST} "1") # Set LC_ALL to meet expectations of some locale-sensitive tests. set(ENV{LC_ALL} "en_US.UTF-8") -set(ENV{VIMRUNTIME} ${WORKING_DIR}/runtime) +set(ENV{VIMRUNTIME} ${ROOT_DIR}/runtime) set(TEST_XDG_PREFIX ${BUILD_DIR}/Xtest_xdg${TEST_SUFFIX}) set(ENV{XDG_CONFIG_HOME} ${TEST_XDG_PREFIX}/config) set(ENV{XDG_DATA_HOME} ${TEST_XDG_PREFIX}/share) @@ -21,6 +21,13 @@ unset(ENV{XDG_DATA_DIRS}) unset(ENV{NVIM}) # Clear $NVIM in case tests are running from Nvim. #11009 unset(ENV{TMUX}) # Nvim TUI shouldn't think it's running in tmux. #34173 +# Prepare for running tests in ${TEST_XDG_PREFIX}. +file(MAKE_DIRECTORY ${TEST_XDG_PREFIX}) +file(CREATE_LINK ${ROOT_DIR}/runtime ${TEST_XDG_PREFIX}/runtime SYMBOLIC) +file(CREATE_LINK ${ROOT_DIR}/src ${TEST_XDG_PREFIX}/src SYMBOLIC) +file(CREATE_LINK ${ROOT_DIR}/test ${TEST_XDG_PREFIX}/test SYMBOLIC) +file(CREATE_LINK ${ROOT_DIR}/README.md ${TEST_XDG_PREFIX}/README.md SYMBOLIC) + # TODO(dundargoc): The CIRRUS_CI environment variable isn't passed to here from # the main CMakeLists.txt, so we have to manually pass it to this script and # re-set the environment variable. Investigate if we can avoid manually setting @@ -50,7 +57,7 @@ endif() # Force $TEST_PATH to workdir-relative path ("test/…"). if(IS_ABSOLUTE ${TEST_PATH}) - file(RELATIVE_PATH TEST_PATH "${WORKING_DIR}" "${TEST_PATH}") + file(RELATIVE_PATH TEST_PATH "${ROOT_DIR}" "${TEST_PATH}") endif() separate_arguments(BUSTED_ARGS NATIVE_COMMAND $ENV{BUSTED_ARGS}) @@ -69,7 +76,7 @@ endif() # TMPDIR: for testutil.tmpname() and Nvim tempname(). set(ENV{TMPDIR} "${BUILD_DIR}/Xtest_tmpdir${TEST_SUFFIX}") -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory $ENV{TMPDIR}) +file(MAKE_DIRECTORY $ENV{TMPDIR}) # HISTFILE: do not write into user's ~/.bash_history set(ENV{HISTFILE} "/dev/null") @@ -88,17 +95,17 @@ endif() execute_process( # Note: because of "-ll" (low-level interpreter mode), some modules like # _core/editor.lua are not loaded. - COMMAND ${NVIM_PRG} -ll ${WORKING_DIR}/test/lua_runner.lua ${DEPS_INSTALL_DIR}/share/lua/5.1/ busted -v -o test.busted.outputHandlers.nvim + COMMAND ${NVIM_PRG} -ll ${ROOT_DIR}/test/lua_runner.lua ${DEPS_INSTALL_DIR}/share/lua/5.1/ busted -v -o test.busted.outputHandlers.nvim -Xoutput "{\"test_path\": \"${TEST_PATH}\", \"summary_file\": \"${TEST_SUMMARY_FILE}\"}" --lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua --lpath=${BUILD_DIR}/?.lua - --lpath=${WORKING_DIR}/src/?.lua - --lpath=${WORKING_DIR}/runtime/lua/?.lua + --lpath=${ROOT_DIR}/src/?.lua + --lpath=${ROOT_DIR}/runtime/lua/?.lua --lpath=?.lua ${BUSTED_ARGS} ${TEST_PATH} TIMEOUT $ENV{TEST_TIMEOUT} - WORKING_DIRECTORY ${WORKING_DIR} + WORKING_DIRECTORY ${TEST_XDG_PREFIX} RESULT_VARIABLE res ${EXTRA_ARGS}) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3ed2c6d22c..5ede98ed1e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,7 +10,7 @@ set(TEST_OPTIONS -D DEPS_INSTALL_DIR=${DEPS_INSTALL_DIR} -D NVIM_PRG=$ -D TEST_DIR=${TEST_DIR} - -D WORKING_DIR=${PROJECT_SOURCE_DIR}) + -D ROOT_DIR=${PROJECT_SOURCE_DIR}) check_lua_module(${LUA_PRG} "ffi" LUA_HAS_FFI) if(LUA_HAS_FFI) diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index 39e943922f..c8e7ec6612 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -1780,7 +1780,7 @@ describe('inccommand on ex mode', function() '-c', 'set termguicolors background=dark', '-E', - 'test/README.md', + 'README.md', }, { term = true, env = { VIMRUNTIME = os.getenv('VIMRUNTIME') }, diff --git a/test/functional/editor/ftplugin_spec.lua b/test/functional/editor/ftplugin_spec.lua index b7f323b38c..78ceb30390 100644 --- a/test/functional/editor/ftplugin_spec.lua +++ b/test/functional/editor/ftplugin_spec.lua @@ -25,18 +25,18 @@ local function lua_includeexpr(module) end describe("ftplugin: Lua 'includeexpr'", function() - local repo_root = '' + local repo_root = vim.fs.normalize(t.paths.test_source_path) local temp_dir = '' setup(function() - repo_root = vim.fs.normalize(assert(vim.uv.cwd())) temp_dir = t.tmpname(false) n.clear() + n.api.nvim_set_current_dir(repo_root) end) teardown(function() n.expect_exit(n.command, 'qall!') - n.rmdir('runtime/lua/foo/') + n.rmdir(repo_root .. '/runtime/lua/foo/') end) before_each(function() diff --git a/test/functional/legacy/008_autocommands_spec.lua b/test/functional/legacy/008_autocommands_spec.lua index b7b411d631..a25862918a 100644 --- a/test/functional/legacy/008_autocommands_spec.lua +++ b/test/functional/legacy/008_autocommands_spec.lua @@ -77,7 +77,7 @@ describe('autocommands that delete and unload buffers:', function() command('set nohidden') command('silent! edit Xxx2') command('silent! edit Xxx1') - command('silent! edit Makefile') -- an existing file + command('silent! edit README.md') -- an existing file command('silent! split new2') expect_exit(command, 'silent! quit') eq('VimLeave done', string.match(read_file(test_file), '^%s*(.-)%s*$')) diff --git a/test/functional/options/autochdir_spec.lua b/test/functional/options/autochdir_spec.lua index a409262d84..612ede4681 100644 --- a/test/functional/options/autochdir_spec.lua +++ b/test/functional/options/autochdir_spec.lua @@ -9,16 +9,16 @@ local mkdir = t.mkdir describe("'autochdir'", function() it('given on the shell gets processed properly', function() - local targetdir = 'test/functional/fixtures' + local start_dir = vim.uv.cwd() + local target_dir = t.paths.test_source_path .. '/test/functional/fixtures' - -- By default 'autochdir' is off, thus getcwd() returns the repo root. - clear(targetdir .. '/tty-test.c') - local rootdir = fn.getcwd() - local expected = rootdir .. '/' .. targetdir + -- By default 'autochdir' is off, thus getcwd() returns the initial directory. + clear(target_dir .. '/tty-test.c') + eq(start_dir, fn.getcwd()) -- With 'autochdir' on, we should get the directory of tty-test.c. - clear('--cmd', 'set autochdir', targetdir .. '/tty-test.c') - eq(t.is_os('win') and expected:gsub('/', '\\') or expected, fn.getcwd()) + clear('--cmd', 'set autochdir', target_dir .. '/tty-test.c') + eq(t.is_os('win') and target_dir:gsub('/', '\\') or target_dir, fn.getcwd()) end) it('is not overwritten by getwinvar() call #17609', function() diff --git a/test/functional/plugin/pack_spec.lua b/test/functional/plugin/pack_spec.lua index c63769b82f..f14684b763 100644 --- a/test/functional/plugin/pack_spec.lua +++ b/test/functional/plugin/pack_spec.lua @@ -1083,8 +1083,8 @@ describe('vim.pack', function() end) it('is not affected by special environment variables', function() - fn.setenv('GIT_WORK_TREE', fn.getcwd()) - fn.setenv('GIT_DIR', vim.fs.joinpath(fn.getcwd(), '.git')) + fn.setenv('GIT_WORK_TREE', t.paths.test_source_path) + fn.setenv('GIT_DIR', vim.fs.joinpath(t.paths.test_source_path, '.git')) local ref_environ = fn.environ() vim_pack_add({ repos_src.basic }) @@ -1889,8 +1889,8 @@ describe('vim.pack', function() end) it('is not affected by special environment variables', function() - fn.setenv('GIT_WORK_TREE', fn.getcwd()) - fn.setenv('GIT_DIR', vim.fs.joinpath(fn.getcwd(), '.git')) + fn.setenv('GIT_WORK_TREE', t.paths.test_source_path) + fn.setenv('GIT_DIR', vim.fs.joinpath(t.paths.test_source_path, '.git')) local ref_environ = fn.environ() vim_pack_add({ repos_src.fetch }) diff --git a/test/functional/provider/clipboard_spec.lua b/test/functional/provider/clipboard_spec.lua index b4de1fbd7c..5666927d6e 100644 --- a/test/functional/provider/clipboard_spec.lua +++ b/test/functional/provider/clipboard_spec.lua @@ -144,7 +144,11 @@ describe('clipboard', function() it('`:redir @+>` with invalid g:clipboard shows exactly one error #7184', function() command("let g:clipboard = 'bogus'") - command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END') + n.exec([[ + redir @+> + silent echo system("cat test/functional/fixtures/tty-test.c") + redir END + ]]) screen:expect([[ ^ | {1:~ }|*2 @@ -301,8 +305,12 @@ describe('clipboard (with fake clipboard.vim)', function() it('`:redir @+>` invokes clipboard once-per-message', function() eq(0, eval('g:clip_called_set')) - command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END') - -- Assuming CONTRIBUTING.md has >100 lines. + n.exec([[ + redir @+> + silent echo system("cat test/functional/fixtures/tty-test.c") + redir END + ]]) + -- Assuming tty-test.c has >100 lines. assert(eval('g:clip_called_set') > 100) end) @@ -311,7 +319,11 @@ describe('clipboard (with fake clipboard.vim)', function() -- NOT propagate to the clipboard. This is consistent with Vim. command('set clipboard=unnamedplus') eq(0, eval('g:clip_called_set')) - command('redir @"> | :silent echo system("cat CONTRIBUTING.md") | redir END') + n.exec([[ + redir @"> + silent echo system("cat test/functional/fixtures/tty-test.c") + redir END + ]]) eq(0, eval('g:clip_called_set')) end) diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua index 587b96bcd8..958c558998 100644 --- a/test/functional/terminal/ex_terminal_spec.lua +++ b/test/functional/terminal/ex_terminal_spec.lua @@ -202,6 +202,12 @@ local function test_terminal_with_fake_shell(backslash) api.nvim_set_option_value('shell', shell_path, {}) api.nvim_set_option_value('shellcmdflag', 'EXE', {}) api.nvim_set_option_value('shellxquote', '', {}) -- win: avoid extra quotes + t.mkdir('Xsomedir') + t.write_file('Xsomedir/Xuniquefile', '') + end) + + after_each(function() + n.rmdir('Xsomedir') end) it('with no argument, acts like jobstart(…,{term=true})', function() @@ -290,7 +296,7 @@ local function test_terminal_with_fake_shell(backslash) command('autocmd! nvim.terminal TermClose') feed_command('terminal') eq('term://', string.match(eval('bufname("%")'), '^term://')) - eq('scripts/shadacat.py', eval('findfile("scripts/shadacat.py", ".")')) + eq('Xsomedir/Xuniquefile', eval('findfile("Xsomedir/Xuniquefile", ".")')) end) it('works with :find', function() @@ -304,26 +310,26 @@ local function test_terminal_with_fake_shell(backslash) ]]) eq('term://', string.match(eval('bufname("%")'), '^term://')) feed([[]]) - feed_command([[find */shadacat.py]]) + feed_command([[find */Xuniquefile]]) if is_os('win') then - eq('scripts\\shadacat.py', eval('bufname("%")')) + eq('Xsomedir\\Xuniquefile', eval('bufname("%")')) else - eq('scripts/shadacat.py', eval('bufname("%")')) + eq('Xsomedir/Xuniquefile', eval('bufname("%")')) end end) it('works with gf', function() - feed_command([[terminal echo "scripts/shadacat.py"]]) + feed_command([[terminal echo "Xsomedir/Xuniquefile"]]) screen:expect([[ - ^ready $ echo "scripts/shadacat.py" | + ^ready $ echo "Xsomedir/Xuniquefile" | | [Process exited 0] | - :terminal echo "scripts/shadacat.py" | + :terminal echo "Xsomedir/Xuniquefile" | ]]) feed([[]]) eq('term://', string.match(eval('bufname("%")'), '^term://')) feed([[ggf"lgf]]) - eq('scripts/shadacat.py', eval('bufname("%")')) + eq('Xsomedir/Xuniquefile', eval('bufname("%")')) end) it('with bufhidden=delete #3958', function() diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua index bf085aa42d..40731420fc 100644 --- a/test/functional/treesitter/highlight_spec.lua +++ b/test/functional/treesitter/highlight_spec.lua @@ -1443,7 +1443,7 @@ end) it('no nil index for missing highlight query', function() clear() - local cqueries = vim.uv.cwd() .. '/runtime/queries/c/' + local cqueries = t.paths.test_source_path .. '/runtime/queries/c/' os.rename(cqueries .. 'highlights.scm', cqueries .. '_highlights.scm') finally(function() os.rename(cqueries .. '_highlights.scm', cqueries .. 'highlights.scm') diff --git a/test/functional/treesitter/inspect_tree_spec.lua b/test/functional/treesitter/inspect_tree_spec.lua index 01d8260fce..fb87618fa9 100644 --- a/test/functional/treesitter/inspect_tree_spec.lua +++ b/test/functional/treesitter/inspect_tree_spec.lua @@ -38,7 +38,7 @@ describe('vim.treesitter.inspect_tree', function() it('sets correct buffer name', function() t.skip(t.is_zig_build(), 'vim.treesitter not found after chdir with build.zig') - n.api.nvim_set_current_dir('test/functional/fixtures') + n.api.nvim_set_current_dir(t.paths.test_source_path .. '/test/functional/fixtures') n.command('edit lua/syntax_error.lua') eq('lua/syntax_error.lua', n.fn.bufname('%')) local full_path = n.api.nvim_buf_get_name(0) diff --git a/test/functional/ui/embed_spec.lua b/test/functional/ui/embed_spec.lua index 67a5d6643f..56fb59feac 100644 --- a/test/functional/ui/embed_spec.lua +++ b/test/functional/ui/embed_spec.lua @@ -236,6 +236,7 @@ describe('--embed UI', function() it('updates cwd of attached UI #21771', function() clear { args_rm = { '--headless' } } + api.nvim_set_current_dir(t.paths.test_source_path) local screen = Screen.new(40, 8) diff --git a/test/functional/vimscript/executable_spec.lua b/test/functional/vimscript/executable_spec.lua index 05d249ca32..3840f55e84 100644 --- a/test/functional/vimscript/executable_spec.lua +++ b/test/functional/vimscript/executable_spec.lua @@ -20,6 +20,9 @@ describe('executable()', function() if is_os('win') then it('exepath respects shellslash', function() + -- test/ cannot be a symlink in this test. + n.api.nvim_set_current_dir(t.paths.test_source_path) + command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")') eq( [[test\functional\fixtures\bin\null.CMD]], @@ -33,6 +36,9 @@ describe('executable()', function() end) it('stdpath respects shellslash', function() + -- Needs to check paths relative to repo root dir. + n.api.nvim_set_current_dir(t.paths.test_source_path) + t.matches( [[build\Xtest_xdg[%w_]*\share\nvim%-data]], call('fnamemodify', call('stdpath', 'data'), ':.') diff --git a/test/functional/vimscript/fnamemodify_spec.lua b/test/functional/vimscript/fnamemodify_spec.lua index f2cee9b83e..8b0b242c62 100644 --- a/test/functional/vimscript/fnamemodify_spec.lua +++ b/test/functional/vimscript/fnamemodify_spec.lua @@ -45,6 +45,9 @@ describe('fnamemodify()', function() end) it('handles examples from ":help filename-modifiers"', function() + -- src/ cannot be a symlink in this test. + n.api.nvim_set_current_dir(t.paths.test_source_path) + local filename = 'src/version.c' local cwd = getcwd() diff --git a/test/functional/vimscript/system_spec.lua b/test/functional/vimscript/system_spec.lua index 54650caa71..67a613d848 100644 --- a/test/functional/vimscript/system_spec.lua +++ b/test/functional/vimscript/system_spec.lua @@ -131,11 +131,16 @@ describe('system()', function() before_each(function() screen = Screen.new() + t.write_file('Xmorefile', ('line1\nline2\nline3\n'):rep(10)) + end) + + after_each(function() + os.remove('Xmorefile') end) if is_os('win') then local function test_more() - eq('root = true', eval([[get(split(system('"more" ".editorconfig"'), "\n"), 0, '')]])) + eq('line1', eval([[get(split(system('"more" "Xmorefile"'), "\n"), 0, '')]])) end local function test_shell_unquoting() eval([[system('"ping" "-n" "1" "127.0.0.1"')]])