mirror of
https://github.com/neovim/neovim.git
synced 2026-04-21 06:45:37 +00:00
Merge branch 'master' into expression-parser
This commit is contained in:
216
test/README.md
216
test/README.md
@@ -1,10 +1,224 @@
|
||||
Tests
|
||||
=====
|
||||
|
||||
Tests are run by `/cmake/RunTests.cmake` file, using busted.
|
||||
Tests are run by `/cmake/RunTests.cmake` file, using `busted`.
|
||||
|
||||
For some failures, `.nvimlog` (or `$NVIM_LOG_FILE`) may provide insight.
|
||||
|
||||
---
|
||||
|
||||
- [Running tests](#running-tests)
|
||||
- [Unit tests](#unit-tests)
|
||||
- [Lint](#lint)
|
||||
- [Environment variables](#environment-variables)
|
||||
|
||||
---
|
||||
|
||||
Running tests
|
||||
-------------
|
||||
|
||||
Neovim uses third-party tooling to execute tests. So be sure, from the
|
||||
repository directory, to build the tools before testing:
|
||||
|
||||
make cmake
|
||||
|
||||
## Executing Tests
|
||||
|
||||
To run all _non-legacy_ (unit + functional) tests:
|
||||
|
||||
make test
|
||||
|
||||
To run only _unit_ tests:
|
||||
|
||||
make unittest
|
||||
|
||||
To run only _functional_ tests:
|
||||
|
||||
make functionaltest
|
||||
|
||||
---
|
||||
|
||||
## Filter Tests
|
||||
|
||||
### Filter by name
|
||||
|
||||
Another filter method is by setting a pattern of test name to `TEST_FILTER`.
|
||||
|
||||
``` lua
|
||||
it('foo api',function()
|
||||
...
|
||||
end)
|
||||
it('bar api',function()
|
||||
...
|
||||
end)
|
||||
```
|
||||
|
||||
To run only test with filter name:
|
||||
|
||||
TEST_TAG='foo.*api' make functionaltest
|
||||
|
||||
### Filter by file
|
||||
|
||||
To run a *specific* unit test:
|
||||
|
||||
TEST_FILE=test/unit/foo.lua make unittest
|
||||
|
||||
To run a *specific* functional test:
|
||||
|
||||
TEST_FILE=test/functional/foo.lua make functionaltest
|
||||
|
||||
To *repeat* a test many times:
|
||||
|
||||
.deps/usr/bin/busted --filter 'foo' --repeat 1000 test/functional/ui/foo_spec.lua
|
||||
|
||||
### Filter by tag
|
||||
|
||||
Tests can be "tagged" by adding `#` before a token in the test description.
|
||||
|
||||
``` lua
|
||||
it('#foo bar baz', function()
|
||||
...
|
||||
end)
|
||||
it('#foo another test', function()
|
||||
...
|
||||
end)
|
||||
```
|
||||
|
||||
To run only the tagged tests:
|
||||
|
||||
TEST_TAG=foo make functionaltest
|
||||
|
||||
**NOTES**:
|
||||
* 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:
|
||||
|
||||
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
|
||||
|
||||
`$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
|
||||
----------
|
||||
|
||||
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
|
||||
behavior.
|
||||
- For testing static functions or functions that have side effects visible only
|
||||
in module-global variables, create accessors for the modified variables. For
|
||||
example, say you are testing a function in misc1.c that modifies a static
|
||||
variable, create a file `test/c-helpers/misc1.c` and add a function that
|
||||
retrieves the value after the function call. Files under `test/c-helpers` will
|
||||
only be compiled when building the test shared library.
|
||||
- Luajit needs to know about type and constant declarations used in function
|
||||
prototypes. The
|
||||
[helpers.lua](https://github.com/neovim/neovim/blob/master/test/unit/helpers.lua)
|
||||
file automatically parses `types.h`, so types used in the tested functions
|
||||
must be moved to it to avoid having to rewrite the declarations in the test
|
||||
files (even though this is how it's currently done currently in the misc1/fs
|
||||
modules, but contributors are encouraged to refactor the declarations).
|
||||
- Macro constants must be rewritten as enums so they can be "visible" to the
|
||||
tests automatically.
|
||||
- Busted supports various "output providers". The
|
||||
**[gtest](https://github.com/Olivine-Labs/busted/pull/394) output provider**
|
||||
shows verbose details that can be useful to diagnose hung tests. Either modify
|
||||
the Makefile or compile with `make
|
||||
CMAKE_EXTRA_FLAGS=-DBUSTED_OUTPUT_TYPE=gtest` to enable it.
|
||||
- **Use busted's `pending()` feature** to skip tests
|
||||
([example](https://github.com/neovim/neovim/commit/5c1dc0fbe7388528875aff9d7b5055ad718014de#diff-bf80b24c724b0004e8418102f68b0679R18)).
|
||||
Do not silently skip the test with `if-else`. If a functional test depends on
|
||||
some external factor (e.g. the existence of `md5sum` on `$PATH`), *and* you
|
||||
can't mock or fake the dependency, then skip the test via `pending()` if the
|
||||
external factor is missing. This ensures that the *total* test-count (success
|
||||
+ fail + error + pending) is the same in all environments.
|
||||
- *Note:* `pending()` is ignored if it is missing an argument _unless_ it is
|
||||
[contained in an `it()`
|
||||
block](https://github.com/neovim/neovim/blob/d21690a66e7eb5ebef18046c7a79ef898966d786/test/functional/ex_cmds/grep_spec.lua#L11).
|
||||
Provide empty function argument if the `pending()` call is outside of
|
||||
`it()`
|
||||
([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.
|
||||
|
||||
### Where tests go
|
||||
|
||||
- _Unit tests_
|
||||
([test/unit](https://github.com/neovim/neovim/tree/master/test/unit)) should
|
||||
match 1-to-1 with the structure of `src/nvim/`, because they are testing
|
||||
functions directly. E.g. unit-tests for `src/nvim/undo.c` should live in
|
||||
`test/unit/undo_spec.lua`.
|
||||
- _Functional tests_
|
||||
([test/functional](https://github.com/neovim/neovim/tree/master/test/functional))
|
||||
are higher-level (plugins and user input) than unit tests; they are organized
|
||||
by concept.
|
||||
- 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/testdir/*.in`) legacy tests should be
|
||||
converted. Please _do not_ convert "new style" Vim tests (`src/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 test from the Makefile (`src/nvim/testdir/Makefile`).
|
||||
- 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
|
||||
----
|
||||
|
||||
|
||||
96
test/functional/core/startup_spec.lua
Normal file
96
test/functional/core/startup_spec.lua
Normal file
@@ -0,0 +1,96 @@
|
||||
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 funcs = helpers.funcs
|
||||
local nvim_prog = helpers.nvim_prog
|
||||
local nvim_set = helpers.nvim_set
|
||||
local read_file = helpers.read_file
|
||||
local retry = helpers.retry
|
||||
local iswin = helpers.iswin
|
||||
|
||||
describe('startup', function()
|
||||
before_each(function()
|
||||
clear()
|
||||
end)
|
||||
after_each(function()
|
||||
os.remove('Xtest_startup_ttyout')
|
||||
end)
|
||||
|
||||
it('pipe at both ends: has("ttyin")==0 has("ttyout")==0', function()
|
||||
-- system() puts a pipe at both ends.
|
||||
local out = funcs.system({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless',
|
||||
'--cmd', nvim_set,
|
||||
'-c', [[echo has('ttyin') has('ttyout')]],
|
||||
'+q' })
|
||||
eq('0 0', out)
|
||||
end)
|
||||
it('with --embed: has("ttyin")==0 has("ttyout")==0', function()
|
||||
local screen = Screen.new(25, 3)
|
||||
-- Remote UI connected by --embed.
|
||||
screen:attach()
|
||||
command([[echo has('ttyin') has('ttyout')]])
|
||||
screen:expect([[
|
||||
^ |
|
||||
~ |
|
||||
0 0 |
|
||||
]])
|
||||
end)
|
||||
it('in a TTY: has("ttyin")==1 has("ttyout")==1', function()
|
||||
local screen = Screen.new(25, 3)
|
||||
screen:attach()
|
||||
if iswin() then
|
||||
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
||||
end
|
||||
-- Running in :terminal
|
||||
command([[exe printf("terminal %s -u NONE -i NONE --cmd \"]]
|
||||
..nvim_set..[[\" ]]
|
||||
..[[-c \"echo has('ttyin') has('ttyout')\""]]
|
||||
..[[, shellescape(v:progpath))]])
|
||||
screen:expect([[
|
||||
^ |
|
||||
1 1 |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
it('output to pipe: has("ttyin")==1 has("ttyout")==0', function()
|
||||
local screen = Screen.new(25, 5)
|
||||
screen:attach()
|
||||
if iswin() then
|
||||
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
||||
end
|
||||
-- Running in :terminal
|
||||
command([[exe printf("terminal %s -u NONE -i NONE --cmd \"]]
|
||||
..nvim_set..[[\" ]]
|
||||
..[[-c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
|
||||
..[[-c q | cat -v"]] -- Output to a pipe.
|
||||
..[[, shellescape(v:progpath))]])
|
||||
retry(nil, 3000, function()
|
||||
screen:sleep(1)
|
||||
eq('1\n0\n', -- stdin is a TTY, stdout is a pipe
|
||||
read_file('Xtest_startup_ttyout'))
|
||||
end)
|
||||
end)
|
||||
it('input from pipe: has("ttyin")==0 has("ttyout")==1', function()
|
||||
local screen = Screen.new(25, 5)
|
||||
screen:attach()
|
||||
if iswin() then
|
||||
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
||||
end
|
||||
-- Running in :terminal
|
||||
command([[exe printf("terminal echo foo | ]] -- Input from a pipe.
|
||||
..[[%s -u NONE -i NONE --cmd \"]]
|
||||
..nvim_set..[[\" ]]
|
||||
..[[-c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
|
||||
..[[-c q -- -"]]
|
||||
..[[, shellescape(v:progpath))]])
|
||||
retry(nil, 3000, function()
|
||||
screen:sleep(1)
|
||||
eq('0\n1\n', -- stdin is a pipe, stdout is a TTY
|
||||
read_file('Xtest_startup_ttyout'))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -168,4 +168,11 @@ describe('Special values', function()
|
||||
'Expected True but got v:null',
|
||||
}, meths.get_vvar('errors'))
|
||||
end)
|
||||
|
||||
describe('compat', function()
|
||||
it('v:count is distinct from count', function()
|
||||
command('let count = []') -- v:count is readonly
|
||||
eq(1, eval('count is# g:["count"]'))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
67
test/functional/ex_cmds/mkview_spec.lua
Normal file
67
test/functional/ex_cmds/mkview_spec.lua
Normal file
@@ -0,0 +1,67 @@
|
||||
local lfs = require('lfs')
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local clear = helpers.clear
|
||||
local command = helpers.command
|
||||
local get_pathsep = helpers.get_pathsep
|
||||
local eq = helpers.eq
|
||||
local funcs = helpers.funcs
|
||||
local rmdir = helpers.rmdir
|
||||
|
||||
local file_prefix = 'Xtest-functional-ex_cmds-mkview_spec'
|
||||
|
||||
describe(':mkview', function()
|
||||
local tmp_file_base = file_prefix .. '-tmpfile'
|
||||
local local_dir = file_prefix .. '.d'
|
||||
local view_dir = file_prefix .. '.view.d'
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
lfs.mkdir(view_dir)
|
||||
lfs.mkdir(local_dir)
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
-- Remove any views created in the view directory
|
||||
rmdir(view_dir)
|
||||
lfs.rmdir(local_dir)
|
||||
end)
|
||||
|
||||
it('viewoption curdir restores local current directory', function()
|
||||
local cwd_dir = funcs.getcwd()
|
||||
local set_view_dir_command = 'set viewdir=' .. cwd_dir ..
|
||||
get_pathsep() .. view_dir
|
||||
|
||||
-- By default the local current directory should save
|
||||
command(set_view_dir_command)
|
||||
command('edit ' .. tmp_file_base .. '1')
|
||||
command('lcd ' .. local_dir)
|
||||
command('mkview')
|
||||
|
||||
-- Create a new instance of Nvim to remove the 'lcd'
|
||||
clear()
|
||||
|
||||
-- Disable saving the local current directory for the second view
|
||||
command(set_view_dir_command)
|
||||
command('set viewoptions-=curdir')
|
||||
command('edit ' .. tmp_file_base .. '2')
|
||||
command('lcd ' .. local_dir)
|
||||
command('mkview')
|
||||
|
||||
-- Create a new instance of Nvim to test saved 'lcd' option
|
||||
clear()
|
||||
command(set_view_dir_command)
|
||||
|
||||
-- Load the view without a saved local current directory
|
||||
command('edit ' .. tmp_file_base .. '2')
|
||||
command('loadview')
|
||||
-- The view's current directory should not have changed
|
||||
eq(cwd_dir, funcs.getcwd())
|
||||
-- Load the view with a saved local current directory
|
||||
command('edit ' .. tmp_file_base .. '1')
|
||||
command('loadview')
|
||||
-- The view's local directory should have been saved
|
||||
eq(cwd_dir .. get_pathsep() .. local_dir, funcs.getcwd())
|
||||
end)
|
||||
|
||||
end)
|
||||
BIN
test/functional/fixtures/api_level_3.mpack
Normal file
BIN
test/functional/fixtures/api_level_3.mpack
Normal file
Binary file not shown.
@@ -16,6 +16,13 @@ describe(':checkhealth', function()
|
||||
eq(false, status)
|
||||
eq('Invalid $VIMRUNTIME: bogus', string.match(err, 'Invalid.*'))
|
||||
end)
|
||||
it("detects invalid 'runtimepath'", function()
|
||||
clear()
|
||||
command('set runtimepath=bogus')
|
||||
local status, err = pcall(command, 'checkhealth')
|
||||
eq(false, status)
|
||||
eq("Invalid 'runtimepath'", string.match(err, 'Invalid.*'))
|
||||
end)
|
||||
it("detects invalid $VIM", function()
|
||||
clear()
|
||||
-- Do this after startup, otherwise it just breaks $VIMRUNTIME.
|
||||
|
||||
@@ -50,8 +50,8 @@ describe('terminal cursor', function()
|
||||
it('is positioned correctly when unfocused', function()
|
||||
screen:expect([[
|
||||
{7: 1 }tty ready |
|
||||
{7: 2 }{2:^ } |
|
||||
{7: 3 } |
|
||||
{7: 2 }^rows: 6, cols: 46 |
|
||||
{7: 3 }{2: } |
|
||||
{7: 4 } |
|
||||
{7: 5 } |
|
||||
{7: 6 } |
|
||||
@@ -60,12 +60,21 @@ describe('terminal cursor', function()
|
||||
end)
|
||||
|
||||
it('is positioned correctly when focused', function()
|
||||
screen:expect([[
|
||||
{7: 1 }tty ready |
|
||||
{7: 2 }^rows: 6, cols: 46 |
|
||||
{7: 3 }{2: } |
|
||||
{7: 4 } |
|
||||
{7: 5 } |
|
||||
{7: 6 } |
|
||||
:set number |
|
||||
]])
|
||||
feed('i')
|
||||
helpers.wait()
|
||||
screen:expect([[
|
||||
{7: 1 }tty ready |
|
||||
{7: 2 }{1: } |
|
||||
{7: 3 } |
|
||||
{7: 2 }rows: 6, cols: 46 |
|
||||
{7: 3 }{1: } |
|
||||
{7: 4 } |
|
||||
{7: 5 } |
|
||||
{7: 6 } |
|
||||
|
||||
@@ -101,7 +101,7 @@ describe('terminal mouse', function()
|
||||
line28 |line28 |
|
||||
line29 |line29 |
|
||||
line30 |line30 |
|
||||
rows: 5, cols: 25 |rows: 5, cols: 25 |
|
||||
rows: 5, cols: 24 |rows: 5, cols: 24 |
|
||||
{2:^ } |{2: } |
|
||||
========== ========== |
|
||||
:vsp |
|
||||
@@ -111,7 +111,7 @@ describe('terminal mouse', function()
|
||||
{7: 1 }^ |line28 |
|
||||
{4:~ }|line29 |
|
||||
{4:~ }|line30 |
|
||||
{4:~ }|rows: 5, cols: 25 |
|
||||
{4:~ }|rows: 5, cols: 24 |
|
||||
{4:~ }|{2: } |
|
||||
========== ========== |
|
||||
:enew | set number |
|
||||
@@ -121,16 +121,16 @@ describe('terminal mouse', function()
|
||||
{7: 27 }line |line28 |
|
||||
{7: 28 }line |line29 |
|
||||
{7: 29 }line |line30 |
|
||||
{7: 30 }line |rows: 5, cols: 25 |
|
||||
{7: 30 }line |rows: 5, cols: 24 |
|
||||
{7: 31 }^ |{2: } |
|
||||
========== ========== |
|
||||
|
|
||||
]])
|
||||
feed('<c-w>li')
|
||||
screen:expect([[
|
||||
{7: 27 }line |line29 |
|
||||
{7: 28 }line |line30 |
|
||||
{7: 29 }line |rows: 5, cols: 25 |
|
||||
{7: 27 }line |line28 |
|
||||
{7: 28 }line |line29 |
|
||||
{7: 29 }line |line30 |
|
||||
{7: 30 }line |rows: 5, cols: 24 |
|
||||
{7: 31 } |{1: } |
|
||||
========== ========== |
|
||||
@@ -140,8 +140,8 @@ describe('terminal mouse', function()
|
||||
thelpers.enable_mouse()
|
||||
thelpers.feed_data('mouse enabled\n')
|
||||
screen:expect([[
|
||||
{7: 27 }line |line30 |
|
||||
{7: 28 }line |rows: 5, cols: 25 |
|
||||
{7: 27 }line |line29 |
|
||||
{7: 28 }line |line30 |
|
||||
{7: 29 }line |rows: 5, cols: 24 |
|
||||
{7: 30 }line |mouse enabled |
|
||||
{7: 31 } |{1: } |
|
||||
@@ -153,8 +153,8 @@ describe('terminal mouse', function()
|
||||
it('wont lose focus if another window is scrolled', function()
|
||||
feed('<ScrollWheelUp><0,0><ScrollWheelUp><0,0>')
|
||||
screen:expect([[
|
||||
{7: 21 }line |line30 |
|
||||
{7: 22 }line |rows: 5, cols: 25 |
|
||||
{7: 21 }line |line29 |
|
||||
{7: 22 }line |line30 |
|
||||
{7: 23 }line |rows: 5, cols: 24 |
|
||||
{7: 24 }line |mouse enabled |
|
||||
{7: 25 }line |{1: } |
|
||||
@@ -163,8 +163,8 @@ describe('terminal mouse', function()
|
||||
]])
|
||||
feed('<S-ScrollWheelDown><0,0>')
|
||||
screen:expect([[
|
||||
{7: 26 }line |line30 |
|
||||
{7: 27 }line |rows: 5, cols: 25 |
|
||||
{7: 26 }line |line29 |
|
||||
{7: 27 }line |line30 |
|
||||
{7: 28 }line |rows: 5, cols: 24 |
|
||||
{7: 29 }line |mouse enabled |
|
||||
{7: 30 }line |{1: } |
|
||||
@@ -176,8 +176,8 @@ describe('terminal mouse', function()
|
||||
it('will lose focus if another window is clicked', function()
|
||||
feed('<LeftMouse><5,1>')
|
||||
screen:expect([[
|
||||
{7: 27 }line |line30 |
|
||||
{7: 28 }l^ine |rows: 5, cols: 25 |
|
||||
{7: 27 }line |line29 |
|
||||
{7: 28 }l^ine |line30 |
|
||||
{7: 29 }line |rows: 5, cols: 24 |
|
||||
{7: 30 }line |mouse enabled |
|
||||
{7: 31 } |{2: } |
|
||||
|
||||
@@ -462,10 +462,10 @@ describe("'scrollback' option", function()
|
||||
screen:detach()
|
||||
end)
|
||||
|
||||
it('defaults to 1000 in terminal buffers', function()
|
||||
it('defaults to 10000 in terminal buffers', function()
|
||||
set_fake_shell()
|
||||
command('terminal')
|
||||
eq(1000, curbufmeths.get_option('scrollback'))
|
||||
eq(10000, curbufmeths.get_option('scrollback'))
|
||||
end)
|
||||
|
||||
it('error if set to invalid value', function()
|
||||
|
||||
@@ -380,7 +380,7 @@ describe("tui 't_Co' (terminal colors)", function()
|
||||
-- TODO: Revisit this after jobstart/termopen accept `env` dict.
|
||||
screen = thelpers.screen_setup(0, string.format(
|
||||
[=[['sh', '-c', 'LANG=C TERM=%s %s %s -u NONE -i NONE --cmd "silent set noswapfile noshowcmd noruler"']]=],
|
||||
term,
|
||||
term or "",
|
||||
(colorterm ~= nil and "COLORTERM="..colorterm or ""),
|
||||
helpers.nvim_prog))
|
||||
|
||||
|
||||
@@ -43,14 +43,23 @@ describe('terminal window', function()
|
||||
-- numberwidth=9
|
||||
feed([[<C-\><C-N>]])
|
||||
feed([[:set numberwidth=9 number<CR>i]])
|
||||
screen:expect([[
|
||||
{7: 1 }tty ready |
|
||||
{7: 2 }rows: 6, cols: 48 |
|
||||
{7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO|
|
||||
{7: 4 }WXYZrows: 6, cols: 41 |
|
||||
{7: 5 }{1: } |
|
||||
{7: 6 } |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
thelpers.feed_data({' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'})
|
||||
screen:expect([[
|
||||
{7: 1 }tty ready |
|
||||
{7: 2 }rows: 6, cols: 48 |
|
||||
{7: 3 }abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO|
|
||||
{7: 4 }WXYZ abcdefghijklmnopqrstuvwxyzABCDEFGHIJ|
|
||||
{7: 5 }KLMNOPQRSTUVWXYZrows: 6, cols: 41 |
|
||||
{7: 6 }{1: } |
|
||||
{7: 4 }WXYZrows: 6, cols: 41 |
|
||||
{7: 5 } abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN|
|
||||
{7: 6 }OPQRSTUVWXYZ{1: } |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
end)
|
||||
|
||||
@@ -3,6 +3,9 @@ local thelpers = require('test.functional.terminal.helpers')
|
||||
local clear = helpers.clear
|
||||
local feed, nvim = helpers.feed, helpers.nvim
|
||||
local feed_command = helpers.feed_command
|
||||
local command = helpers.command
|
||||
local eq = helpers.eq
|
||||
local eval = helpers.eval
|
||||
|
||||
describe('terminal', function()
|
||||
local screen
|
||||
@@ -22,72 +25,66 @@ describe('terminal', function()
|
||||
screen:detach()
|
||||
end)
|
||||
|
||||
it('resets its size when entering terminal window', function()
|
||||
it('next to a closing window', function()
|
||||
command('split')
|
||||
command('terminal')
|
||||
command('vsplit foo')
|
||||
eq(3, eval("winnr('$')"))
|
||||
feed('ZQ') -- Close split, should not crash. #7538
|
||||
eq(2, eval("1+1")) -- Still alive?
|
||||
end)
|
||||
|
||||
it('does not change size on WinEnter', function()
|
||||
if helpers.pending_win32(pending) then return end
|
||||
feed('<c-\\><c-n>')
|
||||
feed_command('2split')
|
||||
screen:expect([[
|
||||
rows: 2, cols: 50 |
|
||||
{2:^ } |
|
||||
tty ready |
|
||||
^rows: 5, cols: 50 |
|
||||
========== |
|
||||
rows: 2, cols: 50 |
|
||||
tty ready |
|
||||
rows: 5, cols: 50 |
|
||||
{2: } |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
|
|
||||
|
|
||||
========== |
|
||||
:2split |
|
||||
]])
|
||||
feed_command('wincmd p')
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
rows: 2, cols: 50 |
|
||||
rows: 5, cols: 50 |
|
||||
========== |
|
||||
tty ready |
|
||||
rows: 2, cols: 50 |
|
||||
rows: 5, cols: 50 |
|
||||
^rows: 5, cols: 50 |
|
||||
{2: } |
|
||||
^ |
|
||||
========== |
|
||||
:wincmd p |
|
||||
]])
|
||||
feed_command('wincmd p')
|
||||
screen:expect([[
|
||||
rows: 2, cols: 50 |
|
||||
{2:^ } |
|
||||
========== |
|
||||
rows: 2, cols: 50 |
|
||||
{2: } |
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
|
|
||||
|
|
||||
========== |
|
||||
:wincmd p |
|
||||
]])
|
||||
end)
|
||||
|
||||
describe('when the screen is resized', function()
|
||||
it('will forward a 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)
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
rows: 7, cols: 47 |
|
||||
{2: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
:^ |
|
||||
]])
|
||||
screen:try_resize(screen._width - 6, screen._height - 3)
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
rows: 7, cols: 47 |
|
||||
rows: 4, cols: 41 |
|
||||
{2: } |
|
||||
:^ |
|
||||
]])
|
||||
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)
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
rows: 7, cols: 47 |
|
||||
{2: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
:^ |
|
||||
]])
|
||||
screen:try_resize(screen._width - 6, screen._height - 3)
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
rows: 7, cols: 47 |
|
||||
rows: 4, cols: 41 |
|
||||
{2: } |
|
||||
:^ |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -366,134 +366,156 @@ describe('path.c', function()
|
||||
end)
|
||||
|
||||
describe('vim_FullName', function()
|
||||
local function vim_FullName(filename, buf, len, force)
|
||||
filename = to_cstr(filename)
|
||||
return cimp.vim_FullName(filename, buf, len, force)
|
||||
local function vim_FullName(filename, buflen, do_expand)
|
||||
local buf = cstr(buflen, '')
|
||||
local result = cimp.vim_FullName(to_cstr(filename), buf, buflen, do_expand)
|
||||
return buf, result
|
||||
end
|
||||
|
||||
before_each(function()
|
||||
-- Create empty string buffer which will contain the resulting path.
|
||||
length = (string.len(lfs.currentdir())) + 33
|
||||
buffer = cstr(length, '')
|
||||
end)
|
||||
local function get_buf_len(s, t)
|
||||
return math.max(string.len(s), string.len(t)) + 1
|
||||
end
|
||||
|
||||
itp('fails if given filename is NULL', function()
|
||||
local force_expansion = 1
|
||||
local result = cimp.vim_FullName(NULL, buffer, length, force_expansion)
|
||||
local do_expand = 1
|
||||
local buflen = 10
|
||||
local buf = cstr(buflen, '')
|
||||
local result = cimp.vim_FullName(NULL, buf, buflen, do_expand)
|
||||
eq(FAIL, result)
|
||||
end)
|
||||
|
||||
itp('fails safely if given length is wrong #5737', function()
|
||||
local force_expansion = 1
|
||||
local filename = 'foo/bar/bazzzzzzz/buz/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/a'
|
||||
local too_short_len = 8
|
||||
local buf = cstr(too_short_len, '')
|
||||
local result = cimp.vim_FullName(filename, buf, too_short_len, force_expansion)
|
||||
local do_expand = 1
|
||||
local result = cimp.vim_FullName(filename, buf, too_short_len, do_expand)
|
||||
local expected = string.sub(filename, 1, (too_short_len - 1))
|
||||
eq(expected, (ffi.string(buf)))
|
||||
eq(expected, ffi.string(buf))
|
||||
eq(FAIL, result)
|
||||
end)
|
||||
|
||||
itp('uses the filename if the filename is a URL', function()
|
||||
local force_expansion = 1
|
||||
local filename = 'http://www.neovim.org'
|
||||
local result = vim_FullName(filename, buffer, length, force_expansion)
|
||||
eq(filename, (ffi.string(buffer)))
|
||||
local buflen = string.len(filename) + 1
|
||||
local do_expand = 1
|
||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||
eq(filename, ffi.string(buf))
|
||||
eq(OK, result)
|
||||
end)
|
||||
|
||||
itp('fails and uses filename if given filename contains non-existing directory', function()
|
||||
local force_expansion = 1
|
||||
local filename = 'non_existing_dir/test.file'
|
||||
local result = vim_FullName(filename, buffer, length, force_expansion)
|
||||
eq(filename, (ffi.string(buffer)))
|
||||
local buflen = string.len(filename) + 1
|
||||
local do_expand = 1
|
||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||
eq(filename, ffi.string(buf))
|
||||
eq(FAIL, result)
|
||||
end)
|
||||
|
||||
itp('concatenates filename if it does not contain a slash', function()
|
||||
local force_expansion = 1
|
||||
local result = vim_FullName('test.file', buffer, length, force_expansion)
|
||||
local expected = lfs.currentdir() .. '/test.file'
|
||||
eq(expected, (ffi.string(buffer)))
|
||||
local filename = 'test.file'
|
||||
local buflen = get_buf_len(expected, filename)
|
||||
local do_expand = 1
|
||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||
eq(expected, ffi.string(buf))
|
||||
eq(OK, result)
|
||||
end)
|
||||
|
||||
itp('concatenates directory name if it does not contain a slash', function()
|
||||
local force_expansion = 1
|
||||
local result = vim_FullName('..', buffer, length, force_expansion)
|
||||
local expected = lfs.currentdir() .. '/..'
|
||||
eq(expected, (ffi.string(buffer)))
|
||||
local filename = '..'
|
||||
local buflen = get_buf_len(expected, filename)
|
||||
local do_expand = 1
|
||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||
eq(expected, ffi.string(buf))
|
||||
eq(OK, result)
|
||||
end)
|
||||
|
||||
-- Is it possible for every developer to enter '..' directory while running
|
||||
-- the unit tests? Which other directory would be better?
|
||||
itp('enters given directory (instead of just concatenating the strings) if possible and if path contains a slash', function()
|
||||
local force_expansion = 1
|
||||
local result = vim_FullName('../test.file', buffer, length, force_expansion)
|
||||
local old_dir = lfs.currentdir()
|
||||
lfs.chdir('..')
|
||||
local expected = lfs.currentdir() .. '/test.file'
|
||||
lfs.chdir(old_dir)
|
||||
eq(expected, (ffi.string(buffer)))
|
||||
local filename = '../test.file'
|
||||
local buflen = get_buf_len(expected, filename)
|
||||
local do_expand = 1
|
||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||
eq(expected, ffi.string(buf))
|
||||
eq(OK, result)
|
||||
end)
|
||||
|
||||
itp('just copies the path if it is already absolute and force=0', function()
|
||||
local force_expansion = 0
|
||||
local absolute_path = '/absolute/path'
|
||||
local result = vim_FullName(absolute_path, buffer, length, force_expansion)
|
||||
eq(absolute_path, (ffi.string(buffer)))
|
||||
local buflen = string.len(absolute_path) + 1
|
||||
local do_expand = 0
|
||||
local buf, result = vim_FullName(absolute_path, buflen, do_expand)
|
||||
eq(absolute_path, ffi.string(buf))
|
||||
eq(OK, result)
|
||||
end)
|
||||
|
||||
itp('fails and uses filename when the path is relative to HOME', function()
|
||||
eq(false, cimp.os_isdir('~')) -- sanity check: no literal "~" directory.
|
||||
local force_expansion = 1
|
||||
local absolute_path = '~/home.file'
|
||||
local result = vim_FullName(absolute_path, buffer, length, force_expansion)
|
||||
eq(absolute_path, (ffi.string(buffer)))
|
||||
local buflen = string.len(absolute_path) + 1
|
||||
local do_expand = 1
|
||||
local buf, result = vim_FullName(absolute_path, buflen, do_expand)
|
||||
eq(absolute_path, ffi.string(buf))
|
||||
eq(FAIL, result)
|
||||
end)
|
||||
|
||||
itp('works with some "normal" relative path with directories', function()
|
||||
local force_expansion = 1
|
||||
local result = vim_FullName('unit-test-directory/test.file', buffer, length, force_expansion)
|
||||
local expected = lfs.currentdir() .. '/unit-test-directory/test.file'
|
||||
local filename = 'unit-test-directory/test.file'
|
||||
local buflen = get_buf_len(expected, filename)
|
||||
local do_expand = 1
|
||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||
eq(expected, ffi.string(buf))
|
||||
eq(OK, result)
|
||||
eq(lfs.currentdir() .. '/unit-test-directory/test.file', (ffi.string(buffer)))
|
||||
end)
|
||||
|
||||
itp('does not modify the given filename', function()
|
||||
local force_expansion = 1
|
||||
local expected = lfs.currentdir() .. '/unit-test-directory/test.file'
|
||||
local filename = to_cstr('unit-test-directory/test.file')
|
||||
-- Don't use the wrapper here but pass a cstring directly to the c
|
||||
-- function.
|
||||
local result = cimp.vim_FullName(filename, buffer, length, force_expansion)
|
||||
eq(lfs.currentdir() .. '/unit-test-directory/test.file', (ffi.string(buffer)))
|
||||
eq('unit-test-directory/test.file', (ffi.string(filename)))
|
||||
local buflen = string.len(expected) + 1
|
||||
local buf = cstr(buflen, '')
|
||||
local do_expand = 1
|
||||
-- Don't use the wrapper but pass a cstring directly to the c function.
|
||||
eq('unit-test-directory/test.file', ffi.string(filename))
|
||||
local result = cimp.vim_FullName(filename, buf, buflen, do_expand)
|
||||
eq(expected, ffi.string(buf))
|
||||
eq(OK, result)
|
||||
end)
|
||||
|
||||
itp('works with directories that have one path component', function()
|
||||
local force_expansion = 1
|
||||
local filename = to_cstr('/tmp')
|
||||
local result = cimp.vim_FullName(filename, buffer, length, force_expansion)
|
||||
eq('/tmp', ffi.string(buffer))
|
||||
local filename = '/tmp'
|
||||
local expected = filename
|
||||
local buflen = get_buf_len(expected, filename)
|
||||
local do_expand = 1
|
||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||
eq('/tmp', ffi.string(buf))
|
||||
eq(OK, result)
|
||||
end)
|
||||
|
||||
itp('expands "./" to the current directory #7117', function()
|
||||
local force_expansion = 1
|
||||
local result = vim_FullName('./unit-test-directory/test.file', buffer, length, force_expansion)
|
||||
local expected = lfs.currentdir() .. '/unit-test-directory/test.file'
|
||||
local filename = './unit-test-directory/test.file'
|
||||
local buflen = get_buf_len(expected, filename)
|
||||
local do_expand = 1
|
||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||
eq(OK, result)
|
||||
eq(lfs.currentdir() .. '/unit-test-directory/test.file', (ffi.string(buffer)))
|
||||
eq(expected, ffi.string(buf))
|
||||
end)
|
||||
|
||||
itp('collapses "foo/../foo" to "foo" #7117', function()
|
||||
local force_expansion = 1
|
||||
local result = vim_FullName('unit-test-directory/../unit-test-directory/test.file', buffer, length, force_expansion)
|
||||
local expected = lfs.currentdir() .. '/unit-test-directory/test.file'
|
||||
local filename = 'unit-test-directory/../unit-test-directory/test.file'
|
||||
local buflen = get_buf_len(expected, filename)
|
||||
local do_expand = 1
|
||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||
eq(OK, result)
|
||||
eq(lfs.currentdir() .. '/unit-test-directory/test.file', (ffi.string(buffer)))
|
||||
eq(expected, ffi.string(buf))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user