diff options
Diffstat (limited to 'test/unit/os/shell_spec.lua')
-rw-r--r-- | test/unit/os/shell_spec.lua | 139 |
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) |