UnitTest.h

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2005-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 #ifndef __UNIT_TEST_H__
00018 #define __UNIT_TEST_H__
00019 
00020 #include <cstring>
00021 #include <string>
00022 #include <vector>
00023 #include <stdio.h>
00024 #include <errno.h>
00025 
00026 #include "../debug/FatalSignals.h"
00027 #include "../debug/Log.h"
00028 #include "../io/PrettyPrintBuffer.h"
00029 #include "../util/Random.h"
00030 
00031 namespace oasys {
00032 
00069 struct UnitTest {
00070     UnitTest(std::string name) : name_(name), failed_(false) {}
00071     virtual ~UnitTest() {}
00072 
00073     virtual int run() = 0;
00074     
00075     std::string name_;
00076     bool failed_;
00077 
00078     int         errno_;
00079     const char* strerror_;
00080 };
00081 
00082 enum {
00083     UNIT_TEST_PASSED = 0,
00084     UNIT_TEST_FAILED,
00085     UNIT_TEST_INPUT,      
00086 };
00087 
00104 class UnitTester {
00105     typedef std::vector<UnitTest*> UnitTestList;
00106 
00107 public:
00108     UnitTester(std::string name) :
00109         name_(name), passed_(0), failed_(0), input_(0),
00110         progname_(0), in_tcl_(false)
00111     {}
00112 
00113     virtual ~UnitTester() {}
00114     
00115     void init(int argc, const char* argv[], bool init_log)
00116     {
00117         progname_ = argv[0];
00118         argc -= 1;
00119         argv += 1;
00120         
00121         log_level_t level = LOG_NOTICE;
00122         struct timeval tv;
00123         ::gettimeofday(&tv, 0);
00124         u_int random_seed = tv.tv_sec;
00125 
00126         while (argc != 0) {
00127             if ((strcmp(argv[0], "-l") == 0) && (argc >= 2))
00128             {
00129                 level = str2level(argv[1]);
00130                 argc -= 2;
00131                 argv += 2;
00132             }
00133             else if (((strcmp(argv[0], "-h") == 0) ||
00134                       (strcmp(argv[0], "-help") == 0) ||
00135                       (strcmp(argv[0], "--help") == 0)))
00136             {
00137                 printf("%s [-h] {[test name]}*\n", progname_);
00138                 printf("test names:\n");
00139                 for (UnitTestList::const_iterator i = tests_.begin();
00140                      i != tests_.end(); ++i)
00141                 {
00142                     printf("    %s\n", (*i)->name_.c_str());
00143                 }
00144                 
00145                 exit(0);
00146             }
00147             else if (strcmp(argv[0], "--in_tcl") == 0)
00148             {
00149                 in_tcl_ = true;
00150             }
00151             else if ((strcmp(argv[0], "--seed") == 0) && (argc >= 2))
00152             {
00153                 char* end;
00154                 random_seed = strtoul(argv[1], &end, 10);
00155                 argc -= 2;
00156                 argv += 2;
00157             }
00158             else
00159             {
00160                 fprintf(stderr, "unknown unit test argument '%s',",
00161                         argv[0]);
00162                 exit(1);
00163             }
00164         }
00165 
00166         if (init_log) {
00167             Log::init(level);
00168         }
00169         FatalSignals::init(name_.c_str());
00170 
00171         oasys::Random::seed(random_seed);
00172         printf("Test random seed: %u\n", random_seed);
00173     }
00174 
00175     int run_tests() {
00176         add_tests();
00177 
00178         if (in_tcl_) {
00179             print_tcl_header();
00180         } else {
00181             print_header();
00182         }
00183 
00184         int test_num = 1;
00185         for (UnitTestList::iterator i=tests_.begin(); 
00186              i != tests_.end(); ++i, ++test_num) 
00187         {
00188             printf("%s...\n",  (*i)->name_.c_str());
00189             fflush(stdout);
00190             
00191             int err = (*i)->run();
00192             switch(err) {
00193             case UNIT_TEST_PASSED:
00194                 if (in_tcl_) {
00195                     fprintf(stderr, "{ %d %s P } ", 
00196                             test_num, (*i)->name_.c_str());
00197                 } else {
00198                     printf("%s... Passed\n\n",  (*i)->name_.c_str());
00199                 }
00200                 passed_++;
00201                 break;
00202             case UNIT_TEST_FAILED:
00203                 if (in_tcl_) {
00204                     fprintf(stderr, "{ %d %s F } ", 
00205                             test_num, (*i)->name_.c_str());
00206                 } else {
00207                     printf("%s... Failed\n\n",  (*i)->name_.c_str());
00208                 }
00209                 failed_++;
00210                 break;
00211             case UNIT_TEST_INPUT:
00212                 if (in_tcl_) {
00213                     fprintf(stderr, "{ %d %s I } ", 
00214                             test_num, (*i)->name_.c_str());
00215                 } else {
00216                     printf("%s... Unknown (UNIT_TEST_INPUT)\n\n",
00217                            (*i)->name_.c_str());
00218                 }
00219                 input_++;
00220                 break;                
00221             }
00222         }
00223 
00224         if (in_tcl_) {
00225             print_tcl_tail();
00226         } else {
00227             print_results();
00228         }
00229 
00230         return 0;
00231     }
00232 
00233     void print_tcl_header() {
00234         fprintf(stderr, "set result { \"%s\" { ", name_.c_str());
00235     }
00236     void print_tcl_tail() {
00237         fprintf(stderr, "} { %zu %d %d %d } }\n", 
00238                 tests_.size(), passed_, failed_, input_);
00239     }
00240     void print_header() {
00241         printf("\n\nRunning Test: %s\n\n", name_.c_str());
00242     }
00243     
00244     void print_results() {
00245         printf("\n%s Complete:\n", name_.c_str());
00246         if (passed_ != 0) {
00247             printf("\t\t%u Passed\n", passed_);
00248         }
00249         if (failed_ != 0) {
00250             printf("\t\t%u Failed\n", failed_);
00251         }
00252     }
00253 
00254 protected:
00258     virtual void add_tests() = 0;
00259 
00263     void add(UnitTest* unit) {
00264         tests_.push_back(unit);
00265     }
00266     
00267 private:
00268     std::string  name_;
00269     UnitTestList tests_;
00270 
00271     int passed_;
00272     int failed_;
00273     int input_;
00274     const char* progname_;
00275     bool in_tcl_;
00276 };
00277 
00279 #define ADD_TEST(_name)                         \
00280         add(new _name ## UnitTest())
00281 
00282 #define DECLARE_TEST(_name)                             \
00283     struct _name ## UnitTest : public oasys::UnitTest { \
00284         _name ## UnitTest() : UnitTest(#_name) {}       \
00285         int run();                                      \
00286     };                                                  \
00287     int _name ## UnitTest::run()
00288 
00289 #define RUN_TESTER(_UnitTesterClass, testname, argc, argv)      \
00290     _UnitTesterClass test(testname);                            \
00291     test.init(argc, argv, true);                                \
00292     int _ret = test.run_tests();                                \
00293     return _ret;
00294 
00295 #define RUN_TESTER_NO_LOG(_UnitTesterClass, testname, argc, argv) \
00296     _UnitTesterClass test(testname);                              \
00297     test.init(argc, argv, false);                                 \
00298     int _ret = test.run_tests();                                  \
00299     return _ret;
00300 
00301 #define DECLARE_TEST_FILE(_UnitTesterClass, testname)           \
00302 int main(int argc, const char* argv[]) {                        \
00303     RUN_TESTER(_UnitTesterClass, testname, argc, argv);         \
00304 }
00305 
00306 #define DECLARE_TESTER(_name)                                   \
00307 class _name : public oasys::UnitTester {                        \
00308 public:                                                         \
00309     _name(std::string name) : UnitTester(name) {}               \
00310 protected:                                                      \
00311     void add_tests();                                           \
00312 };                                                              \
00313 void _name::add_tests()                                         \
00314 
00315 #define DO(x)                                                           \
00316     do {                                                                \
00317         log_notice_p("/test",                                           \
00318                     "DO (%s) at %s:%d", #x, __FILE__, __LINE__);        \
00319         x;                                                              \
00320     } while (0)
00321 
00322 #define CHECK(x)                                                        \
00323     do { if (! (x)) {                                                   \
00324         errno_ = errno;                                                 \
00325         strerror_ = strerror(errno_);                                   \
00326         ::oasys::Breaker::break_here();                                 \
00327         log_err_p("/test",                                              \
00328                     "CHECK FAILED (%s) at %s:%d",                       \
00329                     #x, __FILE__, __LINE__);                            \
00330         return oasys::UNIT_TEST_FAILED;                                 \
00331     } else {                                                            \
00332         log_notice_p("/test",                                           \
00333                     "CHECK (%s) ok at %s:%d", #x, __FILE__, __LINE__);  \
00334     } } while(0)
00335 
00336 #define CHECK_SYS(x)                                                    \
00337     do { if (! (x)) {                                                   \
00338         errno_ = errno;                                                 \
00339         strerror_ = strerror(errno_);                                   \
00340         ::oasys::Breaker::break_here();                                 \
00341         log_err_p("/test",                                              \
00342                     "CHECK FAILED (%s) at %s:%d, errno=%s",             \
00343                     #x, __FILE__, __LINE__, strerror_);                 \
00344         return oasys::UNIT_TEST_FAILED;                                 \
00345     } else {                                                            \
00346         log_notice_p("/test",                                           \
00347                     "CHECK (%s) ok at %s:%d", #x, __FILE__, __LINE__);  \
00348     } } while(0)
00349 
00350 #define CHECK_EQUAL(_a, _b)                                                     \
00351     do { int a = _a; int b = _b; if ((a) != (b)) {                              \
00352         errno_ = errno;                                                         \
00353         strerror_ = strerror(errno_);                                           \
00354         ::oasys::Breaker::break_here();                                         \
00355         log_err_p("/test",                                                      \
00356                     "CHECK FAILED: '" #_a "' (%d) != '" #_b "' (%d) at %s:%d",  \
00357                     (a), (b), __FILE__, __LINE__);                              \
00358         return oasys::UNIT_TEST_FAILED;                                         \
00359     } else {                                                                    \
00360         log_notice_p("/test",                                                   \
00361                     "CHECK '" #_a "' (%d) == '" #_b "' (%d) "                   \
00362                     "at %s:%d", (a), (b), __FILE__, __LINE__);                  \
00363     } } while(0)
00364 
00365 #define CHECK_LT(_a, _b)                                                        \
00366     do { int a = _a; int b = _b; if (! (((a) < (b))) {                          \
00367         errno_ = errno;                                                         \
00368         strerror_ = strerror(errno_);                                           \
00369         ::oasys::Breaker::break_here();                                         \
00370         log_err_p("/test",                                                      \
00371                     "CHECK FAILED: '" #_a "' (%d) < '" #_b "' (%d) at %s:%d",   \
00372                     (a), (b), __FILE__, __LINE__);                              \
00373         return oasys::UNIT_TEST_FAILED;                                         \
00374     } else {                                                                    \
00375         log_notice_p("/test",                                                   \
00376                     "CHECK '" #_a "' (%d) < '" #_b "' (%d) "                    \
00377                     "at %s:%d", (a), (b), __FILE__, __LINE__);                  \
00378     } } while(0)
00379 
00380 #define CHECK_GT(_a, _b)                                                        \
00381     do { int a = _a; int b = _b; if (! ((a) > (b))) {                           \
00382         errno_ = errno;                                                         \
00383         strerror_ = strerror(errno_);                                           \
00384         ::oasys::Breaker::break_here();                                         \
00385         log_err_p("/test",                                                      \
00386                     "CHECK FAILED: '" #_a "' (%d) > '" #_b "' (%d) at %s:%d",  \
00387                     (a), (b), __FILE__, __LINE__);                              \
00388         return oasys::UNIT_TEST_FAILED;                                         \
00389     } else {                                                                    \
00390         log_notice_p("/test",                                                   \
00391                     "CHECK '" #_a "' (%d) > '" #_b "' (%d) "                    \
00392                     "at %s:%d", (a), (b), __FILE__, __LINE__);                  \
00393     } } while(0)
00394 
00395 #define CHECK_LTU(_a, _b)                                                       \
00396     do { u_int a = _a; u_int b = _b; if (! ((a) <= (b))) {                      \
00397         errno_ = errno;                                                         \
00398         strerror_ = strerror(errno_);                                           \
00399         ::oasys::Breaker::break_here();                                         \
00400         log_err_p("/test",                                                      \
00401                     "CHECK FAILED: '" #_a "' (%u) <= '" #_b "' (%u) at %s:%u",  \
00402                     (a), (b), __FILE__, __LINE__);                              \
00403         return oasys::UNIT_TEST_FAILED;                                         \
00404     } else {                                                                    \
00405         log_notice_p("/test",                                                   \
00406                     "CHECK '" #_a "' (%u) <= '" #_b "' (%u) "                   \
00407                     "at %s:%d", (a), (b), __FILE__, __LINE__);                  \
00408     } } while(0)
00409 
00410 #define CHECK_GTU(_a, _b)                                                       \
00411     do { u_int a = _a; u_int b = _b; if (! ((a) >= (b))) {                      \
00412         errno_ = errno;                                                         \
00413         strerror_ = strerror(errno_);                                           \
00414         ::oasys::Breaker::break_here();                                         \
00415         log_err_p("/test",                                                      \
00416                     "CHECK FAILED: '" #_a "' (%u) >= '" #_b "' (%u) at %s:%u",  \
00417                     (a), (b), __FILE__, __LINE__);                              \
00418         return oasys::UNIT_TEST_FAILED;                                         \
00419     } else {                                                                    \
00420         log_notice_p("/test",                                                   \
00421                     "CHECK '" #_a "' (%u) >= '" #_b "' (%u) "                   \
00422                     "at %s:%d", (a), (b), __FILE__, __LINE__);                  \
00423     } } while(0)
00424 
00425 #define CHECK_EQUAL_U64(a, b)                                                           \
00426     do { if ((a) != (b)) {                                                              \
00427         errno_ = errno;                                                                 \
00428         strerror_ = strerror(errno_);                                                   \
00429         ::oasys::Breaker::break_here();                                                 \
00430         log_err_p("/test",                                                              \
00431                     "CHECK FAILED: '" #a "' (%llu) != '" #b "' (%llu) at %s:%d",        \
00432                     (long long unsigned int)(a),                                        \
00433                     (long long unsigned int)(b),                                        \
00434                     __FILE__, __LINE__);                                                \
00435         return oasys::UNIT_TEST_FAILED;                                                 \
00436     } else {                                                                            \
00437         log_notice_p("/test",                                                           \
00438                     "CHECK '" #a "' (%llu) == '" #b "' (%llu) "                         \
00439                     "at %s:%d",                                                         \
00440                     (long long unsigned int)(a),                                        \
00441                     (long long unsigned int)(b),                                        \
00442                     __FILE__, __LINE__);                                                \
00443     } } while(0)
00444 
00445 #define CHECK_EQUALSTR(a, b)                                            \
00446     do { if (strcmp((a), (b)) != 0) {                                   \
00447         errno_ = errno;                                                 \
00448         strerror_ = strerror(errno_);                                   \
00449         ::oasys::Breaker::break_here();                                 \
00450         log_err_p("/test",                                              \
00451                     "CHECK FAILED: '" #a "' != '" #b "' at %s:%d.",     \
00452                     __FILE__, __LINE__);                                \
00453         log_err_p("/test", "Contents of " #a                            \
00454                     " (length %zu): ", strlen(a));                      \
00455         oasys::PrettyPrintBuf buf_a(a, strlen(a));                      \
00456         std::string s;                                                  \
00457         bool done;                                                      \
00458         do {                                                            \
00459             done = buf_a.next_str(&s);                                  \
00460             log_err_p("/test", s.c_str());                              \
00461         } while (!done);                                                \
00462                                                                         \
00463         log_err_p("/test", "Contents of " #b                            \
00464                     " (length %zu): ", strlen(b));                      \
00465         oasys::PrettyPrintBuf buf_b(b, strlen(b));                      \
00466                                                                         \
00467         do {                                                            \
00468             done = buf_b.next_str(&s);                                  \
00469             log_err_p("/test", s.c_str());                              \
00470         } while (!done);                                                \
00471                                                                         \
00472         return oasys::UNIT_TEST_FAILED;                                 \
00473     } else {                                                            \
00474         log_notice_p("/test",                                           \
00475                     "CHECK '" #a "' (%s) == '" #b "' (%s) "             \
00476                     "at %s:%d", (a), (b), __FILE__, __LINE__);          \
00477     } } while(0);
00478 
00479 #define CHECK_EQUALSTRN(a, b, len)                                              \
00480     do { u_int print_len = (len > 32) ? 32 : len;                               \
00481          if (strncmp((const char*)(a), (const char*)(b), (len)) != 0) {         \
00482              errno_ = errno;                                                    \
00483              strerror_ = strerror(errno_);                                      \
00484              ::oasys::Breaker::break_here();                                    \
00485              log_err_p("/test",  "CHECK FAILED: "                               \
00486                          "'" #a "' (%.*s...) != '" #b "' (%.*s...) at %s:%d",   \
00487                          print_len, (a), print_len, (b),                        \
00488                          __FILE__, __LINE__);                                   \
00489              return oasys::UNIT_TEST_FAILED;                                    \
00490          } else {                                                               \
00491              log_notice_p("/test",                                              \
00492                          "CHECK '" #a "' (%.*s...) == '" #b "' (%.*s...) "      \
00493                          "at %s:%d",                                            \
00494                          print_len, (a), print_len, (b), __FILE__, __LINE__);   \
00495         }                                                                       \
00496     } while(0)
00497  
00499 
00500 }; // namespace oasys
00501 
00502 #endif //__UNIT_TEST_H__

Generated on Thu Jun 7 16:56:53 2007 for DTN Reference Implementation by  doxygen 1.5.1