From 63a98fca552b1f7197dd2a37764a57604e3746e8 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Fri, 7 Nov 2014 11:01:59 -0300 Subject: test: Fix nondeterminism in tests with notifications Tests which spin the event loop and stop it in a notification handler have a chance of re-entering the event loop due to the `vim_eval` call in the `request()` helper(assuming the request call is what triggered the notification). Since this will cause an error to be thrown by the lua client, don't send the extra `vim_eval` request when the loop has been stopped. --- test/functional/helpers.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index bf6e3dd38a..6c3f5190c9 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -25,7 +25,7 @@ if os.getenv('VALGRIND') then nvim_argv = valgrind_argv end -local session, loop_running, last_error +local session, loop_running, loop_stopped, last_error local function request(method, ...) local status, rv = session:request(method, ...) @@ -39,7 +39,11 @@ local function request(method, ...) end -- Make sure this will only return after all buffered characters have been -- processed - session:request('vim_eval', '1') + if not loop_stopped then + -- Except when the loop has been stopped by a notification triggered + -- by the initial request, for example. + session:request('vim_eval', '1') + end return rv end @@ -71,6 +75,7 @@ local function run(request_cb, notification_cb, setup_cb) call_and_stop_on_error(setup_cb) end + loop_stopped = false loop_running = true session:run(on_request, on_notification, on_setup) loop_running = false @@ -82,6 +87,7 @@ local function run(request_cb, notification_cb, setup_cb) end local function stop() + loop_stopped = true session:stop() end -- cgit From ab826d88f69a3cc2785baa6367d3bd01dbb84627 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 10 Nov 2014 08:07:16 -0300 Subject: eval: Return an empty list from systemlist() when there's no output This is the behavior on vim's `systemlist()`. --- src/nvim/eval.c | 5 +++++ test/functional/shell/viml_system_spec.lua | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 59363a3608..fc61fed529 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -14492,6 +14492,11 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, set_vim_var_nr(VV_SHELL_ERROR, (long) status); if (res == NULL) { + if (retlist) { + // return an empty list when there's no output + rettv->v_type = VAR_LIST; + rettv->vval.v_list = list_alloc(); + } return; } diff --git a/test/functional/shell/viml_system_spec.lua b/test/functional/shell/viml_system_spec.lua index a8bab8e26e..b36b4691b9 100644 --- a/test/functional/shell/viml_system_spec.lua +++ b/test/functional/shell/viml_system_spec.lua @@ -166,7 +166,7 @@ describe('systemlist()', function() if xclip then describe("with a program that doesn't close stdout", function() it('will exit properly after passing input', function() - eq(nil, eval( + eq({}, eval( "systemlist('xclip -i -selection clipboard', ['clip', 'data'])")) eq({'clip', 'data'}, eval( "systemlist('xclip -o -selection clipboard')")) -- cgit From 3e8ef31ada1f2ae0b0cd58bb25d5516d19eee82d Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 10 Nov 2014 09:19:27 -0300 Subject: shell: Use job_write_cb for closing stdin Commit @45525853d352 removed usage of the `job_write_cb` for closing stdin due to a memory error, but that doesn't work anymore because `job_close_in` closes stdin immediately, possibly trimming input data before it is fully written. Since most memory issues with jobs have been fixed, re-add the `job_write_cb` call to ensure stdin is only closed when it should. Also add tests for scenarios where using the callback makes a difference. --- src/nvim/os/shell.c | 9 +++++++++ test/functional/shell/viml_system_spec.lua | 30 ++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 7449ac637c..1b279f18f5 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -244,6 +244,9 @@ static int shell(const char *cmd, job_stop(job); return -1; } + // close the input stream after everything is written + job_write_cb(job, shell_write_cb); + } else { // close the input stream, let the process know that no more input is // coming job_close_in(job); @@ -447,3 +450,9 @@ static void write_output(char *output, size_t remaining) curbuf->b_no_eol_lnum = 0; } } + +static void shell_write_cb(WStream *wstream, void *data, int status) +{ + Job *job = data; + job_close_in(job); +} diff --git a/test/functional/shell/viml_system_spec.lua b/test/functional/shell/viml_system_spec.lua index b36b4691b9..91e115aedf 100644 --- a/test/functional/shell/viml_system_spec.lua +++ b/test/functional/shell/viml_system_spec.lua @@ -3,8 +3,8 @@ -- - `systemlist()` local helpers = require('test.functional.helpers') -local eq, clear, eval, feed = - helpers.eq, helpers.clear, helpers.eval, helpers.feed +local eq, clear, eval, feed, nvim = + helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.nvim local function create_file_with_nuls(name) @@ -55,6 +55,21 @@ describe('system()', function() end) end) + describe('passing a lot of input', function() + it('returns the program output', function() + local input = {} + -- write more than 1mb of data, which should be enough to overcome + -- the os buffer limit and force multiple event loop iterations to write + -- everything + for i = 1, 0xffff do + input[#input + 1] = '01234567890ABCDEFabcdef' + end + input = table.concat(input, '\n') + nvim('set_var', 'input', input) + eq(input, eval('system("cat -", g:input)')) + end) + end) + describe('passing number as input', function() it('stringifies the input', function() eq('1', eval('system("cat", 1)')) @@ -129,6 +144,17 @@ describe('systemlist()', function() end) end) + describe('passing a lot of input', function() + it('returns the program output', function() + local input = {} + for i = 1, 0xffff do + input[#input + 1] = '01234567890ABCDEFabcdef' + end + nvim('set_var', 'input', input) + eq(input, eval('systemlist("cat -", g:input)')) + end) + end) + describe('with output containing NULs', function() local fname = 'Xtest' -- cgit