TESTBED: Merge gsoc2010-testbed branch

svn-id: r52681
This commit is contained in:
Eugene Sandulenko 2010-09-12 08:08:37 +00:00
commit 74118a7087
29 changed files with 4176 additions and 0 deletions

View file

@ -157,6 +157,9 @@ public:
#if PLUGIN_ENABLED_STATIC(TEENAGENT)
LINK_PLUGIN(TEENAGENT)
#endif
#if PLUGIN_ENABLED_STATIC(TESTBED)
LINK_PLUGIN(TESTBED)
#endif
#if PLUGIN_ENABLED_STATIC(TINSEL)
LINK_PLUGIN(TINSEL)
#endif

1
configure vendored
View file

@ -106,6 +106,7 @@ add_engine sky "Beneath a Steel Sky" yes
add_engine sword1 "Broken Sword" yes
add_engine sword2 "Broken Sword II" yes
add_engine teenagent "Teen Agent" yes
add_engine testbed "TestBed: the Testing framework" no
add_engine tinsel "Tinsel" yes
add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes
add_engine tucker "Bud Tucker in Double Trouble" yes

View file

@ -0,0 +1,52 @@
#!/bin/sh
# Create the directory structure
# Avoided bash shortcuts / file-seperators in interest of portability
if [ -e testbed ]; then
echo "Game-data already present as testbed/"
echo "To regenerate, remove and rerun"
exit 0
fi
mkdir testbed
cd testbed
# For game detection
echo "ScummVM rocks!" > TESTBED
mkdir test1
mkdir Test2
mkdir TEST3
mkdir tEST4
mkdir test5
cd test1
echo "It works!" > file.txt
cd ..
cd Test2
echo "It works!" > File.txt
cd ..
cd TEST3
echo "It works!" > FILE.txt
cd ..
cd tEST4
echo "It works!" > fILe.txt
cd ..
cd test5
echo "It works!" > file.
cd ..
# back to the top
cd ..
# move the audiocd data to newly created directory
cp -r testbed-audiocd-files testbed/audiocd-files
echo "Game data created"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -141,6 +141,11 @@ DEFINES += -DENABLE_SWORD2=$(ENABLE_SWORD2)
MODULES += engines/sword2
endif
ifdef ENABLE_TESTBED
DEFINES += -DENABLE_TESTBED=$(ENABLE_TESTBED)
MODULES += engines/testbed
endif
ifdef ENABLE_TEENAGENT
DEFINES += -DENABLE_TEENAGENT=$(ENABLE_TEENAGENT)
MODULES += engines/teenagent

292
engines/testbed/config.cpp Normal file
View file

@ -0,0 +1,292 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "common/fs.h"
#include "common/stream.h"
#include "common/config-manager.h"
#include "engines/engine.h"
#include "testbed/config.h"
namespace Testbed {
TestbedOptionsDialog::TestbedOptionsDialog(Common::Array<Testsuite *> &tsList, TestbedConfigManager *tsConfMan) : GUI::Dialog("Browser"), _testbedConfMan(tsConfMan) {
new GUI::StaticTextWidget(this, "Browser.Headline", "Select Testsuites to Execute");
new GUI::StaticTextWidget(this, "Browser.Path", "Use Doubleclick to select/deselect");
// Construct a String Array
Common::Array<Testsuite *>::const_iterator iter;
Common::String description;
uint selected = 0;
for (iter = tsList.begin(); iter != tsList.end(); iter++) {
_testSuiteArray.push_back(*iter);
description = (*iter)->getDescription();
if ((*iter)->isEnabled()) {
_testSuiteDescArray.push_back(description + "(selected)");
selected++;
_colors.push_back(GUI::ThemeEngine::kFontColorNormal);
} else {
_testSuiteDescArray.push_back(description);
_colors.push_back(GUI::ThemeEngine::kFontColorAlternate);
}
}
_testListDisplay = new TestbedListWidget(this, "Browser.List", _testSuiteArray);
_testListDisplay->setNumberingMode(GUI::kListNumberingOff);
_testListDisplay->setList(_testSuiteDescArray, &_colors);
// This list shouldn't be editable
_testListDisplay->setEditable(false);
if (selected > (tsList.size() - selected)) {
_selectButton = new GUI::ButtonWidget(this, "Browser.Up", "Deselect All", 0, kTestbedDeselectAll, 0);
} else {
_selectButton = new GUI::ButtonWidget(this, "Browser.Up", "Select All", 0, kTestbedSelectAll, 0);
}
new GUI::ButtonWidget(this, "Browser.Cancel", "Run tests", 0, GUI::kCloseCmd);
new GUI::ButtonWidget(this, "Browser.Choose", "Exit Testbed", 0, kTestbedQuitCmd);
}
TestbedOptionsDialog::~TestbedOptionsDialog() {}
void TestbedOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
Testsuite *ts;
Common::WriteStream *ws;
switch (cmd) {
case GUI::kListItemDoubleClickedCmd:
ts = _testSuiteArray[_testListDisplay->getSelected()];
if (ts) {
if (ts->isEnabled()) {
ts->enable(false);
_testListDisplay->markAsDeselected(_testListDisplay->getSelected());
} else {
ts->enable(true);
_testListDisplay->markAsSelected(_testListDisplay->getSelected());
}
}
break;
case kTestbedQuitCmd:
Engine::quitGame();
close();
break;
case kTestbedDeselectAll:
_selectButton->setLabel("Select All");
_selectButton->setCmd(kTestbedSelectAll);
for (uint i = 0; i < _testSuiteArray.size(); i++) {
_testListDisplay->markAsDeselected(i);
ts = _testSuiteArray[i];
if (ts) {
ts->enable(false);
}
}
break;
case kTestbedSelectAll:
_selectButton->setLabel("Deselect All");
_selectButton->setCmd(kTestbedDeselectAll);
for (uint i = 0; i < _testSuiteArray.size(); i++) {
_testListDisplay->markAsSelected(i);
ts = _testSuiteArray[i];
if (ts) {
ts->enable(true);
}
}
break;
case GUI::kCloseCmd:
// This is final selected state, write it to config file.
ws = _testbedConfMan->getConfigWriteStream();
_testbedConfMan->writeTestbedConfigToStream(ws);
delete ws;
default:
GUI::Dialog::handleCommand(sender, cmd, data);
}
}
void TestbedInteractionDialog::addText(uint w, uint h, const Common::String text, Graphics::TextAlign textAlign, uint xOffset, uint yPadding) {
if (!xOffset) {
xOffset = _xOffset;
}
_yOffset += yPadding;
new GUI::StaticTextWidget(this, xOffset, _yOffset, w, h, text, textAlign);
_yOffset += h;
}
void TestbedInteractionDialog::addButton(uint w, uint h, const Common::String name, uint32 cmd, uint xOffset, uint yPadding) {
if (!xOffset) {
xOffset = _xOffset;
}
_yOffset += yPadding;
_buttonArray.push_back(new GUI::ButtonWidget(this, xOffset, _yOffset, w, h, name, 0, cmd));
_yOffset += h;
}
void TestbedInteractionDialog::addList(uint x, uint y, uint w, uint h, Common::Array<Common::String> &strArray, uint yPadding) {
_yOffset += yPadding;
GUI::ListWidget *list = new GUI::ListWidget(this, x, y, w, h);
list->setEditable(false);
list->setNumberingMode(GUI::kListNumberingOff);
list->setList(strArray);
_yOffset += h;
}
void TestbedInteractionDialog::addButtonXY(uint x, uint y, uint w, uint h, const Common::String name, uint32 cmd) {
_buttonArray.push_back(new GUI::ButtonWidget(this, x, _yOffset, w, h, name, 0, cmd));
}
void TestbedInteractionDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
default:
GUI::Dialog::handleCommand(sender, cmd, data);
}
}
void TestbedConfigManager::initDefaultConfiguration() {
// Default Configuration
// Add Global configuration Parameters here.
_configFileInterface.setKey("isSessionInteractive", "Global", "true");
}
void TestbedConfigManager::writeTestbedConfigToStream(Common::WriteStream *ws) {
Common::String wStr;
for (Common::Array<Testsuite *>::const_iterator i = _testsuiteList.begin(); i < _testsuiteList.end(); i++) {
_configFileInterface.setKey("this", (*i)->getName(), boolToString((*i)->isEnabled()));
const Common::Array<Test *> &testList = (*i)->getTestList();
for (Common::Array<Test *>::const_iterator j = testList.begin(); j != testList.end(); j++) {
_configFileInterface.setKey((*j)->featureName, (*i)->getName(), boolToString((*j)->enabled));
}
}
_configFileInterface.saveToStream(*ws);
_configFileInterface.clear();
ws->flush();
}
Common::SeekableReadStream *TestbedConfigManager::getConfigReadStream() {
// Look for config file in game-path
const Common::String &path = ConfMan.get("path");
Common::FSDirectory gameRoot(path);
Common::SeekableReadStream *rs = gameRoot.createReadStreamForMember(_configFileName);
return rs;
}
Common::WriteStream *TestbedConfigManager::getConfigWriteStream() {
// Look for config file in game-path
const Common::String &path = ConfMan.get("path");
Common::WriteStream *ws;
Common::FSNode gameRoot(path);
Common::FSNode config = gameRoot.getChild(_configFileName);
ws = config.createWriteStream();
return ws;
}
void TestbedConfigManager::parseConfigFile() {
Common::SeekableReadStream *rs = getConfigReadStream();
if (!rs) {
Testsuite::logPrintf("Info! No config file found, using default configuration.\n");
initDefaultConfiguration();
return;
}
_configFileInterface.loadFromStream(*rs);
Common::ConfigFile::SectionList sections = _configFileInterface.getSections();
Testsuite *currTS = 0;
for (Common::ConfigFile::SectionList::const_iterator i = sections.begin(); i != sections.end(); i++) {
if (i->name.equalsIgnoreCase("Global")) {
// Global params may be directly queried, ignore them
} else {
// A testsuite, process it.
currTS = getTestsuiteByName(i->name);
Common::ConfigFile::SectionKeyList kList = i->getKeys();
if (!currTS) {
Testsuite::logPrintf("Warning! Error in config: Testsuite %s not found\n", i->name.c_str());
}
for (Common::ConfigFile::SectionKeyList::const_iterator j = kList.begin(); j != kList.end(); j++) {
if (j->key.equalsIgnoreCase("this")) {
currTS->enable(stringToBool(j->value));
} else {
if (!currTS->enableTest(j->key, stringToBool(j->value))) {
Testsuite::logPrintf("Warning! Error in config: Test %s not found\n", j->key.c_str());
}
}
}
}
}
delete rs;
}
int TestbedConfigManager::getNumSuitesEnabled() {
int count = 0;
for (uint i = 0; i < _testsuiteList.size(); i++) {
if (_testsuiteList[i]->isEnabled()) {
count++;
}
}
return count;
}
Testsuite *TestbedConfigManager::getTestsuiteByName(const Common::String &name) {
for (uint i = 0; i < _testsuiteList.size(); i++) {
if (name.equalsIgnoreCase(_testsuiteList[i]->getName())) {
return _testsuiteList[i];
}
}
return 0;
}
void TestbedConfigManager::selectTestsuites() {
parseConfigFile();
if (_configFileInterface.hasKey("isSessionInteractive", "Global")) {
Common::String in;
_configFileInterface.getKey("isSessionInteractive", "Global", in);
Testsuite::isSessionInteractive = stringToBool(in);
}
if (!Testsuite::isSessionInteractive) {
// Non interactive sessions don't need to go beyond
return;
}
// XXX: disabling these as of now for fastly testing other tests
// Testsuite::isSessionInteractive = false;
Common::String prompt("Welcome to the ScummVM testbed!\n"
"It is a framework to test the various ScummVM subsystems namely GFX, Sound, FS, events etc.\n"
"If you see this, it means interactive tests would run on this system :)");
Testsuite::logPrintf("Info! : Interactive tests are also being executed.\n");
if (Testsuite::handleInteractiveInput(prompt, "Proceed?", "Customize", kOptionRight)) {
// Select testsuites using checkboxes
TestbedOptionsDialog tbd(_testsuiteList, this);
tbd.runModal();
}
}
} // End of namespace Testbed

