diff options
Diffstat (limited to 'engines/testbed')
-rw-r--r-- | engines/testbed/detection.cpp | 95 | ||||
-rw-r--r-- | engines/testbed/gfxtests.cpp | 140 | ||||
-rw-r--r-- | engines/testbed/gfxtests.h | 15 | ||||
-rw-r--r-- | engines/testbed/graphics.cpp | 51 | ||||
-rw-r--r-- | engines/testbed/graphics.h | 37 | ||||
-rw-r--r-- | engines/testbed/module.mk | 18 | ||||
-rw-r--r-- | engines/testbed/testbed.cpp | 73 | ||||
-rw-r--r-- | engines/testbed/testbed.h | 18 | ||||
-rw-r--r-- | engines/testbed/testsuite.h | 144 |
9 files changed, 591 insertions, 0 deletions
diff --git a/engines/testbed/detection.cpp b/engines/testbed/detection.cpp new file mode 100644 index 0000000000..317b9e7dbd --- /dev/null +++ b/engines/testbed/detection.cpp @@ -0,0 +1,95 @@ +#include "testbed/testbed.h" + +#include "common/config-manager.h" +#include "common/error.h" +#include "common/fs.h" + +#include "engines/metaengine.h" + +static const PlainGameDescriptor testbed_setting[] = { + { "testbed", "TestBed: The backend testing framework" }, + { 0, 0 } +}; + +class TestbedMetaEngine : public MetaEngine { +public: + virtual const char *getName() const { + return "TestBed: The backend testing framework"; + } + + virtual const char *getOriginalCopyright() const { + return "Copyright (C) ScummVM"; + } + + virtual GameList getSupportedGames() const { + GameList games; + const PlainGameDescriptor *g = testbed_setting; + while (g->gameid) { + games.push_back(*g); + g++; + } + + return games; + } + + virtual GameDescriptor findGame(const char *gameid) const { + const PlainGameDescriptor *g = testbed_setting; + while (g->gameid) { + if (0 == scumm_stricmp(gameid, g->gameid)) + break; + g++; + } + return GameDescriptor(g->gameid, g->description); + } + + virtual GameList detectGames(const Common::FSList &fslist) const { + GameList detectedGames; + + // Iterate over all files in the given directory + for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { + if (!file->isDirectory()) { + const char *gameName = file->getName().c_str(); + + if (0 == scumm_stricmp("README", gameName)) { + // You could check the contents of the file now if you need to. + detectedGames.push_back(testbed_setting[0]); + break; + } + } + } + return detectedGames; + } + + virtual Common::Error createInstance(OSystem *syst, Engine **engine) const { + assert(syst); + assert(engine); + + // Scan the target directory for files (error out if it does not exist) + Common::FSList fslist; + Common::FSNode dir(ConfMan.get("path")); + if (!dir.getChildren(fslist, Common::FSNode::kListAll)) { + return Common::kInvalidPathError; + } + + // Invoke the detector + Common::String gameid = ConfMan.get("gameid"); + GameList detectedGames = detectGames(fslist); + + for (uint i = 0; i < detectedGames.size(); i++) { + if (detectedGames[i].gameid() == gameid) { + // At this point you may want to perform additional sanity checks. + *engine = new Testbed::TestbedEngine(syst); + return Common::kNoError; + } + } + + // Failed to find any game data + return Common::kNoGameDataFoundError; + } +}; + +#if PLUGIN_ENABLED_DYNAMIC(TESTBED) + REGISTER_PLUGIN_DYNAMIC(TESTBED, PLUGIN_TYPE_ENGINE, TestbedMetaEngine); +#else + REGISTER_PLUGIN_STATIC(TESTBED, PLUGIN_TYPE_ENGINE, TestbedMetaEngine); +#endif diff --git a/engines/testbed/gfxtests.cpp b/engines/testbed/gfxtests.cpp new file mode 100644 index 0000000000..2eeb7125b2 --- /dev/null +++ b/engines/testbed/gfxtests.cpp @@ -0,0 +1,140 @@ +#include "testbed/gfxtests.h" +#include "testbed/graphics.h" +#include "testbed/testsuite.h" + +#include "graphics/fontman.h" +#include "graphics/surface.h" +#include "graphics/cursorman.h" + +namespace Testbed { + +bool testFullScreenMode() { + + Testsuite::displayMessage("Testing fullscreen mode. \n \ + If the feature is supported by the backend, you should expect to see a toggle between fullscreen and normal modes"); + + Common::Point pt(0,100); + Common::Rect rect = Testsuite::writeOnScreen("Testing fullscreen mode", pt); + + bool isFeaturePresent; + bool isFeatureEnabled; + + isFeaturePresent = g_system->hasFeature(OSystem::kFeatureFullscreenMode); + isFeatureEnabled = g_system->getFeatureState(OSystem::kFeatureFullscreenMode); + g_system->delayMillis(1000); + + if (isFeaturePresent) { + //Toggle + + g_system->beginGFXTransaction(); + g_system->setFeatureState(OSystem::kFeatureFullscreenMode, !isFeatureEnabled); + g_system->endGFXTransaction(); + + g_system->delayMillis(1000); + + g_system->beginGFXTransaction(); + g_system->setFeatureState(OSystem::kFeatureFullscreenMode, isFeatureEnabled); + g_system->endGFXTransaction(); + } + else { + Testsuite::displayMessage("feature not supported"); + } + + Testsuite::clearScreen(rect); + return true; +} + +bool testAspectRatio() { + Testsuite::displayMessage("Testing Aspect Ratio Correction. \n \ + With this feature enabled games running at 320x200 should be scaled upto 320x240 pixels"); + + Common::Point pt(0,100); + Common::Rect rect = Testsuite::writeOnScreen("Testing Aspect ratio correction", pt); + + bool isFeaturePresent; + bool isFeatureEnabled; + + isFeaturePresent = g_system->hasFeature(OSystem::kFeatureAspectRatioCorrection); + isFeatureEnabled = g_system->getFeatureState(OSystem::kFeatureAspectRatioCorrection); + g_system->delayMillis(1000); + + if (isFeaturePresent) { + //Toggle + + g_system->beginGFXTransaction(); + g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, !isFeatureEnabled); + g_system->endGFXTransaction(); + + g_system->delayMillis(1000); + + g_system->beginGFXTransaction(); + g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, isFeatureEnabled); + g_system->endGFXTransaction(); + } + else { + Testsuite::displayMessage("feature not supported"); + } + + Testsuite::clearScreen(rect); + return true; +} + +bool testPalettizedCursors() { + Testsuite::displayMessage("Testing Cursors. You should expect to see a red colored cursor.\n"); + + Common::Point pt(0,100); + Common::Rect rect = Testsuite::writeOnScreen("Testing Palettized Cursors", pt); + + bool isFeaturePresent; + bool isFeatureEnabled; + + isFeaturePresent = g_system->hasFeature(OSystem::kFeatureCursorHasPalette); + isFeatureEnabled = g_system->getFeatureState(OSystem::kFeatureCursorHasPalette); + g_system->delayMillis(1000); + + if (isFeaturePresent) { + byte palette[3 * 4]; // Black, white and yellow + palette[0] = palette[1] = palette[2] = 0; + palette[4] = palette[5] = palette[6] = 255; + palette[8] = palette[9] = 255; + palette[10] = 0; + + byte buffer[10 * 10]; + memset(buffer, 2, 10 * 10); + + CursorMan.pushCursorPalette(palette, 0, 3); + CursorMan.pushCursor(buffer, 10, 10, 40, 40, 2, 1); + CursorMan.showMouse(true); + g_system->updateScreen(); + } + else { + Testsuite::displayMessage("feature not supported"); + } + Testsuite::clearScreen(rect); + return true; +} + +bool testCopyRectToScreen() { + Testsuite::displayMessage("Testing Blitting a Bitmap to screen. \n\ + You should expect to see a 20x40 yellow horizontal rectangle centred at the screen."); + + GFXTestSuite::setCustomColor(255, 255, 0); + byte buffer[20 * 40]; + memset(buffer, 2, 20 * 40); + + uint x = g_system->getWidth() / 2 - 20; + uint y = g_system->getHeight() / 2 - 10; + + g_system->copyRectToScreen(buffer, 40, x, y, 40, 20); + g_system->updateScreen(); + g_system->delayMillis(1000); + + Common::Rect rect(x, y, x+40, y+20); + Testsuite::clearScreen(rect); + + return true; + +} + + +} diff --git a/engines/testbed/gfxtests.h b/engines/testbed/gfxtests.h new file mode 100644 index 0000000000..bd219411e9 --- /dev/null +++ b/engines/testbed/gfxtests.h @@ -0,0 +1,15 @@ +#ifndef GFXTESTS_H +#define GFXTESTS_H + +namespace Testbed { + +// will contain function declarations for GFX tests +bool testFullScreenMode(); +bool testAspectRatio(); +bool testPalettizedCursors(); +bool testCopyRectToScreen(); +// add more here + +} + +#endif diff --git a/engines/testbed/graphics.cpp b/engines/testbed/graphics.cpp new file mode 100644 index 0000000000..ea1c1b1130 --- /dev/null +++ b/engines/testbed/graphics.cpp @@ -0,0 +1,51 @@ +#include "testbed/graphics.h" +#include "testbed/gfxtests.h" + +namespace Testbed { + +byte GFXTestSuite::_palette[3 * 4] = {0, 0, 0, 0, 255, 255, 255, 0, 255, 255, 255, 0}; + +GFXTestSuite::GFXTestSuite() { + // Initialize color palettes + // Te fourth field is for alpha channel which is unused + // Assuming 8bpp as of now + g_system->setPalette(_palette, 0, 3); + g_system->grabPalette(_palette, 0, 3); + + // Add tests here +// addTest("FullScreenMode", &testFullScreenMode); +// addTest("AspectRatio", &testAspectRatio); + addTest("PalettizedCursors", &testPalettizedCursors); +// addTest("BlitBitmaps", &testCopyRectToScreen); +} + +const char *GFXTestSuite::getName() { + return "GFX"; +} + +void GFXTestSuite::setCustomColor(uint r, uint g, uint b) { + _palette[8] = r; + _palette[9] = g; + _palette[10] = b; + g_system->setPalette(_palette, 0, 3); + g_system->grabPalette(_palette, 0, 3); +} + +void GFXTestSuite::execute() { + for (Common::Array<Test*>::iterator i = _testsToExecute.begin(); i != _testsToExecute.end(); ++i) { + printf("Executing Test:%s\n", ((*i)->featureName).c_str()); + // Invoke the test + (*i)->driver(); + _numTestsExecuted++; + // Verify result by Interacting with the tester. + Common::String prompt("Was this similar to what you expected?"); + if (handleInteractiveInput(prompt)) { + _numTestsPassed++; + } + } + + // Report Generation + genReport(); +} + +} diff --git a/engines/testbed/graphics.h b/engines/testbed/graphics.h new file mode 100644 index 0000000000..eb84310db7 --- /dev/null +++ b/engines/testbed/graphics.h @@ -0,0 +1,37 @@ +#ifndef GRAPHICS_H +#define GRAPHICS_H + +#include "testbed/testsuite.h" + +namespace Testbed { + +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(){} + void execute(); + const char *getName(); + 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) + */ + static byte _palette[3 * 4]; +}; + +} // End of namespace Testbed + +#endif diff --git a/engines/testbed/module.mk b/engines/testbed/module.mk new file mode 100644 index 0000000000..0c19aba441 --- /dev/null +++ b/engines/testbed/module.mk @@ -0,0 +1,18 @@ +MODULE := engines/testbed + +MODULE_OBJS := \ + detection.o \ + graphics.o \ + gfxtests.o \ + testbed.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 diff --git a/engines/testbed/testbed.cpp b/engines/testbed/testbed.cpp new file mode 100644 index 0000000000..4d178d80bd --- /dev/null +++ b/engines/testbed/testbed.cpp @@ -0,0 +1,73 @@ +#include "common/scummsys.h" +#include "common/system.h" + +#include "engines/util.h" + +#include "testbed/testbed.h" +#include "testbed/graphics.h" + +namespace Testbed { + +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 + + printf("TestbedEngine::TestbedEngine()\n"); +} + +TestbedEngine::~TestbedEngine() { + // Dispose your resources here + printf("TestbedEngine::~TestbedEngine()\n"); + + // Remove all of our debug levels here +} + +Common::Error TestbedEngine::run() { + // Initialize graphics using following: + initGraphics(320, 200, false); + + // You could use backend transactions directly as an alternative, + // but it isn't recommended, until you want to handle the error values + // from OSystem::endGFXTransaction yourself. + // This is just an example template: + //_system->beginGFXTransaction(); + // // This setup the graphics mode according to users seetings + // initCommonGFX(false); + // + // // Specify dimensions of game graphics window. + // // In this example: 320x200 + // _system->initSize(320, 200); + //FIXME: You really want to handle + //OSystem::kTransactionSizeChangeFailed here + //_system->endGFXTransaction(); + + // Additional setup. + printf("TestbedEngine::init\n"); + + // 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 + + bool interactive; + 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 are seeing this correctly, it means interactive tests would run on this system :)"); + interactive = Testsuite::handleInteractiveInput(prompt); + + if (interactive) { + printf("Running tests in Interactive Mode\n"); + // Executing GFX Tests + GFXTestSuite ts; + ts.execute(); + } + + return Common::kNoError; +} + +} // End of namespace Testbed diff --git a/engines/testbed/testbed.h b/engines/testbed/testbed.h new file mode 100644 index 0000000000..47ef6adbf3 --- /dev/null +++ b/engines/testbed/testbed.h @@ -0,0 +1,18 @@ +#ifndef TESTBED_H +#define TESTBED_H + +#include "engines/engine.h" + +namespace Testbed { + +class TestbedEngine : public Engine { +public: + TestbedEngine(OSystem *syst); + ~TestbedEngine(); + + virtual Common::Error run(); +}; + +} // End of namespace Testbed + +#endif diff --git a/engines/testbed/testsuite.h b/engines/testbed/testsuite.h new file mode 100644 index 0000000000..ffeb2588c4 --- /dev/null +++ b/engines/testbed/testsuite.h @@ -0,0 +1,144 @@ +#ifndef TESTSUITE_H +#define TESTSUITE_H + +#include "common/system.h" +#include "common/str.h" +#include "common/array.h" + +#include "graphics/fontman.h" +#include "graphics/surface.h" + +#include "gui/message.h" + +namespace Testbed { + +enum { + kColorBlack = 0, + kColorWhite = 1, + kColorCustom = 2 +}; + +typedef bool (*invokingFunction)(); + +/** + * This represents a feature to be tested + */ + +struct Test { + Test(Common::String name, invokingFunction f) : featureName(name), driver(f), enabled(true), passed(false) {} + 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 +}; + + +/** + * The basic Testsuite class + * All the other testsuites would inherit it and override its virtual methods + */ + +class Testsuite { +public: + Testsuite() { + _numTestsPassed = 0; + _numTestsExecuted = 0; + } + + virtual ~Testsuite() { + for (Common::Array<Test*>::iterator i = _testsToExecute.begin(); i != _testsToExecute.end(); ++i) { + delete (*i); + } + } + + int getNumTests() { return _testsToExecute.size(); } + int getNumTestsPassed() { return _numTestsPassed; } + int getNumTestsFailed() { return _numTestsExecuted - _numTestsPassed; } + void genReport() { + printf("Subsystem:%s\n",getName()); + printf("Tests executed:%d\n", _numTestsExecuted); + printf("Tests Passed:%d\n", _numTestsPassed); + printf("Tests Failed:%d\n", getNumTestsFailed()); + } + + /** + * 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) { + GUI::MessageDialog prompt(textToDisplay, "Yes", "No"); + return prompt.runModal() == GUI::kMessageOK ? true : false; + } + + static void displayMessage(const Common::String &textToDisplay) { + GUI::MessageDialog prompt(textToDisplay); + prompt.runModal(); + } + + static Common::Rect writeOnScreen(const Common::String &textToDisplay, const Common::Point &pt) { + const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont)); + + 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); + + screen->fillRect(rect, kColorBlack); + font.drawString(screen, textToDisplay, rect.left, rect.top, screen->w, kColorWhite, Graphics::kTextAlignCenter); + + g_system->unlockScreen(); + g_system->updateScreen(); + + return rect; + } + + static void clearScreen(const Common::Rect &rect) { + Graphics::Surface *screen = g_system->lockScreen(); + + screen->fillRect(rect, kColorBlack); + + g_system->unlockScreen(); + g_system->updateScreen(); + } + + /** + * 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 + */ + void addTest(const Common::String &name, invokingFunction f) { + Test* featureTest = new Test(name, f); + _testsToExecute.push_back(featureTest); + } + + /** + * The driver function for the testsuite + * All code should go in here. + */ + virtual void execute() { + for (Common::Array<Test*>::iterator i = _testsToExecute.begin(); i != _testsToExecute.end(); ++i) { + printf("Executing Test:%s\n", ((*i)->featureName).c_str()); + _numTestsExecuted++; + if ((*i)->driver()) { + _numTestsPassed++; + } + } + genReport(); + } + virtual const char *getName() = 0; + +protected: + Common::Array<Test*> _testsToExecute; ///< List of tests to be executed + int _numTestsPassed; ///< Number of tests passed + int _numTestsExecuted; ///< Number of tests executed +}; + +} // End of namespace testbed + +#endif |