From b219ee483dadc4f9f460b0ef445bf3369271675d Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 9 Jun 2019 14:20:58 +0800 Subject: testrunner - Timeout support, don't make "success" file until test completes --- tools/testrunner/main.cpp | 56 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/tools/testrunner/main.cpp b/tools/testrunner/main.cpp index 3823215a..0b3a5c03 100644 --- a/tools/testrunner/main.cpp +++ b/tools/testrunner/main.cpp @@ -94,7 +94,7 @@ struct Timestamp } }; -bool run_executable(const ::helpers::path& file, const ::std::vector& args, const ::helpers::path& outfile); +bool run_executable(const ::helpers::path& file, const ::std::vector& args, const ::helpers::path& outfile, unsigned timeout_seconds); bool run_compiler(const ::helpers::path& source_file, const ::helpers::path& output, const ::std::vector<::std::string>& extra_flags, ::helpers::path libdir={}, bool is_dep=false) { @@ -134,7 +134,16 @@ bool run_compiler(const ::helpers::path& source_file, const ::helpers::path& out for(const auto& s : extra_flags) args.push_back(s.c_str()); - return run_executable(MRUSTC_PATH, args, logfile); + return run_executable(MRUSTC_PATH, args, logfile, 0); +} + +static bool gTimeout = false; +static bool gInterrupted = false; +void sigalrm_handler(int) { + gTimeout = true; +} +void sigint_handler(int) { + gInterrupted = true; } int main(int argc, const char* argv[]) @@ -145,6 +154,13 @@ int main(int argc, const char* argv[]) return v; } + { + struct sigaction sa = {0}; + sa.sa_handler = sigalrm_handler; + sigaction(SIGALRM, &sa, NULL); + signal(SIGINT, sigint_handler); + } + ::std::vector<::std::string> skip_list; // > Filter out tests listed in an exceptions file (newline separated, supports comments) if( opts.exceptions_file ) @@ -297,6 +313,10 @@ int main(int argc, const char* argv[]) unsigned n_ok = 0; for(const auto& test : tests) { + if( gInterrupted ) { + DEBUG(">> Interrupted"); + return 1; + } if( !opts.test_list.empty() && ::std::find(opts.test_list.begin(), opts.test_list.end(), test.m_name) == opts.test_list.end() ) { if( opts.debug_level > 0 ) @@ -358,7 +378,7 @@ int main(int argc, const char* argv[]) auto compile_logfile = outdir / test.m_name + "-build.log"; if( !run_compiler(test.m_path, outfile, test.m_extra_flags, depdir) ) { - DEBUG("COMPILE FAIL " << test.m_name); + DEBUG("COMPILE FAIL " << test.m_name << ", log in " << compile_logfile); n_cfail ++; if( opts.fail_fast ) return 1; @@ -371,14 +391,15 @@ int main(int argc, const char* argv[]) auto run_out_file = outdir / test.m_name + ".out"; if( Timestamp::for_file(run_out_file) < test_output_ts ) { - if( !run_executable(outfile, { outfile.str().c_str() }, run_out_file) ) + auto run_out_file_tmp = run_out_file + ".tmp"; + if( !run_executable(outfile, { outfile.str().c_str() }, run_out_file_tmp, 10) ) { DEBUG("RUN FAIL " << test.m_name); // Move the failing output file auto fail_file = run_out_file + "_failed"; remove(fail_file.str().c_str()); - rename(run_out_file.str().c_str(), fail_file.str().c_str()); + rename(run_out_file_tmp.str().c_str(), fail_file.str().c_str()); DEBUG("- Output in " << fail_file); n_fail ++; @@ -387,6 +408,11 @@ int main(int argc, const char* argv[]) else continue; } + else + { + remove(run_out_file.str().c_str()); + rename(run_out_file_tmp.str().c_str(), run_out_file.str().c_str()); + } } else { @@ -501,7 +527,7 @@ void Options::usage_full() const } /// -bool run_executable(const ::helpers::path& exe_name, const ::std::vector& args, const ::helpers::path& outfile) +bool run_executable(const ::helpers::path& exe_name, const ::std::vector& args, const ::helpers::path& outfile, unsigned timeout_seconds) { #ifdef _WIN32 ::std::stringstream cmdline; @@ -530,6 +556,7 @@ bool run_executable(const ::helpers::path& exe_name, const ::std::vector