Merge branch 'fixup_unit_test_replays'

This commit is contained in:
Chris Beck 2014-05-14 01:32:04 -04:00
commit fdf750cbfd
10 changed files with 222 additions and 19 deletions

1
.gitignore vendored
View File

@ -73,3 +73,4 @@ projectfiles/VC201*
*Neuer Ordner*
Thumbs.db
error.log
errors.log

View File

@ -0,0 +1,69 @@
# The purpose of this test is to make a scenario that plays but goes out of sync with the replay.
# This is done as a sanity check of the unit testing mechanism.
# We use the unsynced rng, lua.random, to achieve this.
# Basically we keep giving side 1 a random amount of gold and recruiting as
# many woses as possible, killing them immediately to make space. We do this
# for 30 turns. In the replay we will actually have a random amount of gold
# each time, so if we have bad luck one turn we won't have enough to afford
# that many woses.
# For each turn its about 50-50 not to go out of sync, so the chance not to
# go out of sync should be roughly less than one in a billion.
{GENERIC_UNIT_TEST "break_replay_with_lua_random" (
[event]
name = start
[allow_recruit]
side=1
type=Wose
[/allow_recruit]
[/event]
[event]
name = recruit
first_time_only = no
[kill]
x = $x1
y = $y1
animate=yes
[/kill]
[/event]
[event]
name = side 1 turn refresh
first_time_only=no
[lua]
code =<<
wesnoth.set_variable("rnd_num", math.random(200))
>>
[/lua]
[modify_side]
side = 1
gold = $rnd_num
[/modify_side]
[while]
{VARIABLE_CONDITIONAL rnd_num greater_than_equal_to 20}
[do]
[do_command]
[recruit]
type="Wose"
x,y=7,4
[from]
x,y=7,3
[/from]
[/recruit]
[/do_command]
{VARIABLE_OP rnd_num sub 20}
[/do]
[/while]
[end_turn]
[/end_turn]
[/event]
[event]
name = side 2 turn 30
{RETURN ([true][/true])}
[/event]
[event]
name = side 2 turn refresh
first_time_only=no
[end_turn]
[/end_turn]
[/event]
)}

View File

@ -0,0 +1,62 @@
{GENERIC_UNIT_TEST "fixed_lua_random_replay_with_sync_choice" (
[event]
name = start
[allow_recruit]
side=1
type=Wose
[/allow_recruit]
[/event]
[event]
name = recruit
first_time_only = no
[kill]
x = $x1
y = $y1
animate=yes
[/kill]
[/event]
[event]
name = side 1 turn refresh
first_time_only=no
[lua]
code =<<
local result = wesnoth.synchronize_choice(
function()
return { value = math.random(200) }
end)
wesnoth.set_variable("rnd_num", result.value)
>>
[/lua]
[modify_side]
side = 1
gold = $rnd_num
[/modify_side]
[while]
{VARIABLE_CONDITIONAL rnd_num greater_than_equal_to 20}
[do]
[do_command]
[recruit]
type="Wose"
x,y=7,4
[from]
x,y=7,3
[/from]
[/recruit]
[/do_command]
{VARIABLE_OP rnd_num sub 20}
[/do]
[/while]
[end_turn]
[/end_turn]
[/event]
[event]
name = side 2 turn 30
{RETURN ([true][/true])}
[/event]
[event]
name = side 2 turn refresh
first_time_only=no
[end_turn]
[/end_turn]
[/event]
)}

View File

@ -45,8 +45,14 @@ get_code_string()
4)
CodeString="FAIL (ERRORED REPLAY)"
;;
134)
CodeString="FAIL (ASSERTION FAILURE ? ? ?)"
;;
139)
CodeString="FAIL (SEGFAULT ? ? ?)"
;;
*)
CodeString="? ? ?"
CodeString="FAIL (? ? ?)"
;;
esac
}
@ -62,6 +68,8 @@ check_errs()
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
@ -220,6 +228,7 @@ fi
AllPassed=1
FirstTest=1
TotalPassed=0
for line in "${schedule[@]}"
do
@ -233,6 +242,7 @@ do
if [ $Verbose -ge 2 ]; then
echo "good"
fi
TotalPassed=$((TotalPassed+1))
else
AllPassed=0
fi
@ -241,6 +251,7 @@ do
if [ $Verbose -ge 2 ]; then
echo "good"
fi
TotalPassed=$((TotalPassed+1))
else
AllPassed=0
fi
@ -249,6 +260,7 @@ do
done
if [ $AllPassed -eq 0 ]; then
echo "$TotalPassed" "out of" $TESTS "tests were correct."
echo "Not all tests gave the correct result."
echo "Check errors.log for error reports."
exit 1

