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