aboutsummaryrefslogtreecommitdiff
path: root/test/test_environment.lua
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--test/test_environment.lua599
1 files changed, 599 insertions, 0 deletions
diff --git a/test/test_environment.lua b/test/test_environment.lua
new file mode 100644
index 00000000..6de7a4e2
--- /dev/null
+++ b/test/test_environment.lua
@@ -0,0 +1,599 @@
1local lfs = require("lfs")
2local test_env = {}
3
4local help_message = [[
5LuaRocks test-suite
6
7INFORMATION
8 New test-suite for LuaRocks project, using unit testing framework Busted.
9REQUIREMENTS
10 Be sure sshd is running on your system, or use '--exclude-tags=ssh',
11 to not execute tests which require sshd.
12USAGE
13 busted [-Xhelper <arguments>]
14ARGUMENTS
15 env=<type> Set type of environment to use ("minimal" or "full",
16 default: "minimal").
17 clean Remove existing testing environment.
18 travis Add if running on TravisCI.
19 os=<type> Set OS ("linux", "osx", or "windows").
20]]
21
22local function help()
23 print(help_message)
24 os.exit(1)
25end
26
27local function title(str)
28 print()
29 print(("-"):rep(#str))
30 print(str)
31 print(("-"):rep(#str))
32end
33
34local function exists(path)
35 return lfs.attributes(path, "mode") ~= nil
36end
37
38--- Helper function for execute_bool and execute_output
39-- @param command string: command to execute
40-- @param print_command boolean: print command if 'true'
41-- @param env_variables table: table of environment variables to export {FOO="bar", BAR="foo"}
42-- @return final_command string: concatenated command to execution
43local function execute_helper(command, print_command, env_variables)
44 local final_command = ""
45
46 if print_command then
47 print("\n[EXECUTING]: " .. command)
48 end
49
50 if env_variables then
51 final_command = "export "
52 for k,v in pairs(env_variables) do
53 final_command = final_command .. k .. "='" .. v .. "' "
54 end
55 -- remove last space and add ';' to separate exporting variables from command
56 final_command = final_command:sub(1, -2) .. "; "
57 end
58
59 final_command = final_command .. command
60
61 return final_command
62end
63
64--- Execute command and returns true/false
65-- In Lua5.1 os.execute returns numeric value, but in Lua5.2+ returns boolean
66-- @return true/false boolean: status of the command execution
67local function execute_bool(command, print_command, env_variables)
68 command = execute_helper(command, print_command, env_variables)
69
70 local ok = os.execute(command)
71 return ok == true or ok == 0
72end
73
74--- Execute command and returns output of command
75-- @return output string: output the command execution
76local function execute_output(command, print_command, env_variables)
77 command = execute_helper(command, print_command, env_variables)
78
79 local file = assert(io.popen(command))
80 local output = file:read('*all')
81 file:close()
82 return output:gsub("\n","") -- output adding new line, need to be removed
83end
84
85--- Set test_env.LUA_V or test_env.LUAJIT_V based
86-- on version of Lua used to run this script.
87function test_env.set_lua_version()
88 if _G.jit then
89 test_env.LUAJIT_V = _G.jit.version:match("(2%.%d)%.%d")
90 else
91 test_env.LUA_V = _VERSION:match("5%.%d")
92 end
93end
94
95--- Set all arguments from input into global variables
96function test_env.set_args()
97 -- if at least Lua/LuaJIT version argument was found on input start to parse other arguments to env. variables
98 test_env.TYPE_TEST_ENV = "minimal"
99
100 for _, argument in ipairs(arg) do
101 if argument:find("^env=") then
102 test_env.TYPE_TEST_ENV = argument:match("^env=(.*)$")
103 elseif argument == "clean" then
104 test_env.TEST_ENV_CLEAN = true
105 elseif argument == "travis" then
106 test_env.TRAVIS = true
107 elseif argument:find("^os=") then
108 test_env.TEST_TARGET_OS = argument:match("^os=(.*)$")
109 else
110 help()
111 end
112 end
113
114 if not test_env.TEST_TARGET_OS then
115 title("OS CHECK")
116
117 if execute_bool("sw_vers") then
118 test_env.TEST_TARGET_OS = "osx"
119 elseif execute_bool("uname -s") then
120 test_env.TEST_TARGET_OS = "linux"
121 else
122 test_env.TEST_TARGET_OS = "windows"
123 end
124 end
125 return true
126end
127
128--- Remove directory recursively
129-- @param path string: directory path to delete
130function test_env.remove_dir(path)
131 if exists(path) then
132 for file in lfs.dir(path) do
133 if file ~= "." and file ~= ".." then
134 local full_path = path..'/'..file
135
136 if lfs.attributes(full_path, "mode") == "directory" then
137 test_env.remove_dir(full_path)
138 else
139 os.remove(full_path)
140 end
141 end
142 end
143 end
144 os.remove(path)
145end
146
147--- Remove subdirectories of a directory that match a pattern
148-- @param path string: path to directory
149-- @param pattern string: pattern matching basenames of subdirectories to be removed
150function test_env.remove_subdirs(path, pattern)
151 if exists(path) then
152 for file in lfs.dir(path) do
153 if file ~= "." and file ~= ".." then
154 local full_path = path..'/'..file
155
156 if lfs.attributes(full_path, "mode") == "directory" and file:find(pattern) then
157 test_env.remove_dir(full_path)
158 end
159 end
160 end
161 end
162end
163
164--- Remove files matching a pattern
165-- @param path string: directory where to delete files
166-- @param pattern string: pattern matching basenames of files to be deleted
167-- @return result_check boolean: true if one or more files deleted
168function test_env.remove_files(path, pattern)
169 local result_check = false
170 if exists(path) then
171 for file in lfs.dir(path) do
172 if file ~= "." and file ~= ".." then
173 if file:find(pattern) then
174 if os.remove(path .. "/" .. file) then
175 result_check = true
176 end
177 end
178 end
179 end
180 end
181 return result_check
182end
183
184
185--- Function for downloading rocks and rockspecs
186-- @param urls table: array of full names of rocks/rockspecs to download
187-- @param save_path string: path to directory, where to download rocks/rockspecs
188-- @return make_manifest boolean: true if new rocks downloaded
189local function download_rocks(urls, save_path)
190 local luarocks_repo = "https://luarocks.org"
191 local make_manifest = false
192
193 for _, url in ipairs(urls) do
194 -- check if already downloaded
195 if not exists(save_path .. url) then
196 execute_bool("wget -cP " .. save_path .. " " .. luarocks_repo .. url)
197 make_manifest = true
198 end
199 end
200 return make_manifest
201end
202
203--- Create a file containing a string.
204-- @param path string: path to file.
205-- @param str string: content of the file.
206local function write_file(path, str)
207 local file = assert(io.open(path, "w"))
208 file:write(str)
209 file:close()
210end
211
212--- Create md5sum of directory structure recursively, based on filename and size
213-- @param path string: path to directory for generate md5sum
214-- @return md5sum string: md5sum of directory
215local function hash_environment(path)
216 if test_env.TEST_TARGET_OS == "linux" then
217 return execute_output("find " .. path .. " -printf \"%s %p\n\" | md5sum")
218 elseif test_env.TEST_TARGET_OS == "osx" then
219 return execute_output("find " .. path .. " -type f -exec stat -f \"%z %N\" {} \\; | md5")
220 else
221 -- TODO: Windows
222 return ""
223 end
224end
225
226--- Create environment variables needed for tests
227-- @param testing_paths table: table with paths to testing directory
228-- @return env_variables table: table with created environment variables
229local function create_env(testing_paths)
230 local luaversion_short = _VERSION:gsub("Lua ", "")
231
232 if test_env.LUAJIT_V then
233 luaversion_short="5.1"
234 end
235
236 local env_variables = {}
237 env_variables.LUA_VERSION = luaversion_short
238 env_variables.LUAROCKS_CONFIG = testing_paths.testing_dir .. "/testing_config.lua"
239 env_variables.LUA_PATH = testing_paths.testing_tree .. "/share/lua/" .. luaversion_short .. "/?.lua;"
240 env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_tree .. "/share/lua/".. luaversion_short .. "/?/init.lua;"
241 env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_sys_tree .. "/share/lua/" .. luaversion_short .. "/?.lua;"
242 env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.testing_sys_tree .. "/share/lua/".. luaversion_short .. "/?/init.lua;"
243 env_variables.LUA_PATH = env_variables.LUA_PATH .. testing_paths.src_dir .. "/?.lua;"
244 env_variables.LUA_CPATH = testing_paths.testing_tree .. "/lib/lua/" .. luaversion_short .. "/?.so;"
245 .. testing_paths.testing_sys_tree .. "/lib/lua/" .. luaversion_short .. "/?.so;"
246 env_variables.PATH = os.getenv("PATH") .. ":" .. testing_paths.testing_tree .. "/bin:" .. testing_paths.testing_sys_tree .. "/bin"
247
248 return env_variables
249end
250
251--- Create md5sums of origin system and system-copy testing directory
252-- @param testing_paths table: table with paths to testing directory
253-- @return md5sums table: table of md5sums of system and system-copy testing directory
254local function create_md5sums(testing_paths)
255 local md5sums = {}
256 md5sums.testing_tree_copy_md5 = hash_environment(testing_paths.testing_tree_copy)
257 md5sums.testing_sys_tree_copy_md5 = hash_environment(testing_paths.testing_sys_tree_copy)
258
259 return md5sums
260end
261
262local function make_run_function(cmd_name, exec_function, with_coverage, do_print)
263 local cmd_prefix = test_env.testing_paths.lua .. " "
264
265 if with_coverage then
266 cmd_prefix = cmd_prefix .. "-e \"require('luacov.runner')('" .. test_env.testing_paths.testing_dir .. "/luacov.config')\" "
267 end
268
269 cmd_prefix = cmd_prefix .. test_env.testing_paths.src_dir .. "/bin/" .. cmd_name .. " "
270
271 return function(cmd, new_vars)
272 local temp_vars = {}
273 for k, v in pairs(test_env.env_variables) do
274 temp_vars[k] = v
275 end
276 if new_vars then
277 for k, v in pairs(new_vars) do
278 temp_vars[k] = v
279 end
280 end
281 return exec_function(cmd_prefix .. cmd, do_print, temp_vars)
282 end
283end
284
285local function make_run_functions()
286 return {
287 luarocks = make_run_function("luarocks", execute_output, true, true),
288 luarocks_bool = make_run_function("luarocks", execute_bool, true, true),
289 luarocks_noprint = make_run_function("luarocks", execute_bool, true, false),
290 luarocks_nocov = make_run_function("luarocks", execute_bool, false, true),
291 luarocks_noprint_nocov = make_run_function("luarocks", execute_bool, false, false),
292 luarocks_admin = make_run_function("luarocks-admin", execute_output, true, true),
293 luarocks_admin_bool = make_run_function("luarocks-admin", execute_bool, true, true),
294 luarocks_admin_nocov = make_run_function("luarocks-admin", execute_bool, false, false)
295 }
296end
297
298--- Rebuild environment.
299-- Remove old installed rocks and install new ones,
300-- updating manifests and tree copies.
301local function build_environment(rocks, env_variables)
302 title("BUILDING ENVIRONMENT")
303 local testing_paths = test_env.testing_paths
304 test_env.remove_dir(testing_paths.testing_tree)
305 test_env.remove_dir(testing_paths.testing_sys_tree)
306 test_env.remove_dir(testing_paths.testing_tree_copy)
307 test_env.remove_dir(testing_paths.testing_sys_tree_copy)
308
309 lfs.mkdir(testing_paths.testing_tree)
310 lfs.mkdir(testing_paths.testing_sys_tree)
311
312 test_env.run.luarocks_admin_nocov("make_manifest " .. testing_paths.testing_server)
313 test_env.run.luarocks_admin_nocov("make_manifest " .. testing_paths.testing_cache)
314
315 for _, rock in ipairs(rocks) do
316 if not test_env.run.luarocks_nocov("install --only-server=" .. testing_paths.testing_cache .. " --tree=" .. testing_paths.testing_sys_tree .. " " .. rock, env_variables) then
317 test_env.run.luarocks_nocov("build --tree=" .. testing_paths.testing_sys_tree .. " " .. rock, env_variables)
318 test_env.run.luarocks_nocov("pack --tree=" .. testing_paths.testing_sys_tree .. " " .. rock, env_variables)
319 execute_bool("mv " .. rock .. "-*.rock " .. testing_paths.testing_cache)
320 end
321 end
322
323 execute_bool("cp -a " .. testing_paths.testing_tree .. "/. " .. testing_paths.testing_tree_copy)
324 execute_bool("cp -a " .. testing_paths.testing_sys_tree .. "/. " .. testing_paths.testing_sys_tree_copy)
325end
326
327--- Reset testing environment
328local function reset_environment(testing_paths, md5sums)
329 local testing_tree_md5 = hash_environment(testing_paths.testing_tree)
330 local testing_sys_tree_md5 = hash_environment(testing_paths.testing_sys_tree)
331
332 if testing_tree_md5 ~= md5sums.testing_tree_copy_md5 then
333 test_env.remove_dir(testing_paths.testing_tree)
334 execute_bool("cp -a " .. testing_paths.testing_tree_copy .. "/. " .. testing_paths.testing_tree)
335 end
336 if testing_sys_tree_md5 ~= md5sums.testing_sys_tree_copy_md5 then
337 test_env.remove_dir(testing_paths.testing_sys_tree)
338 execute_bool("cp -a " .. testing_paths.testing_sys_tree_copy .. "/. " .. testing_paths.testing_sys_tree)
339 end
340
341 print("\n[ENVIRONMENT RESET]")
342end
343
344local function create_paths(luaversion_full)
345 local cfg = require("luarocks.cfg")
346
347 local testing_paths = {}
348 testing_paths.luadir = cfg.variables.LUA_BINDIR:gsub("/bin/?$", "")
349 testing_paths.lua = cfg.variables.LUA_BINDIR .. "/" .. cfg.lua_interpreter
350
351 testing_paths.luarocks_tmp = "/tmp/luarocks_testing" --windows?
352
353 testing_paths.luarocks_dir = lfs.currentdir()
354 testing_paths.testing_dir = testing_paths.luarocks_dir .. "/test"
355 testing_paths.src_dir = testing_paths.luarocks_dir .. "/src"
356 testing_paths.testing_lrprefix = testing_paths.testing_dir .. "/testing_lrprefix-" .. luaversion_full
357 testing_paths.testing_tree = testing_paths.testing_dir .. "/testing-" .. luaversion_full
358 testing_paths.testing_tree_copy = testing_paths.testing_dir .. "/testing_copy-" .. luaversion_full
359 testing_paths.testing_sys_tree = testing_paths.testing_dir .. "/testing_sys-" .. luaversion_full
360 testing_paths.testing_sys_tree_copy = testing_paths.testing_dir .. "/testing_sys_copy-" .. luaversion_full
361 testing_paths.testing_cache = testing_paths.testing_dir .. "/testing_cache-" .. luaversion_full
362 testing_paths.testing_server = testing_paths.testing_dir .. "/testing_server-" .. luaversion_full
363
364 return testing_paths
365end
366
367--- Helper function to unload luarocks modules from global table package.loaded
368-- Needed to load our local (testing) version of LuaRocks
369function test_env.unload_luarocks()
370 for modname, _ in pairs(package.loaded) do
371 if modname:match("^luarocks%.") then
372 package.loaded[modname] = nil
373 end
374 end
375end
376
377--- Function for initially setup of environment, variables, md5sums for spec files
378function test_env.setup_specs(extra_rocks)
379 -- if global variable about successful creation of testing environment doesn't exists, build environment
380 if not test_env.setup_done then
381 if test_env.TRAVIS then
382 if not exists(os.getenv("HOME") .. "/.ssh/id_rsa.pub") then
383 execute_bool("ssh-keygen -t rsa -P \"\" -f ~/.ssh/id_rsa")
384 execute_bool("cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys")
385 execute_bool("chmod og-wx ~/.ssh/authorized_keys")
386 execute_bool("ssh-keyscan localhost >> ~/.ssh/known_hosts")
387 end
388 end
389
390 test_env.main()
391 package.path = test_env.env_variables.LUA_PATH
392
393 test_env.platform = execute_output(test_env.testing_paths.lua .. " -e 'print(require(\"luarocks.cfg\").arch)'", false, test_env.env_variables)
394 test_env.md5sums = create_md5sums(test_env.testing_paths)
395 test_env.setup_done = true
396 title("RUNNING TESTS")
397 end
398
399 if extra_rocks then
400 local make_manifest = download_rocks(extra_rocks, test_env.testing_paths.testing_server)
401 if make_manifest then
402 test_env.run.luarocks_admin_nocov("make_manifest " .. test_env.testing_paths.testing_server)
403 end
404 end
405
406 reset_environment(test_env.testing_paths, test_env.md5sums, test_env.env_variables)
407end
408
409--- Helper function for tests which needs luasocket installed
410function test_env.need_luasocket()
411 if test_env.run.luarocks_nocov("show luasocket") then
412 return true
413 else
414 local testing_cache = test_env.testing_paths.testing_cache .. "/"
415 local luasocket_rock = "luasocket-3.0rc1-1." .. test_env.platform .. ".rock"
416 if not exists(testing_cache .. luasocket_rock) then
417 test_env.run.luarocks_nocov("build --pack-binary-rock luasocket 3.0rc1-1")
418 os.rename(luasocket_rock, testing_cache .. luasocket_rock)
419 end
420 return test_env.run.luarocks_nocov("install " .. testing_cache .. luasocket_rock)
421 end
422end
423
424--- For each key-value pair in replacements table
425-- replace %{key} in given string with value.
426local function substitute(str, replacements)
427 return (str:gsub("%%%b{}", function(marker)
428 return replacements[marker:sub(3, -2)]
429 end))
430end
431
432
433--- Create configs for luacov and several versions of Luarocks
434-- configs needed for some tests.
435local function create_configs()
436 -- testing_config.lua and testing_config_show_downloads.lua
437 local config_content = substitute([[
438 rocks_trees = {
439 "%{testing_tree}",
440 { name = "system", root = "%{testing_sys_tree}" },
441 }
442 rocks_servers = {
443 "%{testing_server}"
444 }
445 local_cache = "%{testing_cache}"
446 upload_server = "testing"
447 upload_user = "%{user}"
448 upload_servers = {
449 testing = {
450 rsync = "localhost/tmp/luarocks_testing",
451 },
452 }
453 external_deps_dirs = {
454 "/usr/local",
455 "/usr",
456 -- These are used for a test that fails, so it
457 -- can point to invalid paths:
458 {
459 prefix = "/opt",
460 bin = "bin",
461 include = "include",
462 lib = { "lib", "lib64" },
463 }
464 }
465 ]], {
466 user = os.getenv("USER"),
467 testing_sys_tree = test_env.testing_paths.testing_sys_tree,
468 testing_tree = test_env.testing_paths.testing_tree,
469 testing_server = test_env.testing_paths.testing_server,
470 testing_cache = test_env.testing_paths.testing_cache
471 })
472
473 write_file(test_env.testing_paths.testing_dir .. "/testing_config.lua", config_content .. " \nweb_browser = \"true\"")
474 write_file(test_env.testing_paths.testing_dir .. "/testing_config_show_downloads.lua", config_content
475 .. "show_downloads = true \n rocks_servers={\"http://luarocks.org/repositories/rocks\"}")
476
477 -- testing_config_sftp.lua
478 config_content = substitute([[
479 rocks_trees = {
480 "%{testing_tree}",
481 "%{testing_sys_tree}",
482 }
483 local_cache = "%{testing_cache}"
484 upload_server = "testing"
485 upload_user = "%{user}"
486 upload_servers = {
487 testing = {
488 sftp = "localhost/tmp/luarocks_testing",
489 },
490 }
491 ]], {
492 user = os.getenv("USER"),
493 testing_sys_tree = test_env.testing_paths.testing_sys_tree,
494 testing_tree = test_env.testing_paths.testing_tree,
495 testing_cache = test_env.testing_paths.testing_cache
496 })
497
498 write_file(test_env.testing_paths.testing_dir .. "/testing_config_sftp.lua", config_content)
499
500 -- luacov.config
501 config_content = substitute([[
502 return {
503 statsfile = "%{testing_dir}/luacov.stats.out",
504 reportfile = "%{testing_dir}/luacov.report.out",
505 modules = {
506 ["luarocks"] = "src/bin/luarocks",
507 ["luarocks-admin"] = "src/bin/luarocks-admin",
508 ["luarocks.*"] = "src",
509 ["luarocks.*.*"] = "src",
510 ["luarocks.*.*.*"] = "src"
511 }
512 }
513 ]], {
514 testing_dir = test_env.testing_paths.testing_dir
515 })
516
517 write_file(test_env.testing_paths.testing_dir .. "/luacov.config", config_content)
518end
519
520--- Remove testing directories.
521local function clean()
522 print("Cleaning testing directory...")
523 test_env.remove_dir(test_env.testing_paths.luarocks_tmp)
524 test_env.remove_subdirs(test_env.testing_paths.testing_dir, "testing[_%-]")
525 test_env.remove_files(test_env.testing_paths.testing_dir, "testing_")
526 test_env.remove_files(test_env.testing_paths.testing_dir, "luacov")
527 print("Cleaning done!")
528end
529
530--- Install luarocks into testing prefix.
531local function install_luarocks(install_env_vars)
532 -- Configure LuaRocks testing environment
533 local configure_cmd = "./configure --with-lua=" .. test_env.testing_paths.luadir ..
534 " --prefix=" .. test_env.testing_paths.testing_lrprefix ..
535 " && make clean"
536
537 assert(execute_bool(configure_cmd, false, install_env_vars))
538 assert(execute_bool("make src/luarocks/site_config.lua && make dev", false, install_env_vars))
539end
540
541---
542-- Main function to create config files and testing environment
543function test_env.main()
544 local testing_paths = test_env.testing_paths
545
546 if test_env.TEST_ENV_CLEAN then
547 clean()
548 end
549
550 lfs.mkdir(testing_paths.testing_cache)
551 lfs.mkdir(testing_paths.luarocks_tmp)
552
553 create_configs()
554
555 local install_env_vars = {
556 LUAROCKS_CONFIG = test_env.testing_paths.testing_dir .. "/testing_config.lua",
557 LUA_PATH = "",
558 LUA_CPATH = ""
559 }
560
561 install_luarocks(install_env_vars)
562
563 -- Preparation of rocks for building environment
564 local rocks = {} -- names of rocks, required for building environment
565 local urls = {} -- names of rock and rockspec files to be downloaded
566 table.insert(urls, "/luacov-0.11.0-1.rockspec")
567 table.insert(urls, "/luacov-0.11.0-1.src.rock")
568
569 if test_env.TYPE_TEST_ENV == "full" then
570 table.insert(urls, "/luafilesystem-1.6.3-1.src.rock")
571 table.insert(urls, "/luasocket-3.0rc1-1.src.rock")
572 table.insert(urls, "/luasocket-3.0rc1-1.rockspec")
573 table.insert(urls, "/luaposix-33.2.1-1.src.rock")
574 table.insert(urls, "/md5-1.2-1.src.rock")
575 table.insert(urls, "/lzlib-0.4.1.53-1.src.rock")
576 rocks = {"luafilesystem", "luasocket", "luaposix", "md5", "lzlib"}
577
578 if test_env.LUA_V ~= "5.1" then
579 table.insert(urls, "/luabitop-1.0.2-1.rockspec")
580 table.insert(urls, "/luabitop-1.0.2-1.src.rock")
581 table.insert(rocks, "luabitop")
582 end
583 end
584
585 table.insert(rocks, "luacov") -- luacov is needed for minimal or full environment
586
587 -- Download rocks needed for LuaRocks testing environment
588 lfs.mkdir(testing_paths.testing_server)
589 download_rocks(urls, testing_paths.testing_server)
590 build_environment(rocks, install_env_vars)
591end
592
593test_env.set_lua_version()
594test_env.set_args()
595test_env.testing_paths = create_paths(test_env.LUA_V or test_env.LUAJIT_V)
596test_env.env_variables = create_env(test_env.testing_paths)
597test_env.run = make_run_functions()
598
599return test_env