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