Merge branch 'master' into expression-parser

This commit is contained in:
ZyX
2017-11-19 22:05:22 +03:00
240 changed files with 14756 additions and 9574 deletions

View File

@@ -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
----

View 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)

View File

@@ -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)

View 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)

Binary file not shown.

View File

@@ -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.

View File

@@ -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 } |

View File

@@ -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: } |

View File

@@ -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()

View File

@@ -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))

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)