diff options
Diffstat (limited to 'test/functional')
21 files changed, 351 insertions, 149 deletions
diff --git a/test/functional/api/proc_spec.lua b/test/functional/api/proc_spec.lua index e11e03203f..063d382790 100644 --- a/test/functional/api/proc_spec.lua +++ b/test/functional/api/proc_spec.lua @@ -4,8 +4,8 @@ local clear = helpers.clear local eq = helpers.eq local funcs = helpers.funcs local iswin = helpers.iswin +local neq = helpers.neq local nvim_argv = helpers.nvim_argv -local ok = helpers.ok local request = helpers.request local retry = helpers.retry local NIL = helpers.NIL @@ -63,8 +63,9 @@ describe('api', function() local pid = funcs.getpid() local pinfo = request('nvim_get_proc', pid) eq((iswin() and 'nvim.exe' or 'nvim'), pinfo.name) - ok(pinfo.pid == pid) - ok(type(pinfo.ppid) == 'number' and pinfo.ppid ~= pid) + eq(pinfo.pid, pid) + eq(type(pinfo.ppid), 'number') + neq(pinfo.ppid, pid) end) it('validates input', function() diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua index dbe9f20412..ddd044a10f 100644 --- a/test/functional/api/server_requests_spec.lua +++ b/test/functional/api/server_requests_spec.lua @@ -169,8 +169,7 @@ describe('server -> client', function() if method == "notification" then eq('done!', eval('rpcrequest('..cid..', "nested")')) elseif method == "nested_done" then - -- this should never have been sent - ok(false) + ok(false, 'this should never have been sent') end end diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 110b3a4b16..cd45914552 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -178,6 +178,11 @@ describe('API', function() -- Verify NO hit-enter prompt. eq({mode='n', blocking=false}, nvim("get_mode")) end) + + it('Does not cause heap buffer overflow with large output', function() + eq(eval('string(range(1000000))'), + nvim('command_output', 'echo range(1000000)')) + end) end) describe('nvim_eval', function() @@ -1148,6 +1153,13 @@ describe('API', function() before_each(function() meths.set_option('isident', '') end) + + local it_maybe_pending = it + if (helpers.isCI('appveyor') and os.getenv('CONFIGURATION') == 'MSVC_32') then + -- For "works with &opt" (flaky on MSVC_32), but not easy to skip alone. #10241 + it_maybe_pending = pending + end + local function simplify_east_api_node(line, east_api_node) if east_api_node == NIL then return nil @@ -1345,7 +1357,7 @@ describe('API', function() end assert:set_parameter('TableFormatLevel', 1000000) require('test.unit.viml.expressions.parser_tests')( - it, _check_parsing, hl, fmtn) + it_maybe_pending, _check_parsing, hl, fmtn) end) describe('nvim_list_uis', function() diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index 180ed9aa02..2531b45521 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -707,11 +707,10 @@ describe('jobs', function() it('will return -1 if the wait timed out', function() source([[ call rpcnotify(g:channel, 'wait', jobwait([ - \ jobstart('exit 4'), \ jobstart((has('win32') ? 'Start-Sleep 10' : 'sleep 10').'; exit 5'), - \ ], has('win32') ? 6000 : 100)) + \ ], 100)) ]]) - eq({'notification', 'wait', {{4, -1}}}, next_msg()) + eq({'notification', 'wait', {{-1}}}, next_msg()) end) it('can pass 0 to check if a job exists', function() @@ -769,16 +768,79 @@ describe('jobs', function() -- ..c.."', '-c', '"..c.."'])") -- Create child with several descendants. + if iswin() then + source([[ + function! s:formatprocs(pid, prefix) + let result = '' + let result .= a:prefix . printf("%-24.24s%6s %12.12s %s\n", + \ s:procs[a:pid]['name'], + \ a:pid, + \ s:procs[a:pid]['Session Name'], + \ s:procs[a:pid]['Session']) + if has_key(s:procs[a:pid], 'children') + for pid in s:procs[a:pid]['children'] + let result .= s:formatprocs(pid, a:prefix . ' ') + endfor + endif + return result + endfunction + + function! PsTree() abort + let s:procs = {} + for proc in map( + \ map( + \ systemlist('tasklist /NH'), + \ 'substitute(v:val, "\r", "", "")'), + \ 'split(v:val, "\\s\\+")') + if len(proc) == 6 + let s:procs[proc[1]] ..']]'..[[= {'name': proc[0], + \ 'Session Name': proc[2], + \ 'Session': proc[3]} + endif + endfor + for pid in keys(s:procs) + let children = nvim_get_proc_children(str2nr(pid)) + if !empty(children) + let s:procs[pid]['children'] = children + for cpid in children + let s:procs[printf('%d', cpid)]['parent'] = str2nr(pid) + endfor + endif + endfor + let result = '' + for pid in sort(keys(s:procs), {i1, i2 -> i1 - i2}) + if !has_key(s:procs[pid], 'parent') + let result .= s:formatprocs(pid, '') + endif + endfor + return result + endfunction + ]]) + end local sleep_cmd = (iswin() and 'ping -n 31 127.0.0.1' or 'sleep 30') local j = eval("jobstart('"..sleep_cmd..' | '..sleep_cmd..' | '..sleep_cmd.."')") local ppid = funcs.jobpid(j) local children - retry(nil, nil, function() - children = meths.get_proc_children(ppid) - eq((iswin() and 4 or 3), #children) - end) + if iswin() then + local status, result = pcall(retry, nil, nil, function() + children = meths.get_proc_children(ppid) + -- On Windows conhost.exe may exist, and + -- e.g. vctip.exe might appear. #10783 + ok(#children >= 3 and #children <= 5) + end) + if not status then + print('') + print(eval('PsTree()')) + error(result) + end + else + retry(nil, nil, function() + children = meths.get_proc_children(ppid) + eq(3, #children) + end) + end -- Assert that nvim_get_proc() sees the children. for _, child_pid in ipairs(children) do local info = meths.get_proc(child_pid) diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index 62a45fdf88..3b32c42ec0 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -226,6 +226,31 @@ describe('startup', function() clear{env={CDPATH='~doesnotexist'}} eq(',~doesnotexist', eval('&cdpath')) end) + + it('ENTER dismisses early message #7967', function() + local screen + screen = Screen.new(60, 6) + screen:attach() + command([[let g:id = termopen('"]]..nvim_prog.. + [[" -u NONE -i NONE --cmd "set noruler" --cmd "let g:foo = g:bar"')]]) + screen:expect([[ + ^ | + Error detected while processing pre-vimrc command line: | + E121: Undefined variable: g:bar | + E15: Invalid expression: g:bar | + Press ENTER or type command to continue | + | + ]]) + command([[call chansend(g:id, "\n")]]) + screen:expect([[ + ^ | + ~ | + ~ | + [No Name] | + | + | + ]]) + end) end) describe('sysinit', function() diff --git a/test/functional/eval/timer_spec.lua b/test/functional/eval/timer_spec.lua index cd099e30ed..5c5b1b42cb 100644 --- a/test/functional/eval/timer_spec.lua +++ b/test/functional/eval/timer_spec.lua @@ -1,6 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local feed, eq, eval = helpers.feed, helpers.eq, helpers.eval +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 @@ -19,59 +19,71 @@ describe('timers', function() end) it('works one-shot', function() - command("call timer_start(50, 'MyHandler')") - eq(0,eval("g:val")) - run(nil, nil, nil, load_adjust(200)) + 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() - command("call timer_start(50, 'MyHandler', {'repeat': 0})") - eq(0,eval("g:val")) - run(nil, nil, nil, load_adjust(200)) - eq(1,eval("g:val")) + 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() - command("call timer_start(50, 'MyHandler', {'repeat': 2})") - eq(0,eval("g:val")) - run(nil, nil, nil, load_adjust(300)) - eq(2,eval("g:val")) + 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() - command("call timer_start(50, 'MyHandler', {'repeat': 2})") + 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(0,eval("g:val")) - run(nil, nil, nil, load_adjust(300)) - eq(2,eval("g:val")) + 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]")) - run(nil, nil, nil, load_adjust(400)) - eq(1000,eval("g:val")) + 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 - eval("timer_start(50, 'MyHandler', {'repeat': 2})") - eq(0,eval("g:val")) - run(nil, nil, nil, load_adjust(300)) - eq(2,eval("g:val")) + 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(50, 'MyHandler', {'repeat': -1})") - run(nil, nil, nil, load_adjust(100)) + 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(300)) + run(nil, nil, nil, load_adjust(30)) feed("<cr>") local diff = eval("g:val") - count assert(0 <= diff and diff <= 4, @@ -79,12 +91,14 @@ describe('timers', function() 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, load_adjust(300)) + 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") - local count = eval("g:val") - assert(count >= 3, 'expected count >= 3, got: '..tostring(count)) eq(99, eval("g:c")) end) @@ -99,12 +113,15 @@ describe('timers', function() source([[ func! AddItem(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 - call timer_start(200, 'AddItem') ]]) nvim_async("command", "let g:c2 = getchar()") + nvim_async("command", "call timer_start("..load_adjust(100)..", 'AddItem')") screen:expect([[ ITEM 1 | @@ -137,18 +154,15 @@ describe('timers', function() end) it('can be stopped', function() - local t = eval("timer_start(50, 'MyHandler', {'repeat': -1})") - eq(0,eval("g:val")) - run(nil, nil, nil, load_adjust(300)) - funcs.timer_stop(t) + 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, nil, nil, load_adjust(300)) + 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) - assert((3 <= count and count <= load_adjust(7)), - string.format('expected (3 <= count <= %s), got: %s', - load_adjust(7), tostring(count))) end) it('can be stopped from the handler', function() @@ -162,10 +176,9 @@ describe('timers', function() endif endfunc ]]) + eq(0, eval("g:val")) command("call timer_start(10, 'MyHandler', {'repeat': -1})") - eq(0,eval("g:val")) - run(nil, nil, nil, load_adjust(50)) - retry(nil, 5000, function() + retry(nil, nil, function() eq(3, eval("g:val")) end) end) @@ -177,9 +190,9 @@ describe('timers', function() let g:val2 += 1 endfunc ]]) - command("call timer_start(20, 'MyHandler', {'repeat': 3})") - command("call timer_start(40, 'MyHandler2', {'repeat': 2})") - run(nil, nil, nil, load_adjust(300)) + command("call timer_start(2, 'MyHandler', {'repeat': 3})") + command("call timer_start(4, 'MyHandler2', {'repeat': 2})") + run(nil, nil, nil, load_adjust(30)) eq(3,eval("g:val")) eq(2,eval("g:val2")) end) @@ -189,13 +202,15 @@ describe('timers', function() let g:val = 0 func! MyHandler(timer) call timer_stop(a:timer) - sleep 100m + sleep 10m let g:val += 1 endfunc ]]) command("call timer_start(5, 'MyHandler', {'repeat': 1})") - run(nil, nil, nil, load_adjust(300)) - eq(1,eval("g:val")) + run(nil, nil, nil, load_adjust(10)) + retry(nil, load_adjust(100), function() + eq(1, eval("g:val")) + end) end) @@ -232,5 +247,4 @@ describe('timers', function() eq(1, eval('g:val')) end) - end) diff --git a/test/functional/fixtures/tty-test.c b/test/functional/fixtures/tty-test.c index e2a78a594b..4438b73a22 100644 --- a/test/functional/fixtures/tty-test.c +++ b/test/functional/fixtures/tty-test.c @@ -38,6 +38,9 @@ bool owns_tty(void) static void walk_cb(uv_handle_t *handle, void *arg) { if (!uv_is_closing(handle)) { +#ifdef WIN32 + uv_tty_set_mode(&tty, UV_TTY_MODE_NORMAL); +#endif uv_close(handle, NULL); } } diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index d4ace3030c..d040ff5f8c 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -445,6 +445,8 @@ function module.new_argv(...) for _, k in ipairs({ 'HOME', 'ASAN_OPTIONS', + 'TSAN_OPTIONS', + 'MSAN_OPTIONS', 'LD_LIBRARY_PATH', 'PATH', 'NVIM_LOG_FILE', diff --git a/test/functional/legacy/055_list_and_dict_types_spec.lua b/test/functional/legacy/055_list_and_dict_types_spec.lua index dcbd8b7dff..91ba8bb106 100644 --- a/test/functional/legacy/055_list_and_dict_types_spec.lua +++ b/test/functional/legacy/055_list_and_dict_types_spec.lua @@ -666,7 +666,7 @@ describe('list and dictionary types', function() Vim(put):E741: {'a': 99, 'b': 100} No remove() of write-protected scope-level variable: - Vim(put):E795: + Vim(put):E742: No extend() of write-protected scope-level variable: Vim(put):E742: No :unlet of variable in locked scope: diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua index 68d4d1e2a1..a3c6c57a73 100644 --- a/test/functional/provider/python3_spec.lua +++ b/test/functional/provider/python3_spec.lua @@ -90,6 +90,12 @@ describe('python3 provider', function() eq({1, 2, {['key'] = 'val'}}, eval([[py3eval('[1, 2, {"key": "val"}]')]])) end) + it('pyxeval #10758', function() + eq(0, eval([[&pyxversion]])) + eq(3, eval([[pyxeval('sys.version_info[:3][0]')]])) + eq(3, eval([[&pyxversion]])) + end) + it('RPC call to expand("<afile>") during BufDelete #5245 #5617', function() source([=[ python3 << EOF diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index e598c325a8..1763574bf9 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -158,14 +158,15 @@ describe(':terminal buffer', function() end) it('handles loss of focus gracefully', function() - if helpers.pending_win32(pending) then return end -- Change the statusline to avoid printing the file name, which varies. nvim('set_option', 'statusline', '==========') feed_command('set laststatus=0') -- Save the buffer number of the terminal for later testing. local tbuf = eval('bufnr("%")') - + local exitcmd = helpers.iswin() + and "['cmd', '/c', 'exit']" + or "['sh', '-c', 'exit']" source([[ function! SplitWindow(id, data, event) new @@ -173,7 +174,7 @@ describe(':terminal buffer', function() endfunction startinsert - call jobstart(['sh', '-c', 'exit'], {'on_exit': function("SplitWindow")}) + call jobstart(]]..exitcmd..[[, {'on_exit': function("SplitWindow")}) call feedkeys("\<C-\>", 't') " vim will expect <C-n>, but be exited out of " the terminal before it can be entered. ]]) diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua index ad70b3d14f..7b49a38e77 100644 --- a/test/functional/terminal/window_split_tab_spec.lua +++ b/test/functional/terminal/window_split_tab_spec.lua @@ -37,7 +37,6 @@ describe(':terminal', function() end) it('does not change size on WinEnter', function() - if helpers.pending_win32(pending) then return end feed('<c-\\><c-n>') feed('k') feed_command('2split') diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 8a1758c4a0..8dfe36c799 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -383,6 +383,7 @@ describe('floating windows', function() command('set number') command('set signcolumn=yes') command('set cursorline') + command('set foldcolumn=1') command('hi NormalFloat guibg=#333333') feed('ix<cr>y<cr><esc>gg') local win = meths.open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10, style='minimal'}) @@ -397,9 +398,9 @@ describe('floating windows', function() [2:----------------------------------------]| | ## grid 2 - {19: }{20: 1 }{21:^x }| - {19: }{14: 2 }y | - {19: }{14: 3 } | + {19: }{20: 1 }{21:^x }| + {19: }{14: 2 }y | + {19: }{14: 3 } | {0:~ }| {0:~ }| {0:~ }| @@ -410,15 +411,15 @@ describe('floating windows', function() {15: }| ]], float_pos={[3] = {{id = 1001}, "NW", 1, 4, 10, true}}} else - screen:expect([[ - {19: }{20: 1 }{21:^x }| - {19: }{14: 2 }y | - {19: }{14: 3 } {15:x } | + screen:expect{grid=[[ + {19: }{20: 1 }{21:^x }| + {19: }{14: 2 }y | + {19: }{14: 3 } {15:x } | {0:~ }{15:y }{0: }| {0:~ }{15: }{0: }| {0:~ }{15: }{0: }| | - ]]) + ]]} end -- signcolumn=yes still works if there actually are signs @@ -435,9 +436,9 @@ describe('floating windows', function() [2:----------------------------------------]| | ## grid 2 - {17:π’ΜΜΜΜΜ
Μπ’ΜΜΜΜΜ
Μ}{20: 1 }{21:^x }| - {19: }{14: 2 }y | - {19: }{14: 3 } | + {19: }{17:π’ΜΜΜΜΜ
Μπ’ΜΜΜΜΜ
Μ}{20: 1 }{21:^x }| + {19: }{14: 2 }y | + {19: }{14: 3 } | {0:~ }| {0:~ }| {0:~ }| @@ -450,9 +451,9 @@ describe('floating windows', function() else screen:expect([[ - {17:π’ΜΜΜΜΜ
Μπ’ΜΜΜΜΜ
Μ}{20: 1 }{21:^x }| - {19: }{14: 2 }y | - {19: }{14: 3 } {17:π’ΜΜΜΜΜ
Μπ’ΜΜΜΜΜ
Μ}{15:x } | + {19: }{17:π’ΜΜΜΜΜ
Μπ’ΜΜΜΜΜ
Μ}{20: 1 }{21:^x }| + {19: }{14: 2 }y | + {19: }{14: 3 } {17:π’ΜΜΜΜΜ
Μπ’ΜΜΜΜΜ
Μ}{15:x } | {0:~ }{19: }{15:y }{0: }| {0:~ }{19: }{15: }{0: }| {0:~ }{15: }{0: }| @@ -474,9 +475,9 @@ describe('floating windows', function() [2:----------------------------------------]| | ## grid 2 - {19: }{20: 1 }{21:^x }| - {19: }{14: 2 }y | - {19: }{14: 3 } | + {19: }{20: 1 }{21:^x }| + {19: }{14: 2 }y | + {19: }{14: 3 } | {0:~ }| {0:~ }| {0:~ }| @@ -488,9 +489,9 @@ describe('floating windows', function() ]], float_pos={[3] = {{id = 1001}, "NW", 1, 4, 10, true}}} else screen:expect([[ - {19: }{20: 1 }{21:^x }| - {19: }{14: 2 }y | - {19: }{14: 3 } {15: } | + {19: }{20: 1 }{21:^x }| + {19: }{14: 2 }y | + {19: }{14: 3 } {15: } | {0:~ }{15: }{0: }| {0:~ }{15: }{0: }| {0:~ }{15: }{0: }| @@ -4143,14 +4144,14 @@ describe('floating windows', function() [4:----------------------------------------]| [4:----------------------------------------]| :tabnew | - ## grid 2 + ## grid 2 (hidden) x | {0:~ }| {0:~ }| {0:~ }| {0:~ }| {0:~ }| - ## grid 3 + ## grid 3 (hidden) {1:y }| {2:~ }| ## grid 4 @@ -4192,7 +4193,7 @@ describe('floating windows', function() ## grid 3 {1:y }| {2:~ }| - ## grid 4 + ## grid 4 (hidden) | {0:~ }| {0:~ }| @@ -4222,13 +4223,13 @@ describe('floating windows', function() [4:----------------------------------------]| [4:----------------------------------------]| :tabnext | - ## grid 2 + ## grid 2 (hidden) x | {0:~ }| {0:~ }| {0:~ }| {0:~ }| - ## grid 3 + ## grid 3 (hidden) {1:y }| {2:~ }| ## grid 4 @@ -4266,7 +4267,7 @@ describe('floating windows', function() [4:----------------------------------------]| [4:----------------------------------------]| :tabnew | - ## grid 2 + ## grid 2 (hidden) x | {0:~ }| {0:~ }| @@ -4312,7 +4313,7 @@ describe('floating windows', function() {0:~ }| {0:~ }| {0:~ }| - ## grid 4 + ## grid 4 (hidden) | {0:~ }| {0:~ }| @@ -4332,7 +4333,7 @@ describe('floating windows', function() [4:----------------------------------------]| [4:----------------------------------------]| :tabnext | - ## grid 2 + ## grid 2 (hidden) x | {0:~ }| {0:~ }| @@ -4364,7 +4365,11 @@ describe('floating windows', function() [5] = {foreground = tonumber('0x990000'), background = tonumber('0xfff1ff')}, [6] = {foreground = tonumber('0x332533'), background = tonumber('0xfff1ff')}, [7] = {background = tonumber('0xffcfff'), bold = true, foreground = tonumber('0x0000d8')}, - [8] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1} + [8] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1}, + [9] = {background = Screen.colors.LightMagenta, blend=30}, + [10] = {foreground = Screen.colors.Red, background = Screen.colors.LightMagenta, blend=0}, + [11] = {foreground = Screen.colors.Red, background = Screen.colors.LightMagenta, blend=80}, + [12] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1, blend=30}, }) insert([[ Lorem ipsum dolor sit amet, consectetur @@ -4444,9 +4449,9 @@ describe('floating windows', function() qui officia deserunt mollit anim id est | laborum^. | ## grid 4 - {1:test }| - {1: }| - {1:popup text }| + {9:test }| + {9: }| + {9:popup text }| ]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}, unchanged=true} else screen:expect([[ @@ -4486,9 +4491,9 @@ describe('floating windows', function() qui officia deserunt mollit anim id est | laborum^. | ## grid 4 - {1:test }| - {1: }| - {4:popup text}{1: }| + {9:test }| + {9: }| + {10:popup text}{9: }| ]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}} else screen:expect([[ @@ -4496,7 +4501,7 @@ describe('floating windows', function() exercitation ullamco laboris nisi ut aliquip ex | ea co{2:test}{3:o consequat}. Duis aute irure dolor in | repre{3:henderit in vol}uptate velit esse cillum | - dolor{4:popup text}{3:ul}la pariatur. Excepteur sint | + dolor{10:popup text}{3:ul}la pariatur. Excepteur sint | occaecat cupidatat non proident, sunt in culpa | qui officia deserunt mollit anim id est | laborum^. | @@ -4527,9 +4532,9 @@ describe('floating windows', function() qui officia deserunt mollit anim id est | laborum^. | ## grid 4 - {1:test }| - {1: }| - {4:popup text}{1: }| + {9:test }| + {9: }| + {11:popup text}{9: }| ]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}, unchanged=true} else screen:expect([[ @@ -4569,9 +4574,9 @@ describe('floating windows', function() qui officia deserunt mollit anim id est | laborum^. | ## grid 4 - {4:popup text}{1: }| - {8:~ }| - {8:~ }| + {11:popup text}{9: }| + {12:~ }| + {12:~ }| ]], float_pos={[4] = {{id = 1002}, "NW", 1, 2, 5, true}}} else meths.input_mouse('wheel', 'down', '', 0, 4, 7) @@ -4671,7 +4676,7 @@ describe('floating windows', function() [2] = {foreground = Screen.colors.Grey0, background = tonumber('0xffcfff')}, [3] = {bold = true, foreground = Screen.colors.Blue1}, [4] = {background = tonumber('0xffcfff'), bold = true, foreground = tonumber('0xb282ff')}, - [5] = {background = Screen.colors.LightMagenta}, + [5] = {background = Screen.colors.LightMagenta, blend=30}, }) if multigrid then screen:expect{grid=[[ diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 4f243e6413..238cc368da 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -2634,3 +2634,19 @@ it(':substitute with inccommand, timer-induced :redraw #9777', function() :%s/foo/ZZZ^ | ]]) end) + +it('long :%s/ with inccommand does not collapse cmdline', function() + local screen = Screen.new(10,5) + clear() + common_setup(screen) + command('set inccommand=nosplit') + feed(':%s/AAAAAAA', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A') + screen:expect([[ + {15:~ }| + {15:~ }| + :%s/AAAAAAAA| + AAAAAAAAAAAA| + AAAAAAA^ | + ]]) +end) diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua index 121cbe47d6..0009f2c31b 100644 --- a/test/functional/ui/input_spec.lua +++ b/test/functional/ui/input_spec.lua @@ -103,6 +103,11 @@ describe('mappings', function() check_mapping('<kequal>','<kequal>') check_mapping('<KPEquals>','<kequal>') end) + + it('support meta + multibyte char mapping', function() + add_mapping('<m-Γ€>', '<m-Γ€>') + check_mapping('<m-Γ€>', '<m-Γ€>') + end) end) describe('feeding large chunks of input with <Paste>', function() diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 9a1a0f66a2..ed65c4526f 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -6,7 +6,10 @@ local eq = helpers.eq local command = helpers.command local set_method_error = helpers.set_method_error local meths = helpers.meths - +local test_build_dir = helpers.test_build_dir +local nvim_prog = helpers.nvim_prog +local iswin = helpers.iswin +local exc_exec = helpers.exc_exec describe('ui/ext_messages', function() local screen @@ -1004,3 +1007,48 @@ describe('ui/ext_messages', function() }} end) end) + +describe('ui/msg_puts_printf', function() + it('output multibyte characters correctly', function() + local screen + local cmd = '' + local locale_dir = test_build_dir..'/share/locale/ja/LC_MESSAGES' + + clear({env={LANG='ja_JP.UTF-8'}}) + screen = Screen.new(25, 5) + screen:attach() + + if iswin() then + if os.execute('chcp 932 > NUL 2>&1') ~= 0 then + pending('missing japanese language features', function() end) + return + else + cmd = 'chcp 932 > NULL & ' + end + else + if (exc_exec('lang ja_JP.UTF-8') ~= 0) then + pending('Locale ja_JP.UTF-8 not supported', function() end) + return + elseif helpers.isCI() then + -- Fails non--Windows CI. Message catalog direcotry issue? + pending('fails on unix CI', function() end) + return + end + end + + os.execute('cmake -E make_directory '..locale_dir) + os.execute('cmake -E copy '..test_build_dir..'/src/nvim/po/ja.mo '..locale_dir..'/nvim.mo') + + cmd = cmd..'"'..nvim_prog..'" -u NONE -i NONE -Es -V1' + command([[call termopen(']]..cmd..[[')]]) + screen:expect([[ + ^Exγ’γΌγγ«ε
₯γγΎγ. γγΌ | + γγ«γ’γΌγγ«ζ»γγ«γ―"visu| + al"γ¨ε
₯εγγ¦γγ γγ. | + : | + | + ]]) + + os.execute('cmake -E remove_directory '..test_build_dir..'/share') + end) +end) diff --git a/test/functional/ui/mode_spec.lua b/test/functional/ui/mode_spec.lua index f6b3c1c3c9..a09df075aa 100644 --- a/test/functional/ui/mode_spec.lua +++ b/test/functional/ui/mode_spec.lua @@ -2,8 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert -local command, eval = helpers.command, helpers.eval -local eq = helpers.eq +local command = helpers.command describe('ui mode_change event', function() local screen @@ -63,7 +62,7 @@ describe('ui mode_change event', function() ]], mode="normal"} command("set showmatch") - eq(eval('&matchtime'), 5) -- tenths of seconds + command("set matchtime=1") -- tenths of seconds feed('a(stuff') screen:expect{grid=[[ word(stuff^ | @@ -80,7 +79,6 @@ describe('ui mode_change event', function() {2:-- INSERT --} | ]], mode="showmatch"} - screen:sleep(400) screen:expect{grid=[[ word(stuff)^ | {0:~ }| diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua index c5a23e4661..a910f5e2ea 100644 --- a/test/functional/ui/multigrid_spec.lua +++ b/test/functional/ui/multigrid_spec.lua @@ -76,7 +76,7 @@ describe('ext_multigrid', function() it('positions windows correctly', function() command('vsplit') - screen:expect([[ + screen:expect{grid=[[ ## grid 1 [3:--------------------------]{12:β}[2:--------------------------]| [3:--------------------------]{12:β}[2:--------------------------]| @@ -118,15 +118,15 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| {1:~ }| - ]], nil, nil, function() + ]], condition=function() eq({ - [2] = { win = 1000, startrow = 0, startcol = 27, width = 26, height = 12 }, - [3] = { win = 1001, startrow = 0, startcol = 0, width = 26, height = 12 } + [2] = { win = {id=1000}, startrow = 0, startcol = 27, width = 26, height = 12 }, + [3] = { win = {id=1001}, startrow = 0, startcol = 0, width = 26, height = 12 } }, screen.win_position) - end) + end} command('wincmd l') command('split') - screen:expect([[ + screen:expect{grid=[[ ## grid 1 [3:--------------------------]{12:β}[4:--------------------------]| [3:--------------------------]{12:β}[4:--------------------------]| @@ -168,16 +168,16 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| {1:~ }| - ]], nil, nil, function() + ]], condition=function() eq({ - [2] = { win = 1000, startrow = 7, startcol = 27, width = 26, height = 5 }, - [3] = { win = 1001, startrow = 0, startcol = 0, width = 26, height = 12 }, - [4] = { win = 1002, startrow = 0, startcol = 27, width = 26, height = 6 } + [2] = { win = {id=1000}, startrow = 7, startcol = 27, width = 26, height = 5 }, + [3] = { win = {id=1001}, startrow = 0, startcol = 0, width = 26, height = 12 }, + [4] = { win = {id=1002}, startrow = 0, startcol = 27, width = 26, height = 6 } }, screen.win_position) - end) + end} command('wincmd h') command('q') - screen:expect([[ + screen:expect{grid=[[ ## grid 1 [4:-----------------------------------------------------]| [4:-----------------------------------------------------]| @@ -206,12 +206,12 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| {1:~ }| - ]], nil, nil, function() + ]], condition=function() eq({ - [2] = { win = 1000, startrow = 7, startcol = 0, width = 53, height = 5 }, - [4] = { win = 1002, startrow = 0, startcol = 0, width = 53, height = 6 } + [2] = { win = {id=1000}, startrow = 7, startcol = 0, width = 53, height = 5 }, + [4] = { win = {id=1002}, startrow = 0, startcol = 0, width = 53, height = 6 } }, screen.win_position) - end) + end} end) describe('split', function () @@ -1206,7 +1206,7 @@ describe('ext_multigrid', function() ]]) end) - it('handles switich tabs', function() + it('handles switch tabs', function() command('vsp') screen:expect([[ ## grid 1 @@ -1271,7 +1271,7 @@ describe('ext_multigrid', function() [4:-----------------------------------------------------]| {11:[No Name] }| | - ## grid 2 + ## grid 2 (hidden) | {1:~ }| {1:~ }| @@ -1284,7 +1284,7 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| {1:~ }| - ## grid 3 + ## grid 3 (hidden) | {1:~ }| {1:~ }| @@ -1328,7 +1328,7 @@ describe('ext_multigrid', function() [4:-----------------------------------------------------]| {12:[No Name] }| | - ## grid 2 + ## grid 2 (hidden) | {1:~ }| {1:~ }| @@ -1341,7 +1341,7 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| {1:~ }| - ## grid 3 + ## grid 3 (hidden) | {1:~ }| {1:~ }| @@ -1409,13 +1409,13 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| {1:~ }| - ## grid 4 + ## grid 4 (hidden) | {1:~ }| {1:~ }| {1:~ }| {1:~ }| - ## grid 5 + ## grid 5 (hidden) | {1:~ }| {1:~ }| @@ -1440,7 +1440,7 @@ describe('ext_multigrid', function() [4:-----------------------------------------------------]| {12:[No Name] }| | - ## grid 2 + ## grid 2 (hidden) | {1:~ }| {1:~ }| @@ -1452,7 +1452,7 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| {1:~ }| - ## grid 3 + ## grid 3 (hidden) | {1:~ }| {1:~ }| diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua index 24bf66e2d8..4a0e7ccad0 100644 --- a/test/functional/ui/output_spec.lua +++ b/test/functional/ui/output_spec.lua @@ -12,8 +12,6 @@ local command = helpers.command local nvim_dir = helpers.nvim_dir describe("shell command :!", function() - if helpers.pending_win32(pending) then return end - local screen before_each(function() clear() @@ -36,6 +34,7 @@ describe("shell command :!", function() end) it("displays output without LF/EOF. #4646 #4569 #3772", function() + if helpers.pending_win32(pending) then return end -- NOTE: We use a child nvim (within a :term buffer) -- to avoid triggering a UI flush. child_session.feed_data(":!printf foo; sleep 200\n") diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 9bfea28ed7..c4cfc9d8d3 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -1644,6 +1644,7 @@ describe('builtin popupmenu', function() [42] = {foreground = tonumber('0x0c0c0c'), background = tonumber('0xe5a8e5')}, [43] = {background = tonumber('0x7f5d7f'), bold = true, foreground = tonumber('0x3f3f3f')}, [44] = {foreground = tonumber('0x3f3f3f'), background = tonumber('0x7f5d7f')}, + [45] = {background = Screen.colors.WebGray, blend=0}, }) command('syntax on') command('set mouse=a') @@ -1761,7 +1762,7 @@ describe('builtin popupmenu', function() Lorem ipsum d{1:ol}or sit amet, consectetur | adipisicing elit, sed do eiusmod tempor | bla bla incididunt^ | - incidid{22: incididunt }{27: }d{1:ol}ore magna aliqua. | + incidid{45: incididunt }{27: }d{1:ol}ore magna aliqua. | Ut enim{28: }{29:ut}{28: minim veniam}{25:,} quis nostrud | exercit{28:a}{29:labore}{28:llamco la}{25:b}oris nisi ut aliquip ex | {2:[No Nam}{30:e}{43:et}{30:[+] }{32: }{2: }| diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 81a15cada2..3b39794465 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -316,9 +316,10 @@ local ext_keys = { -- cmdline_block: Expected ext_cmdline block (for function definitions) -- wildmenu_items: Expected items for ext_wildmenu -- wildmenu_pos: Expected position for ext_wildmenu -function Screen:expect(expected, attr_ids, attr_ignore) +function Screen:expect(expected, attr_ids, attr_ignore, ...) local grid, condition = nil, nil local expected_rows = {} + assert(next({...}) == nil, "invalid args to expect()") if type(expected) == "table" then assert(not (attr_ids ~= nil or attr_ignore ~= nil)) local is_key = {grid=true, attr_ids=true, attr_ignore=true, condition=true, @@ -499,7 +500,8 @@ function Screen:_wait(check, flags) local did_miminal_timeout = false local function notification_cb(method, args) - assert(method == 'redraw') + assert(method == 'redraw', string.format( + 'notification_cb: unexpected method (%s, args=%s)', method, inspect(args))) did_flush = self:_redraw(args) if not did_flush then return @@ -1211,7 +1213,11 @@ function Screen:render(headers, attr_state, preview) local rv = {} for igrid,grid in pairs(self._grids) do if headers then - table.insert(rv, "## grid "..igrid) + local suffix = "" + if igrid > 1 and self.win_position[igrid] == nil and self.float_pos[igrid] == nil then + suffix = " (hidden)" + end + table.insert(rv, "## grid "..igrid..suffix) end for i = 1, grid.height do local cursor = self._cursor.grid == igrid and self._cursor.row == i @@ -1491,7 +1497,7 @@ function Screen:_equal_attrs(a, b) a.underline == b.underline and a.undercurl == b.undercurl and a.italic == b.italic and a.reverse == b.reverse and a.foreground == b.foreground and a.background == b.background and - a.special == b.special + a.special == b.special and a.blend == b.blend end function Screen:_equal_info(a, b) |