Refactor/fix test lib harness, assert and log component; add harness driver; port platform suite from GSOC code

This commit is contained in:
Andreas Schiffler 2012-12-14 23:05:34 -08:00
parent dfe7f2bc59
commit a6185d6ad9
10 changed files with 907 additions and 94 deletions

View file

@ -49,9 +49,13 @@ extern "C" {
/* *INDENT-ON* */ /* *INDENT-ON* */
#endif #endif
/* Function prototypes */ /* Global definitions */
/* ADD STUFF HERE */ /*
* Note: Maximum size of SDLTest log message is less than SDLs limit
* to ensure we can fit additional information such as the timestamp.
*/
#define SDLTEST_MAX_LOGMESSAGE_LENGTH 3584
/* Ends C function definitions when using C++ */ /* Ends C function definitions when using C++ */
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -60,17 +60,24 @@ extern "C" {
* \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0). * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0).
* \param assertDescription Message to log with the assert describing it. * \param assertDescription Message to log with the assert describing it.
*/ */
void SDLTest_Assert(int assertCondition, char *assertDescription); void SDLTest_Assert(int assertCondition, char *assertDescription, ...);
/** /**
* \brief Assert for test cases that logs but does not break execution flow on failures. * \brief Assert for test cases that logs but does not break execution flow on failures. Updates assertion counters.
* *
* \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0). * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0).
* \param assertDescription Message to log with the assert describing it. * \param assertDescription Message to log with the assert describing it.
* *
* \returns Returns the assertCondition so it can be used to externall to break execution flow if desired. * \returns Returns the assertCondition so it can be used to externally to break execution flow if desired.
*/ */
int SDLTest_AssertCheck(int assertCondition, char *assertDescription); int SDLTest_AssertCheck(int assertCondition, char *assertDescription, ...);
/**
* \brief Explicitely pass without checking an assertion condition. Updates assertion counter.
*
* \param assertDescription Message to log with the assert describing it.
*/
void SDLTest_AssertPass(char *assertDescription, ...);
/** /**
* \brief Resets the assert summary counters to zero. * \brief Resets the assert summary counters to zero.

View file

@ -98,6 +98,20 @@ typedef struct SDLTest_TestSuiteReference {
SDLTest_TestCaseTearDownFp testTearDown; SDLTest_TestCaseTearDownFp testTearDown;
} SDLTest_TestSuiteReference; } SDLTest_TestSuiteReference;
/**
* \brief Execute a test suite using the given run seed and execution key.
*
* \param testSuites Suites containing the test case.
* \param userRunSeed Custom run seed provided by user, or NULL to autogenerate one.
* \param userExecKey Custom execution key provided by user, or 0 to autogenerate one.
* \param testIterations Number of iterations to run each test case.
*
* \returns Test run result; 0 when all tests passed, 1 if any tests failed.
*/
int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], char *userRunSeed, Uint64 userExecKey, int testIterations);
/* Ends C function definitions when using C++ */ /* Ends C function definitions when using C++ */
#ifdef __cplusplus #ifdef __cplusplus
/* *INDENT-OFF* */ /* *INDENT-OFF* */

View file

@ -30,10 +30,10 @@
#include "SDL_test.h" #include "SDL_test.h"
/* Assert check message format */ /* Assert check message format */
const char *SDLTest_AssertCheckFmt = "Assert '%s': %s"; const char *SDLTest_AssertCheckFormat = "Assert '%s': %s";
/* Assert summary message format */ /* Assert summary message format */
const char *SDLTest_AssertSummaryFmt = "Assert Summary: Total=%d Passed=%d Failed=%d"; const char *SDLTest_AssertSummaryFormat = "Assert Summary: Total=%d Passed=%d Failed=%d";
/*! \brief counts the failed asserts */ /*! \brief counts the failed asserts */
static Uint32 SDLTest_AssertsFailed = 0; static Uint32 SDLTest_AssertsFailed = 0;
@ -44,31 +44,71 @@ static Uint32 SDLTest_AssertsPassed = 0;
/* /*
* Assert that logs and break execution flow on failures (i.e. for harness errors). * Assert that logs and break execution flow on failures (i.e. for harness errors).
*/ */
void SDLTest_Assert(int assertCondition, char *assertDescription) void SDLTest_Assert(int assertCondition, char *assertDescription, ...)
{ {
SDL_assert((SDLTest_AssertCheck(assertCondition, assertDescription))); va_list list;
char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
// Print assert description into a buffer
memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
va_start(list, assertDescription);
SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, assertDescription, list);
va_end(list);
// Log, then assert and break on failure
SDL_assert((SDLTest_AssertCheck(assertCondition, logMessage)));
} }
/* /*
* Assert that logs but does not break execution flow on failures (i.e. for test cases). * Assert that logs but does not break execution flow on failures (i.e. for test cases).
*/ */
int SDLTest_AssertCheck(int assertCondition, char *assertDescription) int SDLTest_AssertCheck(int assertCondition, char *assertDescription, ...)
{ {
char *fmt = (char *)SDLTest_AssertCheckFmt; va_list list;
char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
char *logFormat = (char *)SDLTest_AssertCheckFormat;
// Print assert description into a buffer
memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
va_start(list, assertDescription);
SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, assertDescription, list);
va_end(list);
// Log pass or fail message
if (assertCondition == ASSERT_FAIL) if (assertCondition == ASSERT_FAIL)
{ {
SDLTest_AssertsFailed++; SDLTest_AssertsFailed++;
SDLTest_LogError(fmt, assertDescription, "Failed"); SDLTest_LogError(logFormat, logMessage, "Failed");
} }
else else
{ {
SDLTest_AssertsPassed++; SDLTest_AssertsPassed++;
SDLTest_Log(fmt, assertDescription, "Passed"); SDLTest_Log(logFormat, logMessage, "Passed");
} }
return assertCondition; return assertCondition;
} }
/*
* Explicitly passing Assert that logs (i.e. for test cases).
*/
void SDLTest_AssertPass(char *assertDescription, ...)
{
va_list list;
char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
char *logFormat = (char *)SDLTest_AssertCheckFormat;
// Print assert description into a buffer
memset(logMessage, 0, SDLTEST_MAX_LOGMESSAGE_LENGTH);
va_start(list, assertDescription);
SDL_vsnprintf(logMessage, SDLTEST_MAX_LOGMESSAGE_LENGTH - 1, assertDescription, list);
va_end(list);
// Log pass message
SDLTest_AssertsPassed++;
SDLTest_Log(logFormat, logMessage, "Pass");
}
/* /*
* Resets the assert summary counters to zero. * Resets the assert summary counters to zero.
*/ */
@ -84,15 +124,15 @@ void SDLTest_ResetAssertSummary()
*/ */
void SDLTest_LogAssertSummary() void SDLTest_LogAssertSummary()
{ {
char *fmt = (char *)SDLTest_AssertSummaryFmt; char *logFormat = (char *)SDLTest_AssertSummaryFormat;
Uint32 totalAsserts = SDLTest_AssertsPassed + SDLTest_AssertsFailed; Uint32 totalAsserts = SDLTest_AssertsPassed + SDLTest_AssertsFailed;
if (SDLTest_AssertsFailed == 0) if (SDLTest_AssertsFailed == 0)
{ {
SDLTest_Log(fmt, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed); SDLTest_Log(logFormat, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed);
} }
else else
{ {
SDLTest_LogError(fmt, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed); SDLTest_LogError(logFormat, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed);
} }
} }

