CuTest.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include <assert.h>
  2. #include <math.h>
  3. #include <setjmp.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "CuTest.h"
  8. /*-------------------------------------------------------------------------*
  9. * CuStr
  10. *-------------------------------------------------------------------------*/
  11. char* CuStrAlloc(size_t size) {
  12. char* newStr = (char*)malloc(sizeof(char) * (size));
  13. return newStr;
  14. }
  15. char* CuStrCopy(const char* old) {
  16. size_t len = strlen(old);
  17. char* newStr = CuStrAlloc(len + 1);
  18. #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
  19. strcpy_s(newStr, len + 1, old);
  20. #else
  21. strcpy(newStr, old);
  22. #endif
  23. return newStr;
  24. }
  25. /*-------------------------------------------------------------------------*
  26. * CuString
  27. *-------------------------------------------------------------------------*/
  28. void CuStringInit(CuString* str) {
  29. str->length = 0;
  30. str->size = STRING_MAX;
  31. str->buffer = (char*)malloc(sizeof(char) * str->size);
  32. str->buffer[0] = '\0';
  33. }
  34. CuString* CuStringNew(void) {
  35. CuString* str = (CuString*)malloc(sizeof(CuString));
  36. str->length = 0;
  37. str->size = STRING_MAX;
  38. str->buffer = (char*)malloc(sizeof(char) * str->size);
  39. str->buffer[0] = '\0';
  40. return str;
  41. }
  42. void CuStringDelete(CuString* str) {
  43. if (!str)
  44. return;
  45. free(str->buffer);
  46. free(str);
  47. }
  48. void CuStringResize(CuString* str, size_t newSize) {
  49. str->buffer = (char*)realloc(str->buffer, sizeof(char) * newSize);
  50. str->size = newSize;
  51. }
  52. void CuStringAppend(CuString* str, const char* text) {
  53. size_t length;
  54. if (text == NULL) {
  55. text = "NULL";
  56. }
  57. length = strlen(text);
  58. if (str->length + length + 1 >= str->size)
  59. CuStringResize(str, str->length + length + 1 + STRING_INC);
  60. str->length += length;
  61. #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
  62. strcat_s(str->buffer, str->size, text);
  63. #else
  64. strcat(str->buffer, text);
  65. #endif
  66. }
  67. void CuStringAppendChar(CuString* str, char ch) {
  68. char text[2];
  69. text[0] = ch;
  70. text[1] = '\0';
  71. CuStringAppend(str, text);
  72. }
  73. void CuStringAppendFormat(CuString* str, const char* format, ...) {
  74. va_list argp;
  75. char buf[HUGE_STRING_LEN];
  76. va_start(argp, format);
  77. #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
  78. vsprintf_s(buf, sizeof(buf), format, argp);
  79. #else
  80. vsprintf(buf, format, argp);
  81. #endif
  82. va_end(argp);
  83. CuStringAppend(str, buf);
  84. }
  85. void CuStringInsert(CuString* str, const char* text, int pos) {
  86. size_t length = strlen(text);
  87. if ((size_t)pos > str->length)
  88. pos = (int)str->length;
  89. if (str->length + length + 1 >= str->size)
  90. CuStringResize(str, str->length + length + 1 + STRING_INC);
  91. memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1);
  92. str->length += length;
  93. memcpy(str->buffer + pos, text, length);
  94. }
  95. /*-------------------------------------------------------------------------*
  96. * CuTest
  97. *-------------------------------------------------------------------------*/
  98. void CuTestInit(CuTest* t, const char* name, TestFunction function) {
  99. t->name = CuStrCopy(name);
  100. t->failed = 0;
  101. t->ran = 0;
  102. t->message = NULL;
  103. t->function = function;
  104. t->jumpBuf = NULL;
  105. }
  106. CuTest* CuTestNew(const char* name, TestFunction function) {
  107. CuTest* tc = CU_ALLOC(CuTest);
  108. CuTestInit(tc, name, function);
  109. return tc;
  110. }
  111. void CuTestDelete(CuTest* t) {
  112. if (!t)
  113. return;
  114. free(t->name);
  115. free(t);
  116. }
  117. void CuTestRun(CuTest* tc) {
  118. jmp_buf buf;
  119. tc->jumpBuf = &buf;
  120. if (setjmp(buf) == 0) {
  121. tc->ran = 1;
  122. (tc->function)(tc);
  123. }
  124. tc->jumpBuf = 0;
  125. }
  126. static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) {
  127. char buf[HUGE_STRING_LEN];
  128. #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
  129. sprintf_s(buf, sizeof(buf), "%s:%d: ", file, line);
  130. #else
  131. sprintf(buf, "%s:%d: ", file, line);
  132. #endif
  133. CuStringInsert(string, buf, 0);
  134. tc->failed = 1;
  135. tc->message = string->buffer;
  136. if (tc->jumpBuf != 0)
  137. longjmp(*(tc->jumpBuf), 0);
  138. }
  139. void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) {
  140. CuString string;
  141. CuStringInit(&string);
  142. if (message2 != NULL) {
  143. CuStringAppend(&string, message2);
  144. CuStringAppend(&string, ": ");
  145. }
  146. CuStringAppend(&string, message);
  147. CuFailInternal(tc, file, line, &string);
  148. }
  149. void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) {
  150. if (condition)
  151. return;
  152. CuFail_Line(tc, file, line, NULL, message);
  153. }
  154. void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual) {
  155. CuString string;
  156. if ((expected == NULL && actual == NULL) || (expected != NULL && actual != NULL && strcmp(expected, actual) == 0)) {
  157. return;
  158. }
  159. CuStringInit(&string);
  160. if (message != NULL) {
  161. CuStringAppend(&string, message);
  162. CuStringAppend(&string, ": ");
  163. }
  164. CuStringAppend(&string, "expected <");
  165. CuStringAppend(&string, expected);
  166. CuStringAppend(&string, "> but was <");
  167. CuStringAppend(&string, actual);
  168. CuStringAppend(&string, ">");
  169. CuFailInternal(tc, file, line, &string);
  170. }
  171. void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual) {
  172. char buf[STRING_MAX];
  173. if (expected == actual)
  174. return;
  175. #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
  176. sprintf_s(buf, sizeof(buf), "expected <%d> but was <%d>", expected, actual);
  177. #else
  178. sprintf(buf, "expected <%d> but was <%d>", expected, actual);
  179. #endif
  180. CuFail_Line(tc, file, line, message, buf);
  181. }
  182. void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta) {
  183. char buf[STRING_MAX];
  184. if (fabs(expected - actual) <= delta)
  185. return;
  186. #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
  187. sprintf_s(buf, sizeof(buf), "expected <%f> but was <%f>", expected, actual);
  188. #else
  189. sprintf(buf, "expected <%f> but was <%f>", expected, actual);
  190. #endif
  191. CuFail_Line(tc, file, line, message, buf);
  192. }
  193. void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, void* expected, void* actual) {
  194. char buf[STRING_MAX];
  195. if (expected == actual)
  196. return;
  197. #if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__))
  198. sprintf_s(buf, sizeof(buf), "expected pointer <0x%p> but was <0x%p>", expected, actual);
  199. #else
  200. sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual);
  201. #endif
  202. CuFail_Line(tc, file, line, message, buf);
  203. }
  204. /*-------------------------------------------------------------------------*
  205. * CuSuite
  206. *-------------------------------------------------------------------------*/
  207. void CuSuiteInit(CuSuite* testSuite) {
  208. testSuite->count = 0;
  209. testSuite->failCount = 0;
  210. memset(testSuite->list, 0, sizeof(testSuite->list));
  211. }
  212. CuSuite* CuSuiteNew(void) {
  213. CuSuite* testSuite = CU_ALLOC(CuSuite);
  214. CuSuiteInit(testSuite);
  215. return testSuite;
  216. }
  217. void CuSuiteDelete(CuSuite* testSuite) {
  218. unsigned int n;
  219. for (n = 0; n < MAX_TEST_CASES; n++) {
  220. if (testSuite->list[n]) {
  221. CuTestDelete(testSuite->list[n]);
  222. }
  223. }
  224. free(testSuite);
  225. }
  226. void CuSuiteAdd(CuSuite* testSuite, CuTest* testCase) {
  227. assert(testSuite->count < MAX_TEST_CASES);
  228. testSuite->list[testSuite->count] = testCase;
  229. testSuite->count++;
  230. }
  231. void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) {
  232. int i;
  233. for (i = 0; i < testSuite2->count; ++i) {
  234. CuTest* testCase = testSuite2->list[i];
  235. CuSuiteAdd(testSuite, testCase);
  236. }
  237. }
  238. void CuSuiteRun(CuSuite* testSuite) {
  239. int i;
  240. for (i = 0; i < testSuite->count; ++i) {
  241. CuTest* testCase = testSuite->list[i];
  242. CuTestRun(testCase);
  243. if (testCase->failed) {
  244. testSuite->failCount += 1;
  245. }
  246. }
  247. }
  248. void CuSuiteSummary(CuSuite* testSuite, CuString* summary) {
  249. int i;
  250. for (i = 0; i < testSuite->count; ++i) {
  251. CuTest* testCase = testSuite->list[i];
  252. CuStringAppend(summary, testCase->failed ? "F" : ".");
  253. }
  254. CuStringAppend(summary, "\n\n");
  255. }
  256. void CuSuiteDetails(CuSuite* testSuite, CuString* details) {
  257. int i;
  258. int failCount = 0;
  259. if (testSuite->failCount == 0) {
  260. int passCount = testSuite->count - testSuite->failCount;
  261. const char* testWord = passCount == 1 ? "test" : "tests";
  262. CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord);
  263. } else {
  264. if (testSuite->failCount == 1)
  265. CuStringAppend(details, "There was 1 failure:\n");
  266. else
  267. CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount);
  268. for (i = 0; i < testSuite->count; ++i) {
  269. CuTest* testCase = testSuite->list[i];
  270. if (testCase->failed) {
  271. failCount++;
  272. CuStringAppendFormat(details, "%d) %s: %s\n", failCount, testCase->name, testCase->message);
  273. }
  274. }
  275. CuStringAppend(details, "\n!!!FAILURES!!!\n");
  276. CuStringAppendFormat(details, "Runs: %d ", testSuite->count);
  277. CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount);
  278. CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount);
  279. }
  280. }