From: Artem via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: Leonid Vasiliev <lvasiliev@tarantool.org>, Alexander Turenko <alexander.turenko@tarantool.org>, Sergey Bronnikov <sergeyb@tarantool.org> Cc: tarantool-patches@dev.tarantool.org Subject: Re: [Tarantool-patches] [PATCHv2 2/2] lua: fix tarantool -e always enters interactive mode Date: Tue, 2 Mar 2021 20:05:55 +0300 [thread overview] Message-ID: <73fdad5e-f886-56cd-4dde-65214b8a58c6@tarantool.org> (raw) In-Reply-To: <de42e74f-865c-b9f5-18f1-c6053763d03f@tarantool.org> Hello! Thanks for your review! Branch is updated. See my answers below. 01.03.2021 18:10, Leonid Vasiliev пишет: > HI! Thank you for the patch. > Generally OK. > I'll paste the last variation of the diff with comments. > > > From 9b04075006f24a8226aca8398ae643b8f8cd8f05 Mon Sep 17 00:00:00 2001 > Message-Id: > <9b04075006f24a8226aca8398ae643b8f8cd8f05.1614609240.git.lvasiliev@tarantool.org> > In-Reply-To: <cover.1614609240.git.lvasiliev@tarantool.org> > References: <cover.1614609240.git.lvasiliev@tarantool.org> > From: Artem Starshov <artemreyt@tarantool.org> > Date: Tue, 19 Jan 2021 23:21:05 +0300 > Subject: [PATCH 2/2] lua: fix tarantool -e always enters interactive mode > Cc: tarantool-patches@dev.tarantool.org > > The reason why tarantool -e always enters interactive mode is that > statement after option -e isn't considered as a script. > > In man PUC-Rio lua there are different names for statement -e (stat) > and script, but they have the same behavior regarding interactive > mode. (Also cases, when interpreter loads stdin, have the same > behaviour). > > Fixes #5040 > --- > src/lib/core/errinj.h | 1 + > src/lua/init.c | 20 ++- > ...40-always-enters-interactive-mode.test.lua | 131 ++++++++++++++++++ > test/box/errinj.result | 1 + > 4 files changed, 149 insertions(+), 4 deletions(-) > create mode 100755 > test/app-tap/gh-5040-always-enters-interactive-mode.test.lua > > diff --git a/src/lib/core/errinj.h b/src/lib/core/errinj.h > index d76aedf7a..d5fdbc209 100644 > --- a/src/lib/core/errinj.h > +++ b/src/lib/core/errinj.h > @@ -149,6 +149,7 @@ struct errinj { > _(ERRINJ_AUTO_UPGRADE, ERRINJ_BOOL, {.bparam = false})\ > _(ERRINJ_COIO_WRITE_CHUNK, ERRINJ_BOOL, {.bparam = false}) \ > _(ERRINJ_APPLIER_SLOW_ACK, ERRINJ_BOOL, {.bparam = false}) \ > + _(ERRINJ_STDIN_ISATTY, ERRINJ_INT, {.iparam = -1}) \ > > ENUM0(errinj_id, ERRINJ_LIST); > extern struct errinj errinjs[]; > diff --git a/src/lua/init.c b/src/lua/init.c > index 25e8884a6..1a95b9748 100644 > --- a/src/lua/init.c > +++ b/src/lua/init.c > @@ -62,6 +62,7 @@ > #include "lua/swim.h" > #include "lua/decimal.h" > #include "digest.h" > +#include "errinj.h" > #include <small/ibuf.h> > > #include <ctype.h> > @@ -583,6 +584,7 @@ run_script_f(va_list ap) > */ > struct diag *diag = va_arg(ap, struct diag *); > bool aux_loop_is_run = false; > + bool option_e_ran = false; > > Comment: > For a boolean variable name typically `is` is used. > Maybe `is_option_e_ran`. 1. Done. > > /* > * Load libraries and execute chunks passed by -l and -e > @@ -613,6 +615,7 @@ run_script_f(va_list ap) > if (luaT_call(L, 0, 0) != 0) > goto error; > lua_settop(L, 0); > + option_e_ran = true; > break; > default: > unreachable(); /* checked by getopt() in main() */ > @@ -627,25 +630,34 @@ run_script_f(va_list ap) > fiber_sleep(0.0); > aux_loop_is_run = true; > > + int is_a_tty; > + struct errinj *inj = errinj(ERRINJ_STDIN_ISATTY, ERRINJ_INT); > > Comment: > I think it would be nice to add a comment as to why > `ERRINJ_STDIN_ISATTY` is not a boolean. > 2. Done. > + if (inj != NULL && inj->iparam >= 0) { > + is_a_tty = inj->iparam; > + } else { > + is_a_tty = isatty(STDIN_FILENO); > + } > + > if (path && strcmp(path, "-") != 0 && access(path, F_OK) == 0) { > /* Execute script. */ > if (luaL_loadfile(L, path) != 0) > goto luajit_error; > if (lua_main(L, argc, argv) != 0) > goto error; > - } else if (!isatty(STDIN_FILENO) || (path && strcmp(path, "-") == > 0)) { > + } else if (!is_a_tty || (path && strcmp(path, "-") == 0)) { > /* Execute stdin */ > if (luaL_loadfile(L, NULL) != 0) > goto luajit_error; > if (lua_main(L, argc, argv) != 0) > goto error; > - } else { > + } else if (!option_e_ran) { > interactive = true; > } > > /* > - * Start interactive mode when it was explicitly requested > - * by "-i" option or stdin is TTY or there are no script. > + * Start interactive mode in any of the cases: > + * - it was explicitly requested by "-i" option; > + * - stdin is TTY and there are no script (-e is considered as a > script). > */ > if (interactive) { > say_crit("%s %s\ntype 'help' for interactive help", > diff --git > a/test/app-tap/gh-5040-always-enters-interactive-mode.test.lua > b/test/app-tap/gh-5040-always-enters-interactive-mode.test.lua > new file mode 100755 > index 000000000..df3ee2f2d > --- /dev/null > +++ b/test/app-tap/gh-5040-always-enters-interactive-mode.test.lua > @@ -0,0 +1,131 @@ > +#!/usr/bin/env tarantool > + > +local process_timeout = require('process_timeout') > +local ffi = require('ffi') > +local tap = require('tap') > +local fio = require('fio') > + > +-- > +-- Tests to check if the tarantool binary enters > +-- interactive mode or not. > +-- > + > +local build_target = require('tarantool').build.target > +local is_debug = build_target:match('Debug$') ~= nil > + > +local TARANTOOL_PATH = arg[-1] > +local output_file = fio.abspath('out.txt') > +local cmd_end = (' >%s & echo $!'):format(output_file) > + > +-- Like a default timeout for `cond_wait` in test-run > +local process_waiting_timeout = 60.0 > +local file_read_timeout = 60.0 > +local file_read_interval = 0.2 > +local file_open_timeout = 60.0 > + > +-- Each testcase consists of: > +-- * cmd_args - command line arguments for tarantool binary > +-- * stdin - stdin for tarantool > +-- * interactive - true if interactive mode expected > +-- * empty_output - true if command should have empty output > +local testcases = { > + { > + cmd_args = '', > + stdin = 'tty', > + interactive = true > + }, > + { > + cmd_args = '', > + stdin = '/dev/null', > + interactive = false, > + empty_output = true > + }, > + > + { > + cmd_args = ' -e "print(_VERSION)"', > + stdin = 'tty', > + interactive = false > + }, > + { > + cmd_args = ' -e "print(_VERSION)"', > + stdin = '/dev/null', > + interactive = false > + }, > + > + { > + cmd_args = ' -i -e "print(_VERSION)"', > + stdin = 'tty', > + interactive = true > + }, > + { > + cmd_args = ' -i -e "print(_VERSION)"', > + stdin = '/dev/null', > + interactive = true > + } > +} > + > +local test = tap.test('gh-5040') > + > +if not is_debug then > > Comment: > AFAIU `release_disabled` from "suite.ini" is used for this purpose. 3. Unfortunately, in app-tap directory this option doesn't work. https://github.com/tarantool/test-run/issues/199 > + test:plan(1) > + test:skip('This test runs only with Debug build. Build: ' .. > build_target) > + os.exit(test:check() and 0 or 1) > +end > + > +test:plan(#testcases) > +for _, cmd in pairs(testcases) do > + local full_cmd = '' > + if cmd.stdin == 'tty' then > + cmd.stdin = '' > + full_cmd = 'ERRINJ_STDIN_ISATTY=1 ' > + else > + cmd.stdin = '< ' .. cmd.stdin > + end > + > + local full_cmd = full_cmd .. ('%s %s %s %s'):format( > + TARANTOOL_PATH, > + cmd.cmd_args, > + cmd.stdin, > + cmd_end > + ) > + test:test(full_cmd, function(test) > + test:plan(cmd.interactive and 1 or 2) > + > + local pid = tonumber(io.popen(full_cmd):read("*line")) > + assert(pid, "pipe error for: " .. cmd.cmd_args) > + > + local fh = process_timeout.open_with_timeout(output_file, > + file_open_timeout) > + assert(fh, 'error while opening ' .. output_file) > + > + if cmd.interactive then > + local data = process_timeout.read_with_timeout(fh, > + file_read_timeout, > + file_read_interval) > + test:like(data, 'tarantool>', 'interactive mode detected') > + else > + local process_completed = > process_timeout.wait_process_completion( > + pid, > + process_waiting_timeout) > + test:ok(process_completed, 'process completed') > + > + -- If empty output expected, then don't wait full > file_read_timeout > + -- for non-empty output_file, only a little time to be > sure that > + -- file is empty. > + local read_timeout = cmd.empty_output and file_read_interval > + or file_read_timeout > + local data = process_timeout.read_with_timeout(fh, > read_timeout, > + file_read_interval) > + if cmd.empty_output then > + test:ok(#data == 0, 'output is empty') > + else > + test:unlike(data, 'tarantool>', 'iteractive mode > wasn\'t detected') > > Comment: > Maximal width of a code line is 80 symbols. 4. Done. > > + end > + end > + if process_timeout.process_is_alive(pid) then ffi.C.kill(pid, > 9) end > > Comment: > From C code style: "Don't put multiple statements on a single line > unless you have something to hide". > Up to you. 5. Done. > + fh:close() > + os.remove(output_file) > + end) > +end > + > +os.exit(test:check() and 0 or 1) > diff --git a/test/box/errinj.result b/test/box/errinj.result > index b8c2476c3..a962dbe2d 100644 > --- a/test/box/errinj.result > +++ b/test/box/errinj.result > @@ -74,6 +74,7 @@ evals > - ERRINJ_SNAP_COMMIT_DELAY: false > - ERRINJ_SNAP_WRITE_DELAY: false > - ERRINJ_SQL_NAME_NORMALIZATION: false > + - ERRINJ_STDIN_ISATTY: -1 > - ERRINJ_SWIM_FD_ONLY: false > - ERRINJ_TESTING: false > - ERRINJ_TUPLE_ALLOC: false
next prev parent reply other threads:[~2021-03-02 17:05 UTC|newest] Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-02-18 19:30 [Tarantool-patches] [PATCHv2 0/2] " Artem Starshov via Tarantool-patches 2021-02-18 19:30 ` [Tarantool-patches] [PATCHv2 1/2] core: add setting error injections via env Artem Starshov via Tarantool-patches 2021-02-20 9:03 ` Sergey Bronnikov via Tarantool-patches 2021-02-20 11:21 ` Artem via Tarantool-patches 2021-02-20 14:27 ` Sergey Bronnikov via Tarantool-patches 2021-02-24 9:38 ` Artem via Tarantool-patches 2021-02-25 14:36 ` Sergey Bronnikov via Tarantool-patches 2021-03-01 14:47 ` Leonid Vasiliev via Tarantool-patches 2021-03-02 17:00 ` Artem via Tarantool-patches 2021-02-18 19:30 ` [Tarantool-patches] [PATCHv2 2/2] lua: fix tarantool -e always enters interactive mode Artem Starshov via Tarantool-patches 2021-02-19 9:15 ` Konstantin Osipov via Tarantool-patches 2021-02-19 14:33 ` Artem via Tarantool-patches 2021-02-20 10:05 ` Sergey Bronnikov via Tarantool-patches 2021-02-20 11:27 ` Artem via Tarantool-patches 2021-03-01 15:10 ` Leonid Vasiliev via Tarantool-patches 2021-03-02 17:05 ` Artem via Tarantool-patches [this message] 2021-03-03 12:55 ` Leonid Vasiliev via Tarantool-patches 2021-02-25 14:37 ` [Tarantool-patches] [PATCHv2 0/2] " Sergey Bronnikov via Tarantool-patches
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=73fdad5e-f886-56cd-4dde-65214b8a58c6@tarantool.org \ --to=tarantool-patches@dev.tarantool.org \ --cc=alexander.turenko@tarantool.org \ --cc=artemreyt@tarantool.org \ --cc=lvasiliev@tarantool.org \ --cc=sergeyb@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCHv2 2/2] lua: fix tarantool -e always enters interactive mode' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox