diff options
| author | William Boman <william@redwill.se> | 2023-03-12 08:21:15 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-12 08:21:15 +0100 |
| commit | a01d02ad7f680aec98a1e2ec35b04cedd307cfa8 (patch) | |
| tree | 1a09e274a1f2a4da85b911abcbb182a211035501 /tests | |
| parent | feat(golangci-lint): support linux_arm64 (#1089) (diff) | |
| download | mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar.gz mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar.bz2 mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar.lz mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar.xz mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar.zst mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.zip | |
feat: add github registry source capabilities (#1091)
Diffstat (limited to 'tests')
33 files changed, 2388 insertions, 8 deletions
diff --git a/tests/helpers/lua/dummy2_package.lua b/tests/helpers/lua/dummy-registry/dummy2_package.lua index 424e47d7..424e47d7 100644 --- a/tests/helpers/lua/dummy2_package.lua +++ b/tests/helpers/lua/dummy-registry/dummy2_package.lua diff --git a/tests/helpers/lua/dummy_package.lua b/tests/helpers/lua/dummy-registry/dummy_package.lua index b38d1cd8..b38d1cd8 100644 --- a/tests/helpers/lua/dummy_package.lua +++ b/tests/helpers/lua/dummy-registry/dummy_package.lua diff --git a/tests/helpers/lua/dummy-registry/index.lua b/tests/helpers/lua/dummy-registry/index.lua new file mode 100644 index 00000000..85fe000f --- /dev/null +++ b/tests/helpers/lua/dummy-registry/index.lua @@ -0,0 +1,5 @@ +return { + ["dummy"] = "dummy-registry.dummy_package", + ["dummy2"] = "dummy-registry.dummy2_package", + ["registry"] = "dummy-registry.registry_package", +} diff --git a/tests/helpers/lua/dummy-registry/registry_package.lua b/tests/helpers/lua/dummy-registry/registry_package.lua new file mode 100644 index 00000000..e72284a8 --- /dev/null +++ b/tests/helpers/lua/dummy-registry/registry_package.lua @@ -0,0 +1,14 @@ +local Pkg = require "mason-core.package" + +return Pkg.new { + schema = "registry+v1", + name = "registry", + description = [[This is a dummy package.]], + homepage = "https://example.com", + licenses = { "MIT" }, + languages = { "DummyLang" }, + categories = { "LSP" }, + source = { + id = "pkg:dummy/registry@1.0.0", + }, +} diff --git a/tests/helpers/lua/test_helpers.lua b/tests/helpers/lua/test_helpers.lua index f11765d5..8a69ead8 100644 --- a/tests/helpers/lua/test_helpers.lua +++ b/tests/helpers/lua/test_helpers.lua @@ -2,7 +2,9 @@ local util = require "luassert.util" local spy = require "luassert.spy" +local path = require "mason-core.path" local a = require "mason-core.async" +local Result = require "mason-core.result" local InstallHandle = require "mason-core.installer.handle" local InstallContext = require "mason-core.installer.context" local registry = require "mason-registry" @@ -32,6 +34,21 @@ mockx = { end, } +---@param opts? PackageInstallOpts +function create_dummy_context(opts) + local ctx = InstallContextGenerator(InstallHandleGenerator "registry", opts) + ctx.cwd:set(path.package_build_prefix "registry") + ctx.spawn = setmetatable({}, { + __index = function(s, cmd) + s[cmd] = spy.new(function() + return Result.success { stdout = nil, stderr = nil } + end) + return s[cmd] + end, + }) + return ctx +end + -- selene: allow(unused_variable) ---@param package_name string function InstallHandleGenerator(package_name) diff --git a/tests/mason-core/installer/installer_spec.lua b/tests/mason-core/installer/installer_spec.lua index 66cdb89b..aa459cce 100644 --- a/tests/mason-core/installer/installer_spec.lua +++ b/tests/mason-core/installer/installer_spec.lua @@ -63,7 +63,7 @@ describe("installer", function() local handler = InstallHandleGenerator "dummy" ---@param ctx InstallContext handler.package.spec.install = function(ctx) - ctx.receipt:with_primary_source { type = "source", metadata = {} } + ctx.receipt:with_primary_source { type = "source", source = {} } ctx.fs:write_file("target", "") ctx.fs:write_file("file.jar", "") @@ -86,7 +86,7 @@ describe("installer", function() ---@type InstallReceipt local receipt = vim.json.decode(arg) assert.equals("dummy", receipt.name) - assert.same({ type = "source", metadata = {} }, receipt.primary_source) + assert.same({ type = "source", source = {} }, receipt.primary_source) assert.same({}, receipt.secondary_sources) assert.same("1.1", receipt.schema_version) assert.same({ diff --git a/tests/mason-core/installer/managers/cargo_spec.lua b/tests/mason-core/installer/managers/cargo_spec.lua new file mode 100644 index 00000000..63768f4d --- /dev/null +++ b/tests/mason-core/installer/managers/cargo_spec.lua @@ -0,0 +1,112 @@ +local installer = require "mason-core.installer" +local cargo = require "mason-core.installer.managers.cargo" + +describe("cargo manager", function() + it("should install", function() + local handle = InstallHandleGenerator "dummy" + local ctx = InstallContextGenerator(handle) + installer.exec_in_context(ctx, function() + cargo.install("my-crate", "1.0.0") + end) + + assert.spy(ctx.spawn.cargo).was_called(1) + assert.spy(ctx.spawn.cargo).was_called_with { + "install", + "--root", + ".", + { "--version", "1.0.0" }, + vim.NIL, -- features + vim.NIL, -- locked + "my-crate", + } + end) + + it("should install locked", function() + local handle = InstallHandleGenerator "dummy" + local ctx = InstallContextGenerator(handle) + installer.exec_in_context(ctx, function() + cargo.install("my-crate", "1.0.0", { + locked = true, + }) + end) + + assert.spy(ctx.spawn.cargo).was_called(1) + assert.spy(ctx.spawn.cargo).was_called_with { + "install", + "--root", + ".", + { "--version", "1.0.0" }, + vim.NIL, -- features + "--locked", -- locked + "my-crate", + } + end) + + it("should install provided features", function() + local handle = InstallHandleGenerator "dummy" + local ctx = InstallContextGenerator(handle) + installer.exec_in_context(ctx, function() + cargo.install("my-crate", "1.0.0", { + features = "lsp,cli", + }) + end) + + assert.spy(ctx.spawn.cargo).was_called(1) + assert.spy(ctx.spawn.cargo).was_called_with { + "install", + "--root", + ".", + { "--version", "1.0.0" }, + { "--features", "lsp,cli" }, -- features + vim.NIL, -- locked + "my-crate", + } + end) + + it("should install git tag source", function() + local handle = InstallHandleGenerator "dummy" + local ctx = InstallContextGenerator(handle) + installer.exec_in_context(ctx, function() + cargo.install("my-crate", "1.0.0", { + git = { + url = "https://github.com/neovim/neovim", + }, + }) + end) + + assert.spy(ctx.spawn.cargo).was_called(1) + assert.spy(ctx.spawn.cargo).was_called_with { + "install", + "--root", + ".", + { "--git", "https://github.com/neovim/neovim", "--tag", "1.0.0" }, + vim.NIL, -- features + vim.NIL, -- locked + "my-crate", + } + end) + + it("should install git rev source", function() + local handle = InstallHandleGenerator "dummy" + local ctx = InstallContextGenerator(handle) + installer.exec_in_context(ctx, function() + cargo.install("my-crate", "16dfc89abd413c391e5b63ae5d132c22843ce9a7", { + git = { + url = "https://github.com/neovim/neovim", + rev = true, + }, + }) + end) + + assert.spy(ctx.spawn.cargo).was_called(1) + assert.spy(ctx.spawn.cargo).was_called_with { + "install", + "--root", + ".", + { "--git", "https://github.com/neovim/neovim", "--rev", "16dfc89abd413c391e5b63ae5d132c22843ce9a7" }, + vim.NIL, -- features + vim.NIL, -- locked + "my-crate", + } + end) +end) diff --git a/tests/mason-core/installer/managers/composer_spec.lua b/tests/mason-core/installer/managers/composer_spec.lua new file mode 100644 index 00000000..a4e1f82f --- /dev/null +++ b/tests/mason-core/installer/managers/composer_spec.lua @@ -0,0 +1,22 @@ +local installer = require "mason-core.installer" +local composer = require "mason-core.installer.managers.composer" + +describe("composer manager", function() + it("should install", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + composer.install("my-package", "1.0.0") + end) + + assert.spy(ctx.spawn.composer).was_called(2) + assert.spy(ctx.spawn.composer).was_called_with { + "init", + "--no-interaction", + "--stability=stable", + } + assert.spy(ctx.spawn.composer).was_called_with { + "require", + "my-package:1.0.0", + } + end) +end) diff --git a/tests/mason-core/installer/managers/gem_spec.lua b/tests/mason-core/installer/managers/gem_spec.lua new file mode 100644 index 00000000..580c6432 --- /dev/null +++ b/tests/mason-core/installer/managers/gem_spec.lua @@ -0,0 +1,50 @@ +local installer = require "mason-core.installer" +local gem = require "mason-core.installer.managers.gem" + +describe("gem manager", function() + it("should install", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + gem.install("my-gem", "1.0.0") + end) + + assert.spy(ctx.spawn.gem).was_called(1) + assert.spy(ctx.spawn.gem).was_called_with { + "install", + "--no-user-install", + "--no-format-executable", + "--install-dir=.", + "--bindir=bin", + "--no-document", + "my-gem:1.0.0", + vim.NIL, -- extra_packages + env = { + GEM_HOME = ctx.cwd:get(), + }, + } + end) + + it("should install extra packages", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + gem.install("my-gem", "1.0.0", { + extra_packages = { "extra-gem" }, + }) + end) + + assert.spy(ctx.spawn.gem).was_called(1) + assert.spy(ctx.spawn.gem).was_called_with { + "install", + "--no-user-install", + "--no-format-executable", + "--install-dir=.", + "--bindir=bin", + "--no-document", + "my-gem:1.0.0", + { "extra-gem" }, + env = { + GEM_HOME = ctx.cwd:get(), + }, + } + end) +end) diff --git a/tests/mason-core/installer/managers/golang_spec.lua b/tests/mason-core/installer/managers/golang_spec.lua new file mode 100644 index 00000000..cdad6e25 --- /dev/null +++ b/tests/mason-core/installer/managers/golang_spec.lua @@ -0,0 +1,56 @@ +local installer = require "mason-core.installer" +local golang = require "mason-core.installer.managers.golang" + +describe("golang manager", function() + it("should install", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + golang.install("my-golang", "1.0.0") + end) + + assert.spy(ctx.spawn.go).was_called(1) + assert.spy(ctx.spawn.go).was_called_with { + "install", + "-v", + "my-golang@1.0.0", + env = { + GOBIN = ctx.cwd:get(), + }, + } + end) + + it("should install extra packages", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + golang.install("my-golang", "1.0.0", { + extra_packages = { "extra", "package" }, + }) + end) + + assert.spy(ctx.spawn.go).was_called(3) + assert.spy(ctx.spawn.go).was_called_with { + "install", + "-v", + "my-golang@1.0.0", + env = { + GOBIN = ctx.cwd:get(), + }, + } + assert.spy(ctx.spawn.go).was_called_with { + "install", + "-v", + "extra@latest", + env = { + GOBIN = ctx.cwd:get(), + }, + } + assert.spy(ctx.spawn.go).was_called_with { + "install", + "-v", + "package@latest", + env = { + GOBIN = ctx.cwd:get(), + }, + } + end) +end) diff --git a/tests/mason-core/installer/managers/luarocks_spec.lua b/tests/mason-core/installer/managers/luarocks_spec.lua new file mode 100644 index 00000000..69ac3946 --- /dev/null +++ b/tests/mason-core/installer/managers/luarocks_spec.lua @@ -0,0 +1,63 @@ +local installer = require "mason-core.installer" +local stub = require "luassert.stub" +local luarocks = require "mason-core.installer.managers.luarocks" + +describe("luarocks manager", function() + it("should install", function() + local ctx = create_dummy_context() + stub(ctx, "promote_cwd") + installer.exec_in_context(ctx, function() + luarocks.install("my-rock", "1.0.0") + end) + + assert.spy(ctx.promote_cwd).was_called(1) + assert.spy(ctx.spawn.luarocks).was_called(1) + assert.spy(ctx.spawn.luarocks).was_called_with { + "install", + { "--tree", ctx.cwd:get() }, + vim.NIL, -- dev + vim.NIL, -- server + { "my-rock", "1.0.0" }, + } + end) + + it("should install dev mode", function() + local ctx = create_dummy_context() + stub(ctx, "promote_cwd") + installer.exec_in_context(ctx, function() + luarocks.install("my-rock", "1.0.0", { + dev = true, + }) + end) + + assert.spy(ctx.promote_cwd).was_called(1) + assert.spy(ctx.spawn.luarocks).was_called(1) + assert.spy(ctx.spawn.luarocks).was_called_with { + "install", + { "--tree", ctx.cwd:get() }, + "--dev", + vim.NIL, -- server + { "my-rock", "1.0.0" }, + } + end) + + it("should install using provided server", function() + local ctx = create_dummy_context() + stub(ctx, "promote_cwd") + installer.exec_in_context(ctx, function() + luarocks.install("my-rock", "1.0.0", { + server = "https://luarocks.org/dev", + }) + end) + + assert.spy(ctx.promote_cwd).was_called(1) + assert.spy(ctx.spawn.luarocks).was_called(1) + assert.spy(ctx.spawn.luarocks).was_called_with { + "install", + { "--tree", ctx.cwd:get() }, + vim.NIL, -- dev + "--server=https://luarocks.org/dev", + { "my-rock", "1.0.0" }, + } + end) +end) diff --git a/tests/mason-core/installer/managers/npm_spec.lua b/tests/mason-core/installer/managers/npm_spec.lua new file mode 100644 index 00000000..655acb64 --- /dev/null +++ b/tests/mason-core/installer/managers/npm_spec.lua @@ -0,0 +1,53 @@ +local installer = require "mason-core.installer" +local stub = require "luassert.stub" +local match = require "luassert.match" +local npm = require "mason-core.installer.managers.npm" + +describe("npm manager", function() + it("should init package.json", function() + local ctx = create_dummy_context() + stub(ctx.fs, "append_file") + installer.exec_in_context(ctx, function() + npm.init() + end) + + assert.spy(ctx.spawn.npm).was_called(1) + assert.spy(ctx.spawn.npm).was_called_with { + "init", + "--yes", + "--scope=mason", + } + assert.spy(ctx.fs.append_file).was_called(1) + assert.spy(ctx.fs.append_file).was_called_with(match.is_ref(ctx.fs), ".npmrc", "global-style=true") + end) + + it("should install", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + npm.install("my-package", "1.0.0") + end) + + assert.spy(ctx.spawn.npm).was_called(1) + assert.spy(ctx.spawn.npm).was_called_with { + "install", + "my-package@1.0.0", + vim.NIL, -- extra_packages + } + end) + + it("should install extra packages", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + npm.install("my-package", "1.0.0", { + extra_packages = { "extra-package" }, + }) + end) + + assert.spy(ctx.spawn.npm).was_called(1) + assert.spy(ctx.spawn.npm).was_called_with { + "install", + "my-package@1.0.0", + { "extra-package" }, + } + end) +end) diff --git a/tests/mason-core/installer/managers/nuget_spec.lua b/tests/mason-core/installer/managers/nuget_spec.lua new file mode 100644 index 00000000..1bdecf37 --- /dev/null +++ b/tests/mason-core/installer/managers/nuget_spec.lua @@ -0,0 +1,21 @@ +local installer = require "mason-core.installer" +local nuget = require "mason-core.installer.managers.nuget" + +describe("nuget manager", function() + it("should install", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + nuget.install("nuget-package", "1.0.0") + end) + + assert.spy(ctx.spawn.dotnet).was_called(1) + assert.spy(ctx.spawn.dotnet).was_called_with { + "tool", + "update", + "--tool-path", + ".", + { "--version", "1.0.0" }, + "nuget-package", + } + end) +end) diff --git a/tests/mason-core/installer/managers/opam_spec.lua b/tests/mason-core/installer/managers/opam_spec.lua new file mode 100644 index 00000000..c1fe59f6 --- /dev/null +++ b/tests/mason-core/installer/managers/opam_spec.lua @@ -0,0 +1,20 @@ +local installer = require "mason-core.installer" +local opam = require "mason-core.installer.managers.opam" + +describe("opam manager", function() + it("should install", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + opam.install("opam-package", "1.0.0") + end) + + assert.spy(ctx.spawn.opam).was_called(1) + assert.spy(ctx.spawn.opam).was_called_with { + "install", + "--destdir=.", + "--yes", + "--verbose", + "opam-package.1.0.0", + } + end) +end) diff --git a/tests/mason-core/installer/managers/pypi_spec.lua b/tests/mason-core/installer/managers/pypi_spec.lua new file mode 100644 index 00000000..f0a6cdc6 --- /dev/null +++ b/tests/mason-core/installer/managers/pypi_spec.lua @@ -0,0 +1,126 @@ +local installer = require "mason-core.installer" +local stub = require "luassert.stub" +local path = require "mason-core.path" +local pypi = require "mason-core.installer.managers.pypi" + +---@param ctx InstallContext +local function venv_py(ctx) + return path.concat { + ctx.cwd:get(), + "venv", + "bin", + "python", + } +end + +describe("pypi manager", function() + it("should init venv without upgrading pip", function() + local ctx = create_dummy_context() + stub(ctx, "promote_cwd") + installer.exec_in_context(ctx, function() + pypi.init { upgrade_pip = false } + end) + + assert.spy(ctx.promote_cwd).was_called(1) + assert.spy(ctx.spawn.python3).was_called(1) + assert.spy(ctx.spawn.python3).was_called_with { + "-m", + "venv", + "venv", + } + end) + + it("should init venv and upgrade pip", function() + local ctx = create_dummy_context() + stub(ctx, "promote_cwd") + installer.exec_in_context(ctx, function() + pypi.init { upgrade_pip = true, install_extra_args = { "--proxy", "http://localhost" } } + end) + + assert.spy(ctx.promote_cwd).was_called(1) + assert.spy(ctx.spawn.python3).was_called(1) + assert.spy(ctx.spawn.python3).was_called_with { + "-m", + "venv", + "venv", + } + assert.spy(ctx.spawn[venv_py(ctx)]).was_called(1) + assert.spy(ctx.spawn[venv_py(ctx)]).was_called_with { + "-m", + "pip", + "--disable-pip-version-check", + "install", + "-U", + { "--proxy", "http://localhost" }, + { "pip" }, + } + end) + + it("should install", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + pypi.install("pypi-package", "1.0.0") + end) + + assert.spy(ctx.spawn[venv_py(ctx)]).was_called(1) + assert.spy(ctx.spawn[venv_py(ctx)]).was_called_with { + "-m", + "pip", + "--disable-pip-version-check", + "install", + "-U", + vim.NIL, -- install_extra_args + { + "pypi-package==1.0.0", + vim.NIL, -- extra_packages + }, + } + end) + + it("should install extra specifier", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + pypi.install("pypi-package", "1.0.0", { + extra = "lsp", + }) + end) + + assert.spy(ctx.spawn[venv_py(ctx)]).was_called(1) + assert.spy(ctx.spawn[venv_py(ctx)]).was_called_with { + "-m", + "pip", + "--disable-pip-version-check", + "install", + "-U", + vim.NIL, -- install_extra_args + { + "pypi-package[lsp]==1.0.0", + vim.NIL, -- extra_packages + }, + } + end) + + it("should install extra packages", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + pypi.install("pypi-package", "1.0.0", { + extra_packages = { "extra-package" }, + install_extra_args = { "--proxy", "http://localhost:9000" }, + }) + end) + + assert.spy(ctx.spawn[venv_py(ctx)]).was_called(1) + assert.spy(ctx.spawn[venv_py(ctx)]).was_called_with { + "-m", + "pip", + "--disable-pip-version-check", + "install", + "-U", + { "--proxy", "http://localhost:9000" }, + { + "pypi-package==1.0.0", + { "extra-package" }, + }, + } + end) +end) diff --git a/tests/mason-core/installer/managers/std_spec.lua b/tests/mason-core/installer/managers/std_spec.lua new file mode 100644 index 00000000..feff9abe --- /dev/null +++ b/tests/mason-core/installer/managers/std_spec.lua @@ -0,0 +1,150 @@ +local installer = require "mason-core.installer" +local stub = require "luassert.stub" +local match = require "luassert.match" +local std = require "mason-core.installer.managers.std" + +describe("std unpack [Unix]", function() + it("should unpack .gz", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + std.unpack "file.gz" + end) + + assert.spy(ctx.spawn.gzip).was_called(1) + assert.spy(ctx.spawn.gzip).was_called_with { "-d", "file.gz" } + end) + + it("should unpack .tar", function() + local ctx = create_dummy_context() + stub(ctx.fs, "unlink") + installer.exec_in_context(ctx, function() + std.unpack "file.tar" + end) + + assert.spy(ctx.spawn.tar).was_called(1) + assert.spy(ctx.spawn.tar).was_called_with { "--no-same-owner", "-xvf", "file.tar" } + assert.spy(ctx.fs.unlink).was_called(1) + assert.spy(ctx.fs.unlink).was_called_with(match.is_ref(ctx.fs), "file.tar") + end) + + it("should unpack .tar.bz2", function() + local ctx = create_dummy_context() + stub(ctx.fs, "unlink") + installer.exec_in_context(ctx, function() + std.unpack "file.tar.bz2" + end) + + assert.spy(ctx.spawn.tar).was_called(1) + assert.spy(ctx.spawn.tar).was_called_with { "--no-same-owner", "-xvf", "file.tar.bz2" } + assert.spy(ctx.fs.unlink).was_called(1) + assert.spy(ctx.fs.unlink).was_called_with(match.is_ref(ctx.fs), "file.tar.bz2") + end) + + it("should unpack .tar.gz", function() + local ctx = create_dummy_context() + stub(ctx.fs, "unlink") + installer.exec_in_context(ctx, function() + std.unpack "file.tar.gz" + end) + + assert.spy(ctx.spawn.tar).was_called(1) + assert.spy(ctx.spawn.tar).was_called_with { "--no-same-owner", "-xvf", "file.tar.gz" } + assert.spy(ctx.fs.unlink).was_called(1) + assert.spy(ctx.fs.unlink).was_called_with(match.is_ref(ctx.fs), "file.tar.gz") + end) + + it("should unpack .tar.xz", function() + local ctx = create_dummy_context() + stub(ctx.fs, "unlink") + installer.exec_in_context(ctx, function() + std.unpack "file.tar.xz" + end) + + assert.spy(ctx.spawn.tar).was_called(1) + assert.spy(ctx.spawn.tar).was_called_with { "--no-same-owner", "-xvf", "file.tar.xz" } + assert.spy(ctx.fs.unlink).was_called(1) + assert.spy(ctx.fs.unlink).was_called_with(match.is_ref(ctx.fs), "file.tar.xz") + end) + + it("should unpack .tar.zst", function() + local ctx = create_dummy_context() + stub(ctx.fs, "unlink") + installer.exec_in_context(ctx, function() + std.unpack "file.tar.zst" + end) + + assert.spy(ctx.spawn.tar).was_called(1) + assert.spy(ctx.spawn.tar).was_called_with { "--no-same-owner", "-xvf", "file.tar.zst" } + assert.spy(ctx.fs.unlink).was_called(1) + assert.spy(ctx.fs.unlink).was_called_with(match.is_ref(ctx.fs), "file.tar.zst") + end) + + it("should unpack .vsix", function() + local ctx = create_dummy_context() + stub(ctx.fs, "unlink") + installer.exec_in_context(ctx, function() + std.unpack "file.vsix" + end) + + assert.spy(ctx.spawn.unzip).was_called(1) + assert.spy(ctx.spawn.unzip).was_called_with { "-d", ".", "file.vsix" } + assert.spy(ctx.fs.unlink).was_called(1) + assert.spy(ctx.fs.unlink).was_called_with(match.is_ref(ctx.fs), "file.vsix") + end) + + it("should unpack .zip", function() + local ctx = create_dummy_context() + stub(ctx.fs, "unlink") + installer.exec_in_context(ctx, function() + std.unpack "file.zip" + end) + + assert.spy(ctx.spawn.unzip).was_called(1) + assert.spy(ctx.spawn.unzip).was_called_with { "-d", ".", "file.zip" } + assert.spy(ctx.fs.unlink).was_called(1) + assert.spy(ctx.fs.unlink).was_called_with(match.is_ref(ctx.fs), "file.zip") + end) +end) + +describe("std clone", function() + it("should clone", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + std.clone "https://github.com/williamboman/mason.nvim" + end) + + assert.spy(ctx.spawn.git).was_called(1) + assert.spy(ctx.spawn.git).was_called_with { + "clone", + "--depth", + "1", + vim.NIL, -- recursive + "https://github.com/williamboman/mason.nvim", + ".", + } + end) + + it("should clone and checkout rev", function() + local ctx = create_dummy_context() + installer.exec_in_context(ctx, function() + std.clone("https://github.com/williamboman/mason.nvim", { + rev = "e1fd03b1856cb5ad8425f49e18353dc524b02f91", + recursive = true, + }) + end) + + assert.spy(ctx.spawn.git).was_called(3) + assert.spy(ctx.spawn.git).was_called_with { + "clone", + "--depth", + "1", + "--recursive", + "https://github.com/williamboman/mason.nvim", + ".", + } + assert + .spy(ctx.spawn.git) + .was_called_with { "fetch", "--depth", "1", "origin", "e1fd03b1856cb5ad8425f49e18353dc524b02f91" } + assert.spy(ctx.spawn.git).was_called_with { "checkout", "FETCH_HEAD" } + end) +end) diff --git a/tests/mason-core/installer/registry/installer_spec.lua b/tests/mason-core/installer/registry/installer_spec.lua new file mode 100644 index 00000000..e6ca6f91 --- /dev/null +++ b/tests/mason-core/installer/registry/installer_spec.lua @@ -0,0 +1,203 @@ +local match = require "luassert.match" +local stub = require "luassert.stub" +local Result = require "mason-core.result" +local installer = require "mason-core.installer.registry" +local util = require "mason-core.installer.registry.util" + +---@type InstallerProvider +local dummy_provider = { + ---@param source RegistryPackageSource + ---@param purl Purl + ---@param opts PackageInstallOpts + parse = function(source, purl, opts) + return Result.try(function(try) + if source.supported_platforms then + try(util.ensure_valid_platform(source.supported_platforms)) + end + return { + package = purl.name, + extra_info = source.extra_info, + should_fail = source.should_fail, + } + end) + end, + install = function(ctx, source) + if source.should_fail then + return Result.failure "This is a failure." + else + return Result.success() + end + end, +} + +describe("registry installer :: parsing", function() + it("should parse valid package specs", function() + installer.register_provider("dummy", dummy_provider) + + local result = installer.parse({ + schema = "registry+v1", + source = { + id = "pkg:dummy/package-name@v1.2.3", + extra_info = "here", + }, + }, {}) + local parsed = result:get_or_nil() + + assert.is_true(result:is_success()) + assert.is_true(match.is_ref(dummy_provider)(parsed.provider)) + assert.same({ + name = "package-name", + scheme = "pkg", + type = "dummy", + version = "v1.2.3", + }, parsed.purl) + assert.same({ + package = "package-name", + extra_info = "here", + }, parsed.source) + end) + + it("should reject incompatible schema versions", function() + installer.register_provider("dummy", dummy_provider) + + local result = installer.parse({ + schema = "registry+v1337", + source = { + id = "pkg:dummy/package-name@v1.2.3", + }, + }, {}) + assert.same( + Result.failure [[Current version of mason.nvim is not capable of parsing package schema version "registry+v1337".]], + result + ) + end) + + it("should use requested version", function() + installer.register_provider("dummy", dummy_provider) + + local result = installer.parse({ + schema = "registry+v1", + source = { + id = "pkg:dummy/package-name@v1.2.3", + }, + }, { version = "v2.0.0" }) + + assert.is_true(result:is_success()) + local parsed = result:get_or_nil() + + assert.same({ + name = "package-name", + scheme = "pkg", + type = "dummy", + version = "v2.0.0", + }, parsed.purl) + end) + + it("should handle PLATFORM_UNSUPPORTED", function() + installer.register_provider("dummy", dummy_provider) + + local result = installer.compile({ + schema = "registry+v1", + source = { + id = "pkg:dummy/package-name@v1.2.3", + supported_platforms = { "VIC64" }, + }, + }, { version = "v2.0.0" }) + + assert.same(Result.failure "The current platform is unsupported.", result) + end) + + it("should error upon parsing failures", function() + installer.register_provider("dummy", dummy_provider) + + local result = installer.compile({ + schema = "registry+v1", + source = { + id = "pkg:dummy/package-name@v1.2.3", + supported_platforms = { "VIC64" }, + }, + }, { version = "v2.0.0" }) + + assert.same(Result.failure "The current platform is unsupported.", result) + end) +end) + +describe("registry installer :: compiling", function() + it("should run compiled installer function successfully", function() + installer.register_provider("dummy", dummy_provider) + + local result = installer.compile({ + schema = "registry+v1", + source = { + id = "pkg:dummy/package-name@v1.2.3", + }, + }, {}) + + assert.is_true(result:is_success()) + local installer_fn = result:get_or_nil() + + local ctx = create_dummy_context() + local installer_result = require("mason-core.installer").exec_in_context(ctx, installer_fn) + assert.same(Result.success(), installer_result) + end) + + it("should raise errors upon installer failures", function() + installer.register_provider("dummy", dummy_provider) + + local result = installer.compile({ + schema = "registry+v1", + source = { + id = "pkg:dummy/package-name@v1.2.3", + should_fail = true, + }, + }, {}) + + assert.is_true(result:is_success()) + local installer_fn = result:get_or_nil() + + local ctx = create_dummy_context() + local err = assert.has_error(function() + require("mason-core.installer").exec_in_context(ctx, installer_fn) + end) + assert.equals("This is a failure.", err) + end) + + it("should register links", function() + installer.register_provider("dummy", dummy_provider) + local link = require "mason-core.installer.registry.link" + stub(link, "bin", mockx.returns(Result.success())) + stub(link, "share", mockx.returns(Result.success())) + stub(link, "opt", mockx.returns(Result.success())) + + local spec = { + schema = "registry+v1", + source = { + id = "pkg:dummy/package-name@v1.2.3", + }, + bin = { ["exec"] = "exec" }, + opt = { ["opt/"] = "opt/" }, + share = { ["share/"] = "share/" }, + } + + local result = installer.compile(spec, {}) + + assert.is_true(result:is_success()) + local installer_fn = result:get_or_nil() + + local ctx = create_dummy_context() + local installer_result = require("mason-core.installer").exec_in_context(ctx, installer_fn) + assert.is_true(installer_result:is_success()) + + for _, spy in ipairs { link.bin, link.share, link.opt } do + assert.spy(spy).was_called(1) + assert.spy(spy).was_called_with(match.is_ref(ctx), spec, { + scheme = "pkg", + type = "dummy", + name = "package-name", + version = "v1.2.3", + }, { + package = "package-name", + }) + end + end) +end) diff --git a/tests/mason-core/installer/registry/link_spec.lua b/tests/mason-core/installer/registry/link_spec.lua new file mode 100644 index 00000000..eef66349 --- /dev/null +++ b/tests/mason-core/installer/registry/link_spec.lua @@ -0,0 +1,231 @@ +local stub = require "luassert.stub" +local match = require "luassert.match" +local Result = require "mason-core.result" +local Purl = require "mason-core.purl" +local link = require "mason-core.installer.registry.link" +local fs = require "mason-core.fs" +local path = require "mason-core.path" + +describe("registry linker", function() + it("should expand bin table", function() + local ctx = create_dummy_context() + stub(ctx.fs, "file_exists") + stub(ctx.fs, "chmod") + stub(ctx.fs, "fstat") + + ctx.fs.file_exists.on_call_with(match.is_ref(ctx.fs), "exec.sh").returns(true) + ctx.fs.fstat.on_call_with(match.is_ref(ctx.fs), "exec.sh").returns { + mode = 493, -- 0755 + } + + local result = link.bin( + ctx, + { + bin = { + ["exec"] = "exec.sh", + }, + }, + Purl.parse("pkg:dummy/package@v1.0.0"):get_or_throw(), + { + metadata = "value", + } + ) + + assert.same( + Result.success { + ["exec"] = "exec.sh", + }, + result + ) + assert.same({ + ["exec"] = "exec.sh", + }, ctx.links.bin) + + assert.spy(ctx.fs.chmod).was_not_called() + end) + + it("should chmod executable if necessary", function() + local ctx = create_dummy_context() + stub(ctx.fs, "file_exists") + stub(ctx.fs, "chmod") + stub(ctx.fs, "fstat") + + ctx.fs.file_exists.on_call_with(match.is_ref(ctx.fs), "exec.sh").returns(true) + ctx.fs.fstat.on_call_with(match.is_ref(ctx.fs), "exec.sh").returns { + mode = 420, -- 0644 + } + + local result = link.bin( + ctx, + { + bin = { + ["exec"] = "exec.sh", + }, + }, + Purl.parse("pkg:dummy/package@v1.0.0"):get_or_throw(), + { + metadata = "value", + } + ) + + assert.is_true(result:is_success()) + assert.spy(ctx.fs.chmod).was_called(1) + assert.spy(ctx.fs.chmod).was_called_with(match.is_ref(ctx.fs), "exec.sh", 493) + end) + + it("should interpolate bin table", function() + local ctx = create_dummy_context() + stub(ctx.fs, "file_exists") + stub(ctx.fs, "chmod") + stub(ctx.fs, "fstat") + + ctx.fs.file_exists.on_call_with(match.is_ref(ctx.fs), "v1.0.0-exec.sh").returns(true) + ctx.fs.fstat.on_call_with(match.is_ref(ctx.fs), "v1.0.0-exec.sh").returns { + mode = 493, -- 0755 + } + + local result = link.bin( + ctx, + { + bin = { + ["exec"] = "{{version}}-{{source.script}}", + }, + }, + Purl.parse("pkg:dummy/package@v1.0.0"):get_or_throw(), + { + script = "exec.sh", + } + ) + + assert.same( + Result.success { + ["exec"] = "v1.0.0-exec.sh", + }, + result + ) + end) + + it("should delegate bin paths", function() + local ctx = create_dummy_context() + stub(ctx.fs, "file_exists") + stub(ctx.fs, "chmod") + stub(ctx.fs, "fstat") + + local matrix = { + ["cargo:executable"] = "bin/executable", + ["composer:executable"] = "vendor/bin/executable", + ["golang:executable"] = "executable", + ["luarocks:executable"] = "bin/executable", + ["npm:executable"] = "node_modules/.bin/executable", + ["nuget:executable"] = "executable", + ["opam:executable"] = "bin/executable", + ["pypi:executable"] = "venv/bin/executable", + } + + for bin, path in pairs(matrix) do + ctx.fs.file_exists.on_call_with(match.is_ref(ctx.fs), path).returns(true) + ctx.fs.fstat.on_call_with(match.is_ref(ctx.fs), path).returns { + mode = 493, -- 0755 + } + + local result = link.bin(ctx, { + bin = { + ["executable"] = bin, + }, + }, Purl.parse("pkg:dummy/package@v1.0.0"):get_or_throw(), {}) + + assert.same( + Result.success { + ["executable"] = path, + }, + result + ) + end + end) + + it("should register share links", function() + local ctx = create_dummy_context() + stub(ctx.fs, "file_exists") + stub(fs.sync, "file_exists") + stub(vim.fn, "glob") + + vim.fn.glob.on_call_with(path.concat { ctx.cwd:get(), "v1.0.0/dir/" } .. "**/*", false, true).returns { + path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file1" }, + path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file2" }, + path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file3" }, + } + fs.sync.file_exists.on_call_with(path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file1" }).returns(true) + fs.sync.file_exists.on_call_with(path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file2" }).returns(true) + fs.sync.file_exists.on_call_with(path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file3" }).returns(true) + + ctx.fs.file_exists.on_call_with(match.is_ref(ctx.fs), "v1.0.0-exec.sh").returns(true) + + local result = link.share( + ctx, + { + share = { + ["file"] = "{{version}}-{{source.file}}", + ["dir/"] = "{{version}}/dir/", + ["empty/"] = "{{source.empty}}", + }, + }, + Purl.parse("pkg:dummy/package@v1.0.0"):get_or_throw(), + { + file = "file", + } + ) + + assert.same( + Result.success { + ["file"] = "v1.0.0-file", + ["dir/file1"] = "v1.0.0/dir/file1", + ["dir/file2"] = "v1.0.0/dir/file2", + ["dir/file3"] = "v1.0.0/dir/file3", + }, + result + ) + end) + + it("should register opt links", function() + local ctx = create_dummy_context() + stub(ctx.fs, "file_exists") + stub(fs.sync, "file_exists") + stub(vim.fn, "glob") + + vim.fn.glob.on_call_with(path.concat { ctx.cwd:get(), "v1.0.0/dir/" } .. "**/*", false, true).returns { + path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file1" }, + path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file2" }, + path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file3" }, + } + fs.sync.file_exists.on_call_with(path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file1" }).returns(true) + fs.sync.file_exists.on_call_with(path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file2" }).returns(true) + fs.sync.file_exists.on_call_with(path.concat { ctx.cwd:get(), "v1.0.0", "dir", "file3" }).returns(true) + + ctx.fs.file_exists.on_call_with(match.is_ref(ctx.fs), "v1.0.0-exec.sh").returns(true) + + local result = link.opt( + ctx, + { + opt = { + ["file"] = "{{version}}-{{source.file}}", + ["dir/"] = "{{version}}/dir/", + ["empty/"] = "{{source.empty}}", + }, + }, + Purl.parse("pkg:dummy/package@v1.0.0"):get_or_throw(), + { + file = "file", + } + ) + + assert.same( + Result.success { + ["file"] = "v1.0.0-file", + ["dir/file1"] = "v1.0.0/dir/file1", + ["dir/file2"] = "v1.0.0/dir/file2", + ["dir/file3"] = "v1.0.0/dir/file3", + }, + result + ) + end) +end) diff --git a/tests/mason-core/installer/registry/providers/cargo_spec.lua b/tests/mason-core/installer/registry/providers/cargo_spec.lua new file mode 100644 index 00000000..f2ae679c --- /dev/null +++ b/tests/mason-core/installer/registry/providers/cargo_spec.lua @@ -0,0 +1,143 @@ +local stub = require "luassert.stub" +local Result = require "mason-core.result" +local cargo = require "mason-core.installer.registry.providers.cargo" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:cargo/crate-name@1.4.3"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("cargo provider :: parsing", function() + it("should parse package", function() + assert.same( + Result.success { + crate = "crate-name", + version = "1.4.3", + features = nil, + locked = true, + git = nil, + }, + cargo.parse({}, purl()) + ) + end) + + it("should respect repository_url qualifier", function() + assert.same( + Result.success { + crate = "crate-name", + version = "1.4.3", + features = nil, + locked = true, + git = { url = "https://github.com/crate-org/crate-name", rev = false }, + }, + cargo.parse({}, purl { qualifiers = { repository_url = "https://github.com/crate-org/crate-name" } }) + ) + end) + + it("should respect repository_url qualifier with rev=true qualifier", function() + assert.same( + Result.success { + crate = "crate-name", + version = "1.4.3", + features = nil, + locked = true, + git = { url = "https://github.com/crate-org/crate-name", rev = true }, + }, + cargo.parse( + {}, + purl { qualifiers = { repository_url = "https://github.com/crate-org/crate-name", rev = "true" } } + ) + ) + end) + + it("should respect features qualifier", function() + assert.same( + Result.success { + crate = "crate-name", + version = "1.4.3", + features = "lsp,cli", + locked = true, + git = nil, + }, + cargo.parse({}, purl { qualifiers = { features = "lsp,cli" } }) + ) + end) + + it("should respect locked qualifier", function() + assert.same( + Result.success { + crate = "crate-name", + version = "1.4.3", + features = nil, + locked = false, + git = nil, + }, + cargo.parse({}, purl { qualifiers = { locked = "false" } }) + ) + end) + + it("should check supported platforms", function() + assert.same( + Result.failure "PLATFORM_UNSUPPORTED", + cargo.parse({ + supported_platforms = { "VIC64" }, + }, purl { qualifiers = { locked = "false" } }) + ) + end) +end) + +describe("cargo provider :: installing", function() + it("should install cargo packages", function() + local ctx = create_dummy_context() + local manager = require "mason-core.installer.managers.cargo" + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return cargo.install(ctx, { + crate = "crate-name", + version = "1.2.0", + features = nil, + locked = true, + git = nil, + }) + end) + + assert.is_true(result:is_success()) + assert.spy(manager.install).was_called(1) + assert.spy(manager.install).was_called_with("crate-name", "1.2.0", { + git = nil, + features = nil, + locked = true, + }) + end) + + it("should ensure valid version", function() + local ctx = create_dummy_context { + version = "1.10.0", + } + local manager = require "mason-core.installer.managers.cargo" + local providers = require "mason-core.providers" + stub(providers.crates, "get_all_versions", mockx.returns(Result.success { "1.0.0" })) + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return cargo.install(ctx, { + crate = "crate-name", + version = "1.10.0", + features = nil, + locked = true, + git = nil, + }) + end) + + assert.is_true(result:is_failure()) + assert.same(Result.failure [[Version "1.10.0" is not available.]], result) + assert.spy(manager.install).was_called(0) + end) +end) diff --git a/tests/mason-core/installer/registry/providers/composer_spec.lua b/tests/mason-core/installer/registry/providers/composer_spec.lua new file mode 100644 index 00000000..4849e3f7 --- /dev/null +++ b/tests/mason-core/installer/registry/providers/composer_spec.lua @@ -0,0 +1,66 @@ +local stub = require "luassert.stub" +local Result = require "mason-core.result" +local composer = require "mason-core.installer.registry.providers.composer" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:composer/vendor/package@2.0.0"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("composer provider :: parsing", function() + it("should parse package", function() + assert.same( + Result.success { + package = "vendor/package", + version = "2.0.0", + }, + composer.parse({}, purl()) + ) + end) +end) + +describe("composer provider :: installing", function() + it("should install composer packages", function() + local ctx = create_dummy_context() + local manager = require "mason-core.installer.managers.composer" + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return composer.install(ctx, { + package = "vendor/package", + version = "1.2.0", + }) + end) + + assert.is_true(result:is_success()) + assert.spy(manager.install).was_called(1) + assert.spy(manager.install).was_called_with("vendor/package", "1.2.0") + end) + + it("should ensure valid version", function() + local ctx = create_dummy_context { + version = "1.10.0", + } + local manager = require "mason-core.installer.managers.composer" + local providers = require "mason-core.providers" + stub(providers.packagist, "get_all_versions", mockx.returns(Result.success { "1.0.0" })) + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return composer.install(ctx, { + package = "vendor/package", + version = "1.10.0", + }) + end) + + assert.is_true(result:is_failure()) + assert.same(Result.failure [[Version "1.10.0" is not available.]], result) + assert.spy(manager.install).was_called(0) + end) +end) diff --git a/tests/mason-core/installer/registry/providers/gem_spec.lua b/tests/mason-core/installer/registry/providers/gem_spec.lua new file mode 100644 index 00000000..9696ec6e --- /dev/null +++ b/tests/mason-core/installer/registry/providers/gem_spec.lua @@ -0,0 +1,72 @@ +local stub = require "luassert.stub" +local Result = require "mason-core.result" +local gem = require "mason-core.installer.registry.providers.gem" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:gem/package@1.2.0"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("gem provider :: parsing", function() + it("should parse package", function() + assert.same( + Result.success { + package = "package", + version = "1.2.0", + extra_packages = { "extra" }, + }, + gem.parse({ extra_packages = { "extra" } }, purl()) + ) + end) + + it("should check supported platforms", function() + assert.same(Result.failure "PLATFORM_UNSUPPORTED", gem.parse({ supported_platforms = { "VIC64" } }, purl())) + end) +end) + +describe("gem provider :: installing", function() + it("should install gem packages", function() + local ctx = create_dummy_context() + local manager = require "mason-core.installer.managers.gem" + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return gem.install(ctx, { + package = "package", + version = "5.2.0", + extra_packages = { "extra" }, + }) + end) + + assert.is_true(result:is_success()) + assert.spy(manager.install).was_called(1) + assert.spy(manager.install).was_called_with("package", "5.2.0", { extra_packages = { "extra" } }) + end) + + it("should ensure valid version", function() + local ctx = create_dummy_context { + version = "1.10.0", + } + local manager = require "mason-core.installer.managers.gem" + local providers = require "mason-core.providers" + stub(providers.rubygems, "get_all_versions", mockx.returns(Result.success { "1.0.0" })) + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return gem.install(ctx, { + package = "package", + version = "1.10.0", + }) + end) + + assert.is_true(result:is_failure()) + assert.same(Result.failure [[Version "1.10.0" is not available.]], result) + assert.spy(manager.install).was_called(0) + end) +end) diff --git a/tests/mason-core/installer/registry/providers/generic_spec.lua b/tests/mason-core/installer/registry/providers/generic_spec.lua new file mode 100644 index 00000000..899709c5 --- /dev/null +++ b/tests/mason-core/installer/registry/providers/generic_spec.lua @@ -0,0 +1,100 @@ +local stub = require "luassert.stub" +local Result = require "mason-core.result" +local generic = require "mason-core.installer.registry.providers.generic" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:generic/namespace/name@v1.2.0"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("generic provider :: parsing", function() + it("should parse single download target", function() + assert.same( + Result.success { + download = { + files = { + ["name.tar.gz"] = [[https://getpackage.org/downloads/1.2.0/name.tar.gz]], + }, + }, + }, + generic.parse({ + download = { + files = { + ["name.tar.gz"] = [[https://getpackage.org/downloads/{{version | strip_prefix "v"}}/name.tar.gz]], + }, + }, + }, purl()) + ) + end) + + it("should coalesce download target", function() + assert.same( + Result.success { + download = { + target = "linux_arm64", + files = { + ["name.tar.gz"] = [[https://getpackage.org/downloads/linux-aarch64/1.2.0/name.tar.gz]], + }, + }, + }, + generic.parse({ + download = { + { + target = "linux_arm64", + files = { + ["name.tar.gz"] = [[https://getpackage.org/downloads/linux-aarch64/{{version | strip_prefix "v"}}/name.tar.gz]], + }, + }, + { + target = "win_arm64", + files = { + ["name.tar.gz"] = [[https://getpackage.org/downloads/win-aarch64/{{version | strip_prefix "v"}}/name.tar.gz]], + }, + }, + }, + }, purl(), { target = "linux_arm64" }) + ) + end) + + it("should check supported platforms", function() + assert.same(Result.failure "PLATFORM_UNSUPPORTED", generic.parse({ supported_platforms = { "VIC64" } }, purl())) + end) +end) + +describe("generic provider :: installing", function() + it("should install generic packages", function() + local ctx = create_dummy_context() + local std = require "mason-core.installer.managers.std" + stub(std, "download_file", mockx.returns(Result.success())) + stub(std, "unpack", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return generic.install(ctx, { + download = { + files = { + ["name.tar.gz"] = [[https://getpackage.org/downloads/linux-aarch64/1.2.0/name.tar.gz]], + ["archive.tar.gz"] = [[https://getpackage.org/downloads/linux-aarch64/1.2.0/archive.tar.gz]], + }, + }, + }) + end) + + assert.is_true(result:is_success()) + assert.spy(std.download_file).was_called(2) + assert + .spy(std.download_file) + .was_called_with("https://getpackage.org/downloads/linux-aarch64/1.2.0/name.tar.gz", "name.tar.gz") + assert + .spy(std.download_file) + .was_called_with("https://getpackage.org/downloads/linux-aarch64/1.2.0/archive.tar.gz", "archive.tar.gz") + assert.spy(std.unpack).was_called(2) + assert.spy(std.unpack).was_called_with "name.tar.gz" + assert.spy(std.unpack).was_called_with "archive.tar.gz" + end) +end) diff --git a/tests/mason-core/installer/registry/providers/github_spec.lua b/tests/mason-core/installer/registry/providers/github_spec.lua new file mode 100644 index 00000000..0c43e3cf --- /dev/null +++ b/tests/mason-core/installer/registry/providers/github_spec.lua @@ -0,0 +1,355 @@ +local stub = require "luassert.stub" +local mock = require "luassert.mock" +local spy = require "luassert.spy" +local match = require "luassert.match" +local Result = require "mason-core.result" +local github = require "mason-core.installer.registry.providers.github" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" +local registry_installer = require "mason-core.installer.registry" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:github/namespace/name@2023-03-09"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("github provider :: parsing", function() + it("should parse release asset source", function() + assert.same( + Result.success { + repo = "namespace/name", + asset = { + file = "file-2023-03-09.jar", + }, + downloads = { + { + out_file = "file-2023-03-09.jar", + download_url = "https://github.com/namespace/name/releases/download/2023-03-09/file-2023-03-09.jar", + }, + }, + }, + github.parse({ + asset = { + file = "file-{{version}}.jar", + }, + }, purl()) + ) + end) + + it("should parse release asset source with multiple targets", function() + assert.same( + Result.success { + repo = "namespace/name", + asset = { + target = "linux_x64", + file = "file-linux-amd64-2023-03-09.tar.gz", + }, + downloads = { + { + out_file = "file-linux-amd64-2023-03-09.tar.gz", + download_url = "https://github.com/namespace/name/releases/download/2023-03-09/file-linux-amd64-2023-03-09.tar.gz", + }, + }, + }, + github.parse({ + asset = { + { + target = "win_arm", + file = "file-win-arm-{{version}}.zip", + }, + { + target = "linux_x64", + file = "file-linux-amd64-{{version}}.tar.gz", + }, + }, + }, purl(), { target = "linux_x64" }) + ) + end) + + it("should parse release asset source with output to different directory", function() + assert.same( + Result.success { + repo = "namespace/name", + asset = { + file = "file-linux-amd64-2023-03-09.tar.gz:out-dir/", + }, + downloads = { + { + out_file = "out-dir/file-linux-amd64-2023-03-09.tar.gz", + download_url = "https://github.com/namespace/name/releases/download/2023-03-09/file-linux-amd64-2023-03-09.tar.gz", + }, + }, + }, + github.parse({ + asset = { + file = "file-linux-amd64-{{version}}.tar.gz:out-dir/", + }, + }, purl(), { target = "linux_x64" }) + ) + end) + + it("should parse build source", function() + assert.same( + Result.success { + build = { run = [[npm install && npm run compile]] }, + repo = "https://github.com/namespace/name.git", + rev = "2023-03-09", + }, + github.parse({ + build = { + run = [[npm install && npm run compile]], + }, + }, purl()) + ) + end) + + it("should parse build source with multiple targets", function() + assert.same( + Result.success { + build = { target = "win_x64", run = [[npm install]] }, + repo = "https://github.com/namespace/name.git", + rev = "2023-03-09", + }, + github.parse({ + build = { + { + target = "linux_arm64", + run = [[npm install && npm run compile]], + }, + { + target = "win_x64", + run = [[npm install]], + }, + }, + }, purl(), { target = "win_x64" }) + ) + end) + + it("should upsert version overrides", function() + local result = registry_installer.parse({ + schema = "registry+v1", + source = { + id = "pkg:github/owner/repo@1.2.3", + asset = { + { + target = "darwin_x64", + file = "asset.tar.gz", + }, + }, + version_overrides = { + { + constraint = "semver:<=1.0.0", + asset = { + { + target = "darwin_x64", + file = "old-asset.tar.gz", + }, + }, + }, + }, + }, + }, { version = "1.0.0", target = "darwin_x64" }) + local parsed = result:get_or_nil() + + assert.is_true(result:is_success()) + assert.same({ + asset = { + target = "darwin_x64", + file = "old-asset.tar.gz", + }, + downloads = { + { + download_url = "https://github.com/owner/repo/releases/download/1.0.0/old-asset.tar.gz", + out_file = "old-asset.tar.gz", + }, + }, + repo = "owner/repo", + }, parsed.source) + end) + + it("should override source if version override provides its own purl id", function() + local result = registry_installer.parse({ + schema = "registry+v1", + source = { + id = "pkg:github/owner/repo@1.2.3", + asset = { + file = "asset.tar.gz", + }, + version_overrides = { + { + constraint = "semver:<=1.0.0", + id = "pkg:npm/old-package", + }, + }, + }, + }, { version = "1.0.0", target = "darwin_x64" }) + + assert.is_true(result:is_success()) + local parsed = result:get_or_throw() + assert.same({ + type = "npm", + scheme = "pkg", + name = "old-package", + version = "1.0.0", + }, parsed.purl) + end) +end) + +describe("github provider :: installing", function() + it("should install github release assets", function() + local ctx = create_dummy_context() + local std = require "mason-core.installer.managers.std" + stub(std, "download_file", mockx.returns(Result.success())) + stub(std, "unpack", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return github.install(ctx, { + repo = "namespace/name", + asset = { + file = "file-linux-amd64-2023-03-09.tar.gz", + }, + downloads = { + { + out_file = "file-linux-amd64-2023-03-09.tar.gz", + download_url = "https://github.com/namespace/name/releases/download/2023-03-09/file-linux-amd64-2023-03-09.tar.gz", + }, + { + out_file = "another-file-linux-amd64-2023-03-09.tar.gz", + download_url = "https://github.com/namespace/name/releases/download/2023-03-09/another-file-linux-amd64-2023-03-09.tar.gz", + }, + }, + }) + end) + + assert.is_true(result:is_success()) + assert.spy(std.download_file).was_called(2) + assert.spy(std.download_file).was_called_with( + "https://github.com/namespace/name/releases/download/2023-03-09/file-linux-amd64-2023-03-09.tar.gz", + "file-linux-amd64-2023-03-09.tar.gz" + ) + assert.spy(std.download_file).was_called_with( + "https://github.com/namespace/name/releases/download/2023-03-09/another-file-linux-amd64-2023-03-09.tar.gz", + "another-file-linux-amd64-2023-03-09.tar.gz" + ) + assert.spy(std.unpack).was_called(2) + assert.spy(std.unpack).was_called_with "file-linux-amd64-2023-03-09.tar.gz" + assert.spy(std.unpack).was_called_with "another-file-linux-amd64-2023-03-09.tar.gz" + end) + + it("should install github release assets into specified output directory", function() + local ctx = create_dummy_context() + local std = require "mason-core.installer.managers.std" + local download_file_cwd, unpack_cwd + stub(std, "download_file", function() + download_file_cwd = ctx.cwd:get() + return Result.success() + end) + stub(std, "unpack", function() + unpack_cwd = ctx.cwd:get() + return Result.success() + end) + stub(ctx.fs, "mkdirp") + spy.on(ctx, "chdir") + + local result = installer.exec_in_context(ctx, function() + return github.install(ctx, { + repo = "namespace/name", + asset = { + file = "file.zip", + }, + downloads = { + { + out_file = "out/dir/file.zip", + download_url = "https://github.com/namespace/name/releases/download/2023-03-09/file.zip", + }, + }, + }) + end) + + assert.is_true(result:is_success()) + assert.spy(ctx.fs.mkdirp).was_called(1) + assert.spy(ctx.fs.mkdirp).was_called_with(match.is_ref(ctx.fs), "out/dir") + assert.spy(ctx.chdir).was_called(1) + assert.spy(ctx.chdir).was_called_with(match.is_ref(ctx), "out/dir", match.is_function()) + assert.spy(std.download_file).was_called(1) + assert.is_true(match.matches "out/dir$"(download_file_cwd)) + assert + .spy(std.download_file) + .was_called_with("https://github.com/namespace/name/releases/download/2023-03-09/file.zip", "file.zip") + assert.spy(std.unpack).was_called(1) + assert.is_true(match.matches "out/dir$"(unpack_cwd)) + assert.spy(std.unpack).was_called_with "file.zip" + end) + + it("should install ensure valid version when installing release asset", function() + local ctx = create_dummy_context { + version = "1.42.0", + } + local std = require "mason-core.installer.managers.std" + local providers = require "mason-core.providers" + stub(std, "download_file") + stub(providers.github, "get_all_release_versions", mockx.returns(Result.success { "2023-03-09" })) + + local result = installer.exec_in_context(ctx, function() + return github.install(ctx, { + repo = "namespace/name", + asset = { + file = "file.zip", + }, + downloads = { + { + out_file = "out/dir/file.zip", + download_url = "https://github.com/namespace/name/releases/download/2023-03-09/file.zip", + }, + }, + }) + end) + + assert.is_true(result:is_failure()) + assert.same(Result.failure [[Version "1.42.0" is not available.]], result) + assert.spy(std.download_file).was_called(0) + end) + + it("should install github build sources", function() + local ctx = create_dummy_context() + local std = require "mason-core.installer.managers.std" + local uv = require "mason-core.async.uv" + stub(uv, "write") + stub(uv, "shutdown") + stub(uv, "close") + local stdin = mock.new() + stub(std, "clone", mockx.returns(Result.success())) + stub( + ctx.spawn, + "bash", ---@param args SpawnArgs + function(args) + args.on_spawn(mock.new(), { stdin }) + return Result.success() + end + ) + + local result = installer.exec_in_context(ctx, function() + return github.install(ctx, { + repo = "namespace/name", + rev = "2023-03-09", + build = { + run = [[npm install && npm run compile]], + }, + }) + end) + + assert.is_true(result:is_success()) + assert.spy(std.clone).was_called(1) + assert.spy(std.clone).was_called_with("namespace/name", { rev = "2023-03-09" }) + assert.spy(ctx.spawn.bash).was_called(1) + assert.spy(uv.write).was_called(2) + assert.spy(uv.write).was_called_with(stdin, "set -euxo pipefail;\n") + assert.spy(uv.write).was_called_with(stdin, "npm install && npm run compile") + assert.spy(uv.shutdown).was_called_with(stdin) + assert.spy(uv.close).was_called_with(stdin) + end) +end) diff --git a/tests/mason-core/installer/registry/providers/golang_spec.lua b/tests/mason-core/installer/registry/providers/golang_spec.lua new file mode 100644 index 00000000..d7b9f448 --- /dev/null +++ b/tests/mason-core/installer/registry/providers/golang_spec.lua @@ -0,0 +1,68 @@ +local stub = require "luassert.stub" +local Result = require "mason-core.result" +local golang = require "mason-core.installer.registry.providers.golang" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:golang/namespace/package@v1.5.0"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("golang provider :: parsing", function() + it("should parse package", function() + assert.same( + Result.success { + package = "namespace/package", + version = "v1.5.0", + extra_packages = { "extra" }, + }, + golang.parse({ extra_packages = { "extra" } }, purl()) + ) + end) +end) + +describe("golang provider :: installing", function() + it("should install golang packages", function() + local ctx = create_dummy_context() + local manager = require "mason-core.installer.managers.golang" + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return golang.install(ctx, { + package = "namespace/package", + version = "v1.5.0", + extra_packages = { "extra" }, + }) + end) + + assert.is_true(result:is_success()) + assert.spy(manager.install).was_called(1) + assert.spy(manager.install).was_called_with("namespace/package", "v1.5.0", { extra_packages = { "extra" } }) + end) + + it("should ensure valid version", function() + local ctx = create_dummy_context { + version = "1.10.0", + } + local manager = require "mason-core.installer.managers.golang" + local providers = require "mason-core.providers" + stub(providers.golang, "get_all_versions", mockx.returns(Result.success { "1.0.0" })) + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return golang.install(ctx, { + package = "package", + version = "1.10.0", + }) + end) + + assert.is_true(result:is_failure()) + assert.same(Result.failure [[Version "1.10.0" is not available.]], result) + assert.spy(manager.install).was_called(0) + end) +end) diff --git a/tests/mason-core/installer/registry/providers/luarocks_spec.lua b/tests/mason-core/installer/registry/providers/luarocks_spec.lua new file mode 100644 index 00000000..992726eb --- /dev/null +++ b/tests/mason-core/installer/registry/providers/luarocks_spec.lua @@ -0,0 +1,78 @@ +local stub = require "luassert.stub" +local match = require "luassert.match" +local Result = require "mason-core.result" +local luarocks = require "mason-core.installer.registry.providers.luarocks" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:luarocks/namespace/name@1.0.0"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("luarocks provider :: parsing", function() + it("should parse package", function() + assert.same( + Result.success { + package = "namespace/name", + version = "1.0.0", + server = nil, + dev = false, + }, + luarocks.parse({}, purl()) + ) + end) + + it("should parse package dev flag", function() + assert.same( + Result.success { + package = "namespace/name", + version = "1.0.0", + server = nil, + dev = true, + }, + luarocks.parse({}, purl { qualifiers = { dev = "true" } }) + ) + end) + + it("should parse package server flag", function() + assert.same( + Result.success { + package = "namespace/name", + version = "1.0.0", + server = "https://luarocks.org/dev", + dev = false, + }, + luarocks.parse({}, purl { qualifiers = { repository_url = "https://luarocks.org/dev" } }) + ) + end) +end) + +describe("luarocks provider :: installing", function() + it("should install luarocks packages", function() + local ctx = create_dummy_context() + local manager = require "mason-core.installer.managers.luarocks" + local ret_val = Result.success() + stub(manager, "install", mockx.returns(ret_val)) + + local result = installer.exec_in_context(ctx, function() + return luarocks.install(ctx, { + package = "namespace/name", + version = "1.0.0", + server = "https://luarocks.org/dev", + dev = false, + }) + end) + + assert.is_true(match.is_ref(ret_val)(result)) + assert.spy(manager.install).was_called(1) + assert.spy(manager.install).was_called_with("namespace/name", "1.0.0", { + dev = false, + server = "https://luarocks.org/dev", + }) + end) +end) diff --git a/tests/mason-core/installer/registry/providers/npm_spec.lua b/tests/mason-core/installer/registry/providers/npm_spec.lua new file mode 100644 index 00000000..cd20a07d --- /dev/null +++ b/tests/mason-core/installer/registry/providers/npm_spec.lua @@ -0,0 +1,72 @@ +local stub = require "luassert.stub" +local Result = require "mason-core.result" +local npm = require "mason-core.installer.registry.providers.npm" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:npm/%40namespace/package@v1.5.0"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("npm provider :: parsing", function() + it("should parse package", function() + assert.same( + Result.success { + package = "@namespace/package", + version = "v1.5.0", + extra_packages = { "extra" }, + }, + npm.parse({ extra_packages = { "extra" } }, purl()) + ) + end) +end) + +describe("npm provider :: installing", function() + it("should install npm packages", function() + local ctx = create_dummy_context() + local manager = require "mason-core.installer.managers.npm" + stub(manager, "init", mockx.returns(Result.success())) + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return npm.install(ctx, { + package = "@namespace/package", + version = "v1.5.0", + extra_packages = { "extra" }, + }) + end) + + assert.is_true(result:is_success()) + assert.spy(manager.init).was_called(1) + assert.spy(manager.install).was_called(1) + assert.spy(manager.install).was_called_with("@namespace/package", "v1.5.0", { extra_packages = { "extra" } }) + end) + + it("should ensure valid version", function() + local ctx = create_dummy_context { + version = "1.10.0", + } + local manager = require "mason-core.installer.managers.npm" + local providers = require "mason-core.providers" + stub(providers.npm, "get_all_versions", mockx.returns(Result.success { "1.0.0" })) + stub(manager, "init", mockx.returns(Result.success())) + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return npm.install(ctx, { + package = "package", + version = "1.10.0", + }) + end) + + assert.is_true(result:is_failure()) + assert.same(Result.failure [[Version "1.10.0" is not available.]], result) + assert.spy(manager.init).was_called(0) + assert.spy(manager.install).was_called(0) + end) +end) diff --git a/tests/mason-core/installer/registry/providers/nuget_spec.lua b/tests/mason-core/installer/registry/providers/nuget_spec.lua new file mode 100644 index 00000000..eac96251 --- /dev/null +++ b/tests/mason-core/installer/registry/providers/nuget_spec.lua @@ -0,0 +1,45 @@ +local stub = require "luassert.stub" +local Result = require "mason-core.result" +local nuget = require "mason-core.installer.registry.providers.nuget" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:nuget/package@2.2.0"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("nuget provider :: parsing", function() + it("should parse package", function() + assert.same( + Result.success { + package = "package", + version = "2.2.0", + }, + nuget.parse({}, purl()) + ) + end) +end) + +describe("nuget provider :: installing", function() + it("should install nuget packages", function() + local ctx = create_dummy_context() + local manager = require "mason-core.installer.managers.nuget" + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return nuget.install(ctx, { + package = "package", + version = "1.5.0", + }) + end) + + assert.is_true(result:is_success()) + assert.spy(manager.install).was_called(1) + assert.spy(manager.install).was_called_with("package", "1.5.0") + end) +end) diff --git a/tests/mason-core/installer/registry/providers/opam_spec.lua b/tests/mason-core/installer/registry/providers/opam_spec.lua new file mode 100644 index 00000000..53b5d767 --- /dev/null +++ b/tests/mason-core/installer/registry/providers/opam_spec.lua @@ -0,0 +1,45 @@ +local stub = require "luassert.stub" +local Result = require "mason-core.result" +local opam = require "mason-core.installer.registry.providers.opam" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:opam/package@2.2.0"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("opam provider :: parsing", function() + it("should parse package", function() + assert.same( + Result.success { + package = "package", + version = "2.2.0", + }, + opam.parse({}, purl()) + ) + end) +end) + +describe("opam provider :: installing", function() + it("should install opam packages", function() + local ctx = create_dummy_context() + local manager = require "mason-core.installer.managers.opam" + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return opam.install(ctx, { + package = "package", + version = "1.5.0", + }) + end) + + assert.is_true(result:is_success()) + assert.spy(manager.install).was_called(1) + assert.spy(manager.install).was_called_with("package", "1.5.0") + end) +end) diff --git a/tests/mason-core/installer/registry/providers/pypi_spec.lua b/tests/mason-core/installer/registry/providers/pypi_spec.lua new file mode 100644 index 00000000..222b473e --- /dev/null +++ b/tests/mason-core/installer/registry/providers/pypi_spec.lua @@ -0,0 +1,110 @@ +local stub = require "luassert.stub" +local settings = require "mason.settings" +local Result = require "mason-core.result" +local pypi = require "mason-core.installer.registry.providers.pypi" +local Purl = require "mason-core.purl" +local installer = require "mason-core.installer" + +---@param overrides Purl +local function purl(overrides) + local purl = Purl.parse("pkg:pypi/package@5.5.0"):get_or_throw() + if not overrides then + return purl + end + return vim.tbl_deep_extend("force", purl, overrides) +end + +describe("pypi provider :: parsing", function() + it("should parse package", function() + settings.set { + pip = { + install_args = { "--proxy", "http://localghost" }, + upgrade_pip = true, + }, + } + + assert.same( + Result.success { + package = "package", + version = "5.5.0", + extra_packages = { "extra" }, + pip = { + upgrade = true, + extra_args = { "--proxy", "http://localghost" }, + }, + }, + pypi.parse({ extra_packages = { "extra" } }, purl()) + ) + settings.set(settings._DEFAULT_SETTINGS) + end) + + it("should check supported platforms", function() + assert.same(Result.failure "PLATFORM_UNSUPPORTED", pypi.parse({ supported_platforms = { "VIC64" } }, purl())) + end) +end) + +describe("pypi provider :: installing", function() + it("should install pypi packages", function() + local ctx = create_dummy_context() + local manager = require "mason-core.installer.managers.pypi" + stub(manager, "init", mockx.returns(Result.success())) + stub(manager, "install", mockx.returns(Result.success())) + settings.set { + pip = { + install_args = { "--proxy", "http://localghost" }, + upgrade_pip = true, + }, + } + + local result = installer.exec_in_context(ctx, function() + return pypi.install(ctx, { + package = "package", + extra = "lsp", + version = "1.5.0", + extra_packages = { "extra" }, + pip = { + upgrade = true, + extra_args = { "--proxy", "http://localghost" }, + }, + }) + end) + + assert.is_true(result:is_success()) + assert.spy(manager.init).was_called(1) + assert.spy(manager.init).was_called_with { + upgrade_pip = true, + install_extra_args = { "--proxy", "http://localghost" }, + } + assert.spy(manager.install).was_called(1) + assert.spy(manager.install).was_called_with("package", "1.5.0", { extra = "lsp", extra_packages = { "extra" } }) + settings.set(settings._DEFAULT_SETTINGS) + end) + + it("should ensure valid version", function() + local ctx = create_dummy_context { + version = "1.10.0", + } + local manager = require "mason-core.installer.managers.pypi" + local providers = require "mason-core.providers" + stub(providers.pypi, "get_all_versions", mockx.returns(Result.success { "1.0.0" })) + stub(manager, "init", mockx.returns(Result.success())) + stub(manager, "install", mockx.returns(Result.success())) + + local result = installer.exec_in_context(ctx, function() + return pypi.install(ctx, { + package = "package", + version = "1.5.0", + extra_packages = {}, + pip = { + upgrade = true, + extra_args = { "--proxy", "http://localghost" }, + }, + }) + end) + + assert.is_true(result:is_failure()) + assert.same(Result.failure [[Version "1.10.0" is not available.]], result) + assert.spy(manager.init).was_called(0) + assert.spy(manager.install).was_called(0) + end) +end) diff --git a/tests/mason-core/installer/registry/util_spec.lua b/tests/mason-core/installer/registry/util_spec.lua new file mode 100644 index 00000000..d6cdd6b5 --- /dev/null +++ b/tests/mason-core/installer/registry/util_spec.lua @@ -0,0 +1,81 @@ +local match = require "luassert.match" +local Result = require "mason-core.result" +local util = require "mason-core.installer.registry.util" +local platform = require "mason-core.platform" +local installer = require "mason-core.installer" + +describe("registry installer util", function() + it("should coalesce single target", function() + local source = { value = "here" } + local coalesced = util.coalesce_by_target(source, {}):get() + assert.is_true(match.is_ref(source)(coalesced)) + end) + + it("should coalesce multiple targets", function() + local source = { target = "VIC64", value = "here" } + local coalesced = util.coalesce_by_target({ + { + target = "linux_arm64", + value = "here", + }, + source, + }, { target = "VIC64" }):get() + + assert.is_true(match.is_ref(source)(coalesced)) + end) + + it("should accept valid platform", function() + platform.is.VIC64 = true + local result = util.ensure_valid_platform { + "VIC64", + "linux_arm64", + } + assert.is_true(result:is_success()) + platform.is.VIC64 = nil + end) + + it("should reject invalid platform", function() + local result = util.ensure_valid_platform { "VIC64" } + assert.same(Result.failure "PLATFORM_UNSUPPORTED", result) + end) + + it("should accept valid version", function() + local ctx = create_dummy_context { version = "1.0.0" } + local result = installer.exec_in_context(ctx, function() + return util.ensure_valid_version(function() + return Result.success { "1.0.0", "2.0.0", "3.0.0" } + end) + end) + assert.is_true(result:is_success()) + end) + + it("should reject invalid version", function() + local ctx = create_dummy_context { version = "13.3.7" } + local result = installer.exec_in_context(ctx, function() + return util.ensure_valid_version(function() + return Result.success { "1.0.0", "2.0.0", "3.0.0" } + end) + end) + assert.same(Result.failure [[Version "13.3.7" is not available.]], result) + end) + + it("should gracefully accept version if unable to resolve available versions", function() + local ctx = create_dummy_context { version = "13.3.7" } + local result = installer.exec_in_context(ctx, function() + return util.ensure_valid_version(function() + return Result.failure() + end) + end) + assert.is_true(result:is_success()) + end) + + it("should accept version if in force mode", function() + local ctx = create_dummy_context { version = "13.3.7", force = true } + local result = installer.exec_in_context(ctx, function() + return util.ensure_valid_version(function() + return Result.success { "1.0.0" } + end) + end) + assert.is_true(result:is_success()) + end) +end) diff --git a/tests/mason-core/managers/powershell_spec.lua b/tests/mason-core/managers/powershell_spec.lua index 46e096bf..b8facacb 100644 --- a/tests/mason-core/managers/powershell_spec.lua +++ b/tests/mason-core/managers/powershell_spec.lua @@ -31,7 +31,9 @@ describe("powershell manager", function() stub(vim.fn, "executable") vim.fn.executable.on_call_with("pwsh").returns(0) - powershell().command "echo 'Is this bash?'" + local powershell = powershell() + a.scheduler() + powershell.command "echo 'Is this bash?'" assert.spy(spawn.pwsh).was_called(0) assert.spy(spawn.powershell).was_called(1) diff --git a/tests/mason-core/package/package_spec.lua b/tests/mason-core/package/package_spec.lua index 1eee3ed5..6f8eb8d4 100644 --- a/tests/mason-core/package/package_spec.lua +++ b/tests/mason-core/package/package_spec.lua @@ -86,6 +86,7 @@ describe("package", function() local handle = dummy:new_handle() assert.spy(handle_handler).was_called(1) assert.spy(handle_handler).was_called_with(match.ref(handle)) + handle:close() end) it("should not create new handle if one already exists", function() @@ -100,6 +101,7 @@ describe("package", function() end) assert.equals("Cannot create new handle because existing handle is not closed.", err) assert.spy(handle_handler).was_called(0) + dummy.handle = nil end) it( @@ -186,7 +188,6 @@ describe("package", function() assert.wait_for(function() assert.is_true(handle:is_closed()) - assert.is_true(dummy:is_installed()) end) end) ) diff --git a/tests/minimal_init.vim b/tests/minimal_init.vim index f099416c..0d9fb211 100644 --- a/tests/minimal_init.vim +++ b/tests/minimal_init.vim @@ -16,12 +16,11 @@ lua require("luassertx") lua require("test_helpers") lua <<EOF -local index = require "mason-registry.index" -index["dummy"] = "dummy_package" -index["dummy2"] = "dummy2_package" - require("mason").setup { install_root_dir = vim.env.INSTALL_ROOT_DIR, + registries = { + "lua:dummy-registry.index" + } } EOF |
