diff options
Diffstat (limited to 'spec')
145 files changed, 12058 insertions, 0 deletions
diff --git a/spec/README.md b/spec/README.md new file mode 100644 index 0000000..89e13ea --- /dev/null +++ b/spec/README.md @@ -0,0 +1,58 @@ + +# LuaRocks testsuite + +## Overview + +Test suite for LuaRocks project with Busted unit testing framework(http://olivinelabs.com/busted/). + +* Contains unit and integration tests +* Easy setup for your purpose on command line or from configuration file + +## Dependencies + +* Lua >= 5.1 +* Busted with dependencies + +## Usage + +Running of tests is based on basic Busted usage. *-Xhelper* flag is used +for inserting arguments into testing. Flag *--tags=* or *-t* is used +for specifying which tests will run. Start tests inside +LuaRocks folder or specify with *-C* flag. + +**Arguments for Busted helper script** + +``` +env=<type>, (default:"minimal") type what kind of environment to use ["minimal", "full"] +noreset, Don't reset environment after each test +clean, remove existing testing environment +appveyor, add just if running on Appveyor +ci, add just if running on Unix CI +os=<version>, type your OS ["linux", "os x", "windows"] +``` +--------------------------------------------------------------------------------------------- +## _**Tags** of tests are required and are in this format:_ + +**unit** - run all unit tests + +**integration** - run all integration tests + +**ssh** - run all tests which require ssh + +**mock** - run all tests which require mock LuaRocks server (upload tests) + +**unix** - run all tests which are UNIX based, won't work on Windows systems + +## Examples + +To run all tests: + +`busted` + +To run unit tests in LuaRocks directory type : + +`busted -t "unit"` + +To run integration tests without tests which use ssh: + +`busted -t "integration" --exclude-tags=ssh` diff --git a/spec/add_spec.lua b/spec/add_spec.lua new file mode 100644 index 0000000..60eea86 --- /dev/null +++ b/spec/add_spec.lua @@ -0,0 +1,41 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run +local testing_paths = test_env.testing_paths + +local extra_rocks = { + "/luasocket-${LUASOCKET}.src.rock", +} + +describe("LuaRocks add tests #integration", function() + + before_each(function() + test_env.setup_specs(extra_rocks) + end) + + describe("LuaRocks-admin add tests", function() + it("invalid rock #ssh", function() + assert.is_false(run.luarocks_admin_bool("--server=testing add invalid")) + end) + + it("missing argument", function() + assert.is_false(run.luarocks_admin_bool("--server=testing add")) + end) + + it("invalid server", function() + assert.is_false(run.luarocks_admin_bool("--server=invalid add " .. testing_paths.testing_server .. "/luasocket-${LUASOCKET}.src.rock")) + end) + + it("invalid server #ssh", function() + assert.is_true(run.luarocks_admin_bool("--server=testing add " .. testing_paths.testing_server .. "/luasocket-${LUASOCKET}.src.rock")) + end) + + --TODO This test fails, sftp support not yet implemented + it("invalid server", function() + assert.is_false(run.luarocks_admin_bool("--server=testing add luasocket-${LUASOCKET}.src.rock", { LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/testing_config_sftp.lua" } )) + end) + + it("split server url", function() + assert.is_false(run.luarocks_admin_bool("--server=\"localhost@/tmp/luarocks_testing\" add " .. testing_paths.testing_server .. "/luasocket-${LUASOCKET}.src.rock")) + end) + end) +end) diff --git a/spec/build_spec.lua b/spec/build_spec.lua new file mode 100644 index 0000000..034c70d --- /dev/null +++ b/spec/build_spec.lua @@ -0,0 +1,456 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local get_tmp_path = test_env.get_tmp_path +local run = test_env.run +local testing_paths = test_env.testing_paths +local write_file = test_env.write_file +local git_repo = require("spec.util.git_repo") + +local cfg, fs + +local extra_rocks = { + "/lmathx-20120430.51-1.src.rock", + "/lmathx-20120430.51-1.rockspec", + "/lmathx-20120430.52-1.src.rock", + "/lmathx-20120430.52-1.rockspec", + "/lmathx-20150505-1.src.rock", + "/lmathx-20150505-1.rockspec", + "/lpeg-1.0.0-1.src.rock", + "/luafilesystem-${LUAFILESYSTEM}.src.rock", + "/luasocket-${LUASOCKET}.src.rock", + "spec/fixtures/a_rock-1.0-1.src.rock", +} + +local c_module_source = [[ + #include <lua.h> + #include <lauxlib.h> + + int luaopen_c_module(lua_State* L) { + lua_newtable(L); + lua_pushinteger(L, 1); + lua_setfield(L, -2, "c_module"); + return 1; + } +]] + +describe("LuaRocks build #integration", function() + before_each(function() + test_env.setup_specs(extra_rocks) + cfg = require("luarocks.core.cfg") + fs = require("luarocks.fs") + cfg.init() + fs.init() + end) + + describe("building with flags", function() + it("verbose", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]]) + write_file("test.lua", "return {}") + + assert.is_true(run.luarocks_bool("build --verbose test-1.0-1.rockspec")) + assert.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/test/1.0-1/test-1.0-1.rockspec")) + end, finally) + end) + + it("fails if the deps-mode argument is invalid", function() + assert.is_false(run.luarocks_bool("build --deps-mode=123 " .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec")) + assert.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + end) + + it("with --only-sources", function() + assert.is_true(run.luarocks_bool("download --server=" .. testing_paths.fixtures_dir .. "/a_repo --rockspec a_rock 1.0")) + assert.is_false(run.luarocks_bool("build --only-sources=\"http://example.com\" a_rock-1.0-1.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + + assert.is_true(run.luarocks_bool("download --server=" .. testing_paths.fixtures_dir .. "/a_repo --source a_rock 1.0")) + assert.is_true(run.luarocks_bool("build --only-sources=\"http://example.com\" a_rock-1.0-1.src.rock")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + + assert.is_true(os.remove("a_rock-1.0-1.rockspec")) + assert.is_true(os.remove("a_rock-1.0-1.src.rock")) + end) + + it("fails if an empty tree is given", function() + assert.is_false(run.luarocks_bool("build --tree=\"\" " .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec")) + assert.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + end) + end) + + describe("basic builds", function() + it("luacov diff version", function() + assert.is_true(run.luarocks_bool("build luacov ${LUACOV}")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/luacov/${LUACOV}/luacov-${LUACOV}.rockspec")) + end) + + it("fails if the current platform is not supported", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + supported_platforms = { + "unix", "macosx" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]]) + write_file("test.lua", "return {}") + + if test_env.TEST_TARGET_OS == "windows" then + assert.is_false(run.luarocks_bool("build test-1.0-1.rockspec")) -- Error: This rockspec does not support windows platforms + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/test/1.0-1/test-1.0-1.rockspec")) + else + assert.is_true(run.luarocks_bool("build test-1.0-1.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/test/1.0-1/test-1.0-1.rockspec")) + end + end, finally) + end) + + it("with skipping dependency checks", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock 1.0" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]]) + write_file("test.lua", "return {}") + + assert.is_true(run.luarocks_bool("build test-1.0-1.rockspec --deps-mode=none")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/test/1.0-1/test-1.0-1.rockspec")) + end, finally) + end) + + it("lmathx deps partial match", function() + if test_env.LUA_V == "5.1" or test_env.LUAJIT_V then + assert.is_true(run.luarocks_bool("build lmathx")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lmathx/20120430.51-1/lmathx-20120430.51-1.rockspec")) + elseif test_env.LUA_V == "5.2" then + assert.is_true(run.luarocks_bool("build lmathx")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lmathx/20120430.52-1/lmathx-20120430.52-1.rockspec")) + elseif test_env.LUA_V == "5.3" then + assert.is_true(run.luarocks_bool("build lmathx")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lmathx/20150505-1/lmathx-20150505-1.rockspec")) + end + end) + end) + + describe("#namespaces", function() + it("builds a namespaced package from the command-line", function() + assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert.is_false(run.luarocks_bool("show a_rock 1.0")) + assert(run.luarocks_bool("show a_rock 2.0")) + assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace")) + end) + + it("builds a package with a namespaced dependency", function() + assert(run.luarocks_bool("build has_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(run.luarocks_bool("show has_namespaced_dep")) + assert.is_false(run.luarocks_bool("show a_rock 1.0")) + assert(run.luarocks_bool("show a_rock 2.0")) + end) + + it("builds a package reusing a namespaced dependency", function() + assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(run.luarocks_bool("show a_rock 2.0")) + assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace")) + local output = run.luarocks("build has_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" ) + assert.has.no.match("Missing dependencies", output) + end) + + it("builds a package considering namespace of locally installed package", function() + assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(run.luarocks_bool("show a_rock 2.0")) + assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace")) + local output = run.luarocks("build has_another_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" ) + assert.has.match("Missing dependencies", output) + print(output) + assert(run.luarocks_bool("show a_rock 3.0")) + end) + end) + + describe("more complex tests", function() + if test_env.TYPE_TEST_ENV == "full" then + it("luacheck show downloads test_config", function() + local output = run.luarocks("build luacheck", { LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/testing_config_show_downloads.lua"} ) + assert.is.truthy(output:match("%.%.%.")) + end) + end + + it("only deps", function() + local rockspec = testing_paths.fixtures_dir .. "/build_only_deps-0.1-1.rockspec" + + assert.is_true(run.luarocks_bool("build " .. rockspec .. " --only-deps")) + assert.is_false(run.luarocks_bool("show build_only_deps")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/build_only_deps/0.1-1/build_only_deps-0.1-1.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + end) + + it("only deps of a given rockspec", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock 1.0" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]]) + write_file("test.lua", "return {}") + + assert.is.truthy(run.luarocks_bool("build --server=" .. testing_paths.fixtures_dir .. "/a_repo test-1.0-1.rockspec --only-deps")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/test/1.0-1/test-1.0-1.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + end, finally) + end) + + it("only deps of a given rock", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock 1.0" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]]) + write_file("test.lua", "return {}") + + assert.is.truthy(run.luarocks_bool("pack test-1.0-1.rockspec")) + assert.is.truthy(lfs.attributes("test-1.0-1.src.rock")) + + assert.is.truthy(run.luarocks_bool("build --server=" .. testing_paths.fixtures_dir .. "/a_repo test-1.0-1.src.rock --only-deps")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/test/1.0-1/test-1.0-1.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + end, finally) + end) + + it("fails if given an argument with an invalid patch", function() + assert.is_false(run.luarocks_bool("build " .. testing_paths.fixtures_dir .. "/invalid_patch-0.1-1.rockspec")) + end) + end) + + describe("rockspec format 3.0 #rs3", function() + local tmpdir + local olddir + + before_each(function() + tmpdir = get_tmp_path() + olddir = lfs.currentdir() + lfs.mkdir(tmpdir) + lfs.chdir(tmpdir) + + lfs.mkdir("autodetect") + write_file("autodetect/bla.lua", "return {}", finally) + write_file("c_module.c", c_module_source, finally) + end) + + after_each(function() + if olddir then + lfs.chdir(olddir) + if tmpdir then + lfs.rmdir("autodetect") + lfs.rmdir(tmpdir) + end + end + end) + + it("defaults to build.type == 'builtin'", function() + local rockspec = "a_rock-1.0-1.rockspec" + test_env.write_file(rockspec, [[ + rockspec_format = "3.0" + package = "a_rock" + version = "1.0-1" + source = { + url = "file://]] .. testing_paths.fixtures_dir:gsub("\\", "/") .. [[/a_rock.lua" + } + description = { + summary = "An example rockspec", + } + dependencies = { + "lua >= 5.1" + } + build = { + modules = { + build = "a_rock.lua" + }, + } + ]], finally) + assert.truthy(run.luarocks_bool("build " .. rockspec)) + assert.is.truthy(run.luarocks("show a_rock")) + end) + + it("'builtin' detects lua files if build is not given", function() + local rockspec = "autodetect-1.0-1.rockspec" + test_env.write_file(rockspec, [[ + rockspec_format = "3.0" + package = "autodetect" + version = "1.0-1" + source = { + url = "file://autodetect/bla.lua" + } + description = { + summary = "An example rockspec", + } + dependencies = { + "lua >= 5.1" + } + ]], finally) + assert.truthy(run.luarocks_bool("build " .. rockspec)) + assert.match("bla.lua", run.luarocks("show autodetect")) + end) + + it("'builtin' synthesizes external_dependencies if not given but a library is given in build", function() + local rockspec = "autodetect-1.0-1.rockspec" + test_env.write_file(rockspec, [[ + rockspec_format = "3.0" + package = "autodetect" + version = "1.0-1" + source = { + url = "file://c_module.c" + } + description = { + summary = "An example rockspec", + } + dependencies = { + "lua >= 5.1" + } + build = { + modules = { + c_module = { + sources = "c_module.c", + libraries = "inexistent_library", + } + } + } + ]], finally) + assert.match("INEXISTENT_LIBRARY_DIR", run.luarocks("build " .. rockspec)) + end) + end) + + describe("#mock external dependencies", function() + lazy_setup(function() + test_env.setup_specs(nil, "mock") + test_env.mock_server_init() + end) + + lazy_teardown(function() + test_env.mock_server_done() + end) + + it("fails when missing external dependency", function() + test_env.run_in_tmp(function(tmpdir) + write_file("missing_external-0.1-1.rockspec", [[ + package = "missing_external" + version = "0.1-1" + source = { + url = "https://example.com/build.lua" + } + external_dependencies = { + INEXISTENT = { + library = "inexistentlib*", + header = "inexistentheader*.h", + } + } + dependencies = { + "lua >= 5.1" + } + build = { + type = "builtin", + modules = { + build = "build.lua" + } + } + ]]) + assert.is_false(run.luarocks_bool("build missing_external-0.1-1.rockspec INEXISTENT_INCDIR=\"/invalid/dir\"")) + end, finally) + end) + + it("builds with external dependency", function() + local rockspec = testing_paths.fixtures_dir .. "/with_external_dep-0.1-1.rockspec" + local foo_incdir = testing_paths.fixtures_dir .. "/with_external_dep" + assert.is_truthy(run.luarocks_bool("build " .. rockspec .. " FOO_INCDIR=\"" .. foo_incdir .. "\"")) + assert.is.truthy(run.luarocks("show with_external_dep")) + end) + end) + + describe("#build_dependencies", function() + it("builds with a build dependency", function() + assert(run.luarocks_bool("build has_build_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(run.luarocks_bool("show has_build_dep 1.0")) + assert(run.luarocks_bool("show a_build_dep 1.0")) + end) + end) + + describe("#unix build from #git", function() + local git + + lazy_setup(function() + git = git_repo.start() + end) + + lazy_teardown(function() + if git then + git:stop() + end + end) + + it("using --branch", function() + write_file("my_branch-1.0-1.rockspec", [[ + rockspec_format = "3.0" + package = "my_branch" + version = "1.0-1" + source = { + url = "git://localhost/testrock" + } + ]], finally) + assert.is_false(run.luarocks_bool("build --branch unknown-branch ./my_branch-1.0-1.rockspec")) + assert.is_true(run.luarocks_bool("build --branch test-branch ./my_branch-1.0-1.rockspec")) + end) + end) +end) diff --git a/spec/cmd_spec.lua b/spec/cmd_spec.lua new file mode 100644 index 0000000..20248af --- /dev/null +++ b/spec/cmd_spec.lua @@ -0,0 +1,105 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run + +describe("LuaRocks command line #integration", function() + + lazy_setup(function() + test_env.setup_specs() + end) + + describe("--version", function() + it("returns the LuaRocks version", function() + local output = run.luarocks("--version") + assert.match("LuaRocks main command-line interface", output, 1, true) + end) + + it("runs if Lua detection fails", function() + test_env.run_in_tmp(function(tmpdir) + test_env.write_file("bad_config.lua", [[ + variables = { + LUA_DIR = "/bad/lua/dir", + } + ]], finally) + local env = { + LUAROCKS_CONFIG = "bad_config.lua" + } + local output = run.luarocks("--version", env) + assert.match("LuaRocks main command-line interface", output, 1, true) + end, finally) + end) + end) + + describe("--lua-dir", function() + it("fails if given an invalid path", function() + local output = run.luarocks("--lua-dir=/bad/lua/path") + assert.match("Lua interpreter not found at /bad/lua/path", output, 1, true) + end) + + it("fails if given a valid path without Lua", function() + local output = run.luarocks("--lua-dir=.") + assert.match("Lua interpreter not found at .", output, 1, true) + end) + + it("passes if given a valid path with Lua", function() + assert.truthy(run.luarocks("--lua-dir=" .. test_env.testing_paths.luadir)) + end) + + it("passes if given a quoted path with Lua", function() + assert.truthy(run.luarocks("--lua-dir '" .. test_env.testing_paths.luadir .. "'")) + end) + end) + + describe("--lua-version", function() + it("fails if given something that is not a number", function() + local output = run.luarocks("--lua-version=bozo") + assert.match("malformed", output, 1, true) + end) + + it("sets the version independently of project tree", function() + test_env.run_in_tmp(function(tmpdir) + assert.truthy(run.luarocks_bool("init --lua-version=" .. test_env.lua_version .. " --lua-versions=" .. test_env.lua_version)) + + local output = run.luarocks("--lua-version=1.0") + assert.match("Version%s*:%s*1.0", output) + + output = run.luarocks("--lua-version=1.0 --project-tree=.") + assert.match("Version%s*:%s*1.0", output) + end, finally) + end) + end) + + it("detects version based on project tree", function() + test_env.run_in_tmp(function(tmpdir) + assert.truthy(run.luarocks_bool("init --lua-version=" .. test_env.lua_version)) + assert.truthy(run.luarocks_bool("config lua_version 1.0 --project-tree=" .. tmpdir .. "/lua_modules")) + + lfs.mkdir("aaa") + lfs.chdir("aaa") + lfs.mkdir("bbb") + lfs.chdir("bbb") + + local output = run.luarocks("") + assert.match("Version%s*:%s*1.0", output) + end, finally) + end) + + -- for backward compatibility + it("detects version of a project based on config", function() + test_env.run_in_tmp(function(tmpdir) + assert.truthy(run.luarocks_bool("init --lua-version=" .. test_env.lua_version)) + os.remove(".luarocks/config-" .. test_env.lua_version .. ".lua") + os.remove(".luarocks/default-lua-version.lua") + test_env.write_file(".luarocks/config-5.2.lua", [[ ]], finally) + + lfs.mkdir("aaa") + lfs.chdir("aaa") + lfs.mkdir("bbb") + lfs.chdir("bbb") + + local output = run.luarocks("") + assert.match("Version%s*:%s*5.2", output) + end, finally) + end) + +end) diff --git a/spec/config_spec.lua b/spec/config_spec.lua new file mode 100644 index 0000000..9dd8fbc --- /dev/null +++ b/spec/config_spec.lua @@ -0,0 +1,253 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run +local testing_paths = test_env.testing_paths +local env_variables = test_env.env_variables +local write_file = test_env.write_file +local get_tmp_path = test_env.get_tmp_path +local hardcoded + +describe("LuaRocks config tests #integration", function() + + lazy_setup(function() + test_env.setup_specs() + -- needs to be required here, because hardcoded is created after first loading of specs + hardcoded = require("luarocks.core.hardcoded") + end) + + describe("full configuration query", function() + it("no flags/arguments", function() + assert.match("rocks_servers = {", run.luarocks("config")) + end) + + it("--json", function() + assert.match('"rocks_servers":[', run.luarocks("config --json"), 1, true) + end) + + it("with --tree respects custom config", function() + write_file("my_config.lua", [[ + rocks_trees = { + { + name = "system", + root = "/example/tree", + lua_dir = "/example/luadir", + }, + } + ]], finally) + local output = run.luarocks("config", {LUAROCKS_CONFIG = "my_config.lua"}) + assert.match([[deploy_lua_dir = "/example/luadir"]], output) + output = run.luarocks("config --tree=system", {LUAROCKS_CONFIG = "my_config.lua"}) + assert.match([[deploy_lua_dir = "/example/luadir"]], output) + end) + + it("#unix can find config via $XDG_CONFIG_HOME", function() + local tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + lfs.mkdir(tmpdir .. "/luarocks") + local tmp_config_file = tmpdir .. "/luarocks/config-" .. test_env.lua_version .. ".lua" + write_file(tmp_config_file, [[ + rocks_trees = { + { + name = "system", + root = "/example/tree", + lua_dir = "/example/luadir", + }, + } + ]]) + finally(function() + os.remove(tmp_config_file) + lfs.rmdir(tmpdir .. "/luarocks") + lfs.rmdir(tmpdir) + end) + + local output = run.luarocks("config --verbose", {XDG_CONFIG_HOME = tmpdir, LUAROCKS_CONFIG="invalid"}) + assert.match([[deploy_lua_dir = "/example/luadir"]], output) + end) + end) + + describe("query flags", function() + it("--lua-incdir returns a subdir of LUA_DIR", function() + local output = run.luarocks("config --lua-incdir") + assert.match(hardcoded.LUA_DIR, output, 1, true) + end) + + it("--lua-libdir returns a subdir of LUA_DIR", function() + local output = run.luarocks("config --lua-libdir") + assert.match(hardcoded.LUA_DIR, output, 1, true) + end) + + it("--lua-ver returns the Lua version", function() + local output = run.luarocks("config --lua-ver") + local lua_version = _VERSION:gsub("Lua ", "") + if test_env.LUAJIT_V then + lua_version = "5.1" + end + assert.are.same(lua_version, output) + end) + + it("--rock-trees lists rock trees", function() + assert.is_true(run.luarocks_bool("config --rock-trees")) + end) + + describe("--user-config", function() + it("returns user config dir", function() + local user_config_path = run.luarocks("config --user-config") + assert.is.truthy(lfs.attributes(user_config_path)) + end) + + it("handles a missing user config", function() + local output = run.luarocks("config --user-config", {LUAROCKS_CONFIG = "missing_file.lua"}) + assert.match("Warning", output) + end) + end) + + describe("--system-config", function() + local scdir = testing_paths.testing_lrprefix .. "/etc/luarocks" + local configfile = scdir .. "/config-" .. env_variables.LUA_VERSION .. ".lua" + + it("fails if system config doesn't exist", function() + os.rename(configfile, configfile .. ".bak") + finally(function() + os.rename(configfile .. ".bak", configfile) + end) + assert.is_false(run.luarocks_bool("config --system-config")) + end) + + it("fails if system config is invalid", function() + lfs.mkdir(testing_paths.testing_lrprefix) + lfs.mkdir(testing_paths.testing_lrprefix .. "/etc/") + lfs.mkdir(scdir) + + local sysconfig = io.open(configfile, "w+") + sysconfig:write("if if if") + sysconfig:close() + finally(function() + os.remove(configfile) + end) + assert.is_false(run.luarocks_bool("config --system-config")) + end) + end) + end) + + describe("read config keys", function() + it("reads a simple config key", function() + local output = run.luarocks("config user_agent") + assert.match("LuaRocks/", output) + end) + + it("reads an array config key", function() + local output = run.luarocks("config rocks_trees[2]") + assert.match("{%s*name", output) + end) + + it("can read as JSON", function() + local output = run.luarocks("config rocks_trees --json") + assert.match('^%[{', output) + end) + + it("reads an array -> hash config key", function() + local output = run.luarocks("config rocks_trees[2].name") + assert.match("[a-z]+", output) + end) + + it("reads a hash config key", function() + local output = run.luarocks("config variables.ICACLS") + assert.same("icacls", output) + end) + + it("fails on invalid config key", function() + local output = run.luarocks("config xyz") + assert.match("Error: Unknown entry xyz", output) + end) + end) + + describe("unset config keys", function() + it("unsets a simple config key", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init")) + assert.truthy(run.luarocks_bool("config my_var my_value")) + + local output = run.luarocks("config my_var") + assert.match("my_value", output) + + assert.truthy(run.luarocks_bool("config my_var --unset")) + + output = run.luarocks("config my_var") + assert.not_match("my_value", output) + end, finally) + end) + end) + + describe("write config keys", function() + it("rejects invalid --scope", function() + assert.is_false(run.luarocks_bool("config web_browser foo --scope=foo")) + end) + + it("reads an array config key", function() + local output = run.luarocks("config rocks_trees[2]") + assert.match("{%s*name", output) + end) + + it("writes a simple config key", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init")) + assert.truthy(run.luarocks_bool("config web_browser foo --scope=project")) + + local output = run.luarocks("config web_browser") + assert.match("foo", output) + end, finally) + end) + + it("writes a hash config key", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init")) + assert.truthy(run.luarocks_bool("config variables.FOO_DIR /foo/bar --scope=project")) + + local output = run.luarocks("config variables.FOO_DIR") + assert.match("/foo/bar", output) + end, finally) + end) + + it("writes a boolean config key", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init")) + assert.truthy(run.luarocks_bool("config hooks_enabled true")) + + local output = run.luarocks("config hooks_enabled") + assert.match("true", output) + end, finally) + end) + + it("writes an array config key", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init")) + assert.truthy(run.luarocks_bool("config external_deps_patterns.lib[1] testtest --scope=project")) + + local output = run.luarocks("config external_deps_patterns.lib[1]") + assert.match("testtest", output) + end, finally) + end) + + end) + +end) diff --git a/spec/deps_spec.lua b/spec/deps_spec.lua new file mode 100644 index 0000000..766e0f0 --- /dev/null +++ b/spec/deps_spec.lua @@ -0,0 +1,114 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run +local testing_paths = test_env.testing_paths + +local extra_rocks = { + "/lxsh-${LXSH}.src.rock", + "/luasocket-${LUASOCKET}.src.rock", + "/lpeg-${LPEG}.src.rock", +} + +describe("LuaRocks deps-mode #integration", function() + + before_each(function() + test_env.setup_specs(extra_rocks) + end) + + it("one", function() + assert.is_true(run.luarocks_bool("build --tree=system lpeg")) + assert.is_true(run.luarocks_bool("build --deps-mode=one --tree=" .. testing_paths.testing_tree .. " lxsh")) + + assert.is.truthy(lfs.attributes(testing_paths.testing_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) + + it("order", function() + assert.is_true(run.luarocks_bool("build --tree=system lpeg")) + assert.is_true(run.luarocks_bool("build --deps-mode=order --tree=" .. testing_paths.testing_tree .. " lxsh")) + + assert.is.falsy(lfs.attributes(testing_paths.testing_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) + + it("order sys", function() + assert.is_true(run.luarocks_bool("build --tree=" .. testing_paths.testing_tree .. " lpeg")) + assert.is_true(run.luarocks_bool("build --deps-mode=order --tree=" .. testing_paths.testing_sys_tree .. " lxsh")) + + assert.is.truthy(lfs.attributes(testing_paths.testing_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) + + it("all sys", function() + assert.is_true(run.luarocks_bool("build --tree=" .. testing_paths.testing_tree .. " lpeg")) + assert.is_true(run.luarocks_bool("build --deps-mode=all --tree=" .. testing_paths.testing_sys_tree .. " lxsh")) + + assert.is.truthy(lfs.attributes(testing_paths.testing_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) + + it("none", function() + assert.is_true(run.luarocks_bool("build --tree=" .. testing_paths.testing_tree .. " lpeg")) + assert.is_true(run.luarocks_bool("build --deps-mode=none lxsh")) + + assert.is.truthy(lfs.attributes(testing_paths.testing_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) + + it("LuaRocks nodeps alias", function() + assert.is_true(run.luarocks_bool("build --tree=" .. testing_paths.testing_tree .. " --nodeps lxsh")) + + assert.is.falsy(lfs.attributes(testing_paths.testing_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) + + it("make order", function() + assert.is_true(run.luarocks_bool("build --tree=" .. testing_paths.testing_sys_tree .. " lpeg")) + assert.is_true(run.luarocks_bool("download --source lxsh ${LXSH_V}")) + assert.is_true(run.luarocks_bool("unpack lxsh-${LXSH}.src.rock")) + lfs.chdir("lxsh-${LXSH}/lxsh-${LXSH_V}-1/") + assert.is_true(run.luarocks_bool("make --tree=" .. testing_paths.testing_tree .. " --deps-mode=order")) + + finally(function() + lfs.chdir(testing_paths.testrun_dir) + test_env.remove_dir("lxsh-${LXSH}") + assert.is_true(os.remove("lxsh-${LXSH}.src.rock")) + end) + + assert.is.falsy(lfs.attributes(testing_paths.testing_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) + + it("make order sys", function() + assert.is_true(run.luarocks_bool("build --tree=" .. testing_paths.testing_tree .. " lpeg")) + assert.is_true(run.luarocks_bool("download --source lxsh ${LXSH_V}")) + assert.is_true(run.luarocks_bool("unpack lxsh-${LXSH}.src.rock")) + lfs.chdir("lxsh-${LXSH}/lxsh-${LXSH_V}-1/") + assert.is_true(run.luarocks_bool("make --tree=" .. testing_paths.testing_sys_tree .. " --deps-mode=order")) + + finally(function() + lfs.chdir(testing_paths.testrun_dir) + test_env.remove_dir("lxsh-${LXSH}") + assert.is_true(os.remove("lxsh-${LXSH}.src.rock")) + end) + + assert.is.truthy(lfs.attributes(testing_paths.testing_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lpeg/${LPEG}/lpeg-${LPEG}.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) +end) diff --git a/spec/doc_spec.lua b/spec/doc_spec.lua new file mode 100644 index 0000000..f48f951 --- /dev/null +++ b/spec/doc_spec.lua @@ -0,0 +1,154 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run +local testing_paths = test_env.testing_paths + +describe("luarocks doc #integration", function() + before_each(function() + test_env.setup_specs() + end) + + describe("basic tests", function() + it("with no flags/arguments", function() + assert.is_false(run.luarocks_bool("doc")) + end) + + it("with invalid argument", function() + assert.is_false(run.luarocks_bool("doc invalid")) + end) + + it("with no homepage and no doc folder", function() + test_env.run_in_tmp(function(tmpdir) + test_env.write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://test.lua" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + test_env.write_file("test.lua", "return {}", finally) + + assert.is_true(run.luarocks_bool("install test-1.0-1.rockspec")) + assert.is_false(run.luarocks_bool("doc test --home")) + end, finally) + end) + + it("with no doc folder but with homepage", function() + test_env.run_in_tmp(function(tmpdir) + test_env.write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://test.lua" + } + description = { + homepage = "http://www.example.com" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + test_env.write_file("test.lua", "return {}", finally) + + assert.is_true(run.luarocks_bool("install test-1.0-1.rockspec")) + local output = assert.is.truthy(run.luarocks("doc test")) + assert.is.truthy(output:find("documentation directory not found")) + end, finally) + end) + end) + + describe("#namespaces", function() + it("retrieves docs for a namespaced package from the command-line", function() + assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(run.luarocks_bool("build a_rock 1.0 --keep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert.match("a_rock 2.0", run.luarocks("doc a_user/a_rock")) + end) + end) + + describe("tests with flags", function() + it("of installed package", function() + test_env.run_in_tmp(function(tmpdir) + test_env.write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://test.lua" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + test_env.write_file("test.lua", "return {}", finally) + + assert.is_true(run.luarocks_bool("install test-1.0-1.rockspec")) + lfs.mkdir(testing_paths.testing_sys_rocks .. "/test/1.0-1/doc") + test_env.write_file(testing_paths.testing_sys_rocks .. "/test/1.0-1/doc/doc.md", "", finally) + test_env.write_file(testing_paths.testing_sys_rocks .. "/test/1.0-1/doc/readme.md", "", finally) + assert.is_true(run.luarocks_bool("doc test")) + end, finally) + end) + + it("with --list", function() + test_env.run_in_tmp(function(tmpdir) + test_env.write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://test.lua" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + test_env.write_file("test.lua", "return {}", finally) + + assert.is_true(run.luarocks_bool("install test-1.0-1.rockspec")) + lfs.mkdir(testing_paths.testing_sys_rocks .. "/test/1.0-1/doc") + test_env.write_file(testing_paths.testing_sys_rocks .. "/test/1.0-1/doc/doc1.md", "", finally) + test_env.write_file(testing_paths.testing_sys_rocks .. "/test/1.0-1/doc/doc2.md", "", finally) + local output = assert.is.truthy(run.luarocks("doc test --list")) + assert.is.truthy(output:find("doc1%.md")) + assert.is.truthy(output:find("doc2%.md")) + end, finally) + end) + + it("with --porcelain", function() + test_env.run_in_tmp(function(tmpdir) + test_env.write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://test.lua" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + test_env.write_file("test.lua", "return {}", finally) + + assert.is_true(run.luarocks_bool("install test-1.0-1.rockspec")) + lfs.mkdir(testing_paths.testing_sys_rocks .. "/test/1.0-1/doc") + test_env.write_file(testing_paths.testing_sys_rocks .. "/test/1.0-1/doc/doc1.md", "", finally) + test_env.write_file(testing_paths.testing_sys_rocks .. "/test/1.0-1/doc/doc2.md", "", finally) + assert.is_true(run.luarocks_bool("doc test --porcelain")) + end, finally) + end) + end) +end) diff --git a/spec/download_spec.lua b/spec/download_spec.lua new file mode 100644 index 0000000..f7c10e8 --- /dev/null +++ b/spec/download_spec.lua @@ -0,0 +1,55 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run +local testing_paths = test_env.testing_paths + +local extra_rocks = { + "/say-1.3-1.rockspec", +} + +describe("luarocks download #integration", function() + + before_each(function() + test_env.setup_specs(extra_rocks) + end) + + it("with no flags/arguments", function() + assert.is_false(run.luarocks_bool("download")) + end) + + it("invalid", function() + assert.is_false(run.luarocks_bool("download invalid")) + end) + + it("all with delete downloaded files", function() --TODO maybe download --all more rocks + assert.is_true(run.luarocks_bool("download --all say")) + assert.is.truthy(lfs.attributes("say-1.3-1.rockspec")) + test_env.remove_files(lfs.currentdir(), "say--") + end) + + it("rockspec version", function() + assert.is_true(run.luarocks_bool("download --rockspec say 1.3-1")) + assert.is.truthy(lfs.attributes("say-1.3-1.rockspec")) + test_env.remove_files(lfs.currentdir(), "say--") + end) + + describe("#namespaces", function() + it("retrieves namespaced rockspec", function() + finally(function() + os.remove("a_rock-2.0-1.rockspec") + end) + assert(run.luarocks_bool("download a_user/a_rock --rockspec --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(lfs.attributes("a_rock-2.0-1.rockspec")) + end) + + it("retrieves namespaced rock", function() + finally(function() + os.remove("a_rock-2.0-1.src.rock") + end) + assert(run.luarocks_bool("download a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(lfs.attributes("a_rock-2.0-1.src.rock")) + end) + end) + + +end) diff --git a/spec/dummy_spec.lua b/spec/dummy_spec.lua new file mode 100644 index 0000000..9ddd669 --- /dev/null +++ b/spec/dummy_spec.lua @@ -0,0 +1,24 @@ +-- Dummy test file for including files with 0% coverage in the luacov report + +local test_env = require("spec.util.test_env") +local testing_paths = test_env.testing_paths + +test_env.setup_specs() +local runner = require("luacov.runner") +runner.init(testing_paths.testrun_dir .. "/luacov.config") + +require("luarocks.build.cmake") +require("luarocks.build.command") +require("luarocks.tools.tar") +require("luarocks.fetch.cvs") +require("luarocks.fetch.git_file") +require("luarocks.fetch.git_https") +require("luarocks.fetch.git_ssh") +require("luarocks.fetch.hg_http") +require("luarocks.fetch.hg_https") +require("luarocks.fetch.hg_ssh") +require("luarocks.fetch.hg") +require("luarocks.fetch.sscm") +require("luarocks.fetch.svn") + +runner.save_stats() diff --git a/spec/external_spec.lua b/spec/external_spec.lua new file mode 100644 index 0000000..5a69a67 --- /dev/null +++ b/spec/external_spec.lua @@ -0,0 +1,32 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run +local testing_paths = test_env.testing_paths + +describe("luarocks external commands #integration", function() + lazy_setup(function() + test_env.setup_specs() + test_env.mock_server_init() + end) + + lazy_teardown(function() + test_env.mock_server_done() + end) + + it("installs a legacy external command", function() + local rockspec = testing_paths.fixtures_dir .. "/legacyexternalcommand-0.1-1.rockspec" + assert.is_truthy(run.luarocks_bool("build " .. rockspec)) + assert.is.truthy(run.luarocks("show legacyexternalcommand")) + local output = run.luarocks("legacyexternalcommand") + assert.match("Argument missing", output) + output = run.luarocks("legacyexternalcommand foo") + assert.match("ARG1\tfoo", output) + assert.match("ARG2\tnil", output) + output = run.luarocks("legacyexternalcommand foo bar") + assert.match("ARG1\tfoo", output) + assert.match("ARG2\tbar", output) + output = run.luarocks("legacyexternalcommand foo bar bla") + assert.match("ARG1\tfoo", output) + assert.match("ARG2\tbar", output) + end) +end) + diff --git a/spec/fixtures/a_repo/a_build_dep-1.0-1.rockspec b/spec/fixtures/a_repo/a_build_dep-1.0-1.rockspec new file mode 100644 index 0000000..2398d3d --- /dev/null +++ b/spec/fixtures/a_repo/a_build_dep-1.0-1.rockspec @@ -0,0 +1,18 @@ +rockspec_format = "3.0" +package = "a_build_dep" +version = "1.0-1" +source = { + url = "http://localhost:8080/file/a_rock.lua" +} +description = { + summary = "An example rockspec that is a build dependency for has_build_dep.", +} +dependencies = { + "lua >= 5.1", +} +build = { + type = "builtin", + modules = { + build_dep = "a_rock.lua" + }, +} diff --git a/spec/fixtures/a_repo/a_build_dep-1.0-1.src.rock b/spec/fixtures/a_repo/a_build_dep-1.0-1.src.rock Binary files differnew file mode 100644 index 0000000..c56ee34 --- /dev/null +++ b/spec/fixtures/a_repo/a_build_dep-1.0-1.src.rock diff --git a/spec/fixtures/a_repo/a_rock-1.0-1.rockspec b/spec/fixtures/a_repo/a_rock-1.0-1.rockspec new file mode 100644 index 0000000..69d7820 --- /dev/null +++ b/spec/fixtures/a_repo/a_rock-1.0-1.rockspec @@ -0,0 +1,18 @@ +package = "a_rock" +version = "1.0-1" +source = { + url = "http://localhost:8080/file/a_rock.lua" +} +description = { + summary = "An example rockspec", + homepage = "http://www.example.com" +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + build = "a_rock.lua" + }, +} diff --git a/spec/fixtures/a_repo/a_rock-1.0-1.src.rock b/spec/fixtures/a_repo/a_rock-1.0-1.src.rock Binary files differnew file mode 100644 index 0000000..9d0bb45 --- /dev/null +++ b/spec/fixtures/a_repo/a_rock-1.0-1.src.rock diff --git a/spec/fixtures/a_repo/a_rock-2.0-1.src.rock b/spec/fixtures/a_repo/a_rock-2.0-1.src.rock Binary files differnew file mode 100644 index 0000000..5824c76 --- /dev/null +++ b/spec/fixtures/a_repo/a_rock-2.0-1.src.rock diff --git a/spec/fixtures/a_repo/busted_project-0.1-1.rockspec b/spec/fixtures/a_repo/busted_project-0.1-1.rockspec new file mode 100644 index 0000000..54ed28a --- /dev/null +++ b/spec/fixtures/a_repo/busted_project-0.1-1.rockspec @@ -0,0 +1,19 @@ +rockspec_format = "3.0" +package = "busted_project" +version = "0.1-1" +source = { + url = "http://localhost:8080/file/busted_project-0.1.tar.gz", + dir = "busted_project", +} +description = { + summary = "A project that uses Busted tests", +} +build = { + type = "builtin", + modules = { + sum = "sum.lua", + } +} +test = { + type = "busted", +} diff --git a/spec/fixtures/a_repo/busted_project-0.1-1.src.rock b/spec/fixtures/a_repo/busted_project-0.1-1.src.rock Binary files differnew file mode 100644 index 0000000..db92411 --- /dev/null +++ b/spec/fixtures/a_repo/busted_project-0.1-1.src.rock diff --git a/spec/fixtures/a_repo/has_another_namespaced_dep-1.0-1.rockspec b/spec/fixtures/a_repo/has_another_namespaced_dep-1.0-1.rockspec new file mode 100644 index 0000000..04cb06c --- /dev/null +++ b/spec/fixtures/a_repo/has_another_namespaced_dep-1.0-1.rockspec @@ -0,0 +1,19 @@ +rockspec_format = "3.0" +package = "has_another_namespaced_dep" +version = "1.0-1" +source = { + url = "http://localhost:8080/file/a_rock.lua" +} +description = { + summary = "An example rockspec", +} +dependencies = { + "another_user/a_rock", + "lua >= 5.1", +} +build = { + type = "builtin", + modules = { + bla = "a_rock.lua" + }, +} diff --git a/spec/fixtures/a_repo/has_another_namespaced_dep-1.0-1.src.rock b/spec/fixtures/a_repo/has_another_namespaced_dep-1.0-1.src.rock Binary files differnew file mode 100644 index 0000000..4bbbf1a --- /dev/null +++ b/spec/fixtures/a_repo/has_another_namespaced_dep-1.0-1.src.rock diff --git a/spec/fixtures/a_repo/has_build_dep-1.0-1.all.rock b/spec/fixtures/a_repo/has_build_dep-1.0-1.all.rock Binary files differnew file mode 100644 index 0000000..a2d09ab --- /dev/null +++ b/spec/fixtures/a_repo/has_build_dep-1.0-1.all.rock diff --git a/spec/fixtures/a_repo/has_build_dep-1.0-1.rockspec b/spec/fixtures/a_repo/has_build_dep-1.0-1.rockspec new file mode 100644 index 0000000..417473a --- /dev/null +++ b/spec/fixtures/a_repo/has_build_dep-1.0-1.rockspec @@ -0,0 +1,22 @@ +rockspec_format = "3.0" +package = "has_build_dep" +version = "1.0-1" +source = { + url = "http://localhost:8080/file/a_rock.lua" +} +description = { + summary = "An example rockspec that has build dependencies.", +} +dependencies = { + "a_rock", + "lua >= 5.1", +} +build_dependencies = { + "a_build_dep", +} +build = { + type = "builtin", + modules = { + bla = "a_rock.lua" + }, +} diff --git a/spec/fixtures/a_repo/has_build_dep-1.0-1.src.rock b/spec/fixtures/a_repo/has_build_dep-1.0-1.src.rock Binary files differnew file mode 100644 index 0000000..fc4e11b --- /dev/null +++ b/spec/fixtures/a_repo/has_build_dep-1.0-1.src.rock diff --git a/spec/fixtures/a_repo/has_namespaced_dep-1.0-1.rockspec b/spec/fixtures/a_repo/has_namespaced_dep-1.0-1.rockspec new file mode 100644 index 0000000..6152c78 --- /dev/null +++ b/spec/fixtures/a_repo/has_namespaced_dep-1.0-1.rockspec @@ -0,0 +1,19 @@ +rockspec_format = "3.0" +package = "has_namespaced_dep" +version = "1.0-1" +source = { + url = "http://localhost:8080/file/a_rock.lua" +} +description = { + summary = "An example rockspec", +} +dependencies = { + "a_user/a_rock", + "lua >= 5.1", +} +build = { + type = "builtin", + modules = { + bla = "a_rock.lua" + }, +} diff --git a/spec/fixtures/a_repo/has_namespaced_dep-1.0-1.src.rock b/spec/fixtures/a_repo/has_namespaced_dep-1.0-1.src.rock Binary files differnew file mode 100644 index 0000000..c4d5f94 --- /dev/null +++ b/spec/fixtures/a_repo/has_namespaced_dep-1.0-1.src.rock diff --git a/spec/fixtures/a_repo/manifest b/spec/fixtures/a_repo/manifest new file mode 100644 index 0000000..a5f770a --- /dev/null +++ b/spec/fixtures/a_repo/manifest @@ -0,0 +1,90 @@ +commands = {} +modules = {} +repository = { + a_build_dep = { + ["1.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + }, + a_rock = { + ["1.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + }, + ["2.0-1"] = { + { + arch = "src" + } + } + }, + busted_project = { + ["0.1-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + }, + has_another_namespaced_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + }, + has_build_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + }, + { + arch = "all" + } + } + }, + has_namespaced_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + }, + non_lua_file = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + }, + ["1.0-2"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifest-5.1 b/spec/fixtures/a_repo/manifest-5.1 new file mode 100644 index 0000000..a5f770a --- /dev/null +++ b/spec/fixtures/a_repo/manifest-5.1 @@ -0,0 +1,90 @@ +commands = {} +modules = {} +repository = { + a_build_dep = { + ["1.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + }, + a_rock = { + ["1.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + }, + ["2.0-1"] = { + { + arch = "src" + } + } + }, + busted_project = { + ["0.1-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + }, + has_another_namespaced_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + }, + has_build_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + }, + { + arch = "all" + } + } + }, + has_namespaced_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + }, + non_lua_file = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + }, + ["1.0-2"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifest-5.1.zip b/spec/fixtures/a_repo/manifest-5.1.zip Binary files differnew file mode 100644 index 0000000..e63d6f1 --- /dev/null +++ b/spec/fixtures/a_repo/manifest-5.1.zip diff --git a/spec/fixtures/a_repo/manifest-5.2 b/spec/fixtures/a_repo/manifest-5.2 new file mode 100644 index 0000000..a5f770a --- /dev/null +++ b/spec/fixtures/a_repo/manifest-5.2 @@ -0,0 +1,90 @@ +commands = {} +modules = {} +repository = { + a_build_dep = { + ["1.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + }, + a_rock = { + ["1.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + }, + ["2.0-1"] = { + { + arch = "src" + } + } + }, + busted_project = { + ["0.1-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + }, + has_another_namespaced_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + }, + has_build_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + }, + { + arch = "all" + } + } + }, + has_namespaced_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + }, + non_lua_file = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + }, + ["1.0-2"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifest-5.2.zip b/spec/fixtures/a_repo/manifest-5.2.zip Binary files differnew file mode 100644 index 0000000..cec28c0 --- /dev/null +++ b/spec/fixtures/a_repo/manifest-5.2.zip diff --git a/spec/fixtures/a_repo/manifest-5.3 b/spec/fixtures/a_repo/manifest-5.3 new file mode 100644 index 0000000..a5f770a --- /dev/null +++ b/spec/fixtures/a_repo/manifest-5.3 @@ -0,0 +1,90 @@ +commands = {} +modules = {} +repository = { + a_build_dep = { + ["1.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + }, + a_rock = { + ["1.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + }, + ["2.0-1"] = { + { + arch = "src" + } + } + }, + busted_project = { + ["0.1-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + }, + has_another_namespaced_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + }, + has_build_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + }, + { + arch = "all" + } + } + }, + has_namespaced_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + }, + non_lua_file = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + }, + ["1.0-2"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifest-5.3.zip b/spec/fixtures/a_repo/manifest-5.3.zip Binary files differnew file mode 100644 index 0000000..23df5c3 --- /dev/null +++ b/spec/fixtures/a_repo/manifest-5.3.zip diff --git a/spec/fixtures/a_repo/manifest-5.4 b/spec/fixtures/a_repo/manifest-5.4 new file mode 100644 index 0000000..a5f770a --- /dev/null +++ b/spec/fixtures/a_repo/manifest-5.4 @@ -0,0 +1,90 @@ +commands = {} +modules = {} +repository = { + a_build_dep = { + ["1.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + }, + a_rock = { + ["1.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + }, + ["2.0-1"] = { + { + arch = "src" + } + } + }, + busted_project = { + ["0.1-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + }, + has_another_namespaced_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + }, + has_build_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + }, + { + arch = "all" + } + } + }, + has_namespaced_dep = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + }, + non_lua_file = { + ["1.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + }, + ["1.0-2"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifest-5.4.zip b/spec/fixtures/a_repo/manifest-5.4.zip Binary files differnew file mode 100644 index 0000000..14b5621 --- /dev/null +++ b/spec/fixtures/a_repo/manifest-5.4.zip diff --git a/spec/fixtures/a_repo/manifests/a_user/a_rock-2.0-1.rockspec b/spec/fixtures/a_repo/manifests/a_user/a_rock-2.0-1.rockspec new file mode 100644 index 0000000..da5a9a1 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/a_user/a_rock-2.0-1.rockspec @@ -0,0 +1,17 @@ +package = "a_rock" +version = "2.0-1" +source = { + url = "http://localhost:8080/file/a_rock.lua" +} +description = { + summary = "An example rockspec", +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + build = "a_rock.lua" + }, +} diff --git a/spec/fixtures/a_repo/manifests/a_user/a_rock-2.0-1.src.rock b/spec/fixtures/a_repo/manifests/a_user/a_rock-2.0-1.src.rock Binary files differnew file mode 100644 index 0000000..8d10fac --- /dev/null +++ b/spec/fixtures/a_repo/manifests/a_user/a_rock-2.0-1.src.rock diff --git a/spec/fixtures/a_repo/manifests/a_user/manifest b/spec/fixtures/a_repo/manifests/a_user/manifest new file mode 100644 index 0000000..74b0c61 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/a_user/manifest @@ -0,0 +1,14 @@ +commands = {} +modules = {} +repository = { + a_rock = { + ["2.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifests/a_user/manifest-5.1 b/spec/fixtures/a_repo/manifests/a_user/manifest-5.1 new file mode 100644 index 0000000..74b0c61 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/a_user/manifest-5.1 @@ -0,0 +1,14 @@ +commands = {} +modules = {} +repository = { + a_rock = { + ["2.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifests/a_user/manifest-5.2 b/spec/fixtures/a_repo/manifests/a_user/manifest-5.2 new file mode 100644 index 0000000..74b0c61 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/a_user/manifest-5.2 @@ -0,0 +1,14 @@ +commands = {} +modules = {} +repository = { + a_rock = { + ["2.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifests/a_user/manifest-5.3 b/spec/fixtures/a_repo/manifests/a_user/manifest-5.3 new file mode 100644 index 0000000..74b0c61 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/a_user/manifest-5.3 @@ -0,0 +1,14 @@ +commands = {} +modules = {} +repository = { + a_rock = { + ["2.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifests/a_user/manifest-5.4 b/spec/fixtures/a_repo/manifests/a_user/manifest-5.4 new file mode 100644 index 0000000..74b0c61 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/a_user/manifest-5.4 @@ -0,0 +1,14 @@ +commands = {} +modules = {} +repository = { + a_rock = { + ["2.0-1"] = { + { + arch = "rockspec" + }, + { + arch = "src" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifests/another_user/a_rock-3.0-1.rockspec b/spec/fixtures/a_repo/manifests/another_user/a_rock-3.0-1.rockspec new file mode 100644 index 0000000..628c5a4 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/another_user/a_rock-3.0-1.rockspec @@ -0,0 +1,17 @@ +package = "a_rock" +version = "3.0-1" +source = { + url = "http://localhost:8080/file/a_rock.lua" +} +description = { + summary = "An example rockspec", +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + a_rock = "a_rock.lua" + }, +} diff --git a/spec/fixtures/a_repo/manifests/another_user/a_rock-3.0-1.src.rock b/spec/fixtures/a_repo/manifests/another_user/a_rock-3.0-1.src.rock Binary files differnew file mode 100644 index 0000000..4c20afc --- /dev/null +++ b/spec/fixtures/a_repo/manifests/another_user/a_rock-3.0-1.src.rock diff --git a/spec/fixtures/a_repo/manifests/another_user/manifest b/spec/fixtures/a_repo/manifests/another_user/manifest new file mode 100644 index 0000000..185aed0 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/another_user/manifest @@ -0,0 +1,14 @@ +commands = {} +modules = {} +repository = { + a_rock = { + ["3.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifests/another_user/manifest-5.1 b/spec/fixtures/a_repo/manifests/another_user/manifest-5.1 new file mode 100644 index 0000000..185aed0 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/another_user/manifest-5.1 @@ -0,0 +1,14 @@ +commands = {} +modules = {} +repository = { + a_rock = { + ["3.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifests/another_user/manifest-5.2 b/spec/fixtures/a_repo/manifests/another_user/manifest-5.2 new file mode 100644 index 0000000..185aed0 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/another_user/manifest-5.2 @@ -0,0 +1,14 @@ +commands = {} +modules = {} +repository = { + a_rock = { + ["3.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifests/another_user/manifest-5.3 b/spec/fixtures/a_repo/manifests/another_user/manifest-5.3 new file mode 100644 index 0000000..185aed0 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/another_user/manifest-5.3 @@ -0,0 +1,14 @@ +commands = {} +modules = {} +repository = { + a_rock = { + ["3.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + } +} diff --git a/spec/fixtures/a_repo/manifests/another_user/manifest-5.4 b/spec/fixtures/a_repo/manifests/another_user/manifest-5.4 new file mode 100644 index 0000000..185aed0 --- /dev/null +++ b/spec/fixtures/a_repo/manifests/another_user/manifest-5.4 @@ -0,0 +1,14 @@ +commands = {} +modules = {} +repository = { + a_rock = { + ["3.0-1"] = { + { + arch = "src" + }, + { + arch = "rockspec" + } + } + } +} diff --git a/spec/fixtures/a_repo/non_lua_file-1.0-1.rockspec b/spec/fixtures/a_repo/non_lua_file-1.0-1.rockspec new file mode 100644 index 0000000..51ef42e --- /dev/null +++ b/spec/fixtures/a_repo/non_lua_file-1.0-1.rockspec @@ -0,0 +1,22 @@ +-- regression test for sailorproject/sailor#138 +rockspec_format = "3.0" +package = "non_lua_file" +version = "1.0-1" +source = { + url = "file://../upstream/non_lua_file-1.0.tar.gz" +} +description = { + summary = "An example rockspec that has a script.", +} +dependencies = { + "lua >= 5.1", +} +build = { + type = "builtin", + modules = {}, + install = { + lua = { + ["sailor.blank-app.htaccess"] = "src/sailor/blank-app/.htaccess", + } + } +} diff --git a/spec/fixtures/a_repo/non_lua_file-1.0-1.src.rock b/spec/fixtures/a_repo/non_lua_file-1.0-1.src.rock Binary files differnew file mode 100644 index 0000000..148f703 --- /dev/null +++ b/spec/fixtures/a_repo/non_lua_file-1.0-1.src.rock diff --git a/spec/fixtures/a_repo/non_lua_file-1.0-2.rockspec b/spec/fixtures/a_repo/non_lua_file-1.0-2.rockspec new file mode 100644 index 0000000..f9d2e2c --- /dev/null +++ b/spec/fixtures/a_repo/non_lua_file-1.0-2.rockspec @@ -0,0 +1,22 @@ +-- regression test for sailorproject/sailor#138 +rockspec_format = "3.0" +package = "non_lua_file" +version = "1.0-2" +source = { + url = "file://../upstream/non_lua_file-1.0.tar.gz" +} +description = { + summary = "An example rockspec that has a script.", +} +dependencies = { + "lua >= 5.1", +} +build = { + type = "builtin", + modules = {}, + install = { + lua = { + ["sailor.blank-app.htaccess"] = "src/sailor/blank-app/.htaccess", + } + } +} diff --git a/spec/fixtures/a_repo/non_lua_file-1.0-2.src.rock b/spec/fixtures/a_repo/non_lua_file-1.0-2.src.rock Binary files differnew file mode 100644 index 0000000..06eb9ac --- /dev/null +++ b/spec/fixtures/a_repo/non_lua_file-1.0-2.src.rock diff --git a/spec/fixtures/a_rock-1.0-1.rockspec b/spec/fixtures/a_rock-1.0-1.rockspec new file mode 100644 index 0000000..9f15e87 --- /dev/null +++ b/spec/fixtures/a_rock-1.0-1.rockspec @@ -0,0 +1,17 @@ +package = "a_rock" +version = "1.0-1" +source = { + url = "http://localhost:8080/file/a_rock.lua" +} +description = { + summary = "An example rockspec", +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + build = "a_rock.lua" + }, +} diff --git a/spec/fixtures/a_rock-1.0-1.src.rock b/spec/fixtures/a_rock-1.0-1.src.rock Binary files differnew file mode 100644 index 0000000..9d0bb45 --- /dev/null +++ b/spec/fixtures/a_rock-1.0-1.src.rock diff --git a/spec/fixtures/a_rock.lua b/spec/fixtures/a_rock.lua new file mode 100644 index 0000000..a564707 --- /dev/null +++ b/spec/fixtures/a_rock.lua @@ -0,0 +1 @@ +return {} diff --git a/spec/fixtures/abc.bz2 b/spec/fixtures/abc.bz2 Binary files differnew file mode 100644 index 0000000..ee78671 --- /dev/null +++ b/spec/fixtures/abc.bz2 diff --git a/spec/fixtures/an_upstream_tarball-0.1.tar.gz b/spec/fixtures/an_upstream_tarball-0.1.tar.gz Binary files differnew file mode 100644 index 0000000..518c8cb --- /dev/null +++ b/spec/fixtures/an_upstream_tarball-0.1.tar.gz diff --git a/spec/fixtures/bad_pack-0.1-1.rockspec b/spec/fixtures/bad_pack-0.1-1.rockspec new file mode 100644 index 0000000..2393424 --- /dev/null +++ b/spec/fixtures/bad_pack-0.1-1.rockspec @@ -0,0 +1,19 @@ +rockspec_format = "3.0" +package = "bad_pack" +version = "0.1-1" +source = { + url = "http://localhost:8080/file/busted_project-0.1.tar.gz", + dir = "invalid_dir", +} +description = { + summary = "A project that uses Busted tests", +} +build = { + type = "builtin", + modules = { + sum = "sum.lua", + } +} +test = { + type = "busted", +} diff --git a/spec/fixtures/build_only_deps-0.1-1.rockspec b/spec/fixtures/build_only_deps-0.1-1.rockspec new file mode 100644 index 0000000..02d2b47 --- /dev/null +++ b/spec/fixtures/build_only_deps-0.1-1.rockspec @@ -0,0 +1,18 @@ +package = "build_only_deps" +version = "0.1-1" +source = { + url = "file://./a_rock.lua" +} +description = { + summary = "Fixture to test --only-deps", +} +dependencies = { + "lua >= 5.1", + "a_rock 1.0", +} +build = { + type = "builtin", + modules = { + dummy = "a_rock.lua", + } +} diff --git a/spec/fixtures/build_only_deps-0.1-1.src.rock b/spec/fixtures/build_only_deps-0.1-1.src.rock Binary files differnew file mode 100644 index 0000000..74b2d1e --- /dev/null +++ b/spec/fixtures/build_only_deps-0.1-1.src.rock diff --git a/spec/fixtures/busted_project-0.1-1.rockspec b/spec/fixtures/busted_project-0.1-1.rockspec new file mode 100644 index 0000000..54ed28a --- /dev/null +++ b/spec/fixtures/busted_project-0.1-1.rockspec @@ -0,0 +1,19 @@ +rockspec_format = "3.0" +package = "busted_project" +version = "0.1-1" +source = { + url = "http://localhost:8080/file/busted_project-0.1.tar.gz", + dir = "busted_project", +} +description = { + summary = "A project that uses Busted tests", +} +build = { + type = "builtin", + modules = { + sum = "sum.lua", + } +} +test = { + type = "busted", +} diff --git a/spec/fixtures/busted_project-0.1.tar.gz b/spec/fixtures/busted_project-0.1.tar.gz Binary files differnew file mode 100644 index 0000000..bd4e055 --- /dev/null +++ b/spec/fixtures/busted_project-0.1.tar.gz diff --git a/spec/fixtures/busted_project/spec/sum_spec.lua b/spec/fixtures/busted_project/spec/sum_spec.lua new file mode 100644 index 0000000..2fa0537 --- /dev/null +++ b/spec/fixtures/busted_project/spec/sum_spec.lua @@ -0,0 +1,10 @@ + +local sum = require("sum") + +describe("sum", function() + + it("sums", function() + assert.equal(2, sum.sum(1, 1)) + end) + +end) diff --git a/spec/fixtures/busted_project/sum.lua b/spec/fixtures/busted_project/sum.lua new file mode 100644 index 0000000..ba12805 --- /dev/null +++ b/spec/fixtures/busted_project/sum.lua @@ -0,0 +1,7 @@ +local sum = {} + +function sum.sum(a, b) + return a + b +end + +return sum diff --git a/spec/fixtures/double_deploy_type/ddt.c b/spec/fixtures/double_deploy_type/ddt.c new file mode 100644 index 0000000..f9050a4 --- /dev/null +++ b/spec/fixtures/double_deploy_type/ddt.c @@ -0,0 +1,6 @@ +#include "lua.h" + +int luaopen_ddt(lua_State *L) { + lua_pushstring(L, "ddt.c"); + return 1; +} diff --git a/spec/fixtures/double_deploy_type/ddt1.lua b/spec/fixtures/double_deploy_type/ddt1.lua new file mode 100644 index 0000000..ea1dafe --- /dev/null +++ b/spec/fixtures/double_deploy_type/ddt1.lua @@ -0,0 +1 @@ +return "ddt1" diff --git a/spec/fixtures/double_deploy_type/ddt2.lua b/spec/fixtures/double_deploy_type/ddt2.lua new file mode 100644 index 0000000..b1fa5d7 --- /dev/null +++ b/spec/fixtures/double_deploy_type/ddt2.lua @@ -0,0 +1 @@ +return "ddt2" diff --git a/spec/fixtures/double_deploy_type/ddt_file b/spec/fixtures/double_deploy_type/ddt_file new file mode 100644 index 0000000..988bbfb --- /dev/null +++ b/spec/fixtures/double_deploy_type/ddt_file @@ -0,0 +1 @@ +return "ddt_file" diff --git a/spec/fixtures/double_deploy_type/double_deploy_type-0.1.0-1.rockspec b/spec/fixtures/double_deploy_type/double_deploy_type-0.1.0-1.rockspec new file mode 100644 index 0000000..ff13df0 --- /dev/null +++ b/spec/fixtures/double_deploy_type/double_deploy_type-0.1.0-1.rockspec @@ -0,0 +1,22 @@ +package = "double_deploy_type" +version = "0.1.0-1" +source = { + url = "http://example.com" +} +description = { + homepage = "http://example.com", + license = "*** please specify a license ***" +} +dependencies = {} +build = { + type = "builtin", + modules = { + ddt = "ddt/ddt.c" + }, + install = { + lua = { + ddt = "ddt/ddt1.lua", + ddt_file = "ddt/ddt_file", + } + } +} diff --git a/spec/fixtures/double_deploy_type/double_deploy_type-0.2.0-1.rockspec b/spec/fixtures/double_deploy_type/double_deploy_type-0.2.0-1.rockspec new file mode 100644 index 0000000..15f0c15 --- /dev/null +++ b/spec/fixtures/double_deploy_type/double_deploy_type-0.2.0-1.rockspec @@ -0,0 +1,22 @@ +package = "double_deploy_type" +version = "0.2.0-1" +source = { + url = "http://example.com" +} +description = { + homepage = "http://example.com", + license = "*** please specify a license ***" +} +dependencies = {} +build = { + type = "builtin", + modules = { + ddt = "ddt/ddt.c" + }, + install = { + lua = { + ddt = "ddt/ddt2.lua", + ddt_file = "ddt/ddt_file", + } + } +} diff --git a/spec/fixtures/fixturedep.c b/spec/fixtures/fixturedep.c new file mode 100644 index 0000000..e3fcdd5 --- /dev/null +++ b/spec/fixtures/fixturedep.c @@ -0,0 +1,4 @@ + +int fixturedep_fn() { + return 0; +} diff --git a/spec/fixtures/git_repo/LICENSE b/spec/fixtures/git_repo/LICENSE new file mode 100644 index 0000000..e8c415d --- /dev/null +++ b/spec/fixtures/git_repo/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018 Test + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/spec/fixtures/git_repo/README.md b/spec/fixtures/git_repo/README.md new file mode 100644 index 0000000..220327e --- /dev/null +++ b/spec/fixtures/git_repo/README.md @@ -0,0 +1,3 @@ + + +Test repo diff --git a/spec/fixtures/gpg/private-keys-v1.d/5D2D3F97B88B18604D819EA9DF5B730C75D71B60.key b/spec/fixtures/gpg/private-keys-v1.d/5D2D3F97B88B18604D819EA9DF5B730C75D71B60.key Binary files differnew file mode 100644 index 0000000..26240f5 --- /dev/null +++ b/spec/fixtures/gpg/private-keys-v1.d/5D2D3F97B88B18604D819EA9DF5B730C75D71B60.key diff --git a/spec/fixtures/gpg/private-keys-v1.d/B71C36B4EDEB72A047FED1C01BCFF4D08837E3B1.key b/spec/fixtures/gpg/private-keys-v1.d/B71C36B4EDEB72A047FED1C01BCFF4D08837E3B1.key Binary files differnew file mode 100644 index 0000000..e75a2eb --- /dev/null +++ b/spec/fixtures/gpg/private-keys-v1.d/B71C36B4EDEB72A047FED1C01BCFF4D08837E3B1.key diff --git a/spec/fixtures/gpg/pubring.kbx b/spec/fixtures/gpg/pubring.kbx Binary files differnew file mode 100644 index 0000000..fc63cbc --- /dev/null +++ b/spec/fixtures/gpg/pubring.kbx diff --git a/spec/fixtures/gpg/trustdb.gpg b/spec/fixtures/gpg/trustdb.gpg Binary files differnew file mode 100644 index 0000000..cabca66 --- /dev/null +++ b/spec/fixtures/gpg/trustdb.gpg diff --git a/spec/fixtures/invalid_patch-0.1-1.rockspec b/spec/fixtures/invalid_patch-0.1-1.rockspec new file mode 100644 index 0000000..c2ecd16 --- /dev/null +++ b/spec/fixtures/invalid_patch-0.1-1.rockspec @@ -0,0 +1,29 @@ +package = "invalid_patch" +version = "0.1-1" +source = { + -- any valid URL + url = "https://raw.github.com/keplerproject/luarocks/master/src/luarocks/build.lua" +} +description = { + summary = "A rockspec with an invalid patch", +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + build = "build.lua" + }, + patches = { + ["I_am_an_invalid_patch.patch"] = +[[ +diff -Naur luadoc-3.0.1/src/luadoc/doclet/html.lua luadoc-3.0.1-new/src/luadoc/doclet/html.lua +--- luadoc-3.0.1/src/luadoc/doclet/html.lua2007-12-21 15:50:48.000000000 -0200 ++++ luadoc-3.0.1-new/src/luadoc/doclet/html.lua2008-02-28 01:59:53.000000000 -0300 +@@ -18,6 +18,7 @@ +- gabba gabba gabba ++ gobo gobo gobo +]] + } +} diff --git a/spec/fixtures/invalid_say-1.3-1.rockspec b/spec/fixtures/invalid_say-1.3-1.rockspec new file mode 100644 index 0000000..890b4db --- /dev/null +++ b/spec/fixtures/invalid_say-1.3-1.rockspec @@ -0,0 +1,23 @@ +package = "say" +version = "1.3-1" +source = {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{++{ + url = "https://github.com/Olivine-Labs/say/archive/v1.3-1.tar.gz", + dir = "say-1.3-1" +} +description = { + summary = "Lua String Hashing/Indexing Library", + detailed = [[ + Useful for internationalization. + ]], + homepage = "http://olivinelabs.com/busted/", + license = "MIT <http://opensource.org/licenses/MIT>" +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + ["say.init"] = "src/init.lua" + } +} diff --git a/spec/fixtures/legacyexternalcommand-0.1-1.rockspec b/spec/fixtures/legacyexternalcommand-0.1-1.rockspec new file mode 100644 index 0000000..47bcbb0 --- /dev/null +++ b/spec/fixtures/legacyexternalcommand-0.1-1.rockspec @@ -0,0 +1,17 @@ +package = "legacyexternalcommand" +version = "0.1-1" +source = { + url = "http://localhost:8080/file/legacyexternalcommand.lua" +} +description = { + summary = "an external command with legacy arg parsing", +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + ["luarocks.cmd.external.legacyexternalcommand"] = "legacyexternalcommand.lua", + } +} diff --git a/spec/fixtures/legacyexternalcommand.lua b/spec/fixtures/legacyexternalcommand.lua new file mode 100644 index 0000000..af57537 --- /dev/null +++ b/spec/fixtures/legacyexternalcommand.lua @@ -0,0 +1,34 @@ + +--- Module implementing an external command with legacy arg parsing. +local legacyexternalcommand = {} + +local util = require("luarocks.util") + +legacyexternalcommand.help_summary = "generate legacyexternalcommand package files of a rock." +legacyexternalcommand.help_arguments = "arg1 [arg2]" +legacyexternalcommand.help = [[ +This addon generates legacyexternalcommand package files of a rock. +First argument is the name of a rock, the second argument is optional +and needed when legacyexternalcommand uses another name (usually prefixed by lua-). +Files are generated with the source content of the rock and more +especially the rockspec. So, the rock is downloaded and unpacked. +]] + +--- Driver function for the "legacyexternalcommand" command. +-- @param arg1 string: arg1. +-- @param arg2 string: arg2 (optional) +-- @return boolean: true if successful +function legacyexternalcommand.command(flags, arg1, arg2) + if type(arg1) ~= 'string' then + return nil, "Argument missing. "..util.see_help('legacyexternalcommand') + end + + for k,v in pairs(flags) do + print("FLAGS", k,v) + end + print("ARG1", tostring(arg1)) + print("ARG2", tostring(arg2)) + return true +end + +return legacyexternalcommand diff --git a/spec/fixtures/luajit-fail-1.0-1.rockspec b/spec/fixtures/luajit-fail-1.0-1.rockspec new file mode 100644 index 0000000..f820460 --- /dev/null +++ b/spec/fixtures/luajit-fail-1.0-1.rockspec @@ -0,0 +1,22 @@ +package = "luajit-fail" +version = "1.0-1" +source = { + url = "https://raw.githubusercontent.com/keplerproject/luarocks/master/test/testing.lua", +} +description = { + summary = "Test luajit dependency fail", + detailed = [[ +Fail luajit dependency when running with rockspec_format < 3.0. +]], + homepage = "http://luarocks.org/", + license = "MIT/X license" +} +dependencies = { + "luajit >= 2.0" +} +build = { + type = "builtin", + modules = { + testing = "testing.lua" + } +} diff --git a/spec/fixtures/luajit-success-1.0-1.rockspec b/spec/fixtures/luajit-success-1.0-1.rockspec new file mode 100644 index 0000000..31c930c --- /dev/null +++ b/spec/fixtures/luajit-success-1.0-1.rockspec @@ -0,0 +1,23 @@ +rockspec_format = "3.0" +package = "luajit-success" +version = "1.0-1" +source = { + url = "https://raw.githubusercontent.com/keplerproject/luarocks/master/test/testing.lua", +} +description = { + summary = "Test luajit dependency fail", + detailed = [[ +Use luajit dependency when running with rockspec_format >= 3.0. +]], + homepage = "http://luarocks.org/", + license = "MIT/X license" +} +dependencies = { + "luajit >= 2.0" +} +build = { + type = "builtin", + modules = { + testing = "testing.lua" + } +} diff --git a/spec/fixtures/mixed_deploy_type/mdt.c b/spec/fixtures/mixed_deploy_type/mdt.c new file mode 100644 index 0000000..a162ce2 --- /dev/null +++ b/spec/fixtures/mixed_deploy_type/mdt.c @@ -0,0 +1,6 @@ +#include "lua.h" + +int luaopen_mdt(lua_State *L) { + lua_pushstring(L, "mdt.c"); + return 1; +} diff --git a/spec/fixtures/mixed_deploy_type/mdt.lua b/spec/fixtures/mixed_deploy_type/mdt.lua new file mode 100644 index 0000000..c9ca9c6 --- /dev/null +++ b/spec/fixtures/mixed_deploy_type/mdt.lua @@ -0,0 +1 @@ +return "mdt.lua" diff --git a/spec/fixtures/mixed_deploy_type/mdt_file b/spec/fixtures/mixed_deploy_type/mdt_file new file mode 100644 index 0000000..1a15f7d --- /dev/null +++ b/spec/fixtures/mixed_deploy_type/mdt_file @@ -0,0 +1 @@ +return "mdt_file" diff --git a/spec/fixtures/mixed_deploy_type/mixed_deploy_type-0.1.0-1.rockspec b/spec/fixtures/mixed_deploy_type/mixed_deploy_type-0.1.0-1.rockspec new file mode 100644 index 0000000..91b725d --- /dev/null +++ b/spec/fixtures/mixed_deploy_type/mixed_deploy_type-0.1.0-1.rockspec @@ -0,0 +1,21 @@ +package = "mixed_deploy_type" +version = "0.1.0-1" +source = { + url = "http://example.com" +} +description = { + homepage = "http://example.com", + license = "*** please specify a license ***" +} +dependencies = {} +build = { + type = "builtin", + modules = { + mdt = "mdt/mdt.lua" + }, + install = { + lua = { + mdt_file = "mdt/mdt_file" + } + } +} diff --git a/spec/fixtures/mixed_deploy_type/mixed_deploy_type-0.2.0-1.rockspec b/spec/fixtures/mixed_deploy_type/mixed_deploy_type-0.2.0-1.rockspec new file mode 100644 index 0000000..9ca0318 --- /dev/null +++ b/spec/fixtures/mixed_deploy_type/mixed_deploy_type-0.2.0-1.rockspec @@ -0,0 +1,21 @@ +package = "mixed_deploy_type" +version = "0.2.0-1" +source = { + url = "http://example.com" +} +description = { + homepage = "http://example.com", + license = "*** please specify a license ***" +} +dependencies = {} +build = { + type = "builtin", + modules = { + mdt = "mdt/mdt.c" + }, + install = { + lib = { + mdt_file = "mdt/mdt_file" + } + } +} diff --git a/spec/fixtures/patch_create_delete-0.1-1.rockspec b/spec/fixtures/patch_create_delete-0.1-1.rockspec new file mode 100644 index 0000000..3d55da5 --- /dev/null +++ b/spec/fixtures/patch_create_delete-0.1-1.rockspec @@ -0,0 +1,34 @@ +rockspec_format = "3.0" +package = "patch_create_delete" +version = "0.1-1" +source = { + -- any valid URL + url = "git://github.com/luarocks/luarocks" +} +description = { + summary = "A rockspec with a patch that creates and deletes files", +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + ["luarocks.loader"] = "src/luarocks/loader.lua" + }, + patches = { + ["create_delete.patch"] = +[[ +diff -Naur luarocks/spec/fixtures/patch_create_delete/a_file.txt luarocks-patch/spec/fixtures/patch_create_delete/a_file.txt +--- luarocks/spec/fixtures/patch_create_delete/a_file.txt 2017-10-04 15:39:44.179306674 -0300 ++++ luarocks-patch/spec/fixtures/patch_create_delete/a_file.txt 1969-12-31 21:00:00.000000000 -0300 +@@ -1 +0,0 @@ +-I am a file. +diff -Naur luarocks/spec/fixtures/patch_create_delete/another_file.txt luarocks-patch/spec/fixtures/patch_create_delete/another_file.txt +--- luarocks/spec/fixtures/patch_create_delete/another_file.txt 1969-12-31 21:00:00.000000000 -0300 ++++ luarocks-patch/spec/fixtures/patch_create_delete/another_file.txt 2017-10-04 15:40:12.836306564 -0300 +@@ -0,0 +1 @@ ++I am another file. +]] + } +} diff --git a/spec/fixtures/patch_create_delete/a_file.txt b/spec/fixtures/patch_create_delete/a_file.txt new file mode 100644 index 0000000..6539c24 --- /dev/null +++ b/spec/fixtures/patch_create_delete/a_file.txt @@ -0,0 +1 @@ +I am a file. diff --git a/spec/fixtures/renamed_upstream_tarball-0.1.tar.gz b/spec/fixtures/renamed_upstream_tarball-0.1.tar.gz Binary files differnew file mode 100644 index 0000000..518c8cb --- /dev/null +++ b/spec/fixtures/renamed_upstream_tarball-0.1.tar.gz diff --git a/spec/fixtures/with_external_dep-0.1-1.rockspec b/spec/fixtures/with_external_dep-0.1-1.rockspec new file mode 100644 index 0000000..45fea4b --- /dev/null +++ b/spec/fixtures/with_external_dep-0.1-1.rockspec @@ -0,0 +1,25 @@ +package = "with_external_dep" +version = "0.1-1" +source = { + url = "http://localhost:8080/file/with_external_dep.c" +} +description = { + summary = "An example rockspec", +} +external_dependencies = { + FOO = { + header = "foo/foo.h" + } +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + with_external_dep = { + sources = "with_external_dep.c", + incdirs = "$(FOO_INCDIR)", + } + } +} diff --git a/spec/fixtures/with_external_dep.c b/spec/fixtures/with_external_dep.c new file mode 100644 index 0000000..16435d8 --- /dev/null +++ b/spec/fixtures/with_external_dep.c @@ -0,0 +1,10 @@ +#include <foo/foo.h> +#include <lua.h> +#include <lauxlib.h> + +int luaopen_with_external_dep(lua_State* L) { + lua_newtable(L); + lua_pushinteger(L, FOO); + lua_setfield(L, -2, "foo"); + return 1; +} diff --git a/spec/fixtures/with_external_dep/foo/foo.h b/spec/fixtures/with_external_dep/foo/foo.h new file mode 100644 index 0000000..eedd558 --- /dev/null +++ b/spec/fixtures/with_external_dep/foo/foo.h @@ -0,0 +1 @@ +#define FOO 42 diff --git a/spec/fs_spec.lua b/spec/fs_spec.lua new file mode 100644 index 0000000..d5e93c4 --- /dev/null +++ b/spec/fs_spec.lua @@ -0,0 +1,76 @@ +local test_env = require("spec.util.test_env") + +local lfs = require("lfs") +local testing_paths = test_env.testing_paths +local get_tmp_path = test_env.get_tmp_path + +describe("luarocks.fs #integration", function() + + local fs + + describe("fs.download #mock", function() + local tmpfile + local tmpdir + + lazy_setup(function() + test_env.setup_specs(nil, "mock") + local cfg = require("luarocks.core.cfg") + fs = require("luarocks.fs") + cfg.init() + fs.init() + test_env.mock_server_init() + end) + + lazy_teardown(function() + test_env.mock_server_done() + end) + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns true and fetches the url argument into the specified filename", function() + tmpfile = get_tmp_path() + assert.truthy(fs.download("http://localhost:8080/file/a_rock.lua", tmpfile)) + local fd = assert(io.open(tmpfile, "r")) + local downloadcontent = assert(fd:read("*a")) + fd:close() + fd = assert(io.open(testing_paths.fixtures_dir .. "/a_rock.lua", "r")) + local originalcontent = assert(fd:read("*a")) + fd:close() + assert.same(downloadcontent, originalcontent) + end) + + it("returns true and fetches the url argument into a file whose name matches the basename of the url if the filename argument is not given", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + fs.change_dir(tmpdir) + assert.truthy(fs.download("http://localhost:8080/file/a_rock.lua")) + tmpfile = tmpdir .. "/a_rock.lua" + local fd = assert(io.open(tmpfile, "r")) + local downloadcontent = assert(fd:read("*a")) + fd:close() + fd = assert(io.open(testing_paths.fixtures_dir .. "/a_rock.lua", "r")) + local originalcontent = assert(fd:read("*a")) + fd:close() + assert.same(downloadcontent, originalcontent) + fs.pop_dir() + end) + + it("returns false and does nothing if the url argument contains a nonexistent file", function() + tmpfile = get_tmp_path() + assert.falsy(fs.download("http://localhost:8080/file/nonexistent", tmpfile)) + end) + + it("returns false and does nothing if the url argument is invalid", function() + assert.falsy(fs.download("invalidurl")) + end) + end) +end) diff --git a/spec/help_spec.lua b/spec/help_spec.lua new file mode 100644 index 0000000..e13f1c3 --- /dev/null +++ b/spec/help_spec.lua @@ -0,0 +1,25 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run + +describe("luarocks help #integration", function() + + before_each(function() + test_env.setup_specs() + end) + + it("with no flags/arguments", function() + assert.is_true(run.luarocks_bool("help")) + end) + + it("invalid argument", function() + assert.is_false(run.luarocks_bool("help invalid")) + end) + + it("config", function() + assert.is_true(run.luarocks_bool("help config")) + end) + + it("luarocks-admin help with no flags/arguments", function() + assert.is_true(run.luarocks_admin_bool(test_env.quiet("help"))) + end) +end) diff --git a/spec/init_spec.lua b/spec/init_spec.lua new file mode 100644 index 0000000..88bd23a --- /dev/null +++ b/spec/init_spec.lua @@ -0,0 +1,235 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run +local testing_paths = test_env.testing_paths +local copy_dir = test_env.copy_dir +local is_win = test_env.TEST_TARGET_OS == "windows" +local write_file = test_env.write_file +local lfs = require("lfs") + +describe("luarocks init #integration", function() + + lazy_setup(function() + test_env.setup_specs() + end) + + it("with no arguments", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init")) + if is_win then + assert.truthy(lfs.attributes(myproject .. "/lua.bat")) + assert.truthy(lfs.attributes(myproject .. "/luarocks.bat")) + else + assert.truthy(lfs.attributes(myproject .. "/lua")) + assert.truthy(lfs.attributes(myproject .. "/luarocks")) + end + assert.truthy(lfs.attributes(myproject .. "/lua_modules")) + assert.truthy(lfs.attributes(myproject .. "/.luarocks")) + assert.truthy(lfs.attributes(myproject .. "/.luarocks/config-" .. test_env.lua_version .. ".lua")) + assert.truthy(lfs.attributes(myproject .. "/.gitignore")) + assert.truthy(lfs.attributes(myproject .. "/myproject-dev-1.rockspec")) + end, finally) + end) + + it("with --no-gitignore", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init --no-gitignore")) + if is_win then + assert.truthy(lfs.attributes(myproject .. "/lua.bat")) + assert.truthy(lfs.attributes(myproject .. "/luarocks.bat")) + else + assert.truthy(lfs.attributes(myproject .. "/lua")) + assert.truthy(lfs.attributes(myproject .. "/luarocks")) + end + assert.truthy(lfs.attributes(myproject .. "/lua_modules")) + assert.truthy(lfs.attributes(myproject .. "/.luarocks")) + assert.truthy(lfs.attributes(myproject .. "/.luarocks/config-" .. test_env.lua_version .. ".lua")) + assert.falsy(lfs.attributes(myproject .. "/.gitignore")) + assert.truthy(lfs.attributes(myproject .. "/myproject-dev-1.rockspec")) + end, finally) + end) + + it("with --no-wrapper-scripts", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init --no-wrapper-scripts")) + assert.falsy(lfs.attributes(myproject .. "/lua.bat")) + assert.falsy(lfs.attributes(myproject .. "/luarocks.bat")) + assert.falsy(lfs.attributes(myproject .. "/lua")) + assert.falsy(lfs.attributes(myproject .. "/luarocks")) + assert.truthy(lfs.attributes(myproject .. "/lua_modules")) + assert.truthy(lfs.attributes(myproject .. "/.luarocks")) + assert.truthy(lfs.attributes(myproject .. "/.luarocks/config-" .. test_env.lua_version .. ".lua")) + assert.truthy(lfs.attributes(myproject .. "/.gitignore")) + assert.truthy(lfs.attributes(myproject .. "/myproject-dev-1.rockspec")) + end, finally) + end) + + it("with --wrapper-dir", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init --wrapper-dir=./bin")) + if is_win then + assert.truthy(lfs.attributes(myproject .. "/bin/lua.bat")) + assert.truthy(lfs.attributes(myproject .. "/bin/luarocks.bat")) + else + assert.truthy(lfs.attributes(myproject .. "/bin/lua")) + assert.truthy(lfs.attributes(myproject .. "/bin/luarocks")) + end + assert.truthy(lfs.attributes(myproject .. "/lua_modules")) + assert.truthy(lfs.attributes(myproject .. "/.luarocks")) + assert.truthy(lfs.attributes(myproject .. "/.luarocks/config-" .. test_env.lua_version .. ".lua")) + assert.truthy(lfs.attributes(myproject .. "/.gitignore")) + assert.truthy(lfs.attributes(myproject .. "/myproject-dev-1.rockspec")) + end, finally) + end) + + it("lua wrapper works", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init")) + if is_win then + assert.truthy(lfs.attributes(myproject .. "/lua.bat")) + assert.truthy(lfs.attributes(myproject .. "/luarocks.bat")) + local pd = assert(io.popen([[echo print(_VERSION) | lua.bat]], "r")) + local output = pd:read("*a") + pd:close() + assert.match("5", output, 1, true) + local fd = io.open("hello.lua", "w") + fd:write("print('hello' .. _VERSION)") + fd:close() + pd = assert(io.popen([[lua.bat hello.lua]], "r")) + output = pd:read("*a") + pd:close() + assert.match("hello", output, 1, true) + else + assert.truthy(lfs.attributes(myproject .. "/lua")) + assert.truthy(lfs.attributes(myproject .. "/luarocks")) + local pd = assert(io.popen([[echo "print('hello ' .. _VERSION)" | ./lua]], "r")) + local output = pd:read("*a") + pd:close() + assert.match("hello", output, 1, true) + local fd = io.open("hello.lua", "w") + fd:write("print('hello' .. _VERSION)") + fd:close() + pd = assert(io.popen([[./lua ./hello.lua]], "r")) + output = pd:read("*a") + pd:close() + assert.match("hello", output, 1, true) + end + end, finally) + end) + + it("with given arguments", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init customname 1.0")) + assert.truthy(lfs.attributes(myproject .. "/customname-1.0-1.rockspec")) + end, finally) + end) + + it("with --lua-versions", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init --lua-versions=5.1,5.2,5.3,5.4")) + local rockspec_name = myproject .. "/myproject-dev-1.rockspec" + assert.truthy(lfs.attributes(rockspec_name)) + local fd = assert(io.open(rockspec_name, "rb")) + local data = fd:read("*a") + fd:close() + assert.truthy(data:find("lua >= 5.1, < 5.5", 1, true)) + end, finally) + end) + + it("in a git repo", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + copy_dir(testing_paths.fixtures_dir .. "/git_repo", myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init")) + local fd = assert(io.open(myproject .. "/myproject-dev-1.rockspec", "r")) + local content = assert(fd:read("*a")) + assert.truthy(content:find("summary = \"Test repo\"")) + assert.truthy(content:find("detailed = .+Test repo.+")) + assert.truthy(content:find("license = \"MIT\"")) + + fd = assert(io.open(myproject .. "/.gitignore", "r")) + content = assert(fd:read("*a")) + assert.truthy(content:find("/foo")) + assert.truthy(content:find("/lua")) + assert.truthy(content:find("/lua_modules")) + end, finally) + end) + + it("does not autodetect config or dependencies as modules of the package", function() + test_env.run_in_tmp(function(tmpdir) + local myproject = tmpdir .. "/myproject" + lfs.mkdir(myproject) + lfs.chdir(myproject) + + assert(run.luarocks("init")) + assert.truthy(lfs.attributes(myproject .. "/.luarocks/config-" .. test_env.lua_version .. ".lua")) + local rockspec_filename = myproject .. "/myproject-dev-1.rockspec" + assert.truthy(lfs.attributes(rockspec_filename)) + + -- install a package locally + write_file("my_dependency-1.0-1.rockspec", [[ + package = "my_dependency" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/my_dependency.lua" + } + build = { + type = "builtin", + modules = { + my_dependency = "my_dependency.lua" + } + } + ]], finally) + write_file(tmpdir .. "/my_dependency.lua", "return {}", finally) + + assert.truthy(run.luarocks("build my_dependency-1.0-1.rockspec")) + assert.truthy(lfs.attributes(myproject .. "/lua_modules/share/lua/" .. test_env.lua_version .."/my_dependency.lua")) + + os.remove(rockspec_filename) + os.remove("my_dependency-1.0-1.rockspec") + + -- re-run init + assert(run.luarocks("init")) + + -- file is recreated + assert.truthy(lfs.attributes(rockspec_filename)) + + local fd = assert(io.open(rockspec_filename, "rb")) + local rockspec = assert(fd:read("*a")) + fd:close() + + assert.no.match("my_dependency", rockspec, 1, true) + assert.no.match("config", rockspec, 1, true) + + end, finally) + end) +end) diff --git a/spec/install_spec.lua b/spec/install_spec.lua new file mode 100644 index 0000000..e6b1ad0 --- /dev/null +++ b/spec/install_spec.lua @@ -0,0 +1,235 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run +local testing_paths = test_env.testing_paths +local env_variables = test_env.env_variables +local write_file = test_env.write_file +local git_repo = require("spec.util.git_repo") +local V = test_env.V + +local extra_rocks = { + "/cprint-${CPRINT}.src.rock", + "/lpeg-${LPEG}.src.rock", + "/luassert-1.7.0-1.src.rock", + "/luasocket-${LUASOCKET}.src.rock", + "/lxsh-${LXSH}.src.rock", + "/luafilesystem-${LUAFILESYSTEM}.src.rock", + "/luafilesystem-${LUAFILESYSTEM_OLD}.src.rock", + "spec/fixtures/a_repo/has_build_dep-1.0-1.all.rock", + "spec/fixtures/a_repo/a_build_dep-1.0-1.all.rock", + "spec/fixtures/a_repo/a_rock-1.0-1.src.rock", +} + +describe("luarocks install #integration", function() + + before_each(function() + test_env.setup_specs(extra_rocks) + end) + + describe("basic tests", function() + pending("fails with local flag as root #unix", function() + if test_env.TYPE_TEST_ENV ~= "full" then + assert.is_false(run.luarocks_bool("install --local luasocket ", { USER = "root" } )) + end + end) + + pending("fails with no downloader", function() + if test_env.TYPE_TEST_ENV ~= "full" then + local output = assert(run.luarocks("install https://example.com/rock-1.0.src.rock", { LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/testing_config_no_downloader.lua" } )) + assert.match("no downloader tool", output) + + -- can do http but not https + assert(run.luarocks("install luasocket")) + output = assert(run.luarocks("install https://example.com/rock-1.0.src.rock", { LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/testing_config_no_downloader.lua" } )) + assert.match("no downloader tool", output) + end + end) + + it("only-deps of lxsh show there is no lxsh", function() + assert.is_true(run.luarocks_bool("install lxsh ${LXSH} --only-deps")) + assert.is_false(run.luarocks_bool("show lxsh")) + end) + + it("installs a package with a dependency", function() + assert.is_true(run.luarocks_bool("install has_build_dep")) + assert.is_true(run.luarocks_bool("show a_rock")) + end) + end) + + describe("#namespaces", function() + it("installs a namespaced package from the command-line", function() + assert(run.luarocks_bool("install a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert.is_false(run.luarocks_bool("show a_rock 1.0")) + assert(run.luarocks_bool("show a_rock 2.0")) + assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace")) + end) + + it("installs a namespaced package given an URL and any string in --namespace", function() + -- This is not a "valid" namespace (as per luarocks.org rules) + -- but we're not doing any format checking in the luarocks codebase + -- so this keeps our options open. + assert(run.luarocks_bool("install --namespace=x.y@z file://" .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.src.rock" )) + assert.truthy(run.luarocks_bool("show a_rock 1.0")) + local fd = assert(io.open(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/rock_namespace", "r")) + finally(function() fd:close() end) + assert.same("x.y@z", fd:read("*l")) + end) + + it("installs a package with a namespaced dependency", function() + assert(run.luarocks_bool("install has_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(run.luarocks_bool("show has_namespaced_dep")) + assert.is_false(run.luarocks_bool("show a_rock 1.0")) + assert(run.luarocks_bool("show a_rock 2.0")) + assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace")) + end) + + it("installs a package reusing a namespaced dependency", function() + assert(run.luarocks_bool("install a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(run.luarocks_bool("show a_rock 2.0")) + assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace")) + local output = run.luarocks("install has_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" ) + assert.has.no.match("Missing dependencies", output) + end) + + it("installs a package considering namespace of locally installed package", function() + assert(run.luarocks_bool("install a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(run.luarocks_bool("show a_rock 2.0")) + assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace")) + local output = run.luarocks("install has_another_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" ) + assert.has.match("Missing dependencies", output) + print(output) + assert(run.luarocks_bool("show a_rock 3.0")) + end) + end) + + describe("more complex tests", function() + it('skipping dependency checks', function() + assert.is_true(run.luarocks_bool("install has_build_dep --nodeps")) + assert.is_true(run.luarocks_bool("show has_build_dep")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/has_build_dep")) + end) + + it('handle relative path in --tree #632', function() + local relative_path = "./temp_dir_"..math.random(100000) + if test_env.TEST_TARGET_OS == "windows" then + relative_path = relative_path:gsub("/", "\\") + end + test_env.remove_dir(relative_path) + assert.is.falsy(lfs.attributes(relative_path)) + assert.is_true(run.luarocks_bool("install luafilesystem --tree="..relative_path)) + assert.is.truthy(lfs.attributes(relative_path)) + test_env.remove_dir(relative_path) + assert.is.falsy(lfs.attributes(relative_path)) + end) + + it("only-deps of luasocket packed rock", function() + assert.is_true(run.luarocks_bool("build --pack-binary-rock luasocket ${LUASOCKET}")) + local output = run.luarocks("install --only-deps " .. "luasocket-${LUASOCKET}." .. test_env.platform .. ".rock") + assert.match(V"Successfully installed dependencies for luasocket ${LUASOCKET}", output, 1, true) + assert.is_true(os.remove("luasocket-${LUASOCKET}." .. test_env.platform .. ".rock")) + end) + + it("reinstall", function() + assert.is_true(run.luarocks_bool("build --pack-binary-rock luasocket ${LUASOCKET}")) + assert.is_true(run.luarocks_bool("install " .. "luasocket-${LUASOCKET}." .. test_env.platform .. ".rock")) + assert.is_true(run.luarocks_bool("install --deps-mode=none " .. "luasocket-${LUASOCKET}." .. test_env.platform .. ".rock")) + assert.is_true(os.remove("luasocket-${LUASOCKET}." .. test_env.platform .. ".rock")) + end) + + it("binary rock of cprint", function() + assert.is_true(run.luarocks_bool("build --pack-binary-rock cprint")) + assert.is_true(run.luarocks_bool("install cprint-${CPRINT}." .. test_env.platform .. ".rock")) + assert.is_true(os.remove("cprint-${CPRINT}." .. test_env.platform .. ".rock")) + end) + + it("accepts --no-manifest flag", function() + assert.is_true(run.luarocks_bool("install lxsh ${LXSH}")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/manifest")) + assert.is.truthy(os.remove(testing_paths.testing_sys_rocks .. "/manifest")) + + assert.is_true(run.luarocks_bool("install --no-manifest lxsh ${LXSH}")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/manifest")) + end) + end) + + describe("#build_dependencies", function() + it("install does not install a build dependency", function() + assert(run.luarocks_bool("install has_build_dep")) + assert(run.luarocks_bool("show has_build_dep 1.0")) + assert.falsy(run.luarocks_bool("show a_build_dep 1.0")) + end) + end) + + it("respects luarocks.lock in package #pinning", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock >= 0.8" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]]) + write_file("test.lua", "return {}") + write_file("luarocks.lock", [[ + return { + dependencies = { + ["a_rock"] = "1.0-1", + } + } + ]]) + + assert.is_true(run.luarocks_bool("make --pack-binary-rock --server=" .. testing_paths.fixtures_dir .. "/a_repo test-1.0-1.rockspec")) + assert.is_true(os.remove("luarocks.lock")) + + assert.is.truthy(lfs.attributes("./test-1.0-1.all.rock")) + + assert.is.falsy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) + assert.is.falsy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + + print(run.luarocks("install ./test-1.0-1.all.rock --tree=lua_modules --server=" .. testing_paths.fixtures_dir .. "/a_repo")) + + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/luarocks.lock")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + assert.is.falsy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/2.0-1")) + end, finally) + end) + + describe("#unix install runs build from #git", function() + local git + + lazy_setup(function() + git = git_repo.start() + end) + + lazy_teardown(function() + if git then + git:stop() + end + end) + + it("using --branch", function() + write_file("my_branch-1.0-1.rockspec", [[ + rockspec_format = "3.0" + package = "my_branch" + version = "1.0-1" + source = { + url = "git://localhost/testrock" + } + ]], finally) + assert.is_false(run.luarocks_bool("install --branch unknown-branch ./my_branch-1.0-1.rockspec")) + assert.is_true(run.luarocks_bool("install --branch test-branch ./my_branch-1.0-1.rockspec")) + end) + end) + +end) diff --git a/spec/lint_spec.lua b/spec/lint_spec.lua new file mode 100644 index 0000000..919e4e7 --- /dev/null +++ b/spec/lint_spec.lua @@ -0,0 +1,109 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run +local get_tmp_path = test_env.get_tmp_path +local write_file = test_env.write_file +local lfs = require("lfs") + +local extra_rocks = { + "/say-1.3-1.rockspec" +} + +describe("luarocks lint #integration", function() + + before_each(function() + test_env.setup_specs(extra_rocks) + end) + + it("with no flags/arguments", function() + assert.is_false(run.luarocks_bool("lint")) + end) + + it("invalid argument", function() + assert.is_false(run.luarocks_bool("lint invalid")) + end) + + it("OK", function() + assert.is_true(run.luarocks_bool("download --rockspec say 1.3-1")) + local output = run.luarocks("lint say-1.3-1.rockspec") + assert.are.same(output, "") + assert.is_true(os.remove("say-1.3-1.rockspec")) + end) + + describe("mismatch set", function() + local tmpdir + local olddir + + before_each(function() + tmpdir = get_tmp_path() + olddir = lfs.currentdir() + lfs.mkdir(tmpdir) + lfs.chdir(tmpdir) + end) + + after_each(function() + if olddir then + lfs.chdir(olddir) + if tmpdir then + lfs.rmdir(tmpdir) + end + end + end) + + it("mismatch string", function() + write_file("type_mismatch_string-1.0-1.rockspec", [[ + package="type_mismatch_version" + version=1.0 + ]], finally) + assert.is_false(run.luarocks_bool("lint type_mismatch_string-1.0-1.rockspec")) + end) + + it("mismatch version", function() + write_file("type_mismatch_version-1.0-1.rockspec", [[ + package="type_mismatch_version" + version="1.0" + ]], finally) + assert.is_false(run.luarocks_bool("lint type_mismatch_version-1.0-1.rockspec")) + end) + + it("mismatch table", function() + write_file("type_mismatch_table-1.0-1.rockspec", [[ + package="type_mismatch_table" + version="1.0-1" + + source = "not a table" + ]], finally) + assert.is_false(run.luarocks_bool("lint type_mismatch_table-1.0-1.rockspec")) + end) + + it("mismatch no build table", function() + write_file("no_build_table-1.0-1.rockspec", [[ + package = "no_build_table" + version = "0.1-1" + source = { + url = "http://example.com/foo/tar.gz" + } + description = { + summary = "A rockspec with no build field", + } + dependencies = { + "lua >= 5.1" + } + ]], finally) + assert.is_false(run.luarocks_bool("lint no_build_table-1.0-1.rockspec")) + end) + + it("no description field", function() + write_file("nodesc-1.0-1.rockspec", [[ + package = "nodesc" + version = "0.1-1" + source = { + url = "http://example.com/foo/tar.gz" + } + dependencies = { + "lua >= 5.1" + } + ]], finally) + assert.is_false(run.luarocks_bool("lint nodesc-1.0-1.rockspec")) + end) + end) +end) diff --git a/spec/list_spec.lua b/spec/list_spec.lua new file mode 100644 index 0000000..08d8587 --- /dev/null +++ b/spec/list_spec.lua @@ -0,0 +1,34 @@ +local test_env = require("spec.util.test_env") +local V = test_env.V +local run = test_env.run +local testing_paths = test_env.testing_paths + +local extra_rocks = { + "/say-1.0-1.src.rock", + "/say-1.2-1.src.rock" +} + +describe("luarocks list #integration", function() + + before_each(function() + test_env.setup_specs(extra_rocks) + end) + + it("with no flags/arguments", function() + local output = run.luarocks("list") + assert.match("luacov", output) + end) + + it("shows version number", function() + local output = run.luarocks("list") + assert.is.truthy(output:find("luacov")) + assert.matches(V"${LUACOV}", output, 1, true) + end) + + it("LuaRocks install outdated and list it", function() + assert.is_true(run.luarocks_bool("install say 1.0-1")) + local output = run.luarocks("list --outdated") + assert.is.truthy(output:find("say")) + assert.matches("1.0-1 < ", output, 1, true) + end) +end) diff --git a/spec/loader_spec.lua b/spec/loader_spec.lua new file mode 100644 index 0000000..bd95a29 --- /dev/null +++ b/spec/loader_spec.lua @@ -0,0 +1,73 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run +local testing_paths = test_env.testing_paths +local write_file = test_env.write_file + +describe("luarocks.loader", function() + + before_each(function() + test_env.setup_specs() + end) + + describe("#integration", function() + it("respects version constraints", function() + test_env.run_in_tmp(function(tmpdir) + write_file("rock_b_01.lua", "print('ROCK B 0.1'); return {}") + write_file("rock_b-0.1-1.rockspec", [[ + package = "rock_b" + version = "0.1-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/rock_b_01.lua" + } + build = { + type = "builtin", + modules = { + rock_b = "rock_b_01.lua" + } + } + ]]) + + write_file("rock_b_10.lua", "print('ROCK B 1.0'); return {}") + write_file("rock_b-1.0-1.rockspec", [[ + package = "rock_b" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/rock_b_10.lua" + } + build = { + type = "builtin", + modules = { + rock_b = "rock_b_10.lua" + } + } + ]]) + + write_file("rock_a.lua", "require('rock_b'); return {}") + write_file("rock_a-2.0-1.rockspec", [[ + package = "rock_a" + version = "2.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/rock_a.lua" + } + dependencies = { + "rock_b < 1.0", + } + build = { + type = "builtin", + modules = { + rock_a = "rock_a.lua" + } + } + ]]) + + print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=" .. testing_paths.testing_tree .. " ./rock_b-0.1-1.rockspec")) + print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=" .. testing_paths.testing_tree .. " ./rock_b-1.0-1.rockspec --keep")) + print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=" .. testing_paths.testing_tree .. " ./rock_a-2.0-1.rockspec")) + + local output = run.lua([[-e "require 'luarocks.loader'; require('rock_a')"]]) + + assert.matches("ROCK B 0.1", output, 1, true) + end, finally) + end) + end) +end) diff --git a/spec/make_spec.lua b/spec/make_spec.lua new file mode 100644 index 0000000..b057263 --- /dev/null +++ b/spec/make_spec.lua @@ -0,0 +1,387 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run +local testing_paths = test_env.testing_paths +local env_variables = test_env.env_variables +local write_file = test_env.write_file + +local extra_rocks = { + "/luasocket-${LUASOCKET}.src.rock", + "/luasocket-${LUASOCKET}.rockspec", + "/lpeg-${LPEG}.src.rock", + "/lxsh-${LXSH}.src.rock", + "/lxsh-${LXSH}.rockspec" +} + +describe("luarocks make #integration", function() + + before_each(function() + test_env.setup_specs(extra_rocks) + end) + + it("with no flags/arguments", function() + finally(function() + lfs.chdir(testing_paths.testrun_dir) + test_env.remove_dir("empty") + end) + assert(lfs.mkdir("empty")) + assert(lfs.chdir("empty")) + assert.is_false(run.luarocks_bool("make")) + end) + + it("with rockspec", function() + finally(function() + -- delete downloaded and unpacked files + lfs.chdir(testing_paths.testrun_dir) + test_env.remove_dir("luasocket-${LUASOCKET}") + os.remove("luasocket-${LUASOCKET}.src.rock") + end) + + -- make luasocket + assert.is_true(run.luarocks_bool("download --source luasocket ${LUASOCKET}")) + assert.is_true(run.luarocks_bool("unpack luasocket-${LUASOCKET}.src.rock")) + lfs.chdir("luasocket-${LUASOCKET}/luasocket/") + assert.is_true(run.luarocks_bool("make luasocket-${LUASOCKET}.rockspec")) + + -- test it + assert.is_true(run.luarocks_bool("show luasocket")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/luasocket/${LUASOCKET}/luasocket-${LUASOCKET}.rockspec")) + end) + + it("--no-doc", function() + finally(function() + lfs.chdir(testing_paths.testrun_dir) + test_env.remove_dir("luasocket-${LUASOCKET}") + os.remove("luasocket-${LUASOCKET}.src.rock") + end) + + assert.is_true(run.luarocks_bool("download --source luasocket ${LUASOCKET}")) + assert.is_true(run.luarocks_bool("unpack luasocket-${LUASOCKET}.src.rock")) + lfs.chdir("luasocket-${LUASOCKET}/luasocket") + assert.is_true(run.luarocks_bool("make --no-doc luasocket-${LUASOCKET}.rockspec")) + + assert.is_true(run.luarocks_bool("show luasocket")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/luasocket/${LUASOCKET}/doc")) + end) + + it("--only-deps", function() + local rockspec = "build_only_deps-0.1-1.rockspec" + local src_rock = testing_paths.fixtures_dir .. "/build_only_deps-0.1-1.src.rock" + + test_env.remove_dir("build_only_deps-0.1-1/") + assert.is_true(run.luarocks_bool("unpack " .. src_rock)) + lfs.chdir("build_only_deps-0.1-1/") + assert.is_true(run.luarocks_bool("make " .. rockspec .. " --only-deps")) + assert.is_false(run.luarocks_bool("show build_only_deps")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/build_only_deps/0.1-1/build_only_deps-0.1-1.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + end) + + describe("LuaRocks making rockspecs (using lxsh)", function() + --download lxsh and unpack it + before_each(function() + assert.is_true(run.luarocks_bool("download --source lxsh ${LXSH}")) + assert.is_true(run.luarocks_bool("unpack lxsh-${LXSH}.src.rock")) + assert.is_true(lfs.chdir("lxsh-${LXSH}/lxsh-${LXSH_V}-1/")) + end) + + -- delete downloaded and unpacked files + after_each(function() + assert(lfs.chdir(testing_paths.testrun_dir)) + test_env.remove_dir("lxsh-${LXSH}") + assert.is_true(os.remove("lxsh-${LXSH}.src.rock")) + end) + + it("default rockspec", function() + assert.is_true(run.luarocks_bool("new_version lxsh-${LXSH}.rockspec")) + assert.is_true(run.luarocks_bool("make")) + + assert.is_true(run.luarocks_bool("show lxsh")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH_V}-3/lxsh-${LXSH_V}-3.rockspec")) + end) + + it("unnamed rockspec", function() + finally(function() + os.remove("rockspec") + end) + + test_env.copy("lxsh-${LXSH}.rockspec", "rockspec") + assert.is_true(run.luarocks_bool("make")) + + assert.is_true(run.luarocks_bool("show lxsh")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) + + it("ambiguous rockspec", function() + assert.is.truthy(os.rename("lxsh-${LXSH}.rockspec", "lxsh2-${LXSH}.rockspec")) + local output = run.luarocks("make") + assert.is.truthy(output:match("Error: Inconsistency between rockspec filename")) + + assert.is_false(run.luarocks_bool("show lxsh")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) + + it("ambiguous unnamed rockspec", function() + assert.is.truthy(os.rename("lxsh-${LXSH}.rockspec", "1_rockspec")) + test_env.copy("1_rockspec", "2_rockspec") + local output = run.luarocks("make") + assert.is.truthy(output:match("Error: Please specify which rockspec file to use")) + + assert.is_false(run.luarocks_bool("show lxsh")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lxsh/${LXSH}/lxsh-${LXSH}.rockspec")) + end) + + it("pack binary rock", function() + assert.is_true(run.luarocks_bool("make --deps-mode=none --pack-binary-rock")) + assert.is.truthy(lfs.attributes("lxsh-${LXSH}.all.rock")) + end) + end) + + it("supports --pin #pinning", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock 1.0" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]]) + write_file("test.lua", "return {}") + + assert.is_true(run.luarocks_bool("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --pin --tree=lua_modules")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + local lockfilename = "./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/luarocks.lock" + assert.is.truthy(lfs.attributes(lockfilename)) + local lockdata = loadfile(lockfilename)() + assert.same({ + dependencies = { + ["a_rock"] = "1.0-1", + ["lua"] = test_env.lua_version .. "-1", + } + }, lockdata) + end, finally) + end) + + it("respects luarocks.lock when present #pinning", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-2.0-1.rockspec", [[ + package = "test" + version = "2.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock >= 0.8" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]]) + write_file("test.lua", "return {}") + write_file("luarocks.lock", [[ + return { + dependencies = { + ["a_rock"] = "1.0-1", + } + } + ]]) + + print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=lua_modules")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/2.0-1/test-2.0-1.rockspec")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) + local lockfilename = "./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/2.0-1/luarocks.lock" + assert.is.truthy(lfs.attributes(lockfilename)) + local lockdata = loadfile(lockfilename)() + assert.same({ + dependencies = { + ["a_rock"] = "1.0-1", + } + }, lockdata) + end, finally) + end) + + describe("#ddt upgrading rockspecs with double deploy types", function() + local deploy_lib_dir = testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION + local deploy_lua_dir = testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION + local so = test_env.lib_extension + + before_each(function() + test_env.copy_dir(testing_paths.fixtures_dir .. "/double_deploy_type", "ddt") + end) + + after_each(function() + test_env.remove_dir("ddt") + os.remove("ddt."..test_env.lib_extension) + end) + + it("when upgrading", function() + assert.is_true(run.luarocks_bool("make ddt/double_deploy_type-0.1.0-1.rockspec")) + assert.is.truthy(lfs.attributes(deploy_lib_dir.."/ddt."..so)) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt.lua")) + assert.same("ddt1", loadfile(deploy_lua_dir.."/ddt.lua")()) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt_file")) + assert.is.falsy(lfs.attributes(deploy_lib_dir.."/ddt."..so.."~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt.lua~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt_file~")) + + assert.is_true(run.luarocks_bool("make ddt/double_deploy_type-0.2.0-1.rockspec")) + assert.is.truthy(lfs.attributes(deploy_lib_dir.."/ddt."..so)) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt.lua")) + assert.same("ddt2", loadfile(deploy_lua_dir.."/ddt.lua")()) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt_file")) + assert.is.falsy(lfs.attributes(deploy_lib_dir.."/ddt."..so.."~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt.lua~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt_file~")) + end) + + it("modules with same name from lua/ and lib/ when upgrading with --keep", function() + assert.is_true(run.luarocks_bool("make ddt/double_deploy_type-0.1.0-1.rockspec")) + assert.is.truthy(lfs.attributes(deploy_lib_dir.."/ddt."..so)) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt.lua")) + assert.same("ddt1", loadfile(deploy_lua_dir.."/ddt.lua")()) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt_file")) + assert.is.falsy(lfs.attributes(deploy_lib_dir.."/ddt."..so.."~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt.lua~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt_file~")) + + assert.is_true(run.luarocks_bool("make ddt/double_deploy_type-0.2.0-1.rockspec --keep")) + assert.is.truthy(lfs.attributes(deploy_lib_dir.."/ddt."..so)) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt.lua")) + assert.same("ddt2", loadfile(deploy_lua_dir.."/ddt.lua")()) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt_file")) + assert.is.falsy(lfs.attributes(deploy_lib_dir.."/ddt."..so.."~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt.lua~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt_file~")) + assert.is.truthy(lfs.attributes(deploy_lib_dir.."/double_deploy_type_0_1_0_1-ddt."..so)) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/double_deploy_type_0_1_0_1-ddt.lua")) + assert.same("ddt1", loadfile(deploy_lua_dir.."/double_deploy_type_0_1_0_1-ddt.lua")()) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/double_deploy_type_0_1_0_1-ddt_file")) + end) + + it("modules with same name from lua/ and lib/ when downgrading", function() + assert.is_true(run.luarocks_bool("make ddt/double_deploy_type-0.2.0-1.rockspec")) + assert.is.truthy(lfs.attributes(deploy_lib_dir.."/ddt."..so)) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt.lua")) + assert.same("ddt2", loadfile(deploy_lua_dir.."/ddt.lua")()) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt_file")) + assert.is.falsy(lfs.attributes(deploy_lib_dir.."/ddt."..so.."~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt.lua~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt_file~")) + + assert.is_true(run.luarocks_bool("make ddt/double_deploy_type-0.1.0-1.rockspec")) + assert.is.truthy(lfs.attributes(deploy_lib_dir.."/ddt."..so)) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt.lua")) + assert.same("ddt1", loadfile(deploy_lua_dir.."/ddt.lua")()) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt_file")) + assert.is.falsy(lfs.attributes(deploy_lib_dir.."/ddt."..so.."~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt.lua~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt_file~")) + end) + + it("modules with same name from lua/ and lib/ when downgrading with --keep", function() + assert.is_true(run.luarocks_bool("make ddt/double_deploy_type-0.2.0-1.rockspec")) + assert.is.truthy(lfs.attributes(deploy_lib_dir.."/ddt."..so)) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt.lua")) + assert.same("ddt2", loadfile(deploy_lua_dir.."/ddt.lua")()) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt_file")) + assert.is.falsy(lfs.attributes(deploy_lib_dir.."/ddt."..so.."~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt.lua~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt_file~")) + + assert.is_true(run.luarocks_bool("make ddt/double_deploy_type-0.1.0-1.rockspec --keep")) + assert.is.truthy(lfs.attributes(deploy_lib_dir.."/ddt."..so)) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt.lua")) + assert.same("ddt2", loadfile(deploy_lua_dir.."/ddt.lua")()) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/ddt_file")) + assert.is.falsy(lfs.attributes(deploy_lib_dir.."/ddt."..so.."~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt.lua~")) + assert.is.falsy(lfs.attributes(deploy_lua_dir.."/ddt_file~")) + assert.is.truthy(lfs.attributes(deploy_lib_dir.."/double_deploy_type_0_1_0_1-ddt."..so)) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/double_deploy_type_0_1_0_1-ddt.lua")) + assert.same("ddt1", loadfile(deploy_lua_dir.."/double_deploy_type_0_1_0_1-ddt.lua")()) + assert.is.truthy(lfs.attributes(deploy_lua_dir.."/double_deploy_type_0_1_0_1-ddt_file")) + end) + end) + + describe("upgrading rockspecs with mixed deploy types", function() + before_each(function() + test_env.copy_dir(testing_paths.fixtures_dir .. "/mixed_deploy_type", "mdt") + end) + + after_each(function() + test_env.remove_dir("mdt") + os.remove("mdt."..test_env.lib_extension) + end) + + it("modules with same name from lua/ and lib/ when upgrading", function() + assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.1.0-1.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + + assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.2.0-1.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt.lua")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt_file")) + end) + + it("modules with same name from lua/ and lib/ when upgrading with --keep", function() + assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.1.0-1.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + + assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.2.0-1.rockspec --keep")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt.lua")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt_file")) + end) + + it("modules with same name from lua/ and lib/ when downgrading", function() + assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.2.0-1.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + + assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.1.0-1.rockspec")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt."..test_env.lib_extension)) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt_file")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt.lua")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt_file")) + end) + + it("modules with same name from lua/ and lib/ when downgrading with --keep", function() + assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.2.0-1.rockspec")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + + assert.is_true(run.luarocks_bool("make mdt/mixed_deploy_type-0.1.0-1.rockspec --keep")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt."..test_env.lib_extension)) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt.lua")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mdt_file")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt.lua")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION.."/mixed_deploy_type_0_1_0_1-mdt_file")) + end) + end) +end) diff --git a/spec/pack_spec.lua b/spec/pack_spec.lua new file mode 100644 index 0000000..2a2fb3a --- /dev/null +++ b/spec/pack_spec.lua @@ -0,0 +1,102 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run +local testing_paths = test_env.testing_paths +local write_file = test_env.write_file + +describe("luarocks pack #integration", function() + + lazy_setup(function() + test_env.setup_specs() + end) + + describe("#mock", function() + + lazy_setup(function() + test_env.setup_specs(extra_rocks, "mock") + test_env.mock_server_init() + end) + + lazy_teardown(function() + test_env.mock_server_done() + end) + + it("can pack a rockspec into a .src.rock", function() + finally(function() + os.remove("a_rock-1.0-1.src.rock") + end) + assert(run.luarocks_bool("download --rockspec --server=" .. testing_paths.fixtures_dir .. "/a_repo a_rock 1.0-1")) + assert(run.luarocks_bool("pack a_rock-1.0-1.rockspec")) + assert.is_truthy(lfs.attributes("a_rock-1.0-1.src.rock")) + end) + + it("can pack a rockspec with a bare file:// in the url", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock 1.0" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + write_file("test.lua", "return {}", finally) + + assert.is.truthy(run.luarocks_bool("pack test-1.0-1.rockspec")) + assert.is.truthy(lfs.attributes("test-1.0-1.src.rock")) + + assert.is.truthy(run.luarocks_bool("unpack test-1.0-1.src.rock")) + assert.is.truthy(lfs.attributes("test-1.0-1/test.lua")) + end, finally) + end) + + it("can pack a rockspec with a bare file:// fails if doesn't exist", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test_doesnt_exist.lua" + } + dependencies = { + "a_rock 1.0" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + + assert.is.falsy(run.luarocks_bool("pack test-1.0-1.rockspec")) + assert.is.falsy(lfs.attributes("test-1.0-1.src.rock")) + end, finally) + end) + + + it("fails packing a rockspec into a .src.rock if dir doesn't exist", function() + local output = run.luarocks("pack " .. testing_paths.fixtures_dir .. "/bad_pack-0.1-1.rockspec") + assert.match("Directory invalid_dir not found", output) + assert.is_falsy(lfs.attributes("bad_pack-0.1-1.src.rock")) + end) + + describe("namespaced dependencies", function() + it("can pack rockspec with namespaced dependencies", function() + finally(function() + os.remove("has_namespaced_dep-1.0-1.src.rock") + end) + assert(run.luarocks_bool("pack " .. testing_paths.fixtures_dir .. "/a_repo/has_namespaced_dep-1.0-1.rockspec")) + assert.is_truthy(lfs.attributes("has_namespaced_dep-1.0-1.src.rock")) + end) + end) + end) +end) diff --git a/spec/path_spec.lua b/spec/path_spec.lua new file mode 100644 index 0000000..1ad6b3a --- /dev/null +++ b/spec/path_spec.lua @@ -0,0 +1,58 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run + +describe("luarocks path #integration", function() + before_each(function() + test_env.setup_specs() + end) + + it("runs", function() + local output = run.luarocks("path") + assert.match("LUA_PATH=", output) + assert.match("LUA_CPATH=", output) + end) + + if _VERSION:match("[23]") then + local v = _VERSION:gsub("Lua (%d+)%.(%d+)", "%1_%2") + + it("with LUA_PATH_"..v, function() + local output = run.luarocks("path", { + ["LUA_PATH_"..v] = package.path, + }) + assert.match("LUA_PATH_"..v.."=", output) + end) + + it("with LUA_CPATH_"..v, function() + local output = run.luarocks("path", { + ["LUA_CPATH_"..v] = package.cpath, + }) + assert.match("LUA_CPATH_"..v.."=", output) + end) + + it("with LUA_PATH_"..v.." and LUA_CPATH_"..v, function() + local output = run.luarocks("path", { + ["LUA_PATH_"..v] = package.path, + ["LUA_CPATH_"..v] = package.cpath, + }) + assert.match("LUA_PATH_"..v.."=", output) + assert.match("LUA_CPATH_"..v.."=", output) + end) + + end + + it("--bin", function() + assert.is_true(run.luarocks_bool("path --bin")) + end) + + it("--lr-path", function() + assert.is_true(run.luarocks_bool("path --lr-path")) + end) + + it("--lr-cpath", function() + assert.is_true(run.luarocks_bool("path --lr-cpath")) + end) + + it("--tree", function() + assert.is_true(run.luarocks_bool("path --tree=lua_modules")) + end) +end) diff --git a/spec/quick/admin_make_manifest.q b/spec/quick/admin_make_manifest.q new file mode 100644 index 0000000..527e86a --- /dev/null +++ b/spec/quick/admin_make_manifest.q @@ -0,0 +1,46 @@ +SUITE: luarocks-admin make_manifest + +================================================================================ +TEST: runs + +FILE: test-1.0-1.rockspec +-------------------------------------------------------------------------------- +package = "test" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/test.lua" +} +build = { + type = "builtin", + modules = { + test = "test.lua" + } +} +-------------------------------------------------------------------------------- + +FILE: test.lua +-------------------------------------------------------------------------------- +return {} +-------------------------------------------------------------------------------- + +RUN: luarocks make --pack-binary-rock ./test-1.0-1.rockspec + +RUN: luarocks-admin make_manifest . + +FILE_CONTENTS: ./manifest-%{lua_version} +-------------------------------------------------------------------------------- +commands = {} +modules = {} +repository = { + test = { + ["1.0-1"] = { + { + arch = "all" + }, + { + arch = "rockspec" + } + } + } +} +-------------------------------------------------------------------------------- diff --git a/spec/quick/build.q b/spec/quick/build.q new file mode 100644 index 0000000..d0d6a89 --- /dev/null +++ b/spec/quick/build.q @@ -0,0 +1,405 @@ +SUITE: luarocks build + +================================================================================ +TEST: fails when given invalid argument +RUN: luarocks build aoesuthaoeusahtoeustnaou --only-server=localhost +EXIT: 1 +STDERR: +-------------------------------------------------------------------------------- +Could not find a result named aoesuthaoeusahtoeustnaou +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: with no arguments behaves as luarocks make + +FILE: c_module-1.0-1.rockspec +-------------------------------------------------------------------------------- +package = "c_module" +version = "1.0-1" +source = { + url = "http://example.com/c_module" +} +build = { + type = "builtin", + modules = { + c_module = { "c_module.c" } + } +} +-------------------------------------------------------------------------------- +FILE: c_module.c +-------------------------------------------------------------------------------- +#include <lua.h> +#include <lauxlib.h> + +int luaopen_c_module(lua_State* L) { + lua_newtable(L); + lua_pushinteger(L, 1); + lua_setfield(L, -2, "c_module"); + return 1; +} +-------------------------------------------------------------------------------- +RUN: luarocks build +EXISTS: c_module.%{lib_extension} + + + +================================================================================ +TEST: defaults to builtin type + +FILE: a_rock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "a_rock" +version = "1.0-1" +source = { + url = "file://%{url(%{fixtures_dir})}/a_rock.lua" +} +description = { + summary = "An example rockspec", +} +dependencies = { + "lua >= 5.1" +} +build = { + modules = { + build = "a_rock.lua" + }, +} +-------------------------------------------------------------------------------- +RUN: luarocks build a_rock-1.0-1.rockspec +RUN: luarocks show a_rock +STDOUT: +-------------------------------------------------------------------------------- +a_rock 1.0 +-------------------------------------------------------------------------------- + + +================================================================================ +TEST: fails if no permissions to access the specified tree #unix + +RUN: luarocks build --tree=/usr ./a_rock-1.0-1.rockspec +EXIT: 2 +STDERR: +-------------------------------------------------------------------------------- +You may want to run as a privileged user, +or use --local to install into your local tree +or run 'luarocks config local_by_default true' to make --local the default. + +(You may need to configure your Lua package paths +to use the local tree, see 'luarocks path --help') +-------------------------------------------------------------------------------- + +We show the OS permission denied error, so we don't show the --force-lock +message. + +NOT_STDERR: +-------------------------------------------------------------------------------- +try --force-lock +-------------------------------------------------------------------------------- + +NOT_EXISTS: %{testing_sys_rocks}/a_rock/1.0-1/a_rock-1.0-1.rockspec + + + +================================================================================ +TEST: fails if tree is locked, --force-lock overrides #unix + +FILE: a_rock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "a_rock" +version = "1.0-1" +source = { + url = "file://%{url(%{fixtures_dir})}/a_rock.lua" +} +description = { + summary = "An example rockspec", +} +dependencies = { + "lua >= 5.1" +} +build = { + modules = { + build = "a_rock.lua" + }, +} +-------------------------------------------------------------------------------- + +FILE: %{testing_tree}/lockfile.lfs +-------------------------------------------------------------------------------- +dummy lock file for testing +-------------------------------------------------------------------------------- + +RUN: luarocks build --tree=%{testing_tree} ./a_rock-1.0-1.rockspec +EXIT: 4 +STDERR: +-------------------------------------------------------------------------------- +requires exclusive write access +try --force-lock +-------------------------------------------------------------------------------- + +RUN: luarocks build --tree=%{testing_tree} ./a_rock-1.0-1.rockspec --force-lock +EXIT: 0 + + + +================================================================================ +TEST: fails if no permissions to access the parent #unix + +RUN: luarocks build --tree=/usr/invalid ./a_rock-1.0-1.rockspec +EXIT: 2 +STDERR: +-------------------------------------------------------------------------------- +Error: /usr/invalid/lib/luarocks/rocks-%{lua_version} does not exist +and your user does not have write permissions in /usr + +You may want to run as a privileged user, +or use --local to install into your local tree +or run 'luarocks config local_by_default true' to make --local the default. + +(You may need to configure your Lua package paths +to use the local tree, see 'luarocks path --help') +-------------------------------------------------------------------------------- + +We show the OS permission denied error, so we don't show the --force-lock +message. + +NOT_STDERR: +-------------------------------------------------------------------------------- +try --force-lock +-------------------------------------------------------------------------------- + +NOT_EXISTS: %{testing_sys_rocks}/a_rock/1.0-1/a_rock-1.0-1.rockspec + + + +================================================================================ +TEST: luarocks build: do not rebuild when already installed + +FILE: a_rock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "a_rock" +version = "1.0-1" +source = { + url = "file://%{url(%{fixtures_dir})}/a_rock.lua" +} +description = { + summary = "An example rockspec", +} +dependencies = { + "lua >= 5.1" +} +build = { + modules = { + build = "a_rock.lua" + }, +} +-------------------------------------------------------------------------------- +RUN: luarocks build a_rock-1.0-1.rockspec + +RUN: luarocks show a_rock +STDOUT: +-------------------------------------------------------------------------------- +a_rock 1.0 +-------------------------------------------------------------------------------- + +RUN: luarocks build a_rock-1.0-1.rockspec +STDOUT: +-------------------------------------------------------------------------------- +a_rock 1.0-1 is already installed +Use --force to reinstall +-------------------------------------------------------------------------------- + + +RUN: luarocks build a_rock-1.0-1.rockspec --force +NOT_STDOUT: +-------------------------------------------------------------------------------- +a_rock 1.0-1 is already installed +Use --force to reinstall +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: supports --pin #pinning + +FILE: test-1.0-1.rockspec +-------------------------------------------------------------------------------- +package = "test" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/test.lua" +} +dependencies = { + "a_rock >= 0.8" +} +build = { + type = "builtin", + modules = { + test = "test.lua" + } +} +-------------------------------------------------------------------------------- + +FILE: test.lua +-------------------------------------------------------------------------------- +return {} +-------------------------------------------------------------------------------- + +RUN: luarocks build --only-server=%{fixtures_dir}/a_repo test-1.0-1.rockspec --pin --tree=lua_modules + +EXISTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/test/1.0-1/test-1.0-1.rockspec +EXISTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/a_rock/2.0-1/a_rock-2.0-1.rockspec + +EXISTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/test/1.0-1/luarocks.lock + +FILE_CONTENTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/test/1.0-1/luarocks.lock +-------------------------------------------------------------------------------- +return { + dependencies = { + a_rock = "2.0-1", + lua = "%{lua_version}-1" + } +} +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: supports --pin --only-deps #pinning + +FILE: test-1.0-1.rockspec +-------------------------------------------------------------------------------- +package = "test" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/test.lua" +} +dependencies = { + "a_rock >= 0.8" +} +build = { + type = "builtin", + modules = { + test = "test.lua" + } +} +-------------------------------------------------------------------------------- + +FILE: test.lua +-------------------------------------------------------------------------------- +return {} +-------------------------------------------------------------------------------- + +RUN: luarocks build --only-server=%{fixtures_dir}/a_repo test-1.0-1.rockspec --pin --only-deps --tree=lua_modules + +NOT_EXISTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/test/1.0-1/test-1.0-1.rockspec +EXISTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/a_rock/2.0-1/a_rock-2.0-1.rockspec + +EXISTS: ./luarocks.lock + +FILE_CONTENTS: ./luarocks.lock +-------------------------------------------------------------------------------- +return { + dependencies = { + a_rock = "2.0-1", + lua = "%{lua_version}-1" + } +} +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: installs bin entries correctly + +FILE: test-1.0-1.rockspec +-------------------------------------------------------------------------------- +package = "test" +version = "1.0-1" +source = { + url = "file://%{url(%{fixtures_dir})}/an_upstream_tarball-0.1.tar.gz", + dir = "an_upstream_tarball-0.1", +} +build = { + type = "builtin", + modules = { + my_module = "src/my_module.lua" + }, + install = { + bin = { + "src/my_module.lua" + } + } +} +-------------------------------------------------------------------------------- + +RUN: luarocks build test-1.0-1.rockspec --tree=lua_modules + +RM: %{fixtures_dir}/bin/something.lua + +EXISTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/test/1.0-1/test-1.0-1.rockspec + +FILE_CONTENTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/test/1.0-1/rock_manifest +-------------------------------------------------------------------------------- +rock_manifest = { + bin = { + ["my_module.lua"] = "25884dbf5be7114791018a48199d4c04" + }, + lua = { + ["my_module.lua"] = "25884dbf5be7114791018a48199d4c04" + }, + ["test-1.0-1.rockspec"] = +} +-------------------------------------------------------------------------------- + +EXISTS: ./lua_modules/bin/my_module.lua%{wrapper_extension} + + + +================================================================================ +TEST: downgrades directories correctly + +FILE: mytest-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "mytest" +version = "1.0-1" +source = { + url = "file://%{url(%{fixtures_dir})}/an_upstream_tarball-0.1.tar.gz", + dir = "an_upstream_tarball-0.1", +} +build = { + modules = { + ["parent.child.my_module"] = "src/my_module.lua" + }, +} +-------------------------------------------------------------------------------- + +FILE: mytest-2.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "mytest" +version = "2.0-1" +source = { + url = "file://%{url(%{fixtures_dir})}/an_upstream_tarball-0.1.tar.gz", + dir = "an_upstream_tarball-0.1", +} +build = { + modules = { + ["parent.child.my_module"] = "src/my_module.lua" + }, +} +-------------------------------------------------------------------------------- + +RUN: luarocks build ./mytest-2.0-1.rockspec +EXISTS: %{testing_sys_tree}/share/lua/%{lua_version}/parent/child/my_module.lua + +RUN: luarocks build ./mytest-1.0-1.rockspec +EXISTS: %{testing_sys_tree}/share/lua/%{lua_version}/parent/child/my_module.lua + +RUN: luarocks build ./mytest-2.0-1.rockspec +EXISTS: %{testing_sys_tree}/share/lua/%{lua_version}/parent/child/my_module.lua diff --git a/spec/quick/cmd.q b/spec/quick/cmd.q new file mode 100644 index 0000000..acde92b --- /dev/null +++ b/spec/quick/cmd.q @@ -0,0 +1,36 @@ +SUITE: luarocks CLI + +================================================================================ +TEST: warns but continues if given an invalid version + +RUN: luarocks --lua-version 1.0 + +STDOUT: +-------------------------------------------------------------------------------- +Version : 1.0 +LUA : (interpreter not found) +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: reports if lua.h header is not found + +RUN: luarocks LUA_INCDIR=/bad/dir + +STDOUT: +-------------------------------------------------------------------------------- +LUA_INCDIR : /bad/dir (lua.h not found) +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: reports if Lua library is not found + +RUN: luarocks LUA_LIBDIR=/bad/dir + +STDOUT: +-------------------------------------------------------------------------------- +LUA_LIBDIR : /bad/dir (Lua library itself not found) +-------------------------------------------------------------------------------- diff --git a/spec/quick/config.q b/spec/quick/config.q new file mode 100644 index 0000000..d623056 --- /dev/null +++ b/spec/quick/config.q @@ -0,0 +1,97 @@ +SUITE: luarocks config + +================================================================================ +TEST: --system-config shows the path of the system config + +FILE: %{testing_lrprefix}/etc/luarocks/config-%{LUA_VERSION}.lua +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +RUN: luarocks config --system-config + +STDOUT: +-------------------------------------------------------------------------------- +%{path(%{testing_lrprefix}/etc/luarocks/config-%{LUA_VERSION}.lua)} +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: reports when setting a bad LUA_LIBDIR + +RUN: luarocks config variables.LUA_LIBDIR /some/bad/path + +LuaRocks writes configuration values as they are given, without auto-conversion +of slashes for Windows: + +STDOUT: +-------------------------------------------------------------------------------- +Wrote +variables.LUA_LIBDIR = "/some/bad/path" +-------------------------------------------------------------------------------- + +STDERR: +-------------------------------------------------------------------------------- +Warning: Failed finding the Lua library. +Tried: + +LuaRocks may not work correctly when building C modules using this configuration. +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: reports when setting a bad LUA_INCDIR + +RUN: luarocks config variables.LUA_INCDIR /some/bad/path + +STDOUT: +-------------------------------------------------------------------------------- +Wrote +variables.LUA_INCDIR = "/some/bad/path" +-------------------------------------------------------------------------------- + +LuaRocks uses configuration values as they are given, without auto-conversion +of slashes for Windows: + +STDERR: +-------------------------------------------------------------------------------- +Warning: Failed finding Lua header lua.h (searched at /some/bad/path). You may need to install Lua development headers. + +LuaRocks may not work correctly when building C modules using this configuration. +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: rejects setting bad lua_dir + +RUN: luarocks config lua_dir /some/bad/dir +EXIT: 1 + +STDERR: +-------------------------------------------------------------------------------- +Lua interpreter not found +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: reports when setting a bad LUA_INCDIR + +RUN: luarocks config variables.LUA_INCDIR /some/bad/path + +STDOUT: +-------------------------------------------------------------------------------- +Wrote +variables.LUA_INCDIR = "/some/bad/path" +-------------------------------------------------------------------------------- + +LuaRocks uses configuration values as they are given, without auto-conversion +of slashes for Windows: + +STDERR: +-------------------------------------------------------------------------------- +Warning: Failed finding Lua header lua.h (searched at /some/bad/path). You may need to install Lua development headers. + +LuaRocks may not work correctly when building C modules using this configuration. +-------------------------------------------------------------------------------- diff --git a/spec/quick/doc.q b/spec/quick/doc.q new file mode 100644 index 0000000..4c71f83 --- /dev/null +++ b/spec/quick/doc.q @@ -0,0 +1,13 @@ +SUITE: luarocks doc + +================================================================================ +TEST: --local + +RUN: luarocks install --local --only-server=%{fixtures_dir}/a_repo a_rock + +RUN: luarocks doc a_rock --local + +STDOUT: +-------------------------------------------------------------------------------- +opening http://www.example.com +-------------------------------------------------------------------------------- diff --git a/spec/quick/install.q b/spec/quick/install.q new file mode 100644 index 0000000..e2df428 --- /dev/null +++ b/spec/quick/install.q @@ -0,0 +1,688 @@ +SUITE: luarocks install + +=============================================================================== +TEST: fails with no flags or arguments +RUN: luarocks install +EXIT: 1 + + + +=============================================================================== +TEST: fails with an unknown rock +RUN: luarocks install aoeuaoeuaoeiaoeuaoeua +EXIT: 1 + + + +=============================================================================== +TEST: fails with an invalid .rock argument +RUN: luarocks install "invalid.rock" +EXIT: 1 + + + +=============================================================================== +TEST: fails with incompatible architecture +RUN: luarocks install foo-1.0-1.impossible-x86.rock +EXIT: 1 +STDERR: +-------------------------------------------------------------------------------- +Incompatible architecture +-------------------------------------------------------------------------------- + + + +=============================================================================== +TEST: fails if not a zip file + +FILE: not_a_zipfile-1.0-1.src.rock +-------------------------------------------------------------------------------- +I am not a zip file! +-------------------------------------------------------------------------------- +RUN: luarocks install not_a_zipfile-1.0-1.src.rock +EXIT: 1 + + + +=============================================================================== +TEST: fails with an invalid patch + +FILE: invalid_patch-0.1-1.rockspec +-------------------------------------------------------------------------------- +package = "invalid_patch" +version = "0.1-1" +source = { + -- any valid URL + url = "https://raw.github.com/keplerproject/luarocks/master/src/luarocks/build.lua" +} +description = { + summary = "A rockspec with an invalid patch", +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + build = "build.lua" + }, + patches = { + ["I_am_an_invalid_patch.patch"] = +[[ +diff -Naur luadoc-3.0.1/src/luadoc/doclet/html.lua luadoc-3.0.1-new/src/luadoc/doclet/html.lua +--- luadoc-3.0.1/src/luadoc/doclet/html.lua2007-12-21 15:50:48.000000000 -0200 ++++ luadoc-3.0.1-new/src/luadoc/doclet/html.lua2008-02-28 01:59:53.000000000 -0300 +@@ -18,6 +18,7 @@ +- gabba gabba gabba ++ gobo gobo gobo +]] + } +} +-------------------------------------------------------------------------------- +RUN: luarocks invalid_patch-0.1-1.rockspec +EXIT: 1 + + + +================================================================================ +TEST: handle versioned modules when installing another version with --keep #268 + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: myrock-2.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "2.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return "hello" +-------------------------------------------------------------------------------- + +RUN: luarocks build myrock-1.0-1.rockspec +RUN: luarocks pack myrock +RUN: luarocks remove myrock + +RUN: luarocks build myrock-2.0-1.rockspec +RUN: luarocks pack myrock +RUN: luarocks remove myrock + +RUN: luarocks install ./myrock-2.0-1.all.rock + +EXISTS: %{testing_sys_tree}/share/lua/%{LUA_VERSION}/rock.lua + +RUN: luarocks install ./myrock-1.0-1.all.rock --keep + +EXISTS: %{testing_sys_tree}/share/lua/%{LUA_VERSION}/rock.lua +EXISTS: %{testing_sys_tree}/share/lua/%{LUA_VERSION}/myrock_1_0_1-rock.lua + +RUN: luarocks install ./myrock-2.0-1.all.rock + +EXISTS: %{testing_sys_tree}/share/lua/%{LUA_VERSION}/rock.lua +NOT_EXISTS: %{testing_sys_tree}/share/lua/%{LUA_VERSION}/myrock_1_0_1-rock.lua + + + +================================================================================ +TEST: handle versioned libraries when installing another version with --keep #268 + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/c_module.c" +} +build = { + modules = { + c_module = { "c_module.c" } + } +} +-------------------------------------------------------------------------------- + +FILE: myrock-2.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "2.0-1" +source = { + url = "file://%{url(%{tmpdir})}/c_module.c" +} +build = { + modules = { + c_module = { "c_module.c" } + } +} +-------------------------------------------------------------------------------- +FILE: c_module.c +-------------------------------------------------------------------------------- +#include <lua.h> +#include <lauxlib.h> + +int luaopen_c_module(lua_State* L) { + lua_newtable(L); + lua_pushinteger(L, 1); + lua_setfield(L, -2, "c_module"); + return 1; +} +-------------------------------------------------------------------------------- + +RUN: luarocks build myrock-1.0-1.rockspec +RUN: luarocks pack myrock +RUN: luarocks remove myrock + +RUN: luarocks build myrock-2.0-1.rockspec +RUN: luarocks pack myrock +RUN: luarocks remove myrock + +RUN: luarocks install ./myrock-2.0-1.%{platform}.rock + +EXISTS: %{testing_sys_tree}/lib/lua/%{LUA_VERSION}/c_module.%{lib_extension} + +RUN: luarocks install ./myrock-1.0-1.%{platform}.rock --keep + +EXISTS: %{testing_sys_tree}/lib/lua/%{LUA_VERSION}/c_module.%{lib_extension} +EXISTS: %{testing_sys_tree}/lib/lua/%{LUA_VERSION}/myrock_1_0_1-c_module.%{lib_extension} + +RUN: luarocks install ./myrock-2.0-1.%{platform}.rock + +EXISTS: %{testing_sys_tree}/lib/lua/%{LUA_VERSION}/c_module.%{lib_extension} +NOT_EXISTS: %{testing_sys_tree}/lib/lua/%{LUA_VERSION}/myrock_1_0_1-c_module.%{lib_extension} + + + +================================================================================ +TEST: installs a package with a bin entry + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" }, + install = { + bin = { + ["scripty"] = "rock.lua", + } + } +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return "hello" +-------------------------------------------------------------------------------- + +RUN: luarocks build myrock-1.0-1.rockspec +EXISTS: %{testing_sys_tree}/bin/scripty%{wrapper_extension} +RUN: luarocks pack myrock +RUN: luarocks remove myrock +NOT_EXISTS: %{testing_sys_tree}/bin/scripty%{wrapper_extension} + +RUN: luarocks install myrock-1.0-1.all.rock +EXISTS: %{testing_sys_tree}/bin/scripty%{wrapper_extension} + + + +================================================================================ +TEST: installs a package without its documentation using --no-doc + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "." +} +build = { + modules = { rock = "rock.lua" }, + install = { + bin = { + ["scripty"] = "rock.lua", + } + } +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return "hello" +-------------------------------------------------------------------------------- + +FILE: doc/something +-------------------------------------------------------------------------------- +a doc +-------------------------------------------------------------------------------- + +RUN: luarocks make +EXISTS: %{testing_sys_rocks}/myrock/1.0-1/doc/something +RUN: luarocks pack myrock +RUN: luarocks remove myrock +NOT_EXISTS: %{testing_sys_rocks}/myrock/1.0-1/doc/something + +RUN: luarocks install myrock-1.0-1.all.rock +EXISTS: %{testing_sys_rocks}/myrock/1.0-1/doc/something +RUN: luarocks remove myrock +NOT_EXISTS: %{testing_sys_rocks}/myrock/1.0-1/doc/something + +RUN: luarocks install myrock-1.0-1.all.rock --no-doc +NOT_EXISTS: %{testing_sys_rocks}/myrock/1.0-1/doc/something + + + +================================================================================ +TEST: handle non-Lua files in build.install.lua when upgrading sailorproject/sailor#138 + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "." +} +build = { + modules = { + rock = "rock.lua", + }, + install = { + lua = { + ["sailor.blank-app.htaccess"] = "src/sailor/blank-app/.htaccess", + } + } +} +-------------------------------------------------------------------------------- + +FILE: myrock-1.0-2.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-2" +source = { + url = "." +} +build = { + modules = { + rock = "rock.lua", + }, + install = { + lua = { + ["sailor.blank-app.htaccess"] = "src/sailor/blank-app/.htaccess", + } + } +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return "hello" +-------------------------------------------------------------------------------- + +FILE: src/sailor/blank-app/.htaccess +-------------------------------------------------------------------------------- +# I am just a file +-------------------------------------------------------------------------------- + +Prepare two versions as .rock packages with the same non-Lua asset: + +RUN: luarocks make ./myrock-1.0-1.rockspec +RUN: luarocks pack myrock +RUN: luarocks remove myrock + +RUN: luarocks make ./myrock-1.0-2.rockspec +RUN: luarocks pack myrock +RUN: luarocks remove myrock + +Now install the first one, and check that the asset was installed, with no "~" +backup leftover: + +RUN: luarocks install myrock-1.0-1.all.rock --no-doc + +EXISTS: %{testing_sys_tree}/share/lua/%{LUA_VERSION}/sailor/blank-app/.htaccess +NOT_EXISTS: %{testing_sys_tree}/share/lua/%{LUA_VERSION}/sailor/blank-app/.htaccess~ + +Then install the second one, and the asset should be replaced, again with no +"~" backup leftover: + +RUN: luarocks install myrock-1.0-2.all.rock --no-doc + +EXISTS: %{testing_sys_tree}/share/lua/%{LUA_VERSION}/sailor/blank-app/.htaccess +NOT_EXISTS: %{testing_sys_tree}/share/lua/%{LUA_VERSION}/sailor/blank-app/.htaccess~ + + + +================================================================================ +TEST: do not reinstall when already installed + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return "hello" +-------------------------------------------------------------------------------- + +RUN: luarocks build myrock-1.0-1.rockspec +RUN: luarocks pack myrock +RUN: luarocks remove myrock + +RUN: luarocks install ./myrock-1.0-1.all.rock + +RUN: luarocks show myrock +STDOUT: +-------------------------------------------------------------------------------- +myrock 1.0 +-------------------------------------------------------------------------------- + +RUN: luarocks install ./myrock-1.0-1.all.rock +STDOUT: +-------------------------------------------------------------------------------- +myrock 1.0-1 is already installed +Use --force to reinstall +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: installation rolls back on failure + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { + ["folder.rock"] = "rock.lua", + ["xyz"] = "xyz.lua", + }, +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return {} +-------------------------------------------------------------------------------- + +FILE: xyz.lua +-------------------------------------------------------------------------------- +return {} +-------------------------------------------------------------------------------- + +RUN: luarocks make --pack-binary-rock ./myrock-1.0-1.rockspec + +FILE: %{testing_sys_tree}/share/lua/%{lua_version}/folder +-------------------------------------------------------------------------------- +a file where a folder should be +-------------------------------------------------------------------------------- + +Try to install and fail because the file is in the folder's spot: + +RUN: luarocks install ./myrock-1.0-1.all.rock +EXIT: 1 + +EXISTS: %{testing_sys_tree}/share/lua/%{lua_version}/folder + +No leftovers from the failed installation: + +NOT_EXISTS: %{testing_sys_tree}/share/lua/%{lua_version}/xyz.lua + +Now we remove the file... + +RM: %{testing_sys_tree}/share/lua/%{lua_version}/folder + +Try again and succeed: + +RUN: luarocks install ./myrock-1.0-1.all.rock + +EXISTS: %{testing_sys_tree}/share/lua/%{lua_version}/folder/rock.lua +EXISTS: %{testing_sys_tree}/share/lua/%{lua_version}/xyz.lua + + + +================================================================================ +TEST: new install functionality based on #552: break dependencies warning + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: myrock-2.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "2.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: hasdep-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "hasdep" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/hasdep.lua" +} +dependencies = { + "myrock >= 2.0", +} +build = { + modules = { hasdep = "hasdep.lua" } +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return "hello" +-------------------------------------------------------------------------------- + +FILE: hasdep.lua +-------------------------------------------------------------------------------- +return "hasdep" +-------------------------------------------------------------------------------- + +RUN: luarocks build myrock-2.0-1.rockspec +RUN: luarocks build hasdep-1.0-1.rockspec +RUN: luarocks build myrock-1.0-1.rockspec + +STDERR: +-------------------------------------------------------------------------------- +Will not remove myrock 2.0 +Removing it would break dependencies for +hasdep 1.0 +-------------------------------------------------------------------------------- + +EXISTS: %{testing_sys_rocks}/myrock/1.0-1 +EXISTS: %{testing_sys_rocks}/myrock/2.0-1 + + + +================================================================================ +TEST: new install functionality based on #552: break dependencies with --force + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: myrock-2.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "2.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: hasdep-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "hasdep" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/hasdep.lua" +} +dependencies = { + "myrock >= 2.0", +} +build = { + modules = { hasdep = "hasdep.lua" } +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return "hello" +-------------------------------------------------------------------------------- + +FILE: hasdep.lua +-------------------------------------------------------------------------------- +return "hasdep" +-------------------------------------------------------------------------------- + +RUN: luarocks build myrock-2.0-1.rockspec +RUN: luarocks build hasdep-1.0-1.rockspec +RUN: luarocks build myrock-1.0-1.rockspec --force + +STDERR: +-------------------------------------------------------------------------------- +The following packages may be broken by this forced removal +hasdep 1.0 +-------------------------------------------------------------------------------- + +NOT_EXISTS: %{testing_sys_rocks}/myrock/2.0-1 +EXISTS: %{testing_sys_rocks}/myrock/1.0-1 + + + +================================================================================ +TEST: new install functionality based on #552: break dependencies with --force-fast + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: myrock-2.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "2.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: hasdep-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "hasdep" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/hasdep.lua" +} +dependencies = { + "myrock >= 2.0", +} +build = { + modules = { hasdep = "hasdep.lua" } +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return "hello" +-------------------------------------------------------------------------------- + +FILE: hasdep.lua +-------------------------------------------------------------------------------- +return "hasdep" +-------------------------------------------------------------------------------- + +RUN: luarocks build myrock-2.0-1.rockspec +RUN: luarocks build hasdep-1.0-1.rockspec +RUN: luarocks build myrock-1.0-1.rockspec --force-fast + +NOT_STDERR: +-------------------------------------------------------------------------------- +The following packages may be broken by this forced removal +hasdep 1.0 +-------------------------------------------------------------------------------- + +NOT_EXISTS: %{testing_sys_rocks}/myrock/2.0-1 +EXISTS: %{testing_sys_rocks}/myrock/1.0-1 diff --git a/spec/quick/list.q b/spec/quick/list.q new file mode 100644 index 0000000..a40f37e --- /dev/null +++ b/spec/quick/list.q @@ -0,0 +1,45 @@ +SUITE: luarocks list + +================================================================================ +TEST: invalid tree + +RUN: luarocks --tree=%{path(/some/invalid/tree)} list + +STDOUT: +-------------------------------------------------------------------------------- +Rocks installed for Lua %{lua_version} in %{path(/some/invalid/tree)} +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: --porcelain + +FILE: a_rock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "a_rock" +version = "1.0-1" +source = { + url = "file://%{url(%{fixtures_dir})}/a_rock.lua" +} +description = { + summary = "An example rockspec", +} +dependencies = { + "lua >= 5.1" +} +build = { + modules = { + build = "a_rock.lua" + }, +} +-------------------------------------------------------------------------------- +RUN: luarocks build a_rock-1.0-1.rockspec + +RUN: luarocks list --porcelain + +STDOUT: +-------------------------------------------------------------------------------- +a_rock 1.0-1 installed %{testing_sys_rocks} +-------------------------------------------------------------------------------- diff --git a/spec/quick/make.q b/spec/quick/make.q new file mode 100644 index 0000000..eb3472b --- /dev/null +++ b/spec/quick/make.q @@ -0,0 +1,88 @@ +SUITE: luarocks make + +================================================================================ +TEST: overrides luarocks.lock with --pin #pinning + +FILE: test-2.0-1.rockspec +-------------------------------------------------------------------------------- +package = "test" +version = "2.0-1" +source = { + url = "file://%{path(tmpdir)}/test.lua" +} +dependencies = { + "a_rock >= 0.8" +} +build = { + type = "builtin", + modules = { + test = "test.lua" + } +} +-------------------------------------------------------------------------------- + +FILE: test.lua +-------------------------------------------------------------------------------- +return {} +-------------------------------------------------------------------------------- + +FILE: luarocks.lock +-------------------------------------------------------------------------------- +return { + dependencies = { + ["a_rock"] = "1.0-1", + } +} +-------------------------------------------------------------------------------- + +RUN: luarocks make --only-server=%{fixtures_dir}/a_repo --pin --tree=lua_modules + +EXISTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/test/2.0-1/test-2.0-1.rockspec +EXISTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/a_rock/2.0-1/a_rock-2.0-1.rockspec + +FILE_CONTENTS: ./lua_modules/lib/luarocks/rocks-%{lua_version}/test/2.0-1/luarocks.lock +-------------------------------------------------------------------------------- +return { + dependencies = { + a_rock = "2.0-1", + lua = "%{lua_version}-1" + } +} +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: running make twice builds twice + +FILE: test-2.0-1.rockspec +-------------------------------------------------------------------------------- +package = "test" +version = "2.0-1" +source = { + url = "file://%{path(tmpdir)}/test.lua" +} +build = { + type = "builtin", + modules = { + test = "test.lua" + } +} +-------------------------------------------------------------------------------- + +FILE: test.lua +-------------------------------------------------------------------------------- +return {} +-------------------------------------------------------------------------------- + +RUN: luarocks make --only-server=%{fixtures_dir}/a_repo --pin --tree=lua_modules +STDOUT: +-------------------------------------------------------------------------------- +test 2.0-1 is now installed +-------------------------------------------------------------------------------- + +RUN: luarocks make --only-server=%{fixtures_dir}/a_repo --pin --tree=lua_modules +STDOUT: +-------------------------------------------------------------------------------- +test 2.0-1 is now installed +-------------------------------------------------------------------------------- diff --git a/spec/quick/new_version.q b/spec/quick/new_version.q new file mode 100644 index 0000000..98426db --- /dev/null +++ b/spec/quick/new_version.q @@ -0,0 +1,213 @@ +SUITE: luarocks new_version + +================================================================================ +TEST: fails without a context + +RUN: luarocks new_version +EXIT: 1 + + + +================================================================================ +TEST: fails with invalid arg + +RUN: luarocks new_version i_dont_exist +EXIT: 1 + + + +================================================================================ +TEST: updates a version + +FILE: myexample-0.1-1.rockspec +-------------------------------------------------------------------------------- +package = "myexample" +version = "0.1-1" +source = { + url = "git+https://localhost/myexample.git", + tag = "v0.1" +} +description = { + summary = "xxx", + detailed = "xxx" +} +build = { + type = "builtin", + modules = { + foo = "src/foo.lua" + } +} +-------------------------------------------------------------------------------- + +RUN: luarocks new_version myexample-0.1-1.rockspec 0.2 + +FILE_CONTENTS: myexample-0.2-1.rockspec +-------------------------------------------------------------------------------- +package = "myexample" +version = "0.2-1" +source = { + url = "git+https://localhost/myexample.git", + tag = "v0.2" +} +description = { + summary = "xxx", + detailed = "xxx" +} +build = { + type = "builtin", + modules = { + foo = "src/foo.lua" + } +} +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: updates via tag + +FILE: myexample-0.1-1.rockspec +-------------------------------------------------------------------------------- +package = "myexample" +version = "0.1-1" +source = { + url = "git+https://localhost/myexample.git", + tag = "v0.1" +} +description = { + summary = "xxx", + detailed = "xxx" +} +build = { + type = "builtin", + modules = { + foo = "src/foo.lua" + } +} +-------------------------------------------------------------------------------- + +RUN: luarocks new_version myexample-0.1-1.rockspec --tag v0.2 + +FILE_CONTENTS: myexample-0.2-1.rockspec +-------------------------------------------------------------------------------- +package = "myexample" +version = "0.2-1" +source = { + url = "git+https://localhost/myexample.git", + tag = "v0.2" +} +description = { + summary = "xxx", + detailed = "xxx" +} +build = { + type = "builtin", + modules = { + foo = "src/foo.lua" + } +} +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: updates URL + +FILE: myexample-0.1-1.rockspec +-------------------------------------------------------------------------------- +package = "myexample" +version = "0.1-1" +source = { + url = "https://localhost/myexample-0.1.tar.gz", +} +description = { + summary = "xxx", + detailed = "xxx" +} +build = { + type = "builtin", + modules = { + foo = "src/foo.lua" + } +} +-------------------------------------------------------------------------------- + +RUN: luarocks new_version myexample-0.1-1.rockspec 0.2 https://localhost/newpath/myexample-0.2.tar.gz + +FILE_CONTENTS: myexample-0.2-1.rockspec +-------------------------------------------------------------------------------- +package = "myexample" +version = "0.2-1" +source = { + url = "https://localhost/newpath/myexample-0.2.tar.gz" +} +description = { + summary = "xxx", + detailed = "xxx" +} +build = { + type = "builtin", + modules = { + foo = "src/foo.lua" + } +} +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: updates MD5 + +FILE: test-1.0-1.rockspec +-------------------------------------------------------------------------------- +package = "test" +version = "1.0-1" +source = { + url = "file://%{url(%{fixtures_dir})}/an_upstream_tarball-0.1.tar.gz", + md5 = "dca2ac30ce6c27cbd8dac4dd8f447630", +} +build = { + type = "builtin", + modules = { + my_module = "src/my_module.lua" + }, + install = { + bin = { + "src/my_module.lua" + } + } +} +-------------------------------------------------------------------------------- + +RUN: luarocks new_version test-1.0-1.rockspec 2.0 file://%{url(%{fixtures_dir})}/busted_project-0.1.tar.gz + +FILE_CONTENTS: test-2.0-1.rockspec +-------------------------------------------------------------------------------- +package = "test" +version = "2.0-1" +source = { + url = "file://%{url(%{fixtures_dir})}/busted_project-0.1.tar.gz", + md5 = "adfdfb8f1caa2b1f935a578fb07536eb", +} +build = { + type = "builtin", + modules = { + my_module = "src/my_module.lua" + }, + install = { + bin = { + "src/my_module.lua" + } + } +} +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: takes a URL, downloads and bumps revision by default + +RUN: luarocks new_version file://%{url(%{fixtures_dir})}/a_rock-1.0-1.rockspec + +EXISTS: a_rock-1.0-1.rockspec +EXISTS: a_rock-1.0-2.rockspec diff --git a/spec/quick/pack.q b/spec/quick/pack.q new file mode 100644 index 0000000..ee44a45 --- /dev/null +++ b/spec/quick/pack.q @@ -0,0 +1,128 @@ +SUITE: luarocks pack + +================================================================================ +TEST: fails no arguments + +RUN: luarocks pack +EXIT: 1 + + + +================================================================================ +TEST: fails with invalid rockspec + +RUN: luarocks pack $%{fixtures_dir}/invalid_say-1.3-1.rockspec +EXIT: 1 + + + +================================================================================ +TEST: fails with rock that is not installed + +RUN: luarocks pack notinstalled +EXIT: 1 + + + +================================================================================ +TEST: fails with non existing path + +RUN: luarocks pack /notexists/notinstalled +EXIT: 1 + + + +================================================================================ +TEST: packs latest version version of rock + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: myrock-2.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "2.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return "hello" +-------------------------------------------------------------------------------- + +RUN: luarocks build myrock-1.0-1.rockspec +RUN: luarocks build myrock-2.0-1.rockspec --keep +RUN: luarocks pack myrock + +EXISTS: myrock-2.0-1.all.rock + + + +================================================================================ +TEST: --sign #gpg +PENDING: true + +FILE: myrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: myrock-2.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +package = "myrock" +version = "2.0-1" +source = { + url = "file://%{url(%{tmpdir})}/rock.lua" +} +build = { + modules = { rock = "rock.lua" } +} +-------------------------------------------------------------------------------- + +FILE: rock.lua +-------------------------------------------------------------------------------- +return "hello" +-------------------------------------------------------------------------------- + +RUN: luarocks build myrock-1.0-1.rockspec +RUN: luarocks build myrock-2.0-1.rockspec --keep +RUN: luarocks pack myrock --sign + +EXISTS: myrock-2.0-1.all.rock +EXISTS: myrock-2.0-1.all.rock.asc + + + +================================================================================ +TEST: packs a namespaced rock #namespaces + +RUN: luarocks build a_user/a_rock --server=%{fixtures_dir}/a_repo +RUN: luarocks build a_rock --keep --server=%{fixtures_dir}/a_repo +RUN: luarocks pack a_user/a_rock + +EXISTS: a_rock-2.0-1.all.rock diff --git a/spec/quick/path.q b/spec/quick/path.q new file mode 100644 index 0000000..77fc188 --- /dev/null +++ b/spec/quick/path.q @@ -0,0 +1,22 @@ +================================================================================ +TEST: luarocks path: --project-tree + + +RUN: luarocks path --project-tree=foo +STDOUT: +-------------------------------------------------------------------------------- +%{path(foo/share/lua/%{lua_version}/?.lua)} +%{path(foo/share/lua/%{lua_version}/?/init.lua)} +-------------------------------------------------------------------------------- + +RUN: luarocks path --project-tree=foo --tree=bar +NOT_STDOUT: +-------------------------------------------------------------------------------- +%{path(foo/share/lua/%{lua_version}/?.lua)} +%{path(foo/share/lua/%{lua_version}/?/init.lua)} +-------------------------------------------------------------------------------- +STDOUT: +-------------------------------------------------------------------------------- +%{path(bar/share/lua/%{lua_version}/?.lua)} +%{path(bar/share/lua/%{lua_version}/?/init.lua)} +-------------------------------------------------------------------------------- diff --git a/spec/quick/purge.q b/spec/quick/purge.q new file mode 100644 index 0000000..1fb6129 --- /dev/null +++ b/spec/quick/purge.q @@ -0,0 +1,103 @@ +SUITE: luarocks purge + +================================================================================ +TEST: needs a --tree argument +RUN: luarocks purge +EXIT: 1 + +================================================================================ +TEST: missing tree +RUN: luarocks purge --tree=missing-tree +EXIT: 1 + +================================================================================ +TEST: missing --tree argument +RUN: luarocks purge --tree= +EXIT: 1 + + +================================================================================ +TEST: runs + +FILE: testrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +package = "testrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/testrock.lua" +} +dependencies = { + "a_rock >= 0.8" +} +build = { + type = "builtin", + modules = { + testrock = "testrock.lua" + } +} +-------------------------------------------------------------------------------- + +FILE: testrock.lua +-------------------------------------------------------------------------------- +return {} +-------------------------------------------------------------------------------- + +RUN: luarocks build --only-server=%{fixtures_dir}/a_repo testrock-1.0-1.rockspec + +EXISTS: %{testing_sys_rocks}/testrock +EXISTS: %{testing_sys_rocks}/a_rock + +RUN: luarocks purge --tree=%{testing_sys_tree} + +NOT_EXISTS: %{testing_sys_rocks}/testrock +NOT_EXISTS: %{testing_sys_rocks}/a_rock + + + +================================================================================ +TEST: works with missing files + +FILE: testrock-1.0-1.rockspec +-------------------------------------------------------------------------------- +package = "testrock" +version = "1.0-1" +source = { + url = "file://%{url(%{tmpdir})}/testrock.lua" +} +dependencies = { + "a_rock >= 0.8" +} +build = { + type = "builtin", + modules = { + testrock = "testrock.lua" + } +} +-------------------------------------------------------------------------------- + +FILE: testrock.lua +-------------------------------------------------------------------------------- +return {} +-------------------------------------------------------------------------------- + +RUN: luarocks build --only-server=%{fixtures_dir}/a_repo testrock-1.0-1.rockspec + +RMDIR: %{testing_sys_tree}/share/lua/%{lua_version}/testrock + +RUN: luarocks purge --tree=%{testing_sys_tree} + +NOT_EXISTS: %{testing_sys_rocks}/testrock +NOT_EXISTS: %{testing_sys_rocks}/a_rock + + + +================================================================================ +TEST: --old-versions + +RUN: luarocks install --only-server=%{fixtures_dir}/a_repo a_rock 2.0 +RUN: luarocks install --only-server=%{fixtures_dir}/a_repo a_rock 1.0 --keep + +RUN: luarocks purge --old-versions --tree=%{testing_sys_tree} + +EXISTS: %{testing_sys_rocks}/a_rock/2.0-1 +NOT_EXISTS: %{testing_sys_rocks}/a_rock/1.0-1 diff --git a/spec/quick/test.q b/spec/quick/test.q new file mode 100644 index 0000000..cb5ccd7 --- /dev/null +++ b/spec/quick/test.q @@ -0,0 +1,51 @@ +================================================================================ +TEST: luarocks test: handle if test.command is not a string + +Regression test for #1055. + +FILE: example-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +source = { + url = "", +} +package = "example" +version = "1.0-1" +test = { + type = "command", + command = {"./unit.lua"}, +} +-------------------------------------------------------------------------------- + +RUN: luarocks test +EXIT: 1 +STDERR: +-------------------------------------------------------------------------------- +'command' expects a string +-------------------------------------------------------------------------------- + + + +================================================================================ +TEST: luarocks test: handle if test.script is not a string + +FILE: example-1.0-1.rockspec +-------------------------------------------------------------------------------- +rockspec_format = "3.0" +source = { + url = "", +} +package = "example" +version = "1.0-1" +test = { + type = "command", + script = {"./unit.lua"}, +} +-------------------------------------------------------------------------------- + +RUN: luarocks test +EXIT: 1 +STDERR: +-------------------------------------------------------------------------------- +'script' expects a string +-------------------------------------------------------------------------------- diff --git a/spec/quick_spec.lua b/spec/quick_spec.lua new file mode 100644 index 0000000..c2d8bb5 --- /dev/null +++ b/spec/quick_spec.lua @@ -0,0 +1,22 @@ +local lfs = require("lfs") +local test_env = require("spec.util.test_env") +local quick = require("spec.util.quick") + +describe("quick tests: #quick", function() + before_each(function() + test_env.setup_specs() + end) + + local spec_quick = test_env.testing_paths.spec_dir .. "/quick" + for f in lfs.dir(spec_quick) do + if f:match("%.q$") then + local tests = quick.compile(spec_quick .. "/" .. f, getfenv and getfenv() or _ENV) + for _, t in ipairs(tests) do + if not t.pending then + it(t.name, t.fn) + end + end + end + end +end) + diff --git a/spec/refresh_cache_spec.lua b/spec/refresh_cache_spec.lua new file mode 100644 index 0000000..73ba9a9 --- /dev/null +++ b/spec/refresh_cache_spec.lua @@ -0,0 +1,13 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run + +describe("luarocks-admin refresh_cache #integration", function() + + before_each(function() + test_env.setup_specs() + end) + + it("runs #ssh", function() + assert.is_true(run.luarocks_admin_bool("--server=testing refresh_cache")) + end) +end) diff --git a/spec/remove_spec.lua b/spec/remove_spec.lua new file mode 100644 index 0000000..3bcfbb2 --- /dev/null +++ b/spec/remove_spec.lua @@ -0,0 +1,129 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run +local testing_paths = test_env.testing_paths +local env_variables = test_env.env_variables +local V = test_env.V +local P = test_env.P + +local extra_rocks = { + "/abelhas-1.1-1.src.rock", + "/copas-${COPAS}.src.rock", + "/coxpcall-1.16.0-1.src.rock", + "/coxpcall-1.16.0-1.rockspec", + "/luafilesystem-${LUAFILESYSTEM}.src.rock", + "/luafilesystem-${LUAFILESYSTEM_OLD}.src.rock", +} + +describe("luarocks remove #integration", function() + + before_each(function() + test_env.setup_specs(extra_rocks) + end) + + describe("basic tests", function() + it("with no flags/arguments", function() + assert.is_false(run.luarocks_bool("remove")) + end) + + it("invalid rock", function() + assert.is_false(run.luarocks_bool("remove invalid.rock")) + end) + + it("missing rock", function() + assert.is_false(run.luarocks_bool("remove missing_rock")) + end) + + it("invalid argument", function() + assert.is_false(run.luarocks_bool("remove luacov --deps-mode")) + end) + + it("built abelhas", function() + assert.is_true(run.luarocks_bool("build abelhas 1.1")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/abelhas")) + assert.is_true(run.luarocks_bool("remove abelhas 1.1")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/abelhas")) + end) + + it("built abelhas with uppercase name", function() + assert.is_true(run.luarocks_bool("build abelhas 1.1")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/abelhas")) + assert.is_true(run.luarocks_bool("remove Abelhas 1.1")) + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/abelhas")) + end) + end) + + describe("more complex tests", function() + before_each(function() + assert.is.truthy(test_env.need_rock("coxpcall")) + end) + + it("fail, break dependencies", function() + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/coxpcall")) + assert.is_true(run.luarocks_bool("build copas")) + + assert.is_false(run.luarocks_bool("remove coxpcall")) + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/coxpcall")) + end) + + it("force", function() + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/coxpcall")) + assert.is_true(run.luarocks_bool("build copas")) + + local output = run.luarocks("remove --force coxpcall") + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/coxpcall")) + assert.is.truthy(output:find("Checking stability of dependencies")) + end) + + it("force fast", function() + assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/coxpcall")) + assert.is_true(run.luarocks_bool("build copas")) + + local output = run.luarocks("remove --force-fast coxpcall") + assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/coxpcall")) + assert.is.falsy(output:find("Checking stability of dependencies")) + end) + + it("restores old versions", function() + local libdir = P(testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION) + + assert.is_true(run.luarocks_bool("install luafilesystem ${LUAFILESYSTEM_OLD_V}")) + assert.is.truthy(lfs.attributes(libdir.."/lfs."..test_env.lib_extension)) + + if test_env.TEST_TARGET_OS ~= "windows" then + local fd = io.open(libdir.."/lfs."..test_env.lib_extension, "r") + assert(fd:read("*a"):match(V"LuaFileSystem ${LUAFILESYSTEM_OLD_V}", 1, true)) + fd:close() + end + + local suffix = (V"${LUAFILESYSTEM_OLD}"):gsub("[%.%-]", "_") + + assert.is_true(run.luarocks_bool("install luafilesystem ${LUAFILESYSTEM_V} --keep")) + assert.is.truthy(lfs.attributes(libdir.."/lfs."..test_env.lib_extension)) + assert.is.truthy(lfs.attributes(libdir.."/luafilesystem_"..suffix.."-lfs."..test_env.lib_extension)) + + if test_env.TEST_TARGET_OS ~= "windows" then + local fd = io.open(libdir.."/lfs."..test_env.lib_extension, "r") + assert(fd:read("*a"):match(V"LuaFileSystem ${LUAFILESYSTEM_V}", 1, true)) + fd:close() + end + + assert.is_true(run.luarocks_bool("remove luafilesystem ${LUAFILESYSTEM_V}")) + assert.is.truthy(lfs.attributes(libdir.."/lfs."..test_env.lib_extension)) + + if test_env.TEST_TARGET_OS ~= "windows" then + local fd = io.open(libdir.."/lfs."..test_env.lib_extension, "r") + assert(fd:read("*a"):match(V"LuaFileSystem ${LUAFILESYSTEM_OLD_V}", 1, true)) + fd:close() + end + end) + end) + + it("#admin remove #ssh", function() + assert.is_true(run.luarocks_admin_bool("--server=testing remove coxpcall-1.16.0-1.src.rock")) + end) + + it("#admin remove missing", function() + assert.is_false(run.luarocks_admin_bool("--server=testing remove")) + end) +end) diff --git a/spec/search_spec.lua b/spec/search_spec.lua new file mode 100644 index 0000000..6d71e00 --- /dev/null +++ b/spec/search_spec.lua @@ -0,0 +1,33 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run + +local extra_rocks = { +"/lzlib-0.4.1.53-1.src.rock" +} + +describe("luarocks search #integration", function() + + before_each(function() + test_env.setup_specs(extra_rocks) + end) + + it("with no flags/arguments", function() + assert.is_false(run.luarocks_bool("search")) + end) + + it("zlib", function() + assert.is_true(run.luarocks_bool("search zlib")) + end) + + it("zlib 1.1", function() + assert.is_true(run.luarocks_bool("search zlib 1.1")) + end) + + it("missing rock", function() + assert.is_true(run.luarocks_bool("search missing_rock")) + end) + + it("with flag all", function() + assert.is_true(run.luarocks_bool("search --all")) + end) +end) diff --git a/spec/show_spec.lua b/spec/show_spec.lua new file mode 100644 index 0000000..cd34b5a --- /dev/null +++ b/spec/show_spec.lua @@ -0,0 +1,105 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run +local testing_paths = test_env.testing_paths + +describe("luarocks show #integration", function() + + before_each(function() + test_env.setup_specs() + end) + + it("with no flags/arguments", function() + assert.is_false(run.luarocks_bool("show")) + end) + + describe("basic tests with flags", function() + it("invalid", function() + assert.is_false(run.luarocks_bool("show invalid")) + end) + + it("luacov", function() + local output = run.luarocks("show luacov") + assert.is.truthy(output:match("LuaCov")) + end) + + it("luacov with uppercase name", function() + local output = run.luarocks("show LuaCov") + assert.is.truthy(output:match("LuaCov")) + end) + + it("modules of luacov", function() + local output = run.luarocks("show --modules luacov") + assert.match("luacov.*luacov.defaults.*luacov.reporter.*luacov.reporter.default.*luacov.runner.*luacov.stats.*luacov.tick", output) + end) + + it("--deps", function() + assert(run.luarocks_bool("build has_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + local output = run.luarocks("show --deps has_namespaced_dep") + assert.match("a_user/a_rock", output) + end) + + it("list dependencies", function() + assert(run.luarocks_bool("build has_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + local output = run.luarocks("show has_namespaced_dep") + assert.match("a_user/a_rock.*2.0", output) + end) + + it("rockspec of luacov", function() + local output = run.luarocks("show --rockspec luacov") + assert.is.truthy(output:match("luacov--0.15.0--1.rockspec")) + end) + + it("mversion of luacov", function() + local output = run.luarocks("show --mversion luacov") + assert.is.truthy(output:match("0.15.0--1")) + end) + + it("rock tree of luacov", function() + local output = run.luarocks("show --rock-tree luacov") + end) + + it("rock directory of luacov", function() + local output = run.luarocks("show --rock-dir luacov") + end) + + it("issues URL of luacov", function() + local output = run.luarocks("show --issues luacov") + end) + + it("labels of luacov", function() + local output = run.luarocks("show --labels luacov") + end) + end) + + it("old version of luacov", function() + run.luarocks("install luacov 0.15.0") + run.luarocks_bool("show luacov 0.15.0") + end) + + it("can find by substring", function() + assert(run.luarocks_bool("install has_build_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert.match("a_build_dep", run.luarocks("show has_")) + end) + + it("fails when substring matches multiple", function() + assert(run.luarocks_bool("install has_build_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(run.luarocks_bool("install a_build_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert.match("multiple installed packages match the name 'dep'", run.luarocks("show dep")) + end) + + it("shows #build_dependencies", function() + assert(run.luarocks_bool("install has_build_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert.match("a_build_dep", run.luarocks("show has_build_dep")) + end) + + it("gets #build_dependencies via --build-deps", function() + assert(run.luarocks_bool("install has_build_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert.match("a_build_dep", run.luarocks("show has_build_dep --build-deps")) + end) + + it("shows #namespaces via --rock-namespace", function() + assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert.match("a_user", run.luarocks("show a_rock --rock-namespace")) + end) + +end) diff --git a/spec/test_spec.lua b/spec/test_spec.lua new file mode 100644 index 0000000..bc5f047 --- /dev/null +++ b/spec/test_spec.lua @@ -0,0 +1,93 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run +local testing_paths = test_env.testing_paths +local write_file = test_env.write_file + +local extra_rocks = { + "/busted-2.2.0-1.src.rock", + "/lua_cliargs-3.0-1.src.rock", + "/luafilesystem-${LUAFILESYSTEM}.src.rock", + "/luasystem-0.2.1-0.src.rock", + "/dkjson-${DKJSON}.src.rock", + "/say-1.4.1-3.src.rock", + "/luassert-1.9.0-1.src.rock", + "/penlight-1.13.1-1.src.rock", + "/lua-term-0.8-1.rockspec", + "/mediator_lua-1.1.2-0.rockspec", +} + +describe("luarocks test #integration", function() + + lazy_setup(function() + test_env.setup_specs(extra_rocks) + end) + + it("fails with no flags/arguments", function() + finally(function() + lfs.chdir(testing_paths.testrun_dir) + test_env.remove_dir("empty") + end) + assert(lfs.mkdir("empty")) + assert(lfs.chdir("empty")) + assert.is_false(run.luarocks_bool("test")) + end) + + describe("busted backend", function() + + it("with rockspec, installing busted", function() + finally(function() + -- delete downloaded and unpacked files + lfs.chdir(testing_paths.testrun_dir) + test_env.remove_dir("busted_project-0.1-1") + os.remove("busted_project-0.1-1.src.rock") + end) + + -- make luassert + assert.is_true(run.luarocks_bool("download --server="..testing_paths.fixtures_repo_dir.." busted_project 0.1-1")) + assert.is_true(run.luarocks_bool("unpack busted_project-0.1-1.src.rock")) + lfs.chdir("busted_project-0.1-1/busted_project") + assert.is_true(run.luarocks_bool("make")) + local output = run.luarocks("test") + print(output) + -- Assert that busted ran, whether successfully or not + assert.match("%d+ success.* / %d+ failure.* / %d+ error.* / %d+ pending", output) + end) + + it("prepare", function() + finally(function() + -- delete downloaded and unpacked files + lfs.chdir(testing_paths.testrun_dir) + test_env.remove_dir("busted_project-0.1-1") + os.remove("busted_project-0.1-1.src.rock") + end) + + -- make luassert + assert.is_true(run.luarocks_bool("download --server="..testing_paths.fixtures_repo_dir.." busted_project 0.1-1")) + assert.is_true(run.luarocks_bool("unpack busted_project-0.1-1.src.rock")) + lfs.chdir("busted_project-0.1-1/busted_project") + assert.is_true(run.luarocks_bool("make")) + + run.luarocks_bool("remove busted") + local prepareOutput = run.luarocks_bool("test --prepare") + assert.is_true(run.luarocks_bool("show busted")) + + -- Assert that "test --prepare" run successfully + assert.is_true(prepareOutput) + + local output = run.luarocks("test") + assert.not_match(tostring(prepareOutput), output) + + end) + end) + + describe("command backend", function() + describe("prepare", function() + it("works with non-busted rocks", function() + write_file("test.lua", "", finally) + assert.is_true(run.luarocks_bool("test --prepare " .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec")) + end) + end) + end) +end) + diff --git a/spec/unit/build_spec.lua b/spec/unit/build_spec.lua new file mode 100644 index 0000000..e8f1394 --- /dev/null +++ b/spec/unit/build_spec.lua @@ -0,0 +1,365 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local get_tmp_path = test_env.get_tmp_path +local run = test_env.run +local testing_paths = test_env.testing_paths +local write_file = test_env.write_file +local P = test_env.P + +test_env.setup_specs() +local cfg = require("luarocks.core.cfg") +local deps = require("luarocks.deps") +local fs = require("luarocks.fs") +local path = require("luarocks.path") +local rockspecs = require("luarocks.rockspecs") +local build_builtin = require("luarocks.build.builtin") + +local c_module_source = [[ + #include <lua.h> + #include <lauxlib.h> + + int luaopen_c_module(lua_State* L) { + lua_newtable(L); + lua_pushinteger(L, 1); + lua_setfield(L, -2, "c_module"); + return 1; + } +]] + +describe("LuaRocks build #unit", function() + local runner + + lazy_setup(function() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + cfg.init() + fs.init() + deps.check_lua_incdir(cfg.variables) + deps.check_lua_libdir(cfg.variables) + end) + + lazy_teardown(function() + runner.save_stats() + end) + + describe("build.builtin", function() + it("builtin auto installs files in lua subdir", function() + test_env.run_in_tmp(function(tmpdir) + lfs.mkdir("lua") + write_file("lua_module-1.0-1.rockspec", [[ + package = "lua_module" + version = "1.0-1" + source = { + url = "http://example.com/lua_module" + } + build = { + type = "builtin", + modules = {} + } + ]], finally) + write_file("lua/lua_module.lua", "return 123", finally) + + assert.is_true(run.luarocks_bool("build")) + assert.match("[\\/]lua_module%.lua", run.luarocks("show lua_module")) + end, finally) + end) + + describe("builtin.autodetect_modules", function() + local tmpdir + local olddir + + before_each(function() + tmpdir = get_tmp_path() + olddir = lfs.currentdir() + lfs.mkdir(tmpdir) + lfs.chdir(tmpdir) + fs.change_dir(tmpdir) + end) + + after_each(function() + if olddir then + lfs.chdir(olddir) + fs.change_dir(olddir) + if tmpdir then + lfs.rmdir(tmpdir) + end + end + end) + + local libs = { "foo1", "foo2" } + local incdirs = { "$(FOO1_INCDIR)", "$(FOO2_INCDIR)" } + local libdirs = { "$(FOO1_LIBDIR)", "$(FOO2_LIBDIR)" } + + it("returns a table of the modules having as location the current directory", function() + write_file("module1.lua", "", finally) + write_file("module2.c", "", finally) + write_file("module3.c", "int luaopen_my_module()", finally) + write_file("test.lua", "", finally) + write_file("tests.lua", "", finally) + + local modules = build_builtin.autodetect_modules(libs, incdirs, libdirs) + assert.same(modules, { + module1 = "module1.lua", + module2 = { + sources = "module2.c", + libraries = libs, + incdirs = incdirs, + libdirs = libdirs + }, + my_module = { + sources = "module3.c", + libraries = libs, + incdirs = incdirs, + libdirs = libdirs + } + }) + end) + + local test_with_location = function(location) + lfs.mkdir(location) + lfs.mkdir(location .. "/dir1") + lfs.mkdir(location .. "/dir1/dir2") + + write_file(location .. "/module1.lua", "", finally) + write_file(location .. "/dir1/module2.c", "", finally) + write_file(location .. "/dir1/dir2/module3.c", "int luaopen_my_module()", finally) + write_file(location .. "/test.lua", "", finally) + write_file(location .. "/tests.lua", "", finally) + + local modules = build_builtin.autodetect_modules(libs, incdirs, libdirs) + assert.same(modules, { + module1 = P(location .. "/module1.lua"), + ["dir1.module2"] = { + sources = P(location .. "/dir1/module2.c"), + libraries = libs, + incdirs = incdirs, + libdirs = libdirs + }, + my_module = { + sources = P(location .. "/dir1/dir2/module3.c"), + libraries = libs, + incdirs = incdirs, + libdirs = libdirs + } + }) + + lfs.rmdir(location .. "/dir1/dir2") + lfs.rmdir(location .. "/dir1") + lfs.rmdir(location) + end + + it("returns a table of the modules having as location the src directory", function() + test_with_location("src") + end) + + it("returns a table of the modules having as location the lua directory", function() + test_with_location("lua") + end) + + it("returns as second and third argument tables of the bin files and copy directories", function() + lfs.mkdir("doc") + lfs.mkdir("docs") + lfs.mkdir("samples") + lfs.mkdir("tests") + lfs.mkdir("bin") + write_file("bin/binfile", "", finally) + + local _, install, copy_directories = build_builtin.autodetect_modules({}, {}, {}) + assert.same(install, { bin = { P"bin/binfile" } }) + assert.same(copy_directories, { "doc", "docs", "samples", "tests" }) + + lfs.rmdir("doc") + lfs.rmdir("docs") + lfs.rmdir("samples") + lfs.rmdir("tests") + lfs.rmdir("bin") + end) + end) + + describe("builtin.run", function() + local tmpdir + local olddir + + before_each(function() + tmpdir = get_tmp_path() + olddir = lfs.currentdir() + lfs.mkdir(tmpdir) + lfs.chdir(tmpdir) + fs.change_dir(tmpdir) + path.use_tree(lfs.currentdir()) + end) + + after_each(function() + if olddir then + lfs.chdir(olddir) + fs.change_dir(olddir) + if tmpdir then + lfs.rmdir(tmpdir) + end + end + end) + + it("returns false if the rockspec has no build modules and its format does not support autoextraction", function() + local rockspec = { + package = "test", + version = "1.0-1", + source = { + url = "http://example.com/test" + }, + build = {} + } + + rockspecs.from_persisted_table("test-1.0-1.rockspec", rockspec) + assert.falsy(build_builtin.run(rockspec)) + rockspec.rockspec_format = "1.0" + assert.falsy(build_builtin.run(rockspec)) + end) + + it("returns false if lua.h could not be found", function() + local rockspec = { + package = "c_module", + version = "1.0-1", + source = { + url = "http://example.com/c_module" + }, + build = { + type = "builtin", + modules = { + c_module = "c_module.c" + } + } + } + write_file("c_module.c", c_module_source, finally) + + rockspecs.from_persisted_table("c_module-1.0-1.rockspec", rockspec) + rockspec.variables = { LUA_INCDIR = "invalid" } + assert.falsy(build_builtin.run(rockspec)) + end) + + it("returns false if the build fails", function() + local rockspec = { + package = "c_module", + version = "1.0-1", + source = { + url = "http://example.com/c_module" + }, + build = { + type = "builtin", + modules = { + c_module = "c_module.c" + } + } + } + write_file("c_module.c", c_module_source .. "invalid", finally) + + rockspecs.from_persisted_table("c_module-1.0-1.rockspec", rockspec) + assert.falsy(build_builtin.run(rockspec)) + end) + + it("returns true if the build succeeds with C module", function() + local rockspec = { + package = "c_module", + version = "1.0-1", + source = { + url = "http://example.com/c_module" + }, + build = { + type = "builtin", + modules = { + c_module = "c_module.c" + } + } + } + write_file("c_module.c", c_module_source, finally) + + rockspecs.from_persisted_table("c_module-1.0-1.rockspec", rockspec) + assert.truthy(build_builtin.run(rockspec)) + assert.truthy(lfs.attributes("lib/luarocks/rocks-" .. test_env.lua_version .. "/c_module/1.0-1/lib/c_module." .. test_env.lib_extension)) + end) + + it("returns true if the build succeeds with Lua module", function() + local rockspec = { + rockspec_format = "1.0", + package = "test", + version = "1.0-1", + source = { + url = "http://example.com/test" + }, + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + } + write_file("test.lua", "return {}", finally) + + rockspecs.from_persisted_table("test-1.0-1.rockspec", rockspec) + assert.truthy(build_builtin.run(rockspec)) + assert.truthy(lfs.attributes("lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/lua/test.lua")) + end) + + it("automatically extracts the modules and libraries if they are not given and builds against any external dependencies", function() + local fdir = testing_paths.fixtures_dir + if test_env.TEST_TARGET_OS == "windows" then + if test_env.MINGW then + os.execute("gcc -shared -o " .. fdir .. "/libfixturedep.dll -Wl,--out-implib," .. fdir .."/libfixturedep.a " .. fdir .. "/fixturedep.c") + else + os.execute("cl " .. fdir .. "\\fixturedep.c /link /export:fixturedep_fn /out:" .. fdir .. "\\fixturedep.dll /implib:" .. fdir .. "\\fixturedep.lib") + end + elseif test_env.TEST_TARGET_OS == "linux" then + os.execute("gcc -shared -o " .. fdir .. "/libfixturedep.so " .. fdir .. "/fixturedep.c") + elseif test_env.TEST_TARGET_OS == "osx" then + os.execute("cc -dynamiclib -o " .. fdir .. "/libfixturedep.dylib " .. fdir .. "/fixturedep.c") + end + + local rockspec = { + rockspec_format = "3.0", + package = "c_module", + version = "1.0-1", + source = { + url = "http://example.com/c_module" + }, + external_dependencies = { + FIXTUREDEP = { + library = "fixturedep" + } + }, + build = { + type = "builtin" + } + } + write_file("c_module.c", c_module_source, finally) + + rockspecs.from_persisted_table("c_module-1.0-1.rockspec", rockspec) + rockspec.variables["FIXTUREDEP_LIBDIR"] = testing_paths.fixtures_dir + assert.truthy(build_builtin.run(rockspec)) + end) + + it("returns false if any external dependency is missing", function() + local rockspec = { + rockspec_format = "3.0", + package = "c_module", + version = "1.0-1", + source = { + url = "https://example.com/c_module" + }, + external_dependencies = { + EXTDEP = { + library = "missing" + } + }, + build = { + type = "builtin" + } + } + write_file("c_module.c", c_module_source, finally) + + rockspecs.from_persisted_table("c_module-1.0-1.rockspec", rockspec) + rockspec.variables["EXTDEP_INCDIR"] = lfs.currentdir() + rockspec.variables["EXTDEP_LIBDIR"] = lfs.currentdir() + assert.falsy(build_builtin.run(rockspec)) + end) + end) + end) +end) diff --git a/spec/unit/deps_spec.lua b/spec/unit/deps_spec.lua new file mode 100644 index 0000000..3be80b9 --- /dev/null +++ b/spec/unit/deps_spec.lua @@ -0,0 +1,143 @@ +local test_env = require("spec.util.test_env") +local testing_paths = test_env.testing_paths + +local cfg = require("luarocks.core.cfg") +local deps = require("luarocks.deps") +local fs = require("luarocks.fs") + +describe("LuaRocks deps #unit", function() + local runner + + lazy_setup(function() + cfg.init() + fs.init() + deps.check_lua_incdir(cfg.variables) + deps.check_lua_libdir(cfg.variables) + + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + end) + + lazy_teardown(function() + runner.save_stats() + end) + + describe("deps", function() + describe("deps.autodetect_external_dependencies", function() + it("returns false if the given build table has no external dependencies", function() + local build_table = { + type = "builtin" + } + + assert.falsy(deps.autodetect_external_dependencies(build_table)) + end) + + it("returns a table of the external dependencies found in the given build table", function() + local build_table = { + type = "builtin", + modules = { + module1 = { + libraries = { "foo1", "foo2" }, + }, + module2 = { + libraries = "foo3" + }, + } + } + + local extdeps = deps.autodetect_external_dependencies(build_table) + assert.same(extdeps["FOO1"], { library = "foo1" }) + assert.same(extdeps["FOO2"], { library = "foo2" }) + assert.same(extdeps["FOO3"], { library = "foo3" }) + end) + + it("adds proper include and library dirs to the given build table", function() + local build_table + + build_table = { + type = "builtin", + modules = { + module1 = { + libraries = "foo" + } + } + } + deps.autodetect_external_dependencies(build_table) + assert.same(build_table, { + type = "builtin", + modules = { + module1 = { + libraries = "foo", + incdirs = { "$(FOO_INCDIR)" }, + libdirs = { "$(FOO_LIBDIR)" } + } + } + }) + + build_table = { + type = "builtin", + modules = { + module1 = { + libraries = "foo", + incdirs = { "INCDIRS" } + } + } + } + deps.autodetect_external_dependencies(build_table) + assert.same(build_table, { + type = "builtin", + modules = { + module1 = { + libraries = "foo", + incdirs = { "INCDIRS" }, + libdirs = { "$(FOO_LIBDIR)" } + } + } + }) + + build_table = { + type = "builtin", + modules = { + module1 = { + libraries = "foo", + libdirs = { "LIBDIRS" } + } + } + } + deps.autodetect_external_dependencies(build_table) + assert.same(build_table, { + type = "builtin", + modules = { + module1 = { + libraries = "foo", + incdirs = { "$(FOO_INCDIR)" }, + libdirs = { "LIBDIRS" } + } + } + }) + + build_table = { + type = "builtin", + modules = { + module1 = { + libraries = "foo", + incdirs = { "INCDIRS" }, + libdirs = { "LIBDIRS" } + } + } + } + deps.autodetect_external_dependencies(build_table) + assert.same(build_table, { + type = "builtin", + modules = { + module1 = { + libraries = "foo", + incdirs = { "INCDIRS" }, + libdirs = { "LIBDIRS" } + } + } + }) + end) + end) + end) +end) diff --git a/spec/unit/dir_spec.lua b/spec/unit/dir_spec.lua new file mode 100644 index 0000000..55dd6e0 --- /dev/null +++ b/spec/unit/dir_spec.lua @@ -0,0 +1,70 @@ +local test_env = require("spec.util.test_env") +local testing_paths = test_env.testing_paths +local P = test_env.P + +test_env.setup_specs() +local dir = require("luarocks.dir") + +describe("luarocks.dir #unit", function() + local runner + + lazy_setup(function() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + end) + + lazy_teardown(function() + runner.save_stats() + end) + + describe("dir.is_basic_protocol", function() + it("checks whether the arguments represent a valid protocol and returns the result of the check", function() + assert.truthy(dir.is_basic_protocol("http")) + assert.truthy(dir.is_basic_protocol("https")) + assert.truthy(dir.is_basic_protocol("ftp")) + assert.truthy(dir.is_basic_protocol("file")) + assert.falsy(dir.is_basic_protocol("git")) + assert.falsy(dir.is_basic_protocol("git+https")) + assert.falsy(dir.is_basic_protocol("invalid")) + end) + end) + + describe("dir.deduce_base_dir", function() + it("deduces the base dir from archives", function() + assert.are.same("v0.3", dir.deduce_base_dir("https://example.com/hishamhm/lua-compat-5.2/archive/v0.3.zip")) + assert.are.same("lua-compat-5.2", dir.deduce_base_dir("https://example.com/hishamhm/lua-compat-5.2.zip")) + assert.are.same("lua-compat-5.2", dir.deduce_base_dir("https://example.com/hishamhm/lua-compat-5.2.tar.gz")) + assert.are.same("lua-compat-5.2", dir.deduce_base_dir("https://example.com/hishamhm/lua-compat-5.2.tar.bz2")) + end) + it("returns the basename when not given an archive", function() + assert.are.same("parser.moon", dir.deduce_base_dir("git://example.com/Cirru/parser.moon")) + assert.are.same("v0.3", dir.deduce_base_dir("https://example.com/hishamhm/lua-compat-5.2/archive/v0.3")) + end) + end) + + describe("dir.normalize", function() + it("converts backslashes and removes trailing slashes", function() + assert.are.same(P"/foo/ovo", dir.normalize("\\foo\\ovo\\")) + assert.are.same(P"c:/some/dir", dir.normalize("c:\\..\\some\\foo\\..\\dir")) + assert.are.same("http://example.com/foo/ovo", dir.normalize("http://example.com/foo\\ovo\\")) + end) + it("strips unneeded /../ and /./", function() + assert.are.same(P"/some/dir/file.txt", dir.normalize("/../../../some/./foo/bar/.././../dir/bla/../file.txt")) + assert.are.same(P"/some/dir/file.txt", dir.normalize("/../../../some/./foo/bar/.././../dir/bla/../file.txt")) + assert.are.same(P"/some/dir", dir.normalize("/../../../some/./foo/bar/.././../dir/./some/subdir/../..")) + assert.are.same(P"/some/dir", dir.normalize("/../../../some/./foo/bar/.././../dir/./.")) + end) + it("respects relative paths", function() + assert.are.same(P".", dir.normalize(".")) + assert.are.same(P"boo", dir.normalize("./boo")) + assert.are.same(P"/boo", dir.normalize("/./boo")) + assert.are.same(P"../../../../boo", dir.normalize("../../../hello/world/../../../boo")) + end) + it("respects root directory", function() + assert.are.same(P"/", dir.normalize("/")) + assert.are.same(P"/", dir.normalize("/////")) + assert.are.same(P"/", dir.normalize("/a/b/.././../c/./../../")) + end) + end) + +end) diff --git a/spec/unit/fetch_spec.lua b/spec/unit/fetch_spec.lua new file mode 100644 index 0000000..bea50d7 --- /dev/null +++ b/spec/unit/fetch_spec.lua @@ -0,0 +1,486 @@ +local test_env = require("spec.util.test_env") + +test_env.setup_specs() +local cfg = require("luarocks.core.cfg") +local fetch = require("luarocks.fetch") +local fs = require("luarocks.fs") +local dir = require("luarocks.dir") +local path = require("luarocks.path") +local rockspecs = require("luarocks.rockspecs") +local lfs = require("lfs") +local get_tmp_path = test_env.get_tmp_path +local testing_paths = test_env.testing_paths +local write_file = test_env.write_file +local P = test_env.P + +describe("luarocks fetch #unit", function() + local are_same_files = function(file1, file2) + return file1 == file2 or lfs.attributes(file1).ino == lfs.attributes(file2).ino + end + + local runner + + lazy_setup(function() + cfg.init() + fs.init() + + -- mock network access + fs.download = function(url, destfile) + local mockfile = P(url:gsub("http://localhost:8080/file", testing_paths.fixtures_dir)) + if not destfile then + destfile = dir.base_name(mockfile) + end + destfile = fs.absolute_name(destfile) + + local fdr = io.open(mockfile, "rb") + if not fdr then + return nil, "mock failed opening for reading" + end + + local fdw = io.open(destfile, "wb") + if not fdr then + return nil, "mock failed opening for writing" + end + + local data = fdr:read("*a") + if not data then + return nil, "mock failed reading" + end + + local ok = fdw:write(data) + if not ok then + return nil, "mock failed writing" + end + + fdr:close() + fdw:close() + + return true, destfile + end + + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + end) + + lazy_teardown(function() + runner.save_stats() + end) + + + describe("fetch.fetch_url", function() + + it("fetches the url argument and returns the absolute path of the fetched file", function() + test_env.run_in_tmp(function() + local fetchedfile, err = fetch.fetch_url("http://localhost:8080/file/a_rock.lua") + assert(fetchedfile, err) + assert.truthy(are_same_files(fetchedfile, lfs.currentdir() .. "/a_rock.lua")) + local fd = assert(io.open(fetchedfile, "r")) + local fetchedcontent = assert(fd:read("*a")) + fd:close() + fd = assert(io.open(testing_paths.fixtures_dir .. "/a_rock.lua", "r")) + local filecontent = assert(fd:read("*a")) + fd:close() + assert.same(fetchedcontent, filecontent) + end, finally) + end) + + it("returns the absolute path of the filename argument if the url represents a file", function() + test_env.run_in_tmp(function() + write_file("test.lua", "return {}") + + local file, err = fetch.fetch_url("file://test.lua") + assert.truthy(file, err) + assert.truthy(are_same_files(file, lfs.currentdir() .. "/test.lua")) + fs.pop_dir() + end, finally) + end) + + it("fails if local path is invalid and returns a helpful hint for relative paths", function() + test_env.run_in_tmp(function() + local ok, err = fetch.fetch_url("file://boo.lua") + assert.falsy(ok) + assert.match("note that given path in rockspec is not absolute: file://boo.lua", err) + end, finally) + end) + + it("returns false and does nothing if the url argument contains a nonexistent file", function() + assert.falsy(fetch.fetch_url("http://localhost:8080/file/nonexistent")) + end) + + it("returns false and does nothing if the url argument is invalid", function() + assert.falsy(fetch.fetch_url("invalid://url", "file")) + end) + end) + + describe("fetch.fetch_url_at_temp_dir", function() + + it("returns the absolute path and the parent directory of the file specified by the url", function() + test_env.run_in_tmp(function(tmpdir) + local tmpfile = tmpdir .. "/tmpfile" + assert(io.open(tmpfile, "w")) + local pathname, dirname = fetch.fetch_url_at_temp_dir("file://" .. tmpfile, "test") + assert.truthy(are_same_files(tmpfile, pathname)) + assert.truthy(are_same_files(tmpdir, dirname)) + end, finally) + end) + + it("returns true and fetches the url into a temporary dir", function() + test_env.run_in_tmp(function() + local fetchedfile, tmpdir = fetch.fetch_url_at_temp_dir("http://localhost:8080/file/a_rock.lua", "test") + assert(fetchedfile, tmpdir) + assert.truthy(are_same_files(fetchedfile, tmpdir .. "/a_rock.lua")) + local fd = assert(io.open(fetchedfile, "r")) + local fetchedcontent = assert(fd:read("*a")) + fd:close() + fd = assert(io.open(testing_paths.fixtures_dir .. "/a_rock.lua", "r")) + local filecontent = assert(fd:read("*a")) + fd:close() + assert.same(fetchedcontent, filecontent) + end, finally) + end) + + it("returns true and fetches the url into a temporary dir with custom filename", function() + test_env.run_in_tmp(function() + local fetchedfile, tmpdir = fetch.fetch_url_at_temp_dir("http://localhost:8080/file/a_rock.lua", "test", "my_a_rock.lua") + assert(fetchedfile, tmpdir) + assert.truthy(are_same_files(fetchedfile, tmpdir .. "/my_a_rock.lua")) + assert.truthy(string.find(tmpdir, "test")) + local fd = assert(io.open(fetchedfile, "r")) + local fetchedcontent = assert(fd:read("*a")) + fd:close() + fd = assert(io.open(testing_paths.fixtures_dir .. "/a_rock.lua", "r")) + local filecontent = assert(fd:read("*a")) + fd:close() + assert.same(fetchedcontent, filecontent) + end, finally) + end) + + it("returns false and does nothing if the file specified in the url is nonexistent", function() + assert.falsy(fetch.fetch_url_at_temp_dir("file://nonexistent", "test")) + assert.falsy(fetch.fetch_url_at_temp_dir("http://localhost:8080/file/nonexistent", "test")) + end) + + it("returns false and does nothing if the url is invalid", function() + assert.falsy(fetch.fetch_url_at_temp_dir("url://invalid", "test")) + end) + end) + + describe("fetch.find_base_dir", function() + it("extracts the archive given by the file argument and returns the inferred and the actual root directory in the archive", function() + test_env.run_in_tmp(function() + local url = "http://localhost:8080/file/an_upstream_tarball-0.1.tar.gz" + local file, tmpdir = assert(fetch.fetch_url_at_temp_dir(url, "test")) + local inferreddir, founddir = fetch.find_base_dir(file, tmpdir, url) + assert.truthy(are_same_files(inferreddir, founddir)) + assert.truthy(lfs.attributes(tmpdir .. "/" .. founddir)) + end, finally) + end) + + it("extracts the archive given by the file argument with given base directory and returns the inferred and the actual root directory in the archive", function() + test_env.run_in_tmp(function() + local url = "http://localhost:8080/file/an_upstream_tarball-0.1.tar.gz" + local file, tmpdir = assert(fetch.fetch_url_at_temp_dir(url, "test")) + local inferreddir, founddir = fetch.find_base_dir(file, tmpdir, url, "basedir") + assert.truthy(are_same_files(inferreddir, "basedir")) + assert.truthy(are_same_files(founddir, "an_upstream_tarball-0.1")) + assert.truthy(lfs.attributes(tmpdir .. "/" .. founddir)) + end, finally) + end) + + it("returns false and does nothing if the temporary directory doesn't exist", function() + assert.falsy(fetch.find_base_dir("file", "nonexistent", "url")) + end) + end) + + describe("fetch.fetch_and_unpack_rock", function() + + it("unpacks the rock file from the url and returns its resulting temporary parent directory", function() + test_env.run_in_tmp(function() + local tmpdir = fetch.fetch_and_unpack_rock("http://localhost:8080/file/a_rock-1.0-1.src.rock") + assert.truthy(string.find(tmpdir, "a_rock%-1%.0%-1")) + assert.truthy(lfs.attributes(tmpdir .. "/a_rock-1.0-1.rockspec")) + assert.truthy(lfs.attributes(tmpdir .. "/a_rock.lua")) + end, finally) + end) + + it("unpacks the rock file from the url with custom unpacking directory", function() + test_env.run_in_tmp(function() + local tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + local resultingdir = fetch.fetch_and_unpack_rock("http://localhost:8080/file/a_rock-1.0-1.src.rock", tmpdir) + assert.truthy(are_same_files(resultingdir, tmpdir)) + assert.truthy(lfs.attributes(resultingdir .. "/a_rock-1.0-1.rockspec")) + assert.truthy(lfs.attributes(resultingdir .. "/a_rock.lua")) + end, finally) + end) + + it("does nothing if the url doesn't represent a rock file", function() + assert.falsy(pcall(fetch.fetch_and_unpack_rock, "http://localhost:8080/file/a_rock.lua")) + end) + + it("does nothing if the rock file url is invalid", function() + assert.falsy(pcall(fetch.fetch_and_unpack_rock, "url://invalid")) + end) + + it("does nothing if the rock file url represents a nonexistent file", function() + assert.falsy(pcall(fetch.fetch_and_unpack_rock, "url://invalid")) + assert.falsy(pcall(fetch.fetch_and_unpack_rock, "http://localhost:8080/file/nonexistent")) + end) + end) + + describe("fetch.load_local_rockspec", function() + it("returns a table representing the rockspec from the given file skipping some checks if the quick argument is enabled", function() + test_env.run_in_tmp(function() + local rockspec = fetch.load_local_rockspec(testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec", true) + assert.same(rockspec.name, "a_rock") + assert.same(rockspec.version, "1.0-1") + assert.same(rockspec.source.url, "http://localhost:8080/file/a_rock.lua") + assert.same(rockspec.description, { summary = "An example rockspec" }) + + write_file("missing_mandatory_field-1.0-1.rockspec", [[ + package="missing_mandatory_field" + version="1.0-1" + source = { + url = "http://example.com/foo.tar.gz" + } + ]]) + rockspec = fetch.load_local_rockspec("missing_mandatory_field-1.0-1.rockspec", true) + assert.same(rockspec.name, "missing_mandatory_field") + assert.same(rockspec.version, "1.0-1") + assert.same(rockspec.source.url, "http://example.com/foo.tar.gz") + + write_file("unknown_field-1.0-1.rockspec", [[ + package="unknown_field" + version="1.0-1" + source = { + url = "http://example.com/foo.tar.gz" + } + unknown="foo" + ]]) + rockspec = fetch.load_local_rockspec("unknown_field-1.0-1.rockspec", true) + assert.same(rockspec.name, "unknown_field") + assert.same(rockspec.version, "1.0-1") + assert.same(rockspec.source.url, "http://example.com/foo.tar.gz") + + -- The previous calls fail if the detailed checking is done + path.use_tree(testing_paths.testing_tree) + assert.falsy(fetch.load_local_rockspec("missing_mandatory_field-1.0-1.rockspec")) + assert.falsy(fetch.load_local_rockspec("unknown_field-1.0-1.rockspec")) + end, finally) + end) + + it("returns a table representing the rockspec from the given file", function() + test_env.run_in_tmp(function() + path.use_tree(testing_paths.testing_tree) + local rockspec = fetch.load_local_rockspec(testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec") + assert.same(rockspec.name, "a_rock") + assert.same(rockspec.version, "1.0-1") + assert.same(rockspec.description, { summary = "An example rockspec" }) + assert.same(rockspec.source.url, "http://localhost:8080/file/a_rock.lua") + end, finally) + end) + + it("returns false if the rockspec in invalid", function() + assert.falsy(fetch.load_local_rockspec(testing_paths.fixtures_dir .. "/invalid_say-1.3-1.rockspec")) + end) + + it("returns false if the rockspec version is not supported", function() + assert.falsy(fetch.load_local_rockspec("invalid_version.rockspec")) + end) + + it("returns false if the rockspec doesn't pass the type checking", function() + test_env.run_in_tmp(function() + write_file("type_mismatch_string-1.0-1.rockspec", [[ + package="type_mismatch_version" + version=1.0 + ]]) + assert.falsy(fetch.load_local_rockspec("type_mismatch_string-1.0-1.rockspec")) + end, finally) + end) + + it("returns false if the rockspec file name is not right", function() + test_env.run_in_tmp(function() + write_file("invalid_rockspec_name.rockspec", [[ + package="invalid_rockspec_name" + version="1.0-1" + source = { + url = "http://example.com/foo.tar.gz" + } + build = { + + } + ]]) + assert.falsy(fetch.load_local_rockspec("invalid_rockspec_name.rockspec")) + end, finally) + end) + + it("returns false if the version in the rockspec file name doesn't match the version declared in the rockspec", function() + test_env.run_in_tmp(function() + write_file("inconsistent_versions-1.0-1.rockspec", [[ + package="inconsistent_versions" + version="1.0-2" + source = { + url = "http://example.com/foo.tar.gz" + } + build = { + + } + ]]) + assert.falsy(fetch.load_local_rockspec("inconsistent_versions-1.0-1.rockspec")) + end, finally) + end) + end) + + describe("fetch.load_rockspec", function() + + it("returns a table containing the requested rockspec by downloading it into a temporary directory", function() + test_env.run_in_tmp(function() + path.use_tree(testing_paths.testing_tree) + local rockspec = fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec") + assert.same(rockspec.name, "a_rock") + assert.same(rockspec.version, "1.0-1") + assert.same(rockspec.description, { summary = "An example rockspec" }) + assert.same(rockspec.source.url, "http://localhost:8080/file/a_rock.lua") + rockspec = fetch.load_rockspec(testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec") + assert.same(rockspec.name, "a_rock") + assert.same(rockspec.version, "1.0-1") + assert.same(rockspec.description, { summary = "An example rockspec" }) + assert.same(rockspec.source.url, "http://localhost:8080/file/a_rock.lua") + end, finally) + end) + + it("returns a table containing the requested rockspec by downloading it into a given directory", function() + test_env.run_in_tmp(function() + local tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + + path.use_tree(testing_paths.testing_tree) + local rockspec = fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec", tmpdir) + assert.same(rockspec.name, "a_rock") + assert.same(rockspec.version, "1.0-1") + assert.same(rockspec.description, { summary = "An example rockspec" }) + assert.same(rockspec.source.url, "http://localhost:8080/file/a_rock.lua") + assert.truthy(lfs.attributes(tmpdir .. "/a_rock-1.0-1.rockspec")) + + lfs.rmdir(tmpdir) + end, finally) + end) + + it("returns false if the given download directory doesn't exist", function() + assert.falsy(fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec", "nonexistent")) + end) + + it("returns false if the given filename is not a valid rockspec name", function() + assert.falsy(fetch.load_rockspec("http://localhost:8080/file/a_rock.lua")) + end) + end) + + describe("fetch.get_sources", function() + + it("downloads the sources for building a rock and returns the resulting source filename and its parent directory", function() + test_env.run_in_tmp(function() + local rockspec = assert(fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec")) + local file, dirname = fetch.get_sources(rockspec, false) + assert.truthy(are_same_files(dirname .. "/a_rock.lua", file)) + end, finally) + end) + + it("downloads the sources for building a rock into a given directory and returns the resulting source filename and its parent directory", function() + test_env.run_in_tmp(function() + local tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + local rockspec = assert(fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec")) + local file, dirname = fetch.get_sources(rockspec, false, tmpdir) + assert.truthy(are_same_files(tmpdir, dirname)) + assert.truthy(are_same_files(dirname .. "/a_rock.lua", file)) + lfs.rmdir(tmpdir) + end, finally) + end) + + it("downloads the sources for building a rock, extracts the downloaded tarball and returns the resulting source filename and its parent directory", function() + test_env.run_in_tmp(function() + local rockspec = assert(fetch.load_rockspec("http://localhost:8080/file/busted_project-0.1-1.rockspec")) + local file, dirname = fetch.get_sources(rockspec, true) + assert.truthy(are_same_files(dirname .. "/busted_project-0.1.tar.gz", file)) + assert.truthy(lfs.attributes(dirname .. "/busted_project")) + assert.truthy(lfs.attributes(dirname .. "/busted_project/sum.lua")) + assert.truthy(lfs.attributes(dirname .. "/busted_project/spec/sum_spec.lua")) + end, finally) + end) + + it("returns false and does nothing if the destination directory doesn't exist", function() + test_env.run_in_tmp(function() + local rockspec = assert(fetch.load_rockspec("http://localhost:8080/file/a_rock-1.0-1.rockspec")) + assert.falsy(fetch.get_sources(rockspec, false, "nonexistent")) + end, finally) + end) + + it("returns false and does nothing if the rockspec source url is invalid", function() + test_env.run_in_tmp(function(tmpdir) + write_file(tmpdir .. "/invalid_url-1.0-1.rockspec", [[ + package="invalid_url" + version="1.0-1" + source = { + url = "http://localhost:8080/file/nonexistent" + } + build = { + + } + ]]) + local rockspec = assert(fetch.load_rockspec(tmpdir .. "/invalid_url-1.0-1.rockspec")) + assert.falsy(fetch.get_sources(rockspec, false)) + end, finally) + end) + + it("returns false and does nothing if the downloaded rockspec has an invalid md5 checksum", function() + test_env.run_in_tmp(function() + write_file("invalid_checksum-1.0-1.rockspec", [[ + package="invalid_checksum" + version="1.0-1" + source = { + url = "http://localhost:8080/file/a_rock.lua", + md5 = "invalid" + } + build = { + + } + ]]) + local rockspec = assert(fetch.load_rockspec("invalid_checksum-1.0-1.rockspec")) + assert.falsy(fetch.get_sources(rockspec, false)) + end, finally) + end) + end) + + describe("fetch_sources #unix #git", function() + local git_repo = require("spec.util.git_repo") + + local git + + setup(function() + git = git_repo.start() + end) + + teardown(function() + if git then + git:stop() + end + end) + + it("from #git", function() + local rockspec, err = rockspecs.from_persisted_table("testrock-dev-1.rockspec", { + rockspec_format = "3.0", + package = "testrock", + version = "dev-1", + source = { + url = "git://localhost/testrock", + }, + }, nil) + assert.falsy(err) + local pathname, tmpdir = fetch.fetch_sources(rockspec, false) + assert.are.same("testrock", pathname) + assert.match("luarocks_testrock%-dev%-1%-", tmpdir) + assert.match("^%d%d%d%d%d%d%d%d.%d%d%d%d%d%d.%x+$", tostring(rockspec.source.identifier)) + end) + end) + +end) diff --git a/spec/unit/fs_spec.lua b/spec/unit/fs_spec.lua new file mode 100644 index 0000000..c2a842b --- /dev/null +++ b/spec/unit/fs_spec.lua @@ -0,0 +1,1595 @@ +local test_env = require("spec.util.test_env") + +test_env.setup_specs() +local fs = require("luarocks.fs") +local path = require("luarocks.path") +local cfg = require("luarocks.core.cfg") +local lfs = require("lfs") +local is_win = test_env.TEST_TARGET_OS == "windows" +local posix_ok = pcall(require, "posix") +local testing_paths = test_env.testing_paths +local get_tmp_path = test_env.get_tmp_path +local write_file = test_env.write_file +local P = test_env.P + +-- A chdir that works in both full and minimal mode, setting +-- both the real process current dir and the LuaRocks internal stack in minimal mode +local function chdir(d) + lfs.chdir(d) + fs.change_dir(d) +end + +describe("luarocks.fs #unit", function() + local exists_file = function(path) + local ok, err, code = os.rename(path, path) + if not ok and code == 13 then + return true + end + return ok + end + + local create_file = function(path, content) + local fd = assert(io.open(path, "w")) + if not content then + content = "foo" + end + assert(fd:write(content)) + fd:close() + end + + local make_unreadable = function(path) + if is_win then + fs.execute("icacls " .. fs.Q(path) .. " /inheritance:d /deny \"%USERNAME%\":(R)") + else + fs.execute("chmod -r " .. fs.Q(path)) + end + end + + local make_unwritable = function(path) + if is_win then + fs.execute("icacls " .. fs.Q(path) .. " /inheritance:d /deny \"%USERNAME%\":(W,M)") + else + fs.execute("chmod -w " .. fs.Q(path)) + end + end + + local make_unexecutable = function(path) + if is_win then + fs.execute("icacls " .. fs.Q(path) .. " /inheritance:d /deny \"%USERNAME%\":(X)") + else + fs.execute("chmod -x " .. fs.Q(path)) + end + end + + local runner + + lazy_setup(function() + cfg.init() + fs.init() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + end) + + lazy_teardown(function() + runner.save_stats() + end) + + describe("fs.Q", function() + it("simple argument", function() + assert.are.same(is_win and '"foo"' or "'foo'", fs.Q("foo")) + end) + + it("argument with quotes", function() + assert.are.same(is_win and [["it's \"quoting\""]] or [['it'\''s "quoting"']], fs.Q([[it's "quoting"]])) + end) + + it("argument with special characters", function() + assert.are.same(is_win and [["\\"%" \\\\" \\\\\\"]] or [['\% \\" \\\']], fs.Q([[\% \\" \\\]])) + end) + end) + + describe("fs.absolute_name", function() + it("unchanged if already absolute", function() + if is_win then + assert.are.same(P"c:\\foo\\bar", fs.absolute_name("\"c:\\foo\\bar\"")) + assert.are.same(P"c:\\foo\\bar", fs.absolute_name("c:\\foo\\bar")) + assert.are.same(P"d:\\foo\\bar", fs.absolute_name("d:\\foo\\bar")) + assert.are.same(P"\\foo\\bar", fs.absolute_name("\\foo\\bar")) + else + assert.are.same(P"/foo/bar", fs.absolute_name("/foo/bar")) + end + end) + + it("converts to absolute if relative", function() + local cur = fs.current_dir() + if is_win then + assert.are.same(P(cur .. "/foo\\bar"), fs.absolute_name("\"foo\\bar\"")) + assert.are.same(P(cur .. "/foo\\bar"), fs.absolute_name("foo\\bar")) + else + assert.are.same(P(cur .. "/foo/bar"), fs.absolute_name("foo/bar")) + end + end) + + it("converts a relative to specified base if given", function() + if is_win then + assert.are.same(P"c:\\bla/foo\\bar", fs.absolute_name("\"foo\\bar\"", "c:\\bla")) + assert.are.same(P"c:\\bla/foo\\bar", fs.absolute_name("foo/bar", "c:\\bla")) + assert.are.same(P"c:\\bla/foo\\bar", fs.absolute_name("foo\\bar", "c:\\bla\\")) + else + assert.are.same(P"/bla/foo/bar", fs.absolute_name("foo/bar", "/bla")) + assert.are.same(P"/bla/foo/bar", fs.absolute_name("foo/bar", "/bla/")) + end + end) + end) + + describe("fs.execute_string", function() + local tmpdir + + after_each(function() + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns the status code and runs the command given in the argument", function() + tmpdir = get_tmp_path() + assert.truthy(fs.execute_string("mkdir " .. fs.Q(tmpdir))) + assert.truthy(fs.is_dir(tmpdir)) + assert.falsy(fs.execute_string("invalidcommand")) + end) + end) + + describe("fs.dir_iterator", function() + local tmpfile1 + local tmpfile2 + local tmpdir + local intdir + + after_each(function() + if tmpfile1 then + os.remove(tmpfile1) + tmpfile1 = nil + end + if tmpfile2 then + os.remove(tmpfile2) + tmpfile2 = nil + end + if intdir then + lfs.rmdir(intdir) + intdir = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("yields all files and directories in the directory given as argument during the iterations", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + tmpfile1 = tmpdir .. "/file1" + create_file(tmpfile1) + tmpfile2 = tmpdir .. "/file2" + create_file(tmpfile2) + intdir = tmpdir .. "/intdir" + lfs.mkdir(intdir) + local dirTable = {} + local dirCount = 0 + local crt = coroutine.create(fs.dir_iterator) + while coroutine.status(crt) ~= "dead" do + local ok, val = coroutine.resume(crt, tmpdir) + if ok and val ~= nil then + dirTable[val] = true + dirCount = dirCount + 1 + end + end + assert.same(dirCount, 3) + assert.is_not.same(dirTable["file1"], nil) + assert.is_not.same(dirTable["file2"], nil) + assert.is_not.same(dirTable["intdir"], nil) + dirCount = 0 + crt = coroutine.create(fs.dir_iterator) + while coroutine.status(crt) ~= "dead" do + local ok, val = coroutine.resume(crt, intdir) + if ok and val ~= nil then + dirCount = dirCount + 1 + end + end + assert.same(dirCount, 0) + end) + + it("does nothing if the argument is a file", function() + tmpfile1 = get_tmp_path() + create_file(tmpfile1) + local crt = coroutine.create(fs.dir_iterator) + while coroutine.status(crt) ~= "dead" do + local ok, val = coroutine.resume(crt, tmpfile1) + assert.falsy(ok and res) + end + end) + + it("does nothing if the argument is invalid", function() + local crt = coroutine.create(fs.dir_iterator) + while coroutine.status(crt) ~= "dead" do + local ok, val = coroutine.resume(crt, "/nonexistent") + assert.falsy(ok and res) + end + end) + end) + + describe("fs.is_writable", function() + local tmpfile + local tmpdir + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns true if the file given as argument is writable", function() + tmpfile = get_tmp_path() + create_file(tmpfile) + assert.truthy(fs.is_writable(tmpfile)) + end) + + it("returns true if the directory given as argument is writable", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + assert.truthy(fs.is_writable(tmpdir)) + tmpfile = tmpdir .. "/internalfile" + create_file(tmpfile) + make_unwritable(tmpfile) + assert.truthy(fs.is_writable(tmpdir)) + end) + + it("returns false if the file given as argument is not writable", function() + tmpfile = get_tmp_path() + create_file(tmpfile) + make_unwritable(tmpfile) + assert.falsy(fs.is_writable(tmpfile)) + end) + + it("returns false if the directory given as argument is not writable", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + make_unwritable(tmpdir) + assert.falsy(fs.is_writable(tmpdir)) + end) + + it("returns false if the file or directory given as argument does not exist", function() + assert.falsy(fs.is_writable("/nonexistent")) + end) + end) + + describe("fs.set_time #unix", function() + local tmpfile + local tmpdir + local intdir + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + if intdir then + os.remove(intdir) + intdir = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns true and modifies the access time of the file given as argument", function() + tmpfile = get_tmp_path() + create_file(tmpfile) + local newtime = os.time() - 100 + assert.truthy(fs.set_time(tmpfile, newtime)) + assert.same(lfs.attributes(tmpfile, "access"), newtime) + assert.same(lfs.attributes(tmpfile, "modification"), newtime) + end) + + it("returns true and modifies the access time of the directory given as argument", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + tmpfile = tmpdir .. "/internalfile" + create_file(tmpfile) + local newtime = os.time() - 100 + assert.truthy(fs.set_time(tmpdir, newtime)) + assert.same(lfs.attributes(tmpdir, "access"), newtime) + assert.same(lfs.attributes(tmpdir, "modification"), newtime) + assert.is_not.same(lfs.attributes(tmpfile, "access"), newtime) + assert.is_not.same(lfs.attributes(tmpfile, "modification"), newtime) + end) + + it("returns false and does nothing if the file or directory given as arguments doesn't exist", function() + assert.falsy(fs.set_time("/nonexistent")) + end) + end) + + describe("fs.set_permissions", function() + local readfile + local execfile + local tmpdir + + after_each(function() + if readfile then + os.remove(readfile) + readfile = nil + end + if execfile then + os.remove(execfile) + execfile = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns true and sets the permissions of the argument accordingly", function() + readfile = get_tmp_path() + create_file(readfile) + make_unreadable(readfile) + assert.falsy(io.open(readfile, "r")) + assert.truthy(fs.set_permissions(readfile, "read", "user")) + assert.truthy(io.open(readfile, "r")) + + if is_win then + execfile = get_tmp_path() .. ".exe" + create_file(execfile) + else + execfile = get_tmp_path() .. ".sh" + create_file(execfile, "#!/bin/bash") + end + make_unexecutable(execfile) + local fd = assert(io.popen(execfile .. " 2>&1")) + local result = assert(fd:read("*a")) + assert.truthy(result:match("denied")) + fd:close() + assert.truthy(fs.set_permissions(execfile, "exec", "user")) + fd = assert(io.popen(execfile .. " 2>&1")) + result = assert(fd:read("*a")) + assert.falsy(result:match("denied")) + fd:close() + + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + make_unexecutable(tmpdir) + fd = assert(io.popen("cd " .. fs.Q(tmpdir) .. " 2>&1")) + result = assert(fd:read("*a")) + assert.truthy(result:match("denied") or result:match("can't cd")) + fd:close() + assert.truthy(fs.set_permissions(tmpdir, "exec", "user")) + fd = assert(io.popen("cd " .. fs.Q(tmpdir) .. " 2>&1")) + result = assert(fd:read("*a")) + assert.falsy(result:match("denied") or result:match("can't cd")) + fd:close() + end) + + it("returns false and does nothing if the argument is nonexistent", function() + assert.falsy(fs.set_permissions("/nonexistent", "read", "user")) + end) + end) + + describe("fs.is_file", function() + local tmpfile + local tmpdir + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns true when the argument is a file", function() + tmpfile = get_tmp_path() + create_file(tmpfile) + assert.same(true, fs.is_file(tmpfile)) + end) + + it("returns false when the argument does not exist", function() + assert.same(false, fs.is_file("/nonexistent")) + end) + + it("returns false when the argument exists but is not a file", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + assert.same(false, fs.is_file("/nonexistent")) + end) + + it("#unix returns false when the argument is a symlink to a directory", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + local linkname = tmpdir .. "/symlink" + finally(function() os.remove(linkname) end) + lfs.link(tmpdir, linkname, true) + assert.falsy(fs.is_file(linkname)) + end) + + it("#unix returns true when the argument is a symlink to a file", function() + tmpfile = get_tmp_path() + create_file(tmpfile) + local linkname = tmpfile .. "_symlink" + finally(function() os.remove(linkname) end) + lfs.link(tmpfile, linkname, true) + assert.truthy(fs.is_file(linkname)) + end) + end) + + describe("fs.is_dir", function() + local tmpfile + local tmpdir + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns true when the argument is a directory", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + assert.truthy(fs.is_dir(tmpdir)) + end) + + it("returns false when the argument is a file", function() + tmpfile = get_tmp_path() + create_file(tmpfile) + assert.falsy(fs.is_dir(tmpfile)) + end) + + it("#unix returns true when the argument is a symlink to a directory", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + local linkname = tmpdir .. "/symlink" + finally(function() os.remove(linkname) end) + lfs.link(tmpdir, linkname, true) + assert.truthy(fs.is_dir(linkname)) + end) + + it("#unix returns false when the argument is a symlink to a file", function() + tmpfile = get_tmp_path() + create_file(tmpfile) + local linkname = tmpfile .. "_symlink" + finally(function() os.remove(linkname) end) + lfs.link(tmpfile, linkname, true) + assert.falsy(fs.is_dir(linkname)) + end) + + it("returns false when the argument does not exist", function() + assert.falsy(fs.is_dir("/nonexistent")) + end) + end) + + describe("fs.exists", function() + local tmpfile + local tmpdir + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns true when the argument is a file", function() + tmpfile = get_tmp_path() + create_file(tmpfile) + assert.truthy(fs.exists(tmpfile)) + end) + + it("returns true when the argument is a directory", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + assert.truthy(fs.exists(tmpdir)) + end) + + it("returns false when the argument does not exist", function() + assert.falsy(fs.exists("/nonexistent")) + end) + end) + + describe("fs.current_dir", function() + local tmpdir + local olddir + + before_each(function() + olddir = lfs.currentdir() + end) + + after_each(function() + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + if olddir then + chdir(olddir) + olddir = nil + end + end) + + it("returns the current working directory", function() + local currentdir = lfs.currentdir() + assert.same(currentdir, fs.current_dir()) + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + assert.truthy(fs.change_dir(tmpdir)) + if is_win then + assert.same(tmpdir, fs.current_dir()) + else + assert.same(lfs.attributes(tmpdir).ino, lfs.attributes((fs.current_dir())).ino) + end + end) + end) + + describe("fs.change_dir", function() + local tmpfile + local tmpdir + local olddir + + before_each(function() + olddir = lfs.currentdir() + end) + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + if olddir then + chdir(olddir) + olddir = nil + end + end) + + it("returns true and changes the current working directory if the argument is a directory", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + assert.truthy(fs.change_dir(tmpdir)) + if is_win then + assert.same(tmpdir, fs.current_dir()) + else + assert.same(lfs.attributes(tmpdir).ino, lfs.attributes(fs.current_dir()).ino) + end + end) + + it("returns false and does nothing when the argument is a file", function() + tmpfile = get_tmp_path() + create_file(tmpfile) + assert.falsy(fs.change_dir(tmpfile)) + assert.same(olddir, lfs.currentdir()) + end) + + it("returns false and does nothing when the argument does not exist", function() + assert.falsy(fs.change_dir("/nonexistent")) + assert.same(olddir, lfs.currentdir()) + end) + end) + + describe("fs.change_dir_to_root", function() + local tmpdir + local olddir + + before_each(function() + olddir = lfs.currentdir() + end) + + after_each(function() + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + if olddir then + chdir(olddir) + end + end) + + it("returns true and changes the current directory to root if the current directory is valid", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + assert.truthy(fs.change_dir(tmpdir)) + assert.truthy(fs.change_dir_to_root()) + if is_win then + local curr_dir = fs.current_dir() + assert.truthy(curr_dir == "C:\\" or curr_dir == P"/") + else + assert.same(P"/", fs.current_dir()) + end + end) + + it("returns false and does nothing if the current directory is not valid #unix", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + chdir(tmpdir) + lfs.rmdir(tmpdir) + assert.falsy(fs.change_dir_to_root()) + assert.is_not.same("/", lfs.currentdir()) + end) + end) + + describe("fs.pop_dir", function() + local tmpdir + local olddir + + before_each(function() + olddir = lfs.currentdir() + end) + + after_each(function() + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + if olddir then + chdir(olddir) + end + end) + + it("returns true and changes the current directory to the previous one in the dir stack if the dir stack is not empty", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + assert.truthy(fs.change_dir(tmpdir)) + assert.truthy(fs.pop_dir()) + assert.same(olddir, lfs.currentdir()) + end) + end) + + describe("fs.make_dir", function() + local tmpfile + local tmpdir + local intdir + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + if intdir then + lfs.rmdir(intdir) + intdir = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns true and creates the directory specified by the argument", function() + tmpdir = get_tmp_path() + assert.truthy(fs.make_dir(tmpdir)) + assert.same("directory", lfs.attributes(tmpdir, "mode")) + end) + + it("returns true and creates the directory path specified by the argument", function() + tmpdir = get_tmp_path() + intdir = "/internaldir" + local dirpath = tmpdir .. intdir + assert.truthy(fs.make_dir(dirpath)) + assert.same("directory", lfs.attributes(tmpdir, "mode")) + assert.same("directory", lfs.attributes(dirpath, "mode")) + end) + + it("returns false and does nothing if the argument is not valid (file in the path)", function() + tmpfile = get_tmp_path() + local fd = assert(io.open(tmpfile, "w")) + assert(fd:write("foo")) + fd:close() + intdir = "/internaldir" + local dirpath = tmpfile .. intdir + assert.falsy(fs.make_dir(dirpath)) + end) + + it("returns false and does nothing if the argument already exists", function() + tmpfile = get_tmp_path() + create_file(tmpfile) + assert.falsy(fs.make_dir(tmpfile)) + end) + end) + + describe("fs.remove_dir_if_empty", function() + local tmpfile + local tmpdir + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("removes the directory specified by the argument if it is empty", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + fs.remove_dir_if_empty(tmpdir) + assert.falsy(exists_file(tmpdir)) + end) + + it("does nothing if the directory specified by the argument is not empty", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + tmpfile = "/internalfile" + local filepath = tmpdir .. tmpfile + create_file(filepath) + fs.remove_dir_if_empty(tmpdir) + assert.truthy(exists_file(tmpdir)) + end) + end) + + describe("fs.remove_dir_tree_if_empty", function() + local tmpfile + local tmpdir + local intdir + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + if intdir then + lfs.rmdir(intdir) + intdir = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("removes the directory path specified by the argument if it is empty", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + fs.remove_dir_tree_if_empty(tmpdir) + assert.falsy(exists_file(tmpdir)) + end) + + it("does nothing if the directory path specified by the argument is not empty", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + intdir = "/internaldir" + local dirpath = tmpdir .. intdir + lfs.mkdir(dirpath) + tmpfile = "/internalfile" + local filepath = dirpath .. tmpfile + fs.remove_dir_tree_if_empty(tmpdir) + assert.truthy(exists_file(dirpath)) + assert.truthy(exists_file(tmpdir)) + end) + end) + + describe("fs.list_dir", function() + local intfile1 + local intfile2 + local intdir + local tmpdir + + before_each(function() + if intfile1 then + os.remove(intfile1) + intfile1 = nil + end + if intfile2 then + os.remove(intfile2) + intfile2 = nil + end + if intdir then + lfs.rmdir(intdir) + intdir = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns a table with the contents of the given directory", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + intfile1 = tmpdir .. "/intfile1" + create_file(intfile1) + intdir = tmpdir .. "/intdir" + lfs.mkdir(intdir) + intfile2 = intdir .. "/intfile2" + create_file(intfile2) + local result = fs.list_dir(tmpdir) + assert.same(#result, 2) + assert.truthy(result[1] == "intfile1" or result[1] == "intdir") + assert.truthy(result[2] == "intfile1" or result[2] == "intdir") + assert.is_not.same(result[1], result[2]) + end) + + it("returns an empty table if the argument is a file", function() + intfile1 = get_tmp_path() + create_file(intfile1) + local result = fs.list_dir(intfile1) + assert.same(#result, 0) + end) + + it("does nothing if the argument is nonexistent", function() + assert.same(fs.list_dir("/nonexistent"), {}) + end) + + it("does nothing if the argument doesn't have the proper permissions", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + make_unreadable(tmpdir) + assert.same(fs.list_dir(tmpdir), {}) + end) + end) + + describe("fs.copy", function() + local srcfile + local dstfile + local tmpdir + + after_each(function() + if srcfile then + os.remove(srcfile) + srcfile = nil + end + if dstfile then + os.remove(dstfile) + dstfile = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns true and copies the contents and the permissions of the source file to the destination file", function() + srcfile = get_tmp_path() + create_file(srcfile, srccontent) + dstfile = get_tmp_path() + assert.truthy(fs.copy(srcfile, dstfile)) + local fd = assert(io.open(dstfile, "r")) + local dstcontent = fd:read("*a") + assert.same("foo", dstcontent) + if posix_ok then + assert.same(lfs.attributes(srcfile, "permissions"), lfs.attributes(dstfile, "permissions")) + end + end) + + it("returns true and copies contents of the source file to the destination file with custom permissions", function() + srcfile = get_tmp_path() + create_file(srcfile, srccontent) + dstfile = get_tmp_path() + assert.truthy(fs.copy(srcfile, dstfile, "exec")) + local fd = assert(io.open(dstfile, "r")) + local dstcontent = fd:read("*a") + assert.same("foo", dstcontent) + end) + + it("returns false and does nothing if the source file does not exist", function() + srcfile = get_tmp_path() + dstfile = get_tmp_path() + local ok, err = fs.copy(srcfile, dstfile, nil) + assert.falsy(ok) + assert.not_match("are the same file", err) + assert.falsy(exists_file(dstfile)) + end) + + it("returns false and does nothing if the source file doesn't have the proper permissions", function() + srcfile = get_tmp_path() + create_file(srcfile) + make_unreadable(srcfile) + dstfile = get_tmp_path() + assert.falsy(fs.copy(srcfile, dstfile, nil)) + assert.falsy(exists_file(dstfile)) + end) + + it("returns false and does nothing if the destination file directory doesn't have the proper permissions", function() + srcfile = get_tmp_path() + create_file(srcfile) + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + make_unwritable(tmpdir) + dstfile = tmpdir .. "/dstfile" + assert.falsy(fs.copy(srcfile, dstfile, nil)) + assert(fs.set_permissions(tmpdir, "exec", "all")) + assert.falsy(exists_file(dstfile)) + end) + end) + + describe("fs.copy_contents", function() + local srcfile + local dstfile + local srcintdir + local dstintdir + local srcdir + local dstdir + + after_each(function() + if srcfile then + os.remove(srcfile) + srcfile = nil + end + if dstfile then + os.remove(dstfile) + dstfile = nil + end + if srcintdir then + lfs.rmdir(srcintdir) + srcintdir = nil + end + if dstintdir then + lfs.rmdir(dstintdir) + dstintdir = nil + end + if srcdir then + lfs.rmdir(srcdir) + srcdir = nil + end + if dstdir then + lfs.rmdir(dstdir) + dstdir = nil + end + end) + + local create_dir_tree = function() + srcdir = get_tmp_path() + lfs.mkdir(srcdir) + srcintdir = srcdir .. "/internaldir" + lfs.mkdir(srcintdir) + srcfile = srcintdir .. "/internalfile" + create_file(srcfile) + dstdir = get_tmp_path() + end + + it("returns true and copies the contents (with their permissions) of the source dir to the destination dir", function() + create_dir_tree() + assert.truthy(fs.copy_contents(srcdir, dstdir)) + assert.truthy(exists_file(dstdir)) + dstintdir = dstdir .. "/internaldir" + assert.truthy(exists_file(dstintdir)) + dstfile = dstdir .. "/internaldir/internalfile" + local fd = assert(io.open(dstfile, "r")) + local dstfilecontent = fd:read("*a") + assert.same("foo", dstfilecontent) + if posix_ok then + assert.same(lfs.attributes(srcfile, "permissions"), lfs.attributes(dstfile, "permissions")) + end + end) + + it("returns true and copies the contents of the source dir to the destination dir with custom permissions", function() + create_dir_tree() + assert.truthy(fs.copy_contents(srcdir, dstdir, "read")) + assert.truthy(exists_file(dstdir)) + dstintdir = dstdir .. "/internaldir" + assert.truthy(exists_file(dstintdir)) + dstfile = dstdir .. "/internaldir/internalfile" + local fd = assert(io.open(dstfile, "r")) + local dstfilecontent = fd:read("*a") + assert.same("foo", dstfilecontent) + end) + + it("returns false and does nothing if the source dir doesn't exist", function() + srcdir = get_tmp_path() + dstdir = get_tmp_path() + assert.falsy(fs.copy_contents(srcdir, dstdir)) + assert.falsy(exists_file(dstdir)) + end) + + it("returns false if the source argument is a file", function() + srcdir = get_tmp_path() + create_file(srcdir) + dstdir = get_tmp_path() + assert.falsy(fs.copy_contents(srcdir, dstdir)) + assert.falsy(exists_file(dstdir)) + end) + + it("returns false and does nothing if the source dir doesn't have the proper permissions", function() + create_dir_tree() + make_unreadable(srcdir) + assert.falsy(fs.copy_contents(srcdir, dstdir)) + assert.falsy(exists_file(dstdir .. "/internaldir")) + assert.falsy(exists_file(dstdir .. "/internalfile")) + end) + end) + + describe("fs.find", function() + local tmpdir + local intdir + local intfile1 + local intfile2 + + after_each(function() + if intfile1 then + os.remove(intfile1) + intfile1 = nil + end + if intfile2 then + os.remove(intfile2) + intfile2 = nil + end + if intdir then + lfs.rmdir(intdir) + intdir = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + local create_dir_tree = function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + intfile1 = tmpdir .. "/intfile1" + create_file(intfile1) + intdir = tmpdir .. "/intdir" + lfs.mkdir(intdir) + intfile2 = intdir .. "/intfile2" + create_file(intfile2) + end + + it("returns a table of all the contents in the directory given as argument", function() + create_dir_tree() + local contents = {} + local count = 0 + for _, file in pairs(fs.find(tmpdir)) do + contents[file] = true + count = count + 1 + end + assert.same(count, 3) + assert.is_not.same(contents[tmpdir], true) + assert.same(contents[P"intfile1"], true) + assert.same(contents[P"intdir"], true) + assert.same(contents[P"intdir/intfile2"], true) + end) + + it("uses the current working directory if the argument is nil", function() + create_dir_tree() + local olddir = fs.current_dir() + fs.change_dir(intdir) + local contents = {} + local count = 0 + for _, file in pairs(fs.find()) do + contents[file] = true + count = count + 1 + end + assert.same(count, 1) + assert.is_not.same(contents["intfile1"], true) + assert.is_not.same(contents["intdir"], true) + assert.same(contents["intfile2"], true) + fs.change_dir(olddir) + end) + + it("returns an empty table if the argument is nonexistent", function() + local contents = fs.find("/nonexistent") + local count = 0 + for _, file in pairs(contents) do + count = count + 1 + end + assert.same(count, 0) + end) + + it("returns an empty table if the argument is a file", function() + intfile1 = get_tmp_path() + create_file(intfile1) + local contents = fs.find(intfile1) + local count = 0 + for _, file in pairs(contents) do + count = count + 1 + end + assert.same(count, 0) + end) + + it("does nothing if the argument doesn't have the proper permissions", function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + make_unreadable(tmpdir) + assert.same(fs.find(tmpdir), {}) + end) + end) + + describe("fs.move", function() + local srcfile + local dstfile + local tmpdir + + after_each(function() + if srcfile then + os.remove(srcfile) + srcfile = nil + end + if dstfile then + os.remove(dstfile) + dstfile = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + it("returns true and moves the source (together with its permissions) to the destination", function() + srcfile = get_tmp_path() + create_file(srcfile) + dstfile = get_tmp_path() + local oldperms = lfs.attributes(srcfile, "permissions") + assert.truthy(fs.move(srcfile, dstfile)) + assert.truthy(fs.exists(dstfile)) + assert.falsy(fs.exists(srcfile)) + local fd = assert(io.open(dstfile, "r")) + local dstcontents = assert(fd:read("*a")) + assert.same(dstcontents, "foo") + if posix_ok then + assert.same(oldperms, lfs.attributes(dstfile, "permissions")) + end + end) + + it("returns true and moves the source (with custom permissions) to the destination", function() + srcfile = get_tmp_path() + create_file(srcfile) + dstfile = get_tmp_path() + assert.truthy(fs.move(srcfile, dstfile, "read")) + assert.truthy(fs.exists(dstfile)) + assert.falsy(fs.exists(srcfile)) + local fd = assert(io.open(dstfile, "r")) + local dstcontents = assert(fd:read("*a")) + assert.same(dstcontents, "foo") + end) + + it("returns false and does nothing if the source doesn't exist", function() + dstfile = get_tmp_path() + assert.falsy(fs.move("/nonexistent", dstfile)) + assert.falsy(fs.exists(dstfile)) + end) + + it("returns false and does nothing if the destination already exists", function() + srcfile = get_tmp_path() + create_file(srcfile) + dstfile = get_tmp_path() + create_file(dstfile, "bar") + assert.falsy(fs.move(srcfile, dstfile)) + assert.truthy(fs.exists(srcfile)) + local fd = assert(io.open(dstfile, "r")) + local dstcontents = assert(fd:read("*a")) + assert.same(dstcontents, "bar") + end) + + it("returns false and does nothing if the destination path doesn't have the proper permissions", function() + srcfile = get_tmp_path() + create_file(srcfile) + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + make_unwritable(tmpdir) + assert.falsy(fs.move(srcfile, tmpdir .. "/dstfile")) + assert.falsy(fs.exists(tmpdir .. "/dstfile")) + end) + end) + + describe("fs.is_lua", function() + local tmpfile + + after_each(function() + if tmpfile then + os.remove(tmpfile) + tmpfile = nil + end + end) + + it("returns true if the argument is a valid lua script", function() + tmpfile = get_tmp_path() + create_file(tmpfile, "print(\"foo\")") + assert.truthy(fs.is_lua(tmpfile)) + end) + + it("returns true if the argument is a valid lua script with shebang", function() + tmpfile = get_tmp_path() + create_file(tmpfile, "#!/usr/bin/env lua\n\nprint(\"foo\")") + assert.truthy(fs.is_lua(tmpfile)) + end) + + it("returns false if the argument is not a valid lua script", function() + tmpfile = os.tmpname() + create_file(tmpfile) + assert.falsy(fs.is_lua(tmpfile)) + end) + + it("returns false if the argument is a valid lua script but doesn't have the proper permissions", function() + tmpfile = get_tmp_path() + create_file(tmpfile, "print(\"foo\")") + make_unreadable(tmpfile) + assert.falsy(fs.is_lua(tmpfile)) + end) + end) + + describe("fs.delete", function() + local tmpfile1 + local tmpfile2 + local tmpintdir + local tmpdir + + after_each(function() + if tmpfile1 then + os.remove(tmpfile1) + tmpfile1 = nil + end + if tmpfile2 then + os.remove(tmpfile2) + tmpfile2 = nil + end + if tmpintdir then + lfs.rmdir(tmpintdir) + tmpintdir = nil + end + if tmpdir then + lfs.rmdir(tmpdir) + tmpdir = nil + end + end) + + local create_dir_tree = function() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + tmpintdir = tmpdir .. "/internaldir" + lfs.mkdir(tmpintdir) + tmpfile1 = tmpdir .. "/internalfile1" + create_file(tmpfile1) + tmpfile2 = tmpdir .. "/internalfile2" + create_file(tmpfile2) + end + + it("deletes the file specified by the argument", function() + tmpfile1 = get_tmp_path() + tmpfile2 = get_tmp_path() + fs.delete(tmpfile1) + fs.delete(tmpfile2) + assert.falsy(exists_file(tmpfile1)) + assert.falsy(exists_file(tmpfile2)) + end) + + it("deletes the contents of the directory specified by the argument", function() + create_dir_tree() + fs.delete(tmpdir) + assert.falsy(exists_file(tmpfile2)) + assert.falsy(exists_file(tmpintdir)) + assert.falsy(exists_file(tmpfile1)) + assert.falsy(exists_file(tmpdir)) + end) + end) + + describe("fs.zip", function() + local tmpdir + local olddir + + before_each(function() + olddir = lfs.currentdir() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + chdir(tmpdir) + + write_file("file1", "content1", finally) + write_file("file2", "content2", finally) + lfs.mkdir("dir") + write_file("dir/file3", "content3", finally) + end) + + after_each(function() + if olddir then + chdir(olddir) + if tmpdir then + lfs.rmdir(tmpdir .. "/dir") + lfs.rmdir(tmpdir) + end + end + end) + + it("returns true and creates a zip archive of the given files", function() + assert.truthy(fs.zip("archive.zip", "file1", "file2", "dir")) + assert.truthy(exists_file("archive.zip")) + end) + + it("returns false and does nothing if the files specified in the arguments are invalid", function() + assert.falsy(fs.zip("archive.zip", "nonexistent")) + assert.falsy(exists_file("nonexistent")) + end) + end) + + describe("fs.bunzip2", function() + + it("uncompresses a .bz2 file", function() + local input = testing_paths.fixtures_dir .. "/abc.bz2" + local output = os.tmpname() + assert.truthy(fs.bunzip2(input, output)) + local fd = io.open(output, "r") + local content = fd:read("*a") + fd:close() + assert.same(300000, #content) + local abc = ("a"):rep(100000)..("b"):rep(100000)..("c"):rep(100000) + assert.same(abc, content) + end) + + end) + + describe("fs.unzip", function() + local tmpdir + local olddir + + before_each(function() + olddir = lfs.currentdir() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + chdir(tmpdir) + + write_file("file1", "content1", finally) + write_file("file2", "content2", finally) + lfs.mkdir("dir") + write_file("dir/file3", "content3", finally) + end) + + after_each(function() + if olddir then + chdir(olddir) + if tmpdir then + lfs.rmdir(tmpdir .. "/dir") + lfs.rmdir(tmpdir) + end + end + end) + + it("returns true and unzips the given zip archive", function() + assert.truthy(fs.zip("archive.zip", "file1", "file2", "dir")) + os.remove("file1") + os.remove("file2") + lfs.rmdir("dir") + + assert.truthy(fs.unzip("archive.zip")) + assert.truthy(exists_file("file1")) + assert.truthy(exists_file("file2")) + assert.truthy(exists_file("dir/file3")) + + local fd + + fd = assert(io.open("file1", "r")) + assert.same(fd:read("*a"), "content1") + fd:close() + + fd = assert(io.open("file2", "r")) + assert.same(fd:read("*a"), "content2") + fd:close() + + fd = assert(io.open("dir/file3", "r")) + assert.same(fd:read("*a"), "content3") + fd:close() + end) + + it("does nothing if the given archive is invalid", function() + assert.falsy(fs.unzip("archive.zip")) + end) + end) + + describe("fs.wrap_script", function() + local tmpdir + local olddir + + before_each(function() + olddir = lfs.currentdir() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + chdir(tmpdir) + end) + + after_each(function() + if olddir then + chdir(olddir) + if tmpdir then + lfs.rmdir(tmpdir) + end + end + end) + + it("produces a wrapper for a Lua script", function() + write_file("my_script", "io.write('Hello ' .. arg[1])", finally) + path.use_tree(testing_paths.testing_tree) + local wrapper_name = fs.absolute_name("wrapper") .. test_env.wrapper_extension + fs.wrap_script("my_script", wrapper_name, "one", nil, nil, "World") + local pd = assert(io.popen(wrapper_name)) + local data = pd:read("*a") + pd:close() + assert.same("Hello World", data) + end) + end) + + describe("fs.copy_binary", function() + local tmpdir + local olddir + + before_each(function() + olddir = lfs.currentdir() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + chdir(tmpdir) + + write_file("test.exe", "", finally) + end) + + after_each(function() + if olddir then + chdir(olddir) + if tmpdir then + lfs.rmdir(tmpdir) + end + end + end) + + it("returns true and copies the given binary file to the file specified in the dest argument", function() + assert.truthy(fs.copy_binary("test.exe", lfs.currentdir() .. "/copy.exe")) + assert.truthy(exists_file("copy.exe")) + if is_win then + assert.truthy(exists_file("test.lua")) + local fd = assert(io.open("test.lua", "r")) + local content = assert(fd:read("*a")) + assert.truthy(content:find("package.path", 1, true)) + assert.truthy(content:find("package.cpath", 1, true)) + fd:close() + end + end) + + it("returns false and does nothing if the source file is invalid", function() + assert.falsy(fs.copy_binary("invalid.exe", "copy.exe")) + end) + end) + + describe("fs.modules", function() + local tmpdir + local olddir + local oldpath + + before_each(function() + olddir = lfs.currentdir() + tmpdir = get_tmp_path() + lfs.mkdir(tmpdir) + chdir(tmpdir) + lfs.mkdir("lib") + write_file("lib/module1.lua", "", finally) + write_file("lib/module2.lua", "", finally) + write_file("lib/module1.LuA", "", finally) + write_file("lib/non_lua", "", finally) + lfs.mkdir("lib/internal") + write_file("lib/internal/module11.lua", "", finally) + write_file("lib/internal/module22.lua", "", finally) + + oldpath = package.path + package.path = package.path .. tmpdir .. "/?.lua;" + end) + + after_each(function() + if olddir then + chdir(olddir) + if tmpdir then + lfs.rmdir(tmpdir .. "/lib/internal") + lfs.rmdir(tmpdir .. "/lib") + lfs.rmdir(tmpdir) + end + end + if oldpath then + package.path = oldpath + end + end) + + it("returns a table of the lua modules at a specific require path", function() + local result + + result = fs.modules("lib") + assert.same(#result, 2) + assert.truthy(result[1] == "module1" or result[2] == "module1") + assert.truthy(result[1] == "module2" or result[2] == "module2") + + result = fs.modules("lib.internal") + assert.same(#result, 2) + assert.truthy(result[1] == "module11" or result[2] == "module11") + assert.truthy(result[1] == "module22" or result[2] == "module22") + end) + + it("returns an empty table if the modules couldn't be found in package.path", function() + package.path = "" + assert.same(fs.modules("lib"), {}) + end) + end) + + describe("#unix fs._unix_rwx_to_number", function() + + it("converts permissions in rwx notation to numeric ones", function() + assert.same(tonumber("0644", 8), fs._unix_rwx_to_number("rw-r--r--")) + assert.same(tonumber("0755", 8), fs._unix_rwx_to_number("rwxr-xr-x")) + assert.same(tonumber("0000", 8), fs._unix_rwx_to_number("---------")) + assert.same(tonumber("0777", 8), fs._unix_rwx_to_number("rwxrwxrwx")) + assert.same(tonumber("0700", 8), fs._unix_rwx_to_number("rwx------")) + assert.same(tonumber("0600", 8), fs._unix_rwx_to_number("rw-------")) + end) + + it("produces a negated mask if asked to", function() + assert.same(tonumber("0133", 8), fs._unix_rwx_to_number("rw-r--r--", true)) + assert.same(tonumber("0022", 8), fs._unix_rwx_to_number("rwxr-xr-x", true)) + assert.same(tonumber("0777", 8), fs._unix_rwx_to_number("---------", true)) + assert.same(tonumber("0000", 8), fs._unix_rwx_to_number("rwxrwxrwx", true)) + assert.same(tonumber("0077", 8), fs._unix_rwx_to_number("rwx------", true)) + assert.same(tonumber("0177", 8), fs._unix_rwx_to_number("rw-------", true)) + end) + end) + + describe("fs.execute_env", function() + local tmpname + local tmplua + local LUA = "lua" + + local function readfile(pathname) + local file = assert(io.open(pathname, "rb")) + local data = file:read "*a" + file:close() + return data + end + + lazy_setup(function() + tmpname = os.tmpname() + + tmplua = os.tmpname() + local f = assert(io.open(tmplua, 'wb')) + f:write [[ + local out = io.open((...), 'wb') + out:write(os.getenv 'FOO') + out:close() + ]] + f:close() + LUA = test_env.testing_paths.lua + end) + + after_each(function() + os.remove(tmpname) + end) + + lazy_teardown(function() + os.remove(tmpname) + end) + + it("passes variables w/o spaces correctly", function() + fs.execute_env({ + FOO = "BAR", + }, LUA, tmplua, tmpname) + local data = readfile(tmpname) + assert.same("BAR", data) + end) + + it("passes variables w/ spaces correctly", function() + fs.execute_env({ + FOO = "BAR with spaces", + }, LUA, tmplua, tmpname) + local data = readfile(tmpname) + assert.same("BAR with spaces", data) + end) + end) + +end) diff --git a/spec/unit/fun_spec.lua b/spec/unit/fun_spec.lua new file mode 100644 index 0000000..bffb60d --- /dev/null +++ b/spec/unit/fun_spec.lua @@ -0,0 +1,128 @@ +local test_env = require("spec.util.test_env") +local testing_paths = test_env.testing_paths + +local fun = require("luarocks.fun") + +describe("luarocks.fun #unit", function() + local runner + + lazy_setup(function() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + end) + + lazy_teardown(function() + runner.save_stats() + end) + + describe("fun.concat", function() + it("returns the concatenation of the two tables given as arguments", function() + local t1, t2 + + t1 = {1, 2, 3} + t2 = {4, 5, 6} + assert.same(fun.concat(t1, t2), {1, 2, 3, 4, 5, 6}) + assert.same(fun.concat(t2, t1), {4, 5, 6, 1, 2, 3}) + t1 = {1, 2, 3} + t2 = {} + assert.same(fun.concat(t1, t2), {1, 2, 3}) + assert.same(fun.concat(t2, t1), {1, 2, 3}) + t1 = {} + t2 = {} + assert.same(fun.concat(t1, t2), {}) + end) + end) + + describe("fun.contains", function() + it("checks whether a table contains a given value", function() + local t + + t = {1, 2, 3} + assert.truthy(fun.contains(t, 1)) + assert.falsy(fun.contains(t, 4)) + t = {} + assert.falsy(fun.contains(t, 1)) + end) + end) + + local addOne = function(x) return x + 1 end + + describe("fun.map", function() + it("applies a function to each element in the given table and returns the results in a new table", function() + local t + + t = {1, 2, 3} + assert.same(fun.map(t, addOne), {2, 3, 4}) + t = {} + assert.same(fun.map(t, addOne), {}) + end) + end) + + describe("fun.traverse", function() + it("recursively applies a function to each element in a given table and returns the results in a new table", function() + local t + + t = {1, 2, {3, 4, {5, 6}}} + assert.same(fun.traverse(t, addOne), {2, 3, {4, 5, {6, 7}}}) + t = {1, 2, {}, {1, {}, 2}} + assert.same(fun.traverse(t, addOne), {2, 3, {}, {2, {}, 3}}) + end) + end) + + describe("fun.filter", function() + it("filters the elements in the given table and returns the result in a new table", function() + local t + + t = {1, 2, "a", "b", 3} + assert.same(fun.filter(t, function(x) return type(x) == "number" end), {1, 2, 3}) + t = {2, 4, 7, 8} + assert.same(fun.filter(t, function(x) return x % 2 == 0 end), {2, 4, 8}) + end) + end) + + describe("fun.reverse_in", function() + it("reverses the elements in the given table and returns the result in a new table", function() + local t + + t = {1, 2, 3, 4} + assert.same(fun.reverse_in(t), {4, 3, 2, 1}) + t = {"a", "b", "c"} + assert.same(fun.reverse_in(t), {"c", "b", "a"}) + end) + end) + + describe("fun.sort_in", function() + it("sorts the elements in the given table and returns the result in a new table", function() + local t + + t = {4, 2, 3, 1} + assert.same(fun.sort_in(t), {1, 2, 3, 4}) + t = {"d", "a", "c", "b"} + assert.same(fun.sort_in(t), {"a", "b", "c", "d"}) + end) + end) + + describe("fun.flip", function() + it("returns a function behaving as the one given in the argument but with the arguments interchanged", function() + local a, b = fun.flip(function(a, b) return a, b end)(5, 6) + assert.same(a, 6) + assert.same(b, 5) + end) + end) + + describe("fun.partial", function() + it("partially applies the given arguments to the given function and returns it", function() + local addOne = fun.partial(function(x, y) return x + y end, 1) + assert.same(addOne(1), 2) + assert.same(addOne(2), 3) + + local addTwo = fun.partial(function(x, y, z) return x + y + z end, 1, 1) + assert.same(addTwo(1), 3) + assert.same(addTwo(2), 4) + + local addThree = fun.partial(function(x, y, z, t, u) return x + y + z + t + u end, 1, 1, 1) + assert.same(addThree(1, 1), 5) + assert.same(addThree(1, 2), 6) + end) + end) +end) diff --git a/spec/unit/loader_spec.lua b/spec/unit/loader_spec.lua new file mode 100644 index 0000000..cde3059 --- /dev/null +++ b/spec/unit/loader_spec.lua @@ -0,0 +1,18 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run + +test_env.setup_specs() + +describe("luarocks.loader", function() + describe("#unit", function() + it("starts", function() + assert(run.lua_bool([[-e "require 'luarocks.loader'; print(package.loaded['luarocks.loaded'])"]])) + end) + + describe("which", function() + it("finds modules using package.path", function() + assert(run.lua_bool([[-e "loader = require 'luarocks.loader'; local x,y,z,p = loader.which('luarocks.loader', 'p'); assert(p == 'p')"]])) + end) + end) + end) +end) diff --git a/spec/unit/persist_spec.lua b/spec/unit/persist_spec.lua new file mode 100644 index 0000000..ed78345 --- /dev/null +++ b/spec/unit/persist_spec.lua @@ -0,0 +1,74 @@ +local test_env = require("spec.util.test_env") +local testing_paths = test_env.testing_paths + +local persist = require("luarocks.persist") + +describe("luarocks.persist #unit", function() + local runner + + lazy_setup(function() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + end) + + lazy_teardown(function() + runner.save_stats() + end) + + describe("persist.save_from_table_to_string", function() + it("simple table", function() + assert.are.same([[ +bar = 1234 +foo = "string" +]], persist.save_from_table_to_string({foo = "string", bar = 1234})) + end) + + it("nested tables", function() + assert.are.same([[ +bar = { + baz = "string" +} +foo = { + 1, 2, 3, 4 +} +]], persist.save_from_table_to_string({foo = {1, 2, 3, 4}, bar = {baz = "string"}})) + end) + + it("table with a keyword key (#947)", function() + assert.are.same([[ +bar = { + ["function"] = "foo" +} +]], persist.save_from_table_to_string({bar = {["function"] = "foo"}})) + end) + + it("strings with quotes", function() + assert.are.same([[ +bar = "a \\backslash?" +foo = "a \"quote\"?" +]], persist.save_from_table_to_string({foo = 'a "quote"?', bar = 'a \\backslash?'})) + end) + + it("multiline strings", function() + assert.are.same([===[ +bar = [==[ +]] +]=]]==] +foo = [[ +First line +Second line]] +]===], persist.save_from_table_to_string({foo = "First line\nSecond line", bar = "]]\n]=]"})) + end) + + it("multiline strings ending with brackets", function() + assert.are.same([===[ +bar = [==[ +]] +]=]==] +foo = [=[ +First line +Second line [1]]=] +]===], persist.save_from_table_to_string({foo = "First line\nSecond line [1]", bar = "]]\n]="})) + end) + end) +end) diff --git a/spec/unit/rockspecs_spec.lua b/spec/unit/rockspecs_spec.lua new file mode 100644 index 0000000..7eb033c --- /dev/null +++ b/spec/unit/rockspecs_spec.lua @@ -0,0 +1,126 @@ + +local rockspecs = require("luarocks.rockspecs") +local cfg = require("luarocks.core.cfg") +local test_env = require("spec.util.test_env") +local lfs = require("lfs") + +describe("luarocks.rockspecs #unit", function() + + lazy_setup(function() + cfg.init() + end) + + it("auto adds a build dependency for non-vendored build types", function() + local filename = "test-1.0-1.rockspec" + local rockspec = { + package = "test", + source = { + url = "", + }, + build = { + type = "foo" + }, + } + local globals = {} + local quick = true + + local out = rockspecs.from_persisted_table(filename, rockspec, globals, quick) + + assert(rockspec == out) + assert.same(rockspec.build_dependencies, { + { name = "luarocks-build-foo", constraints = {} }, + }) + end) + + it("does not add a build dependency for non-vendored build type if it's already ther", function() + local filename = "test-1.0-1.rockspec" + local rockspec = { + package = "test", + source = { + url = "", + }, + build_dependencies = { + "luarocks-build-cpp >= 1.0", + }, + build = { + type = "cpp" + }, + } + local globals = {} + local quick = true + + local out = rockspecs.from_persisted_table(filename, rockspec, globals, quick) + + assert(rockspec == out) + + assert.same(rockspec.build_dependencies, { + { name = "luarocks-build-cpp", constraints = { { op = ">=", version = { string = "1.0", 1, 0 } } } }, + }) + end) + + it("does not add a build dependency for 'none' build type", function() + local filename = "test-1.0-1.rockspec" + local rockspec = { + package = "test", + source = { + url = "", + }, + build = { + type = "none" + }, + } + local globals = {} + local quick = true + + local out = rockspecs.from_persisted_table(filename, rockspec, globals, quick) + + assert(rockspec == out) + assert.same(rockspec.build_dependencies, {}) + end) + + it("does not add a build dependency for 'module' build type", function() + local filename = "test-1.0-1.rockspec" + local rockspec = { + package = "test", + source = { + url = "", + }, + build = { + type = "none" + }, + } + local globals = {} + local quick = true + + local out = rockspecs.from_persisted_table(filename, rockspec, globals, quick) + + assert(rockspec == out) + assert.same(rockspec.build_dependencies, {}) + end) + + for d in lfs.dir(test_env.testing_paths.src_dir .. "/luarocks/build") do + local name = d:match("(.*)%.lua") + if name then + it("does not add a build dependency for vendored '" .. name .. "' type", function() + local filename = "test-1.0-1.rockspec" + local rockspec = { + package = "test", + source = { + url = "", + }, + build = { + type = name + }, + } + local globals = {} + local quick = true + + local out = rockspecs.from_persisted_table(filename, rockspec, globals, quick) + + assert(rockspec == out) + assert.same(rockspec.build_dependencies, {}) + end) + end + end + +end) diff --git a/spec/unit/sysdetect_spec.lua b/spec/unit/sysdetect_spec.lua new file mode 100644 index 0000000..d3b1695 --- /dev/null +++ b/spec/unit/sysdetect_spec.lua @@ -0,0 +1,79 @@ + +local sysdetect = require("luarocks.core.sysdetect") +local lfs = require("lfs") + +describe("luarocks.core.sysdetect #unix #unit", function() + + lazy_setup(function() + os.execute([=[ + [ -e binary-samples ] || { + git clone --depth=1 https://github.com/hishamhm/binary-samples + ( cd binary-samples && git pull ) + } + ]=]) + end) + + local files = { + ["."] = "ignore", + [".."] = "ignore", + ["README.md"] = "ignore", + [".git"] = "ignore", + ["MIT_LICENSE"] = "ignore", + ["anti-disassembler"] = "ignore", + ["elf-Linux-lib-x64.so"] = "ignore", + ["elf-Linux-lib-x86.so"] = "ignore", + + ["elf-Linux-x64-bash"] = {"linux", "x86_64"}, + ["elf-Linux-ia64-bash"] = {"linux", "ia_64"}, + ["MachO-OSX-ppc-and-i386-bash"] = {"macosx", "x86"}, + ["MachO-OSX-ppc-openssl-1.0.1h"] = {"macosx", "ppc"}, + ["MachO-iOS-armv7-armv7s-arm64-Helloworld"] = {"macosx", "arm"}, + ["pe-Windows-x64-cmd"] = {"windows", "x86_64"}, + ["MachO-iOS-armv7s-Helloworld"] = {"macosx", "arm"}, + ["elf-Linux-SparcV8-bash"] = {"linux", "sparcv8"}, + ["elf-HPUX-ia64-bash"] = {"hpux", "ia_64"}, + ["MachO-OSX-x64-ls"] = {"macosx", "x86_64"}, + ["pe-Windows-ARMv7-Thumb2LE-HelloWorld"] = {"windows", "armv7l"}, + ["elf-ARMv6-static-gofmt"] = {"sysv", "arm"}, + ["elf-Linux-s390-bash"] = {"linux", "s390"}, + ["elf-Linux-Alpha-bash"] = {"linux", "alpha"}, + ["elf-Linux-hppa-bash"] = {"linux", "hppa"}, + ["elf-Linux-x86_64-static-sln"] = {"linux", "x86_64"}, + ["elf-Linux-Mips4-bash"] = {"linux", "mips"}, + ["elf-ARMv6-dynamic-go"] = {"linux", "arm"}, + ["elf-Linux-SuperH4-bash"] = {"linux", "superh"}, + ["elf-Linux-x86-bash"] = {"linux", "x86"}, + ["elf-Linux-PowerPC-bash"] = {"linux", "ppc"}, + ["libSystem.B.dylib"] = {"macosx", "x86_64"}, + ["MachO-iOS-arm1176JZFS-bash"] = {"macosx", "arm"}, + ["pe-Windows-x86-cmd"] = {"windows", "x86"}, + ["elf-Linux-ARMv7-ls"] = {"linux", "arm"}, + ["elf-Linux-ARM64-bash"] = {"linux", "aarch64"}, + ["MachO-OSX-x86-ls"] = {"macosx", "x86"}, + ["elf-solaris-sparc-ls"] = {"solaris", "sparc"}, + ["elf-solaris-x86-ls"] = {"solaris", "x86"}, + ["pe-mingw32-strip.exe"] = {"windows", "x86"}, + ["elf-OpenBSD-x86_64-sh"] = {"openbsd", "x86_64"}, + ["elf-NetBSD-x86_64-echo"] = {"netbsd", "x86_64"}, + ["elf-FreeBSD-x86_64-echo"] = {"freebsd", "x86_64"}, + ["elf-Haiku-GCC2-ls"] = {"haiku", "x86"}, + ["elf-Haiku-GCC7-WebPositive"] = {"haiku", "x86"}, + ["pe-cygwin-ls.exe"] = {"cygwin", "x86"}, + ["elf-DragonFly-x86_64-less"] = {"dragonfly", "x86_64"}, + + } + + describe("detect_file", function() + it("detects system and processor", function() + for f in lfs.dir("binary-samples") do + if files[f] ~= "ignore" then + assert.table(files[f], "unknown binary " .. f) + local expected_s, expected_p = files[f][1], files[f][2] + local s, p = sysdetect.detect_file("binary-samples/" .. f) + assert.same(expected_s, s, "bad system for " .. f) + assert.same(expected_p, p, "bad processor for " .. f) + end + end + end) + end) +end) diff --git a/spec/unit/test_spec.lua b/spec/unit/test_spec.lua new file mode 100644 index 0000000..4a31777 --- /dev/null +++ b/spec/unit/test_spec.lua @@ -0,0 +1,173 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local get_tmp_path = test_env.get_tmp_path +local testing_paths = test_env.testing_paths +local write_file = test_env.write_file + +local fs = require("luarocks.fs") +local cfg = require("luarocks.core.cfg") +local path = require("luarocks.path") +local test = require("luarocks.test") +local test_busted = require("luarocks.test.busted") +local test_command = require("luarocks.test.command") + +describe("LuaRocks test #unit", function() + local runner + + lazy_setup(function() + cfg.init() + fs.init() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + end) + + lazy_teardown(function() + runner.save_stats() + end) + + local tmpdir + local olddir + + local create_tmp_dir = function() + tmpdir = get_tmp_path() + olddir = lfs.currentdir() + lfs.mkdir(tmpdir) + lfs.chdir(tmpdir) + fs.change_dir(tmpdir) + end + + local destroy_tmp_dir = function() + if olddir then + lfs.chdir(olddir) + if tmpdir then + lfs.rmdir(tmpdir) + end + end + end + + describe("test.command", function() + describe("command.detect_type", function() + before_each(function() + create_tmp_dir() + end) + + after_each(function() + destroy_tmp_dir() + end) + + it("returns true if test.lua exists", function() + write_file("test.lua", "", finally) + assert.truthy(test_command.detect_type()) + end) + + it("returns false if test.lua doesn't exist", function() + assert.falsy(test_command.detect_type()) + end) + end) + + describe("command.run_tests", function() + before_each(function() + create_tmp_dir() + end) + + after_each(function() + destroy_tmp_dir() + end) + + it("returns the result of the executed tests", function() + write_file("test.lua", "assert(1==1)", finally) + assert.truthy(test_command.run_tests(nil, {})) + + write_file("test.lua", "assert(1==2)", finally) + assert.falsy(test_command.run_tests(nil, {})) + end) + + it("returns the result of the executed tests with custom arguments and test command", function() + write_file("test.lua", "assert(1==1)", finally) + + local test = { + script = "test.lua", + flags = { + arg1 = "1", + arg2 = "2" + }, + command = fs.Q(testing_paths.lua) + } + assert.truthy(test_command.run_tests(test, {})) + end) + + it("returns false and does nothing if the test script doesn't exist", function() + assert.falsy(test_command.run_tests(nil, {})) + end) + end) + end) + + describe("test.busted", function() + describe("busted.detect_type", function() + before_each(function() + create_tmp_dir() + end) + + after_each(function() + destroy_tmp_dir() + end) + + it("returns true if .busted exists", function() + write_file(".busted", "", finally) + assert.truthy(test_busted.detect_type()) + end) + + it("returns false if .busted doesn't exist", function() + assert.falsy(test_busted.detect_type()) + end) + end) + + describe("busted.run_tests", function() + before_each(function() + path.use_tree(testing_paths.testing_sys_tree) + create_tmp_dir() + end) + + after_each(function() + destroy_tmp_dir() + end) + + pending("returns the result of the executed tests", function() + -- FIXME: busted issue + write_file("test_spec.lua", "assert(1==1)", finally) + assert.truthy(test_busted.run_tests(nil, {})) + + write_file("test_spec.lua", "assert(1==2)", finally) + assert.falsy(test_busted.run_tests()) + end) + end) + end) + + describe("test", function() + describe("test.run_test_suite", function() + before_each(function() + create_tmp_dir() + end) + + after_each(function() + destroy_tmp_dir() + end) + + it("returns false if the given rockspec cannot be loaded", function() + assert.falsy(test.run_test_suite("invalid", nil, {})) + end) + + it("returns false if no test type was detected", function() + assert.falsy(test.run_test_suite({ package = "test" }, nil, {})) + end) + + it("returns the result of executing the tests specified in the given rockspec", function() + write_file("test.lua", "assert(1==1)", finally) + assert.truthy(test.run_test_suite({ test_dependencies = {} }, nil, {})) + + write_file("test.lua", "assert(1==2)", finally) + assert.falsy(test.run_test_suite({ test_dependencies = {} }, nil, {})) + end) + end) + end) +end) diff --git a/spec/unit/tools_spec.lua b/spec/unit/tools_spec.lua new file mode 100644 index 0000000..5b85c86 --- /dev/null +++ b/spec/unit/tools_spec.lua @@ -0,0 +1,251 @@ +local test_env = require("spec.util.test_env") +local get_tmp_path = test_env.get_tmp_path +local testing_paths = test_env.testing_paths +local write_file = test_env.write_file + +local fs = require("luarocks.fs") +local cfg = require("luarocks.core.cfg") +local patch = require("luarocks.tools.patch") + +local lao = +[[The Nameless is the origin of Heaven and Earth; +The named is the mother of all things. + +Therefore let there always be non-being, + so we may see their subtlety, +And let there always be being, + so we may see their outcome. +The two are the same, +But after they are produced, + they have different names. +They both may be called deep and profound. +Deeper and more profound, +The door of all subtleties!]] + +local tzu = +[[The Way that can be told of is not the eternal Way; +The name that can be named is not the eternal name. +The Nameless is the origin of Heaven and Earth; +The Named is the mother of all things. +Therefore let there always be non-being, + so we may see their subtlety, +And let there always be being, + so we may see their outcome. +The two are the same, +But after they are produced, + they have different names.]] + +local valid_patch1 = +[[--- lao 2002-02-21 23:30:39.942229878 -0800 ++++ tzu 2002-02-21 23:30:50.442260588 -0800 +@@ -1,7 +1,6 @@ +-The Way that can be told of is not the eternal Way; +-The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; +-The Named is the mother of all things. ++The named is the mother of all things. ++ + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, +@@ -9,3 +8,6 @@ + The two are the same, + But after they are produced, + they have different names. ++They both may be called deep and profound. ++Deeper and more profound, ++The door of all subtleties!]] + +local valid_patch2 = +[[--- /dev/null 1969-02-21 23:30:39.942229878 -0800 ++++ tzu 2002-02-21 23:30:50.442260588 -0800 +@@ -1,7 +1,6 @@ +-The Way that can be told of is not the eternal Way; +-The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; +-The Named is the mother of all things. ++The named is the mother of all things. ++ + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, +@@ -9,3 +8,6 @@ + The two are the same, + But after they are produced, + they have different names. ++They both may be called deep and profound. ++Deeper and more profound, ++The door of all subtleties!]] + +local invalid_patch1 = +[[--- lao 2002-02-21 23:30:39.942229878 -0800 ++++ tzu 2002-02-21 23:30:50.442260588 -0800 +@@ -1,7 +1,6 @@ +-The Way that can be told of is not the eternal Way; +-The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; +-The Named is the mother of all things. +--- Extra ++The named is the mother of all things. ++ + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, +--- Extra +@@ -9,3 +8,7 @@ + The two are the same, + But after they are produced, + they have different names. ++They both may be called deep and profound. ++Deeper and more profound, ++The door of all subtleties!]] + +local invalid_patch2 = +[[--- lao 2002-02-21 23:30:39.942229878 -0800 ++++ tzu 2002-02-21 23:30:50.442260588 -0800 +@@ -1,7 +1,6 @@ +-The Way that can be told of is not the eternal Way; +-The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; +-The Named is the mother of all things. ++The named is the mother of all things. ++ + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, +@@ -9,3 +8,6 @@ + The two are the same, + But after they are produced, + they have different names. ++They both may be called deep and profound. ++Deeper and more profound, +? ... ++The door of all subtleties!]] + +local invalid_patch3 = +[[--- lao 2002-02-21 23:30:39.942229878 -0800 ++++ tzu 2002-02-21 23:30:50.442260588 -0800 +@@ -1,7 +1,6 @@ +-The Way that can be told of is not the eternal Way; +-The name that can be named is not the eternal name. + The Nameless is the origin of Heaven and Earth; +-The Named is the mother of all things. ++The named is the mother of all things. ++ + Therefore let there always be non-being, + so we may see their subtlety, + And let there always be being, +@@ -9,3 +8,6 @@ + The two are the same, + But after they are produced, + they have different names. ++They both may be called deep and profound. ++Deeper and more profound, +? ... ++The door of all subtleties!]] + +describe("Luarocks patch test #unit", function() + local runner + + lazy_setup(function() + cfg.init() + fs.init() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + end) + + lazy_teardown(function() + runner.save_stats() + end) + + describe("patch.read_patch", function() + it("returns a table with the patch file info and the result of parsing the file", function() + local t, result + + write_file("test.patch", valid_patch1, finally) + t, result = patch.read_patch("test.patch") + assert.truthy(result) + assert.truthy(t) + + write_file("test.patch", invalid_patch1, finally) + t, result = patch.read_patch("test.patch") + assert.falsy(result) + assert.truthy(t) + + write_file("test.patch", invalid_patch2, finally) + t, result = patch.read_patch("test.patch") + assert.falsy(result) + assert.truthy(t) + + write_file("test.patch", invalid_patch3, finally) + t, result = patch.read_patch("test.patch") + assert.falsy(result) + assert.truthy(t) + end) + end) + + describe("patch.apply_patch", function() + local tmpdir + local olddir + + before_each(function() + tmpdir = get_tmp_path() + olddir = lfs.currentdir() + lfs.mkdir(tmpdir) + lfs.chdir(tmpdir) + + write_file("lao", tzu, finally) + write_file("tzu", lao, finally) + end) + + after_each(function() + if olddir then + lfs.chdir(olddir) + if tmpdir then + lfs.rmdir(tmpdir) + end + end + end) + + it("applies the given patch and returns the result of patching", function() + write_file("test.patch", valid_patch1, finally) + local p = patch.read_patch("test.patch") + local result = patch.apply_patch(p) + assert.truthy(result) + end) + + it("applies the given patch with custom arguments and returns the result of patching", function() + write_file("test.patch", valid_patch2, finally) + local p = patch.read_patch("test.patch") + local result = patch.apply_patch(p, nil, true) + assert.truthy(result) + end) + + it("fails if the patch file is invalid", function() + write_file("test.patch", invalid_patch1, finally) + local p = patch.read_patch("test.patch") + local result = pcall(patch.apply_patch, p) + assert.falsy(result) + end) + + it("returns false if the files from the patch doesn't exist", function() + os.remove("lao") + os.remove("tzu") + + write_file("test.patch", valid_patch1, finally) + local p = patch.read_patch("test.patch") + local result = patch.apply_patch(p) + assert.falsy(result) + end) + + it("returns false if the target file was already patched", function() + write_file("test.patch", valid_patch1, finally) + local p = patch.read_patch("test.patch") + local result = patch.apply_patch(p) + assert.truthy(result) + + result = patch.apply_patch(p) + assert.falsy(result) + end) + end) +end) diff --git a/spec/unit/util_spec.lua b/spec/unit/util_spec.lua new file mode 100644 index 0000000..8b234b2 --- /dev/null +++ b/spec/unit/util_spec.lua @@ -0,0 +1,160 @@ +local test_env = require("spec.util.test_env") +local testing_paths = test_env.testing_paths +local P = test_env.P + +local util = require("luarocks.util") +local core_util = require("luarocks.core.util") + +describe("luarocks.util #unit", function() + local runner + + lazy_setup(function() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + end) + + lazy_teardown(function() + runner.save_stats() + end) + + describe("util.variable_substitutions", function() + it("replaces variables", function() + local t = { + ["hello"] = "$(KIND) world", + } + util.variable_substitutions(t, { + ["KIND"] = "happy", + }) + assert.are.same({ + ["hello"] = "happy world", + }, t) + end) + + it("missing variables are empty", function() + local t = { + ["hello"] = "$(KIND) world", + } + util.variable_substitutions(t, { + }) + assert.are.same({ + ["hello"] = " world", + }, t) + end) + end) + + describe("util.sortedpairs", function() + local function collect(iter, state, var) + local collected = {} + + while true do + local returns = {iter(state, var)} + + if returns[1] == nil then + return collected + else + table.insert(collected, returns) + var = returns[1] + end + end + end + + it("default sort", function() + assert.are.same({}, collect(util.sortedpairs({}))) + assert.are.same({ + {1, "v1"}, + {2, "v2"}, + {3, "v3"}, + {"bar", "v5"}, + {"foo", "v4"} + }, collect(util.sortedpairs({"v1", "v2", "v3", foo = "v4", bar = "v5"}))) + end) + + it("sort by function", function() + local function compare(a, b) return a > b end + assert.are.same({}, collect(util.sortedpairs({}, compare))) + assert.are.same({ + {3, "v3"}, + {2, "v2"}, + {1, "v1"} + }, collect(util.sortedpairs({"v1", "v2", "v3"}, compare))) + end) + + it("sort by priority table", function() + assert.are.same({}, collect(util.sortedpairs({}, {"k1", "k2"}))) + assert.are.same({ + {"k3", "v3"}, + {"k2", "v2", {"sub order"}}, + {"k1", "v1"}, + {"k4", "v4"}, + {"k5", "v5"}, + }, collect(util.sortedpairs({ + k1 = "v1", k2 = "v2", k3 = "v3", k4 = "v4", k5 = "v5" + }, {"k3", {"k2", {"sub order"}}, "k1"}))) + end) + end) + + describe("core.util.show_table", function() + it("returns a pretty-printed string containing the representation of the given table", function() + local result + + local t1 = {1, 2, 3} + result = core_util.show_table(t1) + assert.truthy(result:find("[1] = 1", 1, true)) + assert.truthy(result:find("[2] = 2", 1, true)) + assert.truthy(result:find("[3] = 3", 1, true)) + + local t2 = {a = 1, b = 2, c = 3} + result = core_util.show_table(t2) + assert.truthy(result:find("[\"a\"] = 1", 1, true)) + assert.truthy(result:find("[\"b\"] = 2", 1, true)) + assert.truthy(result:find("[\"c\"] = 3", 1, true)) + + local t3 = {a = 1, b = "2", c = {3}} + result = core_util.show_table(t3) + assert.truthy(result:find("[\"a\"] = 1", 1, true)) + assert.truthy(result:find("[\"b\"] = \"2\"", 1, true)) + assert.truthy(result:find("[\"c\"] = {", 1, true)) + assert.truthy(result:find("[1] = 3", 1, true)) + + local t4 = {a = 1, b = {c = 2, d = {e = "4"}}} + result = core_util.show_table(t4) + assert.truthy(result:find("[\"a\"] = 1", 1, true)) + assert.truthy(result:find("[\"b\"] = {", 1, true)) + assert.truthy(result:find("[\"c\"] = 2", 1, true)) + assert.truthy(result:find("[\"d\"] = {", 1, true)) + assert.truthy(result:find("[\"e\"] = \"4\"", 1, true)) + end) + end) + + describe("core.util.cleanup_path", function() + it("does not change order of existing items of prepended path", function() + local sys_path = P'/usr/local/bin;/usr/bin' + local lr_path = P'/home/user/.luarocks/bin;/usr/bin' + local path = lr_path .. ';' .. sys_path + + local result = core_util.cleanup_path(path, ';', '5.3', false) + assert.are.equal(P'/home/user/.luarocks/bin;/usr/local/bin;/usr/bin', result) + end) + + it("does not change order of existing items of appended path", function() + local sys_path = P'/usr/local/bin;/usr/bin' + local lr_path = P'/home/user/.luarocks/bin;/usr/bin' + local path = sys_path .. ';' .. lr_path + + local result = core_util.cleanup_path(path, ';', '5.3', true) + assert.are.equal(P'/usr/local/bin;/usr/bin;/home/user/.luarocks/bin', result) + end) + + it("rewrites versions that do not match the provided version", function() + local expected = P'a/b/lua/5.3/?.lua;a/b/c/lua/5.3/?.lua' + local result = core_util.cleanup_path(P'a/b/lua/5.2/?.lua;a/b/c/lua/5.3/?.lua', ';', '5.3') + assert.are.equal(expected, result) + end) + + it("does not rewrite versions for which the provided version is a substring", function() + local expected = P'a/b/lua/5.3/?.lua;a/b/c/lua/5.3.4/?.lua' + local result = core_util.cleanup_path(P'a/b/lua/5.2/?.lua;a/b/c/lua/5.3.4/?.lua', ';', '5.3') + assert.are.equal(expected, result) + end) + end) +end) diff --git a/spec/unpack_spec.lua b/spec/unpack_spec.lua new file mode 100644 index 0000000..59f7eb0 --- /dev/null +++ b/spec/unpack_spec.lua @@ -0,0 +1,69 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run +local testing_paths = test_env.testing_paths + +local extra_rocks = { + "/cprint-${CPRINT}.src.rock", + "/cprint-${CPRINT}.rockspec", + "/luazip-1.2.4-1.rockspec" +} + +describe("luarocks unpack #integration", function() + + before_each(function() + test_env.setup_specs(extra_rocks) + end) + + describe("basic fail tests", function() + it("with no flags/arguments", function() + assert.is_false(run.luarocks_bool("unpack")) + end) + + it("with invalid rockspec", function() + assert.is_false(run.luarocks_bool("unpack invalid.rockspec")) + end) + + it("with invalid patch", function() + assert.is_false(run.luarocks_bool("unpack " .. testing_paths.fixtures_dir .. "/invalid_patch-0.1-1.rockspec")) + end) + end) + + describe("more complex tests", function() + it("download", function() + assert.is_true(run.luarocks_bool("unpack cprint")) + test_env.remove_dir("cprint-${CPRINT}") + end) + + it("src", function() + assert.is_true(run.luarocks_bool("download --source cprint")) + assert.is_true(run.luarocks_bool("unpack cprint-${CPRINT}.src.rock")) + os.remove("cprint-${CPRINT}.src.rock") + test_env.remove_dir("cprint-${CPRINT}") + end) + + it("src", function() + assert.is_true(run.luarocks_bool("download --rockspec cprint")) + assert.is_true(run.luarocks_bool("unpack cprint-${CPRINT}.rockspec")) + os.remove("cprint-${CPRINT}.rockspec") + os.remove("lua-cprint") + test_env.remove_dir("cprint-${CPRINT}") + end) + + -- #595 luarocks unpack of a git:// rockspec fails to copy the rockspec + it("git:// rockspec", function() + assert.is_true(run.luarocks_bool("download --rockspec luazip")) + assert.is_true(run.luarocks_bool("unpack luazip-1.2.4-1.rockspec")) + assert.is_truthy(lfs.attributes("luazip-1.2.4-1/luazip/luazip-1.2.4-1.rockspec")) + test_env.remove_dir("luazip-1.2.4-1") + end) + + it("binary", function() + assert.is_true(run.luarocks_bool("build cprint")) + assert.is_true(run.luarocks_bool("pack cprint")) + assert.is_true(run.luarocks_bool("unpack cprint-${CPRINT}." .. test_env.platform .. ".rock")) + test_env.remove_dir("cprint-${CPRINT}") + os.remove("cprint-${CPRINT}." .. test_env.platform .. ".rock") + end) + end) +end) diff --git a/spec/upload_spec.lua b/spec/upload_spec.lua new file mode 100644 index 0000000..cc0b606 --- /dev/null +++ b/spec/upload_spec.lua @@ -0,0 +1,63 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run +local testing_paths = test_env.testing_paths + +describe("luarocks upload #integration", function() + + describe("general tests", function() + before_each(function() + test_env.setup_specs(nil) + end) + + it("with no flags/arguments", function() + assert.is_false(run.luarocks_bool("upload")) + end) + + it("invalid rockspec", function() + assert.is_false(run.luarocks_bool("upload invalid.rockspec")) + end) + + it("api key invalid", function() + assert.is_false(run.luarocks_bool("upload --api-key=invalid invalid.rockspec")) + end) + + it("api key invalid and skip-pack", function() + assert.is_false(run.luarocks_bool("upload --api-key=\"invalid\" --skip-pack " .. testing_paths.testing_server .. "/luasocket-${LUASOCKET}.rockspec")) + end) + + it("force #unix", function() + assert.is_false(run.luarocks_bool("upload --api-key=\"invalid\" --force " .. testing_paths.testing_server .. "/luasocket-${LUASOCKET}.rockspec")) + end) + end) + + describe("tests with Xavante server #mock", function() + lazy_setup(function() + test_env.setup_specs(nil, "mock") + test_env.mock_server_init() + end) + + lazy_teardown(test_env.mock_server_done) + + it("rockspec with api-key", function() + assert.is_true(run.luarocks_bool("upload " .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec " .. test_env.openssl_dirs .. " --api-key=123", {LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/luarocks_site.lua"})) + end) + + it("#gpg rockspec with --sign", function() + os.remove(testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec.asc") + os.remove(testing_paths.testrun_dir .. "/a_rock-1.0-1.src.rock.asc") + print(run.luarocks("upload " .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec " .. test_env.openssl_dirs .. " --api-key=123 --sign", {LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/luarocks_site.lua"})) + end) + + it("with .rockspec and .src.rock", function() + assert.is_true(run.luarocks_bool("upload " .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec " .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.src.rock " .. test_env.openssl_dirs, {LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/luarocks_site.lua"})) + end) + + it("with arguments .src.rock and .rockspec out of order", function() + assert.is_false(run.luarocks_bool("upload " .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.src.rock " .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec " .. test_env.openssl_dirs, {LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/luarocks_site.lua"})) + end) + + it("rockspec with api-key and skip-pack", function() + assert.is_true(run.luarocks_bool("upload --skip-pack " .. testing_paths.fixtures_dir .. "/a_rock-1.0-1.rockspec " .. test_env.openssl_dirs .. " --api-key=123", {LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/luarocks_site.lua"})) + end) + end) +end) diff --git a/spec/util/git_repo.lua b/spec/util/git_repo.lua new file mode 100644 index 0000000..b3ddd9e --- /dev/null +++ b/spec/util/git_repo.lua @@ -0,0 +1,108 @@ +local git_repo = {} + +local test_env = require("spec.util.test_env") +local lfs = require("lfs") + +local files = { +---------------------------------------- +["testrock-dev-1.rockspec"] = [[ +package = "testrock" +version = "dev-1" +source = { + url = "git://localhost:20000/testrock" +} +description = { + homepage = "https://localhost", + license = "MIT" +} +dependencies = {} +build = { + type = "builtin", + modules = { + testrock = "testrock.lua" + } +} +]], +---------------------------------------- +["testrock.lua"] = [[ +local testrock = {} + +function testrock.say() + return "Hello, world!" +end + +return testrock +]], +---------------------------------------- +["foo.c"] = [[ +#include <lua.h> +int luaopen_foo(lua_State* L) { + lua_pushnumber(L, 42); + return 1; +} +]], +---------------------------------------- +["test.lua"] = [[ +print("this should be ignored!") +]], +} + +local function write_file(filename, contents) + local fd = assert(io.open(filename, "w")) + assert(fd:write(contents)) + fd:close() +end + +local function handling(args) + local pok, ret = pcall(args.try) + if not pok then + pok, ret = pcall(args.catch, ret) + end + args.finally() + if not pok then + error(ret) + end + return ret +end + +function git_repo.start() + local dir = lfs.currentdir() + return handling { + try = function() + local pidfile = os.tmpname() + local basedir = test_env.testing_paths.testrun_dir .. "/git_repo" + local repodir = basedir .. "/testrock" + test_env.remove_dir(basedir) + lfs.mkdir(basedir) + lfs.mkdir(repodir) + lfs.chdir(repodir) + assert(test_env.execute("git init")) + for name, contents in pairs(files) do + write_file(name, contents) + test_env.execute("git add " .. name) + end + assert(test_env.execute("git commit -a -m 'initial commit'")) + assert(test_env.execute("git branch test-branch")) + print("git daemon --reuseaddr --pid-file="..pidfile.." --base-path="..basedir.." --export-all "..repodir.." &") + assert(test_env.execute("git daemon --reuseaddr --pid-file="..pidfile.." --base-path="..basedir.." --export-all "..repodir.." &")) + assert(test_env.execute("sleep 0.1; netstat -ln | grep '0.0.0.0:9418 .* LISTEN'")) + return { + stop = function() + local fd = io.open(pidfile) + local pid = fd:read("*a") + fd:close() + assert(test_env.execute("kill -HUP " .. pid)) + test_env.remove_dir(basedir) + end + } + end, + catch = function(err) + error(err) + end, + finally = function() + lfs.chdir(dir) + end, + } +end + +return git_repo diff --git a/spec/util/mock-server.lua b/spec/util/mock-server.lua new file mode 100644 index 0000000..1b09cd6 --- /dev/null +++ b/spec/util/mock-server.lua @@ -0,0 +1,98 @@ +#!/usr/bin/env lua + +--- A simple LuaRocks mock-server for testing. +local restserver = require("restserver") +local server = restserver:new():port(8080) + +server:add_resource("api/tool_version", { + { + method = "GET", + path = "/", + produces = "application/json", + handler = function(query) + local json = { version = query.current } + return restserver.response():status(200):entity(json) + end + } +}) + +server:add_resource("api/1/{id:[0-9]+}/status", { + { + method = "GET", + path = "/", + produces = "application/json", + handler = function(query) + local json = { user_id = "123", created_at = "29.1.1993" } + return restserver.response():status(200):entity(json) + end + } +}) + +server:add_resource("/api/1/{id:[0-9]+}/check_rockspec", { + { + method = "GET", + path = "/", + produces = "application/json", + handler = function(query) + local json = {} + return restserver.response():status(200):entity(json) + end + } +}) + +server:add_resource("/api/1/{id:[0-9]+}/upload", { + { + method = "POST", + path = "/", + produces = "application/json", + handler = function(query) + local json = {module = "luasocket", version = {id = "1.0"}, module_url = "http://localhost/luasocket", manifests = "root", is_new = "is_new"} + return restserver.response():status(200):entity(json) + end + } +}) + +server:add_resource("/api/1/{id:[0-9]+}/upload_rock/{id:[0-9]+}", { + { + method = "POST", + path = "/", + produces = "application/json", + handler = function(query) + local json = {"rock","module_url"} + return restserver.response():status(200):entity(json) + end + } +}) + +server:add_resource("/file/{name:[^/]+}", { + { + method = "GET", + path = "/", + produces = "text/plain", + handler = function(query, name) + local basedir = arg[1] or "./spec/fixtures" + local fd = io.open(basedir .. "/" .. name, "rb") + if not fd then + return restserver.response():status(404) + end + local data = fd:read("*a") + fd:close() + return restserver.response():status(200):entity(data) + end + } +}) + +-- SHUTDOWN this mock-server +server:add_resource("/shutdown", { + { + method = "GET", + path = "/", + handler = function(query) + os.exit() + return restserver.response():status(200):entity() + end + } +}) + +-- This loads the restserver.xavante plugin +server:enable("restserver.xavante"):start() diff --git a/spec/util/quick.lua b/spec/util/quick.lua new file mode 100644 index 0000000..a525aa9 --- /dev/null +++ b/spec/util/quick.lua @@ -0,0 +1,472 @@ +local quick = {} + +local dir_sep = package.config:sub(1, 1) + +local cfg, dir, fs, versions +local initialized = false + +local function initialize() + if initialized then + return + end + initialized = true + + cfg = require("luarocks.core.cfg") + dir = require("luarocks.dir") + fs = require("luarocks.fs") + versions = require("spec.util.versions") + cfg.init() + fs.init() +end + +local function native_slash(pathname) + return (pathname:gsub("[/\\]", dir_sep)) +end + +local function parse_cmd(line) + local cmd, arg = line:match("^%s*([A-Z_]+):%s*(.*)%s*$") + return cmd, arg +end + +local function is_blank(line) + return not not line:match("^%s*$") +end + +local function is_hr(line) + return not not line:match("^%-%-%-%-%-") +end + +local function parse(filename) + local fd = assert(io.open(filename, "rb")) + local input = assert(fd:read("*a")) + fd:close() + + initialize() + + local tests = {} + + local cur_line = 0 + local cur_suite = "" + local cur_test + local cur_op + local cur_block + local cur_block_name + local stack = { "start" } + + local function start_test(arg) + cur_test = { + name = cur_suite .. arg, + ops = {}, + } + cur_op = nil + table.insert(tests, cur_test) + table.insert(stack, "test") + end + + local function fail(msg) + io.stderr:write("Error reading " .. filename .. ":" .. cur_line .. ": " .. msg .. "\n") + os.exit(1) + end + + local function bool_arg(cmd, cur, field, arg) + if arg ~= "true" and arg ~= "false" then + fail(cmd .. " argument must be 'true' or 'false'") + end + cur[field] = (arg == "true") + end + + local function block_start_arg(cmd, cur, field) + if not cur or cur.op ~= "RUN" then + fail(cmd .. " must be given in the context of a RUN") + end + if cur[field] then + fail(cmd .. " was already declared") + end + + cur[field] = { + data = {} + } + cur_block = cur[field] + cur_block_name = cmd + table.insert(stack, "block start") + end + + local test_env = require("spec.util.test_env") + local function expand_vars(line) + if not line then + return nil + end + return (line:gsub("%%%b{}", function(var) + var = var:sub(3, -2) + local fn, fnarg = var:match("^%s*([a-z_]+)%s*%(%s*([^)]+)%s*%)%s*$") + + local value + if var == "tmpdir" then + value = "%{tmpdir}" + elseif var == "url(%{tmpdir})" then + value = "%{url(%{tmpdir})}" + elseif fn == "url" then + value = expand_vars(fnarg) + value = value:gsub("\\", "/") + elseif fn == "path" then + value = expand_vars(fnarg) + value = value:gsub("[/\\]", dir_sep) + elseif fn == "version" then + value = versions[fnarg:lower()] or "" + elseif fn == "version_" then + value = (versions[fnarg:lower()] or ""):gsub("[%.%-]", "_") + else + value = test_env.testing_paths[var] + or test_env.env_variables[var] + or test_env[var] + or "" + end + + return value + end)) + end + + if input:sub(#input, #input) ~= "\n" then + input = input .. "\n" + end + + for line in input:gmatch("([^\r\n]*)\r?\n?") do + cur_line = cur_line + 1 + + local state = stack[#stack] + if state == "start" then + local cmd, arg = parse_cmd(line) + if cmd == "TEST" then + start_test(arg) + elseif cmd == "SUITE" then + cur_suite = arg .. ": " + elseif cmd then + fail("expected TEST, got " .. cmd) + elseif is_blank(line) then + -- skip blank lines and arbitrary text, + -- which is interpreted as a comment + end + elseif state == "test" then + local cmd, arg = parse_cmd(line) + arg = expand_vars(arg) + if cmd == "FILE" then + cur_op = { + op = "FILE", + name = arg, + data = {}, + } + table.insert(cur_test.ops, cur_op) + cur_block = cur_op + cur_block_name = "FILE" + table.insert(stack, "block start") + elseif cmd == "FILE_CONTENTS" then + cur_op = { + op = "FILE_CONTENTS", + name = arg, + data = {}, + } + table.insert(cur_test.ops, cur_op) + cur_block = cur_op + cur_block_name = "FILE_CONTENTS" + table.insert(stack, "block start") + elseif cmd == "RUN" then + local program, args = arg:match("([^ ]+)%s*(.*)$") + if not program then + fail("expected a program argument in RUN") + end + + cur_op = { + op = "RUN", + exit = 0, + exit_line = cur_line, + line = cur_line, + program = program, + args = args, + } + table.insert(cur_test.ops, cur_op) + elseif cmd == "EXISTS" then + cur_op = { + op = "EXISTS", + name = dir.normalize(arg), + line = cur_line, + } + table.insert(cur_test.ops, cur_op) + elseif cmd == "NOT_EXISTS" then + cur_op = { + op = "NOT_EXISTS", + name = dir.normalize(arg), + line = cur_line, + } + table.insert(cur_test.ops, cur_op) + elseif cmd == "MKDIR" then + cur_op = { + op = "MKDIR", + name = dir.normalize(arg), + line = cur_line, + } + table.insert(cur_test.ops, cur_op) + elseif cmd == "RMDIR" then + cur_op = { + op = "RMDIR", + name = dir.normalize(arg), + line = cur_line, + } + table.insert(cur_test.ops, cur_op) + elseif cmd == "RM" then + cur_op = { + op = "RM", + name = dir.normalize(arg), + line = cur_line, + } + table.insert(cur_test.ops, cur_op) + elseif cmd == "EXIT" then + if not cur_op or cur_op.op ~= "RUN" then + fail("EXIT must be given in the context of a RUN") + end + + local code = tonumber(arg) + if not code and not (code >= 0 and code <= 128) then + fail("EXIT code must be a number in the range 0-128, got " .. arg) + end + + cur_op.exit = code + cur_op.exit_line = cur_line + elseif cmd == "VERBOSE" then + if not cur_op or cur_op.op ~= "RUN" then + fail("VERBOSE must be given in the context of a RUN") + end + + bool_arg("VERBOSE", cur_op, "verbose", arg) + elseif cmd == "STDERR" then + block_start_arg("STDERR", cur_op, "stderr") + elseif cmd == "NOT_STDERR" then + block_start_arg("NOT_STDERR", cur_op, "not_stderr") + elseif cmd == "STDOUT" then + block_start_arg("STDOUT", cur_op, "stdout") + elseif cmd == "NOT_STDOUT" then + block_start_arg("NOT_STDOUT", cur_op, "not_stdout") + elseif cmd == "PENDING" then + bool_arg("PENDING", cur_test, "pending", arg) + elseif cmd == "TEST" then + table.remove(stack) + start_test(arg) + elseif cmd then + fail("expected a command, got " .. cmd) + else + -- skip blank lines and arbitrary text, + -- which is interpreted as a comment + end + elseif state == "block start" then + local cmd, arg = parse_cmd(line) + if is_blank(line) then + -- skip + elseif is_hr(line) then + stack[#stack] = "block data" + cur_block.start = cur_line + elseif cmd == "PLAIN" then + bool_arg("PLAIN", cur_block, "plain", arg) + else + fail("expected '-----' to start " .. cur_block_name .. " block") + end + elseif state == "block data" then + if is_hr(line) then + cur_block = nil + table.remove(stack) + else + if not cur_block.plain then + line = expand_vars(line) + end + table.insert(cur_block.data, line) + end + end + end + + return tests +end + +local function check_output(write, block, block_name, data_var) + if block then + local is_positive = not block_name:match("NOT") + local err_msg = is_positive and "did not match" or "did match unwanted output" + + write([=[ do ]=]) + write([=[ local block_at = 1 ]=]) + write([=[ local s, e, line, ok ]=]) + for i, line in ipairs(block.data) do + write(([=[ line = %q ]=]):format(line)) + write(([=[ s, e = string.find(%s, line, block_at, true) ]=]):format(data_var)) + write(is_positive and ([=[ ok = s; if e then block_at = e + 1 end ]=]):format(i) + or ([=[ ok = not s ]=])) + write(([=[ assert(ok, error_message(%d, "%s %s: " .. line, %s)) ]=]):format(block.start + i, block_name, err_msg, data_var)) + end + write([=[ end ]=]) + end +end + +function quick.compile(filename, env) + local tests = parse(filename) + +-- local dev_null = (package.config:sub(1, 1) == "/") +-- and "/dev/null" +-- or "NUL" + + local cmd_helpers = { + ["luarocks"] = "luarocks_cmd", + ["luarocks-admin"] = "luarocks_admin_cmd", + } + + for tn, t in ipairs(tests) do + local code = {} + local function write(...) + table.insert(code, table.concat({...})) + end + + write(([=[ ]=])) + write(([=[ -- **************************************** ]=])) + write(([=[ -- %s ]=]):format(t.name)) + write(([=[ -- **************************************** ]=])) + write(([=[ ]=])) + + write([=[ local test_env = require("spec.util.test_env") ]=]) + write([=[ local lfs = require("lfs") ]=]) + write([=[ local fs = require("lfs") ]=]) + write([=[ local dir_sep = package.config:sub(1, 1) ]=]) + write([=[ local coverage = " -e \"require('luacov.runner')([[" .. test_env.testing_paths.testrun_dir .. dir_sep .. "luacov.config]])\" " ]=]) + write([=[ local luarocks_cmd = test_env.execute_helper(test_env.Q(test_env.testing_paths.lua) .. coverage .. " " .. test_env.testing_paths.src_dir .. "/bin/luarocks", false, test_env.env_variables):sub(1, -5) ]=]) + write([=[ local luarocks_admin_cmd = test_env.execute_helper(test_env.Q(test_env.testing_paths.lua) .. coverage .. " " .. test_env.testing_paths.src_dir .. "/bin/luarocks-admin", false, test_env.env_variables):sub(1, -5) ]=]) + + write([=[ local function make_dir(dirname) ]=]) + write([=[ local bits = {} ]=]) + write([=[ if dirname:sub(1, 1) == dir_sep then bits[1] = "" end ]=]) + write([=[ local ok, err ]=]) + write([=[ for p in dirname:gmatch("[^" .. dir_sep .. "]+") do ]=]) + write([=[ table.insert(bits, p) ]=]) + write([=[ ok, err = lfs.mkdir(table.concat(bits, dir_sep)) ]=]) + write([=[ end ]=]) + write([=[ local exists = (lfs.attributes(dirname) or {}).mode == "directory" ]=]) + write([=[ return exists, (not exists) and err ]=]) + write([=[ end ]=]) + + write(([=[ local function error_message(line, msg, input) ]=])) + write(([=[ local out = {"\n\n", %q, ":", line, ": ", msg} ]=]):format(filename)) + write(([=[ if input then ]=])) + write(([=[ if input:match("\n") then ]=])) + write(([=[ table.insert(out, "\n") ]=])) + write(([=[ table.insert(out, ("-"):rep(40)) ]=])) + write(([=[ table.insert(out, "\n") ]=])) + write(([=[ table.insert(out, input) ]=])) + write(([=[ table.insert(out, ("-"):rep(40)) ]=])) + write(([=[ table.insert(out, "\n") ]=])) + write(([=[ else ]=])) + write(([=[ table.insert(out, ": ") ]=])) + write(([=[ table.insert(out, input) ]=])) + write(([=[ end ]=])) + write(([=[ end ]=])) + write(([=[ return table.concat(out) ]=])) + write(([=[ end ]=])) + + write([=[ return function() ]=]) + write([=[ test_env.run_in_tmp(function(tmpdir) ]=]) + write([=[ local function handle_tmpdir(s) ]=]) + write([=[ return (s:gsub("%%{url%(%%{tmpdir}%)}", (tmpdir:gsub("\\", "/"))) ]=]) + write([=[ :gsub("%%{tmpdir}", (tmpdir:gsub("[\\/]", dir_sep)))) ]=]) + write([=[ end ]=]) + write([=[ local ok, err ]=]) + for _, op in ipairs(t.ops) do + if op.name then + op.name = native_slash(op.name) + write(([=[ local name = handle_tmpdir(%q) ]=]):format(op.name)) + end + if op.op == "FILE" then + if op.name:match("[\\/]") then + write(([=[ make_dir(handle_tmpdir(%q)) ]=]):format(dir.dir_name(op.name))) + end + write([=[ test_env.write_file(name, handle_tmpdir([=====[ ]=]) + for _, line in ipairs(op.data) do + write(line) + end + write([=[ ]=====]), finally) ]=]) + elseif op.op == "EXISTS" then + write(([=[ ok, err = lfs.attributes(name) ]=])) + write(([=[ assert.truthy(ok, error_message(%d, "EXISTS failed: " .. name .. " - " .. (err or "") )) ]=]):format(op.line)) + elseif op.op == "NOT_EXISTS" then + write(([=[ assert.falsy(lfs.attributes(name), error_message(%d, "NOT_EXISTS failed: " .. name .. " exists" )) ]=]):format(op.line)) + elseif op.op == "MKDIR" then + write(([=[ ok, err = make_dir(name) ]=])) + write(([=[ assert.truthy((lfs.attributes(name) or {}).mode == "directory", error_message(%d, "MKDIR failed: " .. name .. " - " .. (err or "") )) ]=]):format(op.line)) + elseif op.op == "RMDIR" then + write(([=[ ok, err = test_env.remove_dir(name) ]=])) + write(([=[ assert.falsy((lfs.attributes(name) or {}).mode == "directory", error_message(%d, "MKDIR failed: " .. name .. " - " .. (err or "") )) ]=]):format(op.line)) + elseif op.op == "RM" then + write(([=[ ok, err = os.remove(name) ]=])) + write(([=[ assert.falsy((lfs.attributes(name) or {}).mode == "file", error_message(%d, "RM failed: " .. name .. " - " .. (err or "") )) ]=]):format(op.line)) + elseif op.op == "FILE_CONTENTS" then + write(([=[ do ]=])) + write(([=[ local fd_file = assert(io.open(name, "rb")) ]=])) + write(([=[ local file_data = fd_file:read("*a") ]=])) + write(([=[ fd_file:close() ]=])) + write([=[ local block_at = 1 ]=]) + write([=[ local s, e, line ]=]) + for i, line in ipairs(op.data) do + write(([=[ line = %q ]=]):format(line)) + write(([=[ s, e = string.find(file_data, line, 1, true) ]=])) + write(([=[ assert(s, error_message(%d, "FILE_CONTENTS " .. name .. " did not match: " .. line, file_data)) ]=]):format(op.start + i)) + write(([=[ block_at = e + 1 ]=]):format(i)) + end + write([=[ end ]=]) + elseif op.op == "RUN" then + local cmd_helper = cmd_helpers[op.program] or ("%q"):format(op.program) + local redirs = " 1>stdout.txt 2>stderr.txt " + write(([=[ local ok, _, code = os.execute(%s .. " " .. %q .. %q) ]=]):format(cmd_helper, op.args, redirs)) + write([=[ if type(ok) == "number" then code = (ok >= 256 and ok / 256 or ok) end ]=]) + + write([=[ local fd_stderr = assert(io.open("stderr.txt", "rb")) ]=]) + write([=[ local stderr_data = fd_stderr:read("*a") ]=]) + write([=[ fd_stderr:close() ]=]) + + write([=[ if stderr_data:match("please report") then ]=]) + write(([=[ assert(false, error_message(%d, "RUN crashed: ", stderr_data)) ]=]):format(op.line)) + write([=[ end ]=]) + + if op.stdout or op.not_stdout or op.verbose then + write([=[ local fd_stdout = assert(io.open("stdout.txt", "rb")) ]=]) + write([=[ local stdout_data = fd_stdout:read("*a") ]=]) + write([=[ fd_stdout:close() ]=]) + end + + if op.verbose then + write([=[ print() ]=]) + write([=[ print("STDOUT: --" .. ("-"):rep(70)) ]=]) + write([=[ print(stdout_data) ]=]) + write([=[ print("STDERR: --" .. ("-"):rep(70)) ]=]) + write([=[ print(stderr_data) ]=]) + write([=[ print(("-"):rep(80)) ]=]) + write([=[ print() ]=]) + end + + check_output(write, op.stdout, "STDOUT", "stdout_data") + check_output(write, op.stderr, "STDERR", "stderr_data") + + check_output(write, op.not_stdout, "NOT_STDOUT", "stdout_data") + check_output(write, op.not_stderr, "NOT_STDERR", "stderr_data") + + if op.exit then + write(([=[ assert.same(%d, code, error_message(%d, "EXIT did not match: " .. %d, stderr_data)) ]=]):format(op.exit, op.exit_line, op.exit)) + end + end + end + write([=[ end, finally) ]=]) + write([=[ end ]=]) + + local program = table.concat(code, "\n") + local chunk = assert(load(program, "@" .. filename .. ":[TEST " .. tn .. "]", "t", env or _ENV)) + if env and setfenv then + setfenv(chunk, env) + end + t.fn = chunk() + end + + return tests +end + +return quick diff --git a/spec/util/test_env.lua b/spec/util/test_env.lua new file mode 100644 index 0000000..92fb193 --- /dev/null +++ b/spec/util/test_env.lua @@ -0,0 +1,1187 @@ +local test_env = {} + +local lfs = require("lfs") +local versions = require("spec.util.versions") + +local help_message = [[ +LuaRocks test-suite + +INFORMATION + New test-suite for LuaRocks project, using unit testing framework Busted. +REQUIREMENTS + Be sure sshd is running on your system, or use '--exclude-tags=ssh', + to not execute tests which require sshd. +USAGE + busted [-Xhelper <arguments>] +ARGUMENTS + env=<type> Set type of environment to use ("minimal" or "full", + default: "minimal"). + noreset Don't reset environment after each test + clean Remove existing testing environment. + ci Add if running on Unix CI. + appveyor Add if running on Appveyor. + os=<type> Set OS ("linux", "osx", or "windows"). + lua_dir=<path> Path of Lua installation (default "/usr/local") + lua=<lua> Name of the interpreter, may be full path (default "lua") +]] + +local function help() + print(help_message) + os.exit(1) +end + +local function title(str) + print() + print(("-"):rep(#str)) + print(str) + print(("-"):rep(#str)) +end + +local dir_sep = package.config:sub(1, 1) +local function P(p) + return (p:gsub("/", dir_sep)) +end + +local function dir_path(...) + return P((table.concat({ ... }, "/"):gsub("\\", "/"):gsub("/+", "/"))) +end + +local function C(...) + return table.concat({...}, " ") +end + +--- Quote argument for shell processing. Fixes paths on Windows. +-- Adds double quotes and escapes. Based on function in fs/win32.lua. +-- @param arg string: Unquoted argument. +-- @return string: Quoted argument. +local function Q(arg) + if test_env.TEST_TARGET_OS == "windows" then + local drive_letter = "[%.a-zA-Z]?:?[\\/]" + -- Quote DIR for Windows + if arg:match("^"..drive_letter) then + arg = P(arg) + end + + if arg == "\\" then + return '\\' -- CHDIR needs special handling for root dir + end + + return '"' .. arg .. '"' + else + return "'" .. arg:gsub("'", "'\\''") .. "'" + end +end + +local function V(str) + return (str:gsub("${([^}]-)}", function(name) + name = name:lower() + local prefix, suffix = name:match("^(.*)_(.)$") + if suffix then + name = prefix + local d = assert(versions[name]) + local v, r = d:match("^([^-]*)%-(%d*)$") + if suffix == "d" then + return d + elseif suffix == "v" then + return v + elseif suffix == "r" then + return r + else + print("Test error: invalid suffix " .. suffix .. " in variable " .. name) + os.exit(1) + end + else + if not versions[name] then + print("Test error: no version definition for " .. name) + os.exit(1) + end + return versions[name] + end + end)) +end + +local function tool(name) + if test_env.TEST_TARGET_OS == "windows" then + return Q(dir_path(test_env.testing_paths.win_tools, name .. ".exe")) + else + return name + end +end + +local os_remove = os.remove +os.remove = function(f) -- luacheck: ignore + return os_remove(V(f)) +end + +local os_rename = os.rename +os.rename = function(a, b) -- luacheck: ignore + return os_rename(V(a), V(b)) +end + +-- Monkeypatch incorrect tmpname's on some Lua distributions for Windows +local os_tmpname = os.tmpname +os.tmpname = function() -- luacheck:ignore + local name = os_tmpname() + if name:sub(1, 1) == '\\' then + name = os.getenv "TEMP"..name + end + return name +end + +local lfs_chdir = lfs.chdir +lfs.chdir = function(d) -- luacheck: ignore + return lfs_chdir(V(d)) +end + +local lfs_attributes = lfs.attributes +lfs.attributes = function(f, ...) -- luacheck: ignore + return lfs_attributes(V(f), ...) +end + +local function exists(path) + return lfs.attributes(path, "mode") ~= nil +end + +function test_env.file_if_exists(path) + return lfs.attributes(path, "mode") and path +end + +function test_env.quiet(command) + if not test_env.VERBOSE then + if test_env.TEST_TARGET_OS == "windows" then + return command .. " 1> NUL 2> NUL" + else + return command .. " 1> /dev/null 2> /dev/null" + end + else + return command + end +end + +function test_env.copy(source, destination) + source = V(source) + destination = V(destination) + + local r_source, r_destination, err + r_source, err = io.open(source, "r") + if err then + print(debug.traceback()) + os.exit(1) + end + + r_destination, err = io.open(destination, "w") + if err then + print(debug.traceback()) + os.exit(1) + end + + while true do + local block = r_source:read(8192) + if not block then break end + r_destination:write(block) + end + + r_source:close() + r_destination:close() +end + +function test_env.get_tmp_path() + local path = os.tmpname() + if test_env.TEST_TARGET_OS == "windows" and not path:find(":") then + path = dir_path(os.getenv("TEMP"), path) + end + os.remove(path) + return path +end + +--- Helper function that runs the given function inside +-- a temporary directory, isolating it +-- @param f function: the function to be run +function test_env.run_in_tmp(f, finally) + local olddir = lfs.currentdir() + local tmpdir = test_env.get_tmp_path() + lfs.mkdir(tmpdir) + lfs.chdir(tmpdir) + + if not finally then + error("run_in_tmp needs a finally argument") + end + + -- for unit tests, so that current dir known by luarocks.fs (when running with non-lfs) + -- is synchronized with actual lfs (system) current dir + local fs = require("luarocks.fs") + if not fs.change_dir then + local cfg = require("luarocks.core.cfg") + cfg.init() + fs.init() + end + fs.change_dir(tmpdir) + + local lr_config = test_env.env_variables.LUAROCKS_CONFIG + + test_env.copy(lr_config, lr_config .. ".bak") + + finally(function() + test_env.copy(lr_config .. ".bak", lr_config) + lfs.chdir(olddir) + lfs.rmdir(tmpdir) + fs.change_dir(olddir) + end) + + f(tmpdir) +end + +--- Helper function for execute_bool and execute_output +-- @param command string: command to execute +-- @param print_command boolean: print command if 'true' +-- @param env_variables table: table of environment variables to export {FOO="bar", BAR="foo"} +-- @return final_command string: concatenated command to execution +function test_env.execute_helper(command, print_command, env_variables) + local final_command = "" + + if print_command then + print("[EXECUTING]: " .. command) + end + + local unset_variables = { + "LUA_PATH", + "LUA_CPATH", + "LUA_PATH_5_2", + "LUA_CPATH_5_2", + "LUA_PATH_5_3", + "LUA_CPATH_5_3", + "LUAROCKS_SYSCONFDIR", + } + + if env_variables then + if test_env.TEST_TARGET_OS == "windows" then + for _, k in ipairs(unset_variables) do + final_command = final_command .. "set " .. k .. "=&" + end + for k,v in pairs(env_variables) do + final_command = final_command .. "set " .. k .. "=" .. v .. "&" + end + final_command = final_command:sub(1, -2) .. "&" + else + for _, k in ipairs(unset_variables) do + final_command = final_command .. "unset " .. k .. "; " + end + final_command = final_command .. "export " + for k,v in pairs(env_variables) do + final_command = final_command .. k .. "='" .. v .. "' " + end + -- remove last space and add ';' to separate exporting variables from command + final_command = final_command:sub(1, -2) .. "; " + end + end + + final_command = final_command .. command .. " 2>&1" + + return final_command +end + +function test_env.execute(cmd) + local ok = os.execute(cmd) + return (ok == true or ok == 0) -- normalize Lua 5.1 output to boolean +end + +--- Execute command and returns true/false +-- @return true/false boolean: status of the command execution +local function execute_bool(command, print_command, env_variables) + command = test_env.execute_helper(command, print_command, env_variables) + + local redirect_filename + local redirect = "" + if print_command ~= nil then + redirect_filename = dir_path(test_env.testing_paths.luarocks_tmp, "output.txt") + redirect = " > " .. redirect_filename + os.remove(redirect_filename) + end + local ok = test_env.execute(command .. redirect) + if redirect ~= "" then + if not ok or test_env.VERBOSE then + local fd = io.open(redirect_filename, "r") + if fd then + print(fd:read("*a")) + fd:close() + end + end + os.remove(redirect_filename) + end + return ok +end + +--- Execute command and returns output of command +-- @return output string: output the command execution +local function execute_output(command, print_command, env_variables) + command = test_env.execute_helper(command, print_command, env_variables) + + local file = assert(io.popen(command)) + local output = file:read('*all') + file:close() + return (output:gsub("\r\n", "\n"):gsub("\n$", "")) -- remove final newline +end + +--- Set test_env.LUA_V or test_env.LUAJIT_V based +-- on version of Lua used to run this script. +function test_env.set_lua_version() + if _G.jit then + test_env.LUAJIT_V = _G.jit.version:match("(2%.%d)%.%d") + test_env.lua_version = "5.1" + else + test_env.LUA_V = _VERSION:match("5%.%d") + test_env.lua_version = test_env.LUA_V + end +end + +--- Set all arguments from input into global variables +function test_env.set_args() + -- if at least Lua/LuaJIT version argument was found on input start to parse other arguments to env. variables + test_env.TYPE_TEST_ENV = "minimal" + test_env.RESET_ENV = true + + for _, argument in ipairs(arg) do + if argument:find("^env=") then + test_env.TYPE_TEST_ENV = argument:match("^env=(.*)$") + elseif argument == "noreset" then + test_env.RESET_ENV = false + elseif argument == "clean" then + test_env.TEST_ENV_CLEAN = true + elseif argument == "verbose" then + test_env.VERBOSE = true + elseif argument == "ci" then + test_env.CI = true + elseif argument == "appveyor" then + test_env.APPVEYOR = true + elseif argument:find("^os=") then + test_env.TEST_TARGET_OS = argument:match("^os=(.*)$") + elseif argument == "mingw" then + test_env.MINGW = true + elseif argument == "vs" then + test_env.MINGW = false + elseif argument:find("^lua_dir=") then + test_env.LUA_DIR = argument:match("^lua_dir=(.*)$") + elseif argument:find("^lua=") then + test_env.LUA = argument:match("^lua=(.*)$") + else + help() + end + end + + if not test_env.TEST_TARGET_OS then + title("OS CHECK") + + if dir_sep == "\\" then + test_env.TEST_TARGET_OS = "windows" + if test_env.APPVEYOR then + test_env.OPENSSL_INCDIR = "C:\\OpenSSL-v111-Win32\\include" + test_env.OPENSSL_LIBDIR = "C:\\OpenSSL-v111-Win32\\lib" + if test_env.MINGW then + test_env.OPENSSL_LIBDIR = "C:\\OpenSSL-v111-Win32\\bin" + end + end + else + local system = execute_output("uname -s") + if system == "Linux" then + test_env.TEST_TARGET_OS = "linux" + if test_env.CI then + test_env.OPENSSL_INCDIR = "/usr/include" + test_env.OPENSSL_LIBDIR = "/usr/lib/x86_64-linux-gnu" + end + elseif system == "Darwin" then + test_env.TEST_TARGET_OS = "osx" + if test_env.CI then + if exists("/opt/homebrew/opt/openssl@3/include") then + test_env.OPENSSL_INCDIR = "/opt/homebrew/opt/openssl@3/include" + test_env.OPENSSL_LIBDIR = "/opt/homebrew/opt/openssl@3/lib" + elseif exists("/opt/homebrew/opt/openssl@1.1/include") then + test_env.OPENSSL_INCDIR = "/opt/homebrew/opt/openssl@1.1/include" + test_env.OPENSSL_LIBDIR = "/opt/homebrew/opt/openssl@1.1/lib" + elseif exists("/opt/homebrew/opt/openssl/include") then + test_env.OPENSSL_INCDIR = "/opt/homebrew/opt/openssl/include" + test_env.OPENSSL_LIBDIR = "/opt/homebrew/opt/openssl/lib" + else + test_env.OPENSSL_INCDIR = "/usr/local/opt/openssl/include" + test_env.OPENSSL_LIBDIR = "/usr/local/opt/openssl/lib" + end + end + end + end + print(test_env.TEST_TARGET_OS) + end + + if test_env.TEST_TARGET_OS == "windows" then + test_env.lib_extension = "dll" + else + test_env.lib_extension = "so" + end + + test_env.openssl_dirs = "" + if test_env.OPENSSL_INCDIR then + test_env.openssl_dirs = C("OPENSSL_INCDIR=" .. test_env.OPENSSL_INCDIR, + "OPENSSL_LIBDIR=" .. test_env.OPENSSL_LIBDIR) + end + + return true +end + +function test_env.copy_dir(source_path, target_path) + source_path = V(source_path) + target_path = V(target_path) + + local flag = test_env.TEST_TARGET_OS == "windows" and "-R" or "-a" + os.execute(C(tool("cp"), flag, dir_path(source_path, "."), target_path)) +end + +--- Remove directory recursively +-- @param path string: directory path to delete +function test_env.remove_dir(path) + path = V(path) + + if exists(path) then + for file in lfs.dir(path) do + if file ~= "." and file ~= ".." then + local full_path = dir_path(path, file) + + if lfs.attributes(full_path, "mode") == "directory" then + test_env.remove_dir(full_path) + else + os.remove(full_path) + end + end + end + end + lfs.rmdir(path) +end + +--- Remove subdirectories of a directory that match a pattern +-- @param path string: path to directory +-- @param pattern string: pattern matching basenames of subdirectories to be removed +function test_env.remove_subdirs(path, pattern) + path = V(path) + + if exists(path) then + for file in lfs.dir(path) do + if file ~= "." and file ~= ".." then + local full_path = dir_path(path, file) + + if lfs.attributes(full_path, "mode") == "directory" and file:find(pattern) then + test_env.remove_dir(full_path) + end + end + end + end +end + +--- Remove files matching a pattern +-- @param path string: directory where to delete files +-- @param pattern string: pattern matching basenames of files to be deleted +-- @return result_check boolean: true if one or more files deleted +function test_env.remove_files(path, pattern) + path = V(path) + + local result_check = false + if exists(path) then + for file in lfs.dir(path) do + if file ~= "." and file ~= ".." then + if file:find(pattern) then + if os.remove(dir_path(path, file)) then + result_check = true + end + end + end + end + end + return result_check +end + + +--- Function for downloading rocks and rockspecs +-- @param urls table: array of full names of rocks/rockspecs to download +-- @param save_path string: path to directory, where to download rocks/rockspecs +-- @return make_manifest boolean: true if new rocks downloaded +local function download_rocks(urls, save_path) + local luarocks_repo = "https://luarocks.org/" + + local to_download = {} + local fixtures = {} + for _, url in ipairs(urls) do + url = V(url) + + if url:match("^spec/fixtures") then + table.insert(fixtures, P(url:gsub("^spec/fixtures", test_env.testing_paths.fixtures_dir))) + else + -- check if already downloaded + if not exists(dir_path(save_path, url)) then + table.insert(to_download, ((luarocks_repo .. url):gsub("org//", "org/"))) + end + end + end + + if #fixtures > 0 then + os.execute(C(tool("cp"), table.concat(fixtures, " "), save_path)) + end + + if #to_download > 0 then + local ok = execute_bool(C(tool("wget"), "--no-check-certificate -cP", save_path, table.concat(to_download, " "))) + if not ok then + os.exit(1) + end + end + + return (#fixtures > 0) or (#to_download > 0) +end + +--- Create a file containing a string. +-- @param pathname string: path to file. +-- @param str string: content of the file. +function test_env.write_file(pathname, str, finally) + pathname = V(pathname) + + local file = assert(io.open(pathname, "wb")) + file:write(str) + file:close() + if finally then + finally(function() + os.remove(pathname) + end) + end +end + +--- Create environment variables needed for tests +-- @param testing_paths table: table with paths to testing directory +-- @return env_variables table: table with created environment variables +local function create_env(testing_paths) + local lua_v = _VERSION:gsub("Lua ", "") + local testrun_dir = test_env.testing_paths.testrun_dir + local lrprefix = testing_paths.testing_lrprefix + local tree = testing_paths.testing_tree + local sys_tree = testing_paths.testing_sys_tree + local deps_tree = testing_paths.testing_deps_tree + + if test_env.LUAJIT_V then + lua_v="5.1" + end + + local env_variables = {} + env_variables.GNUPGHOME = testing_paths.gpg_dir + env_variables.LUA_VERSION = lua_v + env_variables.LUAROCKS_CONFIG = dir_path(testrun_dir, "testing_config.lua") + + local lua_path = {} + if test_env.TEST_TARGET_OS == "windows" then + table.insert(lua_path, dir_path(lrprefix, "lua", "?.lua")) + else + table.insert(lua_path, dir_path(lrprefix, "share", "lua", lua_v, "?.lua")) + end + table.insert(lua_path, dir_path(tree, "share", "lua", lua_v, "?.lua")) + table.insert(lua_path, dir_path(tree, "share", "lua", lua_v, "?", "init.lua")) + table.insert(lua_path, dir_path(sys_tree, "share", "lua", lua_v, "?.lua")) + table.insert(lua_path, dir_path(sys_tree, "share", "lua", lua_v, "?", "init.lua")) + table.insert(lua_path, dir_path(deps_tree, "share", "lua", lua_v, "?.lua")) + table.insert(lua_path, dir_path(deps_tree, "share", "lua", lua_v, "?", "init.lua")) + table.insert(lua_path, dir_path(testing_paths.src_dir, "?.lua")) + env_variables.LUA_PATH = table.concat(lua_path, ";") .. ";" + + local lua_cpath = {} + local lib_pattern = "?." .. test_env.lib_extension + table.insert(lua_cpath, dir_path(tree, "lib", "lua", lua_v, lib_pattern)) + table.insert(lua_cpath, dir_path(sys_tree, "lib", "lua", lua_v, lib_pattern)) + table.insert(lua_cpath, dir_path(deps_tree, "lib", "lua", lua_v, lib_pattern)) + env_variables.LUA_CPATH = table.concat(lua_cpath, ";") .. ";" + + local path = { os.getenv("PATH") } + table.insert(path, dir_path(tree, "bin")) + table.insert(path, dir_path(sys_tree, "bin")) + table.insert(path, dir_path(deps_tree, "bin")) + env_variables.PATH = table.concat(path, test_env.TARGET_OS == "windows" and ";" or ":") + + return env_variables +end + +local function make_run_function(cmd_name, exec_function, with_coverage, do_print) + local cmd_prefix = Q(test_env.testing_paths.lua) + local testrun_dir = test_env.testing_paths.testrun_dir + + if with_coverage then + cmd_prefix = C(cmd_prefix, "-e", "\"require('luacov.runner')([[" .. testrun_dir .. "/luacov.config]])\"") + end + + if cmd_name then + cmd_prefix = C(cmd_prefix, dir_path(test_env.testing_paths.src_dir, "bin", cmd_name)) + end + + cmd_prefix = P(cmd_prefix) + + return function(cmd, new_vars) + cmd = V(cmd) + local temp_vars = {} + for k, v in pairs(test_env.env_variables) do + temp_vars[k] = v + end + if new_vars then + for k, v in pairs(new_vars) do + temp_vars[k] = v + end + end + return exec_function(C(cmd_prefix, cmd), do_print, temp_vars) + end +end + +local function make_run_functions() + local fns = {} + + local cmds = { + ["lua"] = nil, + ["luarocks"] = "luarocks", + ["luarocks_admin"] = "luarocks-admin", + } + + for _, name in ipairs({"lua", "luarocks", "luarocks_admin"}) do + fns[name] = make_run_function(cmds[name], execute_output, true, true) + fns[name .. "_bool"] = make_run_function(cmds[name], execute_bool, true, true) + fns[name .. "_nocov"] = make_run_function(cmds[name], execute_bool, false, true) + fns[name .. "_noprint_nocov"] = make_run_function(cmds[name], execute_bool, false, false) + end + + return fns +end + +local function move_file(src, dst) + local ok = execute_bool(C(tool("mv"), P(src), P(dst))) + if not ok then + print(debug.traceback()) + os.exit(1) + end +end + +--- Rebuild environment. +-- Remove old installed rocks and install new ones, +-- updating manifests and tree copies. +local function build_environment(rocks, env_variables) + title("BUILDING ENVIRONMENT") + local testing_paths = test_env.testing_paths + test_env.remove_dir(testing_paths.testing_tree) + test_env.remove_dir(testing_paths.testing_sys_tree) + + lfs.mkdir(testing_paths.testing_tree) + lfs.mkdir(testing_paths.testing_sys_tree) + lfs.mkdir(testing_paths.testing_deps_tree) + + test_env.run.luarocks_admin_nocov(C("make_manifest", Q(testing_paths.testing_server))) + test_env.run.luarocks_admin_nocov(C("make_manifest", Q(testing_paths.testing_cache))) + + for _, rock in ipairs(rocks) do + local only_server = "--only-server=" .. testing_paths.testing_cache + local tree = "--tree=" .. testing_paths.testing_deps_tree + if not test_env.run.luarocks_nocov(test_env.quiet(C("install", only_server, tree, Q(rock)), env_variables)) then + assert(test_env.run.luarocks_nocov(C("build", tree, Q(rock)), env_variables)) + assert(test_env.run.luarocks_nocov(C("pack", tree, Q(rock)), env_variables)) + move_file(rock .. "-*.rock", testing_paths.testing_cache) + end + end +end + +local function find_lua() + -- (1) LUA is a full path + if test_env.LUA and test_env.LUA:match("[/\\]") then + + local lua_bindir = test_env.LUA:match("^(.-)[/\\][^/\\]*$") + local luadir = test_env.LUA_DIR or lua_bindir:gsub("[/\\]bin$") + local lua = test_env.LUA + + return lua_bindir, luadir, lua + end + + -- (2) LUA is just the interpreter name + local lua_exe = test_env.LUA + or ((test_env.TEST_TARGET_OS == "windows") and "lua.exe") + or "lua" + + -- (2.1) LUA_DIR was given + if test_env.LUA_DIR then + + local luadir = test_env.LUA_DIR + local lua_bindir = exists(dir_path(luadir, "bin")) + and dir_path(luadir, "bin") + or luadir + local lua = dir_path(lua_bindir, lua_exe) + + return lua_bindir, luadir, lua + end + + -- (2.2) LUA_DIR was not given, try some default paths + local try_dirs = (test_env.TEST_TARGET_OS == "windows") + and { os.getenv("ProgramFiles(x86)").."\\LuaRocks" } + or { "/usr/local", "/usr" } + + for _, luadir in ipairs(try_dirs) do + for _, lua_bindir in ipairs({ luadir, dir_path(luadir, "bin") }) do + local lua = dir_path(lua_bindir, lua_exe) + if exists(lua) then + return lua_bindir, luadir, lua + end + end + end +end + +local function create_testing_paths(suffix) + local paths = {} + + paths.lua_bindir, paths.luadir, paths.lua = find_lua() + if (not paths.lua) or (not exists(paths.lua)) then + error("Lua interpreter not found! Run `busted -Xhelper help` for options") + end + + local base_dir = lfs.currentdir() + paths.src_dir = dir_path(base_dir, "src") + paths.spec_dir = dir_path(base_dir, "spec") + paths.util_dir = dir_path(base_dir, "spec", "util") + paths.fixtures_dir = dir_path(base_dir, "spec", "fixtures") + paths.fixtures_repo_dir = dir_path(base_dir, "spec", "fixtures", "a_repo") + paths.gpg_dir = dir_path(base_dir, "spec", "fixtures", "gpg") + + local testrun_dir = dir_path(base_dir, "testrun") + paths.testrun_dir = testrun_dir + paths.testing_lrprefix = dir_path(testrun_dir, "testing_lrprefix-" .. suffix) + paths.testing_tree = dir_path(testrun_dir, "testing-" .. suffix) + paths.testing_sys_tree = dir_path(testrun_dir, "testing_sys-" .. suffix) + paths.testing_deps_tree = dir_path(testrun_dir, "testing_deps-" .. suffix) + paths.testing_cache = dir_path(testrun_dir, "testing_cache-" .. suffix) + paths.testing_server = dir_path(testrun_dir, "testing_server-" .. suffix) + + local rocks_v = "rocks-" .. test_env.lua_version + paths.testing_rocks = dir_path(paths.testing_tree, "lib", "luarocks", rocks_v) + paths.testing_sys_rocks = dir_path(paths.testing_sys_tree, "lib", "luarocks", rocks_v) + paths.testing_deps_rocks = dir_path(paths.testing_deps_tree, "lib", "luarocks", rocks_v) + + if test_env.TEST_TARGET_OS == "windows" then + paths.luarocks_tmp = os.getenv("TEMP") + else + paths.luarocks_tmp = "/tmp/luarocks_testing" + end + + if test_env.TEST_TARGET_OS == "windows" then + paths.win_tools = dir_path(base_dir, "win32", "tools") + end + + return paths +end + +--- Helper function to unload luarocks modules from global table package.loaded +-- Needed to load our local (testing) version of LuaRocks +function test_env.unload_luarocks() + for modname, _ in pairs(package.loaded) do + if modname:match("^luarocks%.") then + package.loaded[modname] = nil + end + end + local src_pattern = dir_path(test_env.testing_paths.src_dir, "?.lua") + if not package.path:find(src_pattern, 1, true) then + package.path = src_pattern .. ";" .. package.path + end +end + +local function get_luarocks_platform(variables) + local print_arch_script = "\"" .. + "cfg = require('luarocks.core.cfg');" .. + "cfg.init();" .. + "print(cfg.arch)" .. + "\"" + local cmd = C(test_env.testing_paths.lua, "-e", print_arch_script) + return execute_output(cmd, false, variables) +end + +--- Test if required rock is installed and if not, install it. +-- Return `true` if the rock is already installed or has been installed successfully, +-- `false` if installation failed. +function test_env.need_rock(rock) + rock = V(rock) + + print("Check if " .. rock .. " is installed") + if test_env.run.luarocks_noprint_nocov(test_env.quiet("show " .. rock)) then + return true + else + local ok = test_env.run.luarocks_noprint_nocov(test_env.quiet("install " .. rock)) + if not ok then + print("WARNING: failed installing " .. rock) + end + return ok + end +end + +--- For each key-value pair in replacements table +-- replace %{key} in given string with value. +local function substitute(str, replacements) + return (str:gsub("%%%b{}", function(marker) + local r = replacements[marker:sub(3, -2)] + if r then + r = r:gsub("\\", "\\\\") + end + return r + end)) +end + + +--- Create configs for luacov and several versions of Luarocks +-- configs needed for some tests. +local function create_configs() + local testrun_dir = test_env.testing_paths.testrun_dir + + -- testing_config.lua + -- testing_config_show_downloads.lua + -- testing_config_no_downloader.lua + local config_content = substitute([[ + rocks_trees = { + { name = "user", root = "%{testing_tree}" }, + { name = "deps", root = "%{testing_deps_tree}" }, + { name = "system", root = "%{testing_sys_tree}" }, + } + rocks_servers = { + "%{testing_server}" + } + local_cache = "%{testing_cache}" + upload_server = "testing" + upload_user = "%{user}" + upload_servers = { + testing = { + rsync = "localhost/tmp/luarocks_testing", + }, + } + ]], { + user = "testuser", + testing_sys_tree = test_env.testing_paths.testing_sys_tree, + testing_deps_tree = test_env.testing_paths.testing_deps_tree, + testing_tree = test_env.testing_paths.testing_tree, + testing_server = test_env.testing_paths.testing_server, + testing_cache = test_env.testing_paths.testing_cache + }) + + test_env.write_file(dir_path(testrun_dir, "testing_config.lua"), config_content .. " \nweb_browser = \"true\"") + test_env.write_file(dir_path(testrun_dir, "testing_config_show_downloads.lua"), config_content + .. "show_downloads = true \n rocks_servers={\"http://luarocks.org/repositories/rocks\"}") + test_env.write_file(dir_path(testrun_dir, "testing_config_no_downloader.lua"), config_content + .. "variables = { WGET = 'invalid', CURL = 'invalid' }") + + -- testing_config_sftp.lua + config_content = substitute([[ + rocks_trees = { + "%{testing_tree}", + "%{testing_deps_tree}", + "%{testing_sys_tree}", + } + local_cache = "%{testing_cache}" + upload_server = "testing" + upload_user = "%{user}" + upload_servers = { + testing = { + sftp = "localhost/tmp/luarocks_testing", + }, + } + ]], { + user = "testuser", + testing_sys_tree = test_env.testing_paths.testing_sys_tree, + testing_deps_tree = test_env.testing_paths.testing_deps_tree, + testing_tree = test_env.testing_paths.testing_tree, + testing_cache = test_env.testing_paths.testing_cache + }) + + test_env.write_file(dir_path(testrun_dir, "testing_config_sftp.lua"), config_content) + + -- luacov.config + config_content = substitute([[ + return { + statsfile = "%{statsfile}", + reportfile = "%{reportfile}", + exclude = { + "src%/luarocks%/vendor.+$", + }, + modules = { + ["luarocks"] = "%{luarocks_path}", + ["luarocks-admin"] = "%{luarocks_admin_path}", + ["luarocks.*"] = "src", + ["luarocks.*.*"] = "src", + ["luarocks.*.*.*"] = "src" + } + } + ]], { + statsfile = dir_path(testrun_dir, "luacov.stats.out"), + reportfile = dir_path(testrun_dir, "luacov.report.out"), + luarocks_path = dir_path("src", "bin", "luarocks"), + luarocks_admin_path = dir_path("src", "bin", "luarocks-admin"), + }) + + test_env.write_file(dir_path(testrun_dir, "luacov.config"), config_content) + + config_content = [[ + -- Config file of mock LuaRocks.org site for tests + upload = { + server = "http://localhost:8080", + tool_version = "1.0.0", + api_version = "1", + } + ]] + test_env.write_file(dir_path(testrun_dir, "luarocks_site.lua"), config_content) +end + +--- Remove testing directories. +local function clean() + local testrun_dir = test_env.testing_paths.testrun_dir + + print("Cleaning testing directory...") + test_env.remove_dir(test_env.testing_paths.luarocks_tmp) + test_env.remove_subdirs(testrun_dir, "testing[_%-]") + test_env.remove_files(testrun_dir, "testing_") + test_env.remove_files(testrun_dir, "luacov") + test_env.remove_files(testrun_dir, "upload_config") + test_env.remove_files(testrun_dir, "luarocks_site") + print("Cleaning done!") +end + +--- Setup current checkout of luarocks to work with testing prefix. +local function setup_luarocks() + local testing_paths = test_env.testing_paths + title("Setting up LuaRocks") + + local lines = { + "return {", + ("SYSCONFDIR = %q,"):format(dir_path(testing_paths.testing_lrprefix, "etc/luarocks")), + ("LUA_DIR = %q,"):format(testing_paths.luadir), + ("LUA_BINDIR = %q,"):format(testing_paths.lua_bindir), + ("LUA = %q,"):format(testing_paths.lua), + } + + if test_env.TEST_TARGET_OS == "windows" then + if test_env.MINGW then + table.insert(lines, [[SYSTEM = "mingw",]]) + else + table.insert(lines, [[SYSTEM = "windows",]]) + end + table.insert(lines, ("WIN_TOOLS = %q,"):format(testing_paths.win_tools)) + end + + table.insert(lines, "}") + + test_env.write_file("src/luarocks/core/hardcoded.lua", table.concat(lines, "\n") .. "\n") + + print("LuaRocks set up correctly!") +end + +local function mock_api_call(path) + return test_env.execute(C(tool("wget"), "--timeout=0.1 --quiet --tries=10 http://localhost:8080" .. path)) +end + +function test_env.mock_server_init() + if not test_env.mock_prepared then + error("need to setup_specs with with_mock set to true") + end + + local testing_paths = test_env.testing_paths + assert(test_env.need_rock("restserver-xavante")) + + local lua = Q(testing_paths.lua) + local mock_server = Q(dir_path(testing_paths.util_dir, "mock-server.lua")) + local fixtures_dir = Q(testing_paths.fixtures_dir) + + local cmd = C(lua, mock_server, fixtures_dir) + + local bg_cmd = test_env.TEST_TARGET_OS == "windows" + and C("start", "/b", "\"\"", cmd) + or C(cmd, "&") + + os.execute(test_env.execute_helper(bg_cmd, true, test_env.env_variables)) + + for _ = 1, 100 do + if mock_api_call("/api/tool_version") then + break + end + os.execute(test_env.TEST_TARGET_OS == "windows" + and "ping 192.0.2.0 -n 1 -w 250 > NUL" + or "sleep 0.1") + end + +end + +function test_env.mock_server_done() + mock_api_call("/shutdown") +end + +local function find_binary_rock(src_rock, dirname) + local patt = src_rock:gsub("([.-])", "%%%1"):gsub("src", ".*[^s][^r][^c]") + for name in lfs.dir(dirname) do + if name:match(patt) then + return true + end + end + return false +end + +local function prepare_mock_server_binary_rocks() + if test_env.mock_prepared then + return + end + + local testing_paths = test_env.testing_paths + + local rocks = { + -- rocks needed for mock-server + "luasocket-${LUASOCKET}.src.rock", + "coxpcall-1.16.0-1.src.rock", + "binaryheap-${BINARYHEAP}.src.rock", + "timerwheel-${TIMERWHEEL}.src.rock", + "copas-${COPAS}.src.rock", + "luafilesystem-${LUAFILESYSTEM}.src.rock", + "xavante-2.4.0-1.src.rock", + "wsapi-1.6.1-1.src.rock", + "rings-1.3.0-1.src.rock", + "wsapi-xavante-1.6.1-1.src.rock", + "dkjson-${DKJSON}.src.rock", + "restserver-0.1-1.src.rock", + "restserver-xavante-0.2-1.src.rock", + } + local make_manifest = download_rocks(rocks, testing_paths.testing_server) + for _, rock in ipairs(rocks) do + rock = V(rock) + local rockname = rock:gsub("%-[^-]+%-%d+%.[%a.]+$", "") + if not find_binary_rock(rock, testing_paths.testing_server) then + local rockpath = dir_path(testing_paths.testing_server, rock) + local tree = "--tree=" .. testing_paths.testing_cache + + test_env.run.luarocks_nocov(C("build", Q(rockpath), tree)) + test_env.run.luarocks_nocov(C("pack", rockname, tree)) + + move_file(rockname .. "-*.rock", testing_paths.testing_server) + make_manifest = true + end + end + if make_manifest then + test_env.run.luarocks_admin_nocov(C("make_manifest", Q(testing_paths.testing_server))) + end + + test_env.mock_prepared = true +end + +--- +-- Main function to create config files and testing environment +function test_env.main() + local testing_paths = test_env.testing_paths + local testrun_dir = test_env.testing_paths.testrun_dir + + if test_env.TEST_ENV_CLEAN then + clean() + end + + lfs.mkdir(testrun_dir) + test_env.write_file(dir_path(testrun_dir, ".luarocks-no-project"), "") + lfs.mkdir(testing_paths.testing_cache) + lfs.mkdir(testing_paths.luarocks_tmp) + + create_configs() + + setup_luarocks() + + -- Preparation of rocks for building environment + local rocks = {} -- names of rocks, required for building environment + local urls = {} -- names of rock and rockspec files to be downloaded + + local env_vars = { + LUAROCKS_CONFIG = dir_path(testrun_dir, "testing_config.lua") + } + + if test_env.TYPE_TEST_ENV == "full" then + table.insert(urls, "/luafilesystem-${LUAFILESYSTEM}.src.rock") + table.insert(urls, "/luasocket-${LUASOCKET}.src.rock") + table.insert(urls, "/luasec-${LUASEC}.src.rock") + table.insert(urls, "/md5-1.2-1.src.rock") + table.insert(urls, "/manifests/hisham/lua-zlib-1.2-0.src.rock") + table.insert(urls, "/manifests/hisham/lua-bz2-0.2.1.1-1.src.rock") + rocks = {"luafilesystem", "luasocket", "luasec", "md5", "lua-zlib", "lua-bz2"} + if test_env.TEST_TARGET_OS ~= "windows" then + if test_env.lua_version == "5.1" then + table.insert(urls, "/bit32-${BIT32}.src.rock") + table.insert(rocks, "bit32") + end + table.insert(urls, "/luaposix-${LUAPOSIX}.src.rock") + table.insert(rocks, "luaposix") + end + assert(test_env.run.luarocks_nocov(C("config", "variables.OPENSSL_INCDIR", Q(test_env.OPENSSL_INCDIR)), env_vars)) + assert(test_env.run.luarocks_nocov(C("config", "variables.OPENSSL_LIBDIR", Q(test_env.OPENSSL_LIBDIR)), env_vars)) + end + + -- luacov is needed for both minimal or full environment + table.insert(urls, "/luacov-${LUACOV}.src.rock") + table.insert(urls, "/cluacov-${CLUACOV}.src.rock") + table.insert(rocks, "luacov") + table.insert(rocks, "cluacov") + + -- Download rocks needed for LuaRocks testing environment + lfs.mkdir(testing_paths.testing_server) + download_rocks(urls, testing_paths.testing_server) + + build_environment(rocks, env_vars) +end + +--- Function for initial setup of environment and variables +function test_env.setup_specs(extra_rocks, use_mock) + test_env.unload_luarocks() + + local testrun_dir = test_env.testing_paths.testrun_dir + local variables = test_env.env_variables + + -- if global variable about successful creation of testing environment doesn't exist, build environment + if not test_env.setup_done then + if test_env.CI then + if not exists(os.getenv("HOME"), ".ssh/id_rsa.pub") then + execute_bool("ssh-keygen -t rsa -P \"\" -f ~/.ssh/id_rsa") + execute_bool("cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys") + execute_bool("chmod og-wx ~/.ssh/authorized_keys") + execute_bool("ssh-keyscan localhost >> ~/.ssh/known_hosts") + end + end + + test_env.main() + + -- preload before meddling with package.path + require("spec.util.git_repo") + require("spec.util.quick") + + package.path = variables.LUA_PATH + package.cpath = variables.LUA_CPATH + + test_env.platform = get_luarocks_platform(test_env.env_variables) + test_env.wrapper_extension = test_env.TEST_TARGET_OS == "windows" and ".bat" or "" + test_env.setup_done = true + title("RUNNING TESTS") + end + + if use_mock == "mock" then + prepare_mock_server_binary_rocks() + end + + if extra_rocks then + local make_manifest = download_rocks(extra_rocks, test_env.testing_paths.testing_server) + if make_manifest then + test_env.run.luarocks_admin_nocov("make_manifest " .. test_env.testing_paths.testing_server) + end + end + + if test_env.RESET_ENV then + test_env.remove_dir(test_env.testing_paths.testing_tree) + test_env.remove_dir(test_env.testing_paths.testing_sys_tree) + end + + lfs.chdir(testrun_dir) +end + +test_env.set_lua_version() +test_env.set_args() +test_env.testing_paths = create_testing_paths(test_env.LUA_V or test_env.LUAJIT_V) +test_env.env_variables = create_env(test_env.testing_paths) +test_env.run = make_run_functions() +test_env.exists = exists +test_env.V = V +test_env.Q = Q +test_env.P = P +test_env.platform = get_luarocks_platform(test_env.env_variables) + +return test_env diff --git a/spec/util/versions.lua b/spec/util/versions.lua new file mode 100644 index 0000000..77c1129 --- /dev/null +++ b/spec/util/versions.lua @@ -0,0 +1,17 @@ +return { + binaryheap = "0.4-1", -- dependency for copas + bit32 = "5.3.5.1-1", -- dependency for luaposix on Lua 5.1 + cluacov = "0.1.3-1", + copas = "3.0.0-2", + cprint = "0.2-1", + dkjson = "2.6-1", + lpeg = "1.0.0-1", + luacov = "0.15.0-1", + luafilesystem = "1.8.0-1", + luafilesystem_old = "1.6.3-2", + luaposix = "35.1-1", + luasocket = "3.0.0-1", + luasec = "1.3.2-1", + lxsh = "0.8.6-2", + timerwheel = "0.2.0-2", -- dependency for copas +} diff --git a/spec/util_spec.lua b/spec/util_spec.lua new file mode 100644 index 0000000..0f199c9 --- /dev/null +++ b/spec/util_spec.lua @@ -0,0 +1,55 @@ +local test_env = require("spec.util.test_env") +local lfs = require("lfs") +local run = test_env.run + +describe("Basic tests #integration", function() + + before_each(function() + test_env.setup_specs() + end) + + it("--version", function() + assert.is_true(run.luarocks_bool("--version")) + end) + + it("unknown command", function() + assert.is_false(run.luarocks_bool("unknown_command")) + end) + + it("arguments fail", function() + assert.is_false(run.luarocks_bool("--porcelain=invalid")) + assert.is_false(run.luarocks_bool("--invalid-flag")) + assert.is_false(run.luarocks_bool("--server")) + assert.is_false(run.luarocks_bool("--server --porcelain")) + assert.is_false(run.luarocks_bool("--invalid-flag=abc")) + assert.is_false(run.luarocks_bool("invalid=5")) + end) + + it("executing from not existing directory #unix", function() + local main_path = lfs.currentdir() + assert.is_true(lfs.mkdir("idontexist")) + assert.is_true(lfs.chdir("idontexist")) + local delete_path = lfs.currentdir() + assert.is_true(os.remove(delete_path)) + + local output = run.luarocks("") + assert.is.falsy(output:find("the Lua package manager")) + assert.is_true(lfs.chdir(main_path)) + + output = run.luarocks("") + assert.is.truthy(output:find("the Lua package manager")) + end) + + it("--timeout", function() + assert.is.truthy(run.luarocks("--timeout=10")) + end) + + it("--timeout invalid", function() + assert.is_false(run.luarocks_bool("--timeout=abc")) + end) + + it("--only-server", function() + assert.is.truthy(run.luarocks("--only-server=testing")) + end) + +end) diff --git a/spec/which_spec.lua b/spec/which_spec.lua new file mode 100644 index 0000000..5712511 --- /dev/null +++ b/spec/which_spec.lua @@ -0,0 +1,39 @@ +local test_env = require("spec.util.test_env") +local run = test_env.run +local P = test_env.P + +local extra_rocks = { + "/say-1.2-1.src.rock", +} + +describe("luarocks which #integration", function() + + lazy_setup(function() + test_env.setup_specs(extra_rocks) + end) + + it("fails on missing arguments", function() + local output = run.luarocks("which") + assert.match("missing argument 'modname'", output, 1, true) + end) + + it("finds modules found in package.path", function() + assert.is_true(run.luarocks_bool("install say 1.2")) + local output = run.luarocks("which say") + assert.match(P"say/init.lua", output, 1, true) + assert.match("provided by say 1.2-1", output, 1, true) + end) + + it("finds modules found in package.path", function() + run.luarocks("install ") + local output = run.luarocks("which luarocks.loader") + assert.match("luarocks/loader.lua", output, 1, true) + assert.match("not installed as a rock", output, 1, true) + end) + + it("report modules not found", function() + local output = run.luarocks("which asdfgaoeui") + assert.match("Module 'asdfgaoeui' not found", output, 1, true) + end) + +end) diff --git a/spec/write_rockspec_spec.lua b/spec/write_rockspec_spec.lua new file mode 100644 index 0000000..abd5c80 --- /dev/null +++ b/spec/write_rockspec_spec.lua @@ -0,0 +1,104 @@ +local test_env = require("spec.util.test_env") +local git_repo = require("spec.util.git_repo") +local lfs = require("lfs") +local run = test_env.run + +describe("luarocks write_rockspec tests #integration", function() + + lazy_setup(function() + test_env.setup_specs() + end) + + it("fails with invalid argument", function() + assert.is_false(run.luarocks_bool("write_rockspec invalid")) + end) + + it("fails with invalid zip", function() + assert.is_false(run.luarocks_bool("write_rockspec http://example.com/invalid.zip")) + end) + + describe("from #git #unix", function() + local git + + lazy_setup(function() + git = git_repo.start() + end) + + teardown(function() + git:stop() + end) + + it("runs with no flags/arguments", function() + local d = lfs.currentdir() + finally(function() + os.remove("testrock-dev-1.rockspec") + lfs.chdir(d) + test_env.remove_dir("testrock") + end) + os.execute("git clone git://localhost/testrock") + lfs.chdir("testrock") + assert.is_true(run.luarocks_bool("write_rockspec")) + assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec")) + end) + + it("runs", function() + finally(function() os.remove("testrock-dev-1.rockspec") end) + assert.is_true(run.luarocks_bool("write_rockspec git://localhost/testrock")) + assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec")) + end) + + it("runs with --tag", function() + finally(function() os.remove("testrock-2.3.0-1.rockspec") end) + assert.is_true(run.luarocks_bool("write_rockspec git://localhost/testrock --tag=v2.3.0")) + assert.is.truthy(lfs.attributes("testrock-2.3.0-1.rockspec")) + -- TODO check contents + end) + + it("runs with format flag", function() + finally(function() os.remove("testrock-dev-1.rockspec") end) + assert.is_true(run.luarocks_bool("write_rockspec git://localhost/testrock --rockspec-format=1.1 --lua-versions=5.1,5.2")) + assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec")) + -- TODO check contents + end) + + it("runs with full flags", function() + finally(function() os.remove("testrock-dev-1.rockspec") end) + assert.is_true(run.luarocks_bool("write_rockspec git://localhost/testrock --lua-versions=5.1,5.2 --license=\"MIT/X11\" " + .. " --homepage=\"http://www.luarocks.org\" --summary=\"A package manager for Lua modules\" ")) + assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec")) + -- TODO check contents + end) + + it("with various flags", function() + finally(function() os.remove("testrock-dev-1.rockspec") end) + assert.is_true(run.luarocks_bool("write_rockspec git://localhost/testrock --lib=fcgi --license=\"3-clause BSD\" " .. "--lua-versions=5.1,5.2")) + assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec")) + -- TODO check contents + end) + end) + + describe("from tarball #mock", function() + + lazy_setup(function() + test_env.setup_specs(nil, "mock") + test_env.mock_server_init() + end) + lazy_teardown(function() + test_env.mock_server_done() + end) + + it("via http", function() + finally(function() os.remove("an_upstream_tarball-0.1-1.rockspec") end) + assert.is_true(run.luarocks_bool("write_rockspec http://localhost:8080/file/an_upstream_tarball-0.1.tar.gz --lua-versions=5.1")) + assert.is.truthy(lfs.attributes("an_upstream_tarball-0.1-1.rockspec")) + -- TODO check contents + end) + + it("with a different basedir", function() + finally(function() os.remove("renamed_upstream_tarball-0.1-1.rockspec") end) + assert.is_true(run.luarocks_bool("write_rockspec http://localhost:8080/file/renamed_upstream_tarball-0.1.tar.gz --lua-versions=5.1")) + assert.is.truthy(lfs.attributes("renamed_upstream_tarball-0.1-1.rockspec")) + -- TODO check contents + end) + end) +end) |
