/* * Copyright (c) 2002-2006 Asim Jalis * * This library is released under the zlib/libpng license as described at * * http://www.opensource.org/licenses/zlib-license.html * * Here is the statement of the license: * * 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, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source distribution. */ /* * This file has been modified from the original distribution. */ #include #include #include #include #include #include "CuTest.h" static int verbose = 0; void CuInit(int argc, char *argv[]) { int i; /* Windows doesn't have getopt, so we have to fake it. We can't use * apr_getopt, because CuTest is meant to be a stand-alone test suite */ for (i = 0; i < argc; i++) { if (!strcmp(argv[i], "-v")) { verbose = 1; } } } /*-------------------------------------------------------------------------* * CuStr *-------------------------------------------------------------------------*/ char* CuStrAlloc(int size) { char* new = (char*) malloc( sizeof(char) * (size) ); return new; } char* CuStrCopy(const char* old) { int len = strlen(old); char* new = CuStrAlloc(len + 1); strcpy(new, old); return new; } /*-------------------------------------------------------------------------* * CuString *-------------------------------------------------------------------------*/ void CuStringInit(CuString* str) { str->length = 0; str->size = STRING_MAX; str->buffer = (char*) malloc(sizeof(char) * str->size); str->buffer[0] = '\0'; } CuString* CuStringNew(void) { CuString* str = (CuString*) malloc(sizeof(CuString)); str->length = 0; str->size = STRING_MAX; str->buffer = (char*) malloc(sizeof(char) * str->size); str->buffer[0] = '\0'; return str; } void CuStringResize(CuString* str, int newSize) { str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); str->size = newSize; } void CuStringAppend(CuString* str, const char* text) { int length = strlen(text); if (str->length + length + 1 >= str->size) CuStringResize(str, str->length + length + 1 + STRING_INC); str->length += length; strcat(str->buffer, text); } void CuStringAppendChar(CuString* str, char ch) { char text[2]; text[0] = ch; text[1] = '\0'; CuStringAppend(str, text); } void CuStringAppendFormat(CuString* str, const char* format, ...) { va_list argp; char buf[HUGE_STRING_LEN]; va_start(argp, format); vsprintf(buf, format, argp); va_end(argp); CuStringAppend(str, buf); } void CuStringRead(CuString *str, char *path) { path = strdup(str->buffer); } /*-------------------------------------------------------------------------* * CuTest *-------------------------------------------------------------------------*/ void CuTestInit(CuTest* t, char* name, TestFunction function) { t->name = CuStrCopy(name); t->notimpl = 0; t->failed = 0; t->ran = 0; t->message = NULL; t->function = function; t->jumpBuf = NULL; } CuTest* CuTestNew(char* name, TestFunction function) { CuTest* tc = CU_ALLOC(CuTest); CuTestInit(tc, name, function); return tc; } void CuNotImpl(CuTest* tc, const char* message) { CuString* newstr = CuStringNew(); CuStringAppend(newstr, message); CuStringAppend(newstr, " not implemented on this platform"); tc->notimpl = 1; tc->message = CuStrCopy(newstr->buffer); if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); } void CuFail(CuTest* tc, const char* message) { tc->failed = 1; tc->message = CuStrCopy(message); if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); } void CuAssert(CuTest* tc, const char* message, int condition) { if (condition) return; CuFail(tc, message); } void CuAssertTrue(CuTest* tc, int condition) { if (condition) return; CuFail(tc, "assert failed"); } void CuAssertStrNEquals(CuTest* tc, const char* expected, const char* actual, int n) { CuString* message; if (strncmp(expected, actual, n) == 0) return; message = CuStringNew(); CuStringAppend(message, "expected\n---->\n"); CuStringAppend(message, expected); CuStringAppend(message, "\n<----\nbut saw\n---->\n"); CuStringAppend(message, actual); CuStringAppend(message, "\n<----"); CuFail(tc, message->buffer); } void CuAssertStrEquals(CuTest* tc, const char* expected, const char* actual) { CuString* message; if (strcmp(expected, actual) == 0) return; message = CuStringNew(); CuStringAppend(message, "expected\n---->\n"); CuStringAppend(message, expected); CuStringAppend(message, "\n<----\nbut saw\n---->\n"); CuStringAppend(message, actual); CuStringAppend(message, "\n<----"); CuFail(tc, message->buffer); } void CuAssertIntEquals(CuTest* tc, int expected, int actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected <%d> but was <%d>", expected, actual); CuFail(tc, buf); } void CuAssertPtrEquals(CuTest* tc, const void* expected, const void* actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected pointer <%p> but was <%p>", expected, actual); CuFail(tc, buf); } void CuAssertPtrNotNull(CuTest* tc, const void* pointer) { char buf[STRING_MAX]; if (pointer != NULL ) return; sprintf(buf, "null pointer unexpected, but was <%p>", pointer); CuFail(tc, buf); } void CuTestRun(CuTest* tc) { jmp_buf buf; tc->jumpBuf = &buf; if (setjmp(buf) == 0) { tc->ran = 1; (tc->function)(tc); } tc->jumpBuf = 0; } /*-------------------------------------------------------------------------* * CuSuite *-------------------------------------------------------------------------*/ void CuSuiteInit(CuSuite* testSuite, char *name) { testSuite->name = strdup(name); testSuite->count = 0; testSuite->failCount = 0; testSuite->notimplCount = 0; } CuSuite* CuSuiteNew(char *name) { CuSuite* testSuite = CU_ALLOC(CuSuite); CuSuiteInit(testSuite, name); return testSuite; } void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) { assert(testSuite->count < MAX_TEST_CASES); testSuite->list[testSuite->count] = testCase; testSuite->count++; } void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) { int i; for (i = 0 ; i < testSuite2->count ; ++i) { CuTest* testCase = testSuite2->list[i]; CuSuiteAdd(testSuite, testCase); } } void CuSuiteRun(CuSuite* testSuite) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; CuTestRun(testCase); if (testCase->failed) { testSuite->failCount += 1; } if (testCase->notimpl) { testSuite->notimplCount += 1; } } } void CuSuiteSummary(CuSuite* testSuite, CuString* summary) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; CuStringAppend(summary, testCase->failed ? "F" : testCase->notimpl ? "N": "."); } CuStringAppend(summary, "\n"); } void CuSuiteOverView(CuSuite* testSuite, CuString* details) { CuStringAppendFormat(details, "%d %s run: %d passed, %d failed, " "%d not implemented.\n", testSuite->count, testSuite->count == 1 ? "test" : "tests", testSuite->count - testSuite->failCount - testSuite->notimplCount, testSuite->failCount, testSuite->notimplCount); } void CuSuiteDetails(CuSuite* testSuite, CuString* details) { int i; int failCount = 0; if (testSuite->failCount != 0 && verbose) { CuStringAppendFormat(details, "\nFailed tests in %s:\n", testSuite->name); for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; if (testCase->failed) { failCount++; CuStringAppendFormat(details, "%d) %s: %s\n", failCount, testCase->name, testCase->message); } } } if (testSuite->notimplCount != 0 && verbose) { CuStringAppendFormat(details, "\nNot Implemented tests in %s:\n", testSuite->name); for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; if (testCase->notimpl) { failCount++; CuStringAppendFormat(details, "%d) %s: %s\n", failCount, testCase->name, testCase->message); } } } } /*-------------------------------------------------------------------------* * CuSuiteList *-------------------------------------------------------------------------*/ CuSuiteList* CuSuiteListNew(char *name) { CuSuiteList* testSuite = CU_ALLOC(CuSuiteList); testSuite->name = strdup(name); testSuite->count = 0; return testSuite; } void CuSuiteListAdd(CuSuiteList *suites, CuSuite *origsuite) { assert(suites->count < MAX_TEST_CASES); suites->list[suites->count] = origsuite; suites->count++; } void CuSuiteListRun(CuSuiteList* testSuite) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuSuite* testCase = testSuite->list[i]; CuSuiteRun(testCase); } } static const char *genspaces(int i) { char *str = malloc((i + 1) * sizeof(char)); memset(str, ' ', i); str[i] = '\0'; return str; } void CuSuiteListRunWithSummary(CuSuiteList* testSuite) { int i; printf("%s:\n", testSuite->name); for (i = 0 ; i < testSuite->count ; ++i) { CuSuite* testCase = testSuite->list[i]; CuString *str = CuStringNew(); printf(" %s:%s", testCase->name, genspaces(21 - strlen(testCase->name))); fflush(stdout); CuSuiteRun(testCase); CuSuiteSummary(testCase, str); printf(" %s", str->buffer); } printf("\n"); } void CuSuiteListSummary(CuSuiteList* testSuite, CuString* summary) { int i; CuStringAppendFormat(summary, "%s:\n", testSuite->name); for (i = 0 ; i < testSuite->count ; ++i) { CuSuite* testCase = testSuite->list[i]; CuString *str = CuStringNew(); CuSuiteSummary(testCase, str); CuStringAppend(summary, " "); CuStringAppend(summary, str->buffer); } CuStringAppend(summary, "\n"); } int CuSuiteListDetails(CuSuiteList* testSuite, CuString* details) { int i; int failCount = 0; int notImplCount = 0; int count = 0; for (i = 0 ; i < testSuite->count ; ++i) { failCount += testSuite->list[i]->failCount; notImplCount += testSuite->list[i]->notimplCount; count += testSuite->list[i]->count; } CuStringAppendFormat(details, "%d %s run: %d passed, %d failed, " "%d not implemented.\n", count, count == 1 ? "test" : "tests", count - failCount - notImplCount, failCount, notImplCount); if (failCount != 0 && verbose) { for (i = 0 ; i < testSuite->count ; ++i) { CuString *str = CuStringNew(); CuSuite* testCase = testSuite->list[i]; if (testCase->failCount) { CuSuiteDetails(testCase, str); CuStringAppend(details, str->buffer); } } } if (notImplCount != 0 && verbose) { for (i = 0 ; i < testSuite->count ; ++i) { CuString *str = CuStringNew(); CuSuite* testCase = testSuite->list[i]; if (testCase->notimplCount) { CuSuiteDetails(testCase, str); CuStringAppend(details, str->buffer); } } } return failCount; }