Phoenix
Object-oriented orthogonally persistent operating system
|
00001 /* 00002 * /phoenix/unit_tests/ut/phoenix_ut.h 00003 * 00004 * This file is a part of Phoenix operating system. 00005 * Copyright (c) 2011-2012, Artyom Lebedev <artyom.lebedev@gmail.com> 00006 * All rights reserved. 00007 * See COPYING file for copyright details. 00008 */ 00009 00016 #ifndef PHOENIX_UT_H_ 00017 #define PHOENIX_UT_H_ 00018 00019 #define __UT_CONCAT2(x, y) x##y 00020 00021 #define __UT_CONCAT(x, y) __UT_CONCAT2(x, y) 00022 00023 #define __UT_STR2(x) # x 00024 00025 #define __UT_STR(x) __UT_STR2(x) 00026 00028 //XXX should use __COUNTER__ after Eclipse will recognize it. 00029 #ifdef __CDT_PARSER__ 00030 #define __UT_UID(str) __UT_CONCAT(str, __LINE__) 00031 #else /* __CDT_PARSER__ */ 00032 #define __UT_UID(str) __UT_CONCAT(str, __COUNTER__) 00033 #endif /* __CDT_PARSER__ */ 00034 00035 #define __UT_TEST_DESC __UT_CONCAT(UtTestDesc_, __LINE__) 00036 00048 #define UT_TEST(name) \ 00049 namespace { \ 00050 class __UT_TEST_DESC : public ut::TestDesc { \ 00051 public: \ 00052 __UT_TEST_DESC() : TestDesc(__FILE__, __LINE__, name) { } \ 00053 \ 00054 virtual void TestBody() 00055 00057 #define UT_TEST_END \ 00058 } __UT_UID(utTestDesc_); \ 00059 } /* anonymous namespace */ 00060 00070 #define UT(value) ut::TestValue<decltype(value)>(value, __UT_STR(value), __FILE__, __LINE__) 00071 00073 #define UT_BOOL(value) ut::TestValue<bool>(static_cast<bool>(value), __UT_STR(value), __FILE__, __LINE__) 00074 00076 #define UT_FALSE UT(false) 00077 00078 #define UT_TRUE UT(true) 00079 00081 #define UT_SIZE(value) UT(static_cast<size_t>(value)) 00082 00084 #define UT_NULL ut::TestValue<void *>(nullptr, "NULL", __FILE__, __LINE__) 00085 00089 #define UT_CPTR(value) ut::TestValue<const void *>( \ 00090 static_cast<const void *>(value), __UT_STR(value), __FILE__, __LINE__) 00091 00093 #define UT_PTR(value) ut::TestValue<void *>( \ 00094 static_cast<void *>(value), __UT_STR(value), __FILE__, __LINE__) 00095 00101 #define UT_CSTR(value) ut::TestValue<const char *>( \ 00102 static_cast<const char *>(value), __UT_STR(value), __FILE__, __LINE__) 00103 00107 #define UT_FAIL(desc, ...) ut::__ut_user_fault(__FILE__, __LINE__, desc, ## __VA_ARGS__) 00108 00112 #define UT_PASS() ut::__ut_hit_assert() 00113 00115 #define UT_TRACE(msg, ...) ut::__ut_trace(__FILE__, __LINE__, msg, ## __VA_ARGS__) 00116 00117 typedef __builtin_va_list __ut_va_list; 00118 00119 #define __ut_va_start(ap, last) __builtin_va_start((ap), (last)) 00120 #define __ut_va_arg(ap, type) __builtin_va_arg((ap), type) 00121 #define __ut_va_copy(dest, src) __builtin_va_copy((dest), (src)) 00122 #define __ut_va_end(ap) __builtin_va_end(ap) 00123 00125 namespace ut { 00126 00132 bool __ut_InitStubs(); 00133 00135 void *__ut_malloc(const char *file, int line, unsigned long size, unsigned long align = 0); 00137 void __ut_mfree(void *ptr); 00138 00140 void __ut_putc(char c); 00142 void __ut_trace(const char *file, int line, const char *msg, ...); 00144 void __ut_vtrace(const char *file, int line, const char *msg, __ut_va_list args); 00145 00147 void __ut_hit_value(); 00149 void __ut_hit_assert(); 00150 00151 unsigned __ut_strlen(const char *s); 00152 int __ut_strcmp(const char *s1, const char *s2); 00153 00154 int __ut_snprintf(char *str, unsigned long size, const char *format, ...); 00155 int __ut_vsnprintf(char *str, unsigned long size, const char *format, __ut_va_list ap); 00156 00157 class UtString { 00158 public: 00159 UtString(); 00160 UtString(void *handle); 00161 ~UtString(); 00162 00163 inline void *GetHandle() { return _handle; } 00164 00165 UtString &operator =(void *handle); 00166 UtString &operator =(const UtString &s); 00167 00168 template <typename T> 00169 void ToString(T value) 00170 { 00171 _ToString(value); 00172 } 00173 00174 template <typename T> 00175 void ToString(T *value) 00176 { 00177 _ToString(static_cast<void *>(value)); 00178 } 00179 00180 template <typename T> 00181 void ToString(const T *value) 00182 { 00183 _ToString(static_cast<void *>(const_cast<T *>(value))); 00184 } 00185 00186 void ToString(char *value) 00187 { 00188 _ToString(value); 00189 } 00190 00191 void ToString(const char *value) 00192 { 00193 _ToString(value); 00194 } 00195 00196 void ToString(bool value) 00197 { 00198 _ToString(value ? "true" : "false"); 00199 } 00200 00201 private: 00202 void *_handle; 00203 bool _allocated; 00204 00205 template <typename T> 00206 void _ToString(T value); 00207 }; 00208 00210 class TestDesc { 00211 public: 00212 TestDesc(const char *file, int line, const char *name); 00213 virtual ~TestDesc(); 00214 00215 virtual void TestBody() = 0; 00216 00217 inline const char *GetName() { return _name; } 00218 inline const char *GetFile() { return _file; } 00219 inline int GetLine() { return _line; } 00220 private: 00221 const char *_file; 00222 int _line; 00223 const char *_name; 00224 }; 00225 00227 class TestValueBase { 00228 public: 00229 TestValueBase() { 00230 _name = 0; 00231 _file = 0; 00232 _line = 0; 00233 } 00234 00235 TestValueBase(const TestValueBase& value) { 00236 _name = value._name; 00237 _file = value._file; 00238 _line = value._line; 00239 _value = value._value; 00240 } 00241 00242 TestValueBase(const char *name, const char *file, int line) { 00243 _name = name; 00244 _file = file; 00245 _line = line; 00246 } 00247 00248 template <typename T> 00249 void SetValue(T value) { 00250 _value.ToString(value); 00251 } 00252 00253 const char *GetName() { return _name; } 00254 00255 void Describe(UtString &_s); 00256 00257 protected: 00258 const char *_name, *_file; 00259 int _line; 00260 UtString _value; 00261 }; 00262 00266 class TestException { 00267 public: 00268 enum Type { 00269 BINARY_ASSERT, 00270 UNARY_ASSERT, 00271 USER_FAILURE 00272 }; 00273 00279 TestException(const char *op, const TestValueBase &value1, 00280 const TestValueBase &value2) : 00281 _value1(value1), _value2(value2) 00282 { 00283 _op = op; 00284 _type = BINARY_ASSERT; 00285 } 00286 00292 TestException(const char *op, const TestValueBase &value) : 00293 _value1(value) 00294 { 00295 _op = op; 00296 _type = UNARY_ASSERT; 00297 } 00298 00304 TestException(const char *desc, const char *file, int line) : 00305 _value1(desc, file, line) 00306 { 00307 _op = desc; 00308 _type = USER_FAILURE; 00309 } 00310 00311 ~TestException() 00312 { 00313 00314 } 00315 00316 void Describe(UtString &s); 00317 00318 private: 00319 TestValueBase _value1, _value2; 00320 const char *_op; 00321 Type _type; 00322 }; 00323 00327 template <typename T> 00328 class TestValue : public TestValueBase { 00329 public: 00330 T value; 00331 00332 TestValue(T value, const char *name, const char *file, int line) : 00333 TestValueBase(name, file, line), value(value) 00334 { 00335 SetValue(value); 00336 __ut_hit_value(); 00337 } 00338 00339 ~TestValue() { 00340 00341 } 00342 00343 /* Binary operators */ 00344 # define __UT_B_OPERATOR(__op) \ 00345 template <typename T2> \ 00346 bool operator __op(const TestValue<T2> &value2) { \ 00347 __ut_hit_assert(); \ 00348 if (value __op value2.value) { \ 00349 return true; \ 00350 } \ 00351 throw TestException(__UT_STR(__op), *this, value2); \ 00352 } 00353 00354 __UT_B_OPERATOR(==) 00355 __UT_B_OPERATOR(!=) 00356 __UT_B_OPERATOR(<) 00357 __UT_B_OPERATOR(<=) 00358 __UT_B_OPERATOR(>) 00359 __UT_B_OPERATOR(>=) 00360 00361 bool operator ==(const TestValue<const char *> &value2) { 00362 __ut_hit_assert(); 00363 if (!__ut_strcmp(value, value2.value)) { 00364 return true; 00365 } 00366 throw TestException("==", *this, value2); 00367 } 00368 00369 bool operator !=(const TestValue<const char *> &value2) { 00370 __ut_hit_assert(); 00371 if (__ut_strcmp(value, value2.value)) { 00372 return true; 00373 } 00374 throw TestException("!=", *this, value2); 00375 } 00376 00377 bool operator ==(const TestValue<char *> &value2) { 00378 __ut_hit_assert(); 00379 if (!__ut_strcmp(value, value2.value)) { 00380 return true; 00381 } 00382 throw TestException("==", *this, value2); 00383 } 00384 00385 bool operator !=(const TestValue<char *> &value2) { 00386 __ut_hit_assert(); 00387 if (__ut_strcmp(value, value2.value)) { 00388 return true; 00389 } 00390 throw TestException("!=", *this, value2); 00391 } 00392 00393 /* Unary operators */ 00394 # define __UT_U_OPERATOR(__op) \ 00395 bool operator __op() { \ 00396 __ut_hit_assert(); \ 00397 if (__op value) { \ 00398 return true; \ 00399 } \ 00400 throw TestException(__UT_STR(__op), *this); \ 00401 } 00402 00403 __UT_U_OPERATOR(!) 00404 }; 00405 00407 void __ut_user_fault(const char *file, int line, const char *desc, ...); 00408 00410 extern const char *__ut_test_description; 00411 00412 } 00413 00414 #endif /* PHOENIX_UT_H_ */