diff options
author | dundargoc <gocdundar@gmail.com> | 2024-04-08 11:03:20 +0200 |
---|---|---|
committer | dundargoc <33953936+dundargoc@users.noreply.github.com> | 2024-04-08 22:51:00 +0200 |
commit | 7035125b2b26aa68fcfb7cda39377ac79926a0f9 (patch) | |
tree | d194a3556a367b42505f9e7d26637e7cb3674928 /test/functional/plugin/lsp/testutil.lua | |
parent | 978962f9a00ce75216d2c36b79397ef3d2b54096 (diff) | |
download | rneovim-7035125b2b26aa68fcfb7cda39377ac79926a0f9.tar.gz rneovim-7035125b2b26aa68fcfb7cda39377ac79926a0f9.tar.bz2 rneovim-7035125b2b26aa68fcfb7cda39377ac79926a0f9.zip |
test: improve test conventions
Work on https://github.com/neovim/neovim/issues/27004.
Diffstat (limited to 'test/functional/plugin/lsp/testutil.lua')
-rw-r--r-- | test/functional/plugin/lsp/testutil.lua | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/test/functional/plugin/lsp/testutil.lua b/test/functional/plugin/lsp/testutil.lua new file mode 100644 index 0000000000..7dc7bd9925 --- /dev/null +++ b/test/functional/plugin/lsp/testutil.lua @@ -0,0 +1,219 @@ +local t = require('test.functional.testutil')(nil) + +local clear = t.clear +local exec_lua = t.exec_lua +local run = t.run +local stop = t.stop +local api = t.api +local NIL = vim.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', + NVIM_APPNAME = 'nvim_lsp_test', + 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"; + NVIM_APPNAME = "nvim_lsp_test"; + }; + 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.uv.cwd(), + name = 'test_folder', + }}; + before_init = function(params, config) + vim.schedule(function() + vim.rpcrequest(1, "setup") + end) + end, + 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 + +--- @class test.lsp.Config +--- @field test_name string +--- @field timeout_ms? integer +--- @field options? table +--- @field settings? table +--- +--- @field on_setup? fun() +--- @field on_init? fun(client: vim.lsp.Client, ...) +--- @field on_handler? fun(...) +--- @field on_exit? fun(code: integer, signal: integer) + +--- @param config test.lsp.Config +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, + }) + --- @type integer, integer + local code, signal + local function on_request(method, args) + if method == 'setup' then + if config.on_setup then + config.on_setup() + end + return NIL + end + 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, nil, 1000) + run(on_request, on_notify, nil) + if config.on_exit then + config.on_exit(code, signal) + end + stop() + if config.test_name then + api.nvim_exec_autocmds('VimLeavePre', { modeline = false }) + end +end + +return M |