github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/cybozu/test.hpp (about) 1 #pragma once 2 /** 3 @file 4 @brief unit test class 5 6 @author MITSUNARI Shigeo(@herumi) 7 */ 8 9 #include <stdio.h> 10 #include <string.h> 11 #include <string> 12 #include <list> 13 #include <iostream> 14 #include <utility> 15 #if defined(_MSC_VER) && (MSC_VER <= 1500) 16 #include <cybozu/inttype.hpp> 17 #else 18 #include <stdint.h> 19 #endif 20 21 namespace cybozu { namespace test { 22 23 class AutoRun { 24 typedef void (*Func)(); 25 typedef std::list<std::pair<const char*, Func> > UnitTestList; 26 public: 27 AutoRun() 28 : init_(0) 29 , term_(0) 30 , okCount_(0) 31 , ngCount_(0) 32 , exceptionCount_(0) 33 { 34 } 35 void setup(Func init, Func term) 36 { 37 init_ = init; 38 term_ = term; 39 } 40 void append(const char *name, Func func) 41 { 42 list_.push_back(std::make_pair(name, func)); 43 } 44 void set(bool isOK) 45 { 46 if (isOK) { 47 okCount_++; 48 } else { 49 ngCount_++; 50 } 51 } 52 std::string getBaseName(const std::string& name) const 53 { 54 #ifdef _WIN32 55 const char sep = '\\'; 56 #else 57 const char sep = '/'; 58 #endif 59 size_t pos = name.find_last_of(sep); 60 std::string ret = name.substr(pos + 1); 61 pos = ret.find('.'); 62 return ret.substr(0, pos); 63 } 64 int run(int, char *argv[]) 65 { 66 std::string msg; 67 try { 68 if (init_) init_(); 69 for (UnitTestList::const_iterator i = list_.begin(), ie = list_.end(); i != ie; ++i) { 70 std::cout << "ctest:module=" << i->first << std::endl; 71 try { 72 (i->second)(); 73 } catch (std::exception& e) { 74 exceptionCount_++; 75 std::cout << "ctest: " << i->first << " is stopped by exception " << e.what() << std::endl; 76 } catch (...) { 77 exceptionCount_++; 78 std::cout << "ctest: " << i->first << " is stopped by unknown exception" << std::endl; 79 } 80 } 81 if (term_) term_(); 82 } catch (std::exception& e) { 83 msg = std::string("ctest:err:") + e.what(); 84 } catch (...) { 85 msg = "ctest:err: catch unknown exception"; 86 } 87 fflush(stdout); 88 if (msg.empty()) { 89 int err = ngCount_ + exceptionCount_; 90 int total = okCount_ + err; 91 std::cout << "ctest:name=" << getBaseName(*argv) 92 << ", module=" << list_.size() 93 << ", total=" << total 94 << ", ok=" << okCount_ 95 << ", ng=" << ngCount_ 96 << ", exception=" << exceptionCount_ << std::endl; 97 return err > 0 ? 1 : 0; 98 } else { 99 std::cout << msg << std::endl; 100 return 1; 101 } 102 } 103 static inline AutoRun& getInstance() 104 { 105 static AutoRun instance; 106 return instance; 107 } 108 private: 109 Func init_; 110 Func term_; 111 int okCount_; 112 int ngCount_; 113 int exceptionCount_; 114 UnitTestList list_; 115 }; 116 117 static AutoRun& autoRun = AutoRun::getInstance(); 118 119 inline void test(bool ret, const std::string& msg, const std::string& param, const char *file, int line) 120 { 121 autoRun.set(ret); 122 if (!ret) { 123 printf("%s(%d):ctest:%s(%s);\n", file, line, msg.c_str(), param.c_str()); 124 } 125 } 126 127 template<typename T, typename U> 128 bool isEqual(const T& lhs, const U& rhs) 129 { 130 return lhs == rhs; 131 } 132 133 // avoid warning of comparision of integers of different signs 134 inline bool isEqual(size_t lhs, int rhs) 135 { 136 return lhs == size_t(rhs); 137 } 138 inline bool isEqual(int lhs, size_t rhs) 139 { 140 return size_t(lhs) == rhs; 141 } 142 inline bool isEqual(const char *lhs, const char *rhs) 143 { 144 return strcmp(lhs, rhs) == 0; 145 } 146 inline bool isEqual(char *lhs, const char *rhs) 147 { 148 return strcmp(lhs, rhs) == 0; 149 } 150 inline bool isEqual(const char *lhs, char *rhs) 151 { 152 return strcmp(lhs, rhs) == 0; 153 } 154 inline bool isEqual(char *lhs, char *rhs) 155 { 156 return strcmp(lhs, rhs) == 0; 157 } 158 // avoid to compare float directly 159 inline bool isEqual(float lhs, float rhs) 160 { 161 union fi { 162 float f; 163 uint32_t i; 164 } lfi, rfi; 165 lfi.f = lhs; 166 rfi.f = rhs; 167 return lfi.i == rfi.i; 168 } 169 // avoid to compare double directly 170 inline bool isEqual(double lhs, double rhs) 171 { 172 union di { 173 double d; 174 uint64_t i; 175 } ldi, rdi; 176 ldi.d = lhs; 177 rdi.d = rhs; 178 return ldi.i == rdi.i; 179 } 180 181 } } // cybozu::test 182 183 #ifndef CYBOZU_TEST_DISABLE_AUTO_RUN 184 int main(int argc, char *argv[]) 185 { 186 return cybozu::test::autoRun.run(argc, argv); 187 } 188 #endif 189 190 /** 191 alert if !x 192 @param x [in] 193 */ 194 #define CYBOZU_TEST_ASSERT(x) cybozu::test::test(!!(x), "CYBOZU_TEST_ASSERT", #x, __FILE__, __LINE__) 195 196 /** 197 alert if x != y 198 @param x [in] 199 @param y [in] 200 */ 201 #define CYBOZU_TEST_EQUAL(x, y) { \ 202 bool _cybozu_eq = cybozu::test::isEqual(x, y); \ 203 cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL", #x ", " #y, __FILE__, __LINE__); \ 204 if (!_cybozu_eq) { \ 205 std::cout << "ctest: lhs=" << (x) << std::endl; \ 206 std::cout << "ctest: rhs=" << (y) << std::endl; \ 207 } \ 208 } 209 /** 210 alert if fabs(x, y) >= eps 211 @param x [in] 212 @param y [in] 213 */ 214 #define CYBOZU_TEST_NEAR(x, y, eps) { \ 215 bool _cybozu_isNear = fabs((x) - (y)) < eps; \ 216 cybozu::test::test(_cybozu_isNear, "CYBOZU_TEST_NEAR", #x ", " #y, __FILE__, __LINE__); \ 217 if (!_cybozu_isNear) { \ 218 std::cout << "ctest: lhs=" << (x) << std::endl; \ 219 std::cout << "ctest: rhs=" << (y) << std::endl; \ 220 } \ 221 } 222 223 #define CYBOZU_TEST_EQUAL_POINTER(x, y) { \ 224 bool _cybozu_eq = x == y; \ 225 cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL_POINTER", #x ", " #y, __FILE__, __LINE__); \ 226 if (!_cybozu_eq) { \ 227 std::cout << "ctest: lhs=" << static_cast<const void*>(x) << std::endl; \ 228 std::cout << "ctest: rhs=" << static_cast<const void*>(y) << std::endl; \ 229 } \ 230 } 231 /** 232 alert if x[] != y[] 233 @param x [in] 234 @param y [in] 235 @param n [in] 236 */ 237 #define CYBOZU_TEST_EQUAL_ARRAY(x, y, n) { \ 238 for (size_t _cybozu_test_i = 0, _cybozu_ie = (size_t)(n); _cybozu_test_i < _cybozu_ie; _cybozu_test_i++) { \ 239 bool _cybozu_eq = cybozu::test::isEqual((x)[_cybozu_test_i], (y)[_cybozu_test_i]); \ 240 cybozu::test::test(_cybozu_eq, "CYBOZU_TEST_EQUAL_ARRAY", #x ", " #y ", " #n, __FILE__, __LINE__); \ 241 if (!_cybozu_eq) { \ 242 std::cout << "ctest: i=" << _cybozu_test_i << std::endl; \ 243 std::cout << "ctest: lhs=" << (x)[_cybozu_test_i] << std::endl; \ 244 std::cout << "ctest: rhs=" << (y)[_cybozu_test_i] << std::endl; \ 245 } \ 246 } \ 247 } 248 249 /** 250 always alert 251 @param msg [in] 252 */ 253 #define CYBOZU_TEST_FAIL(msg) cybozu::test::test(false, "CYBOZU_TEST_FAIL", msg, __FILE__, __LINE__) 254 255 /** 256 verify message in exception 257 */ 258 #define CYBOZU_TEST_EXCEPTION_MESSAGE(statement, Exception, msg) \ 259 { \ 260 int _cybozu_ret = 0; \ 261 std::string _cybozu_errMsg; \ 262 try { \ 263 statement; \ 264 _cybozu_ret = 1; \ 265 } catch (const Exception& _cybozu_e) { \ 266 _cybozu_errMsg = _cybozu_e.what(); \ 267 if (_cybozu_errMsg.find(msg) == std::string::npos) { \ 268 _cybozu_ret = 2; \ 269 } \ 270 } catch (...) { \ 271 _cybozu_ret = 3; \ 272 } \ 273 if (_cybozu_ret) { \ 274 cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION_MESSAGE", #statement ", " #Exception ", " #msg, __FILE__, __LINE__); \ 275 if (_cybozu_ret == 1) { \ 276 std::cout << "ctest: no exception" << std::endl; \ 277 } else if (_cybozu_ret == 2) { \ 278 std::cout << "ctest: bad exception msg:" << _cybozu_errMsg << std::endl; \ 279 } else { \ 280 std::cout << "ctest: unexpected exception" << std::endl; \ 281 } \ 282 } else { \ 283 cybozu::test::autoRun.set(true); \ 284 } \ 285 } 286 287 #define CYBOZU_TEST_EXCEPTION(statement, Exception) \ 288 { \ 289 int _cybozu_ret = 0; \ 290 try { \ 291 statement; \ 292 _cybozu_ret = 1; \ 293 } catch (const Exception&) { \ 294 } catch (...) { \ 295 _cybozu_ret = 2; \ 296 } \ 297 if (_cybozu_ret) { \ 298 cybozu::test::test(false, "CYBOZU_TEST_EXCEPTION", #statement ", " #Exception, __FILE__, __LINE__); \ 299 if (_cybozu_ret == 1) { \ 300 std::cout << "ctest: no exception" << std::endl; \ 301 } else { \ 302 std::cout << "ctest: unexpected exception" << std::endl; \ 303 } \ 304 } else { \ 305 cybozu::test::autoRun.set(true); \ 306 } \ 307 } 308 309 /** 310 verify statement does not throw 311 */ 312 #define CYBOZU_TEST_NO_EXCEPTION(statement) \ 313 try { \ 314 statement; \ 315 cybozu::test::autoRun.set(true); \ 316 } catch (...) { \ 317 cybozu::test::test(false, "CYBOZU_TEST_NO_EXCEPTION", #statement, __FILE__, __LINE__); \ 318 } 319 320 /** 321 append auto unit test 322 @param name [in] module name 323 */ 324 #define CYBOZU_TEST_AUTO(name) \ 325 void cybozu_test_ ## name(); \ 326 struct cybozu_test_local_ ## name { \ 327 cybozu_test_local_ ## name() \ 328 { \ 329 cybozu::test::autoRun.append(#name, cybozu_test_ ## name); \ 330 } \ 331 } cybozu_test_local_instance_ ## name; \ 332 void cybozu_test_ ## name() 333 334 /** 335 append auto unit test with fixture 336 @param name [in] module name 337 */ 338 #define CYBOZU_TEST_AUTO_WITH_FIXTURE(name, Fixture) \ 339 void cybozu_test_ ## name(); \ 340 void cybozu_test_real_ ## name() \ 341 { \ 342 Fixture f; \ 343 cybozu_test_ ## name(); \ 344 } \ 345 struct cybozu_test_local_ ## name { \ 346 cybozu_test_local_ ## name() \ 347 { \ 348 cybozu::test::autoRun.append(#name, cybozu_test_real_ ## name); \ 349 } \ 350 } cybozu_test_local_instance_ ## name; \ 351 void cybozu_test_ ## name() 352 353 /** 354 setup fixture 355 @param Fixture [in] class name of fixture 356 @note cstr of Fixture is called before test and dstr of Fixture is called after test 357 */ 358 #define CYBOZU_TEST_SETUP_FIXTURE(Fixture) \ 359 Fixture *cybozu_test_local_fixture; \ 360 void cybozu_test_local_init() \ 361 { \ 362 cybozu_test_local_fixture = new Fixture(); \ 363 } \ 364 void cybozu_test_local_term() \ 365 { \ 366 delete cybozu_test_local_fixture; \ 367 } \ 368 struct cybozu_test_local_fixture_setup_ { \ 369 cybozu_test_local_fixture_setup_() \ 370 { \ 371 cybozu::test::autoRun.setup(cybozu_test_local_init, cybozu_test_local_term); \ 372 } \ 373 } cybozu_test_local_fixture_setup_instance_;