mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00

This fixes "fake server" from leaking memory, which makes ASAN very upset, except on current ASAN CI for some reason.
174 lines
4.5 KiB
Lua
174 lines
4.5 KiB
Lua
local helpers = require('test.functional.helpers')(nil)
|
|
|
|
local clear = helpers.clear
|
|
local exec_lua = helpers.exec_lua
|
|
local run = helpers.run
|
|
local stop = helpers.stop
|
|
local NIL = helpers.NIL
|
|
|
|
local M = {}
|
|
|
|
function M.clear_notrace()
|
|
-- problem: here be dragons
|
|
-- solution: don't look too closely for dragons
|
|
clear {env={
|
|
NVIM_LUA_NOTRACK="1";
|
|
VIMRUNTIME=os.getenv"VIMRUNTIME";
|
|
}}
|
|
end
|
|
|
|
M.create_server_definition = [[
|
|
function _create_server(opts)
|
|
opts = opts or {}
|
|
local server = {}
|
|
server.messages = {}
|
|
|
|
function server.cmd(dispatchers)
|
|
local closing = false
|
|
local handlers = opts.handlers or {}
|
|
local srv = {}
|
|
|
|
function srv.request(method, params, callback)
|
|
table.insert(server.messages, {
|
|
method = method,
|
|
params = params,
|
|
})
|
|
local handler = handlers[method]
|
|
if handler then
|
|
local response, err = handler(method, params)
|
|
callback(err, response)
|
|
elseif method == 'initialize' then
|
|
callback(nil, {
|
|
capabilities = opts.capabilities or {}
|
|
})
|
|
elseif method == 'shutdown' then
|
|
callback(nil, nil)
|
|
end
|
|
local request_id = #server.messages
|
|
return true, request_id
|
|
end
|
|
|
|
function srv.notify(method, params)
|
|
table.insert(server.messages, {
|
|
method = method,
|
|
params = params
|
|
})
|
|
if method == 'exit' then
|
|
dispatchers.on_exit(0, 15)
|
|
end
|
|
end
|
|
|
|
function srv.is_closing()
|
|
return closing
|
|
end
|
|
|
|
function srv.terminate()
|
|
closing = true
|
|
end
|
|
|
|
return srv
|
|
end
|
|
|
|
return server
|
|
end
|
|
]]
|
|
|
|
-- Fake LSP server.
|
|
M.fake_lsp_code = 'test/functional/fixtures/fake-lsp-server.lua'
|
|
M.fake_lsp_logfile = 'Xtest-fake-lsp.log'
|
|
|
|
local function fake_lsp_server_setup(test_name, timeout_ms, options, settings)
|
|
exec_lua([=[
|
|
lsp = require('vim.lsp')
|
|
local test_name, fake_lsp_code, fake_lsp_logfile, timeout, options, settings = ...
|
|
TEST_RPC_CLIENT_ID = lsp.start_client {
|
|
cmd_env = {
|
|
NVIM_LOG_FILE = fake_lsp_logfile;
|
|
NVIM_LUA_NOTRACK = "1";
|
|
};
|
|
cmd = {
|
|
vim.v.progpath, '-l', fake_lsp_code, test_name, tostring(timeout),
|
|
};
|
|
handlers = setmetatable({}, {
|
|
__index = function(t, method)
|
|
return function(...)
|
|
return vim.rpcrequest(1, 'handler', ...)
|
|
end
|
|
end;
|
|
});
|
|
workspace_folders = {{
|
|
uri = 'file://' .. vim.loop.cwd(),
|
|
name = 'test_folder',
|
|
}};
|
|
on_init = function(client, result)
|
|
TEST_RPC_CLIENT = client
|
|
vim.rpcrequest(1, "init", result)
|
|
end;
|
|
flags = {
|
|
allow_incremental_sync = options.allow_incremental_sync or false;
|
|
debounce_text_changes = options.debounce_text_changes or 0;
|
|
};
|
|
settings = settings;
|
|
on_exit = function(...)
|
|
vim.rpcnotify(1, "exit", ...)
|
|
end;
|
|
}
|
|
]=], test_name, M.fake_lsp_code, M.fake_lsp_logfile, timeout_ms or 1e3, options or {}, settings or {})
|
|
end
|
|
|
|
function M.test_rpc_server(config)
|
|
if config.test_name then
|
|
M.clear_notrace()
|
|
fake_lsp_server_setup(config.test_name, config.timeout_ms or 1e3, config.options, config.settings)
|
|
end
|
|
local client = setmetatable({}, {
|
|
__index = function(_, name)
|
|
-- Workaround for not being able to yield() inside __index for Lua 5.1 :(
|
|
-- Otherwise I would just return the value here.
|
|
return function(...)
|
|
return exec_lua([=[
|
|
local name = ...
|
|
if type(TEST_RPC_CLIENT[name]) == 'function' then
|
|
return TEST_RPC_CLIENT[name](select(2, ...))
|
|
else
|
|
return TEST_RPC_CLIENT[name]
|
|
end
|
|
]=], name, ...)
|
|
end
|
|
end;
|
|
})
|
|
local code, signal
|
|
local function on_request(method, args)
|
|
if method == "init" then
|
|
if config.on_init then
|
|
config.on_init(client, unpack(args))
|
|
end
|
|
return NIL
|
|
end
|
|
if method == 'handler' then
|
|
if config.on_handler then
|
|
config.on_handler(unpack(args))
|
|
end
|
|
end
|
|
return NIL
|
|
end
|
|
local function on_notify(method, args)
|
|
if method == 'exit' then
|
|
code, signal = unpack(args)
|
|
return stop()
|
|
end
|
|
end
|
|
-- TODO specify timeout?
|
|
-- run(on_request, on_notify, config.on_setup, 1000)
|
|
run(on_request, on_notify, config.on_setup)
|
|
if config.on_exit then
|
|
config.on_exit(code, signal)
|
|
end
|
|
stop()
|
|
if config.test_name then
|
|
exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
|
|
end
|
|
end
|
|
|
|
return M
|