UnitTest.h

Go to the documentation of this file.
00001 #ifndef __UNIT_TEST_H__
00002 #define __UNIT_TEST_H__
00003 
00004 #include <string>
00005 #include <vector>
00006 #include <stdio.h>
00007 
00008 #include "../debug/FatalSignals.h"
00009 #include "../debug/Log.h"
00010 #include "../io/PrettyPrintBuffer.h"
00011 
00012 namespace oasys {
00013 
00050 struct UnitTest {
00051     UnitTest(std::string name) : name_(name), failed_(false) {}
00052     virtual ~UnitTest() {}
00053 
00054     virtual int run() = 0;
00055     
00056     std::string name_;
00057     bool failed_;
00058 };
00059 
00060 enum {
00061     UNIT_TEST_PASSED = 0,
00062     UNIT_TEST_FAILED,
00063     UNIT_TEST_INPUT,      
00064 };
00065 
00082 class UnitTester {
00083     typedef std::vector<UnitTest*> UnitTestList;
00084 
00085 public:
00086     UnitTester(std::string name) : 
00087         name_(name), passed_(0), failed_(0), input_(0) 
00088     {
00089     }
00090     
00091     virtual ~UnitTester() {}
00092 
00093     int run_tests(int argc, const char* argv[]) {
00094         log_level_t level = LOG_NOTICE;
00095 
00096         // always skip argv[0]
00097         argc -= 1;
00098         argv += 1;
00099 
00100         // first look for -l debug (which must come first)
00101         if (argc >= 2 && (strcmp(argv[0], "-l") == 0))
00102         {
00103             level = str2level(argv[1]);
00104             argc -= 2;
00105             argv += 2;
00106         }
00107 
00108         Log::init(level);
00109         FatalSignals::init(name_.c_str());
00110         
00111         add_tests();
00112 
00113         bool in_tcl = false;
00114         
00115         if (argc >= 1 &&
00116             ((strcmp(argv[0], "-h") == 0) ||
00117              (strcmp(argv[0], "-help") == 0) ||
00118              (strcmp(argv[0], "--help") == 0)))
00119         {
00120             printf("%s [-h] {[test name]}*\n", argv[0]);
00121             printf("test names:\n");
00122             for (UnitTestList::const_iterator i = tests_.begin();
00123                  i != tests_.end(); ++i)
00124             {
00125                 printf("    %s\n", (*i)->name_.c_str());
00126             }
00127                    
00128             exit(0);
00129         }
00130 
00131         if (argc >= 1 && (strcmp(argv[1], "-test") == 0)) {
00132             argc -= 1;
00133             argv += 1;
00134             in_tcl = true;
00135         }
00136         
00137         UnitTestList new_tests;
00138         while (argc != 0) {
00139             for (UnitTestList::iterator i = tests_.begin();
00140                  i != tests_.end(); ++i)
00141             {
00142                 const char* testname = argv[0];
00143                 if (strcmp((*i)->name_.c_str(), testname) == 0) {
00144                     new_tests.push_back(*i);
00145                 }
00146             }            
00147             argc--;
00148             argv++;
00149         }
00150         if (new_tests.size() > 0) {
00151             std::swap(tests_, new_tests);
00152         }
00153 
00154         if (in_tcl) {
00155             print_tcl_header();
00156         } else {
00157             print_header();
00158         }
00159 
00160         int test_num = 1;
00161         for (UnitTestList::iterator i=tests_.begin(); 
00162              i != tests_.end(); ++i, ++test_num) 
00163         {
00164             printf("%s...\n",  (*i)->name_.c_str());
00165             fflush(stdout);
00166             
00167             int err = (*i)->run();
00168             switch(err) {
00169             case UNIT_TEST_PASSED:
00170                 if (in_tcl) {
00171                     fprintf(stderr, "{ %d %s P } ", 
00172                             test_num, (*i)->name_.c_str());
00173                 } else {
00174                     printf("%s... Passed\n\n",  (*i)->name_.c_str());
00175                 }
00176                 passed_++;
00177                 break;
00178             case UNIT_TEST_FAILED:
00179                 if (in_tcl) {
00180                     fprintf(stderr, "{ %d %s F } ", 
00181                             test_num, (*i)->name_.c_str());
00182                 } else {
00183                     printf("%s... Failed\n\n",  (*i)->name_.c_str());
00184                 }
00185                 failed_++;
00186                 break;
00187             case UNIT_TEST_INPUT:
00188                 if (in_tcl) {
00189                     fprintf(stderr, "{ %d %s I } ", 
00190                             test_num, (*i)->name_.c_str());
00191                 } else {
00192                     printf("%s... Unknown (UNIT_TEST_INPUT)\n\n",
00193                            (*i)->name_.c_str());
00194                 }
00195                 input_++;
00196                 break;                
00197             }
00198         }
00199 
00200         if (in_tcl) {
00201             print_tcl_tail();
00202         } else {
00203             print_results();
00204         }
00205 
00206         return 0;
00207     }
00208 
00209     void print_tcl_header() {
00210         fprintf(stderr, "set result { \"%s\" { ", name_.c_str());
00211     }
00212     void print_tcl_tail() {
00213         fprintf(stderr, "} { %zu %d %d %d } }\n", 
00214                 tests_.size(), passed_, failed_, input_);
00215     }
00216     void print_header() {
00217         printf("\n\nRunning Test: %s\n\n", name_.c_str());
00218     }
00219     
00220     void print_results() {
00221         printf("\n%s Complete:\n", name_.c_str());
00222         if (passed_ != 0) {
00223             printf("\t\t%u Passed\n", passed_);
00224         }
00225         if (failed_ != 0) {
00226             printf("\t\t%u Failed\n", failed_);
00227         }
00228     }
00229 
00230 protected:
00234     virtual void add_tests() = 0;
00235 
00239     void add(UnitTest* unit) {
00240         tests_.push_back(unit);
00241     }
00242     
00243 private:
00244     std::string  name_;
00245     UnitTestList tests_;
00246 
00247     int passed_;
00248     int failed_;
00249     int input_;
00250 };
00251 
00253 #define ADD_TEST(_name)                         \
00254         add(new _name ## UnitTest())
00255 
00256 #define DECLARE_TEST(_name)                             \
00257     struct _name ## UnitTest : public oasys::UnitTest { \
00258         _name ## UnitTest() : UnitTest(#_name) {}       \
00259         int run();                                      \
00260     };                                                  \
00261     int _name ## UnitTest::run()
00262 
00263 #define RUN_TESTER(_UnitTesterClass, testname, argc, argv)      \
00264     _UnitTesterClass test(testname);                            \
00265     return test.run_tests(argc, argv);
00266 
00267 #define DECLARE_TEST_FILE(_UnitTesterClass, testname)           \
00268 int main(int argc, const char* argv[]) {                        \
00269     RUN_TESTER(_UnitTesterClass, testname, argc, argv);         \
00270 }
00271 
00272 #define DECLARE_TESTER(_name)                                   \
00273 class _name : public oasys::UnitTester {                        \
00274 public:                                                         \
00275     _name::_name(std::string name) : UnitTester(name) {}        \
00276 protected:                                                      \
00277     void add_tests();                                           \
00278 };                                                              \
00279 void _name::add_tests()                                         \
00280 
00281 #define DO(x)                                                           \
00282     do {                                                                \
00283         ::oasys::__logf(oasys::LOG_NOTICE, "/test",                     \
00284                     "DO (%s) at %s:%d", #x, __FILE__, __LINE__);        \
00285         x;                                                              \
00286     } while (0)
00287 
00288 #define CHECK(x)                                                        \
00289     do { if (! (x)) {                                                   \
00290         ::oasys::Breaker::break_here();                                 \
00291         ::oasys::__logf(oasys::LOG_ERR, "/test",                        \
00292                     "CHECK FAILED (%s) at %s:%d",                       \
00293                     #x, __FILE__, __LINE__);                            \
00294         return oasys::UNIT_TEST_FAILED;                                 \
00295     } else {                                                            \
00296         ::oasys::__logf(oasys::LOG_NOTICE, "/test",                     \
00297                     "CHECK (%s) ok at %s:%d", #x, __FILE__, __LINE__);  \
00298     } } while(0)
00299 
00300 #define CHECK_EQUAL(_a, _b)                                                     \
00301     do { int a = _a; int b = _b; if ((a) != (b)) {                              \
00302         ::oasys::Breaker::break_here();                                         \
00303         oasys::logf("/test", oasys::LOG_ERR,                                    \
00304                     "CHECK FAILED: '" #_a "' (%d) != '" #_b "' (%d) at %s:%d",  \
00305                     (a), (b), __FILE__, __LINE__);                              \
00306         return oasys::UNIT_TEST_FAILED;                                         \
00307     } else {                                                                    \
00308         oasys::logf("/test", oasys::LOG_NOTICE,                                 \
00309                     "CHECK '" #_a "' (%d) == '" #_b "' (%d) "                   \
00310                     "at %s:%d", (a), (b), __FILE__, __LINE__);                  \
00311     } } while(0)
00312 
00313 #define CHECK_LT(_a, _b)                                                        \
00314     do { int a = _a; int b = _b; if (! (((a) < (b))) {                          \
00315         ::oasys::Breaker::break_here();                                         \
00316         oasys::logf("/test", oasys::LOG_ERR,                                    \
00317                     "CHECK FAILED: '" #_a "' (%d) < '" #_b "' (%d) at %s:%d",  \
00318                     (a), (b), __FILE__, __LINE__);                              \
00319         return oasys::UNIT_TEST_FAILED;                                         \
00320     } else {                                                                    \
00321         oasys::logf("/test", oasys::LOG_NOTICE,                                 \
00322                     "CHECK '" #_a "' (%d) < '" #_b "' (%d) "                    \
00323                     "at %s:%d", (a), (b), __FILE__, __LINE__);                  \
00324     } } while(0)
00325 
00326 #define CHECK_GT(_a, _b)                                                        \
00327     do { int a = _a; int b = _b; if (! ((a) > (b))) {                           \
00328         ::oasys::Breaker::break_here();                                         \
00329         oasys::logf("/test", oasys::LOG_ERR,                                    \
00330                     "CHECK FAILED: '" #_a "' (%d) > '" #_b "' (%d) at %s:%d",  \
00331                     (a), (b), __FILE__, __LINE__);                              \
00332         return oasys::UNIT_TEST_FAILED;                                         \
00333     } else {                                                                    \
00334         oasys::logf("/test", oasys::LOG_NOTICE,                                 \
00335                     "CHECK '" #_a "' (%d) > '" #_b "' (%d) "                    \
00336                     "at %s:%d", (a), (b), __FILE__, __LINE__);                  \
00337     } } while(0)
00338 
00339 #define CHECK_LTU(_a, _b)                                                       \
00340     do { u_int a = _a; u_int b = _b; if (! ((a) <= (b))) {                      \
00341         ::oasys::Breaker::break_here();                                         \
00342         oasys::logf("/test", oasys::LOG_ERR,                                    \
00343                     "CHECK FAILED: '" #_a "' (%u) <= '" #_b "' (%u) at %s:%u",  \
00344                     (a), (b), __FILE__, __LINE__);                              \
00345         return oasys::UNIT_TEST_FAILED;                                         \
00346     } else {                                                                    \
00347         oasys::logf("/test", oasys::LOG_NOTICE,                                 \
00348                     "CHECK '" #_a "' (%u) <= '" #_b "' (%u) "                   \
00349                     "at %s:%d", (a), (b), __FILE__, __LINE__);                  \
00350     } } while(0)
00351 
00352 #define CHECK_GTU(_a, _b)                                                       \
00353     do { u_int a = _a; u_int b = _b; if (! ((a) >= (b))) {                      \
00354         ::oasys::Breaker::break_here();                                         \
00355         oasys::logf("/test", oasys::LOG_ERR,                                    \
00356                     "CHECK FAILED: '" #_a "' (%u) >= '" #_b "' (%u) at %s:%u",  \
00357                     (a), (b), __FILE__, __LINE__);                              \
00358         return oasys::UNIT_TEST_FAILED;                                         \
00359     } else {                                                                    \
00360         oasys::logf("/test", oasys::LOG_NOTICE,                                 \
00361                     "CHECK '" #_a "' (%u) >= '" #_b "' (%u) "                   \
00362                     "at %s:%d", (a), (b), __FILE__, __LINE__);                  \
00363     } } while(0)
00364 
00365 #define CHECK_EQUAL_U64(a, b)                                                           \
00366     do { if ((a) != (b)) {                                                              \
00367         ::oasys::Breaker::break_here();                                                 \
00368         oasys::logf("/test", oasys::LOG_ERR,                                            \
00369                     "CHECK FAILED: '" #a "' (%llu) != '" #b "' (%llu) at %s:%d",        \
00370                     (u_int64_t)(a), (u_int64_t)(b), __FILE__, __LINE__);                \
00371         return oasys::UNIT_TEST_FAILED;                                                 \
00372     } else {                                                                            \
00373         oasys::logf("/test", oasys::LOG_NOTICE,                                         \
00374                     "CHECK '" #a "' (%llu) == '" #b "' (%llu) "                         \
00375                     "at %s:%d",                                                         \
00376                     (u_int64_t)(a), (u_int64_t)(b), __FILE__, __LINE__);                \
00377     } } while(0)
00378 
00379 #define CHECK_EQUALSTR(a, b)                                            \
00380     do { if (strcmp((a), (b)) != 0) {                                   \
00381         ::oasys::Breaker::break_here();                                 \
00382         oasys::logf("/test", oasys::LOG_ERR,                            \
00383                     "CHECK FAILED: '" #a "' != '" #b "' at %s:%d.",     \
00384                     __FILE__, __LINE__);                                \
00385         oasys::logf("/test", oasys::LOG_ERR, "Contents of " #a          \
00386                     " (length %zu): ", strlen(a));                      \
00387         oasys::PrettyPrintBuf buf_a(a, strlen(a));                      \
00388         std::string s;                                                  \
00389         bool done;                                                      \
00390         do {                                                            \
00391             done = buf_a.next_str(&s);                                  \
00392             oasys::logf("/test", oasys::LOG_ERR, s.c_str());            \
00393         } while (!done);                                                \
00394                                                                         \
00395         oasys::logf("/test", oasys::LOG_ERR, "Contents of " #b          \
00396                     " (length %zu): ", strlen(b));                      \
00397         oasys::PrettyPrintBuf buf_b(b, strlen(b));                      \
00398                                                                         \
00399         do {                                                            \
00400             done = buf_b.next_str(&s);                                  \
00401             oasys::logf("/test", oasys::LOG_ERR, s.c_str());            \
00402         } while (!done);                                                \
00403                                                                         \
00404         return oasys::UNIT_TEST_FAILED;                                 \
00405     } else {                                                            \
00406         oasys::logf("/test", oasys::LOG_NOTICE,                         \
00407                     "CHECK '" #a "' (%s) == '" #b "' (%s) "             \
00408                     "at %s:%d", (a), (b), __FILE__, __LINE__);          \
00409     } } while(0);
00410 
00411 #define CHECK_EQUALSTRN(a, b, len)                                              \
00412     do { u_int print_len = (len > 32) ? 32 : len;                               \
00413          if (strncmp((const char*)(a), (const char*)(b), (len)) != 0) {         \
00414              ::oasys::Breaker::break_here();                                    \
00415              oasys::logf("/test", oasys::LOG_ERR,  "CHECK FAILED: "             \
00416                          "'" #a "' (%.*s...) != '" #b "' (%.*s...) at %s:%d",   \
00417                          print_len, (a), print_len, (b),                        \
00418                          __FILE__, __LINE__);                                   \
00419              return oasys::UNIT_TEST_FAILED;                                    \
00420          } else {                                                               \
00421              oasys::logf("/test", oasys::LOG_NOTICE,                            \
00422                          "CHECK '" #a "' (%.*s...) == '" #b "' (%.*s...) "      \
00423                          "at %s:%d",                                            \
00424                          print_len, (a), print_len, (b), __FILE__, __LINE__);   \
00425         }                                                                       \
00426     } while(0)
00427  
00429 
00430 }; // namespace oasys
00431 
00432 #endif //__UNIT_TEST_H__

Generated on Fri Dec 22 14:48:01 2006 for DTN Reference Implementation by  doxygen 1.5.1