aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/api/ui_spec.lua37
-rw-r--r--test/functional/api/vim_spec.lua2
-rw-r--r--test/functional/autocmd/termclose_spec.lua6
-rw-r--r--test/functional/core/fileio_spec.lua68
-rw-r--r--test/functional/core/job_spec.lua183
-rw-r--r--test/functional/core/main_spec.lua131
-rw-r--r--test/functional/eval/server_spec.lua76
-rw-r--r--test/functional/eval/system_spec.lua8
-rw-r--r--test/functional/helpers.lua21
-rw-r--r--test/functional/insert/insert_spec.lua41
-rw-r--r--test/functional/insert/last_inserted_spec.lua22
-rw-r--r--test/functional/options/defaults_spec.lua276
-rw-r--r--test/functional/provider/nodejs_spec.lua4
-rw-r--r--test/functional/shada/merging_spec.lua109
-rw-r--r--test/functional/shada/shada_spec.lua6
-rw-r--r--test/functional/terminal/mouse_spec.lua16
-rw-r--r--test/functional/terminal/tui_spec.lua24
-rw-r--r--test/functional/ui/highlight_spec.lua36
-rw-r--r--test/functional/ui/inccommand_spec.lua102
-rw-r--r--test/functional/ui/input_spec.lua4
-rw-r--r--test/functional/ui/screen_basic_spec.lua33
-rw-r--r--test/functional/ui/searchhl_spec.lua34
-rw-r--r--test/helpers.lua70
-rw-r--r--test/includes/pre/sys/stat.h4
-rw-r--r--test/unit/helpers.lua2
-rw-r--r--test/unit/os/fileio_spec.lua8
-rw-r--r--test/unit/os/fs_spec.lua22
-rw-r--r--test/unit/preprocess.lua58
28 files changed, 1140 insertions, 263 deletions
diff --git a/test/functional/api/ui_spec.lua b/test/functional/api/ui_spec.lua
new file mode 100644
index 0000000000..b028a50b02
--- /dev/null
+++ b/test/functional/api/ui_spec.lua
@@ -0,0 +1,37 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear = helpers.clear
+local eq = helpers.eq
+local eval = helpers.eval
+local expect_err = helpers.expect_err
+local meths = helpers.meths
+local request = helpers.request
+
+describe('nvim_ui_attach()', function()
+ before_each(function()
+ clear()
+ end)
+ it('handles very large width/height #2180', function()
+ local screen = Screen.new(999, 999)
+ screen:attach()
+ eq(999, eval('&lines'))
+ eq(999, eval('&columns'))
+ end)
+ it('invalid option returns error', function()
+ expect_err('No such UI option: foo',
+ meths.ui_attach, 80, 24, { foo={'foo'} })
+ end)
+ it('validates channel arg', function()
+ expect_err('UI not attached to channel: 1',
+ request, 'nvim_ui_try_resize', 40, 10)
+ expect_err('UI not attached to channel: 1',
+ request, 'nvim_ui_set_option', 'rgb', true)
+ expect_err('UI not attached to channel: 1',
+ request, 'nvim_ui_detach')
+
+ local screen = Screen.new()
+ screen:attach({rgb=false})
+ expect_err('UI already attached to channel: 1',
+ request, 'nvim_ui_attach', 40, 10, { rgb=false })
+ end)
+end)
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 7ac20a99af..718294d941 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -73,6 +73,8 @@ describe('api', function()
it('captures command output', function()
eq('this is\nspinal tap',
nvim('command_output', [[echo "this is\nspinal tap"]]))
+ eq('no line ending!',
+ nvim('command_output', [[echon "no line ending!"]]))
end)
it('captures empty command output', function()
diff --git a/test/functional/autocmd/termclose_spec.lua b/test/functional/autocmd/termclose_spec.lua
index 0804579a4f..db4e5379d0 100644
--- a/test/functional/autocmd/termclose_spec.lua
+++ b/test/functional/autocmd/termclose_spec.lua
@@ -32,7 +32,7 @@ describe('TermClose event', function()
end)
it('kills job trapping SIGTERM', function()
- if helpers.pending_win32(pending) then return end
+ if iswin() then return end
nvim('set_option', 'shell', 'sh')
nvim('set_option', 'shellcmdflag', '-c')
command([[ let g:test_job = jobstart('trap "" TERM && echo 1 && sleep 60', { ]]
@@ -51,8 +51,8 @@ describe('TermClose event', function()
ok(duration <= 4000) -- Epsilon for slow CI
end)
- it('kills pty job trapping SIGHUP and SIGTERM', function()
- if helpers.pending_win32(pending) then return end
+ it('kills PTY job trapping SIGHUP and SIGTERM', function()
+ if iswin() then return end
nvim('set_option', 'shell', 'sh')
nvim('set_option', 'shellcmdflag', '-c')
command([[ let g:test_job = jobstart('trap "" HUP TERM && echo 1 && sleep 60', { ]]
diff --git a/test/functional/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua
new file mode 100644
index 0000000000..09533e4e60
--- /dev/null
+++ b/test/functional/core/fileio_spec.lua
@@ -0,0 +1,68 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local command = helpers.command
+local eq = helpers.eq
+local feed = helpers.feed
+local funcs = helpers.funcs
+local nvim_prog = helpers.nvim_prog
+local request = helpers.request
+local retry = helpers.retry
+local rmdir = helpers.rmdir
+local sleep = helpers.sleep
+
+describe('fileio', function()
+ before_each(function()
+ end)
+ after_each(function()
+ command(':qall!')
+ os.remove('Xtest_startup_shada')
+ os.remove('Xtest_startup_file1')
+ os.remove('Xtest_startup_file2')
+ rmdir('Xtest_startup_swapdir')
+ end)
+
+ it('fsync() codepaths #8304', function()
+ clear({ args={ '-i', 'Xtest_startup_shada',
+ '--cmd', 'set directory=Xtest_startup_swapdir' } })
+
+ -- These cases ALWAYS force fsync (regardless of 'fsync' option):
+
+ -- 1. Idle (CursorHold) with modified buffers (+ 'swapfile').
+ command('write Xtest_startup_file1')
+ feed('ifoo<esc>h')
+ command('write')
+ eq(0, request('nvim__stats').fsync) -- 'nofsync' is the default.
+ command('set swapfile')
+ command('set updatetime=1')
+ feed('izub<esc>h') -- File is 'modified'.
+ sleep(3) -- Allow 'updatetime' to expire.
+ retry(3, nil, function()
+ eq(1, request('nvim__stats').fsync)
+ end)
+ command('set updatetime=9999')
+
+ -- 2. Exit caused by deadly signal (+ 'swapfile').
+ local j = funcs.jobstart({ nvim_prog, '-u', 'NONE', '-i',
+ 'Xtest_startup_shada', '--headless',
+ '-c', 'set swapfile',
+ '-c', 'write Xtest_startup_file2',
+ '-c', 'put =localtime()', })
+ sleep(10) -- Let Nvim start.
+ funcs.jobstop(j) -- Send deadly signal.
+
+ -- 3. SIGPWR signal.
+ -- ??
+
+ -- 4. Explicit :preserve command.
+ command('preserve')
+ eq(2, request('nvim__stats').fsync)
+
+ -- 5. Enable 'fsync' option, write file.
+ command('set fsync')
+ feed('ibaz<esc>h')
+ command('write')
+ eq(4, request('nvim__stats').fsync)
+ end)
+end)
+
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 6d4cadbdc8..e90339b0cd 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -19,14 +19,18 @@ local expect_twostreams = helpers.expect_twostreams
local expect_msg_seq = helpers.expect_msg_seq
local Screen = require('test.functional.ui.screen')
+-- Kill process with given pid
+local function os_kill(pid)
+ return os.execute((iswin()
+ and 'taskkill /f /t /pid '..pid..' > nul'
+ or 'kill -9 '..pid..' > /dev/null'))
+end
+
describe('jobs', function()
local channel
before_each(function()
clear()
- if iswin() then
- helpers.set_shell_powershell()
- end
channel = nvim('get_api_info')[1]
nvim('set_var', 'channel', channel)
source([[
@@ -52,7 +56,7 @@ describe('jobs', function()
it('uses &shell and &shellcmdflag if passed a string', function()
nvim('command', "let $VAR = 'abc'")
if iswin() then
- nvim('command', "let j = jobstart('echo $env:VAR', g:job_opts)")
+ nvim('command', "let j = jobstart('echo %VAR%', g:job_opts)")
else
nvim('command', "let j = jobstart('echo $VAR', g:job_opts)")
end
@@ -64,7 +68,7 @@ describe('jobs', function()
it('changes to given / directory', function()
nvim('command', "let g:job_opts.cwd = '/'")
if iswin() then
- nvim('command', "let j = jobstart('(Get-Location).Path', g:job_opts)")
+ nvim('command', "let j = jobstart('cd', g:job_opts)")
else
nvim('command', "let j = jobstart('pwd', g:job_opts)")
end
@@ -79,7 +83,7 @@ describe('jobs', function()
mkdir(dir)
nvim('command', "let g:job_opts.cwd = '" .. dir .. "'")
if iswin() then
- nvim('command', "let j = jobstart('(Get-Location).Path', g:job_opts)")
+ nvim('command', "let j = jobstart('cd', g:job_opts)")
else
nvim('command', "let j = jobstart('pwd', g:job_opts)")
end
@@ -103,7 +107,7 @@ describe('jobs', function()
local _, err = pcall(function()
nvim('command', "let g:job_opts.cwd = '" .. dir .. "'")
if iswin() then
- nvim('command', "let j = jobstart('pwd|%{$_.Path}', g:job_opts)")
+ nvim('command', "let j = jobstart('cd', g:job_opts)")
else
nvim('command', "let j = jobstart('pwd', g:job_opts)")
end
@@ -134,10 +138,8 @@ describe('jobs', function()
end)
it('invokes callbacks when the job writes and exits', function()
- -- TODO: hangs on Windows
- if helpers.pending_win32(pending) then return end
nvim('command', "let g:job_opts.on_stderr = function('OnEvent')")
- nvim('command', [[call jobstart('echo ""', g:job_opts)]])
+ nvim('command', [[call jobstart(has('win32') ? 'echo:' : 'echo', g:job_opts)]])
expect_twostreams({{'notification', 'stdout', {0, {'', ''}}},
{'notification', 'stdout', {0, {''}}}},
{{'notification', 'stderr', {0, {''}}}})
@@ -145,15 +147,28 @@ describe('jobs', function()
end)
it('allows interactive commands', function()
- if helpers.pending_win32(pending) then return end -- TODO: Need `cat`.
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
+ nvim('command', "let j = jobstart(has('win32') ? ['find', '/v', ''] : ['cat', '-'], g:job_opts)")
neq(0, eval('j'))
nvim('command', 'call jobsend(j, "abc\\n")')
eq({'notification', 'stdout', {0, {'abc', ''}}}, next_msg())
nvim('command', 'call jobsend(j, "123\\nxyz\\n")')
- eq({'notification', 'stdout', {0, {'123', 'xyz', ''}}}, next_msg())
+ expect_msg_seq(
+ { {'notification', 'stdout', {0, {'123', 'xyz', ''}}}
+ },
+ -- Alternative sequence:
+ { {'notification', 'stdout', {0, {'123', ''}}},
+ {'notification', 'stdout', {0, {'xyz', ''}}}
+ }
+ )
nvim('command', 'call jobsend(j, [123, "xyz", ""])')
- eq({'notification', 'stdout', {0, {'123', 'xyz', ''}}}, next_msg())
+ expect_msg_seq(
+ { {'notification', 'stdout', {0, {'123', 'xyz', ''}}}
+ },
+ -- Alternative sequence:
+ { {'notification', 'stdout', {0, {'123', ''}}},
+ {'notification', 'stdout', {0, {'xyz', ''}}}
+ }
+ )
nvim('command', "call jobstop(j)")
eq({'notification', 'stdout', {0, {''}}}, next_msg())
eq({'notification', 'exit', {0, 0}}, next_msg())
@@ -226,16 +241,14 @@ describe('jobs', function()
end)
it('closes the job streams with jobclose', function()
- if helpers.pending_win32(pending) then return end -- TODO: Need `cat`.
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
+ nvim('command', "let j = jobstart(has('win32') ? ['find', '/v', ''] : ['cat', '-'], g:job_opts)")
nvim('command', 'call jobclose(j, "stdin")')
eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 0}}, next_msg())
+ eq({'notification', 'exit', {0, iswin() and 1 or 0}}, next_msg())
end)
it("disallows jobsend on a job that closed stdin", function()
- if helpers.pending_win32(pending) then return end -- TODO: Need `cat`.
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
+ nvim('command', "let j = jobstart(has('win32') ? ['find', '/v', ''] : ['cat', '-'], g:job_opts)")
nvim('command', 'call jobclose(j, "stdin")')
eq(false, pcall(function()
nvim('command', 'call jobsend(j, ["some data"])')
@@ -248,8 +261,7 @@ describe('jobs', function()
end)
it('disallows jobstop twice on the same job', function()
- if helpers.pending_win32(pending) then return end -- TODO: Need `cat`.
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
+ nvim('command', "let j = jobstart(has('win32') ? ['find', '/v', ''] : ['cat', '-'], g:job_opts)")
neq(0, eval('j'))
eq(true, pcall(eval, "jobstop(j)"))
eq(false, pcall(eval, "jobstop(j)"))
@@ -260,41 +272,49 @@ describe('jobs', function()
end)
it('can get the pid value using getpid', function()
- if helpers.pending_win32(pending) then return end -- TODO: Need `cat`.
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
+ nvim('command', "let j = jobstart(has('win32') ? ['find', '/v', ''] : ['cat', '-'], g:job_opts)")
local pid = eval('jobpid(j)')
- eq(0,os.execute('ps -p '..pid..' > /dev/null'))
+ neq(NIL, meths.get_proc(pid))
nvim('command', 'call jobstop(j)')
eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 0}}, next_msg())
- neq(0,os.execute('ps -p '..pid..' > /dev/null'))
+ if iswin() then
+ expect_msg_seq(
+ -- win64
+ { {'notification', 'exit', {0, 1}}
+ },
+ -- win32
+ { {'notification', 'exit', {0, 15}}
+ }
+ )
+ else
+ eq({'notification', 'exit', {0, 0}}, next_msg())
+ end
+ eq(NIL, meths.get_proc(pid))
end)
it("do not survive the exit of nvim", function()
- if helpers.pending_win32(pending) then return end
-- use sleep, which doesn't die on stdin close
- nvim('command', "let g:j = jobstart(['sleep', '1000'], g:job_opts)")
+ nvim('command', "let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)")
local pid = eval('jobpid(g:j)')
- eq(0,os.execute('ps -p '..pid..' > /dev/null'))
+ neq(NIL, meths.get_proc(pid))
clear()
- neq(0,os.execute('ps -p '..pid..' > /dev/null'))
+ eq(NIL, meths.get_proc(pid))
end)
it('can survive the exit of nvim with "detach"', function()
- if helpers.pending_win32(pending) then return end
nvim('command', 'let g:job_opts.detach = 1')
- nvim('command', "let g:j = jobstart(['sleep', '1000'], g:job_opts)")
+ nvim('command', "let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)")
local pid = eval('jobpid(g:j)')
- eq(0,os.execute('ps -p '..pid..' > /dev/null'))
+ neq(NIL, meths.get_proc(pid))
clear()
- eq(0,os.execute('ps -p '..pid..' > /dev/null'))
+ neq(NIL, meths.get_proc(pid))
-- clean up after ourselves
- os.execute('kill -9 '..pid..' > /dev/null')
+ eq(0, os_kill(pid))
end)
it('can pass user data to the callback', function()
nvim('command', 'let g:job_opts.user = {"n": 5, "s": "str", "l": [1]}')
- nvim('command', [[call jobstart('echo "foo"', g:job_opts)]])
+ nvim('command', [[call jobstart('echo foo', g:job_opts)]])
local data = {n = 5, s = 'str', l = {1}}
expect_msg_seq(
{ {'notification', 'stdout', {data, {'foo', ''}}},
@@ -312,14 +332,14 @@ describe('jobs', function()
it('can omit data callbacks', function()
nvim('command', 'unlet g:job_opts.on_stdout')
nvim('command', 'let g:job_opts.user = 5')
- nvim('command', [[call jobstart('echo "foo"', g:job_opts)]])
+ nvim('command', [[call jobstart('echo foo', g:job_opts)]])
eq({'notification', 'exit', {5, 0}}, next_msg())
end)
it('can omit exit callback', function()
nvim('command', 'unlet g:job_opts.on_exit')
nvim('command', 'let g:job_opts.user = 5')
- nvim('command', [[call jobstart('echo "foo"', g:job_opts)]])
+ nvim('command', [[call jobstart('echo foo', g:job_opts)]])
expect_msg_seq(
{ {'notification', 'stdout', {5, {'foo', ''} } },
{'notification', 'stdout', {5, {''} } },
@@ -401,15 +421,14 @@ describe('jobs', function()
end)
it('does not repeat output with slow output handlers', function()
- if helpers.pending_win32(pending) then return end
source([[
let d = {'data': []}
function! d.on_stdout(job, data, event) dict
- call add(self.data, a:data)
+ call add(self.data, Normalize(a:data))
sleep 200m
endfunction
if has('win32')
- let cmd = '1,2,3,4,5 | foreach-object -process {echo $_; sleep 0.1}'
+ let cmd = 'for /L %I in (1,1,5) do @(echo %I& ping -n 2 127.0.0.1 > nul)'
else
let cmd = ['sh', '-c', 'for i in $(seq 1 5); do echo $i; sleep 0.1; done']
endif
@@ -428,7 +447,7 @@ describe('jobs', function()
endfunction
let Callback = function('PrintArgs', ["foo", "bar"])
let g:job_opts = {'on_stdout': Callback}
- call jobstart('echo "some text"', g:job_opts)
+ call jobstart('echo some text', g:job_opts)
]])
expect_msg_seq(
{ {'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}},
@@ -448,7 +467,7 @@ describe('jobs', function()
return {id, data, event -> rpcnotify(g:channel, '1', a1, a2, Normalize(data), event)}
endfun
let g:job_opts = {'on_stdout': MkFun()}
- call jobstart('echo "some text"', g:job_opts)
+ call jobstart('echo some text', g:job_opts)
]])
expect_msg_seq(
{ {'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}},
@@ -463,7 +482,7 @@ describe('jobs', function()
it('jobstart() works when closure passed directly to `jobstart`', function()
source([[
let g:job_opts = {'on_stdout': {id, data, event -> rpcnotify(g:channel, '1', 'foo', 'bar', Normalize(data), event)}}
- call jobstart('echo "some text"', g:job_opts)
+ call jobstart('echo some text', g:job_opts)
]])
expect_msg_seq(
{ {'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}},
@@ -476,9 +495,20 @@ describe('jobs', function()
end)
describe('jobwait', function()
+ before_each(function()
+ if iswin() then
+ helpers.set_shell_powershell()
+ end
+ end)
+
it('returns a list of status codes', function()
source([[
- call rpcnotify(g:channel, 'wait', jobwait([
+ call rpcnotify(g:channel, 'wait', jobwait(has('win32') ? [
+ \ jobstart('Start-Sleep -Milliseconds 100; exit 4'),
+ \ jobstart('Start-Sleep -Milliseconds 300; exit 5'),
+ \ jobstart('Start-Sleep -Milliseconds 500; exit 6'),
+ \ jobstart('Start-Sleep -Milliseconds 700; exit 7')
+ \ ] : [
\ jobstart('sleep 0.10; exit 4'),
\ jobstart('sleep 0.110; exit 5'),
\ jobstart('sleep 0.210; exit 6'),
@@ -498,7 +528,12 @@ describe('jobs', function()
endif
let g:exits += 1
endfunction
- call jobwait([
+ call jobwait(has('win32') ? [
+ \ jobstart('Start-Sleep -Milliseconds 100; exit 5', g:dict),
+ \ jobstart('Start-Sleep -Milliseconds 300; exit 5', g:dict),
+ \ jobstart('Start-Sleep -Milliseconds 500; exit 5', g:dict),
+ \ jobstart('Start-Sleep -Milliseconds 700; exit 5', g:dict)
+ \ ] : [
\ jobstart('sleep 0.010; exit 5', g:dict),
\ jobstart('sleep 0.030; exit 5', g:dict),
\ jobstart('sleep 0.050; exit 5', g:dict),
@@ -511,7 +546,12 @@ describe('jobs', function()
it('will return status codes in the order of passed ids', function()
source([[
- call rpcnotify(g:channel, 'wait', jobwait([
+ call rpcnotify(g:channel, 'wait', jobwait(has('win32') ? [
+ \ jobstart('Start-Sleep -Milliseconds 700; exit 4'),
+ \ jobstart('Start-Sleep -Milliseconds 500; exit 5'),
+ \ jobstart('Start-Sleep -Milliseconds 300; exit 6'),
+ \ jobstart('Start-Sleep -Milliseconds 100; exit 7')
+ \ ] : [
\ jobstart('sleep 0.070; exit 4'),
\ jobstart('sleep 0.050; exit 5'),
\ jobstart('sleep 0.030; exit 6'),
@@ -525,7 +565,7 @@ describe('jobs', function()
source([[
call rpcnotify(g:channel, 'wait', jobwait([
\ -10,
- \ jobstart('sleep 0.01; exit 5'),
+ \ jobstart((has('win32') ? 'Start-Sleep -Milliseconds 100' : 'sleep 0.01').'; exit 5'),
\ ]))
]])
eq({'notification', 'wait', {{-3, 5}}}, next_msg())
@@ -534,7 +574,9 @@ describe('jobs', function()
it('will return -2 when interrupted without timeout', function()
feed_command('call rpcnotify(g:channel, "ready") | '..
'call rpcnotify(g:channel, "wait", '..
- 'jobwait([jobstart("sleep 10; exit 55")]))')
+ 'jobwait([jobstart("'..
+ (iswin() and 'Start-Sleep 10' or 'sleep 10')..
+ '; exit 55")]))')
eq({'notification', 'ready', {}}, next_msg())
feed('<c-c>')
eq({'notification', 'wait', {{-2}}}, next_msg())
@@ -543,7 +585,9 @@ describe('jobs', function()
it('will return -2 when interrupted with timeout', function()
feed_command('call rpcnotify(g:channel, "ready") | '..
'call rpcnotify(g:channel, "wait", '..
- 'jobwait([jobstart("sleep 10; exit 55")], 10000))')
+ 'jobwait([jobstart("'..
+ (iswin() and 'Start-Sleep 10' or 'sleep 10')..
+ '; exit 55")], 10000))')
eq({'notification', 'ready', {}}, next_msg())
feed('<c-c>')
eq({'notification', 'wait', {{-2}}}, next_msg())
@@ -598,20 +642,22 @@ describe('jobs', function()
end)
describe('with timeout argument', function()
- if helpers.pending_win32(pending) then return end
it('will return -1 if the wait timed out', function()
source([[
call rpcnotify(g:channel, 'wait', jobwait([
\ jobstart('exit 4'),
- \ jobstart('sleep 10; exit 5'),
- \ ], 100))
+ \ jobstart((has('win32') ? 'Start-Sleep 10' : 'sleep 10').'; exit 5'),
+ \ ], has('win32') ? 3000 : 100))
]])
eq({'notification', 'wait', {{4, -1}}}, next_msg())
end)
it('can pass 0 to check if a job exists', function()
source([[
- call rpcnotify(g:channel, 'wait', jobwait([
+ call rpcnotify(g:channel, 'wait', jobwait(has('win32') ? [
+ \ jobstart('Start-Sleep -Milliseconds 50; exit 4'),
+ \ jobstart('Start-Sleep -Milliseconds 300; exit 5'),
+ \ ] : [
\ jobstart('sleep 0.05; exit 4'),
\ jobstart('sleep 0.3; exit 5'),
\ ], 0))
@@ -633,27 +679,38 @@ describe('jobs', function()
end)
it('cannot have both rpc and pty options', function()
- if helpers.pending_win32(pending) then return end -- TODO: Need `cat`.
command("let g:job_opts.pty = v:true")
command("let g:job_opts.rpc = v:true")
- local _, err = pcall(command, "let j = jobstart(['cat', '-'], g:job_opts)")
+ local _, err = pcall(command, "let j = jobstart(has('win32') ? ['find', '/v', ''] : ['cat', '-'], g:job_opts)")
ok(string.find(err, "E475: Invalid argument: job cannot have both 'pty' and 'rpc' options set") ~= nil)
end)
- it('jobstop() kills entire process tree #6530', function()
- command('set shell& shellcmdflag& shellquote& shellpipe& shellredir& shellxquote&')
+ it('does not crash when repeatedly failing to start shell', function()
+ source([[
+ set shell=nosuchshell
+ func! DoIt()
+ call jobstart('true')
+ call jobstart('true')
+ endfunc
+ ]])
+ -- The crash only triggered if both jobs are cleaned up on the same event
+ -- loop tick. This is also prevented by try-block, so feed must be used.
+ feed_command("call DoIt()")
+ feed('<cr>') -- press RETURN
+ eq(2,eval('1+1'))
+ end)
+ it('jobstop() kills entire process tree #6530', function()
-- XXX: Using `nvim` isn't a good test, it reaps its children on exit.
-- local c = 'call jobstart([v:progpath, "-u", "NONE", "-i", "NONE", "--headless"])'
-- local j = eval("jobstart([v:progpath, '-u', 'NONE', '-i', 'NONE', '--headless', '-c', '"
-- ..c.."', '-c', '"..c.."'])")
-- Create child with several descendants.
- local j = (iswin()
- and eval([=[jobstart('start /b cmd /c "ping 127.0.0.1 -n 1 -w 30000 > NUL"]=]
- ..[=[ & start /b cmd /c "ping 127.0.0.1 -n 1 -w 40000 > NUL"]=]
- ..[=[ & start /b cmd /c "ping 127.0.0.1 -n 1 -w 50000 > NUL"')]=])
- or eval("jobstart('sleep 30 | sleep 30 | sleep 30')"))
+ local sleep_cmd = (iswin()
+ and 'ping -n 31 127.0.0.1'
+ or 'sleep 30')
+ local j = eval("jobstart('"..sleep_cmd..' | '..sleep_cmd..' | '..sleep_cmd.."')")
local ppid = funcs.jobpid(j)
local children
retry(nil, nil, function()
diff --git a/test/functional/core/main_spec.lua b/test/functional/core/main_spec.lua
new file mode 100644
index 0000000000..cd396ef820
--- /dev/null
+++ b/test/functional/core/main_spec.lua
@@ -0,0 +1,131 @@
+local lfs = require('lfs')
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+
+local eq = helpers.eq
+local feed = helpers.feed
+local eval = helpers.eval
+local clear = helpers.clear
+local funcs = helpers.funcs
+local nvim_prog = helpers.nvim_prog
+local write_file = helpers.write_file
+
+local function nvim_prog_abs()
+ -- system(['build/bin/nvim']) does not work for whatever reason. It needs to
+ -- either be executable searched in $PATH or something starting with / or ./.
+ if nvim_prog:match('[/\\]') then
+ return funcs.fnamemodify(nvim_prog, ':p')
+ else
+ return nvim_prog
+ end
+end
+
+describe('Command-line option', function()
+ describe('-s', function()
+ local fname = 'Xtest-functional-core-main-s'
+ local fname_2 = fname .. '.2'
+ local nonexistent_fname = fname .. '.nonexistent'
+ local dollar_fname = '$' .. fname
+ before_each(function()
+ clear()
+ os.remove(fname)
+ os.remove(dollar_fname)
+ end)
+ after_each(function()
+ os.remove(fname)
+ os.remove(dollar_fname)
+ end)
+ it('treats - as stdin', function()
+ eq(nil, lfs.attributes(fname))
+ funcs.system(
+ {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless',
+ '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix',
+ '-s', '-', fname},
+ {':call setline(1, "42")', ':wqall!', ''})
+ eq(0, eval('v:shell_error'))
+ local attrs = lfs.attributes(fname)
+ eq(#('42\n'), attrs.size)
+ end)
+ it('does not expand $VAR', function()
+ eq(nil, lfs.attributes(fname))
+ eq(true, not not dollar_fname:find('%$%w+'))
+ write_file(dollar_fname, ':call setline(1, "100500")\n:wqall!\n')
+ funcs.system(
+ {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless',
+ '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix',
+ '-s', dollar_fname, fname})
+ eq(0, eval('v:shell_error'))
+ local attrs = lfs.attributes(fname)
+ eq(#('100500\n'), attrs.size)
+ end)
+ it('does not crash after reading from stdin in non-headless mode', function()
+ if helpers.pending_win32(pending) then return end
+ local screen = Screen.new(40, 8)
+ screen:attach()
+ funcs.termopen({
+ nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE',
+ '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix',
+ '-s', '-'
+ })
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:[No Name] 0,0-1 All}|
+ |
+ |
+ ]], {
+ [1] = {foreground = 4210943, special = Screen.colors.Grey0},
+ [2] = {special = Screen.colors.Grey0, bold = true, reverse = true}
+ })
+ feed('i:cq<CR>')
+ screen:expect([[
+ |
+ [Process exited 1] |
+ |
+ |
+ |
+ |
+ |
+ -- TERMINAL -- |
+ ]])
+ --[=[ Example of incorrect output:
+ screen:expect([[
+ ^nvim: /var/tmp/portage/dev-libs/libuv-1.|
+ 10.2/work/libuv-1.10.2/src/unix/core.c:5|
+ 19: uv__close: Assertion `fd > STDERR_FI|
+ LENO' failed. |
+ |
+ [Process exited 6] |
+ |
+ |
+ ]])
+ ]=]
+ end)
+ it('errors out when trying to use nonexistent file with -s', function()
+ eq(
+ 'Cannot open for reading: "'..nonexistent_fname..'": no such file or directory\n',
+ funcs.system(
+ {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless',
+ '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix',
+ '--cmd', 'language C',
+ '-s', nonexistent_fname}))
+ eq(2, eval('v:shell_error'))
+ end)
+ it('errors out when trying to use -s twice', function()
+ write_file(fname, ':call setline(1, "1")\n:wqall!\n')
+ write_file(dollar_fname, ':call setline(1, "2")\n:wqall!\n')
+ eq(
+ 'Attempt to open script file again: "-s '..dollar_fname..'"\n',
+ funcs.system(
+ {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless',
+ '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix',
+ '--cmd', 'language C',
+ '-s', fname, '-s', dollar_fname, fname_2}))
+ eq(2, eval('v:shell_error'))
+ eq(nil, lfs.attributes(fname_2))
+ end)
+ end)
+end)
diff --git a/test/functional/eval/server_spec.lua b/test/functional/eval/server_spec.lua
index 393616838e..4e4aed864b 100644
--- a/test/functional/eval/server_spec.lua
+++ b/test/functional/eval/server_spec.lua
@@ -1,31 +1,40 @@
-
local helpers = require('test.functional.helpers')(after_each)
local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval
local command = helpers.command
local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths
-local os_name = helpers.os_name
+local iswin = helpers.iswin
+local ok = helpers.ok
+local matches = helpers.matches
local function clear_serverlist()
- for _, server in pairs(funcs.serverlist()) do
- funcs.serverstop(server)
- end
+ for _, server in pairs(funcs.serverlist()) do
+ funcs.serverstop(server)
+ end
end
-describe('serverstart(), serverstop()', function()
+describe('server', function()
before_each(clear)
- it('sets $NVIM_LISTEN_ADDRESS on first invocation', function()
+ it('serverstart() sets $NVIM_LISTEN_ADDRESS on first invocation', function()
-- Unset $NVIM_LISTEN_ADDRESS
command('let $NVIM_LISTEN_ADDRESS = ""')
local s = eval('serverstart()')
assert(s ~= nil and s:len() > 0, "serverstart() returned empty")
eq(s, eval('$NVIM_LISTEN_ADDRESS'))
- command("call serverstop('"..s.."')")
+ eq(1, eval("serverstop('"..s.."')"))
eq('', eval('$NVIM_LISTEN_ADDRESS'))
end)
- it('sets v:servername _only_ on nvim startup unless all servers are stopped',
+ it('sets new v:servername if $NVIM_LISTEN_ADDRESS is invalid', function()
+ clear({env={NVIM_LISTEN_ADDRESS='.'}})
+ eq('.', eval('$NVIM_LISTEN_ADDRESS'))
+ local servers = funcs.serverlist()
+ eq(1, #servers)
+ ok(string.len(servers[1]) > 4) -- Like /tmp/nvim…/… or \\.\pipe\…
+ end)
+
+ it('sets v:servername at startup or if all servers were stopped',
function()
local initial_server = meths.get_vvar('servername')
assert(initial_server ~= nil and initial_server:len() > 0,
@@ -38,24 +47,23 @@ describe('serverstart(), serverstop()', function()
neq(initial_server, s)
-- serverstop() does _not_ modify v:servername...
- funcs.serverstop(s)
+ eq(1, funcs.serverstop(s))
eq(initial_server, meths.get_vvar('servername'))
-- ...unless we stop _all_ servers.
- funcs.serverstop(funcs.serverlist()[1])
+ eq(1, funcs.serverstop(funcs.serverlist()[1]))
eq('', meths.get_vvar('servername'))
-- v:servername will take the next available server.
- local servername = (os_name() == 'windows'
- and [[\\.\pipe\Xtest-functional-server-pipe]]
- or 'Xtest-functional-server-socket')
+ local servername = (iswin() and [[\\.\pipe\Xtest-functional-server-pipe]]
+ or 'Xtest-functional-server-socket')
funcs.serverstart(servername)
eq(servername, meths.get_vvar('servername'))
end)
- it('serverstop() ignores invalid input', function()
- command("call serverstop('')")
- command("call serverstop('bogus-socket-name')")
+ it('serverstop() returns false for invalid input', function()
+ eq(0, eval("serverstop('')"))
+ eq(0, eval("serverstop('bogus-socket-name')"))
end)
it('parses endpoints correctly', function()
@@ -96,17 +104,13 @@ describe('serverstart(), serverstop()', function()
funcs.serverstart('127.0.0.1:65536') -- invalid port
eq({}, funcs.serverlist())
end)
-end)
-
-describe('serverlist()', function()
- before_each(clear)
- it('returns the list of servers', function()
+ it('serverlist() returns the list of servers', function()
-- There should already be at least one server.
local n = eval('len(serverlist())')
- -- Add a few
- local servs = (os_name() == 'windows'
+ -- Add some servers.
+ local servs = (iswin()
and { [[\\.\pipe\Xtest-pipe0934]], [[\\.\pipe\Xtest-pipe4324]] }
or { [[Xtest-pipe0934]], [[Xtest-pipe4324]] })
for _, s in ipairs(servs) do
@@ -120,9 +124,31 @@ describe('serverlist()', function()
-- The new servers should be at the end of the list.
for i = 1, #servs do
eq(servs[i], new_servs[i + n])
- command("call serverstop('"..servs[i].."')")
+ eq(1, eval("serverstop('"..servs[i].."')"))
end
-- After serverstop() the servers should NOT be in the list.
eq(n, eval('len(serverlist())'))
end)
end)
+
+describe('startup --listen', function()
+ it('validates', function()
+ clear()
+
+ local cmd = { unpack(helpers.nvim_argv) }
+ table.insert(cmd, '--listen')
+ matches('nvim.*: Argument missing after: "%-%-listen"', funcs.system(cmd))
+
+ cmd = { unpack(helpers.nvim_argv) }
+ table.insert(cmd, '--listen2')
+ matches('nvim.*: Garbage after option argument: "%-%-listen2"', funcs.system(cmd))
+ end)
+
+ it('sets v:servername, overrides $NVIM_LISTEN_ADDRESS', function()
+ local addr = (iswin() and [[\\.\pipe\Xtest-listen-pipe]]
+ or 'Xtest-listen-pipe')
+ clear({ env={ NVIM_LISTEN_ADDRESS='Xtest-env-pipe' },
+ args={ '--listen', addr } })
+ eq(addr, meths.get_vvar('servername'))
+ end)
+end)
diff --git a/test/functional/eval/system_spec.lua b/test/functional/eval/system_spec.lua
index 201426c40b..23cea4c038 100644
--- a/test/functional/eval/system_spec.lua
+++ b/test/functional/eval/system_spec.lua
@@ -255,10 +255,8 @@ describe('system()', function()
end
end)
it('to backgrounded command does not crash', function()
- -- cmd.exe doesn't background a command with &
- if iswin() then return end
-- This is indeterminate, just exercise the codepath. May get E5677.
- feed_command('call system("echo -n echoed &")')
+ feed_command('call system(has("win32") ? "start /b /wait cmd /c echo echoed" : "echo -n echoed &")')
local v_errnum = string.match(eval("v:errmsg"), "^E%d*:")
if v_errnum then
eq("E5677:", v_errnum)
@@ -272,10 +270,8 @@ describe('system()', function()
eq("input", eval('system("cat -", "input")'))
end)
it('to backgrounded command does not crash', function()
- -- cmd.exe doesn't background a command with &
- if iswin() then return end
-- This is indeterminate, just exercise the codepath. May get E5677.
- feed_command('call system("cat - &", "input")')
+ feed_command('call system(has("win32") ? "start /b /wait more" : "cat - &", "input")')
local v_errnum = string.match(eval("v:errmsg"), "^E%d*:")
if v_errnum then
eq("E5677:", v_errnum)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index b8d912114d..655200e6f7 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -14,8 +14,10 @@ local check_cores = global_helpers.check_cores
local check_logs = global_helpers.check_logs
local neq = global_helpers.neq
local eq = global_helpers.eq
+local expect_err = global_helpers.expect_err
local ok = global_helpers.ok
local map = global_helpers.map
+local matches = global_helpers.matches
local filter = global_helpers.filter
local dedent = global_helpers.dedent
local table_flatten = global_helpers.table_flatten
@@ -304,12 +306,10 @@ local function retry(max, max_ms, fn)
end
luv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
if (max and tries >= max) or (luv.now() - start_time > timeout) then
- if type(result) == "string" then
- result = "\nretry() attempts: "..tostring(tries).."\n"..result
- end
- error(result)
+ error("\nretry() attempts: "..tostring(tries).."\n"..tostring(result))
end
tries = tries + 1
+ luv.sleep(20) -- Avoid hot loop...
end
end
@@ -425,7 +425,7 @@ end
local function set_shell_powershell()
source([[
set shell=powershell shellquote=( shellpipe=\| shellredir=> shellxquote=
- set shellcmdflag=-NoLogo\ -NoProfile\ -ExecutionPolicy\ RemoteSigned\ -Command
+ let &shellcmdflag = '-NoLogo -NoProfile -ExecutionPolicy RemoteSigned -Command Remove-Item -Force alias:sleep;'
]])
end
@@ -468,14 +468,7 @@ end
-- sleeps the test runner (_not_ the nvim instance)
local function sleep(ms)
- local function notification_cb(method, _)
- if method == "redraw" then
- error("Screen is attached; use screen:sleep() instead.")
- end
- return true
- end
-
- run(nil, notification_cb, nil, ms)
+ luv.sleep(ms)
end
local function curbuf_contents()
@@ -736,6 +729,7 @@ local module = {
exc_exec = exc_exec,
expect = expect,
expect_any = expect_any,
+ expect_err = expect_err,
expect_msg_seq = expect_msg_seq,
expect_twostreams = expect_twostreams,
feed = feed,
@@ -747,6 +741,7 @@ local module = {
insert = insert,
iswin = iswin,
map = map,
+ matches = matches,
merge_args = merge_args,
meth_pcall = meth_pcall,
meths = meths,
diff --git a/test/functional/insert/insert_spec.lua b/test/functional/insert/insert_spec.lua
new file mode 100644
index 0000000000..427954f5a6
--- /dev/null
+++ b/test/functional/insert/insert_spec.lua
@@ -0,0 +1,41 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local command = helpers.command
+local eq = helpers.eq
+local expect = helpers.expect
+local funcs = helpers.funcs
+
+describe('insert-mode', function()
+ before_each(function()
+ clear()
+ end)
+
+ it('CTRL-@', function()
+ -- Inserts last-inserted text, leaves insert-mode.
+ insert('hello')
+ feed('i<C-@>x')
+ expect('hellhello')
+
+ -- C-Space is the same as C-@.
+ -- CTRL-SPC inserts last-inserted text, leaves insert-mode.
+ feed('i<C-Space>x')
+ expect('hellhellhello')
+
+ -- CTRL-A inserts last inserted text
+ feed('i<C-A>x')
+ expect('hellhellhellhelloxo')
+ end)
+
+ it('ALT/META #8213', function()
+ -- Mapped ALT-chord behaves as mapped.
+ command('inoremap <M-l> meta-l')
+ command('inoremap <A-j> alt-j')
+ feed('i<M-l> xxx <A-j><M-h>a<A-h>')
+ expect('meta-l xxx alt-j')
+ eq({ 0, 1, 14, 0, }, funcs.getpos('.'))
+ -- Unmapped ALT-chord behaves as ESC+c.
+ command('iunmap <M-l>')
+ feed('0i<M-l>')
+ eq({ 0, 1, 2, 0, }, funcs.getpos('.'))
+ end)
+end)
diff --git a/test/functional/insert/last_inserted_spec.lua b/test/functional/insert/last_inserted_spec.lua
deleted file mode 100644
index dce23a3790..0000000000
--- a/test/functional/insert/last_inserted_spec.lua
+++ /dev/null
@@ -1,22 +0,0 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
-local expect = helpers.expect
-
-clear()
-
-describe('insert-mode', function()
- it('CTRL-@ inserts last-inserted text, leaves insert-mode', function()
- insert('hello')
- feed('i<C-@>x')
- expect('hellhello')
- end)
- -- C-Space is the same as C-@
- it('CTRL-SPC inserts last-inserted text, leaves insert-mode', function()
- feed('i<C-Space>x')
- expect('hellhellhello')
- end)
- it('CTRL-A inserts last inserted text', function()
- feed('i<C-A>x')
- expect('hellhellhellhelloxo')
- end)
-end)
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index 9e29baba2d..f452cafd22 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -5,12 +5,15 @@ local Screen = require('test.functional.ui.screen')
local meths = helpers.meths
local command = helpers.command
local clear = helpers.clear
+local exc_exec = helpers.exc_exec
local eval = helpers.eval
local eq = helpers.eq
+local funcs = helpers.funcs
local insert = helpers.insert
local neq = helpers.neq
local mkdir = helpers.mkdir
local rmdir = helpers.rmdir
+local alter_slashes = helpers.alter_slashes
describe('startup defaults', function()
describe(':filetype', function()
@@ -422,3 +425,276 @@ describe('XDG-based defaults', function()
end)
end)
end)
+
+
+describe('stdpath()', function()
+ context('returns a String', function()
+ describe('with "config"' , function ()
+ it('knows XDG_CONFIG_HOME', function()
+ clear({env={
+ XDG_CONFIG_HOME=alter_slashes('/home/docwhat/.config'),
+ }})
+ eq(alter_slashes('/home/docwhat/.config/nvim'), funcs.stdpath('config'))
+ end)
+
+ it('handles changes during runtime', function()
+ clear({env={
+ XDG_CONFIG_HOME=alter_slashes('/home/original'),
+ }})
+ eq(alter_slashes('/home/original/nvim'), funcs.stdpath('config'))
+ command("let $XDG_CONFIG_HOME='"..alter_slashes('/home/new').."'")
+ eq(alter_slashes('/home/new/nvim'), funcs.stdpath('config'))
+ end)
+
+ it("doesn't expand $VARIABLES", function()
+ clear({env={
+ XDG_CONFIG_HOME='$VARIABLES',
+ VARIABLES='this-should-not-happen',
+ }})
+ eq(alter_slashes('$VARIABLES/nvim'), funcs.stdpath('config'))
+ end)
+
+ it("doesn't expand ~/", function()
+ clear({env={
+ XDG_CONFIG_HOME=alter_slashes('~/frobnitz'),
+ }})
+ eq(alter_slashes('~/frobnitz/nvim'), funcs.stdpath('config'))
+ end)
+ end)
+
+ describe('with "data"' , function ()
+ local appended_dir
+ setup(function()
+ -- Windows appends 'nvim-data' instead of just 'nvim' to
+ -- prevent collisions due to XDG_CONFIG_HOME and XDG_DATA_HOME
+ -- being the same.
+ if helpers.iswin() then
+ appended_dir = '/nvim-data'
+ else
+ appended_dir = '/nvim'
+ end
+ end)
+
+ it('knows XDG_DATA_HOME', function()
+ clear({env={
+ XDG_DATA_HOME=alter_slashes('/home/docwhat/.local'),
+ }})
+ eq(alter_slashes('/home/docwhat/.local' .. appended_dir), funcs.stdpath('data'))
+ end)
+
+ it('handles changes during runtime', function()
+ clear({env={
+ XDG_DATA_HOME=alter_slashes('/home/original'),
+ }})
+ eq(alter_slashes('/home/original' .. appended_dir), funcs.stdpath('data'))
+ command("let $XDG_DATA_HOME='"..alter_slashes('/home/new').."'")
+ eq(alter_slashes('/home/new' .. appended_dir), funcs.stdpath('data'))
+ end)
+
+ it("doesn't expand $VARIABLES", function()
+ clear({env={
+ XDG_DATA_HOME='$VARIABLES',
+ VARIABLES='this-should-not-happen',
+ }})
+ eq(alter_slashes('$VARIABLES' .. appended_dir), funcs.stdpath('data'))
+ end)
+
+ it("doesn't expand ~/", function()
+ clear({env={
+ XDG_DATA_HOME=alter_slashes('~/frobnitz'),
+ }})
+ eq(alter_slashes('~/frobnitz' .. appended_dir), funcs.stdpath('data'))
+ end)
+ end)
+
+ describe('with "cache"' , function ()
+ it('knows XDG_CACHE_HOME', function()
+ clear({env={
+ XDG_CACHE_HOME=alter_slashes('/home/docwhat/.cache'),
+ }})
+ eq(alter_slashes('/home/docwhat/.cache/nvim'), funcs.stdpath('cache'))
+ end)
+
+ it('handles changes during runtime', function()
+ clear({env={
+ XDG_CACHE_HOME=alter_slashes('/home/original'),
+ }})
+ eq(alter_slashes('/home/original/nvim'), funcs.stdpath('cache'))
+ command("let $XDG_CACHE_HOME='"..alter_slashes('/home/new').."'")
+ eq(alter_slashes('/home/new/nvim'), funcs.stdpath('cache'))
+ end)
+
+ it("doesn't expand $VARIABLES", function()
+ clear({env={
+ XDG_CACHE_HOME='$VARIABLES',
+ VARIABLES='this-should-not-happen',
+ }})
+ eq(alter_slashes('$VARIABLES/nvim'), funcs.stdpath('cache'))
+ end)
+
+ it("doesn't expand ~/", function()
+ clear({env={
+ XDG_CACHE_HOME=alter_slashes('~/frobnitz'),
+ }})
+ eq(alter_slashes('~/frobnitz/nvim'), funcs.stdpath('cache'))
+ end)
+ end)
+ end)
+
+ context('returns a List', function()
+ -- Some OS specific variables the system would have set.
+ local function base_env()
+ if helpers.iswin() then
+ return {
+ HOME='C:\\Users\\docwhat', -- technically, is not a usual PATH
+ HOMEDRIVE='C:',
+ HOMEPATH='\\Users\\docwhat',
+ LOCALAPPDATA='C:\\Users\\docwhat\\AppData\\Local',
+ TEMP='C:\\Users\\docwhat\\AppData\\Local\\Temp',
+ TMPDIR='C:\\Users\\docwhat\\AppData\\Local\\Temp',
+ TMP='C:\\Users\\docwhat\\AppData\\Local\\Temp',
+ }
+ else
+ return {
+ HOME='/home/docwhat',
+ HOMEDRIVE='HOMEDRIVE-should-be-ignored',
+ HOMEPATH='HOMEPATH-should-be-ignored',
+ LOCALAPPDATA='LOCALAPPDATA-should-be-ignored',
+ TEMP='TEMP-should-be-ignored',
+ TMPDIR='TMPDIR-should-be-ignored',
+ TMP='TMP-should-be-ignored',
+ }
+ end
+ end
+
+ local function set_paths_via_system(var_name, paths)
+ local env = base_env()
+ env[var_name] = table.concat(paths, ':')
+ clear({env=env})
+ end
+
+ local function set_paths_at_runtime(var_name, paths)
+ clear({env=base_env()})
+ meths.set_var('env_val', table.concat(paths, ':'))
+ command(('let $%s=g:env_val'):format(var_name))
+ end
+
+ local function behaves_like_dir_list_env(msg, stdpath_arg, env_var_name, paths, expected_paths)
+ describe(msg, function()
+ it('set via system', function()
+ set_paths_via_system(env_var_name, paths)
+ eq(expected_paths, funcs.stdpath(stdpath_arg))
+ end)
+
+ it('set at runtime', function()
+ set_paths_at_runtime(env_var_name, paths)
+ eq(expected_paths, funcs.stdpath(stdpath_arg))
+ end)
+ end)
+ end
+
+ describe('with "config_dirs"' , function ()
+ behaves_like_dir_list_env(
+ 'handles XDG_CONFIG_DIRS with one path',
+ 'config_dirs', 'XDG_CONFIG_DIRS',
+ {
+ alter_slashes('/home/docwhat/.config')
+ },
+ {
+ alter_slashes('/home/docwhat/.config/nvim')
+ })
+
+ behaves_like_dir_list_env(
+ 'handles XDG_CONFIG_DIRS with two paths',
+ 'config_dirs', 'XDG_CONFIG_DIRS',
+ {
+ alter_slashes('/home/docwhat/.config'),
+ alter_slashes('/etc/config')
+ },
+ {
+ alter_slashes('/home/docwhat/.config/nvim'),
+ alter_slashes('/etc/config/nvim')
+ })
+
+ behaves_like_dir_list_env(
+ "doesn't expand $VAR and $IBLES",
+ 'config_dirs', 'XDG_CONFIG_DIRS',
+ { '$HOME', '$TMP' },
+ {
+ alter_slashes('$HOME/nvim'),
+ alter_slashes('$TMP/nvim')
+ })
+
+
+ behaves_like_dir_list_env(
+ "doesn't expand ~/",
+ 'config_dirs', 'XDG_CONFIG_DIRS',
+ {
+ alter_slashes('~/.oldconfig'),
+ alter_slashes('~/.olderconfig')
+ },
+ {
+ alter_slashes('~/.oldconfig/nvim'),
+ alter_slashes('~/.olderconfig/nvim')
+ })
+ end)
+
+ describe('with "data_dirs"' , function ()
+ behaves_like_dir_list_env(
+ 'knows XDG_DATA_DIRS with one path',
+ 'data_dirs', 'XDG_DATA_DIRS',
+ {
+ alter_slashes('/home/docwhat/.data')
+ },
+ {
+ alter_slashes('/home/docwhat/.data/nvim')
+ })
+
+ behaves_like_dir_list_env(
+ 'knows XDG_DATA_DIRS with two paths',
+ 'data_dirs', 'XDG_DATA_DIRS',
+ {
+ alter_slashes('/home/docwhat/.data'),
+ alter_slashes('/etc/local')
+ },
+ {
+ alter_slashes('/home/docwhat/.data/nvim'),
+ alter_slashes('/etc/local/nvim'),
+ })
+
+ behaves_like_dir_list_env(
+ "doesn't expand $VAR and $IBLES",
+ 'data_dirs', 'XDG_DATA_DIRS',
+ { '$HOME', '$TMP' },
+ {
+ alter_slashes('$HOME/nvim'),
+ alter_slashes('$TMP/nvim')
+ })
+
+ behaves_like_dir_list_env(
+ "doesn't expand ~/",
+ 'data_dirs', 'XDG_DATA_DIRS',
+ {
+ alter_slashes('~/.oldconfig'),
+ alter_slashes('~/.olderconfig')
+ },
+ {
+ alter_slashes('~/.oldconfig/nvim'),
+ alter_slashes('~/.olderconfig/nvim'),
+ })
+ end)
+ end)
+
+ describe('errors', function()
+ it('on unknown strings', function()
+ eq('Vim(call):E6100: "capybara" is not a valid stdpath', exc_exec('call stdpath("capybara")'))
+ eq('Vim(call):E6100: "" is not a valid stdpath', exc_exec('call stdpath("")'))
+ eq('Vim(call):E6100: "23" is not a valid stdpath', exc_exec('call stdpath(23)'))
+ end)
+
+ it('on non-strings', function()
+ eq('Vim(call):E731: using Dictionary as a String', exc_exec('call stdpath({"eris": 23})'))
+ eq('Vim(call):E730: using List as a String', exc_exec('call stdpath([23])'))
+ end)
+ end)
+end)
diff --git a/test/functional/provider/nodejs_spec.lua b/test/functional/provider/nodejs_spec.lua
index 0a12b1a154..d9af020bfe 100644
--- a/test/functional/provider/nodejs_spec.lua
+++ b/test/functional/provider/nodejs_spec.lua
@@ -35,7 +35,7 @@ describe('nodejs host', function()
nvim.command('call jobstop(g:job_id)');
]])
command('let g:job_id = jobstart(["node", "'..fname..'"])')
- retry(nil, 1000, function() eq('hello', eval('g:job_out')) end)
+ retry(nil, 2000, function() eq('hello', eval('g:job_out')) end)
end)
it('plugin works', function()
local fname = 'Xtest-nodejs-hello-plugin.js'
@@ -56,6 +56,6 @@ describe('nodejs host', function()
nvim.command('call jobstop(g:job_id)');
]])
command('let g:job_id = jobstart(["node", "'..fname..'"])')
- retry(nil, 1000, function() eq('hello-plugin', eval('g:job_out')) end)
+ retry(nil, 2000, function() eq('hello-plugin', eval('g:job_out')) end)
end)
end)
diff --git a/test/functional/shada/merging_spec.lua b/test/functional/shada/merging_spec.lua
index 7a15c8908b..a628baff53 100644
--- a/test/functional/shada/merging_spec.lua
+++ b/test/functional/shada/merging_spec.lua
@@ -525,6 +525,85 @@ describe('ShaDa marks support code', function()
eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
end)
+ it('can merge with file with mark 9 as the only numeric mark', function()
+ wshada('\007\001\014\130\161f\196\006' .. mock_file_path .. '-\161n9')
+ eq(0, exc_exec(sdrcmd()))
+ nvim_command('normal! `9oabc')
+ eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq(0, exc_exec('wshada ' .. shada_fname))
+ local found = {}
+ for _, v in ipairs(read_shada_file(shada_fname)) do
+ if v.type == 7 and v.value.f == mock_file_path .. '-' then
+ local name = ('%c'):format(v.value.n)
+ found[name] = (found[name] or 0) + 1
+ end
+ end
+ eq({['0']=1, ['1']=1}, found)
+ end)
+
+ it('removes duplicates while merging', function()
+ wshada('\007\001\014\130\161f\196\006' .. mock_file_path .. '-\161n9'
+ .. '\007\001\014\130\161f\196\006' .. mock_file_path .. '-\161n9')
+ eq(0, exc_exec(sdrcmd()))
+ eq(0, exc_exec('wshada ' .. shada_fname))
+ local found = 0
+ for _, v in ipairs(read_shada_file(shada_fname)) do
+ if v.type == 7 and v.value.f == mock_file_path .. '-' then
+ print(require('test.helpers').format_luav(v))
+ found = found + 1
+ end
+ end
+ eq(1, found)
+ end)
+
+ it('does not leak when no append is performed due to too many marks',
+ function()
+ wshada('\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'a\161n0'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'b\161n1'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161n2'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'd\161n3'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'e\161n4'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'f\161n5'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'g\161n6'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'h\161n7'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'i\161n8'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'j\161n9'
+ .. '\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'k\161n9')
+ eq(0, exc_exec(sdrcmd()))
+ eq(0, exc_exec('wshada ' .. shada_fname))
+ local found = {}
+ for _, v in ipairs(read_shada_file(shada_fname)) do
+ if v.type == 7 and v.value.f:sub(1, #mock_file_path) == mock_file_path then
+ found[#found + 1] = v.value.f:sub(#v.value.f)
+ end
+ end
+ eq({'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}, found)
+ end)
+
+ it('does not leak when last mark in file removes some of the earlier ones',
+ function()
+ wshada('\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'a\161n0'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'b\161n1'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161n2'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'd\161n3'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'e\161n4'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'f\161n5'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'g\161n6'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'h\161n7'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'i\161n8'
+ .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'j\161n9'
+ .. '\007\003\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'k\161n9')
+ eq(0, exc_exec(sdrcmd()))
+ eq(0, exc_exec('wshada ' .. shada_fname))
+ local found = {}
+ for _, v in ipairs(read_shada_file(shada_fname)) do
+ if v.type == 7 and v.value.f:sub(1, #mock_file_path) == mock_file_path then
+ found[#found + 1] = v.value.f:sub(#v.value.f)
+ end
+ end
+ eq({'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k'}, found)
+ end)
+
it('uses last A mark with gt timestamp from file when reading with !',
function()
wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
@@ -563,13 +642,14 @@ describe('ShaDa marks support code', function()
nvim_command('normal! `A')
eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
eq(0, exc_exec('wshada ' .. shada_fname))
- local found = 0
+ local found = {}
for _, v in ipairs(read_shada_file(shada_fname)) do
- if v.type == 7 and v.value.f == '' .. mock_file_path .. '-' then
- found = found + 1
+ if v.type == 7 and v.value.f == mock_file_path .. '-' then
+ local name = ('%c'):format(v.value.n)
+ found[name] = (found[name] or 0) + 1
end
end
- eq(1, found)
+ eq({['0']=1, A=1}, found)
end)
it('uses last A mark with eq timestamp from instance when writing',
@@ -580,30 +660,33 @@ describe('ShaDa marks support code', function()
nvim_command('normal! `A')
eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
eq(0, exc_exec('wshada ' .. shada_fname))
- local found = 0
+ local found = {}
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 7 and v.value.f == mock_file_path .. '-' then
- found = found + 1
+ local name = ('%c'):format(v.value.n)
+ found[name] = (found[name] or 0) + 1
end
end
- eq(1, found)
+ eq({['0']=1, A=1}, found)
end)
- it('uses last A mark with gt timestamp from file when writing',
- function()
+ it('uses last A mark with gt timestamp from file when writing', function()
wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
eq(0, exc_exec(sdrcmd()))
wshada('\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
nvim_command('normal! `A')
eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
eq(0, exc_exec('wshada ' .. shada_fname))
- local found = 0
+ local found = {}
for _, v in ipairs(read_shada_file(shada_fname)) do
- if v.type == 7 and v.value.f == '' .. mock_file_path .. '?' then
- found = found + 1
+ if v.type == 7 then
+ local name = ('%c'):format(v.value.n)
+ local t = found[name] or {}
+ t[v.value.f] = (t[v.value.f] or 0) + 1
+ found[name] = t
end
end
- eq(1, found)
+ eq({['0']={[mock_file_path .. '-']=1}, A={[mock_file_path .. '?']=1}}, found)
end)
it('uses last a mark with gt timestamp from instance when reading',
diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua
index ca44026852..720855860a 100644
--- a/test/functional/shada/shada_spec.lua
+++ b/test/functional/shada/shada_spec.lua
@@ -181,13 +181,13 @@ describe('ShaDa support code', function()
nvim_command('set shada+=%')
nvim_command('wshada! ' .. shada_fname)
local readme_fname = funcs.resolve(paths.test_source_path) .. '/README.md'
- eq({[7]=1, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname))
+ eq({[7]=2, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname))
nvim_command('set shada+=r~')
nvim_command('wshada! ' .. shada_fname)
eq({}, find_file(readme_fname))
nvim_command('set shada-=r~')
nvim_command('wshada! ' .. shada_fname)
- eq({[7]=1, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname))
+ eq({[7]=2, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname))
nvim_command('set shada+=r' .. funcs.escape(
funcs.escape(paths.test_source_path, '$~'), ' "\\,'))
nvim_command('wshada! ' .. shada_fname)
@@ -206,7 +206,7 @@ describe('ShaDa support code', function()
nvim_command('undo')
nvim_command('set shada+=%')
nvim_command('wshada! ' .. shada_fname)
- eq({[7]=1, [8]=2, [9]=1, [10]=4, [11]=2}, find_file(fname))
+ eq({[7]=2, [8]=2, [9]=1, [10]=4, [11]=2}, find_file(fname))
nvim_command('set shada+=r' .. pwd .. '/АБВ')
nvim_command('wshada! ' .. shada_fname)
eq({}, find_file(fname))
diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua
index a21d9f0a56..263a5ce79d 100644
--- a/test/functional/terminal/mouse_spec.lua
+++ b/test/functional/terminal/mouse_spec.lua
@@ -101,7 +101,7 @@ describe('terminal mouse', function()
line28 │line28 |
line29 │line29 |
line30 │line30 |
- rows: 5, cols: 24 │rows: 5, cols: 24 |
+ rows: 5, cols: 25 │rows: 5, cols: 25 |
{2:^ } │{2: } |
========== ========== |
:vsp |
@@ -111,7 +111,7 @@ describe('terminal mouse', function()
{7: 1 }^ │line28 |
{4:~ }│line29 |
{4:~ }│line30 |
- {4:~ }│rows: 5, cols: 24 |
+ {4:~ }│rows: 5, cols: 25 |
{4:~ }│{2: } |
========== ========== |
:enew | set number |
@@ -121,7 +121,7 @@ describe('terminal mouse', function()
{7: 27 }line │line28 |
{7: 28 }line │line29 |
{7: 29 }line │line30 |
- {7: 30 }line │rows: 5, cols: 24 |
+ {7: 30 }line │rows: 5, cols: 25 |
{7: 31 }^ │{2: } |
========== ========== |
|
@@ -131,7 +131,7 @@ describe('terminal mouse', function()
{7: 27 }line │line28 |
{7: 28 }line │line29 |
{7: 29 }line │line30 |
- {7: 30 }line │rows: 5, cols: 24 |
+ {7: 30 }line │rows: 5, cols: 25 |
{7: 31 } │{1: } |
========== ========== |
{3:-- TERMINAL --} |
@@ -142,7 +142,7 @@ describe('terminal mouse', function()
screen:expect([[
{7: 27 }line │line29 |
{7: 28 }line │line30 |
- {7: 29 }line │rows: 5, cols: 24 |
+ {7: 29 }line │rows: 5, cols: 25 |
{7: 30 }line │mouse enabled |
{7: 31 } │{1: } |
========== ========== |
@@ -155,7 +155,7 @@ describe('terminal mouse', function()
screen:expect([[
{7: 21 }line │line29 |
{7: 22 }line │line30 |
- {7: 23 }line │rows: 5, cols: 24 |
+ {7: 23 }line │rows: 5, cols: 25 |
{7: 24 }line │mouse enabled |
{7: 25 }line │{1: } |
========== ========== |
@@ -165,7 +165,7 @@ describe('terminal mouse', function()
screen:expect([[
{7: 26 }line │line29 |
{7: 27 }line │line30 |
- {7: 28 }line │rows: 5, cols: 24 |
+ {7: 28 }line │rows: 5, cols: 25 |
{7: 29 }line │mouse enabled |
{7: 30 }line │{1: } |
========== ========== |
@@ -178,7 +178,7 @@ describe('terminal mouse', function()
screen:expect([[
{7: 27 }line │line29 |
{7: 28 }l^ine │line30 |
- {7: 29 }line │rows: 5, cols: 24 |
+ {7: 29 }line │rows: 5, cols: 25 |
{7: 30 }line │mouse enabled |
{7: 31 } │{2: } |
========== ========== |
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 171745eb57..0ae5802a01 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -115,16 +115,12 @@ describe('tui', function()
]])
end)
- it('does not mangle unmapped ALT-key chord', function()
- -- Vim represents ALT/META by setting the "high bit" of the modified key;
- -- we do _not_. #3982
- --
- -- Example: for input ALT+j:
- -- * Vim (Nvim prior to #3982) sets high-bit, inserts "ê".
- -- * Nvim (after #3982) inserts "j".
- feed_data('i\027j')
+ it('interprets ESC+key as ALT chord', function()
+ -- Vim represents ALT/META by setting the "high bit" of the modified key:
+ -- ALT+j inserts "ê". Nvim does not (#3982).
+ feed_data('i\022\027j')
screen:expect([[
- j{1: } |
+ <M-j>{1: } |
{4:~ }|
{4:~ }|
{4:~ }|
@@ -391,15 +387,7 @@ describe('tui FocusGained/FocusLost', function()
-- Exit cmdline-mode. Redraws from timers/events are blocked during
-- cmdline-mode, so the buffer won't be updated until we exit cmdline-mode.
feed_data('\n')
- screen:expect([[
- {1: } |
- lost |
- gained |
- {4:~ }|
- {5:[No Name] [+] }|
- : |
- {3:-- TERMINAL --} |
- ]])
+ screen:expect('lost'..(' '):rep(46)..'\ngained', nil, nil, nil, true)
end)
end)
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 364e0eea7f..ab3b1c3cac 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -778,6 +778,9 @@ describe("'winhighlight' highlight", function()
[22] = {bold = true, foreground = Screen.colors.SeaGreen4},
[23] = {background = Screen.colors.LightMagenta},
[24] = {background = Screen.colors.WebGray},
+ [25] = {bold = true, foreground = Screen.colors.Green1},
+ [26] = {background = Screen.colors.Red},
+ [27] = {background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Green1},
})
command("hi Background1 guibg=DarkBlue")
command("hi Background2 guibg=DarkGreen")
@@ -1047,6 +1050,39 @@ describe("'winhighlight' highlight", function()
]])
end)
+ it("background doesn't override syntax background", function()
+ command('syntax on')
+ command('syntax keyword Foobar foobar')
+ command('syntax keyword Article the')
+ command('hi Foobar guibg=#FF0000')
+ command('hi Article guifg=#00FF00 gui=bold')
+ insert('the foobar was foobar')
+ screen:expect([[
+ {25:the} {26:foobar} was {26:fooba}|
+ {26:^r} |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+
+ -- winhl=Normal:Group with background doesn't override syntax background,
+ -- but does combine with syntax foreground.
+ command('set winhl=Normal:Background1')
+ screen:expect([[
+ {27:the}{1: }{26:foobar}{1: was }{26:fooba}|
+ {26:^r}{1: }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ {2:~ }|
+ |
+ ]])
+ end)
+
it('can override NonText, Conceal and EndOfBuffer', function()
curbufmeths.set_lines(0,-1,true, {"raa\000"})
command('call matchaddpos("Conceal", [[1,2]], 0, -1, {"conceal": "#"})')
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index 27e4066d9f..ee1a3240a2 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -16,6 +16,8 @@ local retry = helpers.retry
local source = helpers.source
local wait = helpers.wait
local nvim = helpers.nvim
+local iswin = helpers.iswin
+local sleep = helpers.sleep
local default_text = [[
Inc substitution on
@@ -1354,6 +1356,23 @@ describe("inccommand=nosplit", function()
:echo 'foo'^ |
]])
end)
+
+ it("does not execute trailing bar-separated commands #7494", function()
+ feed(':%s/two/three/g|q!')
+ screen:expect([[
+ Inc substitution on |
+ {12:three} lines |
+ Inc substitution on |
+ {12:three} lines |
+ |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ :%s/two/three/g|q!^ |
+ ]])
+ eq(eval('v:null'), eval('v:exiting'))
+ end)
end)
describe(":substitute, 'inccommand' with a failing expression", function()
@@ -1833,7 +1852,7 @@ describe(":substitute", function()
clear()
end)
- it(", inccommand=split, highlights multiline substitutions", function()
+ it("inccommand=split, highlights multiline substitutions", function()
common_setup(screen, "split", multiline_text)
feed("gg")
@@ -1895,7 +1914,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=nosplit, highlights multiline substitutions", function()
+ it("inccommand=nosplit, highlights multiline substitutions", function()
common_setup(screen, "nosplit", multiline_text)
feed("gg")
@@ -1938,7 +1957,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=split, highlights multiple matches on a line", function()
+ it("inccommand=split, highlights multiple matches on a line", function()
common_setup(screen, "split", multimatch_text)
command("set gdefault")
feed("gg")
@@ -1963,7 +1982,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=nosplit, highlights multiple matches on a line", function()
+ it("inccommand=nosplit, highlights multiple matches on a line", function()
common_setup(screen, "nosplit", multimatch_text)
command("set gdefault")
feed("gg")
@@ -1988,7 +2007,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=split, with \\zs", function()
+ it("inccommand=split, with \\zs", function()
common_setup(screen, "split", multiline_text)
feed("gg")
@@ -2012,7 +2031,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=nosplit, with \\zs", function()
+ it("inccommand=nosplit, with \\zs", function()
common_setup(screen, "nosplit", multiline_text)
feed("gg")
@@ -2036,7 +2055,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=split, substitutions of different length",
+ it("inccommand=split, substitutions of different length",
function()
common_setup(screen, "split", "T T123 T2T TTT T090804\nx")
@@ -2060,7 +2079,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=nosplit, substitutions of different length", function()
+ it("inccommand=nosplit, substitutions of different length", function()
common_setup(screen, "nosplit", "T T123 T2T TTT T090804\nx")
feed(":%s/T\\([0-9]\\+\\)/\\1\\1/g")
@@ -2083,7 +2102,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=split, contraction of lines", function()
+ it("inccommand=split, contraction of lines", function()
local text = [[
T T123 T T123 T2T TT T23423424
x
@@ -2132,7 +2151,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=nosplit, contraction of lines", function()
+ it("inccommand=nosplit, contraction of lines", function()
local text = [[
T T123 T T123 T2T TT T23423424
x
@@ -2162,7 +2181,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=split, multibyte text", function()
+ it("inccommand=split, multibyte text", function()
common_setup(screen, "split", multibyte_text)
feed(":%s/£.*ѫ/X¥¥")
screen:expect([[
@@ -2203,7 +2222,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=nosplit, multibyte text", function()
+ it("inccommand=nosplit, multibyte text", function()
common_setup(screen, "nosplit", multibyte_text)
feed(":%s/£.*ѫ/X¥¥")
screen:expect([[
@@ -2244,7 +2263,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=split, small cmdwinheight", function()
+ it("inccommand=split, small cmdwinheight", function()
common_setup(screen, "split", long_multiline_text)
command("set cmdwinheight=2")
@@ -2306,7 +2325,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=split, large cmdwinheight", function()
+ it("inccommand=split, large cmdwinheight", function()
common_setup(screen, "split", long_multiline_text)
command("set cmdwinheight=11")
@@ -2368,7 +2387,7 @@ describe(":substitute", function()
]])
end)
- it(", inccommand=split, lookaround", function()
+ it("inccommand=split, lookaround", function()
common_setup(screen, "split", "something\neverything\nsomeone")
feed([[:%s/\(some\)\@<lt>=thing/one/]])
screen:expect([[
@@ -2452,4 +2471,57 @@ describe(":substitute", function()
:%s/some\(thing\)\@!/every/^ |
]])
end)
+
+ it('with inccommand during :terminal activity', function()
+ command("set cmdwinheight=3")
+ if iswin() then
+ feed([[:terminal for /L \%I in (1,1,5000) do @(echo xxx & echo xxx & echo xxx)<cr>]])
+ else
+ feed([[:terminal for i in $(seq 1 5000); do printf 'xxx\nxxx\nxxx\n'; done<cr>]])
+ end
+ command('file term')
+ command('new')
+ common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz')
+ command('wincmd =')
+
+ -- Allow some terminal output.
+ screen:expect([[
+ bar baz fox |
+ bar foo ba^z |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ xxx |
+ xxx |
+ xxx |
+ xxx |
+ xxx |
+ xxx |
+ {10:term }|
+ |
+ ]])
+
+ feed('gg')
+ feed(':%s/foo/ZZZ')
+ sleep(50) -- Allow some terminal activity.
+ screen:expect([[
+ {12:ZZZ} bar baz |
+ bar baz fox |
+ bar {12:ZZZ} baz |
+ {15:~ }|
+ {15:~ }|
+ {15:~ }|
+ {11:[No Name] [+] }|
+ xxx |
+ xxx |
+ {10:term }|
+ |1| {12:ZZZ} bar baz |
+ |3| bar {12:ZZZ} baz |
+ {15:~ }|
+ {10:[Preview] }|
+ :%s/foo/ZZZ^ |
+ ]])
+ end)
end)
diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua
index 9bfc87d835..3dd9a2506e 100644
--- a/test/functional/ui/input_spec.lua
+++ b/test/functional/ui/input_spec.lua
@@ -128,6 +128,10 @@ describe('input utf sequences that contain CSI/K_SPECIAL', function()
end)
describe('input non-printable chars', function()
+ after_each(function()
+ os.remove('Xtest-overwrite')
+ end)
+
it("doesn't crash when echoing them back", function()
write_file("Xtest-overwrite", [[foobar]])
clear()
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
index 563d04416a..7fafd6b352 100644
--- a/test/functional/ui/screen_basic_spec.lua
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -76,11 +76,26 @@ describe('Screen', function()
local function check()
eq(true, screen.suspended)
end
+
+ command('let g:ev = []')
+ command('autocmd VimResume * :call add(g:ev, "r")')
+ command('autocmd VimSuspend * :call add(g:ev, "s")')
+
+ eq(false, screen.suspended)
command('suspend')
+ eq({ 's', 'r' }, eval('g:ev'))
+
screen:expect(check)
screen.suspended = false
+
feed('<c-z>')
+ eq({ 's', 'r', 's', 'r' }, eval('g:ev'))
+
screen:expect(check)
+ screen.suspended = false
+
+ command('suspend')
+ eq({ 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev'))
end)
end)
@@ -631,21 +646,3 @@ describe('Screen', function()
end)
end)
end)
-
-describe('nvim_ui_attach()', function()
- before_each(function()
- clear()
- end)
- it('handles very large width/height #2180', function()
- local screen = Screen.new(999, 999)
- screen:attach()
- eq(999, eval('&lines'))
- eq(999, eval('&columns'))
- end)
- it('invalid option returns error', function()
- local screen = Screen.new()
- local status, rv = pcall(function() screen:attach({foo={'foo'}}) end)
- eq(false, status)
- eq('No such ui option', rv:match("No such .*"))
- end)
-end)
diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua
index 9f273e8dc9..168080a092 100644
--- a/test/functional/ui/searchhl_spec.lua
+++ b/test/functional/ui/searchhl_spec.lua
@@ -4,6 +4,8 @@ local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local feed_command = helpers.feed_command
local eq = helpers.eq
local eval = helpers.eval
+local iswin = helpers.iswin
+local sleep = helpers.sleep
describe('search highlighting', function()
local screen
@@ -91,6 +93,38 @@ describe('search highlighting', function()
]])
end)
+ it('is preserved during :terminal activity', function()
+ if iswin() then
+ feed([[:terminal for /L \%I in (1,1,5000) do @(echo xxx & echo xxx & echo xxx)<cr>]])
+ else
+ feed([[:terminal for i in $(seq 1 5000); do printf 'xxx\nxxx\nxxx\n'; done<cr>]])
+ end
+
+ feed(':file term<CR>')
+ feed(':vnew<CR>')
+ insert([[
+ foo bar baz
+ bar baz foo
+ bar foo baz
+ ]])
+ feed('/foo')
+ sleep(50) -- Allow some terminal activity.
+ screen:expect([[
+ {3:foo} bar baz {3:│}xxx |
+ bar baz {2:foo} {3:│}xxx |
+ bar {2:foo} baz {3:│}xxx |
+ {3:│}xxx |
+ {1:~ }{3:│}xxx |
+ {5:[No Name] [+] }{3:term }|
+ /foo^ |
+ ]], { [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {background = Screen.colors.Yellow},
+ [3] = {reverse = true},
+ [4] = {foreground = Screen.colors.Red},
+ [5] = {bold = true, reverse = true},
+ })
+ end)
+
it('works with incsearch', function()
feed_command('set hlsearch')
feed_command('set incsearch')
diff --git a/test/helpers.lua b/test/helpers.lua
index 91ceed4df1..efc0e911f1 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -1,6 +1,38 @@
local assert = require('luassert')
local lfs = require('lfs')
+local quote_me = '[^.%w%+%-%@%_%/]' -- complement (needn't quote)
+local function shell_quote(str)
+ if string.find(str, quote_me) or str == '' then
+ return '"' .. str:gsub('[$%%"\\]', '\\%0') .. '"'
+ else
+ return str
+ end
+end
+
+local function argss_to_cmd(...)
+ local cmd = ''
+ for i = 1, select('#', ...) do
+ local arg = select(i, ...)
+ if type(arg) == 'string' then
+ cmd = cmd .. ' ' ..shell_quote(arg)
+ else
+ for _, subarg in ipairs(arg) do
+ cmd = cmd .. ' ' .. shell_quote(subarg)
+ end
+ end
+ end
+ return cmd
+end
+
+local function popen_r(...)
+ return io.popen(argss_to_cmd(...), 'r')
+end
+
+local function popen_w(...)
+ return io.popen(argss_to_cmd(...), 'w')
+end
+
local check_logs_useless_lines = {
['Warning: noted but unhandled ioctl']=1,
['could cause spurious value errors to appear']=2,
@@ -16,6 +48,19 @@ end
local function ok(res)
return assert.is_true(res)
end
+local function matches(pat, actual)
+ if nil ~= string.match(actual, pat) then
+ return true
+ end
+ error(string.format('Pattern does not match.\nPattern:\n%s\nActual:\n%s', pat, actual))
+end
+-- Expect an error matching pattern `pat`.
+local function expect_err(pat, ...)
+ local fn = select(1, ...)
+ local fn_args = {...}
+ table.remove(fn_args, 1)
+ assert.error_matches(function() return fn(unpack(fn_args)) end, pat)
+end
-- initial_path: directory to recurse into
-- re: include pattern (string)
@@ -108,7 +153,7 @@ local uname = (function()
return platform
end
- local status, f = pcall(io.popen, "uname -s")
+ local status, f = pcall(popen_r, 'uname', '-s')
if status then
platform = f:read("*l")
f:close()
@@ -240,7 +285,7 @@ local function check_cores(app, force)
end
local function which(exe)
- local pipe = io.popen('which ' .. exe, 'r')
+ local pipe = popen_r('which', exe)
local ret = pipe:read('*a')
pipe:close()
if ret == '' then
@@ -250,6 +295,19 @@ local function which(exe)
end
end
+local function repeated_read_cmd(...)
+ for _ = 1, 10 do
+ local stream = popen_r(...)
+ local ret = stream:read('*a')
+ stream:close()
+ if ret then
+ return ret
+ end
+ end
+ print('ERROR: Failed to execute ' .. argss_to_cmd(...) .. ': nil return after 10 attempts')
+ return nil
+end
+
local function shallowcopy(orig)
if type(orig) ~= 'table' then
return orig
@@ -469,6 +527,8 @@ format_luav = function(v, indent, opts)
end
elseif type(v) == 'nil' then
ret = 'nil'
+ elseif type(v) == 'boolean' then
+ ret = (v and 'true' or 'false')
else
print(type(v))
-- Not implemented yet
@@ -554,6 +614,7 @@ end
return {
REMOVE_THIS = REMOVE_THIS,
+ argss_to_cmd = argss_to_cmd,
check_cores = check_cores,
check_logs = check_logs,
concat_tables = concat_tables,
@@ -561,6 +622,7 @@ return {
deepcopy = deepcopy,
dictdiff = dictdiff,
eq = eq,
+ expect_err = expect_err,
filter = filter,
fixtbl = fixtbl,
fixtbl_rec = fixtbl_rec,
@@ -570,9 +632,13 @@ return {
hasenv = hasenv,
intchar2lua = intchar2lua,
map = map,
+ matches = matches,
mergedicts_copy = mergedicts_copy,
neq = neq,
ok = ok,
+ popen_r = popen_r,
+ popen_w = popen_w,
+ repeated_read_cmd = repeated_read_cmd,
shallowcopy = shallowcopy,
table_flatten = table_flatten,
tmpname = tmpname,
diff --git a/test/includes/pre/sys/stat.h b/test/includes/pre/sys/stat.h
index c6cac80913..1cb811d579 100644
--- a/test/includes/pre/sys/stat.h
+++ b/test/includes/pre/sys/stat.h
@@ -1,4 +1,6 @@
-#define _GNU_SOURCE
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
#include <sys/stat.h>
static const mode_t kS_IFMT = S_IFMT;
diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua
index 5cc2be50b1..f8143a0125 100644
--- a/test/unit/helpers.lua
+++ b/test/unit/helpers.lua
@@ -779,7 +779,7 @@ local function gen_itp(it)
end
local function cppimport(path)
- return cimport(Paths.test_include_path .. '/' .. path)
+ return cimport(Paths.test_source_path .. '/test/includes/pre/' .. path)
end
cimport('./src/nvim/types.h', './src/nvim/main.h', './src/nvim/os/time.h')
diff --git a/test/unit/os/fileio_spec.lua b/test/unit/os/fileio_spec.lua
index d9c98e8afa..4d58a8934e 100644
--- a/test/unit/os/fileio_spec.lua
+++ b/test/unit/os/fileio_spec.lua
@@ -113,7 +113,7 @@ end
describe('file_open_fd', function()
itp('can use file descriptor returned by os_open for reading', function()
local fd = m.os_open(file1, m.kO_RDONLY, 0)
- local err, fp = file_open_fd(fd, false)
+ local err, fp = file_open_fd(fd, m.kFileReadOnly)
eq(0, err)
eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
eq(0, m.file_close(fp, false))
@@ -121,7 +121,7 @@ describe('file_open_fd', function()
itp('can use file descriptor returned by os_open for writing', function()
eq(nil, lfs.attributes(filec))
local fd = m.os_open(filec, m.kO_WRONLY + m.kO_CREAT, 384)
- local err, fp = file_open_fd(fd, true)
+ local err, fp = file_open_fd(fd, m.kFileWriteOnly)
eq(0, err)
eq(4, file_write(fp, 'test'))
eq(0, m.file_close(fp, false))
@@ -133,7 +133,7 @@ end)
describe('file_open_fd_new', function()
itp('can use file descriptor returned by os_open for reading', function()
local fd = m.os_open(file1, m.kO_RDONLY, 0)
- local err, fp = file_open_fd_new(fd, false)
+ local err, fp = file_open_fd_new(fd, m.kFileReadOnly)
eq(0, err)
eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
eq(0, m.file_free(fp, false))
@@ -141,7 +141,7 @@ describe('file_open_fd_new', function()
itp('can use file descriptor returned by os_open for writing', function()
eq(nil, lfs.attributes(filec))
local fd = m.os_open(filec, m.kO_WRONLY + m.kO_CREAT, 384)
- local err, fp = file_open_fd_new(fd, true)
+ local err, fp = file_open_fd_new(fd, m.kFileWriteOnly)
eq(0, err)
eq(4, file_write(fp, 'test'))
eq(0, m.file_free(fp, false))
diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua
index 78455ee324..ae6dfe6423 100644
--- a/test/unit/os/fs_spec.lua
+++ b/test/unit/os/fs_spec.lua
@@ -390,7 +390,7 @@ describe('fs.c', function()
buf = ffi.new('char[?]', size + 1, ('\0'):rep(size))
end
local eof = ffi.new('bool[?]', 1, {true})
- local ret2 = fs.os_read(fd, eof, buf, size)
+ local ret2 = fs.os_read(fd, eof, buf, size, false)
local ret1 = eof[0]
local ret3 = ''
if buf ~= nil then
@@ -408,7 +408,7 @@ describe('fs.c', function()
end
local iov = ffi.new('struct iovec[?]', #sizes, bufs)
local eof = ffi.new('bool[?]', 1, {true})
- local ret2 = fs.os_readv(fd, eof, iov, #sizes)
+ local ret2 = fs.os_readv(fd, eof, iov, #sizes, false)
local ret1 = eof[0]
local ret3 = {}
for i = 1,#sizes do
@@ -418,7 +418,7 @@ describe('fs.c', function()
return ret1, ret2, ret3
end
local function os_write(fd, data)
- return fs.os_write(fd, data, data and #data or 0)
+ return fs.os_write(fd, data, data and #data or 0, false)
end
describe('os_path_exists', function()
@@ -491,6 +491,22 @@ describe('fs.c', function()
end)
end)
+ describe('os_dup', function()
+ itp('returns new file descriptor', function()
+ local dup0 = fs.os_dup(0)
+ local dup1 = fs.os_dup(1)
+ local dup2 = fs.os_dup(2)
+ local tbl = {[0]=true, [1]=true, [2]=true,
+ [tonumber(dup0)]=true, [tonumber(dup1)]=true,
+ [tonumber(dup2)]=true}
+ local i = 0
+ for _, _ in pairs(tbl) do
+ i = i + 1
+ end
+ eq(i, 6) -- All fds must be unique
+ end)
+ end)
+
describe('os_open', function()
local new_file = 'test_new_file'
local existing_file = 'unit-test-directory/test_existing.file'
diff --git a/test/unit/preprocess.lua b/test/unit/preprocess.lua
index 363358d134..1073855a7d 100644
--- a/test/unit/preprocess.lua
+++ b/test/unit/preprocess.lua
@@ -2,6 +2,10 @@
-- windows, will probably need quite a bit of adjustment to run there.
local ffi = require("ffi")
+local global_helpers = require('test.helpers')
+
+local argss_to_cmd = global_helpers.argss_to_cmd
+local repeated_read_cmd = global_helpers.repeated_read_cmd
local ccs = {}
@@ -22,15 +26,6 @@ table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.7"}, type = "gcc"})
table.insert(ccs, {path = {"/usr/bin/env", "clang"}, type = "clang"})
table.insert(ccs, {path = {"/usr/bin/env", "icc"}, type = "gcc"})
-local quote_me = '[^.%w%+%-%@%_%/]' -- complement (needn't quote)
-local function shell_quote(str)
- if string.find(str, quote_me) or str == '' then
- return "'" .. string.gsub(str, "'", [['"'"']]) .. "'"
- else
- return str
- end
-end
-
-- parse Makefile format dependencies into a Lua table
local function parse_make_deps(deps)
-- remove line breaks and line concatenators
@@ -149,16 +144,6 @@ function Gcc:add_to_include_path(...)
end
end
-local function argss_to_cmd(...)
- local cmd = ''
- for i = 1, select('#', ...) do
- for _, arg in ipairs(select(i, ...)) do
- cmd = cmd .. ' ' .. shell_quote(arg)
- end
- end
- return cmd
-end
-
-- returns a list of the headers files upon which this file relies
function Gcc:dependencies(hdr)
local cmd = argss_to_cmd(self.path, {'-M', hdr}) .. ' 2>&1'
@@ -172,29 +157,15 @@ function Gcc:dependencies(hdr)
end
end
-local function repeated_call(...)
- local cmd = argss_to_cmd(...)
- for _ = 1, 10 do
- local stream = io.popen(cmd)
- local ret = stream:read('*a')
- stream:close()
- if ret then
- return ret
- end
- end
- print('ERROR: preprocess.lua: Failed to execute ' .. cmd .. ': nil return after 10 attempts')
- return nil
-end
-
function Gcc:filter_standard_defines(defines)
if not self.standard_defines then
local pseudoheader_fname = 'tmp_empty_pseudoheader.h'
local pseudoheader_file = io.open(pseudoheader_fname, 'w')
pseudoheader_file:close()
- local standard_defines = repeated_call(self.path,
- self.preprocessor_extra_flags,
- self.get_defines_extra_flags,
- {pseudoheader_fname})
+ local standard_defines = repeated_read_cmd(self.path,
+ self.preprocessor_extra_flags,
+ self.get_defines_extra_flags,
+ {pseudoheader_fname})
os.remove(pseudoheader_fname)
self.standard_defines = {}
for line in standard_defines:gmatch('[^\n]+') do
@@ -223,9 +194,9 @@ function Gcc:preprocess(previous_defines, ...)
pseudoheader_file:flush()
pseudoheader_file:close()
- local defines = repeated_call(self.path, self.preprocessor_extra_flags,
- self.get_defines_extra_flags,
- {pseudoheader_fname})
+ local defines = repeated_read_cmd(self.path, self.preprocessor_extra_flags,
+ self.get_defines_extra_flags,
+ {pseudoheader_fname})
defines = self:filter_standard_defines(defines)
-- lfs = require("lfs")
@@ -234,9 +205,10 @@ function Gcc:preprocess(previous_defines, ...)
-- io.stderr\write("CWD: #{lfs.currentdir!}\n")
-- io.stderr\write("CMD: #{cmd}\n")
- local declarations = repeated_call(self.path, self.preprocessor_extra_flags,
- self.get_declarations_extra_flags,
- {pseudoheader_fname})
+ local declarations = repeated_read_cmd(self.path,
+ self.preprocessor_extra_flags,
+ self.get_declarations_extra_flags,
+ {pseudoheader_fname})
os.remove(pseudoheader_fname)