Support for running the testsuite in command line programs for continuous integration.

Here is a small example inspired from SDLmain.c:

g_launcher = new JGameLauncher();
InitGame();
MTGCollection()->loadFolder("sets/primitives/");
MTGCollection()->loadFolder("sets/", "_cards.dat");
options.reloadProfile();
TestSuite testSuite("test/_tests.txt");
int result = testSuite.run();
DestroyGame();
delete g_launcher;
return result;
This commit is contained in:
Xawotihs@gmail.com
2013-10-23 22:08:30 +00:00
parent 98861dd916
commit 1f0485ff8e
6 changed files with 99 additions and 52 deletions

View File

@@ -125,6 +125,8 @@ public:
#endif
MTGCard * getCardByName(string name);
void loadFolder(const string& folder, const string& filename="" );
int load(const char * config_file, const char * setName = NULL, int autoload = 1);
int countByType(const char * _type);
int countByColor(int color);
@@ -181,9 +183,8 @@ public:
return instance->subtypesList.find(value,false);
}
static void loadInstance();
static void unloadAll();
static inline MTGAllCards* getInstance() { return instance; };
static MTGAllCards* getInstance();
private:
boost::mutex mMutex;

View File

@@ -85,26 +85,33 @@ private:
void cleanup();
vector<boost::thread*> mWorkerThread;
Rules* mRules;
bool mProcessing;
public:
bool mProcessing;
int startTime, endTime;
unsigned int seed;
int nbFailed, nbTests, nbAIFailed, nbAITests;
TestSuite(const char * filename);
~TestSuite();
void initGame(GameObserver* g);
void pregameTests();
int loadNext();
static void ThreadProc(void* inParam);
string getNextFile() {
boost::mutex::scoped_lock lock(mMutex);
if (currentfile >= nbfiles) return "";
currentfile++;
return files[currentfile - 1];
};
static void ThreadProc(void* inParam);
void setRules(Rules* rules) {mRules = rules;};
void pregameTests();
public:
int getElapsedTime() {return endTime-startTime;};
unsigned int seed;
int nbFailed, nbTests, nbAIFailed, nbAITests;
TestSuite(const char * filename);
~TestSuite();
void initGame(GameObserver* g);
int loadNext();
void setRules(Rules* rules) {
mRules = rules;
};
void handleResults(bool wasAI, int error);
// run the test suite in turbo mode without UI,
// returns the amount of failed tests (AI or not), so 0 if everything went fine.
int run();
};
class TestSuiteAI:public AIPlayerBaka

View File

@@ -164,7 +164,7 @@ void GameApp::Create()
HasMusic = jfs->FileExists(WResourceManager::Instance()->musicFile("Track0.mp3")) && jfs->FileExists(WResourceManager::Instance()->musicFile("Track1.mp3"));
LOG("Init Collection");
MTGAllCards::loadInstance();
MTGAllCards::getInstance();
LOG("Loading rules");
Rules::loadAllRules();

View File

@@ -1097,7 +1097,7 @@ void GameStateDuel::Render()
char buf[4096];
mFont->SetColor(ARGB(255,255,255,255));
int elapsedTime = (testSuite->endTime - testSuite->startTime);
int elapsedTime = testSuite->getElapsedTime();
sprintf(buf, "Time to run the tests: %is", elapsedTime/1000);
mFont->DrawString(buf,0,SCREEN_HEIGHT/2 - 20);

View File

@@ -336,6 +336,42 @@ void MTGAllCards::init()
initCounters();
}
void MTGAllCards::loadFolder(const string& folder, const string& filename )
{
vector<string> files = JFileSystem::GetInstance()->scanfolder(folder);
if (!files.size())
{
DebugTrace("loadPrimitives:WARNING:Primitives folder is missing");
return;
}
for (size_t i = 0; i < files.size(); ++i)
{
string afile = folder;
afile.append(files[i]);
if(files[i] == "." || files[i] == "..")
continue;
if (!JFileSystem::GetInstance()->FileExists(afile))
continue;
if(JFileSystem::GetInstance()->DirExists(afile))
loadFolder(string(afile+"/").c_str(), filename);
if(filename.size())
{
if(filename == files[i])
{
load(afile.c_str(), folder.c_str());
}
} else {
load(afile.c_str());
}
}
}
int MTGAllCards::load(const char * config_file, const char * set_name, int)
{
conf_read_mode = 0;
@@ -445,10 +481,12 @@ MTGAllCards::~MTGAllCards()
primitives.clear();
}
void MTGAllCards::loadInstance()
MTGAllCards* MTGAllCards::getInstance()
{
if(!instance)
instance = new MTGAllCards();
return instance;
}
void MTGAllCards::unloadAll()

View File

@@ -531,7 +531,6 @@ TestSuite::TestSuite(const char * filename)
int TestSuite::loadNext()
{
endTime = JGEGetTime();
summoningSickness = 0;
seed = 0;
@@ -582,6 +581,43 @@ int TestSuite::loadNext()
return currentfile;
}
void TestSuite::ThreadProc(void* inParam)
{
LOG("Entering TestSuite::ThreadProc");
TestSuite* instance = reinterpret_cast<TestSuite*>(inParam);
if (instance)
{
string filename;
float counter = 1.0f;
while(instance->mProcessing && (filename = instance->getNextFile()) != "")
{
TestSuiteGame theGame(instance, filename);
if(theGame.isOK)
{
theGame.observer->loadTestSuitePlayer(0, &theGame);
theGame.observer->loadTestSuitePlayer(1, &theGame);
theGame.observer->startGame(theGame.gameType, /*instance->mRules*/Rules::getRulesByFilename("testsuite.txt"));
theGame.initGame();
while(!theGame.observer->didWin())
theGame.observer->Update(counter++);
}
}
}
LOG("Leaving TestSuite::ThreadProc");
}
int TestSuite::run()
{
mProcessing = false;
loadNext();
ThreadProc(this);
return nbFailed + nbAIFailed;
}
void TestSuiteActions::cleanup()
{
nbitems = 0;
@@ -755,41 +791,6 @@ void TestSuite::pregameTests()
}
}
void TestSuite::ThreadProc(void* inParam)
{
LOG("Entering TestSuite::ThreadProc");
TestSuite* instance = reinterpret_cast<TestSuite*>(inParam);
if (instance)
{
string filename;
while(instance->mProcessing && (filename = instance->getNextFile()) != "")
{
TestSuiteGame theGame(instance, filename);
if(theGame.isOK)
{
theGame.observer->loadTestSuitePlayer(0, &theGame);
theGame.observer->loadTestSuitePlayer(1, &theGame);
theGame.observer->startGame(theGame.gameType, instance->mRules);
theGame.initGame();
while(!theGame.observer->didWin())
theGame.observer->Update(1);
/*
if(theGame.observer->gameType() != GAME_TYPE_MOMIR)
{
stringstream stream;
stream << *(theGame.observer);
theGame.observer->load(stream.str(), false, &theGame);
theGame.assertGame();
}
*/
}
}
}
LOG("Leaving TestSuite::ThreadProc");
}
boost::mutex TestSuiteGame::mMutex;
TestSuiteGame::~TestSuiteGame()