View file

@ -58,7 +58,7 @@ SDLTest_FuzzerInit(Uint64 execKey)
} }
int int
SDLTest_GetInvocationCount() SDLTest_GetFuzzerInvocationCount()
{ {
return fuzzerInvocationCounter; return fuzzerInvocationCounter;
} }

View file

@ -28,11 +28,14 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
/* Assert check message format */
const char *SDLTest_TestCheckFmt = "Test '%s': %s";
/* Invalid test name/description message format */ /* Invalid test name/description message format */
const char *SDLTest_InvalidNameFmt = "(Invalid)"; const char *SDLTest_InvalidNameFormat = "(Invalid)";
/* Log summary message format */
const char *SDLTest_LogSummaryFormat = "%s Summary: Total=%d Passed=%d Failed=%d Skipped=%d";
/* Final result message format */
const char *SDLTest_FinalResultFormat = ">>> %s '%s': %s\n";
/*! \brief Timeout for single test case execution */ /*! \brief Timeout for single test case execution */
static Uint32 SDLTest_TestCaseTimeout = 3600; static Uint32 SDLTest_TestCaseTimeout = 3600;
@ -228,7 +231,7 @@ SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, SDLTest_TestCaseReference
if (!testCase->enabled) if (!testCase->enabled)
{ {
SDLTest_Log((char *)SDLTest_TestCheckFmt, testCase->name, "Skipped"); SDLTest_Log((char *)SDLTest_FinalResultFormat, "Test", testCase->name, "Skipped");
return TEST_RESULT_SKIPPED; return TEST_RESULT_SKIPPED;
} }
@ -245,7 +248,7 @@ SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, SDLTest_TestCaseReference
if (testSuite->testSetUp) { if (testSuite->testSetUp) {
testSuite->testSetUp(0x0); testSuite->testSetUp(0x0);
if (SDLTest_AssertSummaryToTestResult() == TEST_RESULT_FAILED) { if (SDLTest_AssertSummaryToTestResult() == TEST_RESULT_FAILED) {
SDLTest_LogError((char *)SDLTest_TestCheckFmt, testSuite->name, "Failed"); SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Suite Setup", testSuite->name, "Failed");
return TEST_RESULT_SETUP_FAILURE; return TEST_RESULT_SETUP_FAILURE;
} }
} }
@ -268,16 +271,6 @@ SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, SDLTest_TestCaseReference
SDLTest_Log("Fuzzer invocations: %d", SDLTest_GetFuzzerInvocationCount()); SDLTest_Log("Fuzzer invocations: %d", SDLTest_GetFuzzerInvocationCount());
SDLTest_LogAssertSummary(); SDLTest_LogAssertSummary();
// Analyze assert count to determine final test case result
switch (testResult) {
case TEST_RESULT_PASSED:
SDLTest_LogError((char *)SDLTest_TestCheckFmt, testCase->name, "Failed");
case TEST_RESULT_FAILED:
SDLTest_Log((char *)SDLTest_TestCheckFmt, testCase->name, "Passed");
case TEST_RESULT_NO_ASSERT:
SDLTest_LogError((char *)SDLTest_TestCheckFmt, testCase->name, "No Asserts");
}
return testResult; return testResult;
} }
@ -295,7 +288,7 @@ void SDLTest_LogTestSuiteSummary(SDLTest_TestSuiteReference *testSuites)
testSuite=&testSuites[suiteCounter]; testSuite=&testSuites[suiteCounter];
suiteCounter++; suiteCounter++;
SDLTest_Log("Test Suite %i - %s\n", suiteCounter, SDLTest_Log("Test Suite %i - %s\n", suiteCounter,
(testSuite->name) ? testSuite->name : SDLTest_InvalidNameFmt); (testSuite->name) ? testSuite->name : SDLTest_InvalidNameFormat);
// Loop over all test cases // Loop over all test cases
testCounter = 0; testCounter = 0;
@ -304,15 +297,21 @@ void SDLTest_LogTestSuiteSummary(SDLTest_TestSuiteReference *testSuites)
testCase=(SDLTest_TestCaseReference *)testSuite->testCases[testCounter]; testCase=(SDLTest_TestCaseReference *)testSuite->testCases[testCounter];
testCounter++; testCounter++;
SDLTest_Log(" Test Case %i - %s: %s", testCounter, SDLTest_Log(" Test Case %i - %s: %s", testCounter,
(testCase->name) ? testCase->name : SDLTest_InvalidNameFmt, (testCase->name) ? testCase->name : SDLTest_InvalidNameFormat,
(testCase->description) ? testCase->description : SDLTest_InvalidNameFmt); (testCase->description) ? testCase->description : SDLTest_InvalidNameFormat);
} }
} }
} }
/* Gets a timer value in seconds */
float GetClock()
{
float currentClock = (float)clock();
return currentClock / (float)CLOCKS_PER_SEC;
}
/** /**
* \brief Execute a test using the given execution key. * \brief Execute a test suite using the given run seend and execution key.
* *
* \param testSuites Suites containing the test case. * \param testSuites Suites containing the test case.
* \param userRunSeed Custom run seed provided by user, or NULL to autogenerate one. * \param userRunSeed Custom run seed provided by user, or NULL to autogenerate one.
@ -322,7 +321,7 @@ void SDLTest_LogTestSuiteSummary(SDLTest_TestSuiteReference *testSuites)
* \returns Test run result; 0 when all tests passed, 1 if any tests failed. * \returns Test run result; 0 when all tests passed, 1 if any tests failed.
*/ */
int int
SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites, char *userRunSeed, Uint64 userExecKey, int testIterations) SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], char *userRunSeed, Uint64 userExecKey, int testIterations)
{ {
int suiteCounter; int suiteCounter;
int testCounter; int testCounter;
@ -330,22 +329,25 @@ SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites, char *userRunSeed, Uin
SDLTest_TestSuiteReference *testSuite; SDLTest_TestSuiteReference *testSuite;
SDLTest_TestCaseReference *testCase; SDLTest_TestCaseReference *testCase;
char *runSeed = NULL; char *runSeed = NULL;
char *currentSuiteName;
char *currentTestName;
Uint64 execKey; Uint64 execKey;
Uint32 runStartTicks; float runStartSeconds;
time_t runStartTimestamp; float suiteStartSeconds;
Uint32 suiteStartTicks; float testStartSeconds;
time_t suiteStartTimestamp; float runEndSeconds;
Uint32 testStartTicks; float suiteEndSeconds;
time_t testStartTimestamp; float testEndSeconds;
Uint32 runEndTicks; int testResult = 0;
time_t runEndTimestamp; int runResult = 0;
Uint32 suiteEndTicks; Uint32 totalTestFailedCount = 0;
time_t suiteEndTimestamp; Uint32 totalTestPassedCount = 0;
Uint32 testEndTicks; Uint32 totalTestSkippedCount = 0;
time_t testEndTimestamp; Uint32 testFailedCount = 0;
int testResult; Uint32 testPassedCount = 0;
int totalTestFailedCount, totalTestPassedCount, totalTestSkippedCount; Uint32 testSkippedCount = 0;
int testFailedCount, testPassedCount, testSkippedCount; Uint32 countSum = 0;
char *logFormat = (char *)SDLTest_LogSummaryFormat;
// Sanitize test iterations // Sanitize test iterations
if (testIterations < 1) { if (testIterations < 1) {
@ -356,36 +358,41 @@ SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites, char *userRunSeed, Uin
if (userRunSeed == NULL || strlen(userRunSeed) == 0) { if (userRunSeed == NULL || strlen(userRunSeed) == 0) {
runSeed = SDLTest_GenerateRunSeed(16); runSeed = SDLTest_GenerateRunSeed(16);
if (runSeed == NULL) { if (runSeed == NULL) {
SDLTest_LogError("Generating a random run seed failed"); SDLTest_LogError("Generating a random seed failed");
return 2; return 2;
} }
} }
// Reset per-run counters // Reset per-run counters
totalTestFailedCount = totalTestPassedCount = totalTestSkippedCount = 0; totalTestFailedCount = 0;
totalTestPassedCount = 0;
totalTestSkippedCount = 0;
// Take time - run start // Take time - run start
runStartTicks = SDL_GetTicks(); runStartSeconds = GetClock();
runStartTimestamp = time(0);
// TODO log run started // Log run with fuzzer parameters
SDLTest_Log("::::: Test Run '%s' started\n", runSeed);
// Loop over all suites // Loop over all suites
suiteCounter = 0; suiteCounter = 0;
while(&testSuites[suiteCounter]) { while(testSuites[suiteCounter]) {
testSuite=&testSuites[suiteCounter]; testSuite=(SDLTest_TestSuiteReference *)testSuites[suiteCounter];
suiteCounter++; suiteCounter++;
// Reset per-suite counters // Reset per-suite counters
testFailedCount = testPassedCount = testSkippedCount = 0; testFailedCount = 0;
testPassedCount = 0;
testSkippedCount = 0;
// Take time - suite start // Take time - suite start
suiteStartTicks = SDL_GetTicks(); suiteStartSeconds = GetClock();
suiteStartTimestamp = time(0);
// TODO log suite started // Log suite started
SDLTest_Log("Test Suite %i - %s\n", suiteCounter, currentSuiteName = (char *)((testSuite->name) ? testSuite->name : SDLTest_InvalidNameFormat);
(testSuite->name) ? testSuite->name : SDLTest_InvalidNameFmt); SDLTest_Log("===== Test Suite %i: %s started\n",
suiteCounter,
currentSuiteName);
// Loop over all test cases // Loop over all test cases
testCounter = 0; testCounter = 0;
@ -395,13 +402,15 @@ SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites, char *userRunSeed, Uin
testCounter++; testCounter++;
// Take time - test start // Take time - test start
testStartTicks = SDL_GetTicks(); testStartSeconds = GetClock();
testStartTimestamp = time(0);
// TODO log test started // Log test started
SDLTest_Log("Test Case %i - %s: %s", testCounter, currentTestName = (char *)((testCase->name) ? testCase->name : SDLTest_InvalidNameFormat);
(testCase->name) ? testCase->name : SDLTest_InvalidNameFmt, SDLTest_Log("----- Test Case %i: %s started",
(testCase->description) ? testCase->description : SDLTest_InvalidNameFmt); testCounter,
currentTestName);
SDLTest_Log("Test Description: %s",
(testCase->description) ? testCase->description : SDLTest_InvalidNameFormat);
// Loop over all iterations // Loop over all iterations
iterationCounter = 0; iterationCounter = 0;
@ -431,24 +440,67 @@ SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites, char *userRunSeed, Uin
} }
// Take time - test end // Take time - test end
testEndTicks = SDL_GetTicks(); testEndSeconds = GetClock();
testEndTimestamp = time(0);
// TODO log test ended SDLTest_Log("Test Case %s ended", currentTestName);
// Log test runtime
SDLTest_Log("Test runtime: %.1f sec", testEndSeconds - testStartSeconds);
// Log final test result
switch (testResult) {
case TEST_RESULT_PASSED:
SDLTest_Log((char *)SDLTest_FinalResultFormat, "Test", currentTestName, "Passed");
break;
case TEST_RESULT_FAILED:
SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Test", currentTestName, "Failed");
break;
case TEST_RESULT_NO_ASSERT:
SDLTest_LogError((char *)SDLTest_FinalResultFormat,"Test", currentTestName, "No Asserts");
break;
}
} }
// Take time - suite end // Take time - suite end
suiteEndTicks = SDL_GetTicks(); suiteEndSeconds = GetClock();
suiteEndTimestamp = time(0);
// TODO log suite ended // Log suite runtime
SDLTest_Log("Suite runtime: %.1f sec", suiteEndSeconds - suiteStartSeconds);
// Log summary and final Suite result
countSum = testPassedCount + testFailedCount + testSkippedCount;
if (testFailedCount == 0)
{
SDLTest_Log(logFormat, "Suite", countSum, testPassedCount, testFailedCount, testSkippedCount);
SDLTest_Log((char *)SDLTest_FinalResultFormat, "Suite", currentSuiteName, "Passed");
}
else
{
SDLTest_LogError(logFormat, "Suite", countSum, testPassedCount, testFailedCount, testSkippedCount);
SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Suite", currentSuiteName, "Failed");
}
} }
// Take time - run end // Take time - run end
runEndTicks = SDL_GetTicks(); runEndSeconds = GetClock();
runEndTimestamp = time(0);
// TODO log run ended // Log total runtime
SDLTest_Log("Total runtime: %.1f sec", runEndSeconds - runStartSeconds);
return (totalTestFailedCount ? 1 : 0); // Log summary and final run result
countSum = totalTestPassedCount + totalTestFailedCount + totalTestSkippedCount;
if (testFailedCount == 0)
{
runResult = 0;
SDLTest_Log(logFormat, "Run", countSum, totalTestPassedCount, totalTestFailedCount, totalTestSkippedCount);
SDLTest_Log((char *)SDLTest_FinalResultFormat, "Run", runSeed, "Passed");
}
else
{
runResult = 1;
SDLTest_LogError(logFormat, "Run", countSum, totalTestPassedCount, totalTestFailedCount, totalTestSkippedCount);
SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Run", runSeed, "Failed");
}
return runResult;
} }

