From 65fb622000af8e3dbb65480e1581758ecf4ba3e2 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 00:12:26 +0300 Subject: functests: Replace execute with either command or feed_command Hope this will make people using feed_command less likely: this hides bugs. Already found at least two: 1. msgpackparse() will show internal error: hash_add() in case of duplicate keys, though it will still work correctly. Currently silenced. 2. ttimeoutlen was spelled incorrectly, resulting in option not being set when expected. Test was still functioning somehow though. Currently fixed. --- test/functional/eval/system_spec.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'test/functional/eval/system_spec.lua') diff --git a/test/functional/eval/system_spec.lua b/test/functional/eval/system_spec.lua index ee75b593ff..0b7d3dce21 100644 --- a/test/functional/eval/system_spec.lua +++ b/test/functional/eval/system_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) -local eq, call, clear, eval, execute, feed, nvim = - helpers.eq, helpers.call, helpers.clear, helpers.eval, helpers.execute, +local eq, call, clear, eval, feed_command, feed, nvim = + helpers.eq, helpers.call, helpers.clear, helpers.eval, helpers.feed_command, helpers.feed, helpers.nvim local Screen = require('test.functional.ui.screen') @@ -43,10 +43,10 @@ describe('system()', function() it('parameter validation does NOT modify v:shell_error', function() -- 1. Call system() with invalid parameters. -- 2. Assert that v:shell_error was NOT set. - execute('call system({})') + feed_command('call system({})') eq('E475: Invalid argument: expected String or List', eval('v:errmsg')) eq(0, eval('v:shell_error')) - execute('call system([])') + feed_command('call system([])') eq('E474: Invalid argument', eval('v:errmsg')) eq(0, eval('v:shell_error')) @@ -57,9 +57,9 @@ describe('system()', function() -- 1. Call system() with invalid parameters. -- 2. Assert that v:shell_error was NOT modified. - execute('call system({})') + feed_command('call system({})') eq(old_val, eval('v:shell_error')) - execute('call system([])') + feed_command('call system([])') eq(old_val, eval('v:shell_error')) end) @@ -182,7 +182,7 @@ describe('system()', function() end) it('to backgrounded command does not crash', function() -- This is indeterminate, just exercise the codepath. May get E5677. - execute('call system("echo -n echoed &")') + feed_command('call system("echo -n echoed &")') local v_errnum = string.match(eval("v:errmsg"), "^E%d*:") if v_errnum then eq("E5677:", v_errnum) @@ -197,7 +197,7 @@ describe('system()', function() end) it('to backgrounded command does not crash', function() -- This is indeterminate, just exercise the codepath. May get E5677. - execute('call system("cat - &")') + feed_command('call system("cat - &")') local v_errnum = string.match(eval("v:errmsg"), "^E%d*:") if v_errnum then eq("E5677:", v_errnum) -- cgit From 69d1003bf79b7466d2fea45f94aeddbedd246049 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 9 Apr 2017 01:55:19 +0300 Subject: functests: Fix some tests which are failing locally for unrelated reasons --- test/functional/eval/system_spec.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'test/functional/eval/system_spec.lua') diff --git a/test/functional/eval/system_spec.lua b/test/functional/eval/system_spec.lua index 0b7d3dce21..bf95752e3b 100644 --- a/test/functional/eval/system_spec.lua +++ b/test/functional/eval/system_spec.lua @@ -1,4 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) + +local nvim_dir = helpers.nvim_dir local eq, call, clear, eval, feed_command, feed, nvim = helpers.eq, helpers.call, helpers.clear, helpers.eval, helpers.feed_command, helpers.feed, helpers.nvim @@ -31,7 +33,7 @@ describe('system()', function() describe('command passed as a List', function() local function printargs_path() - return helpers.nvim_dir..'/printargs-test' + return nvim_dir..'/printargs-test' .. (helpers.os_name() == 'windows' and '.exe' or '') end -- cgit From 799443c9942fa145320d9cc7c4638bdaa8c8d67a Mon Sep 17 00:00:00 2001 From: Rui Abreu Ferreira Date: Sat, 25 Mar 2017 22:47:38 +0000 Subject: win/test: Enable more system() tests --- test/functional/eval/system_spec.lua | 74 ++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 21 deletions(-) (limited to 'test/functional/eval/system_spec.lua') diff --git a/test/functional/eval/system_spec.lua b/test/functional/eval/system_spec.lua index bf95752e3b..83d8028b56 100644 --- a/test/functional/eval/system_spec.lua +++ b/test/functional/eval/system_spec.lua @@ -94,17 +94,26 @@ describe('system()', function() end) end) - if helpers.pending_win32(pending) then return end - it('sets v:shell_error', function() - eval([[system("sh -c 'exit'")]]) - eq(0, eval('v:shell_error')) - eval([[system("sh -c 'exit 1'")]]) - eq(1, eval('v:shell_error')) - eval([[system("sh -c 'exit 5'")]]) - eq(5, eval('v:shell_error')) - eval([[system('this-should-not-exist')]]) - eq(127, eval('v:shell_error')) + if helpers.os_name() == 'windows' then + eval([[system("cmd.exe /c exit")]]) + eq(0, eval('v:shell_error')) + eval([[system("cmd.exe /c exit 1")]]) + eq(1, eval('v:shell_error')) + eval([[system("cmd.exe /c exit 5")]]) + eq(5, eval('v:shell_error')) + eval([[system('this-should-not-exist')]]) + eq(1, eval('v:shell_error')) + else + eval([[system("sh -c 'exit'")]]) + eq(0, eval('v:shell_error')) + eval([[system("sh -c 'exit 1'")]]) + eq(1, eval('v:shell_error')) + eval([[system("sh -c 'exit 5'")]]) + eq(5, eval('v:shell_error')) + eval([[system('this-should-not-exist')]]) + eq(127, eval('v:shell_error')) + end end) describe('executes shell function if passed a string', function() @@ -120,6 +129,15 @@ describe('system()', function() screen:detach() end) + it('escapes inner double quotes #6329', function() + if helpers.os_name() == 'windows' then + -- In Windows cmd.exe's echo prints the quotes + eq('""\n', eval([[system('echo ""')]])) + else + eq('\n', eval([[system('echo ""')]])) + end + end) + it('`echo` and waits for its return', function() feed(':call system("echo")') screen:expect([[ @@ -180,7 +198,11 @@ describe('system()', function() describe('passing no input', function() it('returns the program output', function() - eq("echoed", eval('system("echo -n echoed")')) + if helpers.os_name() == 'windows' then + eq("echoed\n", eval('system("echo echoed")')) + else + eq("echoed", eval('system("echo -n echoed")')) + end end) it('to backgrounded command does not crash', function() -- This is indeterminate, just exercise the codepath. May get E5677. @@ -277,21 +299,30 @@ describe('system()', function() end) end) -if helpers.pending_win32(pending) then return end - describe('systemlist()', function() -- Similar to `system()`, but returns List instead of String. before_each(clear) it('sets the v:shell_error variable', function() - eval([[systemlist("sh -c 'exit'")]]) - eq(0, eval('v:shell_error')) - eval([[systemlist("sh -c 'exit 1'")]]) - eq(1, eval('v:shell_error')) - eval([[systemlist("sh -c 'exit 5'")]]) - eq(5, eval('v:shell_error')) - eval([[systemlist('this-should-not-exist')]]) - eq(127, eval('v:shell_error')) + if helpers.os_name() == 'windows' then + eval([[systemlist("cmd.exe /c exit")]]) + eq(0, eval('v:shell_error')) + eval([[systemlist("cmd.exe /c exit 1")]]) + eq(1, eval('v:shell_error')) + eval([[systemlist("cmd.exe /c exit 5")]]) + eq(5, eval('v:shell_error')) + eval([[systemlist('this-should-not-exist')]]) + eq(1, eval('v:shell_error')) + else + eval([[systemlist("sh -c 'exit'")]]) + eq(0, eval('v:shell_error')) + eval([[systemlist("sh -c 'exit 1'")]]) + eq(1, eval('v:shell_error')) + eval([[systemlist("sh -c 'exit 5'")]]) + eq(5, eval('v:shell_error')) + eval([[systemlist('this-should-not-exist')]]) + eq(127, eval('v:shell_error')) + end end) describe('exectues shell function', function() @@ -389,6 +420,7 @@ describe('systemlist()', function() after_each(delete_file(fname)) it('replaces NULs by newline characters', function() + if helpers.pending_win32(pending) then return end eq({'part1\npart2\npart3'}, eval('systemlist("cat '..fname..'")')) end) end) -- cgit From f3cc843755a6d638ada77dc31721aa53b3ff2364 Mon Sep 17 00:00:00 2001 From: Rui Abreu Ferreira Date: Tue, 28 Mar 2017 16:03:53 +0100 Subject: win: libuv_process_spawn(): special-case cmd.exe Disable CommandLineToArgvW-standard quoting for cmd.exe. libuv assumes spawned processes follow the convention expected by CommandLineToArgvW(). But cmd.exe is non-conformant, so for cmd.exe: - With system([]), the caller has full control (and responsibility) to quote arguments correctly. - With system(''), shell* options are used. libuv quoting is disabled if argv[0] is: - cmd.exe - cmd - $COMSPEC resolving to a path with filename cmd.exe Closes #6329 References #6387 --- test/functional/eval/system_spec.lua | 38 +++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'test/functional/eval/system_spec.lua') diff --git a/test/functional/eval/system_spec.lua b/test/functional/eval/system_spec.lua index 83d8028b56..45ca69707d 100644 --- a/test/functional/eval/system_spec.lua +++ b/test/functional/eval/system_spec.lua @@ -129,14 +129,38 @@ describe('system()', function() screen:detach() end) - it('escapes inner double quotes #6329', function() - if helpers.os_name() == 'windows' then - -- In Windows cmd.exe's echo prints the quotes + if helpers.os_name() == 'windows' then + it('with the default cmd.exe shell', function() eq('""\n', eval([[system('echo ""')]])) - else - eq('\n', eval([[system('echo ""')]])) - end - end) + eq('"a b"\n', eval([[system('echo "a b"')]])) + -- TODO: consistent with Vim, but it should be fixed + eq('a & echo b\n', eval([[system('echo a & echo b')]])) + eval([[system('cd "C:\Program Files"')]]) + eq(0, eval('v:shell_error')) + end) + + it('with set shell="cmd"', function() + helpers.source('let &shell="cmd"') + eq('"a b"\n', eval([[system('echo "a b"')]])) + end) + + it('works with cmd.exe from $COMSPEC', function() + local comspecshell = eval("fnamemodify($COMSPEC, ':t')") + if comspecshell == 'cmd.exe' then + helpers.source('let &shell=$COMSPEC') + eq('"a b"\n', eval([[system('echo "a b"')]])) + else + pending('$COMSPEC is not cmd.exe ' .. comspecshell) + end + end) + + it('works with powershell', function() + helpers.set_shell_powershell() + eq('a\nb\n', eval([[system('echo a b')]])) + eq('C:\\\n', eval([[system('cd c:\; (Get-Location).Path')]])) + eq('a b\n', eval([[system('echo "a b"')]])) + end) + end it('`echo` and waits for its return', function() feed(':call system("echo")') -- cgit From d31d177a0c2c9997c2cdb04975bc3354b9a23fb8 Mon Sep 17 00:00:00 2001 From: Rui Abreu Ferreira Date: Thu, 30 Mar 2017 23:41:52 +0100 Subject: win: default shellxescape, shellxquote to empty Calling cmd.exe in Windows follows a very different pattern from Vim. The primary difference is that Vim does a nested call to cmd.exe, e.g. the following call in Vim system('echo a 2>&1') spawns the following processes "C:\Program Files (x86)\Vim\vim80\vimrun" -s C:\Windows\system32\cmd.exe /c (echo a 2^>^&1 ^>C:\Users\dummy\AppData\Local\Temp\VIoC169.tmp 2^>^&1) C:\Windows\system32\cmd.exe /c C:\Windows\system32\cmd.exe /c (echo a 2^>^&1 ^>C:\Users\dummy\AppData\Local\Temp\VIo3C6C.tmp 2^>^&1) C:\Windows\system32\cmd.exe /c (echo a 2>&1 >C:\Users\dummy\AppData\Local\Temp\VIo3C6C.tmp 2>&1) The escaping with ^ is needed because cmd.exe calls itself and needs to preserve the special metacharacters for the last call. However in nvim no nested call is made, system('') spawns a single cmd.exe process. Setting shellxescape to "" disables escaping with ^. The previous default for shellxquote=( wrapped any command in parenthesis, in Vim this is more meaningful due to the use of tempfiles to store the output and redirection (also see &shellquote). There is a slight benefit in having the default be empty because some expressions that run in console will not run within parens e.g. due to unbalanced double quotes system('echo "a b') --- test/functional/eval/system_spec.lua | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'test/functional/eval/system_spec.lua') diff --git a/test/functional/eval/system_spec.lua b/test/functional/eval/system_spec.lua index 45ca69707d..7e213e2156 100644 --- a/test/functional/eval/system_spec.lua +++ b/test/functional/eval/system_spec.lua @@ -4,6 +4,8 @@ local nvim_dir = helpers.nvim_dir local eq, call, clear, eval, feed_command, feed, nvim = helpers.eq, helpers.call, helpers.clear, helpers.eval, helpers.feed_command, helpers.feed, helpers.nvim +local command = helpers.command +local iswin = helpers.iswin local Screen = require('test.functional.ui.screen') @@ -33,8 +35,7 @@ describe('system()', function() describe('command passed as a List', function() local function printargs_path() - return nvim_dir..'/printargs-test' - .. (helpers.os_name() == 'windows' and '.exe' or '') + return nvim_dir..'/printargs-test' .. (iswin() and '.exe' or '') end it('sets v:shell_error if cmd[0] is not executable', function() @@ -88,14 +89,14 @@ describe('system()', function() end) it('does NOT run in shell', function() - if helpers.os_name() ~= 'windows' then + if not iswin() then eq("* $PATH %PATH%\n", eval("system(['echo', '*', '$PATH', '%PATH%'])")) end end) end) it('sets v:shell_error', function() - if helpers.os_name() == 'windows' then + if iswin() then eval([[system("cmd.exe /c exit")]]) eq(0, eval('v:shell_error')) eval([[system("cmd.exe /c exit 1")]]) @@ -129,28 +130,29 @@ describe('system()', function() screen:detach() end) - if helpers.os_name() == 'windows' then - it('with the default cmd.exe shell', function() + if iswin() then + it('with shell=cmd.exe', function() + command('set shell=cmd.exe') eq('""\n', eval([[system('echo ""')]])) eq('"a b"\n', eval([[system('echo "a b"')]])) - -- TODO: consistent with Vim, but it should be fixed - eq('a & echo b\n', eval([[system('echo a & echo b')]])) + eq('a \nb\n', eval([[system('echo a & echo b')]])) + eq('a \n', eval([[system('echo a 2>&1')]])) eval([[system('cd "C:\Program Files"')]]) eq(0, eval('v:shell_error')) end) - it('with set shell="cmd"', function() - helpers.source('let &shell="cmd"') + it('with shell=cmd', function() + command('set shell=cmd') eq('"a b"\n', eval([[system('echo "a b"')]])) end) - it('works with cmd.exe from $COMSPEC', function() + it('with shell=$COMSPEC', function() local comspecshell = eval("fnamemodify($COMSPEC, ':t')") if comspecshell == 'cmd.exe' then - helpers.source('let &shell=$COMSPEC') + command('set shell=$COMSPEC') eq('"a b"\n', eval([[system('echo "a b"')]])) else - pending('$COMSPEC is not cmd.exe ' .. comspecshell) + pending('$COMSPEC is not cmd.exe: ' .. comspecshell) end end) @@ -222,7 +224,7 @@ describe('system()', function() describe('passing no input', function() it('returns the program output', function() - if helpers.os_name() == 'windows' then + if iswin() then eq("echoed\n", eval('system("echo echoed")')) else eq("echoed", eval('system("echo -n echoed")')) @@ -327,8 +329,8 @@ describe('systemlist()', function() -- Similar to `system()`, but returns List instead of String. before_each(clear) - it('sets the v:shell_error variable', function() - if helpers.os_name() == 'windows' then + it('sets v:shell_error', function() + if iswin() then eval([[systemlist("cmd.exe /c exit")]]) eq(0, eval('v:shell_error')) eval([[systemlist("cmd.exe /c exit 1")]]) -- cgit