utest.h 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859
  1. /*
  2. The latest version of this library is available on GitHub;
  3. https://github.com/sheredom/utest.h
  4. */
  5. /*
  6. This is free and unencumbered software released into the public domain.
  7. Anyone is free to copy, modify, publish, use, compile, sell, or
  8. distribute this software, either in source code form or as a compiled
  9. binary, for any purpose, commercial or non-commercial, and by any
  10. means.
  11. In jurisdictions that recognize copyright laws, the author or authors
  12. of this software dedicate any and all copyright interest in the
  13. software to the public domain. We make this dedication for the benefit
  14. of the public at large and to the detriment of our heirs and
  15. successors. We intend this dedication to be an overt act of
  16. relinquishment in perpetuity of all present and future rights to this
  17. software under copyright law.
  18. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  21. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  22. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  23. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  24. OTHER DEALINGS IN THE SOFTWARE.
  25. For more information, please refer to <http://unlicense.org/>
  26. */
  27. #ifndef SHEREDOM_UTEST_H_INCLUDED
  28. #define SHEREDOM_UTEST_H_INCLUDED
  29. #ifdef _MSC_VER
  30. /*
  31. Disable warning about not inlining 'inline' functions.
  32. TODO: We'll fix this later by not using fprintf within our macros, and
  33. instead use snprintf to a realloc'ed buffer.
  34. */
  35. #pragma warning(disable : 4710)
  36. /*
  37. Disable warning about inlining functions that are not marked 'inline'.
  38. TODO: add a UTEST_NOINLINE onto the macro generated functions to fix this.
  39. */
  40. #pragma warning(disable : 4711)
  41. #pragma warning(push, 1)
  42. #endif
  43. #if defined(_MSC_VER)
  44. typedef __int64 int64_t;
  45. typedef unsigned __int64 uint64_t;
  46. #else
  47. #include <stdint.h>
  48. #endif
  49. #include <stddef.h>
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52. #include <string.h>
  53. #if defined(_MSC_VER)
  54. #pragma warning(pop)
  55. #endif
  56. #if defined(_MSC_VER)
  57. #if defined(_M_IX86)
  58. #define _X86_
  59. #endif
  60. #if defined(_M_AMD64)
  61. #define _AMD64_
  62. #endif
  63. #pragma warning(push, 1)
  64. #include <windef.h>
  65. #include <winbase.h>
  66. #pragma warning(pop)
  67. #elif defined(__linux__)
  68. /*
  69. slightly obscure include here - we need to include glibc's features.h, but
  70. we don't want to just include a header that might not be defined for other
  71. c libraries like musl. Instead we include limits.h, which we know on all
  72. glibc distributions includes features.h
  73. */
  74. #include <limits.h>
  75. #if defined(__GLIBC__) && defined(__GLIBC_MINOR__)
  76. #include <time.h>
  77. #if ((2 < __GLIBC__) || ((2 == __GLIBC__) && (17 <= __GLIBC_MINOR__)))
  78. /* glibc is version 2.17 or above, so we can just use clock_gettime */
  79. #define UTEST_USE_CLOCKGETTIME
  80. #else
  81. #include <sys/syscall.h>
  82. #include <unistd.h>
  83. #endif
  84. #endif
  85. #elif defined(__APPLE__)
  86. #include <mach/mach_time.h>
  87. #endif
  88. #if defined(_MSC_VER)
  89. #define UTEST_PRId64 "I64d"
  90. #define UTEST_PRIu64 "I64u"
  91. #define UTEST_INLINE __forceinline
  92. #pragma section(".CRT$XCU", read)
  93. #define UTEST_INITIALIZER(f) \
  94. static void __cdecl f(void); \
  95. __declspec(allocate(".CRT$XCU")) void(__cdecl * f##_)(void) = f; \
  96. static void __cdecl f(void)
  97. #else
  98. #if defined(__linux__)
  99. #if defined(__clang__)
  100. #if __has_warning("-Wreserved-id-macro")
  101. #pragma clang diagnostic push
  102. #pragma clang diagnostic ignored "-Wreserved-id-macro"
  103. #endif
  104. #endif
  105. #define __STDC_FORMAT_MACROS 1
  106. #if defined(__clang__)
  107. #if __has_warning("-Wreserved-id-macro")
  108. #pragma clang diagnostic pop
  109. #endif
  110. #endif
  111. #endif
  112. #include <inttypes.h>
  113. #define UTEST_PRId64 PRId64
  114. #define UTEST_PRIu64 PRIu64
  115. #define UTEST_INLINE inline
  116. #define UTEST_INITIALIZER(f) \
  117. static void f(void) __attribute__((constructor)); \
  118. static void f(void)
  119. #endif
  120. #if defined(__cplusplus)
  121. #define UTEST_CAST(type, x) static_cast<type>(x)
  122. #define UTEST_PTR_CAST(type, x) reinterpret_cast<type>(x)
  123. #define UTEST_EXTERN extern "C"
  124. #else
  125. #define UTEST_CAST(type, x) ((type)x)
  126. #define UTEST_PTR_CAST(type, x) ((type)x)
  127. #define UTEST_EXTERN extern
  128. #endif
  129. #ifdef _MSC_VER
  130. /*
  131. io.h contains definitions for some structures with natural padding. This is
  132. uninteresting, but for some reason MSVC's behaviour is to warn about
  133. including this system header. That *is* interesting
  134. */
  135. #pragma warning(disable : 4820)
  136. #pragma warning(push, 1)
  137. #include <io.h>
  138. #pragma warning(pop)
  139. #define UTEST_COLOUR_OUTPUT() (_isatty(_fileno(stdout)))
  140. #else
  141. #include <unistd.h>
  142. #define UTEST_COLOUR_OUTPUT() (isatty(STDOUT_FILENO))
  143. #endif
  144. static UTEST_INLINE int64_t utest_ns(void) {
  145. #ifdef _MSC_VER
  146. LARGE_INTEGER counter;
  147. LARGE_INTEGER frequency;
  148. QueryPerformanceCounter(&counter);
  149. QueryPerformanceFrequency(&frequency);
  150. return UTEST_CAST(int64_t,
  151. (counter.QuadPart * 1000000000) / frequency.QuadPart);
  152. #elif defined(__linux)
  153. struct timespec ts;
  154. const clockid_t cid = CLOCK_REALTIME;
  155. #if defined(UTEST_USE_CLOCKGETTIME)
  156. clock_gettime(cid, &ts);
  157. #else
  158. syscall(SYS_clock_gettime, cid, &ts);
  159. #endif
  160. return UTEST_CAST(int64_t, ts.tv_sec) * 1000 * 1000 * 1000 + ts.tv_nsec;
  161. #elif __APPLE__
  162. return UTEST_CAST(int64_t, mach_absolute_time());
  163. #else
  164. /* hack to prevent warning on unsupported platforms */
  165. return 1;
  166. #endif
  167. }
  168. typedef void (*utest_testcase_t)(int *, size_t);
  169. struct utest_test_state_s {
  170. utest_testcase_t func;
  171. size_t index;
  172. char *name;
  173. };
  174. struct utest_state_s {
  175. struct utest_test_state_s *tests;
  176. size_t tests_length;
  177. FILE *output;
  178. };
  179. /* extern to the global state utest needs to execute */
  180. UTEST_EXTERN struct utest_state_s utest_state;
  181. #if defined(_MSC_VER)
  182. #define UTEST_WEAK __forceinline
  183. #else
  184. #define UTEST_WEAK __attribute__((weak))
  185. #endif
  186. #if defined(_MSC_VER)
  187. #define UTEST_UNUSED
  188. #else
  189. #define UTEST_UNUSED __attribute__((unused))
  190. #endif
  191. #ifdef __clang__
  192. #pragma clang diagnostic push
  193. #pragma clang diagnostic ignored "-Wvariadic-macros"
  194. #endif
  195. #define UTEST_PRINTF(...) \
  196. if (utest_state.output) { \
  197. fprintf(utest_state.output, __VA_ARGS__); \
  198. } \
  199. printf(__VA_ARGS__)
  200. #ifdef __clang__
  201. #pragma clang diagnostic pop
  202. #endif
  203. #ifdef _MSC_VER
  204. #define UTEST_SNPRINTF(BUFFER, N, ...) _snprintf_s(BUFFER, N, N, __VA_ARGS__)
  205. #else
  206. #ifdef __clang__
  207. #pragma clang diagnostic push
  208. #pragma clang diagnostic ignored "-Wvariadic-macros"
  209. #endif
  210. #define UTEST_SNPRINTF(...) snprintf(__VA_ARGS__)
  211. #ifdef __clang__
  212. #pragma clang diagnostic pop
  213. #endif
  214. #endif
  215. #if defined(__cplusplus)
  216. /* if we are using c++ we can use overloaded methods (its in the language) */
  217. #define UTEST_OVERLOADABLE
  218. #elif defined(__clang__)
  219. /* otherwise, if we are using clang with c - use the overloadable attribute */
  220. #define UTEST_OVERLOADABLE __attribute__((overloadable))
  221. #endif
  222. #if defined(UTEST_OVERLOADABLE)
  223. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f);
  224. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f) {
  225. UTEST_PRINTF("%f", UTEST_CAST(double, f));
  226. }
  227. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d);
  228. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d) {
  229. UTEST_PRINTF("%f", d);
  230. }
  231. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d);
  232. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d) {
  233. UTEST_PRINTF("%Lf", d);
  234. }
  235. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i);
  236. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i) {
  237. UTEST_PRINTF("%d", i);
  238. }
  239. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i);
  240. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i) {
  241. UTEST_PRINTF("%u", i);
  242. }
  243. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i);
  244. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i) {
  245. UTEST_PRINTF("%ld", i);
  246. }
  247. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i);
  248. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i) {
  249. UTEST_PRINTF("%lu", i);
  250. }
  251. /*
  252. long long is a c++11 extension
  253. TODO: grok for c++11 version here
  254. */
  255. #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
  256. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i);
  257. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i) {
  258. UTEST_PRINTF("%lld", i);
  259. }
  260. UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long unsigned int i);
  261. UTEST_WEAK UTEST_OVERLOADABLE void
  262. utest_type_printer(long long unsigned int i) {
  263. UTEST_PRINTF("%llu", i);
  264. }
  265. #endif
  266. #else
  267. /*
  268. we don't have the ability to print the values we got, so we create a macro
  269. to tell our users we can't do anything fancy
  270. */
  271. #define utest_type_printer(...) UTEST_PRINTF("undef")
  272. #endif
  273. #if defined(__clang__)
  274. #define UTEST_EXPECT(x, y, cond) \
  275. { \
  276. _Pragma("clang diagnostic push") _Pragma( \
  277. "clang diagnostic ignored \"-Wlanguage-extension-token\"") typeof(y) \
  278. xEval = (x); \
  279. typeof(y) yEval = (y); \
  280. _Pragma("clang diagnostic pop") if (!((xEval)cond(yEval))) { \
  281. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  282. UTEST_PRINTF(" Expected : "); \
  283. utest_type_printer(xEval); \
  284. UTEST_PRINTF("\n"); \
  285. UTEST_PRINTF(" Actual : "); \
  286. utest_type_printer(yEval); \
  287. UTEST_PRINTF("\n"); \
  288. *utest_result = 1; \
  289. } \
  290. }
  291. #elif defined(__GNUC__)
  292. #define UTEST_EXPECT(x, y, cond) \
  293. { \
  294. typeof(y) xEval = (x); \
  295. typeof(y) yEval = (y); \
  296. if (!((xEval)cond(yEval))) { \
  297. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  298. UTEST_PRINTF(" Expected : "); \
  299. utest_type_printer(xEval); \
  300. UTEST_PRINTF("\n"); \
  301. UTEST_PRINTF(" Actual : "); \
  302. utest_type_printer(yEval); \
  303. UTEST_PRINTF("\n"); \
  304. *utest_result = 1; \
  305. } \
  306. }
  307. #else
  308. #define UTEST_EXPECT(x, y, cond) \
  309. { \
  310. if (!((x)cond(y))) { \
  311. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  312. *utest_result = 1; \
  313. } \
  314. }
  315. #endif
  316. #define EXPECT_TRUE(x) \
  317. if (!(x)) { \
  318. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  319. UTEST_PRINTF(" Expected : true\n"); \
  320. UTEST_PRINTF(" Actual : %s\n", (x) ? "true" : "false"); \
  321. *utest_result = 1; \
  322. }
  323. #define EXPECT_FALSE(x) \
  324. if (x) { \
  325. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  326. UTEST_PRINTF(" Expected : false\n"); \
  327. UTEST_PRINTF(" Actual : %s\n", (x) ? "true" : "false"); \
  328. *utest_result = 1; \
  329. }
  330. #define EXPECT_EQ(x, y) UTEST_EXPECT(x, y, ==)
  331. #define EXPECT_NE(x, y) UTEST_EXPECT(x, y, !=)
  332. #define EXPECT_LT(x, y) UTEST_EXPECT(x, y, <)
  333. #define EXPECT_LE(x, y) UTEST_EXPECT(x, y, <=)
  334. #define EXPECT_GT(x, y) UTEST_EXPECT(x, y, >)
  335. #define EXPECT_GE(x, y) UTEST_EXPECT(x, y, >=)
  336. #define EXPECT_STREQ(x, y) \
  337. if (0 != strcmp(x, y)) { \
  338. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  339. UTEST_PRINTF(" Expected : \"%s\"\n", x); \
  340. UTEST_PRINTF(" Actual : \"%s\"\n", y); \
  341. *utest_result = 1; \
  342. }
  343. #define EXPECT_STRNE(x, y) \
  344. if (0 == strcmp(x, y)) { \
  345. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  346. UTEST_PRINTF(" Expected : \"%s\"\n", x); \
  347. UTEST_PRINTF(" Actual : \"%s\"\n", y); \
  348. *utest_result = 1; \
  349. }
  350. #if defined(__clang__)
  351. #define UTEST_ASSERT(x, y, cond) \
  352. { \
  353. _Pragma("clang diagnostic push") _Pragma( \
  354. "clang diagnostic ignored \"-Wlanguage-extension-token\"") typeof(y) \
  355. xEval = (x); \
  356. typeof(y) yEval = (y); \
  357. _Pragma("clang diagnostic pop") if (!((xEval)cond(yEval))) { \
  358. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  359. UTEST_PRINTF(" Expected : "); \
  360. utest_type_printer(xEval); \
  361. UTEST_PRINTF("\n"); \
  362. UTEST_PRINTF(" Actual : "); \
  363. utest_type_printer(yEval); \
  364. UTEST_PRINTF("\n"); \
  365. *utest_result = 1; \
  366. return; \
  367. } \
  368. }
  369. #elif defined(__GNUC__)
  370. #define UTEST_ASSERT(x, y, cond) \
  371. { \
  372. typeof(y) xEval = (x); \
  373. typeof(y) yEval = (y); \
  374. if (!((xEval)cond(yEval))) { \
  375. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  376. UTEST_PRINTF(" Expected : "); \
  377. utest_type_printer(xEval); \
  378. UTEST_PRINTF("\n"); \
  379. UTEST_PRINTF(" Actual : "); \
  380. utest_type_printer(yEval); \
  381. UTEST_PRINTF("\n"); \
  382. *utest_result = 1; \
  383. return; \
  384. } \
  385. }
  386. #else
  387. #define UTEST_ASSERT(x, y, cond) \
  388. { \
  389. if (!((x)cond(y))) { \
  390. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  391. *utest_result = 1; \
  392. return; \
  393. } \
  394. }
  395. #endif
  396. #define ASSERT_TRUE(x) \
  397. if (!(x)) { \
  398. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  399. UTEST_PRINTF(" Expected : true\n"); \
  400. UTEST_PRINTF(" Actual : %s\n", (x) ? "true" : "false"); \
  401. *utest_result = 1; \
  402. return; \
  403. }
  404. #define ASSERT_FALSE(x) \
  405. if (x) { \
  406. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  407. UTEST_PRINTF(" Expected : false\n"); \
  408. UTEST_PRINTF(" Actual : %s\n", (x) ? "true" : "false"); \
  409. *utest_result = 1; \
  410. return; \
  411. }
  412. #define ASSERT_EQ(x, y) UTEST_ASSERT(x, y, ==)
  413. #define ASSERT_NE(x, y) UTEST_ASSERT(x, y, !=)
  414. #define ASSERT_LT(x, y) UTEST_ASSERT(x, y, <)
  415. #define ASSERT_LE(x, y) UTEST_ASSERT(x, y, <=)
  416. #define ASSERT_GT(x, y) UTEST_ASSERT(x, y, >)
  417. #define ASSERT_GE(x, y) UTEST_ASSERT(x, y, >=)
  418. #define ASSERT_STREQ(x, y) \
  419. EXPECT_STREQ(x, y); \
  420. if (0 != strcmp(x, y)) { \
  421. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  422. UTEST_PRINTF(" Expected : \"%s\"\n", x); \
  423. UTEST_PRINTF(" Actual : \"%s\"\n", y); \
  424. *utest_result = 1; \
  425. return; \
  426. }
  427. #define ASSERT_STRNE(x, y) \
  428. EXPECT_STRNE(x, y); \
  429. if (0 == strcmp(x, y)) { \
  430. UTEST_PRINTF("%s:%u: Failure\n", __FILE__, __LINE__); \
  431. UTEST_PRINTF(" Expected : \"%s\"\n", x); \
  432. UTEST_PRINTF(" Actual : \"%s\"\n", y); \
  433. *utest_result = 1; \
  434. return; \
  435. }
  436. #define UTEST(SET, NAME) \
  437. UTEST_EXTERN struct utest_state_s utest_state; \
  438. static void utest_run_##SET##_##NAME(int *utest_result); \
  439. static void utest_##SET##_##NAME(int *utest_result, size_t utest_index) { \
  440. (void)utest_index; \
  441. utest_run_##SET##_##NAME(utest_result); \
  442. } \
  443. UTEST_INITIALIZER(utest_register_##SET##_##NAME) { \
  444. const size_t index = utest_state.tests_length++; \
  445. const char *name_part = #SET "." #NAME; \
  446. const size_t name_size = strlen(name_part) + 1; \
  447. char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \
  448. utest_state.tests = \
  449. UTEST_PTR_CAST(struct utest_test_state_s *, \
  450. realloc(UTEST_PTR_CAST(void *, utest_state.tests), \
  451. sizeof(struct utest_test_state_s) * \
  452. utest_state.tests_length)); \
  453. utest_state.tests[index].func = &utest_##SET##_##NAME; \
  454. utest_state.tests[index].name = name; \
  455. UTEST_SNPRINTF(name, name_size, "%s", name_part); \
  456. } \
  457. void utest_run_##SET##_##NAME(int *utest_result)
  458. #define UTEST_F_SETUP(FIXTURE) \
  459. static void utest_f_setup_##FIXTURE(int *utest_result, \
  460. struct FIXTURE *utest_fixture)
  461. #define UTEST_F_TEARDOWN(FIXTURE) \
  462. static void utest_f_teardown_##FIXTURE(int *utest_result, \
  463. struct FIXTURE *utest_fixture)
  464. #define UTEST_F(FIXTURE, NAME) \
  465. UTEST_EXTERN struct utest_state_s utest_state; \
  466. static void utest_f_setup_##FIXTURE(int *, struct FIXTURE *); \
  467. static void utest_f_teardown_##FIXTURE(int *, struct FIXTURE *); \
  468. static void utest_run_##FIXTURE##_##NAME(int *, struct FIXTURE *); \
  469. static void utest_f_##FIXTURE##_##NAME(int *utest_result, \
  470. size_t utest_index) { \
  471. struct FIXTURE fixture; \
  472. (void)utest_index; \
  473. memset(&fixture, 0, sizeof(fixture)); \
  474. utest_f_setup_##FIXTURE(utest_result, &fixture); \
  475. if (0 != *utest_result) { \
  476. return; \
  477. } \
  478. utest_run_##FIXTURE##_##NAME(utest_result, &fixture); \
  479. utest_f_teardown_##FIXTURE(utest_result, &fixture); \
  480. } \
  481. UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME) { \
  482. const size_t index = utest_state.tests_length++; \
  483. const char *name_part = #FIXTURE "." #NAME; \
  484. const size_t name_size = strlen(name_part) + 1; \
  485. char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \
  486. utest_state.tests = \
  487. UTEST_PTR_CAST(struct utest_test_state_s *, \
  488. realloc(UTEST_PTR_CAST(void *, utest_state.tests), \
  489. sizeof(struct utest_test_state_s) * \
  490. utest_state.tests_length)); \
  491. utest_state.tests[index].func = &utest_f_##FIXTURE##_##NAME; \
  492. utest_state.tests[index].name = name; \
  493. UTEST_SNPRINTF(name, name_size, "%s", name_part); \
  494. } \
  495. void utest_run_##FIXTURE##_##NAME(int *utest_result, \
  496. struct FIXTURE *utest_fixture)
  497. #define UTEST_I_SETUP(FIXTURE) \
  498. static void utest_i_setup_##FIXTURE( \
  499. int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index)
  500. #define UTEST_I_TEARDOWN(FIXTURE) \
  501. static void utest_i_teardown_##FIXTURE( \
  502. int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index)
  503. #define UTEST_I(FIXTURE, NAME, INDEX) \
  504. UTEST_EXTERN struct utest_state_s utest_state; \
  505. static void utest_run_##FIXTURE##_##NAME##_##INDEX(int *, struct FIXTURE *); \
  506. static void utest_i_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \
  507. size_t index) { \
  508. struct FIXTURE fixture; \
  509. memset(&fixture, 0, sizeof(fixture)); \
  510. utest_i_setup_##FIXTURE(utest_result, &fixture, index); \
  511. if (0 != *utest_result) { \
  512. return; \
  513. } \
  514. utest_run_##FIXTURE##_##NAME##_##INDEX(utest_result, &fixture); \
  515. utest_i_teardown_##FIXTURE(utest_result, &fixture, index); \
  516. } \
  517. UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME##_##INDEX) { \
  518. size_t i; \
  519. uint64_t iUp; \
  520. for (i = 0; i < (INDEX); i++) { \
  521. const size_t index = utest_state.tests_length++; \
  522. const char *name_part = #FIXTURE "." #NAME; \
  523. const size_t name_size = strlen(name_part) + 32; \
  524. char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \
  525. utest_state.tests = \
  526. UTEST_PTR_CAST(struct utest_test_state_s *, \
  527. realloc(UTEST_PTR_CAST(void *, utest_state.tests), \
  528. sizeof(struct utest_test_state_s) * \
  529. utest_state.tests_length)); \
  530. utest_state.tests[index].func = &utest_i_##FIXTURE##_##NAME##_##INDEX; \
  531. utest_state.tests[index].index = i; \
  532. utest_state.tests[index].name = name; \
  533. iUp = UTEST_CAST(uint64_t, i); \
  534. UTEST_SNPRINTF(name, name_size, "%s/%" UTEST_PRIu64, name_part, iUp); \
  535. } \
  536. } \
  537. void utest_run_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \
  538. struct FIXTURE *utest_fixture)
  539. UTEST_WEAK
  540. int utest_should_filter_test(const char *filter, const char *testcase);
  541. UTEST_WEAK int utest_should_filter_test(const char *filter,
  542. const char *testcase) {
  543. if (filter) {
  544. const char *filter_cur = filter;
  545. const char *testcase_cur = testcase;
  546. const char *filter_wildcard = 0;
  547. while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) {
  548. if ('*' == *filter_cur) {
  549. /* store the position of the wildcard */
  550. filter_wildcard = filter_cur;
  551. /* skip the wildcard character */
  552. filter_cur++;
  553. while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) {
  554. if ('*' == *filter_cur) {
  555. /*
  556. we found another wildcard (filter is something like *foo*) so we
  557. exit the current loop, and return to the parent loop to handle
  558. the wildcard case
  559. */
  560. break;
  561. } else if (*filter_cur != *testcase_cur) {
  562. /* otherwise our filter didn't match, so reset it */
  563. filter_cur = filter_wildcard;
  564. }
  565. /* move testcase along */
  566. testcase_cur++;
  567. /* move filter along */
  568. filter_cur++;
  569. }
  570. if (('\0' == *filter_cur) && ('\0' == *testcase_cur)) {
  571. return 0;
  572. }
  573. /* if the testcase has been exhausted, we don't have a match! */
  574. if ('\0' == *testcase_cur) {
  575. return 1;
  576. }
  577. } else {
  578. if (*testcase_cur != *filter_cur) {
  579. /* test case doesn't match filter */
  580. return 1;
  581. } else {
  582. /* move our filter and testcase forward */
  583. testcase_cur++;
  584. filter_cur++;
  585. }
  586. }
  587. }
  588. if (('\0' != *filter_cur) ||
  589. (('\0' != *testcase_cur) &&
  590. ((filter == filter_cur) || ('*' != filter_cur[-1])))) {
  591. /* we have a mismatch! */
  592. return 1;
  593. }
  594. }
  595. return 0;
  596. }
  597. static UTEST_INLINE int utest_strncmp(const char *a, const char *b, size_t n) {
  598. /* strncmp breaks on Wall / Werror on gcc/clang, so we avoid using it */
  599. unsigned i;
  600. for (i = 0; i < n; i++) {
  601. if (a[i] < b[i]) {
  602. return -1;
  603. } else if (a[i] > b[i]) {
  604. return 1;
  605. }
  606. }
  607. return 0;
  608. }
  609. static UTEST_INLINE FILE *utest_fopen(const char *filename, const char *mode) {
  610. #ifdef _MSC_VER
  611. FILE *file;
  612. if (0 == fopen_s(&file, filename, mode)) {
  613. return file;
  614. } else {
  615. return 0;
  616. }
  617. #else
  618. return fopen(filename, mode);
  619. #endif
  620. }
  621. UTEST_WEAK int utest_main(int argc, const char *const argv[]);
  622. UTEST_WEAK int utest_main(int argc, const char *const argv[]) {
  623. uint64_t failed = 0;
  624. size_t index = 0;
  625. size_t *failed_testcases = 0;
  626. size_t failed_testcases_length = 0;
  627. const char *filter = 0;
  628. uint64_t ran_tests = 0;
  629. enum colours { RESET, GREEN, RED };
  630. const int use_colours = UTEST_COLOUR_OUTPUT();
  631. const char *colours[] = {"\033[0m", "\033[32m", "\033[31m"};
  632. if (!use_colours) {
  633. for (index = 0; index < sizeof colours / sizeof colours[0]; index++) {
  634. colours[index] = "";
  635. }
  636. }
  637. /* loop through all arguments looking for our options */
  638. for (index = 1; index < UTEST_CAST(size_t, argc); index++) {
  639. const char help_str[] = "--help";
  640. const char filter_str[] = "--filter=";
  641. const char output_str[] = "--output=";
  642. if (0 == utest_strncmp(argv[index], help_str, strlen(help_str))) {
  643. printf("utest.h - the single file unit testing solution for C/C++!\n"
  644. "Command line Options:\n"
  645. " --help Show this message and exit.\n"
  646. " --filter=<filter> Filter the test cases to run (EG. MyTest*.a "
  647. "would run MyTestCase.a but not MyTestCase.b).\n"
  648. " --output=<output> Output an xunit XML file to the file "
  649. "specified in <output>.\n");
  650. goto cleanup;
  651. } else if (0 ==
  652. utest_strncmp(argv[index], filter_str, strlen(filter_str))) {
  653. /* user wants to filter what test cases run! */
  654. filter = argv[index] + strlen(filter_str);
  655. } else if (0 ==
  656. utest_strncmp(argv[index], output_str, strlen(output_str))) {
  657. utest_state.output = utest_fopen(argv[index] + strlen(output_str), "w+");
  658. }
  659. }
  660. for (index = 0; index < utest_state.tests_length; index++) {
  661. if (utest_should_filter_test(filter, utest_state.tests[index].name)) {
  662. continue;
  663. }
  664. ran_tests++;
  665. }
  666. printf("%s[==========]%s Running %" UTEST_PRIu64 " test cases.\n",
  667. colours[GREEN], colours[RESET], UTEST_CAST(uint64_t, ran_tests));
  668. if (utest_state.output) {
  669. fprintf(utest_state.output, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  670. fprintf(utest_state.output,
  671. "<testsuites tests=\"%" UTEST_PRIu64 "\" name=\"All\">\n",
  672. UTEST_CAST(uint64_t, ran_tests));
  673. fprintf(utest_state.output,
  674. "<testsuite name=\"Tests\" tests=\"%" UTEST_PRIu64 "\">\n",
  675. UTEST_CAST(uint64_t, ran_tests));
  676. }
  677. for (index = 0; index < utest_state.tests_length; index++) {
  678. int result = 0;
  679. int64_t ns = 0;
  680. if (utest_should_filter_test(filter, utest_state.tests[index].name)) {
  681. continue;
  682. }
  683. printf("%s[ RUN ]%s %s\n", colours[GREEN], colours[RESET],
  684. utest_state.tests[index].name);
  685. if (utest_state.output) {
  686. fprintf(utest_state.output, "<testcase name=\"%s\">",
  687. utest_state.tests[index].name);
  688. }
  689. ns = utest_ns();
  690. utest_state.tests[index].func(&result, utest_state.tests[index].index);
  691. ns = utest_ns() - ns;
  692. if (utest_state.output) {
  693. fprintf(utest_state.output, "</testcase>\n");
  694. }
  695. if (0 != result) {
  696. const size_t failed_testcase_index = failed_testcases_length++;
  697. failed_testcases = UTEST_PTR_CAST(
  698. size_t *, realloc(UTEST_PTR_CAST(void *, failed_testcases),
  699. sizeof(size_t) * failed_testcases_length));
  700. failed_testcases[failed_testcase_index] = index;
  701. failed++;
  702. printf("%s[ FAILED ]%s %s (%" UTEST_PRId64 "ns)\n", colours[RED],
  703. colours[RESET], utest_state.tests[index].name, ns);
  704. } else {
  705. printf("%s[ OK ]%s %s (%" UTEST_PRId64 "ns)\n", colours[GREEN],
  706. colours[RESET], utest_state.tests[index].name, ns);
  707. }
  708. }
  709. printf("%s[==========]%s %" UTEST_PRIu64 " test cases ran.\n", colours[GREEN],
  710. colours[RESET], ran_tests);
  711. printf("%s[ PASSED ]%s %" UTEST_PRIu64 " tests.\n", colours[GREEN],
  712. colours[RESET], ran_tests - failed);
  713. if (0 != failed) {
  714. printf("%s[ FAILED ]%s %" UTEST_PRIu64 " tests, listed below:\n",
  715. colours[RED], colours[RESET], failed);
  716. for (index = 0; index < failed_testcases_length; index++) {
  717. printf("%s[ FAILED ]%s %s\n", colours[RED], colours[RESET],
  718. utest_state.tests[failed_testcases[index]].name);
  719. }
  720. }
  721. if (utest_state.output) {
  722. fprintf(utest_state.output, "</testsuite>\n</testsuites>\n");
  723. }
  724. cleanup:
  725. for (index = 0; index < utest_state.tests_length; index++) {
  726. free(UTEST_PTR_CAST(void *, utest_state.tests[index].name));
  727. }
  728. free(UTEST_PTR_CAST(void *, failed_testcases));
  729. free(UTEST_PTR_CAST(void *, utest_state.tests));
  730. if (utest_state.output) {
  731. fclose(utest_state.output);
  732. }
  733. return UTEST_CAST(int, failed);
  734. }
  735. /*
  736. we need, in exactly one source file, define the global struct that will hold
  737. the data we need to run utest. This macro allows the user to declare the
  738. data without having to use the UTEST_MAIN macro, thus allowing them to write
  739. their own main() function.
  740. */
  741. #define UTEST_STATE() struct utest_state_s utest_state = {0, 0, 0}
  742. /*
  743. define a main() function to call into utest.h and start executing tests! A
  744. user can optionally not use this macro, and instead define their own main()
  745. function and manually call utest_main. The user must, in exactly one source
  746. file, use the UTEST_STATE macro to declare a global struct variable that
  747. utest requires.
  748. */
  749. #define UTEST_MAIN() \
  750. UTEST_STATE(); \
  751. int main(int argc, const char *const argv[]) { \
  752. return utest_main(argc, argv); \
  753. }
  754. #endif /* SHEREDOM_UTEST_H_INCLUDED */