mirror of
https://github.com/neovim/neovim.git
synced 2025-01-01 17:23:36 -07:00
235909044a
This is necessary for newer versions of Busted, otherwise assert will be nil and the tests will die. Note: this does not mean the tests now work with the latest Busted. There are still several issues preventing that from happening.
175 lines
4.4 KiB
Lua
175 lines
4.4 KiB
Lua
local assert = require('luassert')
|
|
local ffi = require('ffi')
|
|
local formatc = require('test.unit.formatc')
|
|
local Set = require('test.unit.set')
|
|
local Preprocess = require('test.unit.preprocess')
|
|
local Paths = require('test.config.paths')
|
|
|
|
-- add some standard header locations
|
|
for _, p in ipairs(Paths.include_paths) do
|
|
Preprocess.add_to_include_path(p)
|
|
end
|
|
|
|
-- load neovim shared library
|
|
local libnvim = ffi.load(Paths.test_libnvim_path)
|
|
|
|
local function trim(s)
|
|
return s:match('^%s*(.*%S)') or ''
|
|
end
|
|
|
|
-- a Set that keeps around the lines we've already seen
|
|
if cdefs == nil then
|
|
cdefs = Set:new()
|
|
end
|
|
|
|
if imported == nil then
|
|
imported = Set:new()
|
|
end
|
|
|
|
if pragma_pack_id == nil then
|
|
pragma_pack_id = 1
|
|
end
|
|
|
|
-- some things are just too complex for the LuaJIT C parser to digest. We
|
|
-- usually don't need them anyway.
|
|
local function filter_complex_blocks(body)
|
|
local result = {}
|
|
|
|
for line in body:gmatch("[^\r\n]+") do
|
|
if not (string.find(line, "(^)", 1, true) ~= nil or
|
|
string.find(line, "_ISwupper", 1, true)) then
|
|
result[#result + 1] = line
|
|
end
|
|
end
|
|
|
|
return table.concat(result, "\n")
|
|
end
|
|
|
|
-- use this helper to import C files, you can pass multiple paths at once,
|
|
-- this helper will return the C namespace of the nvim library.
|
|
local function cimport(...)
|
|
local paths = {}
|
|
local args = {...}
|
|
|
|
-- filter out paths we've already imported
|
|
for _,path in pairs(args) do
|
|
if path ~= nil and not imported:contains(path) then
|
|
paths[#paths + 1] = path
|
|
end
|
|
end
|
|
|
|
for _,path in pairs(paths) do
|
|
imported:add(path)
|
|
end
|
|
|
|
if #paths == 0 then
|
|
return libnvim
|
|
end
|
|
|
|
local body = nil
|
|
for i=1, 10 do
|
|
local stream = Preprocess.preprocess_stream(unpack(paths))
|
|
body = stream:read("*a")
|
|
stream:close()
|
|
if body ~= nil then break end
|
|
end
|
|
|
|
if body == nil then
|
|
print("ERROR: helpers.lua: Preprocess.preprocess_stream():read() returned empty")
|
|
end
|
|
|
|
-- format it (so that the lines are "unique" statements), also filter out
|
|
-- Objective-C blocks
|
|
body = formatc(body)
|
|
body = filter_complex_blocks(body)
|
|
|
|
-- add the formatted lines to a set
|
|
local new_cdefs = Set:new()
|
|
for line in body:gmatch("[^\r\n]+") do
|
|
line = trim(line)
|
|
-- give each #pragma pack an unique id, so that they don't get removed
|
|
-- if they are inserted into the set
|
|
-- (they are needed in the right order with the struct definitions,
|
|
-- otherwise luajit has wrong memory layouts for the sturcts)
|
|
if line:match("#pragma%s+pack") then
|
|
line = line .. " // " .. pragma_pack_id
|
|
pragma_pack_id = pragma_pack_id + 1
|
|
end
|
|
new_cdefs:add(line)
|
|
end
|
|
|
|
-- subtract the lines we've already imported from the new lines, then add
|
|
-- the new unique lines to the old lines (so they won't be imported again)
|
|
new_cdefs:diff(cdefs)
|
|
cdefs:union(new_cdefs)
|
|
|
|
if new_cdefs:size() == 0 then
|
|
-- if there's no new lines, just return
|
|
return libnvim
|
|
end
|
|
|
|
-- request a sorted version of the new lines (same relative order as the
|
|
-- original preprocessed file) and feed that to the LuaJIT ffi
|
|
local new_lines = new_cdefs:to_table()
|
|
ffi.cdef(table.concat(new_lines, "\n"))
|
|
|
|
return libnvim
|
|
end
|
|
|
|
local function cppimport(path)
|
|
return cimport(Paths.test_include_path .. '/' .. path)
|
|
end
|
|
|
|
cimport('./src/nvim/types.h')
|
|
|
|
-- take a pointer to a C-allocated string and return an interned
|
|
-- version while also freeing the memory
|
|
local function internalize(cdata, len)
|
|
ffi.gc(cdata, ffi.C.free)
|
|
return ffi.string(cdata, len)
|
|
end
|
|
|
|
local cstr = ffi.typeof('char[?]')
|
|
local function to_cstr(string)
|
|
return cstr((string.len(string)) + 1, string)
|
|
end
|
|
|
|
-- initialize some global variables, this is still necessary to unit test
|
|
-- functions that rely on global state.
|
|
local function vim_init()
|
|
if vim_init_called ~= nil then
|
|
return
|
|
end
|
|
local main = cimport('./src/nvim/main.h')
|
|
local time = cimport('./src/nvim/os/time.h')
|
|
time.time_init()
|
|
main.early_init()
|
|
vim_init_called = true
|
|
end
|
|
|
|
-- C constants.
|
|
local NULL = ffi.cast('void*', 0)
|
|
|
|
local OK = 1
|
|
local FAIL = 0
|
|
|
|
return {
|
|
cimport = cimport,
|
|
cppimport = cppimport,
|
|
internalize = internalize,
|
|
eq = function(expected, actual)
|
|
return assert.are.same(expected, actual)
|
|
end,
|
|
neq = function(expected, actual)
|
|
return assert.are_not.same(expected, actual)
|
|
end,
|
|
ffi = ffi,
|
|
lib = libnvim,
|
|
cstr = cstr,
|
|
to_cstr = to_cstr,
|
|
vim_init = vim_init,
|
|
NULL = NULL,
|
|
OK = OK,
|
|
FAIL = FAIL
|
|
}
|