From 5cba4b83f60966045b86ac615df2692c953ebba7 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Mon, 26 Feb 2024 17:47:28 -0300 Subject: fix(fs): make current_dir always return 1 arg only --- spec/dir_spec.lua | 72 -- spec/fetch_spec.lua | 488 ------------- spec/fs_spec.lua | 1607 ------------------------------------------ spec/fun_spec.lua | 130 ---- spec/persist_spec.lua | 76 -- spec/rockspecs_spec.lua | 126 ---- spec/sysdetect_spec.lua | 75 -- spec/tools_spec.lua | 253 ------- spec/unit/build_spec.lua | 369 ++++++++++ spec/unit/dir_spec.lua | 72 ++ spec/unit/fetch_spec.lua | 488 +++++++++++++ spec/unit/fs_spec.lua | 1607 ++++++++++++++++++++++++++++++++++++++++++ spec/unit/fun_spec.lua | 130 ++++ spec/unit/persist_spec.lua | 76 ++ spec/unit/rockspecs_spec.lua | 126 ++++ spec/unit/sysdetect_spec.lua | 75 ++ spec/unit/tools_spec.lua | 253 +++++++ spec/unit_build_spec.lua | 369 ---------- src/luarocks/fs/tools.lua | 16 +- 19 files changed, 3207 insertions(+), 3201 deletions(-) delete mode 100644 spec/dir_spec.lua delete mode 100644 spec/fetch_spec.lua delete mode 100644 spec/fs_spec.lua delete mode 100644 spec/fun_spec.lua delete mode 100644 spec/persist_spec.lua delete mode 100644 spec/rockspecs_spec.lua delete mode 100644 spec/sysdetect_spec.lua delete mode 100644 spec/tools_spec.lua create mode 100644 spec/unit/build_spec.lua create mode 100644 spec/unit/dir_spec.lua create mode 100644 spec/unit/fetch_spec.lua create mode 100644 spec/unit/fs_spec.lua create mode 100644 spec/unit/fun_spec.lua create mode 100644 spec/unit/persist_spec.lua create mode 100644 spec/unit/rockspecs_spec.lua create mode 100644 spec/unit/sysdetect_spec.lua create mode 100644 spec/unit/tools_spec.lua delete mode 100644 spec/unit_build_spec.lua diff --git a/spec/dir_spec.lua b/spec/dir_spec.lua deleted file mode 100644 index b5dadda8..00000000 --- a/spec/dir_spec.lua +++ /dev/null @@ -1,72 +0,0 @@ -local test_env = require("spec.util.test_env") -local testing_paths = test_env.testing_paths -local P = test_env.P - -test_env.unload_luarocks() -test_env.setup_specs() -local dir = require("luarocks.dir") - -describe("luarocks.dir #unit", function() - local runner - - setup(function() - runner = require("luacov.runner") - runner.init(testing_paths.testrun_dir .. "/luacov.config") - runner.tick = true - end) - - teardown(function() - runner.shutdown() - 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/fetch_spec.lua b/spec/fetch_spec.lua deleted file mode 100644 index 38da379e..00000000 --- a/spec/fetch_spec.lua +++ /dev/null @@ -1,488 +0,0 @@ -local test_env = require("spec.util.test_env") - -test_env.unload_luarocks() -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 - - 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") - runner.tick = true - end) - - teardown(function() - runner.shutdown() - 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/fs_spec.lua b/spec/fs_spec.lua deleted file mode 100644 index aea86af3..00000000 --- a/spec/fs_spec.lua +++ /dev/null @@ -1,1607 +0,0 @@ -local test_env = require("spec.util.test_env") - -test_env.unload_luarocks() -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 - - setup(function() - cfg.init() - fs.init() - runner = require("luacov.runner") - runner.init(testing_paths.testrun_dir .. "/luacov.config") - runner.tick = true - end) - - teardown(function() - runner.shutdown() - 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(lfs.currentdir()).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["intfile1"], true) - assert.same(contents["intdir"], true) - assert.same(contents["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.download #mock", function() - local tmpfile - local tmpdir - - setup(function() - test_env.mock_server_init() - end) - - 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) - - 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) - -end) diff --git a/spec/fun_spec.lua b/spec/fun_spec.lua deleted file mode 100644 index 9844ec27..00000000 --- a/spec/fun_spec.lua +++ /dev/null @@ -1,130 +0,0 @@ -local test_env = require("spec.util.test_env") -local testing_paths = test_env.testing_paths - -test_env.unload_luarocks() -local fun = require("luarocks.fun") - -describe("luarocks.fun #unit", function() - local runner - - setup(function() - runner = require("luacov.runner") - runner.init(testing_paths.testrun_dir .. "/luacov.config") - runner.tick = true - end) - - teardown(function() - runner.shutdown() - 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/persist_spec.lua b/spec/persist_spec.lua deleted file mode 100644 index f426fd83..00000000 --- a/spec/persist_spec.lua +++ /dev/null @@ -1,76 +0,0 @@ -local test_env = require("spec.util.test_env") -local testing_paths = test_env.testing_paths - -test_env.unload_luarocks() -local persist = require("luarocks.persist") - -describe("luarocks.persist #unit", function() - local runner - - setup(function() - runner = require("luacov.runner") - runner.init(testing_paths.testrun_dir .. "/luacov.config") - runner.tick = true - end) - - teardown(function() - runner.shutdown() - 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/rockspecs_spec.lua b/spec/rockspecs_spec.lua deleted file mode 100644 index 5b0573fe..00000000 --- a/spec/rockspecs_spec.lua +++ /dev/null @@ -1,126 +0,0 @@ - -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() - - 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/sysdetect_spec.lua b/spec/sysdetect_spec.lua deleted file mode 100644 index 6ec6f6b6..00000000 --- a/spec/sysdetect_spec.lua +++ /dev/null @@ -1,75 +0,0 @@ - -local sysdetect = require("luarocks.core.sysdetect") -local lfs = require("lfs") - -describe("luarocks.core.sysdetect #unix #unit", function() - - setup(function() - os.execute("[ -e binary-samples ] || git clone --depth=1 https://github.com/hishamhm/binary-samples") - os.execute("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/tools_spec.lua b/spec/tools_spec.lua deleted file mode 100644 index 29e21740..00000000 --- a/spec/tools_spec.lua +++ /dev/null @@ -1,253 +0,0 @@ -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 - -test_env.unload_luarocks() -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 - - setup(function() - cfg.init() - fs.init() - runner = require("luacov.runner") - runner.init(testing_paths.testrun_dir .. "/luacov.config") - runner.tick = true - end) - - teardown(function() - runner.shutdown() - 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/build_spec.lua b/spec/unit/build_spec.lua new file mode 100644 index 00000000..6ab143c6 --- /dev/null +++ b/spec/unit/build_spec.lua @@ -0,0 +1,369 @@ +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.unload_luarocks() + +test_env.unload_luarocks() +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 + #include + + 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") + runner.tick = true + cfg.init() + fs.init() + deps.check_lua_incdir(cfg.variables) + deps.check_lua_libdir(cfg.variables) + end) + + lazy_teardown(function() + runner.shutdown() + 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 = location .. "/module1.lua", + ["dir1.module2"] = { + sources = location .. "/dir1/module2.c", + libraries = libs, + incdirs = incdirs, + libdirs = libdirs + }, + my_module = { + sources = 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/dir_spec.lua b/spec/unit/dir_spec.lua new file mode 100644 index 00000000..b5dadda8 --- /dev/null +++ b/spec/unit/dir_spec.lua @@ -0,0 +1,72 @@ +local test_env = require("spec.util.test_env") +local testing_paths = test_env.testing_paths +local P = test_env.P + +test_env.unload_luarocks() +test_env.setup_specs() +local dir = require("luarocks.dir") + +describe("luarocks.dir #unit", function() + local runner + + setup(function() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + runner.tick = true + end) + + teardown(function() + runner.shutdown() + 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 00000000..38da379e --- /dev/null +++ b/spec/unit/fetch_spec.lua @@ -0,0 +1,488 @@ +local test_env = require("spec.util.test_env") + +test_env.unload_luarocks() +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 + + 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") + runner.tick = true + end) + + teardown(function() + runner.shutdown() + 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 00000000..aea86af3 --- /dev/null +++ b/spec/unit/fs_spec.lua @@ -0,0 +1,1607 @@ +local test_env = require("spec.util.test_env") + +test_env.unload_luarocks() +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 + + setup(function() + cfg.init() + fs.init() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + runner.tick = true + end) + + teardown(function() + runner.shutdown() + 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(lfs.currentdir()).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["intfile1"], true) + assert.same(contents["intdir"], true) + assert.same(contents["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.download #mock", function() + local tmpfile + local tmpdir + + setup(function() + test_env.mock_server_init() + end) + + 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) + + 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) + +end) diff --git a/spec/unit/fun_spec.lua b/spec/unit/fun_spec.lua new file mode 100644 index 00000000..9844ec27 --- /dev/null +++ b/spec/unit/fun_spec.lua @@ -0,0 +1,130 @@ +local test_env = require("spec.util.test_env") +local testing_paths = test_env.testing_paths + +test_env.unload_luarocks() +local fun = require("luarocks.fun") + +describe("luarocks.fun #unit", function() + local runner + + setup(function() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + runner.tick = true + end) + + teardown(function() + runner.shutdown() + 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/persist_spec.lua b/spec/unit/persist_spec.lua new file mode 100644 index 00000000..f426fd83 --- /dev/null +++ b/spec/unit/persist_spec.lua @@ -0,0 +1,76 @@ +local test_env = require("spec.util.test_env") +local testing_paths = test_env.testing_paths + +test_env.unload_luarocks() +local persist = require("luarocks.persist") + +describe("luarocks.persist #unit", function() + local runner + + setup(function() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + runner.tick = true + end) + + teardown(function() + runner.shutdown() + 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 00000000..5b0573fe --- /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() + + 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 00000000..6ec6f6b6 --- /dev/null +++ b/spec/unit/sysdetect_spec.lua @@ -0,0 +1,75 @@ + +local sysdetect = require("luarocks.core.sysdetect") +local lfs = require("lfs") + +describe("luarocks.core.sysdetect #unix #unit", function() + + setup(function() + os.execute("[ -e binary-samples ] || git clone --depth=1 https://github.com/hishamhm/binary-samples") + os.execute("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/tools_spec.lua b/spec/unit/tools_spec.lua new file mode 100644 index 00000000..29e21740 --- /dev/null +++ b/spec/unit/tools_spec.lua @@ -0,0 +1,253 @@ +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 + +test_env.unload_luarocks() +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 + + setup(function() + cfg.init() + fs.init() + runner = require("luacov.runner") + runner.init(testing_paths.testrun_dir .. "/luacov.config") + runner.tick = true + end) + + teardown(function() + runner.shutdown() + 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_build_spec.lua b/spec/unit_build_spec.lua deleted file mode 100644 index 6ab143c6..00000000 --- a/spec/unit_build_spec.lua +++ /dev/null @@ -1,369 +0,0 @@ -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.unload_luarocks() - -test_env.unload_luarocks() -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 - #include - - 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") - runner.tick = true - cfg.init() - fs.init() - deps.check_lua_incdir(cfg.variables) - deps.check_lua_libdir(cfg.variables) - end) - - lazy_teardown(function() - runner.shutdown() - 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 = location .. "/module1.lua", - ["dir1.module2"] = { - sources = location .. "/dir1/module2.c", - libraries = libs, - incdirs = incdirs, - libdirs = libdirs - }, - my_module = { - sources = 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/src/luarocks/fs/tools.lua b/src/luarocks/fs/tools.lua index a7724dc7..23f2561e 100644 --- a/src/luarocks/fs/tools.lua +++ b/src/luarocks/fs/tools.lua @@ -48,12 +48,11 @@ do end end +local current_dir_with_cache do local cache_pwd - --- Obtain current directory. - -- Uses the module's internal directory stack. - -- @return string: the absolute pathname of the current directory. - function tools.current_dir() + + current_dir_with_cache = function() local current = cache_pwd if not current then local pipe = io.popen(fs.quiet_stderr(vars.PWD)) @@ -66,6 +65,13 @@ do end return current, cache_pwd end + + --- Obtain current directory. + -- Uses the module's internal directory stack. + -- @return string: the absolute pathname of the current directory. + function tools.current_dir() + return (current_dir_with_cache()) -- drop second return + end end --- Change the current directory. @@ -107,7 +113,7 @@ end -- @return boolean: true if command succeeds (status code 0), false -- otherwise. function tools.execute_string(cmd) - local current, cache_pwd = fs.current_dir() + local current, cache_pwd = current_dir_with_cache() if not current then return false end if current ~= cache_pwd then cmd = fs.command_at(current, cmd) -- cgit v1.2.3-55-g6feb