From f089d2ae776a450c11901ddab43c44da8af99d2b Mon Sep 17 00:00:00 2001 From: Markus Kauppila Date: Mon, 11 Jul 2011 17:55:35 +0300 Subject: [PATCH] Added SetUp/TearDown functions for test suites. --- test/test-automation/SDL_test.c | 9 +- test/test-automation/SDL_test.h | 17 ++- test/test-automation/runner.c | 146 ++++++++++++++++----- test/test-automation/testdummy/testdummy.c | 35 ++++- 4 files changed, 157 insertions(+), 50 deletions(-) diff --git a/test/test-automation/SDL_test.c b/test/test-automation/SDL_test.c index d9777fe71..0462230f8 100644 --- a/test/test-automation/SDL_test.c +++ b/test/test-automation/SDL_test.c @@ -1,4 +1,4 @@ -/* + /* Copyright (C) 2011 Markus Kauppila This software is provided 'as-is', without any express or implied @@ -36,7 +36,7 @@ int _testAssertsFailed; int _testAssertsPassed; void -_TestCaseInit() +_InitTestEnvironment() // InitTestEnvironment { _testReturnValue = 0; _testAssertsFailed = 0; @@ -44,7 +44,7 @@ _TestCaseInit() } int -_TestCaseQuit() +_QuitTestEnvironment() { AssertSummary(_testAssertsFailed + _testAssertsPassed, _testAssertsFailed, _testAssertsPassed, time(0)); @@ -76,7 +76,6 @@ AssertEquals(const int expected, const int actual, char *message, ...) AssertWithValues("AssertEquals", 1, buf, actual, expected, time(0)); - _testReturnValue = 0; _testAssertsPassed++; } } @@ -98,7 +97,6 @@ AssertTrue(int condition, char *message, ...) } else { Assert("AssertTrue", 1, buf, time(0)); - _testReturnValue = 0; _testAssertsPassed++; } } @@ -115,7 +113,6 @@ AssertPass(char *message, ...) Assert("AssertPass", 1, buf, time(0)); - _testReturnValue = 0; _testAssertsPassed++; } diff --git a/test/test-automation/SDL_test.h b/test/test-automation/SDL_test.h index 590c49327..efb651f8a 100644 --- a/test/test-automation/SDL_test.h +++ b/test/test-automation/SDL_test.h @@ -25,6 +25,10 @@ #include "logger.h" +#include "common/common.h" +#include "common/images.h" + + extern int _testReturnValue; extern int _testAssertsFailed; extern int _testAssertsPassed; @@ -52,18 +56,18 @@ typedef struct TestCaseReference { } TestCaseReference; /*! - * Initialized the test case. Must be called at - * the beginning of every test case, before doing - * anything else. + * Initialized the test environment such as asserts. Must be called at + * the beginning of every test case, before doing 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 */ -int _TestCaseQuit(); +int _QuitTestEnvironment(); /*! * Assert function. Tests if the expected value equals the actual value, then @@ -74,6 +78,7 @@ int _TestCaseQuit(); * \param message Message that will be printed if assert fails */ void AssertEquals(const int expected, const int actual, char *message, ...); + /*! * Assert function. Tests if the given condition is true. True in * this case means non-zero value. If the condition is true, the diff --git a/test/test-automation/runner.c b/test/test-automation/runner.c index 42b964977..9c52d1f89 100644 --- a/test/test-automation/runner.c +++ b/test/test-automation/runner.c @@ -39,9 +39,13 @@ //!< Function pointer to a test case function typedef void (*TestCaseFp)(void *arg); //!< Function pointer to a test case init function -typedef void (*TestCaseInitFp)(void); +typedef void (*InitTestInvironmentFp)(void); //!< 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 @@ -105,20 +109,24 @@ typedef struct TestCaseItem { long requirements; long timeout; - TestCaseInitFp testCaseInit; + InitTestInvironmentFp initTestEnvironment; + TestCaseSetUpFp testSetUp; TestCaseFp testCase; - TestCaseQuitFp testCaseQuit; + TestCaseTearDownFp testTearDown; + QuitTestInvironmentFp quitTestEnvironment; struct TestCaseItem *next; } TestCase; - /*! Some function prototypes. Add the rest of functions and move to runner.h */ TestCaseFp LoadTestCaseFunction(void *suite, char *testName); -TestCaseInitFp LoadTestCaseInitFunction(void *suite); -TestCaseQuitFp LoadTestCaseQuitFunction(void *suite); +InitTestInvironmentFp LoadInitTestInvironmentFunction(void *suite); +QuitTestInvironmentFp LoadQuitTestInvironmentFunction(void *suite); TestCaseReference **QueryTestCaseReferences(void *library); +TestCaseSetUpFp LoadTestSetUpFunction(void *suite); +TestCaseTearDownFp LoadTestTearDownFunction(void *suite); + /*! Pointers to selected logger implementation */ RunStartedFp RunStarted = NULL; @@ -159,18 +167,26 @@ LoadTestCases(TestSuiteReference *suites) void *suite = suiteReference->library; // Load test case functions - TestCaseInitFp testCaseInit = LoadTestCaseInitFunction(suiteReference->library); - TestCaseQuitFp testCaseQuit = LoadTestCaseQuitFunction(suiteReference->library); - TestCaseFp testCase = (TestCaseFp) LoadTestCaseFunction(suiteReference->library, testReference->name); + InitTestInvironmentFp initTestEnvironment = LoadInitTestInvironmentFunction(suiteReference->library); + QuitTestInvironmentFp quitTestEnvironment = LoadQuitTestInvironmentFunction(suiteReference->library); + + TestCaseSetUpFp testSetUp = LoadTestSetUpFunction(suiteReference->library); + TestCaseTearDownFp testTearDown = LoadTestTearDownFunction(suiteReference->library); + + TestCaseFp testCase = LoadTestCaseFunction(suiteReference->library, testReference->name); // Do the filtering if(FilterTestCase(testReference)) { TestCase *item = SDL_malloc(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->testCaseQuit = testCaseQuit; // copy suite name int length = SDL_strlen(suiteReference->name) + 1; @@ -287,7 +303,9 @@ ScanForTestSuites(char *directoryName, char *extension) Entry *entry = NULL; 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)) { @@ -458,42 +476,82 @@ LoadTestCaseFunction(void *suite, char *testName) /*! - * Loads function that initialises the test case from the - * given test suite. + * Loads function that sets up a fixture for a test case. Note: if there's + * no SetUp function present in the suite the function will return NULL. + * + * \param suite Used test suite + * + * \return Function pointer to test case's set up function + */ +TestCaseSetUpFp +LoadTestSetUpFunction(void *suite) { + TestCaseSetUpFp testSetUp = (TestCaseSetUpFp) SDL_LoadFunction(suite, "SetUp"); + if(testSetUp == NULL) { + fprintf(stderr, "Loading SetUp function failed, testSetUp == NULL\n"); + fprintf(stderr, "%s\n", SDL_GetError()); + } + + return testSetUp; +} + + +/*! + * Loads function that tears down a fixture for a test case. Note: if there's + * no TearDown function present in the suite the function will return NULL. + * + * \param suite Used test suite + * + * \return Function pointer to test case's tear down function + */ +TestCaseTearDownFp +LoadTestTearDownFunction(void *suite) { + TestCaseTearDownFp testTearDown = (TestCaseTearDownFp) SDL_LoadFunction(suite, "TearDown"); + if(testTearDown == NULL) { + fprintf(stderr, "Loading TearDown function failed, testTearDown == NULL\n"); + fprintf(stderr, "%s\n", SDL_GetError()); + } + + 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 (TestCaseInit) which points to loaded init function. NULL if function fails. + * \return Function pointer (InitTestInvironmentFp) which points to loaded init function. NULL if function fails. */ -TestCaseInitFp -LoadTestCaseInitFunction(void *suite) { - TestCaseInitFp testCaseInit = (TestCaseInitFp) SDL_LoadFunction(suite, "_TestCaseInit"); - if(testCaseInit == NULL) { - fprintf(stderr, "Loading TestCaseInit function failed, testCaseInit == NULL\n"); +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 testCaseInit; + return testEnvInit; } /*! - * Loads function that deinitialises the executed test case from the - * given test suite. + * 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 (TestCaseInit) which points to loaded init function. NULL if function fails. + * \return Function pointer (QuitTestInvironmentFp) which points to loaded init function. NULL if function fails. */ -TestCaseQuitFp -LoadTestCaseQuitFunction(void *suite) { - TestCaseQuitFp testCaseQuit = (TestCaseQuitFp) SDL_LoadFunction(suite, "_TestCaseQuit"); - if(testCaseQuit == NULL) { - fprintf(stderr, "Loading TestCaseQuit function failed, testCaseQuit == NULL\n"); +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 testCaseQuit; + return testEnvQuit; } @@ -536,19 +594,37 @@ int ExecuteTest(TestCase *testItem) { int retVal = 1; if(execute_inproc) { - testItem->testCaseInit(); + testItem->initTestEnvironment(); + + if(testItem->testSetUp) { + testItem->testSetUp(0x0); + } testItem->testCase(0x0); - retVal = testItem->testCaseQuit(); + if(testItem->testTearDown) { + testItem->testTearDown(0x0); + } + + retVal = testItem->quitTestEnvironment(); } else { int childpid = fork(); if(childpid == 0) { - testItem->testCaseInit(); + testItem->initTestEnvironment(); + + if(testItem->testSetUp) { + testItem->testSetUp(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 { int stat_lock = -1; int child = wait(&stat_lock); diff --git a/test/test-automation/testdummy/testdummy.c b/test/test-automation/testdummy/testdummy.c index 20ad7ac91..c42792832 100644 --- a/test/test-automation/testdummy/testdummy.c +++ b/test/test-automation/testdummy/testdummy.c @@ -21,7 +21,7 @@ /*! \file * 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 - * various asserts and (possible) other utilities. + * various asserts and other (possible) utilities. */ #include @@ -30,8 +30,6 @@ #include "../SDL_test.h" -// \todo add some helpful commenting for possible test writers? - /* Test case references */ static const TestCaseReference test1 = (TestCaseReference){ "dummycase1", "description", TEST_ENABLED, 0, 0}; @@ -52,6 +50,37 @@ TestCaseReference **QueryTestSuite() { 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 */ void dummycase1(void *arg)