diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2018-04-11 03:29:18 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-11 03:29:18 +0200 |
commit | f96d99ad1118d79ae5c38bb5e2c4be1280caa3cc (patch) | |
tree | e5676f34610bafc482179f8c17f45314d2d33acb | |
parent | 84bac9f507e3258c574cfc91ce64889a2e125d46 (diff) | |
parent | 777d34ec376ee8706a80d4f1f44fb83397753116 (diff) | |
download | rneovim-f96d99ad1118d79ae5c38bb5e2c4be1280caa3cc.tar.gz rneovim-f96d99ad1118d79ae5c38bb5e2c4be1280caa3cc.tar.bz2 rneovim-f96d99ad1118d79ae5c38bb5e2c4be1280caa3cc.zip |
Merge #8247 'server: introduce --listen'
-rw-r--r-- | man/nvim.1 | 40 | ||||
-rw-r--r-- | runtime/doc/deprecated.txt | 4 | ||||
-rw-r--r-- | runtime/doc/eval.txt | 24 | ||||
-rw-r--r-- | runtime/doc/msgpack_rpc.txt | 5 | ||||
-rw-r--r-- | runtime/doc/starting.txt | 4 | ||||
-rwxr-xr-x | scripts/run-api-tests.exp | 50 | ||||
-rw-r--r-- | src/nvim/eval.c | 5 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 6 | ||||
-rw-r--r-- | src/nvim/globals.h | 1 | ||||
-rw-r--r-- | src/nvim/main.c | 108 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/server.c | 43 | ||||
-rw-r--r-- | test/functional/eval/server_spec.lua | 76 | ||||
-rw-r--r-- | test/functional/helpers.lua | 2 | ||||
-rw-r--r-- | test/helpers.lua | 7 |
14 files changed, 167 insertions, 208 deletions
diff --git a/man/nvim.1 b/man/nvim.1 index d2a3ea5c43..61dbb13748 100644 --- a/man/nvim.1 +++ b/man/nvim.1 @@ -25,7 +25,7 @@ To enter commands in type a colon .Pq Sq \&: which is also used in this manual to denote commands. -For more information, consult the on-line help system with the +For more information, consult the online help system with the .Ic :help command. .Bl -tag -width Fl @@ -329,6 +329,9 @@ Implies .Fl -headless . .It Fl -headless Do not start a user interface. +.Fl -listen . +.It Fl -listen Ar address +Start RPC server on this pipe or TCP socket. .It Fl h , -help Print usage information and exit. .It Fl v , -version @@ -337,12 +340,12 @@ Print version information and exit. .Sh ENVIRONMENT .Bl -tag -width Fl .It Ev VIM -Used to locate various user files, such as the user's init.vim. +Used to locate various user files, such as init.vim. .It Ev VIMRUNTIME -Used to locate run time files, such as on-line documentation and +Used to locate runtime files, such as online documentation and syntax highlighting definitions. .It Ev XDG_CONFIG_HOME -Path to use for the user-local configuration directory, see +Path to the user-local configuration directory, see .Sx FILES . Defaults to .Pa ~/.config @@ -356,7 +359,7 @@ Defaults to .Pa ~/.local/share if not set. .It Ev VIMINIT -A string of Ex commands to be executed at startup. +Ex commands to be executed at startup. For example, the command to quit is .Ic :q , so to have @@ -375,41 +378,32 @@ command. .Sh FILES .Bl -tag -width "~/.config/nvim/init.vim" .It Pa ~/.config/nvim/init.vim -The user-local +User-local .Nm configuration file. -See -.Ev XDG_CONFIG_HOME -above. .It Pa ~/.config/nvim -The user-local +User-local .Nm configuration directory. -See -.Ev XDG_CONFIG_HOME -above. +See also +.Ev XDG_CONFIG_HOME . .It Pa $VIM/sysinit.vim -The system-global +System-global .Nm configuration file. .It Pa /usr/local/share/nvim -The system-global +System-global .Nm runtime directory. .El .Sh AUTHORS -.Nm -was started by -.An Thiago de Arruda , -with a lot of help from others. -.Pp +Nvim was started by +.An Thiago de Arruda . Most of Vim was written by .An -nosplit -.An Bram Moolenaar , -with a lot of help from others. +.An Bram Moolenaar . See .Ic :help credits . -.Pp Vim is based on Stevie, worked on by .An Tim Thompson , .An Tony Andrews , diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index ea61e847c7..03699b3dfb 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -22,6 +22,10 @@ Commands ~ *:wv* *:wviminfo* Deprecated alias to |:wshada| command. +Environment Variables ~ +*$NVIM_LISTEN_ADDRESS* Deprecated in favor of |--listen|. If both are given, + $NVIM_LISTEN_ADDRESS is ignored. + Events ~ *EncodingChanged* Never fired; 'encoding' is always "utf-8". *FileEncoding* Never fired; equivalent to |EncodingChanged|. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 767fc133d8..11c4b62403 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1788,9 +1788,9 @@ v:scrollstart String describing the script or function that caused the hit-enter prompt. *v:servername* *servername-variable* - *$NVIM_LISTEN_ADDRESS* -v:servername Default Nvim server address. Equivalent to - |$NVIM_LISTEN_ADDRESS| on startup. |serverstop()| +v:servername Primary listen-address of the current Nvim instance, the first + item returned by |serverlist()|. Can be set by |--listen| or + |$NVIM_LISTEN_ADDRESS| at startup. |serverstart()| |serverstop()| Read-only. @@ -6638,15 +6638,11 @@ server2client({clientid}, {string}) *server2client()* :echo server2client(expand("<client>"), "HELLO") < serverlist() *serverlist()* - Returns a list of available server names in a list. - When there are no servers an empty string is returned. + Returns a list of server addresses, or empty if all servers + were stopped. |serverstart()| |serverstop()| Example: > :echo serverlist() -< {Nvim} *--serverlist* - The Vim command-line option `--serverlist` was removed from - Nvim, but it can be imitated: > - nvim --cmd "echo serverlist()" --cmd "q" -< + serverstart([{address}]) *serverstart()* Opens a socket or named pipe at {address} and listens for |RPC| messages. Clients can send |API| commands to the address @@ -6674,13 +6670,9 @@ serverstart([{address}]) *serverstart()* < |$NVIM_LISTEN_ADDRESS| is set to {address} if not already set. - *--servername* - The Vim command-line option `--servername` can be imitated: > - nvim --cmd "let g:server_addr = serverstart('foo')" -< serverstop({address}) *serverstop()* - Closes the pipe or socket at {address}. Does nothing if - {address} is empty or invalid. + Closes the pipe or socket at {address}. + Returns TRUE if {address} is valid, else FALSE. If |$NVIM_LISTEN_ADDRESS| is stopped it is unset. If |v:servername| is stopped it is set to the next available address returned by |serverlist()|. diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt index 11fad105b5..01d4e10cea 100644 --- a/runtime/doc/msgpack_rpc.txt +++ b/runtime/doc/msgpack_rpc.txt @@ -70,9 +70,8 @@ An rpc socket is automatically created with each instance. The socket location is stored in |v:servername|. By default this is a named pipe with an automatically generated address. See |XXX|. -To make Nvim listen on a TCP/IP socket instead, set the - |$NVIM_LISTEN_ADDRESS| environment variable before starting Nvim: > - NVIM_LISTEN_ADDRESS=127.0.0.1:6666 nvim +To make Nvim listen on a TCP/IP socket instead, specify |--listen|: > + nvim --listen 127.0.0.1:6666 <Also, more sockets and named pipes can be listened on using |serverstart()|. Note that localhost TCP sockets are generally less secure than named pipes, diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index e9188ba641..991f88f7b6 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -355,6 +355,10 @@ argument. instead. See also |silent-mode|, which does start a (limited) UI. +--listen {addr} *--listen* + Start |RPC| server on socket or TCP address {addr}. Sets the + primary listen address |v:servername| to {addr}. |serverstart()| + ============================================================================== 2. Initialization *initialization* *startup* diff --git a/scripts/run-api-tests.exp b/scripts/run-api-tests.exp deleted file mode 100755 index 27c9c963e5..0000000000 --- a/scripts/run-api-tests.exp +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env expect - -if {$argc < 2} { - puts "Need commands for running the tests and for starting nvim" - exit 1 -} - -set timeout 60 -set run_tests [split [lindex $argv 0] " "] -set run_nvim [split [lindex $argv 1] " "] - -# don't echo to stdout -log_user 0 -# set NVIM_LISTEN_ADDRESS, so nvim will listen on a known socket -set env(NVIM_LISTEN_ADDRESS) "/tmp/nvim-[exec date +%s%N].sock" -# start nvim -spawn {*}$run_nvim -# save the job descriptor -set nvim_id $spawn_id -# Reset function that can be invoked by test runners to put nvim in a cleaner -# state -send { -:echo "read"."y" -} -# wait until nvim is ready -expect "ready" -# run tests -spawn {*}$run_tests -set tests_id $spawn_id -set status 1 -# listen for test output in the background -expect_background { - * { - # show test output to the user - send_user -- $expect_out(buffer) - } - eof { - # collect the exit status code - set spawn_id $tests_id - catch wait result - set status [lindex $result 3] - set spawn_id $nvim_id - # quit nvim - send ":qa!\r" - } -} -# switch back nvim and wait until it exits -set spawn_id $nvim_id -expect eof -exit $status diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7bdfe7c9ee..284185083e 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -14403,8 +14403,11 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; if (argvars[0].vval.v_string) { - server_stop((char *) argvars[0].vval.v_string); + bool rv = server_stop((char *)argvars[0].vval.v_string); + rettv->vval.v_number = (rv ? 1 : 0); } } diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 4b37abab9e..93cb0e50fa 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6975,12 +6975,10 @@ do_exedit ( ex_no_reprint = TRUE; } -/* - * ":gui" and ":gvim" when there is no GUI. - */ +/// ":gui" and ":gvim" when there is no GUI. static void ex_nogui(exarg_T *eap) { - eap->errmsg = e_nogvim; + eap->errmsg = (char_u *)N_("E25: Nvim does not have a built-in GUI"); } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 776f131437..89d93310a6 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1070,7 +1070,6 @@ EXTERN char_u e_nesting[] INIT(= N_("E22: Scripts nested too deep")); EXTERN char_u e_noalt[] INIT(= N_("E23: No alternate file")); EXTERN char_u e_noabbr[] INIT(= N_("E24: No such abbreviation")); EXTERN char_u e_nobang[] INIT(= N_("E477: No ! allowed")); -EXTERN char_u e_nogvim[] INIT(= N_("E25: Nvim does not have a built-in GUI")); EXTERN char_u e_nogroup[] INIT(= N_("E28: No such highlight group name: %s")); EXTERN char_u e_noinstext[] INIT(= N_("E29: No inserted text yet")); EXTERN char_u e_nolastcmd[] INIT(= N_("E30: No previous command line")); diff --git a/src/nvim/main.c b/src/nvim/main.c index 4288d7f9d7..ce9feedd16 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -72,30 +72,30 @@ # include "nvim/os/pty_process_unix.h" #endif -/* Maximum number of commands from + or -c arguments. */ +// Maximum number of commands from + or -c arguments. #define MAX_ARG_CMDS 10 -/* values for "window_layout" */ -#define WIN_HOR 1 /* "-o" horizontally split windows */ -#define WIN_VER 2 /* "-O" vertically split windows */ -#define WIN_TABS 3 /* "-p" windows on tab pages */ +// values for "window_layout" +#define WIN_HOR 1 // "-o" horizontally split windows +#define WIN_VER 2 // "-O" vertically split windows +#define WIN_TABS 3 // "-p" windows on tab pages -/* Struct for various parameters passed between main() and other functions. */ +// Struct for various parameters passed between main() and other functions. typedef struct { int argc; char **argv; char *use_vimrc; // vimrc from -u argument - int n_commands; /* no. of commands from + or -c */ + int n_commands; // no. of commands from + or -c char *commands[MAX_ARG_CMDS]; // commands from + or -c arg - char_u cmds_tofree[MAX_ARG_CMDS]; /* commands that need free() */ - int n_pre_commands; /* no. of commands from --cmd */ + char_u cmds_tofree[MAX_ARG_CMDS]; // commands that need free() + int n_pre_commands; // no. of commands from --cmd char *pre_commands[MAX_ARG_CMDS]; // commands from --cmd argument - int edit_type; /* type of editing to do */ - char_u *tagname; /* tag from -t argument */ - char_u *use_ef; /* 'errorfile' from -q argument */ + int edit_type; // type of editing to do + char_u *tagname; // tag from -t argument + char_u *use_ef; // 'errorfile' from -q argument int want_full_screen; bool input_isatty; // stdin is a terminal @@ -103,13 +103,15 @@ typedef struct { bool err_isatty; // stderr is a terminal int no_swap_file; // "-n" argument used int use_debug_break_level; - int window_count; /* number of windows to use */ - int window_layout; /* 0, WIN_HOR, WIN_VER or WIN_TABS */ + int window_count; // number of windows to use + int window_layout; // 0, WIN_HOR, WIN_VER or WIN_TABS #if !defined(UNIX) - int literal; /* don't expand file names */ + int literal; // don't expand file names #endif - int diff_mode; /* start with 'diff' set */ + int diff_mode; // start with 'diff' set + + char *listen_addr; // --listen {address} } mparm_T; /* Values for edit_type. */ @@ -150,7 +152,6 @@ void event_init(void) signal_init(); // finish mspgack-rpc initialization channel_init(); - server_init(); terminal_init(); } @@ -241,9 +242,8 @@ int main(int argc, char **argv) char_u *cwd = NULL; // current workding dir on startup time_init(); - /* Many variables are in "params" so that we can pass them to invoked - * functions without a lot of arguments. "argc" and "argv" are also - * copied, so that they can be changed. */ + // Many variables are in `params` so that we can pass them around easily. + // `argc` and `argv` are also copied, so that they can be changed. init_params(¶ms, argc, argv); init_startuptime(¶ms); @@ -254,11 +254,10 @@ int main(int argc, char **argv) check_and_set_isatty(¶ms); event_init(); - /* - * Process the command line arguments. File names are put in the global - * argument list "global_alist". - */ + // Process the command line arguments. File names are put in the global + // argument list "global_alist". command_line_scan(¶ms); + server_init(params.listen_addr); if (GARGCOUNT > 0) { fname = get_fname(¶ms, cwd); @@ -819,6 +818,9 @@ static void command_line_scan(mparm_T *parmp) if (!channel_from_stdio(true, CALLBACK_READER_INIT, &err)) { abort(); } + } else if (STRNICMP(argv[0] + argv_idx, "listen", 6) == 0) { + want_argument = true; + argv_idx += 6; } else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0) { #if !defined(UNIX) parmp->literal = TRUE; @@ -864,10 +866,6 @@ static void command_line_scan(mparm_T *parmp) case 'f': /* "-f" GUI: run in foreground. */ break; - case 'g': /* "-g" start GUI */ - main_start_gui(); - break; - case 'F': { // "-F" start in Farsi mode: rl + fkmap set. p_fkmap = true; set_option_value("rl", 1L, NULL, 0); @@ -906,18 +904,8 @@ static void command_line_scan(mparm_T *parmp) parmp->no_swap_file = TRUE; break; - case 'p': /* "-p[N]" open N tab pages */ -#ifdef TARGET_API_MAC_OSX - /* For some reason on MacOS X, an argument like: - -psn_0_10223617 is passed in when invoke from Finder - or with the 'open' command */ - if (argv[0][argv_idx] == 's') { - argv_idx = -1; /* bypass full -psn */ - main_start_gui(); - break; - } -#endif - /* default is 0: open window for each file */ + case 'p': // "-p[N]" open N tab pages + // default is 0: open window for each file parmp->window_count = get_number_arg(argv[0], &argv_idx, 0); parmp->window_layout = WIN_TABS; break; @@ -1030,15 +1018,12 @@ static void command_line_scan(mparm_T *parmp) mainerr(err_opt_unknown, argv[0]); } - /* - * Handle option arguments with argument. - */ + // Handle option arguments with argument. if (want_argument) { - /* - * Check for garbage immediately after the option letter. - */ - if (argv[0][argv_idx] != NUL) + // Check for garbage immediately after the option letter. + if (argv[0][argv_idx] != NUL) { mainerr(err_opt_garbage, argv[0]); + } --argc; if (argc < 1 && c != 'S') /* -S has an optional argument */ @@ -1077,13 +1062,17 @@ static void command_line_scan(mparm_T *parmp) break; case '-': - if (argv[-1][2] == 'c') { - /* "--cmd {command}" execute command */ - if (parmp->n_pre_commands >= MAX_ARG_CMDS) + if (strequal(argv[-1], "--cmd")) { + // "--cmd {command}" execute command + if (parmp->n_pre_commands >= MAX_ARG_CMDS) { mainerr(err_extra_cmd, NULL); + } parmp->pre_commands[parmp->n_pre_commands++] = argv[0]; + } else if (strequal(argv[-1], "--listen")) { + // "--listen {address}" + parmp->listen_addr = argv[0]; } - /* "--startuptime <file>" already handled */ + // "--startuptime <file>" already handled break; case 'q': /* "-q {errorfile}" QuickFix mode */ @@ -1224,11 +1213,10 @@ static void init_params(mparm_T *paramp, int argc, char **argv) paramp->want_full_screen = true; paramp->use_debug_break_level = -1; paramp->window_count = -1; + paramp->listen_addr = NULL; } -/* - * Initialize global startuptime file if "--startuptime" passed as an argument. - */ +/// Initialize global startuptime file if "--startuptime" passed as an argument. static void init_startuptime(mparm_T *paramp) { for (int i = 1; i < paramp->argc; i++) { @@ -1834,17 +1822,6 @@ static void source_startup_scripts(const mparm_T *const parmp) TIME_MSG("sourcing vimrc file(s)"); } -/* - * Setup to start using the GUI. Exit with an error when not available. - */ -static void main_start_gui(void) -{ - mch_errmsg(_(e_nogvim)); - mch_errmsg("\n"); - mch_exit(2); -} - - /// Get an environment variable, and execute it as Ex commands. /// /// @param env environment variable to execute @@ -1968,6 +1945,7 @@ static void usage(void) mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n")); mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n")); mch_msg(_(" --headless Don't start a user interface\n")); + mch_msg(_(" --listen <address> Start RPC server at this address\n")); #if !defined(UNIX) mch_msg(_(" --literal Don't expand wildcards\n")); #endif diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 9bf122f4db..e5d80aea1d 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -32,26 +32,27 @@ static garray_T watchers = GA_EMPTY_INIT_VALUE; #endif /// Initializes the module -bool server_init(void) +bool server_init(const char *listen_addr) { ga_init(&watchers, sizeof(SocketWatcher *), 1); - bool must_free = false; - const char *listen_address = os_getenv(LISTEN_ADDRESS_ENV_VAR); - if (listen_address == NULL) { - must_free = true; - listen_address = server_address_new(); - } + // $NVIM_LISTEN_ADDRESS + const char *env_addr = os_getenv(LISTEN_ADDRESS_ENV_VAR); + int rv = listen_addr == NULL ? 1 : server_start(listen_addr); - if (!listen_address) { - return false; + if (0 != rv) { + rv = env_addr == NULL ? 1 : server_start(env_addr); + if (0 != rv) { + listen_addr = server_address_new(); + if (listen_addr == NULL) { + return false; + } + rv = server_start(listen_addr); + xfree((char *)listen_addr); + } } - bool ok = (server_start(listen_address) == 0); - if (must_free) { - xfree((char *) listen_address); - } - return ok; + return rv == 0; } /// Teardown a single server @@ -120,8 +121,8 @@ bool server_owns_pipe_address(const char *path) /// @param endpoint Address of the server. Either a 'ip:[port]' string or an /// arbitrary identifier (trimmed to 256 bytes) for the Unix /// socket or named pipe. -/// @returns 0 on success, 1 on a regular error, and negative errno -/// on failure to bind or listen. +/// @returns 0: success, 1: validation error, 2: already listening, +/// -errno: failed to bind or listen. int server_start(const char *endpoint) { if (endpoint == NULL || endpoint[0] == '\0') { @@ -145,7 +146,7 @@ int server_start(const char *endpoint) uv_freeaddrinfo(watcher->uv.tcp.addrinfo); } socket_watcher_close(watcher, free_server); - return 1; + return 2; } } @@ -177,7 +178,7 @@ int server_start(const char *endpoint) /// Stops listening on the address specified by `endpoint`. /// /// @param endpoint Address of the server. -void server_stop(char *endpoint) +bool server_stop(char *endpoint) { SocketWatcher *watcher; bool watcher_found = false; @@ -196,8 +197,8 @@ void server_stop(char *endpoint) } if (!watcher_found) { - ELOG("Not listening on %s", addr); - return; + WLOG("Not listening on %s", addr); + return false; } // Unset $NVIM_LISTEN_ADDRESS if it is the stopped address. @@ -219,6 +220,8 @@ void server_stop(char *endpoint) if (STRCMP(addr, get_vim_var_str(VV_SEND_SERVER)) == 0) { set_vservername(&watchers); } + + return true; } /// Returns an allocated array of server addresses. diff --git a/test/functional/eval/server_spec.lua b/test/functional/eval/server_spec.lua index 393616838e..4e4aed864b 100644 --- a/test/functional/eval/server_spec.lua +++ b/test/functional/eval/server_spec.lua @@ -1,31 +1,40 @@ - local helpers = require('test.functional.helpers')(after_each) local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval local command = helpers.command local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths -local os_name = helpers.os_name +local iswin = helpers.iswin +local ok = helpers.ok +local matches = helpers.matches local function clear_serverlist() - for _, server in pairs(funcs.serverlist()) do - funcs.serverstop(server) - end + for _, server in pairs(funcs.serverlist()) do + funcs.serverstop(server) + end end -describe('serverstart(), serverstop()', function() +describe('server', function() before_each(clear) - it('sets $NVIM_LISTEN_ADDRESS on first invocation', function() + it('serverstart() sets $NVIM_LISTEN_ADDRESS on first invocation', function() -- Unset $NVIM_LISTEN_ADDRESS command('let $NVIM_LISTEN_ADDRESS = ""') local s = eval('serverstart()') assert(s ~= nil and s:len() > 0, "serverstart() returned empty") eq(s, eval('$NVIM_LISTEN_ADDRESS')) - command("call serverstop('"..s.."')") + eq(1, eval("serverstop('"..s.."')")) eq('', eval('$NVIM_LISTEN_ADDRESS')) end) - it('sets v:servername _only_ on nvim startup unless all servers are stopped', + it('sets new v:servername if $NVIM_LISTEN_ADDRESS is invalid', function() + clear({env={NVIM_LISTEN_ADDRESS='.'}}) + eq('.', eval('$NVIM_LISTEN_ADDRESS')) + local servers = funcs.serverlist() + eq(1, #servers) + ok(string.len(servers[1]) > 4) -- Like /tmp/nvim…/… or \\.\pipe\… + end) + + it('sets v:servername at startup or if all servers were stopped', function() local initial_server = meths.get_vvar('servername') assert(initial_server ~= nil and initial_server:len() > 0, @@ -38,24 +47,23 @@ describe('serverstart(), serverstop()', function() neq(initial_server, s) -- serverstop() does _not_ modify v:servername... - funcs.serverstop(s) + eq(1, funcs.serverstop(s)) eq(initial_server, meths.get_vvar('servername')) -- ...unless we stop _all_ servers. - funcs.serverstop(funcs.serverlist()[1]) + eq(1, funcs.serverstop(funcs.serverlist()[1])) eq('', meths.get_vvar('servername')) -- v:servername will take the next available server. - local servername = (os_name() == 'windows' - and [[\\.\pipe\Xtest-functional-server-pipe]] - or 'Xtest-functional-server-socket') + local servername = (iswin() and [[\\.\pipe\Xtest-functional-server-pipe]] + or 'Xtest-functional-server-socket') funcs.serverstart(servername) eq(servername, meths.get_vvar('servername')) end) - it('serverstop() ignores invalid input', function() - command("call serverstop('')") - command("call serverstop('bogus-socket-name')") + it('serverstop() returns false for invalid input', function() + eq(0, eval("serverstop('')")) + eq(0, eval("serverstop('bogus-socket-name')")) end) it('parses endpoints correctly', function() @@ -96,17 +104,13 @@ describe('serverstart(), serverstop()', function() funcs.serverstart('127.0.0.1:65536') -- invalid port eq({}, funcs.serverlist()) end) -end) - -describe('serverlist()', function() - before_each(clear) - it('returns the list of servers', function() + it('serverlist() returns the list of servers', function() -- There should already be at least one server. local n = eval('len(serverlist())') - -- Add a few - local servs = (os_name() == 'windows' + -- Add some servers. + local servs = (iswin() and { [[\\.\pipe\Xtest-pipe0934]], [[\\.\pipe\Xtest-pipe4324]] } or { [[Xtest-pipe0934]], [[Xtest-pipe4324]] }) for _, s in ipairs(servs) do @@ -120,9 +124,31 @@ describe('serverlist()', function() -- The new servers should be at the end of the list. for i = 1, #servs do eq(servs[i], new_servs[i + n]) - command("call serverstop('"..servs[i].."')") + eq(1, eval("serverstop('"..servs[i].."')")) end -- After serverstop() the servers should NOT be in the list. eq(n, eval('len(serverlist())')) end) end) + +describe('startup --listen', function() + it('validates', function() + clear() + + local cmd = { unpack(helpers.nvim_argv) } + table.insert(cmd, '--listen') + matches('nvim.*: Argument missing after: "%-%-listen"', funcs.system(cmd)) + + cmd = { unpack(helpers.nvim_argv) } + table.insert(cmd, '--listen2') + matches('nvim.*: Garbage after option argument: "%-%-listen2"', funcs.system(cmd)) + end) + + it('sets v:servername, overrides $NVIM_LISTEN_ADDRESS', function() + local addr = (iswin() and [[\\.\pipe\Xtest-listen-pipe]] + or 'Xtest-listen-pipe') + clear({ env={ NVIM_LISTEN_ADDRESS='Xtest-env-pipe' }, + args={ '--listen', addr } }) + eq(addr, meths.get_vvar('servername')) + end) +end) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index b8d912114d..84ba6b6853 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -16,6 +16,7 @@ local neq = global_helpers.neq local eq = global_helpers.eq local ok = global_helpers.ok local map = global_helpers.map +local matches = global_helpers.matches local filter = global_helpers.filter local dedent = global_helpers.dedent local table_flatten = global_helpers.table_flatten @@ -747,6 +748,7 @@ local module = { insert = insert, iswin = iswin, map = map, + matches = matches, merge_args = merge_args, meth_pcall = meth_pcall, meths = meths, diff --git a/test/helpers.lua b/test/helpers.lua index 7cce6d8c55..0b6a10a29a 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -16,6 +16,12 @@ end local function ok(res) return assert.is_true(res) end +local function matches(pat, actual) + if nil ~= string.match(actual, pat) then + return true + end + error(string.format('Pattern does not match.\nPattern:\n%s\nActual:\n%s', pat, actual)) +end -- initial_path: directory to recurse into -- re: include pattern (string) @@ -572,6 +578,7 @@ return { hasenv = hasenv, intchar2lua = intchar2lua, map = map, + matches = matches, mergedicts_copy = mergedicts_copy, neq = neq, ok = ok, |