View file

@ -37,12 +37,6 @@
#include "SDL_test.h" #include "SDL_test.h"
/*
* Note: Maximum size of SDLTest log message is less than SDLs limit
* to ensure we can fit additional information such as the timestamp.
*/
#define SDLTEST_MAX_LOGMESSAGE_LENGTH 3584
/*! /*!
* Converts unix timestamp to its ascii representation in localtime * Converts unix timestamp to its ascii representation in localtime
* *
@ -52,18 +46,18 @@
* *
* \param timestamp A Timestamp, i.e. time(0) * \param timestamp A Timestamp, i.e. time(0)
* *
* \return Ascii representation of the timestamp in localtime * \return Ascii representation of the timestamp in localtime in the format '08/23/01 14:55:02'
*/ */
char *SDLTest_TimestampToString(const time_t timestamp) char *SDLTest_TimestampToString(const time_t timestamp)
{ {
time_t copy; time_t copy;
static char buffer[256]; static char buffer[64];
struct tm *local; struct tm *local;
memset(buffer, 0, sizeof(buffer));\ memset(buffer, 0, sizeof(buffer));\
copy = timestamp; copy = timestamp;
local = localtime(&copy); local = localtime(&copy);
strftime(buffer, sizeof(buffer), "%a %Y-%m-%d %H:%M:%S %Z", local); strftime(buffer, sizeof(buffer), "%x %X", local);
return buffer; return buffer;
} }
@ -83,7 +77,7 @@ void SDLTest_Log(char *fmt, ...)
va_end(list); va_end(list);
// Log with timestamp and newline // Log with timestamp and newline
SDL_LogMessage(SDL_LOG_CATEGORY_TEST, SDL_LOG_PRIORITY_INFO, "%s: %s\n", SDLTest_TimestampToString(time(0)), logMessage); SDL_LogMessage(SDL_LOG_CATEGORY_TEST, SDL_LOG_PRIORITY_INFO, " %s: %s", SDLTest_TimestampToString(time(0)), logMessage);
} }
/* /*
@ -101,5 +95,5 @@ void SDLTest_LogError(char *fmt, ...)
va_end(list); va_end(list);
// Log with timestamp and newline // Log with timestamp and newline
SDL_LogMessage(SDL_LOG_CATEGORY_TEST, SDL_LOG_PRIORITY_ERROR, "%s: %s\n", SDLTest_TimestampToString(time(0)), logMessage); SDL_LogMessage(SDL_LOG_CATEGORY_TEST, SDL_LOG_PRIORITY_ERROR, "%s: %s", SDLTest_TimestampToString(time(0)), logMessage);
} }

101
test/testautomation.c Normal file
View file

@ -0,0 +1,101 @@
/*
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely.
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "SDL.h"
#include "SDL_test.h"
#include "tests/testsuites.h"
static SDLTest_CommonState *state;
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void
quit(int rc)
{
SDLTest_CommonQuit(state);
exit(rc);
}
int
main(int argc, char *argv[])
{
int result;
int i;
/* Initialize test framework */
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
if (!state) {
return 1;
}
// Needed?
// state->window_flags |= SDL_WINDOW_RESIZABLE;
/* Parse commandline */
for (i = 1; i < argc;) {
int consumed;
consumed = SDLTest_CommonArg(state, i);
if (consumed == 0) {
consumed = -1;
/* Parse additional parameters
if (SDL_strcasecmp(argv[i], "--BLAH") == 0) {
if (argv[i + 1]) {
if (SDL_strcasecmp(argv[i + 1], "BLUB") == 0) {
blah = blub;
consumed = 2;
}
}
} else if (SDL_strcasecmp(argv[i], "--BINGO") == 0) {
bingo = SDL_TRUE;
consumed = 1;
}
*/
}
if (consumed < 0) {
fprintf(stderr,
"Usage: %s %s [--BLAH BLUB --BINGO]\n",
argv[0], SDLTest_CommonUsage(state));
quit(1);
}
i += consumed;
}
/* Initialize common state */
if (!SDLTest_CommonInit(state)) {
quit(2);
}
/* Create the windows, initialize the renderers */
for (i = 0; i < state->num_windows; ++i) {
SDL_Renderer *renderer = state->renderers[i];
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(renderer);
}
/* Call Harness */
// TODO: pass custom parameters
result = SDLTest_RunSuites(testSuites, NULL, 0, 1);
//int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites, char *userRunSeed, Uint64 userExecKey, int testIterations);
/* Shutdown everything */
quit(result);
return(result);
}
/* vi: set ts=4 sw=4 expandtab: */