135
engines/testbed/config.h Normal file
View file

@ -0,0 +1,135 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef TESTBED_CONFIG_H
#define TESTBED_CONFIG_H
#include "common/array.h"
#include "common/config-file.h"
#include "common/str-array.h"
#include "common/tokenizer.h"
#include "gui/ListWidget.h"
#include "gui/options.h"
#include "gui/ThemeEngine.h"
#include "testbed/testsuite.h"
namespace Testbed {
enum {
kTestbedQuitCmd = 'Quit',
kTestbedSelectAll = 'sAll',
kTestbedDeselectAll = 'dAll'
};
class TestbedConfigManager {
public:
TestbedConfigManager(Common::Array<Testsuite *> &tList, const Common::String fName) : _testsuiteList(tList), _configFileName(fName) {}
~TestbedConfigManager() {}
void selectTestsuites();
void setConfigFile(const Common::String fName) { _configFileName = fName; }
Common::SeekableReadStream *getConfigReadStream();
Common::WriteStream *getConfigWriteStream();
void writeTestbedConfigToStream(Common::WriteStream *ws);
Testsuite *getTestsuiteByName(const Common::String &name);
bool stringToBool(const Common::String str) { return str.equalsIgnoreCase("true") ? true : false; }
Common::String boolToString(bool val) { return val ? "true" : "false"; }
void initDefaultConfiguration();
int getNumSuitesEnabled();
private:
Common::Array<Testsuite *> &_testsuiteList;
Common::String _configFileName;
Common::ConfigFile _configFileInterface;
void parseConfigFile();
};
class TestbedListWidget : public GUI::ListWidget {
public:
TestbedListWidget(GUI::Dialog *boss, const Common::String &name, Common::Array<Testsuite *> tsArray) : GUI::ListWidget(boss, name), _testSuiteArray(tsArray) {}
void markAsSelected(int i) {
if (!_list[i].contains("selected")) {
_list[i] += " (selected)";
}
_listColors[i] = GUI::ThemeEngine::kFontColorNormal;
draw();
}
void markAsDeselected(int i) {
if (_list[i].contains("selected")) {
_list[i] = _testSuiteArray[i]->getDescription();
}
_listColors[i] = GUI::ThemeEngine::kFontColorAlternate;
draw();
}
void setColor(uint32 indx, GUI::ThemeEngine::FontColor color) {
assert(indx < _listColors.size());
_listColors[indx] = color;
draw();
}
private:
Common::Array<Testsuite *> _testSuiteArray;
};
class TestbedOptionsDialog : public GUI::Dialog {
public:
TestbedOptionsDialog(Common::Array<Testsuite *> &tsList, TestbedConfigManager *tsConfMan);
~TestbedOptionsDialog();
void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
private:
GUI::ListWidget::ColorList _colors;
GUI::ButtonWidget *_selectButton;
Common::Array<Testsuite *> _testSuiteArray;
Common::StringArray _testSuiteDescArray;
TestbedListWidget *_testListDisplay;
TestbedConfigManager *_testbedConfMan;
};
class TestbedInteractionDialog : public GUI::Dialog {
public:
TestbedInteractionDialog(uint x, uint y, uint w, uint h) : GUI::Dialog(x, y, w, h) {}
~TestbedInteractionDialog() {}
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
void addButton(uint w, uint h, const Common::String name, uint32 cmd, uint xOffset = 0, uint yPadding = 8);
void addButtonXY(uint x, uint y, uint w, uint h, const Common::String name, uint32 cmd);
void addText(uint w, uint h, const Common::String text, Graphics::TextAlign textAlign, uint xOffset, uint yPadding = 8);
void addList(uint x, uint y, uint w, uint h, Common::Array<Common::String> &strArray, uint yPadding = 8);
protected:
Common::Array<GUI::ButtonWidget *> _buttonArray;
uint _xOffset;
uint _yOffset;
};
} // End of namespace Testbed
#endif // TESTBED_CONFIG_H

View file

@ -0,0 +1,92 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/config-manager.h"
#include "engines/advancedDetector.h"
#include "common/system.h"
#include "common/fs.h"
#include "base/plugins.h"
#include "testbed/testbed.h"
static const PlainGameDescriptor testbed_setting[] = {
{ "testbed", "Testbed: The backend testing framework" },
{ 0, 0 }
};
static const ADGameDescription testbedDescriptions[] = {
{
"testbed",
"",
AD_ENTRY1(NULL, 0), // No data files required
Common::EN_ANY,
Common::kPlatformPC,
ADGF_NO_FLAGS,
Common::GUIO_NONE
},
AD_TABLE_END_MARKER
};
static const ADParams detectionParams = {
(const byte *)testbedDescriptions,
sizeof(ADGameDescription),
512,
testbed_setting,
0,
"testbed",
0,
ADGF_NO_FLAGS,
Common::GUIO_NONE,
1,
0
};
class TestbedMetaEngine : public AdvancedMetaEngine {
public:
TestbedMetaEngine() : AdvancedMetaEngine(detectionParams) {
}
virtual const char *getName() const {
return "TestBed: The backend testing framework";
}
virtual const char *getOriginalCopyright() const {
return "Copyright (C) ScummVM";
}
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
// Instantiate Engine even if the game data is not found.
*engine = new Testbed::TestbedEngine(syst);
return true;
}
};
#if PLUGIN_ENABLED_DYNAMIC(TESTBED)
REGISTER_PLUGIN_DYNAMIC(TESTBED, PLUGIN_TYPE_ENGINE, TestbedMetaEngine);
#else
REGISTER_PLUGIN_STATIC(TESTBED, PLUGIN_TYPE_ENGINE, TestbedMetaEngine);
#endif

294
engines/testbed/events.cpp Normal file
View file

