test_timers.vim 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. " Test for timers
  2. source check.vim
  3. CheckFeature timers
  4. source screendump.vim
  5. source shared.vim
  6. source term_util.vim
  7. source load.vim
  8. func SetUp()
  9. call timer_stopall()
  10. endfunc
  11. func MyHandler(timer)
  12. let g:val += 1
  13. endfunc
  14. func MyHandlerWithLists(lists, timer)
  15. let x = string(a:lists)
  16. endfunc
  17. func Test_timer_oneshot()
  18. let g:test_is_flaky = 1
  19. let g:val = 0
  20. let timer = timer_start(50, 'MyHandler')
  21. let slept = WaitFor('g:val == 1')
  22. call assert_equal(1, g:val)
  23. if has('reltime')
  24. call assert_inrange(40, LoadAdjust(120), slept)
  25. else
  26. call assert_inrange(20, 120, slept)
  27. endif
  28. endfunc
  29. func Test_timer_repeat_three()
  30. let g:test_is_flaky = 1
  31. let g:val = 0
  32. let timer = timer_start(50, 'MyHandler', {'repeat': 3})
  33. let slept = WaitFor('g:val == 3')
  34. call assert_equal(3, g:val)
  35. if has('reltime')
  36. call assert_inrange(120, LoadAdjust(250), slept)
  37. else
  38. call assert_inrange(80, 200, slept)
  39. endif
  40. endfunc
  41. func Test_timer_repeat_many()
  42. let g:test_is_flaky = 1
  43. let g:val = 0
  44. let timer = timer_start(50, 'MyHandler', {'repeat': -1})
  45. sleep 200m
  46. call timer_stop(timer)
  47. call assert_inrange((has('mac') ? 1 : 2), LoadAdjust(5), g:val)
  48. endfunc
  49. func Test_timer_with_partial_callback()
  50. let g:test_is_flaky = 1
  51. let g:val = 0
  52. let meow = {'one': 1}
  53. function meow.bite(...)
  54. let g:val += self.one
  55. endfunction
  56. call timer_start(50, meow.bite)
  57. let slept = WaitFor('g:val == 1')
  58. call assert_equal(1, g:val)
  59. if has('reltime')
  60. call assert_inrange(40, LoadAdjust(130), slept)
  61. else
  62. call assert_inrange(20, 100, slept)
  63. endif
  64. endfunc
  65. func Test_timer_retain_partial()
  66. call timer_start(50, function('MyHandlerWithLists', [['a']]))
  67. call test_garbagecollect_now()
  68. sleep 100m
  69. endfunc
  70. func Test_timer_info()
  71. let id = timer_start(1000, 'MyHandler')
  72. let info = id->timer_info()
  73. call assert_equal(id, info[0]['id'])
  74. call assert_equal(1000, info[0]['time'])
  75. call assert_equal("function('MyHandler')", string(info[0]['callback']))
  76. let found = 0
  77. for info in timer_info()
  78. if info['id'] == id
  79. let found += 1
  80. endif
  81. endfor
  82. call assert_equal(1, found)
  83. call timer_stop(id)
  84. call assert_equal([], timer_info(id))
  85. call assert_fails('call timer_info("abc")', 'E1210:')
  86. " check repeat count inside the callback
  87. let g:timer_repeat = []
  88. let tid = timer_start(10, {tid -> execute("call add(g:timer_repeat, timer_info(tid)[0].repeat)")}, #{repeat: 3})
  89. call WaitForAssert({-> assert_equal([2, 1, 0], g:timer_repeat)})
  90. unlet g:timer_repeat
  91. endfunc
  92. func Test_timer_stopall()
  93. let id1 = timer_start(1000, 'MyHandler')
  94. let id2 = timer_start(2000, 'MyHandler')
  95. let info = timer_info()
  96. call assert_equal(2, len(info))
  97. call timer_stopall()
  98. let info = timer_info()
  99. call assert_equal(0, len(info))
  100. endfunc
  101. func Test_timer_paused()
  102. let g:test_is_flaky = 1
  103. let g:val = 0
  104. let id = timer_start(50, 'MyHandler')
  105. let info = timer_info(id)
  106. call assert_equal(0, info[0]['paused'])
  107. eval id->timer_pause(1)
  108. let info = timer_info(id)
  109. call assert_equal(1, info[0]['paused'])
  110. sleep 200m
  111. call assert_equal(0, g:val)
  112. call timer_pause(id, 0)
  113. let info = timer_info(id)
  114. call assert_equal(0, info[0]['paused'])
  115. let slept = WaitFor('g:val == 1')
  116. call assert_equal(1, g:val)
  117. if has('reltime')
  118. call assert_inrange(0, LoadAdjust(140), slept)
  119. else
  120. call assert_inrange(0, 10, slept)
  121. endif
  122. call assert_fails('call timer_pause("abc", 1)', 'E39:')
  123. endfunc
  124. func StopMyself(timer)
  125. let g:called += 1
  126. if g:called == 2
  127. call timer_stop(a:timer)
  128. endif
  129. endfunc
  130. func Test_timer_delete_myself()
  131. let g:called = 0
  132. let t = timer_start(10, 'StopMyself', {'repeat': -1})
  133. call WaitForAssert({-> assert_equal(2, g:called)})
  134. call assert_equal(2, g:called)
  135. call assert_equal([], timer_info(t))
  136. endfunc
  137. func StopTimer1(timer)
  138. let g:timer2 = 10->timer_start('StopTimer2')
  139. " avoid maxfuncdepth error
  140. call timer_pause(g:timer1, 1)
  141. sleep 20m
  142. endfunc
  143. func StopTimer2(timer)
  144. call timer_stop(g:timer1)
  145. endfunc
  146. func Test_timer_stop_in_callback()
  147. let g:test_is_flaky = 1
  148. call assert_equal(0, len(timer_info()))
  149. let g:timer1 = timer_start(10, 'StopTimer1')
  150. let slept = 0
  151. for i in range(10)
  152. if len(timer_info()) == 0
  153. break
  154. endif
  155. sleep 10m
  156. let slept += 10
  157. endfor
  158. " This should take only 30 msec, but on Mac it's often longer
  159. call assert_inrange(0, 50, slept)
  160. endfunc
  161. func StopTimerAll(timer)
  162. call timer_stopall()
  163. endfunc
  164. func Test_timer_stop_all_in_callback()
  165. let g:test_is_flaky = 1
  166. call assert_equal(0, len(timer_info()))
  167. call timer_start(10, 'StopTimerAll')
  168. call assert_equal(1, len(timer_info()))
  169. let slept = 0
  170. for i in range(10)
  171. if len(timer_info()) == 0
  172. break
  173. endif
  174. sleep 10m
  175. let slept += 10
  176. endfor
  177. call assert_inrange(0, 30, slept)
  178. endfunc
  179. func FeedkeysCb(timer)
  180. call feedkeys("hello\<CR>", 'nt')
  181. endfunc
  182. func InputCb(timer)
  183. call timer_start(10, 'FeedkeysCb')
  184. let g:val = input('?')
  185. call Resume()
  186. endfunc
  187. func Test_timer_input_in_timer()
  188. let g:val = ''
  189. call timer_start(10, 'InputCb')
  190. call Standby(1000)
  191. call assert_equal('hello', g:val)
  192. endfunc
  193. func FuncWithError(timer)
  194. let g:call_count += 1
  195. if g:call_count == 4
  196. return
  197. endif
  198. doesnotexist
  199. endfunc
  200. func Test_timer_errors()
  201. let g:call_count = 0
  202. let timer = timer_start(10, 'FuncWithError', {'repeat': -1})
  203. " Timer will be stopped after failing 3 out of 3 times.
  204. call WaitForAssert({-> assert_equal(3, g:call_count)})
  205. sleep 50m
  206. call assert_equal(3, g:call_count)
  207. call assert_fails('call timer_start(100, "MyHandler", "abc")', 'E1206:')
  208. call assert_fails('call timer_start(100, [])', 'E921:')
  209. call assert_fails('call timer_stop("abc")', 'E1210:')
  210. endfunc
  211. func FuncWithCaughtError(timer)
  212. let g:call_count += 1
  213. try
  214. doesnotexist
  215. catch
  216. " nop
  217. endtry
  218. endfunc
  219. func Test_timer_catch_error()
  220. let g:call_count = 0
  221. let timer = timer_start(10, 'FuncWithCaughtError', {'repeat': 4})
  222. " Timer will not be stopped.
  223. call WaitForAssert({-> assert_equal(4, g:call_count)})
  224. sleep 50m
  225. call assert_equal(4, g:call_count)
  226. endfunc
  227. func FeedAndPeek(timer)
  228. " call test_feedinput('a')
  229. call nvim_input('a')
  230. call getchar(1)
  231. endfunc
  232. func Interrupt(timer)
  233. " eval "\<C-C>"->test_feedinput()
  234. call nvim_input("\<C-C>")
  235. endfunc
  236. func Test_timer_peek_and_get_char()
  237. if !has('unix') && !has('gui_running')
  238. throw 'Skipped: cannot feed low-level input'
  239. endif
  240. call timer_start(0, 'FeedAndPeek')
  241. let intr = timer_start(100, 'Interrupt')
  242. let c = getchar()
  243. call assert_equal(char2nr('a'), c)
  244. eval intr->timer_stop()
  245. endfunc
  246. func Test_timer_getchar_zero()
  247. if has('win32') && !has('gui_running')
  248. throw 'Skipped: cannot feed low-level input'
  249. endif
  250. CheckFunction reltimefloat
  251. " Measure the elapsed time to avoid a hang when it fails.
  252. let start = reltime()
  253. let id = timer_start(20, {-> feedkeys('x', 'L')})
  254. let c = 0
  255. while c == 0 && reltimefloat(reltime(start)) < 0.2
  256. let c = getchar(0)
  257. sleep 10m
  258. endwhile
  259. call assert_equal('x', nr2char(c))
  260. call timer_stop(id)
  261. endfunc
  262. func Test_timer_ex_mode()
  263. " Function with an empty line.
  264. func Foo(...)
  265. endfunc
  266. let timer = timer_start(40, function('g:Foo'), {'repeat':-1})
  267. " This used to throw error E749.
  268. exe "normal Qsleep 100m\rvi\r"
  269. call timer_stop(timer)
  270. endfunc
  271. func Test_timer_restore_count()
  272. CheckRunVimInTerminal
  273. " Check that v:count is saved and restored, not changed by a timer.
  274. call writefile([
  275. \ 'nnoremap <expr><silent> L v:count ? v:count . "l" : "l"',
  276. \ 'func Doit(id)',
  277. \ ' normal 3j',
  278. \ 'endfunc',
  279. \ 'call timer_start(100, "Doit")',
  280. \ ], 'Xtrcscript')
  281. call writefile([
  282. \ '1-1234',
  283. \ '2-1234',
  284. \ '3-1234',
  285. \ ], 'Xtrctext')
  286. let buf = RunVimInTerminal('-S Xtrcscript Xtrctext', {})
  287. " Wait for the timer to move the cursor to the third line.
  288. call WaitForAssert({-> assert_equal(3, term_getcursor(buf)[0])})
  289. call assert_equal(1, term_getcursor(buf)[1])
  290. " Now check that v:count has not been set to 3
  291. call term_sendkeys(buf, 'L')
  292. call WaitForAssert({-> assert_equal(2, term_getcursor(buf)[1])})
  293. call StopVimInTerminal(buf)
  294. call delete('Xtrcscript')
  295. call delete('Xtrctext')
  296. endfunc
  297. " Test that the garbage collector isn't triggered if a timer callback invokes
  298. " vgetc().
  299. func Test_nocatch_timer_garbage_collect()
  300. " FIXME: why does this fail only on MacOS M1?
  301. try
  302. CheckNotMacM1
  303. throw 'Skipped: Nvim does not support test_garbagecollect_soon(), test_override()'
  304. catch /Skipped/
  305. let g:skipped_reason = v:exception
  306. return
  307. endtry
  308. " 'uptimetime. must be bigger than the timer timeout
  309. set ut=200
  310. call test_garbagecollect_soon()
  311. call test_override('no_wait_return', 0)
  312. func CauseAnError(id)
  313. " This will show an error and wait for Enter.
  314. let a = {'foo', 'bar'}
  315. endfunc
  316. func FeedChar(id)
  317. call feedkeys(":\<CR>", 't')
  318. endfunc
  319. call timer_start(300, 'FeedChar')
  320. call timer_start(100, 'CauseAnError')
  321. let x = getchar() " wait for error in timer
  322. let x = getchar(0) " read any remaining chars
  323. let x = getchar(0)
  324. set ut&
  325. call test_override('no_wait_return', 1)
  326. delfunc CauseAnError
  327. delfunc FeedChar
  328. endfunc
  329. func Test_timer_error_in_timer_callback()
  330. if !has('terminal') || (has('win32') && has('gui_running'))
  331. throw 'Skipped: cannot run Vim in a terminal window'
  332. endif
  333. let lines =<< trim [CODE]
  334. func Func(timer)
  335. " fail to create list
  336. let x = [
  337. endfunc
  338. set updatetime=50
  339. call timer_start(1, 'Func')
  340. [CODE]
  341. call writefile(lines, 'Xtest.vim')
  342. let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
  343. let job = term_getjob(buf)
  344. call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
  345. " GC must not run during timer callback, which can make Vim crash.
  346. call TermWait(buf, 50)
  347. call term_sendkeys(buf, "\<CR>")
  348. call TermWait(buf, 50)
  349. call assert_equal('run', job_status(job))
  350. call term_sendkeys(buf, ":qall!\<CR>")
  351. call WaitFor({-> job_status(job) ==# 'dead'})
  352. if has('unix')
  353. call assert_equal('', job_info(job).termsig)
  354. endif
  355. call delete('Xtest.vim')
  356. exe buf .. 'bwipe!'
  357. endfunc
  358. " Test for garbage collection when a timer is still running
  359. func Test_timer_garbage_collect()
  360. let timer = timer_start(1000, function('MyHandler'), {'repeat' : 10})
  361. call test_garbagecollect_now()
  362. let l = timer_info(timer)
  363. call assert_equal(function('MyHandler'), l[0].callback)
  364. call timer_stop(timer)
  365. endfunc
  366. func Test_timer_invalid_callback()
  367. call assert_fails('call timer_start(0, "0")', 'E921')
  368. endfunc
  369. func Test_timer_changing_function_list()
  370. CheckRunVimInTerminal
  371. " Create a large number of functions. Should get the "more" prompt.
  372. " The typing "G" triggers the timer, which changes the function table.
  373. let lines =<< trim END
  374. for func in map(range(1,99), "'Func' .. v:val")
  375. exe "func " .. func .. "()"
  376. endfunc
  377. endfor
  378. au CmdlineLeave : call timer_start(0, {-> 0})
  379. END
  380. call writefile(lines, 'XTest_timerchange')
  381. let buf = RunVimInTerminal('-S XTest_timerchange', #{rows: 10})
  382. call term_sendkeys(buf, ":fu\<CR>")
  383. call WaitForAssert({-> assert_match('-- More --', term_getline(buf, 10))})
  384. call term_sendkeys(buf, "G")
  385. call WaitForAssert({-> assert_match('E454', term_getline(buf, 9))})
  386. call term_sendkeys(buf, "\<Esc>")
  387. call StopVimInTerminal(buf)
  388. call delete('XTest_timerchange')
  389. endfunc
  390. func Test_timer_using_win_execute_undo_sync()
  391. let bufnr1 = bufnr()
  392. new
  393. let g:bufnr2 = bufnr()
  394. let g:winid = win_getid()
  395. exe "buffer " .. bufnr1
  396. wincmd w
  397. call setline(1, ['test'])
  398. autocmd InsertEnter * call timer_start(100, { -> win_execute(g:winid, 'buffer ' .. g:bufnr2) })
  399. call timer_start(200, { -> feedkeys("\<CR>bbbb\<Esc>") })
  400. call feedkeys("Oaaaa", 'x!t')
  401. " will hang here until the second timer fires
  402. call assert_equal(['aaaa', 'bbbb', 'test'], getline(1, '$'))
  403. undo
  404. call assert_equal(['test'], getline(1, '$'))
  405. bwipe!
  406. bwipe!
  407. unlet g:winid
  408. unlet g:bufnr2
  409. au! InsertEnter
  410. endfunc
  411. " vim: shiftwidth=2 sts=2 expandtab