neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit e3d46a63375c84b7bd409f1f07ef56eb985eae50
parent 785ac9f2285a413751ce963082469598aa81f74e
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Fri, 20 Feb 2026 06:53:33 +0800

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.
Diffstat:
Mcmake/RunTests.cmake | 21++++++++++++++-------
Mtest/CMakeLists.txt | 2+-
Mtest/functional/core/startup_spec.lua | 2+-
Mtest/functional/editor/ftplugin_spec.lua | 6+++---
Mtest/functional/legacy/008_autocommands_spec.lua | 2+-
Mtest/functional/options/autochdir_spec.lua | 14+++++++-------
Mtest/functional/plugin/pack_spec.lua | 8++++----
Mtest/functional/provider/clipboard_spec.lua | 20++++++++++++++++----
Mtest/functional/terminal/ex_terminal_spec.lua | 22++++++++++++++--------
Mtest/functional/treesitter/highlight_spec.lua | 2+-
Mtest/functional/treesitter/inspect_tree_spec.lua | 2+-
Mtest/functional/ui/embed_spec.lua | 1+
Mtest/functional/vimscript/executable_spec.lua | 6++++++
Mtest/functional/vimscript/fnamemodify_spec.lua | 3+++
Mtest/functional/vimscript/system_spec.lua | 7++++++-
15 files changed, 79 insertions(+), 39 deletions(-)

diff --git 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 @@ -10,7 +10,7 @@ set(TEST_OPTIONS -D DEPS_INSTALL_DIR=${DEPS_INSTALL_DIR} -D NVIM_PRG=$<TARGET_FILE:nvim_bin> -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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([[<C-\><C-N>]]) - 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([[<C-\><C-N>]]) 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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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"')]])