remove built-in wesnoth timeout

This was buggy and based on deprecated SDL features that will not
continue to be available. aquileia wrote us a very nice windows
port of the run_wml_tests bash script, so for windows mac and
linux we should now be able to run the unit tests as desired.

Maybe someday built-in timeouts can be supported using boost
process library, if that ever materializes.
This commit is contained in:
Chris Beck 2014-05-29 14:17:47 -04:00
parent bab0915c94
commit c8699e2f05
4 changed files with 33 additions and 114 deletions

View File

@ -10,7 +10,7 @@ script:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- ./test_wrapper.sh
- ./run_wml_tests -u -t 15
- ./run_wml_tests -t 15
after_failure:
- ./travis_after_failure.sh
notifications:

View File

@ -11,8 +11,6 @@ usage()
echo -e "\t-h\tShows this help."
echo -e "\t-v\tVerbose mode."
echo -e "\t-w\tVery verbose mode. (Debug script.)"
echo -e "\t-u\tUse unix timeout instead of wesnoth --timeout argument."
echo -e "\t \tUnix timeout will send a TERM signal, followed by KILL."
echo -e "\t-a arg\tAdditional arguments to go to wesnoth."
echo -e "\t-t arg\tNew timer value to use, instead of 10s as default."
echo -e "\t-s\tDisable strict mode. By default, we run wesnoth with option"
@ -53,6 +51,12 @@ get_code_string()
4)
CodeString="FAIL (ERRORED REPLAY)"
;;
124)
CodeString="FAIL (TIMEOUT, by TERM signal)"
;;
137)
CodeString="FAIL (TIMEOUT, by KILL signal)"
;;
134)
CodeString="FAIL (ASSERTION FAILURE ? ? ?)"
;;
@ -70,24 +74,14 @@ check_errs()
# Argument 1 is the name of the test.
# Argument 2 is the wesnoth error code for the test.
# Argument 3 is the expected error code.
if [ "${2}" -eq 134 -a "${3}" -eq 2 -a "$UnixTimeout" -eq 0 ]; then
if [ "$Verbose" -ge 2 ]; then
echo "Caught \'terminate called without an active exception\' return code 134"
echo "This means wesnoth tried to kill the thread but SDL threw an error..."
echo "(This happens occasionally when running the empty_test with a timeout.)"
echo "Since we expected timeout, the test passes."
echo ""
echo "*However*, review the logs, because it may also mean an assertion failure..."
fi
return 0
elif [ "${2}" -eq 124 -a "${3}" -eq 2 -a "$UnixTimeout" -eq 1 ]; then
if [ "${2}" -eq 124 -a "${3}" -eq 2 ]; then
if [ "$Verbose" -ge 2 ]; then
echo "Caught return code 124 from timeout"
echo "This signal means that the unix timeout utility killed wesnoth with TERM."
echo "Since we expected timeout, the test passes."
fi
return 0
elif [ "${2}" -eq 137 -a "${3}" -eq 2 -a "$UnixTimeout" -eq 1 ]; then
elif [ "${2}" -eq 137 -a "${3}" -eq 2 ]; then
if [ "$Verbose" -ge 2 ]; then
echo "Caught return code 137 from timeout"
echo "This signal means that the unix timeout utility killed wesnoth with KILL."
@ -130,35 +124,35 @@ run_test()
{
# Argument 1 is the expected error code
# Argument 2 is the name of the test scenario
preopts=""
binary="$BinPath"
opts="-u $2 "
timer=$basetimer
if [ "$DebugMode" -eq 1 ]; then
binary+="wesnoth-debug "
else
binary+="wesnoth "
fi
timer=$basetimer
# Use validcache on tests that aren't the first test.
if [ "$FirstTest" -eq 1 ]; then
((timer *= 2))
else
opts+="--validcache "
fi
# Add a timeout
if [ "$UnixTimeout" -eq 1 ]; then
timer1=$((timer+1))
preopts+="timeout --kill-after=$timer1 $timer "
else
timerms=$((timer*1000))
opts+="--timeout $timerms "
fi
# Add a timeout using unix timeout utility
timer1=$((timer+1))
preopts+="timeout --kill-after=$timer1 $timer "
# If running strict, then set strict level to "warning"
if [ "$StrictMode" -eq 1 ]; then
opts+="--log-strict=warning "
fi
# Assemble command
command="$preopts"
command+="$binary"
@ -241,6 +235,9 @@ if [ "$Verbose" -ge 2 ]; then
if [ "${#extra_opts}" -ge 0 ]; then
echo "Found additional arguments to wesnoth: " "$extra_opts"
fi
if [ "$UnixTimeout" -eq 1 ]; then
echo "Wesnoth built-in timeout was disabled. This script was updated, and -u is now unnecessary and has no effect."
fi
fi
echo "Getting tests from" "$LoadFile" "..."

View File

@ -196,7 +196,6 @@ commandline_options::commandline_options ( int argc, char** argv ) :
("log-info", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'info'. Similar to --log-error.")
("log-debug", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'debug'. Similar to --log-error.")
("log-precise", "shows the timestamps in the logfile with more precision")
("log-strict", po::value<std::string>(), "sets the strict level of the logger. messages to log domains of this level or more severe generate an in-game exception.")
;
po::options_description multiplayer_opts("Multiplayer options");
@ -222,7 +221,8 @@ commandline_options::commandline_options ( int argc, char** argv ) :
("test,t", po::value<std::string>()->implicit_value(std::string()), "runs the game in a small test scenario. If specified, scenario <arg> will be used instead.")
("unit,u", po::value<std::string>()->implicit_value(std::string()), "runs a unit test scenario. Works like test, except that the exit code of the program reflects the victory / defeat conditions of the scenario.\n\t0 - PASS\n\t1 - FAIL\n\t2 - FAIL (TIMEOUT)\n\t3 - FAIL (INVALID REPLAY)\n\t4 - FAIL (ERRORED REPLAY)")
("showgui", "don't run headlessly (for debugging a failing test)")
("timeout", po::value<unsigned int>(), "sets a timeout (milliseconds) for the unit test. If unused there is no timeout or threading.")
("timeout", po::value<unsigned int>(), "sets a timeout (milliseconds) for the unit test. (DEPRECATED)")
("log-strict", po::value<std::string>(), "sets the strict level of the logger. any messages sent to log domains of this level or more severe will cause the unit test to fail regardless of the victory result.")
("noreplaycheck", "don't try to validate replay of unit test")
;

View File

@ -420,38 +420,6 @@ static void init_locale() {
textdomain (PACKAGE);
}
/**
* SDL Semaphore which the main thread waits on, while the worker does it's job.
* We mainly only need this so we can use the SDL_SemWaitTimeout function to do the timer stuff for us.
*/
static SDL_sem * worker_sem;
/**
* Structure used to pass data to the worker thread. The int* is used to pass the worker result back out.
* This is not, strictly speaking, good practice with threads, but it is fine for a single thread with
* a timeout, that only sets the variable once.
*
* If for some reason you want to run many worker threads at once then don't use this code.
*/
typedef std::pair<boost::shared_ptr<game_controller>, int*> thread_data;
/**
* Function used by worker thread to perform unit test with timeout.
*/
static int run_unit_test (void * data){
thread_data * mydata = static_cast<thread_data *>(data);
if (SDL_SemWait(worker_sem) == -1) {
std::cerr << "Worker failed to lock worker semaphore!" << std::endl;
}
int ret_val = mydata->first->unit_test();
*mydata->second = ret_val;
if (SDL_SemPost(worker_sem) == -1) {
std::cerr << "Worker failed to unlock worker semaphore after working!" << std::endl;
}
return ret_val;
}
/**
* Setups the game environment and enters
* the titlescreen or game loops.
@ -568,64 +536,18 @@ static int do_gameloop(int argc, char** argv)
loadscreen_manager.reset();
if(cmdline_opts.unit_test) {
#if SDL_VERSION_ATLEAST(2,0,0) && !SDL_VERSION_ATLEAST(2,0,2)
if(cmdline_opts.timeout) {
std::cerr << "SDL Version number: " << SDL_COMPILEDVERSION << std::endl;
std::cerr << "Your SDL version is between 2.0.0 and 2.0.2..." << std::endl
<< " I don't know how to handle timedout threads. Disabling timeout." << std::endl;
*cmdline_opts.timeout = 0;
}
#endif
if(cmdline_opts.timeout && *cmdline_opts.timeout > 0) {
int worker_result = 2; //Default timeout return value if worker fails to return
worker_sem = SDL_CreateSemaphore(1);
if (worker_sem == NULL) {
std::cerr << "Failed to create a semaphore for timeout worker thread!" << std::endl;
std::cerr << "FAIL TEST (TIMEOUT): " << *cmdline_opts.unit_test << std::endl;
return 2;
}
thread_data data(game, &worker_result);
#if SDL_VERSION_ATLEAST(2,0,0)
SDL_Thread *worker = SDL_CreateThread(&run_unit_test, "worker", &data);
#else
SDL_Thread *worker = SDL_CreateThread(&run_unit_test, &data);
#endif
std::cerr << "Setting timer for " << *cmdline_opts.timeout << " ms." << std::endl;
int wait_result = SDL_SemWaitTimeout(worker_sem, *cmdline_opts.timeout);
if (wait_result == 0) {
SDL_SemPost(worker_sem);
SDL_DestroySemaphore(worker_sem);
std::cerr << ((worker_result == 0) ? "PASS TEST " : "FAIL TEST ")
<< ((worker_result == 3) ? "(INVALID REPLAY)" : "")
<< ((worker_result == 4) ? "(ERRORED REPLAY)" : "")
<< ": "<<*cmdline_opts.unit_test << std::endl;
return worker_result;
} else {
#if SDL_VERSION_ATLEAST(2,0,2)
SDL_DetachThread(worker);
#else
#if !SDL_VERSION_ATLEAST(2,0,0)
SDL_KillThread(worker);
#endif
#endif
if (wait_result == -1) {
std::cerr << "Error in SemWaitTimeout!" << std::endl;
} else {
std::cerr << "Test timed out!" << std::endl;
}
std::cerr << ("FAIL TEST (TIMEOUT): ") << *cmdline_opts.unit_test << std::endl;
return 2;
}
} else {
int worker_result = game->unit_test();
std::cerr << ((worker_result == 0) ? "PASS TEST " : "FAIL TEST ")
<< ((worker_result == 3) ? "(INVALID REPLAY)" : "")
<< ((worker_result == 4) ? "(ERRORED REPLAY)" : "")
<< ": "<<*cmdline_opts.unit_test << std::endl;
return worker_result;
std::cerr << "The wesnoth built-in timeout feature has been removed.\n" << std::endl;
std::cerr << "Please use a platform-specific script which will kill the overtime process instead.\n" << std::endl;
std::cerr << "For examples in bash, or in windows cmd, see the forums, or the wesnoth repository." << std::endl;
std::cerr << "The bash script is called `run_wml_tests`, the windows script is part of the VC project.\n" << std::endl;
}
int worker_result = game->unit_test();
std::cerr << ((worker_result == 0) ? "PASS TEST " : "FAIL TEST ")
<< ((worker_result == 3) ? "(INVALID REPLAY)" : "")
<< ((worker_result == 4) ? "(ERRORED REPLAY)" : "")
<< ": "<<*cmdline_opts.unit_test << std::endl;
return worker_result;
}
if(game->play_test() == false) {