Commit Graph
75 Commits
Author SHA1 Message Date
zeertzjq d393abad77 test: fix wrong order of args to eq(), neq() #41499 2026-08-26 07:18:22 -04:00
Justin M. Keyes 6d8c8b18d5 test(harness): migrate away from magic globals
Problem:
The magic globals `it`, `describe`, etc., are more trouble than they are
worth.

- Hooking into `after_each` requires `getfenv()` hacks.
- They confuse luals/emmylua, because the top-level `.luarc.json` isn't
  merged with `test/.luarc.json` (apparently a luals limitation?)
- They totally defeat discoverability because the user just has to
  "know" about the various magic symbols.

So they harm DX, which means they serve no purpose at all.

Solution:
- Expose the test API from `testutil`, so tests can call `t.it()`,
  `t.describe()`, etc., in the conventional way.
- Drop `getfenv()` hacks.
- Drop the `setfenv()` injection in `load_chunk`.
- Drop `test/_meta.lua`.
2026-07-21 13:22:39 +02:00
taoandJustin M. Keyes 4a08596314 fix(path): normalize separators (slashes) #39155
Problem:
Continue separators normalization, and try to keep it at the
nvim <-> external boundary, e.g., `fn.xxx`, `api.xxx`, `:xxx`

Solution:
some key changes
- normalize `$HOME-windows`
- normalize entry points of changing directory
  - `nvim_set_current_dir()`, `chdir()`
- normalize the named pipe
  - `--listen` arg, `--server` arg, `:restart`
  - `serverstart()`, `sockconnect()`, `serverstop()`
- make `expand()` respect 'shellslash' again
- clean up `did_set_shellslash`
- replace `forward_slash` with `TO_SLASH`
- remove obsolete `TMP_PATHSEPSTR`
- remove `slash_adjust` in `do_autocmd_dirchanged`?
- make `fnamemodify()` always return `/` (except when substituting
  separators via `:s`, `:gs` ?)

Note:
- these funcs still apply `slash_adjust` on return, as before:
  `:pwd`, `chdir()`, `exepath()`, `getcwd()`
- these funcs alwarys return `/`, unlike before the normalization PRs
  - `getcompletion()`, `finddir()`, `findfile()`

Also
- clean up code, comments, formatting and tests
- move `TO_SLASH` from `f_chdir` to `changedir_func`
- move `TO_SLASH` from `f_bufadd` to `buflist_new`

Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2026-07-12 13:23:44 -04:00
Lewis Russell 9432e6c1e2 test: run Lua harness with nvim -l
Problem:
The Lua test harness still ran through standalone -ll mode, so tests
depended on the low-level Lua path instead of the regular Nvim Lua
environment. That also meant os.exit() coverage had to carry an ASAN
workaround because Lua's raw process exit skipped Nvim teardown and let
LeakSanitizer interfere with the observed exit code.

Solution:
Run the harness and related fixtures with nvim -l. Patch os.exit() in
the main Lua state to exit through getout(), so scripts observe normal
Nvim shutdown while standalone -ll remains available for generator-style
scripts. As a consequence, the startup test can assert os.exit() without
disabling leak detection.

