aboutsummaryrefslogtreecommitdiff
path: root/test/unit/os/shell_spec.lua
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit/os/shell_spec.lua')
-rw-r--r--test/unit/os/shell_spec.lua139
1 files changed, 97 insertions, 42 deletions
diff --git a/test/unit/os/shell_spec.lua b/test/unit/os/shell_spec.lua
index 906f950308..a73fc8e47e 100644
--- a/test/unit/os/shell_spec.lua
+++ b/test/unit/os/shell_spec.lua
@@ -1,16 +1,5 @@
--- not all operating systems support the system()-tests, as of yet.
-local allowed_os = {
- Linux = true,
- OSX = true,
- BSD = true,
- POSIX = true
-}
-
-if allowed_os[jit.os] ~= true then
- return
-end
-
-local helpers = require('test.unit.helpers')
+local helpers = require('test.unit.helpers')(after_each)
+local itp = helpers.gen_itp(it)
local cimported = helpers.cimport(
'./src/nvim/os/shell.h',
'./src/nvim/option_defs.h',
@@ -24,16 +13,19 @@ local to_cstr = helpers.to_cstr
local NULL = ffi.cast('void *', 0)
describe('shell functions', function()
- setup(function()
+ before_each(function()
-- os_system() can't work when the p_sh and p_shcf variables are unset
- cimported.p_sh = to_cstr('/bin/bash')
+ cimported.p_sh = to_cstr('/bin/sh')
cimported.p_shcf = to_cstr('-c')
+ cimported.p_sxq = to_cstr('')
+ cimported.p_sxe = to_cstr('')
end)
local function shell_build_argv(cmd, extra_args)
local res = cimported.shell_build_argv(
cmd and to_cstr(cmd),
extra_args and to_cstr(extra_args))
+ -- `res` is zero-indexed (C pointer, not Lua table)!
local argc = 0
local ret = {}
-- Explicitly free everything, so if it is not in allocated memory it will
@@ -47,6 +39,26 @@ describe('shell functions', function()
return ret
end
+ local function shell_argv_to_str(argv_table)
+ -- C string array (char **).
+ local argv = (argv_table
+ and ffi.new("char*[?]", #argv_table+1)
+ or NULL)
+
+ local argc = 1
+ while argv_table ~= nil and argv_table[argc] ~= nil do
+ -- `argv` is zero-indexed (C pointer, not Lua table)!
+ argv[argc - 1] = to_cstr(argv_table[argc])
+ argc = argc + 1
+ end
+ if argv_table ~= nil then
+ argv[argc - 1] = NULL
+ end
+
+ local res = cimported.shell_argv_to_str(argv)
+ return ffi.string(res)
+ end
+
local function os_system(cmd, input)
local input_or = input and to_cstr(input) or NULL
local input_len = (input ~= nil) and string.len(input) or 0
@@ -61,63 +73,51 @@ describe('shell functions', function()
end
describe('os_system', function()
- it('can echo some output (shell builtin)', function()
- local cmd, text = 'echo -n', 'some text'
+ itp('can echo some output (shell builtin)', function()
+ local cmd, text = 'printf "%s "', 'some text '
local status, output = os_system(cmd .. ' ' .. text)
eq(text, output)
eq(0, status)
end)
- it('can deal with empty output', function()
- local cmd = 'echo -n'
+ itp('can deal with empty output', function()
+ local cmd = 'printf ""'
local status, output = os_system(cmd)
eq('', output)
eq(0, status)
end)
- it('can pass input on stdin', function()
+ itp('can pass input on stdin', function()
local cmd, input = 'cat -', 'some text\nsome other text'
local status, output = os_system(cmd, input)
eq(input, output)
eq(0, status)
end)
- it ('returns non-zero exit code', function()
+ itp('returns non-zero exit code', function()
local status = os_system('exit 2')
eq(2, status)
end)
end)
describe('shell_build_argv', function()
- local saved_opts = {}
-
- setup(function()
- saved_opts.p_sh = cimported.p_sh
- saved_opts.p_shcf = cimported.p_shcf
- end)
-
- teardown(function()
- cimported.p_sh = saved_opts.p_sh
- cimported.p_shcf = saved_opts.p_shcf
+ itp('works with NULL arguments', function()
+ eq({'/bin/sh'}, shell_build_argv(nil, nil))
end)
- it('works with NULL arguments', function()
- eq({'/bin/bash'}, shell_build_argv(nil, nil))
+ itp('works with cmd', function()
+ eq({'/bin/sh', '-c', 'abc def'}, shell_build_argv('abc def', nil))
end)
- it('works with cmd', function()
- eq({'/bin/bash', '-c', 'abc def'}, shell_build_argv('abc def', nil))
+ itp('works with extra_args', function()
+ eq({'/bin/sh', 'ghi jkl'}, shell_build_argv(nil, 'ghi jkl'))
end)
- it('works with extra_args', function()
- eq({'/bin/bash', 'ghi jkl'}, shell_build_argv(nil, 'ghi jkl'))
+ itp('works with cmd and extra_args', function()
+ eq({'/bin/sh', 'ghi jkl', '-c', 'abc def'}, shell_build_argv('abc def', 'ghi jkl'))
end)
- it('works with cmd and extra_args', function()
- eq({'/bin/bash', 'ghi jkl', '-c', 'abc def'}, shell_build_argv('abc def', 'ghi jkl'))
- end)
-
- it('splits and unquotes &shell and &shellcmdflag', function()
+ itp('splits and unquotes &shell and &shellcmdflag', function()
cimported.p_sh = to_cstr('/Program" "Files/zsh -f')
cimported.p_shcf = to_cstr('-x -o "sh word split" "-"c')
eq({'/Program Files/zsh', '-f',
@@ -126,5 +126,60 @@ describe('shell functions', function()
'-c', 'abc def'},
shell_build_argv('abc def', 'ghi jkl'))
end)
+
+ itp('applies shellxescape (p_sxe) and shellxquote (p_sxq)', function()
+ cimported.p_sxq = to_cstr('(')
+ cimported.p_sxe = to_cstr('"&|<>()@^')
+
+ local argv = ffi.cast('char**',
+ cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil))
+ eq(ffi.string(argv[0]), '/bin/sh')
+ eq(ffi.string(argv[1]), '-c')
+ eq(ffi.string(argv[2]), '(echo ^&^|^<^>^(^)^@^^)')
+ eq(nil, argv[3])
+ end)
+
+ itp('applies shellxquote="(', function()
+ cimported.p_sxq = to_cstr('"(')
+ cimported.p_sxe = to_cstr('"&|<>()@^')
+
+ local argv = ffi.cast('char**', cimported.shell_build_argv(
+ to_cstr('echo -n some text'), nil))
+ eq(ffi.string(argv[0]), '/bin/sh')
+ eq(ffi.string(argv[1]), '-c')
+ eq(ffi.string(argv[2]), '"(echo -n some text)"')
+ eq(nil, argv[3])
+ end)
+
+ itp('applies shellxquote="', function()
+ cimported.p_sxq = to_cstr('"')
+ cimported.p_sxe = to_cstr('')
+
+ local argv = ffi.cast('char**', cimported.shell_build_argv(
+ to_cstr('echo -n some text'), nil))
+ eq(ffi.string(argv[0]), '/bin/sh')
+ eq(ffi.string(argv[1]), '-c')
+ eq(ffi.string(argv[2]), '"echo -n some text"')
+ eq(nil, argv[3])
+ end)
+
+ itp('with empty shellxquote/shellxescape', function()
+ local argv = ffi.cast('char**', cimported.shell_build_argv(
+ to_cstr('echo -n some text'), nil))
+ eq(ffi.string(argv[0]), '/bin/sh')
+ eq(ffi.string(argv[1]), '-c')
+ eq(ffi.string(argv[2]), 'echo -n some text')
+ eq(nil, argv[3])
+ end)
+ end)
+
+ itp('shell_argv_to_str', function()
+ eq('', shell_argv_to_str({ nil }))
+ eq("''", shell_argv_to_str({ '' }))
+ eq("'foo' '' 'bar'", shell_argv_to_str({ 'foo', '', 'bar' }))
+ eq("'/bin/sh' '-c' 'abc def'", shell_argv_to_str({'/bin/sh', '-c', 'abc def'}))
+ eq("'abc def' 'ghi jkl'", shell_argv_to_str({'abc def', 'ghi jkl'}))
+ eq("'/bin/sh' '-c' 'abc def' '"..('x'):rep(225).."...",
+ shell_argv_to_str({'/bin/sh', '-c', 'abc def', ('x'):rep(999)}))
end)
end)