561
test/tests/testplatform.c Normal file
View file

@ -0,0 +1,561 @@
/**
* Original code: automated SDL platform test written by Edgar Simo "bobbens"
* Extended and updated by aschiffler at ferzkopp dot net
*/
#include <stdio.h>
#include "SDL.h"
#include "SDL_test.h"
/* ================= Test Case Implementation ================== */
/* Helper functions */
/**
* @brief Compare sizes of types.
*
* @note Watcom C flags these as Warning 201: "Unreachable code" if you just
* compare them directly, so we push it through a function to keep the
* compiler quiet. --ryan.
*/
static int _compareSizeOfType( size_t sizeoftype, size_t hardcodetype )
{
return sizeoftype != hardcodetype;
}
/* Test case functions */
/**
* @brief Tests type sizes.
*/
int platform_testTypes(void *arg)
{
int ret;
ret = _compareSizeOfType( sizeof(Uint8), 1 );
SDLTest_AssertCheck( ret == 0, "sizeof(Uint8) = %lu, expected 1", sizeof(Uint8) );
ret = _compareSizeOfType( sizeof(Uint16), 2 );
SDLTest_AssertCheck( ret == 0, "sizeof(Uint16) = %lu, expected 2", sizeof(Uint16) );
ret = _compareSizeOfType( sizeof(Uint32), 4 );
SDLTest_AssertCheck( ret == 0, "sizeof(Uint32) = %lu, expected 4", sizeof(Uint32) );
ret = _compareSizeOfType( sizeof(Uint64), 8 );
SDLTest_AssertCheck( ret == 0, "sizeof(Uint64) = %lu, expected 8", sizeof(Uint64) );
return TEST_COMPLETED;
}
/**
* @brief Tests platform endianness and SDL_SwapXY functions.
*/
int platform_testEndianessAndSwap(void *arg)
{
int real_byteorder;
Uint16 value = 0x1234;
Uint16 value16 = 0xCDAB;
Uint16 swapped16 = 0xABCD;
Uint32 value32 = 0xEFBEADDE;
Uint32 swapped32 = 0xDEADBEEF;
Uint64 value64, swapped64;
value64 = 0xEFBEADDE;
value64 <<= 32;
value64 |= 0xCDAB3412;
swapped64 = 0x1234ABCD;
swapped64 <<= 32;
swapped64 |= 0xDEADBEEF;
if ((*((char *) &value) >> 4) == 0x1) {
real_byteorder = SDL_BIG_ENDIAN;
} else {
real_byteorder = SDL_LIL_ENDIAN;
}
/* Test endianness. */
SDLTest_AssertCheck( real_byteorder == SDL_BYTEORDER,
"Machine detected as %s endian, appears to be %s endian.",
(SDL_BYTEORDER == SDL_LIL_ENDIAN) ? "little" : "big",
(real_byteorder == SDL_LIL_ENDIAN) ? "little" : "big" );
/* Test 16 swap. */
SDLTest_AssertCheck( SDL_Swap16(value16) == swapped16,
"SDL_Swap16(): 16 bit swapped: 0x%X => 0x%X",
value16, SDL_Swap16(value16) );
/* Test 32 swap. */
SDLTest_AssertCheck( SDL_Swap32(value32) == swapped32,
"SDL_Swap32(): 32 bit swapped: 0x%X => 0x%X",
value32, SDL_Swap32(value32) );
/* Test 64 swap. */
SDLTest_AssertCheck( SDL_Swap64(value64) == swapped64,
#ifdef _MSC_VER
"SDL_Swap64(): 64 bit swapped: 0x%I64X => 0x%I64X",
#else
"SDL_Swap64(): 64 bit swapped: 0x%llX => 0x%llX",
#endif
value64, SDL_Swap64(value64) );
return TEST_COMPLETED;
}
/*!
* \brief Tests SDL_GetXYZ() functions
* \sa
* http://wiki.libsdl.org/moin.cgi/SDL_GetPlatform
* http://wiki.libsdl.org/moin.cgi/SDL_GetCPUCount
* http://wiki.libsdl.org/moin.cgi/SDL_GetCPUCacheLineSize
* http://wiki.libsdl.org/moin.cgi/SDL_GetRevision
* http://wiki.libsdl.org/moin.cgi/SDL_GetRevisionNumber
*/
int platform_testGetFunctions (void *arg)
{
char *platform;
char *revision;
int ret;
int len;
platform = (char *)SDL_GetPlatform();
SDLTest_AssertPass("SDL_GetPlatform()");
SDLTest_AssertCheck(platform != NULL, "SDL_GetPlatform() != NULL");
if (platform != NULL) {
len = strlen(platform);
SDLTest_AssertCheck(len > 0,
"SDL_GetPlatform(): expected non-empty platform, was platform: '%s', len: %i",
platform,
len);
}
ret = SDL_GetCPUCount();
SDLTest_AssertPass("SDL_GetCPUCount()");
SDLTest_AssertCheck(ret > 0,
"SDL_GetCPUCount(): expected count > 0, was: %i",
ret);
ret = SDL_GetCPUCacheLineSize();
SDLTest_AssertPass("SDL_GetCPUCacheLineSize()");
SDLTest_AssertCheck(ret >= 0,
"SDL_GetCPUCacheLineSize(): expected size >= 0, was: %i",
ret);
revision = (char *)SDL_GetRevision();
SDLTest_AssertPass("SDL_GetRevision()");
SDLTest_AssertCheck(revision != NULL, "SDL_GetRevision() != NULL");
ret = SDL_GetRevisionNumber();
SDLTest_AssertPass("SDL_GetRevisionNumber()");
return TEST_COMPLETED;
}
/*!
* \brief Tests SDL_HasXYZ() functions
* \sa
* http://wiki.libsdl.org/moin.cgi/SDL_Has3DNow
* http://wiki.libsdl.org/moin.cgi/SDL_HasAltiVec
* http://wiki.libsdl.org/moin.cgi/SDL_HasMMX
* http://wiki.libsdl.org/moin.cgi/SDL_HasRDTSC
* http://wiki.libsdl.org/moin.cgi/SDL_HasSSE
* http://wiki.libsdl.org/moin.cgi/SDL_HasSSE2
* http://wiki.libsdl.org/moin.cgi/SDL_HasSSE3
* http://wiki.libsdl.org/moin.cgi/SDL_HasSSE41
* http://wiki.libsdl.org/moin.cgi/SDL_HasSSE42
*/
int platform_testHasFunctions (void *arg)
{
int ret;
// TODO: independently determine and compare values as well
ret = SDL_HasRDTSC();
SDLTest_AssertPass("SDL_HasRDTSC()");
ret = SDL_HasAltiVec();
SDLTest_AssertPass("SDL_HasAltiVec()");
ret = SDL_HasMMX();
SDLTest_AssertPass("SDL_HasMMX()");
ret = SDL_Has3DNow();
SDLTest_AssertPass("SDL_Has3DNow()");
ret = SDL_HasSSE();
SDLTest_AssertPass("SDL_HasSSE()");
ret = SDL_HasSSE2();
SDLTest_AssertPass("SDL_HasSSE2()");
ret = SDL_HasSSE3();
SDLTest_AssertPass("SDL_HasSSE3()");
ret = SDL_HasSSE41();
SDLTest_AssertPass("SDL_HasSSE41()");
ret = SDL_HasSSE42();
SDLTest_AssertPass("SDL_HasSSE42()");
return TEST_COMPLETED;
}
/*!
* \brief Tests SDL_GetVersion
* \sa
* http://wiki.libsdl.org/moin.cgi/SDL_GetVersion
*/
int platform_testGetVersion(void *arg)
{
SDL_version linked;
int major = SDL_MAJOR_VERSION;
int minor = SDL_MINOR_VERSION;
SDL_GetVersion(&linked);
SDLTest_AssertCheck( linked.major >= major,
"SDL_GetVersion(): returned major %i (>= %i)",
linked.major,
major);
SDLTest_AssertCheck( linked.minor >= minor,
"SDL_GetVersion(): returned minor %i (>= %i)",
linked.minor,
minor);
return TEST_COMPLETED;
}
/*!
* \brief Tests SDL_VERSION macro
*/
int platform_testSDLVersion(void *arg)
{
SDL_version compiled;
int major = SDL_MAJOR_VERSION;
int minor = SDL_MINOR_VERSION;
SDL_VERSION(&compiled);
SDLTest_AssertCheck( compiled.major >= major,
"SDL_VERSION() returned major %i (>= %i)",
compiled.major,
major);
SDLTest_AssertCheck( compiled.minor >= minor,
"SDL_VERSION() returned minor %i (>= %i)",
compiled.minor,
minor);
return TEST_COMPLETED;
}
/*!
* \brief Tests default SDL_Init
*/
int platform_testDefaultInit(void *arg)
{
int ret;
int subsystem;
subsystem = SDL_WasInit(SDL_INIT_EVERYTHING);
SDLTest_AssertCheck( subsystem != 0,
"SDL_WasInit(0): returned %i, expected != 0",
subsystem);
ret = SDL_Init(SDL_WasInit(SDL_INIT_EVERYTHING));
SDLTest_AssertCheck( ret == 0,
"SDL_Init(0): returned %i, expected 0, error: %s",
ret,
SDL_GetError());
return TEST_COMPLETED;
}
/*!
* \brief Tests SDL_Get/Set/ClearError
* \sa
* http://wiki.libsdl.org/moin.cgi/SDL_GetError
* http://wiki.libsdl.org/moin.cgi/SDL_SetError
* http://wiki.libsdl.org/moin.cgi/SDL_ClearError
*/
int platform_testGetSetClearError(void *arg)
{
const char *testError = "Testing";
char *lastError;
int len;
SDL_ClearError();
SDLTest_AssertPass("SDL_ClearError()");
lastError = (char *)SDL_GetError();
SDLTest_AssertPass("SDL_GetError()");
SDLTest_AssertCheck(lastError != NULL,
"SDL_GetError() != NULL");
if (lastError != NULL)
{
len = strlen(lastError);
SDLTest_AssertCheck(len == 0,
"SDL_GetError(): no message expected, len: %i", len);
}
SDL_SetError("%s", testError);
SDLTest_AssertPass("SDL_SetError()");
lastError = (char *)SDL_GetError();
SDLTest_AssertCheck(lastError != NULL,
"SDL_GetError() != NULL");
if (lastError != NULL)
{
len = strlen(lastError);
SDLTest_AssertCheck(len == strlen(testError),
"SDL_GetError(): expected message len %i, was len: %i",
strlen(testError),
len);
SDLTest_AssertCheck(strcmp(lastError, testError) == 0,
"SDL_GetError(): expected message %s, was message: %s",
testError,
lastError);
}
// Clean up
SDL_ClearError();
SDLTest_AssertPass("SDL_ClearError()");
return TEST_COMPLETED;
}
/*!
* \brief Tests SDL_SetError with empty input
* \sa
* http://wiki.libsdl.org/moin.cgi/SDL_SetError
*/
int platform_testSetErrorEmptyInput(void *arg)
{
const char *testError = "";
char *lastError;
int len;
SDL_SetError("%s", testError);
SDLTest_AssertPass("SDL_SetError()");
lastError = (char *)SDL_GetError();
SDLTest_AssertCheck(lastError != NULL,
"SDL_GetError() != NULL");
if (lastError != NULL)
{
len = strlen(lastError);
SDLTest_AssertCheck(len == strlen(testError),
"SDL_GetError(): expected message len %i, was len: %i",
strlen(testError),
len);
SDLTest_AssertCheck(strcmp(lastError, testError) == 0,
"SDL_GetError(): expected message '%s', was message: '%s'",
testError,
lastError);
}
// Clean up
SDL_ClearError();
SDLTest_AssertPass("SDL_ClearError()");
return TEST_COMPLETED;
}
/*!
* \brief Tests SDL_SetError with invalid input
* \sa
* http://wiki.libsdl.org/moin.cgi/SDL_SetError
*/
int platform_testSetErrorInvalidInput(void *arg)
{
const char *testError = NULL;
const char *probeError = "Testing";
char *lastError;
int len;
// Reset
SDL_ClearError();
SDLTest_AssertPass("SDL_ClearError()");
// Check for no-op
SDL_SetError(testError);
SDLTest_AssertPass("SDL_SetError()");
lastError = (char *)SDL_GetError();
SDLTest_AssertCheck(lastError != NULL,
"SDL_GetError() != NULL");
if (lastError != NULL)
{
len = strlen(lastError);
SDLTest_AssertCheck(len == 0,
"SDL_GetError(): expected message len 0, was len: %i",
0,
len);
SDLTest_AssertCheck(strcmp(lastError, "") == 0,
"SDL_GetError(): expected message '', was message: '%s'",
lastError);
}
// Set
SDL_SetError(probeError);
SDLTest_AssertPass("SDL_SetError()");
// Check for no-op
SDL_SetError(testError);
SDLTest_AssertPass("SDL_SetError()");
lastError = (char *)SDL_GetError();
SDLTest_AssertCheck(lastError != NULL,
"SDL_GetError() != NULL");
if (lastError != NULL)
{
len = strlen(lastError);
SDLTest_AssertCheck(len == strlen(probeError),
"SDL_GetError(): expected message len %i, was len: %i",
strlen(probeError),
len);
SDLTest_AssertCheck(strcmp(lastError, probeError) == 0,
"SDL_GetError(): expected message '%s', was message: '%s'",
probeError,
lastError);
}
// Clean up
SDL_ClearError();
SDLTest_AssertPass("SDL_ClearError()");
return TEST_COMPLETED;
}
/*!
* \brief Tests SDL_GetPowerInfo
* \sa
* http://wiki.libsdl.org/moin.cgi/SDL_GetPowerInfo
*/
int platform_testGetPowerInfo(void *arg)
{
SDL_PowerState state;
SDL_PowerState stateAgain;
int secs;
int secsAgain;
int pct;
int pctAgain;
state = SDL_GetPowerInfo(&secs, &pct);
SDLTest_AssertPass("SDL_GetPowerInfo()");
SDLTest_AssertCheck(
state==SDL_POWERSTATE_UNKNOWN ||
state==SDL_POWERSTATE_ON_BATTERY ||
state==SDL_POWERSTATE_NO_BATTERY ||
state==SDL_POWERSTATE_CHARGING ||
state==SDL_POWERSTATE_CHARGED,
"SDL_GetPowerInfo(): state %i is one of the expected values",
(int)state);
if (state==SDL_POWERSTATE_ON_BATTERY)
{
SDLTest_AssertCheck(
secs >= 0,
"SDL_GetPowerInfo(): on battery, secs >= 0, was: %i",
secs);
SDLTest_AssertCheck(
(pct >= 0) && (pct <= 100),
"SDL_GetPowerInfo(): on battery, pct=[0,100], was: %i",
pct);
}
if (state==SDL_POWERSTATE_UNKNOWN ||
state==SDL_POWERSTATE_NO_BATTERY)
{
SDLTest_AssertCheck(
secs == -1,
"SDL_GetPowerInfo(): no battery, secs == -1, was: %i",
secs);
SDLTest_AssertCheck(
pct == -1,
"SDL_GetPowerInfo(): no battery, pct == -1, was: %i",
pct);
}
// Partial return value variations
stateAgain = SDL_GetPowerInfo(&secsAgain, NULL);
SDLTest_AssertCheck(
state==stateAgain,
"State %i returned when only 'secs' requested",
stateAgain);
SDLTest_AssertCheck(
secs==secsAgain,
"Value %i matches when only 'secs' requested",
secsAgain);
stateAgain = SDL_GetPowerInfo(NULL, &pctAgain);
SDLTest_AssertCheck(
state==stateAgain,
"State %i returned when only 'pct' requested",
stateAgain);
SDLTest_AssertCheck(
pct==pctAgain,
"Value %i matches when only 'pct' requested",
pctAgain);
stateAgain = SDL_GetPowerInfo(NULL, NULL);
SDLTest_AssertCheck(
state==stateAgain,
"State %i returned when no value requested",
stateAgain);
return TEST_COMPLETED;
}
/* ================= Test References ================== */
/* Platform test cases */
static const SDLTest_TestCaseReference platformTest1 =
{ (SDLTest_TestCaseFp)platform_testTypes, "platform_testTypes", "Tests predefined types", TEST_ENABLED};
static const SDLTest_TestCaseReference platformTest2 =
{ (SDLTest_TestCaseFp)platform_testEndianessAndSwap, "platform_testEndianessAndSwap", "Tests endianess and swap functions", TEST_ENABLED};
static const SDLTest_TestCaseReference platformTest3 =
{ (SDLTest_TestCaseFp)platform_testGetFunctions, "platform_testGetFunctions", "Tests various SDL_GetXYZ functions", TEST_ENABLED};
static const SDLTest_TestCaseReference platformTest4 =
{ (SDLTest_TestCaseFp)platform_testHasFunctions, "platform_testHasFunctions", "Tests various SDL_HasXYZ functions", TEST_ENABLED};
static const SDLTest_TestCaseReference platformTest5 =
{ (SDLTest_TestCaseFp)platform_testGetVersion, "platform_testGetVersion", "Tests SDL_GetVersion function", TEST_ENABLED};
static const SDLTest_TestCaseReference platformTest6 =
{ (SDLTest_TestCaseFp)platform_testSDLVersion, "platform_testSDLVersion", "Tests SDL_VERSION macro", TEST_ENABLED};
static const SDLTest_TestCaseReference platformTest7 =
{ (SDLTest_TestCaseFp)platform_testDefaultInit, "platform_testDefaultInit", "Tests default SDL_Init", TEST_ENABLED};
static const SDLTest_TestCaseReference platformTest8 =
{ (SDLTest_TestCaseFp)platform_testGetSetClearError, "platform_testGetSetClearError", "Tests SDL_Get/Set/ClearError", TEST_ENABLED};
static const SDLTest_TestCaseReference platformTest9 =
{ (SDLTest_TestCaseFp)platform_testSetErrorEmptyInput, "platform_testSetErrorEmptyInput", "Tests SDL_SetError with empty input", TEST_ENABLED};
static const SDLTest_TestCaseReference platformTest10 =
{ (SDLTest_TestCaseFp)platform_testSetErrorInvalidInput, "platform_testSetErrorInvalidInput", "Tests SDL_SetError with invalid input", TEST_ENABLED};
static const SDLTest_TestCaseReference platformTest11 =
{ (SDLTest_TestCaseFp)platform_testGetPowerInfo, "platform_testGetPowerInfo", "Tests SDL_GetPowerInfo function", TEST_ENABLED };
/* Sequence of Platform test cases */
static const SDLTest_TestCaseReference *platformTests[] = {
&platformTest1,
&platformTest2,
&platformTest3,
&platformTest4,
&platformTest5,
&platformTest6,
&platformTest7,
&platformTest8,
&platformTest9,
&platformTest10,
&platformTest11,
NULL
};
/* Platform test suite (global) */
SDLTest_TestSuiteReference platformTestSuite = {
"Platform",
NULL,
platformTests,
NULL
};

