test/fs: sanity check for literal "~" directory (#6579)

If the CWD contains a directory with the literal name "~" then the tests
will have bogus failures.
This commit is contained in:
Justin M. Keyes
2017-04-24 22:45:03 +02:00
committed by GitHub
parent 8dc3eca49b
commit 8f346a322b
3 changed files with 73 additions and 64 deletions

View File

@@ -61,9 +61,9 @@ void fs_init(void)
} }
/// Change to the given directory. /// Changes the current directory to `path`.
/// ///
/// @return `0` on success, a libuv error code on failure. /// @return 0 on success, or negative error code.
int os_chdir(const char *path) int os_chdir(const char *path)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {

View File

@@ -35,7 +35,6 @@ for i = 0, 255 do
end end
local fcontents = s:rep(16) local fcontents = s:rep(16)
local buffer = ""
local directory = nil local directory = nil
local absolute_executable = nil local absolute_executable = nil
local executable_name = nil local executable_name = nil
@@ -65,7 +64,11 @@ local function os_getperm(filename)
return tonumber(perm) return tonumber(perm)
end end
describe('fs function', function() describe('fs.c', function()
local function os_isdir(name)
return fs.os_isdir(to_cstr(name))
end
before_each(function() before_each(function()
lfs.mkdir('unit-test-directory'); lfs.mkdir('unit-test-directory');
@@ -91,32 +94,37 @@ describe('fs function', function()
end) end)
describe('os_dirname', function() describe('os_dirname', function()
local length itp('returns OK and writes current directory to the buffer', function()
local length = string.len(lfs.currentdir()) + 1
local function os_dirname(buf, len) local buf = cstr(length, '')
return fs.os_dirname(buf, len) eq(OK, fs.os_dirname(buf, length))
end eq(lfs.currentdir(), ffi.string(buf))
before_each(function()
length = (string.len(lfs.currentdir())) + 1
buffer = cstr(length, '')
end) end)
itp('returns OK and writes current directory into the buffer if it is large\n enough', function()
eq(OK, (os_dirname(buffer, length)))
eq(lfs.currentdir(), (ffi.string(buffer)))
end)
-- What kind of other failing cases are possible?
itp('returns FAIL if the buffer is too small', function() itp('returns FAIL if the buffer is too small', function()
local buf = cstr((length - 1), '') local length = string.len(lfs.currentdir()) + 1
eq(FAIL, (os_dirname(buf, (length - 1)))) local buf = cstr(length - 1, '')
eq(FAIL, fs.os_dirname(buf, length - 1))
end) end)
end) end)
local function os_isdir(name) describe('os_chdir', function()
return fs.os_isdir((to_cstr(name))) itp('fails with path="~"', function()
end eq(false, os_isdir('~')) -- sanity check: no literal "~" directory.
local length = 4096
local expected_cwd = cstr(length, '')
local cwd = cstr(length, '')
eq(OK, fs.os_dirname(expected_cwd, length))
-- os_chdir returns 0 for success, not OK (1).
neq(0, fs.os_chdir('~')) -- fail
neq(0, fs.os_chdir('~/')) -- fail
eq(OK, fs.os_dirname(cwd, length))
-- CWD did not change.
eq(ffi.string(expected_cwd), ffi.string(cwd))
end)
end)
describe('os_isdir', function() describe('os_isdir', function()
itp('returns false if an empty string is given', function() itp('returns false if an empty string is given', function()

View File

@@ -13,7 +13,7 @@ local OK = helpers.OK
local FAIL = helpers.FAIL local FAIL = helpers.FAIL
cimport('string.h') cimport('string.h')
local path = cimport('./src/nvim/path.h') local cimp = cimport('./src/nvim/os/os.h', './src/nvim/path.h')
local length = 0 local length = 0
local buffer = nil local buffer = nil
@@ -30,7 +30,7 @@ describe('path function', function()
local function path_full_dir_name(directory, buf, len) local function path_full_dir_name(directory, buf, len)
directory = to_cstr(directory) directory = to_cstr(directory)
return path.path_full_dir_name(directory, buf, len) return cimp.path_full_dir_name(directory, buf, len)
end end
before_each(function() before_each(function()
@@ -69,7 +69,7 @@ describe('path function', function()
local function path_full_compare(s1, s2, cn) local function path_full_compare(s1, s2, cn)
s1 = to_cstr(s1) s1 = to_cstr(s1)
s2 = to_cstr(s2) s2 = to_cstr(s2)
return path.path_full_compare(s1, s2, cn or 0) return cimp.path_full_compare(s1, s2, cn or 0)
end end
local f1 = 'f1.o' local f1 = 'f1.o'
@@ -86,31 +86,31 @@ describe('path function', function()
end) end)
itp('returns kEqualFiles when passed the same file', function() itp('returns kEqualFiles when passed the same file', function()
eq(path.kEqualFiles, (path_full_compare(f1, f1))) eq(cimp.kEqualFiles, (path_full_compare(f1, f1)))
end) end)
itp('returns kEqualFileNames when files that dont exist and have same name', function() itp('returns kEqualFileNames when files that dont exist and have same name', function()
eq(path.kEqualFileNames, (path_full_compare('null.txt', 'null.txt', true))) eq(cimp.kEqualFileNames, (path_full_compare('null.txt', 'null.txt', true)))
end) end)
itp('returns kBothFilesMissing when files that dont exist', function() itp('returns kBothFilesMissing when files that dont exist', function()
eq(path.kBothFilesMissing, (path_full_compare('null.txt', 'null.txt'))) eq(cimp.kBothFilesMissing, (path_full_compare('null.txt', 'null.txt')))
end) end)
itp('returns kDifferentFiles when passed different files', function() itp('returns kDifferentFiles when passed different files', function()
eq(path.kDifferentFiles, (path_full_compare(f1, f2))) eq(cimp.kDifferentFiles, (path_full_compare(f1, f2)))
eq(path.kDifferentFiles, (path_full_compare(f2, f1))) eq(cimp.kDifferentFiles, (path_full_compare(f2, f1)))
end) end)
itp('returns kOneFileMissing if only one does not exist', function() itp('returns kOneFileMissing if only one does not exist', function()
eq(path.kOneFileMissing, (path_full_compare(f1, 'null.txt'))) eq(cimp.kOneFileMissing, (path_full_compare(f1, 'null.txt')))
eq(path.kOneFileMissing, (path_full_compare('null.txt', f1))) eq(cimp.kOneFileMissing, (path_full_compare('null.txt', f1)))
end) end)
end) end)
describe('path_tail', function() describe('path_tail', function()
local function path_tail(file) local function path_tail(file)
local res = path.path_tail((to_cstr(file))) local res = cimp.path_tail((to_cstr(file)))
neq(NULL, res) neq(NULL, res)
return ffi.string(res) return ffi.string(res)
end end
@@ -126,7 +126,7 @@ describe('path function', function()
describe('path_tail_with_sep', function() describe('path_tail_with_sep', function()
local function path_tail_with_sep(file) local function path_tail_with_sep(file)
local res = path.path_tail_with_sep((to_cstr(file))) local res = cimp.path_tail_with_sep((to_cstr(file)))
neq(NULL, res) neq(NULL, res)
return ffi.string(res) return ffi.string(res)
end end
@@ -159,11 +159,11 @@ describe('path function', function()
-- strcmp. -- strcmp.
local function invocation_path_tail(invk) local function invocation_path_tail(invk)
local plen = ffi.new('size_t[?]', 1) local plen = ffi.new('size_t[?]', 1)
local ptail = path.invocation_path_tail((to_cstr(invk)), plen) local ptail = cimp.invocation_path_tail((to_cstr(invk)), plen)
neq(NULL, ptail) neq(NULL, ptail)
-- it does not change the output if len==NULL -- it does not change the output if len==NULL
local tail2 = path.invocation_path_tail((to_cstr(invk)), NULL) local tail2 = cimp.invocation_path_tail((to_cstr(invk)), NULL)
neq(NULL, tail2) neq(NULL, tail2)
eq((ffi.string(ptail)), (ffi.string(tail2))) eq((ffi.string(ptail)), (ffi.string(tail2)))
return ptail, plen[0] return ptail, plen[0]
@@ -204,7 +204,7 @@ describe('path function', function()
end) end)
itp('is equivalent to path_tail when args do not contain a path separator', function() itp('is equivalent to path_tail when args do not contain a path separator', function()
local ptail = path.path_tail(to_cstr("a/b/c x y z")) local ptail = cimp.path_tail(to_cstr("a/b/c x y z"))
neq(NULL, ptail) neq(NULL, ptail)
local tail = ffi.string(ptail) local tail = ffi.string(ptail)
local invk, _ = invocation_path_tail("a/b/c x y z") local invk, _ = invocation_path_tail("a/b/c x y z")
@@ -212,7 +212,7 @@ describe('path function', function()
end) end)
itp('is not equivalent to path_tail when args contain a path separator', function() itp('is not equivalent to path_tail when args contain a path separator', function()
local ptail = path.path_tail(to_cstr("a/b/c x y/z")) local ptail = cimp.path_tail(to_cstr("a/b/c x y/z"))
neq(NULL, ptail) neq(NULL, ptail)
local invk, _ = invocation_path_tail("a/b/c x y/z") local invk, _ = invocation_path_tail("a/b/c x y/z")
neq((ffi.string(ptail)), (ffi.string(invk))) neq((ffi.string(ptail)), (ffi.string(invk)))
@@ -221,7 +221,7 @@ describe('path function', function()
describe('path_next_component', function() describe('path_next_component', function()
local function path_next_component(file) local function path_next_component(file)
local res = path.path_next_component((to_cstr(file))) local res = cimp.path_next_component((to_cstr(file)))
neq(NULL, res) neq(NULL, res)
return ffi.string(res) return ffi.string(res)
end end
@@ -238,25 +238,25 @@ describe('path function', function()
describe('path_shorten_fname', function() describe('path_shorten_fname', function()
itp('returns NULL if `full_path` is NULL', function() itp('returns NULL if `full_path` is NULL', function()
local dir = to_cstr('some/directory/file.txt') local dir = to_cstr('some/directory/file.txt')
eq(NULL, (path.path_shorten_fname(NULL, dir))) eq(NULL, (cimp.path_shorten_fname(NULL, dir)))
end) end)
itp('returns NULL if the path and dir does not match', function() itp('returns NULL if the path and dir does not match', function()
local dir = to_cstr('not/the/same') local dir = to_cstr('not/the/same')
local full = to_cstr('as/this.txt') local full = to_cstr('as/this.txt')
eq(NULL, (path.path_shorten_fname(full, dir))) eq(NULL, (cimp.path_shorten_fname(full, dir)))
end) end)
itp('returns NULL if the path is not separated properly', function() itp('returns NULL if the path is not separated properly', function()
local dir = to_cstr('some/very/long/') local dir = to_cstr('some/very/long/')
local full = to_cstr('some/very/long/directory/file.txt') local full = to_cstr('some/very/long/directory/file.txt')
eq(NULL, (path.path_shorten_fname(full, dir))) eq(NULL, (cimp.path_shorten_fname(full, dir)))
end) end)
itp('shortens the filename if `dir_name` is the start of `full_path`', function() itp('shortens the filename if `dir_name` is the start of `full_path`', function()
local full = to_cstr('some/very/long/directory/file.txt') local full = to_cstr('some/very/long/directory/file.txt')
local dir = to_cstr('some/very/long') local dir = to_cstr('some/very/long')
eq('directory/file.txt', (ffi.string(path.path_shorten_fname(full, dir)))) eq('directory/file.txt', (ffi.string(cimp.path_shorten_fname(full, dir))))
end) end)
end) end)
end) end)
@@ -277,23 +277,23 @@ describe('path_shorten_fname_if_possible', function()
itp('returns shortened path if possible', function() itp('returns shortened path if possible', function()
lfs.chdir('ut_directory') lfs.chdir('ut_directory')
local full = to_cstr(lfs.currentdir() .. '/subdir/file.txt') local full = to_cstr(lfs.currentdir() .. '/subdir/file.txt')
eq('subdir/file.txt', (ffi.string(path.path_shorten_fname_if_possible(full)))) eq('subdir/file.txt', (ffi.string(cimp.path_shorten_fname_if_possible(full))))
end) end)
itp('returns `full_path` if a shorter version is not possible', function() itp('returns `full_path` if a shorter version is not possible', function()
local old = lfs.currentdir() local old = lfs.currentdir()
lfs.chdir('ut_directory') lfs.chdir('ut_directory')
local full = old .. '/subdir/file.txt' local full = old .. '/subdir/file.txt'
eq(full, (ffi.string(path.path_shorten_fname_if_possible(to_cstr(full))))) eq(full, (ffi.string(cimp.path_shorten_fname_if_possible(to_cstr(full)))))
end) end)
itp('returns NULL if `full_path` is NULL', function() itp('returns NULL if `full_path` is NULL', function()
eq(NULL, (path.path_shorten_fname_if_possible(NULL))) eq(NULL, (cimp.path_shorten_fname_if_possible(NULL)))
end) end)
end) end)
end) end)
describe('more path function', function() describe('path.c', function()
setup(function() setup(function()
lfs.mkdir('unit-test-directory'); lfs.mkdir('unit-test-directory');
io.open('unit-test-directory/test.file', 'w').close() io.open('unit-test-directory/test.file', 'w').close()
@@ -315,7 +315,7 @@ describe('more path function', function()
describe('vim_FullName', function() describe('vim_FullName', function()
local function vim_FullName(filename, buf, len, force) local function vim_FullName(filename, buf, len, force)
filename = to_cstr(filename) filename = to_cstr(filename)
return path.vim_FullName(filename, buf, len, force) return cimp.vim_FullName(filename, buf, len, force)
end end
before_each(function() before_each(function()
@@ -326,7 +326,7 @@ describe('more path function', function()
itp('fails if given filename is NULL', function() itp('fails if given filename is NULL', function()
local force_expansion = 1 local force_expansion = 1
local result = path.vim_FullName(NULL, buffer, length, force_expansion) local result = cimp.vim_FullName(NULL, buffer, length, force_expansion)
eq(FAIL, result) eq(FAIL, result)
end) end)
@@ -335,7 +335,7 @@ describe('more path function', function()
local filename = 'foo/bar/bazzzzzzz/buz/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/a' local filename = 'foo/bar/bazzzzzzz/buz/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/a'
local too_short_len = 8 local too_short_len = 8
local buf = cstr(too_short_len, '') local buf = cstr(too_short_len, '')
local result = path.vim_FullName(filename, buf, too_short_len, force_expansion) local result = cimp.vim_FullName(filename, buf, too_short_len, force_expansion)
local expected = string.sub(filename, 1, (too_short_len - 1)) local expected = string.sub(filename, 1, (too_short_len - 1))
eq(expected, (ffi.string(buf))) eq(expected, (ffi.string(buf)))
eq(FAIL, result) eq(FAIL, result)
@@ -357,7 +357,7 @@ describe('more path function', function()
eq(FAIL, result) eq(FAIL, result)
end) end)
itp('concatenates given filename if it does not contain a slash', function() itp('concatenates filename if it does not contain a slash', function()
local force_expansion = 1 local force_expansion = 1
local result = vim_FullName('test.file', buffer, length, force_expansion) local result = vim_FullName('test.file', buffer, length, force_expansion)
local expected = lfs.currentdir() .. '/test.file' local expected = lfs.currentdir() .. '/test.file'
@@ -365,7 +365,7 @@ describe('more path function', function()
eq(OK, result) eq(OK, result)
end) end)
itp('concatenates given filename if it is a directory but does not contain a\n slash', function() itp('concatenates directory name if it does not contain a slash', function()
local force_expansion = 1 local force_expansion = 1
local result = vim_FullName('..', buffer, length, force_expansion) local result = vim_FullName('..', buffer, length, force_expansion)
local expected = lfs.currentdir() .. '/..' local expected = lfs.currentdir() .. '/..'
@@ -395,6 +395,7 @@ describe('more path function', function()
end) end)
itp('fails and uses filename when the path is relative to HOME', function() 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 force_expansion = 1
local absolute_path = '~/home.file' local absolute_path = '~/home.file'
local result = vim_FullName(absolute_path, buffer, length, force_expansion) local result = vim_FullName(absolute_path, buffer, length, force_expansion)
@@ -414,7 +415,7 @@ describe('more path function', function()
local filename = to_cstr('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 -- Don't use the wrapper here but pass a cstring directly to the c
-- function. -- function.
local result = path.vim_FullName(filename, buffer, length, force_expansion) local result = cimp.vim_FullName(filename, buffer, length, force_expansion)
eq(lfs.currentdir() .. '/unit-test-directory/test.file', (ffi.string(buffer))) eq(lfs.currentdir() .. '/unit-test-directory/test.file', (ffi.string(buffer)))
eq('unit-test-directory/test.file', (ffi.string(filename))) eq('unit-test-directory/test.file', (ffi.string(filename)))
eq(OK, result) eq(OK, result)
@@ -423,7 +424,7 @@ describe('more path function', function()
itp('works with directories that have one path component', function() itp('works with directories that have one path component', function()
local force_expansion = 1 local force_expansion = 1
local filename = to_cstr('/tmp') local filename = to_cstr('/tmp')
local result = path.vim_FullName(filename, buffer, length, force_expansion) local result = cimp.vim_FullName(filename, buffer, length, force_expansion)
eq('/tmp', ffi.string(buffer)) eq('/tmp', ffi.string(buffer))
eq(OK, result) eq(OK, result)
end) end)
@@ -432,7 +433,7 @@ describe('more path function', function()
describe('path_fix_case', function() describe('path_fix_case', function()
local function fix_case(file) local function fix_case(file)
local c_file = to_cstr(file) local c_file = to_cstr(file)
path.path_fix_case(c_file) cimp.path_fix_case(c_file)
return ffi.string(c_file) return ffi.string(c_file)
end end
@@ -456,41 +457,41 @@ describe('more path function', function()
itp('joins given paths with a slash', function() itp('joins given paths with a slash', function()
local path1 = cstr(100, 'path1') local path1 = cstr(100, 'path1')
local to_append = to_cstr('path2') local to_append = to_cstr('path2')
eq(OK, (path.append_path(path1, to_append, 100))) eq(OK, (cimp.append_path(path1, to_append, 100)))
eq("path1/path2", (ffi.string(path1))) eq("path1/path2", (ffi.string(path1)))
end) end)
itp('joins given paths without adding an unnecessary slash', function() itp('joins given paths without adding an unnecessary slash', function()
local path1 = cstr(100, 'path1/') local path1 = cstr(100, 'path1/')
local to_append = to_cstr('path2') local to_append = to_cstr('path2')
eq(OK, path.append_path(path1, to_append, 100)) eq(OK, cimp.append_path(path1, to_append, 100))
eq("path1/path2", (ffi.string(path1))) eq("path1/path2", (ffi.string(path1)))
end) end)
itp('fails and uses filename if there is not enough space left for to_append', function() itp('fails and uses filename if there is not enough space left for to_append', function()
local path1 = cstr(11, 'path1/') local path1 = cstr(11, 'path1/')
local to_append = to_cstr('path2') local to_append = to_cstr('path2')
eq(FAIL, (path.append_path(path1, to_append, 11))) eq(FAIL, (cimp.append_path(path1, to_append, 11)))
end) end)
itp('does not append a slash if to_append is empty', function() itp('does not append a slash if to_append is empty', function()
local path1 = cstr(6, 'path1') local path1 = cstr(6, 'path1')
local to_append = to_cstr('') local to_append = to_cstr('')
eq(OK, (path.append_path(path1, to_append, 6))) eq(OK, (cimp.append_path(path1, to_append, 6)))
eq('path1', (ffi.string(path1))) eq('path1', (ffi.string(path1)))
end) end)
itp('does not append unnecessary dots', function() itp('does not append unnecessary dots', function()
local path1 = cstr(6, 'path1') local path1 = cstr(6, 'path1')
local to_append = to_cstr('.') local to_append = to_cstr('.')
eq(OK, (path.append_path(path1, to_append, 6))) eq(OK, (cimp.append_path(path1, to_append, 6)))
eq('path1', (ffi.string(path1))) eq('path1', (ffi.string(path1)))
end) end)
itp('copies to_append to path, if path is empty', function() itp('copies to_append to path, if path is empty', function()
local path1 = cstr(7, '') local path1 = cstr(7, '')
local to_append = to_cstr('/path2') local to_append = to_cstr('/path2')
eq(OK, (path.append_path(path1, to_append, 7))) eq(OK, (cimp.append_path(path1, to_append, 7)))
eq('/path2', (ffi.string(path1))) eq('/path2', (ffi.string(path1)))
end) end)
end) end)
@@ -498,7 +499,7 @@ describe('more path function', function()
describe('path_is_absolute_path', function() describe('path_is_absolute_path', function()
local function path_is_absolute_path(filename) local function path_is_absolute_path(filename)
filename = to_cstr(filename) filename = to_cstr(filename)
return path.path_is_absolute_path(filename) return cimp.path_is_absolute_path(filename)
end end
itp('returns true if filename starts with a slash', function() itp('returns true if filename starts with a slash', function()