@ -0,0 +1,294 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "common/events.h"
#include "common/keyboard.h"
#include "engines/engine.h"
#include "graphics/cursorman.h"
#include "testbed/events.h"
#include "testbed/graphics.h"
namespace Testbed {
struct keycodeToChar {
Common::KeyCode code;
char value;
} keyCodeLUT[] = {
{Common::KEYCODE_a, 'a'},
{Common::KEYCODE_b, 'b'},
{Common::KEYCODE_c, 'c'},
{Common::KEYCODE_d, 'd'},
{Common::KEYCODE_e, 'e'},
{Common::KEYCODE_f, 'f'},
{Common::KEYCODE_g, 'g'},
{Common::KEYCODE_h, 'h'},
{Common::KEYCODE_i, 'i'},
{Common::KEYCODE_j, 'j'},
{Common::KEYCODE_k, 'k'},
{Common::KEYCODE_l, 'l'},
{Common::KEYCODE_m, 'm'},
{Common::KEYCODE_n, 'n'},
{Common::KEYCODE_o, 'o'},
{Common::KEYCODE_p, 'p'},
{Common::KEYCODE_q, 'q'},
{Common::KEYCODE_r, 'r'},
{Common::KEYCODE_s, 's'},
{Common::KEYCODE_t, 't'},
{Common::KEYCODE_u, 'u'},
{Common::KEYCODE_v, 'v'},
{Common::KEYCODE_w, 'w'},
{Common::KEYCODE_x, 'x'},
{Common::KEYCODE_y, 'y'},
{Common::KEYCODE_z, 'z'},
{Common::KEYCODE_SPACE, ' '}
};
char EventTests::keystrokeToChar() {
Common::EventManager *eventMan = g_system->getEventManager();
bool quitLoop = false;
Common::Event event;
// handle all keybd events
while (!quitLoop) {
while (eventMan->pollEvent(event)) {
// Quit if explicitly requested!
if (Engine::shouldQuit()) {
return 0;
}
switch (event.type) {
case Common::EVENT_KEYDOWN:
if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
return 0;
}
for (int i = 0; i < ARRAYSIZE(keyCodeLUT); i++) {
if (event.kbd.keycode == keyCodeLUT[i].code) {
return keyCodeLUT[i].value;
}
}
break;
default:
break; // Ignore other events
}
}
}
return 0;
}
Common::Rect EventTests::drawFinishZone() {
Graphics::Surface *screen = g_system->lockScreen();
const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont));
int width = 35;
int height = 20;
int right = g_system->getWidth();
Common::Rect rect(0, 0, right, height);
Common::Rect rect2(0, 0, right - width, height);
screen->fillRect(rect, kColorSpecial);
screen->fillRect(rect2, kColorBlack);
g_system->unlockScreen();
font.drawString(screen, "Close", rect.left, rect.top, screen->w, kColorBlack, Graphics::kTextAlignRight);
g_system->updateScreen();
return Common::Rect(right - width, 0, right, height);
}
bool EventTests::mouseEvents() {
Testsuite::clearScreen();
Common::String info = "Testing Mouse events.\n "
"Any movement/click generated by L/R/M mouse buttons or the mouse wheel should be detected.\n"
"Press X to exit";
if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) {
Testsuite::logPrintf("Info! Skipping test : keyboard events\n");
return true;
}
Common::EventManager *eventMan = g_system->getEventManager();
Common::Point pt(0, 100);
Common::Rect rect = Testsuite::writeOnScreen("Generate mouse events make L/R/M button clicks", pt);
pt.y = 120;
Testsuite::writeOnScreen("Testbed should be able to detect them, Press X to exit", pt);
// Init Mouse Palette
GFXtests::initMousePalette();
Common::Rect finishZone = drawFinishZone();
bool quitLoop = false;
bool passed = true;
// handle all mouse events
Common::Event event;
while (!quitLoop) {
// Show mouse
CursorMan.showMouse(true);
g_system->updateScreen();
while (eventMan->pollEvent(event)) {
// Quit if explicitly requested
if (Engine::shouldQuit()) {
return passed;
}
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
// Movements havee already been tested in GFX
break;
case Common::EVENT_LBUTTONDOWN:
Testsuite::clearScreen(rect);
Testsuite::writeOnScreen("Mouse left-button pressed", pt);
break;
case Common::EVENT_RBUTTONDOWN:
Testsuite::clearScreen(rect);
Testsuite::writeOnScreen("Mouse right-button pressed", pt);
break;
case Common::EVENT_WHEELDOWN:
Testsuite::clearScreen(rect);
Testsuite::writeOnScreen("Mouse wheel moved down", pt);
break;
case Common::EVENT_MBUTTONDOWN:
Testsuite::clearScreen(rect);
Testsuite::writeOnScreen("Mouse middle-button pressed ", pt);
break;
case Common::EVENT_LBUTTONUP:
Testsuite::clearScreen(rect);
if (finishZone.contains(eventMan->getMousePos())) {
quitLoop = true;
}
Testsuite::writeOnScreen("Mouse left-button released", pt);
break;
case Common::EVENT_RBUTTONUP:
Testsuite::clearScreen(rect);
Testsuite::writeOnScreen("Mouse right-button released", pt);
break;
case Common::EVENT_WHEELUP:
Testsuite::clearScreen(rect);
Testsuite::writeOnScreen("Mouse wheel moved up", pt);
break;
case Common::EVENT_MBUTTONUP:
Testsuite::clearScreen(rect);
Testsuite::writeOnScreen("Mouse middle-button released ", pt);
break;
case Common::EVENT_KEYDOWN:
if (event.kbd.keycode == Common::KEYCODE_x) {
Testsuite::clearScreen(rect);
Testsuite::writeOnScreen("Exit requested", pt);
quitLoop = true;
}
break;
default:
break;
}
}
}
CursorMan.showMouse(false);
// Verify results now!
if (Testsuite::handleInteractiveInput("Were mouse clicks L/R/M buttons identfied?", "Yes", "No", kOptionRight)) {
Testsuite::logDetailedPrintf("Mouse clicks (L/R/M buttons) failed");
passed = false;
}
if (Testsuite::handleInteractiveInput("Were mouse wheel movements identified?", "Yes", "No", kOptionRight)) {
Testsuite::logDetailedPrintf("Mouse wheel movements failed");
passed = false;
}
return passed;
}
bool EventTests::kbdEvents() {
Testsuite::clearScreen();
Common::String info = "Testing keyboard events.\n "
"Testbed should be able to figure out any alphanumeric keystrokes made by the user and display them back.\n"
"Press ESC key when done of the input.";
if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) {
Testsuite::logPrintf("Info! Skipping test : keyboard events\n");
return true;
}
// Make user type some word and display the output on screen
Common::String text = "You Entered : ";
Common::Point pt(0, 100);
Testsuite::clearScreen();
Testsuite::writeOnScreen("Enter your word, press ESC when done, it will be echoed back", pt);
pt.y += 20;
Common::Rect rect = Testsuite::writeOnScreen(text, pt);
char letter;
while ((letter = keystrokeToChar()) != 0) {
Testsuite::clearScreen(rect);
text += letter;
rect = Testsuite::writeOnScreen(text, pt);
}
bool passed = true;
if (Testsuite::handleInteractiveInput("Was the word you entered same as that displayed on screen?", "Yes", "No", kOptionRight)) {
Testsuite::logDetailedPrintf("Keyboard Events failed");
passed = false;
}
Testsuite::clearScreen();
return passed;
}
bool EventTests::showMainMenu() {
Testsuite::clearScreen();
Common::String info = "Testing Main Menu events.\n "
"Main Menu event is normally trigerred by user pressing (Ctrl + f5).\n"
"Click 'resume' to continue testbed.";
if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) {
Testsuite::logPrintf("Info! Skipping test : Main Menu\n");
return true;
}
Common::EventManager *eventMan = g_system->getEventManager();
Common::Event mainMenuEvent;
mainMenuEvent.type = Common::EVENT_MAINMENU;
eventMan->pushEvent(mainMenuEvent);
bool passed = true;
if (Testsuite::handleInteractiveInput("Were you able to see a main menu widget?", "Yes", "No", kOptionRight)) {
Testsuite::logDetailedPrintf("Event MAINMENU failed");
passed = false;
}
return passed;
}
EventTestSuite::EventTestSuite() {
addTest("MouseEvents", &EventTests::mouseEvents);
addTest("KeyboardEvents", &EventTests::kbdEvents);
addTest("MainmenuEvent", &EventTests::showMainMenu);
}
} // End of namespace Testbed

67
engines/testbed/events.h Normal file
View file

@ -0,0 +1,67 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef TESTBED_EVENTS_H
#define TESTBED_EVENTS_H
#include "testbed/testsuite.h"
namespace Testbed {
namespace EventTests {
// Helper functions for Event tests
char keystrokeToChar();
Common::Rect drawFinishZone();
// will contain function declarations for Event tests
bool mouseEvents();
bool kbdEvents();
bool showMainMenu();
// add more here
} // End of namespace EventTests
class EventTestSuite : public Testsuite {
public:
/**
* The constructor for the EventTestSuite
* For every test to be executed one must:
* 1) Create a function that would invoke the test
* 2) Add that test to list by executing addTest()
*
* @see addTest()
*/
EventTestSuite();
~EventTestSuite() {}
const char *getName() const {
return "Events";
}
const char *getDescription() const {
return "Events : Keyboard/Mouse/RTL";
}
};
} // End of namespace Testbed
#endif // TESTBED_EVENTS_H

169
engines/testbed/fs.cpp Normal file
View file

@ -0,0 +1,169 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "common/config-manager.h"
#include "common/stream.h"
#include "common/util.h"
#include "testbed/fs.h"
namespace Testbed {
/**
* This test does the following:
* 1) acquires the game-data path
* 2) In the game-root it navigates to "directory" and opens the file "file"
*
* The code accesses the appropriate file using the fileSystem API, creates a read stream of it and
* compares the message contained in it, with what it expects.
*
*/
bool FStests::readDataFromFile(Common::FSDirectory *directory, const char *file) {
Common::SeekableReadStream *readStream = directory->createReadStreamForMember(file);
if (!readStream) {
Testsuite::logDetailedPrintf("Can't open game file for reading\n");
return false;
}
Common::String msg = readStream->readLine();
delete readStream;
Testsuite::logDetailedPrintf("Message Extracted from %s/%s : %s\n", directory->getFSNode().getName().c_str(), file, msg.c_str());
Common::String expectedMsg = "It works!";
if (!msg.equals(expectedMsg)) {
Testsuite::logDetailedPrintf("Can't read Correct data from file\n");
return false;
}
return true;
}
bool FStests::testReadFile() {
const Common::String &path = ConfMan.get("path");
Common::FSDirectory gameRoot(path);
int numFailed = 0;
if (!gameRoot.getFSNode().isDirectory()) {
Testsuite::logDetailedPrintf("game Path should be a directory");
return false;
}
const char *dirList[] = {"test1" ,"Test2", "TEST3" , "tEST4", "test5"};
const char *file[] = {"file.txt", "File.txt", "FILE.txt", "fILe.txt", "file"};
for (unsigned int i = 0; i < ARRAYSIZE(dirList); i++) {
Common::String dirName = dirList[i];
Common::String fileName = file[i];
Common::FSDirectory *directory = gameRoot.getSubDirectory(dirName);
if (!readDataFromFile(directory, fileName.c_str())) {
Testsuite::logDetailedPrintf("Reading from %s/%s failed\n", dirName.c_str(), fileName.c_str());
numFailed++;
}
dirName.toLowercase();
fileName.toLowercase();
delete directory;
directory = gameRoot.getSubDirectory(dirName);
if (!readDataFromFile(directory, fileName.c_str())) {
Testsuite::logDetailedPrintf("Reading from %s/%s failed\n", dirName.c_str(), fileName.c_str());
numFailed++;
}
dirName.toUppercase();
fileName.toUppercase();
delete directory;
directory = gameRoot.getSubDirectory(dirName);
if (!readDataFromFile(directory, fileName.c_str())) {
Testsuite::logDetailedPrintf("Reading from %s/%s failed\n", dirName.c_str(), fileName.c_str());
numFailed++;
}
delete directory;
}
Testsuite::logDetailedPrintf("Failed %d out of 15\n", numFailed);
return false;
}
/**
* This test creates a file testbed.out, writes a sample data and confirms if
* it is same by reading the file again.
*/
bool FStests::testWriteFile() {
const Common::String &path = ConfMan.get("path");
Common::FSNode gameRoot(path);
Common::FSNode fileToWrite = gameRoot.getChild("testbed.out");
Common::WriteStream *ws = fileToWrite.createWriteStream();
if (!ws) {
Testsuite::logDetailedPrintf("Can't open writable file in game data dir\n");
return false;
}
ws->writeString("ScummVM Rocks!");
ws->flush();
delete ws;
Common::SeekableReadStream *rs = fileToWrite.createReadStream();
Common::String readFromFile = rs->readLine();
delete rs;
if (readFromFile.equals("ScummVM Rocks!")) {
// All good
Testsuite::logDetailedPrintf("Data written and read correctly\n");
return true;
}
return false;
}
FSTestSuite::FSTestSuite() {
addTest("ReadingFile", &FStests::testReadFile, false);
addTest("WritingFile", &FStests::testWriteFile, false);
}
void FSTestSuite::enable(bool flag) {
const Common::String &path = ConfMan.get("path");
Common::FSNode gameRoot(path);
Common::FSNode gameIdentificationFile = gameRoot.getChild("TESTBED");
if (!gameIdentificationFile.exists()) {
logPrintf("WARNING! : Game Data not found. Skipping FS tests\n");
Testsuite::enable(false);
return;
}
Testsuite::enable(flag);
}
} // End of namespace Testbed

