server_notifications_spec.lua 3.5 KB

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