Commit 3efe0fed authored by Markus Kauppila's avatar Markus Kauppila

Added SetUp/TearDown functions for test suites.

parent 0eb354ce
/* /*
Copyright (C) 2011 Markus Kauppila <markus.kauppila@gmail.com> Copyright (C) 2011 Markus Kauppila <markus.kauppila@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
...@@ -36,7 +36,7 @@ int _testAssertsFailed; ...@@ -36,7 +36,7 @@ int _testAssertsFailed;
int _testAssertsPassed; int _testAssertsPassed;
void void
_TestCaseInit() _InitTestEnvironment() // InitTestEnvironment
{ {
_testReturnValue = 0; _testReturnValue = 0;
_testAssertsFailed = 0; _testAssertsFailed = 0;
...@@ -44,7 +44,7 @@ _TestCaseInit() ...@@ -44,7 +44,7 @@ _TestCaseInit()
} }
int int
_TestCaseQuit() _QuitTestEnvironment()
{ {
AssertSummary(_testAssertsFailed + _testAssertsPassed, AssertSummary(_testAssertsFailed + _testAssertsPassed,
_testAssertsFailed, _testAssertsPassed, time(0)); _testAssertsFailed, _testAssertsPassed, time(0));
...@@ -76,7 +76,6 @@ AssertEquals(const int expected, const int actual, char *message, ...) ...@@ -76,7 +76,6 @@ AssertEquals(const int expected, const int actual, char *message, ...)
AssertWithValues("AssertEquals", 1, buf, AssertWithValues("AssertEquals", 1, buf,
actual, expected, time(0)); actual, expected, time(0));
_testReturnValue = 0;
_testAssertsPassed++; _testAssertsPassed++;
} }
} }
...@@ -98,7 +97,6 @@ AssertTrue(int condition, char *message, ...) ...@@ -98,7 +97,6 @@ AssertTrue(int condition, char *message, ...)
} else { } else {
Assert("AssertTrue", 1, buf, time(0)); Assert("AssertTrue", 1, buf, time(0));
_testReturnValue = 0;
_testAssertsPassed++; _testAssertsPassed++;
} }
} }
...@@ -115,7 +113,6 @@ AssertPass(char *message, ...) ...@@ -115,7 +113,6 @@ AssertPass(char *message, ...)
Assert("AssertPass", 1, buf, time(0)); Assert("AssertPass", 1, buf, time(0));
_testReturnValue = 0;
_testAssertsPassed++; _testAssertsPassed++;
} }
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
#include "logger.h" #include "logger.h"
#include "common/common.h"
#include "common/images.h"
extern int _testReturnValue; extern int _testReturnValue;
extern int _testAssertsFailed; extern int _testAssertsFailed;
extern int _testAssertsPassed; extern int _testAssertsPassed;
...@@ -52,18 +56,18 @@ typedef struct TestCaseReference { ...@@ -52,18 +56,18 @@ typedef struct TestCaseReference {
} TestCaseReference; } TestCaseReference;
/*! /*!
* Initialized the test case. Must be called at * Initialized the test environment such as asserts. Must be called at
* the beginning of every test case, before doing * the beginning of every test case, before doing anything else.
* anything else.
*/ */
void _TestCaseInit(); void _InitTestEnvironment();
/*! /*!
* Deinitializes and exits the test case * Deinitializes the test environment and
* returns the result of the test (pass or failure)
* *
* \return 0 if test succeeded, otherwise 1 * \return 0 if test succeeded, otherwise 1
*/ */
int _TestCaseQuit(); int _QuitTestEnvironment();
/*! /*!
* Assert function. Tests if the expected value equals the actual value, then * Assert function. Tests if the expected value equals the actual value, then
...@@ -74,6 +78,7 @@ int _TestCaseQuit(); ...@@ -74,6 +78,7 @@ int _TestCaseQuit();
* \param message Message that will be printed if assert fails * \param message Message that will be printed if assert fails
*/ */
void AssertEquals(const int expected, const int actual, char *message, ...); void AssertEquals(const int expected, const int actual, char *message, ...);
/*! /*!
* Assert function. Tests if the given condition is true. True in * Assert function. Tests if the given condition is true. True in
* this case means non-zero value. If the condition is true, the * this case means non-zero value. If the condition is true, the
......
...@@ -39,9 +39,13 @@ ...@@ -39,9 +39,13 @@
//!< Function pointer to a test case function //!< Function pointer to a test case function
typedef void (*TestCaseFp)(void *arg); typedef void (*TestCaseFp)(void *arg);
//!< Function pointer to a test case init function //!< Function pointer to a test case init function
typedef void (*TestCaseInitFp)(void); typedef void (*InitTestInvironmentFp)(void);
//!< Function pointer to a test case quit function //!< Function pointer to a test case quit function
typedef int (*TestCaseQuitFp)(void); typedef int (*QuitTestInvironmentFp)(void);
//!< Function pointer to a test case set up function
typedef void (*TestCaseSetUpFp)(void *arg);
//!< Function pointer to a test case tear down function
typedef void (*TestCaseTearDownFp)(void *arg);
//!< Flag for executing tests in-process //!< Flag for executing tests in-process
...@@ -105,20 +109,24 @@ typedef struct TestCaseItem { ...@@ -105,20 +109,24 @@ typedef struct TestCaseItem {
long requirements; long requirements;
long timeout; long timeout;
TestCaseInitFp testCaseInit; InitTestInvironmentFp initTestEnvironment;
TestCaseSetUpFp testSetUp;
TestCaseFp testCase; TestCaseFp testCase;
TestCaseQuitFp testCaseQuit; TestCaseTearDownFp testTearDown;
QuitTestInvironmentFp quitTestEnvironment;
struct TestCaseItem *next; struct TestCaseItem *next;
} TestCase; } TestCase;
/*! Some function prototypes. Add the rest of functions and move to runner.h */ /*! Some function prototypes. Add the rest of functions and move to runner.h */
TestCaseFp LoadTestCaseFunction(void *suite, char *testName); TestCaseFp LoadTestCaseFunction(void *suite, char *testName);
TestCaseInitFp LoadTestCaseInitFunction(void *suite); InitTestInvironmentFp LoadInitTestInvironmentFunction(void *suite);
TestCaseQuitFp LoadTestCaseQuitFunction(void *suite); QuitTestInvironmentFp LoadQuitTestInvironmentFunction(void *suite);
TestCaseReference **QueryTestCaseReferences(void *library); TestCaseReference **QueryTestCaseReferences(void *library);
TestCaseSetUpFp LoadTestSetUpFunction(void *suite);
TestCaseTearDownFp LoadTestTearDownFunction(void *suite);
/*! Pointers to selected logger implementation */ /*! Pointers to selected logger implementation */
RunStartedFp RunStarted = NULL; RunStartedFp RunStarted = NULL;
...@@ -159,18 +167,26 @@ LoadTestCases(TestSuiteReference *suites) ...@@ -159,18 +167,26 @@ LoadTestCases(TestSuiteReference *suites)
void *suite = suiteReference->library; void *suite = suiteReference->library;
// Load test case functions // Load test case functions
TestCaseInitFp testCaseInit = LoadTestCaseInitFunction(suiteReference->library); InitTestInvironmentFp initTestEnvironment = LoadInitTestInvironmentFunction(suiteReference->library);
TestCaseQuitFp testCaseQuit = LoadTestCaseQuitFunction(suiteReference->library); QuitTestInvironmentFp quitTestEnvironment = LoadQuitTestInvironmentFunction(suiteReference->library);
TestCaseFp testCase = (TestCaseFp) LoadTestCaseFunction(suiteReference->library, testReference->name);
TestCaseSetUpFp testSetUp = LoadTestSetUpFunction(suiteReference->library);
TestCaseTearDownFp testTearDown = LoadTestTearDownFunction(suiteReference->library);
TestCaseFp testCase = LoadTestCaseFunction(suiteReference->library, testReference->name);
// Do the filtering // Do the filtering
if(FilterTestCase(testReference)) { if(FilterTestCase(testReference)) {
TestCase *item = SDL_malloc(sizeof(TestCase)); TestCase *item = SDL_malloc(sizeof(TestCase));
memset(item, 0, sizeof(TestCase)); memset(item, 0, sizeof(TestCase));
item->testCaseInit = testCaseInit; item->initTestEnvironment = initTestEnvironment;
item->quitTestEnvironment = quitTestEnvironment;
item->testSetUp = testSetUp;
item->testTearDown = testTearDown;
item->testCase = testCase; item->testCase = testCase;
item->testCaseQuit = testCaseQuit;
// copy suite name // copy suite name
int length = SDL_strlen(suiteReference->name) + 1; int length = SDL_strlen(suiteReference->name) + 1;
...@@ -287,7 +303,9 @@ ScanForTestSuites(char *directoryName, char *extension) ...@@ -287,7 +303,9 @@ ScanForTestSuites(char *directoryName, char *extension)
Entry *entry = NULL; Entry *entry = NULL;
if(!directory) { if(!directory) {
perror("Couldn't open test suite directory!"); fprintf(stderr, "Failed to open test suite directory: %s\n", directoryName);
perror("Error message");
exit(1);
} }
while(entry = readdir(directory)) { while(entry = readdir(directory)) {
...@@ -458,42 +476,82 @@ LoadTestCaseFunction(void *suite, char *testName) ...@@ -458,42 +476,82 @@ LoadTestCaseFunction(void *suite, char *testName)
/*! /*!
* Loads function that initialises the test case from the * Loads function that sets up a fixture for a test case. Note: if there's
* given test suite. * no SetUp function present in the suite the function will return NULL.
* *
* \param suite Used test suite * \param suite Used test suite
* *
* \return Function pointer (TestCaseInit) which points to loaded init function. NULL if function fails. * \return Function pointer to test case's set up function
*/ */
TestCaseInitFp TestCaseSetUpFp
LoadTestCaseInitFunction(void *suite) { LoadTestSetUpFunction(void *suite) {
TestCaseInitFp testCaseInit = (TestCaseInitFp) SDL_LoadFunction(suite, "_TestCaseInit"); TestCaseSetUpFp testSetUp = (TestCaseSetUpFp) SDL_LoadFunction(suite, "SetUp");
if(testCaseInit == NULL) { if(testSetUp == NULL) {
fprintf(stderr, "Loading TestCaseInit function failed, testCaseInit == NULL\n"); fprintf(stderr, "Loading SetUp function failed, testSetUp == NULL\n");
fprintf(stderr, "%s\n", SDL_GetError()); fprintf(stderr, "%s\n", SDL_GetError());
} }
return testCaseInit; return testSetUp;
} }
/*! /*!
* Loads function that deinitialises the executed test case from the * Loads function that tears down a fixture for a test case. Note: if there's
* given test suite. * no TearDown function present in the suite the function will return NULL.
* *
* \param suite Used test suite * \param suite Used test suite
* *
* \return Function pointer (TestCaseInit) which points to loaded init function. NULL if function fails. * \return Function pointer to test case's tear down function
*/ */
TestCaseQuitFp TestCaseTearDownFp
LoadTestCaseQuitFunction(void *suite) { LoadTestTearDownFunction(void *suite) {
TestCaseQuitFp testCaseQuit = (TestCaseQuitFp) SDL_LoadFunction(suite, "_TestCaseQuit"); TestCaseTearDownFp testTearDown = (TestCaseTearDownFp) SDL_LoadFunction(suite, "TearDown");
if(testCaseQuit == NULL) { if(testTearDown == NULL) {
fprintf(stderr, "Loading TestCaseQuit function failed, testCaseQuit == NULL\n"); fprintf(stderr, "Loading TearDown function failed, testTearDown == NULL\n");
fprintf(stderr, "%s\n", SDL_GetError()); fprintf(stderr, "%s\n", SDL_GetError());
} }
return testCaseQuit; return testTearDown;
}
/*!
* Loads function that initialises the test environment for
* a test case in the given suite.
*
* \param suite Used test suite
*
* \return Function pointer (InitTestInvironmentFp) which points to loaded init function. NULL if function fails.
*/
InitTestInvironmentFp
LoadInitTestInvironmentFunction(void *suite) {
InitTestInvironmentFp testEnvInit = (InitTestInvironmentFp) SDL_LoadFunction(suite, "_InitTestEnvironment");
if(testEnvInit == NULL) {
fprintf(stderr, "Loading _InitTestInvironment function failed, testEnvInit == NULL\n");
fprintf(stderr, "%s\n", SDL_GetError());
}
return testEnvInit;
}
/*!
* Loads function that deinitialises the test environment (and returns
* the test case's result) created for the test case in the given suite.
*
* \param suite Used test suite
*
* \return Function pointer (QuitTestInvironmentFp) which points to loaded init function. NULL if function fails.
*/
QuitTestInvironmentFp
LoadQuitTestInvironmentFunction(void *suite) {
QuitTestInvironmentFp testEnvQuit = (QuitTestInvironmentFp) SDL_LoadFunction(suite, "_QuitTestEnvironment");
if(testEnvQuit == NULL) {
fprintf(stderr, "Loading _QuitTestEnvironment function failed, testEnvQuit == NULL\n");
fprintf(stderr, "%s\n", SDL_GetError());
}
return testEnvQuit;
} }
...@@ -536,19 +594,37 @@ int ...@@ -536,19 +594,37 @@ int
ExecuteTest(TestCase *testItem) { ExecuteTest(TestCase *testItem) {
int retVal = 1; int retVal = 1;
if(execute_inproc) { if(execute_inproc) {
testItem->testCaseInit(); testItem->initTestEnvironment();
if(testItem->testSetUp) {
testItem->testSetUp(0x0);
}
testItem->testCase(0x0); testItem->testCase(0x0);
retVal = testItem->testCaseQuit(); if(testItem->testTearDown) {
testItem->testTearDown(0x0);
}
retVal = testItem->quitTestEnvironment();
} else { } else {
int childpid = fork(); int childpid = fork();
if(childpid == 0) { if(childpid == 0) {
testItem->testCaseInit(); testItem->initTestEnvironment();
if(testItem->testSetUp) {
testItem->testSetUp(0x0);
}
testItem->testCase(0x0); testItem->testCase(0x0);
exit(testItem->testCaseQuit()); // note: if test case is is aborted by some signal
// then TearDown function won't be called
if(testItem->testTearDown) {
testItem->testTearDown(0x0);
}
exit(testItem->quitTestEnvironment());
} else { } else {
int stat_lock = -1; int stat_lock = -1;
int child = wait(&stat_lock); int child = wait(&stat_lock);
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
/*! \file /*! \file
* Dummy test suite for test runner. This can be used as a base for * Dummy test suite for test runner. This can be used as a base for
* writing new tests. Dummy suite also works as reference to using * writing new tests. Dummy suite also works as reference to using
* various asserts and (possible) other utilities. * various asserts and other (possible) utilities.
*/ */
#include <stdio.h> #include <stdio.h>
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
#include "../SDL_test.h" #include "../SDL_test.h"
// \todo add some helpful commenting for possible test writers?
/* Test case references */ /* Test case references */
static const TestCaseReference test1 = static const TestCaseReference test1 =
(TestCaseReference){ "dummycase1", "description", TEST_ENABLED, 0, 0}; (TestCaseReference){ "dummycase1", "description", TEST_ENABLED, 0, 0};
...@@ -52,6 +50,37 @@ TestCaseReference **QueryTestSuite() { ...@@ -52,6 +50,37 @@ TestCaseReference **QueryTestSuite() {
return (TestCaseReference **)testSuite; return (TestCaseReference **)testSuite;
} }
/* Create test fixture */
/*!
* SetUp function can be used to create a test fixture for test cases.
* The function will be called right before executing the test case.
*
* Note: this function is optional.
*
* \param arg parameters given to test. Usually NULL
*/
void
SetUp(void *arg)
{
// create test fixture,
// for example, set up static variables used by test cases here
}
/*!
* TearDown function can be used to destroy a test fixture for test cases.
* The function will be called right after executing the test case.
*
* Note: this function is optional.
*
* \param arg parameters given to test. Usually NULL
*/
void
TearDown(void *arg)
{
// destroy test fixture
}
/* Test case functions */ /* Test case functions */
void void
dummycase1(void *arg) dummycase1(void *arg)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment