Repository: neovim/neovim
File: test/functional/testnvim.lua (Lua)

Code before:
--- Does not replace the current global session, unlike `clear()`.
---
--- @param keep boolean (default: false) Don't close the current global session.
--- @param ... string Nvim CLI args (or see overload)
--- @return test.Session
--- @overload fun(keep: boolean, opts: test.session.Opts): test.Session
function M.new_session(keep, ...)
  if not keep then
    M.check_close()
  end

  local argv, env, io_extra = M._new_argv(...)

  local proc = ProcStream.spawn(argv, env, io_extra)
  return Session.new(proc)
end

--- Starts a (non-RPC, `--headless --listen "Tx"`) Nvim process, waits for exit, and returns result.
---
--- @param ... string Nvim CLI args, or `test.session.Opts` table.
--- @return test.ProcStream
--- @overload fun(opts: test.session.Opts): test.ProcStream
function M.spawn_wait(...)
  local opts = type(...) == 'string' and { args = { ... } } or ...
  opts.args_rm = opts.args_rm and opts.args_rm or {}
  table.insert(opts.args_rm, '--embed')
  local argv, env, io_extra = M._new_argv(opts)
  local proc = ProcStream.spawn(argv, env, io_extra)
  proc.collect_text = true
  proc:read_start()
  proc:wait()
  proc:close()
  return proc
end

--- @class test.session.Opts
--- Nvim CLI args
--- @field args? string[]
--- Remove these args from the default `nvim_argv` args set. Ignored if `merge=false`.
--- @field args_rm? string[]
--- (default: true) Merge `args` with the default set. Else use only the provided `args`.
--- @field merge? boolean
--- Environment variables
--- @field env? table<string,string>
--- Used for stdin_fd, see `:help ui-option`
--- @field io_extra? uv.uv_pipe_t

--- @private
---
--- Builds an argument list for use in `new_session()`, `clear()`, and `spawn_wait()`.
---

Review comment (suggestion):
```suggestion
  -- Multiple sessions may belong to the same test.
  new_session.data = { test_id = test_id }
```

Code after:
    -- Don't block for the previous session's exit if it's from a different test.
    session:close(nil, session.data and session.data.test_id ~= test_id)
    session = nil
  end

  local argv, env, io_extra = M._new_argv(...)

  local proc = ProcStream.spawn(argv, env, io_extra, function(closed)
    n_processes = n_processes - 1
    local delta = 0
    if closed then
      uv.update_time() -- Update cached value of uv.now() (libuv: uv_now()).
      delta = uv.now() - closed
    end
    if delta > 500 then
      print(
        ('Nvim session %s took %d milliseconds to exit\n'):format(test_id, delta)
          .. 'This indicates a likely problem with the test even if it passed!\n'
      )
      io.stdout:flush()
    end
  end)
  n_processes = n_processes + 1

  local new_session = Session.new(proc)
  new_session.data = { test_id = test_id }
  return new_session
end

busted.subscribe({ 'suite', 'end' }, function()
  M.check_close(true)
  while n_processes > 0 do
    uv.run('once')
  end
end)

--- Starts a (non-RPC, `--headless --listen "Tx"`) Nvim process, waits for exit, and returns result.
---
--- @param ... string Nvim CLI args, or `test.session.Opts` table.
--- @return test.ProcStream
--- @overload fun(opts: test.session.Opts): test.ProcStream
function M.spawn_wait(...)
  local opts = type(...) == 'string' and { args = { ... } } or ...
  opts.args_rm = opts.args_rm and opts.args_rm or {}
  table.insert(opts.args_rm, '--embed')
  local argv, env, io_extra = M._new_argv(opts)
  local proc = ProcStream.spawn(argv, env, io_extra)
  proc.collect_text = true
  proc:read_start()
  proc:wait()
  proc:close()