mirror of
https://github.com/neovim/neovim
synced 2025-07-18 10:11:50 +00: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:
@ -2,4 +2,10 @@
|
|||||||
/runtime/lua/coxpcall.lua
|
/runtime/lua/coxpcall.lua
|
||||||
/runtime/lua/vim/_meta
|
/runtime/lua/vim/_meta
|
||||||
/runtime/lua/vim/re.lua
|
/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
|
TARGET lintlua-stylua
|
||||||
COMMAND ${STYLUA_PRG}
|
COMMAND ${STYLUA_PRG}
|
||||||
FLAGS --color=always --check --respect-ignores
|
FLAGS --color=always --check --respect-ignores
|
||||||
GLOB_DIRS runtime/ scripts/ src/
|
GLOB_DIRS runtime/ scripts/ src/ test/unit/
|
||||||
GLOB_PAT *.lua
|
GLOB_PAT *.lua
|
||||||
TOUCH_STRATEGY SINGLE)
|
TOUCH_STRATEGY SINGLE)
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ add_glob_target(
|
|||||||
TARGET formatlua
|
TARGET formatlua
|
||||||
COMMAND ${STYLUA_PRG}
|
COMMAND ${STYLUA_PRG}
|
||||||
FLAGS --respect-ignores
|
FLAGS --respect-ignores
|
||||||
GLOB_DIRS runtime/ scripts/ src/
|
GLOB_DIRS runtime/ scripts/ src/ test/unit/
|
||||||
GLOB_PAT *.lua)
|
GLOB_PAT *.lua)
|
||||||
|
|
||||||
add_custom_target(format)
|
add_custom_target(format)
|
||||||
|
@ -27,7 +27,8 @@ describe('autocmd perf', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('nvim_create_autocmd, nvim_del_autocmd (same pattern)', function()
|
it('nvim_create_autocmd, nvim_del_autocmd (same pattern)', function()
|
||||||
exec_lua([[
|
exec_lua(
|
||||||
|
[[
|
||||||
local N = ...
|
local N = ...
|
||||||
local ids = {}
|
local ids = {}
|
||||||
|
|
||||||
@ -45,11 +46,14 @@ describe('autocmd perf', function()
|
|||||||
vim.api.nvim_del_autocmd(ids[i])
|
vim.api.nvim_del_autocmd(ids[i])
|
||||||
end
|
end
|
||||||
stop('nvim_del_autocmd')
|
stop('nvim_del_autocmd')
|
||||||
]], N)
|
]],
|
||||||
|
N
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('nvim_create_autocmd, nvim_del_autocmd (unique patterns)', function()
|
it('nvim_create_autocmd, nvim_del_autocmd (unique patterns)', function()
|
||||||
exec_lua([[
|
exec_lua(
|
||||||
|
[[
|
||||||
local N = ...
|
local N = ...
|
||||||
local ids = {}
|
local ids = {}
|
||||||
|
|
||||||
@ -67,11 +71,14 @@ describe('autocmd perf', function()
|
|||||||
vim.api.nvim_del_autocmd(ids[i])
|
vim.api.nvim_del_autocmd(ids[i])
|
||||||
end
|
end
|
||||||
stop('nvim_del_autocmd')
|
stop('nvim_del_autocmd')
|
||||||
]], N)
|
]],
|
||||||
|
N
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('nvim_create_autocmd + nvim_del_autocmd', function()
|
it('nvim_create_autocmd + nvim_del_autocmd', function()
|
||||||
exec_lua([[
|
exec_lua(
|
||||||
|
[[
|
||||||
local N = ...
|
local N = ...
|
||||||
|
|
||||||
start()
|
start()
|
||||||
@ -83,11 +90,14 @@ describe('autocmd perf', function()
|
|||||||
vim.api.nvim_del_autocmd(id)
|
vim.api.nvim_del_autocmd(id)
|
||||||
end
|
end
|
||||||
stop('nvim_create_autocmd + nvim_del_autocmd')
|
stop('nvim_create_autocmd + nvim_del_autocmd')
|
||||||
]], N)
|
]],
|
||||||
|
N
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('nvim_exec_autocmds (same pattern)', function()
|
it('nvim_exec_autocmds (same pattern)', function()
|
||||||
exec_lua([[
|
exec_lua(
|
||||||
|
[[
|
||||||
local N = ...
|
local N = ...
|
||||||
|
|
||||||
for i = 1, N do
|
for i = 1, N do
|
||||||
@ -100,11 +110,14 @@ describe('autocmd perf', function()
|
|||||||
start()
|
start()
|
||||||
vim.api.nvim_exec_autocmds('User', { pattern = 'Benchmark', modeline = false })
|
vim.api.nvim_exec_autocmds('User', { pattern = 'Benchmark', modeline = false })
|
||||||
stop('nvim_exec_autocmds')
|
stop('nvim_exec_autocmds')
|
||||||
]], N)
|
]],
|
||||||
|
N
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('nvim_del_augroup_by_id', function()
|
it('nvim_del_augroup_by_id', function()
|
||||||
exec_lua([[
|
exec_lua(
|
||||||
|
[[
|
||||||
local N = ...
|
local N = ...
|
||||||
local group = vim.api.nvim_create_augroup('Benchmark', {})
|
local group = vim.api.nvim_create_augroup('Benchmark', {})
|
||||||
|
|
||||||
@ -119,11 +132,14 @@ describe('autocmd perf', function()
|
|||||||
start()
|
start()
|
||||||
vim.api.nvim_del_augroup_by_id(group)
|
vim.api.nvim_del_augroup_by_id(group)
|
||||||
stop('nvim_del_augroup_by_id')
|
stop('nvim_del_augroup_by_id')
|
||||||
]], N)
|
]],
|
||||||
|
N
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('nvim_del_augroup_by_name', function()
|
it('nvim_del_augroup_by_name', function()
|
||||||
exec_lua([[
|
exec_lua(
|
||||||
|
[[
|
||||||
local N = ...
|
local N = ...
|
||||||
local group = vim.api.nvim_create_augroup('Benchmark', {})
|
local group = vim.api.nvim_create_augroup('Benchmark', {})
|
||||||
|
|
||||||
@ -138,11 +154,14 @@ describe('autocmd perf', function()
|
|||||||
start()
|
start()
|
||||||
vim.api.nvim_del_augroup_by_name('Benchmark')
|
vim.api.nvim_del_augroup_by_name('Benchmark')
|
||||||
stop('nvim_del_augroup_by_id')
|
stop('nvim_del_augroup_by_id')
|
||||||
]], N)
|
]],
|
||||||
|
N
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it(':autocmd, :autocmd! (same pattern)', function()
|
it(':autocmd, :autocmd! (same pattern)', function()
|
||||||
exec_lua([[
|
exec_lua(
|
||||||
|
[[
|
||||||
local N = ...
|
local N = ...
|
||||||
|
|
||||||
start()
|
start()
|
||||||
@ -154,11 +173,14 @@ describe('autocmd perf', function()
|
|||||||
start()
|
start()
|
||||||
vim.cmd('autocmd! User Benchmark')
|
vim.cmd('autocmd! User Benchmark')
|
||||||
stop(':autocmd!')
|
stop(':autocmd!')
|
||||||
]], N)
|
]],
|
||||||
|
N
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it(':autocmd, :autocmd! (unique patterns)', function()
|
it(':autocmd, :autocmd! (unique patterns)', function()
|
||||||
exec_lua([[
|
exec_lua(
|
||||||
|
[[
|
||||||
local N = ...
|
local N = ...
|
||||||
|
|
||||||
start()
|
start()
|
||||||
@ -170,6 +192,8 @@ describe('autocmd perf', function()
|
|||||||
start()
|
start()
|
||||||
vim.cmd('autocmd! User')
|
vim.cmd('autocmd! User')
|
||||||
stop(':autocmd!')
|
stop(':autocmd!')
|
||||||
]], N)
|
]],
|
||||||
|
N
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -10,8 +10,7 @@ local result_file = 'benchmark.out'
|
|||||||
local sample_file = 'test/old/testdir/samples/re.freeze.txt'
|
local sample_file = 'test/old/testdir/samples/re.freeze.txt'
|
||||||
|
|
||||||
-- Vim script code that does both the work and the benchmarking of that work.
|
-- Vim script code that does both the work and the benchmarking of that work.
|
||||||
local measure_cmd =
|
local measure_cmd = [[call Measure(%d, ']] .. sample_file .. [[', '\s\+\%%#\@<!$', '+5')]]
|
||||||
[[call Measure(%d, ']] .. sample_file .. [[', '\s\+\%%#\@<!$', '+5')]]
|
|
||||||
local measure_script = [[
|
local measure_script = [[
|
||||||
func Measure(re, file, pattern, arg)
|
func Measure(re, file, pattern, arg)
|
||||||
let sstart = reltime()
|
let sstart = reltime()
|
||||||
|
@ -4,7 +4,6 @@ local clear = helpers.clear
|
|||||||
local exec_lua = helpers.exec_lua
|
local exec_lua = helpers.exec_lua
|
||||||
|
|
||||||
describe('treesitter perf', function()
|
describe('treesitter perf', function()
|
||||||
|
|
||||||
setup(function()
|
setup(function()
|
||||||
clear()
|
clear()
|
||||||
end)
|
end)
|
||||||
@ -47,7 +46,5 @@ describe('treesitter perf', function()
|
|||||||
|
|
||||||
return vim.uv.hrtime() - start
|
return vim.uv.hrtime() - start
|
||||||
]]
|
]]
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
local pretty = require 'pl.pretty'
|
local pretty = require 'pl.pretty'
|
||||||
local global_helpers = require('test.helpers')
|
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
|
local enable_colors = true
|
||||||
if os.getenv "TEST_COLORS" then
|
if os.getenv 'TEST_COLORS' then
|
||||||
local test_colors = os.getenv("TEST_COLORS"):lower()
|
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'
|
local disable_colors = test_colors == 'false'
|
||||||
|
or test_colors == '0'
|
||||||
|
or test_colors == 'no'
|
||||||
|
or test_colors == 'off'
|
||||||
enable_colors = not disable_colors
|
enable_colors = not disable_colors
|
||||||
end
|
end
|
||||||
if enable_colors then
|
if enable_colors then
|
||||||
@ -18,15 +27,25 @@ return function(options)
|
|||||||
local handler = require 'busted.outputHandlers.base'()
|
local handler = require 'busted.outputHandlers.base'()
|
||||||
|
|
||||||
local c = {
|
local c = {
|
||||||
succ = function(s) return colors.bright(colors.green(s)) end,
|
succ = function(s)
|
||||||
skip = function(s) return colors.bright(colors.yellow(s)) end,
|
return colors.bright(colors.green(s))
|
||||||
fail = function(s) return colors.bright(colors.magenta(s)) end,
|
end,
|
||||||
errr = function(s) return colors.bright(colors.red(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,
|
test = tostring,
|
||||||
file = colors.cyan,
|
file = colors.cyan,
|
||||||
time = colors.dim,
|
time = colors.dim,
|
||||||
note = colors.yellow,
|
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,
|
nmbr = colors.bright,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,9 +58,23 @@ return function(options)
|
|||||||
local skippedString = c.skip('SKIP') .. '\n'
|
local skippedString = c.skip('SKIP') .. '\n'
|
||||||
local failureString = c.fail('FAIL') .. '\n'
|
local failureString = c.fail('FAIL') .. '\n'
|
||||||
local errorString = c.errr('ERR') .. '\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 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 successStatus = c.succ('PASSED ') .. ' ' .. c.nmbr('%d') .. ' %s.\n'
|
||||||
local timeString = c.time('%.2f ms')
|
local timeString = c.time('%.2f ms')
|
||||||
|
|
||||||
@ -107,8 +140,10 @@ return function(options)
|
|||||||
local getFileLine = function(element)
|
local getFileLine = function(element)
|
||||||
local fileline = ''
|
local fileline = ''
|
||||||
if element.trace or element.trace.short_src then
|
if element.trace or element.trace.short_src then
|
||||||
fileline = colors.cyan(element.trace.short_src) .. ' @ ' ..
|
fileline = colors.cyan(element.trace.short_src)
|
||||||
colors.cyan(element.trace.currentline) .. ': '
|
.. ' @ '
|
||||||
|
.. colors.cyan(element.trace.currentline)
|
||||||
|
.. ': '
|
||||||
end
|
end
|
||||||
return fileline
|
return fileline
|
||||||
end
|
end
|
||||||
@ -219,7 +254,9 @@ return function(options)
|
|||||||
local elapsedTime_ms = getElapsedTime(file)
|
local elapsedTime_ms = getElapsedTime(file)
|
||||||
local tests = (fileTestCount == 1 and 'test' or 'tests')
|
local tests = (fileTestCount == 1 and 'test' or 'tests')
|
||||||
fileCount = fileCount + 1
|
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()
|
io.flush()
|
||||||
return nil, true
|
return nil, true
|
||||||
end
|
end
|
||||||
@ -256,7 +293,7 @@ return function(options)
|
|||||||
errorCount = errorCount + 1
|
errorCount = errorCount + 1
|
||||||
string = errorString .. failureDescription(handler.errors[#handler.errors])
|
string = errorString .. failureDescription(handler.errors[#handler.errors])
|
||||||
else
|
else
|
||||||
string = "unexpected test status! ("..status..")"
|
string = 'unexpected test status! (' .. status .. ')'
|
||||||
end
|
end
|
||||||
write_status(element, string)
|
write_status(element, string)
|
||||||
|
|
||||||
|
@ -3,13 +3,19 @@ local mpack = require('mpack')
|
|||||||
-- temporary hack to be able to manipulate buffer/window/tabpage
|
-- temporary hack to be able to manipulate buffer/window/tabpage
|
||||||
local Buffer = {}
|
local Buffer = {}
|
||||||
Buffer.__index = 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 = {}
|
local Window = {}
|
||||||
Window.__index = 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 = {}
|
local Tabpage = {}
|
||||||
Tabpage.__index = 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 = {}
|
local Response = {}
|
||||||
Response.__index = Response
|
Response.__index = Response
|
||||||
@ -17,7 +23,7 @@ Response.__index = Response
|
|||||||
function Response.new(msgpack_rpc_stream, request_id)
|
function Response.new(msgpack_rpc_stream, request_id)
|
||||||
return setmetatable({
|
return setmetatable({
|
||||||
_msgpack_rpc_stream = msgpack_rpc_stream,
|
_msgpack_rpc_stream = msgpack_rpc_stream,
|
||||||
_request_id = request_id
|
_request_id = request_id,
|
||||||
}, Response)
|
}, Response)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -41,19 +47,31 @@ function MsgpackRpcStream.new(stream)
|
|||||||
_stream = stream,
|
_stream = stream,
|
||||||
_pack = mpack.Packer({
|
_pack = mpack.Packer({
|
||||||
ext = {
|
ext = {
|
||||||
[Buffer] = function(o) return 0, mpack.encode(o.id) end,
|
[Buffer] = function(o)
|
||||||
[Window] = function(o) return 1, mpack.encode(o.id) end,
|
return 0, mpack.encode(o.id)
|
||||||
[Tabpage] = function(o) return 2, mpack.encode(o.id) end
|
end,
|
||||||
}
|
[Window] = function(o)
|
||||||
|
return 1, mpack.encode(o.id)
|
||||||
|
end,
|
||||||
|
[Tabpage] = function(o)
|
||||||
|
return 2, mpack.encode(o.id)
|
||||||
|
end,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
_session = mpack.Session({
|
_session = mpack.Session({
|
||||||
unpack = mpack.Unpacker({
|
unpack = mpack.Unpacker({
|
||||||
ext = {
|
ext = {
|
||||||
[0] = function(_c, s) return Buffer.new(mpack.decode(s)) end,
|
[0] = function(_c, s)
|
||||||
[1] = function(_c, s) return Window.new(mpack.decode(s)) end,
|
return Buffer.new(mpack.decode(s))
|
||||||
[2] = function(_c, s) return Tabpage.new(mpack.decode(s)) end
|
end,
|
||||||
}
|
[1] = function(_c, s)
|
||||||
})
|
return Window.new(mpack.decode(s))
|
||||||
|
end,
|
||||||
|
[2] = function(_c, s)
|
||||||
|
return Tabpage.new(mpack.decode(s))
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
}, MsgpackRpcStream)
|
}, MsgpackRpcStream)
|
||||||
end
|
end
|
||||||
@ -80,12 +98,10 @@ function MsgpackRpcStream:read_start(request_cb, notification_cb, eof_cb)
|
|||||||
local pos = 1
|
local pos = 1
|
||||||
local len = #data
|
local len = #data
|
||||||
while pos <= len do
|
while pos <= len do
|
||||||
type, id_or_cb, method_or_error, args_or_result, pos =
|
type, id_or_cb, method_or_error, args_or_result, pos = self._session:receive(data, pos)
|
||||||
self._session:receive(data, pos)
|
|
||||||
if type == 'request' or type == 'notification' then
|
if type == 'request' or type == 'notification' then
|
||||||
if type == 'request' then
|
if type == 'request' then
|
||||||
request_cb(method_or_error, args_or_result, Response.new(self,
|
request_cb(method_or_error, args_or_result, Response.new(self, id_or_cb))
|
||||||
id_or_cb))
|
|
||||||
else
|
else
|
||||||
notification_cb(method_or_error, args_or_result)
|
notification_cb(method_or_error, args_or_result)
|
||||||
end
|
end
|
||||||
|
@ -50,7 +50,7 @@ function Session.new(stream)
|
|||||||
_pending_messages = {},
|
_pending_messages = {},
|
||||||
_prepare = uv.new_prepare(),
|
_prepare = uv.new_prepare(),
|
||||||
_timer = uv.new_timer(),
|
_timer = uv.new_timer(),
|
||||||
_is_running = false
|
_is_running = false,
|
||||||
}, Session)
|
}, Session)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -141,8 +141,12 @@ function Session:stop()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Session:close(signal)
|
function Session:close(signal)
|
||||||
if not self._timer:is_closing() then self._timer:close() end
|
if not self._timer:is_closing() then
|
||||||
if not self._prepare:is_closing() then self._prepare:close() end
|
self._timer:close()
|
||||||
|
end
|
||||||
|
if not self._prepare:is_closing() then
|
||||||
|
self._prepare:close()
|
||||||
|
end
|
||||||
self._msgpack_rpc_stream:close(signal)
|
self._msgpack_rpc_stream:close(signal)
|
||||||
self.closed = true
|
self.closed = true
|
||||||
end
|
end
|
||||||
@ -187,7 +191,7 @@ function Session:_run(request_cb, notification_cb, timeout)
|
|||||||
end
|
end
|
||||||
self._msgpack_rpc_stream:read_start(request_cb, notification_cb, function()
|
self._msgpack_rpc_stream:read_start(request_cb, notification_cb, function()
|
||||||
uv.stop()
|
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)
|
end)
|
||||||
uv.run()
|
uv.run()
|
||||||
self._prepare:stop()
|
self._prepare:stop()
|
||||||
|
@ -6,7 +6,7 @@ StdioStream.__index = StdioStream
|
|||||||
function StdioStream.open()
|
function StdioStream.open()
|
||||||
local self = setmetatable({
|
local self = setmetatable({
|
||||||
_in = uv.new_pipe(false),
|
_in = uv.new_pipe(false),
|
||||||
_out = uv.new_pipe(false)
|
_out = uv.new_pipe(false),
|
||||||
}, StdioStream)
|
}, StdioStream)
|
||||||
self._in:open(0)
|
self._in:open(0)
|
||||||
self._out:open(1)
|
self._out:open(1)
|
||||||
@ -42,7 +42,7 @@ function SocketStream.open(file)
|
|||||||
local socket = uv.new_pipe(false)
|
local socket = uv.new_pipe(false)
|
||||||
local self = setmetatable({
|
local self = setmetatable({
|
||||||
_socket = socket,
|
_socket = socket,
|
||||||
_stream_error = nil
|
_stream_error = nil,
|
||||||
}, SocketStream)
|
}, SocketStream)
|
||||||
uv.pipe_connect(socket, file, function(err)
|
uv.pipe_connect(socket, file, function(err)
|
||||||
self._stream_error = self._stream_error or err
|
self._stream_error = self._stream_error or err
|
||||||
@ -54,7 +54,7 @@ function SocketStream.connect(host, port)
|
|||||||
local socket = uv.new_tcp()
|
local socket = uv.new_tcp()
|
||||||
local self = setmetatable({
|
local self = setmetatable({
|
||||||
_socket = socket,
|
_socket = socket,
|
||||||
_stream_error = nil
|
_stream_error = nil,
|
||||||
}, SocketStream)
|
}, 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
|
self._stream_error = self._stream_error or err
|
||||||
@ -62,7 +62,6 @@ function SocketStream.connect(host, port)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function SocketStream:write(data)
|
function SocketStream:write(data)
|
||||||
if self._stream_error then
|
if self._stream_error then
|
||||||
error(self._stream_error)
|
error(self._stream_error)
|
||||||
@ -102,9 +101,9 @@ ChildProcessStream.__index = ChildProcessStream
|
|||||||
|
|
||||||
function ChildProcessStream.spawn(argv, env, io_extra)
|
function ChildProcessStream.spawn(argv, env, io_extra)
|
||||||
local self = setmetatable({
|
local self = setmetatable({
|
||||||
_child_stdin = uv.new_pipe(false);
|
_child_stdin = uv.new_pipe(false),
|
||||||
_child_stdout = uv.new_pipe(false);
|
_child_stdout = uv.new_pipe(false),
|
||||||
_exiting = false;
|
_exiting = false,
|
||||||
}, ChildProcessStream)
|
}, ChildProcessStream)
|
||||||
local prog = argv[1]
|
local prog = argv[1]
|
||||||
local args = {}
|
local args = {}
|
||||||
@ -163,7 +162,7 @@ function ChildProcessStream:close(signal)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
StdioStream = StdioStream;
|
StdioStream = StdioStream,
|
||||||
ChildProcessStream = ChildProcessStream;
|
ChildProcessStream = ChildProcessStream,
|
||||||
SocketStream = SocketStream;
|
SocketStream = SocketStream,
|
||||||
}
|
}
|
||||||
|
170
test/helpers.lua
170
test/helpers.lua
@ -25,7 +25,7 @@ local module = {
|
|||||||
local function relpath(p)
|
local function relpath(p)
|
||||||
p = vim.fs.normalize(p)
|
p = vim.fs.normalize(p)
|
||||||
local cwd = luv.cwd()
|
local cwd = luv.cwd()
|
||||||
return p:gsub("^" .. cwd)
|
return p:gsub('^' .. cwd)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param path string
|
--- @param path string
|
||||||
@ -94,7 +94,7 @@ function module.retry(max, max_ms, fn)
|
|||||||
end
|
end
|
||||||
luv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
|
luv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
|
||||||
if (max and tries >= max) or (luv.now() - start_time > timeout) then
|
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
|
end
|
||||||
tries = tries + 1
|
tries = tries + 1
|
||||||
luv.sleep(20) -- Avoid hot loop...
|
luv.sleep(20) -- Avoid hot loop...
|
||||||
@ -120,7 +120,10 @@ end
|
|||||||
--- @param expected (any) description of expected result
|
--- @param expected (any) description of expected result
|
||||||
--- @param actual (any) description of actual result
|
--- @param actual (any) description of actual result
|
||||||
function module.ok(cond, expected, actual)
|
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
|
local msg = expected and ('expected %s, got: %s'):format(expected, tostring(actual)) or nil
|
||||||
return assert(cond, msg)
|
return assert(cond, msg)
|
||||||
end
|
end
|
||||||
@ -129,7 +132,7 @@ local function epicfail(state, arguments, _)
|
|||||||
state.failure_message = arguments[1]
|
state.failure_message = arguments[1]
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
assert:register("assertion", "epicfail", epicfail)
|
assert:register('assertion', 'epicfail', epicfail)
|
||||||
function module.fail(msg)
|
function module.fail(msg)
|
||||||
return assert.epicfail(msg)
|
return assert.epicfail(msg)
|
||||||
end
|
end
|
||||||
@ -157,14 +160,26 @@ function module.assert_log(pat, logfile, nrlines, inverse)
|
|||||||
|
|
||||||
module.retry(nil, 1000, function()
|
module.retry(nil, 1000, function()
|
||||||
local lines = module.read_file_list(logfile, -nrlines) or {}
|
local lines = module.read_file_list(logfile, -nrlines) or {}
|
||||||
local msg = string.format('Pattern %q %sfound in log (last %d lines): %s:\n%s',
|
local msg = string.format(
|
||||||
pat, (inverse and '' or 'not '), nrlines, logfile, ' '..table.concat(lines, '\n '))
|
'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
|
for _, line in ipairs(lines) do
|
||||||
if line:match(pat) then
|
if line:match(pat) then
|
||||||
if inverse then error(msg) else return end
|
if inverse then
|
||||||
|
error(msg)
|
||||||
|
else
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not inverse then error(msg) end
|
end
|
||||||
|
if not inverse then
|
||||||
|
error(msg)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -186,7 +201,8 @@ function module.pcall(fn, ...)
|
|||||||
-- C:/long/path/foo.lua:186: Expected string, got number
|
-- C:/long/path/foo.lua:186: Expected string, got number
|
||||||
-- to:
|
-- to:
|
||||||
-- .../foo.lua:0: Expected string, got number
|
-- .../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('[^%s<]-[/\\]([^%s:/\\]+):%d+', '.../%1:0')
|
||||||
:gsub('\xffvim\xff', 'vim/')
|
:gsub('\xffvim\xff', 'vim/')
|
||||||
|
|
||||||
@ -233,7 +249,8 @@ end
|
|||||||
function module.pcall_err_withtrace(fn, ...)
|
function module.pcall_err_withtrace(fn, ...)
|
||||||
local errmsg = module.pcall_err_withfile(fn, ...)
|
local errmsg = module.pcall_err_withfile(fn, ...)
|
||||||
|
|
||||||
return errmsg:gsub('^%.%.%./helpers%.lua:0: ', '')
|
return errmsg
|
||||||
|
:gsub('^%.%.%./helpers%.lua:0: ', '')
|
||||||
:gsub('^Error executing lua:- ', '')
|
:gsub('^Error executing lua:- ', '')
|
||||||
:gsub('^%[string "<nvim>"%]:0: ', '')
|
:gsub('^%[string "<nvim>"%]:0: ', '')
|
||||||
end
|
end
|
||||||
@ -243,7 +260,7 @@ function module.pcall_err(...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function module.remove_trace(s)
|
function module.remove_trace(s)
|
||||||
return (s:gsub("\n%s*stack traceback:.*", ""))
|
return (s:gsub('\n%s*stack traceback:.*', ''))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- initial_path: directory to recurse into
|
-- initial_path: directory to recurse into
|
||||||
@ -256,7 +273,9 @@ function module.glob(initial_path, re, exc_re)
|
|||||||
local checked_files = {}
|
local checked_files = {}
|
||||||
local function is_excluded(path)
|
local function is_excluded(path)
|
||||||
for _, pat in pairs(exc_re) do
|
for _, pat in pairs(exc_re) do
|
||||||
if path:match(pat) then return true end
|
if path:match(pat) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@ -331,9 +350,10 @@ function module.check_logs()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
assert(0 == #runtime_errors, string.format(
|
assert(
|
||||||
'Found runtime errors in logfile(s): %s',
|
0 == #runtime_errors,
|
||||||
table.concat(runtime_errors, ', ')))
|
string.format('Found runtime errors in logfile(s): %s', table.concat(runtime_errors, ', '))
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function module.sysname()
|
function module.sysname()
|
||||||
@ -344,18 +364,16 @@ function module.sysname()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function module.is_os(s)
|
function module.is_os(s)
|
||||||
if not (s == 'win'
|
if not (s == 'win' or s == 'mac' or s == 'freebsd' or s == 'openbsd' or s == 'bsd') then
|
||||||
or s == 'mac'
|
|
||||||
or s == 'freebsd'
|
|
||||||
or s == 'openbsd'
|
|
||||||
or s == 'bsd') then
|
|
||||||
error('unknown platform: ' .. tostring(s))
|
error('unknown platform: ' .. tostring(s))
|
||||||
end
|
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 == 'mac' and module.sysname() == 'darwin')
|
||||||
or (s == 'freebsd' and module.sysname() == 'freebsd')
|
or (s == 'freebsd' and module.sysname() == 'freebsd')
|
||||||
or (s == 'openbsd' and module.sysname() == 'openbsd')
|
or (s == 'openbsd' and module.sysname() == 'openbsd')
|
||||||
or (s == 'bsd' and module.sysname():find('bsd')))
|
or (s == 'bsd' and module.sysname():find('bsd'))
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function tmpdir_get()
|
local function tmpdir_get()
|
||||||
@ -371,7 +389,7 @@ end
|
|||||||
module.tmpname = (function()
|
module.tmpname = (function()
|
||||||
local seq = 0
|
local seq = 0
|
||||||
local tmpdir = tmpdir_get()
|
local tmpdir = tmpdir_get()
|
||||||
return (function()
|
return function()
|
||||||
if tmpdir_is_local(tmpdir) then
|
if tmpdir_is_local(tmpdir) then
|
||||||
-- Cannot control os.tmpname() dir, so hack our own tmpname() impl.
|
-- Cannot control os.tmpname() dir, so hack our own tmpname() impl.
|
||||||
seq = seq + 1
|
seq = seq + 1
|
||||||
@ -392,7 +410,7 @@ module.tmpname = (function()
|
|||||||
return fname
|
return fname
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end
|
||||||
end)()
|
end)()
|
||||||
|
|
||||||
function module.hasenv(name)
|
function module.hasenv(name)
|
||||||
@ -417,14 +435,17 @@ function module.check_cores(app, force) -- luacheck: ignore
|
|||||||
end
|
end
|
||||||
app = app or 'build/bin/nvim' -- luacheck: ignore
|
app = app or 'build/bin/nvim' -- luacheck: ignore
|
||||||
local initial_path, re, exc_re
|
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 lldb_db_cmd = 'lldb -Q -o "bt all" -f "$_NVIM_TEST_APP" -c "$_NVIM_TEST_CORE"'
|
||||||
local random_skip = false
|
local random_skip = false
|
||||||
-- Workspace-local $TMPDIR, scrubbed and pattern-escaped.
|
-- Workspace-local $TMPDIR, scrubbed and pattern-escaped.
|
||||||
-- "./Xtest-tmpdir/" => "Xtest%-tmpdir"
|
-- "./Xtest-tmpdir/" => "Xtest%-tmpdir"
|
||||||
local local_tmpdir = (tmpdir_is_local(tmpdir_get())
|
local local_tmpdir = (
|
||||||
|
tmpdir_is_local(tmpdir_get())
|
||||||
and relpath(tmpdir_get()):gsub('^[ ./]+', ''):gsub('%/+$', ''):gsub('([^%w])', '%%%1')
|
and relpath(tmpdir_get()):gsub('^[ ./]+', ''):gsub('%/+$', ''):gsub('([^%w])', '%%%1')
|
||||||
or nil)
|
or nil
|
||||||
|
)
|
||||||
local db_cmd
|
local db_cmd
|
||||||
if module.hasenv('NVIM_TEST_CORE_GLOB_DIRECTORY') then
|
if module.hasenv('NVIM_TEST_CORE_GLOB_DIRECTORY') then
|
||||||
initial_path = os.getenv('NVIM_TEST_CORE_GLOB_DIRECTORY')
|
initial_path = os.getenv('NVIM_TEST_CORE_GLOB_DIRECTORY')
|
||||||
@ -457,7 +478,7 @@ function module.check_cores(app, force) -- luacheck: ignore
|
|||||||
local found_cores = 0
|
local found_cores = 0
|
||||||
local out = io.stdout
|
local out = io.stdout
|
||||||
for _, core in ipairs(cores) do
|
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)
|
local esigns = ('='):rep(len / 2)
|
||||||
out:write(('\n%s Core file %s %s\n'):format(esigns, core, esigns))
|
out:write(('\n%s Core file %s %s\n'):format(esigns, core, esigns))
|
||||||
out:flush()
|
out:flush()
|
||||||
@ -471,7 +492,7 @@ function module.check_cores(app, force) -- luacheck: ignore
|
|||||||
end
|
end
|
||||||
tests_skipped = 0
|
tests_skipped = 0
|
||||||
if found_cores > 0 then
|
if found_cores > 0 then
|
||||||
error("crash detected (see above)")
|
error('crash detected (see above)')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -611,13 +632,38 @@ local function format_float(v)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local SUBTBL = {
|
local SUBTBL = {
|
||||||
'\\000', '\\001', '\\002', '\\003', '\\004',
|
'\\000',
|
||||||
'\\005', '\\006', '\\007', '\\008', '\\t',
|
'\\001',
|
||||||
'\\n', '\\011', '\\012', '\\r', '\\014',
|
'\\002',
|
||||||
'\\015', '\\016', '\\017', '\\018', '\\019',
|
'\\003',
|
||||||
'\\020', '\\021', '\\022', '\\023', '\\024',
|
'\\004',
|
||||||
'\\025', '\\026', '\\027', '\\028', '\\029',
|
'\\005',
|
||||||
'\\030', '\\031',
|
'\\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`.
|
-- Formats Lua value `v`.
|
||||||
@ -647,13 +693,14 @@ function module.format_luav(v, indent, opts)
|
|||||||
if opts.literal_strings then
|
if opts.literal_strings then
|
||||||
ret = v
|
ret = v
|
||||||
else
|
else
|
||||||
local quote = opts.dquote_strings and '"' or '\''
|
local quote = opts.dquote_strings and '"' or "'"
|
||||||
ret = quote .. tostring(v):gsub(
|
ret = quote
|
||||||
opts.dquote_strings and '["\\]' or '[\'\\]',
|
.. tostring(v)
|
||||||
'\\%0'):gsub(
|
:gsub(opts.dquote_strings and '["\\]' or "['\\]", '\\%0')
|
||||||
'[%z\1-\31]', function(match)
|
:gsub('[%z\1-\31]', function(match)
|
||||||
return SUBTBL[match:byte() + 1]
|
return SUBTBL[match:byte() + 1]
|
||||||
end) .. quote
|
end)
|
||||||
|
.. quote
|
||||||
end
|
end
|
||||||
elseif type(v) == 'table' then
|
elseif type(v) == 'table' then
|
||||||
if v == module.REMOVE_THIS then
|
if v == module.REMOVE_THIS then
|
||||||
@ -664,8 +711,7 @@ function module.format_luav(v, indent, opts)
|
|||||||
local non_empty = false
|
local non_empty = false
|
||||||
local format_luav = module.format_luav
|
local format_luav = module.format_luav
|
||||||
for i, subv in ipairs(v) do
|
for i, subv in ipairs(v) do
|
||||||
ret = ('%s%s%s,%s'):format(ret, next_indent,
|
ret = ('%s%s%s,%s'):format(ret, next_indent, format_luav(subv, next_indent_arg, opts), nl)
|
||||||
format_luav(subv, next_indent_arg, opts), nl)
|
|
||||||
processed_keys[i] = true
|
processed_keys[i] = true
|
||||||
non_empty = true
|
non_empty = true
|
||||||
end
|
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
|
if type(k) == 'string' and k:match('^[a-zA-Z_][a-zA-Z0-9_]*$') then
|
||||||
ret = ret .. next_indent .. k .. ' = '
|
ret = ret .. next_indent .. k .. ' = '
|
||||||
else
|
else
|
||||||
ret = ('%s%s[%s] = '):format(ret, next_indent,
|
ret = ('%s%s[%s] = '):format(ret, next_indent, format_luav(k, nil, opts))
|
||||||
format_luav(k, nil, opts))
|
|
||||||
end
|
end
|
||||||
ret = ret .. format_luav(subv, next_indent_arg, opts) .. ',' .. nl
|
ret = ret .. format_luav(subv, next_indent_arg, opts) .. ',' .. nl
|
||||||
non_empty = true
|
non_empty = true
|
||||||
@ -767,27 +812,27 @@ end
|
|||||||
|
|
||||||
function module.hexdump(str)
|
function module.hexdump(str)
|
||||||
local len = string.len(str)
|
local len = string.len(str)
|
||||||
local dump = ""
|
local dump = ''
|
||||||
local hex = ""
|
local hex = ''
|
||||||
local asc = ""
|
local asc = ''
|
||||||
|
|
||||||
for i = 1, len do
|
for i = 1, len do
|
||||||
if 1 == i % 8 then
|
if 1 == i % 8 then
|
||||||
dump = dump .. hex .. asc .. "\n"
|
dump = dump .. hex .. asc .. '\n'
|
||||||
hex = string.format("%04x: ", i - 1)
|
hex = string.format('%04x: ', i - 1)
|
||||||
asc = ""
|
asc = ''
|
||||||
end
|
end
|
||||||
|
|
||||||
local ord = string.byte(str, i)
|
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
|
if ord >= 32 and ord <= 126 then
|
||||||
asc = asc .. string.char(ord)
|
asc = asc .. string.char(ord)
|
||||||
else
|
else
|
||||||
asc = asc .. "."
|
asc = asc .. '.'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return dump .. hex .. string.rep(" ", 8 - len % 8) .. asc
|
return dump .. hex .. string.rep(' ', 8 - len % 8) .. asc
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Reads text lines from `filename` into a table.
|
-- 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
|
-- There is no need to read more than the last 2MB of the log file, so seek
|
||||||
-- to that.
|
-- to that.
|
||||||
local file_size = file:seek("end")
|
local file_size = file:seek('end')
|
||||||
local offset = file_size - 2000000
|
local offset = file_size - 2000000
|
||||||
if offset < 0 then
|
if offset < 0 then
|
||||||
offset = 0
|
offset = 0
|
||||||
end
|
end
|
||||||
file:seek("set", offset)
|
file:seek('set', offset)
|
||||||
|
|
||||||
local lines = {}
|
local lines = {}
|
||||||
local i = 1
|
local i = 1
|
||||||
local line = file:read("*l")
|
local line = file:read('*l')
|
||||||
while line ~= nil do
|
while line ~= nil do
|
||||||
if i >= start then
|
if i >= start then
|
||||||
table.insert(lines, line)
|
table.insert(lines, line)
|
||||||
@ -823,7 +868,7 @@ function module.read_file_list(filename, start)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
i = i + 1
|
i = i + 1
|
||||||
line = file:read("*l")
|
line = file:read('*l')
|
||||||
end
|
end
|
||||||
file:close()
|
file:close()
|
||||||
return lines
|
return lines
|
||||||
@ -875,9 +920,12 @@ function module.read_nvim_log(logfile, ci_rename)
|
|||||||
local is_ci = module.is_ci()
|
local is_ci = module.is_ci()
|
||||||
local keep = is_ci and 100 or 10
|
local keep = is_ci and 100 or 10
|
||||||
local lines = module.read_file_list(logfile, -keep) or {}
|
local lines = module.read_file_list(logfile, -keep) or {}
|
||||||
local log = (('-'):rep(78)..'\n'
|
local log = (
|
||||||
|
('-'):rep(78)
|
||||||
|
.. '\n'
|
||||||
.. string.format('$NVIM_LOG_FILE: %s\n', logfile)
|
.. string.format('$NVIM_LOG_FILE: %s\n', logfile)
|
||||||
..(#lines > 0 and '(last '..tostring(keep)..' lines)\n' or '(empty)\n'))
|
.. (#lines > 0 and '(last ' .. tostring(keep) .. ' lines)\n' or '(empty)\n')
|
||||||
|
)
|
||||||
for _, line in ipairs(lines) do
|
for _, line in ipairs(lines) do
|
||||||
log = log .. line .. '\n'
|
log = log .. line .. '\n'
|
||||||
end
|
end
|
||||||
|
@ -2,8 +2,12 @@ local platform = vim.uv.os_uname()
|
|||||||
local deps_install_dir = table.remove(_G.arg, 1)
|
local deps_install_dir = table.remove(_G.arg, 1)
|
||||||
local subcommand = 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'
|
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.path = deps_install_dir
|
||||||
package.cpath = deps_install_dir.."/lib/lua/5.1/?"..suffix..";"..package.cpath;
|
.. '/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
|
local uv = vim.uv
|
||||||
|
|
||||||
@ -39,7 +43,9 @@ function lfs.attributes(path, attr)
|
|||||||
if attr == 'mode' then
|
if attr == 'mode' then
|
||||||
return stat and stat.type or ''
|
return stat and stat.type or ''
|
||||||
elseif attr == 'modification' then
|
elseif attr == 'modification' then
|
||||||
if not stat then return nil end
|
if not stat then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
local mtime = stat.mtime
|
local mtime = stat.mtime
|
||||||
return mtime.sec + mtime.nsec * 1e-9
|
return mtime.sec + mtime.nsec * 1e-9
|
||||||
else
|
else
|
||||||
@ -74,9 +80,9 @@ function lfs.mkdir(dir)
|
|||||||
return uv.fs_mkdir(dir, 493) -- octal 755
|
return uv.fs_mkdir(dir, 493) -- octal 755
|
||||||
end
|
end
|
||||||
|
|
||||||
if subcommand == "busted" then
|
if subcommand == 'busted' then
|
||||||
require 'busted.runner'({ standalone = false })
|
require 'busted.runner'({ standalone = false })
|
||||||
elseif subcommand == "luacheck" then
|
elseif subcommand == 'luacheck' then
|
||||||
require 'luacheck.main'
|
require 'luacheck.main'
|
||||||
else
|
else
|
||||||
error 'unknown subcommand'
|
error 'unknown subcommand'
|
||||||
|
@ -13,9 +13,11 @@ local int_type = eval_helpers.int_type
|
|||||||
local flt_type = eval_helpers.flt_type
|
local flt_type = eval_helpers.flt_type
|
||||||
local type_key = eval_helpers.type_key
|
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/api/private/helpers.h',
|
||||||
'./src/nvim/memory.h')
|
'./src/nvim/memory.h'
|
||||||
|
)
|
||||||
|
|
||||||
local obj2lua
|
local obj2lua
|
||||||
|
|
||||||
@ -68,14 +70,18 @@ end
|
|||||||
|
|
||||||
obj2lua = function(obj)
|
obj2lua = function(obj)
|
||||||
init_obj2lua_tab()
|
init_obj2lua_tab()
|
||||||
return ((obj2lua_tab[tonumber(obj['type'])] or function(obj_inner)
|
return (
|
||||||
assert(false, 'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet')
|
(obj2lua_tab[tonumber(obj['type'])] or function(obj_inner)
|
||||||
end)(obj))
|
assert(
|
||||||
|
false,
|
||||||
|
'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet'
|
||||||
|
)
|
||||||
|
end)(obj)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local obj = function(typ, data)
|
local obj = function(typ, data)
|
||||||
return ffi.gc(ffi.new('Object', {['type']=typ, data=data}),
|
return ffi.gc(ffi.new('Object', { ['type'] = typ, data = data }), api.api_free_object)
|
||||||
api.api_free_object)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local lua2obj
|
local lua2obj
|
||||||
@ -89,11 +95,13 @@ local lua2obj_type_tab = {
|
|||||||
end,
|
end,
|
||||||
[list_type] = function(l)
|
[list_type] = function(l)
|
||||||
local len = #l
|
local len = #l
|
||||||
local arr = obj(api.kObjectTypeArray, {array={
|
local arr = obj(api.kObjectTypeArray, {
|
||||||
|
array = {
|
||||||
size = len,
|
size = len,
|
||||||
capacity = len,
|
capacity = len,
|
||||||
items = ffi.cast('Object *', api.xmalloc(len * ffi.sizeof('Object'))),
|
items = ffi.cast('Object *', api.xmalloc(len * ffi.sizeof('Object'))),
|
||||||
}})
|
},
|
||||||
|
})
|
||||||
for i = 1, len do
|
for i = 1, len do
|
||||||
arr.data.array.items[i - 1] = ffi.gc(lua2obj(l[i]), nil)
|
arr.data.array.items[i - 1] = ffi.gc(lua2obj(l[i]), nil)
|
||||||
end
|
end
|
||||||
@ -107,17 +115,19 @@ local lua2obj_type_tab = {
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local len = #kvs
|
local len = #kvs
|
||||||
local dct = obj(api.kObjectTypeDictionary, {dictionary={
|
local dct = obj(api.kObjectTypeDictionary, {
|
||||||
|
dictionary = {
|
||||||
size = len,
|
size = len,
|
||||||
capacity = len,
|
capacity = len,
|
||||||
items=ffi.cast('KeyValuePair *',
|
items = ffi.cast('KeyValuePair *', api.xmalloc(len * ffi.sizeof('KeyValuePair'))),
|
||||||
api.xmalloc(len * ffi.sizeof('KeyValuePair'))),
|
},
|
||||||
}})
|
})
|
||||||
for i = 1, len do
|
for i = 1, len do
|
||||||
local key, val = unpack(kvs[i])
|
local key, val = unpack(kvs[i])
|
||||||
dct.data.dictionary.items[i - 1] = ffi.new(
|
dct.data.dictionary.items[i - 1] = ffi.new(
|
||||||
'KeyValuePair', {key=ffi.gc(lua2obj(key), nil).data.string,
|
'KeyValuePair',
|
||||||
value=ffi.gc(lua2obj(val), nil)})
|
{ key = ffi.gc(lua2obj(key), nil).data.string, value = ffi.gc(lua2obj(val), nil) }
|
||||||
|
)
|
||||||
end
|
end
|
||||||
return dct
|
return dct
|
||||||
end,
|
end,
|
||||||
@ -139,10 +149,13 @@ lua2obj = function(l)
|
|||||||
elseif type(l) == 'boolean' then
|
elseif type(l) == 'boolean' then
|
||||||
return obj(api.kObjectTypeBoolean, { boolean = l })
|
return obj(api.kObjectTypeBoolean, { boolean = l })
|
||||||
elseif type(l) == 'string' then
|
elseif type(l) == 'string' then
|
||||||
return obj(api.kObjectTypeString, {string={
|
return obj(
|
||||||
|
api.kObjectTypeString,
|
||||||
|
{ string = {
|
||||||
size = #l,
|
size = #l,
|
||||||
data = api.xmemdupz(to_cstr(l), #l),
|
data = api.xmemdupz(to_cstr(l), #l),
|
||||||
}})
|
} }
|
||||||
|
)
|
||||||
elseif l == nil or l == nil_value then
|
elseif l == nil or l == nil_value then
|
||||||
return obj(api.kObjectTypeNil, { integer = 0 })
|
return obj(api.kObjectTypeNil, { integer = 0 })
|
||||||
end
|
end
|
||||||
|
@ -48,7 +48,10 @@ describe('vim_to_object', function()
|
|||||||
simple_test('converts dictionary with containers inside', { test = {}, test2 = { 1, 2 } })
|
simple_test('converts dictionary with containers inside', { test = {}, test2 = { 1, 2 } })
|
||||||
simple_test('converts empty list', { [type_key] = list_type })
|
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 scalar values', { 1, 2, 'test', 'foo' })
|
||||||
simple_test('converts list with containers inside', {{}, {test={}, test3={test4=true}}})
|
simple_test(
|
||||||
|
'converts list with containers inside',
|
||||||
|
{ {}, { test = {}, test3 = { test4 = true } } }
|
||||||
|
)
|
||||||
|
|
||||||
local dct = {}
|
local dct = {}
|
||||||
dct.dct = dct
|
dct.dct = dct
|
||||||
@ -60,13 +63,19 @@ describe('vim_to_object', function()
|
|||||||
|
|
||||||
local dct2 = { test = true, dict = nil_value }
|
local dct2 = { test = true, dict = nil_value }
|
||||||
dct2.dct = { dct2 }
|
dct2.dct = { dct2 }
|
||||||
different_output_test('outputs nil for nested dictionaries (2 level, in list)',
|
different_output_test(
|
||||||
dct2, {dct={nil_value}, test=true, dict=nil_value})
|
'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 }
|
local dct3 = { test = true, dict = nil_value }
|
||||||
dct3.dct = { dctin = dct3 }
|
dct3.dct = { dctin = dct3 }
|
||||||
different_output_test('outputs nil for nested dictionaries (2 level, in dict)',
|
different_output_test(
|
||||||
dct3, {dct={dctin=nil_value}, test=true, dict=nil_value})
|
'outputs nil for nested dictionaries (2 level, in dict)',
|
||||||
|
dct3,
|
||||||
|
{ dct = { dctin = nil_value }, test = true, dict = nil_value }
|
||||||
|
)
|
||||||
|
|
||||||
local lst2 = {}
|
local lst2 = {}
|
||||||
lst2[1] = { lst2 }
|
lst2[1] = { lst2 }
|
||||||
@ -74,8 +83,11 @@ describe('vim_to_object', function()
|
|||||||
|
|
||||||
local lst3 = { nil, true, false, 'ttest' }
|
local lst3 = { nil, true, false, 'ttest' }
|
||||||
lst3[1] = { lst = lst3 }
|
lst3[1] = { lst = lst3 }
|
||||||
different_output_test('outputs nil for nested lists (2 level, in dict)',
|
different_output_test(
|
||||||
lst3, {{lst=nil_value}, true, false, 'ttest'})
|
'outputs nil for nested lists (2 level, in dict)',
|
||||||
|
lst3,
|
||||||
|
{ { lst = nil_value }, true, false, 'ttest' }
|
||||||
|
)
|
||||||
|
|
||||||
itp('outputs empty list for NULL list', function()
|
itp('outputs empty list for NULL list', function()
|
||||||
local tt = typvalt('VAR_LIST', { v_list = NULL })
|
local tt = typvalt('VAR_LIST', { v_list = NULL })
|
||||||
|
@ -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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
local NULL = helpers.NULL
|
local NULL = helpers.NULL
|
||||||
|
|
||||||
local buffer = helpers.cimport("./src/nvim/buffer.h")
|
local buffer = helpers.cimport('./src/nvim/buffer.h')
|
||||||
|
|
||||||
describe('buffer functions', function()
|
describe('buffer functions', function()
|
||||||
|
|
||||||
local buflist_new = function(file, flags)
|
local buflist_new = function(file, flags)
|
||||||
local c_file = to_cstr(file)
|
local c_file = to_cstr(file)
|
||||||
return buffer.buflist_new(c_file, c_file, 1, flags)
|
return buffer.buflist_new(c_file, c_file, 1, flags)
|
||||||
@ -36,7 +35,6 @@ describe('buffer functions', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe('buf_valid', function()
|
describe('buf_valid', function()
|
||||||
|
|
||||||
itp('should view NULL as an invalid buffer', function()
|
itp('should view NULL as an invalid buffer', function()
|
||||||
eq(false, buffer.buf_valid(NULL))
|
eq(false, buffer.buf_valid(NULL))
|
||||||
end)
|
end)
|
||||||
@ -72,9 +70,7 @@ describe('buffer functions', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
describe('buflist_findpat', function()
|
describe('buflist_findpat', function()
|
||||||
|
|
||||||
local ALLOW_UNLISTED = 1
|
local ALLOW_UNLISTED = 1
|
||||||
local ONLY_LISTED = 0
|
local ONLY_LISTED = 0
|
||||||
|
|
||||||
@ -95,9 +91,9 @@ describe('buffer functions', function()
|
|||||||
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
|
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
|
||||||
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
|
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
|
||||||
|
|
||||||
eq(buf1.handle, buflist_findpat("test", ONLY_LISTED))
|
eq(buf1.handle, buflist_findpat('test', ONLY_LISTED))
|
||||||
eq(buf2.handle, buflist_findpat("file", ONLY_LISTED))
|
eq(buf2.handle, buflist_findpat('file', ONLY_LISTED))
|
||||||
eq(buf3.handle, buflist_findpat("path", ONLY_LISTED))
|
eq(buf3.handle, buflist_findpat('path', ONLY_LISTED))
|
||||||
|
|
||||||
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
|
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
|
||||||
close_buffer(NULL, buf2, 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)
|
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
|
||||||
|
|
||||||
-- Then: buf2 is the buffer that is found
|
-- 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
|
--{ When: We close buf2
|
||||||
@ -121,7 +117,7 @@ describe('buffer functions', function()
|
|||||||
local buf1 = buflist_new(path1, buffer.BLN_LISTED)
|
local buf1 = buflist_new(path1, buffer.BLN_LISTED)
|
||||||
|
|
||||||
-- Then: buf3 is found since 'file' appears at the end of the name
|
-- 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)
|
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 buf2 = buflist_new(path2, buffer.BLN_LISTED)
|
||||||
local buf3 = buflist_new(path3, 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, buf1, buffer.DOBUF_WIPE, 0, 0)
|
||||||
close_buffer(NULL, buf2, 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)
|
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
|
||||||
|
|
||||||
-- Then: We should find the buffer when it is given a unique pattern
|
-- 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
|
--{ When: We unlist the buffer
|
||||||
close_buffer(NULL, buf3, buffer.DOBUF_DEL, 0, 0)
|
close_buffer(NULL, buf3, buffer.DOBUF_DEL, 0, 0)
|
||||||
|
|
||||||
-- Then: It should not find the buffer when searching only listed buffers
|
-- 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
|
-- 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
|
--{ When: We wipe the buffer
|
||||||
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0, 0)
|
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0, 0)
|
||||||
|
|
||||||
-- Then: It should not find the buffer at all
|
-- Then: It should not find the buffer at all
|
||||||
eq(-1, buflist_findpat("_test_", ONLY_LISTED))
|
eq(-1, buflist_findpat('_test_', ONLY_LISTED))
|
||||||
eq(-1, buflist_findpat("_test_", ALLOW_UNLISTED))
|
eq(-1, buflist_findpat('_test_', ALLOW_UNLISTED))
|
||||||
--}
|
--}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -173,7 +169,7 @@ describe('buffer functions', function()
|
|||||||
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
|
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
|
||||||
|
|
||||||
-- Then: The first buffer is preferred when both are 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
|
--{ When: The first buffer is unlisted
|
||||||
@ -181,13 +177,13 @@ describe('buffer functions', function()
|
|||||||
|
|
||||||
-- Then: The second buffer is preferred because
|
-- Then: The second buffer is preferred because
|
||||||
-- unlisted buffers are not allowed
|
-- 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
|
--{ When: We allow unlisted buffers
|
||||||
-- Then: The second buffer is still preferred
|
-- Then: The second buffer is still preferred
|
||||||
-- because listed buffers are preferred to unlisted
|
-- 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
|
--{ When: We unlist the second buffer
|
||||||
@ -196,10 +192,10 @@ describe('buffer functions', function()
|
|||||||
-- Then: The first buffer is preferred again
|
-- Then: The first buffer is preferred again
|
||||||
-- because buf1 matches better which takes precedence
|
-- because buf1 matches better which takes precedence
|
||||||
-- when both buffers have the same listing status.
|
-- 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
|
-- 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)
|
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 bit = require('bit')
|
||||||
|
|
||||||
local itp = helpers.gen_itp(it)
|
local itp = helpers.gen_itp(it)
|
||||||
@ -44,7 +44,9 @@ local function argreset(arg, args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function test_vim_str2nr(s, what, exp, maxlen, strict)
|
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 = {}
|
local bits = {}
|
||||||
for k, _ in pairs(exp) do
|
for k, _ in pairs(exp) do
|
||||||
bits[#bits + 1] = k
|
bits[#bits + 1] = k
|
||||||
@ -54,7 +56,7 @@ local function test_vim_str2nr(s, what, exp, maxlen, strict)
|
|||||||
for k, _ in pairs(ARGTYPES) do
|
for k, _ in pairs(ARGTYPES) do
|
||||||
args[k] = arginit(k)
|
args[k] = arginit(k)
|
||||||
end
|
end
|
||||||
for case = 0, ((2 ^ (#bits)) - 1) do
|
for case = 0, ((2 ^ #bits) - 1) do
|
||||||
local cv = {}
|
local cv = {}
|
||||||
for b = 0, (#bits - 1) do
|
for b = 0, (#bits - 1) do
|
||||||
if bit.band(case, (2 ^ b)) == 0 then
|
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)
|
lib.vim_str2nr(s, cv.pre, cv.len, what, cv.num, cv.unum, maxlen, strict, nil)
|
||||||
for cck, ccv in pairs(cv) do
|
for cck, ccv in pairs(cv) do
|
||||||
if exp[cck] ~= tonumber(ccv[0]) then
|
if exp[cck] ~= tonumber(ccv[0]) then
|
||||||
error(('Failed check (%s = %d) in test (s=%s, w=%u, m=%d, strict=%s): %d'):format(
|
error(
|
||||||
cck, exp[cck], s, tonumber(what), maxlen, tostring(strict), tonumber(ccv[0])
|
('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
|
end
|
||||||
end
|
end
|
||||||
@ -88,12 +98,42 @@ describe('vim_str2nr()', function()
|
|||||||
test_vim_str2nr('', lib.STR2NR_OCT, { 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_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_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(
|
||||||
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)
|
lib.STR2NR_FORCE + lib.STR2NR_DEC,
|
||||||
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
{ len = 0, num = 0, unum = 0, pre = 0 },
|
||||||
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
|
0
|
||||||
test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_HEX, {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)
|
end)
|
||||||
itp('works with decimal numbers', function()
|
itp('works with decimal numbers', function()
|
||||||
for _, flags in ipairs({
|
for _, flags in ipairs({
|
||||||
|
@ -6,9 +6,13 @@ local eq = helpers.eq
|
|||||||
local neq = helpers.neq
|
local neq = helpers.neq
|
||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
|
|
||||||
local decode = cimport('./src/nvim/eval/decode.h', './src/nvim/eval/typval.h',
|
local decode = cimport(
|
||||||
'./src/nvim/globals.h', './src/nvim/memory.h',
|
'./src/nvim/eval/decode.h',
|
||||||
'./src/nvim/message.h')
|
'./src/nvim/eval/typval.h',
|
||||||
|
'./src/nvim/globals.h',
|
||||||
|
'./src/nvim/memory.h',
|
||||||
|
'./src/nvim/message.h'
|
||||||
|
)
|
||||||
|
|
||||||
describe('json_decode_string()', function()
|
describe('json_decode_string()', function()
|
||||||
local char = function(c)
|
local char = function(c)
|
||||||
@ -74,8 +78,7 @@ describe('json_decode_string()', function()
|
|||||||
collectgarbage('restart')
|
collectgarbage('restart')
|
||||||
check_failure(']test', 1, 'E474: No container to close: ]')
|
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 list with curly bracket: }')
|
||||||
check_failure('{]test', 2,
|
check_failure('{]test', 2, 'E474: Closing dictionary with square bracket: ]')
|
||||||
'E474: Closing dictionary with square bracket: ]')
|
|
||||||
check_failure('[1,]test', 4, 'E474: Trailing comma: ]')
|
check_failure('[1,]test', 4, 'E474: Trailing comma: ]')
|
||||||
check_failure('{"1":}test', 6, 'E474: Expected value after colon: }')
|
check_failure('{"1":}test', 6, 'E474: Expected value after colon: }')
|
||||||
check_failure('{"1"}test', 5, 'E474: Expected value: }')
|
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('ttest', 1, 'E474: Expected true: t')
|
||||||
check_failure('ftest', 1, 'E474: Expected false: f')
|
check_failure('ftest', 1, 'E474: Expected false: f')
|
||||||
check_failure('"\\test', 2, 'E474: Unfinished escape sequence: "\\')
|
check_failure('"\\test', 2, 'E474: Unfinished escape sequence: "\\')
|
||||||
check_failure('"\\u"test', 4,
|
check_failure('"\\u"test', 4, 'E474: Unfinished unicode escape sequence: "\\u"')
|
||||||
'E474: Unfinished unicode escape sequence: "\\u"')
|
check_failure('"\\uXXXX"est', 8, 'E474: Expected four hex digits after \\u: \\uXXXX"')
|
||||||
check_failure('"\\uXXXX"est', 8,
|
|
||||||
'E474: Expected four hex digits after \\u: \\uXXXX"')
|
|
||||||
check_failure('"\\?"test', 4, 'E474: Unknown escape sequence: \\?"')
|
check_failure('"\\?"test', 4, 'E474: Unknown escape sequence: \\?"')
|
||||||
check_failure(
|
check_failure(
|
||||||
'"\t"test', 3,
|
'"\t"test',
|
||||||
'E474: ASCII control characters cannot be present inside string: \t"')
|
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('"\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: Expected string end: "')
|
||||||
check_failure('-test', 1, 'E474: Missing number after minus sign: -')
|
check_failure('-test', 1, 'E474: Missing number after minus sign: -')
|
||||||
check_failure('-1.test', 3, 'E474: Missing number after decimal dot: -1.')
|
check_failure('-1.test', 3, 'E474: Missing number after decimal dot: -1.')
|
||||||
|
@ -96,6 +96,9 @@ describe('encode_list_write()', function()
|
|||||||
eq(0, encode_list_write(l, '\n\n\n'))
|
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(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)
|
||||||
end)
|
end)
|
||||||
|
@ -6,8 +6,12 @@ local to_cstr = helpers.to_cstr
|
|||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
|
|
||||||
local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h',
|
local eval = cimport(
|
||||||
'./src/nvim/hashtab.h', './src/nvim/memory.h')
|
'./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_string = { [true] = 'NULL string' }
|
||||||
local null_list = { [true] = 'NULL list' }
|
local null_list = { [true] = 'NULL list' }
|
||||||
@ -35,7 +39,9 @@ end
|
|||||||
|
|
||||||
local function li_alloc(nogc)
|
local function li_alloc(nogc)
|
||||||
local gcfunc = tv_list_item_free
|
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)
|
local li = ffi.gc(tv_list_item_alloc(), gcfunc)
|
||||||
li.li_next = nil
|
li.li_next = nil
|
||||||
li.li_prev = nil
|
li.li_prev = nil
|
||||||
@ -182,9 +188,11 @@ end
|
|||||||
|
|
||||||
typvalt2lua = function(t, processed)
|
typvalt2lua = function(t, processed)
|
||||||
typvalt2lua_tab_init()
|
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')
|
assert(false, 'Converting ' .. tonumber(t_inner.v_type) .. ' was not implemented yet')
|
||||||
end)(t, processed or {}))
|
end)(t, processed or {})
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function list_iter(l)
|
local function list_iter(l)
|
||||||
@ -242,7 +250,9 @@ local function dict_iter(d, return_hi)
|
|||||||
hi = d.dv_hashtab.ht_array,
|
hi = d.dv_hashtab.ht_array,
|
||||||
}
|
}
|
||||||
local function f(s, _)
|
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
|
while s.todo > 0 do
|
||||||
if s.hi.hi_key ~= nil and s.hi.hi_key ~= hi_key_removed then
|
if s.hi.hi_key ~= nil and s.hi.hi_key ~= hi_key_removed then
|
||||||
local key = ffi.string(s.hi.hi_key)
|
local key = ffi.string(s.hi.hi_key)
|
||||||
@ -250,8 +260,7 @@ local function dict_iter(d, return_hi)
|
|||||||
if return_hi then
|
if return_hi then
|
||||||
ret = s.hi
|
ret = s.hi
|
||||||
else
|
else
|
||||||
ret = ffi.cast('dictitem_T*',
|
ret = ffi.cast('dictitem_T*', s.hi.hi_key - ffi.offsetof('dictitem_T', 'di_key'))
|
||||||
s.hi.hi_key - ffi.offsetof('dictitem_T', 'di_key'))
|
|
||||||
end
|
end
|
||||||
s.todo = s.todo - 1
|
s.todo = s.todo - 1
|
||||||
s.hi = s.hi + 1
|
s.hi = s.hi + 1
|
||||||
@ -333,12 +342,15 @@ local lua2typvalt_type_tab = {
|
|||||||
return typvalt(eval.VAR_PARTIAL, { v_partial = processed[l] })
|
return typvalt(eval.VAR_PARTIAL, { v_partial = processed[l] })
|
||||||
end
|
end
|
||||||
if l.args or l.dict then
|
if l.args or l.dict then
|
||||||
local pt = populate_partial(ffi.gc(ffi.cast('partial_T*',
|
local pt = populate_partial(
|
||||||
eval.xcalloc(1, ffi.sizeof('partial_T'))), nil), l, processed)
|
ffi.gc(ffi.cast('partial_T*', eval.xcalloc(1, ffi.sizeof('partial_T'))), nil),
|
||||||
|
l,
|
||||||
|
processed
|
||||||
|
)
|
||||||
return typvalt(eval.VAR_PARTIAL, { v_partial = pt })
|
return typvalt(eval.VAR_PARTIAL, { v_partial = pt })
|
||||||
else
|
else
|
||||||
return typvalt(eval.VAR_FUNC, {
|
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
|
||||||
end,
|
end,
|
||||||
@ -408,24 +420,44 @@ local function alloc_len(len, get_ptr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local alloc_logging_helpers = {
|
local alloc_logging_helpers = {
|
||||||
list = function(l) return {func='calloc', args={1, ffi.sizeof('list_T')}, ret=void(l)} end,
|
list = function(l)
|
||||||
li = function(li) return {func='malloc', args={ffi.sizeof('listitem_T')}, ret=void(li)} end,
|
return { func = 'calloc', args = { 1, ffi.sizeof('list_T') }, ret = void(l) }
|
||||||
dict = function(d) return {func='calloc', args={1, ffi.sizeof('dict_T')}, ret=void(d)} end,
|
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)
|
di = function(di, size)
|
||||||
size = alloc_len(size, function() return di.di_key end)
|
size = alloc_len(size, function()
|
||||||
return {func='malloc', args={ffi.offsetof('dictitem_T', 'di_key') + size + 1}, ret=void(di)}
|
return di.di_key
|
||||||
|
end)
|
||||||
|
return {
|
||||||
|
func = 'malloc',
|
||||||
|
args = { ffi.offsetof('dictitem_T', 'di_key') + size + 1 },
|
||||||
|
ret = void(di),
|
||||||
|
}
|
||||||
end,
|
end,
|
||||||
str = function(s, size)
|
str = function(s, size)
|
||||||
size = alloc_len(size, function() return s end)
|
size = alloc_len(size, function()
|
||||||
|
return s
|
||||||
|
end)
|
||||||
return { func = 'malloc', args = { size + 1 }, ret = void(s) }
|
return { func = 'malloc', args = { size + 1 }, ret = void(s) }
|
||||||
end,
|
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_…: 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)
|
lua_tvs = function(argv, argc)
|
||||||
argc = alloc_len(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) }
|
||||||
@ -437,14 +469,15 @@ local function int(n)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function list(...)
|
local function list(...)
|
||||||
return populate_list(ffi.gc(eval.tv_list_alloc(select('#', ...)),
|
return populate_list(
|
||||||
eval.tv_list_unref),
|
ffi.gc(eval.tv_list_alloc(select('#', ...)), eval.tv_list_unref),
|
||||||
{...}, {})
|
{ ... },
|
||||||
|
{}
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dict(d)
|
local function dict(d)
|
||||||
return populate_dict(ffi.gc(eval.tv_dict_alloc(), eval.tv_dict_free),
|
return populate_dict(ffi.gc(eval.tv_dict_alloc(), eval.tv_dict_free), d or {}, {})
|
||||||
d or {}, {})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local callback2tbl_type_tab = nil
|
local callback2tbl_type_tab = nil
|
||||||
@ -454,14 +487,16 @@ local function init_callback2tbl_type_tab()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
callback2tbl_type_tab = {
|
callback2tbl_type_tab = {
|
||||||
[tonumber(eval.kCallbackNone)] = function(_) return {type='none'} end,
|
[tonumber(eval.kCallbackNone)] = function(_)
|
||||||
|
return { type = 'none' }
|
||||||
|
end,
|
||||||
[tonumber(eval.kCallbackFuncref)] = function(cb)
|
[tonumber(eval.kCallbackFuncref)] = function(cb)
|
||||||
return { type = 'fref', fref = ffi.string(cb.data.funcref) }
|
return { type = 'fref', fref = ffi.string(cb.data.funcref) }
|
||||||
end,
|
end,
|
||||||
[tonumber(eval.kCallbackPartial)] = function(cb)
|
[tonumber(eval.kCallbackPartial)] = function(cb)
|
||||||
local lua_pt = partial2lua(cb.data.partial)
|
local lua_pt = partial2lua(cb.data.partial)
|
||||||
return { type = 'pt', fref = ffi.string(lua_pt.value), pt = lua_pt }
|
return { type = 'pt', fref = ffi.string(lua_pt.value), pt = lua_pt }
|
||||||
end
|
end,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -475,13 +510,16 @@ local function tbl2callback(tbl)
|
|||||||
if tbl.type == 'none' then
|
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
|
elseif tbl.type == 'fref' then
|
||||||
ret = ffi.new('Callback[1]', {{type=eval.kCallbackFuncref,
|
ret = ffi.new(
|
||||||
data={funcref=eval.xstrdup(tbl.fref)}}})
|
'Callback[1]',
|
||||||
|
{ { type = eval.kCallbackFuncref, data = { funcref = eval.xstrdup(tbl.fref) } } }
|
||||||
|
)
|
||||||
elseif tbl.type == 'pt' then
|
elseif tbl.type == 'pt' then
|
||||||
local pt = ffi.gc(ffi.cast('partial_T*',
|
local pt = ffi.gc(ffi.cast('partial_T*', eval.xcalloc(1, ffi.sizeof('partial_T'))), nil)
|
||||||
eval.xcalloc(1, ffi.sizeof('partial_T'))), nil)
|
ret = ffi.new(
|
||||||
ret = ffi.new('Callback[1]', {{type=eval.kCallbackPartial,
|
'Callback[1]',
|
||||||
data={partial=populate_partial(pt, tbl.pt, {})}}})
|
{ { type = eval.kCallbackPartial, data = { partial = populate_partial(pt, tbl.pt, {}) } } }
|
||||||
|
)
|
||||||
else
|
else
|
||||||
assert(false)
|
assert(false)
|
||||||
end
|
end
|
||||||
@ -495,8 +533,8 @@ local function dict_watchers(d)
|
|||||||
local qs = {}
|
local qs = {}
|
||||||
local key_patterns = {}
|
local key_patterns = {}
|
||||||
while q ~= h do
|
while q ~= h do
|
||||||
local qitem = ffi.cast('DictWatcher *',
|
local qitem =
|
||||||
ffi.cast('char *', q) - ffi.offsetof('DictWatcher', 'node'))
|
ffi.cast('DictWatcher *', ffi.cast('char *', q) - ffi.offsetof('DictWatcher', 'node'))
|
||||||
ret[#ret + 1] = {
|
ret[#ret + 1] = {
|
||||||
cb = callback2tbl(qitem.callback),
|
cb = callback2tbl(qitem.callback),
|
||||||
pat = ffi.string(qitem.key_pattern, qitem.key_pattern_len),
|
pat = ffi.string(qitem.key_pattern, qitem.key_pattern_len),
|
||||||
@ -510,8 +548,7 @@ local function dict_watchers(d)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function eval0(expr)
|
local function eval0(expr)
|
||||||
local tv = ffi.gc(ffi.new('typval_T', {v_type=eval.VAR_UNKNOWN}),
|
local tv = ffi.gc(ffi.new('typval_T', { v_type = eval.VAR_UNKNOWN }), eval.tv_clear)
|
||||||
eval.tv_clear)
|
|
||||||
local evalarg = ffi.new('evalarg_T', { eval_flags = eval.EVAL_EVALUATE })
|
local evalarg = ffi.new('evalarg_T', { eval_flags = eval.EVAL_EVALUATE })
|
||||||
if eval.eval0(to_cstr(expr), tv, nil, evalarg) == 0 then
|
if eval.eval0(to_cstr(expr), tv, nil, evalarg) == 0 then
|
||||||
return nil
|
return nil
|
||||||
|
@ -8,8 +8,7 @@ local eq = helpers.eq
|
|||||||
|
|
||||||
local eval0 = eval_helpers.eval0
|
local eval0 = eval_helpers.eval0
|
||||||
|
|
||||||
local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h',
|
local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h', './src/nvim/memory.h')
|
||||||
'./src/nvim/memory.h')
|
|
||||||
|
|
||||||
describe('NULL typval_T', function()
|
describe('NULL typval_T', function()
|
||||||
itp('is produced by $XXX_UNEXISTENT_VAR_XXX', function()
|
itp('is produced by $XXX_UNEXISTENT_VAR_XXX', function()
|
||||||
|
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)
|
local itp = helpers.gen_itp(it)
|
||||||
--{:cimport, :internalize, :eq, :neq, :ffi, :lib, :cstr, :to_cstr} = require 'test.unit.helpers'
|
--{:cimport, :internalize, :eq, :neq, :ffi, :lib, :cstr, :to_cstr} = require 'test.unit.helpers'
|
||||||
|
|
||||||
@ -7,11 +7,10 @@ local ffi = helpers.ffi
|
|||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
local NULL = helpers.NULL
|
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 functions', function()
|
||||||
describe('file_pat_to_reg_pat', function()
|
describe('file_pat_to_reg_pat', function()
|
||||||
|
|
||||||
local file_pat_to_reg_pat = function(pat)
|
local file_pat_to_reg_pat = function(pat)
|
||||||
local res = fileio.file_pat_to_reg_pat(to_cstr(pat), NULL, NULL, 0)
|
local res = fileio.file_pat_to_reg_pat(to_cstr(pat), NULL, NULL, 0)
|
||||||
return ffi.string(res)
|
return ffi.string(res)
|
||||||
@ -37,10 +36,12 @@ describe('file_pat functions', function()
|
|||||||
eq('^foo.bar$', file_pat_to_reg_pat('foo?bar'))
|
eq('^foo.bar$', file_pat_to_reg_pat('foo?bar'))
|
||||||
end)
|
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()
|
function()
|
||||||
eq('^foo.*bar$', file_pat_to_reg_pat('foo*bar'))
|
eq('^foo.*bar$', file_pat_to_reg_pat('foo*bar'))
|
||||||
end)
|
end
|
||||||
|
)
|
||||||
|
|
||||||
itp([[unescapes \? to ?]], function()
|
itp([[unescapes \? to ?]], function()
|
||||||
eq('^foo?bar$', file_pat_to_reg_pat([[foo\?bar]]))
|
eq('^foo?bar$', file_pat_to_reg_pat([[foo\?bar]]))
|
||||||
|
@ -24,99 +24,141 @@ SOFTWARE. --]]
|
|||||||
-- work.
|
-- work.
|
||||||
-- see: http://lua-users.org/wiki/LpegRecipes
|
-- 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 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 Carg, Cc, Cp, Ct = lpeg.Carg, lpeg.Cc, lpeg.Cp, lpeg.Ct
|
||||||
|
|
||||||
local tokens = P { "tokens";
|
local tokens = P {
|
||||||
|
'tokens',
|
||||||
-- Comment of form /* ... */
|
-- 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
|
-- 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
|
-- 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 = state.line + 1
|
||||||
state.line_start = pos
|
state.line_start = pos
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- Line continuation
|
-- 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 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)
|
-- Special form of #include with filename followed in angled brackets (matches 3 tokens)
|
||||||
include = Ct(C(P"#include") * Cc"preprocessor") *
|
include = Ct(C(P '#include') * Cc 'preprocessor') * Ct(C(S ' \t' ^ 1) * Cc 'whitespace') * Ct(
|
||||||
Ct(C(S" \t"^1) * Cc"whitespace") *
|
C(P '<' * (1 - P '>') ^ 1 * P '>') * Cc 'string'
|
||||||
Ct(C(P"<" * (1 - P">")^1 * P">") * Cc"string"),
|
),
|
||||||
|
|
||||||
-- Preprocessor instruction
|
-- Preprocessor instruction
|
||||||
preprocessor = V"include" +
|
preprocessor = V 'include'
|
||||||
Ct(C(P"#" * P" "^0 * ( P"define" + P"elif" + P"else" + P"endif" + P"#" +
|
+ Ct(
|
||||||
P"error" + P"ifdef" + P"ifndef" + P"if" + P"import" +
|
C(
|
||||||
P"include" + P"line" + P"pragma" + P"undef" + P"using" +
|
P '#'
|
||||||
P"pragma"
|
* P ' ' ^ 0
|
||||||
) * #S" \r\n\t") * Cc"preprocessor"),
|
* (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 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
|
-- Single character in a string
|
||||||
sstring_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]]),
|
dstring_char = R('\001!', '#[', ']\255') + (P '\\' * S [[ntvbrfa\?'"0x]]),
|
||||||
|
|
||||||
-- String literal
|
-- String literal
|
||||||
string = Ct(C(P"'" * (V"sstring_char" + P'"')^0 * P"'" +
|
string = Ct(
|
||||||
P'"' * (V"dstring_char" + P"'")^0 * P'"') * Cc"string"),
|
C(
|
||||||
|
P "'" * (V 'sstring_char' + P '"') ^ 0 * P "'"
|
||||||
|
+ P '"' * (V 'dstring_char' + P "'") ^ 0 * P '"'
|
||||||
|
) * Cc 'string'
|
||||||
|
),
|
||||||
|
|
||||||
-- Operator
|
-- Operator
|
||||||
operator = Ct(C(P">>=" + P"<<=" + P"..." +
|
operator = Ct(
|
||||||
P"::" + P"<<" + P">>" + P"<=" + P">=" + P"==" + P"!=" +
|
C(
|
||||||
P"||" + P"&&" + P"++" + P"--" + P"->" + P"+=" + P"-=" +
|
P '>>='
|
||||||
P"*=" + P"/=" + P"|=" + P"&=" + P"^=" + S"+-*/=<>%^|&.?:!~,") * Cc"operator"),
|
+ 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)
|
-- 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
|
-- 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
|
-- Floating point number
|
||||||
f_exponent = S"eE" + S"+-"^-1 * R"09"^1,
|
f_exponent = S 'eE' + S '+-' ^ -1 * R '09' ^ 1,
|
||||||
f_terminator = S"fFlL",
|
f_terminator = S 'fFlL',
|
||||||
float = Ct(C(
|
float = Ct(
|
||||||
R"09"^1 * V"f_exponent" * V"f_terminator"^-1 +
|
C(
|
||||||
R"09"^0 * P"." * R"09"^1 * V"f_exponent"^-1 * V"f_terminator"^-1 +
|
R '09' ^ 1 * V 'f_exponent' * V 'f_terminator' ^ -1
|
||||||
R"09"^1 * P"." * R"09"^0 * V"f_exponent"^-1 * V"f_terminator"^-1
|
+ R '09' ^ 0 * P '.' * R '09' ^ 1 * V 'f_exponent' ^ -1 * V 'f_terminator' ^ -1
|
||||||
) * Cc"float"),
|
+ R '09' ^ 1 * P '.' * R '09' ^ 0 * V 'f_exponent' ^ -1 * V 'f_terminator' ^ -1
|
||||||
|
) * Cc 'float'
|
||||||
|
),
|
||||||
|
|
||||||
-- Any token
|
-- Any token
|
||||||
token = V"comment" +
|
token = V 'comment'
|
||||||
V"line_comment" +
|
+ V 'line_comment'
|
||||||
V"identifier" +
|
+ V 'identifier'
|
||||||
V"whitespace" +
|
+ V 'whitespace'
|
||||||
V"line_extend" +
|
+ V 'line_extend'
|
||||||
V"preprocessor" +
|
+ V 'preprocessor'
|
||||||
V"string" +
|
+ V 'string'
|
||||||
V"char" +
|
+ V 'char'
|
||||||
V"operator" +
|
+ V 'operator'
|
||||||
V"float" +
|
+ V 'float'
|
||||||
V"int",
|
+ V 'int',
|
||||||
|
|
||||||
-- Error for when nothing else matches
|
-- Error for when nothing else matches
|
||||||
error = (Cp() * C(P(1) ^ -8) * Carg(1)) / function(pos, where, state)
|
error = (Cp() * C(P(1) ^ -8) * Carg(1)) / function(pos, where, state)
|
||||||
error(("Tokenising error on line %i, position %i, near '%s'")
|
error(
|
||||||
:format(state.line, pos - state.line_start + 1, where))
|
("Tokenising error on line %i, position %i, near '%s'"):format(
|
||||||
|
state.line,
|
||||||
|
pos - state.line_start + 1,
|
||||||
|
where
|
||||||
|
)
|
||||||
|
)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- Match end of input or throw error
|
-- Match end of input or throw error
|
||||||
finish = -P(1) + V"error",
|
finish = -P(1) + V 'error',
|
||||||
|
|
||||||
-- Match stream of tokens into a table
|
-- 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)
|
local function TokeniseC(str)
|
||||||
@ -132,10 +174,37 @@ local function set(t)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local C_keywords = set { -- luacheck: ignore
|
local C_keywords = set { -- luacheck: ignore
|
||||||
"break", "case", "char", "const", "continue", "default", "do", "double",
|
'break',
|
||||||
"else", "enum", "extern", "float", "for", "goto", "if", "int", "long",
|
'case',
|
||||||
"register", "return", "short", "signed", "sizeof", "static", "struct",
|
'char',
|
||||||
"switch", "typedef", "union", "unsigned", "void", "volatile", "while",
|
'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
|
-- 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,
|
-- 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
|
-- and ';' indicates we're at the end of a statement, so we put end
|
||||||
-- it with a newline.
|
-- it with a newline.
|
||||||
token[1] = token[1] .. "\n"
|
token[1] = token[1] .. '\n'
|
||||||
end_at_brace = false
|
end_at_brace = false
|
||||||
end
|
end
|
||||||
elseif typ == 'identifier' then
|
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,
|
-- 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
|
-- and ';' indicates we're at the end of a statement, so we put end
|
||||||
-- it with a newline.
|
-- it with a newline.
|
||||||
token[1] = ";\n"
|
token[1] = ';\n'
|
||||||
end
|
end
|
||||||
elseif typ == 'whitespace' then
|
elseif typ == 'whitespace' then
|
||||||
-- replace all whitespace by one space
|
-- 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
|
-- 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
|
-- in that case we replace all whitespace by one newline
|
||||||
repl = "\n"
|
repl = '\n'
|
||||||
allow_one_nl = false
|
allow_one_nl = false
|
||||||
end
|
end
|
||||||
|
|
||||||
token[1] = string.gsub(token[1], "%s+", repl)
|
token[1] = string.gsub(token[1], '%s+', repl)
|
||||||
end
|
end
|
||||||
result[#result + 1] = token[1]
|
result[#result + 1] = token[1]
|
||||||
end
|
end
|
||||||
@ -217,7 +286,7 @@ end
|
|||||||
|
|
||||||
-- standalone operation (very handy for debugging)
|
-- standalone operation (very handy for debugging)
|
||||||
local function standalone(...) -- luacheck: ignore
|
local function standalone(...) -- luacheck: ignore
|
||||||
local Preprocess = require("preprocess")
|
local Preprocess = require('preprocess')
|
||||||
Preprocess.add_to_include_path('./../../src')
|
Preprocess.add_to_include_path('./../../src')
|
||||||
Preprocess.add_to_include_path('./../../build/include')
|
Preprocess.add_to_include_path('./../../build/include')
|
||||||
Preprocess.add_to_include_path('./../../.deps/usr/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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local cimport = helpers.cimport
|
local cimport = helpers.cimport
|
||||||
@ -157,7 +157,9 @@ local ga_append_ints = function(garr, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- enhanced constructors
|
-- 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 new_garray = function()
|
||||||
local garr = garray_ctype()
|
local garr = garray_ctype()
|
||||||
return ffi.gc(garr, ga_clear)
|
return ffi.gc(garr, ga_clear)
|
||||||
@ -165,7 +167,7 @@ end
|
|||||||
|
|
||||||
local new_string_garray = function()
|
local new_string_garray = function()
|
||||||
local garr = garray_ctype()
|
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)
|
return ffi.gc(garr, ga_clear_strings)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -182,7 +184,6 @@ local ga_scramble = function(garr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe('garray', function()
|
describe('garray', function()
|
||||||
|
|
||||||
describe('ga_init', function()
|
describe('ga_init', function()
|
||||||
itp('initializes the values of the garray', function()
|
itp('initializes the values of the garray', function()
|
||||||
local garr = new_garray()
|
local garr = new_garray()
|
||||||
@ -252,7 +253,7 @@ describe('garray', function()
|
|||||||
-- this is the actual ga_append, the others are just emulated lua
|
-- this is the actual ga_append, the others are just emulated lua
|
||||||
-- versions
|
-- versions
|
||||||
local garr = new_garray()
|
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, 'h')
|
||||||
ga_append(garr, 'e')
|
ga_append(garr, 'e')
|
||||||
ga_append(garr, 'l')
|
ga_append(garr, 'l')
|
||||||
@ -265,13 +266,13 @@ describe('garray', function()
|
|||||||
|
|
||||||
itp('can append integers', function()
|
itp('can append integers', function()
|
||||||
local garr = new_garray()
|
local garr = new_garray()
|
||||||
ga_init(garr, ffi.sizeof("int"), 1)
|
ga_init(garr, ffi.sizeof('int'), 1)
|
||||||
local input = {
|
local input = {
|
||||||
-20,
|
-20,
|
||||||
94,
|
94,
|
||||||
867615,
|
867615,
|
||||||
90927,
|
90927,
|
||||||
86
|
86,
|
||||||
}
|
}
|
||||||
ga_append_ints(garr, unpack(input))
|
ga_append_ints(garr, unpack(input))
|
||||||
local ints = ga_data_as_ints(garr)
|
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()
|
itp('can append strings to a growing array of strings', function()
|
||||||
local garr = new_string_garray()
|
local garr = new_string_garray()
|
||||||
local input = {
|
local input = {
|
||||||
"some",
|
'some',
|
||||||
"str",
|
'str',
|
||||||
"\r\n\r●●●●●●,,,",
|
'\r\n\r●●●●●●,,,',
|
||||||
"hmm",
|
'hmm',
|
||||||
"got it"
|
'got it',
|
||||||
}
|
}
|
||||||
ga_append_strings(garr, unpack(input))
|
ga_append_strings(garr, unpack(input))
|
||||||
-- check that we can get the same strings out of the array
|
-- check that we can get the same strings out of the array
|
||||||
@ -301,8 +302,8 @@ describe('garray', function()
|
|||||||
describe('ga_concat', function()
|
describe('ga_concat', function()
|
||||||
itp('concatenates the parameter to the growing byte array', function()
|
itp('concatenates the parameter to the growing byte array', function()
|
||||||
local garr = new_garray()
|
local garr = new_garray()
|
||||||
ga_init(garr, ffi.sizeof("char"), 1)
|
ga_init(garr, ffi.sizeof('char'), 1)
|
||||||
local str = "ohwell●●"
|
local str = 'ohwell●●'
|
||||||
local loop = 5
|
local loop = 5
|
||||||
for _ = 1, loop do
|
for _ = 1, loop do
|
||||||
ga_concat(garr, str)
|
ga_concat(garr, str)
|
||||||
@ -338,7 +339,7 @@ describe('garray', function()
|
|||||||
test_concat_fn({
|
test_concat_fn({
|
||||||
'oh',
|
'oh',
|
||||||
'my',
|
'my',
|
||||||
'neovim'
|
'neovim',
|
||||||
}, ga_concat_strings)
|
}, ga_concat_strings)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -353,7 +354,7 @@ describe('garray', function()
|
|||||||
test_concat_fn({
|
test_concat_fn({
|
||||||
'oh',
|
'oh',
|
||||||
'my',
|
'my',
|
||||||
'neovim'
|
'neovim',
|
||||||
}, ga_concat_strings_sep, sep)
|
}, ga_concat_strings_sep, sep)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -370,13 +371,13 @@ describe('garray', function()
|
|||||||
'bbb',
|
'bbb',
|
||||||
'ccc',
|
'ccc',
|
||||||
'ccc',
|
'ccc',
|
||||||
'ddd●●'
|
'ddd●●',
|
||||||
}
|
}
|
||||||
local sorted_dedup_input = {
|
local sorted_dedup_input = {
|
||||||
'aaa',
|
'aaa',
|
||||||
'bbb',
|
'bbb',
|
||||||
'ccc',
|
'ccc',
|
||||||
'ddd●●'
|
'ddd●●',
|
||||||
}
|
}
|
||||||
ga_append_strings(garr, unpack(input))
|
ga_append_strings(garr, unpack(input))
|
||||||
ga_remove_duplicate_strings(garr)
|
ga_remove_duplicate_strings(garr)
|
||||||
|
@ -133,25 +133,28 @@ local pragma_pack_id = 1
|
|||||||
local function filter_complex_blocks(body)
|
local function filter_complex_blocks(body)
|
||||||
local result = {} --- @type string[]
|
local result = {} --- @type string[]
|
||||||
|
|
||||||
for line in body:gmatch("[^\r\n]+") do
|
for line in body:gmatch('[^\r\n]+') do
|
||||||
if not (string.find(line, "(^)", 1, true) ~= nil
|
if
|
||||||
or string.find(line, "_ISwupper", 1, true)
|
not (
|
||||||
or string.find(line, "_Float")
|
string.find(line, '(^)', 1, true) ~= nil
|
||||||
or string.find(line, "__s128")
|
or string.find(line, '_ISwupper', 1, true)
|
||||||
or string.find(line, "__u128")
|
or string.find(line, '_Float')
|
||||||
or string.find(line, "msgpack_zone_push_finalizer")
|
or string.find(line, '__s128')
|
||||||
or string.find(line, "msgpack_unpacker_reserve_buffer")
|
or string.find(line, '__u128')
|
||||||
or string.find(line, "value_init_")
|
or string.find(line, 'msgpack_zone_push_finalizer')
|
||||||
or string.find(line, "UUID_NULL") -- static const uuid_t UUID_NULL = {...}
|
or string.find(line, 'msgpack_unpacker_reserve_buffer')
|
||||||
or string.find(line, "inline _Bool")) then
|
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
|
result[#result + 1] = line
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return table.concat(result, "\n")
|
return table.concat(result, '\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local cdef = ffi.cdef
|
local cdef = ffi.cdef
|
||||||
|
|
||||||
local cimportstr
|
local cimportstr
|
||||||
@ -185,8 +188,7 @@ local function cimport(...)
|
|||||||
cdefs = cdefs_init
|
cdefs = cdefs_init
|
||||||
end
|
end
|
||||||
for _, path in ipairs({ ... }) do
|
for _, path in ipairs({ ... }) do
|
||||||
if not (path:sub(1, 1) == '/' or path:sub(1, 1) == '.'
|
if not (path:sub(1, 1) == '/' or path:sub(1, 1) == '.' or path:sub(2, 2) == ':') then
|
||||||
or path:sub(2, 2) == ':') then
|
|
||||||
path = './' .. path
|
path = './' .. path
|
||||||
end
|
end
|
||||||
if not preprocess_cache[path] then
|
if not preprocess_cache[path] then
|
||||||
@ -205,15 +207,15 @@ local function cimport(...)
|
|||||||
body = filter_complex_blocks(body)
|
body = filter_complex_blocks(body)
|
||||||
-- add the formatted lines to a set
|
-- add the formatted lines to a set
|
||||||
local new_cdefs = Set:new()
|
local new_cdefs = Set:new()
|
||||||
for line in body:gmatch("[^\r\n]+") do
|
for line in body:gmatch('[^\r\n]+') do
|
||||||
line = trim(line)
|
line = trim(line)
|
||||||
-- give each #pragma pack an unique id, so that they don't get removed
|
-- give each #pragma pack an unique id, so that they don't get removed
|
||||||
-- if they are inserted into the set
|
-- if they are inserted into the set
|
||||||
-- (they are needed in the right order with the struct definitions,
|
-- (they are needed in the right order with the struct definitions,
|
||||||
-- otherwise luajit has wrong memory layouts for the sturcts)
|
-- 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
|
--- @type string
|
||||||
line = line .. " // " .. pragma_pack_id
|
line = line .. ' // ' .. pragma_pack_id
|
||||||
pragma_pack_id = pragma_pack_id + 1
|
pragma_pack_id = pragma_pack_id + 1
|
||||||
end
|
end
|
||||||
new_cdefs:add(line)
|
new_cdefs:add(line)
|
||||||
@ -314,7 +316,9 @@ local function alloc_log_new()
|
|||||||
log_entry.args[i] = self.null
|
log_entry.args[i] = self.null
|
||||||
end
|
end
|
||||||
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
|
if log_entry.ret then
|
||||||
return log_entry.ret
|
return log_entry.ret
|
||||||
end
|
end
|
||||||
@ -365,11 +369,9 @@ local function alloc_log_new()
|
|||||||
log:set_mocks()
|
log:set_mocks()
|
||||||
end
|
end
|
||||||
|
|
||||||
function log:before_each()
|
function log:before_each() end
|
||||||
end
|
|
||||||
|
|
||||||
function log:after_each()
|
function log:after_each() end
|
||||||
end
|
|
||||||
|
|
||||||
log:setup()
|
log:setup()
|
||||||
|
|
||||||
@ -400,10 +402,9 @@ function sc.pipe()
|
|||||||
local ret = ffi.new('int[2]', { -1, -1 })
|
local ret = ffi.new('int[2]', { -1, -1 })
|
||||||
ffi.errno(0)
|
ffi.errno(0)
|
||||||
local res = ffi.C.pipe(ret)
|
local res = ffi.C.pipe(ret)
|
||||||
if (res ~= 0) then
|
if res ~= 0 then
|
||||||
local err = ffi.errno(0)
|
local err = ffi.errno(0)
|
||||||
assert(res == 0, ("pipe() error: %u: %s"):format(
|
assert(res == 0, ('pipe() error: %u: %s'):format(err, ffi.string(ffi.C.strerror(err))))
|
||||||
err, ffi.string(ffi.C.strerror(err))))
|
|
||||||
end
|
end
|
||||||
assert(ret[0] ~= -1 and ret[1] ~= -1)
|
assert(ret[0] ~= -1 and ret[1] ~= -1)
|
||||||
return ret[0], ret[1]
|
return ret[0], ret[1]
|
||||||
@ -415,15 +416,12 @@ function sc.read(rd, len)
|
|||||||
local total_bytes_read = 0
|
local total_bytes_read = 0
|
||||||
ffi.errno(0)
|
ffi.errno(0)
|
||||||
while total_bytes_read < len do
|
while total_bytes_read < len do
|
||||||
local bytes_read = tonumber(ffi.C.read(
|
local bytes_read =
|
||||||
rd,
|
tonumber(ffi.C.read(rd, ffi.cast('void*', ret + total_bytes_read), len - total_bytes_read))
|
||||||
ffi.cast('void*', ret + total_bytes_read),
|
|
||||||
len - total_bytes_read))
|
|
||||||
if bytes_read == -1 then
|
if bytes_read == -1 then
|
||||||
local err = ffi.errno(0)
|
local err = ffi.errno(0)
|
||||||
if err ~= ffi.C.kPOSIXErrnoEINTR then
|
if err ~= ffi.C.kPOSIXErrnoEINTR then
|
||||||
assert(false, ("read() error: %u: %s"):format(
|
assert(false, ('read() error: %u: %s'):format(err, ffi.string(ffi.C.strerror(err))))
|
||||||
err, ffi.string(ffi.C.strerror(err))))
|
|
||||||
end
|
end
|
||||||
elseif bytes_read == 0 then
|
elseif bytes_read == 0 then
|
||||||
break
|
break
|
||||||
@ -439,15 +437,16 @@ function sc.write(wr, s)
|
|||||||
local total_bytes_written = 0
|
local total_bytes_written = 0
|
||||||
ffi.errno(0)
|
ffi.errno(0)
|
||||||
while total_bytes_written < #s do
|
while total_bytes_written < #s do
|
||||||
local bytes_written = tonumber(ffi.C.write(
|
local bytes_written = tonumber(
|
||||||
wr,
|
ffi.C.write(wr, ffi.cast('void*', wbuf + total_bytes_written), #s - total_bytes_written)
|
||||||
ffi.cast('void*', wbuf + total_bytes_written),
|
)
|
||||||
#s - total_bytes_written))
|
|
||||||
if bytes_written == -1 then
|
if bytes_written == -1 then
|
||||||
local err = ffi.errno(0)
|
local err = ffi.errno(0)
|
||||||
if err ~= ffi.C.kPOSIXErrnoEINTR then
|
if err ~= ffi.C.kPOSIXErrnoEINTR then
|
||||||
assert(false, ("write() error: %u: %s ('%s')"):format(
|
assert(
|
||||||
err, ffi.string(ffi.C.strerror(err)), s))
|
false,
|
||||||
|
("write() error: %u: %s ('%s')"):format(err, ffi.string(ffi.C.strerror(err)), s)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
elseif bytes_written == 0 then
|
elseif bytes_written == 0 then
|
||||||
break
|
break
|
||||||
@ -472,8 +471,7 @@ function sc.wait(pid)
|
|||||||
if err == ffi.C.kPOSIXErrnoECHILD then
|
if err == ffi.C.kPOSIXErrnoECHILD then
|
||||||
break
|
break
|
||||||
elseif err ~= ffi.C.kPOSIXErrnoEINTR then
|
elseif err ~= ffi.C.kPOSIXErrnoEINTR then
|
||||||
assert(false, ("waitpid() error: %u: %s"):format(
|
assert(false, ('waitpid() error: %u: %s'):format(err, ffi.string(ffi.C.strerror(err))))
|
||||||
err, ffi.string(ffi.C.strerror(err))))
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert(r == pid)
|
assert(r == pid)
|
||||||
@ -499,8 +497,7 @@ if os.getenv('NVIM_TEST_PRINT_SYSCALLS') == '1' then
|
|||||||
(function(k, v)
|
(function(k, v)
|
||||||
sc[k] = function(...)
|
sc[k] = function(...)
|
||||||
local rets = { v(...) }
|
local rets = { v(...) }
|
||||||
io.stderr:write(('%s(%s) = %s\n'):format(k, format_list({...}),
|
io.stderr:write(('%s(%s) = %s\n'):format(k, format_list({ ... }), format_list(rets)))
|
||||||
format_list(rets)))
|
|
||||||
return unpack(rets)
|
return unpack(rets)
|
||||||
end
|
end
|
||||||
end)(k_, v_)
|
end)(k_, v_)
|
||||||
@ -512,9 +509,13 @@ local function just_fail(_)
|
|||||||
end
|
end
|
||||||
say:set('assertion.just_fail.positive', '%s')
|
say:set('assertion.just_fail.positive', '%s')
|
||||||
say:set('assertion.just_fail.negative', '%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.positive',
|
||||||
'assertion.just_fail.negative')
|
'assertion.just_fail.negative'
|
||||||
|
)
|
||||||
|
|
||||||
local hook_fnamelen = 30
|
local hook_fnamelen = 30
|
||||||
local hook_sfnamelen = 30
|
local hook_sfnamelen = 30
|
||||||
@ -615,11 +616,14 @@ local function child_sethook(wr)
|
|||||||
.. whatchar
|
.. whatchar
|
||||||
.. namewhatchar
|
.. 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'
|
.. '\n'
|
||||||
)
|
)
|
||||||
-- eq(hook_msglen, #msg)
|
-- eq(hook_msglen, #msg)
|
||||||
@ -751,7 +755,7 @@ local function itp_parent(rd, pid, allow_failure, location)
|
|||||||
end
|
end
|
||||||
elseif status ~= 0 then
|
elseif status ~= 0 then
|
||||||
if not allow_failure 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
|
end
|
||||||
end
|
end
|
||||||
@ -760,7 +764,9 @@ local function gen_itp(it)
|
|||||||
child_calls_mod = {}
|
child_calls_mod = {}
|
||||||
child_calls_mod_once = {}
|
child_calls_mod_once = {}
|
||||||
child_cleanups_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
|
previous_defines_mod = previous_defines_init
|
||||||
cdefs_mod = cdefs_init:copy()
|
cdefs_mod = cdefs_init:copy()
|
||||||
local function itp(name, func, allow_failure)
|
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)
|
return cimport(Paths.test_source_path .. '/test/includes/pre/' .. path)
|
||||||
end
|
end
|
||||||
|
|
||||||
cimport('./src/nvim/types.h', './src/nvim/main.h', './src/nvim/os/time.h',
|
cimport('./src/nvim/types.h', './src/nvim/main.h', './src/nvim/os/time.h', './src/nvim/os/fs.h')
|
||||||
'./src/nvim/os/fs.h')
|
|
||||||
|
|
||||||
local function conv_enum(etab, eval)
|
local function conv_enum(etab, eval)
|
||||||
local n = tonumber(eval)
|
local n = tonumber(eval)
|
||||||
@ -853,7 +858,9 @@ end
|
|||||||
|
|
||||||
local function is_asan()
|
local function is_asan()
|
||||||
cimport('./src/nvim/version.h')
|
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
|
if status then
|
||||||
return ffi.string(res):match('-fsanitize=[a-z,]*address')
|
return ffi.string(res):match('-fsanitize=[a-z,]*address')
|
||||||
else
|
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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
|
|
||||||
local indent = helpers.cimport("./src/nvim/indent.h")
|
local indent = helpers.cimport('./src/nvim/indent.h')
|
||||||
local globals = helpers.cimport("./src/nvim/globals.h")
|
local globals = helpers.cimport('./src/nvim/globals.h')
|
||||||
|
|
||||||
describe('get_sts_value', function()
|
describe('get_sts_value', function()
|
||||||
itp([[returns 'softtabstop' when it is non-negative]], 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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
@ -9,7 +9,6 @@ local keycodes = helpers.cimport('./src/nvim/keycodes.h')
|
|||||||
local NULL = helpers.NULL
|
local NULL = helpers.NULL
|
||||||
|
|
||||||
describe('keycodes.c', function()
|
describe('keycodes.c', function()
|
||||||
|
|
||||||
describe('find_special_key()', function()
|
describe('find_special_key()', function()
|
||||||
local srcp = ffi.new('const unsigned char *[1]')
|
local srcp = ffi.new('const unsigned char *[1]')
|
||||||
local modp = ffi.new('int[1]')
|
local modp = ffi.new('int[1]')
|
||||||
@ -28,31 +27,26 @@ describe('keycodes.c', function()
|
|||||||
itp('case-insensitive', function()
|
itp('case-insensitive', function()
|
||||||
-- Compare other capitalizations to this.
|
-- Compare other capitalizations to this.
|
||||||
srcp[0] = '<C-A>'
|
srcp[0] = '<C-A>'
|
||||||
local all_caps_key =
|
local all_caps_key = keycodes.find_special_key(srcp, 5, modp, 0, NULL)
|
||||||
keycodes.find_special_key(srcp, 5, modp, 0, NULL)
|
|
||||||
local all_caps_mod = modp[0]
|
local all_caps_mod = modp[0]
|
||||||
|
|
||||||
srcp[0] = '<C-a>'
|
srcp[0] = '<C-a>'
|
||||||
eq(all_caps_key,
|
eq(all_caps_key, keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||||
keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
|
||||||
eq(all_caps_mod, modp[0])
|
eq(all_caps_mod, modp[0])
|
||||||
|
|
||||||
srcp[0] = '<c-A>'
|
srcp[0] = '<c-A>'
|
||||||
eq(all_caps_key,
|
eq(all_caps_key, keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||||
keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
|
||||||
eq(all_caps_mod, modp[0])
|
eq(all_caps_mod, modp[0])
|
||||||
|
|
||||||
srcp[0] = '<c-a>'
|
srcp[0] = '<c-a>'
|
||||||
eq(all_caps_key,
|
eq(all_caps_key, keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||||
keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
|
||||||
eq(all_caps_mod, modp[0])
|
eq(all_caps_mod, modp[0])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('double-quote in keycode #7411', function()
|
itp('double-quote in keycode #7411', function()
|
||||||
-- Unescaped with in_string=false
|
-- Unescaped with in_string=false
|
||||||
srcp[0] = '<C-">'
|
srcp[0] = '<C-">'
|
||||||
eq(string.byte('"'),
|
eq(string.byte('"'), keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
||||||
keycodes.find_special_key(srcp, 5, modp, 0, NULL))
|
|
||||||
|
|
||||||
-- Unescaped with in_string=true
|
-- Unescaped with in_string=true
|
||||||
eq(0, keycodes.find_special_key(srcp, 5, modp, keycodes.FSK_IN_STRING, NULL))
|
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))
|
eq(0, keycodes.find_special_key(srcp, 6, modp, 0, NULL))
|
||||||
|
|
||||||
-- Escaped with in_string=true
|
-- Escaped with in_string=true
|
||||||
eq(string.byte('"'),
|
eq(string.byte('"'), keycodes.find_special_key(srcp, 6, modp, keycodes.FSK_IN_STRING, NULL))
|
||||||
keycodes.find_special_key(srcp, 6, modp, keycodes.FSK_IN_STRING, NULL))
|
|
||||||
end)
|
end)
|
||||||
end)
|
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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
local ok = helpers.ok
|
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 function tablelength(t)
|
||||||
local count = 0
|
local count = 0
|
||||||
for _ in pairs(t) do count = count + 1 end
|
for _ in pairs(t) do
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
return count
|
return count
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -32,15 +34,27 @@ local function shadoworder(tree, shadow, iter, giveorder)
|
|||||||
local mark = lib.marktree_itr_current(iter)
|
local mark = lib.marktree_itr_current(iter)
|
||||||
local id = tonumber(mark.id)
|
local id = tonumber(mark.id)
|
||||||
local spos = shadow[id]
|
local spos = shadow[id]
|
||||||
if (mark.pos.row ~= spos[1] or mark.pos.col ~= spos[2]) then
|
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]..")")
|
error(
|
||||||
|
'invalid pos for '
|
||||||
|
.. id
|
||||||
|
.. ':('
|
||||||
|
.. mark.pos.row
|
||||||
|
.. ', '
|
||||||
|
.. mark.pos.col
|
||||||
|
.. ') instead of ('
|
||||||
|
.. spos[1]
|
||||||
|
.. ', '
|
||||||
|
.. spos[2]
|
||||||
|
.. ')'
|
||||||
|
)
|
||||||
end
|
end
|
||||||
if lib.mt_right_test(mark) ~= spos[3] then
|
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
|
end
|
||||||
if count > 0 then
|
if count > 0 then
|
||||||
if not pos_leq(last, spos) then
|
if not pos_leq(last, spos) then
|
||||||
error("DISORDER")
|
error('DISORDER')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
count = count + 1
|
count = count + 1
|
||||||
@ -52,16 +66,20 @@ local function shadoworder(tree, shadow, iter, giveorder)
|
|||||||
until not lib.marktree_itr_next(tree, iter)
|
until not lib.marktree_itr_next(tree, iter)
|
||||||
local shadowlen = tablelength(shadow)
|
local shadowlen = tablelength(shadow)
|
||||||
if shadowlen ~= count then
|
if shadowlen ~= count then
|
||||||
error("missed some keys? (shadow "..shadowlen..", tree "..count..")")
|
error('missed some keys? (shadow ' .. shadowlen .. ', tree ' .. count .. ')')
|
||||||
end
|
end
|
||||||
return id2pos, pos2id
|
return id2pos, pos2id
|
||||||
end
|
end
|
||||||
|
|
||||||
local function shadowsplice(shadow, start, old_extent, new_extent)
|
local function shadowsplice(shadow, start, old_extent, new_extent)
|
||||||
local old_end = {start[1] + old_extent[1],
|
local old_end = {
|
||||||
(old_extent[1] == 0 and start[2] or 0) + old_extent[2]}
|
start[1] + old_extent[1],
|
||||||
local new_end = {start[1] + new_extent[1],
|
(old_extent[1] == 0 and start[2] or 0) + old_extent[2],
|
||||||
(new_extent[1] == 0 and start[2] or 0) + new_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 delta = { new_end[1] - old_end[1], new_end[2] - old_end[2] }
|
||||||
for _, pos in pairs(shadow) do
|
for _, pos in pairs(shadow) do
|
||||||
if pos_leq(start, pos) then
|
if pos_leq(start, pos) then
|
||||||
@ -83,7 +101,15 @@ local function shadowsplice(shadow, start, old_extent, new_extent)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function dosplice(tree, shadow, start, old_extent, new_extent)
|
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)
|
shadowsplice(shadow, start, old_extent, new_extent)
|
||||||
end
|
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_col = end_col or -1
|
||||||
end_gravitate = end_gravitate or false
|
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
|
return my_id
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -108,10 +134,10 @@ describe('marktree', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('works', function()
|
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 shadow = {}
|
||||||
local iter = ffi.new("MarkTreeIter[1]")
|
local iter = ffi.new('MarkTreeIter[1]')
|
||||||
local iter2 = ffi.new("MarkTreeIter[1]")
|
local iter2 = ffi.new('MarkTreeIter[1]')
|
||||||
|
|
||||||
for i = 1, 100 do
|
for i = 1, 100 do
|
||||||
for j = 1, 100 do
|
for j = 1, 100 do
|
||||||
@ -224,27 +250,39 @@ describe('marktree', function()
|
|||||||
|
|
||||||
itp("'intersect_mov' function works correctly", function()
|
itp("'intersect_mov' function works correctly", function()
|
||||||
local function mov(x, y, w)
|
local function mov(x, y, w)
|
||||||
local xa = ffi.new("uint64_t[?]", #x)
|
local xa = ffi.new('uint64_t[?]', #x)
|
||||||
for i, xi in ipairs(x) do xa[i-1] = xi end
|
for i, xi in ipairs(x) do
|
||||||
local ya = ffi.new("uint64_t[?]", #y)
|
xa[i - 1] = xi
|
||||||
for i, yi in ipairs(y) do ya[i-1] = yi end
|
end
|
||||||
local wa = ffi.new("uint64_t[?]", #w)
|
local ya = ffi.new('uint64_t[?]', #y)
|
||||||
for i, wi in ipairs(w) do wa[i-1] = wi end
|
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 dummy_size = #x + #y + #w
|
||||||
local wouta = ffi.new("uint64_t[?]", dummy_size)
|
local wouta = ffi.new('uint64_t[?]', dummy_size)
|
||||||
local douta = ffi.new("uint64_t[?]", dummy_size)
|
local douta = ffi.new('uint64_t[?]', dummy_size)
|
||||||
local wsize = ffi.new("size_t[1]")
|
local wsize = ffi.new('size_t[1]')
|
||||||
wsize[0] = dummy_size
|
wsize[0] = dummy_size
|
||||||
local dsize = ffi.new("size_t[1]")
|
local dsize = ffi.new('size_t[1]')
|
||||||
dsize[0] = dummy_size
|
dsize[0] = dummy_size
|
||||||
|
|
||||||
local status = lib.intersect_mov_test(xa, #x, ya, #y, wa, #w, wouta, wsize, douta, dsize)
|
local status = lib.intersect_mov_test(xa, #x, ya, #y, wa, #w, wouta, wsize, douta, dsize)
|
||||||
if status == 0 then error'wowza' end
|
if status == 0 then
|
||||||
|
error 'wowza'
|
||||||
|
end
|
||||||
|
|
||||||
local wout, dout = {}, {}
|
local wout, dout = {}, {}
|
||||||
for i = 0,tonumber(wsize[0])-1 do table.insert(wout, tonumber(wouta[i])) end
|
for i = 0, tonumber(wsize[0]) - 1 do
|
||||||
for i = 0,tonumber(dsize[0])-1 do table.insert(dout, tonumber(douta[i])) end
|
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 }
|
return { wout, dout }
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -260,10 +298,12 @@ describe('marktree', function()
|
|||||||
eq({ { 1, 3, 5, 7, 9 }, { 2, 6, 10 } }, mov({ 1, 3, 5, 7, 9 }, { 2, 4, 6, 8, 10 }, { 4, 8 }))
|
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 }, { 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({ { 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(
|
||||||
|
{ { 0, 1, 4, 7, 10 }, {} },
|
||||||
|
mov({ 1, 3, 4, 6, 7, 9 }, { 2, 3, 5, 6, 8, 9 }, { 0, 2, 5, 8, 10 })
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
local function check_intersections(tree)
|
local function check_intersections(tree)
|
||||||
lib.marktree_check(tree)
|
lib.marktree_check(tree)
|
||||||
-- to debug stuff disable this branch
|
-- to debug stuff disable this branch
|
||||||
@ -279,13 +319,13 @@ describe('marktree', function()
|
|||||||
if not val then
|
if not val then
|
||||||
local str2 = lib.mt_inspect(tree, true, true)
|
local str2 = lib.mt_inspect(tree, true, true)
|
||||||
local dot2 = ffi.string(str2.data, str2.size)
|
local dot2 = ffi.string(str2.data, str2.size)
|
||||||
print("actual:\n\n".."Xafile.dot".."\n\nexpected:\n\n".."Xefile.dot".."\n")
|
print('actual:\n\n' .. 'Xafile.dot' .. '\n\nexpected:\n\n' .. 'Xefile.dot' .. '\n')
|
||||||
print("nivå", tree[0].root.level);
|
print('nivå', tree[0].root.level)
|
||||||
io.stdout:flush()
|
io.stdout:flush()
|
||||||
local afil = io.open("Xafile.dot", "wb")
|
local afil = io.open('Xafile.dot', 'wb')
|
||||||
afil:write(dot1)
|
afil:write(dot1)
|
||||||
afil:close()
|
afil:close()
|
||||||
local efil = io.open("Xefile.dot", "wb")
|
local efil = io.open('Xefile.dot', 'wb')
|
||||||
efil:write(dot2)
|
efil:write(dot2)
|
||||||
efil:close()
|
efil:close()
|
||||||
ok(false)
|
ok(false)
|
||||||
@ -295,7 +335,7 @@ describe('marktree', function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
itp('works with intersections', function()
|
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 = {}
|
local ids = {}
|
||||||
|
|
||||||
@ -324,7 +364,7 @@ describe('marktree', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('works with intersections with a big tree', function()
|
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 = {}
|
local ids = {}
|
||||||
|
|
||||||
@ -339,7 +379,7 @@ describe('marktree', function()
|
|||||||
eq(2000, tree[0].n_keys)
|
eq(2000, tree[0].n_keys)
|
||||||
ok(tree[0].root.level >= 2)
|
ok(tree[0].root.level >= 2)
|
||||||
|
|
||||||
local iter = ffi.new("MarkTreeIter[1]")
|
local iter = ffi.new('MarkTreeIter[1]')
|
||||||
|
|
||||||
local k = 0
|
local k = 0
|
||||||
for i = 1, 20 do
|
for i = 1, 20 do
|
||||||
@ -367,7 +407,7 @@ describe('marktree', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('works with intersections and marktree_splice', function()
|
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
|
for i = 1, 1000 do
|
||||||
put(tree, 1, i, false, 2, 1000 - i, false)
|
put(tree, 1, i, false, 2, 1000 - i, false)
|
||||||
@ -387,8 +427,8 @@ describe('marktree', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('marktree_move should preserve key order', function()
|
itp('marktree_move should preserve key order', function()
|
||||||
local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
|
local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
|
||||||
local iter = ffi.new("MarkTreeIter[1]")
|
local iter = ffi.new('MarkTreeIter[1]')
|
||||||
local ids = {}
|
local ids = {}
|
||||||
|
|
||||||
-- new index and old index look the same, but still have to move because
|
-- new index and old index look the same, but still have to move because
|
||||||
@ -405,7 +445,7 @@ describe('marktree', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('works with intersections and marktree_move', function()
|
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 = {}
|
local ids = {}
|
||||||
|
|
||||||
@ -416,7 +456,7 @@ describe('marktree', function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local iter = ffi.new("MarkTreeIter[1]")
|
local iter = ffi.new('MarkTreeIter[1]')
|
||||||
for i = 1, 1000 do
|
for i = 1, 1000 do
|
||||||
local which = i % 2
|
local which = i % 2
|
||||||
lib.marktree_lookup_ns(tree, ns, ids[i], which, iter)
|
lib.marktree_lookup_ns(tree, ns, ids[i], which, iter)
|
||||||
@ -425,11 +465,10 @@ describe('marktree', function()
|
|||||||
check_intersections(tree)
|
check_intersections(tree)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('works with intersections with a even bigger tree', function()
|
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 = {}
|
local ids = {}
|
||||||
|
|
||||||
@ -467,8 +506,8 @@ describe('marktree', function()
|
|||||||
ok(tree[0].root.level >= 3)
|
ok(tree[0].root.level >= 3)
|
||||||
check_intersections(tree)
|
check_intersections(tree)
|
||||||
|
|
||||||
local iter = ffi.new("MarkTreeIter[1]")
|
local iter = ffi.new('MarkTreeIter[1]')
|
||||||
local pair = ffi.new("MTPair[1]")
|
local pair = ffi.new('MTPair[1]')
|
||||||
for i = 1, 10 do
|
for i = 1, 10 do
|
||||||
-- use array as set and not {[id]=true} map, to detect duplicates
|
-- use array as set and not {[id]=true} map, to detect duplicates
|
||||||
local set = {}
|
local set = {}
|
||||||
@ -499,7 +538,7 @@ describe('marktree', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('works with intersections with a even bigger tree and splice', function()
|
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
|
-- too much overhead on ASAN
|
||||||
local size_factor = helpers.is_asan() and 3 or 10
|
local size_factor = helpers.is_asan() and 3 or 10
|
||||||
|
@ -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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
@ -16,8 +16,7 @@ describe('mbyte', function()
|
|||||||
return table.concat(s)
|
return table.concat(s)
|
||||||
end
|
end
|
||||||
|
|
||||||
before_each(function()
|
before_each(function() end)
|
||||||
end)
|
|
||||||
|
|
||||||
itp('utf_ptr2char', function()
|
itp('utf_ptr2char', function()
|
||||||
-- For strings with length 1 the first byte is returned.
|
-- For strings with length 1 the first byte is returned.
|
||||||
@ -48,8 +47,8 @@ describe('mbyte', function()
|
|||||||
|
|
||||||
describe('utfc_ptr2schar_len', function()
|
describe('utfc_ptr2schar_len', function()
|
||||||
local function test_seq(seq)
|
local function test_seq(seq)
|
||||||
local firstc = ffi.new("int[1]")
|
local firstc = ffi.new('int[1]')
|
||||||
local buf = ffi.new("char[32]")
|
local buf = ffi.new('char[32]')
|
||||||
lib.schar_get(buf, lib.utfc_ptr2schar_len(to_string(seq), #seq, firstc))
|
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
|
end
|
||||||
@ -89,36 +88,35 @@ describe('mbyte', function()
|
|||||||
eq(byte(0x7f), test_seq { 0x7f, 0xc2, 0x80 })
|
eq(byte(0x7f), test_seq { 0x7f, 0xc2, 0x80 })
|
||||||
|
|
||||||
-- Combining character is U+0300
|
-- 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
|
-- No UTF-8 sequence
|
||||||
eq({ '', 0xc2 }, test_seq { 0xc2, 0x7f, 0xcc })
|
eq({ '', 0xc2 }, test_seq { 0xc2, 0x7f, 0xcc })
|
||||||
-- Incomplete combining character
|
-- 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)
|
-- 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)
|
end)
|
||||||
|
|
||||||
itp('4-byte sequences', function()
|
itp('4-byte sequences', function()
|
||||||
|
|
||||||
-- No following combining character
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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)
|
end)
|
||||||
|
|
||||||
itp('5+-byte sequences', function()
|
itp('5+-byte sequences', function()
|
||||||
@ -128,46 +126,81 @@ describe('mbyte', function()
|
|||||||
eq(byte(0x7f), test_seq { 0x7f, 0xc2, 0xcc, 0x80, 0x80 })
|
eq(byte(0x7f), test_seq { 0x7f, 0xc2, 0xcc, 0x80, 0x80 })
|
||||||
|
|
||||||
-- Combining character U+0300
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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
|
-- 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)
|
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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local cimport = helpers.cimport
|
local cimport = helpers.cimport
|
||||||
@ -22,8 +22,7 @@ describe('xstrlcat()', function()
|
|||||||
assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests
|
assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests
|
||||||
local dst_cstr = cstr(dsize, dst)
|
local dst_cstr = cstr(dsize, dst)
|
||||||
local src_cstr = dst_cstr + src_idx -- pointer into `dst` (overlaps)
|
local src_cstr = dst_cstr + src_idx -- pointer into `dst` (overlaps)
|
||||||
eq(string.len(dst) + string.len(dst) - src_idx,
|
eq(string.len(dst) + string.len(dst) - src_idx, cimp.xstrlcat(dst_cstr, src_cstr, dsize))
|
||||||
cimp.xstrlcat(dst_cstr, src_cstr, dsize))
|
|
||||||
return ffi.string(dst_cstr)
|
return ffi.string(dst_cstr)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -48,5 +47,4 @@ describe('xstrlcat()', function()
|
|||||||
eq('', test_xstrlcat('', 'b', 1))
|
eq('', test_xstrlcat('', 'b', 1))
|
||||||
eq('ABCיהZd', test_xstrlcat('ABCיהZ', 'defgiיהZ', 10))
|
eq('ABCיהZd', test_xstrlcat('ABCיהZ', 'defgiיהZ', 10))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
|
|
||||||
local cimp = helpers.cimport('./src/nvim/message.h', './src/nvim/memory.h',
|
local cimp = helpers.cimport('./src/nvim/message.h', './src/nvim/memory.h', './src/nvim/strings.h')
|
||||||
'./src/nvim/strings.h')
|
|
||||||
|
|
||||||
describe('trunc_string', function()
|
describe('trunc_string', function()
|
||||||
local buflen = 40
|
local buflen = 40
|
||||||
|
@ -35,7 +35,9 @@ end
|
|||||||
|
|
||||||
describe('msgpack', function()
|
describe('msgpack', function()
|
||||||
describe('unpacker', 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", [
|
-- [kMessageTypeNotification, "redraw", [
|
||||||
-- ["grid_line",
|
-- ["grid_line",
|
||||||
-- [2, 0, 0, [[" " , 0, 77]], false]
|
-- [2, 0, 0, [[" " , 0, 77]], false]
|
||||||
@ -54,13 +56,15 @@ describe('msgpack', function()
|
|||||||
unpacker[0].read_size = unpacker[0].read_size + 1
|
unpacker[0].read_size = unpacker[0].read_size + 1
|
||||||
finished = unpacker_advance(unpacker)
|
finished = unpacker_advance(unpacker)
|
||||||
eq(finished, true)
|
eq(finished, true)
|
||||||
end)
|
end
|
||||||
|
)
|
||||||
|
|
||||||
itp('does not crash when parsing grid_line event with 0 `cells` #25184', function()
|
itp('does not crash when parsing grid_line event with 0 `cells` #25184', function()
|
||||||
local unpacker = make_unpacker()
|
local unpacker = make_unpacker()
|
||||||
lib.unpacker_init(unpacker)
|
lib.unpacker_init(unpacker)
|
||||||
|
|
||||||
unpacker_goto(unpacker,
|
unpacker_goto(
|
||||||
|
unpacker,
|
||||||
-- [kMessageTypeNotification, "redraw", [
|
-- [kMessageTypeNotification, "redraw", [
|
||||||
-- ["grid_line",
|
-- ["grid_line",
|
||||||
-- [2, 0, 0, [], false]
|
-- [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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local child_call_once = helpers.child_call_once
|
local child_call_once = helpers.child_call_once
|
||||||
@ -6,9 +6,9 @@ local cimport = helpers.cimport
|
|||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
local eq = helpers.eq
|
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 parent, child1, child2, child3
|
||||||
|
|
||||||
local function put(q, str)
|
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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
local eq = helpers.eq
|
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)
|
local check_ff_value = function(ff)
|
||||||
return optionstr.check_ff_value(to_cstr(ff))
|
return optionstr.check_ff_value(to_cstr(ff))
|
||||||
end
|
end
|
||||||
|
|
||||||
describe('check_ff_value', function()
|
describe('check_ff_value', function()
|
||||||
|
|
||||||
itp('views empty string as valid', function()
|
itp('views empty string as valid', function()
|
||||||
eq(1, check_ff_value(""))
|
eq(1, check_ff_value(''))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('views "unix", "dos" and "mac" as valid', function()
|
itp('views "unix", "dos" and "mac" as valid', function()
|
||||||
eq(1, check_ff_value("unix"))
|
eq(1, check_ff_value('unix'))
|
||||||
eq(1, check_ff_value("dos"))
|
eq(1, check_ff_value('dos'))
|
||||||
eq(1, check_ff_value("mac"))
|
eq(1, check_ff_value('mac'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('views "foo" as invalid', function()
|
itp('views "foo" as invalid', function()
|
||||||
eq(0, check_ff_value("foo"))
|
eq(0, check_ff_value('foo'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -62,7 +62,7 @@ describe('env.c', function()
|
|||||||
eq('non-empty', os.getenv(name))
|
eq('non-empty', os.getenv(name))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp("`overwrite` behavior", function()
|
itp('`overwrite` behavior', function()
|
||||||
local name = 'NVIM_UNIT_TEST_SETENV_2N'
|
local name = 'NVIM_UNIT_TEST_SETENV_2N'
|
||||||
local value = 'NVIM_UNIT_TEST_SETENV_2V'
|
local value = 'NVIM_UNIT_TEST_SETENV_2V'
|
||||||
local value_updated = 'NVIM_UNIT_TEST_SETENV_2V_UPDATED'
|
local value_updated = 'NVIM_UNIT_TEST_SETENV_2V_UPDATED'
|
||||||
@ -245,7 +245,7 @@ describe('env.c', function()
|
|||||||
local input = '~/foo ~ foo'
|
local input = '~/foo ~ foo'
|
||||||
local homedir = cstr(255, '')
|
local homedir = cstr(255, '')
|
||||||
cimp.expand_env_esc(to_cstr('~'), homedir, 255, false, true, NULL)
|
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, '')
|
local output = cstr(255, '')
|
||||||
cimp.expand_env_esc(to_cstr(input), output, 255, false, true, NULL)
|
cimp.expand_env_esc(to_cstr(input), output, 255, false, true, NULL)
|
||||||
eq(ffi.string(output), ffi.string(output_expected))
|
eq(ffi.string(output), ffi.string(output_expected))
|
||||||
@ -256,7 +256,7 @@ describe('env.c', function()
|
|||||||
local dst = cstr(255, '')
|
local dst = cstr(255, '')
|
||||||
cimp.expand_env_esc(to_cstr('~'), dst, 255, false, true, NULL)
|
cimp.expand_env_esc(to_cstr('~'), dst, 255, false, true, NULL)
|
||||||
local homedir = ffi.string(dst)
|
local homedir = ffi.string(dst)
|
||||||
local output_expected = homedir .. "/foo " .. homedir .. " foo"
|
local output_expected = homedir .. '/foo ' .. homedir .. ' foo'
|
||||||
local output = cstr(255, '')
|
local output = cstr(255, '')
|
||||||
cimp.expand_env_esc(input, output, 255, false, false, NULL)
|
cimp.expand_env_esc(input, output, 255, false, false, NULL)
|
||||||
eq(output_expected, ffi.string(output))
|
eq(output_expected, ffi.string(output))
|
||||||
@ -267,8 +267,9 @@ describe('env.c', function()
|
|||||||
cimp.os_get_username(name_out, 100)
|
cimp.os_get_username(name_out, 100)
|
||||||
local curuser = ffi.string(name_out)
|
local curuser = ffi.string(name_out)
|
||||||
|
|
||||||
local src = to_cstr("~"..curuser.."/Vcs/django-rest-framework/rest_framework/renderers.py")
|
local src =
|
||||||
local dst = cstr(256, "~"..curuser)
|
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)
|
cimp.expand_env_esc(src, dst, 256, false, false, NULL)
|
||||||
local len = string.len(ffi.string(dst))
|
local len = string.len(ffi.string(dst))
|
||||||
assert.True(len > 56)
|
assert.True(len > 56)
|
||||||
|
@ -26,7 +26,7 @@ local linkb = dir .. '/broken.lnk'
|
|||||||
local filec = dir .. '/created-file.dat'
|
local filec = dir .. '/created-file.dat'
|
||||||
|
|
||||||
before_each(function()
|
before_each(function()
|
||||||
mkdir(dir);
|
mkdir(dir)
|
||||||
|
|
||||||
local f1 = io.open(file1, 'w')
|
local f1 = io.open(file1, 'w')
|
||||||
f1:write(fcontents)
|
f1:write(fcontents)
|
||||||
@ -193,7 +193,9 @@ describe('file_open', function()
|
|||||||
local err, _ = file_open(linkf, m.kFileNoSymlink, 384)
|
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 ==
|
-- 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.
|
-- 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)
|
end)
|
||||||
|
|
||||||
itp('can open an existing file write-only with kFileCreate', function()
|
itp('can open an existing file write-only with kFileCreate', function()
|
||||||
@ -249,8 +251,7 @@ describe('file_open', function()
|
|||||||
eq(nil, attrs)
|
eq(nil, attrs)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('can truncate an existing file with kFileTruncate when opening a symlink',
|
itp('can truncate an existing file with kFileTruncate when opening a symlink', function()
|
||||||
function()
|
|
||||||
local err, fp = file_open(linkf, m.kFileTruncate, 384)
|
local err, fp = file_open(linkf, m.kFileTruncate, 384)
|
||||||
eq(0, err)
|
eq(0, err)
|
||||||
eq(true, fp.wr)
|
eq(true, fp.wr)
|
||||||
@ -356,8 +357,7 @@ describe('file_read', function()
|
|||||||
local exp_s = fcontents:sub(shift + 1, shift + size)
|
local exp_s = fcontents:sub(shift + 1, shift + size)
|
||||||
if shift + size >= #fcontents then
|
if shift + size >= #fcontents then
|
||||||
exp_err = #fcontents - shift
|
exp_err = #fcontents - shift
|
||||||
exp_s = (fcontents:sub(shift + 1, shift + size)
|
exp_s = (fcontents:sub(shift + 1, shift + size) .. (('\0'):rep(size - exp_err)))
|
||||||
.. (('\0'):rep(size - exp_err)))
|
|
||||||
end
|
end
|
||||||
eq({ exp_err, exp_s }, { file_read(fp, size) })
|
eq({ exp_err, exp_s }, { file_read(fp, size) })
|
||||||
shift = shift + size
|
shift = shift + size
|
||||||
@ -379,8 +379,7 @@ describe('file_read', function()
|
|||||||
eq(0, err)
|
eq(0, err)
|
||||||
eq(false, fp.wr)
|
eq(false, fp.wr)
|
||||||
eq({ 5, fcontents:sub(1, 5) }, { file_read(fp, 5) })
|
eq({ 5, fcontents:sub(1, 5) }, { file_read(fp, 5) })
|
||||||
eq({#fcontents - 5, fcontents:sub(6) .. (('\0'):rep(5))},
|
eq({ #fcontents - 5, fcontents:sub(6) .. (('\0'):rep(5)) }, { file_read(fp, #fcontents) })
|
||||||
{file_read(fp, #fcontents)})
|
|
||||||
eq(0, m.file_close(fp, false))
|
eq(0, m.file_close(fp, false))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -395,8 +394,7 @@ describe('file_read', function()
|
|||||||
local exp_s = fcontents:sub(shift + 1, shift + size)
|
local exp_s = fcontents:sub(shift + 1, shift + size)
|
||||||
if shift + size >= #fcontents then
|
if shift + size >= #fcontents then
|
||||||
exp_err = #fcontents - shift
|
exp_err = #fcontents - shift
|
||||||
exp_s = (fcontents:sub(shift + 1, shift + size)
|
exp_s = (fcontents:sub(shift + 1, shift + size) .. (('\0'):rep(size - exp_err)))
|
||||||
.. (('\0'):rep(size - exp_err)))
|
|
||||||
end
|
end
|
||||||
eq({ exp_err, exp_s }, { file_read(fp, size) })
|
eq({ exp_err, exp_s }, { file_read(fp, size) })
|
||||||
shift = shift + size
|
shift = shift + size
|
||||||
|
@ -68,7 +68,7 @@ describe('fs.c', function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
before_each(function()
|
before_each(function()
|
||||||
mkdir('unit-test-directory');
|
mkdir('unit-test-directory')
|
||||||
|
|
||||||
io.open('unit-test-directory/test.file', 'w'):close()
|
io.open('unit-test-directory/test.file', 'w'):close()
|
||||||
|
|
||||||
@ -284,17 +284,19 @@ describe('fs.c', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
-- Some systems may not have `id` utility.
|
-- 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)
|
pending('skipped (missing `id` utility)', function() end)
|
||||||
else
|
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
|
local file_gid = luv.fs_stat(filename).gid
|
||||||
|
|
||||||
-- Gets ID of any group of which current user is a member except the
|
-- Gets ID of any group of which current user is a member except the
|
||||||
-- group that owns the file.
|
-- group that owns the file.
|
||||||
local id_fd = io.popen('id -G')
|
local id_fd = io.popen('id -G')
|
||||||
local new_gid = id_fd:read('*n')
|
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')
|
new_gid = id_fd:read('*n')
|
||||||
end
|
end
|
||||||
id_fd:close()
|
id_fd:close()
|
||||||
@ -305,10 +307,11 @@ describe('fs.c', function()
|
|||||||
eq(0, (os_fchown(filename, -1, new_gid)))
|
eq(0, (os_fchown(filename, -1, new_gid)))
|
||||||
eq(new_gid, luv.fs_stat(filename).gid)
|
eq(new_gid, luv.fs_stat(filename).gid)
|
||||||
end
|
end
|
||||||
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)
|
pending('skipped (uv_fs_chown is no-op on Windows)', function() end)
|
||||||
else
|
else
|
||||||
itp('returns nonzero if process has not enough permissions', function()
|
itp('returns nonzero if process has not enough permissions', function()
|
||||||
@ -318,7 +321,6 @@ describe('fs.c', function()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
describe('os_file_is_readable', function()
|
describe('os_file_is_readable', function()
|
||||||
itp('returns false if the file is not readable', function()
|
itp('returns false if the file is not readable', function()
|
||||||
local perm = os_getperm('unit-test-directory/test.file')
|
local perm = os_getperm('unit-test-directory/test.file')
|
||||||
@ -330,13 +332,11 @@ describe('fs.c', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('returns false if the file does not exist', function()
|
itp('returns false if the file does not exist', function()
|
||||||
eq(false, os_file_is_readable(
|
eq(false, os_file_is_readable('unit-test-directory/what_are_you_smoking.gif'))
|
||||||
'unit-test-directory/what_are_you_smoking.gif'))
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('returns true if the file is readable', function()
|
itp('returns true if the file is readable', function()
|
||||||
eq(true, os_file_is_readable(
|
eq(true, os_file_is_readable('unit-test-directory/test.file'))
|
||||||
'unit-test-directory/test.file'))
|
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -494,9 +494,14 @@ describe('fs.c', function()
|
|||||||
local dup0 = fs.os_dup(0)
|
local dup0 = fs.os_dup(0)
|
||||||
local dup1 = fs.os_dup(1)
|
local dup1 = fs.os_dup(1)
|
||||||
local dup2 = fs.os_dup(2)
|
local dup2 = fs.os_dup(2)
|
||||||
local tbl = {[0]=true, [1]=true, [2]=true,
|
local tbl = {
|
||||||
[tonumber(dup0)]=true, [tonumber(dup1)]=true,
|
[0] = true,
|
||||||
[tonumber(dup2)]=true}
|
[1] = true,
|
||||||
|
[2] = true,
|
||||||
|
[tonumber(dup0)] = true,
|
||||||
|
[tonumber(dup1)] = true,
|
||||||
|
[tonumber(dup2)] = true,
|
||||||
|
}
|
||||||
local i = 0
|
local i = 0
|
||||||
for _, _ in pairs(tbl) do
|
for _, _ in pairs(tbl) do
|
||||||
i = i + 1
|
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)))
|
eq(ffi.C.UV_ENOENT, (os_open('non-existing-file', ffi.C.kO_RDWR, 0)))
|
||||||
end)
|
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)
|
assert_file_does_not_exist(new_file)
|
||||||
local fd = os_open(new_file, ffi.C.kO_CREAT, 0)
|
local fd = os_open(new_file, ffi.C.kO_CREAT, 0)
|
||||||
assert.is_true(0 <= fd)
|
assert.is_true(0 <= fd)
|
||||||
eq(0, os_close(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()
|
itp('returns non-negative for O_CREAT on a existing file which then can be closed', function()
|
||||||
assert_file_exists(existing_file)
|
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()
|
itp('sets `rwx` permissions for O_CREAT 700 which then can be closed', function()
|
||||||
assert_file_does_not_exist(new_file)
|
assert_file_does_not_exist(new_file)
|
||||||
--create the 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
|
--verify permissions
|
||||||
eq(33216, luv.fs_stat(new_file).mode)
|
eq(33216, luv.fs_stat(new_file).mode)
|
||||||
eq(0, os_close(fd))
|
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()
|
itp('sets `rw` permissions for O_CREAT 600 which then can be closed', function()
|
||||||
assert_file_does_not_exist(new_file)
|
assert_file_does_not_exist(new_file)
|
||||||
--create the 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
|
--verify permissions
|
||||||
eq(33152, luv.fs_stat(new_file).mode)
|
eq(33152, luv.fs_stat(new_file).mode)
|
||||||
eq(0, os_close(fd))
|
eq(0, os_close(fd))
|
||||||
end)
|
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)
|
local fd = os_open(existing_file, ffi.C.kO_RDWR, 0)
|
||||||
assert.is_true(0 <= fd)
|
assert.is_true(0 <= fd)
|
||||||
eq(0, os_close(fd))
|
eq(0, os_close(fd))
|
||||||
end)
|
end
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('os_close', function()
|
describe('os_close', function()
|
||||||
@ -613,19 +624,24 @@ describe('fs.c', function()
|
|||||||
itp('can read the whole file in two calls, one partially', function()
|
itp('can read the whole file in two calls, one partially', function()
|
||||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||||
ok(fd >= 0)
|
ok(fd >= 0)
|
||||||
eq({false, #fcontents * 3/4, fcontents:sub(1, #fcontents * 3/4)},
|
eq(
|
||||||
{os_read(fd, #fcontents * 3/4)})
|
{ false, #fcontents * 3 / 4, fcontents:sub(1, #fcontents * 3 / 4) },
|
||||||
eq({true,
|
{ os_read(fd, #fcontents * 3 / 4) }
|
||||||
|
)
|
||||||
|
eq({
|
||||||
|
true,
|
||||||
(#fcontents * 1 / 4),
|
(#fcontents * 1 / 4),
|
||||||
fcontents:sub(#fcontents * 3/4 + 1) .. ('\0'):rep(#fcontents * 2/4)},
|
fcontents:sub(#fcontents * 3 / 4 + 1) .. ('\0'):rep(#fcontents * 2 / 4),
|
||||||
{os_read(fd, #fcontents * 3/4)})
|
}, { os_read(fd, #fcontents * 3 / 4) })
|
||||||
eq(0, os_close(fd))
|
eq(0, os_close(fd))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('os_readv', function()
|
describe('os_readv', function()
|
||||||
-- Function may be absent
|
-- 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
|
return
|
||||||
end
|
end
|
||||||
local file = 'test-unit-os-fs_spec-os_readv.dat'
|
local file = 'test-unit-os-fs_spec-os_readv.dat'
|
||||||
@ -659,16 +675,21 @@ describe('fs.c', function()
|
|||||||
itp('can read the whole file at once and then report eof', function()
|
itp('can read the whole file at once and then report eof', function()
|
||||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||||
ok(fd >= 0)
|
ok(fd >= 0)
|
||||||
eq({false,
|
eq({
|
||||||
|
false,
|
||||||
#fcontents,
|
#fcontents,
|
||||||
{fcontents:sub(1, #fcontents * 1/4),
|
{
|
||||||
|
fcontents:sub(1, #fcontents * 1 / 4),
|
||||||
fcontents:sub(#fcontents * 1 / 4 + 1, #fcontents * 3 / 4),
|
fcontents:sub(#fcontents * 1 / 4 + 1, #fcontents * 3 / 4),
|
||||||
fcontents:sub(#fcontents * 3 / 4 + 1, #fcontents * 15 / 16),
|
fcontents:sub(#fcontents * 3 / 4 + 1, #fcontents * 15 / 16),
|
||||||
fcontents:sub(#fcontents * 15/16 + 1, #fcontents)}},
|
fcontents:sub(#fcontents * 15 / 16 + 1, #fcontents),
|
||||||
{os_readv(fd, {#fcontents * 1/4,
|
},
|
||||||
#fcontents * 2/4,
|
}, {
|
||||||
#fcontents * 3/16,
|
os_readv(
|
||||||
#fcontents * 1/16})})
|
fd,
|
||||||
|
{ #fcontents * 1 / 4, #fcontents * 2 / 4, #fcontents * 3 / 16, #fcontents * 1 / 16 }
|
||||||
|
),
|
||||||
|
})
|
||||||
eq({ true, 0, { '\0' } }, { os_readv(fd, { 1 }) })
|
eq({ true, 0, { '\0' } }, { os_readv(fd, { 1 }) })
|
||||||
eq(0, os_close(fd))
|
eq(0, os_close(fd))
|
||||||
end)
|
end)
|
||||||
@ -676,12 +697,15 @@ describe('fs.c', function()
|
|||||||
itp('can read the whole file in two calls, one partially', function()
|
itp('can read the whole file in two calls, one partially', function()
|
||||||
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
|
||||||
ok(fd >= 0)
|
ok(fd >= 0)
|
||||||
eq({false, #fcontents * 3/4, {fcontents:sub(1, #fcontents * 3/4)}},
|
eq(
|
||||||
{os_readv(fd, {#fcontents * 3/4})})
|
{ false, #fcontents * 3 / 4, { fcontents:sub(1, #fcontents * 3 / 4) } },
|
||||||
eq({true,
|
{ os_readv(fd, { #fcontents * 3 / 4 }) }
|
||||||
|
)
|
||||||
|
eq({
|
||||||
|
true,
|
||||||
(#fcontents * 1 / 4),
|
(#fcontents * 1 / 4),
|
||||||
{fcontents:sub(#fcontents * 3/4 + 1) .. ('\0'):rep(#fcontents * 2/4)}},
|
{ fcontents:sub(#fcontents * 3 / 4 + 1) .. ('\0'):rep(#fcontents * 2 / 4) },
|
||||||
{os_readv(fd, {#fcontents * 3/4})})
|
}, { os_readv(fd, { #fcontents * 3 / 4 }) })
|
||||||
eq(0, os_close(fd))
|
eq(0, os_close(fd))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -784,8 +808,7 @@ describe('fs.c', function()
|
|||||||
|
|
||||||
itp('fails to create a directory where there is a file', 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 mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
local ret, failed_dir, created_dir = os_mkdir_recurse('unit-test-directory/test.file', mode)
|
||||||
'unit-test-directory/test.file', mode)
|
|
||||||
neq(0, ret)
|
neq(0, ret)
|
||||||
eq('unit-test-directory/test.file', failed_dir)
|
eq('unit-test-directory/test.file', failed_dir)
|
||||||
eq(nil, created_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()
|
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 mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
local ret, failed_dir, created_dir =
|
||||||
'unit-test-directory/test.file/test', mode)
|
os_mkdir_recurse('unit-test-directory/test.file/test', mode)
|
||||||
neq(0, ret)
|
neq(0, ret)
|
||||||
eq('unit-test-directory/test.file', failed_dir)
|
eq('unit-test-directory/test.file', failed_dir)
|
||||||
eq(nil, created_dir)
|
eq(nil, created_dir)
|
||||||
@ -802,8 +825,8 @@ describe('fs.c', function()
|
|||||||
|
|
||||||
itp('succeeds to create a directory', function()
|
itp('succeeds to create a directory', function()
|
||||||
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
local ret, failed_dir, created_dir =
|
||||||
'unit-test-directory/new-dir-recurse', mode)
|
os_mkdir_recurse('unit-test-directory/new-dir-recurse', mode)
|
||||||
eq(0, ret)
|
eq(0, ret)
|
||||||
eq(nil, failed_dir)
|
eq(nil, failed_dir)
|
||||||
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
|
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()
|
itp('succeeds to create a directory ending with ///', function()
|
||||||
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
local ret, failed_dir, created_dir =
|
||||||
'unit-test-directory/new-dir-recurse///', mode)
|
os_mkdir_recurse('unit-test-directory/new-dir-recurse///', mode)
|
||||||
eq(0, ret)
|
eq(0, ret)
|
||||||
eq(nil, failed_dir)
|
eq(nil, failed_dir)
|
||||||
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
|
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()
|
itp('succeeds to create a directory ending with /', function()
|
||||||
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
local ret, failed_dir, created_dir =
|
||||||
'unit-test-directory/new-dir-recurse/', mode)
|
os_mkdir_recurse('unit-test-directory/new-dir-recurse/', mode)
|
||||||
eq(0, ret)
|
eq(0, ret)
|
||||||
eq(nil, failed_dir)
|
eq(nil, failed_dir)
|
||||||
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
|
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()
|
itp('succeeds to create a directory tree', function()
|
||||||
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
|
||||||
local ret, failed_dir, created_dir = os_mkdir_recurse(
|
local ret, failed_dir, created_dir =
|
||||||
'unit-test-directory/new-dir-recurse/1/2/3', mode)
|
os_mkdir_recurse('unit-test-directory/new-dir-recurse/1/2/3', mode)
|
||||||
eq(0, ret)
|
eq(0, ret)
|
||||||
eq(nil, failed_dir)
|
eq(nil, failed_dir)
|
||||||
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
|
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
|
||||||
|
@ -21,9 +21,7 @@ describe('shell functions', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
local function shell_build_argv(cmd, extra_args)
|
local function shell_build_argv(cmd, extra_args)
|
||||||
local res = cimported.shell_build_argv(
|
local res = cimported.shell_build_argv(cmd and to_cstr(cmd), extra_args and to_cstr(extra_args))
|
||||||
cmd and to_cstr(cmd),
|
|
||||||
extra_args and to_cstr(extra_args))
|
|
||||||
-- `res` is zero-indexed (C pointer, not Lua table)!
|
-- `res` is zero-indexed (C pointer, not Lua table)!
|
||||||
local argc = 0
|
local argc = 0
|
||||||
local ret = {}
|
local ret = {}
|
||||||
@ -40,9 +38,7 @@ describe('shell functions', function()
|
|||||||
|
|
||||||
local function shell_argv_to_str(argv_table)
|
local function shell_argv_to_str(argv_table)
|
||||||
-- C string array (char **).
|
-- C string array (char **).
|
||||||
local argv = (argv_table
|
local argv = (argv_table and ffi.new('char*[?]', #argv_table + 1) or NULL)
|
||||||
and ffi.new("char*[?]", #argv_table+1)
|
|
||||||
or NULL)
|
|
||||||
|
|
||||||
local argc = 1
|
local argc = 1
|
||||||
while argv_table ~= nil and argv_table[argc] ~= nil do
|
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 output = ffi.new('char *[1]')
|
||||||
local nread = ffi.new('size_t[1]')
|
local nread = ffi.new('size_t[1]')
|
||||||
|
|
||||||
local argv = ffi.cast('char**',
|
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr(cmd), nil))
|
||||||
cimported.shell_build_argv(to_cstr(cmd), nil))
|
|
||||||
local status = cimported.os_system(argv, input_or, input_len, output, nread)
|
local status = cimported.os_system(argv, input_or, input_len, output, nread)
|
||||||
|
|
||||||
return status, intern(output[0], nread[0])
|
return status, intern(output[0], nread[0])
|
||||||
@ -119,19 +114,17 @@ describe('shell functions', function()
|
|||||||
itp('splits and unquotes &shell and &shellcmdflag', function()
|
itp('splits and unquotes &shell and &shellcmdflag', function()
|
||||||
cimported.p_sh = to_cstr('/Program" "Files/zsh -f')
|
cimported.p_sh = to_cstr('/Program" "Files/zsh -f')
|
||||||
cimported.p_shcf = to_cstr('-x -o "sh word split" "-"c')
|
cimported.p_shcf = to_cstr('-x -o "sh word split" "-"c')
|
||||||
eq({'/Program Files/zsh', '-f',
|
eq(
|
||||||
'ghi jkl',
|
{ '/Program Files/zsh', '-f', 'ghi jkl', '-x', '-o', 'sh word split', '-c', 'abc def' },
|
||||||
'-x', '-o', 'sh word split',
|
shell_build_argv('abc def', 'ghi jkl')
|
||||||
'-c', 'abc def'},
|
)
|
||||||
shell_build_argv('abc def', 'ghi jkl'))
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('applies shellxescape (p_sxe) and shellxquote (p_sxq)', function()
|
itp('applies shellxescape (p_sxe) and shellxquote (p_sxq)', function()
|
||||||
cimported.p_sxq = to_cstr('(')
|
cimported.p_sxq = to_cstr('(')
|
||||||
cimported.p_sxe = to_cstr('"&|<>()@^')
|
cimported.p_sxe = to_cstr('"&|<>()@^')
|
||||||
|
|
||||||
local argv = ffi.cast('char**',
|
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil))
|
||||||
cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil))
|
|
||||||
eq(ffi.string(argv[0]), '/bin/sh')
|
eq(ffi.string(argv[0]), '/bin/sh')
|
||||||
eq(ffi.string(argv[1]), '-c')
|
eq(ffi.string(argv[1]), '-c')
|
||||||
eq(ffi.string(argv[2]), '(echo ^&^|^<^>^(^)^@^^)')
|
eq(ffi.string(argv[2]), '(echo ^&^|^<^>^(^)^@^^)')
|
||||||
@ -142,8 +135,7 @@ describe('shell functions', function()
|
|||||||
cimported.p_sxq = to_cstr('"(')
|
cimported.p_sxq = to_cstr('"(')
|
||||||
cimported.p_sxe = to_cstr('"&|<>()@^')
|
cimported.p_sxe = to_cstr('"&|<>()@^')
|
||||||
|
|
||||||
local argv = ffi.cast('char**', cimported.shell_build_argv(
|
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
|
||||||
to_cstr('echo -n some text'), nil))
|
|
||||||
eq(ffi.string(argv[0]), '/bin/sh')
|
eq(ffi.string(argv[0]), '/bin/sh')
|
||||||
eq(ffi.string(argv[1]), '-c')
|
eq(ffi.string(argv[1]), '-c')
|
||||||
eq(ffi.string(argv[2]), '"(echo -n some text)"')
|
eq(ffi.string(argv[2]), '"(echo -n some text)"')
|
||||||
@ -154,8 +146,7 @@ describe('shell functions', function()
|
|||||||
cimported.p_sxq = to_cstr('"')
|
cimported.p_sxq = to_cstr('"')
|
||||||
cimported.p_sxe = to_cstr('')
|
cimported.p_sxe = to_cstr('')
|
||||||
|
|
||||||
local argv = ffi.cast('char**', cimported.shell_build_argv(
|
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
|
||||||
to_cstr('echo -n some text'), nil))
|
|
||||||
eq(ffi.string(argv[0]), '/bin/sh')
|
eq(ffi.string(argv[0]), '/bin/sh')
|
||||||
eq(ffi.string(argv[1]), '-c')
|
eq(ffi.string(argv[1]), '-c')
|
||||||
eq(ffi.string(argv[2]), '"echo -n some text"')
|
eq(ffi.string(argv[2]), '"echo -n some text"')
|
||||||
@ -163,8 +154,7 @@ describe('shell functions', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('with empty shellxquote/shellxescape', function()
|
itp('with empty shellxquote/shellxescape', function()
|
||||||
local argv = ffi.cast('char**', cimported.shell_build_argv(
|
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
|
||||||
to_cstr('echo -n some text'), nil))
|
|
||||||
eq(ffi.string(argv[0]), '/bin/sh')
|
eq(ffi.string(argv[0]), '/bin/sh')
|
||||||
eq(ffi.string(argv[1]), '-c')
|
eq(ffi.string(argv[1]), '-c')
|
||||||
eq(ffi.string(argv[2]), 'echo -n some text')
|
eq(ffi.string(argv[2]), 'echo -n some text')
|
||||||
@ -178,7 +168,9 @@ describe('shell functions', function()
|
|||||||
eq("'foo' '' 'bar'", shell_argv_to_str({ 'foo', '', 'bar' }))
|
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("'/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("'abc def' 'ghi jkl'", shell_argv_to_str({ 'abc def', 'ghi jkl' }))
|
||||||
eq("'/bin/sh' '-c' 'abc def' '"..('x'):rep(225).."...",
|
eq(
|
||||||
shell_argv_to_str({'/bin/sh', '-c', 'abc def', ('x'):rep(999)}))
|
"'/bin/sh' '-c' 'abc def' '" .. ('x'):rep(225) .. '...',
|
||||||
|
shell_argv_to_str({ '/bin/sh', '-c', 'abc def', ('x'):rep(999) })
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -184,7 +184,7 @@ describe('path.c', function()
|
|||||||
|
|
||||||
itp('returns the executable name of an invocation given a relative invocation', 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')
|
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)
|
eq(3, len)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -202,7 +202,7 @@ describe('path.c', function()
|
|||||||
|
|
||||||
itp('does not count arguments to the executable as part of its path', 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')
|
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)
|
eq(3, len)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -212,17 +212,17 @@ describe('path.c', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('is equivalent to path_tail when args do not contain a path separator', function()
|
itp('is equivalent to path_tail when args do not contain a path separator', function()
|
||||||
local ptail = 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)
|
neq(NULL, ptail)
|
||||||
local tail = ffi.string(ptail)
|
local tail = ffi.string(ptail)
|
||||||
local invk, _ = invocation_path_tail("a/b/c x y z")
|
local invk, _ = invocation_path_tail('a/b/c x y z')
|
||||||
eq(tail, ffi.string(invk))
|
eq(tail, ffi.string(invk))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('is not equivalent to path_tail when args contain a path separator', function()
|
itp('is not equivalent to path_tail when args contain a path separator', function()
|
||||||
local ptail = 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)
|
neq(NULL, ptail)
|
||||||
local invk, _ = invocation_path_tail("a/b/c x y/z")
|
local invk, _ = invocation_path_tail('a/b/c x y/z')
|
||||||
neq((ffi.string(ptail)), (ffi.string(invk)))
|
neq((ffi.string(ptail)), (ffi.string(invk)))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -334,7 +334,7 @@ describe('path.c path_guess_exepath', function()
|
|||||||
local name = 'cat' -- Some executable in $PATH.
|
local name = 'cat' -- Some executable in $PATH.
|
||||||
local bufsize = 255
|
local bufsize = 255
|
||||||
local buf = cstr(bufsize, '')
|
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.os_setenv('PATH', insane_path, true)
|
||||||
cimp.path_guess_exepath(name, buf, bufsize)
|
cimp.path_guess_exepath(name, buf, bufsize)
|
||||||
@ -356,7 +356,7 @@ end)
|
|||||||
|
|
||||||
describe('path.c', function()
|
describe('path.c', function()
|
||||||
setup(function()
|
setup(function()
|
||||||
mkdir('unit-test-directory');
|
mkdir('unit-test-directory')
|
||||||
io.open('unit-test-directory/test.file', 'w'):close()
|
io.open('unit-test-directory/test.file', 'w'):close()
|
||||||
|
|
||||||
-- Since the tests are executed, they are called by an executable. We use
|
-- Since the tests are executed, they are called by an executable. We use
|
||||||
@ -441,7 +441,9 @@ describe('path.c', function()
|
|||||||
eq(OK, result)
|
eq(OK, result)
|
||||||
end)
|
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()
|
local old_dir = luv.cwd()
|
||||||
luv.chdir('..')
|
luv.chdir('..')
|
||||||
local expected = luv.cwd() .. '/test.file'
|
local expected = luv.cwd() .. '/test.file'
|
||||||
@ -452,7 +454,8 @@ describe('path.c', function()
|
|||||||
local buf, result = vim_FullName(filename, buflen, do_expand)
|
local buf, result = vim_FullName(filename, buflen, do_expand)
|
||||||
eq(expected, ffi.string(buf))
|
eq(expected, ffi.string(buf))
|
||||||
eq(OK, result)
|
eq(OK, result)
|
||||||
end)
|
end
|
||||||
|
)
|
||||||
|
|
||||||
itp('just copies the path if it is already absolute and force=0', function()
|
itp('just copies the path if it is already absolute and force=0', function()
|
||||||
local absolute_path = '/absolute/path'
|
local absolute_path = '/absolute/path'
|
||||||
@ -544,8 +547,12 @@ describe('path.c', function()
|
|||||||
return ffi.string(c_file)
|
return ffi.string(c_file)
|
||||||
end
|
end
|
||||||
|
|
||||||
before_each(function() mkdir('CamelCase') end)
|
before_each(function()
|
||||||
after_each(function() luv.fs_rmdir('CamelCase') end)
|
mkdir('CamelCase')
|
||||||
|
end)
|
||||||
|
after_each(function()
|
||||||
|
luv.fs_rmdir('CamelCase')
|
||||||
|
end)
|
||||||
|
|
||||||
if ffi.os == 'Windows' or ffi.os == 'OSX' then
|
if ffi.os == 'Windows' or ffi.os == 'OSX' then
|
||||||
itp('Corrects the case of file names in Mac and Windows', function()
|
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 path1 = cstr(100, 'path1')
|
||||||
local to_append = to_cstr('path2')
|
local to_append = to_cstr('path2')
|
||||||
eq(OK, (cimp.append_path(path1, to_append, 100)))
|
eq(OK, (cimp.append_path(path1, to_append, 100)))
|
||||||
eq("path1/path2", (ffi.string(path1)))
|
eq('path1/path2', (ffi.string(path1)))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('joins given paths without adding an unnecessary slash', function()
|
itp('joins given paths without adding an unnecessary slash', function()
|
||||||
local path1 = cstr(100, 'path1/')
|
local path1 = cstr(100, 'path1/')
|
||||||
local to_append = to_cstr('path2')
|
local to_append = to_cstr('path2')
|
||||||
eq(OK, cimp.append_path(path1, to_append, 100))
|
eq(OK, cimp.append_path(path1, to_append, 100))
|
||||||
eq("path1/path2", (ffi.string(path1)))
|
eq('path1/path2', (ffi.string(path1)))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('fails and uses filename if there is not enough space left for to_append', function()
|
itp('fails and uses filename if there is not enough space left for to_append', function()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
-- helps managing loading different headers into the LuaJIT ffi. Untested on
|
-- helps managing loading different headers into the LuaJIT ffi. Untested on
|
||||||
-- windows, will probably need quite a bit of adjustment to run there.
|
-- 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 global_helpers = require('test.helpers')
|
||||||
|
|
||||||
local argss_to_cmd = global_helpers.argss_to_cmd
|
local argss_to_cmd = global_helpers.argss_to_cmd
|
||||||
@ -12,37 +12,37 @@ local repeated_read_cmd = global_helpers.repeated_read_cmd
|
|||||||
--- @type Compiler[]
|
--- @type Compiler[]
|
||||||
local ccs = {}
|
local ccs = {}
|
||||||
|
|
||||||
local env_cc = os.getenv("CC")
|
local env_cc = os.getenv('CC')
|
||||||
if env_cc then
|
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
|
end
|
||||||
|
|
||||||
if ffi.os == "Windows" then
|
if ffi.os == 'Windows' then
|
||||||
table.insert(ccs, {path = {"cl"}, type = "msvc"})
|
table.insert(ccs, { path = { 'cl' }, type = 'msvc' })
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(ccs, {path = {"/usr/bin/env", "cc"}, 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' }, type = 'gcc' })
|
||||||
table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.9"}, 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.8' }, type = 'gcc' })
|
||||||
table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.7"}, 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', 'clang' }, type = 'clang' })
|
||||||
table.insert(ccs, {path = {"/usr/bin/env", "icc"}, type = "gcc"})
|
table.insert(ccs, { path = { '/usr/bin/env', 'icc' }, type = 'gcc' })
|
||||||
|
|
||||||
-- parse Makefile format dependencies into a Lua table
|
-- parse Makefile format dependencies into a Lua table
|
||||||
--- @param deps string
|
--- @param deps string
|
||||||
--- @return string[]
|
--- @return string[]
|
||||||
local function parse_make_deps(deps)
|
local function parse_make_deps(deps)
|
||||||
-- remove line breaks and line concatenators
|
-- remove line breaks and line concatenators
|
||||||
deps = deps:gsub("\n", ""):gsub("\\", "")
|
deps = deps:gsub('\n', ''):gsub('\\', '')
|
||||||
-- remove the Makefile "target:" element
|
-- remove the Makefile "target:" element
|
||||||
deps = deps:gsub(".+:", "")
|
deps = deps:gsub('.+:', '')
|
||||||
-- remove redundant spaces
|
-- remove redundant spaces
|
||||||
deps = deps:gsub(" +", " ")
|
deps = deps:gsub(' +', ' ')
|
||||||
|
|
||||||
-- split according to token (space in this case)
|
-- split according to token (space in this case)
|
||||||
local headers = {} --- @type string[]
|
local headers = {} --- @type string[]
|
||||||
for token in deps:gmatch("[^%s]+") do
|
for token in deps:gmatch('[^%s]+') do
|
||||||
-- headers[token] = true
|
-- headers[token] = true
|
||||||
headers[#headers + 1] = token
|
headers[#headers + 1] = token
|
||||||
end
|
end
|
||||||
@ -50,9 +50,9 @@ local function parse_make_deps(deps)
|
|||||||
-- resolve path redirections (..) to normalize all paths
|
-- resolve path redirections (..) to normalize all paths
|
||||||
for i, v in ipairs(headers) do
|
for i, v in ipairs(headers) do
|
||||||
-- double dots (..)
|
-- double dots (..)
|
||||||
headers[i] = v:gsub("/[^/%s]+/%.%.", "")
|
headers[i] = v:gsub('/[^/%s]+/%.%.', '')
|
||||||
-- single dot (.)
|
-- single dot (.)
|
||||||
headers[i] = v:gsub("%./", "")
|
headers[i] = v:gsub('%./', '')
|
||||||
end
|
end
|
||||||
|
|
||||||
return headers
|
return headers
|
||||||
@ -80,7 +80,7 @@ local function headerize(headers, global)
|
|||||||
formatted[#formatted + 1] = string.format(fmt, hdr)
|
formatted[#formatted + 1] = string.format(fmt, hdr)
|
||||||
end
|
end
|
||||||
|
|
||||||
return table.concat(formatted, "\n")
|
return table.concat(formatted, '\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @class Gcc
|
--- @class Gcc
|
||||||
@ -160,7 +160,7 @@ function Gcc:dependencies(hdr)
|
|||||||
--- @type string
|
--- @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 out = assert(io.popen(cmd))
|
||||||
local deps = out:read("*a")
|
local deps = out:read('*a')
|
||||||
out:close()
|
out:close()
|
||||||
if deps then
|
if deps then
|
||||||
return parse_make_deps(deps)
|
return parse_make_deps(deps)
|
||||||
@ -174,10 +174,14 @@ function Gcc:filter_standard_defines(defines)
|
|||||||
local pseudoheader_fname = 'tmp_empty_pseudoheader.h'
|
local pseudoheader_fname = 'tmp_empty_pseudoheader.h'
|
||||||
local pseudoheader_file = assert(io.open(pseudoheader_fname, 'w'))
|
local pseudoheader_file = assert(io.open(pseudoheader_fname, 'w'))
|
||||||
pseudoheader_file:close()
|
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.preprocessor_extra_flags,
|
||||||
self.get_defines_extra_flags,
|
self.get_defines_extra_flags,
|
||||||
{pseudoheader_fname}))
|
{ pseudoheader_fname }
|
||||||
|
)
|
||||||
|
)
|
||||||
os.remove(pseudoheader_fname)
|
os.remove(pseudoheader_fname)
|
||||||
self.standard_defines = {} --- @type table<string,true>
|
self.standard_defines = {} --- @type table<string,true>
|
||||||
for line in standard_defines:gmatch('[^\n]+') do
|
for line in standard_defines:gmatch('[^\n]+') do
|
||||||
@ -192,7 +196,7 @@ function Gcc:filter_standard_defines(defines)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return table.concat(ret, "\n")
|
return table.concat(ret, '\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
--- returns a stream representing a preprocessed form of the passed-in headers.
|
--- returns a stream representing a preprocessed form of the passed-in headers.
|
||||||
@ -206,20 +210,29 @@ function Gcc:preprocess(previous_defines, ...)
|
|||||||
local pseudoheader_fname = 'tmp_pseudoheader.h'
|
local pseudoheader_fname = 'tmp_pseudoheader.h'
|
||||||
local pseudoheader_file = assert(io.open(pseudoheader_fname, 'w'))
|
local pseudoheader_file = assert(io.open(pseudoheader_fname, 'w'))
|
||||||
pseudoheader_file:write(previous_defines)
|
pseudoheader_file:write(previous_defines)
|
||||||
pseudoheader_file:write("\n")
|
pseudoheader_file:write('\n')
|
||||||
pseudoheader_file:write(pseudoheader)
|
pseudoheader_file:write(pseudoheader)
|
||||||
pseudoheader_file:flush()
|
pseudoheader_file:flush()
|
||||||
pseudoheader_file:close()
|
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,
|
self.get_defines_extra_flags,
|
||||||
{pseudoheader_fname}))
|
{ pseudoheader_fname }
|
||||||
|
)
|
||||||
|
)
|
||||||
defines = self:filter_standard_defines(defines)
|
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.preprocessor_extra_flags,
|
||||||
self.get_declarations_extra_flags,
|
self.get_declarations_extra_flags,
|
||||||
{pseudoheader_fname}))
|
{ pseudoheader_fname }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
os.remove(pseudoheader_fname)
|
os.remove(pseudoheader_fname)
|
||||||
|
|
||||||
@ -233,7 +246,7 @@ end
|
|||||||
--- @return Gcc?
|
--- @return Gcc?
|
||||||
local function find_best_cc(compilers)
|
local function find_best_cc(compilers)
|
||||||
for _, meta in pairs(compilers) do
|
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()
|
version:close()
|
||||||
if version then
|
if version then
|
||||||
return Gcc:new({ path = meta.path })
|
return Gcc:new({ path = meta.path })
|
||||||
|
@ -10,11 +10,11 @@ local prof = cimport('./src/nvim/profile.h')
|
|||||||
|
|
||||||
local function split(inputstr, sep)
|
local function split(inputstr, sep)
|
||||||
if sep == nil then
|
if sep == nil then
|
||||||
sep = "%s"
|
sep = '%s'
|
||||||
end
|
end
|
||||||
|
|
||||||
local t, i = {}, 1
|
local t, i = {}, 1
|
||||||
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
|
for str in string.gmatch(inputstr, '([^' .. sep .. ']+)') do
|
||||||
t[i] = str
|
t[i] = str
|
||||||
i = i + 1
|
i = i + 1
|
||||||
end
|
end
|
||||||
@ -23,8 +23,8 @@ local function split(inputstr, sep)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function trim(s)
|
local function trim(s)
|
||||||
local from = s:match"^%s*()"
|
local from = s:match '^%s*()'
|
||||||
return from > #s and "" or s:match(".*%S", from)
|
return from > #s and '' or s:match('.*%S', from)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function starts(str, start)
|
local function starts(str, start)
|
||||||
@ -34,25 +34,33 @@ end
|
|||||||
local function cmp_assert(v1, v2, op, opstr)
|
local function cmp_assert(v1, v2, op, opstr)
|
||||||
local res = op(v1, v2)
|
local res = op(v1, v2)
|
||||||
if res == false then
|
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
|
end
|
||||||
assert.is_true(res)
|
assert.is_true(res)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function lt(a, b) -- luacheck: ignore
|
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
|
end
|
||||||
|
|
||||||
local function lte(a, b) -- luacheck: ignore
|
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
|
end
|
||||||
|
|
||||||
local function gt(a, b) -- luacheck: ignore
|
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
|
end
|
||||||
|
|
||||||
local function gte(a, b)
|
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
|
end
|
||||||
|
|
||||||
-- missing functions:
|
-- missing functions:
|
||||||
@ -61,21 +69,43 @@ end
|
|||||||
-- profile_set_wait
|
-- profile_set_wait
|
||||||
-- profile_sub_wait
|
-- profile_sub_wait
|
||||||
describe('profiling related functions', function()
|
describe('profiling related functions', function()
|
||||||
local function profile_start() return prof.profile_start() end
|
local function profile_start()
|
||||||
local function profile_end(t) return prof.profile_end(t) end
|
return prof.profile_start()
|
||||||
local function profile_zero() return prof.profile_zero() end
|
end
|
||||||
local function profile_setlimit(ms) return prof.profile_setlimit(ms) end
|
local function profile_end(t)
|
||||||
local function profile_passed_limit(t) return prof.profile_passed_limit(t) end
|
return prof.profile_end(t)
|
||||||
local function profile_add(t1, t2) return prof.profile_add(t1, t2) end
|
end
|
||||||
local function profile_sub(t1, t2) return prof.profile_sub(t1, t2) end
|
local function profile_zero()
|
||||||
local function profile_divide(t, cnt) return prof.profile_divide(t, cnt) end
|
return prof.profile_zero()
|
||||||
local function profile_cmp(t1, t2) return prof.profile_cmp(t1, t2) end
|
end
|
||||||
local function profile_equal(t1, t2) return prof.profile_equal(t1, t2) end
|
local function profile_setlimit(ms)
|
||||||
local function profile_msg(t) return ffi.string(prof.profile_msg(t)) end
|
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 function toseconds(t) -- luacheck: ignore
|
||||||
local str = trim(profile_msg(t))
|
local str = trim(profile_msg(t))
|
||||||
local spl = split(str, ".")
|
local spl = split(str, '.')
|
||||||
local s, us = spl[1], spl[2]
|
local s, us = spl[1], spl[2]
|
||||||
return tonumber(s) + tonumber(us) / 1000000
|
return tonumber(s) + tonumber(us) / 1000000
|
||||||
end
|
end
|
||||||
@ -199,14 +229,14 @@ describe('profiling related functions', function()
|
|||||||
describe('profile_msg', function()
|
describe('profile_msg', function()
|
||||||
itp('prints the zero time as 0.00000', function()
|
itp('prints the zero time as 0.00000', function()
|
||||||
local str = trim(profile_msg(profile_zero()))
|
local str = trim(profile_msg(profile_zero()))
|
||||||
eq(str, "0.000000")
|
eq(str, '0.000000')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('prints the time passed, in seconds.microsends', function()
|
itp('prints the time passed, in seconds.microsends', function()
|
||||||
local start = profile_start()
|
local start = profile_start()
|
||||||
local endt = profile_end(start)
|
local endt = profile_end(start)
|
||||||
local str = trim(profile_msg(endt))
|
local str = trim(profile_msg(endt))
|
||||||
local spl = split(str, ".")
|
local spl = split(str, '.')
|
||||||
|
|
||||||
-- string has two parts (before dot and after dot)
|
-- string has two parts (before dot and after dot)
|
||||||
eq(2, #spl)
|
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
|
-- 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)
|
-- 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
|
-- more or less the same goes for the microsecond part, if it doesn't
|
||||||
-- start with 0, it's too slow.
|
-- start with 0, it's too slow.
|
||||||
assert.is_true(starts(us, "0"))
|
assert.is_true(starts(us, '0'))
|
||||||
end)
|
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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
@ -7,7 +7,7 @@ local cstr = helpers.cstr
|
|||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
local child_call_once = helpers.child_call_once
|
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()
|
describe('rbuffer functions', function()
|
||||||
local capacity = 16
|
local capacity = 16
|
||||||
@ -187,8 +187,19 @@ describe('rbuffer functions', function()
|
|||||||
read(10)
|
read(10)
|
||||||
write('long string')
|
write('long string')
|
||||||
collect_chars()
|
collect_chars()
|
||||||
eq({{'l', 0}, {'o', 1}, {'n', 2}, {'g', 3}, {' ', 4}, {'s', 5},
|
eq({
|
||||||
{'t', 6}, {'r', 7}, {'i', 8}, {'n', 9}, {'g', 10}}, chars)
|
{ '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)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -218,8 +229,19 @@ describe('rbuffer functions', function()
|
|||||||
read(10)
|
read(10)
|
||||||
write('long string')
|
write('long string')
|
||||||
collect_chars()
|
collect_chars()
|
||||||
eq({{'g', 10}, {'n', 9}, {'i', 8}, {'r', 7}, {'t', 6}, {'s', 5},
|
eq({
|
||||||
{' ', 4}, {'g', 3}, {'n', 2}, {'o', 1}, {'l', 0}}, chars)
|
{ '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)
|
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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
local eq = helpers.eq
|
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 globals = helpers.cimport('./src/nvim/globals.h')
|
||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
|
|
||||||
itp('pat_has_uppercase', function()
|
itp('pat_has_uppercase', function()
|
||||||
-- works on empty string
|
-- works on empty string
|
||||||
eq(false, search.pat_has_uppercase(to_cstr("")))
|
eq(false, search.pat_has_uppercase(to_cstr('')))
|
||||||
|
|
||||||
-- works with utf uppercase
|
-- works with utf uppercase
|
||||||
eq(false, search.pat_has_uppercase(to_cstr("ä")))
|
eq(false, search.pat_has_uppercase(to_cstr('ä')))
|
||||||
eq(true, search.pat_has_uppercase(to_cstr("Ä")))
|
eq(true, search.pat_has_uppercase(to_cstr('Ä')))
|
||||||
eq(true, search.pat_has_uppercase(to_cstr("äaÅ")))
|
eq(true, search.pat_has_uppercase(to_cstr('äaÅ')))
|
||||||
|
|
||||||
-- works when pat ends with backslash
|
-- works when pat ends with backslash
|
||||||
eq(false, search.pat_has_uppercase(to_cstr("\\")))
|
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('ab$\\')))
|
||||||
|
|
||||||
-- skips escaped characters
|
-- skips escaped characters
|
||||||
eq(false, search.pat_has_uppercase(to_cstr("\\Ab")))
|
eq(false, search.pat_has_uppercase(to_cstr('\\Ab')))
|
||||||
eq(true, search.pat_has_uppercase(to_cstr("\\AU")))
|
eq(true, search.pat_has_uppercase(to_cstr('\\AU')))
|
||||||
|
|
||||||
-- skips _X escaped characters
|
-- skips _X escaped characters
|
||||||
eq(false, search.pat_has_uppercase(to_cstr("\\_Ab")))
|
eq(false, search.pat_has_uppercase(to_cstr('\\_Ab')))
|
||||||
eq(true, search.pat_has_uppercase(to_cstr("\\_AU")))
|
eq(true, search.pat_has_uppercase(to_cstr('\\_AU')))
|
||||||
|
|
||||||
-- skips %X escaped characters
|
-- skips %X escaped characters
|
||||||
eq(false, search.pat_has_uppercase(to_cstr("aa\\%Ab")))
|
eq(false, search.pat_has_uppercase(to_cstr('aa\\%Ab')))
|
||||||
eq(true, search.pat_has_uppercase(to_cstr("aab\\%AU")))
|
eq(true, search.pat_has_uppercase(to_cstr('aab\\%AU')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('search_regcomp', function()
|
describe('search_regcomp', function()
|
||||||
local search_regcomp = function(pat, pat_save, pat_use, options)
|
local search_regcomp = function(pat, pat_save, pat_use, options)
|
||||||
local regmatch = ffi.new("regmmatch_T")
|
local regmatch = ffi.new('regmmatch_T')
|
||||||
local fail = search.search_regcomp(to_cstr(pat), nil, pat_save, pat_use, options, regmatch)
|
local fail = search.search_regcomp(to_cstr(pat), nil, pat_save, pat_use, options, regmatch)
|
||||||
return fail, regmatch
|
return fail, regmatch
|
||||||
end
|
end
|
||||||
@ -45,13 +45,13 @@ describe('search_regcomp', function()
|
|||||||
return helpers.internalize(search.get_search_pat())
|
return helpers.internalize(search.get_search_pat())
|
||||||
end
|
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
|
--crafted to call reverse_text with invalid utf
|
||||||
globals.curwin.w_onebuf_opt.wo_rl = 1
|
globals.curwin.w_onebuf_opt.wo_rl = 1
|
||||||
globals.curwin.w_onebuf_opt.wo_rlc = to_cstr('s')
|
globals.curwin.w_onebuf_opt.wo_rlc = to_cstr('s')
|
||||||
globals.cmdmod.cmod_flags = globals.CMOD_KEEPPATTERNS
|
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(1, fail)
|
||||||
eq("\192a", get_search_pat())
|
eq('\192a', get_search_pat())
|
||||||
end)
|
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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
@ -6,9 +6,9 @@ local get_str = helpers.ffi.string
|
|||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
local NULL = helpers.NULL
|
local NULL = helpers.NULL
|
||||||
|
|
||||||
local buffer = helpers.cimport("./src/nvim/buffer.h")
|
local buffer = helpers.cimport('./src/nvim/buffer.h')
|
||||||
local globals = helpers.cimport("./src/nvim/globals.h")
|
local globals = helpers.cimport('./src/nvim/globals.h')
|
||||||
local stl = helpers.cimport("./src/nvim/statusline.h")
|
local stl = helpers.cimport('./src/nvim/statusline.h')
|
||||||
|
|
||||||
describe('build_stl_str_hl', function()
|
describe('build_stl_str_hl', function()
|
||||||
local buffer_byte_size = 100
|
local buffer_byte_size = 100
|
||||||
@ -22,13 +22,14 @@ describe('build_stl_str_hl', function()
|
|||||||
-- .fillchar The fill character used in the statusline
|
-- .fillchar The fill character used in the statusline
|
||||||
-- .maximum_cell_count The number of cells available in the statusline
|
-- .maximum_cell_count The number of cells available in the statusline
|
||||||
local function build_stl_str_hl(arg)
|
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 pat = arg.pat or ''
|
||||||
local fillchar = arg.fillchar or (' '):byte()
|
local fillchar = arg.fillchar or (' '):byte()
|
||||||
local maximum_cell_count = arg.maximum_cell_count or buffer_byte_size
|
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,
|
output_buffer,
|
||||||
buffer_byte_size,
|
buffer_byte_size,
|
||||||
to_cstr(pat),
|
to_cstr(pat),
|
||||||
@ -38,7 +39,8 @@ describe('build_stl_str_hl', function()
|
|||||||
maximum_cell_count,
|
maximum_cell_count,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL)
|
NULL
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Use this function to simplify testing the comparison between
|
-- 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)
|
-- .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)
|
-- .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
|
-- .fillchar The character that will be used to fill any 'extra' space in the stl
|
||||||
local function statusline_test(description,
|
local function statusline_test(description, statusline_cell_count, input_stl, expected_stl, arg)
|
||||||
statusline_cell_count,
|
|
||||||
input_stl,
|
|
||||||
expected_stl,
|
|
||||||
arg)
|
|
||||||
|
|
||||||
-- arg is the optional parameter
|
-- arg is the optional parameter
|
||||||
-- so we either fill in option with arg or an empty dictionary
|
-- so we either fill in option with arg or an empty dictionary
|
||||||
local option = arg or {}
|
local option = arg or {}
|
||||||
@ -75,9 +72,11 @@ describe('build_stl_str_hl', function()
|
|||||||
buffer.setfname(globals.curbuf, nil, NULL, 1)
|
buffer.setfname(globals.curbuf, nil, NULL, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
local result_cell_count = build_stl_str_hl{pat=input_stl,
|
local result_cell_count = build_stl_str_hl {
|
||||||
|
pat = input_stl,
|
||||||
maximum_cell_count = statusline_cell_count,
|
maximum_cell_count = statusline_cell_count,
|
||||||
fillchar=fillchar}
|
fillchar = fillchar,
|
||||||
|
}
|
||||||
|
|
||||||
eq(expected_stl, get_str(output_buffer, expected_byte_length))
|
eq(expected_stl, get_str(output_buffer, expected_byte_length))
|
||||||
eq(expected_cell_count, result_cell_count)
|
eq(expected_cell_count, result_cell_count)
|
||||||
@ -85,198 +84,383 @@ describe('build_stl_str_hl', function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- expression testing
|
-- expression testing
|
||||||
statusline_test('Should expand expression', 2,
|
statusline_test('Should expand expression', 2, '%!expand(20+1)', '21')
|
||||||
'%!expand(20+1)', '21')
|
statusline_test('Should expand broken expression to itself', 11, '%!expand(20+1', 'expand(20+1')
|
||||||
statusline_test('Should expand broken expression to itself', 11,
|
|
||||||
'%!expand(20+1', 'expand(20+1')
|
|
||||||
|
|
||||||
-- file name testing
|
-- file name testing
|
||||||
statusline_test('should print no file name', 10,
|
statusline_test('should print no file name', 10, '%f', '[No Name]', { expected_cell_count = 9 })
|
||||||
'%f', '[No Name]',
|
statusline_test(
|
||||||
{expected_cell_count=9})
|
'should print the relative file name',
|
||||||
statusline_test('should print the relative file name', 30,
|
30,
|
||||||
'%f', 'test/unit/buffer_spec.lua',
|
'%f',
|
||||||
{file_name='test/unit/buffer_spec.lua', expected_cell_count=25})
|
'test/unit/buffer_spec.lua',
|
||||||
statusline_test('should print the full file name', 40,
|
{ file_name = 'test/unit/buffer_spec.lua', expected_cell_count = 25 }
|
||||||
'%F', '/test/unit/buffer_spec.lua',
|
)
|
||||||
{file_name='/test/unit/buffer_spec.lua', expected_cell_count=26})
|
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
|
-- fillchar testing
|
||||||
statusline_test('should handle `!` as a fillchar', 10,
|
statusline_test(
|
||||||
'abcde%=', 'abcde!!!!!',
|
'should handle `!` as a fillchar',
|
||||||
{fillchar=('!'):byte()})
|
10,
|
||||||
statusline_test('should handle `~` as a fillchar', 10,
|
'abcde%=',
|
||||||
'%=abcde', '~~~~~abcde',
|
'abcde!!!!!',
|
||||||
{fillchar=('~'):byte()})
|
{ fillchar = ('!'):byte() }
|
||||||
statusline_test('should put fillchar `!` in between text', 10,
|
)
|
||||||
'abc%=def', 'abc!!!!def',
|
statusline_test(
|
||||||
{fillchar=('!'):byte()})
|
'should handle `~` as a fillchar',
|
||||||
statusline_test('should put fillchar `~` in between text', 10,
|
10,
|
||||||
'abc%=def', 'abc~~~~def',
|
'%=abcde',
|
||||||
{fillchar=('~'):byte()})
|
'~~~~~abcde',
|
||||||
statusline_test('should put fillchar `━` in between text', 10,
|
{ fillchar = ('~'):byte() }
|
||||||
'abc%=def', 'abc━━━━def',
|
)
|
||||||
{fillchar=0x2501})
|
statusline_test(
|
||||||
statusline_test('should handle zero-fillchar as a space', 10,
|
'should put fillchar `!` in between text',
|
||||||
'abcde%=', 'abcde ',
|
10,
|
||||||
{fillchar=0})
|
'abc%=def',
|
||||||
statusline_test('should print the tail file name', 80,
|
'abc!!!!def',
|
||||||
'%t', 'buffer_spec.lua',
|
{ fillchar = ('!'):byte() }
|
||||||
{file_name='test/unit/buffer_spec.lua', expected_cell_count=15})
|
)
|
||||||
|
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
|
-- standard text testing
|
||||||
statusline_test('should copy plain text', 80,
|
statusline_test(
|
||||||
'this is a test', 'this is a test',
|
'should copy plain text',
|
||||||
{expected_cell_count=14})
|
80,
|
||||||
|
'this is a test',
|
||||||
|
'this is a test',
|
||||||
|
{ expected_cell_count = 14 }
|
||||||
|
)
|
||||||
|
|
||||||
-- line number testing
|
-- line number testing
|
||||||
statusline_test('should print the buffer number', 80,
|
statusline_test('should print the buffer number', 80, '%n', '1', { expected_cell_count = 1 })
|
||||||
'%n', '1',
|
statusline_test(
|
||||||
{expected_cell_count=1})
|
'should print the current line number in the buffer',
|
||||||
statusline_test('should print the current line number in the buffer', 80,
|
80,
|
||||||
'%l', '0',
|
'%l',
|
||||||
{expected_cell_count=1})
|
'0',
|
||||||
statusline_test('should print the number of lines in the buffer', 80,
|
{ expected_cell_count = 1 }
|
||||||
'%L', '1',
|
)
|
||||||
{expected_cell_count=1})
|
statusline_test(
|
||||||
|
'should print the number of lines in the buffer',
|
||||||
|
80,
|
||||||
|
'%L',
|
||||||
|
'1',
|
||||||
|
{ expected_cell_count = 1 }
|
||||||
|
)
|
||||||
|
|
||||||
-- truncation testing
|
-- truncation testing
|
||||||
statusline_test('should truncate when standard text pattern is too long', 10,
|
statusline_test(
|
||||||
'0123456789abcde', '<6789abcde')
|
'should truncate when standard text pattern is too long',
|
||||||
statusline_test('should truncate when using =', 10,
|
10,
|
||||||
'abcdef%=ghijkl', 'abcdef<jkl')
|
'0123456789abcde',
|
||||||
statusline_test('should truncate centered text when using ==', 10,
|
'<6789abcde'
|
||||||
'abcde%=gone%=fghij', 'abcde<ghij')
|
)
|
||||||
statusline_test('should respect the `<` marker', 10,
|
statusline_test('should truncate when using =', 10, 'abcdef%=ghijkl', 'abcdef<jkl')
|
||||||
'abc%<defghijkl', 'abc<ghijkl')
|
statusline_test(
|
||||||
statusline_test('should truncate at `<` with one `=`, test 1', 10,
|
'should truncate centered text when using ==',
|
||||||
'abc%<def%=ghijklmno', 'abc<jklmno')
|
10,
|
||||||
statusline_test('should truncate at `<` with one `=`, test 2', 10,
|
'abcde%=gone%=fghij',
|
||||||
'abcdef%=ghijkl%<mno', 'abcdefghi>')
|
'abcde<ghij'
|
||||||
statusline_test('should truncate at `<` with one `=`, test 3', 10,
|
)
|
||||||
'abc%<def%=ghijklmno', 'abc<jklmno')
|
statusline_test('should respect the `<` marker', 10, 'abc%<defghijkl', 'abc<ghijkl')
|
||||||
statusline_test('should truncate at `<` with one `=`, test 4', 10,
|
statusline_test(
|
||||||
'abc%<def%=ghij', 'abcdefghij')
|
'should truncate at `<` with one `=`, test 1',
|
||||||
statusline_test('should truncate at `<` with one `=`, test 4', 10,
|
10,
|
||||||
'abc%<def%=ghijk', 'abc<fghijk')
|
'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,
|
statusline_test(
|
||||||
'ab%<cdef%=g%=h%=ijk', 'ab<efghijk')
|
'should truncate at `<` with many `=`, test 4',
|
||||||
|
10,
|
||||||
|
'ab%<cdef%=g%=h%=ijk',
|
||||||
|
'ab<efghijk'
|
||||||
|
)
|
||||||
|
|
||||||
statusline_test('should truncate at the first `<`', 10,
|
statusline_test('should truncate at the first `<`', 10, 'abc%<def%<ghijklm', 'abc<hijklm')
|
||||||
'abc%<def%<ghijklm', 'abc<hijklm')
|
|
||||||
|
|
||||||
statusline_test('should ignore trailing %', 3, 'abc%', 'abc')
|
statusline_test('should ignore trailing %', 3, 'abc%', 'abc')
|
||||||
|
|
||||||
-- alignment testing with fillchar
|
-- alignment testing with fillchar
|
||||||
local function statusline_test_align(description,
|
local function statusline_test_align(
|
||||||
|
description,
|
||||||
statusline_cell_count,
|
statusline_cell_count,
|
||||||
input_stl,
|
input_stl,
|
||||||
expected_stl,
|
expected_stl,
|
||||||
arg)
|
arg
|
||||||
|
)
|
||||||
arg = arg or {}
|
arg = arg or {}
|
||||||
statusline_test(description .. ' without fillchar',
|
statusline_test(
|
||||||
statusline_cell_count, input_stl, expected_stl:gsub('%~', ' '), arg)
|
description .. ' without fillchar',
|
||||||
|
statusline_cell_count,
|
||||||
|
input_stl,
|
||||||
|
expected_stl:gsub('%~', ' '),
|
||||||
|
arg
|
||||||
|
)
|
||||||
arg.fillchar = ('!'):byte()
|
arg.fillchar = ('!'):byte()
|
||||||
statusline_test(description .. ' with fillchar `!`',
|
statusline_test(
|
||||||
statusline_cell_count, input_stl, expected_stl:gsub('%~', '!'), arg)
|
description .. ' with fillchar `!`',
|
||||||
|
statusline_cell_count,
|
||||||
|
input_stl,
|
||||||
|
expected_stl:gsub('%~', '!'),
|
||||||
|
arg
|
||||||
|
)
|
||||||
arg.fillchar = 0x2501
|
arg.fillchar = 0x2501
|
||||||
statusline_test(description .. ' with fillchar `━`',
|
statusline_test(
|
||||||
statusline_cell_count, input_stl, expected_stl:gsub('%~', '━'), arg)
|
description .. ' with fillchar `━`',
|
||||||
|
statusline_cell_count,
|
||||||
|
input_stl,
|
||||||
|
expected_stl:gsub('%~', '━'),
|
||||||
|
arg
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
statusline_test_align('should right align when using =', 20,
|
statusline_test_align('should right align when using =', 20, 'neo%=vim', 'neo~~~~~~~~~~~~~~vim')
|
||||||
'neo%=vim', 'neo~~~~~~~~~~~~~~vim')
|
statusline_test_align(
|
||||||
statusline_test_align('should, when possible, center text when using %=text%=', 20,
|
'should, when possible, center text when using %=text%=',
|
||||||
'abc%=neovim%=def', 'abc~~~~neovim~~~~def')
|
20,
|
||||||
statusline_test_align('should handle uneven spacing in the buffer when using %=text%=', 20,
|
'abc%=neovim%=def',
|
||||||
'abc%=neo_vim%=def', 'abc~~~neo_vim~~~~def')
|
'abc~~~~neovim~~~~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(
|
||||||
statusline_test_align('should have equal spaces even with longer right side when using =', 20,
|
'should handle uneven spacing in the buffer when using %=text%=',
|
||||||
'a%=test%=longtext', 'a~~~test~~~~longtext')
|
20,
|
||||||
statusline_test_align('should handle an empty left side when using ==', 20,
|
'abc%=neo_vim%=def',
|
||||||
'%=test%=baz', '~~~~~~test~~~~~~~baz')
|
'abc~~~neo_vim~~~~def'
|
||||||
statusline_test_align('should handle an empty right side when using ==', 20,
|
)
|
||||||
'foobar%=test%=', 'foobar~~~~~test~~~~~')
|
statusline_test_align(
|
||||||
statusline_test_align('should handle consecutive empty ==', 20,
|
'should have equal spaces even with non-equal sides when using =',
|
||||||
'%=%=test%=', '~~~~~~~~~~test~~~~~~')
|
20,
|
||||||
statusline_test_align('should handle an = alone', 20,
|
'foobar%=test%=baz',
|
||||||
'%=', '~~~~~~~~~~~~~~~~~~~~')
|
'foobar~~~test~~~~baz'
|
||||||
statusline_test_align('should right align text when it is alone with =', 20,
|
)
|
||||||
'%=foo', '~~~~~~~~~~~~~~~~~foo')
|
statusline_test_align(
|
||||||
statusline_test_align('should left align text when it is alone with =', 20,
|
'should have equal spaces even with longer right side when using =',
|
||||||
'foo%=', 'foo~~~~~~~~~~~~~~~~~')
|
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,
|
statusline_test_align(
|
||||||
'abc%=neovim%=def', 'abc~~~~neovim~~~~~def')
|
'should approximately center text when using %=text%=',
|
||||||
statusline_test_align('should completely fill the buffer when using %=text%=', 21,
|
21,
|
||||||
'abc%=neo_vim%=def', 'abc~~~~neo_vim~~~~def')
|
'abc%=neovim%=def',
|
||||||
statusline_test_align('should have equal spacing even with non-equal sides when using =', 21,
|
'abc~~~~neovim~~~~~def'
|
||||||
'foobar%=test%=baz', 'foobar~~~~test~~~~baz')
|
)
|
||||||
statusline_test_align('should have equal spacing even with longer right side when using =', 21,
|
statusline_test_align(
|
||||||
'a%=test%=longtext', 'a~~~~test~~~~longtext')
|
'should completely fill the buffer when using %=text%=',
|
||||||
statusline_test_align('should handle an empty left side when using ==', 21,
|
21,
|
||||||
'%=test%=baz', '~~~~~~~test~~~~~~~baz')
|
'abc%=neo_vim%=def',
|
||||||
statusline_test_align('should handle an empty right side when using ==', 21,
|
'abc~~~~neo_vim~~~~def'
|
||||||
'foobar%=test%=', 'foobar~~~~~test~~~~~~')
|
)
|
||||||
|
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,
|
statusline_test_align(
|
||||||
'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~ef')
|
'should quadrant the text when using 3 %=',
|
||||||
statusline_test_align('should work well with %t', 40,
|
40,
|
||||||
'%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~right_aligned',
|
'abcd%=n%=eovim%=ef',
|
||||||
{file_name='test/unit/buffer_spec.lua'})
|
'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~ef'
|
||||||
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',
|
statusline_test_align(
|
||||||
{file_name='test/unit/buffer_spec.lua'})
|
'should work well with %t',
|
||||||
statusline_test_align('should work well with %=, %t, %L, and %l', 40,
|
40,
|
||||||
'%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~ 1 ~~~~~~~~~~ 0',
|
'%t%=right_aligned',
|
||||||
{file_name='test/unit/buffer_spec.lua'})
|
'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,
|
statusline_test_align(
|
||||||
'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~~ef')
|
'should quadrant the text when using 3 %=',
|
||||||
statusline_test_align('should work well with %t', 41,
|
41,
|
||||||
'%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~~right_aligned',
|
'abcd%=n%=eovim%=ef',
|
||||||
{file_name='test/unit/buffer_spec.lua'})
|
'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~~ef'
|
||||||
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',
|
statusline_test_align(
|
||||||
{file_name='test/unit/buffer_spec.lua'})
|
'should work well with %t',
|
||||||
statusline_test_align('should work well with %=, %t, %L, and %l', 41,
|
41,
|
||||||
'%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~~ 1 ~~~~~~~~~~ 0',
|
'%t%=right_aligned',
|
||||||
{file_name='test/unit/buffer_spec.lua'})
|
'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')
|
'aaaa~~b~~c~~d~~e~~fg~~hi~~jk~~lmnop~~qrstuv~~~wxyz'
|
||||||
|
)
|
||||||
|
|
||||||
-- stl item testing
|
-- stl item testing
|
||||||
local tabline = ''
|
local tabline = ''
|
||||||
for i = 1, 1000 do
|
for i = 1, 1000 do
|
||||||
tabline = tabline .. (i % 2 == 0 and '%#TabLineSel#' or '%#TabLineFill#') .. tostring(i % 2)
|
tabline = tabline .. (i % 2 == 0 and '%#TabLineSel#' or '%#TabLineFill#') .. tostring(i % 2)
|
||||||
end
|
end
|
||||||
statusline_test('should handle a large amount of any items', 20,
|
statusline_test('should handle a large amount of any items', 20, tabline, '<1010101010101010101') -- Should not show any error
|
||||||
tabline,
|
statusline_test(
|
||||||
'<1010101010101010101') -- Should not show any error
|
'should handle a larger amount of = than stl initial item',
|
||||||
statusline_test('should handle a larger amount of = than stl initial item', 20,
|
20,
|
||||||
('%='):rep(STL_INITIAL_ITEMS * 5),
|
('%='):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),
|
'a' .. ('a'):rep(STL_INITIAL_ITEMS * 5),
|
||||||
'<aaaaaaaaaaaaaaaaaaa') -- Does not show any error
|
'<aaaaaaaaaaaaaaaaaaa'
|
||||||
statusline_test('should handle many extra characters and flags', 20,
|
) -- Does not show any error
|
||||||
|
statusline_test(
|
||||||
|
'should handle many extra characters and flags',
|
||||||
|
20,
|
||||||
'a' .. ('%=a'):rep(STL_INITIAL_ITEMS * 2),
|
'a' .. ('%=a'):rep(STL_INITIAL_ITEMS * 2),
|
||||||
'a<aaaaaaaaaaaaaaaaaa') -- Should not show any error
|
'a<aaaaaaaaaaaaaaaaaa'
|
||||||
|
) -- Should not show any error
|
||||||
|
|
||||||
-- multi-byte testing
|
-- multi-byte testing
|
||||||
statusline_test('should handle multibyte characters', 10,
|
statusline_test('should handle multibyte characters', 10, 'Ĉ%=x', 'Ĉ x')
|
||||||
'Ĉ%=x', 'Ĉ x')
|
statusline_test(
|
||||||
statusline_test('should handle multibyte characters and different fillchars', 10,
|
'should handle multibyte characters and different fillchars',
|
||||||
'Ą%=mid%=end', 'Ą@mid@@end',
|
10,
|
||||||
{fillchar=('@'):byte()})
|
'Ą%=mid%=end',
|
||||||
|
'Ą@mid@@end',
|
||||||
|
{ fillchar = ('@'):byte() }
|
||||||
|
)
|
||||||
|
|
||||||
-- escaping % testing
|
-- escaping % testing
|
||||||
statusline_test('should handle escape of %', 4, 'abc%%', 'abc%')
|
statusline_test('should handle escape of %', 4, 'abc%%', 'abc%')
|
||||||
statusline_test('case where escaped % does not fit', 3, 'abc%%abcabc', '<bc')
|
statusline_test('case where escaped % does not fit', 3, 'abc%%abcabc', '<bc')
|
||||||
statusline_test('escaped % is first', 1, '%%', '%')
|
statusline_test('escaped % is first', 1, '%%', '%')
|
||||||
|
|
||||||
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 itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local cimport = helpers.cimport
|
local cimport = helpers.cimport
|
||||||
@ -6,8 +6,7 @@ local eq = helpers.eq
|
|||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
|
|
||||||
local strings = cimport('stdlib.h', './src/nvim/strings.h',
|
local strings = cimport('stdlib.h', './src/nvim/strings.h', './src/nvim/memory.h')
|
||||||
'./src/nvim/memory.h')
|
|
||||||
|
|
||||||
describe('vim_strsave_escaped()', function()
|
describe('vim_strsave_escaped()', function()
|
||||||
local vim_strsave_escaped = function(s, chars)
|
local vim_strsave_escaped = function(s, chars)
|
||||||
@ -148,14 +147,30 @@ describe('vim_snprintf()', function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function i(n) return ffi.cast('int', n) end
|
local function i(n)
|
||||||
local function l(n) return ffi.cast('long', n) end
|
return ffi.cast('int', n)
|
||||||
local function ll(n) return ffi.cast('long long', n) end
|
end
|
||||||
local function z(n) return ffi.cast('ptrdiff_t', n) end
|
local function l(n)
|
||||||
local function u(n) return ffi.cast('unsigned', n) end
|
return ffi.cast('long', n)
|
||||||
local function ul(n) return ffi.cast('unsigned long', n) end
|
end
|
||||||
local function ull(n) return ffi.cast('unsigned long long', n) end
|
local function ll(n)
|
||||||
local function uz(n) return ffi.cast('size_t', n) end
|
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()
|
itp('truncation', function()
|
||||||
for bsize = 0, 14 do
|
for bsize = 0, 14 do
|
||||||
@ -239,42 +254,44 @@ describe('strcase_save()' , function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
itp('decodes overlong encoded characters.', function()
|
itp('decodes overlong encoded characters.', function()
|
||||||
eq("A", strcase_save("\xc1\x81", true))
|
eq('A', strcase_save('\xc1\x81', true))
|
||||||
eq("a", strcase_save("\xc1\x81", false))
|
eq('a', strcase_save('\xc1\x81', false))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe("reverse_text", function()
|
describe('reverse_text', function()
|
||||||
local reverse_text = function(str)
|
local reverse_text = function(str)
|
||||||
return helpers.internalize(strings.reverse_text(to_cstr(str)))
|
return helpers.internalize(strings.reverse_text(to_cstr(str)))
|
||||||
end
|
end
|
||||||
|
|
||||||
itp("handles empty string", function()
|
itp('handles empty string', function()
|
||||||
eq("", reverse_text(""))
|
eq('', reverse_text(''))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp("handles simple cases", function()
|
itp('handles simple cases', function()
|
||||||
eq("a", reverse_text("a"))
|
eq('a', reverse_text('a'))
|
||||||
eq("ba", reverse_text("ab"))
|
eq('ba', reverse_text('ab'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp("handles multibyte characters", function()
|
itp('handles multibyte characters', function()
|
||||||
eq("bα", reverse_text("αb"))
|
eq('bα', reverse_text('αb'))
|
||||||
eq("Yötön yö", reverse_text("öy nötöY"))
|
eq('Yötön yö', reverse_text('öy nötöY'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp("handles combining chars", function()
|
itp('handles combining chars', function()
|
||||||
local utf8_COMBINING_RING_ABOVE = "\204\138"
|
local utf8_COMBINING_RING_ABOVE = '\204\138'
|
||||||
local utf8_COMBINING_RING_BELOW = "\204\165"
|
local utf8_COMBINING_RING_BELOW = '\204\165'
|
||||||
eq("bba" .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. "aa",
|
eq(
|
||||||
reverse_text("aaa" .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. "bb"))
|
'bba' .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. 'aa',
|
||||||
|
reverse_text('aaa' .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. 'bb')
|
||||||
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp("treats invalid utf as separate characters", function()
|
itp('treats invalid utf as separate characters', function()
|
||||||
eq("\192ba", reverse_text("ab\192"))
|
eq('\192ba', reverse_text('ab\192'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp("treats an incomplete utf continuation sequence as valid", function()
|
itp('treats an incomplete utf continuation sequence as valid', function()
|
||||||
eq("\194ba", reverse_text("ab\194"))
|
eq('\194ba', reverse_text('ab\194'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -39,7 +39,6 @@ child_call_once(function()
|
|||||||
undo.u_compute_hash(file_buffer, buffer_hash)
|
undo.u_compute_hash(file_buffer, buffer_hash)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
describe('u_write_undo', function()
|
describe('u_write_undo', function()
|
||||||
setup(function()
|
setup(function()
|
||||||
mkdir('unit-test-directory')
|
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()
|
itp('writes an undo file to undodir given a buffer and hash', function()
|
||||||
u_write_undo(nil, false, file_buffer, buffer_hash)
|
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 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)
|
neq(undo_file, nil)
|
||||||
local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
|
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)
|
end)
|
||||||
|
|
||||||
itp('writes a correctly-named undo file to undodir given a name, buffer, and hash', function()
|
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)
|
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)
|
neq(undo_file, nil)
|
||||||
local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
|
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()
|
itp('writes the undofile with the same permissions as the original file', function()
|
||||||
-- Create Test file and set permissions
|
-- Create Test file and set permissions
|
||||||
local test_file_name = "./test.file"
|
local test_file_name = './test.file'
|
||||||
local test_permission_file = io.open(test_file_name, "w")
|
local test_permission_file = io.open(test_file_name, 'w')
|
||||||
test_permission_file:write("testing permissions")
|
test_permission_file:write('testing permissions')
|
||||||
test_permission_file:close()
|
test_permission_file:close()
|
||||||
local test_permissions = luv.fs_stat(test_file_name).mode
|
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()
|
itp('writes an undofile only readable by the user if the buffer is unnamed', function()
|
||||||
local correct_permissions = 33152
|
local correct_permissions = 33152
|
||||||
local undo_file_name = "test.undo"
|
local undo_file_name = 'test.undo'
|
||||||
|
|
||||||
-- Create vim buffer
|
-- Create vim buffer
|
||||||
file_buffer = buffer.buflist_new(nil, nil, 1, buffer.BLN_LISTED)
|
file_buffer = buffer.buflist_new(nil, nil, 1, buffer.BLN_LISTED)
|
||||||
@ -149,7 +148,7 @@ describe('u_write_undo', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('forces writing undo file for :wundo! command', function()
|
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
|
-- 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))
|
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)
|
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
|
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 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
|
if existing_file then
|
||||||
existing_file:close()
|
existing_file:close()
|
||||||
os.remove(correct_name)
|
os.remove(correct_name)
|
||||||
end
|
end
|
||||||
u_write_undo(nil, false, file_buffer, buffer_hash)
|
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)
|
eq(undo_file, nil)
|
||||||
end)
|
end)
|
||||||
|
@ -83,24 +83,23 @@ local function eltkn2lua(pstate, tkn)
|
|||||||
type = conv_eltkn_type(tkn.type),
|
type = conv_eltkn_type(tkn.type),
|
||||||
}
|
}
|
||||||
pstate_set_str(pstate, tkn.start, tkn.len, ret)
|
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'
|
ret.error = '#str /= len'
|
||||||
end
|
end
|
||||||
if ret.type == 'Comparison' then
|
if ret.type == 'Comparison' then
|
||||||
ret.data = {
|
ret.data = {
|
||||||
type = conv_cmp_type(tkn.data.cmp.type),
|
type = conv_cmp_type(tkn.data.cmp.type),
|
||||||
ccs = conv_ccs(tkn.data.cmp.ccs),
|
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
|
elseif ret.type == 'Multiplication' then
|
||||||
ret.data = { type = conv_enum(eltkn_mul_type_tab, tkn.data.mul.type) }
|
ret.data = { type = conv_enum(eltkn_mul_type_tab, tkn.data.mul.type) }
|
||||||
elseif bracket_types[ret.type] then
|
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
|
elseif ret.type == 'Register' then
|
||||||
ret.data = { name = intchar2lua(tkn.data.reg.name) }
|
ret.data = { name = intchar2lua(tkn.data.reg.name) }
|
||||||
elseif (ret.type == 'SingleQuotedString'
|
elseif ret.type == 'SingleQuotedString' or ret.type == 'DoubleQuotedString' then
|
||||||
or ret.type == 'DoubleQuotedString') then
|
ret.data = { closed = not not tkn.data.str.closed }
|
||||||
ret.data = { closed = (not not tkn.data.str.closed) }
|
|
||||||
elseif ret.type == 'Option' then
|
elseif ret.type == 'Option' then
|
||||||
ret.data = {
|
ret.data = {
|
||||||
scope = conv_enum(eltkn_opt_scope_tab, tkn.data.opt.scope),
|
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
|
elseif ret.type == 'PlainIdentifier' then
|
||||||
ret.data = {
|
ret.data = {
|
||||||
scope = intchar2lua(tkn.data.var.scope),
|
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
|
elseif ret.type == 'Number' then
|
||||||
ret.data = {
|
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),
|
base = tonumber(tkn.data.num.base),
|
||||||
}
|
}
|
||||||
ret.data.val = tonumber(tkn.data.num.is_float
|
ret.data.val =
|
||||||
and tkn.data.num.val.floating
|
tonumber(tkn.data.num.is_float and tkn.data.num.val.floating or tkn.data.num.val.integer)
|
||||||
or tkn.data.num.val.integer)
|
|
||||||
elseif ret.type == 'Assignment' then
|
elseif ret.type == 'Assignment' then
|
||||||
ret.data = { type = conv_expr_asgn_type(tkn.data.ass.type) }
|
ret.data = { type = conv_expr_asgn_type(tkn.data.ass.type) }
|
||||||
elseif ret.type == 'Invalid' then
|
elseif ret.type == 'Invalid' then
|
||||||
@ -151,24 +149,31 @@ describe('Expressions lexer', function()
|
|||||||
end
|
end
|
||||||
local function singl_eltkn_test(typ, str, data)
|
local function singl_eltkn_test(typ, str, data)
|
||||||
local pstate = new_pstate({ str })
|
local pstate = new_pstate({ str })
|
||||||
eq({data=data, len=#str, start={col=0, line=0}, str=str, type=typ},
|
eq(
|
||||||
next_eltkn(pstate, flags))
|
{ data = data, len = #str, start = { col = 0, line = 0 }, str = str, type = typ },
|
||||||
|
next_eltkn(pstate, flags)
|
||||||
|
)
|
||||||
check_advance(pstate, #str, 0)
|
check_advance(pstate, #str, 0)
|
||||||
if not (
|
if
|
||||||
|
not (
|
||||||
typ == 'Spacing'
|
typ == 'Spacing'
|
||||||
or (typ == 'Register' and str == '@')
|
or (typ == 'Register' and str == '@')
|
||||||
or ((typ == 'SingleQuotedString' or typ == 'DoubleQuotedString')
|
or ((typ == 'SingleQuotedString' or typ == 'DoubleQuotedString') and not data.closed)
|
||||||
and not data.closed)
|
)
|
||||||
) then
|
then
|
||||||
pstate = new_pstate({ str .. ' ' })
|
pstate = new_pstate({ str .. ' ' })
|
||||||
eq({data=data, len=#str, start={col=0, line=0}, str=str, type=typ},
|
eq(
|
||||||
next_eltkn(pstate, flags))
|
{ data = data, len = #str, start = { col = 0, line = 0 }, str = str, type = typ },
|
||||||
|
next_eltkn(pstate, flags)
|
||||||
|
)
|
||||||
check_advance(pstate, #str, 0)
|
check_advance(pstate, #str, 0)
|
||||||
end
|
end
|
||||||
pstate = new_pstate({ 'x' .. str })
|
pstate = new_pstate({ 'x' .. str })
|
||||||
pstate.pos.col = 1
|
pstate.pos.col = 1
|
||||||
eq({data=data, len=#str, start={col=1, line=0}, str=str, type=typ},
|
eq(
|
||||||
next_eltkn(pstate, flags))
|
{ data = data, len = #str, start = { col = 1, line = 0 }, str = str, type = typ },
|
||||||
|
next_eltkn(pstate, flags)
|
||||||
|
)
|
||||||
check_advance(pstate, #str, 1)
|
check_advance(pstate, #str, 1)
|
||||||
end
|
end
|
||||||
local function scope_test(scope)
|
local function scope_test(scope)
|
||||||
@ -179,15 +184,23 @@ describe('Expressions lexer', function()
|
|||||||
singl_eltkn_test('Comparison', op, { type = cmp_type, inv = false, ccs = 'UseOption' })
|
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', 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', 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',
|
||||||
|
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', 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',
|
||||||
|
inv_op .. '?',
|
||||||
|
{ type = cmp_type, inv = true, ccs = 'IgnoreCase' }
|
||||||
|
)
|
||||||
end
|
end
|
||||||
local function simple_test(pstate_arg, exp_type, exp_len, exp)
|
local function simple_test(pstate_arg, exp_type, exp_len, exp)
|
||||||
local pstate = new_pstate(pstate_arg)
|
local pstate = new_pstate(pstate_arg)
|
||||||
exp = shallowcopy(exp)
|
exp = shallowcopy(exp)
|
||||||
exp.type = exp_type
|
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 }
|
exp.start = { col = 0, line = 0 }
|
||||||
eq(exp, next_eltkn(pstate, flags))
|
eq(exp, next_eltkn(pstate, flags))
|
||||||
end
|
end
|
||||||
@ -211,7 +224,11 @@ describe('Expressions lexer', function()
|
|||||||
singl_eltkn_test('Spacing', ' \t\t \t\t')
|
singl_eltkn_test('Spacing', ' \t\t \t\t')
|
||||||
singl_eltkn_test('Spacing', ' ')
|
singl_eltkn_test('Spacing', ' ')
|
||||||
singl_eltkn_test('Spacing', '\t')
|
singl_eltkn_test('Spacing', '\t')
|
||||||
singl_eltkn_test('Invalid', '\x01\x02\x03', {error='E15: Invalid control character present in input: %.*s'})
|
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', '0123', { is_float = false, base = 8, val = 83 })
|
||||||
singl_eltkn_test('Number', '01234567', { is_float = false, base = 8, val = 342391 })
|
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', '012345678', { is_float = false, base = 10, val = 12345678 })
|
||||||
@ -254,14 +271,14 @@ describe('Expressions lexer', function()
|
|||||||
singl_eltkn_test('Register', '@\r', { name = 13 })
|
singl_eltkn_test('Register', '@\r', { name = 13 })
|
||||||
singl_eltkn_test('Register', '@ ', { name = ' ' })
|
singl_eltkn_test('Register', '@ ', { name = ' ' })
|
||||||
singl_eltkn_test('Register', '@\t', { name = 9 })
|
singl_eltkn_test('Register', '@\t', { name = 9 })
|
||||||
singl_eltkn_test('SingleQuotedString', '\'test', {closed=false})
|
singl_eltkn_test('SingleQuotedString', "'test", { closed = false })
|
||||||
singl_eltkn_test('SingleQuotedString', '\'test\'', {closed=true})
|
singl_eltkn_test('SingleQuotedString', "'test'", { closed = true })
|
||||||
singl_eltkn_test('SingleQuotedString', '\'\'\'\'', {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', '\'\'\'x\'', {closed=true})
|
singl_eltkn_test('SingleQuotedString', "'''x'", { closed = true })
|
||||||
singl_eltkn_test('SingleQuotedString', '\'\'\'', {closed=false})
|
singl_eltkn_test('SingleQuotedString', "'''", { closed = false })
|
||||||
singl_eltkn_test('SingleQuotedString', '\'x\'\'', {closed=false})
|
singl_eltkn_test('SingleQuotedString', "'x''", { 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 = false })
|
||||||
singl_eltkn_test('DoubleQuotedString', '"test"', { closed = true })
|
singl_eltkn_test('DoubleQuotedString', '"test"', { closed = true })
|
||||||
singl_eltkn_test('DoubleQuotedString', '"\\""', { closed = true })
|
singl_eltkn_test('DoubleQuotedString', '"\\""', { closed = true })
|
||||||
@ -282,24 +299,112 @@ describe('Expressions lexer', function()
|
|||||||
singl_eltkn_test('Invalid', '~', { error = 'E15: Unidentified character: %.*s' })
|
singl_eltkn_test('Invalid', '~', { error = 'E15: Unidentified character: %.*s' })
|
||||||
simple_test({ { data = nil, size = 0 } }, 'EOC', 0, { error = 'start.col >= #pstr' })
|
simple_test({ { data = nil, size = 0 } }, 'EOC', 0, { error = 'start.col >= #pstr' })
|
||||||
simple_test({ '' }, '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(
|
||||||
simple_test({'2e5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
{ '2.' },
|
||||||
simple_test({'2.x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
'Number',
|
||||||
simple_test({'2.2.'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
1,
|
||||||
simple_test({'2.0x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
{ 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(
|
||||||
simple_test({'2.0e-'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
{ '2e5' },
|
||||||
simple_test({'2.0e+x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
'Number',
|
||||||
simple_test({'2.0e-x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
1,
|
||||||
simple_test({'2.0e+1a'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
{ 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(
|
||||||
simple_test({'10F'}, 'Number', 2, {data={is_float=false, base=10, val=10}, str='10'})
|
{ '2.x' },
|
||||||
simple_test({'0x0123456789ABCDEFG'}, 'Number', 18, {data={is_float=false, base=16, val=81985529216486895}, str='0x0123456789ABCDEF'})
|
'Number',
|
||||||
simple_test({{data='00', size=2}}, 'Number', 2, {data={is_float=false, base=8, val=0}, str='00'})
|
1,
|
||||||
simple_test({{data='009', size=2}}, 'Number', 2, {data={is_float=false, base=8, val=0}, str='00'})
|
{ data = { is_float = false, base = 10, val = 2 }, str = '2' }
|
||||||
simple_test({{data='01', size=1}}, 'Number', 1, {data={is_float=false, base=10, val=0}, str='0'})
|
)
|
||||||
|
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
|
end
|
||||||
|
|
||||||
local function regular_scope_tests()
|
local function regular_scope_tests()
|
||||||
@ -312,29 +417,104 @@ describe('Expressions lexer', function()
|
|||||||
scope_test('l')
|
scope_test('l')
|
||||||
scope_test('a')
|
scope_test('a')
|
||||||
|
|
||||||
simple_test({'g:'}, 'PlainIdentifier', 2, {data={scope='g', autoload=false}, str='g:'})
|
simple_test(
|
||||||
simple_test({'g:is#foo'}, 'PlainIdentifier', 8, {data={scope='g', autoload=true}, str='g:is#foo'})
|
{ 'g:' },
|
||||||
simple_test({'g:isnot#foo'}, 'PlainIdentifier', 11, {data={scope='g', autoload=true}, str='g:isnot#foo'})
|
'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
|
end
|
||||||
|
|
||||||
local function regular_is_tests()
|
local function regular_is_tests()
|
||||||
comparison_test('is', 'isnot', 'Identical')
|
comparison_test('is', 'isnot', 'Identical')
|
||||||
|
|
||||||
simple_test({'is'}, 'Comparison', 2, {data={type='Identical', inv=false, ccs='UseOption'}, str='is'})
|
simple_test(
|
||||||
simple_test({'isnot'}, 'Comparison', 5, {data={type='Identical', inv=true, ccs='UseOption'}, str='isnot'})
|
{ 'is' },
|
||||||
simple_test({'is?'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='IgnoreCase'}, str='is?'})
|
'Comparison',
|
||||||
simple_test({'isnot?'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='IgnoreCase'}, str='isnot?'})
|
2,
|
||||||
simple_test({'is#'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='MatchCase'}, str='is#'})
|
{ data = { type = 'Identical', inv = false, ccs = 'UseOption' }, 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(
|
||||||
simple_test({'isnot#foo'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='MatchCase'}, str='isnot#'})
|
{ '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
|
end
|
||||||
|
|
||||||
local function regular_number_tests()
|
local function regular_number_tests()
|
||||||
simple_test({'2.0'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
simple_test(
|
||||||
simple_test({'2.0e5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
{ '2.0' },
|
||||||
simple_test({'2.0e+5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
'Number',
|
||||||
simple_test({'2.0e-5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
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
|
end
|
||||||
|
|
||||||
local function regular_eoc_tests()
|
local function regular_eoc_tests()
|
||||||
@ -369,7 +549,12 @@ describe('Expressions lexer', function()
|
|||||||
regular_is_tests()
|
regular_is_tests()
|
||||||
regular_number_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)
|
end)
|
||||||
itp('allows floats', function()
|
itp('allows floats', function()
|
||||||
flags = tonumber(lib.kELFlagAllowFloat)
|
flags = tonumber(lib.kELFlagAllowFloat)
|
||||||
@ -379,20 +564,72 @@ describe('Expressions lexer', function()
|
|||||||
regular_scope_tests()
|
regular_scope_tests()
|
||||||
regular_is_tests()
|
regular_is_tests()
|
||||||
|
|
||||||
simple_test({'2.2'}, 'Number', 3, {data={is_float=true, base=10, val=2.2}, str='2.2'})
|
simple_test(
|
||||||
simple_test({'2.0e5'}, 'Number', 5, {data={is_float=true, base=10, val=2e5}, str='2.0e5'})
|
{ '2.2' },
|
||||||
simple_test({'2.0e+5'}, 'Number', 6, {data={is_float=true, base=10, val=2e5}, str='2.0e+5'})
|
'Number',
|
||||||
simple_test({'2.0e-5'}, 'Number', 6, {data={is_float=true, base=10, val=2e-5}, str='2.0e-5'})
|
3,
|
||||||
simple_test({'2.500000e-5'}, 'Number', 11, {data={is_float=true, base=10, val=2.5e-5}, str='2.500000e-5'})
|
{ data = { is_float = true, base = 10, val = 2.2 }, str = '2.2' }
|
||||||
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(
|
||||||
simple_test({'2.5555e-2'}, 'Number', 9, {data={is_float=true, base=10, val=2.5555e-2}, str='2.5555e-2'})
|
{ '2.0e5' },
|
||||||
simple_test({{data='2.5e-5', size=3}},
|
'Number',
|
||||||
'Number', 3, {data={is_float=true, base=10, val=2.5}, str='2.5'})
|
5,
|
||||||
simple_test({{data='2.5e5', size=4}},
|
{ data = { is_float = true, base = 10, val = 2e5 }, str = '2.0e5' }
|
||||||
'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
|
)
|
||||||
simple_test({{data='2.5e-50', size=6}},
|
simple_test(
|
||||||
'Number', 6, {data={is_float=true, base=10, val=2.5e-5}, str='2.5e-5'})
|
{ '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)
|
end)
|
||||||
itp('treats `is` as an identifier', function()
|
itp('treats `is` as an identifier', function()
|
||||||
flags = tonumber(lib.kELFlagIsNotCmp)
|
flags = tonumber(lib.kELFlagIsNotCmp)
|
||||||
@ -402,14 +639,54 @@ describe('Expressions lexer', function()
|
|||||||
regular_scope_tests()
|
regular_scope_tests()
|
||||||
regular_number_tests()
|
regular_number_tests()
|
||||||
|
|
||||||
simple_test({'is'}, 'PlainIdentifier', 2, {data={scope=0, autoload=false}, str='is'})
|
simple_test(
|
||||||
simple_test({'isnot'}, 'PlainIdentifier', 5, {data={scope=0, autoload=false}, str='isnot'})
|
{ 'is' },
|
||||||
simple_test({'is?'}, 'PlainIdentifier', 2, {data={scope=0, autoload=false}, str='is'})
|
'PlainIdentifier',
|
||||||
simple_test({'isnot?'}, 'PlainIdentifier', 5, {data={scope=0, autoload=false}, str='isnot'})
|
2,
|
||||||
simple_test({'is#'}, 'PlainIdentifier', 3, {data={scope=0, autoload=true}, str='is#'})
|
{ data = { scope = 0, autoload = false }, 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(
|
||||||
simple_test({'isnot#foo'}, 'PlainIdentifier', 9, {data={scope=0, autoload=true}, str='isnot#foo'})
|
{ '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)
|
end)
|
||||||
itp('forbids EOC', function()
|
itp('forbids EOC', function()
|
||||||
flags = tonumber(lib.kELFlagForbidEOC)
|
flags = tonumber(lib.kELFlagForbidEOC)
|
||||||
|
@ -25,8 +25,7 @@ local conv_cmp_type = viml_helpers.conv_cmp_type
|
|||||||
local pstate_set_str = viml_helpers.pstate_set_str
|
local pstate_set_str = viml_helpers.pstate_set_str
|
||||||
local conv_expr_asgn_type = viml_helpers.conv_expr_asgn_type
|
local conv_expr_asgn_type = viml_helpers.conv_expr_asgn_type
|
||||||
|
|
||||||
local lib = cimport('./src/nvim/viml/parser/expressions.h',
|
local lib = cimport('./src/nvim/viml/parser/expressions.h', './src/nvim/syntax.h')
|
||||||
'./src/nvim/syntax.h')
|
|
||||||
|
|
||||||
local alloc_log = alloc_log_new()
|
local alloc_log = alloc_log_new()
|
||||||
|
|
||||||
@ -136,22 +135,18 @@ child_call_once(function()
|
|||||||
-- linking, otherwise it will be created as cleared. So existence
|
-- linking, otherwise it will be created as cleared. So existence
|
||||||
-- of the group is checked here and not in the next pass over
|
-- of the group is checked here and not in the next pass over
|
||||||
-- nvim_hl_defs.
|
-- nvim_hl_defs.
|
||||||
eq(true, not not (nvim_hl_defs[grp_link]
|
eq(true, not not (nvim_hl_defs[grp_link] or predefined_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]))
|
||||||
eq(false, not not (nvim_hl_defs[new_grp]
|
|
||||||
or predefined_hl_defs[new_grp]))
|
|
||||||
nvim_hl_defs[new_grp] = { 'link', grp_link }
|
nvim_hl_defs[new_grp] = { 'link', grp_link }
|
||||||
else
|
else
|
||||||
local new_grp, grp_args = s:match('^(%w+) (.*)')
|
local new_grp, grp_args = s:match('^(%w+) (.*)')
|
||||||
neq(nil, new_grp)
|
neq(nil, new_grp)
|
||||||
eq(false, not not (nvim_hl_defs[new_grp]
|
eq(false, not not (nvim_hl_defs[new_grp] or predefined_hl_defs[new_grp]))
|
||||||
or predefined_hl_defs[new_grp]))
|
|
||||||
nvim_hl_defs[new_grp] = { 'definition', grp_args }
|
nvim_hl_defs[new_grp] = { 'definition', grp_args }
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
if not err then
|
if not err then
|
||||||
msg = format_string(
|
msg = format_string('Error while processing string %s at position %u:\n%s', s, i, msg)
|
||||||
'Error while processing string %s at position %u:\n%s', s, i, msg)
|
|
||||||
error(msg)
|
error(msg)
|
||||||
end
|
end
|
||||||
i = i + 1
|
i = i + 1
|
||||||
@ -185,12 +180,12 @@ local function hls_to_hl_fs(hls)
|
|||||||
local col_shift = col - next_col
|
local col_shift = col - next_col
|
||||||
assert(col_shift >= 0)
|
assert(col_shift >= 0)
|
||||||
next_col = col + #str
|
next_col = col + #str
|
||||||
ret[i] = format_string('hl(%r, %r%s)',
|
ret[i] = format_string(
|
||||||
|
'hl(%r, %r%s)',
|
||||||
group,
|
group,
|
||||||
str,
|
str,
|
||||||
(col_shift == 0
|
(col_shift == 0 and '' or (', %u'):format(col_shift))
|
||||||
and ''
|
)
|
||||||
or (', %u'):format(col_shift)))
|
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
@ -205,9 +200,9 @@ local function format_check(expr, format_check_data, opts)
|
|||||||
dig_len = #opts.funcname + 2
|
dig_len = #opts.funcname + 2
|
||||||
else
|
else
|
||||||
print(format_string('\n_check_parsing(%r, %r, {', opts, expr))
|
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
|
end
|
||||||
local digits = ' --' .. (' '):rep(dig_len - #(' --'))
|
local digits = ' --' .. (' '):rep(dig_len - #' --')
|
||||||
local digits2 = digits:sub(1, -10)
|
local digits2 = digits:sub(1, -10)
|
||||||
for i = 0, #expr - 1 do
|
for i = 0, #expr - 1 do
|
||||||
if i % 10 == 0 then
|
if i % 10 == 0 then
|
||||||
@ -240,10 +235,9 @@ local function format_check(expr, format_check_data, opts)
|
|||||||
diffs[flags] = dictdiff(zdata, v)
|
diffs[flags] = dictdiff(zdata, v)
|
||||||
if diffs[flags] then
|
if diffs[flags] then
|
||||||
if flags == 3 + zflags then
|
if flags == 3 + zflags then
|
||||||
if (dictdiff(format_check_data[1 + zflags],
|
if
|
||||||
format_check_data[3 + zflags]) == nil
|
dictdiff(format_check_data[1 + zflags], format_check_data[3 + zflags]) == nil
|
||||||
or dictdiff(format_check_data[2 + zflags],
|
or dictdiff(format_check_data[2 + zflags], format_check_data[3 + zflags]) == nil
|
||||||
format_check_data[3 + zflags]) == nil)
|
|
||||||
then
|
then
|
||||||
diffs[flags] = nil
|
diffs[flags] = nil
|
||||||
else
|
else
|
||||||
@ -268,7 +262,7 @@ local function format_check(expr, format_check_data, opts)
|
|||||||
end
|
end
|
||||||
if diff.hl_fs then
|
if diff.hl_fs then
|
||||||
print(' hl_fs = ' .. format_luav(diff.hl_fs, ' ', {
|
print(' hl_fs = ' .. format_luav(diff.hl_fs, ' ', {
|
||||||
literal_strings=true
|
literal_strings = true,
|
||||||
}) .. ',')
|
}) .. ',')
|
||||||
end
|
end
|
||||||
print(' },')
|
print(' },')
|
||||||
@ -280,7 +274,9 @@ local function format_check(expr, format_check_data, opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local east_node_type_tab
|
local east_node_type_tab
|
||||||
make_enum_conv_tab(lib, {
|
make_enum_conv_tab(
|
||||||
|
lib,
|
||||||
|
{
|
||||||
'kExprNodeMissing',
|
'kExprNodeMissing',
|
||||||
'kExprNodeOpMissing',
|
'kExprNodeOpMissing',
|
||||||
'kExprNodeTernary',
|
'kExprNodeTernary',
|
||||||
@ -320,7 +316,12 @@ make_enum_conv_tab(lib, {
|
|||||||
'kExprNodeOption',
|
'kExprNodeOption',
|
||||||
'kExprNodeEnvironment',
|
'kExprNodeEnvironment',
|
||||||
'kExprNodeAssignment',
|
'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)
|
local function conv_east_node_type(typ)
|
||||||
return conv_enum(east_node_type_tab, 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)
|
ret_str = ('%u:%u:%s'):format(str.start.line, str.start.col, str.str)
|
||||||
end
|
end
|
||||||
if typ == 'Register' then
|
if typ == 'Register' then
|
||||||
typ = typ .. ('(name=%s)'):format(
|
typ = typ .. ('(name=%s)'):format(tostring(intchar2lua(eastnode.data.reg.name)))
|
||||||
tostring(intchar2lua(eastnode.data.reg.name)))
|
|
||||||
elseif typ == 'PlainIdentifier' then
|
elseif typ == 'PlainIdentifier' then
|
||||||
typ = typ .. ('(scope=%s,ident=%s)'):format(
|
typ = typ
|
||||||
|
.. ('(scope=%s,ident=%s)'):format(
|
||||||
tostring(intchar2lua(eastnode.data.var.scope)),
|
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
|
elseif typ == 'PlainKey' then
|
||||||
typ = typ .. ('(key=%s)'):format(
|
typ = typ
|
||||||
ffi.string(eastnode.data.var.ident, eastnode.data.var.ident_len))
|
.. ('(key=%s)'):format(ffi.string(eastnode.data.var.ident, eastnode.data.var.ident_len))
|
||||||
elseif (typ == 'UnknownFigure' or typ == 'DictLiteral'
|
elseif
|
||||||
or typ == 'CurlyBracesIdentifier' or typ == 'Lambda') then
|
typ == 'UnknownFigure'
|
||||||
typ = typ .. ('(%s)'):format(
|
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_lambda and '\\' or '-')
|
||||||
.. (eastnode.data.fig.type_guesses.allow_dict and 'd' 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
|
elseif typ == 'Comparison' then
|
||||||
typ = typ .. ('(type=%s,inv=%u,ccs=%s)'):format(
|
typ = typ
|
||||||
conv_cmp_type(eastnode.data.cmp.type), eastnode.data.cmp.inv and 1 or 0,
|
.. ('(type=%s,inv=%u,ccs=%s)'):format(
|
||||||
conv_ccs(eastnode.data.cmp.ccs))
|
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
|
elseif typ == 'Integer' then
|
||||||
typ = typ .. ('(val=%u)'):format(tonumber(eastnode.data.num.value))
|
typ = typ .. ('(val=%u)'):format(tonumber(eastnode.data.num.value))
|
||||||
elseif typ == 'Float' then
|
elseif typ == 'Float' then
|
||||||
@ -380,11 +391,13 @@ local function eastnode2lua(pstate, eastnode, checked_nodes)
|
|||||||
typ = ('%s(scope=%s,ident=%s)'):format(
|
typ = ('%s(scope=%s,ident=%s)'):format(
|
||||||
typ,
|
typ,
|
||||||
tostring(intchar2lua(eastnode.data.opt.scope)),
|
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
|
elseif typ == 'Environment' then
|
||||||
typ = ('%s(ident=%s)'):format(
|
typ = ('%s(ident=%s)'):format(
|
||||||
typ,
|
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
|
elseif typ == 'Assignment' then
|
||||||
typ = ('%s(%s)'):format(typ, conv_expr_asgn_type(eastnode.data.ass.type))
|
typ = ('%s(%s)'):format(typ, conv_expr_asgn_type(eastnode.data.ass.type))
|
||||||
end
|
end
|
||||||
@ -433,22 +446,21 @@ local function phl2lua(pstate)
|
|||||||
local ret = {}
|
local ret = {}
|
||||||
for i = 0, (tonumber(pstate.colors.size) - 1) do
|
for i = 0, (tonumber(pstate.colors.size) - 1) do
|
||||||
local chunk = pstate.colors.items[i]
|
local chunk = pstate.colors.items[i]
|
||||||
local chunk_tbl = pstate_set_str(
|
local chunk_tbl = pstate_set_str(pstate, chunk.start, chunk.end_col - chunk.start.col, {
|
||||||
pstate, chunk.start, chunk.end_col - chunk.start.col, {
|
|
||||||
group = ffi.string(chunk.group),
|
group = ffi.string(chunk.group),
|
||||||
})
|
})
|
||||||
ret[i + 1] = ('%s:%u:%u:%s'):format(
|
ret[i + 1] = ('%s:%u:%u:%s'):format(
|
||||||
chunk_tbl.group,
|
chunk_tbl.group,
|
||||||
chunk_tbl.start.line,
|
chunk_tbl.start.line,
|
||||||
chunk_tbl.start.col,
|
chunk_tbl.start.col,
|
||||||
chunk_tbl.str)
|
chunk_tbl.str
|
||||||
|
)
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
describe('Expressions parser', function()
|
describe('Expressions parser', function()
|
||||||
local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs,
|
local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs, nz_flags_exps)
|
||||||
nz_flags_exps)
|
|
||||||
local zflags = opts.flags[1]
|
local zflags = opts.flags[1]
|
||||||
nz_flags_exps = nz_flags_exps or {}
|
nz_flags_exps = nz_flags_exps or {}
|
||||||
local format_check_data = {}
|
local format_check_data = {}
|
||||||
@ -499,8 +511,7 @@ describe('Expressions parser', function()
|
|||||||
alloc_log:check({})
|
alloc_log:check({})
|
||||||
end)
|
end)
|
||||||
if not err then
|
if not err then
|
||||||
msg = format_string('Error while processing test (%r, %u):\n%s',
|
msg = format_string('Error while processing test (%r, %u):\n%s', str, flags, msg)
|
||||||
str, flags, msg)
|
|
||||||
error(msg)
|
error(msg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -514,16 +525,11 @@ describe('Expressions parser', function()
|
|||||||
error(('Unknown group: Nvim%s'):format(group))
|
error(('Unknown group: Nvim%s'):format(group))
|
||||||
end
|
end
|
||||||
local col = next_col + (shift or 0)
|
local col = next_col + (shift or 0)
|
||||||
return (('%s:%u:%u:%s'):format(
|
return (('%s:%u:%u:%s'):format('Nvim' .. group, 0, col, str)), (col + #str)
|
||||||
'Nvim' .. group,
|
|
||||||
0,
|
|
||||||
col,
|
|
||||||
str)), (col + #str)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function fmtn(typ, args, rest)
|
local function fmtn(typ, args, rest)
|
||||||
return ('%s(%s)%s'):format(typ, args, rest)
|
return ('%s(%s)%s'):format(typ, args, rest)
|
||||||
end
|
end
|
||||||
require('test.unit.viml.expressions.parser_tests')(
|
require('test.unit.viml.expressions.parser_tests')(itp, _check_parsing, hl, fmtn)
|
||||||
itp, _check_parsing, hl, fmtn)
|
|
||||||
end)
|
end)
|
||||||
|
@ -142,7 +142,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
len = 2,
|
len = 2,
|
||||||
err = REMOVE_THIS,
|
err = REMOVE_THIS,
|
||||||
ast = {
|
ast = {
|
||||||
'Register(name=a):0:0:@a'
|
'Register(name=a):0:0:@a',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hl_fs = {
|
hl_fs = {
|
||||||
@ -174,7 +174,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
len = 6,
|
len = 6,
|
||||||
err = REMOVE_THIS,
|
err = REMOVE_THIS,
|
||||||
ast = {
|
ast = {
|
||||||
'Register(name=a):0:0: @a'
|
'Register(name=a):0:0: @a',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hl_fs = {
|
hl_fs = {
|
||||||
@ -541,7 +541,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
children = {
|
children = {
|
||||||
{
|
{
|
||||||
'Nested:0:4:(',
|
'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 = {
|
children = {
|
||||||
{
|
{
|
||||||
'Nested:0:4:(',
|
'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('BinaryPlus', '+'),
|
||||||
hl('Register', '@c'),
|
hl('Register', '@c'),
|
||||||
})
|
})
|
||||||
check_parsing(
|
check_parsing('@a + (@b + @c) + @d(@e) + (+@f) + ((+@g(@h))(@j)(@k))(@l)', {--[[
|
||||||
'@a + (@b + @c) + @d(@e) + (+@f) + ((+@g(@h))(@j)(@k))(@l)', {--[[
|
|
||||||
| | | | | | | | || | | || | | ||| || || || ||
|
| | | | | | | | || | | || | | ||| || || || ||
|
||||||
000000000011111111112222222222333333333344444444445555555
|
000000000011111111112222222222333333333344444444445555555
|
||||||
012345678901234567890123456789012345678901234567890123456
|
012345678901234567890123456789012345678901234567890123456
|
||||||
]]
|
]]
|
||||||
ast = {{
|
ast = {
|
||||||
|
{
|
||||||
'BinaryPlus:0:31: +',
|
'BinaryPlus:0:31: +',
|
||||||
children = {
|
children = {
|
||||||
{
|
{
|
||||||
@ -696,7 +696,8 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
},
|
||||||
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('Register', '@a'),
|
hl('Register', '@a'),
|
||||||
hl('BinaryPlus', '+', 1),
|
hl('BinaryPlus', '+', 1),
|
||||||
@ -2851,7 +2852,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
},
|
},
|
||||||
err = {
|
err = {
|
||||||
arg = '{a : b',
|
arg = '{a : b',
|
||||||
msg = 'E723: Missing end of Dictionary \'}\': %.*s',
|
msg = "E723: Missing end of Dictionary '}': %.*s",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('Dict', '{'),
|
hl('Dict', '{'),
|
||||||
@ -3182,7 +3183,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
},
|
},
|
||||||
err = {
|
err = {
|
||||||
arg = '?b',
|
arg = '?b',
|
||||||
msg = 'E109: Missing \':\' after \'?\': %.*s',
|
msg = "E109: Missing ':' after '?': %.*s",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('IdentifierName', 'a'),
|
hl('IdentifierName', 'a'),
|
||||||
@ -3207,7 +3208,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
},
|
},
|
||||||
err = {
|
err = {
|
||||||
arg = '?b:',
|
arg = '?b:',
|
||||||
msg = 'E109: Missing \':\' after \'?\': %.*s',
|
msg = "E109: Missing ':' after '?': %.*s",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('IdentifierName', 'a'),
|
hl('IdentifierName', 'a'),
|
||||||
@ -4840,7 +4841,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
},
|
},
|
||||||
err = {
|
err = {
|
||||||
arg = '[1',
|
arg = '[1',
|
||||||
msg = 'E697: Missing end of List \']\': %.*s',
|
msg = "E697: Missing end of List ']': %.*s",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('List', '['),
|
hl('List', '['),
|
||||||
@ -4848,15 +4849,15 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
itp('works with strings', function()
|
itp('works with strings', function()
|
||||||
check_parsing('\'abc\'', {
|
check_parsing("'abc'", {
|
||||||
-- 01234
|
-- 01234
|
||||||
ast = {
|
ast = {
|
||||||
fmtn('SingleQuotedString', 'val="abc"', ':0:0:\'abc\''),
|
fmtn('SingleQuotedString', 'val="abc"', ":0:0:'abc'"),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('SingleQuote', '\''),
|
hl('SingleQuote', "'"),
|
||||||
hl('SingleQuotedBody', 'abc'),
|
hl('SingleQuotedBody', 'abc'),
|
||||||
hl('SingleQuote', '\''),
|
hl('SingleQuote', "'"),
|
||||||
})
|
})
|
||||||
check_parsing('"abc"', {
|
check_parsing('"abc"', {
|
||||||
-- 01234
|
-- 01234
|
||||||
@ -4868,14 +4869,14 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
hl('DoubleQuotedBody', 'abc'),
|
hl('DoubleQuotedBody', 'abc'),
|
||||||
hl('DoubleQuote', '"'),
|
hl('DoubleQuote', '"'),
|
||||||
})
|
})
|
||||||
check_parsing('\'\'', {
|
check_parsing("''", {
|
||||||
-- 01
|
-- 01
|
||||||
ast = {
|
ast = {
|
||||||
fmtn('SingleQuotedString', 'val=NULL', ':0:0:\'\''),
|
fmtn('SingleQuotedString', 'val=NULL', ":0:0:''"),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('SingleQuote', '\''),
|
hl('SingleQuote', "'"),
|
||||||
hl('SingleQuote', '\''),
|
hl('SingleQuote', "'"),
|
||||||
})
|
})
|
||||||
check_parsing('""', {
|
check_parsing('""', {
|
||||||
-- 01
|
-- 01
|
||||||
@ -4898,17 +4899,17 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
}, {
|
}, {
|
||||||
hl('InvalidDoubleQuote', '"'),
|
hl('InvalidDoubleQuote', '"'),
|
||||||
})
|
})
|
||||||
check_parsing('\'', {
|
check_parsing("'", {
|
||||||
-- 0
|
-- 0
|
||||||
ast = {
|
ast = {
|
||||||
fmtn('SingleQuotedString', 'val=NULL', ':0:0:\''),
|
fmtn('SingleQuotedString', 'val=NULL', ":0:0:'"),
|
||||||
},
|
},
|
||||||
err = {
|
err = {
|
||||||
arg = '\'',
|
arg = "'",
|
||||||
msg = 'E115: Missing single quote: %.*s',
|
msg = 'E115: Missing single quote: %.*s',
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('InvalidSingleQuote', '\''),
|
hl('InvalidSingleQuote', "'"),
|
||||||
})
|
})
|
||||||
check_parsing('"a', {
|
check_parsing('"a', {
|
||||||
-- 01
|
-- 01
|
||||||
@ -4923,71 +4924,71 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
hl('InvalidDoubleQuote', '"'),
|
hl('InvalidDoubleQuote', '"'),
|
||||||
hl('InvalidDoubleQuotedBody', 'a'),
|
hl('InvalidDoubleQuotedBody', 'a'),
|
||||||
})
|
})
|
||||||
check_parsing('\'a', {
|
check_parsing("'a", {
|
||||||
-- 01
|
-- 01
|
||||||
ast = {
|
ast = {
|
||||||
fmtn('SingleQuotedString', 'val="a"', ':0:0:\'a'),
|
fmtn('SingleQuotedString', 'val="a"', ":0:0:'a"),
|
||||||
},
|
},
|
||||||
err = {
|
err = {
|
||||||
arg = '\'a',
|
arg = "'a",
|
||||||
msg = 'E115: Missing single quote: %.*s',
|
msg = 'E115: Missing single quote: %.*s',
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('InvalidSingleQuote', '\''),
|
hl('InvalidSingleQuote', "'"),
|
||||||
hl('InvalidSingleQuotedBody', 'a'),
|
hl('InvalidSingleQuotedBody', 'a'),
|
||||||
})
|
})
|
||||||
check_parsing('\'abc\'\'def\'', {
|
check_parsing("'abc''def'", {
|
||||||
-- 0123456789
|
-- 0123456789
|
||||||
ast = {
|
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('SingleQuotedBody', 'abc'),
|
||||||
hl('SingleQuotedQuote', '\'\''),
|
hl('SingleQuotedQuote', "''"),
|
||||||
hl('SingleQuotedBody', 'def'),
|
hl('SingleQuotedBody', 'def'),
|
||||||
hl('SingleQuote', '\''),
|
hl('SingleQuote', "'"),
|
||||||
})
|
})
|
||||||
check_parsing('\'abc\'\'', {
|
check_parsing("'abc''", {
|
||||||
-- 012345
|
-- 012345
|
||||||
ast = {
|
ast = {
|
||||||
fmtn('SingleQuotedString', 'val="abc\'"', ':0:0:\'abc\'\''),
|
fmtn('SingleQuotedString', 'val="abc\'"', ":0:0:'abc''"),
|
||||||
},
|
},
|
||||||
err = {
|
err = {
|
||||||
arg = '\'abc\'\'',
|
arg = "'abc''",
|
||||||
msg = 'E115: Missing single quote: %.*s',
|
msg = 'E115: Missing single quote: %.*s',
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('InvalidSingleQuote', '\''),
|
hl('InvalidSingleQuote', "'"),
|
||||||
hl('InvalidSingleQuotedBody', 'abc'),
|
hl('InvalidSingleQuotedBody', 'abc'),
|
||||||
hl('InvalidSingleQuotedQuote', '\'\''),
|
hl('InvalidSingleQuotedQuote', "''"),
|
||||||
})
|
})
|
||||||
check_parsing('\'\'\'\'\'\'\'\'', {
|
check_parsing("''''''''", {
|
||||||
-- 01234567
|
-- 01234567
|
||||||
ast = {
|
ast = {
|
||||||
fmtn('SingleQuotedString', 'val="\'\'\'"', ':0:0:\'\'\'\'\'\'\'\''),
|
fmtn('SingleQuotedString', "val=\"'''\"", ":0:0:''''''''"),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('SingleQuote', '\''),
|
hl('SingleQuote', "'"),
|
||||||
hl('SingleQuotedQuote', '\'\''),
|
hl('SingleQuotedQuote', "''"),
|
||||||
hl('SingleQuotedQuote', '\'\''),
|
hl('SingleQuotedQuote', "''"),
|
||||||
hl('SingleQuotedQuote', '\'\''),
|
hl('SingleQuotedQuote', "''"),
|
||||||
hl('SingleQuote', '\''),
|
hl('SingleQuote', "'"),
|
||||||
})
|
})
|
||||||
check_parsing('\'\'\'a\'\'\'\'bc\'', {
|
check_parsing("'''a''''bc'", {
|
||||||
-- 01234567890
|
-- 01234567890
|
||||||
-- 0 1
|
-- 0 1
|
||||||
ast = {
|
ast = {
|
||||||
fmtn('SingleQuotedString', 'val="\'a\'\'bc"', ':0:0:\'\'\'a\'\'\'\'bc\''),
|
fmtn('SingleQuotedString', "val=\"'a''bc\"", ":0:0:'''a''''bc'"),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
hl('SingleQuote', '\''),
|
hl('SingleQuote', "'"),
|
||||||
hl('SingleQuotedQuote', '\'\''),
|
hl('SingleQuotedQuote', "''"),
|
||||||
hl('SingleQuotedBody', 'a'),
|
hl('SingleQuotedBody', 'a'),
|
||||||
hl('SingleQuotedQuote', '\'\''),
|
hl('SingleQuotedQuote', "''"),
|
||||||
hl('SingleQuotedQuote', '\'\''),
|
hl('SingleQuotedQuote', "''"),
|
||||||
hl('SingleQuotedBody', 'bc'),
|
hl('SingleQuotedBody', 'bc'),
|
||||||
hl('SingleQuote', '\''),
|
hl('SingleQuote', "'"),
|
||||||
})
|
})
|
||||||
check_parsing('"\\"\\"\\"\\""', {
|
check_parsing('"\\"\\"\\"\\""', {
|
||||||
-- 0123456789
|
-- 0123456789
|
||||||
@ -5006,7 +5007,11 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
-- 0123456789012345678901234
|
-- 0123456789012345678901234
|
||||||
-- 0 1 2
|
-- 0 1 2
|
||||||
ast = {
|
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', '"'),
|
hl('DoubleQuote', '"'),
|
||||||
@ -6977,8 +6982,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
arg = '\0002&A:\000',
|
arg = '\0002&A:\000',
|
||||||
msg = 'E15: Expected value, got EOC: %.*s',
|
msg = 'E15: Expected value, got EOC: %.*s',
|
||||||
},
|
},
|
||||||
}, {
|
}, {}, {
|
||||||
}, {
|
|
||||||
[2] = {
|
[2] = {
|
||||||
ast = {
|
ast = {
|
||||||
len = REMOVE_THIS,
|
len = REMOVE_THIS,
|
||||||
@ -7076,8 +7080,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
arg = '|"\\U\\',
|
arg = '|"\\U\\',
|
||||||
msg = 'E15: Expected value, got EOC: %.*s',
|
msg = 'E15: Expected value, got EOC: %.*s',
|
||||||
},
|
},
|
||||||
}, {
|
}, {}, {
|
||||||
}, {
|
|
||||||
[2] = {
|
[2] = {
|
||||||
ast = {
|
ast = {
|
||||||
len = REMOVE_THIS,
|
len = REMOVE_THIS,
|
||||||
@ -7109,8 +7112,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
arg = '|"\\e"',
|
arg = '|"\\e"',
|
||||||
msg = 'E15: Expected value, got EOC: %.*s',
|
msg = 'E15: Expected value, got EOC: %.*s',
|
||||||
},
|
},
|
||||||
}, {
|
}, {}, {
|
||||||
}, {
|
|
||||||
[2] = {
|
[2] = {
|
||||||
ast = {
|
ast = {
|
||||||
len = REMOVE_THIS,
|
len = REMOVE_THIS,
|
||||||
@ -7142,8 +7144,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
arg = '|\029',
|
arg = '|\029',
|
||||||
msg = 'E15: Expected value, got EOC: %.*s',
|
msg = 'E15: Expected value, got EOC: %.*s',
|
||||||
},
|
},
|
||||||
}, {
|
}, {}, {
|
||||||
}, {
|
|
||||||
[2] = {
|
[2] = {
|
||||||
ast = {
|
ast = {
|
||||||
len = REMOVE_THIS,
|
len = REMOVE_THIS,
|
||||||
@ -7373,7 +7374,7 @@ return function(itp, _check_parsing, hl, fmtn)
|
|||||||
hl_fs = {
|
hl_fs = {
|
||||||
[2] = REMOVE_THIS,
|
[2] = REMOVE_THIS,
|
||||||
[3] = REMOVE_THIS,
|
[3] = REMOVE_THIS,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ local function pstate_set_str(pstate, start, len, ret)
|
|||||||
ret = ret or {}
|
ret = ret or {}
|
||||||
ret.start = {
|
ret.start = {
|
||||||
line = tonumber(start.line),
|
line = tonumber(start.line),
|
||||||
col = tonumber(start.col)
|
col = tonumber(start.col),
|
||||||
}
|
}
|
||||||
ret.len = tonumber(len)
|
ret.len = tonumber(len)
|
||||||
ret.str, ret.error = pstate_str(pstate, start, len)
|
ret.str, ret.error = pstate_str(pstate, start, len)
|
||||||
@ -84,36 +84,57 @@ local function pstate_set_str(pstate, start, len, ret)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local eltkn_cmp_type_tab
|
local eltkn_cmp_type_tab
|
||||||
make_enum_conv_tab(lib, {
|
make_enum_conv_tab(
|
||||||
|
lib,
|
||||||
|
{
|
||||||
'kExprCmpEqual',
|
'kExprCmpEqual',
|
||||||
'kExprCmpMatches',
|
'kExprCmpMatches',
|
||||||
'kExprCmpGreater',
|
'kExprCmpGreater',
|
||||||
'kExprCmpGreaterOrEqual',
|
'kExprCmpGreaterOrEqual',
|
||||||
'kExprCmpIdentical',
|
'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)
|
local function conv_cmp_type(typ)
|
||||||
return conv_enum(eltkn_cmp_type_tab, typ)
|
return conv_enum(eltkn_cmp_type_tab, typ)
|
||||||
end
|
end
|
||||||
|
|
||||||
local ccs_tab
|
local ccs_tab
|
||||||
make_enum_conv_tab(lib, {
|
make_enum_conv_tab(
|
||||||
|
lib,
|
||||||
|
{
|
||||||
'kCCStrategyUseOption',
|
'kCCStrategyUseOption',
|
||||||
'kCCStrategyMatchCase',
|
'kCCStrategyMatchCase',
|
||||||
'kCCStrategyIgnoreCase',
|
'kCCStrategyIgnoreCase',
|
||||||
}, 'kCCStrategy', function(ret) ccs_tab = ret end)
|
},
|
||||||
|
'kCCStrategy',
|
||||||
|
function(ret)
|
||||||
|
ccs_tab = ret
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
local function conv_ccs(ccs)
|
local function conv_ccs(ccs)
|
||||||
return conv_enum(ccs_tab, ccs)
|
return conv_enum(ccs_tab, ccs)
|
||||||
end
|
end
|
||||||
|
|
||||||
local expr_asgn_type_tab
|
local expr_asgn_type_tab
|
||||||
make_enum_conv_tab(lib, {
|
make_enum_conv_tab(
|
||||||
|
lib,
|
||||||
|
{
|
||||||
'kExprAsgnPlain',
|
'kExprAsgnPlain',
|
||||||
'kExprAsgnAdd',
|
'kExprAsgnAdd',
|
||||||
'kExprAsgnSubtract',
|
'kExprAsgnSubtract',
|
||||||
'kExprAsgnConcat',
|
'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)
|
local function conv_expr_asgn_type(expr_asgn_type)
|
||||||
return conv_enum(expr_asgn_type_tab, expr_asgn_type)
|
return conv_enum(expr_asgn_type_tab, expr_asgn_type)
|
||||||
|
Reference in New Issue
Block a user