74
engines/testbed/fs.h Normal file
View file

@ -0,0 +1,74 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef TESTBED_FS_H
#define TESTBED_FS_H
#include "common/fs.h"
#include "testbed/testsuite.h"
namespace Testbed {
namespace FStests {
// Note: These tests require a game-data directory
// So would work if game-path is set in the launcher or invoked as ./scummvm --path="path-to-testbed-data" testbed
// from commandline
// Helper functions for FS tests
bool readDataFromFile(Common::FSDirectory *directory, const char *file);
// will contain function declarations for FS tests
bool testReadFile();
bool testWriteFile();
bool testOpeningSaveFile();
// add more here
} // End of namespace FStests
class FSTestSuite : public Testsuite {
public:
/**
* The constructor for the FSTestSuite
* For every test to be executed one must:
* 1) Create a function that would invoke the test
* 2) Add that test to list by executing addTest()
*
* @see addTest()
*/
FSTestSuite();
~FSTestSuite() {}
const char *getName() const {
return "FS";
}
const char *getDescription() const {
return "File system tests (Navigation, Read/Write)";
}
void enable(bool flag);
};
} // End of namespace Testbed
#endif // TESTBED_FS_H

1102
engines/testbed/graphics.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,94 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef TESTBED_GRAPHICS_H
#define TESTBED_GRAPHICS_H
#include "testbed/testsuite.h"
namespace Testbed {
namespace GFXtests {
// Helper functions for GFX tests
void drawEllipse(int x, int y, int a, int b);
void setupMouseLoop(bool disableCursorPalette = false, const char *gfxModeName = "", int cursorTargetScale = 1);
void initMousePalette();
Common::Rect computeSize(Common::Rect &cursorRect, int scalingFactor, int cursorTargetScale);
void HSVtoRGB(int &rComp, int &gComp, int &bComp, int hue, int sat, int val);
Common::Rect drawCursor(bool cursorPaletteDisabled = false, const char *gfxModeName = "", int cursorTargetScale = 1);
// will contain function declarations for GFX tests
bool cursorTrails();
bool fullScreenMode();
bool aspectRatio();
bool palettizedCursors();
bool mouseMovements();
bool copyRectToScreen();
bool iconifyWindow();
bool scaledCursors();
bool shakingEffect();
bool focusRectangle();
bool overlayGraphics();
bool paletteRotation();
bool pixelFormats();
// add more here
} // End of namespace GFXtests
class GFXTestSuite : public Testsuite {
public:
/**
* The constructor for the GFXTestSuite
* For every test to be executed one must:
* 1) Create a function that would invoke the test
* 2) Add that test to list by executing addTest()
*
* @see addTest()
*/
GFXTestSuite();
~GFXTestSuite() {}
const char *getName() const {
return "GFX";
}
const char *getDescription() const {
return "Graphics Subsystem";
}
static void setCustomColor(uint r, uint g, uint b);
private:
/**
* A Palette consists of 4 components RGBA.
* As of now we only take 3 colors
* 0 (R:0, G:0, B:0) Black (kColorBlack)
* 1 (R:255, G:255, B:255) White (kColorWhite)
* 2 (R:255, G:255, B:255) your customized color (by default white) (kColorCustom)
* The remaining values are zero
*/
static byte _palette[256 * 4];
};
} // End of namespace Testbed
#endif // TESTBED_GRAPHICS_H

172
engines/testbed/misc.cpp Normal file
View file

@ -0,0 +1,172 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "testbed/misc.h"
#include "common/timer.h"
namespace Testbed {
Common::String MiscTests::getHumanReadableFormat(TimeDate &td) {
return Common::String::printf("%d:%d:%d on %d/%d/%d (dd/mm/yyyy)", td.tm_hour, td.tm_min, td.tm_sec, td.tm_mday, td.tm_mon + 1, td.tm_year + 1900);
}
void MiscTests::timerCallback(void *arg) {
// Increment arg which actually points to an int
// arg must point to a static data, threads otherwise have their own stack
int &valToModify = *((int *) arg);
valToModify = 999; // some arbitrary value
}
void MiscTests::criticalSection(void *arg) {
SharedVars &sv = *((SharedVars *)arg);
Testsuite::logDetailedPrintf("Before critical section: %d %d\n", sv.first, sv.second);
g_system->lockMutex(sv.mutex);
// In any case, the two vars must be equal at entry, if mutex works fine.
// verify this here.
if (sv.first != sv.second) {
sv.resultSoFar = false;
}
sv.first++;
g_system->delayMillis(1000);
// This should bring no change as well in the difference between vars
// verify this too.
if (sv.second + 1 != sv.first) {
sv.resultSoFar = false;
}
sv.second *= sv.first;
Testsuite::logDetailedPrintf("After critical section: %d %d\n", sv.first, sv.second);
g_system->unlockMutex(sv.mutex);
g_system->getTimerManager()->removeTimerProc(criticalSection);
}
bool MiscTests::testDateTime() {
if (Testsuite::isSessionInteractive) {
if (Testsuite::handleInteractiveInput("Testing the date time API implementation", "Continue", "Skip", kOptionRight)) {
Testsuite::logPrintf("Info! Date time tests skipped by the user.\n");
return true;
}
Testsuite::writeOnScreen("Verifying Date-Time...", Common::Point(0, 100));
}
TimeDate t1, t2;
g_system->getTimeAndDate(t1);
Testsuite::logDetailedPrintf("Current Time and Date: ");
Common::String dateTimeNow;
dateTimeNow = getHumanReadableFormat(t1);
if (Testsuite::isSessionInteractive) {
// Directly verify date
dateTimeNow = "We expect the current date time to be " + dateTimeNow;
if (Testsuite::handleInteractiveInput(dateTimeNow, "Correct!", "Wrong", kOptionRight)) {
return false;
}
}
g_system->getTimeAndDate(t1);
dateTimeNow = getHumanReadableFormat(t1);
Testsuite::logDetailedPrintf("%s\n", dateTimeNow.c_str());
// Now, Put some delay
g_system->delayMillis(2000);
g_system->getTimeAndDate(t2);
Testsuite::logDetailedPrintf("Time and Date 2s later: ");
dateTimeNow = getHumanReadableFormat(t2);
Testsuite::logDetailedPrintf("%s\n", dateTimeNow.c_str());
if (t1.tm_year == t2.tm_year && t1.tm_mon == t2.tm_mon && t1.tm_mday == t2.tm_mday) {
if (t1.tm_mon == t2.tm_mon && t1.tm_year == t2.tm_year) {
// Ignore lag due to processing time
if (t1.tm_sec + 2 == t2.tm_sec) {
return true;
}
}
}
return false;
}
bool MiscTests::testTimers() {
static int valToModify = 0;
if (g_system->getTimerManager()->installTimerProc(timerCallback, 100000, &valToModify)) {
g_system->delayMillis(150);
g_system->getTimerManager()->removeTimerProc(timerCallback);
if (999 == valToModify) {
return true;
}
}
return false;
}
bool MiscTests::testMutexes() {
if (Testsuite::isSessionInteractive) {
if (Testsuite::handleInteractiveInput("Testing the Mutual Exclusion API implementation", "Continue", "Skip", kOptionRight)) {
Testsuite::logPrintf("Info! Mutex tests skipped by the user.\n");
return true;
}
Testsuite::writeOnScreen("Installing mutex", Common::Point(0, 100));
}
static SharedVars sv = {1, 1, true, g_system->createMutex()};
if (g_system->getTimerManager()->installTimerProc(criticalSection, 100000, &sv)) {
g_system->delayMillis(150);
}
g_system->lockMutex(sv.mutex);
sv.first++;
g_system->delayMillis(1000);
sv.second *= sv.first;
g_system->unlockMutex(sv.mutex);
// wait till timed process exits
if (Testsuite::isSessionInteractive) {
Testsuite::writeOnScreen("Waiting for 3s so that timed processes finish", Common::Point(0, 100));
}
g_system->delayMillis(3000);
Testsuite::logDetailedPrintf("Final Value: %d %d\n", sv.first, sv.second);
g_system->deleteMutex(sv.mutex);
if (sv.resultSoFar && 6 == sv.second) {
return true;
}
return false;
}
MiscTestSuite::MiscTestSuite() {
addTest("Datetime", &MiscTests::testDateTime, false);
addTest("Timers", &MiscTests::testTimers, false);
addTest("Mutexes", &MiscTests::testMutexes, false);
}
} // End of namespace Testbed

80
engines/testbed/misc.h Normal file
View file

@ -0,0 +1,80 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef TESTBED_MISC_H
#define TESTBED_MISC_H
#include "testbed/testsuite.h"
namespace Testbed {
// Shared variables used in mutex handling test
struct SharedVars {
int first;
int second;
bool resultSoFar;
OSystem::MutexRef mutex;
};
namespace MiscTests {
// Miscellaneous tests include testing datetime, timers and mutexes
// Helper functions for Misc tests
Common::String getHumanReadableFormat(TimeDate &td);
void timerCallback(void *arg);
void criticalSection(void *arg);
// will contain function declarations for Misc tests
bool testDateTime();
bool testTimers();
bool testMutexes();
// add more here
} // End of namespace MiscTests
class MiscTestSuite : public Testsuite {
public:
/**
* The constructor for the MiscTestSuite
* For every test to be executed one must:
* 1) Create a function that would invoke the test
* 2) Add that test to list by executing addTest()
*
* @see addTest()
*/
MiscTestSuite();
~MiscTestSuite() {}
const char *getName() const {
return "Misc";
}
const char *getDescription() const {
return "Miscellaneous: Timers/Mutexes/Datetime";
}
};
} // End of namespace Testbed
#endif // TESTBED_MISC_H