40
test/tests/testsuites.h Normal file
View file

@ -0,0 +1,40 @@
/**
* Reference to all test suites.
*
*/
#ifndef _testsuites_h
#define _testsuites_h
#include "SDL_test.h"
// Test collections
//extern SDLTest_TestSuiteReference audioTestSuite;
//extern SDLTest_TestSuiteReference clipboardTestSuite;
//extern SDLTest_TestSuiteReference eventsTestSuite;
//extern SDLTest_TestSuiteReference keyboardTestSuite;
extern SDLTest_TestSuiteReference platformTestSuite;
//extern SDLTest_TestSuiteReference rectTestSuite;
//extern SDLTest_TestSuiteReference renderTestSuite;
//extern SDLTest_TestSuiteReference rwopsTestSuite;
//extern SDLTest_TestSuiteReference surfaceTestSuite;
//extern SDLTest_TestSuiteReference syswmTestSuite;
//extern SDLTest_TestSuiteReference videoTestSuite;
// All test suites
SDLTest_TestSuiteReference *testSuites[] = {
// &audioTestSuite,
// &clipboardTestSuite,
// &eventsTestSuite,
// &keyboardTestSuite,
&platformTestSuite,
// &rectTestSuite,
// &renderTestSuite,
// &rwopsTestSuite,
// &surfaceTestSuite,
// &syswmTestSuite,
// &videoTestSuite,
NULL
};
#endif