cut.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #ifndef __CUT_H__
  2. #define __CUT_H__
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. #include <stdio.h>
  7. #include <stdarg.h>
  8. #include <stdlib.h>
  9. #include <setjmp.h>
  10. #include <string.h>
  11. #include <assert.h>
  12. #define CUT_CASE_MAX_CNT (1024)
  13. #define CUT_MSG_MAX_LEN (512)
  14. #define cut_printf printf
  15. #define cut_snprintf snprintf
  16. #define cut_malloc malloc
  17. #define cut_free free
  18. #define CASE2 CASEs
  19. extern int cut_main(int argc, char **argv);
  20. extern struct cut_runtime cut;
  21. struct cut_case {
  22. const char *sname;
  23. const char *cname;
  24. void *data;
  25. void (*run)(void *, void *);
  26. void (*setup)(void *, void *);
  27. void (*teardown)(void *);
  28. int skip;
  29. };
  30. struct cut_runtime {
  31. jmp_buf jmpbuf;
  32. int scnt_total;
  33. int ccnt_total;
  34. int ccnt_pass;
  35. int ccnt_fail;
  36. int ccnt_skip;
  37. struct cut_case *clist[CUT_CASE_MAX_CNT];
  38. struct cut_case *ccur;
  39. char *cerrmsg[CUT_CASE_MAX_CNT];
  40. };
  41. #define CUT_CASE_RUNNER(sname, cname) cut_##sname##_##cname##_run
  42. #define CUT_CASE_NAME(sname, cname) cut_##sname##_##cname
  43. #define CUT_CASE_DATA(sname) cut_##sname##_data
  44. #define CUT_CASE_SETUP(sname) cut_##sname##_setup
  45. #define CUT_CASE_TEARDOWN(sname) cut_##sname##_teardown
  46. #define DATA(sname) \
  47. struct CUT_CASE_DATA(sname)
  48. #define SETUP(sname) \
  49. static void CUT_CASE_SETUP(sname)(struct CUT_CASE_DATA(sname) *data, struct cut_case *case_data)
  50. #define TEARDOWN(sname) \
  51. static void CUT_CASE_TEARDOWN(sname)(struct CUT_CASE_DATA(sname) *data)
  52. /*
  53. * @brief: construct a test case structor and a test case runner
  54. * @sname: suite name
  55. * @cname: case name
  56. * e.g.
  57. CASE(mysuite, mycase1) {
  58. // do something here
  59. ASSERT_TRUE(1);
  60. }
  61. */
  62. #define CASE(sname, cname) \
  63. static void CUT_CASE_RUNNER(sname, cname)(void *null, struct cut_case *case_data); \
  64. static struct cut_case CUT_CASE_NAME(sname, cname) = \
  65. { \
  66. #sname, #cname, NULL, (void(*)(void*,void*))CUT_CASE_RUNNER(sname, cname), NULL, NULL, 0}; \
  67. static void CUT_CASE_RUNNER(sname, cname)(void *null, struct cut_case *case_data)
  68. /*
  69. * @brief: construct a test case structor and a test case runner
  70. * with case_data/setup/teardown for each case.
  71. * @sname: suite name
  72. * @cname: case name
  73. * e.g.
  74. CASE_DATA(mysuite) {
  75. int errmsg;
  76. char *errcode;
  77. };
  78. CASE_SETUP(mysuite) {
  79. data->errcode = 0;
  80. data->errmsg = (char*)malloc(100);
  81. }
  82. CASE_TEARDOWN(mysuite) {
  83. if(data->errmsg) {
  84. free(data->errmsg);
  85. data->errmsg = NULL;
  86. }
  87. }
  88. CASEs(mysuite, mycase1) {
  89. data->errcode = 1;
  90. strcpy(data->errmsg, "timeout error");
  91. ASSERT_TRUE(1);
  92. }
  93. */
  94. #define CASEs(sname, cname) \
  95. static struct CUT_CASE_DATA(sname) CUT_CASE_DATA(sname); \
  96. static void CUT_CASE_RUNNER(sname, cname)(struct CUT_CASE_DATA(sname) * data,struct cut_case *case_data); \
  97. static struct cut_case CUT_CASE_NAME(sname, cname) = \
  98. { \
  99. #sname, #cname, &CUT_CASE_DATA(sname), (void(*)(void*,void*))CUT_CASE_RUNNER(sname, cname), \
  100. (void(*)(void*,void*))CUT_CASE_SETUP(sname), (void(*)(void*))CUT_CASE_TEARDOWN(sname), 0}; \
  101. \
  102. static void CUT_CASE_RUNNER(sname, cname)(struct CUT_CASE_DATA(sname) * data, struct cut_case *case_data)
  103. /*
  104. * @brief: construct a test suite by adding test case(s)
  105. * @sname: suite name
  106. * e.g.
  107. SUITE(mysuite) = {
  108. ADD_CASE(mysuite, mycase1),
  109. ADD_CASE(mysuite, mycase2),
  110. ADD_CASE_NULL
  111. };
  112. */
  113. #define SUITE(sname) struct cut_case *cut_suite_##sname[]
  114. /*
  115. * @brief: add a test case into a test suite
  116. * @sname: suite name
  117. * @cname: case name
  118. */
  119. #define ADD_CASE(sname, cname) &CUT_CASE_NAME(sname, cname)
  120. #define ADD_CASE_NULL (struct cut_case*)(NULL)
  121. /*
  122. * @brief: add a test suite into case list
  123. * @sname: suite name
  124. */
  125. #define ADD_SUITE(sname) \
  126. do { \
  127. int i = 0; \
  128. extern struct cut_case *cut_suite_##sname[]; \
  129. struct cut_case *c = cut_suite_##sname[i]; \
  130. if (cut.ccnt_total >= CUT_CASE_MAX_CNT) { \
  131. cut_printf("reaches maximum case count:%d\n", \
  132. CUT_CASE_MAX_CNT); \
  133. break; \
  134. } \
  135. while (c) { \
  136. *(cut.clist + cut.ccnt_total++) = c; \
  137. c = *(cut_suite_##sname + (++i)); \
  138. } \
  139. } while (0)
  140. #define TRY if (0 == setjmp(cut.jmpbuf))
  141. #define EXCEPT else
  142. #define RAISE_EXCEPTION_WITH_MSG(msg) \
  143. do { \
  144. int ret = 0, i = cut.ccnt_fail; \
  145. cut.cerrmsg[i] = (char*)cut_malloc(CUT_MSG_MAX_LEN); \
  146. assert(cut.cerrmsg[i] != NULL); \
  147. memset(cut.cerrmsg[i], 0, CUT_MSG_MAX_LEN); \
  148. ret = cut_snprintf(cut.cerrmsg[i], \
  149. CUT_MSG_MAX_LEN - 1, \
  150. "%s.%s in %s(%d) expected %s", \
  151. cut.ccur->sname, cut.ccur->cname, \
  152. __FILE__, __LINE__, msg); \
  153. if (ret >= CUT_MSG_MAX_LEN) \
  154. cut_snprintf(cut.cerrmsg[i] + CUT_MSG_MAX_LEN - 4, \
  155. 4, "..."); \
  156. longjmp(cut.jmpbuf, 1); \
  157. } while (0)
  158. #define ASSERT_TRUE(cond) \
  159. do { \
  160. if (!(cond)) \
  161. RAISE_EXCEPTION_WITH_MSG("[True]"); \
  162. } while (0)
  163. #define ASSERT_INT(expected, compare, actual) \
  164. do { \
  165. if (!((expected)compare(actual))) \
  166. RAISE_EXCEPTION_WITH_MSG("[" #expected " " #compare " " #actual "]"); \
  167. } while (0)
  168. #define ASSERT_STR(expected, compare, actual) \
  169. do { \
  170. if (!(strcmp((expected), (actual)) compare 0)) \
  171. RAISE_EXCEPTION_WITH_MSG("[" #expected " " #compare " " #actual "]"); \
  172. } while (0)
  173. #define ASSERT_IN(expected1, actual, expected2) \
  174. do { \
  175. if ((actual) < (expected1) || (actual) > (expected2)) \
  176. RAISE_EXCEPTION_WITH_MSG("[" #expected1 " <= " #actual " <= " #expected2 "]"); \
  177. } while (0)
  178. #define ASSERT_NSTR(expected, compare, actual, len) \
  179. do { \
  180. if (!(strncmp((expected), (actual), (len)) compare 0)) \
  181. RAISE_EXCEPTION_WITH_MSG("[" #expected " " #compare " " #actual "]"); \
  182. } while (0)
  183. #define ASSERT_FAIL() RAISE_EXCEPTION_WITH_MSG("[should not be here]")
  184. #define ASSERT_FALSE(cond) ASSERT_TRUE(!(cond))
  185. #define ASSERT_NULL(ptr) ASSERT_INT(ptr, ==, NULL)
  186. #define ASSERT_NOT_NULL(ptr) ASSERT_INT(ptr, !=, NULL)
  187. #define ASSERT_EQ(actual, expected) ASSERT_INT(actual, ==, expected)
  188. #define ASSERT_NE(actual, expected) ASSERT_INT(actual, !=, expected)
  189. #define ASSERT_GT(actual, expected) ASSERT_INT(actual, >, expected)
  190. #define ASSERT_GE(actual, expected) ASSERT_INT(actual, >=, expected)
  191. #define ASSERT_LT(actual, expected) ASSERT_INT(actual, <, expected)
  192. #define ASSERT_LE(actual, expected) ASSERT_INT(actual, <=, expected)
  193. #define ASSERT_STR_EQ(actual, expected) ASSERT_STR(actual, ==, expected)
  194. #define ASSERT_STR_NE(actual, expected) ASSERT_STR(actual, !=, expected)
  195. #define ASSERT_STR_GT(actual, expected) ASSERT_STR(actual, >, expected)
  196. #define ASSERT_STR_LT(actual, expected) ASSERT_STR(actual, <, expected)
  197. #define ASSERT_NSTR_EQ(actual, expected, len) ASSERT_NSTR(actual, ==, expected, len)
  198. #define ASSERT_NSTR_NE(actual, expected, len) ASSERT_NSTR(actual, !=, expected, len)
  199. #define ASSERT_NSTR_GT(actual, expected, len) ASSERT_NSTR(actual, >, expected, len)
  200. #define ASSERT_NSTR_LT(actual, expected, len) ASSERT_NSTR(actual, <, expected, len)
  201. /*
  202. * see http://stackoverflow.com/questions/3585846/color-text-in-terminal-applications-in-unix
  203. */
  204. #define COL_DEF "\x1B[0m"
  205. #define COL_RED "\x1B[1;31m"
  206. #define COL_GRE "\x1B[1;32m"
  207. #define COL_YEL "\x1B[1;33m"
  208. #define COL_BLU "\x1B[1;34m"
  209. #define COL_MAG "\x1B[1;35m"
  210. #define COL_CYN "\x1B[1;36m"
  211. #define COL_WHE "\x1B[1;37m"
  212. #ifdef __cplusplus
  213. }
  214. #endif
  215. #endif /* __CUT_H__ */