mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-15 17:25:32 +00:00
Merge branch 'fixup_unit_test_replays'
This commit is contained in:
commit
fdf750cbfd
1
.gitignore
vendored
1
.gitignore
vendored
@ -73,3 +73,4 @@ projectfiles/VC201*
|
||||
*Neuer Ordner*
|
||||
Thumbs.db
|
||||
error.log
|
||||
errors.log
|
||||
|
69
data/test/scenarios/break_replay_with_lua_random.cfg
Normal file
69
data/test/scenarios/break_replay_with_lua_random.cfg
Normal 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]
|
||||
)}
|
@ -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]
|
||||
)}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
#
|
||||
|
Loading…
x
Reference in New Issue
Block a user