24
engines/testbed/module.mk Normal file
View file

@ -0,0 +1,24 @@
MODULE := engines/testbed
MODULE_OBJS := \
config.o \
detection.o \
events.o \
fs.o \
graphics.o \
misc.o \
savegame.o \
sound.o \
testbed.o \
testsuite.o
MODULE_DIRS += \
engines/testbed
# This module can be built as a plugin
ifeq ($(ENABLE_TESTBED), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk

View file

@ -0,0 +1,199 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "common/savefile.h"
#include "testbed/savegame.h"
namespace Testbed {
/**
* This test creates a savefile for the given testbed-state and could be reloaded using the saveFile API.
* It is intended to test saving and loading from savefiles.
*/
bool SaveGametests::writeDataToFile(const char *fileName, const char *msg) {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::OutSaveFile *saveFile = saveFileMan->openForSaving(fileName);
if (!saveFile) {
Testsuite::logDetailedPrintf("Can't open saveFile %s\n", fileName);
return false;
}
saveFile->writeString(msg);
saveFile->finalize();
delete saveFile;
return true;
}
bool SaveGametests::readAndVerifyData(const char *fileName, const char *expected) {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::InSaveFile *loadFile = saveFileMan->openForLoading(fileName);
if (!loadFile) {
Testsuite::logDetailedPrintf("Can't open save File to load\n");
return false;
}
Common::String lineToRead = loadFile->readLine();
delete loadFile;
if (lineToRead.equals(expected)) {
return true;
}
return false;
}
bool SaveGametests::testSaveLoadState() {
// create a savefile with "ScummVM Rocks!" written on it
if (!writeDataToFile("tBedSavefile.0", "ScummVM Rocks!")) {
Testsuite::logDetailedPrintf("Writing data to savefile failed\n");
return false;
}
// Verify if it contains the same data
if (!readAndVerifyData("tBedSavefile.0", "ScummVM Rocks!")) {
Testsuite::logDetailedPrintf("Reading data from savefile failed\n");
return false;
}
return true;
}
bool SaveGametests::testRemovingSavefile() {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
// Create a dummy savefile
if (!writeDataToFile("tBedSavefileToRemove.0", "Dummy Savefile!")) {
Testsuite::logDetailedPrintf("Writing data to savefile failed\n");
return false;
}
// Remove it
saveFileMan->removeSavefile("tBedSavefileToRemove.0");
// Try opening it Now
Common::InSaveFile *loadFile = saveFileMan->openForLoading("saveFile.0");
if (loadFile) {
// Removing failed
Testsuite::logDetailedPrintf("Removing savefile failed\n");
return false;
}
return true;
}
bool SaveGametests::testRenamingSavefile() {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
// Open a file for renaming
if (!writeDataToFile("tBedSomeWeirdName.0", "Rename me!")) {
Testsuite::logDetailedPrintf("Writing data to savefile failed\n");
return false;
}
// Rename it
saveFileMan->renameSavefile("tBedSomeWeirdName.0", "tBedSomeCoolName.0");
// Verify if it contains the same data
if (!readAndVerifyData("tBedSomeCoolName.0", "Rename me!")) {
Testsuite::logDetailedPrintf("Renaming savefile failed\n");
return false;
}
return true;
}
bool SaveGametests::testListingSavefile() {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
saveFileMan->clearError();
// create some savefiles
const char *savefileName[] = {"tBedSavefileToList.0", "tBedSavefileToList.1", "tBedSavefileToList.2"};
writeDataToFile("tBedSavefileToList.0", "Save me!");
writeDataToFile("tBedSavefileToList.1", "Save me!");
writeDataToFile("tBedSavefileToList.2", "Save me!");
Common::Error error = saveFileMan->getError();
if (error != Common::kNoError) {
// Abort. Some Error in writing files
Testsuite::logDetailedPrintf("Error while creating savefiles: %s\n", Common::errorToString(error));
return false;
}
Common::StringArray savefileList = saveFileMan->listSavefiles("tBedSavefileToList.?");
if (savefileList.size() == ARRAYSIZE(savefileName)) {
// Match them exactly
// As the order of savefileList may be platform specific, match them exhaustively
for (uint i = 0; i < ARRAYSIZE(savefileName); i++) {
for (uint j = 0; j < savefileList.size(); j++) {
if (savefileList[j].equals(savefileName[i])) {
break;
}
if (savefileList.size() == j) {
// A match for this name not found
Testsuite::logDetailedPrintf("Listed Names don't match\n");
return false;
}
}
}
return true;
} else {
Testsuite::logDetailedPrintf("listing Savefiles failed!\n");
return false;
}
return false;
}
bool SaveGametests::testErrorMessages() {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
saveFileMan->clearError();
// Try opening a non existing file
readAndVerifyData("tBedSomeNonExistentSaveFile.0", "File doesn't exists!");
Common::Error error = saveFileMan->getError();
if (error == Common::kNoError) {
// blunder! how come?
Testsuite::logDetailedPrintf("SaveFileMan.getError() failed\n");
return false;
}
// Can't actually predict whether which error, kInvalidPath or kPathDoesNotExist or some other?
// So just return true if some error
Testsuite::logDetailedPrintf("getError returned : %s\n", saveFileMan->getErrorDesc().c_str());
return true;
}
SaveGameTestSuite::SaveGameTestSuite() {
addTest("OpeningSaveFile", &SaveGametests::testSaveLoadState, false);
addTest("RemovingSaveFile", &SaveGametests::testRemovingSavefile, false);
addTest("RenamingSaveFile", &SaveGametests::testRenamingSavefile, false);
addTest("ListingSaveFile", &SaveGametests::testListingSavefile, false);
addTest("VerifyErrorMessages", &SaveGametests::testErrorMessages, false);
}
} // End of namespace Testbed

View file

@ -0,0 +1,69 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef TESTBED_SAVEGAME_H
#define TESTBED_SAVEGAME_H
#include "testbed/testsuite.h"
namespace Testbed {
namespace SaveGametests {
// Helper functions for SaveGame tests
bool writeDataToFile(const char *fileName, const char *msg);
bool readAndVerifyData(const char *fileName, const char *expected);
// will contain function declarations for SaveGame tests
bool testSaveLoadState();
bool testRemovingSavefile();
bool testRenamingSavefile();
bool testListingSavefile();
bool testErrorMessages();
// add more here
} // End of namespace SaveGametests
class SaveGameTestSuite : public Testsuite {
public:
/**
* The constructor for the SaveGameTestSuite
* For every test to be executed one must:
* 1) Create a function that would invoke the test
* 2) Add that test to list by executing addTest()
*
* @see addTest()
*/
SaveGameTestSuite();
~SaveGameTestSuite() {}
const char *getName() const {
return "SaveGames";
}
const char *getDescription() const {
return "Saving Game state tests";
}
};
} // End of namespace Testbed
#endif // TESTBED_SAVEGAME_H

264
engines/testbed/sound.cpp Normal file
View file

@ -0,0 +1,264 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "sound/audiocd.h"
#include "sound/softsynth/pcspk.h"
#include "testbed/sound.h"
namespace Testbed {
enum {
kPlayChannel1 = 'pch1',
kPlayChannel2 = 'pch2',
kPlayChannel3 = 'pch3',
kPauseChannel1 = 'pac1',
kPauseChannel2 = 'pac2',
kPauseChannel3 = 'pac3'
};
SoundSubsystemDialog::SoundSubsystemDialog() : TestbedInteractionDialog(80, 60, 400, 170) {
_xOffset = 25;
_yOffset = 0;
Common::String text = "Sound Subsystem Tests: Test Mixing of Audio Streams.";
addText(350, 20, text, Graphics::kTextAlignCenter, _xOffset, 15);
addButton(200, 20, "Play Channel #1", kPlayChannel1);
addButton(200, 20, "Play Channel #2", kPlayChannel2);
addButton(200, 20, "Play Channel #3", kPlayChannel3);
addButton(50, 20, "Close", GUI::kCloseCmd, 160, 15);
_mixer = g_system->getMixer();
// the three streams to be mixed
Audio::PCSpeaker *s1 = new Audio::PCSpeaker();
Audio::PCSpeaker *s2 = new Audio::PCSpeaker();
Audio::PCSpeaker *s3 = new Audio::PCSpeaker();
s1->play(Audio::PCSpeaker::kWaveFormSine, 1000, -1);
s2->play(Audio::PCSpeaker::kWaveFormSine, 1200, -1);
s3->play(Audio::PCSpeaker::kWaveFormSine, 1400, -1);
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_h1, s1);
_mixer->pauseHandle(_h1, true);
_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_h2, s2);
_mixer->pauseHandle(_h2, true);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_h3, s3);
_mixer->pauseHandle(_h3, true);
}
void SoundSubsystemDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kPlayChannel1:
_buttonArray[0]->setLabel("Pause Channel #1");
_buttonArray[0]->setCmd(kPauseChannel1);
_mixer->pauseHandle(_h1, false);
break;
case kPlayChannel2:
_buttonArray[1]->setLabel("Pause Channel #2");
_buttonArray[1]->setCmd(kPauseChannel2);
_mixer->pauseHandle(_h2, false);
break;
case kPlayChannel3:
_buttonArray[2]->setLabel("Pause Channel #3");
_buttonArray[2]->setCmd(kPauseChannel3);
_mixer->pauseHandle(_h3, false);
break;
case kPauseChannel1:
_buttonArray[0]->setLabel("Play Channel #1");
_buttonArray[0]->setCmd(kPlayChannel1);
_mixer->pauseHandle(_h1, true);
break;
case kPauseChannel2:
_buttonArray[1]->setLabel("Play Channel #2");
_buttonArray[1]->setCmd(kPlayChannel2);
_mixer->pauseHandle(_h2, true);
break;
case kPauseChannel3:
_buttonArray[2]->setLabel("Play Channel #3");
_buttonArray[2]->setCmd(kPlayChannel3);
_mixer->pauseHandle(_h3, true);
break;
default:
_mixer->stopAll();
GUI::Dialog::handleCommand(sender, cmd, data);
}
}
bool SoundSubsystem::playBeeps() {
Testsuite::clearScreen();
bool passed = true;
Common::String info = "Testing Sound Output by generating beeps\n"
"You should hear a left beep followed by a right beep\n";
if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) {
Testsuite::logPrintf("Info! Skipping test : Play Beeps\n");
return true;
}
Audio::PCSpeaker *speaker = new Audio::PCSpeaker();
Audio::Mixer *mixer = g_system->getMixer();
Audio::SoundHandle handle;
mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, speaker);
// Left Beep
Testsuite::writeOnScreen("Left Beep", Common::Point(0, 100));
mixer->setChannelBalance(handle, -127);
speaker->play(Audio::PCSpeaker::kWaveFormSine, 1000, -1);
g_system->delayMillis(500);
mixer->pauseHandle(handle, true);
if (Testsuite::handleInteractiveInput("Were you able to hear the left beep?", "Yes", "No", kOptionRight)) {
Testsuite::logDetailedPrintf("Error! Left Beep couldn't be detected : Error with Mixer::setChannelBalance()\n");
passed = false;
}
// Right Beep
Testsuite::writeOnScreen("Right Beep", Common::Point(0, 100));
mixer->setChannelBalance(handle, 127);
mixer->pauseHandle(handle, false);
g_system->delayMillis(500);
mixer->stopAll();
if (Testsuite::handleInteractiveInput("Were you able to hear the right beep?", "Yes", "No", kOptionRight)) {
Testsuite::logDetailedPrintf("Error! Right Beep couldn't be detected : Error with Mixer::setChannelBalance()\n");
passed = false;
}
return passed;
}
bool SoundSubsystem::mixSounds() {
Testsuite::clearScreen();
bool passed = true;
Common::String info = "Testing Mixer Output by generating multichannel sound output using PC speaker emulator.\n"
"The mixer should be able to play them simultaneously\n";
if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) {
Testsuite::logPrintf("Info! Skipping test : Mix Sounds\n");
return true;
}
SoundSubsystemDialog sDialog;
sDialog.runModal();
if (Testsuite::handleInteractiveInput("Was the mixer able to simultaneously play multiple channels?", "Yes", "No", kOptionRight)) {
Testsuite::logDetailedPrintf("Error! Multiple channels couldn't be played : Error with Mixer Class\n");
passed = false;
}
return passed;
}
bool SoundSubsystem::audiocdOutput() {
Testsuite::clearScreen();
bool passed = true;
Common::String info = "Testing AudioCD API implementation.\n"
"Here we have four tracks, we play them in order i.e 1-2-3-last.\n"
"The user should verify if the tracks were run in correct order or not.";
if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) {
Testsuite::logPrintf("Info! Skipping test : AudioCD API\n");
return true;
}
Common::Point pt(0, 100);
Testsuite::writeOnScreen("Playing the tracks of testCD in order i.e 1-2-3-last", pt);
// Make audio-files discoverable
Common::FSNode gameRoot(ConfMan.get("path"));
SearchMan.addSubDirectoryMatching(gameRoot, "audiocd-files");
// Play all tracks
for (int i = 1; i < 5; i++) {
AudioCD.play(i, 1, 0, 0);
while (AudioCD.isPlaying()) {
g_system->delayMillis(500);
Testsuite::writeOnScreen(Common::String::printf("Playing Now: track%02d", i), pt);
}
g_system->delayMillis(500);
}
Testsuite::clearScreen();
if (Testsuite::handleInteractiveInput("Were all the tracks played in order i.e 1-2-3-last ?", "Yes", "No", kOptionRight)) {
Testsuite::logPrintf("Error! Error in AudioCD.play() or probably sound files were not detected, try -d1 (debuglevel 1)\n");
passed = false;
}
return passed;
}
bool SoundSubsystem::sampleRates() {
bool passed = true;
Audio::Mixer *mixer = g_system->getMixer();
Audio::PCSpeaker *s1 = new Audio::PCSpeaker();
// Stream at half sampling rate
Audio::PCSpeaker *s2 = new Audio::PCSpeaker(s1->getRate() - 10000);
// Stream at twice sampling rate
Audio::PCSpeaker *s3 = new Audio::PCSpeaker(s1->getRate() + 10000);
s1->play(Audio::PCSpeaker::kWaveFormSine, 1000, -1);
s2->play(Audio::PCSpeaker::kWaveFormSine, 1000, -1);
s3->play(Audio::PCSpeaker::kWaveFormSine, 1000, -1);
Audio::SoundHandle handle;
Common::Point pt(0, 100);
mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, s1);
Testsuite::writeOnScreen(Common::String::printf("Playing at smaple rate: %d", s1->getRate()), pt);
g_system->delayMillis(1000);
mixer->stopHandle(handle);
g_system->delayMillis(1000);
mixer->playStream(Audio::Mixer::kSpeechSoundType, &handle, s2);
Testsuite::writeOnScreen(Common::String::printf("Playing at sample rate : %d", s2->getRate()), pt);
g_system->delayMillis(1000);
mixer->stopHandle(handle);
g_system->delayMillis(1000);
mixer->playStream(Audio::Mixer::kSFXSoundType, &handle, s3);
Testsuite::writeOnScreen(Common::String::printf("Playing at sample rate : %d", s3->getRate()), pt);
g_system->delayMillis(1000);
mixer->stopHandle(handle);
g_system->delayMillis(1000);
Testsuite::clearScreen();
if (Testsuite::handleInteractiveInput("Was the mixer able to play beeps with variable sample rates?", "Yes", "No", kOptionRight)) {
Testsuite::logDetailedPrintf("Error! Error with variable sample rates\n");
passed = false;
}
return passed;
}
SoundSubsystemTestSuite::SoundSubsystemTestSuite() {
addTest("SimpleBeeps", &SoundSubsystem::playBeeps, true);
addTest("MixSounds", &SoundSubsystem::mixSounds, true);
addTest("AudiocdOutput", &SoundSubsystem::audiocdOutput, true);
addTest("SampleRates", &SoundSubsystem::sampleRates, true);
}
} // End of namespace Testbed

