16cd6a6acSopenharmony_ci/* 26cd6a6acSopenharmony_ci * Copyright (c) 2003 Asim Jalis 36cd6a6acSopenharmony_ci * 46cd6a6acSopenharmony_ci * This software is provided 'as-is', without any express or implied 56cd6a6acSopenharmony_ci * warranty. In no event will the authors be held liable for any damages 66cd6a6acSopenharmony_ci * arising from the use of this software. 76cd6a6acSopenharmony_ci * 86cd6a6acSopenharmony_ci * Permission is granted to anyone to use this software for any purpose, 96cd6a6acSopenharmony_ci * including commercial applications, and to alter it and redistribute it 106cd6a6acSopenharmony_ci * freely, subject to the following restrictions: 116cd6a6acSopenharmony_ci * 126cd6a6acSopenharmony_ci * 1. The origin of this software must not be misrepresented; you must not 136cd6a6acSopenharmony_ci * claim that you wrote the original software. If you use this software in 146cd6a6acSopenharmony_ci * a product, an acknowledgment in the product documentation would be 156cd6a6acSopenharmony_ci * appreciated but is not required. 166cd6a6acSopenharmony_ci * 176cd6a6acSopenharmony_ci * 2. Altered source versions must be plainly marked as such, and must not 186cd6a6acSopenharmony_ci * be misrepresented as being the original software. 196cd6a6acSopenharmony_ci * 206cd6a6acSopenharmony_ci * 3. This notice may not be removed or altered from any source 216cd6a6acSopenharmony_ci * distribution. 226cd6a6acSopenharmony_ci */ 236cd6a6acSopenharmony_ci 246cd6a6acSopenharmony_ci#include <assert.h> 256cd6a6acSopenharmony_ci#include <setjmp.h> 266cd6a6acSopenharmony_ci#include <stdlib.h> 276cd6a6acSopenharmony_ci#include <stdio.h> 286cd6a6acSopenharmony_ci#include <string.h> 296cd6a6acSopenharmony_ci#include <math.h> 306cd6a6acSopenharmony_ci 316cd6a6acSopenharmony_ci#include "CuTest.h" 326cd6a6acSopenharmony_ci 336cd6a6acSopenharmony_ci/*-------------------------------------------------------------------------* 346cd6a6acSopenharmony_ci * CuStr 356cd6a6acSopenharmony_ci *-------------------------------------------------------------------------*/ 366cd6a6acSopenharmony_ci 376cd6a6acSopenharmony_cichar* CuStrAlloc(int size) 386cd6a6acSopenharmony_ci{ 396cd6a6acSopenharmony_ci char* newStr = (char*) malloc( sizeof(char) * (size) ); 406cd6a6acSopenharmony_ci return newStr; 416cd6a6acSopenharmony_ci} 426cd6a6acSopenharmony_ci 436cd6a6acSopenharmony_cichar* CuStrCopy(const char* old) 446cd6a6acSopenharmony_ci{ 456cd6a6acSopenharmony_ci int len = strlen(old); 466cd6a6acSopenharmony_ci char* newStr = CuStrAlloc(len + 1); 476cd6a6acSopenharmony_ci strcpy(newStr, old); 486cd6a6acSopenharmony_ci return newStr; 496cd6a6acSopenharmony_ci} 506cd6a6acSopenharmony_ci 516cd6a6acSopenharmony_ci/*-------------------------------------------------------------------------* 526cd6a6acSopenharmony_ci * CuString 536cd6a6acSopenharmony_ci *-------------------------------------------------------------------------*/ 546cd6a6acSopenharmony_ci 556cd6a6acSopenharmony_civoid CuStringInit(CuString* str) 566cd6a6acSopenharmony_ci{ 576cd6a6acSopenharmony_ci str->length = 0; 586cd6a6acSopenharmony_ci str->size = STRING_MAX; 596cd6a6acSopenharmony_ci str->buffer = (char*) malloc(sizeof(char) * str->size); 606cd6a6acSopenharmony_ci str->buffer[0] = '\0'; 616cd6a6acSopenharmony_ci} 626cd6a6acSopenharmony_ci 636cd6a6acSopenharmony_ciCuString* CuStringNew(void) 646cd6a6acSopenharmony_ci{ 656cd6a6acSopenharmony_ci CuString* str = (CuString*) malloc(sizeof(CuString)); 666cd6a6acSopenharmony_ci str->length = 0; 676cd6a6acSopenharmony_ci str->size = STRING_MAX; 686cd6a6acSopenharmony_ci str->buffer = (char*) malloc(sizeof(char) * str->size); 696cd6a6acSopenharmony_ci str->buffer[0] = '\0'; 706cd6a6acSopenharmony_ci return str; 716cd6a6acSopenharmony_ci} 726cd6a6acSopenharmony_ci 736cd6a6acSopenharmony_civoid CuStringDelete(CuString *str) 746cd6a6acSopenharmony_ci{ 756cd6a6acSopenharmony_ci if (!str) return; 766cd6a6acSopenharmony_ci free(str->buffer); 776cd6a6acSopenharmony_ci free(str); 786cd6a6acSopenharmony_ci} 796cd6a6acSopenharmony_ci 806cd6a6acSopenharmony_civoid CuStringResize(CuString* str, int newSize) 816cd6a6acSopenharmony_ci{ 826cd6a6acSopenharmony_ci str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); 836cd6a6acSopenharmony_ci str->size = newSize; 846cd6a6acSopenharmony_ci} 856cd6a6acSopenharmony_ci 866cd6a6acSopenharmony_civoid CuStringAppend(CuString* str, const char* text) 876cd6a6acSopenharmony_ci{ 886cd6a6acSopenharmony_ci int length; 896cd6a6acSopenharmony_ci 906cd6a6acSopenharmony_ci if (text == NULL) { 916cd6a6acSopenharmony_ci text = "NULL"; 926cd6a6acSopenharmony_ci } 936cd6a6acSopenharmony_ci 946cd6a6acSopenharmony_ci length = strlen(text); 956cd6a6acSopenharmony_ci if (str->length + length + 1 >= str->size) 966cd6a6acSopenharmony_ci CuStringResize(str, str->length + length + 1 + STRING_INC); 976cd6a6acSopenharmony_ci str->length += length; 986cd6a6acSopenharmony_ci strcat(str->buffer, text); 996cd6a6acSopenharmony_ci} 1006cd6a6acSopenharmony_ci 1016cd6a6acSopenharmony_civoid CuStringAppendChar(CuString* str, char ch) 1026cd6a6acSopenharmony_ci{ 1036cd6a6acSopenharmony_ci char text[2]; 1046cd6a6acSopenharmony_ci text[0] = ch; 1056cd6a6acSopenharmony_ci text[1] = '\0'; 1066cd6a6acSopenharmony_ci CuStringAppend(str, text); 1076cd6a6acSopenharmony_ci} 1086cd6a6acSopenharmony_ci 1096cd6a6acSopenharmony_ci__attribute__ ((format (printf, 2, 3))) void CuStringAppendFormat(CuString* str, const char* format, ...) 1106cd6a6acSopenharmony_ci{ 1116cd6a6acSopenharmony_ci va_list argp; 1126cd6a6acSopenharmony_ci char buf[HUGE_STRING_LEN]; 1136cd6a6acSopenharmony_ci va_start(argp, format); 1146cd6a6acSopenharmony_ci vsprintf(buf, format, argp); 1156cd6a6acSopenharmony_ci va_end(argp); 1166cd6a6acSopenharmony_ci CuStringAppend(str, buf); 1176cd6a6acSopenharmony_ci} 1186cd6a6acSopenharmony_ci 1196cd6a6acSopenharmony_civoid CuStringInsert(CuString* str, const char* text, int pos) 1206cd6a6acSopenharmony_ci{ 1216cd6a6acSopenharmony_ci int length = strlen(text); 1226cd6a6acSopenharmony_ci if (pos > str->length) 1236cd6a6acSopenharmony_ci pos = str->length; 1246cd6a6acSopenharmony_ci if (str->length + length + 1 >= str->size) 1256cd6a6acSopenharmony_ci CuStringResize(str, str->length + length + 1 + STRING_INC); 1266cd6a6acSopenharmony_ci memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); 1276cd6a6acSopenharmony_ci str->length += length; 1286cd6a6acSopenharmony_ci memcpy(str->buffer + pos, text, length); 1296cd6a6acSopenharmony_ci} 1306cd6a6acSopenharmony_ci 1316cd6a6acSopenharmony_ci/*-------------------------------------------------------------------------* 1326cd6a6acSopenharmony_ci * CuTest 1336cd6a6acSopenharmony_ci *-------------------------------------------------------------------------*/ 1346cd6a6acSopenharmony_ci 1356cd6a6acSopenharmony_civoid CuTestInit(CuTest* t, const char* name, TestFunction function) 1366cd6a6acSopenharmony_ci{ 1376cd6a6acSopenharmony_ci t->name = CuStrCopy(name); 1386cd6a6acSopenharmony_ci t->failed = 0; 1396cd6a6acSopenharmony_ci t->ran = 0; 1406cd6a6acSopenharmony_ci t->message = NULL; 1416cd6a6acSopenharmony_ci t->function = function; 1426cd6a6acSopenharmony_ci t->jumpBuf = NULL; 1436cd6a6acSopenharmony_ci} 1446cd6a6acSopenharmony_ci 1456cd6a6acSopenharmony_ciCuTest* CuTestNew(const char* name, TestFunction function) 1466cd6a6acSopenharmony_ci{ 1476cd6a6acSopenharmony_ci CuTest* tc = CU_ALLOC(CuTest); 1486cd6a6acSopenharmony_ci CuTestInit(tc, name, function); 1496cd6a6acSopenharmony_ci return tc; 1506cd6a6acSopenharmony_ci} 1516cd6a6acSopenharmony_ci 1526cd6a6acSopenharmony_civoid CuTestDelete(CuTest *t) 1536cd6a6acSopenharmony_ci{ 1546cd6a6acSopenharmony_ci if (!t) return; 1556cd6a6acSopenharmony_ci free(t->name); 1566cd6a6acSopenharmony_ci free(t); 1576cd6a6acSopenharmony_ci} 1586cd6a6acSopenharmony_ci 1596cd6a6acSopenharmony_civoid CuTestRun(CuTest* tc) 1606cd6a6acSopenharmony_ci{ 1616cd6a6acSopenharmony_ci jmp_buf buf; 1626cd6a6acSopenharmony_ci tc->jumpBuf = &buf; 1636cd6a6acSopenharmony_ci if (setjmp(buf) == 0) 1646cd6a6acSopenharmony_ci { 1656cd6a6acSopenharmony_ci tc->ran = 1; 1666cd6a6acSopenharmony_ci (tc->function)(tc); 1676cd6a6acSopenharmony_ci } 1686cd6a6acSopenharmony_ci tc->jumpBuf = 0; 1696cd6a6acSopenharmony_ci} 1706cd6a6acSopenharmony_ci 1716cd6a6acSopenharmony_cistatic void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) 1726cd6a6acSopenharmony_ci{ 1736cd6a6acSopenharmony_ci char buf[HUGE_STRING_LEN]; 1746cd6a6acSopenharmony_ci 1756cd6a6acSopenharmony_ci sprintf(buf, "%s:%d: ", file, line); 1766cd6a6acSopenharmony_ci CuStringInsert(string, buf, 0); 1776cd6a6acSopenharmony_ci 1786cd6a6acSopenharmony_ci tc->failed = 1; 1796cd6a6acSopenharmony_ci tc->message = string->buffer; 1806cd6a6acSopenharmony_ci if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); 1816cd6a6acSopenharmony_ci} 1826cd6a6acSopenharmony_ci 1836cd6a6acSopenharmony_civoid CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) 1846cd6a6acSopenharmony_ci{ 1856cd6a6acSopenharmony_ci CuString string; 1866cd6a6acSopenharmony_ci 1876cd6a6acSopenharmony_ci CuStringInit(&string); 1886cd6a6acSopenharmony_ci if (message2 != NULL) 1896cd6a6acSopenharmony_ci { 1906cd6a6acSopenharmony_ci CuStringAppend(&string, message2); 1916cd6a6acSopenharmony_ci CuStringAppend(&string, ": "); 1926cd6a6acSopenharmony_ci } 1936cd6a6acSopenharmony_ci CuStringAppend(&string, message); 1946cd6a6acSopenharmony_ci CuFailInternal(tc, file, line, &string); 1956cd6a6acSopenharmony_ci} 1966cd6a6acSopenharmony_ci 1976cd6a6acSopenharmony_civoid CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) 1986cd6a6acSopenharmony_ci{ 1996cd6a6acSopenharmony_ci if (condition) return; 2006cd6a6acSopenharmony_ci CuFail_Line(tc, file, line, NULL, message); 2016cd6a6acSopenharmony_ci} 2026cd6a6acSopenharmony_ci 2036cd6a6acSopenharmony_civoid CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 2046cd6a6acSopenharmony_ci const char* expected, const char* actual) 2056cd6a6acSopenharmony_ci{ 2066cd6a6acSopenharmony_ci CuString string; 2076cd6a6acSopenharmony_ci if ((expected == NULL && actual == NULL) || 2086cd6a6acSopenharmony_ci (expected != NULL && actual != NULL && 2096cd6a6acSopenharmony_ci strcmp(expected, actual) == 0)) 2106cd6a6acSopenharmony_ci { 2116cd6a6acSopenharmony_ci return; 2126cd6a6acSopenharmony_ci } 2136cd6a6acSopenharmony_ci 2146cd6a6acSopenharmony_ci CuStringInit(&string); 2156cd6a6acSopenharmony_ci if (message != NULL) 2166cd6a6acSopenharmony_ci { 2176cd6a6acSopenharmony_ci CuStringAppend(&string, message); 2186cd6a6acSopenharmony_ci CuStringAppend(&string, ": "); 2196cd6a6acSopenharmony_ci } 2206cd6a6acSopenharmony_ci CuStringAppend(&string, "expected <"); 2216cd6a6acSopenharmony_ci CuStringAppend(&string, expected); 2226cd6a6acSopenharmony_ci CuStringAppend(&string, "> but was <"); 2236cd6a6acSopenharmony_ci CuStringAppend(&string, actual); 2246cd6a6acSopenharmony_ci CuStringAppend(&string, ">"); 2256cd6a6acSopenharmony_ci CuFailInternal(tc, file, line, &string); 2266cd6a6acSopenharmony_ci} 2276cd6a6acSopenharmony_ci 2286cd6a6acSopenharmony_civoid CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 2296cd6a6acSopenharmony_ci int expected, int actual) 2306cd6a6acSopenharmony_ci{ 2316cd6a6acSopenharmony_ci char buf[STRING_MAX]; 2326cd6a6acSopenharmony_ci if (expected == actual) return; 2336cd6a6acSopenharmony_ci sprintf(buf, "expected <%d> but was <%d>", expected, actual); 2346cd6a6acSopenharmony_ci CuFail_Line(tc, file, line, message, buf); 2356cd6a6acSopenharmony_ci} 2366cd6a6acSopenharmony_ci 2376cd6a6acSopenharmony_civoid CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 2386cd6a6acSopenharmony_ci double expected, double actual, double delta) 2396cd6a6acSopenharmony_ci{ 2406cd6a6acSopenharmony_ci char buf[STRING_MAX]; 2416cd6a6acSopenharmony_ci if (fabs(expected - actual) <= delta) return; 2426cd6a6acSopenharmony_ci sprintf(buf, "expected <%f> but was <%f>", expected, actual); 2436cd6a6acSopenharmony_ci 2446cd6a6acSopenharmony_ci CuFail_Line(tc, file, line, message, buf); 2456cd6a6acSopenharmony_ci} 2466cd6a6acSopenharmony_ci 2476cd6a6acSopenharmony_civoid CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, 2486cd6a6acSopenharmony_ci void* expected, void* actual) 2496cd6a6acSopenharmony_ci{ 2506cd6a6acSopenharmony_ci char buf[STRING_MAX]; 2516cd6a6acSopenharmony_ci if (expected == actual) return; 2526cd6a6acSopenharmony_ci sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); 2536cd6a6acSopenharmony_ci CuFail_Line(tc, file, line, message, buf); 2546cd6a6acSopenharmony_ci} 2556cd6a6acSopenharmony_ci 2566cd6a6acSopenharmony_ci 2576cd6a6acSopenharmony_ci/*-------------------------------------------------------------------------* 2586cd6a6acSopenharmony_ci * CuSuite 2596cd6a6acSopenharmony_ci *-------------------------------------------------------------------------*/ 2606cd6a6acSopenharmony_ci 2616cd6a6acSopenharmony_civoid CuSuiteInit(CuSuite* testSuite) 2626cd6a6acSopenharmony_ci{ 2636cd6a6acSopenharmony_ci testSuite->count = 0; 2646cd6a6acSopenharmony_ci testSuite->failCount = 0; 2656cd6a6acSopenharmony_ci memset(testSuite->list, 0, sizeof(testSuite->list)); 2666cd6a6acSopenharmony_ci} 2676cd6a6acSopenharmony_ci 2686cd6a6acSopenharmony_ciCuSuite* CuSuiteNew(void) 2696cd6a6acSopenharmony_ci{ 2706cd6a6acSopenharmony_ci CuSuite* testSuite = CU_ALLOC(CuSuite); 2716cd6a6acSopenharmony_ci CuSuiteInit(testSuite); 2726cd6a6acSopenharmony_ci return testSuite; 2736cd6a6acSopenharmony_ci} 2746cd6a6acSopenharmony_ci 2756cd6a6acSopenharmony_civoid CuSuiteDelete(CuSuite *testSuite) 2766cd6a6acSopenharmony_ci{ 2776cd6a6acSopenharmony_ci unsigned int n; 2786cd6a6acSopenharmony_ci for (n=0; n < MAX_TEST_CASES; n++) 2796cd6a6acSopenharmony_ci { 2806cd6a6acSopenharmony_ci if (testSuite->list[n]) 2816cd6a6acSopenharmony_ci { 2826cd6a6acSopenharmony_ci CuTestDelete(testSuite->list[n]); 2836cd6a6acSopenharmony_ci } 2846cd6a6acSopenharmony_ci } 2856cd6a6acSopenharmony_ci free(testSuite); 2866cd6a6acSopenharmony_ci 2876cd6a6acSopenharmony_ci} 2886cd6a6acSopenharmony_ci 2896cd6a6acSopenharmony_civoid CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) 2906cd6a6acSopenharmony_ci{ 2916cd6a6acSopenharmony_ci assert(testSuite->count < MAX_TEST_CASES); 2926cd6a6acSopenharmony_ci testSuite->list[testSuite->count] = testCase; 2936cd6a6acSopenharmony_ci testSuite->count++; 2946cd6a6acSopenharmony_ci} 2956cd6a6acSopenharmony_ci 2966cd6a6acSopenharmony_civoid CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) 2976cd6a6acSopenharmony_ci{ 2986cd6a6acSopenharmony_ci int i; 2996cd6a6acSopenharmony_ci for (i = 0 ; i < testSuite2->count ; ++i) 3006cd6a6acSopenharmony_ci { 3016cd6a6acSopenharmony_ci CuTest* testCase = testSuite2->list[i]; 3026cd6a6acSopenharmony_ci CuSuiteAdd(testSuite, testCase); 3036cd6a6acSopenharmony_ci } 3046cd6a6acSopenharmony_ci} 3056cd6a6acSopenharmony_ci 3066cd6a6acSopenharmony_civoid CuSuiteRun(CuSuite* testSuite) 3076cd6a6acSopenharmony_ci{ 3086cd6a6acSopenharmony_ci int i; 3096cd6a6acSopenharmony_ci for (i = 0 ; i < testSuite->count ; ++i) 3106cd6a6acSopenharmony_ci { 3116cd6a6acSopenharmony_ci CuTest* testCase = testSuite->list[i]; 3126cd6a6acSopenharmony_ci CuTestRun(testCase); 3136cd6a6acSopenharmony_ci if (testCase->failed) { testSuite->failCount += 1; } 3146cd6a6acSopenharmony_ci } 3156cd6a6acSopenharmony_ci} 3166cd6a6acSopenharmony_ci 3176cd6a6acSopenharmony_civoid CuSuiteSummary(CuSuite* testSuite, CuString* summary) 3186cd6a6acSopenharmony_ci{ 3196cd6a6acSopenharmony_ci int i; 3206cd6a6acSopenharmony_ci for (i = 0 ; i < testSuite->count ; ++i) 3216cd6a6acSopenharmony_ci { 3226cd6a6acSopenharmony_ci CuTest* testCase = testSuite->list[i]; 3236cd6a6acSopenharmony_ci CuStringAppend(summary, testCase->failed ? "F" : "."); 3246cd6a6acSopenharmony_ci } 3256cd6a6acSopenharmony_ci CuStringAppend(summary, "\n\n"); 3266cd6a6acSopenharmony_ci} 3276cd6a6acSopenharmony_ci 3286cd6a6acSopenharmony_civoid CuSuiteDetails(CuSuite* testSuite, CuString* details) 3296cd6a6acSopenharmony_ci{ 3306cd6a6acSopenharmony_ci int i; 3316cd6a6acSopenharmony_ci int failCount = 0; 3326cd6a6acSopenharmony_ci 3336cd6a6acSopenharmony_ci if (testSuite->failCount == 0) 3346cd6a6acSopenharmony_ci { 3356cd6a6acSopenharmony_ci int passCount = testSuite->count - testSuite->failCount; 3366cd6a6acSopenharmony_ci const char* testWord = passCount == 1 ? "test" : "tests"; 3376cd6a6acSopenharmony_ci CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); 3386cd6a6acSopenharmony_ci } 3396cd6a6acSopenharmony_ci else 3406cd6a6acSopenharmony_ci { 3416cd6a6acSopenharmony_ci if (testSuite->failCount == 1) 3426cd6a6acSopenharmony_ci CuStringAppend(details, "There was 1 failure:\n"); 3436cd6a6acSopenharmony_ci else 3446cd6a6acSopenharmony_ci CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); 3456cd6a6acSopenharmony_ci 3466cd6a6acSopenharmony_ci for (i = 0 ; i < testSuite->count ; ++i) 3476cd6a6acSopenharmony_ci { 3486cd6a6acSopenharmony_ci CuTest* testCase = testSuite->list[i]; 3496cd6a6acSopenharmony_ci if (testCase->failed) 3506cd6a6acSopenharmony_ci { 3516cd6a6acSopenharmony_ci failCount++; 3526cd6a6acSopenharmony_ci CuStringAppendFormat(details, "%d) %s: %s\n", 3536cd6a6acSopenharmony_ci failCount, testCase->name, testCase->message); 3546cd6a6acSopenharmony_ci } 3556cd6a6acSopenharmony_ci } 3566cd6a6acSopenharmony_ci CuStringAppend(details, "\n!!!FAILURES!!!\n"); 3576cd6a6acSopenharmony_ci 3586cd6a6acSopenharmony_ci CuStringAppendFormat(details, "Runs: %d ", testSuite->count); 3596cd6a6acSopenharmony_ci CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); 3606cd6a6acSopenharmony_ci CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); 3616cd6a6acSopenharmony_ci } 3626cd6a6acSopenharmony_ci} 363