00001 #include <assert.h>
00002 #include <setjmp.h>
00003 #include <stdlib.h>
00004 #include <stdio.h>
00005 #include <string.h>
00006 #include <math.h>
00007
00008 #include "CuTestSmall.h"
00009
00010
00011
00012
00013
00014 char* CuStrAlloc(int size)
00015 {
00016 char* newStr = (char*) malloc( sizeof(char) * (size) );
00017 assert(newStr != NULL);
00018 return newStr;
00019 }
00020
00021 char* CuStrCopy(const char* old)
00022 {
00023 int len = strlen(old);
00024 char* newStr = CuStrAlloc(len + 1);
00025 strcpy(newStr, old);
00026 return newStr;
00027 }
00028
00029
00030
00031
00032
00033 void CuStringInit(CuString* str)
00034 {
00035 str->length = 0;
00036 str->size = STRING_MAX;
00037 str->buffer = (char*) malloc(sizeof(char) * str->size);
00038 assert(str->buffer != NULL);
00039 str->buffer[0] = '\0';
00040 }
00041
00042 CuString* CuStringNew(void)
00043 {
00044 CuString* str = (CuString*) malloc(sizeof(CuString));
00045 assert(str != NULL);
00046 str->length = 0;
00047 str->size = STRING_MAX;
00048 str->buffer = (char*) malloc(sizeof(char) * str->size);
00049 assert(str->buffer != NULL);
00050 str->buffer[0] = '\0';
00051 return str;
00052 }
00053
00054 void CuStringResize(CuString* str, int newSize)
00055 {
00056 str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize);
00057 assert(str->buffer != NULL);
00058 str->size = newSize;
00059 }
00060
00061 void CuStringAppend(CuString* str, const char* text)
00062 {
00063 int length;
00064
00065 if (text == NULL) {
00066 text = "NULL";
00067 }
00068
00069 length = strlen(text);
00070 if (str->length + length + 1 >= str->size)
00071 CuStringResize(str, str->length + length + 1 + STRING_INC);
00072 str->length += length;
00073 strcat(str->buffer, text);
00074 }
00075
00076 void CuStringAppendChar(CuString* str, char ch)
00077 {
00078 char text[2];
00079 text[0] = ch;
00080 text[1] = '\0';
00081 CuStringAppend(str, text);
00082 }
00083
00084 void CuStringAppendFormat(CuString* str, const char* format, ...)
00085 {
00086 va_list argp;
00087 char buf[HUGE_STRING_LEN];
00088 va_start(argp, format);
00089 vsprintf(buf, format, argp);
00090 va_end(argp);
00091 CuStringAppend(str, buf);
00092 }
00093
00094 void CuStringInsert(CuString* str, const char* text, int pos)
00095 {
00096 int length = strlen(text);
00097 if (pos > str->length)
00098 pos = str->length;
00099 if (str->length + length + 1 >= str->size)
00100 CuStringResize(str, str->length + length + 1 + STRING_INC);
00101 memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1);
00102 str->length += length;
00103 memcpy(str->buffer + pos, text, length);
00104 }
00105
00106
00107
00108
00109
00110 void CuTestInit(CuTest* t, const char* name, TestFunction function)
00111 {
00112 t->name = CuStrCopy(name);
00113 t->failed = 0;
00114 t->ran = 0;
00115 t->message = NULL;
00116 t->function = function;
00117 t->jumpBuf = NULL;
00118 }
00119
00120 CuTest* CuTestNew(const char* name, TestFunction function)
00121 {
00122 CuTest* tc = CU_ALLOC(CuTest);
00123 assert(tc != NULL);
00124 CuTestInit(tc, name, function);
00125 return tc;
00126 }
00127
00128 void CuTestRun(CuTest* tc)
00129 {
00130 jmp_buf buf;
00131 tc->jumpBuf = &buf;
00132 if (setjmp(buf) == 0)
00133 {
00134 tc->ran = 1;
00135 (tc->function)(tc);
00136 }
00137 tc->jumpBuf = 0;
00138 }
00139
00140 static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string)
00141 {
00142 char buf[HUGE_STRING_LEN];
00143
00144 sprintf(buf, "%s:%d: ", file, line);
00145 CuStringInsert(string, buf, 0);
00146
00147 tc->failed = 1;
00148 tc->message = string->buffer;
00149 if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
00150 }
00151
00152 void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message)
00153 {
00154 CuString string;
00155
00156 CuStringInit(&string);
00157 if (message2 != NULL)
00158 {
00159 CuStringAppend(&string, message2);
00160 CuStringAppend(&string, ": ");
00161 }
00162 CuStringAppend(&string, message);
00163 CuFailInternal(tc, file, line, &string);
00164 }
00165
00166 void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition)
00167 {
00168 if (condition) return;
00169 CuFail_Line(tc, file, line, NULL, message);
00170 }
00171
00172 void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
00173 const char* expected, const char* actual)
00174 {
00175 CuString string;
00176 if ((expected == NULL && actual == NULL) ||
00177 (expected != NULL && actual != NULL &&
00178 strcmp(expected, actual) == 0))
00179 {
00180 return;
00181 }
00182
00183 CuStringInit(&string);
00184 if (message != NULL)
00185 {
00186 CuStringAppend(&string, message);
00187 CuStringAppend(&string, ": ");
00188 }
00189 CuStringAppend(&string, "expected <");
00190 CuStringAppend(&string, expected);
00191 CuStringAppend(&string, "> but was <");
00192 CuStringAppend(&string, actual);
00193 CuStringAppend(&string, ">");
00194 CuFailInternal(tc, file, line, &string);
00195 }
00196
00197 void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
00198 int expected, int actual)
00199 {
00200 char buf[STRING_MAX];
00201 if (expected == actual) return;
00202 sprintf(buf, "expected <%d> but was <%d>", expected, actual);
00203 CuFail_Line(tc, file, line, message, buf);
00204 }
00205
00206 void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
00207 double expected, double actual, double delta)
00208 {
00209 char buf[STRING_MAX];
00210 if (fabs(expected - actual) <= delta) return;
00211 sprintf(buf, "expected <%lf> but was <%lf>", expected, actual);
00212 CuFail_Line(tc, file, line, message, buf);
00213 }
00214
00215 void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
00216 void* expected, void* actual)
00217 {
00218 char buf[STRING_MAX];
00219 if (expected == actual) return;
00220 sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual);
00221 CuFail_Line(tc, file, line, message, buf);
00222 }
00223
00224
00225
00226
00227
00228
00229 void CuSuiteInit(CuSuite* testSuite)
00230 {
00231 testSuite->count = 0;
00232 testSuite->failCount = 0;
00233 }
00234
00235 CuSuite* CuSuiteNew(void)
00236 {
00237 CuSuite* testSuite = CU_ALLOC(CuSuite);
00238 assert(testSuite);
00239 CuSuiteInit(testSuite);
00240 return testSuite;
00241 }
00242
00243 void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase)
00244 {
00245 assert(testSuite->count < MAX_TEST_CASES);
00246 testSuite->list[testSuite->count] = testCase;
00247 testSuite->count++;
00248 }
00249
00250 void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2)
00251 {
00252 int i;
00253 for (i = 0 ; i < testSuite2->count ; ++i)
00254 {
00255 CuTest* testCase = testSuite2->list[i];
00256 CuSuiteAdd(testSuite, testCase);
00257 }
00258 }
00259
00260 void CuSuiteRun(CuSuite* testSuite)
00261 {
00262 int i;
00263 for (i = 0 ; i < testSuite->count ; ++i)
00264 {
00265 CuTest* testCase = testSuite->list[i];
00266 CuTestRun(testCase);
00267 if (testCase->failed) { testSuite->failCount += 1; }
00268 }
00269 }
00270
00271 void CuSuiteSummary(CuSuite* testSuite, CuString* summary)
00272 {
00273 int i;
00274 for (i = 0 ; i < testSuite->count ; ++i)
00275 {
00276 CuTest* testCase = testSuite->list[i];
00277 CuStringAppend(summary, testCase->failed ? "F" : ".");
00278 }
00279 CuStringAppend(summary, "\n\n");
00280 }
00281
00282 void CuSuiteDetails(CuSuite* testSuite, CuString* details)
00283 {
00284 int i;
00285 int failCount = 0;
00286
00287 if (testSuite->failCount == 0)
00288 {
00289 int passCount = testSuite->count - testSuite->failCount;
00290 const char* testWord = passCount == 1 ? "test" : "tests";
00291 CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord);
00292 }
00293 else
00294 {
00295 if (testSuite->failCount == 1)
00296 CuStringAppend(details, "There was 1 failure:\n");
00297 else
00298 CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount);
00299
00300 for (i = 0 ; i < testSuite->count ; ++i)
00301 {
00302 CuTest* testCase = testSuite->list[i];
00303 if (testCase->failed)
00304 {
00305 failCount++;
00306 CuStringAppendFormat(details, "%d) %s: %s\n",
00307 failCount, testCase->name, testCase->message);
00308 }
00309 }
00310 CuStringAppend(details, "\n!!!FAILURES!!!\n");
00311
00312 CuStringAppendFormat(details, "Runs: %d ", testSuite->count);
00313 CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount);
00314 CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount);
00315 }
00316 }