AI-assisted: Codex
2026-05-13 13:14:07 +01:00
zeertzjq a9454f8511 test(api/server_requests_spec): fix flaky test (#37771)
Sometimes the scheduled :qall can arrive too late, so that EOF isn't
received in the same uv_run() call as the response.
2026-02-08 00:49:13 +00:00
zeertzjq 94144d4678 fix(lua): vim._with() doesn't save boolean options properly (#37354)
Problem:  vim._with() doesn't save boolean options with false values
          properly.
Solution: Use vim.F.if_nil().
2026-01-11 20:04:32 +08:00
zeertzjq 39d8aa0a1a fix(rpc): don't overwrite already received results on error (#37339)
This fixes a regression from cf6f60ce4d
(possibly), as before that commit a frame is popped from the call stack
immediately after its response is received.

Also fix leaking the allocated error messages.
2026-01-11 17:40:32 +08:00
zeertzjq b7adf8081c test(api/server_requests_spec): fix flaky test (again) (#37100) 2025-12-26 01:27:30 +00:00
zeertzjq c924d68021 test(api/server_requests_spec): fix flaky test (again) (#36570)
Use a fast API, as a deferred API request may be aborted by EOF.
2025-11-16 09:47:16 +00:00
zeertzjq 2b83237b0f test(api/server_requests_spec): fix flaky test (#36410)
Wait for the notification to be processed.
2025-10-31 14:06:11 +00:00
zeertzjq accd392f4d Merge pull request #36393 from zeertzjq/rstream-close-cb
fix(channel): closing socket with pending writes leaks memory
2025-10-31 09:14:19 +08:00
Justin M. Keyes fc2dee1736 feat(messages): cleanup Lua error messages
"Error" in error messages is redundant. Just provide the context, don't
say "Error ...".
2025-05-04 11:22:57 -04:00
Justin M. Keyes 64b0e6582a refactor(tests): merge n.spawn/n.spawn_argv into n.new_session #31859
Problem:
- `n.spawn()` is misleading because it also connects RPC, it's not just
  "spawning" a process.
- It's confusing that `n.spawn()` and `n.spawn_argv()` are separate.

Solution:
- Replace `n.spawn()`/`n.spawn_argv()` with a single function `n.new_session()`.
  This name aligns with the existing functions `n.set_session`/`n.get_session`.
    - Note: removes direct handling of `prepend_argv`, but I doubt that was
      important or intentional. If callers want to control use of `prepend_argv`
      then we should add a new flag to `test.session.Opts`.
- Move `keep` to first parameter of `n.new_session()`.
- Add a `merge` flag to `test.session.Opts`
- Mark `_new_argv()` as private. Test should use clear/new_session/spawn_wait
  instead.
2025-01-04 16:48:00 -08:00
dundargoc 052498ed42 test: improve test conventions
Specifically, functions that are run in the context of the test runner
are put in module `test/testutil.lua` while the functions that are run
in the context of the test session are put in
`test/functional/testnvim.lua`.

Closes https://github.com/neovim/neovim/issues/27004.
2024-04-23 18:17:04 +02:00
Lewis Russell 81fc27124b refactor(test): inject after_each differently 2024-04-10 15:53:50 +01:00
dundargoc 7035125b2b test: improve test conventions
Work on https://github.com/neovim/neovim/issues/27004.
2024-04-08 22:51:00 +02:00
bfredlandglacambre 8921d56053 fix(rpc): do not crash when no input is consumed
fixes #23781

Co-authored-by: glacambre <code@lacamb.re>
2024-03-21 15:52:28 +01:00
Justin M. Keyes 0185152802 refactor(tests): get channel id via nvim_get_chan_info #27441
Minor "best practices" nudge.
2024-02-12 05:50:39 -08:00
Lewis Russell 795f896a57 test: rename (meths, funcs) -> (api, fn) 2024-01-12 18:59:14 +00:00
Lewis Russell 4f81f506f9 test: normalise nvim bridge functions
- remove helpers.cur*meths
- remove helpers.nvim
2024-01-12 17:53:27 +00:00
Lewis Russell c30f2e3182 test: typing for helpers.meths 2024-01-12 13:01:06 +00:00
Justin M. Keyes 04f2f864e2 refactor: format test/* 2024-01-03 02:09:29 +01:00
zeertzjq a6cba103ce refactor: move some constants out of vim_defs.h (#26298) 2023-11-29 20:32:40 +08:00
bfredl f8f82901cd fix(tests): fixes for using vim.mpack and more ASAN 2023-02-10 20:19:04 +01:00
zeertzjq ecc40660d1 fix(rpc): ignore redraw events when not in UI client (#21892)
Otherwise it will crash.
2023-02-09 10:53:47 +08:00
dundargoc 5eb5f49488 test: simplify platform detection (#21020)
Extend the capabilities of is_os to detect more platforms such as
freebsd and openbsd. Also remove `iswin()` helper function as it can be
replaced by `is_os("win")`.
2022-11-22 08:13:30 +08:00
dundargoc 736c36c02f test: introduce skip() #21010
This is essentially a convenience wrapper around the `pending()`
function, similar to `skip_fragile()` but more general-purpose.

Also remove `pending_win32` function as it can be replaced by
`skip(iswin())`.
2022-11-13 05:52:19 -08:00
Justin M. Keyes f50135a32e feat: stdpath('run'), /tmp/nvim.user/ #18993
Problem:
- Since c57f6b28d7 #8519, sockets are created in ~/.local/… but XDG
  spec says: "XDG_RUNTIME_DIR: Must be on the local filesystem", which
  implies that XDG_STATE_DIR is potentially non-local.
- Not easy to inspect Nvim-created temp files (for debugging etc).

Solution:
- Store sockets in stdpath('run') ($XDG_RUNTIME_DIR).
- Establish "/tmp/nvim.user/" as the tempdir root shared by all Nvims.
- Make ok() actually useful.
- Introduce assert_nolog().

closes #3517
closes #17093
2022-06-30 04:16:46 -07:00
Dundar Göc f3e6cc1a23 test: remove checks to see if current CI job is travis or appveyor 2022-02-17 22:43:48 +01:00
Shreyansh Chouhan 73d12a8b71 test: fix running functional tests under gdbserver
It was not possible to run the tests under the gdbserver because we were
not closing the old session before starting a new one. This caused the
server to not to be able to bind to the given address and crashing the
tests.

This commit closes the session before starting a new one.

Signed-off-by: Shreyansh Chouhan <chouhan.shreyansh2702@gmail.com>
2021-09-20 18:10:40 +05:30
Justin M. Keyes 6751d6254b refactor(tests): use assert_alive() #15546 2021-09-01 09:42:53 -07:00
Justin M. Keyes 019c8d13dd build/doc/CI: remove/update quickbuild references #11258 2019-10-19 18:04:08 -07:00
Daniel Hahler 4bbad54817 tests: fix non-controversial misuse of pending (#11247)
Ref: https://github.com/neovim/neovim/pull/11184
2019-10-18 04:46:30 +02:00
Daniel Hahler 4df38ec9df server_requests_spec: fix assertion, pass Lua paths via args (#10875)
This makes it pick up the nvim Luarocks module properly when not
installed via third-party.
2019-09-16 19:16:39 +02:00
Justin M. Keyes af946046b9 test: Rename meth_pcall to pcall_err
- Rename `meth_pcall`.
- Make `pcall_err` raise an error if the function does not fail.
- Add `vim.pesc()` to treat a string as literal where a Lua pattern is
  expected.
2019-09-06 17:19:07 -07:00
Justin M. Keyes 540360a775 test: is_os() #10933
- Move os_name() up to "global helpers".
- Rename it to is_os().
- Make it depend on uname() instead of a running Nvim instance.
2019-09-04 06:58:04 -07:00
Daniel HahlerandJustin M. Keyes 47e27a4f5b tests: support msg with global_helpers.ok (#10820)
Ref: https://github.com/neovim/neovim/pull/10768#discussion_r315904175

Co-Authored-By: Justin M. Keyes <justinkz@gmail.com>
2019-08-21 02:32:20 +02:00
Justin M. Keyes 94afc201bc test: isCI(): add "name" parameter 2019-08-05 04:02:41 +02:00
Björn Linse 8ed54bbec3 messages: use proper multiline error message for rpcrequest and API wrappers 2019-05-26 15:42:16 +02:00
Justin M. Keyes 2b87485c22 test: Extend {unit,functional}.helpers with global helpers
Automatically include all "global helper" util functions in the
unit.helpers and functional.helpers and modules.  So tests don't need to
expicitly do:

    local global_helpers = require('test.helpers')
2019-05-18 14:51:01 +02:00
Björn Linse 4da5cb38d3 startup: always wait for UI with --embed, unless --headless also is supplied 2018-09-22 10:18:28 +02:00
Justin M. Keyes 3abf17ae88 API: validation: mention invalid method name (#8489) 2018-06-07 10:56:44 +02:00
Justin M. Keyes 79a0d82755 test: API: fix tests after improved error capture 2018-05-10 04:01:25 +02:00
Justin M. Keyes c9f3174075 API: return non-generic VimL errors
- Return VimL errors instead of generic errors for:
  - nvim_call_function
  - nvim_call_dict_function
- Fix tests which were silently broken before this change.

This violates #6150 where we agreed not to translate API errors.  But
that can be fixed later.
2018-05-09 23:18:38 +02:00
Justin M. Keyes fd4021387e test: rename next_message() to next_msg() 2018-03-11 12:43:42 +01:00
Björn Linse 91b856ccce channels: tests 2017-11-26 09:17:04 +01:00
James McCoy a39c8b7ce3 test: server_spec: Tolerate missing protocol (#7478)
Travis disabled IPv6:

[ RUN      ] serverstart(), serverstop() parses endpoints correctly: FAIL
...build/neovim/neovim/test/functional/eval/server_spec.lua:83: Expected objects to be the same.
Passed in:
(table) {
  [1] = '127.0.0.1:12345' }
Expected:
(table) {
  [1] = '127.0.0.1:12345'
 *[2] = '::1:12345' }

Change all tests to ensure a server was actually started before
expecting it to be returned from serverlist().
2017-11-02 10:45:38 +01:00
Björn Linse 2a3bcd1ff8 rpc: Don't delay notifications when request is pending (#6544)
With the old behavior, if a GUI makes a blocking request that requires user
interaction (like nvim_input()), it would not get any screen updates.

The client, not nvim, should decide how to handle notifications during a
pending request. If an rplugin wants to avoid async calls while a sync call is
busy, it likely wants to avoid processing async calls while another async call
also is handled as well.

This may break the expectation of some existing rplugins. For compatibility,
remote/define.vim reimplements the old behavior. Clients can opt-out by
specifying `sync=urgent`.

- Legacy hosts should be updated to use `sync=urgent`. They could add a flag
  indicating which async methods are always safe to call and which must wait
  until the main loop returns.
- New hosts can expose the full asyncness, they don't need to offer both
  behaviors.

ref #6532
ref #1398 d83868fe90
2017-10-29 03:06:53 +01:00
Justin M. Keyes af993da435 rpc: close channel if stream was closed
f_jobstop()/f_rpcstop() .. process_stop() .. process_close_in(proc)
closes the write-stream of a RPC channel. But there might be
a pending RPC notification on the queue, which may get processed just
before the channel is closed.

To handle that case, check the Stream.closed in
channel.c:receive_msgpack().

Before this change, the above scenario could trigger
this assert(!stream->closed) in wstream_write():

    0x00007f96e1cd3428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
    0x00007f96e1cd502a in __GI_abort () at abort.c:89
    0x00007f96e1ccbbd7 in __assert_fail_base (fmt=<optimized out>, assertion=assertion@entry=0x768f9b "!stream->closed",
    file=file@entry=0x768f70 "../src/nvim/event/wstream.c", line=line@entry=77,
    function=function@entry=0x768fb0 <__PRETTY_FUNCTION__.13735> "wstream_write") at assert.c:92
    0x00007f96e1ccbc82 in __GI___assert_fail (assertion=0x768f9b "!stream->closed", file=0x768f70 "../src/nvim/event/wstream.c", line=77,
    function=0x768fb0 <__PRETTY_FUNCTION__.13735> "wstream_write") at assert.c:101
    0x00000000004d2c1f in wstream_write (stream=0x7f96e0a35078, buffer=0x7f96e09f9b40) at ../src/nvim/event/wstream.c:77
    0x00000000005857b2 in channel_write (channel=0x7f96e0ae5800, buffer=0x7f96e09f9b40) at ../src/nvim/msgpack_rpc/channel.c:551
    0x000000000058567d in on_request_event (argv=0x7ffed792efa0) at ../src/nvim/msgpack_rpc/channel.c:523
    0x00000000005854c8 in handle_request (channel=0x7f96e0ae5800, request=0x7ffed792f1b8) at ../src/nvim/msgpack_rpc/channel.c:503
    0x00000000005850cb in parse_msgpack (channel=0x7f96e0ae5800) at ../src/nvim/msgpack_rpc/channel.c:423
    0x0000000000584f90 in receive_msgpack (stream=0x7f96e0a35218, rbuf=0x7f96e0d1d4c0, c=22, data=0x7f96e0ae5800, eof=false)
    at ../src/nvim/msgpack_rpc/channel.c:389
    0x00000000004d0b20 in read_event (argv=0x7ffed792f4a8) at ../src/nvim/event/rstream.c:190
    0x00000000004ce462 in multiqueue_process_events (this=0x7f96e18172d0) at ../src/nvim/event/multiqueue.c:150
    0x000000000059b630 in nv_event (cap=0x7ffed792f620) at ../src/nvim/normal.c:7908
    0x000000000058be69 in normal_execute (state=0x7ffed792f580, key=-25341) at ../src/nvim/normal.c:1137
    0x0000000000652463 in state_enter (s=0x7ffed792f580) at ../src/nvim/state.c:61
    0x000000000058a1fe in normal_enter (cmdwin=false, noexmode=false) at ../src/nvim/normal.c:467
    0x00000000005500c2 in main (argc=2, argv=0x7ffed792f8d8) at ../src/nvim/main.c:554

Alternative approach suggested by bfredl is to use close_cb of the
process. My unsuccessful attempt is below. (It seems close_cb is queued
too late, which is the similar problem addressed by this commit):

    commit 75fc12c6ab15711bdb7b18c6d42ec9d157f5145e
    Author: Justin M. Keyes <justinkz@gmail.com>
    Date:   Fri Aug 18 01:30:41 2017 +0200

        rpc: use Stream's close_cb instead of explicit check in receive_msgpack()

    diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
    index 8371d3cd482e..e52da23cdc40 100644
    --- a/src/nvim/event/process.c
    +++ b/src/nvim/event/process.c
    @@ -416,6 +416,10 @@ static void on_process_exit(Process *proc)
     static void on_process_stream_close(Stream *stream, void *data)
     {
       Process *proc = data;
    +  ILOG("on_process_stream_close");
    +  if (proc->stream_close_cb != NULL) {
    +    proc->stream_close_cb(stream, proc->stream_close_data);
    +  }
       decref(proc);
     }

    diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h
    index 5c00e8e7ecd5..34a8d54f6f8c 100644
    --- a/src/nvim/event/process.h
    +++ b/src/nvim/event/process.h
    @@ -26,6 +26,11 @@ struct process {
       Stream *in, *out, *err;
       process_exit_cb cb;
       internal_process_cb internal_exit_cb, internal_close_cb;
    +
    +  // Called when any of the process streams (in/out/err) closes.
    +  stream_close_cb stream_close_cb;
    +  void *stream_close_data;
    +
       bool closed, detach;
       MultiQueue *events;
     };
    @@ -50,6 +55,8 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data)
         .closed = false,
         .internal_close_cb = NULL,
         .internal_exit_cb = NULL,
    +    .stream_close_cb = NULL,
    +    .stream_close_data = NULL,
         .detach = false
       };
     }
    diff --git a/src/nvim/event/stream.c b/src/nvim/event/stream.c
    index 7c865bfe1e8c..c8720d1e45d9 100644
    --- a/src/nvim/event/stream.c
    +++ b/src/nvim/event/stream.c
    @@ -95,7 +95,11 @@ void stream_close(Stream *stream, stream_close_cb on_stream_close, void *data)
     void stream_close_handle(Stream *stream)
       FUNC_ATTR_NONNULL_ALL
     {
    +  ILOG("stream=%d", stream);
    +  // LOG_CALLSTACK();
       if (stream->uvstream) {
    +    // problem:  this schedules on the queue, but channel.c:receive_msgpack may
    +    // be processed before close_cb is called by libuv.
         uv_close((uv_handle_t *)stream->uvstream, close_cb);
       } else {
         uv_close((uv_handle_t *)&stream->uv.idle, close_cb);
    @@ -105,6 +109,7 @@ void stream_close_handle(Stream *stream)
     static void close_cb(uv_handle_t *handle)
     {
       Stream *stream = handle->data;
    +  ILOG(">>>>>>>>>>>>>>>>>>>>>>> stream=%p stream->internal_close_cb=%p", stream, stream->internal_close_cb);
       if (stream->buffer) {
         rbuffer_free(stream->buffer);
       }
    diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
    index 782eabe04e4a..dc2b794e366a 100644
    --- a/src/nvim/msgpack_rpc/channel.c
    +++ b/src/nvim/msgpack_rpc/channel.c
    @@ -128,6 +128,8 @@ uint64_t channel_from_process(Process *proc, uint64_t id, char *source)
                                           source);
       incref(channel);  // process channels are only closed by the exit_cb
       channel->data.proc = proc;
    +  channel->data.proc->stream_close_cb = close_cb2;
    +  channel->data.proc->stream_close_data = channel;

       wstream_init(proc->in, 0);
       rstream_init(proc->out, 0);
    @@ -387,17 +389,6 @@ static void receive_msgpack(Stream *stream, RBuffer *rbuf, size_t c,
         goto end;
       }

    -  if ((chan_wstream(channel) != NULL && chan_wstream(channel)->closed)
    -      || (chan_rstream(channel) != NULL && chan_rstream(channel)->closed)) {
    -    char buf[256];
    -    snprintf(buf, sizeof(buf),
    -             "ch %" PRIu64 ": stream closed unexpectedly. "
    -             "closing channel",
    -             channel->id);
    -    call_set_error(channel, buf, WARN_LOG_LEVEL);
    -    goto end;
    -  }
    -
       size_t count = rbuffer_size(rbuf);
       DLOG("ch %" PRIu64 ": parsing %u bytes from msgpack Stream: %p",
            channel->id, count, stream);
    @@ -571,23 +562,6 @@ static Stream *chan_wstream(Channel *chan)
       abort();
     }

    -/// Returns the Stream that a Channel reads from.
    -static Stream *chan_rstream(Channel *chan)
    -{
    -  switch (chan->type) {
    -    case kChannelTypeSocket:
    -      return &chan->data.stream;
    -    case kChannelTypeProc:
    -      return chan->data.proc->out;
    -    case kChannelTypeStdio:
    -      return &chan->data.std.in;
    -    case kChannelTypeInternal:
    -      return NULL;
    -  }
    -  abort();
    -}
    -
    -
     static bool channel_write(Channel *channel, WBuffer *buffer)
     {
       bool success = false;
    @@ -799,6 +773,12 @@ static void close_cb(Stream *stream, void *data)
       decref(data);
     }

    +static void close_cb2(Stream *stream, void *data)
    +{
    +  ILOG("close_cb2");
    +  close_channel(data);
    +}
    +
     /// @param source description of source function, rplugin name, TCP addr, etc
     static Channel *register_channel(ChannelType type, uint64_t id,
                                      MultiQueue *events, char *source)
2017-08-21 01:04:28 +02:00
Justin M. Keyes ca4633bfe4 ci/quickbuild: XXX: disable server_requests test (#6851)
Temporarily disable this test which hangs quickbuild.

From #6905: The hang occurs when calling nvim_set_current_line.

References #6594 5a151555c8
2017-07-02 00:30:00 +02:00