diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2021-09-17 09:16:40 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-17 09:16:40 -0700 |
commit | d8de4eb685e35646c7d541e9a75bdc296127b7e2 (patch) | |
tree | 4bb05ec713856715ac9ba57e5d116eed344511b9 /test/functional/vimscript/timer_spec.lua | |
parent | d56002f7b722facd97b0958e141c8ed2d01495f7 (diff) | |
download | rneovim-d8de4eb685e35646c7d541e9a75bdc296127b7e2.tar.gz rneovim-d8de4eb685e35646c7d541e9a75bdc296127b7e2.tar.bz2 rneovim-d8de4eb685e35646c7d541e9a75bdc296127b7e2.zip |
test: reorg #15698
Problem:
Subdirectories like "visual", "insert", "normal" encourage people to
separate *related* tests for no good reason. Typically the _mode_ is
not the relevant topic of a test (and when it is, _then_ create
an appropriate describe() or it()).
Solution:
- Delete the various `test/functional/<mode>/` subdirectories, move
their tests to more meaningful topics.
- Rename `…/normal/` to `…/editor/`.
- Move or merge `…/visual/*` and `…/insert/*` tests into here where
appropriate.
- Rename `…/eval/` to `…/vimscript/`.
- Move `…/viml/*` into here also.
* test(reorg): insert/* => editor/mode_insert_spec.lua
* test(reorg): cmdline/* => editor/mode_cmdline_spec.lua
* test(reorg): eval core tests => eval_spec.lua
Diffstat (limited to 'test/functional/vimscript/timer_spec.lua')
-rw-r--r-- | test/functional/vimscript/timer_spec.lua | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/test/functional/vimscript/timer_spec.lua b/test/functional/vimscript/timer_spec.lua new file mode 100644 index 0000000000..9ee0735e40 --- /dev/null +++ b/test/functional/vimscript/timer_spec.lua @@ -0,0 +1,265 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local feed, eq, eval, ok = helpers.feed, helpers.eq, helpers.eval, helpers.ok +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 +local load_adjust = helpers.load_adjust +local retry = helpers.retry + +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() + eq(0, eval("[timer_start(10, 'MyHandler'), g:val][1]")) + run(nil, nil, nil, load_adjust(100)) + eq(1,eval("g:val")) + end) + + it('works one-shot when repeat=0', function() + eq(0, eval("[timer_start(10, 'MyHandler', {'repeat': 0}), g:val][1]")) + run(nil, nil, nil, load_adjust(100)) + eq(1, eval("g:val")) + end) + + it('works with repeat two', function() + eq(0, eval("[timer_start(10, 'MyHandler', {'repeat': 2}), g:val][1]")) + run(nil, nil, nil, load_adjust(20)) + retry(nil, load_adjust(300), function() + eq(2, eval("g:val")) + end) + end) + + it('are triggered during sleep', function() + source([[ + let g:val = -1 + func! MyHandler(timer) + if g:val >= 0 + let g:val += 1 + if g:val == 2 + call timer_stop(a:timer) + endif + endif + endfunc + ]]) + eval("timer_start(10, 'MyHandler', {'repeat': -1})") + nvim_async("command", "sleep 10") + eq(-1, eval("g:val")) -- timer did nothing yet. + nvim_async("command", "let g:val = 0") + run(nil, nil, nil, load_adjust(20)) + retry(nil, nil, function() + eq(2, eval("g:val")) + end) + 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]")) + retry(nil, nil, function() + eq(1000, eval("g:val")) + end) + end) + + it('can be started during sleep', function() + nvim_async("command", "sleep 10") + -- this also tests that remote requests works during sleep + eq(0, eval("[timer_start(10, 'MyHandler', {'repeat': 2}), g:val][1]")) + run(nil, nil, nil, load_adjust(20)) + retry(nil, load_adjust(300), function() eq(2,eval("g:val")) end) + end) + + it('are paused when event processing is disabled', function() + command("call timer_start(5, 'MyHandler', {'repeat': -1})") + run(nil, nil, nil, load_adjust(10)) + 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"<CR>') + run(nil, nil, nil, load_adjust(30)) + feed("<cr>") + local diff = eval("g:val") - count + assert(0 <= diff and diff <= 4, + 'expected (0 <= diff <= 4), got: '..tostring(diff)) + end) + + it('are triggered in blocking getchar() call', function() + command("call timer_start(5, 'MyHandler', {'repeat': -1})") + nvim_async("command", "let g:val = 0 | let g:c = getchar()") + retry(nil, nil, function() + local val = eval("g:val") + ok(val >= 2, "expected >= 2, got: "..tostring(val)) + eq(0, eval("getchar(1)")) + end) + feed("c") + 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([[ + let g:cont = 0 + func! AddItem(timer) + if !g:cont + return + endif + call timer_stop(a:timer) + + call nvim_buf_set_lines(0, 2, 2, v:true, ['ITEM 3']) + + " Meant to test for what Vim tests in Test_peek_and_get_char. + call getchar(1) + + redraw + endfunc + ]]) + nvim_async("command", "let g:c2 = getchar()") + nvim_async("command", "call timer_start("..load_adjust(100)..", 'AddItem', {'repeat': -1})") + + screen:expect([[ + ITEM 1 | + ITEM 2 | + {1:~ }| + {1:~ }| + {1:~ }| + ^ | + ]]) + nvim_async("command", "let g:cont = 1") + + 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_init_val = eval("[timer_start(5, 'MyHandler', {'repeat': -1}), g:val]") + eq(0, t_init_val[2]) + run(nil, nil, nil, load_adjust(30)) + funcs.timer_stop(t_init_val[1]) + local count = eval("g:val") + run(nil, load_adjust(300), nil, load_adjust(30)) + local count2 = eval("g:val") + -- 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 + ]]) + eq(0, eval("g:val")) + command("call timer_start(10, 'MyHandler', {'repeat': -1})") + retry(nil, nil, function() + eq(3, eval("g:val")) + end) + end) + + it('can have two timers', function() + source([[ + let g:val2 = 0 + func! MyHandler2(timer) + let g:val2 += 1 + endfunc + ]]) + command("call timer_start(2, 'MyHandler', {'repeat': 3})") + command("call timer_start(4, 'MyHandler2', {'repeat': 2})") + retry(nil, nil, function() + eq(3, eval("g:val")) + eq(2, eval("g:val2")) + end) + 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 10m + let g:val += 1 + endfunc + ]]) + command("call timer_start(5, 'MyHandler', {'repeat': 1})") + run(nil, nil, nil, load_adjust(20)) + retry(nil, load_adjust(150), function() + eq(1, eval("g:val")) + end) + 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([[ + let g:val = 0 + func! MyHandler(timer) + while !g:val + return + endwhile + call timer_stop(a:timer) + + echo "evil" + redraw + let g:val = 2 + endfunc + ]]) + command("call timer_start(100, 'MyHandler', {'repeat': -1})") + feed(":good") + screen:expect([[ + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + :good^ | + ]]) + command('let g:val = 1') + + screen:expect{grid=[[ + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + :good^ | + ]], intermediate=true, timeout=load_adjust(200)} + + eq(2, eval('g:val')) + end) +end) |