CuTest.c (10435B)
1 #include <assert.h> 2 #include <setjmp.h> 3 #include <stdlib.h> 4 #include <stdio.h> 5 #include <string.h> 6 #include <math.h> 7 #include <inttypes.h> 8 9 #include "CuTest.h" 10 11 /*-------------------------------------------------------------------------* 12 * CuStr 13 *-------------------------------------------------------------------------*/ 14 15 char* CuStrAlloc(int size) 16 { 17 char* newStr = (char*) malloc( sizeof(char) * (size) ); 18 return newStr; 19 } 20 21 char* CuStrCopy(const char* old) 22 { 23 int len = strlen(old); 24 char* newStr = CuStrAlloc(len + 1); 25 strcpy(newStr, old); 26 return newStr; 27 } 28 29 /*-------------------------------------------------------------------------* 30 * CuString 31 *-------------------------------------------------------------------------*/ 32 33 void CuStringInit(CuString* str) 34 { 35 str->length = 0; 36 str->size = STRING_MAX; 37 str->buffer = (char*) malloc(sizeof(char) * str->size); 38 str->buffer[0] = '\0'; 39 } 40 41 CuString* CuStringNew(void) 42 { 43 CuString* str = (CuString*) malloc(sizeof(CuString)); 44 str->length = 0; 45 str->size = STRING_MAX; 46 str->buffer = (char*) malloc(sizeof(char) * str->size); 47 str->buffer[0] = '\0'; 48 return str; 49 } 50 51 void CuStringDelete(CuString *str) 52 { 53 if (!str) return; 54 free(str->buffer); 55 free(str); 56 } 57 58 void CuStringResize(CuString* str, int newSize) 59 { 60 str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); 61 str->size = newSize; 62 } 63 64 void CuStringAppend(CuString* str, const char* text) 65 { 66 int length; 67 68 if (text == NULL) { 69 text = "NULL"; 70 } 71 72 length = strlen(text); 73 if (str->length + length + 1 >= str->size) 74 CuStringResize(str, str->length + length + 1 + STRING_INC); 75 str->length += length; 76 strcat(str->buffer, text); 77 } 78 79 void CuStringAppendChar(CuString* str, char ch) 80 { 81 char text[2]; 82 text[0] = ch; 83 text[1] = '\0'; 84 CuStringAppend(str, text); 85 } 86 87 void CuStringAppendFormat(CuString* str, const char* format, ...) 88 { 89 va_list argp; 90 char buf[HUGE_STRING_LEN]; 91 va_start(argp, format); 92 vsprintf(buf, format, argp); 93 va_end(argp); 94 CuStringAppend(str, buf); 95 } 96 97 void CuStringInsert(CuString* str, const char* text, int pos) 98 { 99 int length = strlen(text); 100 if (pos > str->length) 101 pos = str->length; 102 if (str->length + length + 1 >= str->size) 103 CuStringResize(str, str->length + length + 1 + STRING_INC); 104 memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); 105 str->length += length; 106 memcpy(str->buffer + pos, text, length); 107 } 108 109 /*-------------------------------------------------------------------------* 110 * CuTest 111 *-------------------------------------------------------------------------*/ 112 113 void CuTestInit(CuTest* t, const char* name, TestFunction function) 114 { 115 t->name = CuStrCopy(name); 116 t->failed = 0; 117 t->ran = 0; 118 t->message = NULL; 119 t->function = function; 120 t->jumpBuf = NULL; 121 } 122 123 CuTest* CuTestNew(const char* name, TestFunction function) 124 { 125 CuTest* tc = CU_ALLOC(CuTest); 126 CuTestInit(tc, name, function); 127 return tc; 128 } 129 130 void CuTestDelete(CuTest *t) 131 { 132 if (!t) return; 133 CuStringDelete(t->message); 134 free(t->name); 135 free(t); 136 } 137 138 void CuTestRun(CuTest* tc) 139 { 140 jmp_buf buf; 141 tc->jumpBuf = &buf; 142 if (setjmp(buf) == 0) 143 { 144 tc->ran = 1; 145 (tc->function)(tc); 146 } 147 tc->jumpBuf = 0; 148 } 149 150 static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) 151 { 152 char buf[HUGE_STRING_LEN]; 153 154 sprintf(buf, "%s:%d: ", file, line); 155 CuStringInsert(string, buf, 0); 156 157 tc->failed = 1; 158 free(tc->message); 159 tc->message = CuStringNew(); 160 CuStringAppend(tc->message, string->buffer); 161 if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); 162 } 163 164 void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) 165 { 166 CuString string; 167 168 CuStringInit(&string); 169 if (message2 != NULL) 170 { 171 CuStringAppend(&string, message2); 172 CuStringAppend(&string, ": "); 173 } 174 CuStringAppend(&string, message); 175 CuFailInternal(tc, file, line, &string); 176 } 177 178 void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) 179 { 180 if (condition) return; 181 CuFail_Line(tc, file, line, NULL, message); 182 } 183 184 void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 185 const char* expected, const char* actual) 186 { 187 CuString string; 188 if ((expected == NULL && actual == NULL) || 189 (expected != NULL && actual != NULL && 190 strcmp(expected, actual) == 0)) 191 { 192 return; 193 } 194 195 CuStringInit(&string); 196 if (message != NULL) 197 { 198 CuStringAppend(&string, message); 199 CuStringAppend(&string, ": "); 200 } 201 CuStringAppend(&string, "expected <"); 202 CuStringAppend(&string, expected); 203 CuStringAppend(&string, "> but was <"); 204 CuStringAppend(&string, actual); 205 CuStringAppend(&string, ">"); 206 CuFailInternal(tc, file, line, &string); 207 } 208 209 void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 210 double expected, double actual, double delta) 211 { 212 char buf[STRING_MAX]; 213 if (fabs(expected - actual) <= delta) return; 214 sprintf(buf, "expected <%f> but was <%f>", expected, actual); 215 216 CuFail_Line(tc, file, line, message, buf); 217 } 218 219 220 /*-------------------------------------------------------------------------* 221 * CuSuite 222 *-------------------------------------------------------------------------*/ 223 224 void CuSuiteInit(CuSuite* testSuite) 225 { 226 testSuite->count = 0; 227 testSuite->failCount = 0; 228 memset(testSuite->list, 0, sizeof(testSuite->list)); 229 } 230 231 CuSuite* CuSuiteNew(void) 232 { 233 CuSuite* testSuite = CU_ALLOC(CuSuite); 234 CuSuiteInit(testSuite); 235 return testSuite; 236 } 237 238 void CuSuiteDelete(CuSuite *testSuite) 239 { 240 unsigned int n; 241 for (n=0; n < MAX_TEST_CASES; n++) 242 { 243 if (testSuite->list[n]) 244 { 245 CuTestDelete(testSuite->list[n]); 246 } 247 } 248 free(testSuite); 249 250 } 251 252 void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) 253 { 254 assert(testSuite->count < MAX_TEST_CASES); 255 testSuite->list[testSuite->count] = testCase; 256 testSuite->count++; 257 } 258 259 void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) 260 { 261 int i; 262 for (i = 0 ; i < testSuite2->count ; ++i) 263 { 264 CuTest* testCase = testSuite2->list[i]; 265 CuSuiteAdd(testSuite, testCase); 266 } 267 } 268 269 void CuSuiteRun(CuSuite* testSuite) 270 { 271 int i; 272 for (i = 0 ; i < testSuite->count ; ++i) 273 { 274 CuTest* testCase = testSuite->list[i]; 275 CuTestRun(testCase); 276 if (testCase->failed) { testSuite->failCount += 1; } 277 } 278 } 279 280 void CuSuiteSummary(CuSuite* testSuite, CuString* summary) 281 { 282 int i; 283 for (i = 0 ; i < testSuite->count ; ++i) 284 { 285 CuTest* testCase = testSuite->list[i]; 286 CuStringAppend(summary, testCase->failed ? "F" : "."); 287 } 288 CuStringAppend(summary, "\n\n"); 289 } 290 291 void CuSuiteDetails(CuSuite* testSuite, CuString* details) 292 { 293 int i; 294 int failCount = 0; 295 296 if (testSuite->failCount == 0) 297 { 298 int passCount = testSuite->count - testSuite->failCount; 299 const char* testWord = passCount == 1 ? "test" : "tests"; 300 CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); 301 } 302 else 303 { 304 if (testSuite->failCount == 1) 305 CuStringAppend(details, "There was 1 failure:\n"); 306 else 307 CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); 308 309 for (i = 0 ; i < testSuite->count ; ++i) 310 { 311 CuTest* testCase = testSuite->list[i]; 312 if (testCase->failed) 313 { 314 failCount++; 315 CuStringAppendFormat(details, "%d) %s: %s\n", 316 failCount, testCase->name, testCase->message->buffer); 317 } 318 } 319 CuStringAppend(details, "\n!!!FAILURES!!!\n"); 320 321 CuStringAppendFormat(details, "Runs: %d ", testSuite->count); 322 CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); 323 CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); 324 } 325 } 326 327 328 /*-------------------------------------------------------------------------* 329 * CuTest changes by Remy Noulin 330 *-------------------------------------------------------------------------*/ 331 332 333 void CuAssertStrNotEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 334 const char* expected, const char* actual) 335 { 336 CuString string; 337 if ((expected == NULL && actual == NULL) || 338 (expected != NULL && actual != NULL && 339 strcmp(expected, actual) == 0)) 340 { 341 CuStringInit(&string); 342 if (message != NULL) 343 { 344 CuStringAppend(&string, message); 345 CuStringAppend(&string, ": "); 346 } 347 CuStringAppend(&string, "expected <"); 348 CuStringAppend(&string, expected); 349 CuStringAppend(&string, "> not equal to <"); 350 CuStringAppend(&string, actual); 351 CuStringAppend(&string, ">"); 352 CuFailInternal(tc, file, line, &string); 353 } 354 355 return; 356 } 357 358 void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 359 const void* expected, const void* actual) 360 { 361 char buf[STRING_MAX]; 362 if (expected == actual) return; 363 sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); 364 CuFail_Line(tc, file, line, message, buf); 365 } 366 367 void CuAssertPtrNotEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 368 const void* expected, const void* actual) 369 { 370 char buf[STRING_MAX]; 371 if (expected == actual) 372 { 373 sprintf(buf, "expected pointer <0x%p> not equal to <0x%p>", expected, actual); 374 CuFail_Line(tc, file, line, message, buf); 375 return; 376 } 377 } 378 379 void CuAssertUintEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 380 uint64_t expected, uint64_t actual) 381 { 382 char buf[STRING_MAX]; 383 if (expected == actual) return; 384 sprintf(buf, "expected <%"PRIu64"> but was <%"PRIu64">", expected, actual); 385 CuFail_Line(tc, file, line, message, buf); 386 } 387 388 void CuAssertUintNotEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 389 uint64_t expected, uint64_t actual) 390 { 391 char buf[STRING_MAX]; 392 if (expected == actual) 393 { 394 sprintf(buf, "expected <%"PRIu64"> not equal to <%"PRIu64">", expected, actual); 395 CuFail_Line(tc, file, line, message, buf); 396 return; 397 } 398 } 399 400 void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 401 int64_t expected, int64_t actual) 402 { 403 char buf[STRING_MAX]; 404 if (expected == actual) return; 405 sprintf(buf, "expected <%"PRIi64"> but was <%"PRIi64">", expected, actual); 406 CuFail_Line(tc, file, line, message, buf); 407 } 408 409 void CuAssertIntNotEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 410 int64_t expected, int64_t actual) 411 { 412 char buf[STRING_MAX]; 413 if (expected == actual) 414 { 415 sprintf(buf, "expected <%"PRIi64"> not equal to <%"PRIi64">", expected, actual); 416 CuFail_Line(tc, file, line, message, buf); 417 return; 418 } 419 } 420