diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2018-12-27 22:49:44 +0100 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2018-12-27 22:49:44 +0100 |
commit | c1015121ec626cab6cb384f544bc0be1a1760c0e (patch) | |
tree | 6cc9a5d1899a4486a24c491e07d17a7dd01f9503 /test | |
parent | 4f030ec24e0e148bbb83aedaef7dd629e5fef130 (diff) | |
parent | e1876c7ad1b5e30c0a9919e2c4587d11550c8507 (diff) | |
download | rneovim-c1015121ec626cab6cb384f544bc0be1a1760c0e.tar.gz rneovim-c1015121ec626cab6cb384f544bc0be1a1760c0e.tar.bz2 rneovim-c1015121ec626cab6cb384f544bc0be1a1760c0e.zip |
Merge 'upstream/master' into pr-win-erw7
Diffstat (limited to 'test')
38 files changed, 1973 insertions, 397 deletions
diff --git a/test/README.md b/test/README.md index 0999f412ac..1a5dc022f4 100644 --- a/test/README.md +++ b/test/README.md @@ -1,27 +1,63 @@ Tests ===== -Tests are run by `/cmake/RunTests.cmake` file, using `busted`. +Tests are broadly divided into *unit tests* ([test/unit](https://github.com/neovim/neovim/tree/master/test/unit/)), +*functional tests* ([test/functional](https://github.com/neovim/neovim/tree/master/test/functional/)), +and *old tests* ([src/nvim/testdir/](https://github.com/neovim/neovim/tree/master/src/nvim/testdir/)). -For some failures, `.nvimlog` (or `$NVIM_LOG_FILE`) may provide insight. +- _Unit_ testing is achieved by compiling the tests as a shared library which is + loaded and called by [LuaJit FFI](http://luajit.org/ext_ffi.html). +- _Functional_ tests are driven by RPC, so they do not require LuaJit (as + opposed to Lua). + +You can learn the [key concepts of Lua in 15 minutes](http://learnxinyminutes.com/docs/lua/). +Use any existing test as a template to start writing new tests. + +Tests are run by `/cmake/RunTests.cmake` file, using `busted` (a Lua test-runner). +For some failures, `.nvimlog` (or `$NVIM_LOG_FILE`) may provide insight. + +Depending on the presence of binaries (e.g., `xclip`) some tests will be +ignored. You must compile with libintl to prevent `E319: The command is not +available in this version` errors. -Depending on the presence of binaries (e.g., `xclip`) some tests will be ignored. You must compile with libintl to prevent `E319: The command is not available in this version` errors. --- - [Running tests](#running-tests) -- [Unit tests](#unit-tests) +- [Writing tests](#writing-tests) - [Lint](#lint) - [Environment variables](#environment-variables) --- + +Layout +====== + +- `/test/benchmark` : benchmarks +- `/test/functional` : functional tests +- `/test/unit` : unit tests +- `/test/config` : contains `*.in` files which are transformed into `*.lua` + files using `configure_file` CMake command: this is for acessing CMake + variables in lua tests. +- `/test/includes` : include-files for use by luajit `ffi.cdef` C definitions + parser: normally used to make macros not accessible via this mechanism + accessible the other way. +- `/test/*/preload.lua` : modules preloaded by busted `--helper` option +- `/test/**/helpers.lua` : common utility functions for test code +- `/test/*/**/*_spec.lua` : actual tests. Files that do not end with + `_spec.lua` are libraries like `/test/**/helpers.lua`, except that they have + some common topic. +- `/src/nvim/testdir` : old tests (from Vim) + + Running tests -------------- +============= -## Executing Tests +Executing Tests +--------------- -To run all _non-legacy_ (unit + functional) tests: +To run all tests (except "old" tests): make test @@ -33,9 +69,32 @@ To run only _functional_ tests: make functionaltest ---- -## Filter Tests +Legacy tests +------------ + +To run all legacy Vim tests: + + make oldtest + +To run a *single* legacy test set `TEST_FILE`, for example: + + TEST_FILE=test_syntax.res make oldtest + +- The `.res` extension (instead of `.vim`) is required. +- Specify only the test file name, not the full path. + + +Debugging tests +--------------- + +You can set `$GDB` to [run tests under gdbserver](https://github.com/neovim/neovim/pull/1527). +And if `$VALGRIND` is set it will pass `--vgdb=yes` to valgrind instead of +starting gdbserver directly. + + +Filtering Tests +--------------- ### Filter by name @@ -85,58 +144,20 @@ To run only the tagged tests: TEST_TAG=foo make functionaltest -**NOTES**: +**NOTE:** -* Tags are mainly used for testing issues (ex: `#1234`), so use the following - method. * `TEST_FILE` is not a pattern string like `TEST_TAG` or `TEST_FILTER`. The given value to `TEST_FILE` must be a path to an existing file. -* Both `TEST_TAG` and `TEST_FILTER` filter tests by the strings from either - `it()` or `describe()` functions. - ---- - -### Legacy - -To run all legacy (Vim) integration tests: +* Both `TEST_TAG` and `TEST_FILTER` filter tests by the string descriptions + found in `it()` and `describe()`. - make oldtest - -To run a *single* legacy test, run `make` with `TEST_FILE=test_name.res`. E.g. -to run `test_syntax.vim`: - - TEST_FILE=test_syntax.res make oldtest - -- The `.res` extension (instead of `.vim`) is required. -- Specify only the test file name, not the full path. -### Functional tests +Writing tests +============= -`$GDB` can be set to [run tests under -gdbserver](https://github.com/neovim/neovim/pull/1527). If `$VALGRIND` is also -set, it will add the `--vgdb=yes` option to valgrind instead of -starting gdbserver directly. - -Unit tests +Guidelines ---------- -Tests are broadly divided into *unit tests* -([test/unit](https://github.com/neovim/neovim/tree/master/test/unit) directory) -and *functional tests* -([test/functional](https://github.com/neovim/neovim/tree/master/test/functional) -directory). Use any of the existing tests as a template to start writing new -tests. - -- _Unit_ testing is achieved by compiling the tests as a shared library which is - loaded and called by LuaJit [FFI](http://luajit.org/ext_ffi.html). -- _Functional_ tests are driven by RPC, so they do not require LuaJit (as - opposed to Lua). - -You can learn the [key concepts of Lua in 15 -minutes](http://learnxinyminutes.com/docs/lua/). - -## Guidelines for writing tests - - Consider [BDD](http://en.wikipedia.org/wiki/Behavior-driven_development) guidelines for organization and readability of tests. Describe what you're testing (and the environment if applicable) and create specs that assert its @@ -174,8 +195,14 @@ minutes](http://learnxinyminutes.com/docs/lua/). ([example](https://github.com/neovim/neovim/commit/5c1dc0fbe7388528875aff9d7b5055ad718014de#diff-bf80b24c724b0004e8418102f68b0679R18)). - Use `make testlint` for using the shipped luacheck program ([supported by syntastic](https://github.com/scrooloose/syntastic/blob/d6b96c079be137c83009827b543a83aa113cc011/doc/syntastic-checkers.txt#L3546)) to lint all tests. +- Really long `source([=[...]=])` blocks may break syntax highlighting. Try + `:syntax sync fromstart` to fix it. -### Where tests go +Where tests go +-------------- + +Tests in `/test/unit` and `/test/functional` are divided into groups +by the semantic component they are testing. - _Unit tests_ ([test/unit](https://github.com/neovim/neovim/tree/master/test/unit)) should @@ -189,33 +216,9 @@ minutes](http://learnxinyminutes.com/docs/lua/). - Try to find an existing `test/functional/*/*_spec.lua` group that makes sense, before creating a new one. -## Checklist for migrating legacy tests - -**Note:** Only "old style" (`src/nvim/testdir/*.in`) legacy tests should be -converted. Please _do not_ convert "new style" Vim tests -(`src/nvim/testdir/*.vim`). -The "new style" Vim tests are faster than the old ones, and converting them -takes time and effort better spent elsewhere. - -- Remove the associated `test.in`, `test.out`, and `test.ok` files from - `src/nvim/testdir/`. -- Make sure the lua test ends in `_spec.lua`. -- Make sure the test count increases accordingly in the build log. -- Make sure the new test contains the same control characters (`^]`, ...) as the - old test. - - Instead of the actual control characters, use an equivalent textual - representation (e.g. `<esc>` instead of `^]`). The - `scripts/legacy2luatest.pl` script does some of these conversions - automatically. - -## Tips - -- Really long `source([=[...]=])` blocks may break syntax highlighting. Try - `:syntax sync fromstart` to fix it. - Lint ----- +==== `make lint` (and `make testlint`) runs [luacheck](https://github.com/mpeterv/luacheck) on the test code. @@ -229,29 +232,9 @@ http://luacheck.readthedocs.io/en/stable/warnings.html Ignore the smallest applicable scope (e.g. inside a function, not at the top of the file). -Layout ------- - -- `/test/benchmark` : benchmarks -- `/test/functional` : functional tests -- `/test/unit` : unit tests -- `/test/config` : contains `*.in` files which are transformed into `*.lua` - files using `configure_file` CMake command: this is for acessing CMake - variables in lua tests. -- `/test/includes` : include-files for use by luajit `ffi.cdef` C definitions - parser: normally used to make macros not accessible via this mechanism - accessible the other way. -- `/test/*/preload.lua` : modules preloaded by busted `--helper` option -- `/test/**/helpers.lua` : common utility functions for test code -- `/test/*/**/*_spec.lua` : actual tests. Files that do not end with - `_spec.lua` are libraries like `/test/**/helpers.lua`, except that they have - some common topic. - -Tests in `/test/unit` and `/test/functional` are normally divided into groups -by the semantic component they are testing. Environment variables ---------------------- +===================== Test behaviour is affected by environment variables. Currently supported (Functional, Unit, Benchmarks) (when Defined; when set to _1_; when defined, diff --git a/test/functional/api/version_spec.lua b/test/functional/api/version_spec.lua index b4ae17d963..bf67d4788b 100644 --- a/test/functional/api/version_spec.lua +++ b/test/functional/api/version_spec.lua @@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local mpack = require('mpack') local clear, funcs, eq = helpers.clear, helpers.funcs, helpers.eq local call = helpers.call +local meths = helpers.meths local function read_mpack_file(fname) local fd = io.open(fname, 'rb') @@ -43,7 +44,7 @@ describe("api_info()['version']", function() end) -describe("api functions", function() +describe("api metadata", function() before_each(clear) local function name_table(entries) @@ -87,26 +88,23 @@ describe("api functions", function() end end - it("are compatible with old metadata or have new level", function() - local api = helpers.call('api_info') - local compat = api.version.api_compatible - local api_level = api.version.api_level - local stable + local api, compat, stable, api_level + local old_api = {} + setup(function() + api = meths.get_api_info()[2] + compat = api.version.api_compatible + api_level = api.version.api_level if api.version.api_prerelease then stable = api_level-1 else stable = api_level end - local funcs_new = name_table(api.functions) - local ui_events_new = name_table(api.ui_events) - local funcs_compat = {} - local ui_events_compat = {} for level = compat, stable do local path = ('test/functional/fixtures/api_level_'.. tostring(level)..'.mpack') - local old_api = read_mpack_file(path) - if old_api == nil then + old_api[level] = read_mpack_file(path) + if old_api[level] == nil then local errstr = "missing metadata fixture for stable level "..level..". " if level == api_level and not api.version.api_prerelease then errstr = (errstr.."If NVIM_API_CURRENT was bumped, ".. @@ -116,10 +114,16 @@ describe("api functions", function() end if level == 0 then - clean_level_0(old_api) + clean_level_0(old_api[level]) end + end + end) - for _,f in ipairs(old_api.functions) do + it("functions are compatible with old metadata or have new level", function() + local funcs_new = name_table(api.functions) + local funcs_compat = {} + for level = compat, stable do + for _,f in ipairs(old_api[level].functions) do if funcs_new[f.name] == nil then if f.since >= compat then error('function '..f.name..' was removed but exists in level '.. @@ -130,18 +134,7 @@ describe("api functions", function() filter_function_metadata(funcs_new[f.name])) end end - funcs_compat[level] = name_table(old_api.functions) - - -- UI events were formalized in level 3 - if level >= 3 then - for _,e in ipairs(old_api.ui_events) do - local new_e = ui_events_new[e.name] - if new_e ~= nil then - check_ui_event_compatible(e, new_e) - end - end - ui_events_compat[level] = name_table(old_api.ui_events) - end + funcs_compat[level] = name_table(old_api[level].functions) end for _,f in ipairs(api.functions) do @@ -171,6 +164,22 @@ describe("api functions", function() end end end + end) + + it("UI events are compatible with old metadata or have new level", function() + local ui_events_new = name_table(api.ui_events) + local ui_events_compat = {} + + -- UI events were formalized in level 3 + for level = 3, stable do + for _,e in ipairs(old_api[level].ui_events) do + local new_e = ui_events_new[e.name] + if new_e ~= nil then + check_ui_event_compatible(e, new_e) + end + end + ui_events_compat[level] = name_table(old_api[level].ui_events) + end for _,e in ipairs(api.ui_events) do if e.since <= stable then @@ -197,15 +206,18 @@ describe("api functions", function() end end) -end) - -describe("ui_options in metadata", function() - it('are correct', function() - -- TODO(bfredl) once a release freezes this into metadata, - -- instead check that all old options are present - local api = helpers.call('api_info') - local options = api.ui_options - eq({'rgb', 'ext_cmdline', 'ext_popupmenu', - 'ext_tabline', 'ext_wildmenu', 'ext_linegrid', 'ext_hlstate'}, options) + it("ui_options are preserved from older levels", function() + local available_options = {} + for _, option in ipairs(api.ui_options) do + available_options[option] = true + end + -- UI options were versioned from level 4 + for level = 4, stable do + for _, option in ipairs(old_api[level].ui_options) do + if not available_options[option] then + error("UI option "..option.." from stable metadata is missing") + end + end + end end) end) diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index a9d137391e..ddf5575e31 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -14,6 +14,7 @@ local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed local os_name = helpers.os_name local request = helpers.request local source = helpers.source +local next_msg = helpers.next_msg local expect_err = global_helpers.expect_err local format_string = global_helpers.format_string @@ -46,6 +47,15 @@ describe('API', function() request, nil) end) + it('handles errors in async requests', function() + local error_types = meths.get_api_info()[2].error_types + nvim_async("bogus") + eq({'notification', 'nvim_error_event', + {error_types.Exception.id, 'Invalid method: nvim_bogus'}}, next_msg()) + -- error didn't close channel. + eq(2, eval('1+1')) + end) + describe('nvim_command', function() it('works', function() local fname = helpers.tmpname() @@ -1237,7 +1247,7 @@ describe('API', function() describe('nvim_list_uis', function() it('returns empty if --headless', function() - -- --embed implies --headless. + -- Test runner defaults to --headless. eq({}, nvim("list_uis")) end) it('returns attached UIs', function() @@ -1269,4 +1279,16 @@ describe('API', function() end) end) + describe('nvim_create_namespace', function() + it('works', function() + eq({}, meths.get_namespaces()) + eq(1, meths.create_namespace("ns-1")) + eq(2, meths.create_namespace("ns-2")) + eq(1, meths.create_namespace("ns-1")) + eq({["ns-1"]=1, ["ns-2"]=2}, meths.get_namespaces()) + eq(3, meths.create_namespace("")) + eq(4, meths.create_namespace("")) + eq({["ns-1"]=1, ["ns-2"]=2}, meths.get_namespaces()) + end) + end) end) diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 27d7aa11b4..4496e1f644 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -11,6 +11,7 @@ local NIL = helpers.NIL local meth_pcall = helpers.meth_pcall local meths = helpers.meths local command = helpers.command +local expect_err = helpers.expect_err -- check if str is visible at the beginning of some line local function is_visible(str) @@ -31,7 +32,7 @@ local function is_visible(str) return false end -describe('api/win', function() +describe('API/win', function() before_each(clear) describe('get_buf', function() @@ -45,6 +46,21 @@ describe('api/win', function() end) end) + describe('set_buf', function() + it('works', function() + nvim('command', 'new') + local windows = nvim('list_wins') + neq(window('get_buf', windows[2]), window('get_buf', windows[1])) + window('set_buf', windows[2], window('get_buf', windows[1])) + eq(window('get_buf', windows[2]), window('get_buf', windows[1])) + end) + + it('validates args', function() + expect_err('Invalid buffer id$', window, 'set_buf', nvim('get_current_win'), 23) + expect_err('Invalid window id$', window, 'set_buf', 23, nvim('get_current_buf')) + end) + end) + describe('{get,set}_cursor', function() it('works', function() eq({1, 0}, curwin('get_cursor')) diff --git a/test/functional/autocmd/cmdline_spec.lua b/test/functional/autocmd/cmdline_spec.lua index 3f0504d02f..51b7b819e9 100644 --- a/test/functional/autocmd/cmdline_spec.lua +++ b/test/functional/autocmd/cmdline_spec.lua @@ -5,6 +5,7 @@ local clear = helpers.clear local command = helpers.command local eq = helpers.eq local expect = helpers.expect +local eval = helpers.eval local next_msg = helpers.next_msg local feed = helpers.feed local meths = helpers.meths @@ -63,6 +64,7 @@ describe('cmdline autocommands', function() }) command("autocmd CmdlineEnter * echoerr 'FAIL'") command("autocmd CmdlineLeave * echoerr 'very error'") + feed(':') screen:expect([[ | @@ -74,6 +76,7 @@ describe('cmdline autocommands', function() {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} | :^ | ]]) + feed("put ='lorem ipsum'<cr>") screen:expect([[ | @@ -86,6 +89,7 @@ describe('cmdline autocommands', function() {3:Press ENTER or type command to continue}^ | ]]) + -- cmdline was still executed feed('<cr>') screen:expect([[ | @@ -97,6 +101,71 @@ describe('cmdline autocommands', function() {1:~ }| | ]]) + + command("autocmd CmdlineChanged * echoerr 'change erreor'") + + -- history recall still works + feed(":<c-p>") + screen:expect([[ + | + lorem ipsum | + {4: }| + : | + {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} | + :put ='lorem ipsum' | + {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} | + :put ='lorem ipsum'^ | + ]]) + + feed("<left>") + screen:expect([[ + | + lorem ipsum | + {4: }| + : | + {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} | + :put ='lorem ipsum' | + {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} | + :put ='lorem ipsum^' | + ]]) + + -- edit still works + feed(".") + screen:expect([[ + {4: }| + : | + {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} | + :put ='lorem ipsum' | + {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} | + :put ='lorem ipsum.' | + {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} | + :put ='lorem ipsum.^' | + ]]) + + feed('<cr>') + screen:expect([[ + :put ='lorem ipsum' | + {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} | + :put ='lorem ipsum.' | + {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} | + :put ='lorem ipsum.' | + {2:E5500: autocmd has thrown an exception: Vim(echoerr):very error} | + | + {3:Press ENTER or type command to continue}^ | + ]]) + + -- cmdline was still executed + feed('<cr>') + screen:expect([[ + | + lorem ipsum | + ^lorem ipsum. | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) end) it('works with nested cmdline', function() @@ -115,4 +184,41 @@ describe('cmdline autocommands', function() feed('1+2<cr>') eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg()) end) + + it('supports CmdlineChanged' ,function() + command("autocmd CmdlineChanged * call rpcnotify(g:channel, 'CmdlineChanged', v:event, getcmdline())") + feed(':') + eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg()) + feed('l') + eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "l"}}, next_msg()) + feed('e') + eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "le"}}, next_msg()) + feed('t') + eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let"}}, next_msg()) + feed('<space>') + eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let "}}, next_msg()) + feed('x') + eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x"}}, next_msg()) + feed('<space>') + eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x "}}, next_msg()) + feed('=') + eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x ="}}, next_msg()) + feed('<space>') + eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = "}}, next_msg()) + feed('<c-r>=') + eq({'notification', 'CmdlineEnter', {{cmdtype='=', cmdlevel=2}}}, next_msg()) + feed('1') + eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1"}}, next_msg()) + feed('+') + eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+"}}, next_msg()) + feed('1') + eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+1"}}, next_msg()) + feed('<cr>') + eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg()) + eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = "}}, next_msg()) + eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = 2"}}, next_msg()) + feed('<cr>') + eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg()) + eq(2, eval('x')) + end) end) diff --git a/test/functional/autocmd/termclose_spec.lua b/test/functional/autocmd/termclose_spec.lua index db4e5379d0..62eac59b16 100644 --- a/test/functional/autocmd/termclose_spec.lua +++ b/test/functional/autocmd/termclose_spec.lua @@ -6,6 +6,7 @@ local clear, command, nvim, nvim_dir = local eval, eq, retry = helpers.eval, helpers.eq, helpers.retry local ok = helpers.ok +local feed = helpers.feed local iswin = helpers.iswin @@ -87,5 +88,6 @@ describe('TermClose event', function() command('3bdelete!') retry(nil, nil, function() eq('3', eval('g:abuf')) end) + feed('<c-c>:qa!<cr>') end) end) diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua index a40c080a6d..2bbc678a02 100644 --- a/test/functional/clipboard/clipboard_provider_spec.lua +++ b/test/functional/clipboard/clipboard_provider_spec.lua @@ -3,7 +3,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 feed_command, expect, eq, eval = helpers.feed_command, helpers.expect, helpers.eq, helpers.eval +local feed_command, expect, eq, eval, source = helpers.feed_command, helpers.expect, helpers.eq, helpers.eval, helpers.source local command = helpers.command local meths = helpers.meths @@ -147,6 +147,93 @@ describe('clipboard', function() eq('clippy!', eval('provider#clipboard#Executable()')) eq('', eval('provider#clipboard#Error()')) end) + + it('g:clipboard using VimL functions', function() + -- Implements a fake clipboard provider. cache_enabled is meaningless here. + source([[let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { + \ '+': {lines, regtype -> extend(g:, {'dummy_clipboard_plus': [lines, regtype]}) }, + \ '*': {lines, regtype -> extend(g:, {'dummy_clipboard_star': [lines, regtype]}) }, + \ }, + \ 'paste': { + \ '+': {-> get(g:, 'dummy_clipboard_plus', [])}, + \ '*': {-> get(g:, 'dummy_clipboard_star', [])}, + \ }, + \ 'cache_enabled': 1, + \}]]) + + eq('', eval('provider#clipboard#Error()')) + eq('custom', eval('provider#clipboard#Executable()')) + + eq('', eval("getreg('*')")) + eq('', eval("getreg('+')")) + + command('call setreg("*", "star")') + command('call setreg("+", "plus")') + eq('star', eval("getreg('*')")) + eq('plus', eval("getreg('+')")) + + command('call setreg("*", "star", "v")') + eq({{'star'}, 'v'}, eval("g:dummy_clipboard_star")) + command('call setreg("*", "star", "V")') + eq({{'star', ''}, 'V'}, eval("g:dummy_clipboard_star")) + command('call setreg("*", "star", "b")') + eq({{'star', ''}, 'b'}, eval("g:dummy_clipboard_star")) + end) + + describe('g:clipboard[paste] VimL function', function() + it('can return empty list for empty clipboard', function() + source([[let g:dummy_clipboard = [] + let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { '*': {lines, regtype -> 0} }, + \ 'paste': { '*': {-> g:dummy_clipboard} }, + \}]]) + eq('', eval('provider#clipboard#Error()')) + eq('custom', eval('provider#clipboard#Executable()')) + eq('', eval("getreg('*')")) + end) + + it('can return a list with a single string', function() + source([=[let g:dummy_clipboard = ['hello'] + let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { '*': {lines, regtype -> 0} }, + \ 'paste': { '*': {-> g:dummy_clipboard} }, + \}]=]) + eq('', eval('provider#clipboard#Error()')) + eq('custom', eval('provider#clipboard#Executable()')) + + eq('hello', eval("getreg('*')")) + source([[let g:dummy_clipboard = [''] ]]) + eq('', eval("getreg('*')")) + end) + + it('can return a list of lines if a regtype is provided', function() + source([=[let g:dummy_clipboard = [['hello'], 'v'] + let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { '*': {lines, regtype -> 0} }, + \ 'paste': { '*': {-> g:dummy_clipboard} }, + \}]=]) + eq('', eval('provider#clipboard#Error()')) + eq('custom', eval('provider#clipboard#Executable()')) + eq('hello', eval("getreg('*')")) + end) + + it('can return a list of lines instead of [lines, regtype]', function() + source([=[let g:dummy_clipboard = ['hello', 'v'] + let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { '*': {lines, regtype -> 0} }, + \ 'paste': { '*': {-> g:dummy_clipboard} }, + \}]=]) + eq('', eval('provider#clipboard#Error()')) + eq('custom', eval('provider#clipboard#Executable()')) + eq('hello\nv', eval("getreg('*')")) + end) + end) end) describe('clipboard', function() diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index 34168e10c2..eb02610df0 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -17,6 +17,7 @@ local pathroot = helpers.pathroot local nvim_set = helpers.nvim_set local expect_twostreams = helpers.expect_twostreams local expect_msg_seq = helpers.expect_msg_seq +local expect_err = helpers.expect_err local Screen = require('test.functional.ui.screen') -- Kill process with given pid @@ -115,6 +116,17 @@ describe('jobs', function() ok(string.find(err, "E475: Invalid argument: expected valid directory$") ~= nil) end) + it('produces error when using non-executable `cwd`', function() + if iswin() then return end -- N/A for Windows + + local dir = 'Xtest_not_executable_dir' + mkdir(dir) + funcs.setfperm(dir, 'rw-------') + expect_err('E475: Invalid argument: expected valid directory$', nvim, + 'command', "call jobstart('pwd', {'cwd': '" .. dir .. "'})") + rmdir(dir) + end) + it('returns 0 when it fails to start', function() eq("", eval("v:errmsg")) feed_command("let g:test_jobid = jobstart([])") diff --git a/test/functional/core/main_spec.lua b/test/functional/core/main_spec.lua index cd396ef820..a0981e9207 100644 --- a/test/functional/core/main_spec.lua +++ b/test/functional/core/main_spec.lua @@ -77,8 +77,8 @@ describe('Command-line option', function() | | ]], { - [1] = {foreground = 4210943, special = Screen.colors.Grey0}, - [2] = {special = Screen.colors.Grey0, bold = true, reverse = true} + [1] = {foreground = 4210943}, + [2] = {bold = true, reverse = true} }) feed('i:cq<CR>') screen:expect([[ diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua index 15121261c7..8edb8fc014 100644 --- a/test/functional/core/startup_spec.lua +++ b/test/functional/core/startup_spec.lua @@ -7,12 +7,17 @@ local eq = helpers.eq local eval = helpers.eval local feed = helpers.feed local funcs = helpers.funcs +local mkdir = helpers.mkdir local nvim_prog = helpers.nvim_prog local nvim_set = helpers.nvim_set local read_file = helpers.read_file local retry = helpers.retry +local rmdir = helpers.rmdir +local set_session = helpers.set_session local sleep = helpers.sleep +local spawn = helpers.spawn local iswin = helpers.iswin +local write_file = helpers.write_file describe('startup', function() before_each(function() @@ -204,3 +209,57 @@ describe('startup', function() end) end) +describe('sysinit', function() + local xdgdir = 'Xxdg' + local vimdir = 'Xvim' + local xhome = 'Xhome' + local pathsep = helpers.get_pathsep() + local argv = { + nvim_prog, '--headless', '--embed', '-i', 'NONE', '-n', + '--cmd', 'set nomore undodir=. directory=. belloff=' + } + + before_each(function() + rmdir(xdgdir) + rmdir(vimdir) + rmdir(xhome) + + mkdir(xdgdir) + mkdir(xdgdir .. pathsep .. 'nvim') + write_file(table.concat({xdgdir, 'nvim', 'sysinit.vim'}, pathsep), [[ + let g:loaded = get(g:, "loaded", 0) + 1 + let g:xdg = 1 + ]]) + + mkdir(vimdir) + write_file(table.concat({vimdir, 'sysinit.vim'}, pathsep), [[ + let g:loaded = get(g:, "loaded", 0) + 1 + let g:vim = 1 + ]]) + + mkdir(xhome) + end) + after_each(function() + rmdir(xdgdir) + rmdir(vimdir) + rmdir(xhome) + end) + + it('prefers XDG_CONFIG_DIRS over VIM', function() + set_session(spawn(argv, nil, + { 'HOME='..xhome, + 'XDG_CONFIG_DIRS='..xdgdir, + 'VIM='..vimdir })) + eq('loaded 1 xdg 1 vim 0', + eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))')) + end) + + it('uses VIM if XDG_CONFIG_DIRS unset', function() + set_session(spawn(argv, nil, + { 'HOME='..xhome, + 'XDG_CONFIG_DIRS=', + 'VIM='..vimdir })) + eq('loaded 1 xdg 0 vim 1', + eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))')) + end) +end) diff --git a/test/functional/eval/input_spec.lua b/test/functional/eval/input_spec.lua index 8c65297ac6..e774b939f7 100644 --- a/test/functional/eval/input_spec.lua +++ b/test/functional/eval/input_spec.lua @@ -8,6 +8,7 @@ local clear = helpers.clear local source = helpers.source local command = helpers.command local exc_exec = helpers.exc_exec +local nvim_async = helpers.nvim_async local screen @@ -59,6 +60,7 @@ before_each(function() RBP3={background=Screen.colors.Green}, RBP4={background=Screen.colors.Blue}, SEP={bold = true, reverse = true}, + CONFIRM={bold = true, foreground = Screen.colors.SeaGreen4}, }) end) @@ -439,3 +441,43 @@ describe('inputdialog()', function() ]]) end) end) + +describe('confirm()', function() + it("shows dialog even if :silent #8788", function() + command("autocmd BufNewFile * call confirm('test')") + + local function check_and_clear(edit_line) + screen:expect([[ + | + {SEP: }| + ]]..edit_line..[[ + {CONFIRM:test} | + {CONFIRM:[O]k: }^ | + ]]) + feed('<cr>') + command('redraw') + command('bdelete!') + end + + -- With shortmess-=F + command('set shortmess-=F') + feed(':edit foo<cr>') + check_and_clear('"foo" [New File] |\n') + + -- With shortmess+=F + command('set shortmess+=F') + feed(':edit foo<cr>') + check_and_clear(':edit foo |\n') + + -- With :silent + feed(':silent edit foo<cr>') + check_and_clear(':silent edit foo |\n') + + -- With API (via eval/VimL) call and shortmess+=F + feed(':call nvim_command("edit x")<cr>') + check_and_clear(':call nvim_command("edit |\n') + + nvim_async('command', 'edit x') + check_and_clear(' |\n') + end) +end) diff --git a/test/functional/eval/timer_spec.lua b/test/functional/eval/timer_spec.lua index c945f12e0e..124b9625c3 100644 --- a/test/functional/eval/timer_spec.lua +++ b/test/functional/eval/timer_spec.lua @@ -82,7 +82,7 @@ describe('timers', function() run(nil, nil, nil, 300) feed("c") local count = eval("g:val") - assert(count >= 4, 'expected count >= 4, got: '..tostring(count)) + assert(count >= 3, 'expected count >= 3, got: '..tostring(count)) eq(99, eval("g:c")) end) @@ -144,8 +144,8 @@ describe('timers', function() local count2 = eval("g:val") -- when count is eval:ed after timer_stop this should be non-racy eq(count, count2) - assert(4 <= count and count <= 7, - 'expected (4 <= count <= 7), got: '..tostring(count)) + assert(3 <= count and count <= 7, + 'expected (3 <= count <= 7), got: '..tostring(count)) end) it('can be stopped from the handler', function() @@ -172,8 +172,8 @@ describe('timers', function() let g:val2 += 1 endfunc ]]) - command("call timer_start(50, 'MyHandler', {'repeat': 3})") - command("call timer_start(100, 'MyHandler2', {'repeat': 2})") + command("call timer_start(20, 'MyHandler', {'repeat': 3})") + command("call timer_start(40, 'MyHandler2', {'repeat': 2})") run(nil, nil, nil, 300) eq(3,eval("g:val")) eq(2,eval("g:val2")) diff --git a/test/functional/ex_cmds/cmd_map_spec.lua b/test/functional/ex_cmds/cmd_map_spec.lua index 67b3ab49d6..a5ce1abff7 100644 --- a/test/functional/ex_cmds/cmd_map_spec.lua +++ b/test/functional/ex_cmds/cmd_map_spec.lua @@ -29,6 +29,9 @@ describe('mappings with <Cmd>', function() [5] = {background = Screen.colors.LightGrey}, [6] = {foreground = Screen.colors.Blue1}, [7] = {bold = true, reverse = true}, + [8] = {background = Screen.colors.WebGray}, + [9] = {background = Screen.colors.LightMagenta}, + [10] = {foreground = Screen.colors.Red}, }) screen:attach() @@ -656,6 +659,37 @@ describe('mappings with <Cmd>', function() eq('n', eval('mode(1)')) end) + it('works in insert completion (Ctrl-X) mode', function() + feed('os<c-x><c-n>') + screen:expect([[ + some short lines | + some^ | + {8:some } | + {9:short }{1: }| + {1:~ }| + {1:~ }| + {1:~ }| + {4:-- Keyword Local completion (^N^P) }{3:match 1 of 2} | + ]]) + + feed('<f3>') + eq('ic', eval('m')) + + -- ensure a redraw, this would have moved the cursor + -- instead if CTRL-X mode was left. + feed('<up>') + screen:expect([[ + some short lines | + some^ | + {9:some } | + {9:short }{1: }| + {1:~ }| + {1:~ }| + {1:~ }| + {4:-- Keyword Local completion (^N^P) }{10:Back at original} | + ]]) + end) + it('works in cmdline mode', function() feed(':text<F3>') eq('c', eval('m')) diff --git a/test/functional/ex_cmds/debug_spec.lua b/test/functional/ex_cmds/debug_spec.lua index 5dad8098ea..a4d381d3f1 100644 --- a/test/functional/ex_cmds/debug_spec.lua +++ b/test/functional/ex_cmds/debug_spec.lua @@ -7,7 +7,7 @@ describe(':debug', function() local screen before_each(function() clear() - screen = Screen.new(50, 14) + screen = Screen.new(30, 14) screen:set_default_attr_ids({ [1] = {bold = true, foreground = Screen.colors.Blue1}, [2] = {bold = true, reverse = true}, @@ -19,92 +19,92 @@ describe(':debug', function() it('scrolls messages correctly', function() feed(':echoerr bork<cr>') screen:expect([[ - | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {2: }| - {3:E121: Undefined variable: bork} | - {3:E15: Invalid expression: bork} | - {4:Press ENTER or type command to continue}^ | + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2: }| + {3:E121: Undefined variable: bork}| + | + {4:Press ENTER or type command to}| + {4: continue}^ | ]]) feed(':debug echo "aa"| echo "bb"<cr>') screen:expect([[ - | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {2: }| - {3:E121: Undefined variable: bork} | - {3:E15: Invalid expression: bork} | - Entering Debug mode. Type "cont" to continue. | - cmd: echo "aa"| echo "bb" | - >^ | + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {2: }| + {3:E121: Undefined variable: bork}| + | + {4:Press ENTER or type command to}| + Entering Debug mode. Type "co| + nt" to continue. | + cmd: echo "aa"| echo "bb" | + >^ | ]]) feed('step<cr>') screen:expect([[ - | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {2: }| - {3:E121: Undefined variable: bork} | - {3:E15: Invalid expression: bork} | - Entering Debug mode. Type "cont" to continue. | - cmd: echo "aa"| echo "bb" | - >step | - aa | - cmd: echo "bb" | - >^ | + | + {1:~ }| + {1:~ }| + {2: }| + {3:E121: Undefined variable: bork}| + | + {4:Press ENTER or type command to}| + Entering Debug mode. Type "co| + nt" to continue. | + cmd: echo "aa"| echo "bb" | + >step | + aa | + cmd: echo "bb" | + >^ | ]]) feed('step<cr>') screen:expect([[ - | - {1:~ }| - {1:~ }| - {2: }| - {3:E121: Undefined variable: bork} | - {3:E15: Invalid expression: bork} | - Entering Debug mode. Type "cont" to continue. | - cmd: echo "aa"| echo "bb" | - >step | - aa | - cmd: echo "bb" | - >step | - bb | - {4:Press ENTER or type command to continue}^ | + {2: }| + {3:E121: Undefined variable: bork}| + | + {4:Press ENTER or type command to}| + Entering Debug mode. Type "co| + nt" to continue. | + cmd: echo "aa"| echo "bb" | + >step | + aa | + cmd: echo "bb" | + >step | + bb | + {4:Press ENTER or type command to}| + {4: continue}^ | ]]) feed('<cr>') screen:expect([[ - ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - | + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | ]]) end) end) diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua index 577a26178a..3fcffd422f 100644 --- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua +++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua @@ -11,6 +11,7 @@ local ok = helpers.ok local rmdir = helpers.rmdir local set_session = helpers.set_session local spawn = helpers.spawn +local nvim_async = helpers.nvim_async describe(':recover', function() before_each(clear) @@ -150,5 +151,12 @@ describe('swapfile detection', function() feed('e') -- Chose "Edit" at the swap dialog. feed('<c-c>') screen2:expect(expected_no_dialog) + + -- With API call and shortmess+=F + nvim_async('command', 'edit %') + screen2:expect{any=[[Found a swap file by the name ".*]] + ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]} + feed('e') -- Chose "Edit" at the swap dialog. + feed('<c-c>') end) end) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index a51eca7fdc..272b80466c 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -1,3 +1,4 @@ +require('vim.compat') require('coxpcall') local luv = require('luv') local lfs = require('lfs') @@ -300,8 +301,10 @@ end -- Calls fn() until it succeeds, up to `max` times or until `max_ms` -- milliseconds have passed. local function retry(max, max_ms, fn) + assert(max == nil or max > 0) + assert(max_ms == nil or max_ms > 0) local tries = 1 - local timeout = (max_ms and max_ms > 0) and max_ms or 10000 + local timeout = (max_ms and max_ms or 10000) local start_time = luv.now() while true do local status, result = pcall(fn) @@ -755,6 +758,14 @@ return function(after_each) end check_logs() check_cores('build/bin/nvim') + if session then + local msg = session:next_message(0) + if msg then + if msg[1] == "notification" and msg[2] == "nvim_error_event" then + error(msg[3][2]) + end + end + end end) end return module diff --git a/test/functional/legacy/108_backtrace_debug_commands_spec.lua b/test/functional/legacy/108_backtrace_debug_commands_spec.lua index 9ace4ef093..1c1a2095d5 100644 --- a/test/functional/legacy/108_backtrace_debug_commands_spec.lua +++ b/test/functional/legacy/108_backtrace_debug_commands_spec.lua @@ -121,7 +121,6 @@ describe('108', function() Error detected while processing function Foo[2]..Bar[2]..Bazz: line 3: E121: Undefined variable: var3 - E15: Invalid expression: var3 here var3 is defined with "another var": another var @@ -129,7 +128,6 @@ describe('108', function() Error detected while processing function Foo[2]..Bar: line 3: E121: Undefined variable: var2 - E15: Invalid expression: var2 here var2 is defined with 10: 10 diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua index 93ac3ae017..5e73690986 100644 --- a/test/functional/provider/python3_spec.lua +++ b/test/functional/provider/python3_spec.lua @@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local eval, command, feed = helpers.eval, helpers.command, helpers.feed local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert local expect, write_file = helpers.expect, helpers.write_file +local expect_err = helpers.expect_err local feed_command = helpers.feed_command local source = helpers.source local missing_provider = helpers.missing_provider @@ -9,7 +10,11 @@ local missing_provider = helpers.missing_provider do clear() if missing_provider('python3') then - pending('Python 3 (or the neovim module) is broken/missing', function() end) + it(':python3 reports E319 if provider is missing', function() + expect_err([[Vim%(python3%):E319: No "python3" provider found.*]], + command, 'python3 print("foo")') + end) + pending('Python 3 (or the pynvim module) is broken/missing', function() end) return end end diff --git a/test/functional/provider/python_spec.lua b/test/functional/provider/python_spec.lua index 2fa74e9644..15df76d2f6 100644 --- a/test/functional/provider/python_spec.lua +++ b/test/functional/provider/python_spec.lua @@ -8,6 +8,7 @@ local funcs = helpers.funcs local meths = helpers.meths local insert = helpers.insert local expect = helpers.expect +local expect_err = helpers.expect_err local command = helpers.command local exc_exec = helpers.exc_exec local write_file = helpers.write_file @@ -17,7 +18,11 @@ local missing_provider = helpers.missing_provider do clear() if missing_provider('python') then - pending('Python 2 (or the neovim module) is broken/missing', function() end) + it(':python reports E319 if provider is missing', function() + expect_err([[Vim%(python%):E319: No "python" provider found.*]], + command, 'python print("foo")') + end) + pending('Python 2 (or the pynvim module) is broken/missing', function() end) return end end diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua index e049ac7c41..40cfe80b50 100644 --- a/test/functional/provider/ruby_spec.lua +++ b/test/functional/provider/ruby_spec.lua @@ -6,6 +6,7 @@ local curbufmeths = helpers.curbufmeths local eq = helpers.eq local eval = helpers.eval local expect = helpers.expect +local expect_err = helpers.expect_err local feed = helpers.feed local feed_command = helpers.feed_command local funcs = helpers.funcs @@ -17,6 +18,10 @@ local write_file = helpers.write_file do clear() if missing_provider('ruby') then + it(':ruby reports E319 if provider is missing', function() + expect_err([[Vim%(ruby%):E319: No "ruby" provider found.*]], + command, 'ruby puts "foo"') + end) pending("Missing neovim RubyGem.", function() end) return end diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua index bd24b9785d..ae8d4704e4 100644 --- a/test/functional/terminal/helpers.lua +++ b/test/functional/terminal/helpers.lua @@ -52,7 +52,7 @@ local function screen_setup(extra_rows, command, cols) [7] = {foreground = 130}, [8] = {foreground = 15, background = 1}, -- error message [9] = {foreground = 4}, - [10] = {foreground = 2}, -- "Press ENTER" in embedded :terminal session. + [10] = {foreground = 121}, -- "Press ENTER" in embedded :terminal session. }) screen:attach({rgb=false}) diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua index fddc0bbb71..f33959c58d 100644 --- a/test/functional/terminal/highlight_spec.lua +++ b/test/functional/terminal/highlight_spec.lua @@ -120,7 +120,7 @@ describe('terminal window highlighting with custom palette', function() clear() screen = Screen.new(50, 7) screen:set_default_attr_ids({ - [1] = {foreground = 1193046, special = Screen.colors.Black}, + [1] = {foreground = tonumber('0x123456')}, [2] = {foreground = 12}, [3] = {bold = true, reverse = true}, [5] = {background = 11}, diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 365bd2a0be..1b4441f25f 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -134,15 +134,17 @@ describe('tui', function() feed_data('\022\007') -- ctrl+g feed_data('\022\022') -- ctrl+v feed_data('\022\013') -- ctrl+m + local attrs = screen:get_default_attr_ids() + attrs[11] = {foreground = 81} screen:expect([[ - {9:^G^V^M}{1: } | + {11:^G^V^M}{1: } | {4:~ }| {4:~ }| {4:~ }| {5:[No Name] [+] }| {3:-- INSERT --} | {3:-- TERMINAL --} | - ]]) + ]], attrs) end) it('automatically sends <Paste> for bracketed paste sequences', function() @@ -205,14 +207,14 @@ describe('tui', function() screen:set_option('rgb', true) screen:set_default_attr_ids({ [1] = {reverse = true}, - [2] = {foreground = 13, special = Screen.colors.Grey0}, - [3] = {bold = true, reverse = true, special = Screen.colors.Grey0}, + [2] = {foreground = 13}, + [3] = {bold = true, reverse = true}, [4] = {bold = true}, - [5] = {special = Screen.colors.Grey0, reverse = true, foreground = 4}, - [6] = {foreground = 4, special = Screen.colors.Grey0}, - [7] = {special = Screen.colors.Grey0, reverse = true, foreground = Screen.colors.SeaGreen4}, - [8] = {foreground = Screen.colors.SeaGreen4, special = Screen.colors.Grey0}, - [9] = {special = Screen.colors.Grey0, bold = true, foreground = Screen.colors.Blue1}, + [5] = {reverse = true, foreground = 4}, + [6] = {foreground = 4}, + [7] = {reverse = true, foreground = Screen.colors.SeaGreen4}, + [8] = {foreground = Screen.colors.SeaGreen4}, + [9] = {bold = true, foreground = Screen.colors.Blue1}, }) feed_data(':hi SpecialKey ctermfg=3 guifg=SeaGreen\n') diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua index 07cc8020a5..fecffe3295 100644 --- a/test/functional/terminal/window_split_tab_spec.lua +++ b/test/functional/terminal/window_split_tab_spec.lua @@ -7,6 +7,7 @@ local command = helpers.command local eq = helpers.eq local eval = helpers.eval local iswin = helpers.iswin +local retry = helpers.retry describe('terminal', function() local screen @@ -67,17 +68,22 @@ describe('terminal', function() end) it('forwards resize request to the program', function() - feed([[<C-\><C-N>:]]) -- Go to cmdline-mode, so cursor is at bottom. - screen:try_resize(screen._width - 3, screen._height - 2) + feed([[<C-\><C-N>G:]]) -- Go to cmdline-mode, so cursor is at bottom. + local w1, h1 = screen._width - 3, screen._height - 2 + local w2, h2 = w1 - 6, h1 - 3 if iswin() then - -- win: less-precise test, SIGWINCH is noisy there. #7506 - screen:expect{any='rows: 7, cols: 47'} - screen:try_resize(screen._width - 6, screen._height - 3) - screen:expect{any='rows: 4, cols: 41'} + -- win: SIGWINCH is unreliable, use a weaker test. #7506 + retry(3, 30000, function() + screen:try_resize(w1, h1) + screen:expect{any='rows: 7, cols: 47'} + screen:try_resize(w2, h2) + screen:expect{any='rows: 4, cols: 41'} + end) return end + screen:try_resize(w1, h1) screen:expect([[ tty ready | rows: 7, cols: 47 | @@ -88,7 +94,7 @@ describe('terminal', function() | :^ | ]]) - screen:try_resize(screen._width - 6, screen._height - 3) + screen:try_resize(w2, h2) screen:expect([[ tty ready | rows: 7, cols: 47 | diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua index 95c9427399..bcccef84b6 100644 --- a/test/functional/ui/bufhl_spec.lua +++ b/test/functional/ui/bufhl_spec.lua @@ -3,6 +3,7 @@ local Screen = require('test.functional.ui.screen') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local command, neq = helpers.command, helpers.neq +local meths = helpers.meths local curbufmeths, eq = helpers.curbufmeths, helpers.eq describe('Buffer highlighting', function() @@ -37,8 +38,8 @@ describe('Buffer highlighting', function() screen:detach() end) - local add_hl = curbufmeths.add_highlight - local clear_hl = curbufmeths.clear_highlight + local add_highlight = curbufmeths.add_highlight + local clear_namespace = curbufmeths.clear_namespace it('works', function() insert([[ @@ -57,8 +58,8 @@ describe('Buffer highlighting', function() | ]]) - add_hl(-1, "String", 0 , 10, 14) - add_hl(-1, "Statement", 1 , 5, -1) + add_highlight(-1, "String", 0 , 10, 14) + add_highlight(-1, "Statement", 1 , 5, -1) screen:expect([[ these are {2:some} lines | @@ -83,7 +84,7 @@ describe('Buffer highlighting', function() | ]]) - clear_hl(-1, 0, -1) + clear_namespace(-1, 0, -1) screen:expect([[ these are some lines | ^ | @@ -96,7 +97,7 @@ describe('Buffer highlighting', function() ]]) end) - describe('support adding multiple sources', function() + describe('support using multiple namespaces', function() local id1, id2 before_each(function() insert([[ @@ -106,21 +107,21 @@ describe('Buffer highlighting', function() from different sources]]) command("hi ImportantWord gui=bold cterm=bold") - id1 = add_hl(0, "ImportantWord", 0, 2, 8) - add_hl(id1, "ImportantWord", 1, 12, -1) - add_hl(id1, "ImportantWord", 2, 0, 9) - add_hl(id1, "ImportantWord", 3, 5, 14) + id1 = add_highlight(0, "ImportantWord", 0, 2, 8) + add_highlight(id1, "ImportantWord", 1, 12, -1) + add_highlight(id1, "ImportantWord", 2, 0, 9) + add_highlight(id1, "ImportantWord", 3, 5, 14) -- add_highlight can be called like this to get a new source -- without adding any highlight - id2 = add_hl(0, "", 0, 0, 0) + id2 = add_highlight(0, "", 0, 0, 0) neq(id1, id2) - add_hl(id2, "Special", 0, 2, 8) - add_hl(id2, "Identifier", 1, 3, 8) - add_hl(id2, "Special", 1, 14, 20) - add_hl(id2, "Underlined", 2, 6, 12) - add_hl(id2, "Underlined", 3, 0, 9) + add_highlight(id2, "Special", 0, 2, 8) + add_highlight(id2, "Identifier", 1, 3, 8) + add_highlight(id2, "Special", 1, 14, 20) + add_highlight(id2, "Underlined", 2, 6, 12) + add_highlight(id2, "Underlined", 3, 0, 9) screen:expect([[ a {5:longer} example | @@ -135,7 +136,21 @@ describe('Buffer highlighting', function() end) it('and clearing the first added', function() - clear_hl(id1, 0, -1) + clear_namespace(id1, 0, -1) + screen:expect([[ + a {4:longer} example | + in {6:order} to de{4:monstr}ate | + combin{9:ing hi}ghlights | + {9:from diff}erent source^s | + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]) + end) + + it('and clearing using deprecated name', function() + curbufmeths.clear_highlight(id1, 0, -1) screen:expect([[ a {4:longer} example | in {6:order} to de{4:monstr}ate | @@ -149,7 +164,7 @@ describe('Buffer highlighting', function() end) it('and clearing the second added', function() - clear_hl(id2, 0, -1) + clear_namespace(id2, 0, -1) screen:expect([[ a {7:longer} example | in order to {7:demonstrate} | @@ -163,9 +178,9 @@ describe('Buffer highlighting', function() end) it('and clearing line ranges', function() - clear_hl(-1, 0, 1) - clear_hl(id1, 1, 2) - clear_hl(id2, 2, -1) + clear_namespace(-1, 0, 1) + clear_namespace(id1, 1, 2) + clear_namespace(id2, 2, -1) screen:expect([[ a longer example | in {6:order} to de{4:monstr}ate | @@ -208,9 +223,9 @@ describe('Buffer highlighting', function() it('prioritizes latest added highlight', function() insert([[ three overlapping colors]]) - add_hl(0, "Identifier", 0, 6, 17) - add_hl(0, "String", 0, 14, 23) - local id = add_hl(0, "Special", 0, 0, 9) + add_highlight(0, "Identifier", 0, 6, 17) + add_highlight(0, "String", 0, 14, 23) + local id = add_highlight(0, "Special", 0, 0, 9) screen:expect([[ {4:three ove}{6:rlapp}{2:ing color}^s | @@ -223,7 +238,7 @@ describe('Buffer highlighting', function() | ]]) - clear_hl(id, 0, 1) + clear_namespace(id, 0, 1) screen:expect([[ three {6:overlapp}{2:ing color}^s | {1:~ }| @@ -239,8 +254,8 @@ describe('Buffer highlighting', function() it('works with multibyte text', function() insert([[ Ta båten över sjön!]]) - add_hl(-1, "Identifier", 0, 3, 9) - add_hl(-1, "String", 0, 16, 21) + add_highlight(-1, "Identifier", 0, 3, 9) + add_highlight(-1, "String", 0, 16, 21) screen:expect([[ Ta {6:båten} över {2:sjön}^! | @@ -257,7 +272,7 @@ describe('Buffer highlighting', function() it('works with new syntax groups', function() insert([[ fancy code in a new fancy language]]) - add_hl(-1, "FancyLangItem", 0, 0, 5) + add_highlight(-1, "FancyLangItem", 0, 0, 5) screen:expect([[ fancy code in a new fancy languag^e | {1:~ }| @@ -321,7 +336,7 @@ describe('Buffer highlighting', function() | ]]) - clear_hl(id1, 0, -1) + clear_namespace(id1, 0, -1) screen:expect([[ ^1 + 2 | 3 + | @@ -449,7 +464,7 @@ describe('Buffer highlighting', function() | ]]) - clear_hl(-1, 0, -1) + clear_namespace(-1, 0, -1) screen:expect([[ ^1 + 2{1:$} | 3 +{1:$} | @@ -503,4 +518,13 @@ describe('Buffer highlighting', function() end) end) + it('and virtual text use the same namespace counter', function() + local set_virtual_text = curbufmeths.set_virtual_text + eq(1, add_highlight(0, "String", 0 , 0, -1)) + eq(2, set_virtual_text(0, 0, {{"= text", "Comment"}}, {})) + eq(3, meths.create_namespace("my-ns")) + eq(4, add_highlight(0, "String", 0 , 0, -1)) + eq(5, set_virtual_text(0, 0, {{"= text", "Comment"}}, {})) + eq(6, meths.create_namespace("other-ns")) + end) end) diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index 0ebb62f78f..5d112d7f35 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -117,60 +117,60 @@ local function test_cmdline(linegrid) end) it('but not with scrolled messages', function() - screen:try_resize(50,10) + screen:try_resize(35,10) feed(':echoerr doesnotexist<cr>') screen:expect{grid=[[ - | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {3: }| - {4:E121: Undefined variable: doesnotexist} | - {4:E15: Invalid expression: doesnotexist} | - {5:Press ENTER or type command to continue}^ | + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {3: }| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {5:inue}^ | ]]} feed(':echoerr doesnotexist<cr>') screen:expect{grid=[[ - | - {1:~ }| - {1:~ }| - {1:~ }| - {3: }| - {4:E121: Undefined variable: doesnotexist} | - {4:E15: Invalid expression: doesnotexist} | - {4:E121: Undefined variable: doesnotexist} | - {4:E15: Invalid expression: doesnotexist} | - {5:Press ENTER or type command to continue}^ | + | + {1:~ }| + {3: }| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {5:inue}^ | ]]} feed(':echoerr doesnotexist<cr>') screen:expect{grid=[[ - | - {1:~ }| - {3: }| - {4:E121: Undefined variable: doesnotexist} | - {4:E15: Invalid expression: doesnotexist} | - {4:E121: Undefined variable: doesnotexist} | - {4:E15: Invalid expression: doesnotexist} | - {4:E121: Undefined variable: doesnotexist} | - {4:E15: Invalid expression: doesnotexist} | - {5:Press ENTER or type command to continue}^ | + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {4:E121: Undefined variable: doesnotex}| + {4:ist} | + {5:Press ENTER or type command to cont}| + {5:inue}^ | ]]} feed('<cr>') screen:expect{grid=[[ - ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| - {3:n }| - | + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {3:n }| + | ]]} end) end) diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua new file mode 100644 index 0000000000..8e6756e550 --- /dev/null +++ b/test/functional/ui/diff_spec.lua @@ -0,0 +1,959 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') + +local feed = helpers.feed +local clear = helpers.clear +local write_file = helpers.write_file + +describe('Diff mode screen', function() + local fname = 'Xtest-functional-diff-screen-1' + local fname_2 = fname .. '.2' + local screen + + local reread = function() + feed(':e<cr><c-w>w:e<cr><c-w>w') + end + + setup(function() + clear() + os.remove(fname) + os.remove(fname_2) + end) + + teardown(function() + os.remove(fname) + os.remove(fname_2) + end) + + before_each(function() + clear() + feed(':e ' .. fname_2 .. '<cr>') + feed(':vnew ' .. fname .. '<cr>') + feed(':diffthis<cr>') + feed('<c-w>w:diffthis<cr><c-w>w') + + screen = Screen.new(40, 16) + screen:attach() + screen:set_default_attr_ids({ + [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray}, + [2] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1}, + [3] = {reverse = true}, + [4] = {background = Screen.colors.LightBlue}, + [5] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey}, + [6] = {bold = true, foreground = Screen.colors.Blue1}, + [7] = {bold = true, reverse = true}, + [8] = {bold = true, background = Screen.colors.Red}, + [9] = {background = Screen.colors.LightMagenta}, + }) + end) + + it('Add a line in beginning of file 2', function() + write_file(fname, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false) + write_file(fname_2, "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false) + reread() + + feed(':set diffopt=filler<cr>') + screen:expect([[ + {1: }{2:------------------}{3:│}{1: }{4:0 }| + {1: }^1 {3:│}{1: }1 | + {1: }2 {3:│}{1: }2 | + {1: }3 {3:│}{1: }3 | + {1: }4 {3:│}{1: }4 | + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1:+ }{5:+-- 4 lines: 7···}{3:│}{1:+ }{5:+-- 4 lines: 7··}| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler | + ]]) + + feed(':set diffopt+=internal<cr>') + screen:expect([[ + {1: }{2:------------------}{3:│}{1: }{4:0 }| + {1: }^1 {3:│}{1: }1 | + {1: }2 {3:│}{1: }2 | + {1: }3 {3:│}{1: }3 | + {1: }4 {3:│}{1: }4 | + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1:+ }{5:+-- 4 lines: 7···}{3:│}{1:+ }{5:+-- 4 lines: 7··}| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt+=internal | + ]]) + end) + + it('Add a line in beginning of file 1', function() + write_file(fname, "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false) + write_file(fname_2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false) + reread() + + feed(":set diffopt=filler<cr>") + screen:expect([[ + {1: }{4:^0 }{3:│}{1: }{2:-----------------}| + {1: }1 {3:│}{1: }1 | + {1: }2 {3:│}{1: }2 | + {1: }3 {3:│}{1: }3 | + {1: }4 {3:│}{1: }4 | + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1:+ }{5:+-- 4 lines: 7···}{3:│}{1:+ }{5:+-- 4 lines: 7··}| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler | + ]]) + + feed(":set diffopt+=internal<cr>") + screen:expect([[ + {1: }{4:^0 }{3:│}{1: }{2:-----------------}| + {1: }1 {3:│}{1: }1 | + {1: }2 {3:│}{1: }2 | + {1: }3 {3:│}{1: }3 | + {1: }4 {3:│}{1: }4 | + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1:+ }{5:+-- 4 lines: 7···}{3:│}{1:+ }{5:+-- 4 lines: 7··}| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt+=internal | + ]]) + end) + + it('Add a line at the end of file 2', function() + write_file(fname, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false) + write_file(fname_2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", false) + reread() + + feed(":set diffopt=filler<cr>") + screen:expect([[ + {1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}| + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1: }7 {3:│}{1: }7 | + {1: }8 {3:│}{1: }8 | + {1: }9 {3:│}{1: }9 | + {1: }10 {3:│}{1: }10 | + {1: }{2:------------------}{3:│}{1: }{4:11 }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler | + ]]) + + feed(":set diffopt+=internal<cr>") + screen:expect([[ + {1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}| + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1: }7 {3:│}{1: }7 | + {1: }8 {3:│}{1: }8 | + {1: }9 {3:│}{1: }9 | + {1: }10 {3:│}{1: }10 | + {1: }{2:------------------}{3:│}{1: }{4:11 }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt+=internal | + ]]) + end) + + it('Add a line at the end of file 1', function() + write_file(fname, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", false) + write_file(fname_2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false) + reread() + + feed(":set diffopt=filler<cr>") + screen:expect([[ + {1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}| + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1: }7 {3:│}{1: }7 | + {1: }8 {3:│}{1: }8 | + {1: }9 {3:│}{1: }9 | + {1: }10 {3:│}{1: }10 | + {1: }{4:11 }{3:│}{1: }{2:-----------------}| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler | + ]]) + + feed(":set diffopt+=internal<cr>") + screen:expect([[ + {1:+ }{5:^+-- 4 lines: 1···}{3:│}{1:+ }{5:+-- 4 lines: 1··}| + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1: }7 {3:│}{1: }7 | + {1: }8 {3:│}{1: }8 | + {1: }9 {3:│}{1: }9 | + {1: }10 {3:│}{1: }10 | + {1: }{4:11 }{3:│}{1: }{2:-----------------}| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt+=internal | + ]]) + end) + + it('Add a line in the middle of file 2, remove on at the end of file 1', function() + write_file(fname, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", false) + write_file(fname_2, "1\n2\n3\n4\n4\n5\n6\n7\n8\n9\n10\n", false) + reread() + + feed(':set diffopt=filler<cr>') + screen:expect([[ + {1: }^1 {3:│}{1: }1 | + {1: }2 {3:│}{1: }2 | + {1: }3 {3:│}{1: }3 | + {1: }4 {3:│}{1: }4 | + {1: }{2:------------------}{3:│}{1: }{4:4 }| + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1: }7 {3:│}{1: }7 | + {1: }8 {3:│}{1: }8 | + {1: }9 {3:│}{1: }9 | + {1: }10 {3:│}{1: }10 | + {1: }{4:11 }{3:│}{1: }{2:-----------------}| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler | + ]]) + + feed(':set diffopt+=internal<cr>') + screen:expect([[ + {1: }^1 {3:│}{1: }1 | + {1: }2 {3:│}{1: }2 | + {1: }3 {3:│}{1: }3 | + {1: }4 {3:│}{1: }4 | + {1: }{2:------------------}{3:│}{1: }{4:4 }| + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1: }7 {3:│}{1: }7 | + {1: }8 {3:│}{1: }8 | + {1: }9 {3:│}{1: }9 | + {1: }10 {3:│}{1: }10 | + {1: }{4:11 }{3:│}{1: }{2:-----------------}| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt+=internal | + ]]) + end) + + it('Add a line in the middle of file 1, remove on at the end of file 2', function() + write_file(fname, "1\n2\n3\n4\n4\n5\n6\n7\n8\n9\n10\n", false) + write_file(fname_2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", false) + reread() + + feed(':set diffopt=filler<cr>') + screen:expect([[ + {1: }^1 {3:│}{1: }1 | + {1: }2 {3:│}{1: }2 | + {1: }3 {3:│}{1: }3 | + {1: }4 {3:│}{1: }4 | + {1: }{4:4 }{3:│}{1: }{2:-----------------}| + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1: }7 {3:│}{1: }7 | + {1: }8 {3:│}{1: }8 | + {1: }9 {3:│}{1: }9 | + {1: }10 {3:│}{1: }10 | + {1: }{2:------------------}{3:│}{1: }{4:11 }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler | + ]]) + + feed(':set diffopt+=internal<cr>') + screen:expect([[ + {1: }^1 {3:│}{1: }1 | + {1: }2 {3:│}{1: }2 | + {1: }3 {3:│}{1: }3 | + {1: }4 {3:│}{1: }4 | + {1: }{4:4 }{3:│}{1: }{2:-----------------}| + {1: }5 {3:│}{1: }5 | + {1: }6 {3:│}{1: }6 | + {1: }7 {3:│}{1: }7 | + {1: }8 {3:│}{1: }8 | + {1: }9 {3:│}{1: }9 | + {1: }10 {3:│}{1: }10 | + {1: }{2:------------------}{3:│}{1: }{4:11 }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt+=internal | + ]]) + end) + + describe('normal/patience/histogram diff algorithm', function() + setup(function() + local f1 = [[#include <stdio.h> + +// Frobs foo heartily +int frobnitz(int foo) +{ + int i; + for(i = 0; i < 10; i++) + { + printf("Your answer is: "); + printf("%d\n", foo); + } +} + +int fact(int n) +{ + if(n > 1) + { + return fact(n-1) * n; + } + return 1; +} + +int main(int argc, char **argv) +{ + frobnitz(fact(10)); +}]] + write_file(fname, f1, false) + local f2 = [[#include <stdio.h> + +int fib(int n) +{ + if(n > 2) + { + return fib(n-1) + fib(n-2); + } + return 1; +} + +// Frobs foo heartily +int frobnitz(int foo) +{ + int i; + for(i = 0; i < 10; i++) + { + printf("%d\n", foo); + } +} + +int main(int argc, char **argv) +{ + frobnitz(fib(10)); +}]] + write_file(fname_2, f2, false) + end) + + it('diffopt=+algorithm:myers', function() + reread() + feed(':set diffopt=internal,filler<cr>') + screen:expect([[ + {1: }^#include <stdio.h>{3:│}{1: }#include <stdio.h| + {1: } {3:│}{1: } | + {1: }{8:// Frobs foo heart}{3:│}{1: }{8:int fib(int n)}{9: }| + {1: }{4:int frobnitz(int f}{3:│}{1: }{2:-----------------}| + {1: }{ {3:│}{1: }{ | + {1: }{9: i}{8:nt i;}{9: }{3:│}{1: }{9: i}{8:f(n > 2)}{9: }| + {1: }{4: for(i = 0; i <}{3:│}{1: }{2:-----------------}| + {1: } { {3:│}{1: } { | + {1: }{9: }{8:printf("Yo}{3:│}{1: }{9: }{8:return fi}| + {1: }{4: printf("%d}{3:│}{1: }{2:-----------------}| + {1: } } {3:│}{1: } } | + {1: }{2:------------------}{3:│}{1: }{4: return 1; }| + {1: }} {3:│}{1: }} | + {1: } {3:│}{1: } | + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=internal,filler | + ]]) + + feed('G') + screen:expect([[ + {1: }{2:------------------}{3:│}{1: }{4:int frobnitz(int }| + {1: }{ {3:│}{1: }{ | + {1: }{9: i}{8:f(n > 1)}{9: }{3:│}{1: }{9: i}{8:nt i;}{9: }| + {1: }{2:------------------}{3:│}{1: }{4: for(i = 0; i }| + {1: } { {3:│}{1: } { | + {1: }{9: }{8:return fac}{3:│}{1: }{9: }{8:printf("%}| + {1: } } {3:│}{1: } } | + {1: }{4: return 1; }{3:│}{1: }{2:-----------------}| + {1: }} {3:│}{1: }} | + {1: } {3:│}{1: } | + {1: }int main(int argc,{3:│}{1: }int main(int argc| + {1: }{ {3:│}{1: }{ | + {1: }{9: frobnitz(f}{8:act}{9:(}{3:│}{1: }{9: frobnitz(f}{8:ib}{9:(}| + {1: }^} {3:│}{1: }} | + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=internal,filler | + ]]) + end) + + it('diffopt+=algorithm:patience', function() + reread() + feed(':set diffopt=internal,filler,algorithm:patience<cr>') + screen:expect([[ + {1: }^#include <stdio.h>{3:│}{1: }#include <stdio.h| + {1: } {3:│}{1: } | + {1: }{2:------------------}{3:│}{1: }{4:int fib(int n) }| + {1: }{2:------------------}{3:│}{1: }{4:{ }| + {1: }{2:------------------}{3:│}{1: }{4: if(n > 2) }| + {1: }{2:------------------}{3:│}{1: }{4: { }| + {1: }{2:------------------}{3:│}{1: }{4: return fi}| + {1: }{2:------------------}{3:│}{1: }{4: } }| + {1: }{2:------------------}{3:│}{1: }{4: return 1; }| + {1: }{2:------------------}{3:│}{1: }{4:} }| + {1: }{2:------------------}{3:│}{1: }{4: }| + {1: }// Frobs foo heart{3:│}{1: }// Frobs foo hear| + {1: }int frobnitz(int f{3:│}{1: }int frobnitz(int | + {1: }{ {3:│}{1: }{ | + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + | + ]]) + + feed('G') + screen:expect([[ + {1: } {3:│}{1: } | + {1: }{4:int fact(int n) }{3:│}{1: }{2:-----------------}| + {1: }{4:{ }{3:│}{1: }{2:-----------------}| + {1: }{4: if(n > 1) }{3:│}{1: }{2:-----------------}| + {1: }{4: { }{3:│}{1: }{2:-----------------}| + {1: }{4: return fac}{3:│}{1: }{2:-----------------}| + {1: }{4: } }{3:│}{1: }{2:-----------------}| + {1: }{4: return 1; }{3:│}{1: }{2:-----------------}| + {1: }{4:} }{3:│}{1: }{2:-----------------}| + {1: }{4: }{3:│}{1: }{2:-----------------}| + {1: }int main(int argc,{3:│}{1: }int main(int argc| + {1: }{ {3:│}{1: }{ | + {1: }{9: frobnitz(f}{8:act}{9:(}{3:│}{1: }{9: frobnitz(f}{8:ib}{9:(}| + {1: }^} {3:│}{1: }} | + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + | + ]]) + end) + + it('diffopt+=algorithm:histogram', function() + reread() + feed(':set diffopt=internal,filler,algorithm:histogram<cr>') + screen:expect([[ + {1: }^#include <stdio.h>{3:│}{1: }#include <stdio.h| + {1: } {3:│}{1: } | + {1: }{2:------------------}{3:│}{1: }{4:int fib(int n) }| + {1: }{2:------------------}{3:│}{1: }{4:{ }| + {1: }{2:------------------}{3:│}{1: }{4: if(n > 2) }| + {1: }{2:------------------}{3:│}{1: }{4: { }| + {1: }{2:------------------}{3:│}{1: }{4: return fi}| + {1: }{2:------------------}{3:│}{1: }{4: } }| + {1: }{2:------------------}{3:│}{1: }{4: return 1; }| + {1: }{2:------------------}{3:│}{1: }{4:} }| + {1: }{2:------------------}{3:│}{1: }{4: }| + {1: }// Frobs foo heart{3:│}{1: }// Frobs foo hear| + {1: }int frobnitz(int f{3:│}{1: }int frobnitz(int | + {1: }{ {3:│}{1: }{ | + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + | + ]]) + + feed('G') + screen:expect([[ + {1: } {3:│}{1: } | + {1: }{4:int fact(int n) }{3:│}{1: }{2:-----------------}| + {1: }{4:{ }{3:│}{1: }{2:-----------------}| + {1: }{4: if(n > 1) }{3:│}{1: }{2:-----------------}| + {1: }{4: { }{3:│}{1: }{2:-----------------}| + {1: }{4: return fac}{3:│}{1: }{2:-----------------}| + {1: }{4: } }{3:│}{1: }{2:-----------------}| + {1: }{4: return 1; }{3:│}{1: }{2:-----------------}| + {1: }{4:} }{3:│}{1: }{2:-----------------}| + {1: }{4: }{3:│}{1: }{2:-----------------}| + {1: }int main(int argc,{3:│}{1: }int main(int argc| + {1: }{ {3:│}{1: }{ | + {1: }{9: frobnitz(f}{8:act}{9:(}{3:│}{1: }{9: frobnitz(f}{8:ib}{9:(}| + {1: }^} {3:│}{1: }} | + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + | + ]]) + end) + end) + + describe('diffopt+=indent-heuristic', function() + setup(function() + local f1 = [[ + def finalize(values) + + values.each do |v| + v.finalize + end]] + write_file(fname, f1, false) + local f2 = [[ + def finalize(values) + + values.each do |v| + v.prepare + end + + values.each do |v| + v.finalize + end]] + write_file(fname_2, f2, false) + feed(':diffupdate!<cr>') + end) + + it('internal', function() + reread() + feed(":set diffopt=internal,filler<cr>") + screen:expect([[ + {1: }^def finalize(value{3:│}{1: }def finalize(valu| + {1: } {3:│}{1: } | + {1: } values.each do |{3:│}{1: } values.each do | + {1: }{2:------------------}{3:│}{1: }{4: v.prepare }| + {1: }{2:------------------}{3:│}{1: }{4: end }| + {1: }{2:------------------}{3:│}{1: }{4: }| + {1: }{2:------------------}{3:│}{1: }{4: values.each do }| + {1: } v.finalize {3:│}{1: } v.finalize | + {1: } end {3:│}{1: } end | + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=internal,filler | + ]]) + end) + + it('indent-heuristic', function() + reread() + feed(':set diffopt=internal,filler,indent-heuristic<cr>') + screen:expect([[ + {1: }^def finalize(value{3:│}{1: }def finalize(valu| + {1: } {3:│}{1: } | + {1: }{2:------------------}{3:│}{1: }{4: values.each do }| + {1: }{2:------------------}{3:│}{1: }{4: v.prepare }| + {1: }{2:------------------}{3:│}{1: }{4: end }| + {1: }{2:------------------}{3:│}{1: }{4: }| + {1: } values.each do |{3:│}{1: } values.each do | + {1: } v.finalize {3:│}{1: } v.finalize | + {1: } end {3:│}{1: } end | + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + | + ]]) + end) + + it('indent-heuristic random order', function() + reread() + feed(':set diffopt=internal,filler,indent-heuristic,algorithm:patience<cr>') + feed(':<cr>') + screen:expect([[ + {1: }^def finalize(value{3:│}{1: }def finalize(valu| + {1: } {3:│}{1: } | + {1: }{2:------------------}{3:│}{1: }{4: values.each do }| + {1: }{2:------------------}{3:│}{1: }{4: v.prepare }| + {1: }{2:------------------}{3:│}{1: }{4: end }| + {1: }{2:------------------}{3:│}{1: }{4: }| + {1: } values.each do |{3:│}{1: } values.each do | + {1: } v.finalize {3:│}{1: } v.finalize | + {1: } end {3:│}{1: } end | + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + : | + ]]) + end) + end) + + it('Diff the same file', function() + write_file(fname, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false) + write_file(fname_2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false) + reread() + + feed(':set diffopt=filler<cr>') + screen:expect([[ + {1:+ }{5:^+-- 10 lines: 1···}{3:│}{1:+ }{5:+-- 10 lines: 1··}| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler | + ]]) + + feed(':set diffopt+=internal<cr>') + screen:expect([[ + {1:+ }{5:^+-- 10 lines: 1···}{3:│}{1:+ }{5:+-- 10 lines: 1··}| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt+=internal | + ]]) + end) + + it('Diff an empty file', function() + write_file(fname, "", false) + write_file(fname_2, "", false) + reread() + + feed(':set diffopt=filler<cr>') + screen:expect([[ + {1:- }^ {3:│}{1:- } | + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler | + ]]) + + feed(':set diffopt+=internal<cr>') + screen:expect([[ + {1:- }^ {3:│}{1:- } | + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt+=internal | + ]]) + end) + + it('diffopt+=icase', function() + write_file(fname, "a\nb\ncd\n", false) + write_file(fname_2, "A\nb\ncDe\n", false) + reread() + + feed(':set diffopt=filler,icase<cr>') + screen:expect([[ + {1: }^a {3:│}{1: }A | + {1: }b {3:│}{1: }b | + {1: }{9:cd }{3:│}{1: }{9:cD}{8:e}{9: }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler,icase | + ]]) + + feed(':set diffopt+=internal<cr>') + screen:expect([[ + {1: }^a {3:│}{1: }A | + {1: }b {3:│}{1: }b | + {1: }{9:cd }{3:│}{1: }{9:cD}{8:e}{9: }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt+=internal | + ]]) + end) + + describe('diffopt+=iwhite', function() + setup(function() + local f1 = 'int main()\n{\n printf("Hello, World!");\n return 0;\n}\n' + write_file(fname, f1, false) + local f2 = 'int main()\n{\n if (0)\n {\n printf("Hello, World!");\n return 0;\n }\n}\n' + write_file(fname_2, f2, false) + feed(':diffupdate!<cr>') + end) + + it('external', function() + reread() + feed(':set diffopt=filler,iwhite<cr>') + screen:expect([[ + {1: }^int main() {3:│}{1: }int main() | + {1: }{ {3:│}{1: }{ | + {1: }{2:------------------}{3:│}{1: }{4: if (0) }| + {1: }{2:------------------}{3:│}{1: }{4: { }| + {1: } printf("Hello, {3:│}{1: } printf("Hel| + {1: } return 0; {3:│}{1: } return 0; | + {1: }{2:------------------}{3:│}{1: }{4: } }| + {1: }} {3:│}{1: }} | + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler,iwhite | + ]]) + end) + + it('internal', function() + reread() + feed(':set diffopt=filler,iwhite,internal<cr>') + screen:expect([[ + {1: }^int main() {3:│}{1: }int main() | + {1: }{ {3:│}{1: }{ | + {1: }{2:------------------}{3:│}{1: }{4: if (0) }| + {1: }{2:------------------}{3:│}{1: }{4: { }| + {1: } printf("Hello, {3:│}{1: } printf("Hel| + {1: } return 0; {3:│}{1: } return 0; | + {1: }{2:------------------}{3:│}{1: }{4: } }| + {1: }} {3:│}{1: }} | + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=filler,iwhite,internal | + ]]) + end) + end) + + describe('diffopt+=iblank', function() + setup(function() + write_file(fname, 'a\n\n \ncd\nef\nxxx\n', false) + write_file(fname_2, 'a\ncd\n\nef\nyyy\n', false) + feed(':diffupdate!<cr>') + end) + + it('generic', function() + reread() + feed(':set diffopt=internal,filler,iblank<cr>') + screen:expect([[ + {1: }^a {3:│}{1: }a | + {1: }{4: }{3:│}{1: }{2:-----------------}| + {1: }{4: }{3:│}{1: }{2:-----------------}| + {1: }cd {3:│}{1: }cd | + {1: }ef {3:│}{1: } | + {1: }{8:xxx}{9: }{3:│}{1: }ef | + {1: }{6:~ }{3:│}{1: }{8:yyy}{9: }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + :set diffopt=internal,filler,iblank | + ]]) + end) + + it('diffopt+=iwhite', function() + reread() + feed(':set diffopt=internal,filler,iblank,iwhite<cr>') + feed(':<cr>') + screen:expect([[ + {1: }^a {3:│}{1: }a | + {1: } {3:│}{1: }cd | + {1: } {3:│}{1: } | + {1: }cd {3:│}{1: }ef | + {1: }ef {3:│}{1: }{8:yyy}{9: }| + {1: }{8:xxx}{9: }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + : | + ]]) + end) + + it('diffopt+=iwhiteall', function() + reread() + feed(':set diffopt=internal,filler,iblank,iwhiteall<cr>') + feed(':<cr>') + screen:expect([[ + {1: }^a {3:│}{1: }a | + {1: } {3:│}{1: }cd | + {1: } {3:│}{1: } | + {1: }cd {3:│}{1: }ef | + {1: }ef {3:│}{1: }{8:yyy}{9: }| + {1: }{8:xxx}{9: }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + : | + ]]) + end) + + it('diffopt+=iwhiteeol', function() + reread() + feed(':set diffopt=internal,filler,iblank,iwhiteeol<cr>') + feed(':<cr>') + screen:expect([[ + {1: }^a {3:│}{1: }a | + {1: } {3:│}{1: }cd | + {1: } {3:│}{1: } | + {1: }cd {3:│}{1: }ef | + {1: }ef {3:│}{1: }{8:yyy}{9: }| + {1: }{8:xxx}{9: }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + : | + ]]) + end) + end) + + describe('diffopt+=iwhite{eol,all}', function() + setup(function() + write_file(fname, 'a \nx\ncd\nef\nxx xx\nfoo\nbar\n', false) + write_file(fname_2, 'a\nx\nc d\n ef\nxx xx\nfoo\n\nbar\n', false) + feed(':diffupdate!<cr>') + end) + + it('diffopt+=iwhiteeol', function() + reread() + feed(':set diffopt=internal,filler,iwhiteeol<cr>') + feed(':<cr>') + screen:expect([[ + {1: }^a {3:│}{1: }a | + {1: }x {3:│}{1: }x | + {1: }{9:cd }{3:│}{1: }{9:c}{8: }{9:d }| + {1: }{9:ef }{3:│}{1: }{8: }{9:ef }| + {1: }{9:xx }{8: }{9:xx }{3:│}{1: }{9:xx xx }| + {1: }foo {3:│}{1: }foo | + {1: }{2:------------------}{3:│}{1: }{4: }| + {1: }bar {3:│}{1: }bar | + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + : | + ]]) + end) + + it('diffopt+=iwhiteall', function() + reread() + feed(':set diffopt=internal,filler,iwhiteall<cr>') + feed(':<cr>') + screen:expect([[ + {1: }^a {3:│}{1: }a | + {1: }x {3:│}{1: }x | + {1: }cd {3:│}{1: }c d | + {1: }ef {3:│}{1: } ef | + {1: }xx xx {3:│}{1: }xx xx | + {1: }foo {3:│}{1: }foo | + {1: }{2:------------------}{3:│}{1: }{4: }| + {1: }bar {3:│}{1: }bar | + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {1: }{6:~ }{3:│}{1: }{6:~ }| + {7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }| + : | + ]]) + end) + end) +end) diff --git a/test/functional/ui/embed_spec.lua b/test/functional/ui/embed_spec.lua index 4fc93c3b63..10dbc68672 100644 --- a/test/functional/ui/embed_spec.lua +++ b/test/functional/ui/embed_spec.lua @@ -17,6 +17,7 @@ local function test_embed(ext_linegrid) [1] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, [2] = {bold = true, foreground = Screen.colors.SeaGreen4}, [3] = {bold = true, foreground = Screen.colors.Blue1}, + [4] = {bold = true, foreground = Screen.colors.Green}, }) end @@ -27,9 +28,9 @@ local function test_embed(ext_linegrid) | | | + | Error detected while processing pre-vimrc command line: | E121: Undefined variable: invalid | - E15: Invalid expression: invalid+ | Press ENTER or type command to continue^ | ]]) @@ -56,7 +57,7 @@ local function test_embed(ext_linegrid) Error detected while processing pre-vimrc command line: | foo | {1:bar} | - {2:Press ENTER or type command to continue}^ | + {4:Press ENTER or type command to continue}^ | ]]) end) diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 55fc343e4c..96f6b43320 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -768,6 +768,40 @@ describe('CursorLine highlight', function() {4:[No Name] [+] }{9:[No Name] [+] }| | ]]) + + -- CursorLine with fg=NONE is "low-priority". + -- Rendered as underline in a diff-line. #9028 + command('hi CursorLine ctermbg=red ctermfg=NONE guibg=red guifg=NONE') + feed('kkkk') + screen:expect([[ + {1: }line 1 some text {4:│}{1: }line 1 some text | + {1: }{11:line 2 mo}{12:Re text!}{11: }{4:│}{1: }{11:^line 2 mo}{12:re text}{11: }| + {1: }{5:extra line! }{4:│}{1: }{6:----------------------}| + {1: }extra line! {4:│}{1: }extra line! | + {1: }extra line! {4:│}{1: }extra line! | + {1: }last line ... {4:│}{1: }last line ... | + {1: } {4:│}{1: } | + {1: }{8:~ }{4:│}{1: }{8:~ }| + {1: }{8:~ }{4:│}{1: }{8:~ }| + {1: }{8:~ }{4:│}{1: }{8:~ }| + {4:[No Name] [+] }{9:[No Name] [+] }| + | + ]], { + [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray}, + [2] = {bold = true, background = Screen.colors.Red}, + [3] = {background = Screen.colors.LightMagenta}, + [4] = {reverse = true}, + [5] = {background = Screen.colors.LightBlue}, + [6] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1}, + [7] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + [8] = {bold = true, foreground = Screen.colors.Blue1}, + [9] = {bold = true, reverse = true}, + [10] = {bold = true}, + [11] = {underline = true, + background = Screen.colors.LightMagenta}, + [12] = {bold = true, underline = true, + background = Screen.colors.Red}, + }) end) end) diff --git a/test/functional/ui/hlstate_spec.lua b/test/functional/ui/hlstate_spec.lua index 672af5fb22..775b701438 100644 --- a/test/functional/ui/hlstate_spec.lua +++ b/test/functional/ui/hlstate_spec.lua @@ -177,11 +177,11 @@ describe('ext_hlstate detailed highlights', function() it("work with :terminal", function() screen:set_default_attr_ids({ [1] = {{}, {{hi_name = "TermCursorNC", ui_name = "TermCursorNC", kind = "ui"}}}, - [2] = {{special = Screen.colors.Grey0, foreground = 52479}, {{kind = "term"}}}, - [3] = {{special = Screen.colors.Grey0, bold = true, foreground = 52479}, {{kind = "term"}}}, - [4] = {{special = Screen.colors.Grey0, foreground = 52479}, {2, 1}}, - [5] = {{special = Screen.colors.Grey0, foreground = 4259839}, {{kind = "term"}}}, - [6] = {{special = Screen.colors.Grey0, foreground = 4259839}, {5, 1}}, + [2] = {{foreground = 52479}, {{kind = "term"}}}, + [3] = {{bold = true, foreground = 52479}, {{kind = "term"}}}, + [4] = {{foreground = 52479}, {2, 1}}, + [5] = {{foreground = 4259839}, {{kind = "term"}}}, + [6] = {{foreground = 4259839}, {5, 1}}, }) command('enew | call termopen(["'..nvim_dir..'/tty-test"])') screen:expect([[ diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 736a314426..bb6cb543ed 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -2512,7 +2512,7 @@ describe(":substitute", function() end) it(':substitute with inccommand during :terminal activity', function() - retry(2, nil, function() + retry(2, 40000, function() local screen = Screen.new(30,15) clear() diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua index 99aae16183..32e8faf7d3 100644 --- a/test/functional/ui/options_spec.lua +++ b/test/functional/ui/options_spec.lua @@ -1,85 +1,85 @@ +local global_helpers = require('test.helpers') local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear = helpers.clear local command = helpers.command local eq = helpers.eq +local shallowcopy = global_helpers.shallowcopy describe('ui receives option updates', function() local screen - before_each(function() - clear() + local function reset(opts, ...) + local defaults = { + ambiwidth='single', + arabicshape=true, + emoji=true, + guifont='', + guifontset='', + guifontwide='', + linespace=0, + showtabline=1, + termguicolors=false, + ext_cmdline=false, + ext_popupmenu=false, + ext_tabline=false, + ext_wildmenu=false, + ext_linegrid=false, + ext_hlstate=false, + } + + clear(...) screen = Screen.new(20,5) - end) + screen:attach(opts) + -- NB: UI test suite can be run in both "linegrid" and legacy grid mode. + -- In both cases check that the received value is the one requested. + defaults.ext_linegrid = screen._options.ext_linegrid or false + return defaults + end after_each(function() screen:detach() end) - local defaults = { - ambiwidth='single', - arabicshape=true, - emoji=true, - guifont='', - guifontset='', - guifontwide='', - linespace=0, - showtabline=1, - termguicolors=false, - ext_cmdline=false, - ext_popupmenu=false, - ext_tabline=false, - ext_wildmenu=false, - ext_linegrid=false, - ext_hlstate=false, - } - it("for defaults", function() - screen:attach() - -- NB: UI test suite can be run in both "linegrid" and legacy grid mode. - -- In both cases check that the received value is the one requested. - defaults.ext_linegrid = screen._options.ext_linegrid or false + local expected = reset() screen:expect(function() - eq(defaults, screen.options) + eq(expected, screen.options) end) end) it("when setting options", function() - screen:attach() - defaults.ext_linegrid = screen._options.ext_linegrid or false - local changed = {} - for k,v in pairs(defaults) do - changed[k] = v - end + local expected = reset() + local defaults = shallowcopy(expected) command("set termguicolors") - changed.termguicolors = true + expected.termguicolors = true screen:expect(function() - eq(changed, screen.options) + eq(expected, screen.options) end) command("set guifont=Comic\\ Sans") - changed.guifont = "Comic Sans" + expected.guifont = "Comic Sans" screen:expect(function() - eq(changed, screen.options) + eq(expected, screen.options) end) command("set showtabline=0") - changed.showtabline = 0 + expected.showtabline = 0 screen:expect(function() - eq(changed, screen.options) + eq(expected, screen.options) end) command("set linespace=13") - changed.linespace = 13 + expected.linespace = 13 screen:expect(function() - eq(changed, screen.options) + eq(expected, screen.options) end) command("set linespace=-11") - changed.linespace = -11 + expected.linespace = -11 screen:expect(function() - eq(changed, screen.options) + eq(expected, screen.options) end) command("set all&") @@ -89,29 +89,35 @@ describe('ui receives option updates', function() end) it('with UI extensions', function() - local changed = {} - for k,v in pairs(defaults) do - changed[k] = v - end + local expected = reset({ext_cmdline=true, ext_wildmenu=true}) - screen:attach({ext_cmdline=true, ext_wildmenu=true}) - defaults.ext_linegrid = screen._options.ext_linegrid or false - changed.ext_cmdline = true - changed.ext_wildmenu = true + expected.ext_cmdline = true + expected.ext_wildmenu = true screen:expect(function() - eq(changed, screen.options) + eq(expected, screen.options) end) screen:set_option('ext_popupmenu', true) - changed.ext_popupmenu = true + expected.ext_popupmenu = true screen:expect(function() - eq(changed, screen.options) + eq(expected, screen.options) end) screen:set_option('ext_wildmenu', false) - changed.ext_wildmenu = false + expected.ext_wildmenu = false screen:expect(function() - eq(changed, screen.options) + eq(expected, screen.options) end) end) + + local function startup_test(headless) + local expected = reset(nil,{headless=headless,args={'--cmd', 'set guifont=Comic\\ Sans\\ 12'}}) + expected.guifont = "Comic Sans 12" + screen:expect(function() + eq(expected, screen.options) + end) + end + + it('from startup options with --headless', function() startup_test(true) end) + it('from startup options with --embed', function() startup_test(false) end) end) diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua index 1850d436ac..aa99499ec6 100644 --- a/test/functional/ui/output_spec.lua +++ b/test/functional/ui/output_spec.lua @@ -68,7 +68,12 @@ describe("shell command :!", function() | {10:Press ENTER or type command to continue}{1: } | {3:-- TERMINAL --} | - ]]) + ]], { + -- test/functional/helpers.lua defaults to background=light. + [1] = {reverse = true}, + [3] = {bold = true}, + [10] = {foreground = 2}, + }) end) end) diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index af036913d8..75eb5bb4e3 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -72,6 +72,7 @@ -- To debug screen tests, see Screen:redraw_debug(). local global_helpers = require('test.helpers') +local deepcopy = global_helpers.deepcopy local shallowcopy = global_helpers.shallowcopy local helpers = require('test.functional.helpers')(nil) local request, run, uimeths = helpers.request, helpers.run, helpers.uimeths @@ -176,6 +177,10 @@ function Screen:set_default_attr_ids(attr_ids) self._default_attr_ids = attr_ids end +function Screen:get_default_attr_ids() + return deepcopy(self._default_attr_ids) +end + function Screen:set_default_attr_ignore(attr_ignore) self._default_attr_ignore = attr_ignore end @@ -489,7 +494,7 @@ function Screen:_wait(check, flags) if warn_immediate and immediate_seen then print([[ -Warning: A screen test has immediate success. Try to avoid this unless the +warning: Screen test succeeded immediately. Try to avoid this unless the purpose of the test really requires it.]]) if intermediate_seen then print([[ @@ -498,8 +503,7 @@ Use screen:snapshot_util() or screen:redraw_debug() to find them, and add them to the test if they make sense. ]]) else - print([[If necessary, silence this warning by -supplying the 'unchanged' argument to screen:expect.]]) + print([[If necessary, silence this warning with 'unchanged' argument of screen:expect.]]) end did_warn = true end @@ -507,19 +511,17 @@ supplying the 'unchanged' argument to screen:expect.]]) if failure_after_success then print([[ -Warning: Screen changes were received after the expected state. This indicates +warning: Screen changes were received after the expected state. This indicates indeterminism in the test. Try adding screen:expect(...) (or wait()) between asynchronous (feed(), nvim_input()) and synchronous API calls. - - Use Screen:redraw_debug() to investigate the problem. It might find - relevant intermediate states that should be added to the test to make it - more robust. - - If the point of the test is to assert the state after some user input - sent with feed(...), also adding an screen:expect(...) before the feed(...) - will help ensure the input is sent to nvim when nvim is in a predictable - state. This is preferable to using wait(), as it is more closely emulates - real user interaction. + - Use screen:redraw_debug() to investigate; it may find relevant intermediate + states that should be added to the test to make it more robust. + - If the purpose of the test is to assert state after some user input sent + with feed(), adding screen:expect() before the feed() will help to ensure + the input is sent when Nvim is in a predictable state. This is preferable + to wait(), for being closer to real user interaction. - wait() can trigger redraws and consequently generate more indeterminism. - In that case try removing every wait(). + Try removing wait(). ]]) did_warn = true end diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua index 1a8b7d543a..04d532f6e1 100644 --- a/test/functional/ui/screen_basic_spec.lua +++ b/test/functional/ui/screen_basic_spec.lua @@ -156,6 +156,82 @@ local function screen_tests(linegrid) end) end) + describe('statusline', function() + it('is redrawn after <c-l>', function() + command('set laststatus=2') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {1:[No Name] }| + | + ]]) + + feed('<c-l>') + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {1:[No Name] }| + | + ]], reset=true} + + command('split') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {1:[No Name] }| + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {3:[No Name] }| + | + ]]) + + feed('<c-l>') + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {1:[No Name] }| + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {3:[No Name] }| + | + ]], reset=true} + end) + end) + describe('window', function() describe('split', function() it('horizontal', function() diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua index 6abeb0b2f4..bc0e2e3799 100644 --- a/test/functional/ui/sign_spec.lua +++ b/test/functional/ui/sign_spec.lua @@ -20,6 +20,9 @@ describe('Signs', function() [6] = {foreground = Screen.colors.Brown}, [7] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey}, [8] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + [9] = {bold = true, foreground = Screen.colors.Magenta}, + [10] = {foreground = Screen.colors.Blue1}, + [11] = {bold = true, foreground = Screen.colors.SeaGreen4}, } ) end) @@ -111,5 +114,45 @@ describe('Signs', function() | ]]) end) + + it('can have 32bit sign IDs', function() + command('sign define piet text=>> texthl=Search') + command('sign place 100000 line=1 name=piet buffer=1') + feed(':sign place<cr>') + screen:expect([[ + {1:>>} | + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {4: }| + :sign place | + {9:--- Signs ---} | + {10:Signs for [NULL]:} | + line=1 id=100000 name=piet | + | + {11:Press ENTER or type command to continue}^ | + ]]) + + feed('<cr>') + screen:expect([[ + {1:>>}^ | + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + {2: }{0:~ }| + | + ]]) + end) end) end) diff --git a/test/functional/viml/lang_spec.lua b/test/functional/viml/lang_spec.lua index 3ba9221aef..6d603b8822 100644 --- a/test/functional/viml/lang_spec.lua +++ b/test/functional/viml/lang_spec.lua @@ -18,4 +18,13 @@ describe('viml', function() ]]) eq(nil, string.find(eval('v:errmsg'), '^E129')) end) + + it('str2float is not affected by locale', function() + if exc_exec('lang ctype sv_SE.UTF-8') ~= 0 then + pending("Locale sv_SE.UTF-8 not supported") + return + end + clear{env={LANG="", LC_NUMERIC="sv_SE.UTF-8"}} + eq(2.2, eval('str2float("2.2")')) + end) end) diff --git a/test/unit/mbyte_spec.lua b/test/unit/mbyte_spec.lua index 1e7e9fd6e6..3e65537270 100644 --- a/test/unit/mbyte_spec.lua +++ b/test/unit/mbyte_spec.lua @@ -43,15 +43,17 @@ describe('mbyte', function() -- Sequences with more than four bytes end) - itp('utf_char2bytes', function() - local char_p = ffi.typeof('char[?]') - for c = 0, 0xFFFF do - local p = char_p(4, 0) - mbyte.utf_char2bytes(c, p) - eq(c, mbyte.utf_ptr2char(p)) - eq(charset.vim_iswordc(c), charset.vim_iswordp(p)) - end - end) + for n = 0, 0xF do + itp(('utf_char2bytes for chars 0x%x - 0x%x'):format(n * 0x1000, n * 0x1000 + 0xFFF), function() + local char_p = ffi.typeof('char[?]') + for c = n * 0x1000, n * 0x1000 + 0xFFF do + local p = char_p(4, 0) + mbyte.utf_char2bytes(c, p) + eq(c, mbyte.utf_ptr2char(p)) + eq(charset.vim_iswordc(c), charset.vim_iswordp(p)) + end + end) + end describe('utfc_ptr2char_len', function() |