# # # patch "tester-testsuite.lua" # from [3153cf2384274b7290226e99383378926d9f64ff] # to [befdacc2d9be5065780fd668bd242e01ed25d793] # # patch "tester.cc" # from [f96149cc40286220a17e2c8713fdb94aa0f35118] # to [359d6329c9f549d6d0d47ef66fa24b7ac604255d] # # patch "testlib.lua" # from [8ec06c74bad74bfd0fb2000f39cc2c88d18c5467] # to [a1e48a128c3e3c787204885ac188217be9d3f82a] # # patch "testsuite.lua" # from [468554c427354f1b781a7146cfa78b242afa4ddd] # to [858afba9d790d7ff83092c18d5442bcdc59547fc] # ============================================================ --- tester-testsuite.lua 3153cf2384274b7290226e99383378926d9f64ff +++ tester-testsuite.lua befdacc2d9be5065780fd668bd242e01ed25d793 @@ -1,8 +1,2 @@ - +-- we have very little to do here; just declare the directory of tests. testdir = srcdir.."/tester-tests" - -table.insert(tests, "isolated-1") -table.insert(tests, "isolated-2") -table.insert(tests, "cleanup-1") -table.insert(tests, "cleanup-2") -table.insert(tests, "remove-unwriteable") ============================================================ --- tester.cc f96149cc40286220a17e2c8713fdb94aa0f35118 +++ tester.cc 359d6329c9f549d6d0d47ef66fa24b7ac604255d @@ -831,53 +831,81 @@ int main(int argc, char **argv) { int retcode = 2; lua_State *st = 0; - try{ -// global_sanity.set_debug(); - string testfile; - string firstdir; - bool needhelp = false; - for (int i = 1; i < argc; ++i) - if (string(argv[i]) == "--help" || string(argv[i]) == "-h") - needhelp = true; - if (argc > 1 && !needhelp) + try { - firstdir = get_current_working_dir(); - run_dir = firstdir + "/tester_dir"; - do_remove_recursive(run_dir); - do_mkdir(run_dir); + string testfile; + string firstdir; + bool needhelp = false; + for (int i = 1; i < argc; ++i) + if (string(argv[i]) == "--help" || string(argv[i]) == "-h") + needhelp = true; + if (argc > 1 && !needhelp) + { + firstdir = get_current_working_dir(); + run_dir = firstdir + "/tester_dir"; + switch (get_path_status(run_dir)) + { + case path::directory: break; + case path::file: + P(F("cannot create directory '%s': it is a file") % run_dir); + return 1; + case path::nonexistent: + do_mkdir(run_dir); + } - testfile = argv[1]; - change_current_working_dir(dirname(testfile)); - source_dir = get_current_working_dir(); - testfile = source_dir + "/" + basename(testfile); + testfile = argv[1]; + change_current_working_dir(dirname(testfile)); + source_dir = get_current_working_dir(); + testfile = source_dir + "/" + basename(testfile); - change_current_working_dir(run_dir); - } - else - { - P(F("Usage: %s test-file [arguments]\n") % argv[0]); - P(F("\t-h print this message\n")); - P(F("\t-l print test names only; don't run them\n")); - P(F("\t-d don't clean the scratch directories\n")); - P(F("\tnum run a specific test\n")); - P(F("\tnum..num run tests in a range\n")); - P(F("\t if num is negative, count back from the end\n")); - P(F("\tregex run tests with matching names\n")); - return 1; - } - st = luaL_newstate(); - lua_atpanic (st, &panic_thrower); - luaL_openlibs(st); - add_functions(st); + change_current_working_dir(run_dir); + } + else + { + P(F("Usage: %s test-file [arguments]\n") % argv[0]); + P(F("\t-h print this message\n")); + P(F("\t-l print test names only; don't run them\n")); + P(F("\t-d don't clean the scratch directories\n")); + P(F("\tnum run a specific test\n")); + P(F("\tnum..num run tests in a range\n")); + P(F("\t if num is negative, count back from the end\n")); + P(F("\tregex run tests with matching names\n")); + return needhelp ? 0 : 1; + } + st = luaL_newstate(); + lua_atpanic (st, &panic_thrower); + luaL_openlibs(st); + add_functions(st); - lua_pushstring(st, "initial_dir"); - lua_pushstring(st, firstdir.c_str()); - lua_settable(st, LUA_GLOBALSINDEX); + lua_pushstring(st, firstdir.c_str()); + lua_setglobal(st, "initial_dir"); - try - { run_string(st, testlib_constant, "tester builtin functions"); run_file(st, testfile.c_str()); + + // arrange for isolation between different test suites running in the + // same build directory. + { + lua_getglobal(st, "testdir"); + const char *testdir = lua_tostring(st, 1); + I(testdir); + string testdir_base = basename(testdir); + run_dir = run_dir + "/" + testdir_base; + string logfile = run_dir + ".log"; + switch (get_path_status(run_dir)) + { + case path::directory: break; + case path::file: + P(F("cannot create directory '%s': it is a file") % run_dir); + return 1; + case path::nonexistent: + do_mkdir(run_dir); + } + + lua_pushstring(st, logfile.c_str()); + lua_setglobal(st, "logfile"); + } + Lua ll(st); ll.func("run_tests"); ll.push_table(); @@ -890,17 +918,27 @@ int main(int argc, char **argv) ll.call(1,1) .extract_int(retcode); } - catch (std::exception &e) + catch (informative_failure & e) { - P(F("Error: %s") % e.what()); + P(F("%s\n") % e.what()); + retcode = 1; } - } catch (informative_failure & e) { - P(F("Error: %s\n") % e.what()); - retcode = 1; - } catch (std::logic_error & e) { - P(F("Invariant failure: %s\n") % e.what()); - retcode = 3; - } + catch (std::logic_error & e) + { + P(F("Invariant failure: %s\n") % e.what()); + retcode = 3; + } + catch (std::exception & e) + { + P(F("Uncaught exception: %s") % e.what()); + retcode = 3; + } + catch (...) + { + P(F("Uncaught exception of unknown type")); + retcode = 3; + } + if (st) lua_close(st); return retcode; ============================================================ --- testlib.lua 8ec06c74bad74bfd0fb2000f39cc2c88d18c5467 +++ testlib.lua a1e48a128c3e3c787204885ac188217be9d3f82a @@ -1,18 +1,16 @@ -tests = {} -- list of all tests, not visible when running tests -test = {} -- table of per-test values - -- misc global values - -- where the main testsuite file is srcdir = get_source_dir() -- where the individual test dirs are -- most paths will be testdir.."/something" +-- normally reset by the main testsuite file testdir = srcdir -- was the -d switch given? debugging = false --- combined logfile -logfile = io.open("tester.log", "w") +-- combined logfile; tester.cc will reset this to a filename, which is +-- then opened in run_tests +logfile = nil -- logfiles of failed tests; append these to the main logfile failed_testlogs = {} @@ -22,7 +20,8 @@ files = {stdout = nil, stdin = nil, stde -- for this (at least on Windows). files = {stdout = nil, stdin = nil, stderr = nil} - +-- table of per-test values +test = {} -- misc per-test values test.root = nil test.name = nil @@ -39,7 +38,17 @@ test.log = nil -- logfile for this test test.log = nil -- logfile for this test +-- hook to be overridden by the main testsuite file, if necessary; +-- called after determining the set of tests to run +function prepare_to_run_tests() +end +-- hook to be overridden by the main testsuite file, if necessary; +-- called after opening the master logfile, but _before_ parsing +-- arguments or determining the set of tests to run. +function prepare_to_enumerate_tests() +end + function P(...) io.write(unpack(arg)) io.flush() @@ -766,6 +775,46 @@ function run_tests(args) local torun = {} local run_all = true local list_only = false + + -- NLS nuisances. + for _,name in pairs({ "LANG", + "LANGUAGE", + "LC_ADDRESS", + "LC_ALL", + "LC_COLLATE", + "LC_CTYPE", + "LC_IDENTIFICATION", + "LC_MEASUREMENT", + "LC_MESSAGES", + "LC_MONETARY", + "LC_NAME", + "LC_NUMERIC", + "LC_PAPER", + "LC_TELEPHONE", + "LC_TIME" }) do + set_env(name,"C") + end + + -- no test suite should touch the user's ssh agent + unset_env("SSH_AUTH_SOCK") + + -- tester.cc has set 'logfile' to an appropriate file name + logfile = io.open(logfile, "w") + + prepare_to_enumerate_tests() + + -- any directory in testdir with a __driver__.lua inside is a test case + local tests = {} + for _,candidate in ipairs(read_directory(testdir)) do + -- n.b. it is not necessary to throw out directories before doing + -- this check, because exists(nondirectory/__driver__.lua) will + -- never be true. + if exists(testdir .. "/" .. candidate .. "/__driver__.lua") then + table.insert(tests, candidate) + end + end + table.sort(tests) + for i,a in pairs(args) do local _1,_2,l,r = string.find(a, "^(-?%d+)%.%.(-?%d+)$") if _1 then @@ -803,10 +852,13 @@ function run_tests(args) end end end + if not list_only then logfile:write("Running on ", get_ostype(), "\n\n") P("Running tests...\n") end + prepare_to_run_tests() + local counts = {} counts.success = 0 counts.skip = 0 ============================================================ --- testsuite.lua 468554c427354f1b781a7146cfa78b242afa4ddd +++ testsuite.lua 858afba9d790d7ff83092c18d5442bcdc59547fc @@ -1,12 +1,5 @@ #!./tester --- We have a bunch of tests that depend on being able to create files or --- directories that we cannot read or write (mostly to test error handling --- behavior). -require_not_root() - -ostype = string.sub(get_ostype(), 1, string.find(get_ostype(), " ")-1) - -- maybe this should go in tester.lua instead? function getpathof(exe, ext) local function gotit(now) @@ -47,39 +40,6 @@ end return nil end -monotone_path = getpathof("mtn") -if monotone_path == nil then monotone_path = "mtn" end -set_env("mtn", monotone_path) - -writefile_q("in", nil) -prepare_redirect("in", "out", "err") -execute(monotone_path, "--full-version") -logfile:write(readfile_q("out")) -unlogged_remove("in") -unlogged_remove("out") -unlogged_remove("err") - --- NLS nuisances. -for _,name in pairs({ "LANG", - "LANGUAGE", - "LC_ADDRESS", - "LC_ALL", - "LC_COLLATE", - "LC_CTYPE", - "LC_IDENTIFICATION", - "LC_MEASUREMENT", - "LC_MESSAGES", - "LC_MONETARY", - "LC_NAME", - "LC_NUMERIC", - "LC_PAPER", - "LC_TELEPHONE", - "LC_TIME" }) do - set_env(name,"C") -end -unset_env("SSH_AUTH_SOCK") - - function safe_mtn(...) return {monotone_path, "--norc", "--root=" .. test.root, "--confdir="..test.root, unpack(arg)} @@ -364,15 +324,23 @@ testdir = srcdir.."/tests" ------------------------------------------------------------------------ testdir = srcdir.."/tests" --- any directory in testdir with a __driver__.lua inside is a test case --- perhaps this should be in tester.lua? +function prepare_to_run_tests () + -- We have a bunch of tests that depend on being able to create + -- files or directories that we cannot read or write (mostly to + -- test error handling behavior). + require_not_root() -for _,candidate in ipairs(read_directory(testdir)) do - -- n.b. it is not necessary to throw out directories before doing - -- this check, because exists(nondirectory/__driver__.lua) will - -- never be true. - if exists(testdir .. "/" .. candidate .. "/__driver__.lua") then - table.insert(tests, candidate) - end + ostype = string.sub(get_ostype(), 1, string.find(get_ostype(), " ")-1) + + monotone_path = getpathof("mtn") + if monotone_path == nil then monotone_path = "mtn" end + set_env("mtn", monotone_path) + + writefile_q("in", nil) + prepare_redirect("in", "out", "err") + execute(monotone_path, "--full-version") + logfile:write(readfile_q("out")) + unlogged_remove("in") + unlogged_remove("out") + unlogged_remove("err") end -table.sort(tests)