80
engines/testbed/sound.h Normal file
View file

@ -0,0 +1,80 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef TESTBED_SOUND_H
#define TESTBED_SOUND_H
#include "gui/dialog.h"
#include "sound/mixer.h"
#include "testbed/config.h"
#include "testbed/testsuite.h"
namespace Testbed {
class SoundSubsystemDialog : public TestbedInteractionDialog {
public:
SoundSubsystemDialog();
~SoundSubsystemDialog() {}
void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
Audio::Mixer *_mixer;
Audio::SoundHandle _h1, _h2, _h3;
};
namespace SoundSubsystem {
// Helper functions for SoundSubsystem tests
// will contain function declarations for SoundSubsystem tests
bool playBeeps();
bool mixSounds();
bool audiocdOutput();
bool sampleRates();
}
class SoundSubsystemTestSuite : public Testsuite {
public:
/**
* The constructor for the SoundSubsystemTestSuite
* For every test to be executed one must:
* 1) Create a function that would invoke the test
* 2) Add that test to list by executing addTest()
*
* @see addTest()
*/
SoundSubsystemTestSuite();
~SoundSubsystemTestSuite() {}
const char *getName() const {
return "SoundSubsystem";
}
const char *getDescription() const {
return "Sound Subsystem";
}
};
} // End of namespace Testbed
#endif // TESTBED_SOUND_H

View file

@ -0,0 +1,67 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef TESTBED_TEMPLATE_H
#define TESTBED_TEMPLATE_H
#include "testbed/testsuite.h"
// This file can be used as template for header files of other newer testsuites.
namespace Testbed {
namespace XXXtests {
// Helper functions for XXX tests
// will contain function declarations for XXX tests
// add more here
} // End of namespace XXXtests
class XXXTestSuite : public Testsuite {
public:
/**
* The constructor for the XXXTestSuite
* For every test to be executed one must:
* 1) Create a function that would invoke the test
* 2) Add that test to list by executing addTest()
*
* @see addTest()
*/
XXXTestSuite();
~XXXTestSuite() {}
const char *getName() const {
return "Dummy Template";
}
const char *getDescription() const {
return "Some Arbit description";
}
};
} // End of namespace Testbed
#endif // TESTBED_TEMPLATE_H

169
engines/testbed/testbed.cpp Normal file
View file

