blob: 78676d211cdd739301399d7bc1008ce88159a636 [file] [log] [blame]
Bram Moolenaar975b5272016-03-15 23:10:59 +01001" Test for timers
2
Bram Moolenaarb46fecd2019-06-15 17:58:09 +02003source check.vim
4CheckFeature timers
Bram Moolenaar975b5272016-03-15 23:10:59 +01005
Bram Moolenaar660b85e2017-09-30 14:26:58 +02006source shared.vim
Bram Moolenaar7a39dd72019-06-23 00:50:15 +02007source term_util.vim
Bram Moolenaar11aa62f2017-09-04 22:56:01 +02008
Bram Moolenaar975b5272016-03-15 23:10:59 +01009func MyHandler(timer)
Bram Moolenaarb73598e2016-08-07 18:22:53 +020010 let g:val += 1
Bram Moolenaar975b5272016-03-15 23:10:59 +010011endfunc
12
Bram Moolenaare3188e22016-05-31 21:13:04 +020013func MyHandlerWithLists(lists, timer)
14 let x = string(a:lists)
15endfunc
16
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +020017func Test_timer_oneshot()
Bram Moolenaarb73598e2016-08-07 18:22:53 +020018 let g:val = 0
Bram Moolenaar975b5272016-03-15 23:10:59 +010019 let timer = timer_start(50, 'MyHandler')
Bram Moolenaarb73598e2016-08-07 18:22:53 +020020 let slept = WaitFor('g:val == 1')
21 call assert_equal(1, g:val)
Bram Moolenaarbc28e9f2019-12-18 20:10:23 +010022 if has('mac')
Bram Moolenaar818fed72019-12-25 15:47:14 +010023 " Mac on Travis can be very slow.
24 let limit = 180
Bram Moolenaarf267f8b2016-08-22 21:40:29 +020025 else
Bram Moolenaarbc28e9f2019-12-18 20:10:23 +010026 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)
Bram Moolenaarf267f8b2016-08-22 21:40:29 +020032 endif
Bram Moolenaar975b5272016-03-15 23:10:59 +010033endfunc
34
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +020035func Test_timer_repeat_three()
Bram Moolenaarb73598e2016-08-07 18:22:53 +020036 let g:val = 0
Bram Moolenaar975b5272016-03-15 23:10:59 +010037 let timer = timer_start(50, 'MyHandler', {'repeat': 3})
Bram Moolenaarb73598e2016-08-07 18:22:53 +020038 let slept = WaitFor('g:val == 3')
39 call assert_equal(3, g:val)
Bram Moolenaarf267f8b2016-08-22 21:40:29 +020040 if has('reltime')
Bram Moolenaarbc28e9f2019-12-18 20:10:23 +010041 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
Bram Moolenaarf267f8b2016-08-22 21:40:29 +020047 else
48 call assert_inrange(80, 200, slept)
49 endif
Bram Moolenaar975b5272016-03-15 23:10:59 +010050endfunc
51
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +020052func Test_timer_repeat_many()
Bram Moolenaarb73598e2016-08-07 18:22:53 +020053 let g:val = 0
Bram Moolenaar975b5272016-03-15 23:10:59 +010054 let timer = timer_start(50, 'MyHandler', {'repeat': -1})
55 sleep 200m
56 call timer_stop(timer)
Bram Moolenaarbc28e9f2019-12-18 20:10:23 +010057 " 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
Bram Moolenaar975b5272016-03-15 23:10:59 +010063endfunc
Bram Moolenaar92e35ef2016-03-26 18:20:41 +010064
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +020065func Test_timer_with_partial_callback()
Bram Moolenaarb73598e2016-08-07 18:22:53 +020066 let g:val = 0
Bram Moolenaar26fe0d52016-09-10 14:27:30 +020067 let meow = {'one': 1}
68 function meow.bite(...)
69 let g:val += self.one
Bram Moolenaar92e35ef2016-03-26 18:20:41 +010070 endfunction
71
Bram Moolenaar26fe0d52016-09-10 14:27:30 +020072 call timer_start(50, meow.bite)
Bram Moolenaarb73598e2016-08-07 18:22:53 +020073 let slept = WaitFor('g:val == 1')
74 call assert_equal(1, g:val)
Bram Moolenaarf267f8b2016-08-22 21:40:29 +020075 if has('reltime')
Bram Moolenaar0426bae2016-08-28 16:06:05 +020076 call assert_inrange(49, 130, slept)
Bram Moolenaarf267f8b2016-08-22 21:40:29 +020077 else
78 call assert_inrange(20, 100, slept)
79 endif
Bram Moolenaar92e35ef2016-03-26 18:20:41 +010080endfunc
Bram Moolenaare3188e22016-05-31 21:13:04 +020081
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +020082func Test_timer_retain_partial()
Bram Moolenaarb73598e2016-08-07 18:22:53 +020083 call timer_start(50, function('MyHandlerWithLists', [['a']]))
Bram Moolenaare3188e22016-05-31 21:13:04 +020084 call test_garbagecollect_now()
Bram Moolenaarb73598e2016-08-07 18:22:53 +020085 sleep 100m
Bram Moolenaare3188e22016-05-31 21:13:04 +020086endfunc
Bram Moolenaarb73598e2016-08-07 18:22:53 +020087
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +020088func Test_timer_info()
Bram Moolenaarb73598e2016-08-07 18:22:53 +020089 let id = timer_start(1000, 'MyHandler')
Bram Moolenaarf92e58c2019-09-08 21:51:41 +020090 let info = id->timer_info()
Bram Moolenaarb73598e2016-08-07 18:22:53 +020091 call assert_equal(id, info[0]['id'])
92 call assert_equal(1000, info[0]['time'])
93 call assert_true(info[0]['remaining'] > 500)
94 call assert_true(info[0]['remaining'] <= 1000)
95 call assert_equal(1, info[0]['repeat'])
96 call assert_equal("function('MyHandler')", string(info[0]['callback']))
97
98 let found = 0
99 for info in timer_info()
100 if info['id'] == id
101 let found += 1
102 endif
103 endfor
104 call assert_equal(1, found)
105
106 call timer_stop(id)
107 call assert_equal([], timer_info(id))
108endfunc
109
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200110func Test_timer_stopall()
Bram Moolenaarb73598e2016-08-07 18:22:53 +0200111 let id1 = timer_start(1000, 'MyHandler')
112 let id2 = timer_start(2000, 'MyHandler')
113 let info = timer_info()
114 call assert_equal(2, len(info))
115
116 call timer_stopall()
117 let info = timer_info()
118 call assert_equal(0, len(info))
119endfunc
120
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200121func Test_timer_paused()
Bram Moolenaarb73598e2016-08-07 18:22:53 +0200122 let g:val = 0
123
124 let id = timer_start(50, 'MyHandler')
125 let info = timer_info(id)
126 call assert_equal(0, info[0]['paused'])
127
Bram Moolenaarf92e58c2019-09-08 21:51:41 +0200128 eval id->timer_pause(1)
Bram Moolenaarb73598e2016-08-07 18:22:53 +0200129 let info = timer_info(id)
130 call assert_equal(1, info[0]['paused'])
131 sleep 100m
132 call assert_equal(0, g:val)
133
134 call timer_pause(id, 0)
135 let info = timer_info(id)
136 call assert_equal(0, info[0]['paused'])
137
138 let slept = WaitFor('g:val == 1')
139 call assert_equal(1, g:val)
Bram Moolenaarf267f8b2016-08-22 21:40:29 +0200140 if has('reltime')
Bram Moolenaara47ebdb2017-12-23 18:41:35 +0100141 if has('mac')
142 " The travis Mac machines appear to be very busy.
Bram Moolenaarbc28e9f2019-12-18 20:10:23 +0100143 call assert_inrange(0, 90, slept)
Bram Moolenaara47ebdb2017-12-23 18:41:35 +0100144 else
145 call assert_inrange(0, 30, slept)
146 endif
Bram Moolenaarf267f8b2016-08-22 21:40:29 +0200147 else
148 call assert_inrange(0, 10, slept)
149 endif
Bram Moolenaarb73598e2016-08-07 18:22:53 +0200150endfunc
151
Bram Moolenaar417ccd72016-09-01 21:26:20 +0200152func StopMyself(timer)
153 let g:called += 1
154 if g:called == 2
155 call timer_stop(a:timer)
156 endif
157endfunc
158
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200159func Test_timer_delete_myself()
Bram Moolenaar417ccd72016-09-01 21:26:20 +0200160 let g:called = 0
161 let t = timer_start(10, 'StopMyself', {'repeat': -1})
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200162 call WaitForAssert({-> assert_equal(2, g:called)})
Bram Moolenaar417ccd72016-09-01 21:26:20 +0200163 call assert_equal(2, g:called)
164 call assert_equal([], timer_info(t))
165endfunc
166
Bram Moolenaar75537a92016-09-05 22:45:28 +0200167func StopTimer1(timer)
Bram Moolenaarf92e58c2019-09-08 21:51:41 +0200168 let g:timer2 = 10->timer_start('StopTimer2')
Bram Moolenaar75537a92016-09-05 22:45:28 +0200169 " avoid maxfuncdepth error
170 call timer_pause(g:timer1, 1)
Bram Moolenaar413c04e2019-08-16 22:29:18 +0200171 sleep 20m
Bram Moolenaar75537a92016-09-05 22:45:28 +0200172endfunc
173
174func StopTimer2(timer)
175 call timer_stop(g:timer1)
176endfunc
177
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200178func Test_timer_stop_in_callback()
Bram Moolenaar427dddf2019-08-16 21:22:41 +0200179 call assert_equal(0, len(timer_info()))
Bram Moolenaar75537a92016-09-05 22:45:28 +0200180 let g:timer1 = timer_start(10, 'StopTimer1')
Bram Moolenaar315244d2019-08-17 13:18:16 +0200181 let slept = 0
182 for i in range(10)
183 if len(timer_info()) == 0
184 break
185 endif
186 sleep 10m
187 let slept += 10
188 endfor
189 " This should take only 30 msec, but on Mac it's often longer
190 call assert_inrange(0, 50, slept)
Bram Moolenaar75537a92016-09-05 22:45:28 +0200191endfunc
192
193func StopTimerAll(timer)
194 call timer_stopall()
195endfunc
196
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200197func Test_timer_stop_all_in_callback()
Bram Moolenaar427dddf2019-08-16 21:22:41 +0200198 call assert_equal(0, len(timer_info()))
199 call timer_start(10, 'StopTimerAll')
200 call assert_equal(1, len(timer_info()))
201 let slept = 0
202 for i in range(10)
203 if len(timer_info()) == 0
204 break
205 endif
206 sleep 10m
207 let slept += 10
208 endfor
209 call assert_inrange(0, 30, slept)
Bram Moolenaar75537a92016-09-05 22:45:28 +0200210endfunc
211
Bram Moolenaar1e8e1452017-06-24 16:03:06 +0200212func FeedkeysCb(timer)
213 call feedkeys("hello\<CR>", 'nt')
214endfunc
215
216func InputCb(timer)
217 call timer_start(10, 'FeedkeysCb')
218 let g:val = input('?')
219 call Resume()
220endfunc
221
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200222func Test_timer_input_in_timer()
Bram Moolenaar1e8e1452017-06-24 16:03:06 +0200223 let g:val = ''
224 call timer_start(10, 'InputCb')
225 call Standby(1000)
226 call assert_equal('hello', g:val)
227endfunc
Bram Moolenaar75537a92016-09-05 22:45:28 +0200228
Bram Moolenaarc577d812017-07-08 22:37:34 +0200229func FuncWithError(timer)
230 let g:call_count += 1
231 if g:call_count == 4
232 return
233 endif
234 doesnotexist
235endfunc
236
237func Test_timer_errors()
238 let g:call_count = 0
239 let timer = timer_start(10, 'FuncWithError', {'repeat': -1})
240 " Timer will be stopped after failing 3 out of 3 times.
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200241 call WaitForAssert({-> assert_equal(3, g:call_count)})
Bram Moolenaarc577d812017-07-08 22:37:34 +0200242 sleep 50m
243 call assert_equal(3, g:call_count)
244endfunc
245
Bram Moolenaare723c422017-09-06 23:40:10 +0200246func FuncWithCaughtError(timer)
247 let g:call_count += 1
248 try
249 doesnotexist
250 catch
251 " nop
252 endtry
253endfunc
254
255func Test_timer_catch_error()
256 let g:call_count = 0
257 let timer = timer_start(10, 'FuncWithCaughtError', {'repeat': 4})
258 " Timer will not be stopped.
Bram Moolenaar0e9d1ae2018-04-30 14:28:24 +0200259 call WaitForAssert({-> assert_equal(4, g:call_count)})
Bram Moolenaare723c422017-09-06 23:40:10 +0200260 sleep 50m
261 call assert_equal(4, g:call_count)
262endfunc
263
Bram Moolenaar5e80de32017-09-03 15:48:12 +0200264func FeedAndPeek(timer)
265 call test_feedinput('a')
266 call getchar(1)
267endfunc
268
269func Interrupt(timer)
Bram Moolenaarce90e362019-09-08 18:58:44 +0200270 eval "\<C-C>"->test_feedinput()
Bram Moolenaar5e80de32017-09-03 15:48:12 +0200271endfunc
272
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200273func Test_timer_peek_and_get_char()
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200274 CheckUnix
275 CheckGui
276
Bram Moolenaar5e80de32017-09-03 15:48:12 +0200277 call timer_start(0, 'FeedAndPeek')
278 let intr = timer_start(100, 'Interrupt')
279 let c = getchar()
280 call assert_equal(char2nr('a'), c)
Bram Moolenaarf92e58c2019-09-08 21:51:41 +0200281 eval intr->timer_stop()
Bram Moolenaar5e80de32017-09-03 15:48:12 +0200282endfunc
Bram Moolenaarc577d812017-07-08 22:37:34 +0200283
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200284func Test_timer_getchar_zero()
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100285 if has('win32') && !has('gui_running')
Bram Moolenaar8c5a2782019-08-07 23:07:07 +0200286 throw 'Skipped: cannot get low-level input'
Bram Moolenaarcb908a82019-01-28 23:20:04 +0100287 endif
288
Bram Moolenaar50948e42019-01-29 20:36:56 +0100289 " Measure the elapsed time to avoid a hang when it fails.
290 let start = reltime()
Bram Moolenaar8d4ce562019-01-30 22:01:40 +0100291 let id = timer_start(20, {-> feedkeys('x', 'L')})
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100292 let c = 0
Bram Moolenaar50948e42019-01-29 20:36:56 +0100293 while c == 0 && reltimefloat(reltime(start)) < 0.2
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100294 let c = getchar(0)
295 sleep 10m
296 endwhile
297 call assert_equal('x', nr2char(c))
Bram Moolenaarcb908a82019-01-28 23:20:04 +0100298 call timer_stop(id)
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100299endfunc
300
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200301func Test_timer_ex_mode()
Bram Moolenaarf5291f32017-09-14 22:55:37 +0200302 " Function with an empty line.
303 func Foo(...)
304
305 endfunc
Bram Moolenaarcb908a82019-01-28 23:20:04 +0100306 let timer = timer_start(40, function('g:Foo'), {'repeat':-1})
Bram Moolenaarf5291f32017-09-14 22:55:37 +0200307 " This used to throw error E749.
308 exe "normal Qsleep 100m\rvi\r"
309 call timer_stop(timer)
310endfunc
311
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200312func Test_timer_restore_count()
Bram Moolenaarb0f42ba2018-05-12 15:38:26 +0200313 if !CanRunVimInTerminal()
Bram Moolenaar5d30ff12019-06-06 16:12:12 +0200314 throw 'Skipped: cannot run Vim in a terminal window'
Bram Moolenaarb0f42ba2018-05-12 15:38:26 +0200315 endif
316 " Check that v:count is saved and restored, not changed by a timer.
317 call writefile([
318 \ 'nnoremap <expr><silent> L v:count ? v:count . "l" : "l"',
319 \ 'func Doit(id)',
320 \ ' normal 3j',
321 \ 'endfunc',
322 \ 'call timer_start(100, "Doit")',
323 \ ], 'Xtrcscript')
324 call writefile([
325 \ '1-1234',
326 \ '2-1234',
327 \ '3-1234',
328 \ ], 'Xtrctext')
329 let buf = RunVimInTerminal('-S Xtrcscript Xtrctext', {})
330
331 " Wait for the timer to move the cursor to the third line.
332 call WaitForAssert({-> assert_equal(3, term_getcursor(buf)[0])})
333 call assert_equal(1, term_getcursor(buf)[1])
334 " Now check that v:count has not been set to 3
335 call term_sendkeys(buf, 'L')
336 call WaitForAssert({-> assert_equal(2, term_getcursor(buf)[1])})
337
338 call StopVimInTerminal(buf)
339 call delete('Xtrcscript')
340 call delete('Xtrctext')
341endfunc
342
Bram Moolenaaradc67142019-06-22 01:40:42 +0200343" Test that the garbage collector isn't triggered if a timer callback invokes
344" vgetc().
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200345func Test_timer_nocatch_garbage_collect()
Bram Moolenaaradc67142019-06-22 01:40:42 +0200346 " 'uptimetime. must be bigger than the timer timeout
347 set ut=200
348 call test_garbagecollect_soon()
349 call test_override('no_wait_return', 0)
350 func CauseAnError(id)
351 " This will show an error and wait for Enter.
352 let a = {'foo', 'bar'}
353 endfunc
354 func FeedChar(id)
355 call feedkeys('x', 't')
356 endfunc
357 call timer_start(300, 'FeedChar')
358 call timer_start(100, 'CauseAnError')
359 let x = getchar()
360
361 set ut&
362 call test_override('no_wait_return', 1)
363 delfunc CauseAnError
364 delfunc FeedChar
365endfunc
366
Bram Moolenaar9a2fddc2019-08-16 11:26:06 +0200367func Test_timer_error_in_timer_callback()
Bram Moolenaar0d702022019-07-04 14:20:41 +0200368 if !has('terminal') || (has('win32') && has('gui_running'))
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200369 throw 'Skipped: cannot run Vim in a terminal window'
370 endif
371
372 let lines =<< trim [CODE]
373 func Func(timer)
374 " fail to create list
375 let x = [
376 endfunc
377 set updatetime=50
378 call timer_start(1, 'Func')
379 [CODE]
380 call writefile(lines, 'Xtest.vim')
381
Bram Moolenaar0d702022019-07-04 14:20:41 +0200382 let buf = term_start(GetVimCommandCleanTerm() .. ' -S Xtest.vim', {'term_rows': 8})
Bram Moolenaar7d491c42019-06-25 06:28:02 +0200383 let job = term_getjob(buf)
384 call WaitForAssert({-> assert_notequal('', term_getline(buf, 8))})
385
386 " GC must not run during timer callback, which can make Vim crash.
387 call term_wait(buf, 100)
388 call term_sendkeys(buf, "\<CR>")
389 call term_wait(buf, 100)
390 call assert_equal('run', job_status(job))
391
392 call term_sendkeys(buf, ":qall!\<CR>")
393 call WaitFor({-> job_status(job) ==# 'dead'})
394 if has('unix')
395 call assert_equal('', job_info(job).termsig)
396 endif
397
398 call delete('Xtest.vim')
399 exe buf .. 'bwipe!'
400endfunc
401
Bram Moolenaar9e4d8212016-08-18 23:04:48 +0200402" vim: shiftwidth=2 sts=2 expandtab