irrlicht/tests/main.cpp

261 lines
6.5 KiB
C++

// Copyright (C) 2008-2012 Colin MacDonald and Christian Stehno
// No rights reserved: this software is in the public domain.
// This is the entry point for the Irrlicht test suite.
// This is an MSVC pragma to link against the Irrlicht library.
// Other builds must link against it in the project files.
#if defined(_MSC_VER)
#pragma comment(lib, "Irrlicht.lib")
#define _CRT_SECURE_NO_WARNINGS 1
#endif // _MSC_VER
#include "testUtils.h"
#include <stdio.h>
#include <time.h>
#include <vector>
struct STestDefinition
{
//! The test entry point function
bool(*testSignature)(void);
//! A descriptive name for the test
const char * testName;
};
//! This is the main entry point for the Irrlicht test suite.
/** \return The number of test that failed, i.e. 0 is success. */
int main(int argumentCount, char * arguments[])
{
if(argumentCount > 3)
{
logTestString("\nUsage: %s [testNumber] [testCount]\n");
return 9999;
}
#define TEST(x)\
{\
extern bool x(void);\
STestDefinition newTest;\
newTest.testSignature = x;\
newTest.testName = #x;\
tests.push_back(newTest);\
}
// Use an STL vector so that we don't rely on Irrlicht.
std::vector<STestDefinition> tests;
#if 0
// To interactively debug a test, move it (temporarily) in here and enable the define to only run this test
// Otherwise debugging is slightly tricky as each test runs in it's own process.
TEST(ioScene);
#else
TEST(disambiguateTextures); // Normally you should run this first, since it validates the working directory.
// Now the simple tests without device
TEST(testIrrArray);
TEST(testIrrMap);
TEST(testIrrList);
TEST(exports);
TEST(irrCoreEquals);
TEST(testIrrString);
TEST(testLine2d);
TEST(matrixOps);
TEST(testDimension2d);
TEST(testVector2d);
TEST(testVector3d);
TEST(testQuaternion);
TEST(testS3DVertex);
TEST(testaabbox3d);
TEST(color);
TEST(testTriangle3d);
TEST(vectorPositionDimension2d);
// file system checks (with null driver)
TEST(filesystem);
TEST(archiveReader);
TEST(testXML);
TEST(serializeAttributes);
// null driver
TEST(fast_atof);
TEST(loadTextures);
TEST(collisionResponseAnimator);
TEST(enumerateImageManipulators);
TEST(removeCustomAnimator);
TEST(sceneCollisionManager);
TEST(sceneNodeAnimator);
TEST(meshLoaders);
TEST(testTimer);
TEST(testCoreutil);
// software drivers only
TEST(softwareDevice);
TEST(b3dAnimation);
TEST(burningsVideo);
TEST(billboards);
TEST(createImage);
TEST(cursorSetVisible);
TEST(flyCircleAnimator);
TEST(guiDisabledMenu);
TEST(makeColorKeyTexture);
TEST(md2Animation);
TEST(meshTransform);
TEST(skinnedMesh);
TEST(testGeometryCreator);
TEST(writeImageToFile);
TEST(ioScene);
// all driver checks
TEST(videoDriver);
TEST(screenshot);
TEST(drawPixel);
TEST(drawRectOutline);
TEST(drawVertexPrimitive);
TEST(material);
TEST(renderTargetTexture);
TEST(textureFeatures);
TEST(textureRenderStates);
TEST(transparentMaterials);
TEST(userclipplane);
TEST(antiAliasing);
TEST(draw2DImage);
TEST(lights);
TEST(twodmaterial);
TEST(viewPort);
TEST(mrt);
TEST(projectionMatrix);
// large scenes/long rendering
TEST(orthoCam);
TEST(stencilShadow);
// q3 maps are slow
TEST(planeMatrix);
TEST(terrainSceneNode);
TEST(lightMaps);
TEST(triangleSelector);
TEST(line2DTest);
#endif
unsigned int numberOfTests = tests.size();
unsigned int testToRun = 0;
unsigned int fails = 0;
bool firstRun=true;
const bool spawn=false;
// args: [testNumber] [testCount]
if(argumentCount > 1)
{
if (!strcmp(arguments[1],"--list"))
{
for (unsigned int i=0; i<tests.size(); ++i)
{
logTestString("%3d: %s\n", i, tests[i].testName);
}
logTestString("\n");
return 0;
}
int tmp = atoi(arguments[1]);
firstRun = (tmp>=0);
testToRun=abs(tmp);
if (!firstRun)
testToRun -= 1;
if(argumentCount > 2)
{
numberOfTests = testToRun + abs(atoi(arguments[2]));
if (numberOfTests>=tests.size())
numberOfTests=tests.size();
}
}
if(testToRun >= numberOfTests)
{
logTestString("\nError: invalid test %d (maximum %d)\n",
testToRun, numberOfTests-testToRun);
return 9999;
}
const unsigned int testCount = numberOfTests-testToRun;
const bool logFileOpened = openTestLog(firstRun);
assert(logFileOpened);
if (firstRun)
{
if (numberOfTests)
{
for (unsigned int i=testToRun; i<numberOfTests; ++i)
{
logTestString("\nStarting test %d, '%s'\n",
i, tests[i].testName);
if (spawn)
{
closeTestLog();
char runNextTest[256];
(void)sprintf(runNextTest, "\"%s\" -%d 1", arguments[0], i+1);
// Spawn the next test in a new process.
if (system(runNextTest))
{
(void)openTestLog(false);
logTestString("\n******** Test failure ********\n"\
"Test %d '%s' failed\n"\
"******** Test failure ********\n",
i, tests[i].testName);
++fails;
}
else
(void)openTestLog(false);
}
else
{
if (!tests[i].testSignature())
{
logTestString("\n******** Test failure ********\n"\
"Test %d '%s' failed\n"\
"******** Test failure ********\n",
i, tests[i].testName);
++fails;
}
}
}
}
const int passed = testCount - fails;
logTestString("\nTests finished. %d test%s of %d passed.\n\n",
passed, 1 == passed ? "" : "s", testCount);
if(0 == fails && testCount==tests.size())
{
time_t rawtime;
struct tm * timeinfo;
(void)time(&rawtime);
timeinfo = gmtime(&rawtime);
(void)printf("\nTest suite pass at GMT %s\n", asctime(timeinfo));
FILE * testsLastPassedAtFile = fopen("tests-last-passed-at.txt", "w");
if(testsLastPassedAtFile)
{
(void)fprintf(testsLastPassedAtFile, "Tests finished. %d test%s of %d passed.\n",
passed, 1 == passed ? "" : "s", numberOfTests);
#ifdef _DEBUG
(void)fprintf(testsLastPassedAtFile, "Compiled as DEBUG\n");
#else
(void)fprintf(testsLastPassedAtFile, "Compiled as RELEASE\n");
#endif
(void)fprintf(testsLastPassedAtFile, "Test suite pass at GMT %s\n", asctime(timeinfo));
(void)fclose(testsLastPassedAtFile);
}
}
closeTestLog();
#ifdef _IRR_WINDOWS_
(void)system("tests.log");
#else
(void)system("$PAGER tests.log");
#endif
return fails;
}
else
{
const bool res = tests[testToRun].testSignature();
closeTestLog();
return res?0:1;
}
}