Made endlevel test to use fake screen object

moved fake_event_source class to test tests/utils/
This commit is contained in:
Pauli Nieminen 2008-07-04 13:36:45 +00:00
parent c4046c3466
commit 21b0f0bc47
8 changed files with 324 additions and 140 deletions

View file

@ -318,13 +318,19 @@ exploder_sources = Split("""
env.WesnothProgram("exploder", exploder_sources + [libcutter, libwesnoth_core, libwesnoth_sdl, libwesnothd, libwesnoth], have_client_prereqs,
LIBS = env["LIBS"] + ["png"])
test_utils_sources = Split("""
tests/utils/fake_event_source.cpp
""")
libtest_utils = env.Library("test_utils", test_utils_sources)
test_sources = Split("""
tests/main.cpp
tests/test_util.cpp
tests/test_network_worker.cpp
tests/test_endlevel.cpp
""")
test = test_env.WesnothProgram("test", test_sources + [libwesnoth_extras, libwesnoth_core, libwesnoth_sdl, libwesnoth], have_test_prereqs)
test = test_env.WesnothProgram("test", test_sources + [libwesnoth_extras, libwesnoth_core, libwesnoth_sdl, libwesnoth,libtest_utils], have_test_prereqs)
#Export("test")
if env["svnrev"] != "" and env["svnrev"] != "exported":

View file

@ -165,6 +165,7 @@ handler::handler(const bool auto_join) : unicode_(SDL_EnableUNICODE(1)), has_joi
{
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL);
if(auto_join) {
assert(!event_contexts.empty());
event_contexts.back().add_handler(this);
has_joined_ = true;
}

View file

@ -15,6 +15,7 @@
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_monitor.hpp>
#include <boost/test/detail/unit_test_parameters.hpp>
#include "SDL.h"
#include "game_errors.hpp"
#include "network.hpp"
@ -42,6 +43,7 @@ void exception_translator_game(const game::error& e)
struct wesnoth_global_fixture {
wesnoth_global_fixture()
{
SDL_Init(SDL_INIT_TIMER);
if (boost::unit_test::runtime_config::log_level() < boost::unit_test::log_messages)
boost::unit_test::unit_test_log.set_threshold_level( boost::unit_test::log_messages );
BOOST_MESSAGE("Initializing test!");

View file

@ -14,14 +14,13 @@
#include <boost/test/auto_unit_test.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <queue>
#include "SDL.h"
#include "key.hpp"
#include "events.hpp"
//#include "dialogs.hpp"
#include "unit_types.hpp"
#include "dialogs.hpp"
#include "gamestatus.hpp"
//
#include "tests/utils/fake_event_source.hpp"
// Linker workarounds start here
@ -43,142 +42,28 @@ WML_HANDLER_FUNCTION(test_sources, , , )
// To load libwesnoth_sdl
SDL_Color color = int_to_color(255);
std::cerr << "Fooled you\n";
{
config cfg;
scoped_istream stream = preprocess_file("data/hardwired/language.cfg");
read(cfg, *stream);
}
}
#endif
// Linker workarounds end here
/**
* fake_sdl_event_source is used to generate new events in
* events::pump()
**/
namespace test {
// bool event_fired = false;
template<class T>
struct test_less_ptr {
bool operator()(const T& a, const T& b) const
{
return (*a) < (*b);
}
};
class fake_sdl_event_source
: public events::pump_monitor,
public boost::noncopyable
{
public:
/**
* Base class for all event nodes to be used to fire fake input events
**/
class event_node :
public boost::noncopyable
{
size_t time_;
bool fired_;
protected:
SDL_Event event_;
public:
event_node(const size_t time, const SDL_Event& event) : time_(time), fired_(false), event_(event)
{}
virtual ~event_node()
{ }
virtual void fire_event()
{
const int number_of_events = 1;
const Uint32 mask = 0;
SDL_PeepEvents(&event_, number_of_events, SDL_ADDEVENT, mask);
fired_ = true;
}
/**
* @return true if this should stop firing events
**/
bool test_if_should_fire(const size_t time_now) const
{
return time_ <= time_now;
}
bool is_fired() const
{
return fired_;
}
/**
* We want the smallestat the top
**/
bool operator<(const event_node& o) const
{ return time_ > o.time_; }
};
class event_node_keyboard : public event_node {
public:
event_node_keyboard(size_t time, SDL_Event& event) : event_node(time,event)
{}
void fire_event()
{
event_node::fire_event();
static int num_keys = 300;
Uint8* key_list = SDL_GetKeyState( &num_keys );
if (event_.type == SDL_KEYDOWN)
key_list[SDLK_ESCAPE] = 5;
else
key_list[SDLK_ESCAPE] = 0;
}
};
typedef boost::shared_ptr<event_node> event_node_ptr;
private:
typedef std::priority_queue<event_node_ptr,std::vector<event_node_ptr>,test_less_ptr<event_node_ptr> > event_queue;
event_queue queue_;
public:
void add_event(const size_t time, const SDL_Event& event)
{
event_node_ptr new_node(new event_node(time,event));
queue_.push(new_node);
}
void add_event(event_node_ptr new_node)
{
queue_.push(new_node);
}
void process(events::pump_info& /*info*/);
struct endlevel_fixture {
test_utils::fake_event_source source;
SDL_Event event;
};
void fake_sdl_event_source::process(events::pump_info& /*info*/)
{
if (queue_.empty())
return;
size_t now = SDL_GetTicks();
if (queue_.top()->test_if_should_fire(now))
{
queue_.top()->fire_event();
queue_.pop();
}
}
BOOST_AUTO_TEST_SUITE( endlevel )
BOOST_FIXTURE_TEST_SUITE( endlevel , endlevel_fixture)
BOOST_AUTO_TEST_CASE( test_fake_input )
{
#ifdef LD_WA
{
config cfg;
scoped_istream stream = preprocess_file("data/hardwired/language.cfg");
read(cfg, *stream);
}
#endif
fake_sdl_event_source source;
SDL_Event event;
BOOST_MESSAGE("Starting endlevel test!");
event.type = SDL_KEYDOWN;
event.key.state = SDL_PRESSED;
@ -186,23 +71,20 @@ namespace test {
event.key.keysym.scancode = 65;
event.key.keysym.mod = KMOD_NONE;
event.key.keysym.unicode = 0;
const size_t now = SDL_GetTicks();
fake_sdl_event_source::event_node_ptr new_keypress(new fake_sdl_event_source::event_node_keyboard(now + 10, event));
test_utils::event_node_ptr new_keypress(new test_utils::event_node_keyboard(3, event));
event.type = SDL_KEYUP;
event.key.state = SDL_RELEASED;
fake_sdl_event_source::event_node_ptr new_keyrelease(new fake_sdl_event_source::event_node_keyboard(now + 20, event));
test_utils::event_node_ptr new_keyrelease(new test_utils::event_node_keyboard(5, event));
source.add_event(new_keypress);
source.add_event(new_keyrelease);
BOOST_MESSAGE("Starting endlevel test!");
CKey key;
// dialogs::get_save_name();
while(true)
{
events::pump();
BOOST_CHECK_EQUAL(key[SDLK_ESCAPE], new_keypress->is_fired());
if (key[SDLK_ESCAPE])
break;
@ -216,5 +98,43 @@ namespace test {
}
}
BOOST_AUTO_TEST_CASE( test_dialog_get_save_name_enter_pressed )
{
// fill in events to be used in test
test_utils::event_node_ptr press_return_before = source.press_key(0, SDLK_RETURN);
test_utils::event_node_ptr release_return_before = source.release_key(3, SDLK_RETURN);
test_utils::event_node_ptr press_return_after = source.press_key(6, SDLK_RETURN);
test_utils::event_node_ptr release_return_after = source.release_key(9, SDLK_RETURN);
CVideo video_;
video_.make_test_fake();
unit_map dummy_umap;
config dummy_cfg;
gamemap dummy_map(dummy_cfg, "");
gamestatus dummy_status(dummy_cfg, 0);
std::vector<team> dummy_teams;
const events::event_context main_event_context_;
game_display disp(dummy_umap, video_, dummy_map, dummy_status,
dummy_teams, dummy_cfg, dummy_cfg, dummy_cfg);
std::string fname("press_enter");
// Start test (set ticks start time)
source.start();
// Activated enter press
events::pump();
BOOST_CHECK_MESSAGE(press_return_before->is_fired(), "Enter wasn't activated");
BOOST_CHECK_MESSAGE(!release_return_before->is_fired(), "Enter was released before test");
BOOST_CHECK_EQUAL(dialogs::get_save_name(disp, "Save game?", "file", &fname,gui::OK_CANCEL, "Save game", false, true), 0);
BOOST_CHECK_MESSAGE(release_return_before->is_fired(), "get_save_name returned before releasing first enter.");
BOOST_CHECK_MESSAGE(press_return_after->is_fired(), "get_save_name returned before 2nd enter event was sent");
BOOST_CHECK_MESSAGE(!release_return_after->is_fired(), "get_save_name returned after 2nd release event was sent");
}
BOOST_AUTO_TEST_SUITE_END()
}

View file

@ -0,0 +1,144 @@
/* $Id$ */
/*
Copyright (C) 2008 by Pauli Nieminen <paniemin@cc.hut.fi>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
or at your option any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include <iostream>
#include "tests/utils/fake_event_source.hpp"
namespace test_utils {
/**
* Base class for all event nodes to be used to fire fake input events
**/
event_node::event_node(const size_t time, const SDL_Event& event) : time_(time), fired_(false), event_(event)
{}
event_node::~event_node()
{ }
void event_node::fire_event()
{
const int number_of_events = 1;
const Uint32 mask = 0;
SDL_PeepEvents(&event_, number_of_events, SDL_ADDEVENT, mask);
fired_ = true;
}
/**
* @return true if this should stop firing events
**/
bool event_node::test_if_should_fire(const size_t start_time, const size_t time_now) const
{
return time_now - start_time >= time_;
}
bool event_node::is_fired() const
{
return fired_;
}
/**
* We want the smallestat the top
**/
bool event_node::operator<(const event_node& o) const
{ return time_ > o.time_; }
event_node_keyboard::event_node_keyboard(size_t time, SDL_Event& event) : event_node(time,event)
{}
void event_node_keyboard::fire_event()
{
event_node::fire_event();
static int num_keys = 300;
Uint8* key_list = SDL_GetKeyState( &num_keys );
if (event_.type == SDL_KEYDOWN)
key_list[SDLK_ESCAPE] = 5;
else
key_list[SDLK_ESCAPE] = 0;
}
fake_event_source::fake_event_source() : start_time_(SDL_GetTicks())
{
}
fake_event_source::~fake_event_source()
{
// send all still queued events
// so keyboard/mouse state is restored
while(!queue_.empty())
{
queue_.top()->fire_event();
queue_.pop();
}
events::pump();
}
void fake_event_source::add_event(const size_t time, const SDL_Event& event)
{
event_node_ptr new_node(new event_node(time,event));
queue_.push(new_node);
}
void fake_event_source::add_event(event_node_ptr new_node)
{
queue_.push(new_node);
}
void fake_event_source::start()
{
start_time_ = SDL_GetTicks();
}
SDL_Event fake_event_source::make_key_event(Uint8 type, const SDLKey key, const SDLMod mod)
{
SDL_Event event;
event.type = type;
if (type == SDL_KEYDOWN)
event.key.state = SDL_PRESSED;
else
event.key.state = SDL_RELEASED;
event.key.keysym.sym = key;
event.key.keysym.scancode = 65; // Always report 65 as scancode
event.key.keysym.mod = mod;
event.key.keysym.unicode = 0; // Unicode disabled
return event;
}
event_node_ptr fake_event_source::press_key(const size_t time, const SDLKey key, const SDLMod mod)
{
SDL_Event event = make_key_event(SDL_KEYDOWN, key, mod);
event_node_ptr new_key(new event_node_keyboard(time, event));
add_event(new_key);
return new_key;
}
event_node_ptr fake_event_source::release_key(const size_t time, const SDLKey key, const SDLMod mod)
{
SDL_Event event = make_key_event(SDL_KEYUP, key, mod);
event_node_ptr new_key(new event_node_keyboard(time, event));
add_event(new_key);
return new_key;
}
void fake_event_source::process(events::pump_info& /*info*/)
{
if (queue_.empty())
return;
size_t now = SDL_GetTicks();
while (!queue_.empty()
&& queue_.top()->test_if_should_fire(start_time_, now))
{
queue_.top()->fire_event();
queue_.pop();
}
}
}

View file

@ -0,0 +1,101 @@
/* $Id$ */
/*
Copyright (C) 2008 by Pauli Nieminen <paniemin@cc.hut.fi>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
or at your option any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef TESTS_UTILS_FAKE_EVENT_SOURCE_HPP_INCLUDED
#define TESTS_UTILS_FAKE_EVENT_SOURCE_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <queue>
#include "SDL.h"
#include "events.hpp"
namespace test_utils {
template<class T>
struct less_ptr {
bool operator()(const T& a, const T& b) const
{
return (*a) < (*b);
}
};
/**
* Base class for all event nodes to be used to fire fake input events
**/
class event_node :
public boost::noncopyable
{
size_t time_;
bool fired_;
protected:
SDL_Event event_;
public:
event_node(const size_t time, const SDL_Event& event);
virtual ~event_node();
virtual void fire_event();
/**
* @return true if this should stop firing events
**/
bool test_if_should_fire(const size_t start_time, const size_t time_now) const;
bool is_fired() const;
/**
* We want the smallestat the top
**/
bool operator<(const event_node& o) const;
};
class event_node_keyboard : public event_node {
public:
event_node_keyboard(size_t time, SDL_Event& event);
void fire_event();
};
typedef boost::shared_ptr<event_node> event_node_ptr;
/**
* fake_event_source is used to generate new events in
* events::pump()
**/
class fake_event_source
: public events::pump_monitor,
public boost::noncopyable
{
size_t start_time_;
typedef std::priority_queue<event_node_ptr,std::vector<event_node_ptr>,less_ptr<event_node_ptr> > event_queue;
event_queue queue_;
public:
fake_event_source();
~fake_event_source();
void add_event(const size_t time, const SDL_Event& event);
void add_event(event_node_ptr new_node);
void start();
SDL_Event make_key_event(Uint8 type, const SDLKey key, const SDLMod mod);
event_node_ptr press_key(const size_t time, const SDLKey key, const SDLMod mod = KMOD_NONE);
event_node_ptr release_key(const size_t time, const SDLKey key, const SDLMod mod =KMOD_NONE);
void process(events::pump_info& /*info*/);
};
}
#endif

View file

@ -283,6 +283,15 @@ void CVideo::make_fake()
image::set_pixel_format(frameBuffer->format);
}
void CVideo::make_test_fake()
{
// Create fake screen that is 1024x768 24bpp
// We can then use this in tests to draw
frameBuffer = SDL_CreateRGBSurface(SDL_SWSURFACE,1024,768,24,0xFF0000,0xFF00,0xFF,0);
image::set_pixel_format(frameBuffer->format);
}
int CVideo::modePossible( int x, int y, int bits_per_pixel, int flags )
{
return SDL_VideoModeOK( x, y, bits_per_pixel, get_flags(flags) );

View file

@ -79,6 +79,7 @@ class CVideo {
int getBpp();
void make_fake();
void make_test_fake();
bool faked() const { return fake_screen_; }
//functions to set and clear 'help strings'. A 'help string' is like a tooltip, but it appears