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

Code before:
    local function connect_test(server, mode, address)
      local serverpid = fn.getpid()
      local client = n.new_session(true)
      set_session(client)

      local clientpid = fn.getpid()
      neq(serverpid, clientpid)
      local id = fn.sockconnect(mode, address, { rpc = true })
      ok(id > 0)

      fn.rpcrequest(id, 'nvim_set_current_line', 'hello')
      local client_id = fn.rpcrequest(id, 'nvim_get_chan_info', 0).id

      set_session(server)
      eq(serverpid, fn.getpid())
      eq('hello', api.nvim_get_current_line())

      -- method calls work both ways
      fn.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!')
      eq(id, fn.rpcrequest(client_id, 'nvim_get_chan_info', 0).id)

      set_session(client)
      eq(clientpid, fn.getpid())
      eq('howdy!', api.nvim_get_current_line())

      server:close()
      client:close()
    end

    it('via named pipe', function()
      local server = n.new_session(false)
      set_session(server)
      local address = fn.serverlist()[1]
      local first = string.sub(address, 1, 1)
      ok(first == '/' or first == '\\')
      connect_test(server, 'pipe', address)
    end)

    it('via ipv4 address', function()
      local server = n.new_session(false)
      set_session(server)
      local status, address = pcall(fn.serverstart, '127.0.0.1:')
      if not status then
        pending('no ipv4 stack')
      end
      eq('127.0.0.1:', string.sub(address, 1, 10))
      connect_test(server, 'tcp', address)
    end)

    it('via ipv6 address', function()
      local server = n.new_session(false)

Review comment (bug):
Hi, @zeertzjq, it seems this behavior is unstable in `ubuntu release gcc functionaltest`.
If `EOF` is handled immediately after `nvim_set_current_line `, the latter is ignored due to the channel being closed, which cause this test to fail:
```
DBG 2025-11-16T07:46:01.086 T1.61591.0 receive_msgpack:208: ch 3: parsing 31 bytes from msgpack Stream: 0x55f87e230f70
DBG 2025-11-16T07:46:01.086 T1.61591.0 RPC: <- 3: [notify]    nvim_set_current_line
DBG 2025-11-16T07:46:01.086 T1.61591.0 handle_request:345: RPC: scheduled nvim_set_current_line
DBG 2025-11-16T07:46:01.086 T1.61591.0 read_cb:122: closing Stream (0x55f87e230f70): EOF (end of file)
DBG 2025-11-16T07:46:01.086 T1.61591.0 receive_msgpack:208: ch 3: parsing 0 bytes from msgpack Stream: 0x55f87e230f70
DBG 2025-11-16T07:46:01.086 T1.61591.0 stream_may_close:105: closing Stream: 0x55f87e230f70
INF 2025-11-16T07:46:01.086 T1.61591.0 chan_close_on_err:540: RPC: ch 3 was closed by the peer
DBG 2025-11-16T07:46:01.086 T1.61591.0 state_enter:99: input: K_EVENT
INF 2025-11-16T07:46:01.086 T1.61591.0 request_event:359: handler is nvim_set_current_line, channel->rpc.closed is true
``` 
https://github.com/neovim/neovim/blob/39e27d64ad69ac4a33c1c34915110991405af337/src/nvim/msgpack_rpc/channel.c#L359-L362

Code after:
    local function connect_test(server, mode, address)
      local serverpid = fn.getpid()
      local client = n.new_session(true)
      set_session(client)

      local clientpid = fn.getpid()
      neq(serverpid, clientpid)
      local id = fn.sockconnect(mode, address, { rpc = true })
      ok(id > 0)

      fn.rpcrequest(id, 'nvim_set_current_line', 'hello')
      local client_id = fn.rpcrequest(id, 'nvim_get_chan_info', 0).id

      set_session(server)
      eq(serverpid, fn.getpid())
      eq('hello', api.nvim_get_current_line())

      -- method calls work both ways
      fn.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!')
      eq(id, fn.rpcrequest(client_id, 'nvim_get_chan_info', 0).id)

      set_session(client)
      eq(clientpid, fn.getpid())
      eq('howdy!', api.nvim_get_current_line())

      -- sending notification and then closing channel immediately still works
      n.exec_lua(function()
        vim.rpcnotify(id, 'nvim_set_current_line', 'bye!')
        vim.fn.chanclose(id)
      end)

      set_session(server)
      eq(serverpid, fn.getpid())
      eq('bye!', api.nvim_get_current_line())

      server:close()
      client:close()
    end

    it('via named pipe', function()
      local server = n.new_session(false)
      set_session(server)
      local address = fn.serverlist()[1]
      local first = string.sub(address, 1, 1)
      ok(first == '/' or first == '\\')
      connect_test(server, 'pipe', address)
    end)

    it('via ipv4 address', function()
      local server = n.new_session(false)
      set_session(server)