define_spec.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local eval, command = n.eval, n.command
  4. local eq, run, stop = t.eq, n.run, n.stop
  5. local clear = n.clear
  6. local api = n.api
  7. local function get_prefix(sync)
  8. if sync then
  9. return 'sync'
  10. end
  11. return 'async'
  12. end
  13. local function call(fn, arguments)
  14. command('call ' .. fn .. '(' .. arguments .. ')')
  15. end
  16. local function clear_and_init(init)
  17. return function()
  18. clear()
  19. if init then
  20. init()
  21. end
  22. end
  23. end
  24. local function runx(sync, handler, on_setup)
  25. local function setup_cb(...)
  26. on_setup(...)
  27. -- need to stop on setup callback because there's two session:request
  28. -- calls in `request/testnvim.lua`. The second call will always return
  29. -- after pending notification/request callbacks are processed
  30. stop()
  31. end
  32. local function handler_cb(...)
  33. return handler(...)
  34. end
  35. if sync then
  36. run(handler_cb, nil, setup_cb)
  37. else
  38. run(nil, handler_cb, setup_cb)
  39. end
  40. end
  41. local function command_specs_for(fn, sync, first_arg_factory, init)
  42. local prefix = get_prefix(sync)
  43. describe(prefix .. ' command created by', function()
  44. before_each(clear_and_init(init))
  45. describe(fn, function()
  46. local args
  47. before_each(function()
  48. args = first_arg_factory() .. ', "test-handler", '
  49. if sync then
  50. args = args .. '1'
  51. else
  52. args = args .. '0'
  53. end
  54. args = args .. ', "RpcCommand"'
  55. end)
  56. it('without options', function()
  57. call(fn, args .. ', {}')
  58. local function on_setup()
  59. command('RpcCommand')
  60. end
  61. local function handler(method)
  62. eq('test-handler', method)
  63. return ''
  64. end
  65. runx(sync, handler, on_setup)
  66. end)
  67. it('with nargs', function()
  68. call(fn, args .. ', {"nargs": "*"}')
  69. local function on_setup()
  70. command('RpcCommand arg1 arg2 arg3')
  71. end
  72. local function handler(method, arguments)
  73. eq('test-handler', method)
  74. eq({ 'arg1', 'arg2', 'arg3' }, arguments[1])
  75. return ''
  76. end
  77. runx(sync, handler, on_setup)
  78. end)
  79. it('with nargs/double-quote', function()
  80. call(fn, args .. ', {"nargs": "*"}')
  81. local function on_setup()
  82. command('RpcCommand "arg1" "arg2" "arg3"')
  83. end
  84. local function handler(method, arguments)
  85. eq('test-handler', method)
  86. eq({ '"arg1"', '"arg2"', '"arg3"' }, arguments[1])
  87. return ''
  88. end
  89. runx(sync, handler, on_setup)
  90. end)
  91. it('with range', function()
  92. call(fn, args .. ', {"range": ""}')
  93. local function on_setup()
  94. command('1,1RpcCommand')
  95. end
  96. local function handler(method, arguments)
  97. eq('test-handler', method)
  98. eq({ 1, 1 }, arguments[1])
  99. return ''
  100. end
  101. runx(sync, handler, on_setup)
  102. end)
  103. it('with nargs/range', function()
  104. call(fn, args .. ', {"nargs": "1", "range": ""}')
  105. local function on_setup()
  106. command('1,1RpcCommand arg')
  107. end
  108. local function handler(method, arguments)
  109. eq('test-handler', method)
  110. eq({ 'arg' }, arguments[1])
  111. eq({ 1, 1 }, arguments[2])
  112. return ''
  113. end
  114. runx(sync, handler, on_setup)
  115. end)
  116. it('with nargs/count', function()
  117. call(fn, args .. ', {"nargs": "1", "count": "5"}')
  118. local function on_setup()
  119. command('5RpcCommand arg')
  120. end
  121. local function handler(method, arguments)
  122. eq('test-handler', method)
  123. eq({ 'arg' }, arguments[1])
  124. eq(5, arguments[2])
  125. return ''
  126. end
  127. runx(sync, handler, on_setup)
  128. end)
  129. it('with nargs/count/bang', function()
  130. call(fn, args .. ', {"nargs": "1", "count": "5", "bang": ""}')
  131. local function on_setup()
  132. command('5RpcCommand! arg')
  133. end
  134. local function handler(method, arguments)
  135. eq('test-handler', method)
  136. eq({ 'arg' }, arguments[1])
  137. eq(5, arguments[2])
  138. eq(1, arguments[3])
  139. return ''
  140. end
  141. runx(sync, handler, on_setup)
  142. end)
  143. it('with nargs/count/bang/register', function()
  144. call(fn, args .. ', {"nargs": "1", "count": "5", "bang": "",' .. ' "register": ""}')
  145. local function on_setup()
  146. command('5RpcCommand! b arg')
  147. end
  148. local function handler(method, arguments)
  149. eq('test-handler', method)
  150. eq({ 'arg' }, arguments[1])
  151. eq(5, arguments[2])
  152. eq(1, arguments[3])
  153. eq('b', arguments[4])
  154. return ''
  155. end
  156. runx(sync, handler, on_setup)
  157. end)
  158. it('with nargs/count/bang/register/eval', function()
  159. call(
  160. fn,
  161. args
  162. .. ', {"nargs": "1", "count": "5", "bang": "",'
  163. .. ' "register": "", "eval": "@<reg>"}'
  164. )
  165. local function on_setup()
  166. command('let @b = "regb"')
  167. command('5RpcCommand! b arg')
  168. end
  169. local function handler(method, arguments)
  170. eq('test-handler', method)
  171. eq({ 'arg' }, arguments[1])
  172. eq(5, arguments[2])
  173. eq(1, arguments[3])
  174. eq('b', arguments[4])
  175. eq('regb', arguments[5])
  176. return ''
  177. end
  178. runx(sync, handler, on_setup)
  179. end)
  180. end)
  181. end)
  182. end
  183. local function autocmd_specs_for(fn, sync, first_arg_factory, init)
  184. local prefix = get_prefix(sync)
  185. describe(prefix .. ' autocmd created by', function()
  186. before_each(clear_and_init(init))
  187. describe(fn, function()
  188. local args
  189. before_each(function()
  190. args = first_arg_factory() .. ', "test-handler", '
  191. if sync then
  192. args = args .. '1'
  193. else
  194. args = args .. '0'
  195. end
  196. args = args .. ', "BufEnter"'
  197. end)
  198. it('without options', function()
  199. call(fn, args .. ', {}')
  200. local function on_setup()
  201. command('doautocmd BufEnter x.c')
  202. end
  203. local function handler(method)
  204. eq('test-handler', method)
  205. return ''
  206. end
  207. runx(sync, handler, on_setup)
  208. end)
  209. it('with eval', function()
  210. call(fn, args .. [[, {'eval': 'expand("<afile>")'}]])
  211. local function on_setup()
  212. command('doautocmd BufEnter x.c')
  213. end
  214. local function handler(method, arguments)
  215. eq('test-handler', method)
  216. eq('x.c', arguments[1])
  217. return ''
  218. end
  219. runx(sync, handler, on_setup)
  220. end)
  221. end)
  222. end)
  223. end
  224. local function function_specs_for(fn, sync, first_arg_factory, init)
  225. local prefix = get_prefix(sync)
  226. describe(prefix .. ' function created by', function()
  227. before_each(clear_and_init(init))
  228. describe(fn, function()
  229. local args
  230. before_each(function()
  231. args = first_arg_factory() .. ', "test-handler", '
  232. if sync then
  233. args = args .. '1'
  234. else
  235. args = args .. '0'
  236. end
  237. args = args .. ', "TestFunction"'
  238. end)
  239. it('without options', function()
  240. call(fn, args .. ', {}')
  241. local function on_setup()
  242. if sync then
  243. eq('rv', eval('TestFunction(1, "a", ["b", "c"])'))
  244. else
  245. eq(1, eval('TestFunction(1, "a", ["b", "c"])'))
  246. end
  247. end
  248. local function handler(method, arguments)
  249. eq('test-handler', method)
  250. eq({ { 1, 'a', { 'b', 'c' } } }, arguments)
  251. return 'rv'
  252. end
  253. runx(sync, handler, on_setup)
  254. end)
  255. it('with eval', function()
  256. call(fn, args .. [[, {'eval': '2 + 2'}]])
  257. local function on_setup()
  258. if sync then
  259. eq('rv', eval('TestFunction(1, "a", ["b", "c"])'))
  260. else
  261. eq(1, eval('TestFunction(1, "a", ["b", "c"])'))
  262. end
  263. end
  264. local function handler(method, arguments)
  265. eq('test-handler', method)
  266. eq({ { 1, 'a', { 'b', 'c' } }, 4 }, arguments)
  267. return 'rv'
  268. end
  269. runx(sync, handler, on_setup)
  270. end)
  271. it('with range', function()
  272. n.insert([[
  273. foo
  274. bar
  275. baz
  276. zub]])
  277. call(fn, args .. [[, {'range': ''}]])
  278. local function on_setup()
  279. command('2,3call TestFunction(1, "a", ["b", "c"])')
  280. end
  281. local function handler(method, arguments)
  282. eq('test-handler', method)
  283. eq({ { 1, 'a', { 'b', 'c' } }, { 2, 3 } }, arguments)
  284. return 'rv'
  285. end
  286. runx(sync, handler, on_setup)
  287. end)
  288. it('with eval/range', function()
  289. call(fn, args .. [[, {'eval': '4', 'range': ''}]])
  290. local function on_setup()
  291. command('%call TestFunction(1, "a", ["b", "c"])')
  292. end
  293. local function handler(method, arguments)
  294. eq('test-handler', method)
  295. eq({ { 1, 'a', { 'b', 'c' } }, { 1, 1 }, 4 }, arguments)
  296. return 'rv'
  297. end
  298. runx(sync, handler, on_setup)
  299. end)
  300. end)
  301. end)
  302. end
  303. local function channel()
  304. return api.nvim_get_chan_info(0).id
  305. end
  306. local function host()
  307. return '"busted"'
  308. end
  309. local function register()
  310. eval('remote#host#Register("busted", "busted", ' .. channel() .. ')')
  311. end
  312. command_specs_for('remote#define#CommandOnChannel', true, channel)
  313. command_specs_for('remote#define#CommandOnChannel', false, channel)
  314. command_specs_for('remote#define#CommandOnHost', true, host, register)
  315. command_specs_for('remote#define#CommandOnHost', false, host, register)
  316. autocmd_specs_for('remote#define#AutocmdOnChannel', true, channel)
  317. autocmd_specs_for('remote#define#AutocmdOnChannel', false, channel)
  318. autocmd_specs_for('remote#define#AutocmdOnHost', true, host, register)
  319. autocmd_specs_for('remote#define#AutocmdOnHost', false, host, register)
  320. function_specs_for('remote#define#FunctionOnChannel', true, channel)
  321. function_specs_for('remote#define#FunctionOnChannel', false, channel)
  322. function_specs_for('remote#define#FunctionOnHost', true, host, register)
  323. function_specs_for('remote#define#FunctionOnHost', false, host, register)