mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
build: enable lintlua for test/unit/ dir #26396
Problem: Not all Lua code is checked by stylua. Automating code-style is an important mechanism for reducing time spent on accidental (non-essential) complexity. Solution: - Enable lintlua for `test/unit/` directory. - TODO: only `test/functional/` remains unchecked. previous:45fe4d11ad
previous:517f0cc634
This commit is contained in:
parent
45fe4d11ad
commit
c3836e40a2
@ -2,4 +2,10 @@
|
||||
/runtime/lua/coxpcall.lua
|
||||
/runtime/lua/vim/_meta
|
||||
/runtime/lua/vim/re.lua
|
||||
/test
|
||||
|
||||
/test/functional
|
||||
/test/functional/fixtures/lua/syntax_error.lua
|
||||
/test/functional/legacy/030_fileformats_spec.lua
|
||||
/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua
|
||||
/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua
|
||||
/test/functional/lua/luaeval_spec.lua
|
||||
|
@ -233,7 +233,7 @@ add_glob_target(
|
||||
TARGET lintlua-stylua
|
||||
COMMAND ${STYLUA_PRG}
|
||||
FLAGS --color=always --check --respect-ignores
|
||||
GLOB_DIRS runtime/ scripts/ src/
|
||||
GLOB_DIRS runtime/ scripts/ src/ test/unit/
|
||||
GLOB_PAT *.lua
|
||||
TOUCH_STRATEGY SINGLE)
|
||||
|
||||
@ -260,7 +260,7 @@ add_glob_target(
|
||||
TARGET formatlua
|
||||
COMMAND ${STYLUA_PRG}
|
||||
FLAGS --respect-ignores
|
||||
GLOB_DIRS runtime/ scripts/ src/
|
||||
GLOB_DIRS runtime/ scripts/ src/ test/unit/
|
||||
GLOB_PAT *.lua)
|
||||
|
||||
add_custom_target(format)
|
||||
|
@ -27,7 +27,8 @@ describe('autocmd perf', function()
|
||||
end)
|
||||
|
||||
it('nvim_create_autocmd, nvim_del_autocmd (same pattern)', function()
|
||||
exec_lua([[
|
||||
exec_lua(
|
||||
[[
|
||||
local N = ...
|
||||
local ids = {}
|
||||
|
||||
@ -45,11 +46,14 @@ describe('autocmd perf', function()
|
||||
vim.api.nvim_del_autocmd(ids[i])
|
||||
end
|
||||
stop('nvim_del_autocmd')
|
||||
]], N)
|
||||
]],
|
||||
N
|
||||
)
|
||||
end)
|
||||
|
||||
it('nvim_create_autocmd, nvim_del_autocmd (unique patterns)', function()
|
||||
exec_lua([[
|
||||
exec_lua(
|
||||
[[
|
||||
local N = ...
|
||||
local ids = {}
|
||||
|
||||
@ -67,11 +71,14 @@ describe('autocmd perf', function()
|
||||
vim.api.nvim_del_autocmd(ids[i])
|
||||
end
|
||||
stop('nvim_del_autocmd')
|
||||
]], N)
|
||||
]],
|
||||
N
|
||||
)
|
||||
end)
|
||||
|
||||
it('nvim_create_autocmd + nvim_del_autocmd', function()
|
||||
exec_lua([[
|
||||
exec_lua(
|
||||
[[
|
||||
local N = ...
|
||||
|
||||
start()
|
||||
@ -83,11 +90,14 @@ describe('autocmd perf', function()
|
||||
vim.api.nvim_del_autocmd(id)
|
||||
end
|
||||
stop('nvim_create_autocmd + nvim_del_autocmd')
|
||||
]], N)
|
||||
]],
|
||||
N
|
||||
)
|
||||
end)
|
||||
|
||||
it('nvim_exec_autocmds (same pattern)', function()
|
||||
exec_lua([[
|
||||
exec_lua(
|
||||
[[
|
||||
local N = ...
|
||||
|
||||
for i = 1, N do
|
||||
@ -100,11 +110,14 @@ describe('autocmd perf', function()
|
||||
start()
|
||||
vim.api.nvim_exec_autocmds('User', { pattern = 'Benchmark', modeline = false })
|
||||
stop('nvim_exec_autocmds')
|
||||
]], N)
|
||||
]],
|
||||
N
|
||||
)
|
||||
end)
|
||||
|
||||
it('nvim_del_augroup_by_id', function()
|
||||
exec_lua([[
|
||||
exec_lua(
|
||||
[[
|
||||
local N = ...
|
||||
local group = vim.api.nvim_create_augroup('Benchmark', {})
|
||||
|
||||
@ -119,11 +132,14 @@ describe('autocmd perf', function()
|
||||
start()
|
||||
vim.api.nvim_del_augroup_by_id(group)
|
||||
stop('nvim_del_augroup_by_id')
|
||||
]], N)
|
||||
]],
|
||||
N
|
||||
)
|
||||
end)
|
||||
|
||||
it('nvim_del_augroup_by_name', function()
|
||||
exec_lua([[
|
||||
exec_lua(
|
||||
[[
|
||||
local N = ...
|
||||
local group = vim.api.nvim_create_augroup('Benchmark', {})
|
||||
|
||||
@ -138,11 +154,14 @@ describe('autocmd perf', function()
|
||||
start()
|
||||
vim.api.nvim_del_augroup_by_name('Benchmark')
|
||||
stop('nvim_del_augroup_by_id')
|
||||
]], N)
|
||||
]],
|
||||
N
|
||||
)
|
||||
end)
|
||||
|
||||
it(':autocmd, :autocmd! (same pattern)', function()
|
||||
exec_lua([[
|
||||
exec_lua(
|
||||
[[
|
||||
local N = ...
|
||||
|
||||
start()
|
||||
@ -154,11 +173,14 @@ describe('autocmd perf', function()
|
||||
start()
|
||||
vim.cmd('autocmd! User Benchmark')
|
||||
stop(':autocmd!')
|
||||
]], N)
|
||||
]],
|
||||
N
|
||||
)
|
||||
end)
|
||||
|
||||
it(':autocmd, :autocmd! (unique patterns)', function()
|
||||
exec_lua([[
|
||||
exec_lua(
|
||||
[[
|
||||
local N = ...
|
||||
|
||||
start()
|
||||
@ -170,6 +192,8 @@ describe('autocmd perf', function()
|
||||
start()
|
||||
vim.cmd('autocmd! User')
|
||||
stop(':autocmd!')
|
||||
]], N)
|
||||
]],
|
||||
N
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
@ -10,8 +10,7 @@ local result_file = 'benchmark.out'
|
||||
local sample_file = 'test/old/testdir/samples/re.freeze.txt'
|
||||
|
||||
-- Vim script code that does both the work and the benchmarking of that work.
|
||||
local measure_cmd =
|
||||
[[call Measure(%d, ']] .. sample_file .. [[', '\s\+\%%#\@<!$', '+5')]]
|
||||
local measure_cmd = [[call Measure(%d, ']] .. sample_file .. [[', '\s\+\%%#\@<!$', '+5')]]
|
||||
local measure_script = [[
|
||||
func Measure(re, file, pattern, arg)
|
||||
let sstart = reltime()
|
||||
|
@ -4,14 +4,13 @@ local clear = helpers.clear
|
||||
local exec_lua = helpers.exec_lua
|
||||
|
||||
describe('treesitter perf', function()
|
||||
|
||||
setup(function()
|
||||
clear()
|
||||
end)
|
||||
|
||||
it('can handle large folds', function()
|
||||
helpers.command'edit ./src/nvim/eval.c'
|
||||
exec_lua[[
|
||||
helpers.command 'edit ./src/nvim/eval.c'
|
||||
exec_lua [[
|
||||
local parser = vim.treesitter.get_parser(0, "c", {})
|
||||
vim.treesitter.highlighter.new(parser)
|
||||
|
||||
@ -47,7 +46,5 @@ describe('treesitter perf', function()
|
||||
|
||||
return vim.uv.hrtime() - start
|
||||
]]
|
||||
|
||||
end)
|
||||
|
||||
end)
|
||||
|
@ -1,12 +1,21 @@
|
||||
local pretty = require 'pl.pretty'
|
||||
local global_helpers = require('test.helpers')
|
||||
|
||||
local colors = setmetatable({}, {__index = function() return function(s) return s == nil and '' or tostring(s) end end})
|
||||
local colors = setmetatable({}, {
|
||||
__index = function()
|
||||
return function(s)
|
||||
return s == nil and '' or tostring(s)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
local enable_colors = true
|
||||
if os.getenv "TEST_COLORS" then
|
||||
local test_colors = os.getenv("TEST_COLORS"):lower()
|
||||
local disable_colors = test_colors == 'false' or test_colors == '0' or test_colors == 'no' or test_colors == 'off'
|
||||
if os.getenv 'TEST_COLORS' then
|
||||
local test_colors = os.getenv('TEST_COLORS'):lower()
|
||||
local disable_colors = test_colors == 'false'
|
||||
or test_colors == '0'
|
||||
or test_colors == 'no'
|
||||
or test_colors == 'off'
|
||||
enable_colors = not disable_colors
|
||||
end
|
||||
if enable_colors then
|
||||
@ -18,15 +27,25 @@ return function(options)
|
||||
local handler = require 'busted.outputHandlers.base'()
|
||||
|
||||
local c = {
|
||||
succ = function(s) return colors.bright(colors.green(s)) end,
|
||||
skip = function(s) return colors.bright(colors.yellow(s)) end,
|
||||
fail = function(s) return colors.bright(colors.magenta(s)) end,
|
||||
errr = function(s) return colors.bright(colors.red(s)) end,
|
||||
succ = function(s)
|
||||
return colors.bright(colors.green(s))
|
||||
end,
|
||||
skip = function(s)
|
||||
return colors.bright(colors.yellow(s))
|
||||
end,
|
||||
fail = function(s)
|
||||
return colors.bright(colors.magenta(s))
|
||||
end,
|
||||
errr = function(s)
|
||||
return colors.bright(colors.red(s))
|
||||
end,
|
||||
test = tostring,
|
||||
file = colors.cyan,
|
||||
time = colors.dim,
|
||||
note = colors.yellow,
|
||||
sect = function(s) return colors.green(colors.dim(s)) end,
|
||||
sect = function(s)
|
||||
return colors.green(colors.dim(s))
|
||||
end,
|
||||
nmbr = colors.bright,
|
||||
}
|
||||
|
||||
@ -39,9 +58,23 @@ return function(options)
|
||||
local skippedString = c.skip('SKIP') .. '\n'
|
||||
local failureString = c.fail('FAIL') .. '\n'
|
||||
local errorString = c.errr('ERR') .. '\n'
|
||||
local fileEndString = c.sect('--------') .. ' '.. c.nmbr('%d') .. ' %s from ' .. c.file('%s') .. ' ' .. c.time('(%.2f ms total)') .. '\n\n'
|
||||
local fileEndString = c.sect('--------')
|
||||
.. ' '
|
||||
.. c.nmbr('%d')
|
||||
.. ' %s from '
|
||||
.. c.file('%s')
|
||||
.. ' '
|
||||
.. c.time('(%.2f ms total)')
|
||||
.. '\n\n'
|
||||
local globalTeardown = c.sect('--------') .. ' Global test environment teardown.\n'
|
||||
local suiteEndString = c.sect('========') .. ' ' .. c.nmbr('%d') .. ' %s from ' .. c.nmbr('%d') .. ' test %s ran. ' .. c.time('(%.2f ms total)') .. '\n'
|
||||
local suiteEndString = c.sect('========')
|
||||
.. ' '
|
||||
.. c.nmbr('%d')
|
||||
.. ' %s from '
|
||||
.. c.nmbr('%d')
|
||||
.. ' test %s ran. '
|
||||
.. c.time('(%.2f ms total)')
|
||||
.. '\n'
|
||||
local successStatus = c.succ('PASSED ') .. ' ' .. c.nmbr('%d') .. ' %s.\n'
|
||||
local timeString = c.time('%.2f ms')
|
||||
|
||||
@ -107,8 +140,10 @@ return function(options)
|
||||
local getFileLine = function(element)
|
||||
local fileline = ''
|
||||
if element.trace or element.trace.short_src then
|
||||
fileline = colors.cyan(element.trace.short_src) .. ' @ ' ..
|
||||
colors.cyan(element.trace.currentline) .. ': '
|
||||
fileline = colors.cyan(element.trace.short_src)
|
||||
.. ' @ '
|
||||
.. colors.cyan(element.trace.currentline)
|
||||
.. ': '
|
||||
end
|
||||
return fileline
|
||||
end
|
||||
@ -219,7 +254,9 @@ return function(options)
|
||||
local elapsedTime_ms = getElapsedTime(file)
|
||||
local tests = (fileTestCount == 1 and 'test' or 'tests')
|
||||
fileCount = fileCount + 1
|
||||
io.write(fileEndString:format(fileTestCount, tests, vim.fs.normalize(file.name), elapsedTime_ms))
|
||||
io.write(
|
||||
fileEndString:format(fileTestCount, tests, vim.fs.normalize(file.name), elapsedTime_ms)
|
||||
)
|
||||
io.flush()
|
||||
return nil, true
|
||||
end
|
||||
@ -256,7 +293,7 @@ return function(options)
|
||||
errorCount = errorCount + 1
|
||||
string = errorString .. failureDescription(handler.errors[#handler.errors])
|
||||
else
|
||||
string = "unexpected test status! ("..status..")"
|
||||
string = 'unexpected test status! (' .. status .. ')'
|
||||
end
|
||||
write_status(element, string)
|
||||
|
||||
|
@ -3,13 +3,19 @@ local mpack = require('mpack')
|
||||
-- temporary hack to be able to manipulate buffer/window/tabpage
|
||||
local Buffer = {}
|
||||
Buffer.__index = Buffer
|
||||
function Buffer.new(id) return setmetatable({id=id}, Buffer) end
|
||||
function Buffer.new(id)
|
||||
return setmetatable({ id = id }, Buffer)
|
||||
end
|
||||
local Window = {}
|
||||
Window.__index = Window
|
||||
function Window.new(id) return setmetatable({id=id}, Window) end
|
||||
function Window.new(id)
|
||||
return setmetatable({ id = id }, Window)
|
||||
end
|
||||
local Tabpage = {}
|
||||
Tabpage.__index = Tabpage
|
||||
function Tabpage.new(id) return setmetatable({id=id}, Tabpage) end
|
||||
function Tabpage.new(id)
|
||||
return setmetatable({ id = id }, Tabpage)
|
||||
end
|
||||
|
||||
local Response = {}
|
||||
Response.__index = Response
|
||||
@ -17,7 +23,7 @@ Response.__index = Response
|
||||
function Response.new(msgpack_rpc_stream, request_id)
|
||||
return setmetatable({
|
||||
_msgpack_rpc_stream = msgpack_rpc_stream,
|
||||
_request_id = request_id
|
||||
_request_id = request_id,
|
||||
}, Response)
|
||||
end
|
||||
|
||||
@ -41,19 +47,31 @@ function MsgpackRpcStream.new(stream)
|
||||
_stream = stream,
|
||||
_pack = mpack.Packer({
|
||||
ext = {
|
||||
[Buffer] = function(o) return 0, mpack.encode(o.id) end,
|
||||
[Window] = function(o) return 1, mpack.encode(o.id) end,
|
||||
[Tabpage] = function(o) return 2, mpack.encode(o.id) end
|
||||
}
|
||||
[Buffer] = function(o)
|
||||
return 0, mpack.encode(o.id)
|
||||
end,
|
||||
[Window] = function(o)
|
||||
return 1, mpack.encode(o.id)
|
||||
end,
|
||||
[Tabpage] = function(o)
|
||||
return 2, mpack.encode(o.id)
|
||||
end,
|
||||
},
|
||||
}),
|
||||
_session = mpack.Session({
|
||||
unpack = mpack.Unpacker({
|
||||
ext = {
|
||||
[0] = function(_c, s) return Buffer.new(mpack.decode(s)) end,
|
||||
[1] = function(_c, s) return Window.new(mpack.decode(s)) end,
|
||||
[2] = function(_c, s) return Tabpage.new(mpack.decode(s)) end
|
||||
}
|
||||
})
|
||||
[0] = function(_c, s)
|
||||
return Buffer.new(mpack.decode(s))
|
||||
end,
|
||||
[1] = function(_c, s)
|
||||
return Window.new(mpack.decode(s))
|
||||
end,
|
||||
[2] = function(_c, s)
|
||||
return Tabpage.new(mpack.decode(s))
|
||||
end,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}, MsgpackRpcStream)
|
||||
end
|
||||
@ -80,12 +98,10 @@ function MsgpackRpcStream:read_start(request_cb, notification_cb, eof_cb)
|
||||
local pos = 1
|
||||
local len = #data
|
||||
while pos <= len do
|
||||
type, id_or_cb, method_or_error, args_or_result, pos =
|
||||
self._session:receive(data, pos)
|
||||
type, id_or_cb, method_or_error, args_or_result, pos = self._session:receive(data, pos)
|
||||
if type == 'request' or type == 'notification' then
|
||||
if type == 'request' then
|
||||
request_cb(method_or_error, args_or_result, Response.new(self,
|
||||
id_or_cb))
|
||||
request_cb(method_or_error, args_or_result, Response.new(self, id_or_cb))
|
||||
else
|
||||
notification_cb(method_or_error, args_or_result)
|
||||
end
|
||||
|
@ -7,7 +7,7 @@ if package.loaded['jit'] then
|
||||
-- luajit pcall is already coroutine safe
|
||||
Session.safe_pcall = pcall
|
||||
else
|
||||
Session.safe_pcall = require'coxpcall'.pcall
|
||||
Session.safe_pcall = require 'coxpcall'.pcall
|
||||
end
|
||||
|
||||
local function resume(co, ...)
|
||||
@ -25,7 +25,7 @@ local function resume(co, ...)
|
||||
end
|
||||
|
||||
local function coroutine_exec(func, ...)
|
||||
local args = {...}
|
||||
local args = { ... }
|
||||
local on_complete
|
||||
|
||||
if #args > 0 and type(args[#args]) == 'function' then
|
||||
@ -50,18 +50,18 @@ function Session.new(stream)
|
||||
_pending_messages = {},
|
||||
_prepare = uv.new_prepare(),
|
||||
_timer = uv.new_timer(),
|
||||
_is_running = false
|
||||
_is_running = false,
|
||||
}, Session)
|
||||
end
|
||||
|
||||
function Session:next_message(timeout)
|
||||
local function on_request(method, args, response)
|
||||
table.insert(self._pending_messages, {'request', method, args, response})
|
||||
table.insert(self._pending_messages, { 'request', method, args, response })
|
||||
uv.stop()
|
||||
end
|
||||
|
||||
local function on_notification(method, args)
|
||||
table.insert(self._pending_messages, {'notification', method, args})
|
||||
table.insert(self._pending_messages, { 'notification', method, args })
|
||||
uv.stop()
|
||||
end
|
||||
|
||||
@ -83,11 +83,11 @@ function Session:next_message(timeout)
|
||||
end
|
||||
|
||||
function Session:notify(method, ...)
|
||||
self._msgpack_rpc_stream:write(method, {...})
|
||||
self._msgpack_rpc_stream:write(method, { ... })
|
||||
end
|
||||
|
||||
function Session:request(method, ...)
|
||||
local args = {...}
|
||||
local args = { ... }
|
||||
local err, result
|
||||
if self._is_running then
|
||||
err, result = self:_yielding_request(method, args)
|
||||
@ -141,8 +141,12 @@ function Session:stop()
|
||||
end
|
||||
|
||||
function Session:close(signal)
|
||||
if not self._timer:is_closing() then self._timer:close() end
|
||||
if not self._prepare:is_closing() then self._prepare:close() end
|
||||
if not self._timer:is_closing() then
|
||||
self._timer:close()
|
||||
end
|
||||
if not self._prepare:is_closing() then
|
||||
self._prepare:close()
|
||||
end
|
||||
self._msgpack_rpc_stream:close(signal)
|
||||
self.closed = true
|
||||
end
|
||||
@ -159,11 +163,11 @@ function Session:_blocking_request(method, args)
|
||||
local err, result
|
||||
|
||||
local function on_request(method_, args_, response)
|
||||
table.insert(self._pending_messages, {'request', method_, args_, response})
|
||||
table.insert(self._pending_messages, { 'request', method_, args_, response })
|
||||
end
|
||||
|
||||
local function on_notification(method_, args_)
|
||||
table.insert(self._pending_messages, {'notification', method_, args_})
|
||||
table.insert(self._pending_messages, { 'notification', method_, args_ })
|
||||
end
|
||||
|
||||
self._msgpack_rpc_stream:write(method, args, function(e, r)
|
||||
@ -187,7 +191,7 @@ function Session:_run(request_cb, notification_cb, timeout)
|
||||
end
|
||||
self._msgpack_rpc_stream:read_start(request_cb, notification_cb, function()
|
||||
uv.stop()
|
||||
self.eof_err = {1, "EOF was received from Nvim. Likely the Nvim process crashed."}
|
||||
self.eof_err = { 1, 'EOF was received from Nvim. Likely the Nvim process crashed.' }
|
||||
end)
|
||||
uv.run()
|
||||
self._prepare:stop()
|
||||
|
@ -6,7 +6,7 @@ StdioStream.__index = StdioStream
|
||||
function StdioStream.open()
|
||||
local self = setmetatable({
|
||||
_in = uv.new_pipe(false),
|
||||
_out = uv.new_pipe(false)
|
||||
_out = uv.new_pipe(false),
|
||||
}, StdioStream)
|
||||
self._in:open(0)
|
||||
self._out:open(1)
|
||||
@ -42,9 +42,9 @@ function SocketStream.open(file)
|
||||
local socket = uv.new_pipe(false)
|
||||
local self = setmetatable({
|
||||
_socket = socket,
|
||||
_stream_error = nil
|
||||
_stream_error = nil,
|
||||
}, SocketStream)
|
||||
uv.pipe_connect(socket, file, function (err)
|
||||
uv.pipe_connect(socket, file, function(err)
|
||||
self._stream_error = self._stream_error or err
|
||||
end)
|
||||
return self
|
||||
@ -54,15 +54,14 @@ function SocketStream.connect(host, port)
|
||||
local socket = uv.new_tcp()
|
||||
local self = setmetatable({
|
||||
_socket = socket,
|
||||
_stream_error = nil
|
||||
_stream_error = nil,
|
||||
}, SocketStream)
|
||||
uv.tcp_connect(socket, host, port, function (err)
|
||||
uv.tcp_connect(socket, host, port, function(err)
|
||||
self._stream_error = self._stream_error or err
|
||||
end)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function SocketStream:write(data)
|
||||
if self._stream_error then
|
||||
error(self._stream_error)
|
||||
@ -102,9 +101,9 @@ ChildProcessStream.__index = ChildProcessStream
|
||||
|
||||
function ChildProcessStream.spawn(argv, env, io_extra)
|
||||
local self = setmetatable({
|
||||
_child_stdin = uv.new_pipe(false);
|
||||
_child_stdout = uv.new_pipe(false);
|
||||
_exiting = false;
|
||||
_child_stdin = uv.new_pipe(false),
|
||||
_child_stdout = uv.new_pipe(false),
|
||||
_exiting = false,
|
||||
}, ChildProcessStream)
|
||||
local prog = argv[1]
|
||||
local args = {}
|
||||
@ -112,7 +111,7 @@ function ChildProcessStream.spawn(argv, env, io_extra)
|
||||
args[#args + 1] = argv[i]
|
||||
end
|
||||
self._proc, self._pid = uv.spawn(prog, {
|
||||
stdio = {self._child_stdin, self._child_stdout, 2, io_extra},
|
||||
stdio = { self._child_stdin, self._child_stdout, 2, io_extra },
|
||||
args = args,
|
||||
env = env,
|
||||
}, function(status, signal)
|
||||
@ -154,7 +153,7 @@ function ChildProcessStream:close(signal)
|
||||
self._child_stdin:close()
|
||||
self._child_stdout:close()
|
||||
if type(signal) == 'string' then
|
||||
self._proc:kill('sig'..signal)
|
||||
self._proc:kill('sig' .. signal)
|
||||
end
|
||||
while self.status == nil do
|
||||
uv.run 'once'
|
||||
@ -163,7 +162,7 @@ function ChildProcessStream:close(signal)
|
||||
end
|
||||
|
||||
return {
|
||||
StdioStream = StdioStream;
|
||||
ChildProcessStream = ChildProcessStream;
|
||||
SocketStream = SocketStream;
|
||||
StdioStream = StdioStream,
|
||||
ChildProcessStream = ChildProcessStream,
|
||||
SocketStream = SocketStream,
|
||||
}
|
||||
|
214
test/helpers.lua
214
test/helpers.lua
@ -25,7 +25,7 @@ local module = {
|
||||
local function relpath(p)
|
||||
p = vim.fs.normalize(p)
|
||||
local cwd = luv.cwd()
|
||||
return p:gsub("^" .. cwd)
|
||||
return p:gsub('^' .. cwd)
|
||||
end
|
||||
|
||||
--- @param path string
|
||||
@ -60,7 +60,7 @@ function module.argss_to_cmd(...)
|
||||
for i = 1, select('#', ...) do
|
||||
local arg = select(i, ...)
|
||||
if type(arg) == 'string' then
|
||||
cmd = cmd .. ' ' ..shell_quote(arg)
|
||||
cmd = cmd .. ' ' .. shell_quote(arg)
|
||||
else
|
||||
for _, subarg in ipairs(arg) do
|
||||
cmd = cmd .. ' ' .. shell_quote(subarg)
|
||||
@ -94,7 +94,7 @@ function module.retry(max, max_ms, fn)
|
||||
end
|
||||
luv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
|
||||
if (max and tries >= max) or (luv.now() - start_time > timeout) then
|
||||
busted.fail(string.format("retry() attempts: %d\n%s", tries, tostring(result)), 2)
|
||||
busted.fail(string.format('retry() attempts: %d\n%s', tries, tostring(result)), 2)
|
||||
end
|
||||
tries = tries + 1
|
||||
luv.sleep(20) -- Avoid hot loop...
|
||||
@ -102,9 +102,9 @@ function module.retry(max, max_ms, fn)
|
||||
end
|
||||
|
||||
local check_logs_useless_lines = {
|
||||
['Warning: noted but unhandled ioctl']=1,
|
||||
['could cause spurious value errors to appear']=2,
|
||||
['See README_MISSING_SYSCALL_OR_IOCTL for guidance']=3,
|
||||
['Warning: noted but unhandled ioctl'] = 1,
|
||||
['could cause spurious value errors to appear'] = 2,
|
||||
['See README_MISSING_SYSCALL_OR_IOCTL for guidance'] = 3,
|
||||
}
|
||||
|
||||
function module.eq(expected, actual, context)
|
||||
@ -120,7 +120,10 @@ end
|
||||
--- @param expected (any) description of expected result
|
||||
--- @param actual (any) description of actual result
|
||||
function module.ok(cond, expected, actual)
|
||||
assert((not expected and not actual) or (expected and actual), 'if "expected" is given, "actual" is also required')
|
||||
assert(
|
||||
(not expected and not actual) or (expected and actual),
|
||||
'if "expected" is given, "actual" is also required'
|
||||
)
|
||||
local msg = expected and ('expected %s, got: %s'):format(expected, tostring(actual)) or nil
|
||||
return assert(cond, msg)
|
||||
end
|
||||
@ -129,7 +132,7 @@ local function epicfail(state, arguments, _)
|
||||
state.failure_message = arguments[1]
|
||||
return false
|
||||
end
|
||||
assert:register("assertion", "epicfail", epicfail)
|
||||
assert:register('assertion', 'epicfail', epicfail)
|
||||
function module.fail(msg)
|
||||
return assert.epicfail(msg)
|
||||
end
|
||||
@ -157,14 +160,26 @@ function module.assert_log(pat, logfile, nrlines, inverse)
|
||||
|
||||
module.retry(nil, 1000, function()
|
||||
local lines = module.read_file_list(logfile, -nrlines) or {}
|
||||
local msg = string.format('Pattern %q %sfound in log (last %d lines): %s:\n%s',
|
||||
pat, (inverse and '' or 'not '), nrlines, logfile, ' '..table.concat(lines, '\n '))
|
||||
for _,line in ipairs(lines) do
|
||||
local msg = string.format(
|
||||
'Pattern %q %sfound in log (last %d lines): %s:\n%s',
|
||||
pat,
|
||||
(inverse and '' or 'not '),
|
||||
nrlines,
|
||||
logfile,
|
||||
' ' .. table.concat(lines, '\n ')
|
||||
)
|
||||
for _, line in ipairs(lines) do
|
||||
if line:match(pat) then
|
||||
if inverse then error(msg) else return end
|
||||
if inverse then
|
||||
error(msg)
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
if not inverse then error(msg) end
|
||||
end
|
||||
if not inverse then
|
||||
error(msg)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
@ -186,7 +201,8 @@ function module.pcall(fn, ...)
|
||||
-- C:/long/path/foo.lua:186: Expected string, got number
|
||||
-- to:
|
||||
-- .../foo.lua:0: Expected string, got number
|
||||
local errmsg = tostring(rv):gsub('([%s<])vim[/\\]([^%s:/\\]+):%d+', '%1\xffvim\xff%2:0')
|
||||
local errmsg = tostring(rv)
|
||||
:gsub('([%s<])vim[/\\]([^%s:/\\]+):%d+', '%1\xffvim\xff%2:0')
|
||||
:gsub('[^%s<]-[/\\]([^%s:/\\]+):%d+', '.../%1:0')
|
||||
:gsub('\xffvim\xff', 'vim/')
|
||||
|
||||
@ -233,9 +249,10 @@ end
|
||||
function module.pcall_err_withtrace(fn, ...)
|
||||
local errmsg = module.pcall_err_withfile(fn, ...)
|
||||
|
||||
return errmsg:gsub('^%.%.%./helpers%.lua:0: ', '')
|
||||
:gsub('^Error executing lua:- ' ,'')
|
||||
:gsub('^%[string "<nvim>"%]:0: ' ,'')
|
||||
return errmsg
|
||||
:gsub('^%.%.%./helpers%.lua:0: ', '')
|
||||
:gsub('^Error executing lua:- ', '')
|
||||
:gsub('^%[string "<nvim>"%]:0: ', '')
|
||||
end
|
||||
|
||||
function module.pcall_err(...)
|
||||
@ -243,7 +260,7 @@ function module.pcall_err(...)
|
||||
end
|
||||
|
||||
function module.remove_trace(s)
|
||||
return (s:gsub("\n%s*stack traceback:.*", ""))
|
||||
return (s:gsub('\n%s*stack traceback:.*', ''))
|
||||
end
|
||||
|
||||
-- initial_path: directory to recurse into
|
||||
@ -251,12 +268,14 @@ end
|
||||
-- exc_re: exclude pattern(s) (string or table)
|
||||
function module.glob(initial_path, re, exc_re)
|
||||
exc_re = type(exc_re) == 'table' and exc_re or { exc_re }
|
||||
local paths_to_check = {initial_path}
|
||||
local paths_to_check = { initial_path }
|
||||
local ret = {}
|
||||
local checked_files = {}
|
||||
local function is_excluded(path)
|
||||
for _, pat in pairs(exc_re) do
|
||||
if path:match(pat) then return true end
|
||||
if path:match(pat) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
@ -318,7 +337,7 @@ function module.check_logs()
|
||||
out:write(start_msg .. '\n')
|
||||
if status then
|
||||
for line in f:lines() do
|
||||
out:write('= '..line..'\n')
|
||||
out:write('= ' .. line .. '\n')
|
||||
end
|
||||
f:close()
|
||||
else
|
||||
@ -331,9 +350,10 @@ function module.check_logs()
|
||||
end
|
||||
end
|
||||
end
|
||||
assert(0 == #runtime_errors, string.format(
|
||||
'Found runtime errors in logfile(s): %s',
|
||||
table.concat(runtime_errors, ', ')))
|
||||
assert(
|
||||
0 == #runtime_errors,
|
||||
string.format('Found runtime errors in logfile(s): %s', table.concat(runtime_errors, ', '))
|
||||
)
|
||||
end
|
||||
|
||||
function module.sysname()
|
||||
@ -344,18 +364,16 @@ function module.sysname()
|
||||
end
|
||||
|
||||
function module.is_os(s)
|
||||
if not (s == 'win'
|
||||
or s == 'mac'
|
||||
or s == 'freebsd'
|
||||
or s == 'openbsd'
|
||||
or s == 'bsd') then
|
||||
error('unknown platform: '..tostring(s))
|
||||
if not (s == 'win' or s == 'mac' or s == 'freebsd' or s == 'openbsd' or s == 'bsd') then
|
||||
error('unknown platform: ' .. tostring(s))
|
||||
end
|
||||
return not not ((s == 'win' and (module.sysname():find('windows') or module.sysname():find('mingw')))
|
||||
return not not (
|
||||
(s == 'win' and (module.sysname():find('windows') or module.sysname():find('mingw')))
|
||||
or (s == 'mac' and module.sysname() == 'darwin')
|
||||
or (s == 'freebsd' and module.sysname() == 'freebsd')
|
||||
or (s == 'openbsd' and module.sysname() == 'openbsd')
|
||||
or (s == 'bsd' and module.sysname():find('bsd')))
|
||||
or (s == 'bsd' and module.sysname():find('bsd'))
|
||||
)
|
||||
end
|
||||
|
||||
local function tmpdir_get()
|
||||
@ -371,7 +389,7 @@ end
|
||||
module.tmpname = (function()
|
||||
local seq = 0
|
||||
local tmpdir = tmpdir_get()
|
||||
return (function()
|
||||
return function()
|
||||
if tmpdir_is_local(tmpdir) then
|
||||
-- Cannot control os.tmpname() dir, so hack our own tmpname() impl.
|
||||
seq = seq + 1
|
||||
@ -384,15 +402,15 @@ module.tmpname = (function()
|
||||
if module.is_os('win') and fname:sub(1, 2) == '\\s' then
|
||||
-- In Windows tmpname() returns a filename starting with
|
||||
-- special sequence \s, prepend $TEMP path
|
||||
return tmpdir..fname
|
||||
return tmpdir .. fname
|
||||
elseif fname:match('^/tmp') and module.is_os('mac') then
|
||||
-- In OS X /tmp links to /private/tmp
|
||||
return '/private'..fname
|
||||
return '/private' .. fname
|
||||
else
|
||||
return fname
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)()
|
||||
|
||||
function module.hasenv(name)
|
||||
@ -417,14 +435,17 @@ function module.check_cores(app, force) -- luacheck: ignore
|
||||
end
|
||||
app = app or 'build/bin/nvim' -- luacheck: ignore
|
||||
local initial_path, re, exc_re
|
||||
local gdb_db_cmd = 'gdb -n -batch -ex "thread apply all bt full" "$_NVIM_TEST_APP" -c "$_NVIM_TEST_CORE"'
|
||||
local gdb_db_cmd =
|
||||
'gdb -n -batch -ex "thread apply all bt full" "$_NVIM_TEST_APP" -c "$_NVIM_TEST_CORE"'
|
||||
local lldb_db_cmd = 'lldb -Q -o "bt all" -f "$_NVIM_TEST_APP" -c "$_NVIM_TEST_CORE"'
|
||||
local random_skip = false
|
||||
-- Workspace-local $TMPDIR, scrubbed and pattern-escaped.
|
||||
-- "./Xtest-tmpdir/" => "Xtest%-tmpdir"
|
||||
local local_tmpdir = (tmpdir_is_local(tmpdir_get())
|
||||
and relpath(tmpdir_get()):gsub('^[ ./]+',''):gsub('%/+$',''):gsub('([^%w])', '%%%1')
|
||||
or nil)
|
||||
local local_tmpdir = (
|
||||
tmpdir_is_local(tmpdir_get())
|
||||
and relpath(tmpdir_get()):gsub('^[ ./]+', ''):gsub('%/+$', ''):gsub('([^%w])', '%%%1')
|
||||
or nil
|
||||
)
|
||||
local db_cmd
|
||||
if module.hasenv('NVIM_TEST_CORE_GLOB_DIRECTORY') then
|
||||
initial_path = os.getenv('NVIM_TEST_CORE_GLOB_DIRECTORY')
|
||||
@ -444,7 +465,7 @@ function module.check_cores(app, force) -- luacheck: ignore
|
||||
else
|
||||
re = '/core[^/]*$'
|
||||
end
|
||||
exc_re = { '^/%.deps$', '^/%'..deps_prefix()..'$', local_tmpdir, '^/%node_modules$' }
|
||||
exc_re = { '^/%.deps$', '^/%' .. deps_prefix() .. '$', local_tmpdir, '^/%node_modules$' }
|
||||
db_cmd = gdb_db_cmd
|
||||
random_skip = true
|
||||
end
|
||||
@ -457,7 +478,7 @@ function module.check_cores(app, force) -- luacheck: ignore
|
||||
local found_cores = 0
|
||||
local out = io.stdout
|
||||
for _, core in ipairs(cores) do
|
||||
local len = 80 - #core - #('Core file ') - 2
|
||||
local len = 80 - #core - #'Core file ' - 2
|
||||
local esigns = ('='):rep(len / 2)
|
||||
out:write(('\n%s Core file %s %s\n'):format(esigns, core, esigns))
|
||||
out:flush()
|
||||
@ -471,7 +492,7 @@ function module.check_cores(app, force) -- luacheck: ignore
|
||||
end
|
||||
tests_skipped = 0
|
||||
if found_cores > 0 then
|
||||
error("crash detected (see above)")
|
||||
error('crash detected (see above)')
|
||||
end
|
||||
end
|
||||
|
||||
@ -597,9 +618,9 @@ function module.dedent(str, leave_indent)
|
||||
-- create a pattern for the indent
|
||||
indent = indent:gsub('%s', '[ \t]')
|
||||
-- strip it from the first line
|
||||
str = str:gsub('^'..indent, left_indent)
|
||||
str = str:gsub('^' .. indent, left_indent)
|
||||
-- strip it from the remaining lines
|
||||
str = str:gsub('[\n]'..indent, '\n' .. left_indent)
|
||||
str = str:gsub('[\n]' .. indent, '\n' .. left_indent)
|
||||
return str
|
||||
end
|
||||
|
||||
@ -611,13 +632,38 @@ local function format_float(v)
|
||||
end
|
||||
|
||||
local SUBTBL = {
|
||||
'\\000', '\\001', '\\002', '\\003', '\\004',
|
||||
'\\005', '\\006', '\\007', '\\008', '\\t',
|
||||
'\\n', '\\011', '\\012', '\\r', '\\014',
|
||||
'\\015', '\\016', '\\017', '\\018', '\\019',
|
||||
'\\020', '\\021', '\\022', '\\023', '\\024',
|
||||
'\\025', '\\026', '\\027', '\\028', '\\029',
|
||||
'\\030', '\\031',
|
||||
'\\000',
|
||||
'\\001',
|
||||
'\\002',
|
||||
'\\003',
|
||||
'\\004',
|
||||
'\\005',
|
||||
'\\006',
|
||||
'\\007',
|
||||
'\\008',
|
||||
'\\t',
|
||||
'\\n',
|
||||
'\\011',
|
||||
'\\012',
|
||||
'\\r',
|
||||
'\\014',
|
||||
'\\015',
|
||||
'\\016',
|
||||
'\\017',
|
||||
'\\018',
|
||||
'\\019',
|
||||
'\\020',
|
||||
'\\021',
|
||||
'\\022',
|
||||
'\\023',
|
||||
'\\024',
|
||||
'\\025',
|
||||
'\\026',
|
||||
'\\027',
|
||||
'\\028',
|
||||
'\\029',
|
||||
'\\030',
|
||||
'\\031',
|
||||
}
|
||||
|
||||
-- Formats Lua value `v`.
|
||||
@ -647,13 +693,14 @@ function module.format_luav(v, indent, opts)
|
||||
if opts.literal_strings then
|
||||
ret = v
|
||||
else
|
||||
local quote = opts.dquote_strings and '"' or '\''
|
||||
ret = quote .. tostring(v):gsub(
|
||||
opts.dquote_strings and '["\\]' or '[\'\\]',
|
||||
'\\%0'):gsub(
|
||||
'[%z\1-\31]', function(match)
|
||||
local quote = opts.dquote_strings and '"' or "'"
|
||||
ret = quote
|
||||
.. tostring(v)
|
||||
:gsub(opts.dquote_strings and '["\\]' or "['\\]", '\\%0')
|
||||
:gsub('[%z\1-\31]', function(match)
|
||||
return SUBTBL[match:byte() + 1]
|
||||
end) .. quote
|
||||
end)
|
||||
.. quote
|
||||
end
|
||||
elseif type(v) == 'table' then
|
||||
if v == module.REMOVE_THIS then
|
||||
@ -664,8 +711,7 @@ function module.format_luav(v, indent, opts)
|
||||
local non_empty = false
|
||||
local format_luav = module.format_luav
|
||||
for i, subv in ipairs(v) do
|
||||
ret = ('%s%s%s,%s'):format(ret, next_indent,
|
||||
format_luav(subv, next_indent_arg, opts), nl)
|
||||
ret = ('%s%s%s,%s'):format(ret, next_indent, format_luav(subv, next_indent_arg, opts), nl)
|
||||
processed_keys[i] = true
|
||||
non_empty = true
|
||||
end
|
||||
@ -674,8 +720,7 @@ function module.format_luav(v, indent, opts)
|
||||
if type(k) == 'string' and k:match('^[a-zA-Z_][a-zA-Z0-9_]*$') then
|
||||
ret = ret .. next_indent .. k .. ' = '
|
||||
else
|
||||
ret = ('%s%s[%s] = '):format(ret, next_indent,
|
||||
format_luav(k, nil, opts))
|
||||
ret = ('%s%s[%s] = '):format(ret, next_indent, format_luav(k, nil, opts))
|
||||
end
|
||||
ret = ret .. format_luav(subv, next_indent_arg, opts) .. ',' .. nl
|
||||
non_empty = true
|
||||
@ -709,7 +754,7 @@ end
|
||||
-- Commit: 520c0b91a528
|
||||
function module.format_string(fmt, ...)
|
||||
local i = 0
|
||||
local args = {...}
|
||||
local args = { ... }
|
||||
local function getarg()
|
||||
i = i + 1
|
||||
return args[i]
|
||||
@ -728,7 +773,7 @@ function module.format_string(fmt, ...)
|
||||
-- Builtin %q is replaced here as it gives invalid and inconsistent with
|
||||
-- luajit results for e.g. "\e" on lua: luajit transforms that into `\27`,
|
||||
-- lua leaves as-is.
|
||||
arg = module.format_luav(arg, nil, {dquote_strings = (subfmt:sub(-1) == 'q')})
|
||||
arg = module.format_luav(arg, nil, { dquote_strings = (subfmt:sub(-1) == 'q') })
|
||||
subfmt = subfmt:sub(1, -2) .. 's'
|
||||
end
|
||||
if subfmt == '%e' then
|
||||
@ -767,27 +812,27 @@ end
|
||||
|
||||
function module.hexdump(str)
|
||||
local len = string.len(str)
|
||||
local dump = ""
|
||||
local hex = ""
|
||||
local asc = ""
|
||||
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 = ""
|
||||
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)
|
||||
hex = hex .. string.format('%02x ', ord)
|
||||
if ord >= 32 and ord <= 126 then
|
||||
asc = asc .. string.char(ord)
|
||||
else
|
||||
asc = asc .. "."
|
||||
asc = asc .. '.'
|
||||
end
|
||||
end
|
||||
|
||||
return dump .. hex .. string.rep(" ", 8 - len % 8) .. asc
|
||||
return dump .. hex .. string.rep(' ', 8 - len % 8) .. asc
|
||||
end
|
||||
|
||||
-- Reads text lines from `filename` into a table.
|
||||
@ -805,16 +850,16 @@ function module.read_file_list(filename, start)
|
||||
|
||||
-- There is no need to read more than the last 2MB of the log file, so seek
|
||||
-- to that.
|
||||
local file_size = file:seek("end")
|
||||
local file_size = file:seek('end')
|
||||
local offset = file_size - 2000000
|
||||
if offset < 0 then
|
||||
offset = 0
|
||||
end
|
||||
file:seek("set", offset)
|
||||
file:seek('set', offset)
|
||||
|
||||
local lines = {}
|
||||
local i = 1
|
||||
local line = file:read("*l")
|
||||
local line = file:read('*l')
|
||||
while line ~= nil do
|
||||
if i >= start then
|
||||
table.insert(lines, line)
|
||||
@ -823,7 +868,7 @@ function module.read_file_list(filename, start)
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
line = file:read("*l")
|
||||
line = file:read('*l')
|
||||
end
|
||||
file:close()
|
||||
return lines
|
||||
@ -875,13 +920,16 @@ function module.read_nvim_log(logfile, ci_rename)
|
||||
local is_ci = module.is_ci()
|
||||
local keep = is_ci and 100 or 10
|
||||
local lines = module.read_file_list(logfile, -keep) or {}
|
||||
local log = (('-'):rep(78)..'\n'
|
||||
..string.format('$NVIM_LOG_FILE: %s\n', logfile)
|
||||
..(#lines > 0 and '(last '..tostring(keep)..' lines)\n' or '(empty)\n'))
|
||||
for _,line in ipairs(lines) do
|
||||
log = log..line..'\n'
|
||||
local log = (
|
||||
('-'):rep(78)
|
||||
.. '\n'
|
||||
.. string.format('$NVIM_LOG_FILE: %s\n', logfile)
|
||||
.. (#lines > 0 and '(last ' .. tostring(keep) .. ' lines)\n' or '(empty)\n')
|
||||
)
|
||||
for _, line in ipairs(lines) do
|
||||
log = log .. line .. '\n'
|
||||
end
|
||||
log = log..('-'):rep(78)..'\n'
|
||||
log = log .. ('-'):rep(78) .. '\n'
|
||||
if is_ci and ci_rename then
|
||||
os.rename(logfile, logfile .. '.displayed')
|
||||
end
|
||||
|
@ -1,9 +1,13 @@
|
||||
local platform = vim.uv.os_uname()
|
||||
local deps_install_dir = table.remove(_G.arg, 1)
|
||||
local subcommand = table.remove(_G.arg, 1)
|
||||
local suffix = (platform and platform.sysname:lower():find'windows') and '.dll' or '.so'
|
||||
package.path = deps_install_dir.."/share/lua/5.1/?.lua;"..deps_install_dir.."/share/lua/5.1/?/init.lua;"..package.path
|
||||
package.cpath = deps_install_dir.."/lib/lua/5.1/?"..suffix..";"..package.cpath;
|
||||
local suffix = (platform and platform.sysname:lower():find 'windows') and '.dll' or '.so'
|
||||
package.path = deps_install_dir
|
||||
.. '/share/lua/5.1/?.lua;'
|
||||
.. deps_install_dir
|
||||
.. '/share/lua/5.1/?/init.lua;'
|
||||
.. package.path
|
||||
package.cpath = deps_install_dir .. '/lib/lua/5.1/?' .. suffix .. ';' .. package.cpath
|
||||
|
||||
local uv = vim.uv
|
||||
|
||||
@ -15,14 +19,14 @@ local system = {}
|
||||
package.loaded['system.core'] = system
|
||||
function system.monotime()
|
||||
uv.update_time()
|
||||
return uv.now()*1e-3
|
||||
return uv.now() * 1e-3
|
||||
end
|
||||
function system.gettime()
|
||||
local sec, usec = uv.gettimeofday()
|
||||
return sec+usec*1e-6
|
||||
return sec + usec * 1e-6
|
||||
end
|
||||
function system.sleep(sec)
|
||||
uv.sleep(sec*1e3)
|
||||
uv.sleep(sec * 1e3)
|
||||
end
|
||||
|
||||
local term = {}
|
||||
@ -31,7 +35,7 @@ function term.isatty(_)
|
||||
return uv.guess_handle(1) == 'tty'
|
||||
end
|
||||
|
||||
local lfs = {_VERSION = 'fake'}
|
||||
local lfs = { _VERSION = 'fake' }
|
||||
package.loaded['lfs'] = lfs
|
||||
|
||||
function lfs.attributes(path, attr)
|
||||
@ -39,9 +43,11 @@ function lfs.attributes(path, attr)
|
||||
if attr == 'mode' then
|
||||
return stat and stat.type or ''
|
||||
elseif attr == 'modification' then
|
||||
if not stat then return nil end
|
||||
if not stat then
|
||||
return nil
|
||||
end
|
||||
local mtime = stat.mtime
|
||||
return mtime.sec + mtime.nsec*1e-9
|
||||
return mtime.sec + mtime.nsec * 1e-9
|
||||
else
|
||||
error('not implemented')
|
||||
end
|
||||
@ -74,9 +80,9 @@ function lfs.mkdir(dir)
|
||||
return uv.fs_mkdir(dir, 493) -- octal 755
|
||||
end
|
||||
|
||||
if subcommand == "busted" then
|
||||
if subcommand == 'busted' then
|
||||
require 'busted.runner'({ standalone = false })
|
||||
elseif subcommand == "luacheck" then
|
||||
elseif subcommand == 'luacheck' then
|
||||
require 'luacheck.main'
|
||||
else
|
||||
error 'unknown subcommand'
|
||||
|
@ -13,9 +13,11 @@ local int_type = eval_helpers.int_type
|
||||
local flt_type = eval_helpers.flt_type
|
||||
local type_key = eval_helpers.type_key
|
||||
|
||||
local api = cimport('./src/nvim/api/private/defs.h',
|
||||
local api = cimport(
|
||||
'./src/nvim/api/private/defs.h',
|
||||
'./src/nvim/api/private/helpers.h',
|
||||
'./src/nvim/memory.h')
|
||||
'./src/nvim/memory.h'
|
||||
)
|
||||
|
||||
local obj2lua
|
||||
|
||||
@ -27,8 +29,8 @@ local function init_obj2lua_tab()
|
||||
end
|
||||
obj2lua_tab = {
|
||||
[tonumber(api.kObjectTypeArray)] = function(obj)
|
||||
local ret = {[type_key]=list_type}
|
||||
for i = 1,tonumber(obj.data.array.size) do
|
||||
local ret = { [type_key] = list_type }
|
||||
for i = 1, tonumber(obj.data.array.size) do
|
||||
ret[i] = obj2lua(obj.data.array.items[i - 1])
|
||||
end
|
||||
if ret[1] then
|
||||
@ -38,7 +40,7 @@ local function init_obj2lua_tab()
|
||||
end,
|
||||
[tonumber(api.kObjectTypeDictionary)] = function(obj)
|
||||
local ret = {}
|
||||
for i = 1,tonumber(obj.data.dictionary.size) do
|
||||
for i = 1, tonumber(obj.data.dictionary.size) do
|
||||
local kv_pair = obj.data.dictionary.items[i - 1]
|
||||
ret[ffi.string(kv_pair.key.data, kv_pair.key.size)] = obj2lua(kv_pair.value)
|
||||
end
|
||||
@ -58,7 +60,7 @@ local function init_obj2lua_tab()
|
||||
return tonumber(obj.data.floating)
|
||||
end,
|
||||
[tonumber(api.kObjectTypeInteger)] = function(obj)
|
||||
return {[type_key]=int_type, value=tonumber(obj.data.integer)}
|
||||
return { [type_key] = int_type, value = tonumber(obj.data.integer) }
|
||||
end,
|
||||
[tonumber(api.kObjectTypeString)] = function(obj)
|
||||
return ffi.string(obj.data.string.data, obj.data.string.size)
|
||||
@ -68,32 +70,38 @@ end
|
||||
|
||||
obj2lua = function(obj)
|
||||
init_obj2lua_tab()
|
||||
return ((obj2lua_tab[tonumber(obj['type'])] or function(obj_inner)
|
||||
assert(false, 'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet')
|
||||
end)(obj))
|
||||
return (
|
||||
(obj2lua_tab[tonumber(obj['type'])] or function(obj_inner)
|
||||
assert(
|
||||
false,
|
||||
'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet'
|
||||
)
|
||||
end)(obj)
|
||||
)
|
||||
end
|
||||
|
||||
local obj = function(typ, data)
|
||||
return ffi.gc(ffi.new('Object', {['type']=typ, data=data}),
|
||||
api.api_free_object)
|
||||
return ffi.gc(ffi.new('Object', { ['type'] = typ, data = data }), api.api_free_object)
|
||||
end
|
||||
|
||||
local lua2obj
|
||||
|
||||
local lua2obj_type_tab = {
|
||||
[int_type] = function(l)
|
||||
return obj(api.kObjectTypeInteger, {integer=l.value})
|
||||
return obj(api.kObjectTypeInteger, { integer = l.value })
|
||||
end,
|
||||
[flt_type] = function(l)
|
||||
return obj(api.kObjectTypeFloat, {floating=l})
|
||||
return obj(api.kObjectTypeFloat, { floating = l })
|
||||
end,
|
||||
[list_type] = function(l)
|
||||
local len = #l
|
||||
local arr = obj(api.kObjectTypeArray, {array={
|
||||
size=len,
|
||||
capacity=len,
|
||||
items=ffi.cast('Object *', api.xmalloc(len * ffi.sizeof('Object'))),
|
||||
}})
|
||||
local arr = obj(api.kObjectTypeArray, {
|
||||
array = {
|
||||
size = len,
|
||||
capacity = len,
|
||||
items = ffi.cast('Object *', api.xmalloc(len * ffi.sizeof('Object'))),
|
||||
},
|
||||
})
|
||||
for i = 1, len do
|
||||
arr.data.array.items[i - 1] = ffi.gc(lua2obj(l[i]), nil)
|
||||
end
|
||||
@ -103,21 +111,23 @@ local lua2obj_type_tab = {
|
||||
local kvs = {}
|
||||
for k, v in pairs(l) do
|
||||
if type(k) == 'string' then
|
||||
kvs[#kvs + 1] = {k, v}
|
||||
kvs[#kvs + 1] = { k, v }
|
||||
end
|
||||
end
|
||||
local len = #kvs
|
||||
local dct = obj(api.kObjectTypeDictionary, {dictionary={
|
||||
size=len,
|
||||
capacity=len,
|
||||
items=ffi.cast('KeyValuePair *',
|
||||
api.xmalloc(len * ffi.sizeof('KeyValuePair'))),
|
||||
}})
|
||||
local dct = obj(api.kObjectTypeDictionary, {
|
||||
dictionary = {
|
||||
size = len,
|
||||
capacity = len,
|
||||
items = ffi.cast('KeyValuePair *', api.xmalloc(len * ffi.sizeof('KeyValuePair'))),
|
||||
},
|
||||
})
|
||||
for i = 1, len do
|
||||
local key, val = unpack(kvs[i])
|
||||
dct.data.dictionary.items[i - 1] = ffi.new(
|
||||
'KeyValuePair', {key=ffi.gc(lua2obj(key), nil).data.string,
|
||||
value=ffi.gc(lua2obj(val), nil)})
|
||||
'KeyValuePair',
|
||||
{ key = ffi.gc(lua2obj(key), nil).data.string, value = ffi.gc(lua2obj(val), nil) }
|
||||
)
|
||||
end
|
||||
return dct
|
||||
end,
|
||||
@ -137,28 +147,31 @@ lua2obj = function(l)
|
||||
elseif type(l) == 'number' then
|
||||
return lua2obj_type_tab[flt_type](l)
|
||||
elseif type(l) == 'boolean' then
|
||||
return obj(api.kObjectTypeBoolean, {boolean=l})
|
||||
return obj(api.kObjectTypeBoolean, { boolean = l })
|
||||
elseif type(l) == 'string' then
|
||||
return obj(api.kObjectTypeString, {string={
|
||||
size=#l,
|
||||
data=api.xmemdupz(to_cstr(l), #l),
|
||||
}})
|
||||
return obj(
|
||||
api.kObjectTypeString,
|
||||
{ string = {
|
||||
size = #l,
|
||||
data = api.xmemdupz(to_cstr(l), #l),
|
||||
} }
|
||||
)
|
||||
elseif l == nil or l == nil_value then
|
||||
return obj(api.kObjectTypeNil, {integer=0})
|
||||
return obj(api.kObjectTypeNil, { integer = 0 })
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
list_type=list_type,
|
||||
dict_type=dict_type,
|
||||
func_type=func_type,
|
||||
int_type=int_type,
|
||||
flt_type=flt_type,
|
||||
list_type = list_type,
|
||||
dict_type = dict_type,
|
||||
func_type = func_type,
|
||||
int_type = int_type,
|
||||
flt_type = flt_type,
|
||||
|
||||
nil_value=nil_value,
|
||||
nil_value = nil_value,
|
||||
|
||||
type_key=type_key,
|
||||
type_key = type_key,
|
||||
|
||||
obj2lua=obj2lua,
|
||||
lua2obj=lua2obj,
|
||||
obj2lua = obj2lua,
|
||||
lua2obj = lua2obj,
|
||||
}
|
||||
|
@ -42,49 +42,61 @@ describe('vim_to_object', function()
|
||||
simple_test('converts -1.5', -1.5)
|
||||
simple_test('converts empty string', '')
|
||||
simple_test('converts non-empty string', 'foobar')
|
||||
simple_test('converts integer 10', {[type_key]=int_type, value=10})
|
||||
simple_test('converts integer 10', { [type_key] = int_type, value = 10 })
|
||||
simple_test('converts empty dictionary', {})
|
||||
simple_test('converts dictionary with scalar values', {test=10, test2=true, test3='test'})
|
||||
simple_test('converts dictionary with containers inside', {test={}, test2={1, 2}})
|
||||
simple_test('converts empty list', {[type_key]=list_type})
|
||||
simple_test('converts list with scalar values', {1, 2, 'test', 'foo'})
|
||||
simple_test('converts list with containers inside', {{}, {test={}, test3={test4=true}}})
|
||||
simple_test('converts dictionary with scalar values', { test = 10, test2 = true, test3 = 'test' })
|
||||
simple_test('converts dictionary with containers inside', { test = {}, test2 = { 1, 2 } })
|
||||
simple_test('converts empty list', { [type_key] = list_type })
|
||||
simple_test('converts list with scalar values', { 1, 2, 'test', 'foo' })
|
||||
simple_test(
|
||||
'converts list with containers inside',
|
||||
{ {}, { test = {}, test3 = { test4 = true } } }
|
||||
)
|
||||
|
||||
local dct = {}
|
||||
dct.dct = dct
|
||||
different_output_test('outputs nil for nested dictionaries (1 level)', dct, {dct=nil_value})
|
||||
different_output_test('outputs nil for nested dictionaries (1 level)', dct, { dct = nil_value })
|
||||
|
||||
local lst = {}
|
||||
lst[1] = lst
|
||||
different_output_test('outputs nil for nested lists (1 level)', lst, {nil_value})
|
||||
different_output_test('outputs nil for nested lists (1 level)', lst, { nil_value })
|
||||
|
||||
local dct2 = {test=true, dict=nil_value}
|
||||
dct2.dct = {dct2}
|
||||
different_output_test('outputs nil for nested dictionaries (2 level, in list)',
|
||||
dct2, {dct={nil_value}, test=true, dict=nil_value})
|
||||
local dct2 = { test = true, dict = nil_value }
|
||||
dct2.dct = { dct2 }
|
||||
different_output_test(
|
||||
'outputs nil for nested dictionaries (2 level, in list)',
|
||||
dct2,
|
||||
{ dct = { nil_value }, test = true, dict = nil_value }
|
||||
)
|
||||
|
||||
local dct3 = {test=true, dict=nil_value}
|
||||
dct3.dct = {dctin=dct3}
|
||||
different_output_test('outputs nil for nested dictionaries (2 level, in dict)',
|
||||
dct3, {dct={dctin=nil_value}, test=true, dict=nil_value})
|
||||
local dct3 = { test = true, dict = nil_value }
|
||||
dct3.dct = { dctin = dct3 }
|
||||
different_output_test(
|
||||
'outputs nil for nested dictionaries (2 level, in dict)',
|
||||
dct3,
|
||||
{ dct = { dctin = nil_value }, test = true, dict = nil_value }
|
||||
)
|
||||
|
||||
local lst2 = {}
|
||||
lst2[1] = {lst2}
|
||||
different_output_test('outputs nil for nested lists (2 level, in list)', lst2, {{nil_value}})
|
||||
lst2[1] = { lst2 }
|
||||
different_output_test('outputs nil for nested lists (2 level, in list)', lst2, { { nil_value } })
|
||||
|
||||
local lst3 = {nil, true, false, 'ttest'}
|
||||
lst3[1] = {lst=lst3}
|
||||
different_output_test('outputs nil for nested lists (2 level, in dict)',
|
||||
lst3, {{lst=nil_value}, true, false, 'ttest'})
|
||||
local lst3 = { nil, true, false, 'ttest' }
|
||||
lst3[1] = { lst = lst3 }
|
||||
different_output_test(
|
||||
'outputs nil for nested lists (2 level, in dict)',
|
||||
lst3,
|
||||
{ { lst = nil_value }, true, false, 'ttest' }
|
||||
)
|
||||
|
||||
itp('outputs empty list for NULL list', function()
|
||||
local tt = typvalt('VAR_LIST', {v_list=NULL})
|
||||
local tt = typvalt('VAR_LIST', { v_list = NULL })
|
||||
eq(nil, tt.vval.v_list)
|
||||
eq({[type_key]=list_type}, obj2lua(api.vim_to_object(tt)))
|
||||
eq({ [type_key] = list_type }, obj2lua(api.vim_to_object(tt)))
|
||||
end)
|
||||
|
||||
itp('outputs empty dict for NULL dict', function()
|
||||
local tt = typvalt('VAR_DICT', {v_dict=NULL})
|
||||
local tt = typvalt('VAR_DICT', { v_dict = NULL })
|
||||
eq(nil, tt.vval.v_dict)
|
||||
eq({}, obj2lua(api.vim_to_object(tt)))
|
||||
end)
|
||||
@ -92,15 +104,15 @@ describe('vim_to_object', function()
|
||||
itp('regression: partials in a list', function()
|
||||
local llist = {
|
||||
{
|
||||
[type_key]=func_type,
|
||||
value='printf',
|
||||
args={'%s'},
|
||||
dict={v=1},
|
||||
[type_key] = func_type,
|
||||
value = 'printf',
|
||||
args = { '%s' },
|
||||
dict = { v = 1 },
|
||||
},
|
||||
{},
|
||||
}
|
||||
local list = lua2typvalt(llist)
|
||||
eq(llist, typvalt2lua(list))
|
||||
eq({nil_value, {}}, obj2lua(api.vim_to_object(list)))
|
||||
eq({ nil_value, {} }, obj2lua(api.vim_to_object(list)))
|
||||
end)
|
||||
end)
|
||||
|
@ -1,14 +1,13 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local to_cstr = helpers.to_cstr
|
||||
local eq = helpers.eq
|
||||
local NULL = helpers.NULL
|
||||
|
||||
local buffer = helpers.cimport("./src/nvim/buffer.h")
|
||||
local buffer = helpers.cimport('./src/nvim/buffer.h')
|
||||
|
||||
describe('buffer functions', function()
|
||||
|
||||
local buflist_new = function(file, flags)
|
||||
local c_file = to_cstr(file)
|
||||
return buffer.buflist_new(c_file, c_file, 1, flags)
|
||||
@ -36,7 +35,6 @@ describe('buffer functions', function()
|
||||
end)
|
||||
|
||||
describe('buf_valid', function()
|
||||
|
||||
itp('should view NULL as an invalid buffer', function()
|
||||
eq(false, buffer.buf_valid(NULL))
|
||||
end)
|
||||
@ -72,9 +70,7 @@ describe('buffer functions', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
describe('buflist_findpat', function()
|
||||
|
||||
local ALLOW_UNLISTED = 1
|
||||
local ONLY_LISTED = 0
|
||||
|
||||
@ -95,9 +91,9 @@ describe('buffer functions', function()
|
||||
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
|
||||
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
|
||||
|
||||
eq(buf1.handle, buflist_findpat("test", ONLY_LISTED))
|
||||
eq(buf2.handle, buflist_findpat("file", ONLY_LISTED))
|
||||
eq(buf3.handle, buflist_findpat("path", ONLY_LISTED))
|
||||
eq(buf1.handle, buflist_findpat('test', ONLY_LISTED))
|
||||
eq(buf2.handle, buflist_findpat('file', ONLY_LISTED))
|
||||
eq(buf3.handle, buflist_findpat('path', ONLY_LISTED))
|
||||
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0, 0)
|
||||
@ -111,7 +107,7 @@ describe('buffer functions', function()
|
||||
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
|
||||
|
||||
-- Then: buf2 is the buffer that is found
|
||||
eq(buf2.handle, buflist_findpat("test", ONLY_LISTED))
|
||||
eq(buf2.handle, buflist_findpat('test', ONLY_LISTED))
|
||||
--}
|
||||
|
||||
--{ When: We close buf2
|
||||
@ -121,7 +117,7 @@ describe('buffer functions', function()
|
||||
local buf1 = buflist_new(path1, buffer.BLN_LISTED)
|
||||
|
||||
-- Then: buf3 is found since 'file' appears at the end of the name
|
||||
eq(buf3.handle, buflist_findpat("file", ONLY_LISTED))
|
||||
eq(buf3.handle, buflist_findpat('file', ONLY_LISTED))
|
||||
--}
|
||||
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
|
||||
@ -133,7 +129,7 @@ describe('buffer functions', function()
|
||||
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
|
||||
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
|
||||
|
||||
eq(buf3.handle, buflist_findpat("_test_", ONLY_LISTED))
|
||||
eq(buf3.handle, buflist_findpat('_test_', ONLY_LISTED))
|
||||
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
|
||||
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0, 0)
|
||||
@ -145,25 +141,25 @@ describe('buffer functions', function()
|
||||
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
|
||||
|
||||
-- Then: We should find the buffer when it is given a unique pattern
|
||||
eq(buf3.handle, buflist_findpat("_test_", ONLY_LISTED))
|
||||
eq(buf3.handle, buflist_findpat('_test_', ONLY_LISTED))
|
||||
--}
|
||||
|
||||
--{ When: We unlist the buffer
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_DEL, 0, 0)
|
||||
|
||||
-- Then: It should not find the buffer when searching only listed buffers
|
||||
eq(-1, buflist_findpat("_test_", ONLY_LISTED))
|
||||
eq(-1, buflist_findpat('_test_', ONLY_LISTED))
|
||||
|
||||
-- And: It should find the buffer when including unlisted buffers
|
||||
eq(buf3.handle, buflist_findpat("_test_", ALLOW_UNLISTED))
|
||||
eq(buf3.handle, buflist_findpat('_test_', ALLOW_UNLISTED))
|
||||
--}
|
||||
|
||||
--{ When: We wipe the buffer
|
||||
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0, 0)
|
||||
|
||||
-- Then: It should not find the buffer at all
|
||||
eq(-1, buflist_findpat("_test_", ONLY_LISTED))
|
||||
eq(-1, buflist_findpat("_test_", ALLOW_UNLISTED))
|
||||
eq(-1, buflist_findpat('_test_', ONLY_LISTED))
|
||||
eq(-1, buflist_findpat('_test_', ALLOW_UNLISTED))
|
||||
--}
|
||||
end)
|
||||
|
||||
@ -173,7 +169,7 @@ describe('buffer functions', function()
|
||||
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
|
||||
|
||||
-- Then: The first buffer is preferred when both are listed
|
||||
eq(buf1.handle, buflist_findpat("test", ONLY_LISTED))
|
||||
eq(buf1.handle, buflist_findpat('test', ONLY_LISTED))
|
||||
--}
|
||||
|
||||
--{ When: The first buffer is unlisted
|
||||
@ -181,13 +177,13 @@ describe('buffer functions', function()
|
||||
|
||||
-- Then: The second buffer is preferred because
|
||||
-- unlisted buffers are not allowed
|
||||
eq(buf2.handle, buflist_findpat("test", ONLY_LISTED))
|
||||
eq(buf2.handle, buflist_findpat('test', ONLY_LISTED))
|
||||
--}
|
||||
|
||||
--{ When: We allow unlisted buffers
|
||||
-- Then: The second buffer is still preferred
|
||||
-- because listed buffers are preferred to unlisted
|
||||
eq(buf2.handle, buflist_findpat("test", ALLOW_UNLISTED))
|
||||
eq(buf2.handle, buflist_findpat('test', ALLOW_UNLISTED))
|
||||
--}
|
||||
|
||||
--{ When: We unlist the second buffer
|
||||
@ -196,10 +192,10 @@ describe('buffer functions', function()
|
||||
-- Then: The first buffer is preferred again
|
||||
-- because buf1 matches better which takes precedence
|
||||
-- when both buffers have the same listing status.
|
||||
eq(buf1.handle, buflist_findpat("test", ALLOW_UNLISTED))
|
||||
eq(buf1.handle, buflist_findpat('test', ALLOW_UNLISTED))
|
||||
|
||||
-- And: Neither buffer is returned when ignoring unlisted
|
||||
eq(-1, buflist_findpat("test", ONLY_LISTED))
|
||||
eq(-1, buflist_findpat('test', ONLY_LISTED))
|
||||
--}
|
||||
|
||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
|
||||
|
@ -1,4 +1,4 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local bit = require('bit')
|
||||
|
||||
local itp = helpers.gen_itp(it)
|
||||
@ -26,10 +26,10 @@ local ucnt = 4242
|
||||
local function arginit(arg)
|
||||
if arg == 'unum' then
|
||||
ucnt = ucnt + 1
|
||||
return ARGTYPES[arg]({ucnt})
|
||||
return ARGTYPES[arg]({ ucnt })
|
||||
else
|
||||
icnt = icnt - 1
|
||||
return ARGTYPES[arg]({icnt})
|
||||
return ARGTYPES[arg]({ icnt })
|
||||
end
|
||||
end
|
||||
|
||||
@ -44,7 +44,9 @@ local function argreset(arg, args)
|
||||
end
|
||||
|
||||
local function test_vim_str2nr(s, what, exp, maxlen, strict)
|
||||
if strict == nil then strict = true end
|
||||
if strict == nil then
|
||||
strict = true
|
||||
end
|
||||
local bits = {}
|
||||
for k, _ in pairs(exp) do
|
||||
bits[#bits + 1] = k
|
||||
@ -54,7 +56,7 @@ local function test_vim_str2nr(s, what, exp, maxlen, strict)
|
||||
for k, _ in pairs(ARGTYPES) do
|
||||
args[k] = arginit(k)
|
||||
end
|
||||
for case = 0, ((2 ^ (#bits)) - 1) do
|
||||
for case = 0, ((2 ^ #bits) - 1) do
|
||||
local cv = {}
|
||||
for b = 0, (#bits - 1) do
|
||||
if bit.band(case, (2 ^ b)) == 0 then
|
||||
@ -66,9 +68,17 @@ local function test_vim_str2nr(s, what, exp, maxlen, strict)
|
||||
lib.vim_str2nr(s, cv.pre, cv.len, what, cv.num, cv.unum, maxlen, strict, nil)
|
||||
for cck, ccv in pairs(cv) do
|
||||
if exp[cck] ~= tonumber(ccv[0]) then
|
||||
error(('Failed check (%s = %d) in test (s=%s, w=%u, m=%d, strict=%s): %d'):format(
|
||||
cck, exp[cck], s, tonumber(what), maxlen, tostring(strict), tonumber(ccv[0])
|
||||
))
|
||||
error(
|
||||
('Failed check (%s = %d) in test (s=%s, w=%u, m=%d, strict=%s): %d'):format(
|
||||
cck,
|
||||
exp[cck],
|
||||
s,
|
||||
tonumber(what),
|
||||
maxlen,
|
||||
tostring(strict),
|
||||
tonumber(ccv[0])
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -82,18 +92,48 @@ end
|
||||
|
||||
describe('vim_str2nr()', function()
|
||||
itp('works fine when it has nothing to do', function()
|
||||
test_vim_str2nr('', 0, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_ALL, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_BIN, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_OCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_HEX, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_DEC, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_BIN, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_HEX, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr('', 0, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_ALL, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_BIN, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_OCT, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_OOCT, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
|
||||
test_vim_str2nr('', lib.STR2NR_HEX, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
|
||||
test_vim_str2nr(
|
||||
'',
|
||||
lib.STR2NR_FORCE + lib.STR2NR_DEC,
|
||||
{ len = 0, num = 0, unum = 0, pre = 0 },
|
||||
0
|
||||
)
|
||||
test_vim_str2nr(
|
||||
'',
|
||||
lib.STR2NR_FORCE + lib.STR2NR_BIN,
|
||||
{ len = 0, num = 0, unum = 0, pre = 0 },
|
||||
0
|
||||
)
|
||||
test_vim_str2nr(
|
||||
'',
|
||||
lib.STR2NR_FORCE + lib.STR2NR_OCT,
|
||||
{ len = 0, num = 0, unum = 0, pre = 0 },
|
||||
0
|
||||
)
|
||||
test_vim_str2nr(
|
||||
'',
|
||||
lib.STR2NR_FORCE + lib.STR2NR_OOCT,
|
||||
{ len = 0, num = 0, unum = 0, pre = 0 },
|
||||
0
|
||||
)
|
||||
test_vim_str2nr(
|
||||
'',
|
||||
lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT,
|
||||
{ len = 0, num = 0, unum = 0, pre = 0 },
|
||||
0
|
||||
)
|
||||
test_vim_str2nr(
|
||||
'',
|
||||
lib.STR2NR_FORCE + lib.STR2NR_HEX,
|
||||
{ len = 0, num = 0, unum = 0, pre = 0 },
|
||||
0
|
||||
)
|
||||
end)
|
||||
itp('works with decimal numbers', function()
|
||||
for _, flags in ipairs({
|
||||
@ -110,30 +150,30 @@ describe('vim_str2nr()', function()
|
||||
lib.STR2NR_FORCE + lib.STR2NR_DEC,
|
||||
}) do
|
||||
-- Check that all digits are recognized
|
||||
test_vim_str2nr( '12345', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0)
|
||||
test_vim_str2nr( '67890', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0)
|
||||
test_vim_str2nr( '12345A', flags, {len = 0}, 0)
|
||||
test_vim_str2nr( '67890A', flags, {len = 0}, 0)
|
||||
test_vim_str2nr( '12345A', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0, false)
|
||||
test_vim_str2nr( '67890A', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0, false)
|
||||
test_vim_str2nr('12345', flags, { len = 5, num = 12345, unum = 12345, pre = 0 }, 0)
|
||||
test_vim_str2nr('67890', flags, { len = 5, num = 67890, unum = 67890, pre = 0 }, 0)
|
||||
test_vim_str2nr('12345A', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('67890A', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('12345A', flags, { len = 5, num = 12345, unum = 12345, pre = 0 }, 0, false)
|
||||
test_vim_str2nr('67890A', flags, { len = 5, num = 67890, unum = 67890, pre = 0 }, 0, false)
|
||||
|
||||
test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0)
|
||||
test_vim_str2nr( '42', flags, {len = 1, num = 4, unum = 4, pre = 0}, 1)
|
||||
test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 2)
|
||||
test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3) -- includes NUL byte in maxlen
|
||||
test_vim_str2nr('42', flags, { len = 2, num = 42, unum = 42, pre = 0 }, 0)
|
||||
test_vim_str2nr('42', flags, { len = 1, num = 4, unum = 4, pre = 0 }, 1)
|
||||
test_vim_str2nr('42', flags, { len = 2, num = 42, unum = 42, pre = 0 }, 2)
|
||||
test_vim_str2nr('42', flags, { len = 2, num = 42, unum = 42, pre = 0 }, 3) -- includes NUL byte in maxlen
|
||||
|
||||
test_vim_str2nr( '42x', flags, {len = 0}, 0)
|
||||
test_vim_str2nr( '42x', flags, {len = 0}, 3)
|
||||
test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0, false)
|
||||
test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3, false)
|
||||
test_vim_str2nr('42x', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('42x', flags, { len = 0 }, 3)
|
||||
test_vim_str2nr('42x', flags, { len = 2, num = 42, unum = 42, pre = 0 }, 0, false)
|
||||
test_vim_str2nr('42x', flags, { len = 2, num = 42, unum = 42, pre = 0 }, 3, false)
|
||||
|
||||
test_vim_str2nr('-42', flags, {len = 3, num = -42, unum = 42, pre = 0}, 3)
|
||||
test_vim_str2nr('-42', flags, {len = 1, num = 0, unum = 0, pre = 0}, 1)
|
||||
test_vim_str2nr('-42', flags, { len = 3, num = -42, unum = 42, pre = 0 }, 3)
|
||||
test_vim_str2nr('-42', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
|
||||
test_vim_str2nr('-42x', flags, {len = 0}, 0)
|
||||
test_vim_str2nr('-42x', flags, {len = 0}, 4)
|
||||
test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 0, false)
|
||||
test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 4, false)
|
||||
test_vim_str2nr('-42x', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('-42x', flags, { len = 0 }, 4)
|
||||
test_vim_str2nr('-42x', flags, { len = 3, num = -42, unum = 42, pre = 0 }, 0, false)
|
||||
test_vim_str2nr('-42x', flags, { len = 3, num = -42, unum = 42, pre = 0 }, 4, false)
|
||||
end
|
||||
end)
|
||||
itp('works with binary numbers', function()
|
||||
@ -154,66 +194,66 @@ describe('vim_str2nr()', function()
|
||||
BIN = ('B'):byte()
|
||||
end
|
||||
|
||||
test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0)
|
||||
test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr( '0b101', flags, {len = 0}, 2)
|
||||
test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
|
||||
test_vim_str2nr( '0b101', flags, {len = 3, num = 1, unum = 1, pre = bin}, 3)
|
||||
test_vim_str2nr( '0b101', flags, {len = 4, num = 2, unum = 2, pre = bin}, 4)
|
||||
test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 5)
|
||||
test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6)
|
||||
test_vim_str2nr('0b101', flags, { len = 5, num = 5, unum = 5, pre = bin }, 0)
|
||||
test_vim_str2nr('0b101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('0b101', flags, { len = 0 }, 2)
|
||||
test_vim_str2nr('0b101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
|
||||
test_vim_str2nr('0b101', flags, { len = 3, num = 1, unum = 1, pre = bin }, 3)
|
||||
test_vim_str2nr('0b101', flags, { len = 4, num = 2, unum = 2, pre = bin }, 4)
|
||||
test_vim_str2nr('0b101', flags, { len = 5, num = 5, unum = 5, pre = bin }, 5)
|
||||
test_vim_str2nr('0b101', flags, { len = 5, num = 5, unum = 5, pre = bin }, 6)
|
||||
|
||||
test_vim_str2nr( '0b1012', flags, {len = 0}, 0)
|
||||
test_vim_str2nr( '0b1012', flags, {len = 0}, 6)
|
||||
test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0, false)
|
||||
test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6, false)
|
||||
test_vim_str2nr('0b1012', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('0b1012', flags, { len = 0 }, 6)
|
||||
test_vim_str2nr('0b1012', flags, { len = 5, num = 5, unum = 5, pre = bin }, 0, false)
|
||||
test_vim_str2nr('0b1012', flags, { len = 5, num = 5, unum = 5, pre = bin }, 6, false)
|
||||
|
||||
test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0)
|
||||
test_vim_str2nr('-0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0b101', flags, {len = 0}, 3)
|
||||
test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
|
||||
test_vim_str2nr('-0b101', flags, {len = 4, num = -1, unum = 1, pre = bin}, 4)
|
||||
test_vim_str2nr('-0b101', flags, {len = 5, num = -2, unum = 2, pre = bin}, 5)
|
||||
test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 6)
|
||||
test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7)
|
||||
test_vim_str2nr('-0b101', flags, { len = 6, num = -5, unum = 5, pre = bin }, 0)
|
||||
test_vim_str2nr('-0b101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0b101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0b101', flags, { len = 0 }, 3)
|
||||
test_vim_str2nr('-0b101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
|
||||
test_vim_str2nr('-0b101', flags, { len = 4, num = -1, unum = 1, pre = bin }, 4)
|
||||
test_vim_str2nr('-0b101', flags, { len = 5, num = -2, unum = 2, pre = bin }, 5)
|
||||
test_vim_str2nr('-0b101', flags, { len = 6, num = -5, unum = 5, pre = bin }, 6)
|
||||
test_vim_str2nr('-0b101', flags, { len = 6, num = -5, unum = 5, pre = bin }, 7)
|
||||
|
||||
test_vim_str2nr('-0b1012', flags, {len = 0}, 0)
|
||||
test_vim_str2nr('-0b1012', flags, {len = 0}, 7)
|
||||
test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0, false)
|
||||
test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7, false)
|
||||
test_vim_str2nr('-0b1012', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('-0b1012', flags, { len = 0 }, 7)
|
||||
test_vim_str2nr('-0b1012', flags, { len = 6, num = -5, unum = 5, pre = bin }, 0, false)
|
||||
test_vim_str2nr('-0b1012', flags, { len = 6, num = -5, unum = 5, pre = bin }, 7, false)
|
||||
|
||||
test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0)
|
||||
test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr( '0B101', flags, {len = 0}, 2)
|
||||
test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
|
||||
test_vim_str2nr( '0B101', flags, {len = 3, num = 1, unum = 1, pre = BIN}, 3)
|
||||
test_vim_str2nr( '0B101', flags, {len = 4, num = 2, unum = 2, pre = BIN}, 4)
|
||||
test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 5)
|
||||
test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6)
|
||||
test_vim_str2nr('0B101', flags, { len = 5, num = 5, unum = 5, pre = BIN }, 0)
|
||||
test_vim_str2nr('0B101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('0B101', flags, { len = 0 }, 2)
|
||||
test_vim_str2nr('0B101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
|
||||
test_vim_str2nr('0B101', flags, { len = 3, num = 1, unum = 1, pre = BIN }, 3)
|
||||
test_vim_str2nr('0B101', flags, { len = 4, num = 2, unum = 2, pre = BIN }, 4)
|
||||
test_vim_str2nr('0B101', flags, { len = 5, num = 5, unum = 5, pre = BIN }, 5)
|
||||
test_vim_str2nr('0B101', flags, { len = 5, num = 5, unum = 5, pre = BIN }, 6)
|
||||
|
||||
test_vim_str2nr( '0B1012', flags, {len = 0}, 0)
|
||||
test_vim_str2nr( '0B1012', flags, {len = 0}, 6)
|
||||
test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0, false)
|
||||
test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6, false)
|
||||
test_vim_str2nr('0B1012', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('0B1012', flags, { len = 0 }, 6)
|
||||
test_vim_str2nr('0B1012', flags, { len = 5, num = 5, unum = 5, pre = BIN }, 0, false)
|
||||
test_vim_str2nr('0B1012', flags, { len = 5, num = 5, unum = 5, pre = BIN }, 6, false)
|
||||
|
||||
test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0)
|
||||
test_vim_str2nr('-0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0B101', flags, {len = 0}, 3)
|
||||
test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
|
||||
test_vim_str2nr('-0B101', flags, {len = 4, num = -1, unum = 1, pre = BIN}, 4)
|
||||
test_vim_str2nr('-0B101', flags, {len = 5, num = -2, unum = 2, pre = BIN}, 5)
|
||||
test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 6)
|
||||
test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7)
|
||||
test_vim_str2nr('-0B101', flags, { len = 6, num = -5, unum = 5, pre = BIN }, 0)
|
||||
test_vim_str2nr('-0B101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0B101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0B101', flags, { len = 0 }, 3)
|
||||
test_vim_str2nr('-0B101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
|
||||
test_vim_str2nr('-0B101', flags, { len = 4, num = -1, unum = 1, pre = BIN }, 4)
|
||||
test_vim_str2nr('-0B101', flags, { len = 5, num = -2, unum = 2, pre = BIN }, 5)
|
||||
test_vim_str2nr('-0B101', flags, { len = 6, num = -5, unum = 5, pre = BIN }, 6)
|
||||
test_vim_str2nr('-0B101', flags, { len = 6, num = -5, unum = 5, pre = BIN }, 7)
|
||||
|
||||
test_vim_str2nr('-0B1012', flags, {len = 0}, 0)
|
||||
test_vim_str2nr('-0B1012', flags, {len = 0}, 7)
|
||||
test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0, false)
|
||||
test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7, false)
|
||||
test_vim_str2nr('-0B1012', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('-0B1012', flags, { len = 0 }, 7)
|
||||
test_vim_str2nr('-0B1012', flags, { len = 6, num = -5, unum = 5, pre = BIN }, 0, false)
|
||||
test_vim_str2nr('-0B1012', flags, { len = 6, num = -5, unum = 5, pre = BIN }, 7, false)
|
||||
|
||||
if flags > lib.STR2NR_FORCE then
|
||||
test_vim_str2nr('-101', flags, {len = 4, num = -5, unum = 5, pre = 0}, 0)
|
||||
test_vim_str2nr('-101', flags, { len = 4, num = -5, unum = 5, pre = 0 }, 0)
|
||||
end
|
||||
end
|
||||
end)
|
||||
@ -236,42 +276,42 @@ describe('vim_str2nr()', function()
|
||||
end
|
||||
|
||||
-- Check that all digits are recognized
|
||||
test_vim_str2nr( '012345670', flags, {len = 9, num = 2739128, unum = 2739128, pre = oct}, 0)
|
||||
test_vim_str2nr('012345670', flags, { len = 9, num = 2739128, unum = 2739128, pre = oct }, 0)
|
||||
|
||||
test_vim_str2nr( '054', flags, {len = 3, num = 44, unum = 44, pre = oct}, 0)
|
||||
test_vim_str2nr( '054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr( '054', flags, {len = 2, num = 5, unum = 5, pre = oct}, 2)
|
||||
test_vim_str2nr( '054', flags, {len = 3, num = 44, unum = 44, pre = oct}, 3)
|
||||
test_vim_str2nr( '0548', flags, {len = 3, num = 44, unum = 44, pre = oct}, 3)
|
||||
test_vim_str2nr( '054', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4)
|
||||
test_vim_str2nr('054', flags, { len = 3, num = 44, unum = 44, pre = oct }, 0)
|
||||
test_vim_str2nr('054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('054', flags, { len = 2, num = 5, unum = 5, pre = oct }, 2)
|
||||
test_vim_str2nr('054', flags, { len = 3, num = 44, unum = 44, pre = oct }, 3)
|
||||
test_vim_str2nr('0548', flags, { len = 3, num = 44, unum = 44, pre = oct }, 3)
|
||||
test_vim_str2nr('054', flags, { len = 3, num = 44, unum = 44, pre = oct }, 4)
|
||||
|
||||
test_vim_str2nr( '054x', flags, {len = 0}, 4)
|
||||
test_vim_str2nr( '054x', flags, {len = 0}, 0)
|
||||
test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4, false)
|
||||
test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 0, false)
|
||||
test_vim_str2nr('054x', flags, { len = 0 }, 4)
|
||||
test_vim_str2nr('054x', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('054x', flags, { len = 3, num = 44, unum = 44, pre = oct }, 4, false)
|
||||
test_vim_str2nr('054x', flags, { len = 3, num = 44, unum = 44, pre = oct }, 0, false)
|
||||
|
||||
test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0)
|
||||
test_vim_str2nr('-054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-054', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-054', flags, {len = 3, num = -5, unum = 5, pre = oct}, 3)
|
||||
test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 4)
|
||||
test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = oct}, 4)
|
||||
test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5)
|
||||
test_vim_str2nr('-054', flags, { len = 4, num = -44, unum = 44, pre = oct }, 0)
|
||||
test_vim_str2nr('-054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-054', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-054', flags, { len = 3, num = -5, unum = 5, pre = oct }, 3)
|
||||
test_vim_str2nr('-054', flags, { len = 4, num = -44, unum = 44, pre = oct }, 4)
|
||||
test_vim_str2nr('-0548', flags, { len = 4, num = -44, unum = 44, pre = oct }, 4)
|
||||
test_vim_str2nr('-054', flags, { len = 4, num = -44, unum = 44, pre = oct }, 5)
|
||||
|
||||
test_vim_str2nr('-054x', flags, {len = 0}, 5)
|
||||
test_vim_str2nr('-054x', flags, {len = 0}, 0)
|
||||
test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5, false)
|
||||
test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0, false)
|
||||
test_vim_str2nr('-054x', flags, { len = 0 }, 5)
|
||||
test_vim_str2nr('-054x', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('-054x', flags, { len = 4, num = -44, unum = 44, pre = oct }, 5, false)
|
||||
test_vim_str2nr('-054x', flags, { len = 4, num = -44, unum = 44, pre = oct }, 0, false)
|
||||
|
||||
if flags > lib.STR2NR_FORCE then
|
||||
test_vim_str2nr('-54', flags, {len = 3, num = -44, unum = 44, pre = 0}, 0)
|
||||
test_vim_str2nr('-0548', flags, {len = 0}, 5)
|
||||
test_vim_str2nr('-0548', flags, {len = 0}, 0)
|
||||
test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 5, false)
|
||||
test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 0, false)
|
||||
test_vim_str2nr('-54', flags, { len = 3, num = -44, unum = 44, pre = 0 }, 0)
|
||||
test_vim_str2nr('-0548', flags, { len = 0 }, 5)
|
||||
test_vim_str2nr('-0548', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('-0548', flags, { len = 4, num = -44, unum = 44, pre = 0 }, 5, false)
|
||||
test_vim_str2nr('-0548', flags, { len = 4, num = -44, unum = 44, pre = 0 }, 0, false)
|
||||
else
|
||||
test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 5)
|
||||
test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 0)
|
||||
test_vim_str2nr('-0548', flags, { len = 5, num = -548, unum = 548, pre = 0 }, 5)
|
||||
test_vim_str2nr('-0548', flags, { len = 5, num = -548, unum = 548, pre = 0 }, 0)
|
||||
end
|
||||
end
|
||||
end)
|
||||
@ -298,73 +338,73 @@ describe('vim_str2nr()', function()
|
||||
OCT = ('O'):byte()
|
||||
end
|
||||
|
||||
test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 0)
|
||||
test_vim_str2nr( '0o054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr( '0o054', flags, {len = 0}, 2)
|
||||
test_vim_str2nr( '0o054', flags, {len = 3, num = 0, unum = 0, pre = oct}, 3)
|
||||
test_vim_str2nr( '0o054', flags, {len = 4, num = 5, unum = 5, pre = oct}, 4)
|
||||
test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 5)
|
||||
test_vim_str2nr( '0o0548', flags, {len = 5, num = 44, unum = 44, pre = oct}, 5)
|
||||
test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 6)
|
||||
test_vim_str2nr('0o054', flags, { len = 5, num = 44, unum = 44, pre = oct }, 0)
|
||||
test_vim_str2nr('0o054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('0o054', flags, { len = 0 }, 2)
|
||||
test_vim_str2nr('0o054', flags, { len = 3, num = 0, unum = 0, pre = oct }, 3)
|
||||
test_vim_str2nr('0o054', flags, { len = 4, num = 5, unum = 5, pre = oct }, 4)
|
||||
test_vim_str2nr('0o054', flags, { len = 5, num = 44, unum = 44, pre = oct }, 5)
|
||||
test_vim_str2nr('0o0548', flags, { len = 5, num = 44, unum = 44, pre = oct }, 5)
|
||||
test_vim_str2nr('0o054', flags, { len = 5, num = 44, unum = 44, pre = oct }, 6)
|
||||
|
||||
test_vim_str2nr( '0o054x', flags, {len = 0}, 6)
|
||||
test_vim_str2nr( '0o054x', flags, {len = 0}, 0)
|
||||
test_vim_str2nr( '0o054x', flags, {len = 5, num = 44, unum = 44, pre = oct}, 6, false)
|
||||
test_vim_str2nr( '0o054x', flags, {len = 5, num = 44, unum = 44, pre = oct}, 0, false)
|
||||
test_vim_str2nr('0o054x', flags, { len = 0 }, 6)
|
||||
test_vim_str2nr('0o054x', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('0o054x', flags, { len = 5, num = 44, unum = 44, pre = oct }, 6, false)
|
||||
test_vim_str2nr('0o054x', flags, { len = 5, num = 44, unum = 44, pre = oct }, 0, false)
|
||||
|
||||
test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 0)
|
||||
test_vim_str2nr('-0o054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0o054', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0o054', flags, {len = 0}, 3)
|
||||
test_vim_str2nr('-0o054', flags, {len = 4, num = 0, unum = 0, pre = oct}, 4)
|
||||
test_vim_str2nr('-0o054', flags, {len = 5, num = -5, unum = 5, pre = oct}, 5)
|
||||
test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 6)
|
||||
test_vim_str2nr('-0o0548', flags, {len = 6, num = -44, unum = 44, pre = oct}, 6)
|
||||
test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 7)
|
||||
test_vim_str2nr('-0o054', flags, { len = 6, num = -44, unum = 44, pre = oct }, 0)
|
||||
test_vim_str2nr('-0o054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0o054', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0o054', flags, { len = 0 }, 3)
|
||||
test_vim_str2nr('-0o054', flags, { len = 4, num = 0, unum = 0, pre = oct }, 4)
|
||||
test_vim_str2nr('-0o054', flags, { len = 5, num = -5, unum = 5, pre = oct }, 5)
|
||||
test_vim_str2nr('-0o054', flags, { len = 6, num = -44, unum = 44, pre = oct }, 6)
|
||||
test_vim_str2nr('-0o0548', flags, { len = 6, num = -44, unum = 44, pre = oct }, 6)
|
||||
test_vim_str2nr('-0o054', flags, { len = 6, num = -44, unum = 44, pre = oct }, 7)
|
||||
|
||||
test_vim_str2nr('-0o054x', flags, {len = 0}, 7)
|
||||
test_vim_str2nr('-0o054x', flags, {len = 0}, 0)
|
||||
test_vim_str2nr('-0o054x', flags, {len = 6, num = -44, unum = 44, pre = oct}, 7, false)
|
||||
test_vim_str2nr('-0o054x', flags, {len = 6, num = -44, unum = 44, pre = oct}, 0, false)
|
||||
test_vim_str2nr('-0o054x', flags, { len = 0 }, 7)
|
||||
test_vim_str2nr('-0o054x', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('-0o054x', flags, { len = 6, num = -44, unum = 44, pre = oct }, 7, false)
|
||||
test_vim_str2nr('-0o054x', flags, { len = 6, num = -44, unum = 44, pre = oct }, 0, false)
|
||||
|
||||
test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 0)
|
||||
test_vim_str2nr( '0O054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr( '0O054', flags, {len = 0}, 2)
|
||||
test_vim_str2nr( '0O054', flags, {len = 3, num = 0, unum = 0, pre = OCT}, 3)
|
||||
test_vim_str2nr( '0O054', flags, {len = 4, num = 5, unum = 5, pre = OCT}, 4)
|
||||
test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 5)
|
||||
test_vim_str2nr( '0O0548', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 5)
|
||||
test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 6)
|
||||
test_vim_str2nr('0O054', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 0)
|
||||
test_vim_str2nr('0O054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('0O054', flags, { len = 0 }, 2)
|
||||
test_vim_str2nr('0O054', flags, { len = 3, num = 0, unum = 0, pre = OCT }, 3)
|
||||
test_vim_str2nr('0O054', flags, { len = 4, num = 5, unum = 5, pre = OCT }, 4)
|
||||
test_vim_str2nr('0O054', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 5)
|
||||
test_vim_str2nr('0O0548', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 5)
|
||||
test_vim_str2nr('0O054', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 6)
|
||||
|
||||
test_vim_str2nr( '0O054x', flags, {len = 0}, 6)
|
||||
test_vim_str2nr( '0O054x', flags, {len = 0}, 0)
|
||||
test_vim_str2nr( '0O054x', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 6, false)
|
||||
test_vim_str2nr( '0O054x', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 0, false)
|
||||
test_vim_str2nr('0O054x', flags, { len = 0 }, 6)
|
||||
test_vim_str2nr('0O054x', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('0O054x', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 6, false)
|
||||
test_vim_str2nr('0O054x', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 0, false)
|
||||
|
||||
test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 0)
|
||||
test_vim_str2nr('-0O054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0O054', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0O054', flags, {len = 0}, 3)
|
||||
test_vim_str2nr('-0O054', flags, {len = 4, num = 0, unum = 0, pre = OCT}, 4)
|
||||
test_vim_str2nr('-0O054', flags, {len = 5, num = -5, unum = 5, pre = OCT}, 5)
|
||||
test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 6)
|
||||
test_vim_str2nr('-0O0548', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 6)
|
||||
test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 7)
|
||||
test_vim_str2nr('-0O054', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 0)
|
||||
test_vim_str2nr('-0O054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0O054', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0O054', flags, { len = 0 }, 3)
|
||||
test_vim_str2nr('-0O054', flags, { len = 4, num = 0, unum = 0, pre = OCT }, 4)
|
||||
test_vim_str2nr('-0O054', flags, { len = 5, num = -5, unum = 5, pre = OCT }, 5)
|
||||
test_vim_str2nr('-0O054', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 6)
|
||||
test_vim_str2nr('-0O0548', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 6)
|
||||
test_vim_str2nr('-0O054', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 7)
|
||||
|
||||
test_vim_str2nr('-0O054x', flags, {len = 0}, 7)
|
||||
test_vim_str2nr('-0O054x', flags, {len = 0}, 0)
|
||||
test_vim_str2nr('-0O054x', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 7, false)
|
||||
test_vim_str2nr('-0O054x', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 0, false)
|
||||
test_vim_str2nr('-0O054x', flags, { len = 0 }, 7)
|
||||
test_vim_str2nr('-0O054x', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('-0O054x', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 7, false)
|
||||
test_vim_str2nr('-0O054x', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 0, false)
|
||||
|
||||
if flags > lib.STR2NR_FORCE then
|
||||
test_vim_str2nr('-0548', flags, {len = 0}, 5)
|
||||
test_vim_str2nr('-0548', flags, {len = 0}, 0)
|
||||
test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 5, false)
|
||||
test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 0, false)
|
||||
test_vim_str2nr('-055', flags, {len = 4, num = -45, unum = 45, pre = 0}, 0)
|
||||
test_vim_str2nr('-0548', flags, { len = 0 }, 5)
|
||||
test_vim_str2nr('-0548', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('-0548', flags, { len = 4, num = -44, unum = 44, pre = 0 }, 5, false)
|
||||
test_vim_str2nr('-0548', flags, { len = 4, num = -44, unum = 44, pre = 0 }, 0, false)
|
||||
test_vim_str2nr('-055', flags, { len = 4, num = -45, unum = 45, pre = 0 }, 0)
|
||||
else
|
||||
test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 5)
|
||||
test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 0)
|
||||
test_vim_str2nr('-0548', flags, { len = 5, num = -548, unum = 548, pre = 0 }, 5)
|
||||
test_vim_str2nr('-0548', flags, { len = 5, num = -548, unum = 548, pre = 0 }, 0)
|
||||
end
|
||||
end
|
||||
end)
|
||||
@ -387,92 +427,92 @@ describe('vim_str2nr()', function()
|
||||
end
|
||||
|
||||
-- Check that all digits are recognized
|
||||
test_vim_str2nr('0x12345', flags, {len = 7, num = 74565, unum = 74565, pre = hex}, 0)
|
||||
test_vim_str2nr('0x67890', flags, {len = 7, num = 424080, unum = 424080, pre = hex}, 0)
|
||||
test_vim_str2nr('0xABCDEF', flags, {len = 8, num = 11259375, unum = 11259375, pre = hex}, 0)
|
||||
test_vim_str2nr('0xabcdef', flags, {len = 8, num = 11259375, unum = 11259375, pre = hex}, 0)
|
||||
test_vim_str2nr('0x12345', flags, { len = 7, num = 74565, unum = 74565, pre = hex }, 0)
|
||||
test_vim_str2nr('0x67890', flags, { len = 7, num = 424080, unum = 424080, pre = hex }, 0)
|
||||
test_vim_str2nr('0xABCDEF', flags, { len = 8, num = 11259375, unum = 11259375, pre = hex }, 0)
|
||||
test_vim_str2nr('0xabcdef', flags, { len = 8, num = 11259375, unum = 11259375, pre = hex }, 0)
|
||||
|
||||
test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 0)
|
||||
test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr( '0x101', flags, {len = 0}, 2)
|
||||
test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
|
||||
test_vim_str2nr( '0x101', flags, {len = 3, num = 1, unum = 1, pre = hex}, 3)
|
||||
test_vim_str2nr( '0x101', flags, {len = 4, num = 16, unum = 16, pre = hex}, 4)
|
||||
test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 5)
|
||||
test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 6)
|
||||
test_vim_str2nr('0x101', flags, { len = 5, num = 257, unum = 257, pre = hex }, 0)
|
||||
test_vim_str2nr('0x101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('0x101', flags, { len = 0 }, 2)
|
||||
test_vim_str2nr('0x101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
|
||||
test_vim_str2nr('0x101', flags, { len = 3, num = 1, unum = 1, pre = hex }, 3)
|
||||
test_vim_str2nr('0x101', flags, { len = 4, num = 16, unum = 16, pre = hex }, 4)
|
||||
test_vim_str2nr('0x101', flags, { len = 5, num = 257, unum = 257, pre = hex }, 5)
|
||||
test_vim_str2nr('0x101', flags, { len = 5, num = 257, unum = 257, pre = hex }, 6)
|
||||
|
||||
test_vim_str2nr( '0x101G', flags, {len = 0}, 0)
|
||||
test_vim_str2nr( '0x101G', flags, {len = 0}, 6)
|
||||
test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 0, false)
|
||||
test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 6, false)
|
||||
test_vim_str2nr('0x101G', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('0x101G', flags, { len = 0 }, 6)
|
||||
test_vim_str2nr('0x101G', flags, { len = 5, num = 257, unum = 257, pre = hex }, 0, false)
|
||||
test_vim_str2nr('0x101G', flags, { len = 5, num = 257, unum = 257, pre = hex }, 6, false)
|
||||
|
||||
test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 0)
|
||||
test_vim_str2nr('-0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0x101', flags, {len = 0}, 3)
|
||||
test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
|
||||
test_vim_str2nr('-0x101', flags, {len = 4, num = -1, unum = 1, pre = hex}, 4)
|
||||
test_vim_str2nr('-0x101', flags, {len = 5, num = -16, unum = 16, pre = hex}, 5)
|
||||
test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 6)
|
||||
test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 7)
|
||||
test_vim_str2nr('-0x101', flags, { len = 6, num = -257, unum = 257, pre = hex }, 0)
|
||||
test_vim_str2nr('-0x101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0x101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0x101', flags, { len = 0 }, 3)
|
||||
test_vim_str2nr('-0x101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
|
||||
test_vim_str2nr('-0x101', flags, { len = 4, num = -1, unum = 1, pre = hex }, 4)
|
||||
test_vim_str2nr('-0x101', flags, { len = 5, num = -16, unum = 16, pre = hex }, 5)
|
||||
test_vim_str2nr('-0x101', flags, { len = 6, num = -257, unum = 257, pre = hex }, 6)
|
||||
test_vim_str2nr('-0x101', flags, { len = 6, num = -257, unum = 257, pre = hex }, 7)
|
||||
|
||||
test_vim_str2nr('-0x101G', flags, {len = 0}, 0)
|
||||
test_vim_str2nr('-0x101G', flags, {len = 0}, 7)
|
||||
test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 0, false)
|
||||
test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 7, false)
|
||||
test_vim_str2nr('-0x101G', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('-0x101G', flags, { len = 0 }, 7)
|
||||
test_vim_str2nr('-0x101G', flags, { len = 6, num = -257, unum = 257, pre = hex }, 0, false)
|
||||
test_vim_str2nr('-0x101G', flags, { len = 6, num = -257, unum = 257, pre = hex }, 7, false)
|
||||
|
||||
test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0)
|
||||
test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr( '0X101', flags, {len = 0}, 2)
|
||||
test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
|
||||
test_vim_str2nr( '0X101', flags, {len = 3, num = 1, unum = 1, pre = HEX}, 3)
|
||||
test_vim_str2nr( '0X101', flags, {len = 4, num = 16, unum = 16, pre = HEX}, 4)
|
||||
test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 5)
|
||||
test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6)
|
||||
test_vim_str2nr('0X101', flags, { len = 5, num = 257, unum = 257, pre = HEX }, 0)
|
||||
test_vim_str2nr('0X101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('0X101', flags, { len = 0 }, 2)
|
||||
test_vim_str2nr('0X101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
|
||||
test_vim_str2nr('0X101', flags, { len = 3, num = 1, unum = 1, pre = HEX }, 3)
|
||||
test_vim_str2nr('0X101', flags, { len = 4, num = 16, unum = 16, pre = HEX }, 4)
|
||||
test_vim_str2nr('0X101', flags, { len = 5, num = 257, unum = 257, pre = HEX }, 5)
|
||||
test_vim_str2nr('0X101', flags, { len = 5, num = 257, unum = 257, pre = HEX }, 6)
|
||||
|
||||
test_vim_str2nr( '0X101G', flags, {len = 0}, 0)
|
||||
test_vim_str2nr( '0X101G', flags, {len = 0}, 6)
|
||||
test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0, false)
|
||||
test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6, false)
|
||||
test_vim_str2nr('0X101G', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('0X101G', flags, { len = 0 }, 6)
|
||||
test_vim_str2nr('0X101G', flags, { len = 5, num = 257, unum = 257, pre = HEX }, 0, false)
|
||||
test_vim_str2nr('0X101G', flags, { len = 5, num = 257, unum = 257, pre = HEX }, 6, false)
|
||||
|
||||
test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0)
|
||||
test_vim_str2nr('-0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0X101', flags, {len = 0}, 3)
|
||||
test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
|
||||
test_vim_str2nr('-0X101', flags, {len = 4, num = -1, unum = 1, pre = HEX}, 4)
|
||||
test_vim_str2nr('-0X101', flags, {len = 5, num = -16, unum = 16, pre = HEX}, 5)
|
||||
test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 6)
|
||||
test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7)
|
||||
test_vim_str2nr('-0X101', flags, { len = 6, num = -257, unum = 257, pre = HEX }, 0)
|
||||
test_vim_str2nr('-0X101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
|
||||
test_vim_str2nr('-0X101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
|
||||
test_vim_str2nr('-0X101', flags, { len = 0 }, 3)
|
||||
test_vim_str2nr('-0X101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
|
||||
test_vim_str2nr('-0X101', flags, { len = 4, num = -1, unum = 1, pre = HEX }, 4)
|
||||
test_vim_str2nr('-0X101', flags, { len = 5, num = -16, unum = 16, pre = HEX }, 5)
|
||||
test_vim_str2nr('-0X101', flags, { len = 6, num = -257, unum = 257, pre = HEX }, 6)
|
||||
test_vim_str2nr('-0X101', flags, { len = 6, num = -257, unum = 257, pre = HEX }, 7)
|
||||
|
||||
test_vim_str2nr('-0X101G', flags, {len = 0}, 0)
|
||||
test_vim_str2nr('-0X101G', flags, {len = 0}, 7)
|
||||
test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0, false)
|
||||
test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7, false)
|
||||
test_vim_str2nr('-0X101G', flags, { len = 0 }, 0)
|
||||
test_vim_str2nr('-0X101G', flags, { len = 0 }, 7)
|
||||
test_vim_str2nr('-0X101G', flags, { len = 6, num = -257, unum = 257, pre = HEX }, 0, false)
|
||||
test_vim_str2nr('-0X101G', flags, { len = 6, num = -257, unum = 257, pre = HEX }, 7, false)
|
||||
|
||||
if flags > lib.STR2NR_FORCE then
|
||||
test_vim_str2nr('-101', flags, {len = 4, num = -257, unum = 257, pre = 0}, 0)
|
||||
test_vim_str2nr('-101', flags, { len = 4, num = -257, unum = 257, pre = 0 }, 0)
|
||||
end
|
||||
end
|
||||
end)
|
||||
-- Test_str2nr() in test_functions.vim already tests normal usage
|
||||
itp('works with weirdly quoted numbers', function()
|
||||
local flags = lib.STR2NR_DEC + lib.STR2NR_QUOTE
|
||||
test_vim_str2nr("'027", flags, {len = 0}, 0)
|
||||
test_vim_str2nr("'027", flags, {len = 0}, 0, false)
|
||||
test_vim_str2nr("1'2'3'4", flags, {len = 7, num = 1234, unum = 1234, pre = 0}, 0)
|
||||
test_vim_str2nr("'027", flags, { len = 0 }, 0)
|
||||
test_vim_str2nr("'027", flags, { len = 0 }, 0, false)
|
||||
test_vim_str2nr("1'2'3'4", flags, { len = 7, num = 1234, unum = 1234, pre = 0 }, 0)
|
||||
|
||||
-- counter-intuitive, but like Vim, strict=true should partially accept
|
||||
-- these: (' and - are not alphanumeric)
|
||||
test_vim_str2nr("7''331", flags, {len = 1, num = 7, unum = 7, pre = 0}, 0)
|
||||
test_vim_str2nr("123'x4", flags, {len = 3, num = 123, unum = 123, pre = 0}, 0)
|
||||
test_vim_str2nr("1337'", flags, {len = 4, num = 1337, unum = 1337, pre = 0}, 0)
|
||||
test_vim_str2nr("-'", flags, {len = 1, num = 0, unum = 0, pre = 0}, 0)
|
||||
test_vim_str2nr("7''331", flags, { len = 1, num = 7, unum = 7, pre = 0 }, 0)
|
||||
test_vim_str2nr("123'x4", flags, { len = 3, num = 123, unum = 123, pre = 0 }, 0)
|
||||
test_vim_str2nr("1337'", flags, { len = 4, num = 1337, unum = 1337, pre = 0 }, 0)
|
||||
test_vim_str2nr("-'", flags, { len = 1, num = 0, unum = 0, pre = 0 }, 0)
|
||||
|
||||
flags = lib.STR2NR_HEX + lib.STR2NR_QUOTE
|
||||
local hex = ('x'):byte()
|
||||
test_vim_str2nr("0x'abcd", flags, {len = 0}, 0)
|
||||
test_vim_str2nr("0x'abcd", flags, {len = 1, num = 0, unum = 0, pre = 0}, 0, false)
|
||||
test_vim_str2nr("0xab''cd", flags, {len = 4, num = 171, unum = 171, pre = hex}, 0)
|
||||
test_vim_str2nr("0x'abcd", flags, { len = 0 }, 0)
|
||||
test_vim_str2nr("0x'abcd", flags, { len = 1, num = 0, unum = 0, pre = 0 }, 0, false)
|
||||
test_vim_str2nr("0xab''cd", flags, { len = 4, num = 171, unum = 171, pre = hex }, 0)
|
||||
end)
|
||||
end)
|
||||
|
@ -6,9 +6,13 @@ local eq = helpers.eq
|
||||
local neq = helpers.neq
|
||||
local ffi = helpers.ffi
|
||||
|
||||
local decode = cimport('./src/nvim/eval/decode.h', './src/nvim/eval/typval.h',
|
||||
'./src/nvim/globals.h', './src/nvim/memory.h',
|
||||
'./src/nvim/message.h')
|
||||
local decode = cimport(
|
||||
'./src/nvim/eval/decode.h',
|
||||
'./src/nvim/eval/typval.h',
|
||||
'./src/nvim/globals.h',
|
||||
'./src/nvim/memory.h',
|
||||
'./src/nvim/message.h'
|
||||
)
|
||||
|
||||
describe('json_decode_string()', function()
|
||||
local char = function(c)
|
||||
@ -16,7 +20,7 @@ describe('json_decode_string()', function()
|
||||
end
|
||||
|
||||
itp('does not overflow when running with `n…`, `t…`, `f…`', function()
|
||||
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
|
||||
local rettv = ffi.new('typval_T', { v_type = decode.VAR_UNKNOWN })
|
||||
decode.emsg_silent = 1
|
||||
-- This will not crash, but if `len` argument will be ignored it will parse
|
||||
-- `null` as `null` and if not it will parse `null` as `n`.
|
||||
@ -43,7 +47,7 @@ describe('json_decode_string()', function()
|
||||
end)
|
||||
|
||||
itp('does not overflow and crash when running with `n`, `t`, `f`', function()
|
||||
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
|
||||
local rettv = ffi.new('typval_T', { v_type = decode.VAR_UNKNOWN })
|
||||
decode.emsg_silent = 1
|
||||
eq(0, decode.json_decode_string(char('n'), 1, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
@ -54,7 +58,7 @@ describe('json_decode_string()', function()
|
||||
end)
|
||||
|
||||
itp('does not overflow when running with `"…`', function()
|
||||
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
|
||||
local rettv = ffi.new('typval_T', { v_type = decode.VAR_UNKNOWN })
|
||||
decode.emsg_silent = 1
|
||||
eq(0, decode.json_decode_string('"t"', 2, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
@ -63,7 +67,7 @@ describe('json_decode_string()', function()
|
||||
end)
|
||||
|
||||
local check_failure = function(s, len, msg)
|
||||
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
|
||||
local rettv = ffi.new('typval_T', { v_type = decode.VAR_UNKNOWN })
|
||||
eq(0, decode.json_decode_string(s, len, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
neq(nil, decode.last_msg_hist)
|
||||
@ -74,8 +78,7 @@ describe('json_decode_string()', function()
|
||||
collectgarbage('restart')
|
||||
check_failure(']test', 1, 'E474: No container to close: ]')
|
||||
check_failure('[}test', 2, 'E474: Closing list with curly bracket: }')
|
||||
check_failure('{]test', 2,
|
||||
'E474: Closing dictionary with square bracket: ]')
|
||||
check_failure('{]test', 2, 'E474: Closing dictionary with square bracket: ]')
|
||||
check_failure('[1,]test', 4, 'E474: Trailing comma: ]')
|
||||
check_failure('{"1":}test', 6, 'E474: Expected value after colon: }')
|
||||
check_failure('{"1"}test', 5, 'E474: Expected value: }')
|
||||
@ -93,16 +96,20 @@ describe('json_decode_string()', function()
|
||||
check_failure('ttest', 1, 'E474: Expected true: t')
|
||||
check_failure('ftest', 1, 'E474: Expected false: f')
|
||||
check_failure('"\\test', 2, 'E474: Unfinished escape sequence: "\\')
|
||||
check_failure('"\\u"test', 4,
|
||||
'E474: Unfinished unicode escape sequence: "\\u"')
|
||||
check_failure('"\\uXXXX"est', 8,
|
||||
'E474: Expected four hex digits after \\u: \\uXXXX"')
|
||||
check_failure('"\\u"test', 4, 'E474: Unfinished unicode escape sequence: "\\u"')
|
||||
check_failure('"\\uXXXX"est', 8, 'E474: Expected four hex digits after \\u: \\uXXXX"')
|
||||
check_failure('"\\?"test', 4, 'E474: Unknown escape sequence: \\?"')
|
||||
check_failure(
|
||||
'"\t"test', 3,
|
||||
'E474: ASCII control characters cannot be present inside string: \t"')
|
||||
'"\t"test',
|
||||
3,
|
||||
'E474: ASCII control characters cannot be present inside string: \t"'
|
||||
)
|
||||
check_failure('"\194"test', 3, 'E474: Only UTF-8 strings allowed: \194"')
|
||||
check_failure('"\252\144\128\128\128\128"test', 8, 'E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \252\144\128\128\128\128"')
|
||||
check_failure(
|
||||
'"\252\144\128\128\128\128"test',
|
||||
8,
|
||||
'E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \252\144\128\128\128\128"'
|
||||
)
|
||||
check_failure('"test', 1, 'E474: Expected string end: "')
|
||||
check_failure('-test', 1, 'E474: Missing number after minus sign: -')
|
||||
check_failure('-1.test', 3, 'E474: Missing number after decimal dot: -1.')
|
||||
@ -117,7 +124,7 @@ describe('json_decode_string()', function()
|
||||
end)
|
||||
|
||||
itp('does not overflow and crash when running with `"`', function()
|
||||
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
|
||||
local rettv = ffi.new('typval_T', { v_type = decode.VAR_UNKNOWN })
|
||||
decode.emsg_silent = 1
|
||||
eq(0, decode.json_decode_string(char('"'), 1, rettv))
|
||||
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||
|
@ -22,80 +22,83 @@ describe('encode_list_write()', function()
|
||||
itp('writes empty string', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, ''))
|
||||
eq({[type_key]=list_type}, lst2tbl(l))
|
||||
eq({ [type_key] = list_type }, lst2tbl(l))
|
||||
end)
|
||||
|
||||
itp('writes ASCII string literal with printable characters', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, 'abc'))
|
||||
eq({'abc'}, lst2tbl(l))
|
||||
eq({ 'abc' }, lst2tbl(l))
|
||||
end)
|
||||
|
||||
itp('writes string starting with NL', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\nabc'))
|
||||
eq({null_string, 'abc'}, lst2tbl(l))
|
||||
eq({ null_string, 'abc' }, lst2tbl(l))
|
||||
end)
|
||||
|
||||
itp('writes string starting with NL twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\nabc'))
|
||||
eq({null_string, 'abc'}, lst2tbl(l))
|
||||
eq({ null_string, 'abc' }, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\nabc'))
|
||||
eq({null_string, 'abc', 'abc'}, lst2tbl(l))
|
||||
eq({ null_string, 'abc', 'abc' }, lst2tbl(l))
|
||||
end)
|
||||
|
||||
itp('writes string ending with NL', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, 'abc\n'))
|
||||
eq({'abc', null_string}, lst2tbl(l))
|
||||
eq({ 'abc', null_string }, lst2tbl(l))
|
||||
end)
|
||||
|
||||
itp('writes string ending with NL twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, 'abc\n'))
|
||||
eq({'abc', null_string}, lst2tbl(l))
|
||||
eq({ 'abc', null_string }, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, 'abc\n'))
|
||||
eq({'abc', 'abc', null_string}, lst2tbl(l))
|
||||
eq({ 'abc', 'abc', null_string }, lst2tbl(l))
|
||||
end)
|
||||
|
||||
itp('writes string starting, ending and containing NL twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\na\nb\n'))
|
||||
eq({null_string, 'a', 'b', null_string}, lst2tbl(l))
|
||||
eq({ null_string, 'a', 'b', null_string }, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\na\nb\n'))
|
||||
eq({null_string, 'a', 'b', null_string, 'a', 'b', null_string}, lst2tbl(l))
|
||||
eq({ null_string, 'a', 'b', null_string, 'a', 'b', null_string }, lst2tbl(l))
|
||||
end)
|
||||
|
||||
itp('writes string starting, ending and containing NUL with NL between twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\0\n\0\n\0'))
|
||||
eq({'\n', '\n', '\n'}, lst2tbl(l))
|
||||
eq({ '\n', '\n', '\n' }, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\0\n\0\n\0'))
|
||||
eq({'\n', '\n', '\n\n', '\n', '\n'}, lst2tbl(l))
|
||||
eq({ '\n', '\n', '\n\n', '\n', '\n' }, lst2tbl(l))
|
||||
end)
|
||||
|
||||
itp('writes string starting, ending and containing NL with NUL between twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\n\0\n\0\n'))
|
||||
eq({null_string, '\n', '\n', null_string}, lst2tbl(l))
|
||||
eq({ null_string, '\n', '\n', null_string }, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\n\0\n\0\n'))
|
||||
eq({null_string, '\n', '\n', null_string, '\n', '\n', null_string}, lst2tbl(l))
|
||||
eq({ null_string, '\n', '\n', null_string, '\n', '\n', null_string }, lst2tbl(l))
|
||||
end)
|
||||
|
||||
itp('writes string containing a single NL twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\n'))
|
||||
eq({null_string, null_string}, lst2tbl(l))
|
||||
eq({ null_string, null_string }, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\n'))
|
||||
eq({null_string, null_string, null_string}, lst2tbl(l))
|
||||
eq({ null_string, null_string, null_string }, lst2tbl(l))
|
||||
end)
|
||||
|
||||
itp('writes string containing a few NLs twice', function()
|
||||
local l = list()
|
||||
eq(0, encode_list_write(l, '\n\n\n'))
|
||||
eq({null_string, null_string, null_string, null_string}, lst2tbl(l))
|
||||
eq({ null_string, null_string, null_string, null_string }, lst2tbl(l))
|
||||
eq(0, encode_list_write(l, '\n\n\n'))
|
||||
eq({null_string, null_string, null_string, null_string, null_string, null_string, null_string}, lst2tbl(l))
|
||||
eq(
|
||||
{ null_string, null_string, null_string, null_string, null_string, null_string, null_string },
|
||||
lst2tbl(l)
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
@ -6,21 +6,25 @@ local to_cstr = helpers.to_cstr
|
||||
local ffi = helpers.ffi
|
||||
local eq = helpers.eq
|
||||
|
||||
local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h',
|
||||
'./src/nvim/hashtab.h', './src/nvim/memory.h')
|
||||
local eval = cimport(
|
||||
'./src/nvim/eval.h',
|
||||
'./src/nvim/eval/typval.h',
|
||||
'./src/nvim/hashtab.h',
|
||||
'./src/nvim/memory.h'
|
||||
)
|
||||
|
||||
local null_string = {[true]='NULL string'}
|
||||
local null_list = {[true]='NULL list'}
|
||||
local null_dict = {[true]='NULL dict'}
|
||||
local type_key = {[true]='type key'}
|
||||
local locks_key = {[true]='locks key'}
|
||||
local list_type = {[true]='list type'}
|
||||
local dict_type = {[true]='dict type'}
|
||||
local func_type = {[true]='func type'}
|
||||
local int_type = {[true]='int type'}
|
||||
local flt_type = {[true]='flt type'}
|
||||
local null_string = { [true] = 'NULL string' }
|
||||
local null_list = { [true] = 'NULL list' }
|
||||
local null_dict = { [true] = 'NULL dict' }
|
||||
local type_key = { [true] = 'type key' }
|
||||
local locks_key = { [true] = 'locks key' }
|
||||
local list_type = { [true] = 'list type' }
|
||||
local dict_type = { [true] = 'dict type' }
|
||||
local func_type = { [true] = 'func type' }
|
||||
local int_type = { [true] = 'int type' }
|
||||
local flt_type = { [true] = 'flt type' }
|
||||
|
||||
local nil_value = {[true]='nil'}
|
||||
local nil_value = { [true] = 'nil' }
|
||||
|
||||
local lua2typvalt
|
||||
|
||||
@ -35,11 +39,13 @@ end
|
||||
|
||||
local function li_alloc(nogc)
|
||||
local gcfunc = tv_list_item_free
|
||||
if nogc then gcfunc = nil end
|
||||
if nogc then
|
||||
gcfunc = nil
|
||||
end
|
||||
local li = ffi.gc(tv_list_item_alloc(), gcfunc)
|
||||
li.li_next = nil
|
||||
li.li_prev = nil
|
||||
li.li_tv = {v_type=eval.VAR_UNKNOWN, v_lock=eval.VAR_UNLOCKED}
|
||||
li.li_tv = { v_type = eval.VAR_UNKNOWN, v_lock = eval.VAR_UNLOCKED }
|
||||
return li
|
||||
end
|
||||
|
||||
@ -121,11 +127,11 @@ local function partial2lua(pt, processed)
|
||||
end
|
||||
end
|
||||
return {
|
||||
[type_key]=func_type,
|
||||
value=value,
|
||||
auto=auto,
|
||||
args=argv,
|
||||
dict=dict,
|
||||
[type_key] = func_type,
|
||||
value = value,
|
||||
auto = auto,
|
||||
args = argv,
|
||||
dict = dict,
|
||||
}
|
||||
end
|
||||
|
||||
@ -148,7 +154,7 @@ local function typvalt2lua_tab_init()
|
||||
})[tonumber(t.vval.v_special)]
|
||||
end,
|
||||
[tonumber(eval.VAR_NUMBER)] = function(t)
|
||||
return {[type_key]=int_type, value=tonumber(t.vval.v_number)}
|
||||
return { [type_key] = int_type, value = tonumber(t.vval.v_number) }
|
||||
end,
|
||||
[tonumber(eval.VAR_FLOAT)] = function(t)
|
||||
return tonumber(t.vval.v_float)
|
||||
@ -168,7 +174,7 @@ local function typvalt2lua_tab_init()
|
||||
return dct2tbl(t.vval.v_dict, processed)
|
||||
end,
|
||||
[tonumber(eval.VAR_FUNC)] = function(t, processed)
|
||||
return {[type_key]=func_type, value=typvalt2lua_tab[eval.VAR_STRING](t, processed or {})}
|
||||
return { [type_key] = func_type, value = typvalt2lua_tab[eval.VAR_STRING](t, processed or {}) }
|
||||
end,
|
||||
[tonumber(eval.VAR_PARTIAL)] = function(t, processed)
|
||||
local p_key = ptr2key(t)
|
||||
@ -182,15 +188,17 @@ end
|
||||
|
||||
typvalt2lua = function(t, processed)
|
||||
typvalt2lua_tab_init()
|
||||
return ((typvalt2lua_tab[tonumber(t.v_type)] or function(t_inner)
|
||||
return (
|
||||
(typvalt2lua_tab[tonumber(t.v_type)] or function(t_inner)
|
||||
assert(false, 'Converting ' .. tonumber(t_inner.v_type) .. ' was not implemented yet')
|
||||
end)(t, processed or {}))
|
||||
end)(t, processed or {})
|
||||
)
|
||||
end
|
||||
|
||||
local function list_iter(l)
|
||||
local init_s = {
|
||||
idx=0,
|
||||
li=l.lv_first,
|
||||
idx = 0,
|
||||
li = l.lv_first,
|
||||
}
|
||||
local function f(s, _)
|
||||
-- (listitem_T *) NULL is equal to nil, but yet it is not false.
|
||||
@ -222,7 +230,7 @@ lst2tbl = function(l, processed)
|
||||
if processed[p_key] then
|
||||
return processed[p_key]
|
||||
end
|
||||
local ret = {[type_key]=list_type}
|
||||
local ret = { [type_key] = list_type }
|
||||
processed[p_key] = ret
|
||||
for i, li in list_iter(l) do
|
||||
ret[i] = typvalt2lua(li.li_tv, processed)
|
||||
@ -238,11 +246,13 @@ local hi_key_removed = nil
|
||||
local function dict_iter(d, return_hi)
|
||||
hi_key_removed = hi_key_removed or eval._hash_key_removed()
|
||||
local init_s = {
|
||||
todo=d.dv_hashtab.ht_used,
|
||||
hi=d.dv_hashtab.ht_array,
|
||||
todo = d.dv_hashtab.ht_used,
|
||||
hi = d.dv_hashtab.ht_array,
|
||||
}
|
||||
local function f(s, _)
|
||||
if s.todo == 0 then return nil end
|
||||
if s.todo == 0 then
|
||||
return nil
|
||||
end
|
||||
while s.todo > 0 do
|
||||
if s.hi.hi_key ~= nil and s.hi.hi_key ~= hi_key_removed then
|
||||
local key = ffi.string(s.hi.hi_key)
|
||||
@ -250,8 +260,7 @@ local function dict_iter(d, return_hi)
|
||||
if return_hi then
|
||||
ret = s.hi
|
||||
else
|
||||
ret = ffi.cast('dictitem_T*',
|
||||
s.hi.hi_key - ffi.offsetof('dictitem_T', 'di_key'))
|
||||
ret = ffi.cast('dictitem_T*', s.hi.hi_key - ffi.offsetof('dictitem_T', 'di_key'))
|
||||
end
|
||||
s.todo = s.todo - 1
|
||||
s.hi = s.hi + 1
|
||||
@ -269,7 +278,7 @@ local function first_di(d)
|
||||
end
|
||||
|
||||
local function dict_items(d)
|
||||
local ret = {[0]=0}
|
||||
local ret = { [0] = 0 }
|
||||
for k, hi in dict_iter(d) do
|
||||
ret[k] = hi
|
||||
ret[0] = ret[0] + 1
|
||||
@ -301,12 +310,12 @@ local typvalt = function(typ, vval)
|
||||
elseif type(typ) == 'string' then
|
||||
typ = eval[typ]
|
||||
end
|
||||
return ffi.gc(ffi.new('typval_T', {v_type=typ, vval=vval}), eval.tv_clear)
|
||||
return ffi.gc(ffi.new('typval_T', { v_type = typ, vval = vval }), eval.tv_clear)
|
||||
end
|
||||
|
||||
local lua2typvalt_type_tab = {
|
||||
[int_type] = function(l, _)
|
||||
return typvalt(eval.VAR_NUMBER, {v_number=l.value})
|
||||
return typvalt(eval.VAR_NUMBER, { v_number = l.value })
|
||||
end,
|
||||
[flt_type] = function(l, processed)
|
||||
return lua2typvalt(l.value, processed)
|
||||
@ -314,31 +323,34 @@ local lua2typvalt_type_tab = {
|
||||
[list_type] = function(l, processed)
|
||||
if processed[l] then
|
||||
processed[l].lv_refcount = processed[l].lv_refcount + 1
|
||||
return typvalt(eval.VAR_LIST, {v_list=processed[l]})
|
||||
return typvalt(eval.VAR_LIST, { v_list = processed[l] })
|
||||
end
|
||||
local lst = populate_list(eval.tv_list_alloc(#l), l, processed)
|
||||
return typvalt(eval.VAR_LIST, {v_list=lst})
|
||||
return typvalt(eval.VAR_LIST, { v_list = lst })
|
||||
end,
|
||||
[dict_type] = function(l, processed)
|
||||
if processed[l] then
|
||||
processed[l].dv_refcount = processed[l].dv_refcount + 1
|
||||
return typvalt(eval.VAR_DICT, {v_dict=processed[l]})
|
||||
return typvalt(eval.VAR_DICT, { v_dict = processed[l] })
|
||||
end
|
||||
local dct = populate_dict(eval.tv_dict_alloc(), l, processed)
|
||||
return typvalt(eval.VAR_DICT, {v_dict=dct})
|
||||
return typvalt(eval.VAR_DICT, { v_dict = dct })
|
||||
end,
|
||||
[func_type] = function(l, processed)
|
||||
if processed[l] then
|
||||
processed[l].pt_refcount = processed[l].pt_refcount + 1
|
||||
return typvalt(eval.VAR_PARTIAL, {v_partial=processed[l]})
|
||||
return typvalt(eval.VAR_PARTIAL, { v_partial = processed[l] })
|
||||
end
|
||||
if l.args or l.dict then
|
||||
local pt = populate_partial(ffi.gc(ffi.cast('partial_T*',
|
||||
eval.xcalloc(1, ffi.sizeof('partial_T'))), nil), l, processed)
|
||||
return typvalt(eval.VAR_PARTIAL, {v_partial=pt})
|
||||
local pt = populate_partial(
|
||||
ffi.gc(ffi.cast('partial_T*', eval.xcalloc(1, ffi.sizeof('partial_T'))), nil),
|
||||
l,
|
||||
processed
|
||||
)
|
||||
return typvalt(eval.VAR_PARTIAL, { v_partial = pt })
|
||||
else
|
||||
return typvalt(eval.VAR_FUNC, {
|
||||
v_string=eval.xmemdupz(to_cstr(l.value), #l.value)
|
||||
v_string = eval.xmemdupz(to_cstr(l.value), #l.value),
|
||||
})
|
||||
end
|
||||
end,
|
||||
@ -349,12 +361,12 @@ local special_vals = nil
|
||||
lua2typvalt = function(l, processed)
|
||||
if not special_vals then
|
||||
special_vals = {
|
||||
[null_string] = {'VAR_STRING', {v_string=ffi.cast('char*', nil)}},
|
||||
[null_list] = {'VAR_LIST', {v_list=ffi.cast('list_T*', nil)}},
|
||||
[null_dict] = {'VAR_DICT', {v_dict=ffi.cast('dict_T*', nil)}},
|
||||
[nil_value] = {'VAR_SPECIAL', {v_special=eval.kSpecialVarNull}},
|
||||
[true] = {'VAR_BOOL', {v_bool=eval.kBoolVarTrue}},
|
||||
[false] = {'VAR_BOOL', {v_bool=eval.kBoolVarFalse}},
|
||||
[null_string] = { 'VAR_STRING', { v_string = ffi.cast('char*', nil) } },
|
||||
[null_list] = { 'VAR_LIST', { v_list = ffi.cast('list_T*', nil) } },
|
||||
[null_dict] = { 'VAR_DICT', { v_dict = ffi.cast('dict_T*', nil) } },
|
||||
[nil_value] = { 'VAR_SPECIAL', { v_special = eval.kSpecialVarNull } },
|
||||
[true] = { 'VAR_BOOL', { v_bool = eval.kBoolVarTrue } },
|
||||
[false] = { 'VAR_BOOL', { v_bool = eval.kBoolVarFalse } },
|
||||
}
|
||||
|
||||
for k, v in pairs(special_vals) do
|
||||
@ -382,9 +394,9 @@ lua2typvalt = function(l, processed)
|
||||
end
|
||||
end
|
||||
elseif type(l) == 'number' then
|
||||
return typvalt(eval.VAR_FLOAT, {v_float=l})
|
||||
return typvalt(eval.VAR_FLOAT, { v_float = l })
|
||||
elseif type(l) == 'string' then
|
||||
return typvalt(eval.VAR_STRING, {v_string=eval.xmemdupz(to_cstr(l), #l)})
|
||||
return typvalt(eval.VAR_STRING, { v_string = eval.xmemdupz(to_cstr(l), #l) })
|
||||
elseif type(l) == 'cdata' then
|
||||
local tv = typvalt(eval.VAR_UNKNOWN)
|
||||
eval.tv_copy(l, tv)
|
||||
@ -408,43 +420,64 @@ local function alloc_len(len, get_ptr)
|
||||
end
|
||||
|
||||
local alloc_logging_helpers = {
|
||||
list = function(l) return {func='calloc', args={1, ffi.sizeof('list_T')}, ret=void(l)} end,
|
||||
li = function(li) return {func='malloc', args={ffi.sizeof('listitem_T')}, ret=void(li)} end,
|
||||
dict = function(d) return {func='calloc', args={1, ffi.sizeof('dict_T')}, ret=void(d)} end,
|
||||
list = function(l)
|
||||
return { func = 'calloc', args = { 1, ffi.sizeof('list_T') }, ret = void(l) }
|
||||
end,
|
||||
li = function(li)
|
||||
return { func = 'malloc', args = { ffi.sizeof('listitem_T') }, ret = void(li) }
|
||||
end,
|
||||
dict = function(d)
|
||||
return { func = 'calloc', args = { 1, ffi.sizeof('dict_T') }, ret = void(d) }
|
||||
end,
|
||||
di = function(di, size)
|
||||
size = alloc_len(size, function() return di.di_key end)
|
||||
return {func='malloc', args={ffi.offsetof('dictitem_T', 'di_key') + size + 1}, ret=void(di)}
|
||||
size = alloc_len(size, function()
|
||||
return di.di_key
|
||||
end)
|
||||
return {
|
||||
func = 'malloc',
|
||||
args = { ffi.offsetof('dictitem_T', 'di_key') + size + 1 },
|
||||
ret = void(di),
|
||||
}
|
||||
end,
|
||||
str = function(s, size)
|
||||
size = alloc_len(size, function() return s end)
|
||||
return {func='malloc', args={size + 1}, ret=void(s)}
|
||||
size = alloc_len(size, function()
|
||||
return s
|
||||
end)
|
||||
return { func = 'malloc', args = { size + 1 }, ret = void(s) }
|
||||
end,
|
||||
|
||||
dwatcher = function(w) return {func='malloc', args={ffi.sizeof('DictWatcher')}, ret=void(w)} end,
|
||||
dwatcher = function(w)
|
||||
return { func = 'malloc', args = { ffi.sizeof('DictWatcher') }, ret = void(w) }
|
||||
end,
|
||||
|
||||
freed = function(p) return {func='free', args={type(p) == 'table' and p or void(p)}} end,
|
||||
freed = function(p)
|
||||
return { func = 'free', args = { type(p) == 'table' and p or void(p) } }
|
||||
end,
|
||||
|
||||
-- lua_…: allocated by this file, not by some Neovim function
|
||||
lua_pt = function(pt) return {func='calloc', args={1, ffi.sizeof('partial_T')}, ret=void(pt)} end,
|
||||
lua_pt = function(pt)
|
||||
return { func = 'calloc', args = { 1, ffi.sizeof('partial_T') }, ret = void(pt) }
|
||||
end,
|
||||
lua_tvs = function(argv, argc)
|
||||
argc = alloc_len(argc)
|
||||
return {func='malloc', args={ffi.sizeof('typval_T')*argc}, ret=void(argv)}
|
||||
return { func = 'malloc', args = { ffi.sizeof('typval_T') * argc }, ret = void(argv) }
|
||||
end,
|
||||
}
|
||||
|
||||
local function int(n)
|
||||
return {[type_key]=int_type, value=n}
|
||||
return { [type_key] = int_type, value = n }
|
||||
end
|
||||
|
||||
local function list(...)
|
||||
return populate_list(ffi.gc(eval.tv_list_alloc(select('#', ...)),
|
||||
eval.tv_list_unref),
|
||||
{...}, {})
|
||||
return populate_list(
|
||||
ffi.gc(eval.tv_list_alloc(select('#', ...)), eval.tv_list_unref),
|
||||
{ ... },
|
||||
{}
|
||||
)
|
||||
end
|
||||
|
||||
local function dict(d)
|
||||
return populate_dict(ffi.gc(eval.tv_dict_alloc(), eval.tv_dict_free),
|
||||
d or {}, {})
|
||||
return populate_dict(ffi.gc(eval.tv_dict_alloc(), eval.tv_dict_free), d or {}, {})
|
||||
end
|
||||
|
||||
local callback2tbl_type_tab = nil
|
||||
@ -454,14 +487,16 @@ local function init_callback2tbl_type_tab()
|
||||
return
|
||||
end
|
||||
callback2tbl_type_tab = {
|
||||
[tonumber(eval.kCallbackNone)] = function(_) return {type='none'} end,
|
||||
[tonumber(eval.kCallbackNone)] = function(_)
|
||||
return { type = 'none' }
|
||||
end,
|
||||
[tonumber(eval.kCallbackFuncref)] = function(cb)
|
||||
return {type='fref', fref=ffi.string(cb.data.funcref)}
|
||||
return { type = 'fref', fref = ffi.string(cb.data.funcref) }
|
||||
end,
|
||||
[tonumber(eval.kCallbackPartial)] = function(cb)
|
||||
local lua_pt = partial2lua(cb.data.partial)
|
||||
return {type='pt', fref=ffi.string(lua_pt.value), pt=lua_pt}
|
||||
end
|
||||
return { type = 'pt', fref = ffi.string(lua_pt.value), pt = lua_pt }
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
@ -473,15 +508,18 @@ end
|
||||
local function tbl2callback(tbl)
|
||||
local ret = nil
|
||||
if tbl.type == 'none' then
|
||||
ret = ffi.new('Callback[1]', {{type=eval.kCallbackNone}})
|
||||
ret = ffi.new('Callback[1]', { { type = eval.kCallbackNone } })
|
||||
elseif tbl.type == 'fref' then
|
||||
ret = ffi.new('Callback[1]', {{type=eval.kCallbackFuncref,
|
||||
data={funcref=eval.xstrdup(tbl.fref)}}})
|
||||
ret = ffi.new(
|
||||
'Callback[1]',
|
||||
{ { type = eval.kCallbackFuncref, data = { funcref = eval.xstrdup(tbl.fref) } } }
|
||||
)
|
||||
elseif tbl.type == 'pt' then
|
||||
local pt = ffi.gc(ffi.cast('partial_T*',
|
||||
eval.xcalloc(1, ffi.sizeof('partial_T'))), nil)
|
||||
ret = ffi.new('Callback[1]', {{type=eval.kCallbackPartial,
|
||||
data={partial=populate_partial(pt, tbl.pt, {})}}})
|
||||
local pt = ffi.gc(ffi.cast('partial_T*', eval.xcalloc(1, ffi.sizeof('partial_T'))), nil)
|
||||
ret = ffi.new(
|
||||
'Callback[1]',
|
||||
{ { type = eval.kCallbackPartial, data = { partial = populate_partial(pt, tbl.pt, {}) } } }
|
||||
)
|
||||
else
|
||||
assert(false)
|
||||
end
|
||||
@ -495,24 +533,23 @@ local function dict_watchers(d)
|
||||
local qs = {}
|
||||
local key_patterns = {}
|
||||
while q ~= h do
|
||||
local qitem = ffi.cast('DictWatcher *',
|
||||
ffi.cast('char *', q) - ffi.offsetof('DictWatcher', 'node'))
|
||||
local qitem =
|
||||
ffi.cast('DictWatcher *', ffi.cast('char *', q) - ffi.offsetof('DictWatcher', 'node'))
|
||||
ret[#ret + 1] = {
|
||||
cb=callback2tbl(qitem.callback),
|
||||
pat=ffi.string(qitem.key_pattern, qitem.key_pattern_len),
|
||||
busy=qitem.busy,
|
||||
cb = callback2tbl(qitem.callback),
|
||||
pat = ffi.string(qitem.key_pattern, qitem.key_pattern_len),
|
||||
busy = qitem.busy,
|
||||
}
|
||||
qs[#qs + 1] = qitem
|
||||
key_patterns[#key_patterns + 1] = {qitem.key_pattern, qitem.key_pattern_len}
|
||||
key_patterns[#key_patterns + 1] = { qitem.key_pattern, qitem.key_pattern_len }
|
||||
q = q.next
|
||||
end
|
||||
return ret, qs, key_patterns
|
||||
end
|
||||
|
||||
local function eval0(expr)
|
||||
local tv = ffi.gc(ffi.new('typval_T', {v_type=eval.VAR_UNKNOWN}),
|
||||
eval.tv_clear)
|
||||
local evalarg = ffi.new('evalarg_T', {eval_flags = eval.EVAL_EVALUATE})
|
||||
local tv = ffi.gc(ffi.new('typval_T', { v_type = eval.VAR_UNKNOWN }), eval.tv_clear)
|
||||
local evalarg = ffi.new('evalarg_T', { eval_flags = eval.EVAL_EVALUATE })
|
||||
if eval.eval0(to_cstr(expr), tv, nil, evalarg) == 0 then
|
||||
return nil
|
||||
else
|
||||
@ -521,49 +558,49 @@ local function eval0(expr)
|
||||
end
|
||||
|
||||
return {
|
||||
int=int,
|
||||
int = int,
|
||||
|
||||
null_string=null_string,
|
||||
null_list=null_list,
|
||||
null_dict=null_dict,
|
||||
list_type=list_type,
|
||||
dict_type=dict_type,
|
||||
func_type=func_type,
|
||||
int_type=int_type,
|
||||
flt_type=flt_type,
|
||||
null_string = null_string,
|
||||
null_list = null_list,
|
||||
null_dict = null_dict,
|
||||
list_type = list_type,
|
||||
dict_type = dict_type,
|
||||
func_type = func_type,
|
||||
int_type = int_type,
|
||||
flt_type = flt_type,
|
||||
|
||||
nil_value=nil_value,
|
||||
nil_value = nil_value,
|
||||
|
||||
type_key=type_key,
|
||||
locks_key=locks_key,
|
||||
type_key = type_key,
|
||||
locks_key = locks_key,
|
||||
|
||||
list=list,
|
||||
dict=dict,
|
||||
lst2tbl=lst2tbl,
|
||||
dct2tbl=dct2tbl,
|
||||
list = list,
|
||||
dict = dict,
|
||||
lst2tbl = lst2tbl,
|
||||
dct2tbl = dct2tbl,
|
||||
|
||||
lua2typvalt=lua2typvalt,
|
||||
typvalt2lua=typvalt2lua,
|
||||
lua2typvalt = lua2typvalt,
|
||||
typvalt2lua = typvalt2lua,
|
||||
|
||||
typvalt=typvalt,
|
||||
typvalt = typvalt,
|
||||
|
||||
li_alloc=li_alloc,
|
||||
tv_list_item_free=tv_list_item_free,
|
||||
li_alloc = li_alloc,
|
||||
tv_list_item_free = tv_list_item_free,
|
||||
|
||||
dict_iter=dict_iter,
|
||||
list_iter=list_iter,
|
||||
first_di=first_di,
|
||||
dict_iter = dict_iter,
|
||||
list_iter = list_iter,
|
||||
first_di = first_di,
|
||||
|
||||
alloc_logging_helpers=alloc_logging_helpers,
|
||||
alloc_logging_helpers = alloc_logging_helpers,
|
||||
|
||||
list_items=list_items,
|
||||
dict_items=dict_items,
|
||||
list_items = list_items,
|
||||
dict_items = dict_items,
|
||||
|
||||
dict_watchers=dict_watchers,
|
||||
tbl2callback=tbl2callback,
|
||||
callback2tbl=callback2tbl,
|
||||
dict_watchers = dict_watchers,
|
||||
tbl2callback = tbl2callback,
|
||||
callback2tbl = callback2tbl,
|
||||
|
||||
eval0=eval0,
|
||||
eval0 = eval0,
|
||||
|
||||
empty_list = {[type_key]=list_type},
|
||||
empty_list = { [type_key] = list_type },
|
||||
}
|
||||
|
@ -8,8 +8,7 @@ local eq = helpers.eq
|
||||
|
||||
local eval0 = eval_helpers.eval0
|
||||
|
||||
local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h',
|
||||
'./src/nvim/memory.h')
|
||||
local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h', './src/nvim/memory.h')
|
||||
|
||||
describe('NULL typval_T', function()
|
||||
itp('is produced by $XXX_UNEXISTENT_VAR_XXX', function()
|
||||
|
@ -28,8 +28,8 @@ end)
|
||||
|
||||
describe('tv_clear()', function()
|
||||
itp('successfully frees all lists in [&l [1], *l, *l]', function()
|
||||
local l_inner = {1}
|
||||
local list = {l_inner, l_inner, l_inner}
|
||||
local l_inner = { 1 }
|
||||
local list = { l_inner, l_inner, l_inner }
|
||||
local list_tv = ffi.gc(lua2typvalt(list), nil)
|
||||
local list_p = list_tv.vval.v_list
|
||||
local lis = list_items(list_p)
|
||||
@ -55,8 +55,8 @@ describe('tv_clear()', function()
|
||||
})
|
||||
end)
|
||||
itp('successfully frees all lists in [&l [], *l, *l]', function()
|
||||
local l_inner = {[type_key]=list_type}
|
||||
local list = {l_inner, l_inner, l_inner}
|
||||
local l_inner = { [type_key] = list_type }
|
||||
local list = { l_inner, l_inner, l_inner }
|
||||
local list_tv = ffi.gc(lua2typvalt(list), nil)
|
||||
local list_p = list_tv.vval.v_list
|
||||
local lis = list_items(list_p)
|
||||
@ -80,7 +80,7 @@ describe('tv_clear()', function()
|
||||
end)
|
||||
itp('successfully frees all dictionaries in [&d {}, *d]', function()
|
||||
local d_inner = {}
|
||||
local list = {d_inner, d_inner}
|
||||
local list = { d_inner, d_inner }
|
||||
local list_tv = ffi.gc(lua2typvalt(list), nil)
|
||||
local list_p = list_tv.vval.v_list
|
||||
local lis = list_items(list_p)
|
||||
@ -101,8 +101,8 @@ describe('tv_clear()', function()
|
||||
})
|
||||
end)
|
||||
itp('successfully frees all dictionaries in [&d {a: 1}, *d]', function()
|
||||
local d_inner = {a=1}
|
||||
local list = {d_inner, d_inner}
|
||||
local d_inner = { a = 1 }
|
||||
local list = { d_inner, d_inner }
|
||||
local list_tv = ffi.gc(lua2typvalt(list), nil)
|
||||
local list_p = list_tv.vval.v_list
|
||||
local lis = list_items(list_p)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
--{:cimport, :internalize, :eq, :neq, :ffi, :lib, :cstr, :to_cstr} = require 'test.unit.helpers'
|
||||
|
||||
@ -7,18 +7,17 @@ local ffi = helpers.ffi
|
||||
local to_cstr = helpers.to_cstr
|
||||
local NULL = helpers.NULL
|
||||
|
||||
local fileio = helpers.cimport("./src/nvim/fileio.h")
|
||||
local fileio = helpers.cimport('./src/nvim/fileio.h')
|
||||
|
||||
describe('file_pat functions', function()
|
||||
describe('file_pat_to_reg_pat', function()
|
||||
|
||||
local file_pat_to_reg_pat = function(pat)
|
||||
local res = fileio.file_pat_to_reg_pat(to_cstr(pat), NULL, NULL, 0)
|
||||
return ffi.string(res)
|
||||
end
|
||||
|
||||
itp('returns ^path$ regex for literal path input', function()
|
||||
eq( '^path$', file_pat_to_reg_pat('path'))
|
||||
eq('^path$', file_pat_to_reg_pat('path'))
|
||||
end)
|
||||
|
||||
itp('does not prepend ^ when there is a starting glob (*)', function()
|
||||
@ -37,10 +36,12 @@ describe('file_pat functions', function()
|
||||
eq('^foo.bar$', file_pat_to_reg_pat('foo?bar'))
|
||||
end)
|
||||
|
||||
itp('replaces a glob (*) in the middle of a path with regex multiple any character (.*)',
|
||||
itp(
|
||||
'replaces a glob (*) in the middle of a path with regex multiple any character (.*)',
|
||||
function()
|
||||
eq('^foo.*bar$', file_pat_to_reg_pat('foo*bar'))
|
||||
end)
|
||||
end
|
||||
)
|
||||
|
||||
itp([[unescapes \? to ?]], function()
|
||||
eq('^foo?bar$', file_pat_to_reg_pat([[foo\?bar]]))
|
||||
|
@ -24,103 +24,145 @@ SOFTWARE. --]]
|
||||
-- work.
|
||||
-- see: http://lua-users.org/wiki/LpegRecipes
|
||||
|
||||
local lpeg = require "lpeg"
|
||||
local lpeg = require 'lpeg'
|
||||
|
||||
local C, P, R, S, V = lpeg.C, lpeg.P, lpeg.R, lpeg.S, lpeg.V
|
||||
local Carg, Cc, Cp, Ct = lpeg.Carg, lpeg.Cc, lpeg.Cp, lpeg.Ct
|
||||
|
||||
local tokens = P { "tokens";
|
||||
local tokens = P {
|
||||
'tokens',
|
||||
-- Comment of form /* ... */
|
||||
comment = Ct(P"/*" * C((V"newline" + (1 - P"*/"))^0) * P"*/" * Cc"comment"),
|
||||
comment = Ct(P '/*' * C((V 'newline' + (1 - P '*/')) ^ 0) * P '*/' * Cc 'comment'),
|
||||
|
||||
-- Single line comment
|
||||
line_comment = Ct(P"//" * C((1 - V"newline")^0) * Cc"comment_line"),
|
||||
line_comment = Ct(P '//' * C((1 - V 'newline') ^ 0) * Cc 'comment_line'),
|
||||
|
||||
-- Single platform independent line break which increments line number
|
||||
newline = (P"\r\n" + P"\n\r" + S"\r\n") * (Cp() * Carg(1)) / function(pos, state)
|
||||
newline = (P '\r\n' + P '\n\r' + S '\r\n') * (Cp() * Carg(1)) / function(pos, state)
|
||||
state.line = state.line + 1
|
||||
state.line_start = pos
|
||||
end,
|
||||
|
||||
-- Line continuation
|
||||
line_extend = Ct(C(P[[\]] * V"newline") * Cc"line_extend"),
|
||||
line_extend = Ct(C(P [[\]] * V 'newline') * Cc 'line_extend'),
|
||||
|
||||
-- Whitespace of any length (includes newlines)
|
||||
whitespace = Ct(C((S" \t" + V"newline")^1) * Cc"whitespace"),
|
||||
whitespace = Ct(C((S ' \t' + V 'newline') ^ 1) * Cc 'whitespace'),
|
||||
|
||||
-- Special form of #include with filename followed in angled brackets (matches 3 tokens)
|
||||
include = Ct(C(P"#include") * Cc"preprocessor") *
|
||||
Ct(C(S" \t"^1) * Cc"whitespace") *
|
||||
Ct(C(P"<" * (1 - P">")^1 * P">") * Cc"string"),
|
||||
include = Ct(C(P '#include') * Cc 'preprocessor') * Ct(C(S ' \t' ^ 1) * Cc 'whitespace') * Ct(
|
||||
C(P '<' * (1 - P '>') ^ 1 * P '>') * Cc 'string'
|
||||
),
|
||||
|
||||
-- Preprocessor instruction
|
||||
preprocessor = V"include" +
|
||||
Ct(C(P"#" * P" "^0 * ( P"define" + P"elif" + P"else" + P"endif" + P"#" +
|
||||
P"error" + P"ifdef" + P"ifndef" + P"if" + P"import" +
|
||||
P"include" + P"line" + P"pragma" + P"undef" + P"using" +
|
||||
P"pragma"
|
||||
) * #S" \r\n\t") * Cc"preprocessor"),
|
||||
preprocessor = V 'include'
|
||||
+ Ct(
|
||||
C(
|
||||
P '#'
|
||||
* P ' ' ^ 0
|
||||
* (P 'define' + P 'elif' + P 'else' + P 'endif' + P '#' + P 'error' + P 'ifdef' + P 'ifndef' + P 'if' + P 'import' + P 'include' + P 'line' + P 'pragma' + P 'undef' + P 'using' + P 'pragma')
|
||||
* #S ' \r\n\t'
|
||||
) * Cc 'preprocessor'
|
||||
),
|
||||
|
||||
-- Identifier of form [a-zA-Z_][a-zA-Z0-9_]*
|
||||
identifier = Ct(C(R("az","AZ","__") * R("09","az","AZ","__")^0) * Cc"identifier"),
|
||||
identifier = Ct(C(R('az', 'AZ', '__') * R('09', 'az', 'AZ', '__') ^ 0) * Cc 'identifier'),
|
||||
|
||||
-- Single character in a string
|
||||
sstring_char = R("\001&","([","]\255") + (P"\\" * S[[ntvbrfa\?'"0x]]),
|
||||
dstring_char = R("\001!","#[","]\255") + (P"\\" * S[[ntvbrfa\?'"0x]]),
|
||||
sstring_char = R('\001&', '([', ']\255') + (P '\\' * S [[ntvbrfa\?'"0x]]),
|
||||
dstring_char = R('\001!', '#[', ']\255') + (P '\\' * S [[ntvbrfa\?'"0x]]),
|
||||
|
||||
-- String literal
|
||||
string = Ct(C(P"'" * (V"sstring_char" + P'"')^0 * P"'" +
|
||||
P'"' * (V"dstring_char" + P"'")^0 * P'"') * Cc"string"),
|
||||
string = Ct(
|
||||
C(
|
||||
P "'" * (V 'sstring_char' + P '"') ^ 0 * P "'"
|
||||
+ P '"' * (V 'dstring_char' + P "'") ^ 0 * P '"'
|
||||
) * Cc 'string'
|
||||
),
|
||||
|
||||
-- Operator
|
||||
operator = Ct(C(P">>=" + P"<<=" + P"..." +
|
||||
P"::" + P"<<" + P">>" + P"<=" + P">=" + P"==" + P"!=" +
|
||||
P"||" + P"&&" + P"++" + P"--" + P"->" + P"+=" + P"-=" +
|
||||
P"*=" + P"/=" + P"|=" + P"&=" + P"^=" + S"+-*/=<>%^|&.?:!~,") * Cc"operator"),
|
||||
operator = Ct(
|
||||
C(
|
||||
P '>>='
|
||||
+ P '<<='
|
||||
+ P '...'
|
||||
+ P '::'
|
||||
+ P '<<'
|
||||
+ P '>>'
|
||||
+ P '<='
|
||||
+ P '>='
|
||||
+ P '=='
|
||||
+ P '!='
|
||||
+ P '||'
|
||||
+ P '&&'
|
||||
+ P '++'
|
||||
+ P '--'
|
||||
+ P '->'
|
||||
+ P '+='
|
||||
+ P '-='
|
||||
+ P '*='
|
||||
+ P '/='
|
||||
+ P '|='
|
||||
+ P '&='
|
||||
+ P '^='
|
||||
+ S '+-*/=<>%^|&.?:!~,'
|
||||
) * Cc 'operator'
|
||||
),
|
||||
|
||||
-- Misc. char (token type is the character itself)
|
||||
char = Ct(C(S"[]{}();") / function(x) return x, x end),
|
||||
char = Ct(C(S '[]{}();') / function(x)
|
||||
return x, x
|
||||
end),
|
||||
|
||||
-- Hex, octal or decimal number
|
||||
int = Ct(C((P"0x" * R("09","af","AF")^1) + (P"0" * R"07"^0) + R"09"^1) * Cc"integer"),
|
||||
int = Ct(
|
||||
C((P '0x' * R('09', 'af', 'AF') ^ 1) + (P '0' * R '07' ^ 0) + R '09' ^ 1) * Cc 'integer'
|
||||
),
|
||||
|
||||
-- Floating point number
|
||||
f_exponent = S"eE" + S"+-"^-1 * R"09"^1,
|
||||
f_terminator = S"fFlL",
|
||||
float = Ct(C(
|
||||
R"09"^1 * V"f_exponent" * V"f_terminator"^-1 +
|
||||
R"09"^0 * P"." * R"09"^1 * V"f_exponent"^-1 * V"f_terminator"^-1 +
|
||||
R"09"^1 * P"." * R"09"^0 * V"f_exponent"^-1 * V"f_terminator"^-1
|
||||
) * Cc"float"),
|
||||
f_exponent = S 'eE' + S '+-' ^ -1 * R '09' ^ 1,
|
||||
f_terminator = S 'fFlL',
|
||||
float = Ct(
|
||||
C(
|
||||
R '09' ^ 1 * V 'f_exponent' * V 'f_terminator' ^ -1
|
||||
+ R '09' ^ 0 * P '.' * R '09' ^ 1 * V 'f_exponent' ^ -1 * V 'f_terminator' ^ -1
|
||||
+ R '09' ^ 1 * P '.' * R '09' ^ 0 * V 'f_exponent' ^ -1 * V 'f_terminator' ^ -1
|
||||
) * Cc 'float'
|
||||
),
|
||||
|
||||
-- Any token
|
||||
token = V"comment" +
|
||||
V"line_comment" +
|
||||
V"identifier" +
|
||||
V"whitespace" +
|
||||
V"line_extend" +
|
||||
V"preprocessor" +
|
||||
V"string" +
|
||||
V"char" +
|
||||
V"operator" +
|
||||
V"float" +
|
||||
V"int",
|
||||
token = V 'comment'
|
||||
+ V 'line_comment'
|
||||
+ V 'identifier'
|
||||
+ V 'whitespace'
|
||||
+ V 'line_extend'
|
||||
+ V 'preprocessor'
|
||||
+ V 'string'
|
||||
+ V 'char'
|
||||
+ V 'operator'
|
||||
+ V 'float'
|
||||
+ V 'int',
|
||||
|
||||
-- Error for when nothing else matches
|
||||
error = (Cp() * C(P(1) ^ -8) * Carg(1)) / function(pos, where, state)
|
||||
error(("Tokenising error on line %i, position %i, near '%s'")
|
||||
:format(state.line, pos - state.line_start + 1, where))
|
||||
error(
|
||||
("Tokenising error on line %i, position %i, near '%s'"):format(
|
||||
state.line,
|
||||
pos - state.line_start + 1,
|
||||
where
|
||||
)
|
||||
)
|
||||
end,
|
||||
|
||||
-- Match end of input or throw error
|
||||
finish = -P(1) + V"error",
|
||||
finish = -P(1) + V 'error',
|
||||
|
||||
-- Match stream of tokens into a table
|
||||
tokens = Ct(V"token" ^ 0) * V"finish",
|
||||
tokens = Ct(V 'token' ^ 0) * V 'finish',
|
||||
}
|
||||
|
||||
local function TokeniseC(str)
|
||||
return tokens:match(str, 1, {line = 1, line_start = 1})
|
||||
return tokens:match(str, 1, { line = 1, line_start = 1 })
|
||||
end
|
||||
|
||||
local function set(t)
|
||||
@ -132,10 +174,37 @@ local function set(t)
|
||||
end
|
||||
|
||||
local C_keywords = set { -- luacheck: ignore
|
||||
"break", "case", "char", "const", "continue", "default", "do", "double",
|
||||
"else", "enum", "extern", "float", "for", "goto", "if", "int", "long",
|
||||
"register", "return", "short", "signed", "sizeof", "static", "struct",
|
||||
"switch", "typedef", "union", "unsigned", "void", "volatile", "while",
|
||||
'break',
|
||||
'case',
|
||||
'char',
|
||||
'const',
|
||||
'continue',
|
||||
'default',
|
||||
'do',
|
||||
'double',
|
||||
'else',
|
||||
'enum',
|
||||
'extern',
|
||||
'float',
|
||||
'for',
|
||||
'goto',
|
||||
'if',
|
||||
'int',
|
||||
'long',
|
||||
'register',
|
||||
'return',
|
||||
'short',
|
||||
'signed',
|
||||
'sizeof',
|
||||
'static',
|
||||
'struct',
|
||||
'switch',
|
||||
'typedef',
|
||||
'union',
|
||||
'unsigned',
|
||||
'void',
|
||||
'volatile',
|
||||
'while',
|
||||
}
|
||||
|
||||
-- Very primitive C formatter that tries to put "things" inside braces on one
|
||||
@ -174,7 +243,7 @@ local function formatc(str)
|
||||
-- if we're not inside a block, we're at the basic statement level,
|
||||
-- and ';' indicates we're at the end of a statement, so we put end
|
||||
-- it with a newline.
|
||||
token[1] = token[1] .. "\n"
|
||||
token[1] = token[1] .. '\n'
|
||||
end_at_brace = false
|
||||
end
|
||||
elseif typ == 'identifier' then
|
||||
@ -194,20 +263,20 @@ local function formatc(str)
|
||||
-- if we're not inside a block, we're at the basic statement level,
|
||||
-- and ';' indicates we're at the end of a statement, so we put end
|
||||
-- it with a newline.
|
||||
token[1] = ";\n"
|
||||
token[1] = ';\n'
|
||||
end
|
||||
elseif typ == 'whitespace' then
|
||||
-- replace all whitespace by one space
|
||||
local repl = " "
|
||||
local repl = ' '
|
||||
|
||||
-- except when allow_on_nl is true and there's a newline in the whitespace
|
||||
if string.find(token[1], "[\r\n]+") and allow_one_nl == true then
|
||||
if string.find(token[1], '[\r\n]+') and allow_one_nl == true then
|
||||
-- in that case we replace all whitespace by one newline
|
||||
repl = "\n"
|
||||
repl = '\n'
|
||||
allow_one_nl = false
|
||||
end
|
||||
|
||||
token[1] = string.gsub(token[1], "%s+", repl)
|
||||
token[1] = string.gsub(token[1], '%s+', repl)
|
||||
end
|
||||
result[#result + 1] = token[1]
|
||||
end
|
||||
@ -217,7 +286,7 @@ end
|
||||
|
||||
-- standalone operation (very handy for debugging)
|
||||
local function standalone(...) -- luacheck: ignore
|
||||
local Preprocess = require("preprocess")
|
||||
local Preprocess = require('preprocess')
|
||||
Preprocess.add_to_include_path('./../../src')
|
||||
Preprocess.add_to_include_path('./../../build/include')
|
||||
Preprocess.add_to_include_path('./../../.deps/usr/include')
|
||||
|
@ -1,4 +1,4 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local cimport = helpers.cimport
|
||||
@ -157,7 +157,9 @@ local ga_append_ints = function(garr, ...)
|
||||
end
|
||||
|
||||
-- enhanced constructors
|
||||
local garray_ctype = function(...) return ffi.typeof('garray_T[1]')(...) end
|
||||
local garray_ctype = function(...)
|
||||
return ffi.typeof('garray_T[1]')(...)
|
||||
end
|
||||
local new_garray = function()
|
||||
local garr = garray_ctype()
|
||||
return ffi.gc(garr, ga_clear)
|
||||
@ -165,7 +167,7 @@ end
|
||||
|
||||
local new_string_garray = function()
|
||||
local garr = garray_ctype()
|
||||
ga_init(garr, ffi.sizeof("unsigned char *"), 1)
|
||||
ga_init(garr, ffi.sizeof('unsigned char *'), 1)
|
||||
return ffi.gc(garr, ga_clear_strings)
|
||||
end
|
||||
|
||||
@ -182,7 +184,6 @@ local ga_scramble = function(garr)
|
||||
end
|
||||
|
||||
describe('garray', function()
|
||||
|
||||
describe('ga_init', function()
|
||||
itp('initializes the values of the garray', function()
|
||||
local garr = new_garray()
|
||||
@ -252,7 +253,7 @@ describe('garray', function()
|
||||
-- this is the actual ga_append, the others are just emulated lua
|
||||
-- versions
|
||||
local garr = new_garray()
|
||||
ga_init(garr, ffi.sizeof("uint8_t"), 1)
|
||||
ga_init(garr, ffi.sizeof('uint8_t'), 1)
|
||||
ga_append(garr, 'h')
|
||||
ga_append(garr, 'e')
|
||||
ga_append(garr, 'l')
|
||||
@ -265,13 +266,13 @@ describe('garray', function()
|
||||
|
||||
itp('can append integers', function()
|
||||
local garr = new_garray()
|
||||
ga_init(garr, ffi.sizeof("int"), 1)
|
||||
ga_init(garr, ffi.sizeof('int'), 1)
|
||||
local input = {
|
||||
-20,
|
||||
94,
|
||||
867615,
|
||||
90927,
|
||||
86
|
||||
86,
|
||||
}
|
||||
ga_append_ints(garr, unpack(input))
|
||||
local ints = ga_data_as_ints(garr)
|
||||
@ -283,11 +284,11 @@ describe('garray', function()
|
||||
itp('can append strings to a growing array of strings', function()
|
||||
local garr = new_string_garray()
|
||||
local input = {
|
||||
"some",
|
||||
"str",
|
||||
"\r\n\r●●●●●●,,,",
|
||||
"hmm",
|
||||
"got it"
|
||||
'some',
|
||||
'str',
|
||||
'\r\n\r●●●●●●,,,',
|
||||
'hmm',
|
||||
'got it',
|
||||
}
|
||||
ga_append_strings(garr, unpack(input))
|
||||
-- check that we can get the same strings out of the array
|
||||
@ -301,8 +302,8 @@ describe('garray', function()
|
||||
describe('ga_concat', function()
|
||||
itp('concatenates the parameter to the growing byte array', function()
|
||||
local garr = new_garray()
|
||||
ga_init(garr, ffi.sizeof("char"), 1)
|
||||
local str = "ohwell●●"
|
||||
ga_init(garr, ffi.sizeof('char'), 1)
|
||||
local str = 'ohwell●●'
|
||||
local loop = 5
|
||||
for _ = 1, loop do
|
||||
ga_concat(garr, str)
|
||||
@ -331,21 +332,21 @@ describe('garray', function()
|
||||
|
||||
describe('ga_concat_strings', function()
|
||||
itp('returns an empty string when concatenating an empty array', function()
|
||||
test_concat_fn({ }, ga_concat_strings)
|
||||
test_concat_fn({}, ga_concat_strings)
|
||||
end)
|
||||
|
||||
itp('can concatenate a non-empty array', function()
|
||||
test_concat_fn({
|
||||
'oh',
|
||||
'my',
|
||||
'neovim'
|
||||
'neovim',
|
||||
}, ga_concat_strings)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('ga_concat_strings_sep', function()
|
||||
itp('returns an empty string when concatenating an empty array', function()
|
||||
test_concat_fn({ }, ga_concat_strings_sep, '---')
|
||||
test_concat_fn({}, ga_concat_strings_sep, '---')
|
||||
end)
|
||||
|
||||
itp('can concatenate a non-empty array', function()
|
||||
@ -353,7 +354,7 @@ describe('garray', function()
|
||||
test_concat_fn({
|
||||
'oh',
|
||||
'my',
|
||||
'neovim'
|
||||
'neovim',
|
||||
}, ga_concat_strings_sep, sep)
|
||||
end)
|
||||
end)
|
||||
@ -370,13 +371,13 @@ describe('garray', function()
|
||||
'bbb',
|
||||
'ccc',
|
||||
'ccc',
|
||||
'ddd●●'
|
||||
'ddd●●',
|
||||
}
|
||||
local sorted_dedup_input = {
|
||||
'aaa',
|
||||
'bbb',
|
||||
'ccc',
|
||||
'ddd●●'
|
||||
'ddd●●',
|
||||
}
|
||||
ga_append_strings(garr, unpack(input))
|
||||
ga_remove_duplicate_strings(garr)
|
||||
|
@ -49,7 +49,7 @@ local function child_call(func, ret)
|
||||
return function(...)
|
||||
local child_calls = child_calls_mod or child_calls_init
|
||||
if child_pid ~= 0 then
|
||||
child_calls[#child_calls + 1] = {func=func, args={...}}
|
||||
child_calls[#child_calls + 1] = { func = func, args = { ... } }
|
||||
return ret
|
||||
else
|
||||
return func(...)
|
||||
@ -62,7 +62,7 @@ end
|
||||
--- @param func function
|
||||
local function child_call_once(func, ...)
|
||||
if child_pid ~= 0 then
|
||||
child_calls_mod_once[#child_calls_mod_once + 1] = { func = func, args = {...} }
|
||||
child_calls_mod_once[#child_calls_mod_once + 1] = { func = func, args = { ... } }
|
||||
else
|
||||
func(...)
|
||||
end
|
||||
@ -75,7 +75,7 @@ local child_cleanups_mod_once = nil --- @type ChildCall[]?
|
||||
local function child_cleanup_once(func, ...)
|
||||
local child_cleanups = child_cleanups_mod_once
|
||||
if child_pid ~= 0 then
|
||||
child_cleanups[#child_cleanups + 1] = {func=func, args={...}}
|
||||
child_cleanups[#child_cleanups + 1] = { func = func, args = { ... } }
|
||||
else
|
||||
func(...)
|
||||
end
|
||||
@ -133,25 +133,28 @@ local pragma_pack_id = 1
|
||||
local function filter_complex_blocks(body)
|
||||
local result = {} --- @type string[]
|
||||
|
||||
for line in body:gmatch("[^\r\n]+") do
|
||||
if not (string.find(line, "(^)", 1, true) ~= nil
|
||||
or string.find(line, "_ISwupper", 1, true)
|
||||
or string.find(line, "_Float")
|
||||
or string.find(line, "__s128")
|
||||
or string.find(line, "__u128")
|
||||
or string.find(line, "msgpack_zone_push_finalizer")
|
||||
or string.find(line, "msgpack_unpacker_reserve_buffer")
|
||||
or string.find(line, "value_init_")
|
||||
or string.find(line, "UUID_NULL") -- static const uuid_t UUID_NULL = {...}
|
||||
or string.find(line, "inline _Bool")) then
|
||||
for line in body:gmatch('[^\r\n]+') do
|
||||
if
|
||||
not (
|
||||
string.find(line, '(^)', 1, true) ~= nil
|
||||
or string.find(line, '_ISwupper', 1, true)
|
||||
or string.find(line, '_Float')
|
||||
or string.find(line, '__s128')
|
||||
or string.find(line, '__u128')
|
||||
or string.find(line, 'msgpack_zone_push_finalizer')
|
||||
or string.find(line, 'msgpack_unpacker_reserve_buffer')
|
||||
or string.find(line, 'value_init_')
|
||||
or string.find(line, 'UUID_NULL') -- static const uuid_t UUID_NULL = {...}
|
||||
or string.find(line, 'inline _Bool')
|
||||
)
|
||||
then
|
||||
result[#result + 1] = line
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(result, "\n")
|
||||
return table.concat(result, '\n')
|
||||
end
|
||||
|
||||
|
||||
local cdef = ffi.cdef
|
||||
|
||||
local cimportstr
|
||||
@ -184,9 +187,8 @@ local function cimport(...)
|
||||
previous_defines = previous_defines_init
|
||||
cdefs = cdefs_init
|
||||
end
|
||||
for _, path in ipairs({...}) do
|
||||
if not (path:sub(1, 1) == '/' or path:sub(1, 1) == '.'
|
||||
or path:sub(2, 2) == ':') then
|
||||
for _, path in ipairs({ ... }) do
|
||||
if not (path:sub(1, 1) == '/' or path:sub(1, 1) == '.' or path:sub(2, 2) == ':') then
|
||||
path = './' .. path
|
||||
end
|
||||
if not preprocess_cache[path] then
|
||||
@ -205,15 +207,15 @@ local function cimport(...)
|
||||
body = filter_complex_blocks(body)
|
||||
-- add the formatted lines to a set
|
||||
local new_cdefs = Set:new()
|
||||
for line in body:gmatch("[^\r\n]+") do
|
||||
for line in body:gmatch('[^\r\n]+') do
|
||||
line = trim(line)
|
||||
-- give each #pragma pack an unique id, so that they don't get removed
|
||||
-- if they are inserted into the set
|
||||
-- (they are needed in the right order with the struct definitions,
|
||||
-- otherwise luajit has wrong memory layouts for the sturcts)
|
||||
if line:match("#pragma%s+pack") then
|
||||
if line:match('#pragma%s+pack') then
|
||||
--- @type string
|
||||
line = line .. " // " .. pragma_pack_id
|
||||
line = line .. ' // ' .. pragma_pack_id
|
||||
pragma_pack_id = pragma_pack_id + 1
|
||||
end
|
||||
new_cdefs:add(line)
|
||||
@ -277,13 +279,13 @@ end
|
||||
|
||||
local function alloc_log_new()
|
||||
local log = {
|
||||
log={}, --- @type ChildCallLog[]
|
||||
lib=cimport('./src/nvim/memory.h'), --- @type table<string,function>
|
||||
original_functions={}, --- @type table<string,function>
|
||||
null={['\0:is_null']=true},
|
||||
log = {}, --- @type ChildCallLog[]
|
||||
lib = cimport('./src/nvim/memory.h'), --- @type table<string,function>
|
||||
original_functions = {}, --- @type table<string,function>
|
||||
null = { ['\0:is_null'] = true },
|
||||
}
|
||||
|
||||
local allocator_functions = {'malloc', 'free', 'calloc', 'realloc'}
|
||||
local allocator_functions = { 'malloc', 'free', 'calloc', 'realloc' }
|
||||
|
||||
function log:save_original_functions()
|
||||
for _, funcname in ipairs(allocator_functions) do
|
||||
@ -301,7 +303,7 @@ local function alloc_log_new()
|
||||
local kk = k
|
||||
self.lib['mem_' .. k] = function(...)
|
||||
--- @type ChildCallLog
|
||||
local log_entry = { func = kk, args = {...} }
|
||||
local log_entry = { func = kk, args = { ... } }
|
||||
self.log[#self.log + 1] = log_entry
|
||||
if kk == 'free' then
|
||||
self.original_functions[kk](...)
|
||||
@ -314,7 +316,9 @@ local function alloc_log_new()
|
||||
log_entry.args[i] = self.null
|
||||
end
|
||||
end
|
||||
if self.hook then self:hook(log_entry) end
|
||||
if self.hook then
|
||||
self:hook(log_entry)
|
||||
end
|
||||
if log_entry.ret then
|
||||
return log_entry.ret
|
||||
end
|
||||
@ -355,7 +359,7 @@ local function alloc_log_new()
|
||||
end
|
||||
end
|
||||
table.sort(toremove)
|
||||
for i = #toremove,1,-1 do
|
||||
for i = #toremove, 1, -1 do
|
||||
table.remove(self.log, toremove[i])
|
||||
end
|
||||
end
|
||||
@ -365,11 +369,9 @@ local function alloc_log_new()
|
||||
log:set_mocks()
|
||||
end
|
||||
|
||||
function log:before_each()
|
||||
end
|
||||
function log:before_each() end
|
||||
|
||||
function log:after_each()
|
||||
end
|
||||
function log:after_each() end
|
||||
|
||||
log:setup()
|
||||
|
||||
@ -397,13 +399,12 @@ function sc.fork()
|
||||
end
|
||||
|
||||
function sc.pipe()
|
||||
local ret = ffi.new('int[2]', {-1, -1})
|
||||
local ret = ffi.new('int[2]', { -1, -1 })
|
||||
ffi.errno(0)
|
||||
local res = ffi.C.pipe(ret)
|
||||
if (res ~= 0) then
|
||||
if res ~= 0 then
|
||||
local err = ffi.errno(0)
|
||||
assert(res == 0, ("pipe() error: %u: %s"):format(
|
||||
err, ffi.string(ffi.C.strerror(err))))
|
||||
assert(res == 0, ('pipe() error: %u: %s'):format(err, ffi.string(ffi.C.strerror(err))))
|
||||
end
|
||||
assert(ret[0] ~= -1 and ret[1] ~= -1)
|
||||
return ret[0], ret[1]
|
||||
@ -411,19 +412,16 @@ end
|
||||
|
||||
--- @return string
|
||||
function sc.read(rd, len)
|
||||
local ret = ffi.new('char[?]', len, {0})
|
||||
local ret = ffi.new('char[?]', len, { 0 })
|
||||
local total_bytes_read = 0
|
||||
ffi.errno(0)
|
||||
while total_bytes_read < len do
|
||||
local bytes_read = tonumber(ffi.C.read(
|
||||
rd,
|
||||
ffi.cast('void*', ret + total_bytes_read),
|
||||
len - total_bytes_read))
|
||||
local bytes_read =
|
||||
tonumber(ffi.C.read(rd, ffi.cast('void*', ret + total_bytes_read), len - total_bytes_read))
|
||||
if bytes_read == -1 then
|
||||
local err = ffi.errno(0)
|
||||
if err ~= ffi.C.kPOSIXErrnoEINTR then
|
||||
assert(false, ("read() error: %u: %s"):format(
|
||||
err, ffi.string(ffi.C.strerror(err))))
|
||||
assert(false, ('read() error: %u: %s'):format(err, ffi.string(ffi.C.strerror(err))))
|
||||
end
|
||||
elseif bytes_read == 0 then
|
||||
break
|
||||
@ -439,15 +437,16 @@ function sc.write(wr, s)
|
||||
local total_bytes_written = 0
|
||||
ffi.errno(0)
|
||||
while total_bytes_written < #s do
|
||||
local bytes_written = tonumber(ffi.C.write(
|
||||
wr,
|
||||
ffi.cast('void*', wbuf + total_bytes_written),
|
||||
#s - total_bytes_written))
|
||||
local bytes_written = tonumber(
|
||||
ffi.C.write(wr, ffi.cast('void*', wbuf + total_bytes_written), #s - total_bytes_written)
|
||||
)
|
||||
if bytes_written == -1 then
|
||||
local err = ffi.errno(0)
|
||||
if err ~= ffi.C.kPOSIXErrnoEINTR then
|
||||
assert(false, ("write() error: %u: %s ('%s')"):format(
|
||||
err, ffi.string(ffi.C.strerror(err)), s))
|
||||
assert(
|
||||
false,
|
||||
("write() error: %u: %s ('%s')"):format(err, ffi.string(ffi.C.strerror(err)), s)
|
||||
)
|
||||
end
|
||||
elseif bytes_written == 0 then
|
||||
break
|
||||
@ -464,7 +463,7 @@ sc.close = ffi.C.close
|
||||
--- @return integer
|
||||
function sc.wait(pid)
|
||||
ffi.errno(0)
|
||||
local stat_loc = ffi.new('int[1]', {0})
|
||||
local stat_loc = ffi.new('int[1]', { 0 })
|
||||
while true do
|
||||
local r = ffi.C.waitpid(pid, stat_loc, ffi.C.kPOSIXWaitWUNTRACED)
|
||||
if r == -1 then
|
||||
@ -472,8 +471,7 @@ function sc.wait(pid)
|
||||
if err == ffi.C.kPOSIXErrnoECHILD then
|
||||
break
|
||||
elseif err ~= ffi.C.kPOSIXErrnoEINTR then
|
||||
assert(false, ("waitpid() error: %u: %s"):format(
|
||||
err, ffi.string(ffi.C.strerror(err))))
|
||||
assert(false, ('waitpid() error: %u: %s'):format(err, ffi.string(ffi.C.strerror(err))))
|
||||
end
|
||||
else
|
||||
assert(r == pid)
|
||||
@ -489,7 +487,7 @@ sc.exit = ffi.C._exit
|
||||
local function format_list(lst)
|
||||
local ret = {} --- @type string[]
|
||||
for _, v in ipairs(lst) do
|
||||
ret[#ret+1] = assert:format({v, n=1})[1]
|
||||
ret[#ret + 1] = assert:format({ v, n = 1 })[1]
|
||||
end
|
||||
return table.concat(ret, ', ')
|
||||
end
|
||||
@ -498,9 +496,8 @@ if os.getenv('NVIM_TEST_PRINT_SYSCALLS') == '1' then
|
||||
for k_, v_ in pairs(sc) do
|
||||
(function(k, v)
|
||||
sc[k] = function(...)
|
||||
local rets = {v(...)}
|
||||
io.stderr:write(('%s(%s) = %s\n'):format(k, format_list({...}),
|
||||
format_list(rets)))
|
||||
local rets = { v(...) }
|
||||
io.stderr:write(('%s(%s) = %s\n'):format(k, format_list({ ... }), format_list(rets)))
|
||||
return unpack(rets)
|
||||
end
|
||||
end)(k_, v_)
|
||||
@ -512,9 +509,13 @@ local function just_fail(_)
|
||||
end
|
||||
say:set('assertion.just_fail.positive', '%s')
|
||||
say:set('assertion.just_fail.negative', '%s')
|
||||
assert:register('assertion', 'just_fail', just_fail,
|
||||
assert:register(
|
||||
'assertion',
|
||||
'just_fail',
|
||||
just_fail,
|
||||
'assertion.just_fail.positive',
|
||||
'assertion.just_fail.negative')
|
||||
'assertion.just_fail.negative'
|
||||
)
|
||||
|
||||
local hook_fnamelen = 30
|
||||
local hook_sfnamelen = 30
|
||||
@ -615,11 +616,14 @@ local function child_sethook(wr)
|
||||
.. whatchar
|
||||
.. namewhatchar
|
||||
.. ' '
|
||||
.. source .. (' '):rep(hook_sfnamelen - #source)
|
||||
.. source
|
||||
.. (' '):rep(hook_sfnamelen - #source)
|
||||
.. ':'
|
||||
.. funcname .. (' '):rep(hook_fnamelen - #funcname)
|
||||
.. funcname
|
||||
.. (' '):rep(hook_fnamelen - #funcname)
|
||||
.. ':'
|
||||
.. ('0'):rep(hook_numlen - #lnum_s) .. lnum_s
|
||||
.. ('0'):rep(hook_numlen - #lnum_s)
|
||||
.. lnum_s
|
||||
.. '\n'
|
||||
)
|
||||
-- eq(hook_msglen, #msg)
|
||||
@ -742,16 +746,16 @@ local function itp_parent(rd, pid, allow_failure, location)
|
||||
sc.close(rd)
|
||||
if not ok then
|
||||
if allow_failure then
|
||||
io.stderr:write('Errorred out ('..status..'):\n' .. tostring(emsg) .. '\n')
|
||||
io.stderr:write('Errorred out (' .. status .. '):\n' .. tostring(emsg) .. '\n')
|
||||
os.execute([[
|
||||
sh -c "source ci/common/test.sh
|
||||
check_core_dumps --delete \"]] .. Paths.test_luajit_prg .. [[\""]])
|
||||
else
|
||||
error(tostring(emsg)..'\nexit code: '..status)
|
||||
error(tostring(emsg) .. '\nexit code: ' .. status)
|
||||
end
|
||||
elseif status ~= 0 then
|
||||
if not allow_failure then
|
||||
error("child process errored out with status "..status.."!\n\n"..location)
|
||||
error('child process errored out with status ' .. status .. '!\n\n' .. location)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -760,7 +764,9 @@ local function gen_itp(it)
|
||||
child_calls_mod = {}
|
||||
child_calls_mod_once = {}
|
||||
child_cleanups_mod_once = {}
|
||||
preprocess_cache_mod = map(function(v) return v end, preprocess_cache_init)
|
||||
preprocess_cache_mod = map(function(v)
|
||||
return v
|
||||
end, preprocess_cache_init)
|
||||
previous_defines_mod = previous_defines_init
|
||||
cdefs_mod = cdefs_init:copy()
|
||||
local function itp(name, func, allow_failure)
|
||||
@ -794,8 +800,7 @@ local function cppimport(path)
|
||||
return cimport(Paths.test_source_path .. '/test/includes/pre/' .. path)
|
||||
end
|
||||
|
||||
cimport('./src/nvim/types.h', './src/nvim/main.h', './src/nvim/os/time.h',
|
||||
'./src/nvim/os/fs.h')
|
||||
cimport('./src/nvim/types.h', './src/nvim/main.h', './src/nvim/os/time.h', './src/nvim/os/fs.h')
|
||||
|
||||
local function conv_enum(etab, eval)
|
||||
local n = tonumber(eval)
|
||||
@ -844,7 +849,7 @@ local function ptr2addr(ptr)
|
||||
return tonumber(ffi.cast('intptr_t', ffi.cast('void *', ptr)))
|
||||
end
|
||||
|
||||
local s = ffi.new('char[64]', {0})
|
||||
local s = ffi.new('char[64]', { 0 })
|
||||
|
||||
local function ptr2key(ptr)
|
||||
ffi.C.snprintf(s, ffi.sizeof(s), '%p', ffi.cast('void *', ptr))
|
||||
@ -853,7 +858,9 @@ end
|
||||
|
||||
local function is_asan()
|
||||
cimport('./src/nvim/version.h')
|
||||
local status, res = pcall(function() return lib.version_cflags end)
|
||||
local status, res = pcall(function()
|
||||
return lib.version_cflags
|
||||
end)
|
||||
if status then
|
||||
return ffi.string(res):match('-fsanitize=[a-z,]*address')
|
||||
else
|
||||
|
@ -1,10 +1,10 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local eq = helpers.eq
|
||||
|
||||
local indent = helpers.cimport("./src/nvim/indent.h")
|
||||
local globals = helpers.cimport("./src/nvim/globals.h")
|
||||
local indent = helpers.cimport('./src/nvim/indent.h')
|
||||
local globals = helpers.cimport('./src/nvim/globals.h')
|
||||
|
||||
describe('get_sts_value', function()
|
||||
itp([[returns 'softtabstop' when it is non-negative]], function()
|
||||
|
@ -1,4 +1,4 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local ffi = helpers.ffi
|
||||
@ -9,7 +9,6 @@ local keycodes = helpers.cimport('./src/nvim/keycodes.h')
|
||||
local NULL = helpers.NULL
|
||||
|
||||
describe('keycodes.c', function()
|
||||
|
||||
describe('find_special_key()', function()
|
||||
local srcp = ffi.new('const unsigned char *[1]')
|
||||
local modp = ffi.new('int[1]')
|
||||
@ -28,31 +27,26 @@ describe('keycodes.c', function()
|
||||
itp('case-insensitive', function()
|
||||
-- Compare other capitalizations to this.
|
||||
srcp[0] = '<C-A>'
|
||||
local all_caps_key =
|
||||
keycodes.find_special_key(srcp, 5, modp, 0, NULL)
|
||||
local all_caps_key = keycodes.find_special_key(srcp, 5, modp, 0, NULL)
|
||||
local all_caps_mod = modp[0]
|
||||
|
||||
srcp[0] = '<C-a>'
|
||||
eq(all_caps_key,
|
||||
keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
eq(all_caps_key, keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
eq(all_caps_mod, modp[0])
|
||||
|
||||
srcp[0] = '<c-A>'
|
||||
eq(all_caps_key,
|
||||
keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
eq(all_caps_key, keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
eq(all_caps_mod, modp[0])
|
||||
|
||||
srcp[0] = '<c-a>'
|
||||
eq(all_caps_key,
|
||||
keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
eq(all_caps_key, keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
eq(all_caps_mod, modp[0])
|
||||
end)
|
||||
|
||||
itp('double-quote in keycode #7411', function()
|
||||
-- Unescaped with in_string=false
|
||||
srcp[0] = '<C-">'
|
||||
eq(string.byte('"'),
|
||||
keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
eq(string.byte('"'), keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||
|
||||
-- Unescaped with in_string=true
|
||||
eq(0, keycodes.find_special_key(srcp, 5, modp, keycodes.FSK_IN_STRING, NULL))
|
||||
@ -64,9 +58,7 @@ describe('keycodes.c', function()
|
||||
eq(0, keycodes.find_special_key(srcp, 6, modp, 0, NULL))
|
||||
|
||||
-- Escaped with in_string=true
|
||||
eq(string.byte('"'),
|
||||
keycodes.find_special_key(srcp, 6, modp, keycodes.FSK_IN_STRING, NULL))
|
||||
eq(string.byte('"'), keycodes.find_special_key(srcp, 6, modp, keycodes.FSK_IN_STRING, NULL))
|
||||
end)
|
||||
end)
|
||||
|
||||
end)
|
||||
|
@ -1,15 +1,17 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local ffi = helpers.ffi
|
||||
local eq = helpers.eq
|
||||
local ok = helpers.ok
|
||||
|
||||
local lib = helpers.cimport("./src/nvim/marktree.h")
|
||||
local lib = helpers.cimport('./src/nvim/marktree.h')
|
||||
|
||||
local function tablelength(t)
|
||||
local count = 0
|
||||
for _ in pairs(t) do count = count + 1 end
|
||||
for _ in pairs(t) do
|
||||
count = count + 1
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
@ -32,15 +34,27 @@ local function shadoworder(tree, shadow, iter, giveorder)
|
||||
local mark = lib.marktree_itr_current(iter)
|
||||
local id = tonumber(mark.id)
|
||||
local spos = shadow[id]
|
||||
if (mark.pos.row ~= spos[1] or mark.pos.col ~= spos[2]) then
|
||||
error("invalid pos for "..id..":("..mark.pos.row..", "..mark.pos.col..") instead of ("..spos[1]..", "..spos[2]..")")
|
||||
if mark.pos.row ~= spos[1] or mark.pos.col ~= spos[2] then
|
||||
error(
|
||||
'invalid pos for '
|
||||
.. id
|
||||
.. ':('
|
||||
.. mark.pos.row
|
||||
.. ', '
|
||||
.. mark.pos.col
|
||||
.. ') instead of ('
|
||||
.. spos[1]
|
||||
.. ', '
|
||||
.. spos[2]
|
||||
.. ')'
|
||||
)
|
||||
end
|
||||
if lib.mt_right_test(mark) ~= spos[3] then
|
||||
error("invalid gravity for "..id..":("..mark.pos.row..", "..mark.pos.col..")")
|
||||
error('invalid gravity for ' .. id .. ':(' .. mark.pos.row .. ', ' .. mark.pos.col .. ')')
|
||||
end
|
||||
if count > 0 then
|
||||
if not pos_leq(last, spos) then
|
||||
error("DISORDER")
|
||||
error('DISORDER')
|
||||
end
|
||||
end
|
||||
count = count + 1
|
||||
@ -52,17 +66,21 @@ local function shadoworder(tree, shadow, iter, giveorder)
|
||||
until not lib.marktree_itr_next(tree, iter)
|
||||
local shadowlen = tablelength(shadow)
|
||||
if shadowlen ~= count then
|
||||
error("missed some keys? (shadow "..shadowlen..", tree "..count..")")
|
||||
error('missed some keys? (shadow ' .. shadowlen .. ', tree ' .. count .. ')')
|
||||
end
|
||||
return id2pos, pos2id
|
||||
end
|
||||
|
||||
local function shadowsplice(shadow, start, old_extent, new_extent)
|
||||
local old_end = {start[1] + old_extent[1],
|
||||
(old_extent[1] == 0 and start[2] or 0) + old_extent[2]}
|
||||
local new_end = {start[1] + new_extent[1],
|
||||
(new_extent[1] == 0 and start[2] or 0) + new_extent[2]}
|
||||
local delta = {new_end[1] - old_end[1], new_end[2] - old_end[2]}
|
||||
local old_end = {
|
||||
start[1] + old_extent[1],
|
||||
(old_extent[1] == 0 and start[2] or 0) + old_extent[2],
|
||||
}
|
||||
local new_end = {
|
||||
start[1] + new_extent[1],
|
||||
(new_extent[1] == 0 and start[2] or 0) + new_extent[2],
|
||||
}
|
||||
local delta = { new_end[1] - old_end[1], new_end[2] - old_end[2] }
|
||||
for _, pos in pairs(shadow) do
|
||||
if pos_leq(start, pos) then
|
||||
if pos_leq(pos, old_end) then
|
||||
@ -83,7 +101,15 @@ local function shadowsplice(shadow, start, old_extent, new_extent)
|
||||
end
|
||||
|
||||
local function dosplice(tree, shadow, start, old_extent, new_extent)
|
||||
lib.marktree_splice(tree, start[1], start[2], old_extent[1], old_extent[2], new_extent[1], new_extent[2])
|
||||
lib.marktree_splice(
|
||||
tree,
|
||||
start[1],
|
||||
start[2],
|
||||
old_extent[1],
|
||||
old_extent[2],
|
||||
new_extent[1],
|
||||
new_extent[2]
|
||||
)
|
||||
shadowsplice(shadow, start, old_extent, new_extent)
|
||||
end
|
||||
|
||||
@ -98,7 +124,7 @@ local function put(tree, row, col, gravitate, end_row, end_col, end_gravitate)
|
||||
end_col = end_col or -1
|
||||
end_gravitate = end_gravitate or false
|
||||
|
||||
lib.marktree_put_test(tree, ns, my_id, row, col, gravitate, end_row, end_col, end_gravitate);
|
||||
lib.marktree_put_test(tree, ns, my_id, row, col, gravitate, end_row, end_col, end_gravitate)
|
||||
return my_id
|
||||
end
|
||||
|
||||
@ -108,18 +134,18 @@ describe('marktree', function()
|
||||
end)
|
||||
|
||||
itp('works', function()
|
||||
local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
|
||||
local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
|
||||
local shadow = {}
|
||||
local iter = ffi.new("MarkTreeIter[1]")
|
||||
local iter2 = ffi.new("MarkTreeIter[1]")
|
||||
local iter = ffi.new('MarkTreeIter[1]')
|
||||
local iter2 = ffi.new('MarkTreeIter[1]')
|
||||
|
||||
for i = 1,100 do
|
||||
for j = 1,100 do
|
||||
local gravitate = (i%2) > 0
|
||||
for i = 1, 100 do
|
||||
for j = 1, 100 do
|
||||
local gravitate = (i % 2) > 0
|
||||
local id = put(tree, j, i, gravitate)
|
||||
ok(id > 0)
|
||||
eq(nil, shadow[id])
|
||||
shadow[id] = {j,i,gravitate}
|
||||
shadow[id] = { j, i, gravitate }
|
||||
end
|
||||
-- checking every insert is too slow, but this is ok
|
||||
lib.marktree_check(tree)
|
||||
@ -133,7 +159,7 @@ describe('marktree', function()
|
||||
eq({}, pos2id) -- not set if not requested
|
||||
eq({}, id2pos)
|
||||
|
||||
for i,ipos in pairs(shadow) do
|
||||
for i, ipos in pairs(shadow) do
|
||||
local p = lib.marktree_lookup_ns(tree, ns, i, false, iter)
|
||||
eq(ipos[1], p.pos.row)
|
||||
eq(ipos[2], p.pos.col)
|
||||
@ -145,7 +171,7 @@ describe('marktree', function()
|
||||
-- local k2 = lib.marktree_itr_current(iter)
|
||||
end
|
||||
|
||||
for i,ipos in pairs(shadow) do
|
||||
for i, ipos in pairs(shadow) do
|
||||
lib.marktree_itr_get(tree, ipos[1], ipos[2], iter)
|
||||
local k = lib.marktree_itr_current(iter)
|
||||
eq(i, tonumber(k.id))
|
||||
@ -160,9 +186,9 @@ describe('marktree', function()
|
||||
shadow[tonumber(del.id)] = nil
|
||||
shadoworder(tree, shadow, iter)
|
||||
|
||||
for _, ci in ipairs({0,-1,1,-2,2,-10,10}) do
|
||||
for i = 1,100 do
|
||||
lib.marktree_itr_get(tree, i, 50+ci, iter)
|
||||
for _, ci in ipairs({ 0, -1, 1, -2, 2, -10, 10 }) do
|
||||
for i = 1, 100 do
|
||||
lib.marktree_itr_get(tree, i, 50 + ci, iter)
|
||||
local k = lib.marktree_itr_current(iter)
|
||||
local id = tonumber(k.id)
|
||||
eq(shadow[id][1], k.pos.row)
|
||||
@ -177,14 +203,14 @@ describe('marktree', function()
|
||||
-- NB: this is quite rudimentary. We rely on
|
||||
-- functional tests exercising splicing quite a bit
|
||||
lib.marktree_check(tree)
|
||||
dosplice(tree, shadow, {2,2}, {0,5}, {1, 2})
|
||||
dosplice(tree, shadow, { 2, 2 }, { 0, 5 }, { 1, 2 })
|
||||
lib.marktree_check(tree)
|
||||
shadoworder(tree, shadow, iter)
|
||||
dosplice(tree, shadow, {30,2}, {30,5}, {1, 2})
|
||||
dosplice(tree, shadow, { 30, 2 }, { 30, 5 }, { 1, 2 })
|
||||
lib.marktree_check(tree)
|
||||
shadoworder(tree, shadow, iter)
|
||||
|
||||
dosplice(tree, shadow, {5,3}, {0,2}, {0, 5})
|
||||
dosplice(tree, shadow, { 5, 3 }, { 0, 2 }, { 0, 5 })
|
||||
shadoworder(tree, shadow, iter)
|
||||
lib.marktree_check(tree)
|
||||
|
||||
@ -209,7 +235,7 @@ describe('marktree', function()
|
||||
-- Check iterator validity for 2 specific edge cases:
|
||||
-- https://github.com/neovim/neovim/pull/14719
|
||||
lib.marktree_clear(tree)
|
||||
for i = 1,20 do
|
||||
for i = 1, 20 do
|
||||
put(tree, i, i, false)
|
||||
end
|
||||
|
||||
@ -224,46 +250,60 @@ describe('marktree', function()
|
||||
|
||||
itp("'intersect_mov' function works correctly", function()
|
||||
local function mov(x, y, w)
|
||||
local xa = ffi.new("uint64_t[?]", #x)
|
||||
for i, xi in ipairs(x) do xa[i-1] = xi end
|
||||
local ya = ffi.new("uint64_t[?]", #y)
|
||||
for i, yi in ipairs(y) do ya[i-1] = yi end
|
||||
local wa = ffi.new("uint64_t[?]", #w)
|
||||
for i, wi in ipairs(w) do wa[i-1] = wi end
|
||||
local xa = ffi.new('uint64_t[?]', #x)
|
||||
for i, xi in ipairs(x) do
|
||||
xa[i - 1] = xi
|
||||
end
|
||||
local ya = ffi.new('uint64_t[?]', #y)
|
||||
for i, yi in ipairs(y) do
|
||||
ya[i - 1] = yi
|
||||
end
|
||||
local wa = ffi.new('uint64_t[?]', #w)
|
||||
for i, wi in ipairs(w) do
|
||||
wa[i - 1] = wi
|
||||
end
|
||||
|
||||
local dummy_size = #x + #y + #w
|
||||
local wouta = ffi.new("uint64_t[?]", dummy_size)
|
||||
local douta = ffi.new("uint64_t[?]", dummy_size)
|
||||
local wsize = ffi.new("size_t[1]")
|
||||
local wouta = ffi.new('uint64_t[?]', dummy_size)
|
||||
local douta = ffi.new('uint64_t[?]', dummy_size)
|
||||
local wsize = ffi.new('size_t[1]')
|
||||
wsize[0] = dummy_size
|
||||
local dsize = ffi.new("size_t[1]")
|
||||
local dsize = ffi.new('size_t[1]')
|
||||
dsize[0] = dummy_size
|
||||
|
||||
local status = lib.intersect_mov_test(xa, #x, ya, #y, wa, #w, wouta, wsize, douta, dsize)
|
||||
if status == 0 then error'wowza' end
|
||||
|
||||
local wout, dout = {}, {}
|
||||
for i = 0,tonumber(wsize[0])-1 do table.insert(wout, tonumber(wouta[i])) end
|
||||
for i = 0,tonumber(dsize[0])-1 do table.insert(dout, tonumber(douta[i])) end
|
||||
return {wout, dout}
|
||||
if status == 0 then
|
||||
error 'wowza'
|
||||
end
|
||||
|
||||
eq({{}, {}}, mov({}, {2, 3}, {2, 3}))
|
||||
eq({{2, 3}, {}}, mov({}, {}, {2, 3}))
|
||||
eq({{2, 3}, {}}, mov({2, 3}, {}, {}))
|
||||
eq({{}, {2,3}}, mov({}, {2,3}, {}))
|
||||
local wout, dout = {}, {}
|
||||
for i = 0, tonumber(wsize[0]) - 1 do
|
||||
table.insert(wout, tonumber(wouta[i]))
|
||||
end
|
||||
for i = 0, tonumber(dsize[0]) - 1 do
|
||||
table.insert(dout, tonumber(douta[i]))
|
||||
end
|
||||
return { wout, dout }
|
||||
end
|
||||
|
||||
eq({{1, 5}, {}}, mov({1,2,5}, {2, 3}, {3}))
|
||||
eq({{1, 2}, {}}, mov({1,2,5}, {5, 10}, {10}))
|
||||
eq({{1, 2}, {5}}, mov({1,2}, {5, 10}, {10}))
|
||||
eq({{1,3,5,7,9}, {2,4,6,8,10}}, mov({1,3,5,7,9}, {2,4,6,8,10}, {}))
|
||||
eq({{1,3,5,7,9}, {2,6,10}}, mov({1,3,5,7,9}, {2,4,6,8,10}, {4, 8}))
|
||||
eq({{1,4,7}, {2,5,8}}, mov({1,3,4,6,7,9}, {2,3,5,6,8,9}, {}))
|
||||
eq({{1,4,7}, {}}, mov({1,3,4,6,7,9}, {2,3,5,6,8,9}, {2,5,8}))
|
||||
eq({{0,1,4,7,10}, {}}, mov({1,3,4,6,7,9}, {2,3,5,6,8,9}, {0,2,5,8,10}))
|
||||
eq({ {}, {} }, mov({}, { 2, 3 }, { 2, 3 }))
|
||||
eq({ { 2, 3 }, {} }, mov({}, {}, { 2, 3 }))
|
||||
eq({ { 2, 3 }, {} }, mov({ 2, 3 }, {}, {}))
|
||||
eq({ {}, { 2, 3 } }, mov({}, { 2, 3 }, {}))
|
||||
|
||||
eq({ { 1, 5 }, {} }, mov({ 1, 2, 5 }, { 2, 3 }, { 3 }))
|
||||
eq({ { 1, 2 }, {} }, mov({ 1, 2, 5 }, { 5, 10 }, { 10 }))
|
||||
eq({ { 1, 2 }, { 5 } }, mov({ 1, 2 }, { 5, 10 }, { 10 }))
|
||||
eq({ { 1, 3, 5, 7, 9 }, { 2, 4, 6, 8, 10 } }, mov({ 1, 3, 5, 7, 9 }, { 2, 4, 6, 8, 10 }, {}))
|
||||
eq({ { 1, 3, 5, 7, 9 }, { 2, 6, 10 } }, mov({ 1, 3, 5, 7, 9 }, { 2, 4, 6, 8, 10 }, { 4, 8 }))
|
||||
eq({ { 1, 4, 7 }, { 2, 5, 8 } }, mov({ 1, 3, 4, 6, 7, 9 }, { 2, 3, 5, 6, 8, 9 }, {}))
|
||||
eq({ { 1, 4, 7 }, {} }, mov({ 1, 3, 4, 6, 7, 9 }, { 2, 3, 5, 6, 8, 9 }, { 2, 5, 8 }))
|
||||
eq(
|
||||
{ { 0, 1, 4, 7, 10 }, {} },
|
||||
mov({ 1, 3, 4, 6, 7, 9 }, { 2, 3, 5, 6, 8, 9 }, { 0, 2, 5, 8, 10 })
|
||||
)
|
||||
end)
|
||||
|
||||
|
||||
local function check_intersections(tree)
|
||||
lib.marktree_check(tree)
|
||||
-- to debug stuff disable this branch
|
||||
@ -279,13 +319,13 @@ describe('marktree', function()
|
||||
if not val then
|
||||
local str2 = lib.mt_inspect(tree, true, true)
|
||||
local dot2 = ffi.string(str2.data, str2.size)
|
||||
print("actual:\n\n".."Xafile.dot".."\n\nexpected:\n\n".."Xefile.dot".."\n")
|
||||
print("nivå", tree[0].root.level);
|
||||
print('actual:\n\n' .. 'Xafile.dot' .. '\n\nexpected:\n\n' .. 'Xefile.dot' .. '\n')
|
||||
print('nivå', tree[0].root.level)
|
||||
io.stdout:flush()
|
||||
local afil = io.open("Xafile.dot", "wb")
|
||||
local afil = io.open('Xafile.dot', 'wb')
|
||||
afil:write(dot1)
|
||||
afil:close()
|
||||
local efil = io.open("Xefile.dot", "wb")
|
||||
local efil = io.open('Xefile.dot', 'wb')
|
||||
efil:write(dot2)
|
||||
efil:close()
|
||||
ok(false)
|
||||
@ -295,28 +335,28 @@ describe('marktree', function()
|
||||
end
|
||||
|
||||
itp('works with intersections', function()
|
||||
local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
|
||||
local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
|
||||
|
||||
local ids = {}
|
||||
|
||||
for i = 1,80 do
|
||||
table.insert(ids, put(tree, 1, i, false, 2, 100-i, false))
|
||||
for i = 1, 80 do
|
||||
table.insert(ids, put(tree, 1, i, false, 2, 100 - i, false))
|
||||
check_intersections(tree)
|
||||
end
|
||||
for i = 1,80 do
|
||||
for i = 1, 80 do
|
||||
lib.marktree_del_pair_test(tree, ns, ids[i])
|
||||
check_intersections(tree)
|
||||
end
|
||||
ids = {}
|
||||
|
||||
for i = 1,80 do
|
||||
table.insert(ids, put(tree, 1, i, false, 2, 100-i, false))
|
||||
for i = 1, 80 do
|
||||
table.insert(ids, put(tree, 1, i, false, 2, 100 - i, false))
|
||||
check_intersections(tree)
|
||||
end
|
||||
|
||||
for i = 1,10 do
|
||||
for j = 1,8 do
|
||||
local ival = (j-1)*10+i
|
||||
for i = 1, 10 do
|
||||
for j = 1, 8 do
|
||||
local ival = (j - 1) * 10 + i
|
||||
lib.marktree_del_pair_test(tree, ns, ids[ival])
|
||||
check_intersections(tree)
|
||||
end
|
||||
@ -324,12 +364,12 @@ describe('marktree', function()
|
||||
end)
|
||||
|
||||
itp('works with intersections with a big tree', function()
|
||||
local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
|
||||
local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
|
||||
|
||||
local ids = {}
|
||||
|
||||
for i = 1,1000 do
|
||||
table.insert(ids, put(tree, 1, i, false, 2, 1000-i, false))
|
||||
for i = 1, 1000 do
|
||||
table.insert(ids, put(tree, 1, i, false, 2, 1000 - i, false))
|
||||
if i % 10 == 1 then
|
||||
check_intersections(tree)
|
||||
end
|
||||
@ -339,13 +379,13 @@ describe('marktree', function()
|
||||
eq(2000, tree[0].n_keys)
|
||||
ok(tree[0].root.level >= 2)
|
||||
|
||||
local iter = ffi.new("MarkTreeIter[1]")
|
||||
local iter = ffi.new('MarkTreeIter[1]')
|
||||
|
||||
local k = 0
|
||||
for i = 1,20 do
|
||||
for j = 1,50 do
|
||||
for i = 1, 20 do
|
||||
for j = 1, 50 do
|
||||
k = k + 1
|
||||
local ival = (j-1)*20+i
|
||||
local ival = (j - 1) * 20 + i
|
||||
if false == true then -- if there actually is a failure, this branch will fail out at the actual spot of the error
|
||||
lib.marktree_lookup_ns(tree, ns, ids[ival], false, iter)
|
||||
lib.marktree_del_itr(tree, iter, false)
|
||||
@ -367,10 +407,10 @@ describe('marktree', function()
|
||||
end)
|
||||
|
||||
itp('works with intersections and marktree_splice', function()
|
||||
local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
|
||||
local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
|
||||
|
||||
for i = 1,1000 do
|
||||
put(tree, 1, i, false, 2, 1000-i, false)
|
||||
for i = 1, 1000 do
|
||||
put(tree, 1, i, false, 2, 1000 - i, false)
|
||||
if i % 10 == 1 then
|
||||
check_intersections(tree)
|
||||
end
|
||||
@ -380,15 +420,15 @@ describe('marktree', function()
|
||||
eq(2000, tree[0].n_keys)
|
||||
ok(tree[0].root.level >= 2)
|
||||
|
||||
for _ = 1,10 do
|
||||
for _ = 1, 10 do
|
||||
lib.marktree_splice(tree, 0, 0, 0, 100, 0, 0)
|
||||
check_intersections(tree)
|
||||
end
|
||||
end)
|
||||
|
||||
itp('marktree_move should preserve key order', function()
|
||||
local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
|
||||
local iter = ffi.new("MarkTreeIter[1]")
|
||||
local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
|
||||
local iter = ffi.new('MarkTreeIter[1]')
|
||||
local ids = {}
|
||||
|
||||
-- new index and old index look the same, but still have to move because
|
||||
@ -405,31 +445,30 @@ describe('marktree', function()
|
||||
end)
|
||||
|
||||
itp('works with intersections and marktree_move', function()
|
||||
local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
|
||||
local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
|
||||
|
||||
local ids = {}
|
||||
|
||||
for i = 1,1000 do
|
||||
table.insert(ids, put(tree, 1, i, false, 2, 1000-i, false))
|
||||
for i = 1, 1000 do
|
||||
table.insert(ids, put(tree, 1, i, false, 2, 1000 - i, false))
|
||||
if i % 10 == 1 then
|
||||
check_intersections(tree)
|
||||
end
|
||||
end
|
||||
|
||||
local iter = ffi.new("MarkTreeIter[1]")
|
||||
for i = 1,1000 do
|
||||
local which = i%2
|
||||
local iter = ffi.new('MarkTreeIter[1]')
|
||||
for i = 1, 1000 do
|
||||
local which = i % 2
|
||||
lib.marktree_lookup_ns(tree, ns, ids[i], which, iter)
|
||||
lib.marktree_move(tree, iter, 1+which, 500+i)
|
||||
lib.marktree_move(tree, iter, 1 + which, 500 + i)
|
||||
if i % 10 == 1 then
|
||||
check_intersections(tree)
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
itp('works with intersections with a even bigger tree', function()
|
||||
local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
|
||||
local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
|
||||
|
||||
local ids = {}
|
||||
|
||||
@ -441,21 +480,21 @@ describe('marktree', function()
|
||||
at_row[i] = {}
|
||||
end
|
||||
|
||||
local size = 1000*size_factor
|
||||
local size = 1000 * size_factor
|
||||
local k = 1
|
||||
while k <= size do
|
||||
for row1 = 1,9 do
|
||||
for row2 = row1,10 do -- note row2 can be == row1, leads to empty ranges being tested when k > size/2
|
||||
for row1 = 1, 9 do
|
||||
for row2 = row1, 10 do -- note row2 can be == row1, leads to empty ranges being tested when k > size/2
|
||||
if k > size then
|
||||
break
|
||||
end
|
||||
local id = put(tree, row1, k, false, row2, size-k, false)
|
||||
local id = put(tree, row1, k, false, row2, size - k, false)
|
||||
table.insert(ids, id)
|
||||
for i = row1+1, row2 do
|
||||
for i = row1 + 1, row2 do
|
||||
table.insert(at_row[i], id)
|
||||
end
|
||||
--if tree[0].root.level == 4 then error("kk"..k) end
|
||||
if k % 100*size_factor == 1 or (k < 2000 and k%100 == 1) then
|
||||
if k % 100 * size_factor == 1 or (k < 2000 and k % 100 == 1) then
|
||||
check_intersections(tree)
|
||||
end
|
||||
k = k + 1
|
||||
@ -463,13 +502,13 @@ describe('marktree', function()
|
||||
end
|
||||
end
|
||||
|
||||
eq(2*size, tree[0].n_keys)
|
||||
eq(2 * size, tree[0].n_keys)
|
||||
ok(tree[0].root.level >= 3)
|
||||
check_intersections(tree)
|
||||
|
||||
local iter = ffi.new("MarkTreeIter[1]")
|
||||
local pair = ffi.new("MTPair[1]")
|
||||
for i = 1,10 do
|
||||
local iter = ffi.new('MarkTreeIter[1]')
|
||||
local pair = ffi.new('MTPair[1]')
|
||||
for i = 1, 10 do
|
||||
-- use array as set and not {[id]=true} map, to detect duplicates
|
||||
local set = {}
|
||||
eq(true, ffi.C.marktree_itr_get_overlap(tree, i, 0, iter))
|
||||
@ -482,14 +521,14 @@ describe('marktree', function()
|
||||
end
|
||||
|
||||
k = 0
|
||||
for i = 1,100 do
|
||||
for j = 1,(10*size_factor) do
|
||||
for i = 1, 100 do
|
||||
for j = 1, (10 * size_factor) do
|
||||
k = k + 1
|
||||
local ival = (j-1)*100+i
|
||||
local ival = (j - 1) * 100 + i
|
||||
lib.marktree_del_pair_test(tree, ns, ids[ival])
|
||||
-- just a few stickprov, if there is trouble we need to check
|
||||
-- everyone using the code in the "big tree" case above
|
||||
if k % 100*size_factor == 0 or (k > 3000 and k % 200 == 0) then
|
||||
if k % 100 * size_factor == 0 or (k > 3000 and k % 200 == 0) then
|
||||
check_intersections(tree)
|
||||
end
|
||||
end
|
||||
@ -499,7 +538,7 @@ describe('marktree', function()
|
||||
end)
|
||||
|
||||
itp('works with intersections with a even bigger tree and splice', function()
|
||||
local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
|
||||
local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
|
||||
|
||||
-- too much overhead on ASAN
|
||||
local size_factor = helpers.is_asan() and 3 or 10
|
||||
@ -509,20 +548,20 @@ describe('marktree', function()
|
||||
at_row[i] = {}
|
||||
end
|
||||
|
||||
local size = 1000*size_factor
|
||||
local size = 1000 * size_factor
|
||||
local k = 1
|
||||
while k <= size do
|
||||
for row1 = 1,9 do
|
||||
for row2 = row1,10 do -- note row2 can be == row1, leads to empty ranges being tested when k > size/2
|
||||
for row1 = 1, 9 do
|
||||
for row2 = row1, 10 do -- note row2 can be == row1, leads to empty ranges being tested when k > size/2
|
||||
if k > size then
|
||||
break
|
||||
end
|
||||
local id = put(tree, row1, k, false, row2, size-k, false)
|
||||
for i = row1+1, row2 do
|
||||
local id = put(tree, row1, k, false, row2, size - k, false)
|
||||
for i = row1 + 1, row2 do
|
||||
table.insert(at_row[i], id)
|
||||
end
|
||||
--if tree[0].root.level == 4 then error("kk"..k) end
|
||||
if k % 100*size_factor == 1 or (k < 2000 and k%100 == 1) then
|
||||
if k % 100 * size_factor == 1 or (k < 2000 and k % 100 == 1) then
|
||||
check_intersections(tree)
|
||||
end
|
||||
k = k + 1
|
||||
@ -530,11 +569,11 @@ describe('marktree', function()
|
||||
end
|
||||
end
|
||||
|
||||
eq(2*size, tree[0].n_keys)
|
||||
eq(2 * size, tree[0].n_keys)
|
||||
ok(tree[0].root.level >= 3)
|
||||
check_intersections(tree)
|
||||
|
||||
for _ = 1,10 do
|
||||
for _ = 1, 10 do
|
||||
for j = 3, 8 do
|
||||
lib.marktree_splice(tree, j, 0, 0, 200, 0, 0)
|
||||
check_intersections(tree)
|
||||
|
@ -1,4 +1,4 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local ffi = helpers.ffi
|
||||
@ -16,13 +16,12 @@ describe('mbyte', function()
|
||||
return table.concat(s)
|
||||
end
|
||||
|
||||
before_each(function()
|
||||
end)
|
||||
before_each(function() end)
|
||||
|
||||
itp('utf_ptr2char', function()
|
||||
-- For strings with length 1 the first byte is returned.
|
||||
for c = 0, 255 do
|
||||
eq(c, lib.utf_ptr2char(to_string({c, 0})))
|
||||
eq(c, lib.utf_ptr2char(to_string({ c, 0 })))
|
||||
end
|
||||
|
||||
-- Some ill formed byte sequences that should not be recognized as UTF-8
|
||||
@ -48,126 +47,160 @@ describe('mbyte', function()
|
||||
|
||||
describe('utfc_ptr2schar_len', function()
|
||||
local function test_seq(seq)
|
||||
local firstc = ffi.new("int[1]")
|
||||
local buf = ffi.new("char[32]")
|
||||
local firstc = ffi.new('int[1]')
|
||||
local buf = ffi.new('char[32]')
|
||||
lib.schar_get(buf, lib.utfc_ptr2schar_len(to_string(seq), #seq, firstc))
|
||||
return {ffi.string(buf), firstc[0]}
|
||||
return { ffi.string(buf), firstc[0] }
|
||||
end
|
||||
|
||||
local function byte(val)
|
||||
return {string.char(val), val}
|
||||
return { string.char(val), val }
|
||||
end
|
||||
|
||||
itp('1-byte sequences', function()
|
||||
eq({'', 0}, test_seq{0})
|
||||
eq({ '', 0 }, test_seq { 0 })
|
||||
for c = 1, 127 do
|
||||
eq(byte(c), test_seq{c})
|
||||
eq(byte(c), test_seq { c })
|
||||
end
|
||||
for c = 128, 255 do
|
||||
eq({'', c}, test_seq{c})
|
||||
eq({ '', c }, test_seq { c })
|
||||
end
|
||||
end)
|
||||
|
||||
itp('2-byte sequences', function()
|
||||
-- No combining characters
|
||||
eq(byte(0x7f), test_seq{0x7f, 0x7f})
|
||||
eq(byte(0x7f), test_seq { 0x7f, 0x7f })
|
||||
-- No combining characters
|
||||
eq(byte(0x7f), test_seq{0x7f, 0x80})
|
||||
eq(byte(0x7f), test_seq { 0x7f, 0x80 })
|
||||
|
||||
-- No UTF-8 sequence
|
||||
eq({'', 0xc2}, test_seq{0xc2, 0x7f})
|
||||
eq({ '', 0xc2 }, test_seq { 0xc2, 0x7f })
|
||||
-- One UTF-8 character
|
||||
eq({'\xc2\x80', 0x80}, test_seq{0xc2, 0x80})
|
||||
eq({ '\xc2\x80', 0x80 }, test_seq { 0xc2, 0x80 })
|
||||
-- No UTF-8 sequence
|
||||
eq({'', 0xc2}, test_seq{0xc2, 0xc0})
|
||||
eq({ '', 0xc2 }, test_seq { 0xc2, 0xc0 })
|
||||
end)
|
||||
|
||||
itp('3-byte sequences', function()
|
||||
-- No second UTF-8 character
|
||||
eq(byte(0x7f), test_seq{0x7f, 0x80, 0x80})
|
||||
eq(byte(0x7f), test_seq { 0x7f, 0x80, 0x80 })
|
||||
-- No combining character
|
||||
eq(byte(0x7f), test_seq{0x7f, 0xc2, 0x80})
|
||||
eq(byte(0x7f), test_seq { 0x7f, 0xc2, 0x80 })
|
||||
|
||||
-- Combining character is U+0300
|
||||
eq({"\x7f\xcc\x80", 0x7f}, test_seq{0x7f, 0xcc, 0x80})
|
||||
eq({ '\x7f\xcc\x80', 0x7f }, test_seq { 0x7f, 0xcc, 0x80 })
|
||||
|
||||
-- No UTF-8 sequence
|
||||
eq({'', 0xc2}, test_seq{0xc2, 0x7f, 0xcc})
|
||||
eq({ '', 0xc2 }, test_seq { 0xc2, 0x7f, 0xcc })
|
||||
-- Incomplete combining character
|
||||
eq({"\xc2\x80", 0x80}, test_seq{0xc2, 0x80, 0xcc})
|
||||
eq({ '\xc2\x80', 0x80 }, test_seq { 0xc2, 0x80, 0xcc })
|
||||
|
||||
-- One UTF-8 character (composing only)
|
||||
eq({" \xe2\x83\x90", 0x20d0}, test_seq{0xe2, 0x83, 0x90})
|
||||
eq({ ' \xe2\x83\x90', 0x20d0 }, test_seq { 0xe2, 0x83, 0x90 })
|
||||
end)
|
||||
|
||||
itp('4-byte sequences', function()
|
||||
|
||||
-- No following combining character
|
||||
eq(byte(0x7f), test_seq{0x7f, 0x7f, 0xcc, 0x80})
|
||||
eq(byte(0x7f), test_seq { 0x7f, 0x7f, 0xcc, 0x80 })
|
||||
-- No second UTF-8 character
|
||||
eq(byte(0x7f), test_seq{0x7f, 0xc2, 0xcc, 0x80})
|
||||
eq(byte(0x7f), test_seq { 0x7f, 0xc2, 0xcc, 0x80 })
|
||||
|
||||
-- Combining character U+0300
|
||||
eq({"\x7f\xcc\x80", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc})
|
||||
eq({ '\x7f\xcc\x80', 0x7f }, test_seq { 0x7f, 0xcc, 0x80, 0xcc })
|
||||
|
||||
-- No UTF-8 sequence
|
||||
eq({'', 0xc2}, test_seq{0xc2, 0x7f, 0xcc, 0x80})
|
||||
eq({ '', 0xc2 }, test_seq { 0xc2, 0x7f, 0xcc, 0x80 })
|
||||
-- No following UTF-8 character
|
||||
eq({"\xc2\x80", 0x80}, test_seq{0xc2, 0x80, 0xcc, 0xcc})
|
||||
eq({ '\xc2\x80', 0x80 }, test_seq { 0xc2, 0x80, 0xcc, 0xcc })
|
||||
-- Combining character U+0301
|
||||
eq({"\xc2\x80\xcc\x81", 0x80}, test_seq{0xc2, 0x80, 0xcc, 0x81})
|
||||
eq({ '\xc2\x80\xcc\x81', 0x80 }, test_seq { 0xc2, 0x80, 0xcc, 0x81 })
|
||||
|
||||
-- One UTF-8 character
|
||||
eq({"\xf4\x80\x80\x80", 0x100000}, test_seq{0xf4, 0x80, 0x80, 0x80})
|
||||
eq({ '\xf4\x80\x80\x80', 0x100000 }, test_seq { 0xf4, 0x80, 0x80, 0x80 })
|
||||
end)
|
||||
|
||||
itp('5+-byte sequences', function()
|
||||
-- No following combining character
|
||||
eq(byte(0x7f), test_seq{0x7f, 0x7f, 0xcc, 0x80, 0x80})
|
||||
eq(byte(0x7f), test_seq { 0x7f, 0x7f, 0xcc, 0x80, 0x80 })
|
||||
-- No second UTF-8 character
|
||||
eq(byte(0x7f), test_seq{0x7f, 0xc2, 0xcc, 0x80, 0x80})
|
||||
eq(byte(0x7f), test_seq { 0x7f, 0xc2, 0xcc, 0x80, 0x80 })
|
||||
|
||||
-- Combining character U+0300
|
||||
eq({"\x7f\xcc\x80", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x00})
|
||||
eq({ '\x7f\xcc\x80', 0x7f }, test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x00 })
|
||||
|
||||
-- Combining characters U+0300 and U+0301
|
||||
eq({"\x7f\xcc\x80\xcc\x81", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81})
|
||||
eq({ '\x7f\xcc\x80\xcc\x81', 0x7f }, test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81 })
|
||||
-- Combining characters U+0300, U+0301, U+0302
|
||||
eq({"\x7f\xcc\x80\xcc\x81\xcc\x82", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82})
|
||||
eq(
|
||||
{ '\x7f\xcc\x80\xcc\x81\xcc\x82', 0x7f },
|
||||
test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82 }
|
||||
)
|
||||
-- Combining characters U+0300, U+0301, U+0302, U+0303
|
||||
eq({"\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83})
|
||||
eq(
|
||||
{ '\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83', 0x7f },
|
||||
test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83 }
|
||||
)
|
||||
-- Combining characters U+0300, U+0301, U+0302, U+0303, U+0304
|
||||
eq({"\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83, 0xcc, 0x84})
|
||||
eq(
|
||||
{ '\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84', 0x7f },
|
||||
test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83, 0xcc, 0x84 }
|
||||
)
|
||||
-- Combining characters U+0300, U+0301, U+0302, U+0303, U+0304, U+0305
|
||||
eq({"\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84\xcc\x85", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83, 0xcc, 0x84, 0xcc, 0x85})
|
||||
eq(
|
||||
{ '\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84\xcc\x85', 0x7f },
|
||||
test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83, 0xcc, 0x84, 0xcc, 0x85 }
|
||||
)
|
||||
|
||||
-- Combining characters U+0300, U+0301, U+0302, U+0303, U+0304, U+0305, U+0306
|
||||
eq({"\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84\xcc\x85\xcc\x86", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83, 0xcc, 0x84, 0xcc, 0x85, 0xcc, 0x86})
|
||||
eq(
|
||||
{ '\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84\xcc\x85\xcc\x86', 0x7f },
|
||||
test_seq {
|
||||
0x7f,
|
||||
0xcc,
|
||||
0x80,
|
||||
0xcc,
|
||||
0x81,
|
||||
0xcc,
|
||||
0x82,
|
||||
0xcc,
|
||||
0x83,
|
||||
0xcc,
|
||||
0x84,
|
||||
0xcc,
|
||||
0x85,
|
||||
0xcc,
|
||||
0x86,
|
||||
}
|
||||
)
|
||||
|
||||
-- Only three following combining characters U+0300, U+0301, U+0302
|
||||
eq({"\x7f\xcc\x80\xcc\x81\xcc\x82", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xc2, 0x80, 0xcc, 0x84, 0xcc, 0x85})
|
||||
eq(
|
||||
{ '\x7f\xcc\x80\xcc\x81\xcc\x82', 0x7f },
|
||||
test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xc2, 0x80, 0xcc, 0x84, 0xcc, 0x85 }
|
||||
)
|
||||
|
||||
-- No UTF-8 sequence
|
||||
eq({'', 0xc2}, test_seq{0xc2, 0x7f, 0xcc, 0x80, 0x80})
|
||||
eq({ '', 0xc2 }, test_seq { 0xc2, 0x7f, 0xcc, 0x80, 0x80 })
|
||||
-- No following UTF-8 character
|
||||
eq({"\xc2\x80", 0x80}, test_seq{0xc2, 0x80, 0xcc, 0xcc, 0x80})
|
||||
eq({ '\xc2\x80', 0x80 }, test_seq { 0xc2, 0x80, 0xcc, 0xcc, 0x80 })
|
||||
-- Combining character U+0301
|
||||
eq({"\xc2\x80\xcc\x81", 0x80}, test_seq{0xc2, 0x80, 0xcc, 0x81, 0x7f})
|
||||
eq({ '\xc2\x80\xcc\x81', 0x80 }, test_seq { 0xc2, 0x80, 0xcc, 0x81, 0x7f })
|
||||
-- Combining character U+0301
|
||||
eq({"\xc2\x80\xcc\x81", 0x80}, test_seq{0xc2, 0x80, 0xcc, 0x81, 0xcc})
|
||||
eq({ '\xc2\x80\xcc\x81', 0x80 }, test_seq { 0xc2, 0x80, 0xcc, 0x81, 0xcc })
|
||||
|
||||
-- One UTF-8 character
|
||||
eq({"\xf4\x80\x80\x80", 0x100000}, test_seq{0xf4, 0x80, 0x80, 0x80, 0x7f})
|
||||
eq({ '\xf4\x80\x80\x80', 0x100000 }, test_seq { 0xf4, 0x80, 0x80, 0x80, 0x7f })
|
||||
|
||||
-- One UTF-8 character
|
||||
eq({"\xf4\x80\x80\x80", 0x100000}, test_seq{0xf4, 0x80, 0x80, 0x80, 0x80})
|
||||
eq({ '\xf4\x80\x80\x80', 0x100000 }, test_seq { 0xf4, 0x80, 0x80, 0x80, 0x80 })
|
||||
-- One UTF-8 character
|
||||
eq({"\xf4\x80\x80\x80", 0x100000}, test_seq{0xf4, 0x80, 0x80, 0x80, 0xcc})
|
||||
eq({ '\xf4\x80\x80\x80', 0x100000 }, test_seq { 0xf4, 0x80, 0x80, 0x80, 0xcc })
|
||||
|
||||
-- Combining characters U+1AB0 and U+0301
|
||||
eq({"\xf4\x80\x80\x80\xe1\xaa\xb0\xcc\x81", 0x100000}, test_seq{0xf4, 0x80, 0x80, 0x80, 0xe1, 0xaa, 0xb0, 0xcc, 0x81})
|
||||
eq(
|
||||
{ '\xf4\x80\x80\x80\xe1\xaa\xb0\xcc\x81', 0x100000 },
|
||||
test_seq { 0xf4, 0x80, 0x80, 0x80, 0xe1, 0xaa, 0xb0, 0xcc, 0x81 }
|
||||
)
|
||||
end)
|
||||
|
||||
end)
|
||||
|
||||
end)
|
||||
|
@ -1,4 +1,4 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local cimport = helpers.cimport
|
||||
@ -22,8 +22,7 @@ describe('xstrlcat()', function()
|
||||
assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests
|
||||
local dst_cstr = cstr(dsize, dst)
|
||||
local src_cstr = dst_cstr + src_idx -- pointer into `dst` (overlaps)
|
||||
eq(string.len(dst) + string.len(dst) - src_idx,
|
||||
cimp.xstrlcat(dst_cstr, src_cstr, dsize))
|
||||
eq(string.len(dst) + string.len(dst) - src_idx, cimp.xstrlcat(dst_cstr, src_cstr, dsize))
|
||||
return ffi.string(dst_cstr)
|
||||
end
|
||||
|
||||
@ -48,5 +47,4 @@ describe('xstrlcat()', function()
|
||||
eq('', test_xstrlcat('', 'b', 1))
|
||||
eq('ABCיהZd', test_xstrlcat('ABCיהZ', 'defgiיהZ', 10))
|
||||
end)
|
||||
|
||||
end)
|
||||
|
@ -1,12 +1,11 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local ffi = helpers.ffi
|
||||
local eq = helpers.eq
|
||||
local to_cstr = helpers.to_cstr
|
||||
|
||||
local cimp = helpers.cimport('./src/nvim/message.h', './src/nvim/memory.h',
|
||||
'./src/nvim/strings.h')
|
||||
local cimp = helpers.cimport('./src/nvim/message.h', './src/nvim/memory.h', './src/nvim/strings.h')
|
||||
|
||||
describe('trunc_string', function()
|
||||
local buflen = 40
|
||||
@ -34,8 +33,8 @@ describe('trunc_string', function()
|
||||
{ ['desc'] = 'by copy', ['func'] = test_copy },
|
||||
}
|
||||
|
||||
for _,t in ipairs(permutations) do
|
||||
describe('populates buf '..t.desc, function()
|
||||
for _, t in ipairs(permutations) do
|
||||
describe('populates buf ' .. t.desc, function()
|
||||
itp('with a small string', function()
|
||||
t.func('text', 'text')
|
||||
end)
|
||||
|
@ -35,7 +35,9 @@ end
|
||||
|
||||
describe('msgpack', function()
|
||||
describe('unpacker', function()
|
||||
itp('does not crash when paused between `cells` and `wrap` params of `grid_line` #25184', function()
|
||||
itp(
|
||||
'does not crash when paused between `cells` and `wrap` params of `grid_line` #25184',
|
||||
function()
|
||||
-- [kMessageTypeNotification, "redraw", [
|
||||
-- ["grid_line",
|
||||
-- [2, 0, 0, [[" " , 0, 77]], false]
|
||||
@ -54,13 +56,15 @@ describe('msgpack', function()
|
||||
unpacker[0].read_size = unpacker[0].read_size + 1
|
||||
finished = unpacker_advance(unpacker)
|
||||
eq(finished, true)
|
||||
end)
|
||||
end
|
||||
)
|
||||
|
||||
itp('does not crash when parsing grid_line event with 0 `cells` #25184', function()
|
||||
local unpacker = make_unpacker()
|
||||
lib.unpacker_init(unpacker)
|
||||
|
||||
unpacker_goto(unpacker,
|
||||
unpacker_goto(
|
||||
unpacker,
|
||||
-- [kMessageTypeNotification, "redraw", [
|
||||
-- ["grid_line",
|
||||
-- [2, 0, 0, [], false]
|
||||
|
@ -1,4 +1,4 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local child_call_once = helpers.child_call_once
|
||||
@ -6,9 +6,9 @@ local cimport = helpers.cimport
|
||||
local ffi = helpers.ffi
|
||||
local eq = helpers.eq
|
||||
|
||||
local multiqueue = cimport("./test/unit/fixtures/multiqueue.h")
|
||||
local multiqueue = cimport('./test/unit/fixtures/multiqueue.h')
|
||||
|
||||
describe("multiqueue (multi-level event-queue)", function()
|
||||
describe('multiqueue (multi-level event-queue)', function()
|
||||
local parent, child1, child2, child3
|
||||
|
||||
local function put(q, str)
|
||||
|
@ -1,28 +1,27 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local to_cstr = helpers.to_cstr
|
||||
local eq = helpers.eq
|
||||
|
||||
local optionstr = helpers.cimport("./src/nvim/optionstr.h")
|
||||
local optionstr = helpers.cimport('./src/nvim/optionstr.h')
|
||||
|
||||
local check_ff_value = function(ff)
|
||||
return optionstr.check_ff_value(to_cstr(ff))
|
||||
end
|
||||
|
||||
describe('check_ff_value', function()
|
||||
|
||||
itp('views empty string as valid', function()
|
||||
eq(1, check_ff_value(""))
|
||||
eq(1, check_ff_value(''))
|
||||
end)
|
||||
|
||||
itp('views "unix", "dos" and "mac" as valid', function()
|
||||
eq(1, check_ff_value("unix"))
|
||||
eq(1, check_ff_value("dos"))
|
||||
eq(1, check_ff_value("mac"))
|
||||
eq(1, check_ff_value('unix'))
|
||||
eq(1, check_ff_value('dos'))
|
||||
eq(1, check_ff_value('mac'))
|
||||
end)
|
||||
|
||||
itp('views "foo" as invalid', function()
|
||||
eq(0, check_ff_value("foo"))
|
||||
eq(0, check_ff_value('foo'))
|
||||
end)
|
||||
end)
|
||||
|
@ -62,7 +62,7 @@ describe('env.c', function()
|
||||
eq('non-empty', os.getenv(name))
|
||||
end)
|
||||
|
||||
itp("`overwrite` behavior", function()
|
||||
itp('`overwrite` behavior', function()
|
||||
local name = 'NVIM_UNIT_TEST_SETENV_2N'
|
||||
local value = 'NVIM_UNIT_TEST_SETENV_2V'
|
||||
local value_updated = 'NVIM_UNIT_TEST_SETENV_2V_UPDATED'
|
||||
@ -79,7 +79,7 @@ describe('env.c', function()
|
||||
itp('appends :/foo/bar to $PATH', function()
|
||||
local original_path = os.getenv('PATH')
|
||||
eq(true, cimp.os_setenv_append_path(to_cstr('/foo/bar/baz.exe')))
|
||||
eq(original_path..':/foo/bar', os.getenv('PATH'))
|
||||
eq(original_path .. ':/foo/bar', os.getenv('PATH'))
|
||||
end)
|
||||
|
||||
itp('avoids redundant separator when appending to $PATH #7377', function()
|
||||
@ -166,7 +166,7 @@ describe('env.c', function()
|
||||
local test_value = 'NVIM_UNIT_TEST_GETENVNAME_AT_INDEX_1V'
|
||||
os_setenv(test_name, test_value, 1)
|
||||
local i = 0
|
||||
local names = { }
|
||||
local names = {}
|
||||
local found_name = false
|
||||
local name = cimp.os_getenvname_at_index(i)
|
||||
while name ~= NULL do
|
||||
@ -245,7 +245,7 @@ describe('env.c', function()
|
||||
local input = '~/foo ~ foo'
|
||||
local homedir = cstr(255, '')
|
||||
cimp.expand_env_esc(to_cstr('~'), homedir, 255, false, true, NULL)
|
||||
local output_expected = ffi.string(homedir) .. "/foo ~ foo"
|
||||
local output_expected = ffi.string(homedir) .. '/foo ~ foo'
|
||||
local output = cstr(255, '')
|
||||
cimp.expand_env_esc(to_cstr(input), output, 255, false, true, NULL)
|
||||
eq(ffi.string(output), ffi.string(output_expected))
|
||||
@ -256,7 +256,7 @@ describe('env.c', function()
|
||||
local dst = cstr(255, '')
|
||||
cimp.expand_env_esc(to_cstr('~'), dst, 255, false, true, NULL)
|
||||
local homedir = ffi.string(dst)
|
||||
local output_expected = homedir .. "/foo " .. homedir .. " foo"
|
||||
local output_expected = homedir .. '/foo ' .. homedir .. ' foo'
|
||||
local output = cstr(255, '')
|
||||
cimp.expand_env_esc(input, output, 255, false, false, NULL)
|
||||
eq(output_expected, ffi.string(output))
|
||||
@ -267,8 +267,9 @@ describe('env.c', function()
|
||||
cimp.os_get_username(name_out, 100)
|
||||
local curuser = ffi.string(name_out)
|
||||
|
||||
local src = to_cstr("~"..curuser.."/Vcs/django-rest-framework/rest_framework/renderers.py")
|
||||
local dst = cstr(256, "~"..curuser)
|
||||
local src =
|
||||
to_cstr('~' .. curuser .. '/Vcs/django-rest-framework/rest_framework/renderers.py')
|
||||
local dst = cstr(256, '~' .. curuser)
|
||||
cimp.expand_env_esc(src, dst, 256, false, false, NULL)
|
||||
local len = string.len(ffi.string(dst))
|
||||
assert.True(len > 56)
|
||||
@ -283,7 +284,7 @@ describe('env.c', function()
|
||||
cimp.expand_env_esc(input, output, 5, false, true, NULL)
|
||||
-- Make sure the first few characters are copied properly and that there is a
|
||||
-- terminating null character
|
||||
for i=0,3 do
|
||||
for i = 0, 3 do
|
||||
eq(input[i], output[i])
|
||||
end
|
||||
eq(0, output[4])
|
||||
@ -304,7 +305,7 @@ describe('env.c', function()
|
||||
-- terminating null character
|
||||
-- expand_env_esc SHOULD NOT expand the variable if there is not enough space to
|
||||
-- contain the result
|
||||
for i=0,3 do
|
||||
for i = 0, 3 do
|
||||
eq(output[i], input[i])
|
||||
end
|
||||
eq(output[4], 0)
|
||||
|
@ -26,7 +26,7 @@ local linkb = dir .. '/broken.lnk'
|
||||
local filec = dir .. '/created-file.dat'
|
||||
|
||||
before_each(function()
|
||||
mkdir(dir);
|
||||
mkdir(dir)
|
||||
|
||||
local f1 = io.open(file1, 'w')
|
||||
f1:write(fcontents)
|
||||
@ -56,7 +56,7 @@ local function file_open(fname, flags, mode)
|
||||
end
|
||||
|
||||
local function file_open_new(fname, flags, mode)
|
||||
local ret1 = ffi.new('int[?]', 1, {0})
|
||||
local ret1 = ffi.new('int[?]', 1, { 0 })
|
||||
local ret2 = ffi.gc(m.file_open_new(ret1, fname, flags, mode), nil)
|
||||
return ret1[0], ret2
|
||||
end
|
||||
@ -68,7 +68,7 @@ local function file_open_fd(fd, flags)
|
||||
end
|
||||
|
||||
local function file_open_fd_new(fd, flags)
|
||||
local ret1 = ffi.new('int[?]', 1, {0})
|
||||
local ret1 = ffi.new('int[?]', 1, { 0 })
|
||||
local ret2 = ffi.gc(m.file_open_fd_new(ret1, fd, flags), nil)
|
||||
return ret1[0], ret2
|
||||
end
|
||||
@ -116,7 +116,7 @@ describe('file_open_fd', function()
|
||||
local fd = m.os_open(file1, m.kO_RDONLY, 0)
|
||||
local err, fp = file_open_fd(fd, m.kFileReadOnly)
|
||||
eq(0, err)
|
||||
eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
|
||||
eq({ #fcontents, fcontents }, { file_read(fp, #fcontents) })
|
||||
eq(0, m.file_close(fp, false))
|
||||
end)
|
||||
itp('can use file descriptor returned by os_open for writing', function()
|
||||
@ -136,7 +136,7 @@ describe('file_open_fd_new', function()
|
||||
local fd = m.os_open(file1, m.kO_RDONLY, 0)
|
||||
local err, fp = file_open_fd_new(fd, m.kFileReadOnly)
|
||||
eq(0, err)
|
||||
eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
|
||||
eq({ #fcontents, fcontents }, { file_read(fp, #fcontents) })
|
||||
eq(0, m.file_free(fp, false))
|
||||
end)
|
||||
itp('can use file descriptor returned by os_open for writing', function()
|
||||
@ -193,7 +193,9 @@ describe('file_open', function()
|
||||
local err, _ = file_open(linkf, m.kFileNoSymlink, 384)
|
||||
-- err is UV_EMLINK in FreeBSD, but if I use `ok(err == m.UV_ELOOP or err ==
|
||||
-- m.UV_EMLINK)`, then I loose the ability to see actual `err` value.
|
||||
if err ~= m.UV_ELOOP then eq(m.UV_EMLINK, err) end
|
||||
if err ~= m.UV_ELOOP then
|
||||
eq(m.UV_EMLINK, err)
|
||||
end
|
||||
end)
|
||||
|
||||
itp('can open an existing file write-only with kFileCreate', function()
|
||||
@ -249,8 +251,7 @@ describe('file_open', function()
|
||||
eq(nil, attrs)
|
||||
end)
|
||||
|
||||
itp('can truncate an existing file with kFileTruncate when opening a symlink',
|
||||
function()
|
||||
itp('can truncate an existing file with kFileTruncate when opening a symlink', function()
|
||||
local err, fp = file_open(linkf, m.kFileTruncate, 384)
|
||||
eq(0, err)
|
||||
eq(true, fp.wr)
|
||||
@ -356,10 +357,9 @@ describe('file_read', function()
|
||||
local exp_s = fcontents:sub(shift + 1, shift + size)
|
||||
if shift + size >= #fcontents then
|
||||
exp_err = #fcontents - shift
|
||||
exp_s = (fcontents:sub(shift + 1, shift + size)
|
||||
.. (('\0'):rep(size - exp_err)))
|
||||
exp_s = (fcontents:sub(shift + 1, shift + size) .. (('\0'):rep(size - exp_err)))
|
||||
end
|
||||
eq({exp_err, exp_s}, {file_read(fp, size)})
|
||||
eq({ exp_err, exp_s }, { file_read(fp, size) })
|
||||
shift = shift + size
|
||||
end
|
||||
eq(0, m.file_close(fp, false))
|
||||
@ -369,8 +369,8 @@ describe('file_read', function()
|
||||
local err, fp = file_open(file1, 0, 384)
|
||||
eq(0, err)
|
||||
eq(false, fp.wr)
|
||||
eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
|
||||
eq({0, ('\0'):rep(#fcontents)}, {file_read(fp, #fcontents)})
|
||||
eq({ #fcontents, fcontents }, { file_read(fp, #fcontents) })
|
||||
eq({ 0, ('\0'):rep(#fcontents) }, { file_read(fp, #fcontents) })
|
||||
eq(0, m.file_close(fp, false))
|
||||
end)
|
||||
|
||||
@ -378,9 +378,8 @@ describe('file_read', function()
|
||||
local err, fp = file_open(file1, 0, 384)
|
||||
eq(0, err)
|
||||
eq(false, fp.wr)
|
||||
eq({5, fcontents:sub(1, 5)}, {file_read(fp, 5)})
|
||||
eq({#fcontents - 5, fcontents:sub(6) .. (('\0'):rep(5))},
|
||||
{file_read(fp, #fcontents)})
|
||||
eq({ 5, fcontents:sub(1, 5) }, { file_read(fp, 5) })
|
||||
eq({ #fcontents - 5, fcontents:sub(6) .. (('\0'):rep(5)) }, { file_read(fp, #fcontents) })
|
||||
eq(0, m.file_close(fp, false))
|
||||
end)
|
||||
|
||||
@ -395,10 +394,9 @@ describe('file_read', function()
|
||||
local exp_s = fcontents:sub(shift + 1, shift + size)
|
||||
if shift + size >= #fcontents then
|
||||
exp_err = #fcontents - shift
|
||||
exp_s = (fcontents:sub(shift + 1, shift + size)
|
||||
.. (('\0'):rep(size - exp_err)))
|
||||
exp_s = (fcontents:sub(shift + 1, shift + size) .. (('\0'):rep(size - exp_err)))
|
||||
end
|
||||
eq({exp_err, exp_s}, {file_read(fp, size)})
|
||||
eq({ exp_err, exp_s }, { file_read(fp, size) })
|
||||
shift = shift + size
|
||||
end
|
||||
eq(0, m.file_close(fp, false))
|
||||
|
@ -68,7 +68,7 @@ describe('fs.c', function()
|
||||
end
|
||||
|
||||
before_each(function()
|
||||
mkdir('unit-test-directory');
|
||||
mkdir('unit-test-directory')
|
||||
|
||||
io.open('unit-test-directory/test.file', 'w'):close()
|
||||
|
||||
@ -284,17 +284,19 @@ describe('fs.c', function()
|
||||
end)
|
||||
|
||||
-- Some systems may not have `id` utility.
|
||||
if (os.execute('id -G > /dev/null 2>&1') ~= 0) then
|
||||
if os.execute('id -G > /dev/null 2>&1') ~= 0 then
|
||||
pending('skipped (missing `id` utility)', function() end)
|
||||
else
|
||||
itp('owner of a file may change the group of the file to any group of which that owner is a member', function()
|
||||
itp(
|
||||
'owner of a file may change the group of the file to any group of which that owner is a member',
|
||||
function()
|
||||
local file_gid = luv.fs_stat(filename).gid
|
||||
|
||||
-- Gets ID of any group of which current user is a member except the
|
||||
-- group that owns the file.
|
||||
local id_fd = io.popen('id -G')
|
||||
local new_gid = id_fd:read('*n')
|
||||
if (new_gid == file_gid) then
|
||||
if new_gid == file_gid then
|
||||
new_gid = id_fd:read('*n')
|
||||
end
|
||||
id_fd:close()
|
||||
@ -305,10 +307,11 @@ describe('fs.c', function()
|
||||
eq(0, (os_fchown(filename, -1, new_gid)))
|
||||
eq(new_gid, luv.fs_stat(filename).gid)
|
||||
end
|
||||
end)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
if (ffi.os == 'Windows' or ffi.C.geteuid() == 0) then
|
||||
if ffi.os == 'Windows' or ffi.C.geteuid() == 0 then
|
||||
pending('skipped (uv_fs_chown is no-op on Windows)', function() end)
|
||||
else
|
||||
itp('returns nonzero if process has not enough permissions', function()
|
||||
@ -318,7 +321,6 @@ describe('fs.c', function()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
describe('os_file_is_readable', function()
|
||||
itp('returns false if the file is not readable', function()
|
||||
local perm = os_getperm('unit-test-directory/test.file')
|
||||
@ -330,13 +332,11 @@ describe('fs.c', function()
|
||||
end)
|
||||
|
||||
itp('returns false if the file does not exist', function()
|
||||
eq(false, os_file_is_readable(
|
||||
'unit-test-directory/what_are_you_smoking.gif'))
|
||||
eq(false, os_file_is_readable('unit-test-directory/what_are_you_smoking.gif'))
|
||||
end)
|
||||
|
||||
itp('returns true if the file is readable', function()
|
||||
eq(true, os_file_is_readable(
|
||||
'unit-test-directory/test.file'))
|
||||
eq(true, os_file_is_readable('unit-test-directory/test.file'))
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -387,7 +387,7 @@ describe('fs.c', function()
|
||||
else
|
||||
buf = ffi.new('char[?]', size + 1, ('\0'):rep(size))
|
||||
end
|
||||
local eof = ffi.new('bool[?]', 1, {true})
|
||||
local eof = ffi.new('bool[?]', 1, { true })
|
||||
local ret2 = fs.os_read(fd, eof, buf, size, false)
|
||||
local ret1 = eof[0]
|
||||
local ret3 = ''
|
||||
@ -400,16 +400,16 @@ describe('fs.c', function()
|
||||
local bufs = {}
|
||||
for i, size in ipairs(sizes) do
|
||||
bufs[i] = {
|
||||
iov_base=ffi.new('char[?]', size + 1, ('\0'):rep(size)),
|
||||
iov_len=size,
|
||||
iov_base = ffi.new('char[?]', size + 1, ('\0'):rep(size)),
|
||||
iov_len = size,
|
||||
}
|
||||
end
|
||||
local iov = ffi.new('struct iovec[?]', #sizes, bufs)
|
||||
local eof = ffi.new('bool[?]', 1, {true})
|
||||
local eof = ffi.new('bool[?]', 1, { true })
|
||||
local ret2 = fs.os_readv(fd, eof, iov, #sizes, false)
|
||||
local ret1 = eof[0]
|
||||
local ret3 = {}
|
||||
for i = 1,#sizes do
|
||||
for i = 1, #sizes do
|
||||
-- Warning: iov may not be used.
|
||||
ret3[i] = ffi.string(bufs[i].iov_base, bufs[i].iov_len)
|
||||
end
|
||||
@ -494,9 +494,14 @@ describe('fs.c', function()
|
||||
local dup0 = fs.os_dup(0)
|
||||
local dup1 = fs.os_dup(1)
|
||||
local dup2 = fs.os_dup(2)
|
||||
local tbl = {[0]=true, [1]=true, [2]=true,
|
||||
[tonumber(dup0)]=true, [tonumber(dup1)]=true,
|
||||
[tonumber(dup2)]=true}
|
||||
local tbl = {
|
||||
[0] = true,
|
||||
[1] = true,
|
||||
[2] = true,
|
||||
[tonumber(dup0)] = true,
|
||||
[tonumber(dup1)] = true,
|
||||
[tonumber(dup2)] = true,
|
||||
}
|
||||
local i = 0
|
||||
for _, _ in pairs(tbl) do
|
||||
i = i + 1
|
||||
@ -522,12 +527,15 @@ describe('fs.c', function()
|
||||
eq(ffi.C.UV_ENOENT, (os_open('non-existing-file', ffi.C.kO_RDWR, 0)))
|
||||
end)
|
||||
|
||||
itp('returns non-negative for O_CREAT on a non-existing file which then can be closed', function()
|
||||
itp(
|
||||
'returns non-negative for O_CREAT on a non-existing file which then can be closed',
|
||||
function()
|
||||
assert_file_does_not_exist(new_file)
|
||||
local fd = os_open(new_file, ffi.C.kO_CREAT, 0)
|
||||
assert.is_true(0 <= fd)
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
end
|
||||
)
|
||||
|
||||
itp('returns non-negative for O_CREAT on a existing file which then can be closed', function()
|
||||
assert_file_exists(existing_file)
|
||||
@ -544,7 +552,7 @@ describe('fs.c', function()
|
||||
itp('sets `rwx` permissions for O_CREAT 700 which then can be closed', function()
|
||||
assert_file_does_not_exist(new_file)
|
||||
--create the file
|
||||
local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber("700", 8))
|
||||
local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber('700', 8))
|
||||
--verify permissions
|
||||
eq(33216, luv.fs_stat(new_file).mode)
|
||||
eq(0, os_close(fd))
|
||||
@ -553,17 +561,20 @@ describe('fs.c', function()
|
||||
itp('sets `rw` permissions for O_CREAT 600 which then can be closed', function()
|
||||
assert_file_does_not_exist(new_file)
|
||||
--create the file
|
||||
local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber("600", 8))
|
||||
local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber('600', 8))
|
||||
--verify permissions
|
||||
eq(33152, luv.fs_stat(new_file).mode)
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
|
||||
itp('returns a non-negative file descriptor for an existing file which then can be closed', function()
|
||||
itp(
|
||||
'returns a non-negative file descriptor for an existing file which then can be closed',
|
||||
function()
|
||||
local fd = os_open(existing_file, ffi.C.kO_RDWR, 0)
|
||||
assert.is_true(0 <= fd)
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
end
|
||||
)
|
||||
end)
|
||||
|
||||
describe('os_close', function()
|
||||
@ -589,43 +600,48 @@ describe('fs.c', function()
|
||||
itp('can read zero bytes from a file', function()
|
||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||
ok(fd >= 0)
|
||||
eq({false, 0, ''}, {os_read(fd, nil)})
|
||||
eq({false, 0, ''}, {os_read(fd, 0)})
|
||||
eq({ false, 0, '' }, { os_read(fd, nil) })
|
||||
eq({ false, 0, '' }, { os_read(fd, 0) })
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
|
||||
itp('can read from a file multiple times', function()
|
||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||
ok(fd >= 0)
|
||||
eq({false, 2, '\000\001'}, {os_read(fd, 2)})
|
||||
eq({false, 2, '\002\003'}, {os_read(fd, 2)})
|
||||
eq({ false, 2, '\000\001' }, { os_read(fd, 2) })
|
||||
eq({ false, 2, '\002\003' }, { os_read(fd, 2) })
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
|
||||
itp('can read the whole file at once and then report eof', function()
|
||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||
ok(fd >= 0)
|
||||
eq({false, #fcontents, fcontents}, {os_read(fd, #fcontents)})
|
||||
eq({true, 0, ('\0'):rep(#fcontents)}, {os_read(fd, #fcontents)})
|
||||
eq({ false, #fcontents, fcontents }, { os_read(fd, #fcontents) })
|
||||
eq({ true, 0, ('\0'):rep(#fcontents) }, { os_read(fd, #fcontents) })
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
|
||||
itp('can read the whole file in two calls, one partially', function()
|
||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||
ok(fd >= 0)
|
||||
eq({false, #fcontents * 3/4, fcontents:sub(1, #fcontents * 3/4)},
|
||||
{os_read(fd, #fcontents * 3/4)})
|
||||
eq({true,
|
||||
(#fcontents * 1/4),
|
||||
fcontents:sub(#fcontents * 3/4 + 1) .. ('\0'):rep(#fcontents * 2/4)},
|
||||
{os_read(fd, #fcontents * 3/4)})
|
||||
eq(
|
||||
{ false, #fcontents * 3 / 4, fcontents:sub(1, #fcontents * 3 / 4) },
|
||||
{ os_read(fd, #fcontents * 3 / 4) }
|
||||
)
|
||||
eq({
|
||||
true,
|
||||
(#fcontents * 1 / 4),
|
||||
fcontents:sub(#fcontents * 3 / 4 + 1) .. ('\0'):rep(#fcontents * 2 / 4),
|
||||
}, { os_read(fd, #fcontents * 3 / 4) })
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('os_readv', function()
|
||||
-- Function may be absent
|
||||
if not pcall(function() return fs.os_readv end) then
|
||||
if not pcall(function()
|
||||
return fs.os_readv
|
||||
end) then
|
||||
return
|
||||
end
|
||||
local file = 'test-unit-os-fs_spec-os_readv.dat'
|
||||
@ -643,45 +659,53 @@ describe('fs.c', function()
|
||||
itp('can read zero bytes from a file', function()
|
||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||
ok(fd >= 0)
|
||||
eq({false, 0, {}}, {os_readv(fd, {})})
|
||||
eq({false, 0, {'', '', ''}}, {os_readv(fd, {0, 0, 0})})
|
||||
eq({ false, 0, {} }, { os_readv(fd, {}) })
|
||||
eq({ false, 0, { '', '', '' } }, { os_readv(fd, { 0, 0, 0 }) })
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
|
||||
itp('can read from a file multiple times to a differently-sized buffers', function()
|
||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||
ok(fd >= 0)
|
||||
eq({false, 2, {'\000\001'}}, {os_readv(fd, {2})})
|
||||
eq({false, 5, {'\002\003', '\004\005\006'}}, {os_readv(fd, {2, 3})})
|
||||
eq({ false, 2, { '\000\001' } }, { os_readv(fd, { 2 }) })
|
||||
eq({ false, 5, { '\002\003', '\004\005\006' } }, { os_readv(fd, { 2, 3 }) })
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
|
||||
itp('can read the whole file at once and then report eof', function()
|
||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||
ok(fd >= 0)
|
||||
eq({false,
|
||||
eq({
|
||||
false,
|
||||
#fcontents,
|
||||
{fcontents:sub(1, #fcontents * 1/4),
|
||||
fcontents:sub(#fcontents * 1/4 + 1, #fcontents * 3/4),
|
||||
fcontents:sub(#fcontents * 3/4 + 1, #fcontents * 15/16),
|
||||
fcontents:sub(#fcontents * 15/16 + 1, #fcontents)}},
|
||||
{os_readv(fd, {#fcontents * 1/4,
|
||||
#fcontents * 2/4,
|
||||
#fcontents * 3/16,
|
||||
#fcontents * 1/16})})
|
||||
eq({true, 0, {'\0'}}, {os_readv(fd, {1})})
|
||||
{
|
||||
fcontents:sub(1, #fcontents * 1 / 4),
|
||||
fcontents:sub(#fcontents * 1 / 4 + 1, #fcontents * 3 / 4),
|
||||
fcontents:sub(#fcontents * 3 / 4 + 1, #fcontents * 15 / 16),
|
||||
fcontents:sub(#fcontents * 15 / 16 + 1, #fcontents),
|
||||
},
|
||||
}, {
|
||||
os_readv(
|
||||
fd,
|
||||
{ #fcontents * 1 / 4, #fcontents * 2 / 4, #fcontents * 3 / 16, #fcontents * 1 / 16 }
|
||||
),
|
||||
})
|
||||
eq({ true, 0, { '\0' } }, { os_readv(fd, { 1 }) })
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
|
||||
itp('can read the whole file in two calls, one partially', function()
|
||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||
ok(fd >= 0)
|
||||
eq({false, #fcontents * 3/4, {fcontents:sub(1, #fcontents * 3/4)}},
|
||||
{os_readv(fd, {#fcontents * 3/4})})
|
||||
eq({true,
|
||||
(#fcontents * 1/4),
|
||||
{fcontents:sub(#fcontents * 3/4 + 1) .. ('\0'):rep(#fcontents * 2/4)}},
|
||||
{os_readv(fd, {#fcontents * 3/4})})
|
||||
eq(
|
||||
{ false, #fcontents * 3 / 4, { fcontents:sub(1, #fcontents * 3 / 4) } },
|
||||
{ os_readv(fd, { #fcontents * 3 / 4 }) }
|
||||
)
|
||||
eq({
|
||||
true,
|
||||
(#fcontents * 1 / 4),
|
||||
{ fcontents:sub(#fcontents * 3 / 4 + 1) .. ('\0'):rep(#fcontents * 2 / 4) },
|
||||
}, { os_readv(fd, { #fcontents * 3 / 4 }) })
|
||||
eq(0, os_close(fd))
|
||||
end)
|
||||
end)
|
||||
@ -744,8 +768,8 @@ describe('fs.c', function()
|
||||
end
|
||||
|
||||
local function os_mkdir_recurse(path, mode)
|
||||
local failed_str = ffi.new('char *[1]', {nil})
|
||||
local created_str = ffi.new('char *[1]', {nil})
|
||||
local failed_str = ffi.new('char *[1]', { nil })
|
||||
local created_str = ffi.new('char *[1]', { nil })
|
||||
local ret = fs.os_mkdir_recurse(path, mode, failed_str, created_str)
|
||||
local failed_dir = failed_str[0]
|
||||
if failed_dir ~= nil then
|
||||
@ -784,8 +808,7 @@ describe('fs.c', function()
|
||||
|
||||
itp('fails to create a directory where there is a file', function()
|
||||
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
||||
'unit-test-directory/test.file', mode)
|
||||
local ret, failed_dir, created_dir = os_mkdir_recurse('unit-test-directory/test.file', mode)
|
||||
neq(0, ret)
|
||||
eq('unit-test-directory/test.file', failed_dir)
|
||||
eq(nil, created_dir)
|
||||
@ -793,8 +816,8 @@ describe('fs.c', function()
|
||||
|
||||
itp('fails to create a directory where there is a file in path', function()
|
||||
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
||||
'unit-test-directory/test.file/test', mode)
|
||||
local ret, failed_dir, created_dir =
|
||||
os_mkdir_recurse('unit-test-directory/test.file/test', mode)
|
||||
neq(0, ret)
|
||||
eq('unit-test-directory/test.file', failed_dir)
|
||||
eq(nil, created_dir)
|
||||
@ -802,8 +825,8 @@ describe('fs.c', function()
|
||||
|
||||
itp('succeeds to create a directory', function()
|
||||
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
||||
'unit-test-directory/new-dir-recurse', mode)
|
||||
local ret, failed_dir, created_dir =
|
||||
os_mkdir_recurse('unit-test-directory/new-dir-recurse', mode)
|
||||
eq(0, ret)
|
||||
eq(nil, failed_dir)
|
||||
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
|
||||
@ -814,8 +837,8 @@ describe('fs.c', function()
|
||||
|
||||
itp('succeeds to create a directory ending with ///', function()
|
||||
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
||||
'unit-test-directory/new-dir-recurse///', mode)
|
||||
local ret, failed_dir, created_dir =
|
||||
os_mkdir_recurse('unit-test-directory/new-dir-recurse///', mode)
|
||||
eq(0, ret)
|
||||
eq(nil, failed_dir)
|
||||
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
|
||||
@ -826,8 +849,8 @@ describe('fs.c', function()
|
||||
|
||||
itp('succeeds to create a directory ending with /', function()
|
||||
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
||||
'unit-test-directory/new-dir-recurse/', mode)
|
||||
local ret, failed_dir, created_dir =
|
||||
os_mkdir_recurse('unit-test-directory/new-dir-recurse/', mode)
|
||||
eq(0, ret)
|
||||
eq(nil, failed_dir)
|
||||
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
|
||||
@ -838,8 +861,8 @@ describe('fs.c', function()
|
||||
|
||||
itp('succeeds to create a directory tree', function()
|
||||
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
||||
'unit-test-directory/new-dir-recurse/1/2/3', mode)
|
||||
local ret, failed_dir, created_dir =
|
||||
os_mkdir_recurse('unit-test-directory/new-dir-recurse/1/2/3', mode)
|
||||
eq(0, ret)
|
||||
eq(nil, failed_dir)
|
||||
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
|
||||
|
@ -21,9 +21,7 @@ describe('shell functions', function()
|
||||
end)
|
||||
|
||||
local function shell_build_argv(cmd, extra_args)
|
||||
local res = cimported.shell_build_argv(
|
||||
cmd and to_cstr(cmd),
|
||||
extra_args and to_cstr(extra_args))
|
||||
local res = cimported.shell_build_argv(cmd and to_cstr(cmd), extra_args and to_cstr(extra_args))
|
||||
-- `res` is zero-indexed (C pointer, not Lua table)!
|
||||
local argc = 0
|
||||
local ret = {}
|
||||
@ -40,9 +38,7 @@ describe('shell functions', function()
|
||||
|
||||
local function shell_argv_to_str(argv_table)
|
||||
-- C string array (char **).
|
||||
local argv = (argv_table
|
||||
and ffi.new("char*[?]", #argv_table+1)
|
||||
or NULL)
|
||||
local argv = (argv_table and ffi.new('char*[?]', #argv_table + 1) or NULL)
|
||||
|
||||
local argc = 1
|
||||
while argv_table ~= nil and argv_table[argc] ~= nil do
|
||||
@ -64,8 +60,7 @@ describe('shell functions', function()
|
||||
local output = ffi.new('char *[1]')
|
||||
local nread = ffi.new('size_t[1]')
|
||||
|
||||
local argv = ffi.cast('char**',
|
||||
cimported.shell_build_argv(to_cstr(cmd), nil))
|
||||
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr(cmd), nil))
|
||||
local status = cimported.os_system(argv, input_or, input_len, output, nread)
|
||||
|
||||
return status, intern(output[0], nread[0])
|
||||
@ -101,37 +96,35 @@ describe('shell functions', function()
|
||||
|
||||
describe('shell_build_argv', function()
|
||||
itp('works with NULL arguments', function()
|
||||
eq({'/bin/sh'}, shell_build_argv(nil, nil))
|
||||
eq({ '/bin/sh' }, shell_build_argv(nil, nil))
|
||||
end)
|
||||
|
||||
itp('works with cmd', function()
|
||||
eq({'/bin/sh', '-c', 'abc def'}, shell_build_argv('abc def', nil))
|
||||
eq({ '/bin/sh', '-c', 'abc def' }, shell_build_argv('abc def', nil))
|
||||
end)
|
||||
|
||||
itp('works with extra_args', function()
|
||||
eq({'/bin/sh', 'ghi jkl'}, shell_build_argv(nil, 'ghi jkl'))
|
||||
eq({ '/bin/sh', 'ghi jkl' }, shell_build_argv(nil, 'ghi jkl'))
|
||||
end)
|
||||
|
||||
itp('works with cmd and extra_args', function()
|
||||
eq({'/bin/sh', 'ghi jkl', '-c', 'abc def'}, shell_build_argv('abc def', 'ghi jkl'))
|
||||
eq({ '/bin/sh', 'ghi jkl', '-c', 'abc def' }, shell_build_argv('abc def', 'ghi jkl'))
|
||||
end)
|
||||
|
||||
itp('splits and unquotes &shell and &shellcmdflag', function()
|
||||
cimported.p_sh = to_cstr('/Program" "Files/zsh -f')
|
||||
cimported.p_shcf = to_cstr('-x -o "sh word split" "-"c')
|
||||
eq({'/Program Files/zsh', '-f',
|
||||
'ghi jkl',
|
||||
'-x', '-o', 'sh word split',
|
||||
'-c', 'abc def'},
|
||||
shell_build_argv('abc def', 'ghi jkl'))
|
||||
eq(
|
||||
{ '/Program Files/zsh', '-f', 'ghi jkl', '-x', '-o', 'sh word split', '-c', 'abc def' },
|
||||
shell_build_argv('abc def', 'ghi jkl')
|
||||
)
|
||||
end)
|
||||
|
||||
itp('applies shellxescape (p_sxe) and shellxquote (p_sxq)', function()
|
||||
cimported.p_sxq = to_cstr('(')
|
||||
cimported.p_sxe = to_cstr('"&|<>()@^')
|
||||
|
||||
local argv = ffi.cast('char**',
|
||||
cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil))
|
||||
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil))
|
||||
eq(ffi.string(argv[0]), '/bin/sh')
|
||||
eq(ffi.string(argv[1]), '-c')
|
||||
eq(ffi.string(argv[2]), '(echo ^&^|^<^>^(^)^@^^)')
|
||||
@ -142,8 +135,7 @@ describe('shell functions', function()
|
||||
cimported.p_sxq = to_cstr('"(')
|
||||
cimported.p_sxe = to_cstr('"&|<>()@^')
|
||||
|
||||
local argv = ffi.cast('char**', cimported.shell_build_argv(
|
||||
to_cstr('echo -n some text'), nil))
|
||||
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
|
||||
eq(ffi.string(argv[0]), '/bin/sh')
|
||||
eq(ffi.string(argv[1]), '-c')
|
||||
eq(ffi.string(argv[2]), '"(echo -n some text)"')
|
||||
@ -154,8 +146,7 @@ describe('shell functions', function()
|
||||
cimported.p_sxq = to_cstr('"')
|
||||
cimported.p_sxe = to_cstr('')
|
||||
|
||||
local argv = ffi.cast('char**', cimported.shell_build_argv(
|
||||
to_cstr('echo -n some text'), nil))
|
||||
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
|
||||
eq(ffi.string(argv[0]), '/bin/sh')
|
||||
eq(ffi.string(argv[1]), '-c')
|
||||
eq(ffi.string(argv[2]), '"echo -n some text"')
|
||||
@ -163,8 +154,7 @@ describe('shell functions', function()
|
||||
end)
|
||||
|
||||
itp('with empty shellxquote/shellxescape', function()
|
||||
local argv = ffi.cast('char**', cimported.shell_build_argv(
|
||||
to_cstr('echo -n some text'), nil))
|
||||
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
|
||||
eq(ffi.string(argv[0]), '/bin/sh')
|
||||
eq(ffi.string(argv[1]), '-c')
|
||||
eq(ffi.string(argv[2]), 'echo -n some text')
|
||||
@ -176,9 +166,11 @@ describe('shell functions', function()
|
||||
eq('', shell_argv_to_str({ nil }))
|
||||
eq("''", shell_argv_to_str({ '' }))
|
||||
eq("'foo' '' 'bar'", shell_argv_to_str({ 'foo', '', 'bar' }))
|
||||
eq("'/bin/sh' '-c' 'abc def'", shell_argv_to_str({'/bin/sh', '-c', 'abc def'}))
|
||||
eq("'abc def' 'ghi jkl'", shell_argv_to_str({'abc def', 'ghi jkl'}))
|
||||
eq("'/bin/sh' '-c' 'abc def' '"..('x'):rep(225).."...",
|
||||
shell_argv_to_str({'/bin/sh', '-c', 'abc def', ('x'):rep(999)}))
|
||||
eq("'/bin/sh' '-c' 'abc def'", shell_argv_to_str({ '/bin/sh', '-c', 'abc def' }))
|
||||
eq("'abc def' 'ghi jkl'", shell_argv_to_str({ 'abc def', 'ghi jkl' }))
|
||||
eq(
|
||||
"'/bin/sh' '-c' 'abc def' '" .. ('x'):rep(225) .. '...',
|
||||
shell_argv_to_str({ '/bin/sh', '-c', 'abc def', ('x'):rep(999) })
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
@ -184,7 +184,7 @@ describe('path.c', function()
|
||||
|
||||
itp('returns the executable name of an invocation given a relative invocation', function()
|
||||
local invk, len = invocation_path_tail('directory/exe a b c')
|
||||
compare("exe a b c", invk, len)
|
||||
compare('exe a b c', invk, len)
|
||||
eq(3, len)
|
||||
end)
|
||||
|
||||
@ -202,7 +202,7 @@ describe('path.c', function()
|
||||
|
||||
itp('does not count arguments to the executable as part of its path', function()
|
||||
local invk, len = invocation_path_tail('exe a/b\\c')
|
||||
compare("exe a/b\\c", invk, len)
|
||||
compare('exe a/b\\c', invk, len)
|
||||
eq(3, len)
|
||||
end)
|
||||
|
||||
@ -212,17 +212,17 @@ describe('path.c', function()
|
||||
end)
|
||||
|
||||
itp('is equivalent to path_tail when args do not contain a path separator', function()
|
||||
local ptail = cimp.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)
|
||||
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')
|
||||
eq(tail, ffi.string(invk))
|
||||
end)
|
||||
|
||||
itp('is not equivalent to path_tail when args contain a path separator', function()
|
||||
local ptail = cimp.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)
|
||||
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)))
|
||||
end)
|
||||
end)
|
||||
@ -304,12 +304,12 @@ end)
|
||||
describe('path.c path_guess_exepath', function()
|
||||
local cwd = luv.cwd()
|
||||
|
||||
for _,name in ipairs({'./nvim', '.nvim', 'foo/nvim'}) do
|
||||
itp('"'..name..'" returns name catenated with CWD', function()
|
||||
for _, name in ipairs({ './nvim', '.nvim', 'foo/nvim' }) do
|
||||
itp('"' .. name .. '" returns name catenated with CWD', function()
|
||||
local bufsize = 255
|
||||
local buf = cstr(bufsize, '')
|
||||
cimp.path_guess_exepath(name, buf, bufsize)
|
||||
eq(cwd..'/'..name, ffi.string(buf))
|
||||
eq(cwd .. '/' .. name, ffi.string(buf))
|
||||
end)
|
||||
end
|
||||
|
||||
@ -334,7 +334,7 @@ describe('path.c path_guess_exepath', function()
|
||||
local name = 'cat' -- Some executable in $PATH.
|
||||
local bufsize = 255
|
||||
local buf = cstr(bufsize, '')
|
||||
local insane_path = orig_path_env..':'..(("x/"):rep(4097))
|
||||
local insane_path = orig_path_env .. ':' .. (('x/'):rep(4097))
|
||||
|
||||
cimp.os_setenv('PATH', insane_path, true)
|
||||
cimp.path_guess_exepath(name, buf, bufsize)
|
||||
@ -356,7 +356,7 @@ end)
|
||||
|
||||
describe('path.c', function()
|
||||
setup(function()
|
||||
mkdir('unit-test-directory');
|
||||
mkdir('unit-test-directory')
|
||||
io.open('unit-test-directory/test.file', 'w'):close()
|
||||
|
||||
-- Since the tests are executed, they are called by an executable. We use
|
||||
@ -441,7 +441,9 @@ describe('path.c', function()
|
||||
eq(OK, result)
|
||||
end)
|
||||
|
||||
itp('enters given directory (instead of just concatenating the strings) if possible and if path contains a slash', function()
|
||||
itp(
|
||||
'enters given directory (instead of just concatenating the strings) if possible and if path contains a slash',
|
||||
function()
|
||||
local old_dir = luv.cwd()
|
||||
luv.chdir('..')
|
||||
local expected = luv.cwd() .. '/test.file'
|
||||
@ -452,7 +454,8 @@ describe('path.c', function()
|
||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||
eq(expected, ffi.string(buf))
|
||||
eq(OK, result)
|
||||
end)
|
||||
end
|
||||
)
|
||||
|
||||
itp('just copies the path if it is already absolute and force=0', function()
|
||||
local absolute_path = '/absolute/path'
|
||||
@ -544,8 +547,12 @@ describe('path.c', function()
|
||||
return ffi.string(c_file)
|
||||
end
|
||||
|
||||
before_each(function() mkdir('CamelCase') end)
|
||||
after_each(function() luv.fs_rmdir('CamelCase') end)
|
||||
before_each(function()
|
||||
mkdir('CamelCase')
|
||||
end)
|
||||
after_each(function()
|
||||
luv.fs_rmdir('CamelCase')
|
||||
end)
|
||||
|
||||
if ffi.os == 'Windows' or ffi.os == 'OSX' then
|
||||
itp('Corrects the case of file names in Mac and Windows', function()
|
||||
@ -565,14 +572,14 @@ describe('path.c', function()
|
||||
local path1 = cstr(100, 'path1')
|
||||
local to_append = to_cstr('path2')
|
||||
eq(OK, (cimp.append_path(path1, to_append, 100)))
|
||||
eq("path1/path2", (ffi.string(path1)))
|
||||
eq('path1/path2', (ffi.string(path1)))
|
||||
end)
|
||||
|
||||
itp('joins given paths without adding an unnecessary slash', function()
|
||||
local path1 = cstr(100, 'path1/')
|
||||
local to_append = to_cstr('path2')
|
||||
eq(OK, cimp.append_path(path1, to_append, 100))
|
||||
eq("path1/path2", (ffi.string(path1)))
|
||||
eq('path1/path2', (ffi.string(path1)))
|
||||
end)
|
||||
|
||||
itp('fails and uses filename if there is not enough space left for to_append', function()
|
||||
|
@ -1,7 +1,7 @@
|
||||
-- helps managing loading different headers into the LuaJIT ffi. Untested on
|
||||
-- windows, will probably need quite a bit of adjustment to run there.
|
||||
|
||||
local ffi = require("ffi")
|
||||
local ffi = require('ffi')
|
||||
local global_helpers = require('test.helpers')
|
||||
|
||||
local argss_to_cmd = global_helpers.argss_to_cmd
|
||||
@ -12,37 +12,37 @@ local repeated_read_cmd = global_helpers.repeated_read_cmd
|
||||
--- @type Compiler[]
|
||||
local ccs = {}
|
||||
|
||||
local env_cc = os.getenv("CC")
|
||||
local env_cc = os.getenv('CC')
|
||||
if env_cc then
|
||||
table.insert(ccs, {path = {"/usr/bin/env", env_cc}, type = "gcc"})
|
||||
table.insert(ccs, { path = { '/usr/bin/env', env_cc }, type = 'gcc' })
|
||||
end
|
||||
|
||||
if ffi.os == "Windows" then
|
||||
table.insert(ccs, {path = {"cl"}, type = "msvc"})
|
||||
if ffi.os == 'Windows' then
|
||||
table.insert(ccs, { path = { 'cl' }, type = 'msvc' })
|
||||
end
|
||||
|
||||
table.insert(ccs, {path = {"/usr/bin/env", "cc"}, type = "gcc"})
|
||||
table.insert(ccs, {path = {"/usr/bin/env", "gcc"}, type = "gcc"})
|
||||
table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.9"}, type = "gcc"})
|
||||
table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.8"}, type = "gcc"})
|
||||
table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.7"}, type = "gcc"})
|
||||
table.insert(ccs, {path = {"/usr/bin/env", "clang"}, type = "clang"})
|
||||
table.insert(ccs, {path = {"/usr/bin/env", "icc"}, type = "gcc"})
|
||||
table.insert(ccs, { path = { '/usr/bin/env', 'cc' }, type = 'gcc' })
|
||||
table.insert(ccs, { path = { '/usr/bin/env', 'gcc' }, type = 'gcc' })
|
||||
table.insert(ccs, { path = { '/usr/bin/env', 'gcc-4.9' }, type = 'gcc' })
|
||||
table.insert(ccs, { path = { '/usr/bin/env', 'gcc-4.8' }, type = 'gcc' })
|
||||
table.insert(ccs, { path = { '/usr/bin/env', 'gcc-4.7' }, type = 'gcc' })
|
||||
table.insert(ccs, { path = { '/usr/bin/env', 'clang' }, type = 'clang' })
|
||||
table.insert(ccs, { path = { '/usr/bin/env', 'icc' }, type = 'gcc' })
|
||||
|
||||
-- parse Makefile format dependencies into a Lua table
|
||||
--- @param deps string
|
||||
--- @return string[]
|
||||
local function parse_make_deps(deps)
|
||||
-- remove line breaks and line concatenators
|
||||
deps = deps:gsub("\n", ""):gsub("\\", "")
|
||||
deps = deps:gsub('\n', ''):gsub('\\', '')
|
||||
-- remove the Makefile "target:" element
|
||||
deps = deps:gsub(".+:", "")
|
||||
deps = deps:gsub('.+:', '')
|
||||
-- remove redundant spaces
|
||||
deps = deps:gsub(" +", " ")
|
||||
deps = deps:gsub(' +', ' ')
|
||||
|
||||
-- split according to token (space in this case)
|
||||
local headers = {} --- @type string[]
|
||||
for token in deps:gmatch("[^%s]+") do
|
||||
for token in deps:gmatch('[^%s]+') do
|
||||
-- headers[token] = true
|
||||
headers[#headers + 1] = token
|
||||
end
|
||||
@ -50,9 +50,9 @@ local function parse_make_deps(deps)
|
||||
-- resolve path redirections (..) to normalize all paths
|
||||
for i, v in ipairs(headers) do
|
||||
-- double dots (..)
|
||||
headers[i] = v:gsub("/[^/%s]+/%.%.", "")
|
||||
headers[i] = v:gsub('/[^/%s]+/%.%.', '')
|
||||
-- single dot (.)
|
||||
headers[i] = v:gsub("%./", "")
|
||||
headers[i] = v:gsub('%./', '')
|
||||
end
|
||||
|
||||
return headers
|
||||
@ -80,7 +80,7 @@ local function headerize(headers, global)
|
||||
formatted[#formatted + 1] = string.format(fmt, hdr)
|
||||
end
|
||||
|
||||
return table.concat(formatted, "\n")
|
||||
return table.concat(formatted, '\n')
|
||||
end
|
||||
|
||||
--- @class Gcc
|
||||
@ -90,8 +90,8 @@ end
|
||||
--- @field get_declarations_extra_flags string[]
|
||||
local Gcc = {
|
||||
preprocessor_extra_flags = {},
|
||||
get_defines_extra_flags = {'-std=c99', '-dM', '-E'},
|
||||
get_declarations_extra_flags = {'-std=c99', '-P', '-E'},
|
||||
get_defines_extra_flags = { '-std=c99', '-dM', '-E' },
|
||||
get_declarations_extra_flags = { '-std=c99', '-P', '-E' },
|
||||
}
|
||||
|
||||
--- @param name string
|
||||
@ -115,13 +115,13 @@ end
|
||||
function Gcc:init_defines()
|
||||
-- preprocessor flags that will hopefully make the compiler produce C
|
||||
-- declarations that the LuaJIT ffi understands.
|
||||
self:define('aligned', {'ARGS'}, '')
|
||||
self:define('__attribute__', {'ARGS'}, '')
|
||||
self:define('__asm', {'ARGS'}, '')
|
||||
self:define('__asm__', {'ARGS'}, '')
|
||||
self:define('aligned', { 'ARGS' }, '')
|
||||
self:define('__attribute__', { 'ARGS' }, '')
|
||||
self:define('__asm', { 'ARGS' }, '')
|
||||
self:define('__asm__', { 'ARGS' }, '')
|
||||
self:define('__inline__', nil, '')
|
||||
self:define('EXTERN', nil, 'extern')
|
||||
self:define('INIT', {'...'}, '')
|
||||
self:define('INIT', { '...' }, '')
|
||||
self:define('_GNU_SOURCE')
|
||||
self:define('INCLUDE_GENERATED_DECLARATIONS')
|
||||
self:define('UNIT_TESTING')
|
||||
@ -158,9 +158,9 @@ end
|
||||
--- @return string[]?
|
||||
function Gcc:dependencies(hdr)
|
||||
--- @type string
|
||||
local cmd = argss_to_cmd(self.path, {'-M', hdr}) .. ' 2>&1'
|
||||
local cmd = argss_to_cmd(self.path, { '-M', hdr }) .. ' 2>&1'
|
||||
local out = assert(io.popen(cmd))
|
||||
local deps = out:read("*a")
|
||||
local deps = out:read('*a')
|
||||
out:close()
|
||||
if deps then
|
||||
return parse_make_deps(deps)
|
||||
@ -174,10 +174,14 @@ function Gcc:filter_standard_defines(defines)
|
||||
local pseudoheader_fname = 'tmp_empty_pseudoheader.h'
|
||||
local pseudoheader_file = assert(io.open(pseudoheader_fname, 'w'))
|
||||
pseudoheader_file:close()
|
||||
local standard_defines = assert(repeated_read_cmd(self.path,
|
||||
local standard_defines = assert(
|
||||
repeated_read_cmd(
|
||||
self.path,
|
||||
self.preprocessor_extra_flags,
|
||||
self.get_defines_extra_flags,
|
||||
{pseudoheader_fname}))
|
||||
{ pseudoheader_fname }
|
||||
)
|
||||
)
|
||||
os.remove(pseudoheader_fname)
|
||||
self.standard_defines = {} --- @type table<string,true>
|
||||
for line in standard_defines:gmatch('[^\n]+') do
|
||||
@ -192,7 +196,7 @@ function Gcc:filter_standard_defines(defines)
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(ret, "\n")
|
||||
return table.concat(ret, '\n')
|
||||
end
|
||||
|
||||
--- returns a stream representing a preprocessed form of the passed-in headers.
|
||||
@ -202,24 +206,33 @@ end
|
||||
--- @return string, string
|
||||
function Gcc:preprocess(previous_defines, ...)
|
||||
-- create pseudo-header
|
||||
local pseudoheader = headerize({...}, false)
|
||||
local pseudoheader = headerize({ ... }, false)
|
||||
local pseudoheader_fname = 'tmp_pseudoheader.h'
|
||||
local pseudoheader_file = assert(io.open(pseudoheader_fname, 'w'))
|
||||
pseudoheader_file:write(previous_defines)
|
||||
pseudoheader_file:write("\n")
|
||||
pseudoheader_file:write('\n')
|
||||
pseudoheader_file:write(pseudoheader)
|
||||
pseudoheader_file:flush()
|
||||
pseudoheader_file:close()
|
||||
|
||||
local defines = assert(repeated_read_cmd(self.path, self.preprocessor_extra_flags,
|
||||
local defines = assert(
|
||||
repeated_read_cmd(
|
||||
self.path,
|
||||
self.preprocessor_extra_flags,
|
||||
self.get_defines_extra_flags,
|
||||
{pseudoheader_fname}))
|
||||
{ pseudoheader_fname }
|
||||
)
|
||||
)
|
||||
defines = self:filter_standard_defines(defines)
|
||||
|
||||
local declarations = assert(repeated_read_cmd(self.path,
|
||||
local declarations = assert(
|
||||
repeated_read_cmd(
|
||||
self.path,
|
||||
self.preprocessor_extra_flags,
|
||||
self.get_declarations_extra_flags,
|
||||
{pseudoheader_fname}))
|
||||
{ pseudoheader_fname }
|
||||
)
|
||||
)
|
||||
|
||||
os.remove(pseudoheader_fname)
|
||||
|
||||
@ -233,10 +246,10 @@ end
|
||||
--- @return Gcc?
|
||||
local function find_best_cc(compilers)
|
||||
for _, meta in pairs(compilers) do
|
||||
local version = assert(io.popen(tostring(meta.path) .. " -v 2>&1"))
|
||||
local version = assert(io.popen(tostring(meta.path) .. ' -v 2>&1'))
|
||||
version:close()
|
||||
if version then
|
||||
return Gcc:new({path = meta.path})
|
||||
return Gcc:new({ path = meta.path })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -10,11 +10,11 @@ local prof = cimport('./src/nvim/profile.h')
|
||||
|
||||
local function split(inputstr, sep)
|
||||
if sep == nil then
|
||||
sep = "%s"
|
||||
sep = '%s'
|
||||
end
|
||||
|
||||
local t, i = {}, 1
|
||||
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
|
||||
for str in string.gmatch(inputstr, '([^' .. sep .. ']+)') do
|
||||
t[i] = str
|
||||
i = i + 1
|
||||
end
|
||||
@ -23,8 +23,8 @@ local function split(inputstr, sep)
|
||||
end
|
||||
|
||||
local function trim(s)
|
||||
local from = s:match"^%s*()"
|
||||
return from > #s and "" or s:match(".*%S", from)
|
||||
local from = s:match '^%s*()'
|
||||
return from > #s and '' or s:match('.*%S', from)
|
||||
end
|
||||
|
||||
local function starts(str, start)
|
||||
@ -34,25 +34,33 @@ end
|
||||
local function cmp_assert(v1, v2, op, opstr)
|
||||
local res = op(v1, v2)
|
||||
if res == false then
|
||||
print(string.format("expected: %f %s %f", v1, opstr, v2))
|
||||
print(string.format('expected: %f %s %f', v1, opstr, v2))
|
||||
end
|
||||
assert.is_true(res)
|
||||
end
|
||||
|
||||
local function lt(a, b) -- luacheck: ignore
|
||||
cmp_assert(a, b, function(x, y) return x < y end, "<")
|
||||
cmp_assert(a, b, function(x, y)
|
||||
return x < y
|
||||
end, '<')
|
||||
end
|
||||
|
||||
local function lte(a, b) -- luacheck: ignore
|
||||
cmp_assert(a, b, function(x, y) return x <= y end, "<=")
|
||||
cmp_assert(a, b, function(x, y)
|
||||
return x <= y
|
||||
end, '<=')
|
||||
end
|
||||
|
||||
local function gt(a, b) -- luacheck: ignore
|
||||
cmp_assert(a, b, function(x, y) return x > y end, ">")
|
||||
cmp_assert(a, b, function(x, y)
|
||||
return x > y
|
||||
end, '>')
|
||||
end
|
||||
|
||||
local function gte(a, b)
|
||||
cmp_assert(a, b, function(x, y) return x >= y end, ">=")
|
||||
cmp_assert(a, b, function(x, y)
|
||||
return x >= y
|
||||
end, '>=')
|
||||
end
|
||||
|
||||
-- missing functions:
|
||||
@ -61,21 +69,43 @@ end
|
||||
-- profile_set_wait
|
||||
-- profile_sub_wait
|
||||
describe('profiling related functions', function()
|
||||
local function profile_start() return prof.profile_start() end
|
||||
local function profile_end(t) return prof.profile_end(t) end
|
||||
local function profile_zero() return prof.profile_zero() end
|
||||
local function profile_setlimit(ms) return prof.profile_setlimit(ms) end
|
||||
local function profile_passed_limit(t) return prof.profile_passed_limit(t) end
|
||||
local function profile_add(t1, t2) return prof.profile_add(t1, t2) end
|
||||
local function profile_sub(t1, t2) return prof.profile_sub(t1, t2) end
|
||||
local function profile_divide(t, cnt) return prof.profile_divide(t, cnt) end
|
||||
local function profile_cmp(t1, t2) return prof.profile_cmp(t1, t2) end
|
||||
local function profile_equal(t1, t2) return prof.profile_equal(t1, t2) end
|
||||
local function profile_msg(t) return ffi.string(prof.profile_msg(t)) end
|
||||
local function profile_start()
|
||||
return prof.profile_start()
|
||||
end
|
||||
local function profile_end(t)
|
||||
return prof.profile_end(t)
|
||||
end
|
||||
local function profile_zero()
|
||||
return prof.profile_zero()
|
||||
end
|
||||
local function profile_setlimit(ms)
|
||||
return prof.profile_setlimit(ms)
|
||||
end
|
||||
local function profile_passed_limit(t)
|
||||
return prof.profile_passed_limit(t)
|
||||
end
|
||||
local function profile_add(t1, t2)
|
||||
return prof.profile_add(t1, t2)
|
||||
end
|
||||
local function profile_sub(t1, t2)
|
||||
return prof.profile_sub(t1, t2)
|
||||
end
|
||||
local function profile_divide(t, cnt)
|
||||
return prof.profile_divide(t, cnt)
|
||||
end
|
||||
local function profile_cmp(t1, t2)
|
||||
return prof.profile_cmp(t1, t2)
|
||||
end
|
||||
local function profile_equal(t1, t2)
|
||||
return prof.profile_equal(t1, t2)
|
||||
end
|
||||
local function profile_msg(t)
|
||||
return ffi.string(prof.profile_msg(t))
|
||||
end
|
||||
|
||||
local function toseconds(t) -- luacheck: ignore
|
||||
local str = trim(profile_msg(t))
|
||||
local spl = split(str, ".")
|
||||
local spl = split(str, '.')
|
||||
local s, us = spl[1], spl[2]
|
||||
return tonumber(s) + tonumber(us) / 1000000
|
||||
end
|
||||
@ -199,14 +229,14 @@ describe('profiling related functions', function()
|
||||
describe('profile_msg', function()
|
||||
itp('prints the zero time as 0.00000', function()
|
||||
local str = trim(profile_msg(profile_zero()))
|
||||
eq(str, "0.000000")
|
||||
eq(str, '0.000000')
|
||||
end)
|
||||
|
||||
itp('prints the time passed, in seconds.microsends', function()
|
||||
local start = profile_start()
|
||||
local endt = profile_end(start)
|
||||
local str = trim(profile_msg(endt))
|
||||
local spl = split(str, ".")
|
||||
local spl = split(str, '.')
|
||||
|
||||
-- string has two parts (before dot and after dot)
|
||||
eq(2, #spl)
|
||||
@ -215,11 +245,11 @@ describe('profiling related functions', function()
|
||||
|
||||
-- zero seconds have passed (if this is not true, either LuaJIT is too
|
||||
-- slow or the profiling functions are too slow and need to be fixed)
|
||||
eq(s, "0")
|
||||
eq(s, '0')
|
||||
|
||||
-- more or less the same goes for the microsecond part, if it doesn't
|
||||
-- start with 0, it's too slow.
|
||||
assert.is_true(starts(us, "0"))
|
||||
assert.is_true(starts(us, '0'))
|
||||
end)
|
||||
end)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local eq = helpers.eq
|
||||
@ -7,7 +7,7 @@ local cstr = helpers.cstr
|
||||
local to_cstr = helpers.to_cstr
|
||||
local child_call_once = helpers.child_call_once
|
||||
|
||||
local rbuffer = helpers.cimport("./test/unit/fixtures/rbuffer.h")
|
||||
local rbuffer = helpers.cimport('./test/unit/fixtures/rbuffer.h')
|
||||
|
||||
describe('rbuffer functions', function()
|
||||
local capacity = 16
|
||||
@ -56,7 +56,7 @@ describe('rbuffer functions', function()
|
||||
describe('with empty buffer in one contiguous chunk', function()
|
||||
itp('is called once with the empty chunk', function()
|
||||
collect_write_chunks()
|
||||
eq({'0000000000000000'}, chunks)
|
||||
eq({ '0000000000000000' }, chunks)
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -64,7 +64,7 @@ describe('rbuffer functions', function()
|
||||
itp('is called once with the empty chunk', function()
|
||||
write('string')
|
||||
collect_write_chunks()
|
||||
eq({'0000000000'}, chunks)
|
||||
eq({ '0000000000' }, chunks)
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -81,7 +81,7 @@ describe('rbuffer functions', function()
|
||||
write('1234567890')
|
||||
read(8)
|
||||
collect_write_chunks()
|
||||
eq({'000000', '12345678'}, chunks)
|
||||
eq({ '000000', '12345678' }, chunks)
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -90,7 +90,7 @@ describe('rbuffer functions', function()
|
||||
write('12345678')
|
||||
read(8)
|
||||
collect_write_chunks()
|
||||
eq({'00000000', '12345678'}, chunks)
|
||||
eq({ '00000000', '12345678' }, chunks)
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -129,7 +129,7 @@ describe('rbuffer functions', function()
|
||||
itp('is called once with the filled chunk', function()
|
||||
write('string')
|
||||
collect_read_chunks()
|
||||
eq({'string'}, chunks)
|
||||
eq({ 'string' }, chunks)
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -137,7 +137,7 @@ describe('rbuffer functions', function()
|
||||
itp('is called once with the filled chunk', function()
|
||||
write('abcdefghijklmnopq')
|
||||
collect_read_chunks()
|
||||
eq({'abcdefghijklmnop'}, chunks)
|
||||
eq({ 'abcdefghijklmnop' }, chunks)
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -147,7 +147,7 @@ describe('rbuffer functions', function()
|
||||
read(10)
|
||||
write('long string')
|
||||
collect_read_chunks()
|
||||
eq({'long s', 'tring'}, chunks)
|
||||
eq({ 'long s', 'tring' }, chunks)
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -157,7 +157,7 @@ describe('rbuffer functions', function()
|
||||
read(8)
|
||||
write('abcdefghijklmnopq')
|
||||
collect_read_chunks()
|
||||
eq({'abcdefgh', 'ijklmnop'}, chunks)
|
||||
eq({ 'abcdefgh', 'ijklmnop' }, chunks)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
@ -167,7 +167,7 @@ describe('rbuffer functions', function()
|
||||
|
||||
local function collect_chars()
|
||||
rbuffer.ut_rbuffer_each(rbuf, function(c, i)
|
||||
table.insert(chars, {string.char(c), tonumber(i)})
|
||||
table.insert(chars, { string.char(c), tonumber(i) })
|
||||
end)
|
||||
end
|
||||
before_each(function()
|
||||
@ -187,8 +187,19 @@ describe('rbuffer functions', function()
|
||||
read(10)
|
||||
write('long string')
|
||||
collect_chars()
|
||||
eq({{'l', 0}, {'o', 1}, {'n', 2}, {'g', 3}, {' ', 4}, {'s', 5},
|
||||
{'t', 6}, {'r', 7}, {'i', 8}, {'n', 9}, {'g', 10}}, chars)
|
||||
eq({
|
||||
{ 'l', 0 },
|
||||
{ 'o', 1 },
|
||||
{ 'n', 2 },
|
||||
{ 'g', 3 },
|
||||
{ ' ', 4 },
|
||||
{ 's', 5 },
|
||||
{ 't', 6 },
|
||||
{ 'r', 7 },
|
||||
{ 'i', 8 },
|
||||
{ 'n', 9 },
|
||||
{ 'g', 10 },
|
||||
}, chars)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
@ -198,7 +209,7 @@ describe('rbuffer functions', function()
|
||||
|
||||
local function collect_chars()
|
||||
rbuffer.ut_rbuffer_each_reverse(rbuf, function(c, i)
|
||||
table.insert(chars, {string.char(c), tonumber(i)})
|
||||
table.insert(chars, { string.char(c), tonumber(i) })
|
||||
end)
|
||||
end
|
||||
before_each(function()
|
||||
@ -218,8 +229,19 @@ describe('rbuffer functions', function()
|
||||
read(10)
|
||||
write('long string')
|
||||
collect_chars()
|
||||
eq({{'g', 10}, {'n', 9}, {'i', 8}, {'r', 7}, {'t', 6}, {'s', 5},
|
||||
{' ', 4}, {'g', 3}, {'n', 2}, {'o', 1}, {'l', 0}}, chars)
|
||||
eq({
|
||||
{ 'g', 10 },
|
||||
{ 'n', 9 },
|
||||
{ 'i', 8 },
|
||||
{ 'r', 7 },
|
||||
{ 't', 6 },
|
||||
{ 's', 5 },
|
||||
{ ' ', 4 },
|
||||
{ 'g', 3 },
|
||||
{ 'n', 2 },
|
||||
{ 'o', 1 },
|
||||
{ 'l', 0 },
|
||||
}, chars)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
@ -1,42 +1,42 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local to_cstr = helpers.to_cstr
|
||||
local eq = helpers.eq
|
||||
|
||||
local search = helpers.cimport("./src/nvim/search.h")
|
||||
local search = helpers.cimport('./src/nvim/search.h')
|
||||
local globals = helpers.cimport('./src/nvim/globals.h')
|
||||
local ffi = helpers.ffi
|
||||
|
||||
itp('pat_has_uppercase', function()
|
||||
-- works on empty string
|
||||
eq(false, search.pat_has_uppercase(to_cstr("")))
|
||||
eq(false, search.pat_has_uppercase(to_cstr('')))
|
||||
|
||||
-- works with utf uppercase
|
||||
eq(false, search.pat_has_uppercase(to_cstr("ä")))
|
||||
eq(true, search.pat_has_uppercase(to_cstr("Ä")))
|
||||
eq(true, search.pat_has_uppercase(to_cstr("äaÅ")))
|
||||
eq(false, search.pat_has_uppercase(to_cstr('ä')))
|
||||
eq(true, search.pat_has_uppercase(to_cstr('Ä')))
|
||||
eq(true, search.pat_has_uppercase(to_cstr('äaÅ')))
|
||||
|
||||
-- works when pat ends with backslash
|
||||
eq(false, search.pat_has_uppercase(to_cstr("\\")))
|
||||
eq(false, search.pat_has_uppercase(to_cstr("ab$\\")))
|
||||
eq(false, search.pat_has_uppercase(to_cstr('\\')))
|
||||
eq(false, search.pat_has_uppercase(to_cstr('ab$\\')))
|
||||
|
||||
-- skips escaped characters
|
||||
eq(false, search.pat_has_uppercase(to_cstr("\\Ab")))
|
||||
eq(true, search.pat_has_uppercase(to_cstr("\\AU")))
|
||||
eq(false, search.pat_has_uppercase(to_cstr('\\Ab')))
|
||||
eq(true, search.pat_has_uppercase(to_cstr('\\AU')))
|
||||
|
||||
-- skips _X escaped characters
|
||||
eq(false, search.pat_has_uppercase(to_cstr("\\_Ab")))
|
||||
eq(true, search.pat_has_uppercase(to_cstr("\\_AU")))
|
||||
eq(false, search.pat_has_uppercase(to_cstr('\\_Ab')))
|
||||
eq(true, search.pat_has_uppercase(to_cstr('\\_AU')))
|
||||
|
||||
-- skips %X escaped characters
|
||||
eq(false, search.pat_has_uppercase(to_cstr("aa\\%Ab")))
|
||||
eq(true, search.pat_has_uppercase(to_cstr("aab\\%AU")))
|
||||
eq(false, search.pat_has_uppercase(to_cstr('aa\\%Ab')))
|
||||
eq(true, search.pat_has_uppercase(to_cstr('aab\\%AU')))
|
||||
end)
|
||||
|
||||
describe('search_regcomp', function()
|
||||
local search_regcomp = function(pat, pat_save, pat_use, options )
|
||||
local regmatch = ffi.new("regmmatch_T")
|
||||
local search_regcomp = function(pat, pat_save, pat_use, options)
|
||||
local regmatch = ffi.new('regmmatch_T')
|
||||
local fail = search.search_regcomp(to_cstr(pat), nil, pat_save, pat_use, options, regmatch)
|
||||
return fail, regmatch
|
||||
end
|
||||
@ -45,13 +45,13 @@ describe('search_regcomp', function()
|
||||
return helpers.internalize(search.get_search_pat())
|
||||
end
|
||||
|
||||
itp("accepts regexp pattern with invalid utf", function()
|
||||
itp('accepts regexp pattern with invalid utf', function()
|
||||
--crafted to call reverse_text with invalid utf
|
||||
globals.curwin.w_onebuf_opt.wo_rl = 1
|
||||
globals.curwin.w_onebuf_opt.wo_rlc = to_cstr('s')
|
||||
globals.cmdmod.cmod_flags = globals.CMOD_KEEPPATTERNS
|
||||
local fail = search_regcomp("a\192", 0,0,0)
|
||||
local fail = search_regcomp('a\192', 0, 0, 0)
|
||||
eq(1, fail)
|
||||
eq("\192a", get_search_pat())
|
||||
eq('\192a', get_search_pat())
|
||||
end)
|
||||
end)
|
||||
|
@ -33,7 +33,7 @@ end
|
||||
|
||||
--- @return Set
|
||||
function Set:copy()
|
||||
local obj = {nelem = self.nelem, tbl = {}, items = {}} --- @type Set
|
||||
local obj = { nelem = self.nelem, tbl = {}, items = {} } --- @type Set
|
||||
for k, v in pairs(self.tbl) do
|
||||
obj.tbl[k] = v
|
||||
end
|
||||
@ -128,13 +128,13 @@ function Set:to_table()
|
||||
-- there might be gaps in @tbl, so we have to be careful and sort first
|
||||
local keys = {} --- @type string[]
|
||||
for idx, _ in pairs(self.tbl) do
|
||||
keys[#keys+1] = idx
|
||||
keys[#keys + 1] = idx
|
||||
end
|
||||
|
||||
table.sort(keys)
|
||||
local copy = {} --- @type string[]
|
||||
for _, idx in ipairs(keys) do
|
||||
copy[#copy+1] = self.tbl[idx]
|
||||
copy[#copy + 1] = self.tbl[idx]
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local to_cstr = helpers.to_cstr
|
||||
@ -6,9 +6,9 @@ local get_str = helpers.ffi.string
|
||||
local eq = helpers.eq
|
||||
local NULL = helpers.NULL
|
||||
|
||||
local buffer = helpers.cimport("./src/nvim/buffer.h")
|
||||
local globals = helpers.cimport("./src/nvim/globals.h")
|
||||
local stl = helpers.cimport("./src/nvim/statusline.h")
|
||||
local buffer = helpers.cimport('./src/nvim/buffer.h')
|
||||
local globals = helpers.cimport('./src/nvim/globals.h')
|
||||
local stl = helpers.cimport('./src/nvim/statusline.h')
|
||||
|
||||
describe('build_stl_str_hl', function()
|
||||
local buffer_byte_size = 100
|
||||
@ -22,13 +22,14 @@ describe('build_stl_str_hl', function()
|
||||
-- .fillchar The fill character used in the statusline
|
||||
-- .maximum_cell_count The number of cells available in the statusline
|
||||
local function build_stl_str_hl(arg)
|
||||
output_buffer = to_cstr(string.rep(" ", buffer_byte_size))
|
||||
output_buffer = to_cstr(string.rep(' ', buffer_byte_size))
|
||||
|
||||
local pat = arg.pat or ''
|
||||
local fillchar = arg.fillchar or (' '):byte()
|
||||
local maximum_cell_count = arg.maximum_cell_count or buffer_byte_size
|
||||
|
||||
return stl.build_stl_str_hl(globals.curwin,
|
||||
return stl.build_stl_str_hl(
|
||||
globals.curwin,
|
||||
output_buffer,
|
||||
buffer_byte_size,
|
||||
to_cstr(pat),
|
||||
@ -38,7 +39,8 @@ describe('build_stl_str_hl', function()
|
||||
maximum_cell_count,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL)
|
||||
NULL
|
||||
)
|
||||
end
|
||||
|
||||
-- Use this function to simplify testing the comparison between
|
||||
@ -54,12 +56,7 @@ describe('build_stl_str_hl', function()
|
||||
-- .expected_byte_length The expected byte length of the string (defaults to byte length of expected_stl)
|
||||
-- .file_name The name of the file to be tested (useful in %f type tests)
|
||||
-- .fillchar The character that will be used to fill any 'extra' space in the stl
|
||||
local function statusline_test(description,
|
||||
statusline_cell_count,
|
||||
input_stl,
|
||||
expected_stl,
|
||||
arg)
|
||||
|
||||
local function statusline_test(description, statusline_cell_count, input_stl, expected_stl, arg)
|
||||
-- arg is the optional parameter
|
||||
-- so we either fill in option with arg or an empty dictionary
|
||||
local option = arg or {}
|
||||
@ -75,9 +72,11 @@ describe('build_stl_str_hl', function()
|
||||
buffer.setfname(globals.curbuf, nil, NULL, 1)
|
||||
end
|
||||
|
||||
local result_cell_count = build_stl_str_hl{pat=input_stl,
|
||||
maximum_cell_count=statusline_cell_count,
|
||||
fillchar=fillchar}
|
||||
local result_cell_count = build_stl_str_hl {
|
||||
pat = input_stl,
|
||||
maximum_cell_count = statusline_cell_count,
|
||||
fillchar = fillchar,
|
||||
}
|
||||
|
||||
eq(expected_stl, get_str(output_buffer, expected_byte_length))
|
||||
eq(expected_cell_count, result_cell_count)
|
||||
@ -85,198 +84,383 @@ describe('build_stl_str_hl', function()
|
||||
end
|
||||
|
||||
-- expression testing
|
||||
statusline_test('Should expand expression', 2,
|
||||
'%!expand(20+1)', '21')
|
||||
statusline_test('Should expand broken expression to itself', 11,
|
||||
'%!expand(20+1', 'expand(20+1')
|
||||
statusline_test('Should expand expression', 2, '%!expand(20+1)', '21')
|
||||
statusline_test('Should expand broken expression to itself', 11, '%!expand(20+1', 'expand(20+1')
|
||||
|
||||
-- file name testing
|
||||
statusline_test('should print no file name', 10,
|
||||
'%f', '[No Name]',
|
||||
{expected_cell_count=9})
|
||||
statusline_test('should print the relative file name', 30,
|
||||
'%f', 'test/unit/buffer_spec.lua',
|
||||
{file_name='test/unit/buffer_spec.lua', expected_cell_count=25})
|
||||
statusline_test('should print the full file name', 40,
|
||||
'%F', '/test/unit/buffer_spec.lua',
|
||||
{file_name='/test/unit/buffer_spec.lua', expected_cell_count=26})
|
||||
statusline_test('should print no file name', 10, '%f', '[No Name]', { expected_cell_count = 9 })
|
||||
statusline_test(
|
||||
'should print the relative file name',
|
||||
30,
|
||||
'%f',
|
||||
'test/unit/buffer_spec.lua',
|
||||
{ file_name = 'test/unit/buffer_spec.lua', expected_cell_count = 25 }
|
||||
)
|
||||
statusline_test(
|
||||
'should print the full file name',
|
||||
40,
|
||||
'%F',
|
||||
'/test/unit/buffer_spec.lua',
|
||||
{ file_name = '/test/unit/buffer_spec.lua', expected_cell_count = 26 }
|
||||
)
|
||||
|
||||
-- fillchar testing
|
||||
statusline_test('should handle `!` as a fillchar', 10,
|
||||
'abcde%=', 'abcde!!!!!',
|
||||
{fillchar=('!'):byte()})
|
||||
statusline_test('should handle `~` as a fillchar', 10,
|
||||
'%=abcde', '~~~~~abcde',
|
||||
{fillchar=('~'):byte()})
|
||||
statusline_test('should put fillchar `!` in between text', 10,
|
||||
'abc%=def', 'abc!!!!def',
|
||||
{fillchar=('!'):byte()})
|
||||
statusline_test('should put fillchar `~` in between text', 10,
|
||||
'abc%=def', 'abc~~~~def',
|
||||
{fillchar=('~'):byte()})
|
||||
statusline_test('should put fillchar `━` in between text', 10,
|
||||
'abc%=def', 'abc━━━━def',
|
||||
{fillchar=0x2501})
|
||||
statusline_test('should handle zero-fillchar as a space', 10,
|
||||
'abcde%=', 'abcde ',
|
||||
{fillchar=0})
|
||||
statusline_test('should print the tail file name', 80,
|
||||
'%t', 'buffer_spec.lua',
|
||||
{file_name='test/unit/buffer_spec.lua', expected_cell_count=15})
|
||||
statusline_test(
|
||||
'should handle `!` as a fillchar',
|
||||
10,
|
||||
'abcde%=',
|
||||
'abcde!!!!!',
|
||||
{ fillchar = ('!'):byte() }
|
||||
)
|
||||
statusline_test(
|
||||
'should handle `~` as a fillchar',
|
||||
10,
|
||||
'%=abcde',
|
||||
'~~~~~abcde',
|
||||
{ fillchar = ('~'):byte() }
|
||||
)
|
||||
statusline_test(
|
||||
'should put fillchar `!` in between text',
|
||||
10,
|
||||
'abc%=def',
|
||||
'abc!!!!def',
|
||||
{ fillchar = ('!'):byte() }
|
||||
)
|
||||
statusline_test(
|
||||
'should put fillchar `~` in between text',
|
||||
10,
|
||||
'abc%=def',
|
||||
'abc~~~~def',
|
||||
{ fillchar = ('~'):byte() }
|
||||
)
|
||||
statusline_test(
|
||||
'should put fillchar `━` in between text',
|
||||
10,
|
||||
'abc%=def',
|
||||
'abc━━━━def',
|
||||
{ fillchar = 0x2501 }
|
||||
)
|
||||
statusline_test(
|
||||
'should handle zero-fillchar as a space',
|
||||
10,
|
||||
'abcde%=',
|
||||
'abcde ',
|
||||
{ fillchar = 0 }
|
||||
)
|
||||
statusline_test(
|
||||
'should print the tail file name',
|
||||
80,
|
||||
'%t',
|
||||
'buffer_spec.lua',
|
||||
{ file_name = 'test/unit/buffer_spec.lua', expected_cell_count = 15 }
|
||||
)
|
||||
|
||||
-- standard text testing
|
||||
statusline_test('should copy plain text', 80,
|
||||
'this is a test', 'this is a test',
|
||||
{expected_cell_count=14})
|
||||
statusline_test(
|
||||
'should copy plain text',
|
||||
80,
|
||||
'this is a test',
|
||||
'this is a test',
|
||||
{ expected_cell_count = 14 }
|
||||
)
|
||||
|
||||
-- line number testing
|
||||
statusline_test('should print the buffer number', 80,
|
||||
'%n', '1',
|
||||
{expected_cell_count=1})
|
||||
statusline_test('should print the current line number in the buffer', 80,
|
||||
'%l', '0',
|
||||
{expected_cell_count=1})
|
||||
statusline_test('should print the number of lines in the buffer', 80,
|
||||
'%L', '1',
|
||||
{expected_cell_count=1})
|
||||
statusline_test('should print the buffer number', 80, '%n', '1', { expected_cell_count = 1 })
|
||||
statusline_test(
|
||||
'should print the current line number in the buffer',
|
||||
80,
|
||||
'%l',
|
||||
'0',
|
||||
{ expected_cell_count = 1 }
|
||||
)
|
||||
statusline_test(
|
||||
'should print the number of lines in the buffer',
|
||||
80,
|
||||
'%L',
|
||||
'1',
|
||||
{ expected_cell_count = 1 }
|
||||
)
|
||||
|
||||
-- truncation testing
|
||||
statusline_test('should truncate when standard text pattern is too long', 10,
|
||||
'0123456789abcde', '<6789abcde')
|
||||
statusline_test('should truncate when using =', 10,
|
||||
'abcdef%=ghijkl', 'abcdef<jkl')
|
||||
statusline_test('should truncate centered text when using ==', 10,
|
||||
'abcde%=gone%=fghij', 'abcde<ghij')
|
||||
statusline_test('should respect the `<` marker', 10,
|
||||
'abc%<defghijkl', 'abc<ghijkl')
|
||||
statusline_test('should truncate at `<` with one `=`, test 1', 10,
|
||||
'abc%<def%=ghijklmno', 'abc<jklmno')
|
||||
statusline_test('should truncate at `<` with one `=`, test 2', 10,
|
||||
'abcdef%=ghijkl%<mno', 'abcdefghi>')
|
||||
statusline_test('should truncate at `<` with one `=`, test 3', 10,
|
||||
'abc%<def%=ghijklmno', 'abc<jklmno')
|
||||
statusline_test('should truncate at `<` with one `=`, test 4', 10,
|
||||
'abc%<def%=ghij', 'abcdefghij')
|
||||
statusline_test('should truncate at `<` with one `=`, test 4', 10,
|
||||
'abc%<def%=ghijk', 'abc<fghijk')
|
||||
statusline_test(
|
||||
'should truncate when standard text pattern is too long',
|
||||
10,
|
||||
'0123456789abcde',
|
||||
'<6789abcde'
|
||||
)
|
||||
statusline_test('should truncate when using =', 10, 'abcdef%=ghijkl', 'abcdef<jkl')
|
||||
statusline_test(
|
||||
'should truncate centered text when using ==',
|
||||
10,
|
||||
'abcde%=gone%=fghij',
|
||||
'abcde<ghij'
|
||||
)
|
||||
statusline_test('should respect the `<` marker', 10, 'abc%<defghijkl', 'abc<ghijkl')
|
||||
statusline_test(
|
||||
'should truncate at `<` with one `=`, test 1',
|
||||
10,
|
||||
'abc%<def%=ghijklmno',
|
||||
'abc<jklmno'
|
||||
)
|
||||
statusline_test(
|
||||
'should truncate at `<` with one `=`, test 2',
|
||||
10,
|
||||
'abcdef%=ghijkl%<mno',
|
||||
'abcdefghi>'
|
||||
)
|
||||
statusline_test(
|
||||
'should truncate at `<` with one `=`, test 3',
|
||||
10,
|
||||
'abc%<def%=ghijklmno',
|
||||
'abc<jklmno'
|
||||
)
|
||||
statusline_test('should truncate at `<` with one `=`, test 4', 10, 'abc%<def%=ghij', 'abcdefghij')
|
||||
statusline_test(
|
||||
'should truncate at `<` with one `=`, test 4',
|
||||
10,
|
||||
'abc%<def%=ghijk',
|
||||
'abc<fghijk'
|
||||
)
|
||||
|
||||
statusline_test('should truncate at `<` with many `=`, test 4', 10,
|
||||
'ab%<cdef%=g%=h%=ijk', 'ab<efghijk')
|
||||
statusline_test(
|
||||
'should truncate at `<` with many `=`, test 4',
|
||||
10,
|
||||
'ab%<cdef%=g%=h%=ijk',
|
||||
'ab<efghijk'
|
||||
)
|
||||
|
||||
statusline_test('should truncate at the first `<`', 10,
|
||||
'abc%<def%<ghijklm', 'abc<hijklm')
|
||||
statusline_test('should truncate at the first `<`', 10, 'abc%<def%<ghijklm', 'abc<hijklm')
|
||||
|
||||
statusline_test('should ignore trailing %', 3, 'abc%', 'abc')
|
||||
|
||||
-- alignment testing with fillchar
|
||||
local function statusline_test_align(description,
|
||||
local function statusline_test_align(
|
||||
description,
|
||||
statusline_cell_count,
|
||||
input_stl,
|
||||
expected_stl,
|
||||
arg)
|
||||
arg
|
||||
)
|
||||
arg = arg or {}
|
||||
statusline_test(description .. ' without fillchar',
|
||||
statusline_cell_count, input_stl, expected_stl:gsub('%~', ' '), arg)
|
||||
statusline_test(
|
||||
description .. ' without fillchar',
|
||||
statusline_cell_count,
|
||||
input_stl,
|
||||
expected_stl:gsub('%~', ' '),
|
||||
arg
|
||||
)
|
||||
arg.fillchar = ('!'):byte()
|
||||
statusline_test(description .. ' with fillchar `!`',
|
||||
statusline_cell_count, input_stl, expected_stl:gsub('%~', '!'), arg)
|
||||
statusline_test(
|
||||
description .. ' with fillchar `!`',
|
||||
statusline_cell_count,
|
||||
input_stl,
|
||||
expected_stl:gsub('%~', '!'),
|
||||
arg
|
||||
)
|
||||
arg.fillchar = 0x2501
|
||||
statusline_test(description .. ' with fillchar `━`',
|
||||
statusline_cell_count, input_stl, expected_stl:gsub('%~', '━'), arg)
|
||||
statusline_test(
|
||||
description .. ' with fillchar `━`',
|
||||
statusline_cell_count,
|
||||
input_stl,
|
||||
expected_stl:gsub('%~', '━'),
|
||||
arg
|
||||
)
|
||||
end
|
||||
|
||||
statusline_test_align('should right align when using =', 20,
|
||||
'neo%=vim', 'neo~~~~~~~~~~~~~~vim')
|
||||
statusline_test_align('should, when possible, center text when using %=text%=', 20,
|
||||
'abc%=neovim%=def', 'abc~~~~neovim~~~~def')
|
||||
statusline_test_align('should handle uneven spacing in the buffer when using %=text%=', 20,
|
||||
'abc%=neo_vim%=def', 'abc~~~neo_vim~~~~def')
|
||||
statusline_test_align('should have equal spaces even with non-equal sides when using =', 20,
|
||||
'foobar%=test%=baz', 'foobar~~~test~~~~baz')
|
||||
statusline_test_align('should have equal spaces even with longer right side when using =', 20,
|
||||
'a%=test%=longtext', 'a~~~test~~~~longtext')
|
||||
statusline_test_align('should handle an empty left side when using ==', 20,
|
||||
'%=test%=baz', '~~~~~~test~~~~~~~baz')
|
||||
statusline_test_align('should handle an empty right side when using ==', 20,
|
||||
'foobar%=test%=', 'foobar~~~~~test~~~~~')
|
||||
statusline_test_align('should handle consecutive empty ==', 20,
|
||||
'%=%=test%=', '~~~~~~~~~~test~~~~~~')
|
||||
statusline_test_align('should handle an = alone', 20,
|
||||
'%=', '~~~~~~~~~~~~~~~~~~~~')
|
||||
statusline_test_align('should right align text when it is alone with =', 20,
|
||||
'%=foo', '~~~~~~~~~~~~~~~~~foo')
|
||||
statusline_test_align('should left align text when it is alone with =', 20,
|
||||
'foo%=', 'foo~~~~~~~~~~~~~~~~~')
|
||||
statusline_test_align('should right align when using =', 20, 'neo%=vim', 'neo~~~~~~~~~~~~~~vim')
|
||||
statusline_test_align(
|
||||
'should, when possible, center text when using %=text%=',
|
||||
20,
|
||||
'abc%=neovim%=def',
|
||||
'abc~~~~neovim~~~~def'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should handle uneven spacing in the buffer when using %=text%=',
|
||||
20,
|
||||
'abc%=neo_vim%=def',
|
||||
'abc~~~neo_vim~~~~def'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should have equal spaces even with non-equal sides when using =',
|
||||
20,
|
||||
'foobar%=test%=baz',
|
||||
'foobar~~~test~~~~baz'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should have equal spaces even with longer right side when using =',
|
||||
20,
|
||||
'a%=test%=longtext',
|
||||
'a~~~test~~~~longtext'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should handle an empty left side when using ==',
|
||||
20,
|
||||
'%=test%=baz',
|
||||
'~~~~~~test~~~~~~~baz'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should handle an empty right side when using ==',
|
||||
20,
|
||||
'foobar%=test%=',
|
||||
'foobar~~~~~test~~~~~'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should handle consecutive empty ==',
|
||||
20,
|
||||
'%=%=test%=',
|
||||
'~~~~~~~~~~test~~~~~~'
|
||||
)
|
||||
statusline_test_align('should handle an = alone', 20, '%=', '~~~~~~~~~~~~~~~~~~~~')
|
||||
statusline_test_align(
|
||||
'should right align text when it is alone with =',
|
||||
20,
|
||||
'%=foo',
|
||||
'~~~~~~~~~~~~~~~~~foo'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should left align text when it is alone with =',
|
||||
20,
|
||||
'foo%=',
|
||||
'foo~~~~~~~~~~~~~~~~~'
|
||||
)
|
||||
|
||||
statusline_test_align('should approximately center text when using %=text%=', 21,
|
||||
'abc%=neovim%=def', 'abc~~~~neovim~~~~~def')
|
||||
statusline_test_align('should completely fill the buffer when using %=text%=', 21,
|
||||
'abc%=neo_vim%=def', 'abc~~~~neo_vim~~~~def')
|
||||
statusline_test_align('should have equal spacing even with non-equal sides when using =', 21,
|
||||
'foobar%=test%=baz', 'foobar~~~~test~~~~baz')
|
||||
statusline_test_align('should have equal spacing even with longer right side when using =', 21,
|
||||
'a%=test%=longtext', 'a~~~~test~~~~longtext')
|
||||
statusline_test_align('should handle an empty left side when using ==', 21,
|
||||
'%=test%=baz', '~~~~~~~test~~~~~~~baz')
|
||||
statusline_test_align('should handle an empty right side when using ==', 21,
|
||||
'foobar%=test%=', 'foobar~~~~~test~~~~~~')
|
||||
statusline_test_align(
|
||||
'should approximately center text when using %=text%=',
|
||||
21,
|
||||
'abc%=neovim%=def',
|
||||
'abc~~~~neovim~~~~~def'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should completely fill the buffer when using %=text%=',
|
||||
21,
|
||||
'abc%=neo_vim%=def',
|
||||
'abc~~~~neo_vim~~~~def'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should have equal spacing even with non-equal sides when using =',
|
||||
21,
|
||||
'foobar%=test%=baz',
|
||||
'foobar~~~~test~~~~baz'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should have equal spacing even with longer right side when using =',
|
||||
21,
|
||||
'a%=test%=longtext',
|
||||
'a~~~~test~~~~longtext'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should handle an empty left side when using ==',
|
||||
21,
|
||||
'%=test%=baz',
|
||||
'~~~~~~~test~~~~~~~baz'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should handle an empty right side when using ==',
|
||||
21,
|
||||
'foobar%=test%=',
|
||||
'foobar~~~~~test~~~~~~'
|
||||
)
|
||||
|
||||
statusline_test_align('should quadrant the text when using 3 %=', 40,
|
||||
'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~ef')
|
||||
statusline_test_align('should work well with %t', 40,
|
||||
'%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~right_aligned',
|
||||
{file_name='test/unit/buffer_spec.lua'})
|
||||
statusline_test_align('should work well with %t and regular text', 40,
|
||||
'l%=m_l %t m_r%=r', 'l~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
|
||||
{file_name='test/unit/buffer_spec.lua'})
|
||||
statusline_test_align('should work well with %=, %t, %L, and %l', 40,
|
||||
'%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~ 1 ~~~~~~~~~~ 0',
|
||||
{file_name='test/unit/buffer_spec.lua'})
|
||||
statusline_test_align(
|
||||
'should quadrant the text when using 3 %=',
|
||||
40,
|
||||
'abcd%=n%=eovim%=ef',
|
||||
'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~ef'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should work well with %t',
|
||||
40,
|
||||
'%t%=right_aligned',
|
||||
'buffer_spec.lua~~~~~~~~~~~~right_aligned',
|
||||
{ file_name = 'test/unit/buffer_spec.lua' }
|
||||
)
|
||||
statusline_test_align(
|
||||
'should work well with %t and regular text',
|
||||
40,
|
||||
'l%=m_l %t m_r%=r',
|
||||
'l~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
|
||||
{ file_name = 'test/unit/buffer_spec.lua' }
|
||||
)
|
||||
statusline_test_align(
|
||||
'should work well with %=, %t, %L, and %l',
|
||||
40,
|
||||
'%t %= %L %= %l',
|
||||
'buffer_spec.lua ~~~~~~~~~ 1 ~~~~~~~~~~ 0',
|
||||
{ file_name = 'test/unit/buffer_spec.lua' }
|
||||
)
|
||||
|
||||
statusline_test_align('should quadrant the text when using 3 %=', 41,
|
||||
'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~~ef')
|
||||
statusline_test_align('should work well with %t', 41,
|
||||
'%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~~right_aligned',
|
||||
{file_name='test/unit/buffer_spec.lua'})
|
||||
statusline_test_align('should work well with %t and regular text', 41,
|
||||
'l%=m_l %t m_r%=r', 'l~~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
|
||||
{file_name='test/unit/buffer_spec.lua'})
|
||||
statusline_test_align('should work well with %=, %t, %L, and %l', 41,
|
||||
'%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~~ 1 ~~~~~~~~~~ 0',
|
||||
{file_name='test/unit/buffer_spec.lua'})
|
||||
statusline_test_align(
|
||||
'should quadrant the text when using 3 %=',
|
||||
41,
|
||||
'abcd%=n%=eovim%=ef',
|
||||
'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~~ef'
|
||||
)
|
||||
statusline_test_align(
|
||||
'should work well with %t',
|
||||
41,
|
||||
'%t%=right_aligned',
|
||||
'buffer_spec.lua~~~~~~~~~~~~~right_aligned',
|
||||
{ file_name = 'test/unit/buffer_spec.lua' }
|
||||
)
|
||||
statusline_test_align(
|
||||
'should work well with %t and regular text',
|
||||
41,
|
||||
'l%=m_l %t m_r%=r',
|
||||
'l~~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
|
||||
{ file_name = 'test/unit/buffer_spec.lua' }
|
||||
)
|
||||
statusline_test_align(
|
||||
'should work well with %=, %t, %L, and %l',
|
||||
41,
|
||||
'%t %= %L %= %l',
|
||||
'buffer_spec.lua ~~~~~~~~~~ 1 ~~~~~~~~~~ 0',
|
||||
{ file_name = 'test/unit/buffer_spec.lua' }
|
||||
)
|
||||
|
||||
statusline_test_align('should work with 10 %=', 50,
|
||||
statusline_test_align(
|
||||
'should work with 10 %=',
|
||||
50,
|
||||
'aaaa%=b%=c%=d%=e%=fg%=hi%=jk%=lmnop%=qrstuv%=wxyz',
|
||||
'aaaa~~b~~c~~d~~e~~fg~~hi~~jk~~lmnop~~qrstuv~~~wxyz')
|
||||
'aaaa~~b~~c~~d~~e~~fg~~hi~~jk~~lmnop~~qrstuv~~~wxyz'
|
||||
)
|
||||
|
||||
-- stl item testing
|
||||
local tabline = ''
|
||||
for i = 1, 1000 do
|
||||
tabline = tabline .. (i % 2 == 0 and '%#TabLineSel#' or '%#TabLineFill#') .. tostring(i % 2)
|
||||
end
|
||||
statusline_test('should handle a large amount of any items', 20,
|
||||
tabline,
|
||||
'<1010101010101010101') -- Should not show any error
|
||||
statusline_test('should handle a larger amount of = than stl initial item', 20,
|
||||
statusline_test('should handle a large amount of any items', 20, tabline, '<1010101010101010101') -- Should not show any error
|
||||
statusline_test(
|
||||
'should handle a larger amount of = than stl initial item',
|
||||
20,
|
||||
('%='):rep(STL_INITIAL_ITEMS * 5),
|
||||
' ') -- Should not show any error
|
||||
statusline_test('should handle many extra characters', 20,
|
||||
' '
|
||||
) -- Should not show any error
|
||||
statusline_test(
|
||||
'should handle many extra characters',
|
||||
20,
|
||||
'a' .. ('a'):rep(STL_INITIAL_ITEMS * 5),
|
||||
'<aaaaaaaaaaaaaaaaaaa') -- Does not show any error
|
||||
statusline_test('should handle many extra characters and flags', 20,
|
||||
'<aaaaaaaaaaaaaaaaaaa'
|
||||
) -- Does not show any error
|
||||
statusline_test(
|
||||
'should handle many extra characters and flags',
|
||||
20,
|
||||
'a' .. ('%=a'):rep(STL_INITIAL_ITEMS * 2),
|
||||
'a<aaaaaaaaaaaaaaaaaa') -- Should not show any error
|
||||
'a<aaaaaaaaaaaaaaaaaa'
|
||||
) -- Should not show any error
|
||||
|
||||
-- multi-byte testing
|
||||
statusline_test('should handle multibyte characters', 10,
|
||||
'Ĉ%=x', 'Ĉ x')
|
||||
statusline_test('should handle multibyte characters and different fillchars', 10,
|
||||
'Ą%=mid%=end', 'Ą@mid@@end',
|
||||
{fillchar=('@'):byte()})
|
||||
statusline_test('should handle multibyte characters', 10, 'Ĉ%=x', 'Ĉ x')
|
||||
statusline_test(
|
||||
'should handle multibyte characters and different fillchars',
|
||||
10,
|
||||
'Ą%=mid%=end',
|
||||
'Ą@mid@@end',
|
||||
{ fillchar = ('@'):byte() }
|
||||
)
|
||||
|
||||
-- escaping % testing
|
||||
statusline_test('should handle escape of %', 4, 'abc%%', 'abc%')
|
||||
statusline_test('case where escaped % does not fit', 3, 'abc%%abcabc', '<bc')
|
||||
statusline_test('escaped % is first', 1, '%%', '%')
|
||||
|
||||
end)
|
||||
|
@ -1,4 +1,4 @@
|
||||
local helpers = require("test.unit.helpers")(after_each)
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local itp = helpers.gen_itp(it)
|
||||
|
||||
local cimport = helpers.cimport
|
||||
@ -6,8 +6,7 @@ local eq = helpers.eq
|
||||
local ffi = helpers.ffi
|
||||
local to_cstr = helpers.to_cstr
|
||||
|
||||
local strings = cimport('stdlib.h', './src/nvim/strings.h',
|
||||
'./src/nvim/memory.h')
|
||||
local strings = cimport('stdlib.h', './src/nvim/strings.h', './src/nvim/memory.h')
|
||||
|
||||
describe('vim_strsave_escaped()', function()
|
||||
local vim_strsave_escaped = function(s, chars)
|
||||
@ -21,19 +20,19 @@ describe('vim_strsave_escaped()', function()
|
||||
end
|
||||
|
||||
itp('precedes by a backslash all chars from second argument', function()
|
||||
eq([[\a\b\c\d]], vim_strsave_escaped('abcd','abcd'))
|
||||
eq([[\a\b\c\d]], vim_strsave_escaped('abcd', 'abcd'))
|
||||
end)
|
||||
|
||||
itp('precedes by a backslash chars only from second argument', function()
|
||||
eq([[\a\bcd]], vim_strsave_escaped('abcd','ab'))
|
||||
eq([[\a\bcd]], vim_strsave_escaped('abcd', 'ab'))
|
||||
end)
|
||||
|
||||
itp('returns a copy of passed string if second argument is empty', function()
|
||||
eq('text \n text', vim_strsave_escaped('text \n text',''))
|
||||
eq('text \n text', vim_strsave_escaped('text \n text', ''))
|
||||
end)
|
||||
|
||||
itp('returns an empty string if first argument is empty string', function()
|
||||
eq('', vim_strsave_escaped('','\r'))
|
||||
eq('', vim_strsave_escaped('', '\r'))
|
||||
end)
|
||||
|
||||
itp('returns a copy of passed string if it does not contain chars from 2nd argument', function()
|
||||
@ -148,14 +147,30 @@ describe('vim_snprintf()', function()
|
||||
end
|
||||
end
|
||||
|
||||
local function i(n) return ffi.cast('int', n) end
|
||||
local function l(n) return ffi.cast('long', n) end
|
||||
local function ll(n) return ffi.cast('long long', n) end
|
||||
local function z(n) return ffi.cast('ptrdiff_t', n) end
|
||||
local function u(n) return ffi.cast('unsigned', n) end
|
||||
local function ul(n) return ffi.cast('unsigned long', n) end
|
||||
local function ull(n) return ffi.cast('unsigned long long', n) end
|
||||
local function uz(n) return ffi.cast('size_t', n) end
|
||||
local function i(n)
|
||||
return ffi.cast('int', n)
|
||||
end
|
||||
local function l(n)
|
||||
return ffi.cast('long', n)
|
||||
end
|
||||
local function ll(n)
|
||||
return ffi.cast('long long', n)
|
||||
end
|
||||
local function z(n)
|
||||
return ffi.cast('ptrdiff_t', n)
|
||||
end
|
||||
local function u(n)
|
||||
return ffi.cast('unsigned', n)
|
||||
end
|
||||
local function ul(n)
|
||||
return ffi.cast('unsigned long', n)
|
||||
end
|
||||
local function ull(n)
|
||||
return ffi.cast('unsigned long long', n)
|
||||
end
|
||||
local function uz(n)
|
||||
return ffi.cast('size_t', n)
|
||||
end
|
||||
|
||||
itp('truncation', function()
|
||||
for bsize = 0, 14 do
|
||||
@ -232,49 +247,51 @@ describe('vim_snprintf()', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('strcase_save()' , function()
|
||||
describe('strcase_save()', function()
|
||||
local strcase_save = function(input_string, upper)
|
||||
local res = strings.strcase_save(to_cstr(input_string), upper)
|
||||
return ffi.string(res)
|
||||
end
|
||||
|
||||
itp('decodes overlong encoded characters.', function()
|
||||
eq("A", strcase_save("\xc1\x81", true))
|
||||
eq("a", strcase_save("\xc1\x81", false))
|
||||
eq('A', strcase_save('\xc1\x81', true))
|
||||
eq('a', strcase_save('\xc1\x81', false))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("reverse_text", function()
|
||||
describe('reverse_text', function()
|
||||
local reverse_text = function(str)
|
||||
return helpers.internalize(strings.reverse_text(to_cstr(str)))
|
||||
end
|
||||
|
||||
itp("handles empty string", function()
|
||||
eq("", reverse_text(""))
|
||||
itp('handles empty string', function()
|
||||
eq('', reverse_text(''))
|
||||
end)
|
||||
|
||||
itp("handles simple cases", function()
|
||||
eq("a", reverse_text("a"))
|
||||
eq("ba", reverse_text("ab"))
|
||||
itp('handles simple cases', function()
|
||||
eq('a', reverse_text('a'))
|
||||
eq('ba', reverse_text('ab'))
|
||||
end)
|
||||
|
||||
itp("handles multibyte characters", function()
|
||||
eq("bα", reverse_text("αb"))
|
||||
eq("Yötön yö", reverse_text("öy nötöY"))
|
||||
itp('handles multibyte characters', function()
|
||||
eq('bα', reverse_text('αb'))
|
||||
eq('Yötön yö', reverse_text('öy nötöY'))
|
||||
end)
|
||||
|
||||
itp("handles combining chars", function()
|
||||
local utf8_COMBINING_RING_ABOVE = "\204\138"
|
||||
local utf8_COMBINING_RING_BELOW = "\204\165"
|
||||
eq("bba" .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. "aa",
|
||||
reverse_text("aaa" .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. "bb"))
|
||||
itp('handles combining chars', function()
|
||||
local utf8_COMBINING_RING_ABOVE = '\204\138'
|
||||
local utf8_COMBINING_RING_BELOW = '\204\165'
|
||||
eq(
|
||||
'bba' .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. 'aa',
|
||||
reverse_text('aaa' .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. 'bb')
|
||||
)
|
||||
end)
|
||||
|
||||
itp("treats invalid utf as separate characters", function()
|
||||
eq("\192ba", reverse_text("ab\192"))
|
||||
itp('treats invalid utf as separate characters', function()
|
||||
eq('\192ba', reverse_text('ab\192'))
|
||||
end)
|
||||
|
||||
itp("treats an incomplete utf continuation sequence as valid", function()
|
||||
eq("\194ba", reverse_text("ab\194"))
|
||||
itp('treats an incomplete utf continuation sequence as valid', function()
|
||||
eq('\194ba', reverse_text('ab\194'))
|
||||
end)
|
||||
end)
|
||||
|
@ -39,7 +39,6 @@ child_call_once(function()
|
||||
undo.u_compute_hash(file_buffer, buffer_hash)
|
||||
end)
|
||||
|
||||
|
||||
describe('u_write_undo', function()
|
||||
setup(function()
|
||||
mkdir('unit-test-directory')
|
||||
@ -68,7 +67,7 @@ describe('u_write_undo', function()
|
||||
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")
|
||||
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.
|
||||
@ -78,9 +77,9 @@ describe('u_write_undo', function()
|
||||
end)
|
||||
|
||||
itp('writes a correctly-named undo file to undodir given a name, buffer, and hash', function()
|
||||
local correct_name = "undofile.test"
|
||||
local correct_name = 'undofile.test'
|
||||
u_write_undo(correct_name, false, file_buffer, buffer_hash)
|
||||
local undo_file = io.open(correct_name, "r")
|
||||
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.
|
||||
@ -96,9 +95,9 @@ describe('u_write_undo', function()
|
||||
|
||||
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")
|
||||
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 = luv.fs_stat(test_file_name).mode
|
||||
|
||||
@ -129,7 +128,7 @@ describe('u_write_undo', function()
|
||||
|
||||
itp('writes an undofile only readable by the user if the buffer is unnamed', function()
|
||||
local correct_permissions = 33152
|
||||
local undo_file_name = "test.undo"
|
||||
local undo_file_name = 'test.undo'
|
||||
|
||||
-- Create vim buffer
|
||||
file_buffer = buffer.buflist_new(nil, nil, 1, buffer.BLN_LISTED)
|
||||
@ -149,7 +148,7 @@ describe('u_write_undo', function()
|
||||
end)
|
||||
|
||||
itp('forces writing undo file for :wundo! command', function()
|
||||
local file_contents = "testing permissions"
|
||||
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))
|
||||
helpers.write_file(correct_name, file_contents, true, false)
|
||||
@ -198,13 +197,13 @@ describe('u_write_undo', 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")
|
||||
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")
|
||||
local undo_file = io.open(correct_name, 'r')
|
||||
|
||||
eq(undo_file, nil)
|
||||
end)
|
||||
|
@ -83,24 +83,23 @@ local function eltkn2lua(pstate, tkn)
|
||||
type = conv_eltkn_type(tkn.type),
|
||||
}
|
||||
pstate_set_str(pstate, tkn.start, tkn.len, ret)
|
||||
if not ret.error and (#(ret.str) ~= ret.len) then
|
||||
if not ret.error and (#ret.str ~= ret.len) then
|
||||
ret.error = '#str /= len'
|
||||
end
|
||||
if ret.type == 'Comparison' then
|
||||
ret.data = {
|
||||
type = conv_cmp_type(tkn.data.cmp.type),
|
||||
ccs = conv_ccs(tkn.data.cmp.ccs),
|
||||
inv = (not not tkn.data.cmp.inv),
|
||||
inv = not not tkn.data.cmp.inv,
|
||||
}
|
||||
elseif ret.type == 'Multiplication' then
|
||||
ret.data = { type = conv_enum(eltkn_mul_type_tab, tkn.data.mul.type) }
|
||||
elseif bracket_types[ret.type] then
|
||||
ret.data = { closing = (not not tkn.data.brc.closing) }
|
||||
ret.data = { closing = not not tkn.data.brc.closing }
|
||||
elseif ret.type == 'Register' then
|
||||
ret.data = { name = intchar2lua(tkn.data.reg.name) }
|
||||
elseif (ret.type == 'SingleQuotedString'
|
||||
or ret.type == 'DoubleQuotedString') then
|
||||
ret.data = { closed = (not not tkn.data.str.closed) }
|
||||
elseif ret.type == 'SingleQuotedString' or ret.type == 'DoubleQuotedString' then
|
||||
ret.data = { closed = not not tkn.data.str.closed }
|
||||
elseif ret.type == 'Option' then
|
||||
ret.data = {
|
||||
scope = conv_enum(eltkn_opt_scope_tab, tkn.data.opt.scope),
|
||||
@ -109,16 +108,15 @@ local function eltkn2lua(pstate, tkn)
|
||||
elseif ret.type == 'PlainIdentifier' then
|
||||
ret.data = {
|
||||
scope = intchar2lua(tkn.data.var.scope),
|
||||
autoload = (not not tkn.data.var.autoload),
|
||||
autoload = not not tkn.data.var.autoload,
|
||||
}
|
||||
elseif ret.type == 'Number' then
|
||||
ret.data = {
|
||||
is_float = (not not tkn.data.num.is_float),
|
||||
is_float = not not tkn.data.num.is_float,
|
||||
base = tonumber(tkn.data.num.base),
|
||||
}
|
||||
ret.data.val = tonumber(tkn.data.num.is_float
|
||||
and tkn.data.num.val.floating
|
||||
or tkn.data.num.val.integer)
|
||||
ret.data.val =
|
||||
tonumber(tkn.data.num.is_float and tkn.data.num.val.floating or tkn.data.num.val.integer)
|
||||
elseif ret.type == 'Assignment' then
|
||||
ret.data = { type = conv_expr_asgn_type(tkn.data.ass.type) }
|
||||
elseif ret.type == 'Invalid' then
|
||||
@ -150,156 +148,263 @@ describe('Expressions lexer', function()
|
||||
end
|
||||
end
|
||||
local function singl_eltkn_test(typ, str, data)
|
||||
local pstate = new_pstate({str})
|
||||
eq({data=data, len=#str, start={col=0, line=0}, str=str, type=typ},
|
||||
next_eltkn(pstate, flags))
|
||||
local pstate = new_pstate({ str })
|
||||
eq(
|
||||
{ data = data, len = #str, start = { col = 0, line = 0 }, str = str, type = typ },
|
||||
next_eltkn(pstate, flags)
|
||||
)
|
||||
check_advance(pstate, #str, 0)
|
||||
if not (
|
||||
if
|
||||
not (
|
||||
typ == 'Spacing'
|
||||
or (typ == 'Register' and str == '@')
|
||||
or ((typ == 'SingleQuotedString' or typ == 'DoubleQuotedString')
|
||||
and not data.closed)
|
||||
) then
|
||||
pstate = new_pstate({str .. ' '})
|
||||
eq({data=data, len=#str, start={col=0, line=0}, str=str, type=typ},
|
||||
next_eltkn(pstate, flags))
|
||||
or ((typ == 'SingleQuotedString' or typ == 'DoubleQuotedString') and not data.closed)
|
||||
)
|
||||
then
|
||||
pstate = new_pstate({ str .. ' ' })
|
||||
eq(
|
||||
{ data = data, len = #str, start = { col = 0, line = 0 }, str = str, type = typ },
|
||||
next_eltkn(pstate, flags)
|
||||
)
|
||||
check_advance(pstate, #str, 0)
|
||||
end
|
||||
pstate = new_pstate({'x' .. str})
|
||||
pstate = new_pstate({ 'x' .. str })
|
||||
pstate.pos.col = 1
|
||||
eq({data=data, len=#str, start={col=1, line=0}, str=str, type=typ},
|
||||
next_eltkn(pstate, flags))
|
||||
eq(
|
||||
{ data = data, len = #str, start = { col = 1, line = 0 }, str = str, type = typ },
|
||||
next_eltkn(pstate, flags)
|
||||
)
|
||||
check_advance(pstate, #str, 1)
|
||||
end
|
||||
local function scope_test(scope)
|
||||
singl_eltkn_test('PlainIdentifier', scope .. ':test#var', {autoload=true, scope=scope})
|
||||
singl_eltkn_test('PlainIdentifier', scope .. ':', {autoload=false, scope=scope})
|
||||
singl_eltkn_test('PlainIdentifier', scope .. ':test#var', { autoload = true, scope = scope })
|
||||
singl_eltkn_test('PlainIdentifier', scope .. ':', { autoload = false, scope = scope })
|
||||
end
|
||||
local function comparison_test(op, inv_op, cmp_type)
|
||||
singl_eltkn_test('Comparison', op, {type=cmp_type, inv=false, ccs='UseOption'})
|
||||
singl_eltkn_test('Comparison', inv_op, {type=cmp_type, inv=true, ccs='UseOption'})
|
||||
singl_eltkn_test('Comparison', op .. '#', {type=cmp_type, inv=false, ccs='MatchCase'})
|
||||
singl_eltkn_test('Comparison', inv_op .. '#', {type=cmp_type, inv=true, ccs='MatchCase'})
|
||||
singl_eltkn_test('Comparison', op .. '?', {type=cmp_type, inv=false, ccs='IgnoreCase'})
|
||||
singl_eltkn_test('Comparison', inv_op .. '?', {type=cmp_type, inv=true, ccs='IgnoreCase'})
|
||||
singl_eltkn_test('Comparison', op, { type = cmp_type, inv = false, ccs = 'UseOption' })
|
||||
singl_eltkn_test('Comparison', inv_op, { type = cmp_type, inv = true, ccs = 'UseOption' })
|
||||
singl_eltkn_test('Comparison', op .. '#', { type = cmp_type, inv = false, ccs = 'MatchCase' })
|
||||
singl_eltkn_test(
|
||||
'Comparison',
|
||||
inv_op .. '#',
|
||||
{ type = cmp_type, inv = true, ccs = 'MatchCase' }
|
||||
)
|
||||
singl_eltkn_test('Comparison', op .. '?', { type = cmp_type, inv = false, ccs = 'IgnoreCase' })
|
||||
singl_eltkn_test(
|
||||
'Comparison',
|
||||
inv_op .. '?',
|
||||
{ type = cmp_type, inv = true, ccs = 'IgnoreCase' }
|
||||
)
|
||||
end
|
||||
local function simple_test(pstate_arg, exp_type, exp_len, exp)
|
||||
local pstate = new_pstate(pstate_arg)
|
||||
exp = shallowcopy(exp)
|
||||
exp.type = exp_type
|
||||
exp.len = exp_len or #(pstate_arg[0])
|
||||
exp.len = exp_len or #pstate_arg[0]
|
||||
exp.start = { col = 0, line = 0 }
|
||||
eq(exp, next_eltkn(pstate, flags))
|
||||
end
|
||||
local function stable_tests()
|
||||
singl_eltkn_test('Parenthesis', '(', {closing=false})
|
||||
singl_eltkn_test('Parenthesis', ')', {closing=true})
|
||||
singl_eltkn_test('Bracket', '[', {closing=false})
|
||||
singl_eltkn_test('Bracket', ']', {closing=true})
|
||||
singl_eltkn_test('FigureBrace', '{', {closing=false})
|
||||
singl_eltkn_test('FigureBrace', '}', {closing=true})
|
||||
singl_eltkn_test('Parenthesis', '(', { closing = false })
|
||||
singl_eltkn_test('Parenthesis', ')', { closing = true })
|
||||
singl_eltkn_test('Bracket', '[', { closing = false })
|
||||
singl_eltkn_test('Bracket', ']', { closing = true })
|
||||
singl_eltkn_test('FigureBrace', '{', { closing = false })
|
||||
singl_eltkn_test('FigureBrace', '}', { closing = true })
|
||||
singl_eltkn_test('Question', '?')
|
||||
singl_eltkn_test('Colon', ':')
|
||||
singl_eltkn_test('Dot', '.')
|
||||
singl_eltkn_test('Assignment', '.=', {type='Concat'})
|
||||
singl_eltkn_test('Assignment', '.=', { type = 'Concat' })
|
||||
singl_eltkn_test('Plus', '+')
|
||||
singl_eltkn_test('Assignment', '+=', {type='Add'})
|
||||
singl_eltkn_test('Assignment', '+=', { type = 'Add' })
|
||||
singl_eltkn_test('Comma', ',')
|
||||
singl_eltkn_test('Multiplication', '*', {type='Mul'})
|
||||
singl_eltkn_test('Multiplication', '/', {type='Div'})
|
||||
singl_eltkn_test('Multiplication', '%', {type='Mod'})
|
||||
singl_eltkn_test('Multiplication', '*', { type = 'Mul' })
|
||||
singl_eltkn_test('Multiplication', '/', { type = 'Div' })
|
||||
singl_eltkn_test('Multiplication', '%', { type = 'Mod' })
|
||||
singl_eltkn_test('Spacing', ' \t\t \t\t')
|
||||
singl_eltkn_test('Spacing', ' ')
|
||||
singl_eltkn_test('Spacing', '\t')
|
||||
singl_eltkn_test('Invalid', '\x01\x02\x03', {error='E15: Invalid control character present in input: %.*s'})
|
||||
singl_eltkn_test('Number', '0123', {is_float=false, base=8, val=83})
|
||||
singl_eltkn_test('Number', '01234567', {is_float=false, base=8, val=342391})
|
||||
singl_eltkn_test('Number', '012345678', {is_float=false, base=10, val=12345678})
|
||||
singl_eltkn_test('Number', '0x123', {is_float=false, base=16, val=291})
|
||||
singl_eltkn_test('Number', '0x56FF', {is_float=false, base=16, val=22271})
|
||||
singl_eltkn_test('Number', '0xabcdef', {is_float=false, base=16, val=11259375})
|
||||
singl_eltkn_test('Number', '0xABCDEF', {is_float=false, base=16, val=11259375})
|
||||
singl_eltkn_test('Number', '0x0', {is_float=false, base=16, val=0})
|
||||
singl_eltkn_test('Number', '00', {is_float=false, base=8, val=0})
|
||||
singl_eltkn_test('Number', '0b0', {is_float=false, base=2, val=0})
|
||||
singl_eltkn_test('Number', '0b010111', {is_float=false, base=2, val=23})
|
||||
singl_eltkn_test('Number', '0b100111', {is_float=false, base=2, val=39})
|
||||
singl_eltkn_test('Number', '0', {is_float=false, base=10, val=0})
|
||||
singl_eltkn_test('Number', '9', {is_float=false, base=10, val=9})
|
||||
singl_eltkn_test(
|
||||
'Invalid',
|
||||
'\x01\x02\x03',
|
||||
{ error = 'E15: Invalid control character present in input: %.*s' }
|
||||
)
|
||||
singl_eltkn_test('Number', '0123', { is_float = false, base = 8, val = 83 })
|
||||
singl_eltkn_test('Number', '01234567', { is_float = false, base = 8, val = 342391 })
|
||||
singl_eltkn_test('Number', '012345678', { is_float = false, base = 10, val = 12345678 })
|
||||
singl_eltkn_test('Number', '0x123', { is_float = false, base = 16, val = 291 })
|
||||
singl_eltkn_test('Number', '0x56FF', { is_float = false, base = 16, val = 22271 })
|
||||
singl_eltkn_test('Number', '0xabcdef', { is_float = false, base = 16, val = 11259375 })
|
||||
singl_eltkn_test('Number', '0xABCDEF', { is_float = false, base = 16, val = 11259375 })
|
||||
singl_eltkn_test('Number', '0x0', { is_float = false, base = 16, val = 0 })
|
||||
singl_eltkn_test('Number', '00', { is_float = false, base = 8, val = 0 })
|
||||
singl_eltkn_test('Number', '0b0', { is_float = false, base = 2, val = 0 })
|
||||
singl_eltkn_test('Number', '0b010111', { is_float = false, base = 2, val = 23 })
|
||||
singl_eltkn_test('Number', '0b100111', { is_float = false, base = 2, val = 39 })
|
||||
singl_eltkn_test('Number', '0', { is_float = false, base = 10, val = 0 })
|
||||
singl_eltkn_test('Number', '9', { is_float = false, base = 10, val = 9 })
|
||||
singl_eltkn_test('Env', '$abc')
|
||||
singl_eltkn_test('Env', '$')
|
||||
singl_eltkn_test('PlainIdentifier', 'test', {autoload=false, scope=0})
|
||||
singl_eltkn_test('PlainIdentifier', '_test', {autoload=false, scope=0})
|
||||
singl_eltkn_test('PlainIdentifier', '_test_foo', {autoload=false, scope=0})
|
||||
singl_eltkn_test('PlainIdentifier', 't', {autoload=false, scope=0})
|
||||
singl_eltkn_test('PlainIdentifier', 'test5', {autoload=false, scope=0})
|
||||
singl_eltkn_test('PlainIdentifier', 't0', {autoload=false, scope=0})
|
||||
singl_eltkn_test('PlainIdentifier', 'test#var', {autoload=true, scope=0})
|
||||
singl_eltkn_test('PlainIdentifier', 'test#var#val###', {autoload=true, scope=0})
|
||||
singl_eltkn_test('PlainIdentifier', 't#####', {autoload=true, scope=0})
|
||||
singl_eltkn_test('PlainIdentifier', 'test', { autoload = false, scope = 0 })
|
||||
singl_eltkn_test('PlainIdentifier', '_test', { autoload = false, scope = 0 })
|
||||
singl_eltkn_test('PlainIdentifier', '_test_foo', { autoload = false, scope = 0 })
|
||||
singl_eltkn_test('PlainIdentifier', 't', { autoload = false, scope = 0 })
|
||||
singl_eltkn_test('PlainIdentifier', 'test5', { autoload = false, scope = 0 })
|
||||
singl_eltkn_test('PlainIdentifier', 't0', { autoload = false, scope = 0 })
|
||||
singl_eltkn_test('PlainIdentifier', 'test#var', { autoload = true, scope = 0 })
|
||||
singl_eltkn_test('PlainIdentifier', 'test#var#val###', { autoload = true, scope = 0 })
|
||||
singl_eltkn_test('PlainIdentifier', 't#####', { autoload = true, scope = 0 })
|
||||
singl_eltkn_test('And', '&&')
|
||||
singl_eltkn_test('Or', '||')
|
||||
singl_eltkn_test('Invalid', '&', {error='E112: Option name missing: %.*s'})
|
||||
singl_eltkn_test('Option', '&opt', {scope='Unspecified', name='opt'})
|
||||
singl_eltkn_test('Option', '&t_xx', {scope='Unspecified', name='t_xx'})
|
||||
singl_eltkn_test('Option', '&t_\r\r', {scope='Unspecified', name='t_\r\r'})
|
||||
singl_eltkn_test('Option', '&t_\t\t', {scope='Unspecified', name='t_\t\t'})
|
||||
singl_eltkn_test('Option', '&t_ ', {scope='Unspecified', name='t_ '})
|
||||
singl_eltkn_test('Option', '&g:opt', {scope='Global', name='opt'})
|
||||
singl_eltkn_test('Option', '&l:opt', {scope='Local', name='opt'})
|
||||
singl_eltkn_test('Invalid', '&l:', {error='E112: Option name missing: %.*s'})
|
||||
singl_eltkn_test('Invalid', '&g:', {error='E112: Option name missing: %.*s'})
|
||||
singl_eltkn_test('Register', '@', {name=-1})
|
||||
singl_eltkn_test('Register', '@a', {name='a'})
|
||||
singl_eltkn_test('Register', '@\r', {name=13})
|
||||
singl_eltkn_test('Register', '@ ', {name=' '})
|
||||
singl_eltkn_test('Register', '@\t', {name=9})
|
||||
singl_eltkn_test('SingleQuotedString', '\'test', {closed=false})
|
||||
singl_eltkn_test('SingleQuotedString', '\'test\'', {closed=true})
|
||||
singl_eltkn_test('SingleQuotedString', '\'\'\'\'', {closed=true})
|
||||
singl_eltkn_test('SingleQuotedString', '\'x\'\'\'', {closed=true})
|
||||
singl_eltkn_test('SingleQuotedString', '\'\'\'x\'', {closed=true})
|
||||
singl_eltkn_test('SingleQuotedString', '\'\'\'', {closed=false})
|
||||
singl_eltkn_test('SingleQuotedString', '\'x\'\'', {closed=false})
|
||||
singl_eltkn_test('SingleQuotedString', '\'\'\'x', {closed=false})
|
||||
singl_eltkn_test('DoubleQuotedString', '"test', {closed=false})
|
||||
singl_eltkn_test('DoubleQuotedString', '"test"', {closed=true})
|
||||
singl_eltkn_test('DoubleQuotedString', '"\\""', {closed=true})
|
||||
singl_eltkn_test('DoubleQuotedString', '"x\\""', {closed=true})
|
||||
singl_eltkn_test('DoubleQuotedString', '"\\"x"', {closed=true})
|
||||
singl_eltkn_test('DoubleQuotedString', '"\\"', {closed=false})
|
||||
singl_eltkn_test('DoubleQuotedString', '"x\\"', {closed=false})
|
||||
singl_eltkn_test('DoubleQuotedString', '"\\"x', {closed=false})
|
||||
singl_eltkn_test('Invalid', '&', { error = 'E112: Option name missing: %.*s' })
|
||||
singl_eltkn_test('Option', '&opt', { scope = 'Unspecified', name = 'opt' })
|
||||
singl_eltkn_test('Option', '&t_xx', { scope = 'Unspecified', name = 't_xx' })
|
||||
singl_eltkn_test('Option', '&t_\r\r', { scope = 'Unspecified', name = 't_\r\r' })
|
||||
singl_eltkn_test('Option', '&t_\t\t', { scope = 'Unspecified', name = 't_\t\t' })
|
||||
singl_eltkn_test('Option', '&t_ ', { scope = 'Unspecified', name = 't_ ' })
|
||||
singl_eltkn_test('Option', '&g:opt', { scope = 'Global', name = 'opt' })
|
||||
singl_eltkn_test('Option', '&l:opt', { scope = 'Local', name = 'opt' })
|
||||
singl_eltkn_test('Invalid', '&l:', { error = 'E112: Option name missing: %.*s' })
|
||||
singl_eltkn_test('Invalid', '&g:', { error = 'E112: Option name missing: %.*s' })
|
||||
singl_eltkn_test('Register', '@', { name = -1 })
|
||||
singl_eltkn_test('Register', '@a', { name = 'a' })
|
||||
singl_eltkn_test('Register', '@\r', { name = 13 })
|
||||
singl_eltkn_test('Register', '@ ', { name = ' ' })
|
||||
singl_eltkn_test('Register', '@\t', { name = 9 })
|
||||
singl_eltkn_test('SingleQuotedString', "'test", { closed = false })
|
||||
singl_eltkn_test('SingleQuotedString', "'test'", { closed = true })
|
||||
singl_eltkn_test('SingleQuotedString', "''''", { closed = true })
|
||||
singl_eltkn_test('SingleQuotedString', "'x'''", { closed = true })
|
||||
singl_eltkn_test('SingleQuotedString', "'''x'", { closed = true })
|
||||
singl_eltkn_test('SingleQuotedString', "'''", { closed = false })
|
||||
singl_eltkn_test('SingleQuotedString', "'x''", { closed = false })
|
||||
singl_eltkn_test('SingleQuotedString', "'''x", { closed = false })
|
||||
singl_eltkn_test('DoubleQuotedString', '"test', { closed = false })
|
||||
singl_eltkn_test('DoubleQuotedString', '"test"', { closed = true })
|
||||
singl_eltkn_test('DoubleQuotedString', '"\\""', { closed = true })
|
||||
singl_eltkn_test('DoubleQuotedString', '"x\\""', { closed = true })
|
||||
singl_eltkn_test('DoubleQuotedString', '"\\"x"', { closed = true })
|
||||
singl_eltkn_test('DoubleQuotedString', '"\\"', { closed = false })
|
||||
singl_eltkn_test('DoubleQuotedString', '"x\\"', { closed = false })
|
||||
singl_eltkn_test('DoubleQuotedString', '"\\"x', { closed = false })
|
||||
singl_eltkn_test('Not', '!')
|
||||
singl_eltkn_test('Assignment', '=', {type='Plain'})
|
||||
singl_eltkn_test('Assignment', '=', { type = 'Plain' })
|
||||
comparison_test('==', '!=', 'Equal')
|
||||
comparison_test('=~', '!~', 'Matches')
|
||||
comparison_test('>', '<=', 'Greater')
|
||||
comparison_test('>=', '<', 'GreaterOrEqual')
|
||||
singl_eltkn_test('Minus', '-')
|
||||
singl_eltkn_test('Assignment', '-=', {type='Subtract'})
|
||||
singl_eltkn_test('Assignment', '-=', { type = 'Subtract' })
|
||||
singl_eltkn_test('Arrow', '->')
|
||||
singl_eltkn_test('Invalid', '~', {error='E15: Unidentified character: %.*s'})
|
||||
simple_test({{data=nil, size=0}}, 'EOC', 0, {error='start.col >= #pstr'})
|
||||
simple_test({''}, 'EOC', 0, {error='start.col >= #pstr'})
|
||||
simple_test({'2.'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2e5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.2.'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0e'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0e+'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0e-'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0e+x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0e-x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0e+1a'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0e-1a'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'0b102'}, 'Number', 4, {data={is_float=false, base=2, val=2}, str='0b10'})
|
||||
simple_test({'10F'}, 'Number', 2, {data={is_float=false, base=10, val=10}, str='10'})
|
||||
simple_test({'0x0123456789ABCDEFG'}, 'Number', 18, {data={is_float=false, base=16, val=81985529216486895}, str='0x0123456789ABCDEF'})
|
||||
simple_test({{data='00', size=2}}, 'Number', 2, {data={is_float=false, base=8, val=0}, str='00'})
|
||||
simple_test({{data='009', size=2}}, 'Number', 2, {data={is_float=false, base=8, val=0}, str='00'})
|
||||
simple_test({{data='01', size=1}}, 'Number', 1, {data={is_float=false, base=10, val=0}, str='0'})
|
||||
singl_eltkn_test('Invalid', '~', { error = 'E15: Unidentified character: %.*s' })
|
||||
simple_test({ { data = nil, size = 0 } }, 'EOC', 0, { error = 'start.col >= #pstr' })
|
||||
simple_test({ '' }, 'EOC', 0, { error = 'start.col >= #pstr' })
|
||||
simple_test(
|
||||
{ '2.' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2e5' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.x' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.2.' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0x' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e+' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e-' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e+x' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e-x' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e+1a' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e-1a' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '0b102' },
|
||||
'Number',
|
||||
4,
|
||||
{ data = { is_float = false, base = 2, val = 2 }, str = '0b10' }
|
||||
)
|
||||
simple_test(
|
||||
{ '10F' },
|
||||
'Number',
|
||||
2,
|
||||
{ data = { is_float = false, base = 10, val = 10 }, str = '10' }
|
||||
)
|
||||
simple_test({ '0x0123456789ABCDEFG' }, 'Number', 18, {
|
||||
data = { is_float = false, base = 16, val = 81985529216486895 },
|
||||
str = '0x0123456789ABCDEF',
|
||||
})
|
||||
simple_test(
|
||||
{ { data = '00', size = 2 } },
|
||||
'Number',
|
||||
2,
|
||||
{ data = { is_float = false, base = 8, val = 0 }, str = '00' }
|
||||
)
|
||||
simple_test(
|
||||
{ { data = '009', size = 2 } },
|
||||
'Number',
|
||||
2,
|
||||
{ data = { is_float = false, base = 8, val = 0 }, str = '00' }
|
||||
)
|
||||
simple_test(
|
||||
{ { data = '01', size = 1 } },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 0 }, str = '0' }
|
||||
)
|
||||
end
|
||||
|
||||
local function regular_scope_tests()
|
||||
@ -312,29 +417,104 @@ describe('Expressions lexer', function()
|
||||
scope_test('l')
|
||||
scope_test('a')
|
||||
|
||||
simple_test({'g:'}, 'PlainIdentifier', 2, {data={scope='g', autoload=false}, str='g:'})
|
||||
simple_test({'g:is#foo'}, 'PlainIdentifier', 8, {data={scope='g', autoload=true}, str='g:is#foo'})
|
||||
simple_test({'g:isnot#foo'}, 'PlainIdentifier', 11, {data={scope='g', autoload=true}, str='g:isnot#foo'})
|
||||
simple_test(
|
||||
{ 'g:' },
|
||||
'PlainIdentifier',
|
||||
2,
|
||||
{ data = { scope = 'g', autoload = false }, str = 'g:' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'g:is#foo' },
|
||||
'PlainIdentifier',
|
||||
8,
|
||||
{ data = { scope = 'g', autoload = true }, str = 'g:is#foo' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'g:isnot#foo' },
|
||||
'PlainIdentifier',
|
||||
11,
|
||||
{ data = { scope = 'g', autoload = true }, str = 'g:isnot#foo' }
|
||||
)
|
||||
end
|
||||
|
||||
local function regular_is_tests()
|
||||
comparison_test('is', 'isnot', 'Identical')
|
||||
|
||||
simple_test({'is'}, 'Comparison', 2, {data={type='Identical', inv=false, ccs='UseOption'}, str='is'})
|
||||
simple_test({'isnot'}, 'Comparison', 5, {data={type='Identical', inv=true, ccs='UseOption'}, str='isnot'})
|
||||
simple_test({'is?'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='IgnoreCase'}, str='is?'})
|
||||
simple_test({'isnot?'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='IgnoreCase'}, str='isnot?'})
|
||||
simple_test({'is#'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='MatchCase'}, str='is#'})
|
||||
simple_test({'isnot#'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='MatchCase'}, str='isnot#'})
|
||||
simple_test({'is#foo'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='MatchCase'}, str='is#'})
|
||||
simple_test({'isnot#foo'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='MatchCase'}, str='isnot#'})
|
||||
simple_test(
|
||||
{ 'is' },
|
||||
'Comparison',
|
||||
2,
|
||||
{ data = { type = 'Identical', inv = false, ccs = 'UseOption' }, str = 'is' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'isnot' },
|
||||
'Comparison',
|
||||
5,
|
||||
{ data = { type = 'Identical', inv = true, ccs = 'UseOption' }, str = 'isnot' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'is?' },
|
||||
'Comparison',
|
||||
3,
|
||||
{ data = { type = 'Identical', inv = false, ccs = 'IgnoreCase' }, str = 'is?' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'isnot?' },
|
||||
'Comparison',
|
||||
6,
|
||||
{ data = { type = 'Identical', inv = true, ccs = 'IgnoreCase' }, str = 'isnot?' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'is#' },
|
||||
'Comparison',
|
||||
3,
|
||||
{ data = { type = 'Identical', inv = false, ccs = 'MatchCase' }, str = 'is#' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'isnot#' },
|
||||
'Comparison',
|
||||
6,
|
||||
{ data = { type = 'Identical', inv = true, ccs = 'MatchCase' }, str = 'isnot#' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'is#foo' },
|
||||
'Comparison',
|
||||
3,
|
||||
{ data = { type = 'Identical', inv = false, ccs = 'MatchCase' }, str = 'is#' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'isnot#foo' },
|
||||
'Comparison',
|
||||
6,
|
||||
{ data = { type = 'Identical', inv = true, ccs = 'MatchCase' }, str = 'isnot#' }
|
||||
)
|
||||
end
|
||||
|
||||
local function regular_number_tests()
|
||||
simple_test({'2.0'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0e5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0e+5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({'2.0e-5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test(
|
||||
{ '2.0' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e5' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e+5' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e-5' },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
end
|
||||
|
||||
local function regular_eoc_tests()
|
||||
@ -369,7 +549,12 @@ describe('Expressions lexer', function()
|
||||
regular_is_tests()
|
||||
regular_number_tests()
|
||||
|
||||
simple_test({'g:'}, 'PlainIdentifier', 1, {data={scope=0, autoload=false}, str='g'})
|
||||
simple_test(
|
||||
{ 'g:' },
|
||||
'PlainIdentifier',
|
||||
1,
|
||||
{ data = { scope = 0, autoload = false }, str = 'g' }
|
||||
)
|
||||
end)
|
||||
itp('allows floats', function()
|
||||
flags = tonumber(lib.kELFlagAllowFloat)
|
||||
@ -379,20 +564,72 @@ describe('Expressions lexer', function()
|
||||
regular_scope_tests()
|
||||
regular_is_tests()
|
||||
|
||||
simple_test({'2.2'}, 'Number', 3, {data={is_float=true, base=10, val=2.2}, str='2.2'})
|
||||
simple_test({'2.0e5'}, 'Number', 5, {data={is_float=true, base=10, val=2e5}, str='2.0e5'})
|
||||
simple_test({'2.0e+5'}, 'Number', 6, {data={is_float=true, base=10, val=2e5}, str='2.0e+5'})
|
||||
simple_test({'2.0e-5'}, 'Number', 6, {data={is_float=true, base=10, val=2e-5}, str='2.0e-5'})
|
||||
simple_test({'2.500000e-5'}, 'Number', 11, {data={is_float=true, base=10, val=2.5e-5}, str='2.500000e-5'})
|
||||
simple_test({'2.5555e2'}, 'Number', 8, {data={is_float=true, base=10, val=2.5555e2}, str='2.5555e2'})
|
||||
simple_test({'2.5555e+2'}, 'Number', 9, {data={is_float=true, base=10, val=2.5555e2}, str='2.5555e+2'})
|
||||
simple_test({'2.5555e-2'}, 'Number', 9, {data={is_float=true, base=10, val=2.5555e-2}, str='2.5555e-2'})
|
||||
simple_test({{data='2.5e-5', size=3}},
|
||||
'Number', 3, {data={is_float=true, base=10, val=2.5}, str='2.5'})
|
||||
simple_test({{data='2.5e5', size=4}},
|
||||
'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
||||
simple_test({{data='2.5e-50', size=6}},
|
||||
'Number', 6, {data={is_float=true, base=10, val=2.5e-5}, str='2.5e-5'})
|
||||
simple_test(
|
||||
{ '2.2' },
|
||||
'Number',
|
||||
3,
|
||||
{ data = { is_float = true, base = 10, val = 2.2 }, str = '2.2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e5' },
|
||||
'Number',
|
||||
5,
|
||||
{ data = { is_float = true, base = 10, val = 2e5 }, str = '2.0e5' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e+5' },
|
||||
'Number',
|
||||
6,
|
||||
{ data = { is_float = true, base = 10, val = 2e5 }, str = '2.0e+5' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.0e-5' },
|
||||
'Number',
|
||||
6,
|
||||
{ data = { is_float = true, base = 10, val = 2e-5 }, str = '2.0e-5' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.500000e-5' },
|
||||
'Number',
|
||||
11,
|
||||
{ data = { is_float = true, base = 10, val = 2.5e-5 }, str = '2.500000e-5' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.5555e2' },
|
||||
'Number',
|
||||
8,
|
||||
{ data = { is_float = true, base = 10, val = 2.5555e2 }, str = '2.5555e2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.5555e+2' },
|
||||
'Number',
|
||||
9,
|
||||
{ data = { is_float = true, base = 10, val = 2.5555e2 }, str = '2.5555e+2' }
|
||||
)
|
||||
simple_test(
|
||||
{ '2.5555e-2' },
|
||||
'Number',
|
||||
9,
|
||||
{ data = { is_float = true, base = 10, val = 2.5555e-2 }, str = '2.5555e-2' }
|
||||
)
|
||||
simple_test(
|
||||
{ { data = '2.5e-5', size = 3 } },
|
||||
'Number',
|
||||
3,
|
||||
{ data = { is_float = true, base = 10, val = 2.5 }, str = '2.5' }
|
||||
)
|
||||
simple_test(
|
||||
{ { data = '2.5e5', size = 4 } },
|
||||
'Number',
|
||||
1,
|
||||
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||
)
|
||||
simple_test(
|
||||
{ { data = '2.5e-50', size = 6 } },
|
||||
'Number',
|
||||
6,
|
||||
{ data = { is_float = true, base = 10, val = 2.5e-5 }, str = '2.5e-5' }
|
||||
)
|
||||
end)
|
||||
itp('treats `is` as an identifier', function()
|
||||
flags = tonumber(lib.kELFlagIsNotCmp)
|
||||
@ -402,14 +639,54 @@ describe('Expressions lexer', function()
|
||||
regular_scope_tests()
|
||||
regular_number_tests()
|
||||
|
||||
simple_test({'is'}, 'PlainIdentifier', 2, {data={scope=0, autoload=false}, str='is'})
|
||||
simple_test({'isnot'}, 'PlainIdentifier', 5, {data={scope=0, autoload=false}, str='isnot'})
|
||||
simple_test({'is?'}, 'PlainIdentifier', 2, {data={scope=0, autoload=false}, str='is'})
|
||||
simple_test({'isnot?'}, 'PlainIdentifier', 5, {data={scope=0, autoload=false}, str='isnot'})
|
||||
simple_test({'is#'}, 'PlainIdentifier', 3, {data={scope=0, autoload=true}, str='is#'})
|
||||
simple_test({'isnot#'}, 'PlainIdentifier', 6, {data={scope=0, autoload=true}, str='isnot#'})
|
||||
simple_test({'is#foo'}, 'PlainIdentifier', 6, {data={scope=0, autoload=true}, str='is#foo'})
|
||||
simple_test({'isnot#foo'}, 'PlainIdentifier', 9, {data={scope=0, autoload=true}, str='isnot#foo'})
|
||||
simple_test(
|
||||
{ 'is' },
|
||||
'PlainIdentifier',
|
||||
2,
|
||||
{ data = { scope = 0, autoload = false }, str = 'is' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'isnot' },
|
||||
'PlainIdentifier',
|
||||
5,
|
||||
{ data = { scope = 0, autoload = false }, str = 'isnot' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'is?' },
|
||||
'PlainIdentifier',
|
||||
2,
|
||||
{ data = { scope = 0, autoload = false }, str = 'is' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'isnot?' },
|
||||
'PlainIdentifier',
|
||||
5,
|
||||
{ data = { scope = 0, autoload = false }, str = 'isnot' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'is#' },
|
||||
'PlainIdentifier',
|
||||
3,
|
||||
{ data = { scope = 0, autoload = true }, str = 'is#' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'isnot#' },
|
||||
'PlainIdentifier',
|
||||
6,
|
||||
{ data = { scope = 0, autoload = true }, str = 'isnot#' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'is#foo' },
|
||||
'PlainIdentifier',
|
||||
6,
|
||||
{ data = { scope = 0, autoload = true }, str = 'is#foo' }
|
||||
)
|
||||
simple_test(
|
||||
{ 'isnot#foo' },
|
||||
'PlainIdentifier',
|
||||
9,
|
||||
{ data = { scope = 0, autoload = true }, str = 'isnot#foo' }
|
||||
)
|
||||
end)
|
||||
itp('forbids EOC', function()
|
||||
flags = tonumber(lib.kELFlagForbidEOC)
|
||||
@ -419,8 +696,8 @@ describe('Expressions lexer', function()
|
||||
regular_is_tests()
|
||||
regular_number_tests()
|
||||
|
||||
singl_eltkn_test('Invalid', '|', {error='E15: Unexpected EOC character: %.*s'})
|
||||
singl_eltkn_test('Invalid', '\0', {error='E15: Unexpected EOC character: %.*s'})
|
||||
singl_eltkn_test('Invalid', '\n', {error='E15: Unexpected EOC character: %.*s'})
|
||||
singl_eltkn_test('Invalid', '|', { error = 'E15: Unexpected EOC character: %.*s' })
|
||||
singl_eltkn_test('Invalid', '\0', { error = 'E15: Unexpected EOC character: %.*s' })
|
||||
singl_eltkn_test('Invalid', '\n', { error = 'E15: Unexpected EOC character: %.*s' })
|
||||
end)
|
||||
end)
|
||||
|
@ -25,100 +25,99 @@ local conv_cmp_type = viml_helpers.conv_cmp_type
|
||||
local pstate_set_str = viml_helpers.pstate_set_str
|
||||
local conv_expr_asgn_type = viml_helpers.conv_expr_asgn_type
|
||||
|
||||
local lib = cimport('./src/nvim/viml/parser/expressions.h',
|
||||
'./src/nvim/syntax.h')
|
||||
local lib = cimport('./src/nvim/viml/parser/expressions.h', './src/nvim/syntax.h')
|
||||
|
||||
local alloc_log = alloc_log_new()
|
||||
|
||||
local predefined_hl_defs = {
|
||||
-- From highlight_init_both
|
||||
Conceal=true,
|
||||
Cursor=true,
|
||||
lCursor=true,
|
||||
DiffText=true,
|
||||
ErrorMsg=true,
|
||||
IncSearch=true,
|
||||
ModeMsg=true,
|
||||
NonText=true,
|
||||
PmenuSbar=true,
|
||||
StatusLine=true,
|
||||
StatusLineNC=true,
|
||||
TabLineFill=true,
|
||||
TabLineSel=true,
|
||||
TermCursor=true,
|
||||
VertSplit=true,
|
||||
WildMenu=true,
|
||||
WinSeparator=true,
|
||||
EndOfBuffer=true,
|
||||
QuickFixLine=true,
|
||||
Substitute=true,
|
||||
Whitespace=true,
|
||||
Error=true,
|
||||
Todo=true,
|
||||
String=true,
|
||||
Character=true,
|
||||
Number=true,
|
||||
Boolean=true,
|
||||
Float=true,
|
||||
Function=true,
|
||||
Conditional=true,
|
||||
Repeat=true,
|
||||
Label=true,
|
||||
Operator=true,
|
||||
Keyword=true,
|
||||
Exception=true,
|
||||
Include=true,
|
||||
Define=true,
|
||||
Macro=true,
|
||||
PreCondit=true,
|
||||
StorageClass=true,
|
||||
Structure=true,
|
||||
Typedef=true,
|
||||
Tag=true,
|
||||
SpecialChar=true,
|
||||
Delimiter=true,
|
||||
SpecialComment=true,
|
||||
Debug=true,
|
||||
Conceal = true,
|
||||
Cursor = true,
|
||||
lCursor = true,
|
||||
DiffText = true,
|
||||
ErrorMsg = true,
|
||||
IncSearch = true,
|
||||
ModeMsg = true,
|
||||
NonText = true,
|
||||
PmenuSbar = true,
|
||||
StatusLine = true,
|
||||
StatusLineNC = true,
|
||||
TabLineFill = true,
|
||||
TabLineSel = true,
|
||||
TermCursor = true,
|
||||
VertSplit = true,
|
||||
WildMenu = true,
|
||||
WinSeparator = true,
|
||||
EndOfBuffer = true,
|
||||
QuickFixLine = true,
|
||||
Substitute = true,
|
||||
Whitespace = true,
|
||||
Error = true,
|
||||
Todo = true,
|
||||
String = true,
|
||||
Character = true,
|
||||
Number = true,
|
||||
Boolean = true,
|
||||
Float = true,
|
||||
Function = true,
|
||||
Conditional = true,
|
||||
Repeat = true,
|
||||
Label = true,
|
||||
Operator = true,
|
||||
Keyword = true,
|
||||
Exception = true,
|
||||
Include = true,
|
||||
Define = true,
|
||||
Macro = true,
|
||||
PreCondit = true,
|
||||
StorageClass = true,
|
||||
Structure = true,
|
||||
Typedef = true,
|
||||
Tag = true,
|
||||
SpecialChar = true,
|
||||
Delimiter = true,
|
||||
SpecialComment = true,
|
||||
Debug = true,
|
||||
|
||||
-- From highlight_init_(dark|light)
|
||||
ColorColumn=true,
|
||||
CursorColumn=true,
|
||||
CursorLine=true,
|
||||
CursorLineNr=true,
|
||||
DiffAdd=true,
|
||||
DiffChange=true,
|
||||
DiffDelete=true,
|
||||
Directory=true,
|
||||
FoldColumn=true,
|
||||
Folded=true,
|
||||
LineNr=true,
|
||||
MatchParen=true,
|
||||
MoreMsg=true,
|
||||
Pmenu=true,
|
||||
PmenuSel=true,
|
||||
PmenuThumb=true,
|
||||
Question=true,
|
||||
Search=true,
|
||||
SignColumn=true,
|
||||
SpecialKey=true,
|
||||
SpellBad=true,
|
||||
SpellCap=true,
|
||||
SpellLocal=true,
|
||||
SpellRare=true,
|
||||
TabLine=true,
|
||||
Title=true,
|
||||
Visual=true,
|
||||
WarningMsg=true,
|
||||
Normal=true,
|
||||
Comment=true,
|
||||
Constant=true,
|
||||
Special=true,
|
||||
Identifier=true,
|
||||
Statement=true,
|
||||
PreProc=true,
|
||||
Type=true,
|
||||
Underlined=true,
|
||||
Ignore=true,
|
||||
ColorColumn = true,
|
||||
CursorColumn = true,
|
||||
CursorLine = true,
|
||||
CursorLineNr = true,
|
||||
DiffAdd = true,
|
||||
DiffChange = true,
|
||||
DiffDelete = true,
|
||||
Directory = true,
|
||||
FoldColumn = true,
|
||||
Folded = true,
|
||||
LineNr = true,
|
||||
MatchParen = true,
|
||||
MoreMsg = true,
|
||||
Pmenu = true,
|
||||
PmenuSel = true,
|
||||
PmenuThumb = true,
|
||||
Question = true,
|
||||
Search = true,
|
||||
SignColumn = true,
|
||||
SpecialKey = true,
|
||||
SpellBad = true,
|
||||
SpellCap = true,
|
||||
SpellLocal = true,
|
||||
SpellRare = true,
|
||||
TabLine = true,
|
||||
Title = true,
|
||||
Visual = true,
|
||||
WarningMsg = true,
|
||||
Normal = true,
|
||||
Comment = true,
|
||||
Constant = true,
|
||||
Special = true,
|
||||
Identifier = true,
|
||||
Statement = true,
|
||||
PreProc = true,
|
||||
Type = true,
|
||||
Underlined = true,
|
||||
Ignore = true,
|
||||
}
|
||||
|
||||
local nvim_hl_defs = {}
|
||||
@ -136,22 +135,18 @@ child_call_once(function()
|
||||
-- linking, otherwise it will be created as cleared. So existence
|
||||
-- of the group is checked here and not in the next pass over
|
||||
-- nvim_hl_defs.
|
||||
eq(true, not not (nvim_hl_defs[grp_link]
|
||||
or predefined_hl_defs[grp_link]))
|
||||
eq(false, not not (nvim_hl_defs[new_grp]
|
||||
or predefined_hl_defs[new_grp]))
|
||||
nvim_hl_defs[new_grp] = {'link', grp_link}
|
||||
eq(true, not not (nvim_hl_defs[grp_link] or predefined_hl_defs[grp_link]))
|
||||
eq(false, not not (nvim_hl_defs[new_grp] or predefined_hl_defs[new_grp]))
|
||||
nvim_hl_defs[new_grp] = { 'link', grp_link }
|
||||
else
|
||||
local new_grp, grp_args = s:match('^(%w+) (.*)')
|
||||
neq(nil, new_grp)
|
||||
eq(false, not not (nvim_hl_defs[new_grp]
|
||||
or predefined_hl_defs[new_grp]))
|
||||
nvim_hl_defs[new_grp] = {'definition', grp_args}
|
||||
eq(false, not not (nvim_hl_defs[new_grp] or predefined_hl_defs[new_grp]))
|
||||
nvim_hl_defs[new_grp] = { 'definition', grp_args }
|
||||
end
|
||||
end)
|
||||
if not err then
|
||||
msg = format_string(
|
||||
'Error while processing string %s at position %u:\n%s', s, i, msg)
|
||||
msg = format_string('Error while processing string %s at position %u:\n%s', s, i, msg)
|
||||
error(msg)
|
||||
end
|
||||
i = i + 1
|
||||
@ -185,12 +180,12 @@ local function hls_to_hl_fs(hls)
|
||||
local col_shift = col - next_col
|
||||
assert(col_shift >= 0)
|
||||
next_col = col + #str
|
||||
ret[i] = format_string('hl(%r, %r%s)',
|
||||
ret[i] = format_string(
|
||||
'hl(%r, %r%s)',
|
||||
group,
|
||||
str,
|
||||
(col_shift == 0
|
||||
and ''
|
||||
or (', %u'):format(col_shift)))
|
||||
(col_shift == 0 and '' or (', %u'):format(col_shift))
|
||||
)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
@ -205,9 +200,9 @@ local function format_check(expr, format_check_data, opts)
|
||||
dig_len = #opts.funcname + 2
|
||||
else
|
||||
print(format_string('\n_check_parsing(%r, %r, {', opts, expr))
|
||||
dig_len = #('_check_parsing(, \'') + #(format_string('%r', opts))
|
||||
dig_len = #"_check_parsing(, '" + #(format_string('%r', opts))
|
||||
end
|
||||
local digits = ' --' .. (' '):rep(dig_len - #(' --'))
|
||||
local digits = ' --' .. (' '):rep(dig_len - #' --')
|
||||
local digits2 = digits:sub(1, -10)
|
||||
for i = 0, #expr - 1 do
|
||||
if i % 10 == 0 then
|
||||
@ -240,10 +235,9 @@ local function format_check(expr, format_check_data, opts)
|
||||
diffs[flags] = dictdiff(zdata, v)
|
||||
if diffs[flags] then
|
||||
if flags == 3 + zflags then
|
||||
if (dictdiff(format_check_data[1 + zflags],
|
||||
format_check_data[3 + zflags]) == nil
|
||||
or dictdiff(format_check_data[2 + zflags],
|
||||
format_check_data[3 + zflags]) == nil)
|
||||
if
|
||||
dictdiff(format_check_data[1 + zflags], format_check_data[3 + zflags]) == nil
|
||||
or dictdiff(format_check_data[2 + zflags], format_check_data[3 + zflags]) == nil
|
||||
then
|
||||
diffs[flags] = nil
|
||||
else
|
||||
@ -268,7 +262,7 @@ local function format_check(expr, format_check_data, opts)
|
||||
end
|
||||
if diff.hl_fs then
|
||||
print(' hl_fs = ' .. format_luav(diff.hl_fs, ' ', {
|
||||
literal_strings=true
|
||||
literal_strings = true,
|
||||
}) .. ',')
|
||||
end
|
||||
print(' },')
|
||||
@ -280,7 +274,9 @@ local function format_check(expr, format_check_data, opts)
|
||||
end
|
||||
|
||||
local east_node_type_tab
|
||||
make_enum_conv_tab(lib, {
|
||||
make_enum_conv_tab(
|
||||
lib,
|
||||
{
|
||||
'kExprNodeMissing',
|
||||
'kExprNodeOpMissing',
|
||||
'kExprNodeTernary',
|
||||
@ -320,7 +316,12 @@ make_enum_conv_tab(lib, {
|
||||
'kExprNodeOption',
|
||||
'kExprNodeEnvironment',
|
||||
'kExprNodeAssignment',
|
||||
}, 'kExprNode', function(ret) east_node_type_tab = ret end)
|
||||
},
|
||||
'kExprNode',
|
||||
function(ret)
|
||||
east_node_type_tab = ret
|
||||
end
|
||||
)
|
||||
|
||||
local function conv_east_node_type(typ)
|
||||
return conv_enum(east_node_type_tab, typ)
|
||||
@ -346,25 +347,35 @@ local function eastnode2lua(pstate, eastnode, checked_nodes)
|
||||
ret_str = ('%u:%u:%s'):format(str.start.line, str.start.col, str.str)
|
||||
end
|
||||
if typ == 'Register' then
|
||||
typ = typ .. ('(name=%s)'):format(
|
||||
tostring(intchar2lua(eastnode.data.reg.name)))
|
||||
typ = typ .. ('(name=%s)'):format(tostring(intchar2lua(eastnode.data.reg.name)))
|
||||
elseif typ == 'PlainIdentifier' then
|
||||
typ = typ .. ('(scope=%s,ident=%s)'):format(
|
||||
typ = typ
|
||||
.. ('(scope=%s,ident=%s)'):format(
|
||||
tostring(intchar2lua(eastnode.data.var.scope)),
|
||||
ffi.string(eastnode.data.var.ident, eastnode.data.var.ident_len))
|
||||
ffi.string(eastnode.data.var.ident, eastnode.data.var.ident_len)
|
||||
)
|
||||
elseif typ == 'PlainKey' then
|
||||
typ = typ .. ('(key=%s)'):format(
|
||||
ffi.string(eastnode.data.var.ident, eastnode.data.var.ident_len))
|
||||
elseif (typ == 'UnknownFigure' or typ == 'DictLiteral'
|
||||
or typ == 'CurlyBracesIdentifier' or typ == 'Lambda') then
|
||||
typ = typ .. ('(%s)'):format(
|
||||
typ = typ
|
||||
.. ('(key=%s)'):format(ffi.string(eastnode.data.var.ident, eastnode.data.var.ident_len))
|
||||
elseif
|
||||
typ == 'UnknownFigure'
|
||||
or typ == 'DictLiteral'
|
||||
or typ == 'CurlyBracesIdentifier'
|
||||
or typ == 'Lambda'
|
||||
then
|
||||
typ = typ
|
||||
.. ('(%s)'):format(
|
||||
(eastnode.data.fig.type_guesses.allow_lambda and '\\' or '-')
|
||||
.. (eastnode.data.fig.type_guesses.allow_dict and 'd' or '-')
|
||||
.. (eastnode.data.fig.type_guesses.allow_ident and 'i' or '-'))
|
||||
.. (eastnode.data.fig.type_guesses.allow_ident and 'i' or '-')
|
||||
)
|
||||
elseif typ == 'Comparison' then
|
||||
typ = typ .. ('(type=%s,inv=%u,ccs=%s)'):format(
|
||||
conv_cmp_type(eastnode.data.cmp.type), eastnode.data.cmp.inv and 1 or 0,
|
||||
conv_ccs(eastnode.data.cmp.ccs))
|
||||
typ = typ
|
||||
.. ('(type=%s,inv=%u,ccs=%s)'):format(
|
||||
conv_cmp_type(eastnode.data.cmp.type),
|
||||
eastnode.data.cmp.inv and 1 or 0,
|
||||
conv_ccs(eastnode.data.cmp.ccs)
|
||||
)
|
||||
elseif typ == 'Integer' then
|
||||
typ = typ .. ('(val=%u)'):format(tonumber(eastnode.data.num.value))
|
||||
elseif typ == 'Float' then
|
||||
@ -380,11 +391,13 @@ local function eastnode2lua(pstate, eastnode, checked_nodes)
|
||||
typ = ('%s(scope=%s,ident=%s)'):format(
|
||||
typ,
|
||||
tostring(intchar2lua(eastnode.data.opt.scope)),
|
||||
ffi.string(eastnode.data.opt.ident, eastnode.data.opt.ident_len))
|
||||
ffi.string(eastnode.data.opt.ident, eastnode.data.opt.ident_len)
|
||||
)
|
||||
elseif typ == 'Environment' then
|
||||
typ = ('%s(ident=%s)'):format(
|
||||
typ,
|
||||
ffi.string(eastnode.data.env.ident, eastnode.data.env.ident_len))
|
||||
ffi.string(eastnode.data.env.ident, eastnode.data.env.ident_len)
|
||||
)
|
||||
elseif typ == 'Assignment' then
|
||||
typ = ('%s(%s)'):format(typ, conv_expr_asgn_type(eastnode.data.ass.type))
|
||||
end
|
||||
@ -433,22 +446,21 @@ local function phl2lua(pstate)
|
||||
local ret = {}
|
||||
for i = 0, (tonumber(pstate.colors.size) - 1) do
|
||||
local chunk = pstate.colors.items[i]
|
||||
local chunk_tbl = pstate_set_str(
|
||||
pstate, chunk.start, chunk.end_col - chunk.start.col, {
|
||||
local chunk_tbl = pstate_set_str(pstate, chunk.start, chunk.end_col - chunk.start.col, {
|
||||
group = ffi.string(chunk.group),
|
||||
})
|
||||
ret[i + 1] = ('%s:%u:%u:%s'):format(
|
||||
chunk_tbl.group,
|
||||
chunk_tbl.start.line,
|
||||
chunk_tbl.start.col,
|
||||
chunk_tbl.str)
|
||||
chunk_tbl.str
|
||||
)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
describe('Expressions parser', function()
|
||||
local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs,
|
||||
nz_flags_exps)
|
||||
local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs, nz_flags_exps)
|
||||
local zflags = opts.flags[1]
|
||||
nz_flags_exps = nz_flags_exps or {}
|
||||
local format_check_data = {}
|
||||
@ -460,12 +472,12 @@ describe('Expressions parser', function()
|
||||
end
|
||||
alloc_log:check({})
|
||||
|
||||
local pstate = new_pstate({str})
|
||||
local pstate = new_pstate({ str })
|
||||
local east = lib.viml_pexpr_parse(pstate, flags)
|
||||
local ast = east2lua(str, pstate, east)
|
||||
local hls = phl2lua(pstate)
|
||||
if exp_ast == nil then
|
||||
format_check_data[flags] = {ast=ast, hl_fs=hls_to_hl_fs(hls)}
|
||||
format_check_data[flags] = { ast = ast, hl_fs = hls_to_hl_fs(hls) }
|
||||
else
|
||||
local exps = {
|
||||
ast = exp_ast,
|
||||
@ -499,8 +511,7 @@ describe('Expressions parser', function()
|
||||
alloc_log:check({})
|
||||
end)
|
||||
if not err then
|
||||
msg = format_string('Error while processing test (%r, %u):\n%s',
|
||||
str, flags, msg)
|
||||
msg = format_string('Error while processing test (%r, %u):\n%s', str, flags, msg)
|
||||
error(msg)
|
||||
end
|
||||
end
|
||||
@ -514,16 +525,11 @@ describe('Expressions parser', function()
|
||||
error(('Unknown group: Nvim%s'):format(group))
|
||||
end
|
||||
local col = next_col + (shift or 0)
|
||||
return (('%s:%u:%u:%s'):format(
|
||||
'Nvim' .. group,
|
||||
0,
|
||||
col,
|
||||
str)), (col + #str)
|
||||
return (('%s:%u:%u:%s'):format('Nvim' .. group, 0, col, str)), (col + #str)
|
||||
end
|
||||
end
|
||||
local function fmtn(typ, args, rest)
|
||||
return ('%s(%s)%s'):format(typ, args, rest)
|
||||
end
|
||||
require('test.unit.viml.expressions.parser_tests')(
|
||||
itp, _check_parsing, hl, fmtn)
|
||||
require('test.unit.viml.expressions.parser_tests')(itp, _check_parsing, hl, fmtn)
|
||||
end)
|
||||
|
@ -4,12 +4,12 @@ local REMOVE_THIS = global_helpers.REMOVE_THIS
|
||||
|
||||
return function(itp, _check_parsing, hl, fmtn)
|
||||
local function check_parsing(...)
|
||||
return _check_parsing({flags={0, 1, 2, 3}, funcname='check_parsing'}, ...)
|
||||
return _check_parsing({ flags = { 0, 1, 2, 3 }, funcname = 'check_parsing' }, ...)
|
||||
end
|
||||
local function check_asgn_parsing(...)
|
||||
return _check_parsing({
|
||||
flags={4, 5, 6, 7},
|
||||
funcname='check_asgn_parsing',
|
||||
flags = { 4, 5, 6, 7 },
|
||||
funcname = 'check_asgn_parsing',
|
||||
}, ...)
|
||||
end
|
||||
itp('works with + and @a', function()
|
||||
@ -142,7 +142,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
len = 2,
|
||||
err = REMOVE_THIS,
|
||||
ast = {
|
||||
'Register(name=a):0:0:@a'
|
||||
'Register(name=a):0:0:@a',
|
||||
},
|
||||
},
|
||||
hl_fs = {
|
||||
@ -174,7 +174,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
len = 6,
|
||||
err = REMOVE_THIS,
|
||||
ast = {
|
||||
'Register(name=a):0:0: @a'
|
||||
'Register(name=a):0:0: @a',
|
||||
},
|
||||
},
|
||||
hl_fs = {
|
||||
@ -541,7 +541,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
children = {
|
||||
{
|
||||
'Nested:0:4:(',
|
||||
children = { 'Register(name=b):0:5:@b' }
|
||||
children = { 'Register(name=b):0:5:@b' },
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -579,7 +579,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
children = {
|
||||
{
|
||||
'Nested:0:4:(',
|
||||
children = { 'Register(name=b):0:5:@b' }
|
||||
children = { 'Register(name=b):0:5:@b' },
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -600,13 +600,13 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
hl('BinaryPlus', '+'),
|
||||
hl('Register', '@c'),
|
||||
})
|
||||
check_parsing(
|
||||
'@a + (@b + @c) + @d(@e) + (+@f) + ((+@g(@h))(@j)(@k))(@l)', {--[[
|
||||
check_parsing('@a + (@b + @c) + @d(@e) + (+@f) + ((+@g(@h))(@j)(@k))(@l)', {--[[
|
||||
| | | | | | | | || | | || | | ||| || || || ||
|
||||
000000000011111111112222222222333333333344444444445555555
|
||||
012345678901234567890123456789012345678901234567890123456
|
||||
]]
|
||||
ast = {{
|
||||
ast = {
|
||||
{
|
||||
'BinaryPlus:0:31: +',
|
||||
children = {
|
||||
{
|
||||
@ -696,7 +696,8 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
hl('Register', '@a'),
|
||||
hl('BinaryPlus', '+', 1),
|
||||
@ -1141,7 +1142,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
children = {
|
||||
{
|
||||
'OpMissing:0:3:',
|
||||
children={
|
||||
children = {
|
||||
'PlainIdentifier(scope=a,ident=):0:1:a:',
|
||||
'Register(name=b):0:3:@b',
|
||||
},
|
||||
@ -2851,7 +2852,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
},
|
||||
err = {
|
||||
arg = '{a : b',
|
||||
msg = 'E723: Missing end of Dictionary \'}\': %.*s',
|
||||
msg = "E723: Missing end of Dictionary '}': %.*s",
|
||||
},
|
||||
}, {
|
||||
hl('Dict', '{'),
|
||||
@ -3182,7 +3183,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
},
|
||||
err = {
|
||||
arg = '?b',
|
||||
msg = 'E109: Missing \':\' after \'?\': %.*s',
|
||||
msg = "E109: Missing ':' after '?': %.*s",
|
||||
},
|
||||
}, {
|
||||
hl('IdentifierName', 'a'),
|
||||
@ -3207,7 +3208,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
},
|
||||
err = {
|
||||
arg = '?b:',
|
||||
msg = 'E109: Missing \':\' after \'?\': %.*s',
|
||||
msg = "E109: Missing ':' after '?': %.*s",
|
||||
},
|
||||
}, {
|
||||
hl('IdentifierName', 'a'),
|
||||
@ -4840,7 +4841,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
},
|
||||
err = {
|
||||
arg = '[1',
|
||||
msg = 'E697: Missing end of List \']\': %.*s',
|
||||
msg = "E697: Missing end of List ']': %.*s",
|
||||
},
|
||||
}, {
|
||||
hl('List', '['),
|
||||
@ -4848,15 +4849,15 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
})
|
||||
end)
|
||||
itp('works with strings', function()
|
||||
check_parsing('\'abc\'', {
|
||||
check_parsing("'abc'", {
|
||||
-- 01234
|
||||
ast = {
|
||||
fmtn('SingleQuotedString', 'val="abc"', ':0:0:\'abc\''),
|
||||
fmtn('SingleQuotedString', 'val="abc"', ":0:0:'abc'"),
|
||||
},
|
||||
}, {
|
||||
hl('SingleQuote', '\''),
|
||||
hl('SingleQuote', "'"),
|
||||
hl('SingleQuotedBody', 'abc'),
|
||||
hl('SingleQuote', '\''),
|
||||
hl('SingleQuote', "'"),
|
||||
})
|
||||
check_parsing('"abc"', {
|
||||
-- 01234
|
||||
@ -4868,14 +4869,14 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
hl('DoubleQuotedBody', 'abc'),
|
||||
hl('DoubleQuote', '"'),
|
||||
})
|
||||
check_parsing('\'\'', {
|
||||
check_parsing("''", {
|
||||
-- 01
|
||||
ast = {
|
||||
fmtn('SingleQuotedString', 'val=NULL', ':0:0:\'\''),
|
||||
fmtn('SingleQuotedString', 'val=NULL', ":0:0:''"),
|
||||
},
|
||||
}, {
|
||||
hl('SingleQuote', '\''),
|
||||
hl('SingleQuote', '\''),
|
||||
hl('SingleQuote', "'"),
|
||||
hl('SingleQuote', "'"),
|
||||
})
|
||||
check_parsing('""', {
|
||||
-- 01
|
||||
@ -4898,17 +4899,17 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
}, {
|
||||
hl('InvalidDoubleQuote', '"'),
|
||||
})
|
||||
check_parsing('\'', {
|
||||
check_parsing("'", {
|
||||
-- 0
|
||||
ast = {
|
||||
fmtn('SingleQuotedString', 'val=NULL', ':0:0:\''),
|
||||
fmtn('SingleQuotedString', 'val=NULL', ":0:0:'"),
|
||||
},
|
||||
err = {
|
||||
arg = '\'',
|
||||
arg = "'",
|
||||
msg = 'E115: Missing single quote: %.*s',
|
||||
},
|
||||
}, {
|
||||
hl('InvalidSingleQuote', '\''),
|
||||
hl('InvalidSingleQuote', "'"),
|
||||
})
|
||||
check_parsing('"a', {
|
||||
-- 01
|
||||
@ -4923,71 +4924,71 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
hl('InvalidDoubleQuote', '"'),
|
||||
hl('InvalidDoubleQuotedBody', 'a'),
|
||||
})
|
||||
check_parsing('\'a', {
|
||||
check_parsing("'a", {
|
||||
-- 01
|
||||
ast = {
|
||||
fmtn('SingleQuotedString', 'val="a"', ':0:0:\'a'),
|
||||
fmtn('SingleQuotedString', 'val="a"', ":0:0:'a"),
|
||||
},
|
||||
err = {
|
||||
arg = '\'a',
|
||||
arg = "'a",
|
||||
msg = 'E115: Missing single quote: %.*s',
|
||||
},
|
||||
}, {
|
||||
hl('InvalidSingleQuote', '\''),
|
||||
hl('InvalidSingleQuote', "'"),
|
||||
hl('InvalidSingleQuotedBody', 'a'),
|
||||
})
|
||||
check_parsing('\'abc\'\'def\'', {
|
||||
check_parsing("'abc''def'", {
|
||||
-- 0123456789
|
||||
ast = {
|
||||
fmtn('SingleQuotedString', 'val="abc\'def"', ':0:0:\'abc\'\'def\''),
|
||||
fmtn('SingleQuotedString', 'val="abc\'def"', ":0:0:'abc''def'"),
|
||||
},
|
||||
}, {
|
||||
hl('SingleQuote', '\''),
|
||||
hl('SingleQuote', "'"),
|
||||
hl('SingleQuotedBody', 'abc'),
|
||||
hl('SingleQuotedQuote', '\'\''),
|
||||
hl('SingleQuotedQuote', "''"),
|
||||
hl('SingleQuotedBody', 'def'),
|
||||
hl('SingleQuote', '\''),
|
||||
hl('SingleQuote', "'"),
|
||||
})
|
||||
check_parsing('\'abc\'\'', {
|
||||
check_parsing("'abc''", {
|
||||
-- 012345
|
||||
ast = {
|
||||
fmtn('SingleQuotedString', 'val="abc\'"', ':0:0:\'abc\'\''),
|
||||
fmtn('SingleQuotedString', 'val="abc\'"', ":0:0:'abc''"),
|
||||
},
|
||||
err = {
|
||||
arg = '\'abc\'\'',
|
||||
arg = "'abc''",
|
||||
msg = 'E115: Missing single quote: %.*s',
|
||||
},
|
||||
}, {
|
||||
hl('InvalidSingleQuote', '\''),
|
||||
hl('InvalidSingleQuote', "'"),
|
||||
hl('InvalidSingleQuotedBody', 'abc'),
|
||||
hl('InvalidSingleQuotedQuote', '\'\''),
|
||||
hl('InvalidSingleQuotedQuote', "''"),
|
||||
})
|
||||
check_parsing('\'\'\'\'\'\'\'\'', {
|
||||
check_parsing("''''''''", {
|
||||
-- 01234567
|
||||
ast = {
|
||||
fmtn('SingleQuotedString', 'val="\'\'\'"', ':0:0:\'\'\'\'\'\'\'\''),
|
||||
fmtn('SingleQuotedString', "val=\"'''\"", ":0:0:''''''''"),
|
||||
},
|
||||
}, {
|
||||
hl('SingleQuote', '\''),
|
||||
hl('SingleQuotedQuote', '\'\''),
|
||||
hl('SingleQuotedQuote', '\'\''),
|
||||
hl('SingleQuotedQuote', '\'\''),
|
||||
hl('SingleQuote', '\''),
|
||||
hl('SingleQuote', "'"),
|
||||
hl('SingleQuotedQuote', "''"),
|
||||
hl('SingleQuotedQuote', "''"),
|
||||
hl('SingleQuotedQuote', "''"),
|
||||
hl('SingleQuote', "'"),
|
||||
})
|
||||
check_parsing('\'\'\'a\'\'\'\'bc\'', {
|
||||
check_parsing("'''a''''bc'", {
|
||||
-- 01234567890
|
||||
-- 0 1
|
||||
ast = {
|
||||
fmtn('SingleQuotedString', 'val="\'a\'\'bc"', ':0:0:\'\'\'a\'\'\'\'bc\''),
|
||||
fmtn('SingleQuotedString', "val=\"'a''bc\"", ":0:0:'''a''''bc'"),
|
||||
},
|
||||
}, {
|
||||
hl('SingleQuote', '\''),
|
||||
hl('SingleQuotedQuote', '\'\''),
|
||||
hl('SingleQuote', "'"),
|
||||
hl('SingleQuotedQuote', "''"),
|
||||
hl('SingleQuotedBody', 'a'),
|
||||
hl('SingleQuotedQuote', '\'\''),
|
||||
hl('SingleQuotedQuote', '\'\''),
|
||||
hl('SingleQuotedQuote', "''"),
|
||||
hl('SingleQuotedQuote', "''"),
|
||||
hl('SingleQuotedBody', 'bc'),
|
||||
hl('SingleQuote', '\''),
|
||||
hl('SingleQuote', "'"),
|
||||
})
|
||||
check_parsing('"\\"\\"\\"\\""', {
|
||||
-- 0123456789
|
||||
@ -5006,7 +5007,11 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
-- 0123456789012345678901234
|
||||
-- 0 1 2
|
||||
ast = {
|
||||
fmtn('DoubleQuotedString', 'val="abc\\"def\\"ghi\\"jkl\\"mno"', ':0:0:"abc\\"def\\"ghi\\"jkl\\"mno"'),
|
||||
fmtn(
|
||||
'DoubleQuotedString',
|
||||
'val="abc\\"def\\"ghi\\"jkl\\"mno"',
|
||||
':0:0:"abc\\"def\\"ghi\\"jkl\\"mno"'
|
||||
),
|
||||
},
|
||||
}, {
|
||||
hl('DoubleQuote', '"'),
|
||||
@ -6977,8 +6982,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
arg = '\0002&A:\000',
|
||||
msg = 'E15: Expected value, got EOC: %.*s',
|
||||
},
|
||||
}, {
|
||||
}, {
|
||||
}, {}, {
|
||||
[2] = {
|
||||
ast = {
|
||||
len = REMOVE_THIS,
|
||||
@ -7025,7 +7029,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
},
|
||||
},
|
||||
})
|
||||
check_parsing({data='01', size=1}, {
|
||||
check_parsing({ data = '01', size = 1 }, {
|
||||
len = 1,
|
||||
ast = {
|
||||
'Integer(val=0):0:0:0',
|
||||
@ -7033,7 +7037,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
}, {
|
||||
hl('Number', '0'),
|
||||
})
|
||||
check_parsing({data='001', size=2}, {
|
||||
check_parsing({ data = '001', size = 2 }, {
|
||||
len = 2,
|
||||
ast = {
|
||||
'Integer(val=0):0:0:00',
|
||||
@ -7076,8 +7080,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
arg = '|"\\U\\',
|
||||
msg = 'E15: Expected value, got EOC: %.*s',
|
||||
},
|
||||
}, {
|
||||
}, {
|
||||
}, {}, {
|
||||
[2] = {
|
||||
ast = {
|
||||
len = REMOVE_THIS,
|
||||
@ -7109,8 +7112,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
arg = '|"\\e"',
|
||||
msg = 'E15: Expected value, got EOC: %.*s',
|
||||
},
|
||||
}, {
|
||||
}, {
|
||||
}, {}, {
|
||||
[2] = {
|
||||
ast = {
|
||||
len = REMOVE_THIS,
|
||||
@ -7142,8 +7144,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
arg = '|\029',
|
||||
msg = 'E15: Expected value, got EOC: %.*s',
|
||||
},
|
||||
}, {
|
||||
}, {
|
||||
}, {}, {
|
||||
[2] = {
|
||||
ast = {
|
||||
len = REMOVE_THIS,
|
||||
@ -7373,7 +7374,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
||||
hl_fs = {
|
||||
[2] = REMOVE_THIS,
|
||||
[3] = REMOVE_THIS,
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -76,7 +76,7 @@ local function pstate_set_str(pstate, start, len, ret)
|
||||
ret = ret or {}
|
||||
ret.start = {
|
||||
line = tonumber(start.line),
|
||||
col = tonumber(start.col)
|
||||
col = tonumber(start.col),
|
||||
}
|
||||
ret.len = tonumber(len)
|
||||
ret.str, ret.error = pstate_str(pstate, start, len)
|
||||
@ -84,36 +84,57 @@ local function pstate_set_str(pstate, start, len, ret)
|
||||
end
|
||||
|
||||
local eltkn_cmp_type_tab
|
||||
make_enum_conv_tab(lib, {
|
||||
make_enum_conv_tab(
|
||||
lib,
|
||||
{
|
||||
'kExprCmpEqual',
|
||||
'kExprCmpMatches',
|
||||
'kExprCmpGreater',
|
||||
'kExprCmpGreaterOrEqual',
|
||||
'kExprCmpIdentical',
|
||||
}, 'kExprCmp', function(ret) eltkn_cmp_type_tab = ret end)
|
||||
},
|
||||
'kExprCmp',
|
||||
function(ret)
|
||||
eltkn_cmp_type_tab = ret
|
||||
end
|
||||
)
|
||||
|
||||
local function conv_cmp_type(typ)
|
||||
return conv_enum(eltkn_cmp_type_tab, typ)
|
||||
end
|
||||
|
||||
local ccs_tab
|
||||
make_enum_conv_tab(lib, {
|
||||
make_enum_conv_tab(
|
||||
lib,
|
||||
{
|
||||
'kCCStrategyUseOption',
|
||||
'kCCStrategyMatchCase',
|
||||
'kCCStrategyIgnoreCase',
|
||||
}, 'kCCStrategy', function(ret) ccs_tab = ret end)
|
||||
},
|
||||
'kCCStrategy',
|
||||
function(ret)
|
||||
ccs_tab = ret
|
||||
end
|
||||
)
|
||||
|
||||
local function conv_ccs(ccs)
|
||||
return conv_enum(ccs_tab, ccs)
|
||||
end
|
||||
|
||||
local expr_asgn_type_tab
|
||||
make_enum_conv_tab(lib, {
|
||||
make_enum_conv_tab(
|
||||
lib,
|
||||
{
|
||||
'kExprAsgnPlain',
|
||||
'kExprAsgnAdd',
|
||||
'kExprAsgnSubtract',
|
||||
'kExprAsgnConcat',
|
||||
}, 'kExprAsgn', function(ret) expr_asgn_type_tab = ret end)
|
||||
},
|
||||
'kExprAsgn',
|
||||
function(ret)
|
||||
expr_asgn_type_tab = ret
|
||||
end
|
||||
)
|
||||
|
||||
local function conv_expr_asgn_type(expr_asgn_type)
|
||||
return conv_enum(expr_asgn_type_tab, expr_asgn_type)
|
||||
|
Loading…
Reference in New Issue
Block a user