aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2018-04-27 23:37:30 +0200
committerJustin M. Keyes <justinkz@gmail.com>2018-04-27 23:37:30 +0200
commit7e7c3111b66f4eb5aa7c62936931db3a2c3921ad (patch)
tree30fd863d5403a32fd968ab11e6adbc6ed3216817
parent53f11dcfc7139fe6c8a6b114db4bfec5d91005a9 (diff)
parentbd17ef75b34b0ca10b795b705ffa82cc4eb30ee9 (diff)
downloadrneovim-7e7c3111b66f4eb5aa7c62936931db3a2c3921ad.tar.gz
rneovim-7e7c3111b66f4eb5aa7c62936931db3a2c3921ad.tar.bz2
rneovim-7e7c3111b66f4eb5aa7c62936931db3a2c3921ad.zip
Merge #4985
closes #4985
-rw-r--r--test/functional/helpers.lua70
-rw-r--r--test/helpers.lua67
-rw-r--r--test/unit/undo_spec.lua216
3 files changed, 289 insertions, 64 deletions
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 655200e6f7..9895281773 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -12,15 +12,18 @@ local Paths = require('test.config.paths')
local check_cores = global_helpers.check_cores
local check_logs = global_helpers.check_logs
-local neq = global_helpers.neq
+local dedent = global_helpers.dedent
local eq = global_helpers.eq
local expect_err = global_helpers.expect_err
-local ok = global_helpers.ok
+local filter = global_helpers.filter
local map = global_helpers.map
local matches = global_helpers.matches
-local filter = global_helpers.filter
-local dedent = global_helpers.dedent
+local neq = global_helpers.neq
+local ok = global_helpers.ok
+local read_file = global_helpers.read_file
+local sleep = global_helpers.sleep
local table_flatten = global_helpers.table_flatten
+local write_file = global_helpers.write_file
local start_dir = lfs.currentdir()
-- XXX: NVIM_PROG takes precedence, QuickBuild sets it.
@@ -374,34 +377,6 @@ local function feed_command(...)
end
end
--- Dedent the given text and write it to the file name.
-local function write_file(name, text, no_dedent, append)
- local file = io.open(name, (append and 'a' or 'w'))
- if type(text) == 'table' then
- -- Byte blob
- local bytes = text
- text = ''
- for _, char in ipairs(bytes) do
- text = ('%s%c'):format(text, char)
- end
- elseif not no_dedent then
- text = dedent(text)
- end
- file:write(text)
- file:flush()
- file:close()
-end
-
-local function read_file(name)
- local file = io.open(name, 'r')
- if not file then
- return nil
- end
- local ret = file:read('*a')
- file:close()
- return ret
-end
-
local sourced_fnames = {}
local function source(code)
local fname = tmpname()
@@ -466,11 +441,6 @@ local function wait()
session:request('nvim_eval', '1')
end
--- sleeps the test runner (_not_ the nvim instance)
-local function sleep(ms)
- luv.sleep(ms)
-end
-
local function curbuf_contents()
wait() -- Before inspecting the buffer, process all input.
return table.concat(curbuf('get_lines', 0, -1, true), '\n')
@@ -682,31 +652,6 @@ local function alter_slashes(obj)
end
end
-local function hexdump(str)
- local len = string.len(str)
- local dump = ""
- local hex = ""
- local asc = ""
-
- for i = 1, len do
- if 1 == i % 8 then
- dump = dump .. hex .. asc .. "\n"
- hex = string.format("%04x: ", i - 1)
- asc = ""
- end
-
- local ord = string.byte(str, i)
- hex = hex .. string.format("%02x ", ord)
- if ord >= 32 and ord <= 126 then
- asc = asc .. string.char(ord)
- else
- asc = asc .. "."
- end
- end
-
- return dump .. hex .. string.rep(" ", 8 - len % 8) .. asc
-end
-
local module = {
NIL = mpack.NIL,
alter_slashes = alter_slashes,
@@ -737,7 +682,6 @@ local module = {
filter = filter,
funcs = funcs,
get_pathsep = get_pathsep,
- hexdump = hexdump,
insert = insert,
iswin = iswin,
map = map,
diff --git a/test/helpers.lua b/test/helpers.lua
index efc0e911f1..0d3fe1316b 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -1,4 +1,5 @@
local assert = require('luassert')
+local luv = require('luv')
local lfs = require('lfs')
local quote_me = '[^.%w%+%-%@%_%/]' -- complement (needn't quote)
@@ -33,6 +34,11 @@ local function popen_w(...)
return io.popen(argss_to_cmd(...), 'w')
end
+-- sleeps the test runner (_not_ the nvim instance)
+local function sleep(ms)
+ luv.sleep(ms)
+end
+
local check_logs_useless_lines = {
['Warning: noted but unhandled ioctl']=1,
['could cause spurious value errors to appear']=2,
@@ -612,7 +618,60 @@ local function table_flatten(arr)
return result
end
-return {
+local function hexdump(str)
+ local len = string.len(str)
+ local dump = ""
+ local hex = ""
+ local asc = ""
+
+ for i = 1, len do
+ if 1 == i % 8 then
+ dump = dump .. hex .. asc .. "\n"
+ hex = string.format("%04x: ", i - 1)
+ asc = ""
+ end
+
+ local ord = string.byte(str, i)
+ hex = hex .. string.format("%02x ", ord)
+ if ord >= 32 and ord <= 126 then
+ asc = asc .. string.char(ord)
+ else
+ asc = asc .. "."
+ end
+ end
+
+ return dump .. hex .. string.rep(" ", 8 - len % 8) .. asc
+end
+
+local function read_file(name)
+ local file = io.open(name, 'r')
+ if not file then
+ return nil
+ end
+ local ret = file:read('*a')
+ file:close()
+ return ret
+end
+
+-- Dedent the given text and write it to the file name.
+local function write_file(name, text, no_dedent, append)
+ local file = io.open(name, (append and 'a' or 'w'))
+ if type(text) == 'table' then
+ -- Byte blob
+ local bytes = text
+ text = ''
+ for _, char in ipairs(bytes) do
+ text = ('%s%c'):format(text, char)
+ end
+ elseif not no_dedent then
+ text = dedent(text)
+ end
+ file:write(text)
+ file:flush()
+ file:close()
+end
+
+local module = {
REMOVE_THIS = REMOVE_THIS,
argss_to_cmd = argss_to_cmd,
check_cores = check_cores,
@@ -630,6 +689,7 @@ return {
format_string = format_string,
glob = glob,
hasenv = hasenv,
+ hexdump = hexdump,
intchar2lua = intchar2lua,
map = map,
matches = matches,
@@ -638,11 +698,16 @@ return {
ok = ok,
popen_r = popen_r,
popen_w = popen_w,
+ read_file = read_file,
repeated_read_cmd = repeated_read_cmd,
+ sleep = sleep,
shallowcopy = shallowcopy,
table_flatten = table_flatten,
tmpname = tmpname,
uname = uname,
updated = updated,
which = which,
+ write_file = write_file,
}
+
+return module
diff --git a/test/unit/undo_spec.lua b/test/unit/undo_spec.lua
new file mode 100644
index 0000000000..ab172e89f2
--- /dev/null
+++ b/test/unit/undo_spec.lua
@@ -0,0 +1,216 @@
+local helpers = require('test.unit.helpers')(after_each)
+local itp = helpers.gen_itp(it)
+local lfs = require('lfs')
+local child_call_once = helpers.child_call_once
+
+local global_helpers = require('test.helpers')
+local hexdump = global_helpers.hexdump
+local sleep = global_helpers.sleep
+
+local ffi = helpers.ffi
+local cimport = helpers.cimport
+local to_cstr = helpers.to_cstr
+local neq = helpers.neq
+local eq = helpers.eq
+
+cimport('./src/nvim/ex_cmds_defs.h')
+cimport('./src/nvim/buffer_defs.h')
+local options = cimport('./src/nvim/option_defs.h')
+-- TODO: remove: local vim = cimport('./src/nvim/vim.h')
+local undo = cimport('./src/nvim/undo.h')
+local buffer = cimport('./src/nvim/buffer.h')
+
+local old_p_udir = nil
+
+-- Values expected by tests. Set in the setup function and destroyed in teardown
+local file_buffer = nil
+local buffer_hash = nil
+
+child_call_once(function()
+ if old_p_udir == nil then
+ old_p_udir = options.p_udir -- save the old value of p_udir (undodir)
+ end
+
+ -- create a new buffer
+ local c_file = to_cstr('Xtest-unit-undo')
+ file_buffer = buffer.buflist_new(c_file, c_file, 1, buffer.BLN_LISTED)
+ file_buffer.b_u_numhead = 1 -- Pretend that the buffer has been changed
+
+ -- TODO(christopher.waldon.dev@gmail.com): replace the 32 with UNDO_HASH_SIZE
+ -- requires refactor of UNDO_HASH_SIZE into constant/enum for ffi
+ --
+ -- compute a hash for this undofile
+ buffer_hash = ffi.new('char_u[32]')
+ undo.u_compute_hash(buffer_hash)
+end)
+
+
+describe('u_write_undo', function()
+ setup(function()
+ lfs.mkdir('unit-test-directory')
+ lfs.chdir('unit-test-directory')
+ options.p_udir = to_cstr(lfs.currentdir()) -- set p_udir to be the test dir
+ end)
+
+ teardown(function()
+ lfs.chdir('..')
+ local success, err = lfs.rmdir('unit-test-directory')
+ if not success then
+ print(err) -- inform tester if directory fails to delete
+ end
+ options.p_udir = old_p_udir --restore old p_udir
+ end)
+
+ -- Lua wrapper for u_write_undo
+ local function u_write_undo(name, forceit, buf, buf_hash)
+ if name ~= nil then
+ name = to_cstr(name)
+ end
+
+ return undo.u_write_undo(name, forceit, buf, buf_hash)
+ end
+
+ itp('writes an undo file to undodir given a buffer and hash', function()
+ u_write_undo(nil, false, file_buffer, buffer_hash)
+ local correct_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false))
+ local undo_file = io.open(correct_name, "r")
+
+ neq(undo_file, nil)
+ local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
+ if not success then
+ print(err) -- inform tester if undofile fails to delete
+ end
+ end)
+
+ itp('writes a correctly-named undo file to undodir given a name, buffer, and hash', function()
+ local correct_name = "undofile.test"
+ u_write_undo(correct_name, false, file_buffer, buffer_hash)
+ local undo_file = io.open(correct_name, "r")
+
+ neq(undo_file, nil)
+ local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
+ if not success then
+ print(err) -- inform tester if undofile fails to delete
+ end
+ end)
+
+ itp('does not write an undofile when the buffer has no valid undofile name', function()
+ -- TODO(christopher.waldon.dev@gmail.com): Figure out how to test this.
+ -- it's hard because u_get_undo_file_name() would need to return null
+ end)
+
+ itp('writes the undofile with the same permissions as the original file', function()
+ -- Create Test file and set permissions
+ local test_file_name = "./test.file"
+ local test_permission_file = io.open(test_file_name, "w")
+ test_permission_file:write("testing permissions")
+ test_permission_file:close()
+ local test_permissions = lfs.attributes(test_file_name).permissions
+
+ -- Create vim buffer
+ local c_file = to_cstr(test_file_name)
+ file_buffer = buffer.buflist_new(c_file, c_file, 1, buffer.BLN_LISTED)
+ file_buffer.b_u_numhead = 1 -- Pretend that the buffer has been changed
+
+ u_write_undo(nil, false, file_buffer, buffer_hash)
+
+ -- Find out the correct name of the undofile
+ local undo_file_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false))
+
+ -- Find out the permissions of the new file
+ local permissions = lfs.attributes(undo_file_name).permissions
+ eq(test_permissions, permissions)
+
+ -- delete the file now that we're done with it.
+ local success, err = os.remove(test_file_name)
+ if not success then
+ print(err) -- inform tester if undofile fails to delete
+ end
+ success, err = os.remove(undo_file_name)
+ if not success then
+ print(err) -- inform tester if undofile fails to delete
+ end
+ end)
+
+ itp('writes an undofile only readable by the user if the buffer is unnamed', function()
+ local correct_permissions = "rw-------"
+ local undo_file_name = "test.undo"
+
+ -- Create vim buffer
+ file_buffer = buffer.buflist_new(nil, nil, 1, buffer.BLN_LISTED)
+ file_buffer.b_u_numhead = 1 -- Pretend that the buffer has been changed
+
+ u_write_undo(undo_file_name, false, file_buffer, buffer_hash)
+
+ -- Find out the permissions of the new file
+ local permissions = lfs.attributes(undo_file_name).permissions
+ eq(correct_permissions, permissions)
+
+ -- delete the file now that we're done with it.
+ local success, err = os.remove(undo_file_name)
+ if not success then
+ print(err) -- inform tester if undofile fails to delete
+ end
+ end)
+
+ itp('forces writing undo file for :wundo! command', function()
+ local file_contents = "testing permissions"
+ -- Write a text file where the undofile should go
+ local correct_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false))
+ global_helpers.write_file(correct_name, file_contents, true, false)
+
+ -- Call with `forceit`.
+ u_write_undo(correct_name, true, file_buffer, buffer_hash)
+
+ local undo_file_contents = global_helpers.read_file(correct_name)
+
+ neq(file_contents, undo_file_contents)
+ local success, deletion_err = os.remove(correct_name) -- delete the file now that we're done with it.
+ if not success then
+ print(deletion_err) -- inform tester if undofile fails to delete
+ end
+ end)
+
+ itp('overwrites an existing undo file', function()
+ u_write_undo(nil, false, file_buffer, buffer_hash)
+ local correct_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false))
+
+ local file_last_modified = lfs.attributes(correct_name).modification
+
+ sleep(1000) -- Ensure difference in timestamps.
+ file_buffer.b_u_numhead = 1 -- Mark it as if there are changes
+ u_write_undo(nil, false, file_buffer, buffer_hash)
+
+ local file_last_modified_2 = lfs.attributes(correct_name).modification
+
+ -- print(file_last_modified, file_last_modified_2)
+ neq(file_last_modified, file_last_modified_2)
+ local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
+ if not success then
+ print(err) -- inform tester if undofile fails to delete
+ end
+ end)
+
+ itp('does not overwrite an existing file that is not an undo file', function()
+ -- TODO: write test
+ end)
+
+ itp('does not overwrite an existing file that has the wrong permissions', function()
+ -- TODO: write test
+ end)
+
+ itp('does not write an undo file if there is no undo information for the buffer', function()
+ file_buffer.b_u_numhead = 0 -- Mark it as if there is no undo information
+ local correct_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false))
+
+ local existing_file = io.open(correct_name,"r")
+ if existing_file then
+ existing_file:close()
+ os.remove(correct_name)
+ end
+ u_write_undo(nil, false, file_buffer, buffer_hash)
+ local undo_file = io.open(correct_name, "r")
+
+ eq(undo_file, nil)
+ end)
+end)