server_notifications_spec.lua 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local eq, clear, eval, command, next_msg = t.eq, n.clear, n.eval, n.command, n.next_msg
  4. local api = n.api
  5. local exec_lua = n.exec_lua
  6. local retry = t.retry
  7. local assert_alive = n.assert_alive
  8. local check_close = n.check_close
  9. local testlog = 'Xtest-server-notify-log'
  10. describe('notify', function()
  11. local channel
  12. before_each(function()
  13. clear()
  14. channel = api.nvim_get_chan_info(0).id
  15. end)
  16. after_each(function()
  17. check_close()
  18. os.remove(testlog)
  19. end)
  20. describe('passing a valid channel id', function()
  21. it('sends the notification/args to the corresponding channel', function()
  22. eval('rpcnotify(' .. channel .. ', "test-event", 1, 2, 3)')
  23. eq({ 'notification', 'test-event', { 1, 2, 3 } }, next_msg())
  24. command('au FileType lua call rpcnotify(' .. channel .. ', "lua!")')
  25. command('set filetype=lua')
  26. eq({ 'notification', 'lua!', {} }, next_msg())
  27. end)
  28. end)
  29. describe('channel id 0', function()
  30. it('broadcasts the notification/args to all channels', function()
  31. eval('rpcnotify(0, "event1", 1, 2, 3)')
  32. eval('rpcnotify(0, "event2", 4, 5, 6)')
  33. eval('rpcnotify(0, "event2", 7, 8, 9)')
  34. eq({ 'notification', 'event1', { 1, 2, 3 } }, next_msg())
  35. eq({ 'notification', 'event2', { 4, 5, 6 } }, next_msg())
  36. eq({ 'notification', 'event2', { 7, 8, 9 } }, next_msg())
  37. eval('rpcnotify(0, "event2", 10, 11, 12)')
  38. eval('rpcnotify(0, "event1", 13, 14, 15)')
  39. eq({ 'notification', 'event2', { 10, 11, 12 } }, next_msg())
  40. eq({ 'notification', 'event1', { 13, 14, 15 } }, next_msg())
  41. end)
  42. it('does not crash for deeply nested variable', function()
  43. api.nvim_set_var('l', {})
  44. local nest_level = 1000
  45. command(('call map(range(%u), "extend(g:, {\'l\': [g:l]})")'):format(nest_level - 1))
  46. eval('rpcnotify(' .. channel .. ', "event", g:l)')
  47. local msg = next_msg()
  48. eq('notification', msg[1])
  49. eq('event', msg[2])
  50. local act_ret = msg[3]
  51. local act_nest_level = 0
  52. while act_ret do
  53. if type(act_ret) == 'table' then
  54. local cur_act_ret = nil
  55. for k, v in pairs(act_ret) do
  56. eq(1, k)
  57. cur_act_ret = v
  58. end
  59. if cur_act_ret then
  60. act_nest_level = act_nest_level + 1
  61. end
  62. act_ret = cur_act_ret
  63. else
  64. eq(nil, act_ret)
  65. end
  66. end
  67. eq(nest_level, act_nest_level)
  68. end)
  69. end)
  70. it('cancels stale events on channel close', function()
  71. local catchan = eval("jobstart(['cat'], {'rpc': v:true})")
  72. local catpath = eval('exepath("cat")')
  73. eq(
  74. { id = catchan, argv = { catpath }, stream = 'job', mode = 'rpc', client = {} },
  75. exec_lua(
  76. [[
  77. vim.rpcnotify(..., "nvim_call_function", 'chanclose', {..., 'rpc'})
  78. return vim.api.nvim_get_chan_info(...)
  79. ]],
  80. catchan
  81. )
  82. )
  83. assert_alive()
  84. eq(
  85. { false, 'Invalid channel: ' .. catchan },
  86. exec_lua([[ return {pcall(vim.rpcrequest, ..., 'nvim_eval', '1+1')}]], catchan)
  87. )
  88. retry(nil, 3000, function()
  89. eq({}, api.nvim_get_chan_info(catchan))
  90. end) -- cat be dead :(
  91. end)
  92. end)