@ -0,0 +1,169 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "common/debug-channels.h"
#include "common/scummsys.h"
#include "common/system.h"
#include "engines/util.h"
#include "testbed/events.h"
#include "testbed/fs.h"
#include "testbed/graphics.h"
#include "testbed/misc.h"
#include "testbed/savegame.h"
#include "testbed/sound.h"
#include "testbed/testbed.h"
namespace Testbed {
void TestbedExitDialog::init() {
_xOffset = 25;
_yOffset = 0;
Common::String text = "Thank you for using ScummVM testbed! Here are yor summarized results:";
addText(450, 20, text, Graphics::kTextAlignCenter, _xOffset, 15);
Common::Array<Common::String> strArray;
for (Common::Array<Testsuite *>::const_iterator i = _testsuiteList.begin(); i != _testsuiteList.end(); ++i) {
strArray.push_back(Common::String::printf("%s (%d/%d tests failed)", (*i)->getName(), (*i)->getNumTestsFailed(),
(*i)->getNumTestsEnabled()));
}
addList(0, _yOffset, 500, 200, strArray);
text = "More Details can be viewed in the Log file : " + Testsuite::getLogFile();
addText(450, 20, text, Graphics::kTextAlignLeft, 0, 0);
text = "Directory : " + Testsuite::getLogDir();
addText(500, 20, text, Graphics::kTextAlignLeft, 0, 0);
_yOffset += 5;
addButtonXY(_xOffset + 80, _yOffset, 120, 20, "Rerun Tests", kCmdRerunTestbed);
addButtonXY(_xOffset + 240, _yOffset, 60, 20, "Close", GUI::kCloseCmd);
}
void TestbedExitDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kCmdRerunTestbed :
_rerun = true;
GUI::Dialog::close();
default:
GUI::Dialog::handleCommand(sender, cmd, data);
}
}
bool TestbedEngine::hasFeature(EngineFeature f) const {
return (f == kSupportsRTL) ? true : false;
}
TestbedEngine::TestbedEngine(OSystem *syst)
: Engine(syst) {
// Put your engine in a sane state, but do nothing big yet;
// in particular, do not load data from files; rather, if you
// need to do such things, do them from init().
// Do not initialize graphics here
// However this is the place to specify all default directories
DebugMan.addDebugChannel(kTestbedLogOutput, "LOG", "Log of test results generated by testbed");
DebugMan.addDebugChannel(kTestbedEngineDebug, "Debug", "Engine-specific debug statements");
DebugMan.enableDebugChannel("LOG");
// Initialize testsuites here
// GFX
Testsuite *ts = new GFXTestSuite();
_testsuiteList.push_back(ts);
// FS
ts = new FSTestSuite();
_testsuiteList.push_back(ts);
// Savegames
ts = new SaveGameTestSuite();
_testsuiteList.push_back(ts);
// Misc.
ts = new MiscTestSuite();
_testsuiteList.push_back(ts);
// Events
ts = new EventTestSuite();
_testsuiteList.push_back(ts);
// Sound
ts = new SoundSubsystemTestSuite();
_testsuiteList.push_back(ts);
}
TestbedEngine::~TestbedEngine() {
Testsuite::deleteWriteStream();
// Remove all of our debug levels here
DebugMan.clearAllDebugChannels();
for (Common::Array<Testsuite *>::const_iterator i = _testsuiteList.begin(); i != _testsuiteList.end(); ++i) {
delete (*i);
}
}
void TestbedEngine::invokeTestsuites(TestbedConfigManager &cfMan) {
Common::Array<Testsuite *>::const_iterator iter;
uint count = 1;
Common::Point pt = Testsuite::getDisplayRegionCoordinates();
int numSuitesEnabled = cfMan.getNumSuitesEnabled();
for (iter = _testsuiteList.begin(); iter != _testsuiteList.end(); iter++) {
(*iter)->reset();
if ((*iter)->isEnabled()) {
Testsuite::updateStats("Testsuite", (*iter)->getName(), count++, numSuitesEnabled, pt);
(*iter)->execute();
}
}
}
Common::Error TestbedEngine::run() {
// Initialize graphics using following:
initGraphics(320, 200, false);
// As of now we are using GUI::MessageDialog for interaction, Test if it works.
// interactive mode could also be modified by a config parameter "non-interactive=1"
// TODO: Implement that
TestbedConfigManager cfMan(_testsuiteList, "testbed.config");
// Keep running if rerun requested
TestbedExitDialog tbDialog(_testsuiteList);
do {
Testsuite::clearEntireScreen();
cfMan.selectTestsuites();
// Init logging
Testsuite::initLogging(true);
// Check if user wanted to exit.
if (Engine::shouldQuit()) {
return Common::kNoError;
}
invokeTestsuites(cfMan);
tbDialog.init();
tbDialog.run();
} while (tbDialog.rerunRequired());
return Common::kNoError;
}
} // End of namespace Testbed

85
engines/testbed/testbed.h Normal file
View file

@ -0,0 +1,85 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef TESTBED_H
#define TESTBED_H
#include "engines/engine.h"
#include "gui/options.h"
#include "testbed/config.h"
#include "testbed/testsuite.h"
namespace Testbed {
class TestbedConfigManager;
enum {
kTestbedLogOutput = 1 << 0,
kTestbedEngineDebug = 1 << 2,
kCmdRerunTestbed = 'crtb'
};
class TestbedEngine : public Engine {
public:
TestbedEngine(OSystem *syst);
~TestbedEngine();
virtual Common::Error run();
/**
* Invokes configured testsuites.
*/
void invokeTestsuites(TestbedConfigManager &cfMan);
bool hasFeature(EngineFeature f) const;
private:
Common::Array<Testsuite *> _testsuiteList;
};
class TestbedExitDialog : public TestbedInteractionDialog {
public:
TestbedExitDialog(Common::Array<Testsuite *> &testsuiteList) : TestbedInteractionDialog(80, 60, 500, 320), _rerun(false),
_testsuiteList(testsuiteList) {}
~TestbedExitDialog() {}
void init();
void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
void run() { runModal(); }
bool rerunRequired() {
if (_rerun) {
_rerun = false;
return true;
}
return false;
}
private:
bool _rerun;
Common::Array<Testsuite *> &_testsuiteList;
};
} // End of namespace Testbed
#endif // TESTBED_H

View file

@ -0,0 +1,373 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "common/config-manager.h"
#include "common/events.h"
#include "common/stream.h"
#include "graphics/fontman.h"
#include "graphics/surface.h"
#include "gui/message.h"
#include "testbed/graphics.h"
#include "testbed/testbed.h"
#include "testbed/testsuite.h"
namespace Testbed {
// Static public variable of Testsuite
bool Testsuite::isSessionInteractive = true;
// Static private variable of Testsuite
Common::String Testsuite::_logDirectory = "";
Common::String Testsuite::_logFilename = "";
Graphics::FontManager::FontUsage Testsuite::_displayFont = Graphics::FontManager::kGUIFont;
Common::WriteStream *Testsuite::_ws = 0;
uint Testsuite::toQuit = kLoopNormal;
void Testsuite::setLogDir(const char *dirname) {
_logDirectory = dirname;
}
void Testsuite::setLogFile(const char *filename) {
_logFilename = filename;
}
void Testsuite::deleteWriteStream() {
if (_ws) {
delete _ws;
}
}
void Testsuite::initLogging(const char *logdir, const char *filename, bool enable) {
setLogDir(logdir);
setLogFile(filename);
if (enable) {
_ws = Common::FSNode(_logDirectory).getChild(_logFilename).createWriteStream();
} else {
_ws = 0;
}
}
void Testsuite::initLogging(bool enable) {
setLogDir(ConfMan.get("path").c_str());
setLogFile("testbed.log");
if (enable) {
_ws = Common::FSNode(_logDirectory).getChild(_logFilename).createWriteStream();
} else {
_ws = 0;
}
}
void Testsuite::logPrintf(const char *fmt, ...) {
// Assuming log message size to be not greater than STRINGBUFLEN i.e 256
char buffer[STRINGBUFLEN];
va_list vl;
va_start(vl, fmt);
vsnprintf(buffer, STRINGBUFLEN, fmt, vl);
va_end(vl);
if (_ws) {
_ws->writeString(buffer);
debugCN(kTestbedLogOutput, "%s", buffer);
} else {
debugCN(kTestbedLogOutput, "%s", buffer);
}
}
void Testsuite::logDetailedPrintf(const char *fmt, ...) {
// Assuming log message size to be not greater than STRINGBUFLEN i.e 256
// Messages with this function would only be displayed if -d1 is specified on command line
char buffer[STRINGBUFLEN];
va_list vl;
va_start(vl, fmt);
vsnprintf(buffer, STRINGBUFLEN, fmt, vl);
va_end(vl);
if (_ws) {
_ws->writeString(buffer);
debugCN(1, kTestbedLogOutput, "%s", buffer);
} else {
debugCN(1, kTestbedLogOutput, "%s", buffer);
}
}
Testsuite::Testsuite() {
_numTestsPassed = 0;
_numTestsExecuted = 0;
// Initially all testsuites are enabled, disable them by calling enableTestSuite(name, false)
_isTsEnabled = true;
// Set custom color for progress bar
GFXTestSuite::setCustomColor(0, 0, 0);
}
Testsuite::~Testsuite() {
for (Common::Array<Test *>::iterator i = _testsToExecute.begin(); i != _testsToExecute.end(); ++i) {
delete (*i);
}
}
void Testsuite::reset() {
_numTestsPassed = 0;
_numTestsExecuted = 0;
toQuit = kLoopNormal;
for (Common::Array<Test *>::iterator i = _testsToExecute.begin(); i != _testsToExecute.end(); ++i) {
(*i)->passed = false;
}
}
void Testsuite::genReport() const {
logPrintf("\n");
logPrintf("Consolidating results...\n");
logPrintf("Subsystem: %s ", getName());
logPrintf("(Tests Executed: %d)\n", _numTestsExecuted);
logPrintf("Passed: %d ", _numTestsPassed);
logPrintf("Failed: %d\n", getNumTestsFailed());
logPrintf("\n");
}
bool Testsuite::handleInteractiveInput(const Common::String &textToDisplay, const char *opt1, const char *opt2, OptionSelected result) {
GUI::MessageDialog prompt(textToDisplay, opt1, opt2);
return prompt.runModal() == result ? true : false;
}
void Testsuite::displayMessage(const Common::String &textToDisplay, const char *defaultButton, const char *altButton) {
GUI::MessageDialog prompt(textToDisplay, defaultButton);
prompt.runModal();
}
Common::Rect Testsuite::writeOnScreen(const Common::String &textToDisplay, const Common::Point &pt, bool flag) {
const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont));
uint fillColor = kColorBlack;
uint textColor = kColorWhite;
Graphics::Surface *screen = g_system->lockScreen();
int height = font.getFontHeight();
int width = screen->w;
Common::Rect rect(pt.x, pt.y, pt.x + width, pt.y + height);
if (flag) {
Graphics::PixelFormat pf = g_system->getScreenFormat();
fillColor = pf.RGBToColor(0, 0, 0);
textColor = pf.RGBToColor(255, 255, 255);
}
screen->fillRect(rect, fillColor);
font.drawString(screen, textToDisplay, rect.left, rect.top, screen->w, textColor, Graphics::kTextAlignCenter);
g_system->unlockScreen();
g_system->updateScreen();
return rect;
}
void Testsuite::clearScreen(const Common::Rect &rect) {
Graphics::Surface *screen = g_system->lockScreen();
screen->fillRect(rect, kColorBlack);
g_system->unlockScreen();
g_system->updateScreen();
}
void Testsuite::clearScreen() {
int numBytesPerLine = g_system->getWidth() * g_system->getScreenFormat().bytesPerPixel;
int height = getDisplayRegionCoordinates().y;
// Don't clear test info display region
int size = height * numBytesPerLine;
byte *buffer = new byte[size];
memset(buffer, 0, size);
g_system->copyRectToScreen(buffer, numBytesPerLine, 0, 0, g_system->getWidth(), height);
g_system->updateScreen();
delete[] buffer;
}
void Testsuite::clearScreen(bool flag) {
Graphics::Surface *screen = g_system->lockScreen();
uint fillColor = kColorBlack;
if (flag) {
fillColor = g_system->getScreenFormat().RGBToColor(0, 0, 0);
}
screen->fillRect(Common::Rect(0, 0, g_system->getWidth(), g_system->getHeight()), fillColor);
g_system->unlockScreen();
g_system->updateScreen();
}
void Testsuite::addTest(const Common::String &name, InvokingFunction f, bool isInteractive) {
Test *featureTest = new Test(name, f, isInteractive);
_testsToExecute.push_back(featureTest);
}
int Testsuite::getNumTestsEnabled() {
int count = 0;
Common::Array<Test *>::const_iterator iter;
if (!isEnabled()) {
return 0;
}
for (iter = _testsToExecute.begin(); iter != _testsToExecute.end(); iter++) {
if ((*iter)->enabled) {
count++;
}
}
return count;
}
uint Testsuite::parseEvents() {
uint startTime = g_system->getMillis();
uint end = startTime + kEventHandlingTime;
do {
Common::Event ev;
while (g_system->getEventManager()->pollEvent(ev)) {
switch (ev.type) {
case Common::EVENT_KEYDOWN:
if (ev.kbd.keycode == Common::KEYCODE_ESCAPE) {
return kSkipNext;
}
break;
case Common::EVENT_QUIT:
case Common::EVENT_RTL:
return kEngineQuit;
break;
default:
break;
}
}
g_system->delayMillis(10);
startTime = g_system->getMillis();
} while (startTime <= end);
return kLoopNormal;
}
void Testsuite::updateStats(const char *prefix, const char *info, uint testNum, uint numTests, Common::Point pt) {
Common::String text = Common::String::printf(" Running %s: %s (%d of %d) ", prefix, info, testNum, numTests);
writeOnScreen(text, pt);
uint barColor = kColorSpecial;
// below the text a rectangle denoting the progress in the testsuite can be drawn.
int separation = getLineSeparation();
pt.y += separation;
int wRect = 200;
int lRect = 7;
pt.x = g_system->getWidth() / 2 - 100;
byte *buffer = new byte[lRect * wRect];
memset(buffer, 0, sizeof(byte) * lRect * wRect);
int wShaded = (int) (wRect * (((float)testNum) / numTests));
// draw the boundary
memset(buffer, barColor, sizeof(byte) * wRect);
memset(buffer + (wRect * (lRect - 1)) , barColor, sizeof(byte) * wRect);
for (int i = 0; i < lRect; i++) {
for (int j = 0; j < wRect; j++) {
if (j < wShaded) {
buffer[i * wRect + j] = barColor;
}
}
buffer[i * wRect + 0] = barColor;
buffer[i * wRect + wRect - 1] = barColor;
}
g_system->copyRectToScreen(buffer, wRect, pt.x, pt.y, wRect, lRect);
g_system->updateScreen();
delete[] buffer;
}
bool Testsuite::enableTest(const Common::String &testName, bool toEnable) {
for (uint i = 0; i < _testsToExecute.size(); i++) {
if (_testsToExecute[i]->featureName.equalsIgnoreCase(testName)) {
_testsToExecute[i]->enabled = toEnable;
return true;
}
}
return false;
}
void Testsuite::execute() {
// Main Loop for a testsuite
// Do nothing if meant to exit
if (toQuit == kEngineQuit) {
return;
}
uint count = 0;
Common::Point pt = getDisplayRegionCoordinates();
pt.y += getLineSeparation();
int numEnabledTests = getNumTestsEnabled();
for (Common::Array<Test *>::iterator i = _testsToExecute.begin(); i != _testsToExecute.end(); ++i) {
if (!(*i)->enabled) {
logPrintf("Info! Skipping Test: %s, Skipped by configuration.\n", ((*i)->featureName).c_str());
continue;
}
if (toQuit == kSkipNext) {
logPrintf("Info! Skipping Test: %s, Skipped by user.\n", ((*i)->featureName).c_str());
toQuit = kLoopNormal;
continue;
}
if((*i)->isInteractive && !isSessionInteractive) {
logPrintf("Info! Skipping Test: %s, non-interactive environment is selected\n", ((*i)->featureName).c_str());
continue;
}
logPrintf("Info! Executing Test: %s\n", ((*i)->featureName).c_str());
updateStats("Test", ((*i)->featureName).c_str(), count++, numEnabledTests, pt);
_numTestsExecuted++;
if ((*i)->driver()) {
logPrintf("Result: Passed\n");
_numTestsPassed++;
} else {
logPrintf("Result: Failed\n");
}
updateStats("Test", ((*i)->featureName).c_str(), count, numEnabledTests, pt);
// TODO: Display a screen here to user with details of upcoming test, he can skip it or Quit or RTL
// Check if user wants to quit/RTL/Skip next test by parsing events.
// Quit directly if explicitly requested
if (Engine::shouldQuit()) {
toQuit = kEngineQuit;
genReport();
return;
}
toQuit = parseEvents();
}
genReport();
}
} // End of namespace Testebed

