Phoenix
Object-oriented orthogonally persistent operating system
phoenix_ut.h
Go to the documentation of this file.
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_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines