From 2c4ff5240bf298fec07749f5984de2f08b8736ec Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Tue, 20 Feb 2024 13:43:44 -0300 Subject: fix: better normalization for paths and slashes Fixes #1195. --- spec/util/quick.lua | 106 +++++++++---- spec/util/test_env.lua | 398 ++++++++++++++++++++++++++++--------------------- 2 files changed, 297 insertions(+), 207 deletions(-) (limited to 'spec/util') diff --git a/spec/util/quick.lua b/spec/util/quick.lua index c8bfb61a..1fcf2b36 100644 --- a/spec/util/quick.lua +++ b/spec/util/quick.lua @@ -37,7 +37,7 @@ local function is_hr(line) end local function parse(filename) - local fd = assert(io.open(filename, "r")) + local fd = assert(io.open(filename, "rb")) local input = assert(fd:read("*a")) fd:close() @@ -67,11 +67,27 @@ local function parse(filename) os.exit(1) end - local function bool_arg(cmd, cur_block, field, arg) + local function bool_arg(cmd, cur, field, arg) if arg ~= "true" and arg ~= "false" then fail(cmd .. " argument must be 'true' or 'false'") end - cur_block[field] = (arg == "true") + cur[field] = (arg == "true") + end + + local function block_start_arg(cmd, cur, field) + if not cur or cur.op ~= "RUN" then + fail(cmd .. " must be given in the context of a RUN") + end + if cur[field] then + fail(cmd .. " was already declared") + end + + cur[field] = { + data = {} + } + cur_block = cur[field] + cur_block_name = cmd + table.insert(stack, "block start") end local test_env = require("spec.util.test_env") @@ -109,7 +125,11 @@ local function parse(filename) end)) end - for line in input:gmatch("[^\n]*") do + if input:sub(#input, #input) ~= "\n" then + input = input .. "\n" + end + + for line in input:gmatch("([^\r\n]*)\r?\n?") do cur_line = cur_line + 1 local state = stack[#stack] @@ -182,34 +202,20 @@ local function parse(filename) cur_op.exit = code cur_op.exit_line = cur_line - elseif cmd == "STDERR" then + elseif cmd == "VERBOSE" then if not cur_op or cur_op.op ~= "RUN" then - fail("STDERR must be given in the context of a RUN") - end - if cur_op.stderr then - fail("STDERR was already declared") + fail("VERBOSE must be given in the context of a RUN") end - cur_op.stderr = { - data = {} - } - cur_block = cur_op.stderr - cur_block_name = "STDERR" - table.insert(stack, "block start") + bool_arg("VERBOSE", cur_op, "verbose", arg) + elseif cmd == "STDERR" then + block_start_arg("STDERR", cur_op, "stderr") + elseif cmd == "NOT_STDERR" then + block_start_arg("NOT_STDERR", cur_op, "not_stderr") elseif cmd == "STDOUT" then - if not cur_op or cur_op.op ~= "RUN" then - fail("STDOUT must be given in the context of a RUN") - end - if cur_op.stdout then - fail("STDOUT was already declared") - end - - cur_op.stdout = { - data = {} - } - cur_block = cur_op.stdout - cur_block_name = "STDOUT" - table.insert(stack, "block start") + block_start_arg("STDOUT", cur_op, "stdout") + elseif cmd == "NOT_STDOUT" then + block_start_arg("NOT_STDOUT", cur_op, "not_stdout") elseif cmd == "TEST" then table.remove(stack) start_test(arg) @@ -298,7 +304,7 @@ function quick.compile(filename, env) write([=[ end ]=]) for _, op in ipairs(t.ops) do if op.op == "FILE" then - write([=[ test_env.write_file(handle_tmpdir("]=], op.name, [=["), handle_tmpdir([=====[ ]=]) + write(([=[ test_env.write_file(handle_tmpdir(%q), handle_tmpdir([=====[ ]=]):format(op.name)) for _, line in ipairs(op.data) do write(line) end @@ -324,7 +330,7 @@ function quick.compile(filename, env) write(([=[ local ok, _, code = os.execute(%s .. " " .. %q .. %q) ]=]):format(cmd_helper, op.args, redirs)) write([=[ if type(ok) == "number" then code = (ok >= 256 and ok / 256 or ok) end ]=]) - write([=[ local fd_stderr = assert(io.open("stderr.txt", "r")) ]=]) + write([=[ local fd_stderr = assert(io.open("stderr.txt", "rb")) ]=]) write([=[ local stderr_data = fd_stderr:read("*a") ]=]) write([=[ fd_stderr:close() ]=]) @@ -332,23 +338,46 @@ function quick.compile(filename, env) write(([=[ assert(false, error_message(%d, "RUN crashed: ", stderr_data)) ]=]):format(op.line)) write([=[ end ]=]) - if op.stdout then - write([=[ local fd_stdout = assert(io.open("stdout.txt", "r")) ]=]) + if op.stdout or op.not_stdout or op.verbose then + write([=[ local fd_stdout = assert(io.open("stdout.txt", "rb")) ]=]) write([=[ local stdout_data = fd_stdout:read("*a") ]=]) write([=[ fd_stdout:close() ]=]) + end + + if op.verbose then + write([=[ print() ]=]) + write([=[ print("STDOUT: --" .. ("-"):rep(70)) ]=]) + write([=[ print(stdout_data) ]=]) + write([=[ print("STDERR: --" .. ("-"):rep(70)) ]=]) + write([=[ print(stderr_data) ]=]) + write([=[ print(("-"):rep(80)) ]=]) + write([=[ print() ]=]) + end + if op.stdout then write([=[ do ]=]) write([=[ local block_at = 1 ]=]) write([=[ local s, e, line ]=]) for i, line in ipairs(op.stdout.data) do write(([=[ line = %q ]=]):format(line)) - write(([=[ s, e = string.find(stdout_data, line, block_at, true) ]=])) + write(([=[ s, e = string.find(stdout_data, line, 1, true) ]=])) write(([=[ assert(s, error_message(%d, "STDOUT did not match: " .. line, stdout_data)) ]=]):format(op.stdout.start + i)) write(([=[ block_at = e + 1 ]=]):format(i)) end write([=[ end ]=]) end + if op.not_stdout then + write([=[ do ]=]) + write([=[ local line ]=]) + for i, line in ipairs(op.not_stdout.data) do + write(([=[ line = %q ]=]):format(line)) + write(([=[ s = string.find(stdout_data, line, 1, true) ]=])) + write(([=[ assert(not s, error_message(%d, "NOT_STDOUT did match unwanted output: " .. line, stdout_data)) ]=]):format(op.stdout.start + i)) + end + write([=[ end ]=]) + end + if op.stderr then write([=[ do ]=]) write([=[ local block_at = 1 ]=]) @@ -362,6 +391,17 @@ function quick.compile(filename, env) write([=[ end ]=]) end + if op.not_stderr then + write([=[ do ]=]) + write([=[ local line ]=]) + for i, line in ipairs(op.not_stderr.data) do + write(([=[ line = %q ]=]):format(line)) + write(([=[ s = string.find(stderr_data, line, block_at, true) ]=])) + write(([=[ assert(not s, error_message(%d, "NOT_STDERR did match unwanted output: " .. line, stderr_data)) ]=]):format(op.stderr.start + i)) + end + write([=[ end ]=]) + end + if op.exit then write(([=[ assert.same(%d, code, error_message(%d, "EXIT did not match: " .. %d, stderr_data)) ]=]):format(op.exit, op.exit_line, op.exit)) end diff --git a/spec/util/test_env.lua b/spec/util/test_env.lua index dcda6311..41787cb7 100644 --- a/spec/util/test_env.lua +++ b/spec/util/test_env.lua @@ -37,6 +37,19 @@ local function title(str) print(("-"):rep(#str)) end +local dir_sep = package.config:sub(1, 1) +local function P(p) + return (p:gsub("/", dir_sep)) +end + +local function dir_path(...) + return P((table.concat({ ... }, "/"):gsub("\\", "/"):gsub("/+", "/"))) +end + +local function C(...) + return table.concat({...}, " ") +end + --- Quote argument for shell processing. Fixes paths on Windows. -- Adds double quotes and escapes. Based on function in fs/win32.lua. -- @param arg string: Unquoted argument. @@ -46,7 +59,7 @@ local function Q(arg) local drive_letter = "[%.a-zA-Z]?:?[\\/]" -- Quote DIR for Windows if arg:match("^"..drive_letter) then - arg = arg:gsub("/", "\\") + arg = P(arg) end if arg == "\\" then @@ -72,7 +85,7 @@ local function V(str) elseif suffix == "v" then return v elseif suffix == "r" then - return v + return r else print("Test error: invalid suffix " .. suffix .. " in variable " .. name) os.exit(1) @@ -87,6 +100,14 @@ local function V(str) end)) end +local function tool(name) + if test_env.TEST_TARGET_OS == "windows" then + return Q(dir_path(test_env.testing_paths.win_tools, name .. ".exe")) + else + return name + end +end + local os_remove = os.remove os.remove = function(f) -- luacheck: ignore return os_remove(V(f)) @@ -131,8 +152,18 @@ function test_env.copy(source, destination) source = V(source) destination = V(destination) - local r_source, err = io.open(source, "r") - local r_destination, err = io.open(destination, "w") + local r_source, r_destination, err + r_source, err = io.open(source, "r") + if err then + print(debug.traceback()) + os.exit(1) + end + + r_destination, err = io.open(destination, "w") + if err then + print(debug.traceback()) + os.exit(1) + end while true do local block = r_source:read(8192) @@ -147,7 +178,7 @@ end function test_env.get_tmp_path() local path = os.tmpname() if test_env.TEST_TARGET_OS == "windows" and not path:find(":") then - path = os.getenv("TEMP") .. path + path = dir_path(os.getenv("TEMP"), path) end os.remove(path) return path @@ -234,8 +265,8 @@ local function execute_bool(command, print_command, env_variables) local redirect_filename local redirect = "" if print_command ~= nil then - redirect_filename = test_env.testing_paths.luarocks_tmp.."/output.txt" - redirect = " > "..redirect_filename + redirect_filename = dir_path(test_env.testing_paths.luarocks_tmp, "output.txt") + redirect = " > " .. redirect_filename os.remove(redirect_filename) end local ok = test_env.execute(command .. redirect) @@ -312,7 +343,7 @@ function test_env.set_args() if not test_env.TEST_TARGET_OS then title("OS CHECK") - if package.config:sub(1,1) == "\\" then + if dir_sep == "\\" then test_env.TEST_TARGET_OS = "windows" if test_env.APPVEYOR then test_env.OPENSSL_INCDIR = "C:\\OpenSSL-v111-Win32\\include" @@ -348,7 +379,8 @@ function test_env.set_args() test_env.openssl_dirs = "" if test_env.OPENSSL_INCDIR then - test_env.openssl_dirs = "OPENSSL_INCDIR=" .. test_env.OPENSSL_INCDIR .. " OPENSSL_LIBDIR=" .. test_env.OPENSSL_LIBDIR + test_env.openssl_dirs = C("OPENSSL_INCDIR=" .. test_env.OPENSSL_INCDIR, + "OPENSSL_LIBDIR=" .. test_env.OPENSSL_LIBDIR) end return true @@ -358,12 +390,8 @@ function test_env.copy_dir(source_path, target_path) source_path = V(source_path) target_path = V(target_path) - local testing_paths = test_env.testing_paths - if test_env.TEST_TARGET_OS == "windows" then - execute_bool(testing_paths.win_tools .. "/cp -R ".. source_path .. "/. " .. target_path) - else - execute_bool("cp -a ".. source_path .. "/. " .. target_path) - end + local flag = test_env.TEST_TARGET_OS == "windows" and "-R" or "-a" + os.execute(C(tool("cp"), flag, dir_path(source_path, "."), target_path)) end --- Remove directory recursively @@ -374,7 +402,7 @@ function test_env.remove_dir(path) if exists(path) then for file in lfs.dir(path) do if file ~= "." and file ~= ".." then - local full_path = path..'/'..file + local full_path = dir_path(path, file) if lfs.attributes(full_path, "mode") == "directory" then test_env.remove_dir(full_path) @@ -396,7 +424,7 @@ function test_env.remove_subdirs(path, pattern) if exists(path) then for file in lfs.dir(path) do if file ~= "." and file ~= ".." then - local full_path = path..'/'..file + local full_path = dir_path(path, file) if lfs.attributes(full_path, "mode") == "directory" and file:find(pattern) then test_env.remove_dir(full_path) @@ -418,7 +446,7 @@ function test_env.remove_files(path, pattern) for file in lfs.dir(path) do if file ~= "." and file ~= ".." then if file:find(pattern) then - if os.remove(path .. "/" .. file) then + if os.remove(dir_path(path, file)) then result_check = true end end @@ -442,27 +470,21 @@ local function download_rocks(urls, save_path) url = V(url) if url:match("^spec/fixtures") then - table.insert(fixtures, (url:gsub("^spec/fixtures", test_env.testing_paths.fixtures_dir))) + table.insert(fixtures, P(url:gsub("^spec/fixtures", test_env.testing_paths.fixtures_dir))) else -- check if already downloaded - if not exists(save_path .. "/" .. url) then + if not exists(dir_path(save_path, url)) then table.insert(to_download, ((luarocks_repo .. url):gsub("org//", "org/"))) end end end if #fixtures > 0 then - os.execute("cp " .. table.concat(fixtures, " ") .. " " .. save_path) + os.execute(C(tool("cp"), table.concat(fixtures, " "), save_path)) end if #to_download > 0 then - local cmd - if test_env.TEST_TARGET_OS == "windows" then - cmd = test_env.testing_paths.win_tools .. "/wget --no-check-certificate -cP " .. save_path - else - cmd = "wget -cP " .. save_path - end - local ok = execute_bool(cmd.." "..table.concat(to_download, " ")) + local ok = execute_bool(C(tool("wget"), "--no-check-certificate -cP", save_path, table.concat(to_download, " "))) if not ok then os.exit(1) end @@ -492,12 +514,13 @@ end -- @return md5sum string: md5sum of directory local function hash_environment(path) if test_env.TEST_TARGET_OS == "linux" then - return execute_output("cd " .. path .. " && find . -printf \"%s %p\n\"") + return execute_output(C("cd", path, "&& find . -printf \"%s %p\n\" | md5sum")) elseif test_env.TEST_TARGET_OS == "osx" then - return execute_output("find " .. path .. " -type f -exec stat -f \"%z %N\" {} \\; | md5") + return execute_output(C("find", path, "-type f -exec stat -f \"%z %N\" {} \\; | md5")) elseif test_env.TEST_TARGET_OS == "windows" then - return execute_output("\"" .. Q(test_env.testing_paths.win_tools .. "/find") .. " " .. Q(path) - .. " -printf \"%s %p\"\" > temp_sum.txt && certUtil -hashfile temp_sum.txt && del temp_sum.txt") + return execute_output( + "\"" .. C(tool("find"), Q(path), "-printf", "\"%s %p\"") .. "\"" .. + " > temp_sum.txt && certUtil -hashfile temp_sum.txt && del temp_sum.txt") end end @@ -505,29 +528,44 @@ end -- @param testing_paths table: table with paths to testing directory -- @return env_variables table: table with created environment variables local function create_env(testing_paths) - local luaversion_short = _VERSION:gsub("Lua ", "") + local lua_v = _VERSION:gsub("Lua ", "") + local testrun_dir = test_env.testing_paths.testrun_dir + local lrprefix = testing_paths.testing_lrprefix + local tree = testing_paths.testing_tree + local sys_tree = testing_paths.testing_sys_tree if test_env.LUAJIT_V then - luaversion_short="5.1" + lua_v="5.1" end local env_variables = {} env_variables.GNUPGHOME = testing_paths.gpg_dir - env_variables.LUA_VERSION = luaversion_short - env_variables.LUAROCKS_CONFIG = testing_paths.testrun_dir .. "/testing_config.lua" + env_variables.LUA_VERSION = lua_v + env_variables.LUAROCKS_CONFIG = dir_path(testrun_dir, "testing_config.lua") + + local lua_path = {} if test_env.TEST_TARGET_OS == "windows" then - env_variables.LUA_PATH = testing_paths.testing_lrprefix .. "\\lua\\?.lua;" + table.insert(lua_path, dir_path(lrprefix, "lua", "?.lua")) else - env_variables.LUA_PATH = testing_paths.testing_lrprefix .. "/share/lua/" .. luaversion_short .. "/?.lua;" + table.insert(lua_path, dir_path(lrprefix, "share", "lua", lua_v, "?.lua")) end - env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_tree .. "/share/lua/" .. luaversion_short .. "/?.lua;" - env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_tree .. "/share/lua/".. luaversion_short .. "/?/init.lua;" - env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_sys_tree .. "/share/lua/" .. luaversion_short .. "/?.lua;" - env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_sys_tree .. "/share/lua/".. luaversion_short .. "/?/init.lua;" - env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.src_dir .. "/?.lua;" - env_variables.LUA_CPATH = testing_paths.testing_tree .. "/lib/lua/" .. luaversion_short .. "/?." .. test_env.lib_extension .. ";" - .. testing_paths.testing_sys_tree .. "/lib/lua/" .. luaversion_short .. "/?." .. test_env.lib_extension .. ";" - env_variables.PATH = os.getenv("PATH") .. ";" .. testing_paths.testing_tree .. "/bin;" .. testing_paths.testing_sys_tree .. "/bin;" + table.insert(lua_path, dir_path(tree, "share", "lua", lua_v, "?.lua")) + table.insert(lua_path, dir_path(tree, "share", "lua", lua_v, "?", "init.lua")) + table.insert(lua_path, dir_path(sys_tree, "share", "lua", lua_v, "?.lua")) + table.insert(lua_path, dir_path(sys_tree, "share", "lua", lua_v, "?", "init.lua")) + table.insert(lua_path, dir_path(testing_paths.src_dir, "?.lua")) + env_variables.LUA_PATH = table.concat(lua_path, ";") .. ";" + + local lua_cpath = {} + local lib_pattern = "?." .. test_env.lib_extension + table.insert(lua_cpath, dir_path(tree, "lib", "lua", lua_v, lib_pattern)) + table.insert(lua_cpath, dir_path(sys_tree, "lib", "lua", lua_v, lib_pattern)) + env_variables.LUA_CPATH = table.concat(lua_cpath, ";") .. ";" + + local path = { os.getenv("PATH") } + table.insert(path, dir_path(tree, "bin")) + table.insert(path, dir_path(sys_tree, "bin")) + env_variables.PATH = table.concat(path, test_env.TARGET_OS == "windows" and ";" or ":") return env_variables end @@ -544,16 +582,19 @@ local function create_md5sums(testing_paths) end local function make_run_function(cmd_name, exec_function, with_coverage, do_print) - local cmd_prefix = Q(test_env.testing_paths.lua) .. " " + local cmd_prefix = Q(test_env.testing_paths.lua) + local testrun_dir = test_env.testing_paths.testrun_dir if with_coverage then - cmd_prefix = cmd_prefix .. "-e \"require('luacov.runner')('" .. test_env.testing_paths.testrun_dir .. "/luacov.config')\" " + cmd_prefix = C(cmd_prefix, "-e", "\"require('luacov.runner')([[" .. testrun_dir .. "/luacov.config]])\"") end if cmd_name then - cmd_prefix = cmd_prefix .. test_env.testing_paths.src_dir .. "/bin/" .. cmd_name .. " " + cmd_prefix = C(cmd_prefix, dir_path(test_env.testing_paths.src_dir, "bin", cmd_name)) end + cmd_prefix = P(cmd_prefix) + return function(cmd, new_vars) cmd = V(cmd) local temp_vars = {} @@ -565,34 +606,34 @@ local function make_run_function(cmd_name, exec_function, with_coverage, do_prin temp_vars[k] = v end end - return exec_function(cmd_prefix .. cmd, do_print, temp_vars) + return exec_function(C(cmd_prefix, cmd), do_print, temp_vars) end end local function make_run_functions() - return { - lua = make_run_function(nil, execute_output, true, true), - lua_bool = make_run_function(nil, execute_bool, true, true), - luarocks = make_run_function("luarocks", execute_output, true, true), - luarocks_bool = make_run_function("luarocks", execute_bool, true, true), - luarocks_noprint = make_run_function("luarocks", execute_bool, true, false), - luarocks_nocov = make_run_function("luarocks", execute_bool, false, true), - luarocks_noprint_nocov = make_run_function("luarocks", execute_bool, false, false), - luarocks_admin = make_run_function("luarocks-admin", execute_output, true, true), - luarocks_admin_bool = make_run_function("luarocks-admin", execute_bool, true, true), - luarocks_admin_nocov = make_run_function("luarocks-admin", execute_bool, false, false) + local fns = {} + + local cmds = { + ["lua"] = nil, + ["luarocks"] = "luarocks", + ["luarocks_admin"] = "luarocks-admin", } + + for _, name in ipairs({"lua", "luarocks", "luarocks_admin"}) do + fns[name] = make_run_function(cmds[name], execute_output, true, true) + fns[name .. "_bool"] = make_run_function(cmds[name], execute_bool, true, true) + fns[name .. "_nocov"] = make_run_function(cmds[name], execute_bool, false, true) + fns[name .. "_noprint_nocov"] = make_run_function(cmds[name], execute_bool, false, false) + end + + return fns end local function move_file(src, dst) - if test_env.TEST_TARGET_OS == "windows" then - execute_bool(test_env.testing_paths.win_tools .. "/mv " .. src .. " " .. dst) - else - local ok = execute_bool("mv " .. src .. " " .. dst) - if not ok then - print(debug.traceback()) - os.exit(1) - end + local ok = execute_bool(C(tool("mv"), P(src), P(dst))) + if not ok then + print(debug.traceback()) + os.exit(1) end end @@ -610,13 +651,15 @@ local function build_environment(rocks, env_variables) lfs.mkdir(testing_paths.testing_tree) lfs.mkdir(testing_paths.testing_sys_tree) - test_env.run.luarocks_admin_nocov("make_manifest " .. Q(testing_paths.testing_server)) - test_env.run.luarocks_admin_nocov("make_manifest " .. Q(testing_paths.testing_cache)) + test_env.run.luarocks_admin_nocov(C("make_manifest", Q(testing_paths.testing_server))) + test_env.run.luarocks_admin_nocov(C("make_manifest", Q(testing_paths.testing_cache))) for _, rock in ipairs(rocks) do - if not test_env.run.luarocks_nocov(test_env.quiet("install --only-server=" .. testing_paths.testing_cache .. " --tree=" .. testing_paths.testing_sys_tree .. " " .. Q(rock), env_variables)) then - assert(test_env.run.luarocks_nocov("build --tree=" .. Q(testing_paths.testing_sys_tree) .. " " .. Q(rock), env_variables)) - assert(test_env.run.luarocks_nocov("pack --tree=" .. Q(testing_paths.testing_sys_tree) .. " " .. Q(rock), env_variables)) + local only_server = "--only-server=" .. testing_paths.testing_cache + local tree = "--tree=" .. testing_paths.testing_sys_tree + if not test_env.run.luarocks_nocov(test_env.quiet(C("install", only_server, tree, Q(rock)), env_variables)) then + assert(test_env.run.luarocks_nocov(C("build", tree, Q(rock)), env_variables)) + assert(test_env.run.luarocks_nocov(C("pack", tree, Q(rock)), env_variables)) move_file(rock .. "-*.rock", testing_paths.testing_cache) end end @@ -641,16 +684,6 @@ local function reset_environment(testing_paths, md5sums) end end -local function found_interpreter(testing_paths, luadir, lua_bindir) - local location = lua_bindir .. "/" .. testing_paths.lua_exe - if exists(location) then - testing_paths.lua_bindir = lua_bindir - testing_paths.luadir = luadir - testing_paths.lua = location - return true - end -end - local function find_lua() -- (1) LUA is a full path if test_env.LUA and test_env.LUA:match("[/\\]") then @@ -671,22 +704,22 @@ local function find_lua() if test_env.LUA_DIR then local luadir = test_env.LUA_DIR - local lua_bindir = exists(luadir .. "/bin") - and luadir .. "/bin" + local lua_bindir = exists(dir_path(luadir, "bin")) + and dir_path(luadir, "bin") or luadir - local lua = lua_bindir .. "/" .. lua_exe + local lua = dir_path(lua_bindir, lua_exe) return lua_bindir, luadir, lua end -- (2.2) LUA_DIR was not given, try some default paths local try_dirs = (test_env.TEST_TARGET_OS == "windows") - and { os.getenv("ProgramFiles(x86)").."/LuaRocks" } + and { os.getenv("ProgramFiles(x86)").."\\LuaRocks" } or { "/usr/local", "/usr" } for _, luadir in ipairs(try_dirs) do - for _, lua_bindir in ipairs({ luadir, luadir .. "/bin" }) do - local lua = lua_bindir .. "/" .. lua_exe + for _, lua_bindir in ipairs({ luadir, dir_path(luadir, "bin") }) do + local lua = dir_path(lua_bindir, lua_exe) if exists(lua) then return lua_bindir, luadir, lua end @@ -694,50 +727,47 @@ local function find_lua() end end -local function create_paths(luaversion_full) - - local testing_paths = {} +local function create_testing_paths(suffix) + local paths = {} - testing_paths.lua_bindir, testing_paths.luadir, testing_paths.lua = find_lua() - if (not testing_paths.lua) or (not exists(testing_paths.lua)) then + paths.lua_bindir, paths.luadir, paths.lua = find_lua() + if (not paths.lua) or (not exists(paths.lua)) then error("Lua interpreter not found! Run `busted -Xhelper help` for options") end local base_dir = lfs.currentdir() + paths.src_dir = dir_path(base_dir, "src") + paths.spec_dir = dir_path(base_dir, "spec") + paths.util_dir = dir_path(base_dir, "spec", "util") + paths.fixtures_dir = dir_path(base_dir, "spec", "fixtures") + paths.fixtures_repo_dir = dir_path(base_dir, "spec", "fixtures", "a_repo") + paths.gpg_dir = dir_path(base_dir, "spec", "fixtures", "gpg") + + local testrun_dir = dir_path(base_dir, "testrun") + paths.testrun_dir = testrun_dir + paths.testing_lrprefix = dir_path(testrun_dir, "testing_lrprefix-" .. suffix) + paths.testing_tree = dir_path(testrun_dir, "testing-" .. suffix) + paths.testing_tree_copy = dir_path(testrun_dir, "testing_copy-" .. suffix) + paths.testing_sys_tree = dir_path(testrun_dir, "testing_sys-" .. suffix) + paths.testing_sys_tree_copy = dir_path(testrun_dir, "testing_sys_copy-" .. suffix) + paths.testing_cache = dir_path(testrun_dir, "testing_cache-" .. suffix) + paths.testing_server = dir_path(testrun_dir, "testing_server-" .. suffix) + + local rocks_v = "rocks-" .. test_env.lua_version + paths.testing_rocks = dir_path(paths.testing_tree, "lib", "luarocks", rocks_v) + paths.testing_sys_rocks = dir_path(paths.testing_sys_tree, "lib", "luarocks", rocks_v) if test_env.TEST_TARGET_OS == "windows" then - base_dir = base_dir:gsub("\\","/") - end - - testing_paths.fixtures_dir = base_dir .. "/spec/fixtures" - testing_paths.gpg_dir = testing_paths.fixtures_dir .. "/gpg" - testing_paths.fixtures_repo_dir = base_dir .. "/spec/fixtures/a_repo" - testing_paths.util_dir = base_dir .. "/spec/util" - testing_paths.testrun_dir = base_dir .. "/testrun" - testing_paths.src_dir = base_dir .. "/src" - testing_paths.spec_dir = base_dir .. "/spec" - testing_paths.testing_lrprefix = testing_paths.testrun_dir .. "/testing_lrprefix-" .. luaversion_full - testing_paths.testing_tree = testing_paths.testrun_dir .. "/testing-" .. luaversion_full - testing_paths.testing_tree_copy = testing_paths.testrun_dir .. "/testing_copy-" .. luaversion_full - testing_paths.testing_sys_tree = testing_paths.testrun_dir .. "/testing_sys-" .. luaversion_full - testing_paths.testing_sys_tree_copy = testing_paths.testrun_dir .. "/testing_sys_copy-" .. luaversion_full - testing_paths.testing_cache = testing_paths.testrun_dir .. "/testing_cache-" .. luaversion_full - testing_paths.testing_server = testing_paths.testrun_dir .. "/testing_server-" .. luaversion_full - - testing_paths.testing_rocks = testing_paths.testing_tree .. "/lib/luarocks/rocks-" .. test_env.lua_version - testing_paths.testing_sys_rocks = testing_paths.testing_sys_tree .. "/lib/luarocks/rocks-" .. test_env.lua_version - - if test_env.TEST_TARGET_OS == "windows" then - testing_paths.luarocks_tmp = os.getenv("TEMP") + paths.luarocks_tmp = os.getenv("TEMP") else - testing_paths.luarocks_tmp = "/tmp/luarocks_testing" + paths.luarocks_tmp = "/tmp/luarocks_testing" end if test_env.TEST_TARGET_OS == "windows" then - testing_paths.win_tools = base_dir .. "/win32/tools" + paths.win_tools = dir_path(base_dir, "win32", "tools") end - return testing_paths + return paths end --- Helper function to unload luarocks modules from global table package.loaded @@ -748,7 +778,7 @@ function test_env.unload_luarocks() package.loaded[modname] = nil end end - local src_pattern = test_env.testing_paths.src_dir .. "/?.lua" + local src_pattern = dir_path(test_env.testing_paths.src_dir, "?.lua") if not package.path:find(src_pattern, 1, true) then package.path = src_pattern .. ";" .. package.path end @@ -760,16 +790,19 @@ local function get_luarocks_platform(variables) "cfg.init();" .. "print(cfg.arch)" .. "\"" - local cmd = test_env.testing_paths.lua .. " -e " .. print_arch_script + local cmd = C(test_env.testing_paths.lua, "-e", print_arch_script) return execute_output(cmd, false, variables) end --- Function for initial setup of environment, variables, md5sums for spec files function test_env.setup_specs(extra_rocks) + local testrun_dir = test_env.testing_paths.testrun_dir + local variables = test_env.env_variables + -- if global variable about successful creation of testing environment doesn't exist, build environment if not test_env.setup_done then if test_env.CI then - if not exists(os.getenv("HOME") .. "/.ssh/id_rsa.pub") then + if not exists(os.getenv("HOME"), ".ssh/id_rsa.pub") then execute_bool("ssh-keygen -t rsa -P \"\" -f ~/.ssh/id_rsa") execute_bool("cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys") execute_bool("chmod og-wx ~/.ssh/authorized_keys") @@ -783,8 +816,8 @@ function test_env.setup_specs(extra_rocks) require("spec.util.git_repo") require("spec.util.quick") - package.path = test_env.env_variables.LUA_PATH - package.cpath = test_env.env_variables.LUA_CPATH + package.path = variables.LUA_PATH + package.cpath = variables.LUA_CPATH test_env.platform = get_luarocks_platform(test_env.env_variables) test_env.wrapper_extension = test_env.TEST_TARGET_OS == "windows" and ".bat" or "" @@ -801,10 +834,10 @@ function test_env.setup_specs(extra_rocks) end if test_env.RESET_ENV then - reset_environment(test_env.testing_paths, test_env.md5sums, test_env.env_variables) + reset_environment(test_env.testing_paths, test_env.md5sums, variables) end - lfs.chdir(test_env.testing_paths.testrun_dir) + lfs.chdir(testrun_dir) end --- Test if required rock is installed and if not, install it. @@ -829,7 +862,11 @@ end -- replace %{key} in given string with value. local function substitute(str, replacements) return (str:gsub("%%%b{}", function(marker) - return replacements[marker:sub(3, -2)] + local r = replacements[marker:sub(3, -2)] + if r then + r = r:gsub("\\", "\\\\") + end + return r end)) end @@ -837,6 +874,8 @@ end --- Create configs for luacov and several versions of Luarocks -- configs needed for some tests. local function create_configs() + local testrun_dir = test_env.testing_paths.testrun_dir + -- testing_config.lua -- testing_config_show_downloads.lua -- testing_config_no_downloader.lua @@ -857,17 +896,17 @@ local function create_configs() }, } ]], { - user = os.getenv("USER"), + user = "testuser", testing_sys_tree = test_env.testing_paths.testing_sys_tree, testing_tree = test_env.testing_paths.testing_tree, testing_server = test_env.testing_paths.testing_server, testing_cache = test_env.testing_paths.testing_cache }) - test_env.write_file(test_env.testing_paths.testrun_dir .. "/testing_config.lua", config_content .. " \nweb_browser = \"true\"") - test_env.write_file(test_env.testing_paths.testrun_dir .. "/testing_config_show_downloads.lua", config_content + test_env.write_file(dir_path(testrun_dir, "testing_config.lua"), config_content .. " \nweb_browser = \"true\"") + test_env.write_file(dir_path(testrun_dir, "testing_config_show_downloads.lua"), config_content .. "show_downloads = true \n rocks_servers={\"http://luarocks.org/repositories/rocks\"}") - test_env.write_file(test_env.testing_paths.testrun_dir .. "/testing_config_no_downloader.lua", config_content + test_env.write_file(dir_path(testrun_dir, "testing_config_no_downloader.lua"), config_content .. "variables = { WGET = 'invalid', CURL = 'invalid' }") -- testing_config_sftp.lua @@ -885,32 +924,35 @@ local function create_configs() }, } ]], { - user = os.getenv("USER"), + user = "testuser", testing_sys_tree = test_env.testing_paths.testing_sys_tree, testing_tree = test_env.testing_paths.testing_tree, testing_cache = test_env.testing_paths.testing_cache }) - test_env.write_file(test_env.testing_paths.testrun_dir .. "/testing_config_sftp.lua", config_content) + test_env.write_file(dir_path(testrun_dir, "testing_config_sftp.lua"), config_content) -- luacov.config config_content = substitute([[ return { - statsfile = "%{testrun_dir}/luacov.stats.out", - reportfile = "%{testrun_dir}/luacov.report.out", + statsfile = "%{statsfile}", + reportfile = "%{reportfile}", modules = { - ["luarocks"] = "src/bin/luarocks", - ["luarocks-admin"] = "src/bin/luarocks-admin", + ["luarocks"] = "%{luarocks_path}", + ["luarocks-admin"] = "%{luarocks_admin_path}", ["luarocks.*"] = "src", ["luarocks.*.*"] = "src", ["luarocks.*.*.*"] = "src" } } ]], { - testrun_dir = test_env.testing_paths.testrun_dir + statsfile = dir_path(testrun_dir, "luacov.stats.out"), + reportfile = dir_path(testrun_dir, "luacov.report.out"), + luarocks_path = dir_path("src", "bin", "luarocks"), + luarocks_admin_path = dir_path("src", "bin", "luarocks-admin"), }) - test_env.write_file(test_env.testing_paths.testrun_dir .. "/luacov.config", config_content) + test_env.write_file(dir_path(testrun_dir, "luacov.config"), config_content) config_content = [[ -- Config file of mock LuaRocks.org site for tests @@ -920,18 +962,20 @@ local function create_configs() api_version = "1", } ]] - test_env.write_file(test_env.testing_paths.testrun_dir .. "/luarocks_site.lua", config_content) + test_env.write_file(dir_path(testrun_dir, "luarocks_site.lua"), config_content) end --- Remove testing directories. local function clean() + local testrun_dir = test_env.testing_paths.testrun_dir + print("Cleaning testing directory...") test_env.remove_dir(test_env.testing_paths.luarocks_tmp) - test_env.remove_subdirs(test_env.testing_paths.testrun_dir, "testing[_%-]") - test_env.remove_files(test_env.testing_paths.testrun_dir, "testing_") - test_env.remove_files(test_env.testing_paths.testrun_dir, "luacov") - test_env.remove_files(test_env.testing_paths.testrun_dir, "upload_config") - test_env.remove_files(test_env.testing_paths.testrun_dir, "luarocks_site") + test_env.remove_subdirs(testrun_dir, "testing[_%-]") + test_env.remove_files(testrun_dir, "testing_") + test_env.remove_files(testrun_dir, "luacov") + test_env.remove_files(testrun_dir, "upload_config") + test_env.remove_files(testrun_dir, "luarocks_site") print("Cleaning done!") end @@ -942,7 +986,7 @@ local function setup_luarocks() local lines = { "return {", - ("SYSCONFDIR = %q,"):format(testing_paths.testing_lrprefix .. "/etc/luarocks"), + ("SYSCONFDIR = %q,"):format(dir_path(testing_paths.testing_lrprefix, "etc/luarocks")), ("LUA_DIR = %q,"):format(testing_paths.luadir), ("LUA_BINDIR = %q,"):format(testing_paths.lua_bindir), ("LUA = %q,"):format(testing_paths.lua), @@ -965,33 +1009,33 @@ local function setup_luarocks() end local function mock_api_call(path) - if test_env.TEST_TARGET_OS == "windows" then - return test_env.execute(Q(test_env.testing_paths.win_tools .. "/wget") .. " --quiet --timeout=5 --tries=1 localhost:8080" .. path) - else - return test_env.execute("curl -s localhost:8080" .. path) - end + test_env.execute(C(tool("wget"), "--quiet --timeout=5 --tries=1 localhost:8080" .. path)) end function test_env.mock_server_init() local testing_paths = test_env.testing_paths assert(test_env.need_rock("restserver-xavante")) - if test_env.TEST_TARGET_OS == "windows" then - os.execute(test_env.execute_helper("start /b \"\" " .. Q(testing_paths.lua) .. " " .. Q(testing_paths.util_dir .. "/mock-server.lua") .. " " .. Q(testing_paths.fixtures_dir), true, test_env.env_variables)) - else - os.execute(test_env.execute_helper(testing_paths.lua .. " " .. testing_paths.util_dir .. "/mock-server.lua " .. testing_paths.fixtures_dir .. " &", true, test_env.env_variables)) - end + local lua = Q(testing_paths.lua) + local mock_server = Q(dir_path(testing_paths.util_dir, "mock-server.lua")) + local fixtures_dir = Q(testing_paths.fixtures_dir) + + local cmd = C(lua, mock_server, fixtures_dir) + + local bg_cmd = test_env.TEST_TARGET_OS == "windows" + and C("start", "/b", "\"\"", cmd) + or C(cmd, "&") + + os.execute(test_env.execute_helper(bg_cmd, true, test_env.env_variables)) for _ = 1, 10 do if mock_api_call("/api/tool_version") then break end - if test_env.TEST_TARGET_OS == "windows" then - os.execute("timeout 1 > NUL") - else - os.execute("sleep 1") - end + os.execute(test_env.TEST_TARGET_OS == "windows" + and "timeout 1 > NUL" + or "sleep 1") end end @@ -1000,9 +1044,9 @@ function test_env.mock_server_done() mock_api_call("/shutdown") end -local function find_binary_rock(src_rock, dir) +local function find_binary_rock(src_rock, dirname) local patt = src_rock:gsub("([.-])", "%%%1"):gsub("src", ".*[^s][^r][^c]") - for name in lfs.dir(dir) do + for name in lfs.dir(dirname) do if name:match(patt) then return true end @@ -1034,14 +1078,18 @@ local function prepare_mock_server_binary_rocks() rock = V(rock) local rockname = rock:gsub("%-[^-]+%-%d+%.[%a.]+$", "") if not find_binary_rock(rock, testing_paths.testing_server) then - test_env.run.luarocks_nocov("build " .. Q(testing_paths.testing_server .. "/" .. rock) .. " --tree=" .. testing_paths.testing_cache) - test_env.run.luarocks_nocov("pack " .. rockname .. " --tree=" .. testing_paths.testing_cache) + local rockpath = dir_path(testing_paths.testing_server, rock) + local tree = "--tree=" .. testing_paths.testing_cache + + test_env.run.luarocks_nocov(C("build", Q(rockpath), tree)) + test_env.run.luarocks_nocov(C("pack", rockname, tree)) + move_file(rockname .. "-*.rock", testing_paths.testing_server) make_manifest = true end end if make_manifest then - test_env.run.luarocks_admin_nocov("make_manifest " .. Q(testing_paths.testing_server)) + test_env.run.luarocks_admin_nocov(C("make_manifest", Q(testing_paths.testing_server))) end end @@ -1049,13 +1097,14 @@ end -- Main function to create config files and testing environment function test_env.main() local testing_paths = test_env.testing_paths + local testrun_dir = test_env.testing_paths.testrun_dir if test_env.TEST_ENV_CLEAN then clean() end - lfs.mkdir(testing_paths.testrun_dir) - test_env.write_file(testing_paths.testrun_dir .. "/.luarocks-no-project", "") + lfs.mkdir(testrun_dir) + test_env.write_file(dir_path(testrun_dir, ".luarocks-no-project"), "") lfs.mkdir(testing_paths.testing_cache) lfs.mkdir(testing_paths.luarocks_tmp) @@ -1068,7 +1117,7 @@ function test_env.main() local urls = {} -- names of rock and rockspec files to be downloaded local env_vars = { - LUAROCKS_CONFIG = test_env.testing_paths.testrun_dir .. "/testing_config.lua" + LUAROCKS_CONFIG = dir_path(testrun_dir, "testing_config.lua") } if test_env.TYPE_TEST_ENV == "full" then @@ -1088,8 +1137,8 @@ function test_env.main() table.insert(urls, "/luaposix-${LUAPOSIX}.src.rock") table.insert(rocks, "luaposix") end - assert(test_env.run.luarocks_nocov("config variables.OPENSSL_INCDIR " .. Q(test_env.OPENSSL_INCDIR), env_vars)) - assert(test_env.run.luarocks_nocov("config variables.OPENSSL_LIBDIR " .. Q(test_env.OPENSSL_LIBDIR), env_vars)) + assert(test_env.run.luarocks_nocov(C("config", "variables.OPENSSL_INCDIR", Q(test_env.OPENSSL_INCDIR)), env_vars)) + assert(test_env.run.luarocks_nocov(C("config", "variables.OPENSSL_LIBDIR", Q(test_env.OPENSSL_LIBDIR)), env_vars)) end -- luacov is needed for both minimal or full environment @@ -1111,12 +1160,13 @@ end test_env.set_lua_version() test_env.set_args() -test_env.testing_paths = create_paths(test_env.LUA_V or test_env.LUAJIT_V) +test_env.testing_paths = create_testing_paths(test_env.LUA_V or test_env.LUAJIT_V) test_env.env_variables = create_env(test_env.testing_paths) test_env.run = make_run_functions() test_env.exists = exists test_env.V = V test_env.Q = Q +test_env.P = P test_env.platform = get_luarocks_platform(test_env.env_variables) return test_env -- cgit v1.2.3-55-g6feb