214
engines/testbed/testsuite.h Normal file
View file

@ -0,0 +1,214 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef TESTBED_TESTSUITE_H
#define TESTBED_TESTSUITE_H
#include "common/system.h"
#include "common/str.h"
#include "common/array.h"
#include "graphics/fontman.h"
namespace Testbed {
enum {
kColorBlack = 0,
kColorWhite = 1,
kColorCustom = 2,
kColorSpecial = 5 ///< some random number
};
enum OptionSelected {
kOptionLeft = 1,
kOptionRight = 0
};
enum {
kEngineQuit = 0,
kSkipNext = 1,
kLoopNormal = 2,
// Event handling time,(in ms) used in parseEvent()
kEventHandlingTime = 50
};
typedef bool (*InvokingFunction)();
/**
* This represents a feature to be tested
*/
struct Test {
Test(Common::String name, InvokingFunction f, bool interactive) : featureName(name) {
driver = f;
enabled = true;
passed = false;
isInteractive = interactive;
}
const Common::String featureName; ///< Name of feature to be tested
InvokingFunction driver; ///< Pointer to the function that will invoke this feature test
bool enabled; ///< Decides whether or not this test is to be executed
bool passed; ///< Collects and stores result of this feature test
bool isInteractive; ///< Decides if the test is interactive or not, An interactive testsuite may have non-interactive tests, hence this change.
};
/**
* The basic Testsuite class
* All the other testsuites would inherit it and override its virtual methods
*/
class Testsuite {
public:
Testsuite();
virtual ~Testsuite();
int getNumTests() const { return _testsToExecute.size(); }
int getNumTestsPassed() const { return _numTestsPassed; }
int getNumTestsFailed() const { return _numTestsExecuted - _numTestsPassed; }
void genReport() const;
bool isEnabled() const { return _isTsEnabled; }
virtual void enable(bool flag) {
_isTsEnabled = flag;
}
bool enableTest(const Common::String &testName, bool enable);
void reset();
/**
* Prompts for User Input in form of "Yes" or "No" for interactive tests
* e.g: "Is this like you expect?" "Yes" or "No"
*
* @param textToDisplay Display text
* @return true if "Yes" false otherwise
*/
static bool handleInteractiveInput(const Common::String &textToDisplay, const char *opt1 = "Yes", const char *opt2 = "No", OptionSelected result = kOptionLeft);
static void displayMessage(const Common::String &textToDisplay, const char *defaultButton = "OK", const char *altButton = 0);
static Common::Rect writeOnScreen(const Common::String &textToDisplay, const Common::Point &pt, bool flag = false);
static void clearScreen(const Common::Rect &rect);
static void clearEntireScreen() {
const int width = g_system->getWidth();
const int height = g_system->getHeight();
Common::Rect r(0, 0, width, height);
clearScreen(r);
}
static void clearScreen();
static void clearScreen(bool flag);
/**
* Adds a test to the list of tests to be executed
*
* @param name the string description of the test, for display purposes
* @param f pointer to the function that invokes this test
* @param isInteractive decides if the test is to be executed in interactive mode/ default true
*/
void addTest(const Common::String &name, InvokingFunction f, bool isInteractive = true);
/**
* The driver function for the testsuite
* All code should go in here.
*/
virtual void execute();
static uint parseEvents();
virtual const char *getName() const = 0;
virtual const char *getDescription() const = 0;
static void logPrintf(const char *s, ...) GCC_PRINTF(1, 2);
static void logDetailedPrintf(const char *s, ...) GCC_PRINTF(1, 2);
/**
* Note: To enable logging, this function must be called once first.
*/
static void initLogging(const char *dirname, const char *filename, bool enable = true);
static void initLogging(bool enable = true);
static void setLogDir(const char *dirname);
static void setLogFile(const char *filename);
static Common::String getLogDir() { return _logDirectory; }
static Common::String getLogFile() { return _logFilename; }
static void deleteWriteStream();
// Progress bar (Information Display) related methods.
/**
* Display region is in the bottom. Probably 1/4th of the game screen.
* It contains:
* 1) Information about executing testsuite.
* 2) Total progress within this testsuite.
* 3) Total overall progress in the number of testsuites
*/
static Common::Point getDisplayRegionCoordinates() {
Common::Point pt(0, 0);
// start from bottom
pt.y = g_system->getHeight();
// Will Contain 3 lines
pt.y -= (FontMan.getFontByUsage(_displayFont)->getFontHeight() * 3 + 15); // Buffer of 5 pixels per line
return pt;
}
static uint getLineSeparation() {
return FontMan.getFontByUsage(_displayFont)->getFontHeight() + 5;
}
static Graphics::FontManager::FontUsage getCurrentFontUsageType() { return _displayFont; }
static void setCurrentFontUsageType(Graphics::FontManager::FontUsage f) { _displayFont = f; }
static void updateStats(const char *prefix, const char *info, uint numTests, uint testNum, Common::Point pt);
const Common::Array<Test *>& getTestList() { return _testsToExecute; }
int getNumTestsEnabled();
protected:
Common::Array<Test *> _testsToExecute; ///< List of tests to be executed
int _numTestsPassed; ///< Number of tests passed
int _numTestsExecuted; ///< Number of tests executed
bool _isTsEnabled;
public:
/**
* Static variable of this class that determines if the user initiated testing session is interactive or not.
* Used by various tests to respond accordingly
*/
static bool isSessionInteractive;
/**
* Used from the code to decide if the engine needs to exit
*/
static uint toQuit;
private:
/**
* Private variables related to logging files
*/
static Common::String _logDirectory;
static Common::String _logFilename;
static Common::WriteStream *_ws;
/**
* Private variable used for font
*/
static Graphics::FontManager::FontUsage _displayFont;
};
} // End of namespace Testbed
#endif // TESTBED_TESTSUITE_H