local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local ok, feed, eq, eval = helpers.ok, helpers.feed, helpers.eq, helpers.eval local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run local clear, command, funcs = helpers.clear, helpers.command, helpers.funcs local curbufmeths = helpers.curbufmeths describe('timers', function() before_each(function() clear() source([[ let g:val = 0 func MyHandler(timer) let g:val += 1 endfunc ]]) end) it('works one-shot', function() command("call timer_start(50, 'MyHandler')") eq(0,eval("g:val")) run(nil, nil, nil, 200) eq(1,eval("g:val")) end) it('works one-shot when repeat=0', function() command("call timer_start(50, 'MyHandler', {'repeat': 0})") eq(0,eval("g:val")) run(nil, nil, nil, 200) eq(1,eval("g:val")) end) it('works with repeat two', function() command("call timer_start(50, 'MyHandler', {'repeat': 2})") eq(0,eval("g:val")) run(nil, nil, nil, 300) eq(2,eval("g:val")) end) it('are triggered during sleep', function() command("call timer_start(50, 'MyHandler', {'repeat': 2})") nvim_async("command", "sleep 10") eq(0,eval("g:val")) run(nil, nil, nil, 300) eq(2,eval("g:val")) end) it('works with zero timeout', function() -- timer_start does still not invoke the callback immediately eq(0,eval("[timer_start(0, 'MyHandler', {'repeat': 1000}), g:val][1]")) run(nil, nil, nil, 400) eq(1000,eval("g:val")) end) it('can be started during sleep', function() nvim_async("command", "sleep 10") -- this also tests that remote requests works during sleep eval("timer_start(50, 'MyHandler', {'repeat': 2})") eq(0,eval("g:val")) run(nil, nil, nil, 300) eq(2,eval("g:val")) end) it('are paused when event processing is disabled', function() command("call timer_start(50, 'MyHandler', {'repeat': -1})") run(nil, nil, nil, 100) local count = eval("g:val") -- shows two line error message and thus invokes the return prompt. -- if we start to allow event processing here, we need to change this test. feed(':throw "fatal error"') run(nil, nil, nil, 300) feed("") local diff = eval("g:val") - count ok(0 <= diff and diff <= 4) end) it('are triggered in blocking getchar() call', function() command("call timer_start(50, 'MyHandler', {'repeat': -1})") nvim_async("command", "let g:c = getchar()") run(nil, nil, nil, 300) feed("c") local count = eval("g:val") ok(count >= 4) eq(99, eval("g:c")) end) it('can invoke redraw in blocking getchar() call', function() local screen = Screen.new(40, 6) screen:attach() screen:set_default_attr_ids({ [1] = {bold=true, foreground=Screen.colors.Blue}, }) curbufmeths.set_lines(0, -1, true, {"ITEM 1", "ITEM 2"}) source([[ func! AddItem(timer) call nvim_buf_set_lines(0, 2, 2, v:true, ['ITEM 3']) redraw endfunc call timer_start(200, 'AddItem') ]]) nvim_async("command", "let g:c2 = getchar()") screen:expect([[ ITEM 1 | ITEM 2 | {1:~ }| {1:~ }| {1:~ }| ^ | ]]) screen:sleep(200) screen:expect([[ ITEM 1 | ITEM 2 | ITEM 3 | {1:~ }| {1:~ }| ^ | ]]) feed("3") eq(51, eval("g:c2")) screen:expect([[ ^ITEM 1 | ITEM 2 | ITEM 3 | {1:~ }| {1:~ }| | ]]) end) it('can be stopped', function() local t = eval("timer_start(50, 'MyHandler', {'repeat': -1})") eq(0,eval("g:val")) run(nil, nil, nil, 300) funcs.timer_stop(t) local count = eval("g:val") run(nil, nil, nil, 300) local count2 = eval("g:val") ok(4 <= count and count <= 7) -- when count is eval:ed after timer_stop this should be non-racy eq(count, count2) end) it('can be stopped from the handler', function() source([[ func! MyHandler(timer) let g:val += 1 if g:val == 3 call timer_stop(a:timer) " check double stop is ignored call timer_stop(a:timer) endif endfunc ]]) command("call timer_start(50, 'MyHandler', {'repeat': -1})") eq(0,eval("g:val")) run(nil, nil, nil, 300) eq(3,eval("g:val")) end) it('can have two timers', function() source([[ let g:val2 = 0 func! MyHandler2(timer) let g:val2 += 1 endfunc ]]) command("call timer_start(50, 'MyHandler', {'repeat': 3})") command("call timer_start(100, 'MyHandler2', {'repeat': 2})") run(nil, nil, nil, 300) eq(3,eval("g:val")) eq(2,eval("g:val2")) end) it('do not crash when processing events in the handler', function() source([[ let g:val = 0 func! MyHandler(timer) call timer_stop(a:timer) sleep 100m let g:val += 1 endfunc ]]) command("call timer_start(5, 'MyHandler', {'repeat': 1})") run(nil, nil, nil, 300) eq(1,eval("g:val")) end) it("doesn't mess up the cmdline", function() local screen = Screen.new(40, 6) screen:attach() screen:set_default_attr_ids( {[0] = {bold=true, foreground=255}} ) source([[ func! MyHandler(timer) echo "evil" endfunc ]]) command("call timer_start(100, 'MyHandler', {'repeat': 1})") feed(":good") screen:sleep(200) screen:expect([[ | {0:~ }| {0:~ }| {0:~ }| {0:~ }| :good^ | ]]) end) end)