diff options
-rw-r--r-- | runtime/doc/builtin.txt | 41 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 3 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 2 | ||||
-rw-r--r-- | src/nvim/event/process.c | 2 | ||||
-rw-r--r-- | src/nvim/log.c | 47 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/server.c | 71 | ||||
-rw-r--r-- | src/nvim/os/os.h | 3 | ||||
-rw-r--r-- | src/nvim/os/pty_process_unix.c | 9 | ||||
-rw-r--r-- | src/nvim/path.c | 7 | ||||
-rw-r--r-- | test/README.md | 45 | ||||
-rw-r--r-- | test/busted/outputHandlers/nvim.lua | 34 | ||||
-rw-r--r-- | test/functional/api/keymap_spec.lua | 4 | ||||
-rw-r--r-- | test/functional/core/log_spec.lua | 57 | ||||
-rw-r--r-- | test/functional/core/startup_spec.lua | 6 | ||||
-rw-r--r-- | test/functional/helpers.lua | 22 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 140 | ||||
-rw-r--r-- | test/functional/preload.lua | 28 | ||||
-rw-r--r-- | test/functional/terminal/api_spec.lua | 4 | ||||
-rw-r--r-- | test/functional/vimscript/let_spec.lua | 26 | ||||
-rw-r--r-- | test/functional/vimscript/server_spec.lua | 20 | ||||
-rw-r--r-- | test/helpers.lua | 60 |
21 files changed, 372 insertions, 259 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 57b45f33c1..0b32b3a420 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -6628,30 +6628,29 @@ serverlist() *serverlist()* serverstart([{address}]) *serverstart()* Opens a socket or named pipe at {address} and listens for - |RPC| messages. Clients can send |API| commands to the address - to control Nvim. - - Returns the address string. - - If {address} does not contain a colon ":" it is interpreted as - a named pipe or Unix domain socket path. - - Example: > + |RPC| messages. Clients can send |API| commands to the + returned address to control Nvim. + + Returns the address string (may differ from the requested + {address}). + + - If {address} contains a colon ":" it is interpreted as + a TCP/IPv4/IPv6 address where the last ":" separates host + and port (empty or zero assigns a random port). + - Else it is interpreted as a named pipe or Unix domain socket + path. If there are no slashes it is treated as a name and + appended to a generated path. + - If {address} is empty it generates a path. + + Example named pipe: > if has('win32') - call serverstart('\\.\pipe\nvim-pipe-1234') + echo serverstart('\\.\pipe\nvim-pipe-1234') else - call serverstart('nvim.sock') + echo serverstart('nvim.sock') endif < - If {address} contains a colon ":" it is interpreted as a TCP - address where the last ":" separates the host and port. - Assigns a random port if it is empty or 0. Supports IPv4/IPv6. - - Example: > - :call serverstart('::1:12345') -< - If no address is given, it is equivalent to: > - :call serverstart(tempname()) + Example TCP/IP address: > + echo serverstart('::1:12345') serverstop({address}) *serverstop()* Closes the pipe or socket at {address}. @@ -7545,7 +7544,7 @@ stdpath({what}) *stdpath()* *E6100* data_dirs List Other data directories. log String Logs directory (for use by plugins too). state String Session state directory: storage for file - drafts, undo history, shada, etc. + drafts, undo, shada, named pipes, ... Example: > :echo stdpath("config") diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 77b4900f4f..a60a069fae 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1790,8 +1790,9 @@ Dictionary nvim__stats(void) { Dictionary rv = ARRAY_DICT_INIT; PUT(rv, "fsync", INTEGER_OBJ(g_stats.fsync)); - PUT(rv, "redraw", INTEGER_OBJ(g_stats.redraw)); + PUT(rv, "log_skip", INTEGER_OBJ(g_stats.log_skip)); PUT(rv, "lua_refcount", INTEGER_OBJ(nlua_get_global_ref_count())); + PUT(rv, "redraw", INTEGER_OBJ(g_stats.redraw)); return rv; } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 25f80758d2..2225076a0a 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8497,7 +8497,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) address = xstrdup(tv_get_string(argvars)); } } else { - address = server_address_new(); + address = server_address_new(NULL); } int result = server_start(address); diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 653fffae1c..1ec11f1eb6 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -120,7 +120,7 @@ int process_spawn(Process *proc, bool in, bool out, bool err) proc->internal_close_cb = decref; proc->refcount++; kl_push(WatcherPtr, proc->loop->children, proc); - DLOG("new: pid=%d argv=[%s]", proc->pid, *proc->argv); + DLOG("new: pid=%d argv=[%s]", proc->pid, proc->argv[0]); return 0; } diff --git a/src/nvim/log.c b/src/nvim/log.c index 6ff1aab9a0..d2c7782e5d 100644 --- a/src/nvim/log.c +++ b/src/nvim/log.c @@ -16,15 +16,15 @@ #include <uv.h> #include "auto/config.h" +#include "nvim/eval.h" #include "nvim/log.h" #include "nvim/main.h" #include "nvim/message.h" #include "nvim/os/os.h" #include "nvim/os/time.h" +#include "nvim/path.h" #include "nvim/types.h" -#define LOG_FILE_ENV "NVIM_LOG_FILE" - /// Cached location of the expanded log file path decided by log_path_init(). static char log_file_path[MAXPATHL + 1] = { 0 }; @@ -52,7 +52,7 @@ static bool log_try_create(char *fname) return true; } -/// Initializes path to log file. Sets $NVIM_LOG_FILE if empty. +/// Initializes the log file path and sets $NVIM_LOG_FILE if empty. /// /// Tries $NVIM_LOG_FILE, or falls back to $XDG_STATE_HOME/nvim/log. Failed /// initialization indicates either a bug in expand_env() or both $NVIM_LOG_FILE @@ -60,9 +60,8 @@ static bool log_try_create(char *fname) static void log_path_init(void) { size_t size = sizeof(log_file_path); - expand_env((char_u *)"$" LOG_FILE_ENV, (char_u *)log_file_path, - (int)size - 1); - if (strequal("$" LOG_FILE_ENV, log_file_path) + expand_env((char_u *)"$" ENV_LOGFILE, (char_u *)log_file_path, (int)size - 1); + if (strequal("$" ENV_LOGFILE, log_file_path) || log_file_path[0] == '\0' || os_isdir((char_u *)log_file_path) || !log_try_create(log_file_path)) { @@ -87,7 +86,7 @@ static void log_path_init(void) log_file_path[0] = '\0'; return; } - os_setenv(LOG_FILE_ENV, log_file_path, true); + os_setenv(ENV_LOGFILE, log_file_path, true); if (log_dir_failure) { WLOG("Failed to create directory %s for writing logs: %s", failed_dir, os_strerror(log_dir_failure)); @@ -209,7 +208,7 @@ FILE *open_log_file(void) // - Directory does not exist // - File is not writable do_log_to_file(stderr, LOGLVL_ERR, NULL, __func__, __LINE__, true, - "failed to open $" LOG_FILE_ENV " (%s): %s", + "failed to open $" ENV_LOGFILE " (%s): %s", strerror(errno), log_file_path); return stderr; } @@ -277,6 +276,9 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, const char *context, va_list args) FUNC_ATTR_PRINTF(7, 0) { + // Name of the Nvim instance that produced the log. + static char name[16] = { 0 }; + static const char *log_levels[] = { [LOGLVL_DBG] = "DBG", [LOGLVL_INF] = "INF", @@ -291,8 +293,7 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, const char *context, return false; } char date_time[20]; - if (strftime(date_time, sizeof(date_time), "%Y-%m-%dT%H:%M:%S", - &local_time) == 0) { + if (strftime(date_time, sizeof(date_time), "%Y-%m-%dT%H:%M:%S", &local_time) == 0) { return false; } @@ -302,14 +303,30 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, const char *context, millis = (int)curtime.tv_usec / 1000; } + // Get a name for this Nvim instance. + // TODO(justinmk): expose this as v:name ? + if (starting || name[0] == '\0') { + // Parent servername. + const char *parent = path_tail(os_getenv(ENV_NVIM)); + // Servername. Empty until starting=false. + const char *serv = path_tail(get_vim_var_str(VV_SEND_SERVER)); + if (parent && parent[0] != NUL) { + snprintf(name, sizeof(name), "%s/c", parent); // "/c" indicates child. + } else if (serv && serv[0] != NUL) { + snprintf(name, sizeof(name), "%s", serv ? serv : ""); + } else { + int64_t pid = os_get_pid(); + snprintf(name, sizeof(name), "?.%-5" PRId64, pid); + } + } + // Print the log message. - int64_t pid = os_get_pid(); int rv = (line_num == -1 || func_name == NULL) - ? fprintf(log_file, "%s %s.%03d %-5" PRId64 " %s", - log_levels[log_level], date_time, millis, pid, + ? fprintf(log_file, "%s %s.%03d %-10s %s", + log_levels[log_level], date_time, millis, name, (context == NULL ? "?:" : context)) - : fprintf(log_file, "%s %s.%03d %-5" PRId64 " %s%s:%d: ", - log_levels[log_level], date_time, millis, pid, + : fprintf(log_file, "%s %s.%03d %-10s %s%s:%d: ", + log_levels[log_level], date_time, millis, name, (context == NULL ? "" : context), func_name, line_num); if (rv < 0) { diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index f15ce82917..c9e707aa92 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -23,7 +23,6 @@ #define MAX_CONNECTIONS 32 #define ENV_LISTEN "NVIM_LISTEN_ADDRESS" // deprecated -#define ENV_NVIM "NVIM" static garray_T watchers = GA_EMPTY_INIT_VALUE; @@ -43,7 +42,7 @@ bool server_init(const char *listen_addr) int rv = listen_addr ? server_start(listen_addr) : 1; if (0 != rv) { - listen_addr = server_address_new(); + listen_addr = server_address_new(NULL); if (!listen_addr) { return false; } @@ -56,6 +55,11 @@ bool server_init(const char *listen_addr) os_unsetenv(ENV_LISTEN); } + // TODO(justinmk): this is for logging_spec. Can remove this after nvim_log #7062 is merged. + if (os_env_exists("__NVIM_TEST_LOG")) { + ELOG("test log message"); + } + return rv == 0; } @@ -83,23 +87,26 @@ void server_teardown(void) /// Generates unique address for local server. /// -/// In Windows this is a named pipe in the format -/// \\.\pipe\nvim-<PID>-<COUNTER>. -/// -/// For other systems it is a path returned by vim_tempname(). -/// -/// This function is NOT thread safe -char *server_address_new(void) +/// Named pipe format: +/// - Windows: "\\.\pipe\<name>.<pid>.<counter>" +/// - Other: "~/.local/state/nvim/<name>.<pid>.<counter>" +char *server_address_new(const char *name) { -#ifdef WIN32 static uint32_t count = 0; - char template[ADDRESS_MAX_SIZE]; - snprintf(template, ADDRESS_MAX_SIZE, - "\\\\.\\pipe\\nvim-%" PRIu64 "-%" PRIu32, os_get_pid(), count++); - return xstrdup(template); + char fmt[ADDRESS_MAX_SIZE]; +#ifdef WIN32 + int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32, + name ? name : "nvim", os_get_pid(), count++); #else - return (char *)vim_tempname(); + char *dir = get_xdg_home(kXDGStateHome); + int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32, + dir, name ? name : "nvim", os_get_pid(), count++); + xfree(dir); #endif + if ((size_t)r >= sizeof(fmt)) { + ELOG("truncated server address"); + } + return xstrdup(fmt); } /// Check if this instance owns a pipe address. @@ -114,35 +121,35 @@ bool server_owns_pipe_address(const char *path) return false; } -/// Starts listening for API calls. +/// Starts listening for RPC calls. /// -/// The socket type is determined by parsing `endpoint`: If it's a valid IPv4 -/// or IPv6 address in 'ip:[port]' format, then it will be a TCP socket. -/// Otherwise it will be a Unix socket or named pipe (Windows). +/// Socket type is decided by the format of `addr`: +/// - TCP socket if it looks like an IPv4/6 address ("ip:[port]"). +/// - If [port] is omitted, a random one is assigned. +/// - Unix socket (or named pipe on Windows) otherwise. +/// - If the name doesn't contain slashes it is appended to a generated path. #8519 /// -/// If no port is given, a random one will be assigned. -/// -/// @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: success, 1: validation error, 2: already listening, -/// -errno: failed to bind or listen. -int server_start(const char *endpoint) +/// @param addr Server address: a "ip:[port]" string or arbitrary name or filepath (max 256 bytes) +/// for the Unix socket or named pipe. +/// @returns 0: success, 1: validation error, 2: already listening, -errno: failed to bind/listen. +int server_start(const char *addr) { - if (endpoint == NULL || endpoint[0] == '\0') { - WLOG("Empty or NULL endpoint"); + if (addr == NULL || addr[0] == '\0') { + WLOG("Empty or NULL address"); return 1; } + bool isname = !strstr(addr, ":") && !strstr(addr, "/") && !strstr(addr, "\\"); + char *addr_gen = isname ? server_address_new(addr) : NULL; SocketWatcher *watcher = xmalloc(sizeof(SocketWatcher)); - - int result = socket_watcher_init(&main_loop, watcher, endpoint); + int result = socket_watcher_init(&main_loop, watcher, isname ? addr_gen : addr); + xfree(addr_gen); if (result < 0) { xfree(watcher); return result; } - // Check if a watcher for the endpoint already exists + // Check if a watcher for the address already exists. for (int i = 0; i < watchers.ga_len; i++) { if (!strcmp(watcher->addr, ((SocketWatcher **)watchers.ga_data)[i]->addr)) { ELOG("Already listening on %s", watcher->addr); diff --git a/src/nvim/os/os.h b/src/nvim/os/os.h index bff2936f8e..a7496130cc 100644 --- a/src/nvim/os/os.h +++ b/src/nvim/os/os.h @@ -16,4 +16,7 @@ # include "os/users.h.generated.h" #endif +#define ENV_LOGFILE "NVIM_LOG_FILE" +#define ENV_NVIM "NVIM" + #endif // NVIM_OS_OS_H diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index 4a49c0b162..c5d6af0ff6 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -163,10 +163,15 @@ static struct termios termios_default; /// @param tty_fd TTY file descriptor, or -1 if not in a terminal. void pty_process_save_termios(int tty_fd) { - DLOG("tty_fd=%d", tty_fd); - if (tty_fd == -1 || tcgetattr(tty_fd, &termios_default) != 0) { + if (tty_fd == -1) { return; } + int rv = tcgetattr(tty_fd, &termios_default); + if (rv != 0) { + ELOG("tcgetattr failed (tty_fd=%d): %s", tty_fd, strerror(errno)); + } else { + DLOG("tty_fd=%d", tty_fd); + } } /// @returns zero on success, or negative error code diff --git a/src/nvim/path.c b/src/nvim/path.c index 7f47ce083d..9859ca7daa 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -88,7 +88,12 @@ FileComparison path_full_compare(char_u *const s1, char_u *const s2, const bool return kDifferentFiles; } -/// Gets the tail (i.e., the filename segment) of a path `fname`. +/// Gets the tail (filename segment) of path `fname`. +/// +/// Examples: +/// - "dir/file.txt" => "file.txt" +/// - "file.txt" => "file.txt" +/// - "dir/" => "" /// /// @return pointer just past the last path separator (empty string, if fname /// ends in a slash), or empty string if fname is NULL. diff --git a/test/README.md b/test/README.md index cc630cb8bf..a67040e68c 100644 --- a/test/README.md +++ b/test/README.md @@ -91,25 +91,33 @@ or: Debugging tests --------------- +- Each test gets a test id which looks like "T123". This also appears in the + log file. Child processes spawned from a test appear in the logs with the + *parent* name followed by "/c". Example: + ``` + DBG 2022-06-15T18:37:45.226 T57.58016.0 UI: flush + DBG 2022-06-15T18:37:45.226 T57.58016.0 inbuf_poll:442: blocking... events_enabled=0 events_pending=0 + DBG 2022-06-15T18:37:45.227 T57.58016.0/c UI: stop + INF 2022-06-15T18:37:45.227 T57.58016.0/c os_exit:595: Nvim exit: 0 + DBG 2022-06-15T18:37:45.229 T57.58016.0 read_cb:118: closing Stream (0x7fd5d700ea18): EOF (end of file) + INF 2022-06-15T18:37:45.229 T57.58016.0 on_process_exit:400: exited: pid=58017 status=0 stoptime=0 + ``` - You can set `$GDB` to [run tests under gdbserver](https://github.com/neovim/neovim/pull/1527). And if `$VALGRIND` is set it will pass `--vgdb=yes` to valgrind instead of starting gdbserver directly. -- Hanging tests often happen due to unexpected `:h press-enter` prompts. The +- Hanging tests can happen due to unexpected "press-enter" prompts. The default screen width is 50 columns. Commands that try to print lines longer than 50 columns in the command-line, e.g. `:edit very...long...path`, will - trigger the prompt. In this case, a shorter path or `:silent edit` should be - used. + trigger the prompt. Try using a shorter path, or `:silent edit`. - If you can't figure out what is going on, try to visualize the screen. Put this at the beginning of your test: - - ```lua - local Screen = require('test.functional.ui.screen') - local screen = Screen.new() - screen:attach() - ``` - - Afterwards, put `screen:snapshot_util()` at any position in your test. See the - comment at the top of `test/functional/ui/screen.lua` for more. + ```lua + local Screen = require('test.functional.ui.screen') + local screen = Screen.new() + screen:attach() + ``` + Then put `screen:snapshot_util()` anywhere in your test. See the comments in + `test/functional/ui/screen.lua` for more info. Filtering Tests --------------- @@ -247,12 +255,17 @@ Number; !must be defined to function properly): - `BUSTED_ARGS` (F) (U): arguments forwarded to `busted`. +- `CC` (U) (S): specifies which C compiler to use to preprocess files. + Currently only compilers with gcc-compatible arguments are supported. + - `GDB` (F) (D): makes nvim instances to be run under `gdbserver`. It will be accessible on `localhost:7777`: use `gdb build/bin/nvim`, type `target remote :7777` inside. - `GDBSERVER_PORT` (F) (I): overrides port used for `GDB`. +- `LOG_DIR` (FU) (S!): specifies where to seek for valgrind and ASAN log files. + - `VALGRIND` (F) (D): makes nvim instances to be run under `valgrind`. Log files are named `valgrind-%p.log` in this case. Note that non-empty valgrind log may fail tests. Valgrind arguments may be seen in @@ -269,11 +282,7 @@ Number; !must be defined to function properly): - `NVIM_LUA_NOTRACK` (F) (D): disable reference counting of Lua objects -- `NVIM_PROG`, `NVIM_PRG` (F) (S): override path to Neovim executable (default - to `build/bin/nvim`). - -- `CC` (U) (S): specifies which C compiler to use to preprocess files. - Currently only compilers with gcc-compatible arguments are supported. +- `NVIM_PRG` (F) (S): path to Nvim executable (default: `build/bin/nvim`). - `NVIM_TEST_MAIN_CDEFS` (U) (1): makes `ffi.cdef` run in main process. This raises a possibility of bugs due to conflicts in header definitions, despite @@ -295,8 +304,6 @@ Number; !must be defined to function properly): - `NVIM_TEST_RUN_FAILING_TESTS` (U) (1): makes `itp` run tests which are known to fail (marked by setting third argument to `true`). -- `LOG_DIR` (FU) (S!): specifies where to seek for valgrind and ASAN log files. - - `NVIM_TEST_CORE_*` (FU) (S): a set of environment variables which specify where to search for core files. Are supposed to be defined all at once. diff --git a/test/busted/outputHandlers/nvim.lua b/test/busted/outputHandlers/nvim.lua index 5e9c52e0bd..2ce32c3b7a 100644 --- a/test/busted/outputHandlers/nvim.lua +++ b/test/busted/outputHandlers/nvim.lua @@ -1,4 +1,5 @@ local pretty = require 'pl.pretty' +local global_helpers = require('test.helpers') -- Colors are disabled by default. #15610 local colors = setmetatable({}, {__index = function() return function(s) return s == nil and '' or tostring(s) end end}) @@ -25,35 +26,35 @@ return function(options) local repeatSuiteString = '\nRepeating all tests (run %d of %d) . . .\n\n' local randomizeString = c.note('Note: Randomizing test order with a seed of %d.\n') - local globalSetup = c.sect('[----------]') .. ' Global test environment setup.\n' - local fileStartString = c.sect('[----------]') .. ' Running tests from ' .. c.file('%s') .. '\n' - local runString = c.sect('[ RUN ]') .. ' ' .. c.test('%s') .. ': ' + local globalSetup = c.sect('--------') .. ' Global test environment setup.\n' + local fileStartString = c.sect('--------') .. ' Running tests from ' .. c.file('%s') .. '\n' + local runString = c.sect('RUN ') .. ' ' .. c.test('%s') .. ': ' local successString = c.succ('OK') .. '\n' local skippedString = c.skip('SKIP') .. '\n' local failureString = c.fail('FAIL') .. '\n' local errorString = c.errr('ERR') .. '\n' - local fileEndString = c.sect('[----------]') .. ' '.. c.nmbr('%d') .. ' %s from ' .. c.file('%s') .. ' ' .. c.time('(%.2f ms total)') .. '\n\n' - local globalTeardown = c.sect('[----------]') .. ' Global test environment teardown.\n' - local suiteEndString = c.sect('[==========]') .. ' ' .. c.nmbr('%d') .. ' %s from ' .. c.nmbr('%d') .. ' test %s ran. ' .. c.time('(%.2f ms total)') .. '\n' - local successStatus = c.succ('[ PASSED ]') .. ' ' .. c.nmbr('%d') .. ' %s.\n' + local fileEndString = c.sect('--------') .. ' '.. c.nmbr('%d') .. ' %s from ' .. c.file('%s') .. ' ' .. c.time('(%.2f ms total)') .. '\n\n' + local globalTeardown = c.sect('--------') .. ' Global test environment teardown.\n' + local suiteEndString = c.sect('========') .. ' ' .. c.nmbr('%d') .. ' %s from ' .. c.nmbr('%d') .. ' test %s ran. ' .. c.time('(%.2f ms total)') .. '\n' + local successStatus = c.succ('PASSED ') .. ' ' .. c.nmbr('%d') .. ' %s.\n' local timeString = c.time('%.2f ms') local summaryStrings = { skipped = { - header = c.skip('[ SKIPPED ]') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n', - test = c.skip('[ SKIPPED ]') .. ' %s\n', + header = c.skip('SKIPPED ') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n', + test = c.skip('SKIPPED ') .. ' %s\n', footer = ' ' .. c.nmbr('%d') .. ' SKIPPED %s\n', }, failure = { - header = c.fail('[ FAILED ]') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n', - test = c.fail('[ FAILED ]') .. ' %s\n', + header = c.fail('FAILED ') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n', + test = c.fail('FAILED ') .. ' %s\n', footer = ' ' .. c.nmbr('%d') .. ' FAILED %s\n', }, error = { - header = c.errr('[ ERROR ]') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n', - test = c.errr('[ ERROR ]') .. ' %s\n', + header = c.errr('ERROR ') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n', + test = c.errr('ERROR ') .. ' %s\n', footer = ' ' .. c.nmbr('%d') .. ' %s\n', }, } @@ -193,6 +194,9 @@ return function(options) io.write(globalTeardown) io.write(suiteEndString:format(testCount, tests, fileCount, files, elapsedTime_ms)) io.write(getSummaryString()) + if failureCount > 0 or errorCount > 0 then + io.write(global_helpers.read_nvim_log(nil, true)) + end io.flush() return nil, true @@ -215,7 +219,9 @@ return function(options) end handler.testStart = function(element, _parent) - io.write(runString:format(handler.getFullName(element))) + local testid = _G._nvim_test_id or '' + local desc = ('%s %s'):format(testid, handler.getFullName(element)) + io.write(runString:format(desc)) io.flush() return nil, true diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua index 4bee10a006..6bc6651e04 100644 --- a/test/functional/api/keymap_spec.lua +++ b/test/functional/api/keymap_spec.lua @@ -336,7 +336,7 @@ describe('nvim_get_keymap', function() return GlobalCount ]]) local mapargs = meths.get_keymap('n') - assert.Truthy(type(mapargs[1].callback) == 'number', 'callback is not luaref number') + assert(type(mapargs[1].callback) == 'number', 'callback is not luaref number') mapargs[1].callback = nil eq({ lhs='asdf', @@ -815,7 +815,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function() assert.truthy(string.match(funcs.maparg('asdf', 'n'), "^<Lua function %d+>")) local mapargs = funcs.maparg('asdf', 'n', false, true) - assert.Truthy(type(mapargs.callback) == 'number', 'callback is not luaref number') + assert(type(mapargs.callback) == 'number', 'callback is not luaref number') mapargs.callback = nil eq(generate_mapargs('n', 'asdf', nil, {sid=sid_lua}), mapargs) end) diff --git a/test/functional/core/log_spec.lua b/test/functional/core/log_spec.lua new file mode 100644 index 0000000000..3b1ccd9559 --- /dev/null +++ b/test/functional/core/log_spec.lua @@ -0,0 +1,57 @@ +local helpers = require('test.functional.helpers')(after_each) +local assert_log = helpers.assert_log +local clear = helpers.clear +local command = helpers.command +local eq = helpers.eq +local exec_lua = helpers.exec_lua +local expect_exit = helpers.expect_exit +local request = helpers.request +local retry = helpers.retry + +describe('log', function() + local testlog = 'Xtest_logging' + + after_each(function() + expect_exit(command, 'qa!') + os.remove(testlog) + end) + + it('skipped before log_init', function() + -- This test is for _visibility_: adjust as needed, after checking for regression. + -- + -- During startup some components may try to log before logging is setup. + -- That should be uncommon (ideally never)--and if there are MANY such + -- calls, that needs investigation. + clear() + eq(0, request('nvim__stats').log_skip) + clear{env={CDPATH='~doesnotexist'}} + assert(request('nvim__stats').log_skip <= 13) + end) + + it('messages are formatted with name or test id', function() + -- Examples: + -- ERR 2022-05-29T12:30:03.800 T2 log_init:110: test log message + -- ERR 2022-05-29T12:30:03.814 T2/child log_init:110: test log message + + clear({env={ + NVIM_LOG_FILE=testlog, + -- TODO: remove this after nvim_log #7062 is merged. + __NVIM_TEST_LOG='1' + }}) + + local tid = _G._nvim_test_id + retry(nil, 1000, function() + assert_log(tid..'%.%d+%.%d +server_init:%d+: test log message', testlog, 100) + end) + + exec_lua([[ + local j1 = vim.fn.jobstart({ vim.v.progpath, '-es', '-V1', '+foochild', '+qa!' }, vim.empty_dict()) + vim.fn.jobwait({ j1 }, 10000) + ]]) + + -- Child Nvim spawned by jobstart() appends "/c" to parent name. + retry(nil, 1000, function() + assert_log('%.%d+%.%d/c +server_init:%d+: test log message', testlog, 100) + end) + end) +end) diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index 18d48efadc..919b7b3f9a 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -580,7 +580,7 @@ describe('user config init', function() it('loads default lua config, but shows an error', function() clear{ args_rm={'-u'}, env=xenv } - feed('<cr>') -- confirm "Conflicting config ..." message + feed('<cr><c-c>') -- Dismiss "Conflicting config …" message. eq(1, eval('g:lua_rc')) matches('^E5422: Conflicting configs', meths.exec('messages', true)) end) @@ -632,13 +632,13 @@ describe('runtime:', function() eq(2, eval('g:lua_plugin')) -- Check if plugin_file_path is listed in :scriptname local scripts = meths.exec(':scriptnames', true) - assert.Truthy(scripts:find(plugin_file_path)) + assert(scripts:find(plugin_file_path)) -- Check if plugin_file_path is listed in startup profile local profile_reader = io.open(profiler_file, 'r') local profile_log = profile_reader:read('*a') profile_reader:close() - assert.Truthy(profile_log :find(plugin_file_path)) + assert(profile_log:find(plugin_file_path)) os.remove(profiler_file) rmdir(plugin_path) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index ffb5694c15..d31d337b63 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -431,18 +431,25 @@ end function module.new_argv(...) local args = {unpack(module.nvim_argv)} table.insert(args, '--headless') + if _G._nvim_test_id then + -- Set the server name to the test-id for logging. #8519 + table.insert(args, '--listen') + table.insert(args, _G._nvim_test_id) + end local new_args local io_extra local env = nil local opts = select(1, ...) - if type(opts) == 'table' then + if type(opts) ~= 'table' then + new_args = {...} + else args = remove_args(args, opts.args_rm) if opts.env then - local env_tbl = {} + local env_opt = {} for k, v in pairs(opts.env) do assert(type(k) == 'string') assert(type(v) == 'string') - env_tbl[k] = v + env_opt[k] = v end for _, k in ipairs({ 'HOME', @@ -458,19 +465,18 @@ function module.new_argv(...) 'TMPDIR', 'VIMRUNTIME', }) do - if not env_tbl[k] then - env_tbl[k] = os.getenv(k) + -- Set these from the environment unless the caller defined them. + if not env_opt[k] then + env_opt[k] = os.getenv(k) end end env = {} - for k, v in pairs(env_tbl) do + for k, v in pairs(env_opt) do env[#env + 1] = k .. '=' .. v end end new_args = opts.args or {} io_extra = opts.io_extra - else - new_args = {...} end for _, arg in ipairs(new_args) do table.insert(args, arg) diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 22e2354723..6db969693e 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -266,8 +266,8 @@ describe('LSP', function() end; -- If the program timed out, then code will be nil. on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; -- Note that NIL must be used here. -- on_handler(err, method, result, client_id) @@ -288,8 +288,8 @@ describe('LSP', function() client.stop() end; on_exit = function(code, signal) - eq(101, code, "exit code", fake_lsp_logfile) -- See fake-lsp-server.lua - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(101, code, "exit code") -- See fake-lsp-server.lua + eq(0, signal, "exit signal") assert_log(pesc([[assert_eq failed: left == "\"shutdown\"", right == "\"test\""]]), fake_lsp_logfile) end; @@ -335,8 +335,8 @@ describe('LSP', function() client.stop() end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(...) eq(table.remove(expected_handlers), {...}, "expected handler") @@ -367,8 +367,8 @@ describe('LSP', function() client.notify('finish') end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") @@ -436,8 +436,8 @@ describe('LSP', function() client = _client end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") @@ -496,8 +496,8 @@ describe('LSP', function() eq(false, client.server_capabilities().codeLensProvider) end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(...) eq(table.remove(expected_handlers), {...}, "expected handler") @@ -517,8 +517,8 @@ describe('LSP', function() client = c end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") @@ -547,8 +547,8 @@ describe('LSP', function() client = c end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") @@ -596,8 +596,8 @@ describe('LSP', function() eq(true, client.supports_method("unknown-method")) end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(...) eq(table.remove(expected_handlers), {...}, "expected handler") @@ -626,8 +626,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(...) eq(table.remove(expected_handlers), {...}, "expected handler") @@ -651,8 +651,8 @@ describe('LSP', function() exec_lua("vim.lsp.buf.type_definition()") end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(...) eq(table.remove(expected_handlers), {...}, "expected handler") @@ -672,8 +672,8 @@ describe('LSP', function() client = _client end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") eq(0, #expected_handlers, "did not call expected handler") end; on_handler = function(err, _, ctx) @@ -696,8 +696,8 @@ describe('LSP', function() client = _client end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") eq(0, #expected_handlers, "did not call expected handler") end; on_handler = function(err, _, ctx) @@ -726,8 +726,8 @@ describe('LSP', function() client.notify("release") end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") eq(0, #expected_handlers, "did not call expected handler") end; on_handler = function(err, _, ctx) @@ -759,8 +759,8 @@ describe('LSP', function() client.notify("release") end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") eq(0, #expected_handlers, "did not call expected handler") end; on_handler = function(err, _, ctx) @@ -793,8 +793,8 @@ describe('LSP', function() client.notify("release") end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") eq(0, #expected_handlers, "did not call expected handler") end; on_handler = function(err, _, ctx) @@ -828,8 +828,8 @@ describe('LSP', function() client.notify("release") end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") eq(0, #expected_handlers, "did not call expected handler") eq(3, eval('g:requests')) end; @@ -874,8 +874,8 @@ describe('LSP', function() client.notify('finish') end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") @@ -917,8 +917,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) if ctx.method == 'start' then @@ -960,8 +960,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) if ctx.method == 'start' then @@ -1003,8 +1003,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) if ctx.method == 'start' then @@ -1052,8 +1052,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) if ctx.method == 'start' then @@ -1103,8 +1103,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) if ctx.method == 'start' then @@ -1154,8 +1154,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) if ctx.method == 'start' then @@ -1203,8 +1203,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) if ctx.method == 'start' then @@ -1247,8 +1247,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) if ctx.method == 'start' then @@ -1298,8 +1298,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result,ctx) if ctx.method == 'start' then @@ -1340,8 +1340,8 @@ describe('LSP', function() client.stop(true) end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") @@ -1379,8 +1379,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler") @@ -1725,8 +1725,8 @@ describe('LSP', function() end; -- If the program timed out, then code will be nil. on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; -- Note that NIL must be used here. -- on_handler(err, method, result, client_id) @@ -2728,8 +2728,8 @@ describe('LSP', function() ]=]) end; on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end; on_handler = function(err, result, ctx) -- Don't compare & assert params, they're not relevant for the testcase @@ -2768,8 +2768,8 @@ describe('LSP', function() on_setup = function() end, on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end, on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}) @@ -2846,8 +2846,8 @@ describe('LSP', function() on_setup = function() end, on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end, on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}) @@ -2919,8 +2919,8 @@ describe('LSP', function() on_setup = function() end, on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end, on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}) @@ -2985,8 +2985,8 @@ describe('LSP', function() ]=]) end, on_exit = function(code, signal) - eq(0, code, "exit code", fake_lsp_logfile) - eq(0, signal, "exit signal", fake_lsp_logfile) + eq(0, code, "exit code") + eq(0, signal, "exit signal") end, on_handler = function(err, result, ctx) eq(table.remove(expected_handlers), {err, result, ctx}) diff --git a/test/functional/preload.lua b/test/functional/preload.lua index 24a3977e6b..74f03eaecf 100644 --- a/test/functional/preload.lua +++ b/test/functional/preload.lua @@ -1,8 +1,9 @@ --- Modules loaded here will not be cleared and reloaded by Busted. +-- Modules loaded here will NOT be cleared and reloaded by Busted. -- Busted started doing this to help provide more isolation. See issue #62 -- for more information about this. local helpers = require('test.functional.helpers')(nil) local iswin = helpers.iswin +local busted = require("busted") if iswin() then local ffi = require('ffi') @@ -12,3 +13,28 @@ if iswin() then ]] ffi.C._set_fmode(0x8000) end + +local testid = (function() + local id = 0 + return (function() + id = id + 1 + return id + end) +end)() + +-- Global before_each. https://github.com/Olivine-Labs/busted/issues/613 +local function before_each(_element, _parent) + local id = ('T%d'):format(testid()) + _G._nvim_test_id = id + return nil, true +end +busted.subscribe({ 'test', 'start' }, + before_each, + { + -- Ensure our --helper is handled before --output (see busted/runner.lua). + priority = 1, + -- Don't generate a test-id for skipped tests. /shrug + predicate = function (element, _, status) + return not ((element.descriptor == 'pending' or status == 'pending')) + end + }) diff --git a/test/functional/terminal/api_spec.lua b/test/functional/terminal/api_spec.lua index e28cc03597..b3a0b8a2c8 100644 --- a/test/functional/terminal/api_spec.lua +++ b/test/functional/terminal/api_spec.lua @@ -6,7 +6,7 @@ if helpers.pending_win32(pending) then return end describe('api', function() local screen - local socket_name = "Xtest_functional_api.sock" + local socket_name = "./Xtest_functional_api.sock" before_each(function() helpers.clear() @@ -29,7 +29,7 @@ describe('api', function() {4:~ }| {4:~ }| {4:~ }| - ]]..socket_name..[[ | + ]]..socket_name..[[ | {3:-- TERMINAL --} | ]]) diff --git a/test/functional/vimscript/let_spec.lua b/test/functional/vimscript/let_spec.lua index 4ff4090a18..6e93655e32 100644 --- a/test/functional/vimscript/let_spec.lua +++ b/test/functional/vimscript/let_spec.lua @@ -47,33 +47,33 @@ describe(':let', function() end) it("multibyte env var #8398 #9267", function() - command("let $NVIM_TEST = 'AìaB'") - eq('AìaB', eval('$NVIM_TEST')) - command("let $NVIM_TEST = 'AaあB'") - eq('AaあB', eval('$NVIM_TEST')) + command("let $NVIM_TEST_LET = 'AìaB'") + eq('AìaB', eval('$NVIM_TEST_LET')) + command("let $NVIM_TEST_LET = 'AaあB'") + eq('AaあB', eval('$NVIM_TEST_LET')) local mbyte = [[\p* .ม .ม .ม .ม่ .ม่ .ม่ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹֻ ֹֻ ֹֻ .ֹֻ .ֹֻ .ֹֻ ֹֻ ֹֻ ֹֻ .ֹֻ .ֹֻ .ֹֻ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹֻ ֹֻ .ֹֻ .ֹֻ .ֹֻ a a a ca ca ca à à à]] - command("let $NVIM_TEST = '"..mbyte.."'") - eq(mbyte, eval('$NVIM_TEST')) + command("let $NVIM_TEST_LET = '"..mbyte.."'") + eq(mbyte, eval('$NVIM_TEST_LET')) end) it("multibyte env var to child process #8398 #9267", function() - local cmd_get_child_env = "let g:env_from_child = system(['"..nvim_dir.."/printenv-test', 'NVIM_TEST'])" - command("let $NVIM_TEST = 'AìaB'") + local cmd_get_child_env = "let g:env_from_child = system(['"..nvim_dir.."/printenv-test', 'NVIM_TEST_LET'])" + command("let $NVIM_TEST_LET = 'AìaB'") command(cmd_get_child_env) - eq(eval('$NVIM_TEST'), eval('g:env_from_child')) + eq(eval('$NVIM_TEST_LET'), eval('g:env_from_child')) - command("let $NVIM_TEST = 'AaあB'") + command("let $NVIM_TEST_LET = 'AaあB'") command(cmd_get_child_env) - eq(eval('$NVIM_TEST'), eval('g:env_from_child')) + eq(eval('$NVIM_TEST_LET'), eval('g:env_from_child')) local mbyte = [[\p* .ม .ม .ม .ม่ .ม่ .ม่ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹֻ ֹֻ ֹֻ .ֹֻ .ֹֻ .ֹֻ ֹֻ ֹֻ ֹֻ .ֹֻ .ֹֻ .ֹֻ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹֻ ֹֻ .ֹֻ .ֹֻ .ֹֻ a a a ca ca ca à à à]] - command("let $NVIM_TEST = '"..mbyte.."'") + command("let $NVIM_TEST_LET = '"..mbyte.."'") command(cmd_get_child_env) - eq(eval('$NVIM_TEST'), eval('g:env_from_child')) + eq(eval('$NVIM_TEST_LET'), eval('g:env_from_child')) end) it("release of list assigned to l: variable does not trigger assertion #12387, #12430", function() diff --git a/test/functional/vimscript/server_spec.lua b/test/functional/vimscript/server_spec.lua index de64a77b4d..ea07be231d 100644 --- a/test/functional/vimscript/server_spec.lua +++ b/test/functional/vimscript/server_spec.lua @@ -30,7 +30,7 @@ describe('server', function() eq('', eval('$NVIM_LISTEN_ADDRESS')) local servers = funcs.serverlist() eq(1, #servers) - ok(string.len(servers[1]) > 4) -- Like /tmp/nvim…/… or \\.\pipe\… + ok(string.len(servers[1]) > 4) -- "~/.local/state/nvim…/…" or "\\.\pipe\…" end) it('sets v:servername at startup or if all servers were stopped', function() @@ -54,7 +54,7 @@ describe('server', function() -- v:servername and $NVIM take the next available server. local servername = (iswin() and [[\\.\pipe\Xtest-functional-server-pipe]] - or 'Xtest-functional-server-socket') + or './Xtest-functional-server-socket') funcs.serverstart(servername) eq(servername, meths.get_vvar('servername')) -- Not set in the current process, only in children. @@ -66,7 +66,7 @@ describe('server', function() eq(0, eval("serverstop('bogus-socket-name')")) end) - it('parses endpoints correctly', function() + it('parses endpoints', function() clear_serverlist() eq({}, funcs.serverlist()) @@ -101,6 +101,10 @@ describe('server', function() eq(expected, funcs.serverlist()) clear_serverlist() + -- Address without slashes is a "name" which is appended to a generated path. #8519 + matches([[.*[/\\]xtest1%.2%.3%.4[^/\\]*]], funcs.serverstart('xtest1.2.3.4')) + clear_serverlist() + eq('Vim:Failed to start server: invalid argument', pcall_err(funcs.serverstart, '127.0.0.1:65536')) -- invalid port eq({}, funcs.serverlist()) @@ -113,7 +117,7 @@ describe('server', function() -- Add some servers. local servs = (iswin() and { [[\\.\pipe\Xtest-pipe0934]], [[\\.\pipe\Xtest-pipe4324]] } - or { [[Xtest-pipe0934]], [[Xtest-pipe4324]] }) + or { [[./Xtest-pipe0934]], [[./Xtest-pipe4324]] }) for _, s in ipairs(servs) do eq(s, eval("serverstart('"..s.."')")) end @@ -146,9 +150,13 @@ describe('startup --listen', function() 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' }, + or './Xtest-listen-pipe') + clear({ env={ NVIM_LISTEN_ADDRESS='./Xtest-env-pipe' }, args={ '--listen', addr } }) eq(addr, meths.get_vvar('servername')) + + -- Address without slashes is a "name" which is appended to a generated path. #8519 + clear({ args={ '--listen', 'test-name' } }) + matches([[.*[/\\]test%-name[^/\\]*]], meths.get_vvar('servername')) end) end) diff --git a/test/helpers.lua b/test/helpers.lua index 7d2f8f760a..a3482d1b46 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -40,10 +40,6 @@ function module.popen_r(...) return io.popen(module.argss_to_cmd(...), 'r') end -function module.popen_w(...) - return io.popen(module.argss_to_cmd(...), 'w') -end - -- sleeps the test runner (_not_ the nvim instance) function module.sleep(ms) luv.sleep(ms) @@ -55,42 +51,23 @@ local check_logs_useless_lines = { ['See README_MISSING_SYSCALL_OR_IOCTL for guidance']=3, } ---- Invokes `fn` and includes the tail of `logfile` in the error message if it ---- fails. ---- ----@param logfile string Log file, defaults to $NVIM_LOG_FILE or '.nvimlog' ----@param fn string Function to invoke ----@param ... string Function arguments -local function dumplog(logfile, fn, ...) - -- module.validate({ - -- logfile={logfile,'s',true}, - -- fn={fn,'f',false}, - -- }) - local status, rv = pcall(fn, ...) - if status == false then - logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog' - local logtail = module.read_nvim_log(logfile) - error(string.format('%s\n%s', tostring(rv), logtail)) - end -end -function module.eq(expected, actual, context, logfile) - return dumplog(logfile, assert.are.same, expected, actual, context) +function module.eq(expected, actual, context) + return assert.are.same(expected, actual, context) end -function module.neq(expected, actual, context, logfile) - return dumplog(logfile, assert.are_not.same, expected, actual, context) +function module.neq(expected, actual, context) + return assert.are_not.same(expected, actual, context) end -function module.ok(res, msg, logfile) - return dumplog(logfile, assert.is_true, res, msg) +function module.ok(res, msg) + return assert.is_true(res, msg) end --- TODO(bfredl): this should "failure" not "error" (issue with dumplog() ) local function epicfail(state, arguments, _) state.failure_message = arguments[1] return false end assert:register("assertion", "epicfail", epicfail) -function module.fail(msg, logfile) - return dumplog(logfile, assert.epicfail, msg) +function module.fail(msg) + return assert.epicfail(msg) end function module.matches(pat, actual) @@ -104,16 +81,16 @@ end --- ---@param pat string Lua pattern to search for in the log file ---@param logfile string Full path to log file (default=$NVIM_LOG_FILE) -function module.assert_log(pat, logfile) +---@param nrlines number Search up to this many log lines +function module.assert_log(pat, logfile, nrlines) logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog' - local nrlines = 10 + nrlines = nrlines or 10 local lines = module.read_file_list(logfile, -nrlines) or {} for _,line in ipairs(lines) do if line:match(pat) then return end end - local logtail = module.read_nvim_log(logfile) error(string.format('Pattern %q not found in log (last %d lines): %s:\n%s', - pat, nrlines, logfile, logtail)) + pat, nrlines, logfile, ' '..table.concat(lines, '\n '))) end -- Invokes `fn` and returns the error string (with truncated paths), or raises @@ -271,7 +248,7 @@ module.uname = (function() return platform end - if os.getenv("SYSTEM_NAME") then -- From CMAKE_SYSTEM_NAME. + if os.getenv("SYSTEM_NAME") then -- From CMAKE_HOST_SYSTEM_NAME. platform = string.lower(os.getenv("SYSTEM_NAME")) return platform end @@ -409,17 +386,6 @@ function module.check_cores(app, force) end end -function module.which(exe) - local pipe = module.popen_r('which', exe) - local ret = pipe:read('*a') - pipe:close() - if ret == '' then - return nil - else - return ret:sub(1, -2) - end -end - function module.repeated_read_cmd(...) for _ = 1, 10 do local stream = module.popen_r(...) |