diff --git a/tests/test-sources/modules/performance/combine-plugins.nix b/tests/test-sources/modules/performance/combine-plugins.nix index fe0c3c46..7d7d8c68 100644 --- a/tests/test-sources/modules/performance/combine-plugins.nix +++ b/tests/test-sources/modules/performance/combine-plugins.nix @@ -1,6 +1,6 @@ -{ pkgs, ... }: +{ lib, pkgs, ... }: let - inherit (pkgs) lib; + pluginStubs = pkgs.callPackage ../../../utils/plugin-stubs.nix { }; # Assertion for a number of plugins of given type defined in nvimPackage.packpathDirs expectNPlugins = @@ -20,110 +20,26 @@ let }; # Assertion that exactly one start plugin is defined in nvimPackage.packpathDirs expectOneStartPlugin = config: expectNPlugins config "start" 1; - - # Stub plugins - mkPlugin = - name: args: - pkgs.vimUtils.buildVimPlugin ( - { - pname = name; - version = "2025-04-27"; - src = pkgs.runCommand "${name}-source" { } '' - mkdir "$out" - # Add some colliding files - echo "# ${name}" > "$out/README.md" - echo "Copyright (c) ${name}" > "$out/LICENSE" - mkdir "$out/tests" - echo "return '${name}'" > "$out/tests/test.lua" - # Add import path - mkdir -p "$out/lua/${name}" - echo "return '${name}'" > "$out/lua/${name}/init.lua" - # Add doc - mkdir "$out/doc" - echo "*${name}.txt* ${name}" > "$out/doc/${name}.txt" - ''; - } - // args - ); - # Simple plugins without any features - simplePlugin1 = mkPlugin "simple-plugin-1" { }; - simplePlugin2 = mkPlugin "simple-plugin-2" { }; - simplePlugin3 = mkPlugin "simple-plugin-3" { }; - # Plugins with dependencies - pluginWithDeps1 = mkPlugin "plugin-with-deps-1" { - dependencies = [ simplePlugin1 ]; - }; - pluginWithDeps2 = mkPlugin "plugin-with-deps-2" { - dependencies = [ simplePlugin2 ]; - }; - pluginWithDeps3 = mkPlugin "plugin-with-deps-3" { - dependencies = [ simplePlugin3 ]; - }; - # Plugin with recursive dependencies - pluginWithRecDeps = mkPlugin "plugin-with-rec-deps" { - dependencies = [ - pluginWithDeps1 - pluginWithDeps2 - ]; - }; - # Plugin with non-standard files - pluginWithExtraFiles = mkPlugin "plugin-with-extra-files" { - postInstall = '' - mkdir "$out/_extra" - touch "$out/_extra/test" - ''; - }; - # Plugins with Python dependencies - pluginWithPyDeps1 = mkPlugin "plugin-with-py-deps-1" { - passthru.python3Dependencies = ps: [ ps.pyyaml ]; - }; - pluginWithPyDeps2 = mkPlugin "plugin-with-py-deps-2" { - passthru.python3Dependencies = ps: [ ps.pyyaml ]; - }; - pluginWithPyDeps3 = mkPlugin "plugin-with-py-deps-3" { - passthru.python3Dependencies = ps: [ ps.requests ]; - }; - # Plugins with Lua dependencies - ensureDep = - drv: dep: - drv.overrideAttrs (prev: { - propagatedBuildInputs = lib.unique ( - prev.propagatedBuildInputs or [ ] ++ [ prev.passthru.lua.pkgs.${dep} ] - ); - }); - pluginWithLuaDeps1 = ensureDep pkgs.vimPlugins.telescope-nvim "plenary-nvim"; - pluginWithLuaDeps2 = ensureDep pkgs.vimPlugins.nvim-cmp "plenary-nvim"; - pluginWithLuaDeps3 = ensureDep pkgs.vimPlugins.gitsigns-nvim "nui-nvim"; in { # Test basic functionality default = { config, ... }: - let - extraPlugins = [ - simplePlugin1 - simplePlugin2 - simplePlugin3 - ]; - in { performance.combinePlugins.enable = true; - inherit extraPlugins; - extraConfigLuaPost = lib.concatMapStringsSep "\n" ( - name: - # lua - '' - -- Plugin is loadable - require("${name}") + extraPlugins = pluginStubs.pluginPack; + extraConfigLuaPost = '' + ${pluginStubs.pluginChecks} - -- No separate plugin entry in vim.api.nvim_list_runtime_paths() - assert(not vim.iter(vim.api.nvim_list_runtime_paths()):any(function(entry) - return entry:find("${name}", 1, true) - end), "plugin '${name}' found in runtime, expected to be combined") - - -- Help tags are generated - assert(vim.fn.getcompletion("${name}", "help")[1], "no help tags for '${name}'") - '') (map lib.getName extraPlugins); + -- No separate plugin entry in vim.api.nvim_list_runtime_paths() + ${lib.concatMapStrings ( + name: # lua + '' + assert(not vim.iter(vim.api.nvim_list_runtime_paths()):any(function(entry) + return entry:find("${name}", 1, true) + end), "plugin '${name}' found in runtime, expected to be combined") + '') pluginStubs.pluginNames} + ''; assertions = [ (expectOneStartPlugin config) ]; @@ -132,16 +48,9 @@ in # Test disabled option disabled = { config, ... }: - let - extraPlugins = [ - simplePlugin1 - simplePlugin2 - simplePlugin3 - ]; - in { performance.combinePlugins.enable = false; - inherit extraPlugins; + extraPlugins = pluginStubs.pluginPack; extraConfigLuaPost = lib.concatMapStringsSep "\n" ( name: # lua @@ -150,40 +59,9 @@ in assert(vim.iter(vim.api.nvim_list_runtime_paths()):any(function(entry) return entry:find("${name}", 1, true) end), "plugin '${name}' isn't found in runtime as a separate entry, expected not to be combined") - '') (map lib.getName extraPlugins); + '') pluginStubs.pluginNames; assertions = [ - (expectNPlugins config "start" (builtins.length extraPlugins)) - ]; - }; - - # Test that plugin dependencies are handled - dependencies = - { config, ... }: - { - performance.combinePlugins.enable = true; - extraPlugins = [ - # Depends on pluginWithDeps1 and pluginWithDeps2 which themselves depend on simplePlugin1 and simplePlugin2 - pluginWithRecDeps - # Depends on simplePlugin3 - pluginWithDeps3 - # Duplicated dependency - pluginWithDeps2 - # Duplicated plugin - simplePlugin2 - ]; - extraConfigLuaPost = '' - -- Plugin 'pluginWithRecDeps' and its dependencies are loadable - require("plugin-with-rec-deps") - require("plugin-with-deps-1") - require("plugin-with-deps-2") - require("simple-plugin-1") - require("simple-plugin-2") - -- Plugin 'pluginWithDeps3' and its dependencies are loadable - require("plugin-with-deps-3") - require("simple-plugin-3") - ''; - assertions = [ - (expectOneStartPlugin config) + (expectNPlugins config "start" (builtins.length pluginStubs.pluginPack)) ]; }; @@ -195,8 +73,18 @@ in enable = true; pathsToLink = [ "/_extra" ]; }; - extraPlugins = [ pluginWithExtraFiles ]; + extraPlugins = [ + # A plugin with extra directory + (pluginStubs.mkPlugin "extra" { + postInstall = '' + mkdir $out/_extra + touch $out/_extra/test + ''; + }) + ]; extraConfigLuaPost = '' + ${pluginStubs.pluginChecksFor [ "extra" ]} + -- Test file is in runtime assert( vim.api.nvim_get_runtime_file("_extra/test", false)[1], @@ -208,103 +96,79 @@ in ]; }; - # Test that plugin python3 dependencies are handled - python-dependencies = - { config, ... }: - { - performance.combinePlugins.enable = true; - extraPlugins = [ - # No python3 dependencies - simplePlugin1 - # Duplicated python3-pyyaml dependency - pluginWithPyDeps1 - pluginWithPyDeps2 - # Python3-requests dependency - pluginWithPyDeps3 - ]; - extraConfigLuaPost = '' - -- Python modules are importable - vim.cmd.py3("import yaml") - vim.cmd.py3("import requests") - ''; - assertions = [ - (expectOneStartPlugin config) - ]; - }; - - # Test that plugin lua dependencies are handled - lua-dependencies = - { config, ... }: - { - performance.combinePlugins.enable = true; - extraPlugins = [ - simplePlugin1 - # Duplicated plenary-nvim dependency - pluginWithLuaDeps1 - pluginWithLuaDeps2 - # nui-nvim dependency - pluginWithLuaDeps3 - ]; - extraConfigLuaPost = '' - -- All packages and its dependencies are importable - require("telescope") - require("plenary") - require("cmp") - require("gitsigns") - require("nui.popup") - ''; - assertions = [ - (expectOneStartPlugin config) - ]; - }; - # Test that optional plugins are handled optional-plugins = { config, ... }: { performance.combinePlugins.enable = true; - extraPlugins = [ + extraPlugins = with pluginStubs; [ # Start plugins - simplePlugin1 - simplePlugin2 + plugin1 + plugin3 # Optional plugin { - plugin = simplePlugin3; + plugin = plugin2; optional = true; } - # Optional plugin with dependency on simplePlugin1 + # Optional plugin with dependencies on plugin3 and plugin4 # Dependencies should not be duplicated { - plugin = pluginWithDeps1; + plugin = pluginWithDep4; optional = true; } ]; extraConfigLuaPost = '' - -- Start plugins are loadable - require("simple-plugin-1") - require("simple-plugin-2") + -- Start plugins are working. Dependencies of the optional plugins are also available. + ${pluginStubs.pluginChecksFor [ + "plugin1" + "plugin3" + "plugin4" # Dependency of the optional plugin + ]} - -- Opt plugins are not loadable - local ok = pcall(require, "simple-plugin-3") - assert(not ok, "simplePlugin3 is loadable, expected it to be an opt plugin") - ok = pcall(require, "plugin-with-deps-1") - assert(not ok, "pluginWithDeps1 is loadable, expected it to be an opt plugin") + -- Lua libraries are available. Libs of the optional plugins are also available. + ${pluginStubs.libChecksFor [ + "lib1" + "lib2" # Dependency of the optional plugin + "lib3" + ]} - -- Load plugins - vim.cmd.packadd("simple-plugin-3") - vim.cmd.packadd("plugin-with-deps-1") + ${lib.concatMapStrings + ( + name: # lua + '' + -- Optional plugin is not loadable + local ok = pcall(require, "${name}") + assert(not ok, "${name} is loadable, expected it to be an opt plugin") - -- Now opt plugins are loadable - require("simple-plugin-3") - require("plugin-with-deps-1") + -- Load plugin + vim.cmd.packadd("${name}") - -- Only one copy of simplePlugin1 should be available - local num_plugins = #vim.api.nvim_get_runtime_file("lua/simple-plugin-1/init.lua", true) - assert(num_plugins == 1, "expected 1 copy of simplePlugin1, got " .. num_plugins) + -- Now opt plugin is working + ${pluginStubs.pluginChecksFor [ name ]} + '') + [ + "plugin2" + "plugin_with_dep4" + ] + } + + -- Only one copy of dependent plugin should be available + ${lib.concatMapStrings + ( + name: # lua + '' + local num_plugins = #vim.api.nvim_get_runtime_file("lua/${name}/init.lua", true) + assert(num_plugins == 1, "expected 1 copy of ${name}, got " .. num_plugins) + '') + [ + "plugin3" + "plugin4" + ] + } ''; assertions = [ (expectOneStartPlugin config) - # simplePlugin3 pluginWithDeps1 + # plugin2 plugin_with_dep4 (expectNPlugins config "opt" 2) ]; }; @@ -314,25 +178,25 @@ in { config, ... }: { performance.combinePlugins.enable = true; - extraPlugins = [ + extraPlugins = with pluginStubs; [ # A plugin without config - simplePlugin1 - # Plugin with config + plugin1 + # A plugin with config { - plugin = simplePlugin2; - config = "let g:simple_plugin_2 = 1"; + plugin = plugin2; + config = "let g:plugin2_var = 1"; } # Optional plugin with config { - plugin = simplePlugin3; + plugin = plugin3; optional = true; - config = "let g:simple_plugin_3 = 1"; + config = "let g:plugin3_var = 1"; } ]; extraConfigLuaPost = '' -- Configs are evaluated - assert(vim.g.simple_plugin_2 == 1, "simplePlugin2's config isn't evaluated") - assert(vim.g.simple_plugin_3 == 1, "simplePlugin3's config isn't evaluated") + assert(vim.g.plugin2_var == 1, "plugin2's config isn't evaluated") + assert(vim.g.plugin3_var == 1, "plugin3's config isn't evaluated") ''; assertions = [ (expectOneStartPlugin config) @@ -344,24 +208,24 @@ in { config, ... }: { performance.combinePlugins.enable = true; - extraPlugins = [ - simplePlugin1 - simplePlugin2 + extraPlugins = with pluginStubs; [ + plugin1 + plugin2 ]; # Ensure that build.extraFiles is added to extraPlugins wrapRc = true; # Extra user files colliding with plugins extraFiles = { - "lua/simple-plugin-1/init.lua".text = "return 1"; + "lua/plugin1/init.lua".text = "return 1"; }; # Another form of user files files = { - "lua/simple-plugin-2/init.lua" = { + "lua/plugin2/init.lua" = { extraConfigLua = "return 1"; }; }; extraConfigLuaPost = '' - for _, file in ipairs({"lua/simple-plugin-1/init.lua", "lua/simple-plugin-2/init.lua"}) do + for _, file in ipairs({"lua/plugin1/init.lua", "lua/plugin2/init.lua"}) do local paths_found = vim.api.nvim_get_runtime_file(file, true) local num_found = #paths_found @@ -383,55 +247,53 @@ in # Test that standalonePlugins option works standalone-plugins = { config, ... }: + let + standalonePlugins = [ + # By plugin name + "plugin1" + # By package itself. Its dependency, plugin4, not in this list, so will be combined + pluginStubs.pluginWithDep4 + # Dependency of other plugin + "plugin5" + # Both dependency and top-level plugin + "plugin3" + ]; + in { performance.combinePlugins = { enable = true; - standalonePlugins = [ - # By plugin name - "simple-plugin-1" - # By package itself. Its dependency, simplePlugin2, not in this list, so will be combined - pluginWithDeps2 - # Dependency of other plugin - "simple-plugin-3" - ]; + inherit standalonePlugins; }; - extraPlugins = [ - simplePlugin1 - pluginWithDeps2 - pluginWithDeps3 - pluginWithExtraFiles - ]; + extraPlugins = pluginStubs.pluginPack; extraConfigLuaPost = '' - local tests = { - {"simple-plugin-1", true}, - {"plugin-with-deps-2", true}, - {"simple-plugin-2", false}, - {"plugin-with-deps-3", false}, - {"simple-plugin-3", true}, - {"plugin-with-extra-files", false}, - } - for _, test in ipairs(tests) do - local name = test[1] - local expected_standalone = test[2] + ${pluginStubs.pluginChecks} - -- Plugin is loadable - require(test[1]) - - local paths = vim.api.nvim_get_runtime_file("lua/" .. name, true) - -- Plugins shouldn't be duplicated - assert(#paths == 1, "expected exactly 1 copy of '" .. name .. "' in runtime, got ", #paths) - -- Test if plugin is standalone. This matches directory name before '/lua/'. - local is_standalone = paths[1]:match("^(.+)/lua/"):find(name, 1, true) ~= nil - local expected_text = expected_standalone and "standalone" or "combined" - assert( - is_standalone == expected_standalone, - "expected '" .. name .. "' to be " .. expected_text .. ", found path: " .. paths[1] - ) - end + ${lib.concatMapStringsSep "\n" ( + name: + let + isStandalone = builtins.elem name ( + map (x: if builtins.isString x then x else lib.getName x) standalonePlugins + ); + expectedText = if isStandalone then "standalone" else "combined"; + in + # lua + '' + -- Check that ${name} plugin is ${expectedText} + local paths = vim.api.nvim_get_runtime_file("lua/${name}", true) + -- Plugins shouldn't be duplicated + assert(#paths == 1, "expected exactly 1 copy of '${name}' in runtime, got ", #paths) + -- Test if plugin is standalone. This matches directory name before '/lua/'. + local is_standalone = paths[1]:match("^(.+)/lua/"):find("${name}", 1, true) ~= nil + assert( + is_standalone == ${lib.nixvim.toLuaObject isStandalone}, + "expected '${name}' to be ${expectedText}, found path: " .. paths[1] + ) + '' + ) pluginStubs.pluginNames} ''; assertions = [ - # plugin-pack, simplePlugin1, pluginWithDeps2, simplePlugin3 - (expectNPlugins config "start" 4) + # plugin-pack and 'standalonePlugins' + (expectNPlugins config "start" (builtins.length standalonePlugins + 1)) ]; }; diff --git a/tests/utils/plugin-stubs.nix b/tests/utils/plugin-stubs.nix index 95c45554..6c0cdfe0 100644 --- a/tests/utils/plugin-stubs.nix +++ b/tests/utils/plugin-stubs.nix @@ -58,6 +58,7 @@ let prev: { inherit name; + pname = name; buildCommand = '' ${prev.buildCommand} # Activate vimGenDocHook for doc checks to pass