diff options
| author | ruki <[email protected]> | 2026-08-15 10:38:51 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-08-15 10:38:51 +0800 |
| commit | e4314dc3b2f483ef97b397ed5cf11fcdd397c9a0 (patch) | |
| tree | a28db860b0f7af1a5a66bf2ed29c87126a29324a /tests | |
| parent | 6c246c12a09524780e5bfdc53bc27a892e4793a9 (diff) | |
| parent | 045ce8a7a62e38357af0fd250675f279f14beafe (diff) | |
Merge pull request #7702 from xmake-io/preload
Auto fetch addons
Diffstat (limited to 'tests')
11 files changed, 178 insertions, 4 deletions
diff --git a/tests/actions/addon/custom-toolchain/src/modules/detect/tools/find_mycl6x.lua b/tests/actions/addon/custom-toolchain/src/modules/detect/tools/find_mycl6x.lua index 443690792..c0ed37914 100644 --- a/tests/actions/addon/custom-toolchain/src/modules/detect/tools/find_mycl6x.lua +++ b/tests/actions/addon/custom-toolchain/src/modules/detect/tools/find_mycl6x.lua @@ -9,7 +9,7 @@ function main(opt) for _, name in ipairs({"gcc", "clang", "cc"}) do local program = find_program(name, opt) if program then - return {program = program} + return program end end end diff --git a/tests/actions/addon/projects/autofetch-badinclude/xmake-addons.lua b/tests/actions/addon/projects/autofetch-badinclude/xmake-addons.lua new file mode 100644 index 000000000..6931855ae --- /dev/null +++ b/tests/actions/addon/projects/autofetch-badinclude/xmake-addons.lua @@ -0,0 +1,2 @@ +-- this file only declares the addons, it cannot reference them +includes("@addon/custom-include/check") diff --git a/tests/actions/addon/projects/autofetch-badinclude/xmake.lua b/tests/actions/addon/projects/autofetch-badinclude/xmake.lua new file mode 100644 index 000000000..0d94cf61c --- /dev/null +++ b/tests/actions/addon/projects/autofetch-badinclude/xmake.lua @@ -0,0 +1,2 @@ +target("test") + set_kind("phony") diff --git a/tests/actions/addon/projects/autofetch-badname/xmake-addons.lua b/tests/actions/addon/projects/autofetch-badname/xmake-addons.lua new file mode 100644 index 000000000..165325fb7 --- /dev/null +++ b/tests/actions/addon/projects/autofetch-badname/xmake-addons.lua @@ -0,0 +1,2 @@ +-- the `addon` name is reserved for the addon references +add_addons("addon") diff --git a/tests/actions/addon/projects/autofetch-badname/xmake.lua b/tests/actions/addon/projects/autofetch-badname/xmake.lua new file mode 100644 index 000000000..0d94cf61c --- /dev/null +++ b/tests/actions/addon/projects/autofetch-badname/xmake.lua @@ -0,0 +1,2 @@ +target("test") + set_kind("phony") diff --git a/tests/actions/addon/projects/autofetch-build/src/main.c b/tests/actions/addon/projects/autofetch-build/src/main.c new file mode 100644 index 000000000..112afe090 --- /dev/null +++ b/tests/actions/addon/projects/autofetch-build/src/main.c @@ -0,0 +1,11 @@ +// the addons must provide the option and the toolchain of this project +#ifndef MYOPTION +# error the option of the custom-include addon is not found! +#endif +#ifndef MY_C6000 +# error the toolchain of the custom-toolchain addon is not used! +#endif + +int main(int argc, char** argv) { + return 0; +} diff --git a/tests/actions/addon/projects/autofetch-build/xmake-addons.lua b/tests/actions/addon/projects/autofetch-build/xmake-addons.lua new file mode 100644 index 000000000..2091e3b7f --- /dev/null +++ b/tests/actions/addon/projects/autofetch-build/xmake-addons.lua @@ -0,0 +1,2 @@ +-- the addons which this project needs, they are installed automatically when we load it +add_addons("custom-include", "custom-rule", "custom-toolchain") diff --git a/tests/actions/addon/projects/autofetch-build/xmake.lua b/tests/actions/addon/projects/autofetch-build/xmake.lua new file mode 100644 index 000000000..bad3f8928 --- /dev/null +++ b/tests/actions/addon/projects/autofetch-build/xmake.lua @@ -0,0 +1,11 @@ +-- the option comes from the includes file of an addon +includes("@addon/custom-include/check") + +target("hello") + set_kind("binary") + add_files("src/main.c") + add_rules("@addon/custom-rule/hello") + set_toolchains("@addon/custom-toolchain/my-c6000") + if has_config("myoption") then + add_defines("MYOPTION") + end diff --git a/tests/actions/addon/projects/autofetch/xmake-addons.lua b/tests/actions/addon/projects/autofetch/xmake-addons.lua new file mode 100644 index 000000000..a85e0fe11 --- /dev/null +++ b/tests/actions/addon/projects/autofetch/xmake-addons.lua @@ -0,0 +1 @@ +add_addons("custom-include") diff --git a/tests/actions/addon/projects/autofetch/xmake.lua b/tests/actions/addon/projects/autofetch/xmake.lua new file mode 100644 index 000000000..4eaca0785 --- /dev/null +++ b/tests/actions/addon/projects/autofetch/xmake.lua @@ -0,0 +1,5 @@ +-- the addon is installed automatically, so we can use its includes file here +includes("@addon/custom-include/check") + +target("test") + set_kind("phony") diff --git a/tests/actions/addon/test.lua b/tests/actions/addon/test.lua index 3542c907b..d59ae6f4b 100644 --- a/tests/actions/addon/test.lua +++ b/tests/actions/addon/test.lua @@ -29,10 +29,14 @@ function _with_addons(names, func) func, finally { - function () + -- @note try() swallows the errors if we do not re-raise them here + function (ok, errors) for _, name in ipairs(names) do _remove(name) end + if not ok then + raise(errors) + end end } } @@ -54,6 +58,14 @@ function _with_repo(recipes, func) local cachefile = path.join(global.cachedir(), "repository") local cache = os.isfile(cachefile) and io.load(cachefile) or {} cache.repositories = cache.repositories or {} + + -- a killed test run may leave its temporary repository registered, and a dangling + -- repository breaks every following xrepo command, so we drop them here + for name, dirs in pairs(cache.repositories) do + if name:startswith("addon-test-repo-") and not os.isdir(dirs[1]) then + cache.repositories[name] = nil + end + end cache.repositories[reponame] = {repodir} io.save(cachefile, cache) os.tryrm(path.join(global.cachedir(), "quick_search")) @@ -65,7 +77,8 @@ function _with_repo(recipes, func) end, finally { - function () + -- @note try() swallows the errors if we do not re-raise them here + function (ok, errors) for name, _ in pairs(recipes) do _remove(name) end @@ -76,6 +89,9 @@ function _with_repo(recipes, func) io.save(cachefile, cache) os.tryrm(path.join(global.cachedir(), "quick_search")) os.tryrm(repodir) + if not ok then + raise(errors) + end end } } @@ -114,6 +130,36 @@ function _config_project(content) return _run_project(content, {"config", "-y"}) end +-- copy the given fixture project to a temporary directory and run the given function in it +-- +-- @note we cannot run them in place, they would generate the lock and the build files, +-- @see tests/actions/addon/projects +-- +function _with_project(name, func) + local projectdir = os.tmpfile() .. ".addon-project" + os.tryrm(projectdir) + os.mkdir(projectdir) + os.cp(path.join(os.scriptdir(), "projects", name, "*"), projectdir) + local oldir = os.cd(projectdir) + try + { + function () + func(projectdir) + end, + finally + { + -- @note try() swallows the errors if we do not re-raise them here + function (ok, errors) + os.cd(oldir) + os.tryrm(projectdir) + if not ok then + raise(errors) + end + end + } + } +end + -- only the payloads should be installed, our own files should not function test_install(t) _with_addons({"custom-toolchain"}, function () @@ -223,6 +269,92 @@ target("test") end) end +-- the addons which a project declares in `xmake-addons.lua` are installed automatically +-- +-- @note they must be installed before loading the project, it may use their includes files +function test_autofetch(t) + local recipes = {["custom-include"] = ("set_sourcedir(%q)"):format(_addondir("custom-include"))} + _with_repo(recipes, function () + _remove("custom-include") + _with_project("autofetch", function (projectdir) + + -- it should be installed when loading the project, so that its includes file can be found, + -- and we should tell the user why we install something, it may need to confirm and download + local output = os.iorunv("xmake", {"config", "-y"}) + t:require(output:find("custom-include: includes check is loaded", 1, true)) + t:require(output:find("this project needs the addons", 1, true)) + + -- and it should be locked + local lockfile = path.join(projectdir, "xmake-addons.lock") + t:require(os.isfile(lockfile)) + t:require(io.load(lockfile)["custom-include"] ~= nil) + + -- we should not install it again + t:require_not(os.iorunv("xmake", {"config", "-y"}):find("install custom-include", 1, true)) + end) + end) +end + +-- every command builds the option menu, which merges the project tasks in a best-effort way, +-- so the commands which need not the project should never install its addons +function test_autofetch_skipped_for_option_menu(t) + local recipes = {["custom-include"] = ("set_sourcedir(%q)"):format(_addondir("custom-include"))} + _with_repo(recipes, function () + _remove("custom-include") + _with_project("autofetch", function (projectdir) + os.runv("xmake", {"addon", "--list"}) + os.runv("xmake", {"lua", "-c", "print(\"hello\")"}) + t:require_not(os.isfile(path.join(projectdir, "xmake-addons.lock"))) + end) + end) +end + +-- a complete project which declares its addons in `xmake-addons.lua` and builds with them, +-- @see tests/actions/addon/projects/autofetch-build +function test_autofetch_build(t) + + -- @note the compiler of the custom toolchain is just the host one, + -- so we can only build it if there is one + if not (find_program("gcc") or find_program("clang") or find_program("cc")) then + return + end + + local names = {"custom-include", "custom-rule", "custom-toolchain"} + local recipes = {} + for _, name in ipairs(names) do + recipes[name] = ("set_sourcedir(%q)"):format(_addondir(name)) + end + _with_repo(recipes, function () + for _, name in ipairs(names) do + _remove(name) + end + _with_project("autofetch-build", function (projectdir) + + -- all of them should be installed when loading the project, and it should build + -- with their includes file, rule and toolchain, @see src/main.c + local output = os.iorunv("xmake", {"build", "-y"}) + t:require(output:find("custom-include: includes check is loaded", 1, true)) + t:require(output:find("custom-rule: hello from custom-rule: hello", 1, true)) + t:require(output:find("build ok", 1, true)) + + -- and all of them should be locked + local lockinfo = io.load(path.join(projectdir, "xmake-addons.lock")) + for _, name in ipairs(names) do + t:require(lockinfo[name] ~= nil) + end + end) + end) +end + +-- the addons file only declares the addons, it cannot reference them +function test_autofetch_invalid(t) + for _, name in ipairs({"autofetch-badinclude", "autofetch-badname"}) do + _with_project(name, function () + t:require_not(try { function () os.runv("xmake", {"config", "-y"}); return true end }) + end) + end +end + -- the addons can be installed from a repository, by plain name and by repo@name function test_install_from_repo(t) local recipes = {["custom-plugin"] = ("set_sourcedir(%q)"):format(_addondir("custom-plugin"))} @@ -235,8 +367,12 @@ function test_install_from_repo(t) t:require(os.iorunv("xmake", {"hello_addon"}):find("hello from custom-plugin", 1, true)) -- it should be searchable, and the addons should not be found by the package search + -- + -- @note we cannot run the `xrepo` program here, it may not be in the PATH, e.g. on the ci, + -- and `xrepo search` is just a wrapper of it + -- t:require(os.iorunv("xmake", {"addon", "--search", "custom-plugin"}):find("custom-plugin", 1, true)) - t:require_not(os.iorunv("xrepo", {"search", "custom-plugin"}):find("custom-plugin", 1, true)) + t:require_not(os.iorunv("xmake", {"lua", "private.xrepo", "search", "custom-plugin"}):find("custom-plugin", 1, true)) end) end |