View File

@ -462,7 +462,7 @@ int game_controller::unit_test()
load_game_config_for_game(state_.classification());
try {
LEVEL_RESULT res = play_game(disp(),state_,resources::config_manager->game_config());
LEVEL_RESULT res = play_game(disp(),state_,resources::config_manager->game_config(), IO_NONE, false, false, false, true);
if (!(res == VICTORY || res == NONE)) {
return 1;
}
@ -482,6 +482,8 @@ int game_controller::unit_test()
savegame::replay_savegame save(state_, compression::NONE);
save.save_game_automatic(disp().video(), false, "unit_test_replay"); //false means don't check for overwrite
clear_loaded_game();
//game::load_game_exception::game = *cmdline_opts_.load
game::load_game_exception::game = "unit_test_replay";
// game::load_game_exception::game = "Unit_test_" + test_scenario_ + "_replay";
@ -495,13 +497,15 @@ int game_controller::unit_test()
}
try {
LEVEL_RESULT res = play_game(disp(), state_, resources::config_manager->game_config());
//LEVEL_RESULT res = play_game(disp(), state_, resources::config_manager->game_config(), IO_NONE, false,false,false,true);
LEVEL_RESULT res = ::play_replay(disp(), state_, resources::config_manager->game_config(), video_, true);
if (!(res == VICTORY || res == NONE)) {
std::cerr << "Observed failure on replay" << std::endl;
return 4;
}
/*::play_replay(disp(),state_,resources::config_manager->game_config(),
video_);*/
clear_loaded_game();
} catch (game::load_game_exception &) {
std::cerr << "Load_game_exception encountered during play_replay!" << std::endl;
return 3; //failed to load replay

View File

@ -206,8 +206,8 @@ static void generate_map(config const*& scenario)
scenario = &new_scenario;
}
void play_replay(display& disp, game_state& gamestate, const config& game_config,
CVideo& video)
LEVEL_RESULT play_replay(display& disp, game_state& gamestate, const config& game_config,
CVideo& video, bool is_unit_test)
{
std::string type = gamestate.classification().campaign_type;
if(type.empty())
@ -236,21 +236,44 @@ void play_replay(display& disp, game_state& gamestate, const config& game_config
//if (gamestate.abbrev.empty())
// gamestate.abbrev = (*scenario)["abbrev"];
play_replay_level(game_config, &starting_pos, video, gamestate);
LEVEL_RESULT res = play_replay_level(game_config, &starting_pos, video, gamestate, is_unit_test);
gamestate.snapshot = config();
recorder.clear();
gamestate.replay_data.clear();
return res;
} catch(game::load_game_failed& e) {
if (is_unit_test) {
std::cerr << std::string(_("The game could not be loaded: ")) + " (game::load_game_failed) " + e.message << std::endl;
return DEFEAT;
} else {
gui2::show_error_message(disp.video(), _("The game could not be loaded: ") + e.message);
}
} catch(game::game_error& e) {
gui2::show_error_message(disp.video(), _("Error while playing the game: ") + e.message);
if (is_unit_test) {
std::cerr << std::string(_("Error while playing the game: ")) + " (game::game_error) " + e.message << std::endl;
return DEFEAT;
} else {
gui2::show_error_message(disp.video(), std::string(_("Error while playing the game: ")) + e.message);
}
} catch(incorrect_map_format_error& e) {
if (is_unit_test) {
std::cerr << std::string(_("The game map could not be loaded: ")) + " (incorrect_map_format_error) " + e.message << std::endl;
return DEFEAT;
} else {
gui2::show_error_message(disp.video(), std::string(_("The game map could not be loaded: ")) + e.message);
}
} catch(twml_exception& e) {
if (is_unit_test) {
std::cerr << std::string("WML Exception: ") + e.user_message << std::endl;
std::cerr << std::string("Dev Message: ") + e.dev_message << std::endl;
return DEFEAT;
} else {
e.show(disp);
}
}
return NONE;
}
static LEVEL_RESULT playsingle_scenario(const config& game_config,
@ -377,7 +400,7 @@ static LEVEL_RESULT playmp_scenario(const config& game_config,
LEVEL_RESULT play_game(game_display& disp, game_state& gamestate,
const config& game_config, io_type_t io_type, bool skip_replay,
bool network_game, bool blindfold_replay)
bool network_game, bool blindfold_replay, bool is_unit_test)
{
std::string type = gamestate.classification().campaign_type;
if(type.empty())
@ -512,6 +535,10 @@ LEVEL_RESULT play_game(game_display& disp, game_state& gamestate,
return QUIT;
}
if (is_unit_test) {
return res;
}
// Save-management options fire on game end.
// This means: (a) we have a victory, or
// or (b) we're multiplayer live, in which

View File

@ -36,10 +36,12 @@ LEVEL_RESULT play_game(game_display& disp, game_state& state,
io_type_t io_type=IO_NONE,
bool skip_replay = false,
bool network_game = false,
bool blindfold_replay = false);
bool blindfold_replay = false,
bool is_unit_test = false);
void play_replay(display& disp, game_state& state,
const config& game_config, CVideo& video);
LEVEL_RESULT play_replay(display& disp, game_state& state,
const config& game_config, CVideo& video,
bool is_unit_test = false);
#endif // PLAYCAMPAIGN_H_INCLUDED

View File

@ -40,7 +40,7 @@ static lg::log_domain log_replay("replay");
#define ERR_REPLAY LOG_STREAM(err, log_replay)
LEVEL_RESULT play_replay_level(const config& game_config,
const config* level, CVideo& video, game_state& state_of_game)
const config* level, CVideo& video, game_state& state_of_game, bool is_unit_test)
{
try{
const int ticks = SDL_GetTicks();
@ -59,6 +59,11 @@ LEVEL_RESULT play_replay_level(const config& game_config,
//replay event-loop
for (;;){
replaycontroller.play_slice();
if (is_unit_test) {
if (replaycontroller.manage_noninteractively()) {
return VICTORY;
}
}
}
}
catch(end_level_exception&){
@ -352,14 +357,20 @@ void replay_controller::replay_next_side(){
void replay_controller::process_oos(const std::string& msg) const
{
if (game_config::ignore_replay_errors) return;
if (game_config::ignore_replay_errors) {
return;
}
std::stringstream message;
message << _("The replay is corrupt/out of sync. It might not make much sense to continue. Do you want to save the game?");
message << "\n\n" << _("Error details:") << "\n\n" << msg;
if (non_interactive()) {
throw game::game_error(message.str()); //throw end_level_exception(DEFEAT);
} else {
savegame::oos_savegame save(to_config());
save.save_game_interactive(resources::screen->video(), message.str(), gui::YES_NO); // can throw end_level_exception
}
}
void replay_controller::replay_show_everything(){
@ -567,3 +578,14 @@ bool replay_controller::can_execute_command(const hotkey::hotkey_command& cmd, i
return result;
}
}
bool replay_controller::manage_noninteractively() {
if (recorder.at_end()) {
return true;
} else {
if (!is_playing_) {
play_replay();
}
return false;
}
}

View File

@ -54,6 +54,8 @@ public:
std::vector<team> teams_start_;
bool manage_noninteractively();
protected:
virtual void init_gui();
@ -98,6 +100,6 @@ private:
LEVEL_RESULT play_replay_level(const config& terrain_config,
const config* level, CVideo& video,
game_state& state_of_game);
game_state& state_of_game, bool is_unit_test = false);
#endif

View File

@ -7,6 +7,8 @@
1 test_assert_fail
1 test_assert_fail_two
2 empty_test
4 break_replay_with_lua_random
0 fixed_lua_random_replay_with_sync_choice
#
# WML API tests
#