From 2ac73343d937f9c8355d3b6facf329c9960f867d Mon Sep 17 00:00:00 2001 From: Andreas Schiffler Date: Fri, 14 Dec 2012 23:05:34 -0800 Subject: [PATCH] Refactor/fix test lib harness, assert and log component; add harness driver; port platform suite from GSOC code --- include/SDL_test.h | 8 +- include/SDL_test_assert.h | 15 +- include/SDL_test_harness.h | 14 + src/test/SDL_test_assert.c | 62 +++- src/test/SDL_test_fuzzer.c | 2 +- src/test/SDL_test_harness.c | 184 +++++++----- src/test/SDL_test_log.c | 16 +- test/testautomation.c | 101 +++++++ test/tests/testplatform.c | 561 ++++++++++++++++++++++++++++++++++++ test/tests/testsuites.h | 40 +++ 10 files changed, 908 insertions(+), 95 deletions(-) create mode 100644 test/testautomation.c create mode 100644 test/tests/testplatform.c create mode 100644 test/tests/testsuites.h diff --git a/include/SDL_test.h b/include/SDL_test.h index af7613316..b21c0199e 100644 --- a/include/SDL_test.h +++ b/include/SDL_test.h @@ -49,9 +49,13 @@ extern "C" { /* *INDENT-ON* */ #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++ */ #ifdef __cplusplus diff --git a/include/SDL_test_assert.h b/include/SDL_test_assert.h index d557a76fb..8648aa9c2 100644 --- a/include/SDL_test_assert.h +++ b/include/SDL_test_assert.h @@ -60,17 +60,24 @@ extern "C" { * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0). * \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 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. diff --git a/include/SDL_test_harness.h b/include/SDL_test_harness.h index cf30600e2..e2608ace9 100644 --- a/include/SDL_test_harness.h +++ b/include/SDL_test_harness.h @@ -98,6 +98,20 @@ typedef struct SDLTest_TestSuiteReference { SDLTest_TestCaseTearDownFp testTearDown; } 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++ */ #ifdef __cplusplus /* *INDENT-OFF* */ diff --git a/src/test/SDL_test_assert.c b/src/test/SDL_test_assert.c index 13eda7be8..03fa0580c 100644 --- a/src/test/SDL_test_assert.c +++ b/src/test/SDL_test_assert.c @@ -30,10 +30,10 @@ #include "SDL_test.h" /* Assert check message format */ -const char *SDLTest_AssertCheckFmt = "Assert '%s': %s"; +const char *SDLTest_AssertCheckFormat = "Assert '%s': %s"; /* 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 */ 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). */ -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). */ -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) { SDLTest_AssertsFailed++; - SDLTest_LogError(fmt, assertDescription, "Failed"); + SDLTest_LogError(logFormat, logMessage, "Failed"); } else { SDLTest_AssertsPassed++; - SDLTest_Log(fmt, assertDescription, "Passed"); + SDLTest_Log(logFormat, logMessage, "Passed"); } 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. */ @@ -84,15 +124,15 @@ void SDLTest_ResetAssertSummary() */ void SDLTest_LogAssertSummary() { - char *fmt = (char *)SDLTest_AssertSummaryFmt; + char *logFormat = (char *)SDLTest_AssertSummaryFormat; Uint32 totalAsserts = SDLTest_AssertsPassed + SDLTest_AssertsFailed; if (SDLTest_AssertsFailed == 0) { - SDLTest_Log(fmt, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed); + SDLTest_Log(logFormat, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed); } else { - SDLTest_LogError(fmt, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed); + SDLTest_LogError(logFormat, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed); } } diff --git a/src/test/SDL_test_fuzzer.c b/src/test/SDL_test_fuzzer.c index a25a8c260..b66e75efc 100644 --- a/src/test/SDL_test_fuzzer.c +++ b/src/test/SDL_test_fuzzer.c @@ -58,7 +58,7 @@ SDLTest_FuzzerInit(Uint64 execKey) } int -SDLTest_GetInvocationCount() +SDLTest_GetFuzzerInvocationCount() { return fuzzerInvocationCounter; } diff --git a/src/test/SDL_test_harness.c b/src/test/SDL_test_harness.c index 15b721f86..ec10e7d42 100644 --- a/src/test/SDL_test_harness.c +++ b/src/test/SDL_test_harness.c @@ -28,11 +28,14 @@ #include #include -/* Assert check message format */ -const char *SDLTest_TestCheckFmt = "Test '%s': %s"; - /* 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 */ static Uint32 SDLTest_TestCaseTimeout = 3600; @@ -228,7 +231,7 @@ SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, SDLTest_TestCaseReference if (!testCase->enabled) { - SDLTest_Log((char *)SDLTest_TestCheckFmt, testCase->name, "Skipped"); + SDLTest_Log((char *)SDLTest_FinalResultFormat, "Test", testCase->name, "Skipped"); return TEST_RESULT_SKIPPED; } @@ -245,7 +248,7 @@ SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, SDLTest_TestCaseReference if (testSuite->testSetUp) { testSuite->testSetUp(0x0); 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; } } @@ -268,16 +271,6 @@ SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, SDLTest_TestCaseReference SDLTest_Log("Fuzzer invocations: %d", SDLTest_GetFuzzerInvocationCount()); 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; } @@ -295,7 +288,7 @@ void SDLTest_LogTestSuiteSummary(SDLTest_TestSuiteReference *testSuites) testSuite=&testSuites[suiteCounter]; 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 testCounter = 0; @@ -304,15 +297,21 @@ void SDLTest_LogTestSuiteSummary(SDLTest_TestSuiteReference *testSuites) testCase=(SDLTest_TestCaseReference *)testSuite->testCases[testCounter]; testCounter++; SDLTest_Log(" Test Case %i - %s: %s", testCounter, - (testCase->name) ? testCase->name : SDLTest_InvalidNameFmt, - (testCase->description) ? testCase->description : SDLTest_InvalidNameFmt); + (testCase->name) ? testCase->name : SDLTest_InvalidNameFormat, + (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 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. */ 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 testCounter; @@ -330,22 +329,25 @@ SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites, char *userRunSeed, Uin SDLTest_TestSuiteReference *testSuite; SDLTest_TestCaseReference *testCase; char *runSeed = NULL; + char *currentSuiteName; + char *currentTestName; Uint64 execKey; - Uint32 runStartTicks; - time_t runStartTimestamp; - Uint32 suiteStartTicks; - time_t suiteStartTimestamp; - Uint32 testStartTicks; - time_t testStartTimestamp; - Uint32 runEndTicks; - time_t runEndTimestamp; - Uint32 suiteEndTicks; - time_t suiteEndTimestamp; - Uint32 testEndTicks; - time_t testEndTimestamp; - int testResult; - int totalTestFailedCount, totalTestPassedCount, totalTestSkippedCount; - int testFailedCount, testPassedCount, testSkippedCount; + float runStartSeconds; + float suiteStartSeconds; + float testStartSeconds; + float runEndSeconds; + float suiteEndSeconds; + float testEndSeconds; + int testResult = 0; + int runResult = 0; + Uint32 totalTestFailedCount = 0; + Uint32 totalTestPassedCount = 0; + Uint32 totalTestSkippedCount = 0; + Uint32 testFailedCount = 0; + Uint32 testPassedCount = 0; + Uint32 testSkippedCount = 0; + Uint32 countSum = 0; + char *logFormat = (char *)SDLTest_LogSummaryFormat; // Sanitize test iterations if (testIterations < 1) { @@ -356,36 +358,41 @@ SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites, char *userRunSeed, Uin if (userRunSeed == NULL || strlen(userRunSeed) == 0) { runSeed = SDLTest_GenerateRunSeed(16); if (runSeed == NULL) { - SDLTest_LogError("Generating a random run seed failed"); + SDLTest_LogError("Generating a random seed failed"); return 2; } } // Reset per-run counters - totalTestFailedCount = totalTestPassedCount = totalTestSkippedCount = 0; + totalTestFailedCount = 0; + totalTestPassedCount = 0; + totalTestSkippedCount = 0; // Take time - run start - runStartTicks = SDL_GetTicks(); - runStartTimestamp = time(0); + runStartSeconds = GetClock(); - // TODO log run started + // Log run with fuzzer parameters + SDLTest_Log("::::: Test Run '%s' started\n", runSeed); // Loop over all suites suiteCounter = 0; - while(&testSuites[suiteCounter]) { - testSuite=&testSuites[suiteCounter]; + while(testSuites[suiteCounter]) { + testSuite=(SDLTest_TestSuiteReference *)testSuites[suiteCounter]; suiteCounter++; // Reset per-suite counters - testFailedCount = testPassedCount = testSkippedCount = 0; + testFailedCount = 0; + testPassedCount = 0; + testSkippedCount = 0; // Take time - suite start - suiteStartTicks = SDL_GetTicks(); - suiteStartTimestamp = time(0); + suiteStartSeconds = GetClock(); - // TODO log suite started - SDLTest_Log("Test Suite %i - %s\n", suiteCounter, - (testSuite->name) ? testSuite->name : SDLTest_InvalidNameFmt); + // Log suite started + currentSuiteName = (char *)((testSuite->name) ? testSuite->name : SDLTest_InvalidNameFormat); + SDLTest_Log("===== Test Suite %i: %s started\n", + suiteCounter, + currentSuiteName); // Loop over all test cases testCounter = 0; @@ -395,13 +402,15 @@ SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites, char *userRunSeed, Uin testCounter++; // Take time - test start - testStartTicks = SDL_GetTicks(); - testStartTimestamp = time(0); + testStartSeconds = GetClock(); - // TODO log test started - SDLTest_Log("Test Case %i - %s: %s", testCounter, - (testCase->name) ? testCase->name : SDLTest_InvalidNameFmt, - (testCase->description) ? testCase->description : SDLTest_InvalidNameFmt); + // Log test started + currentTestName = (char *)((testCase->name) ? testCase->name : SDLTest_InvalidNameFormat); + SDLTest_Log("----- Test Case %i: %s started", + testCounter, + currentTestName); + SDLTest_Log("Test Description: %s", + (testCase->description) ? testCase->description : SDLTest_InvalidNameFormat); // Loop over all iterations iterationCounter = 0; @@ -431,24 +440,67 @@ SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites, char *userRunSeed, Uin } // Take time - test end - testEndTicks = SDL_GetTicks(); - testEndTimestamp = time(0); - - // TODO log test ended + testEndSeconds = GetClock(); + + 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 - suiteEndTicks = SDL_GetTicks(); - suiteEndTimestamp = time(0); + suiteEndSeconds = GetClock(); - // 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 - runEndTicks = SDL_GetTicks(); - runEndTimestamp = time(0); + runEndSeconds = GetClock(); + + // Log total runtime + SDLTest_Log("Total runtime: %.1f sec", runEndSeconds - runStartSeconds); - // TODO log run ended + // 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 (totalTestFailedCount ? 1 : 0); + return runResult; } diff --git a/src/test/SDL_test_log.c b/src/test/SDL_test_log.c index 0c38c44f1..4c7579510 100644 --- a/src/test/SDL_test_log.c +++ b/src/test/SDL_test_log.c @@ -37,12 +37,6 @@ #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 * @@ -52,18 +46,18 @@ * * \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) { time_t copy; - static char buffer[256]; + static char buffer[64]; struct tm *local; memset(buffer, 0, sizeof(buffer));\ copy = timestamp; local = localtime(©); - strftime(buffer, sizeof(buffer), "%a %Y-%m-%d %H:%M:%S %Z", local); + strftime(buffer, sizeof(buffer), "%x %X", local); return buffer; } @@ -83,7 +77,7 @@ void SDLTest_Log(char *fmt, ...) va_end(list); // 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); // 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); } diff --git a/test/testautomation.c b/test/testautomation.c new file mode 100644 index 000000000..f3f193030 --- /dev/null +++ b/test/testautomation.c @@ -0,0 +1,101 @@ +/* + Copyright (C) 1997-2011 Sam Lantinga + + 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 +#include +#include + +#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: */ diff --git a/test/tests/testplatform.c b/test/tests/testplatform.c new file mode 100644 index 000000000..1c4c91a11 --- /dev/null +++ b/test/tests/testplatform.c @@ -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 + +#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 +}; diff --git a/test/tests/testsuites.h b/test/tests/testsuites.h new file mode 100644 index 000000000..42a8044a4 --- /dev/null +++ b/test/tests/testsuites.h @@ -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