Home | History | Annotate | Download | only in util
      1 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file. See the AUTHORS file for names of contributors.
      4 
      5 #ifndef STORAGE_LEVELDB_UTIL_TESTHARNESS_H_
      6 #define STORAGE_LEVELDB_UTIL_TESTHARNESS_H_
      7 
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <sstream>
     11 #include "leveldb/env.h"
     12 #include "leveldb/slice.h"
     13 #include "util/random.h"
     14 
     15 namespace leveldb {
     16 namespace test {
     17 
     18 // Run some of the tests registered by the TEST() macro.  If the
     19 // environment variable "LEVELDB_TESTS" is not set, runs all tests.
     20 // Otherwise, runs only the tests whose name contains the value of
     21 // "LEVELDB_TESTS" as a substring.  E.g., suppose the tests are:
     22 //    TEST(Foo, Hello) { ... }
     23 //    TEST(Foo, World) { ... }
     24 // LEVELDB_TESTS=Hello will run the first test
     25 // LEVELDB_TESTS=o     will run both tests
     26 // LEVELDB_TESTS=Junk  will run no tests
     27 //
     28 // Returns 0 if all tests pass.
     29 // Dies or returns a non-zero value if some test fails.
     30 extern int RunAllTests();
     31 
     32 // Return the directory to use for temporary storage.
     33 extern std::string TmpDir();
     34 
     35 // Return a randomization seed for this run.  Typically returns the
     36 // same number on repeated invocations of this binary, but automated
     37 // runs may be able to vary the seed.
     38 extern int RandomSeed();
     39 
     40 // An instance of Tester is allocated to hold temporary state during
     41 // the execution of an assertion.
     42 class Tester {
     43  private:
     44   bool ok_;
     45   const char* fname_;
     46   int line_;
     47   std::stringstream ss_;
     48 
     49  public:
     50   Tester(const char* f, int l)
     51       : ok_(true), fname_(f), line_(l) {
     52   }
     53 
     54   ~Tester() {
     55     if (!ok_) {
     56       fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str());
     57       exit(1);
     58     }
     59   }
     60 
     61   Tester& Is(bool b, const char* msg) {
     62     if (!b) {
     63       ss_ << " Assertion failure " << msg;
     64       ok_ = false;
     65     }
     66     return *this;
     67   }
     68 
     69   Tester& IsOk(const Status& s) {
     70     if (!s.ok()) {
     71       ss_ << " " << s.ToString();
     72       ok_ = false;
     73     }
     74     return *this;
     75   }
     76 
     77 #define BINARY_OP(name,op)                              \
     78   template <class X, class Y>                           \
     79   Tester& name(const X& x, const Y& y) {                \
     80     if (! (x op y)) {                                   \
     81       ss_ << " failed: " << x << (" " #op " ") << y;    \
     82       ok_ = false;                                      \
     83     }                                                   \
     84     return *this;                                       \
     85   }
     86 
     87   BINARY_OP(IsEq, ==)
     88   BINARY_OP(IsNe, !=)
     89   BINARY_OP(IsGe, >=)
     90   BINARY_OP(IsGt, >)
     91   BINARY_OP(IsLe, <=)
     92   BINARY_OP(IsLt, <)
     93 #undef BINARY_OP
     94 
     95   // Attach the specified value to the error message if an error has occurred
     96   template <class V>
     97   Tester& operator<<(const V& value) {
     98     if (!ok_) {
     99       ss_ << " " << value;
    100     }
    101     return *this;
    102   }
    103 };
    104 
    105 #define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c)
    106 #define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s))
    107 #define ASSERT_EQ(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a),(b))
    108 #define ASSERT_NE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a),(b))
    109 #define ASSERT_GE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a),(b))
    110 #define ASSERT_GT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a),(b))
    111 #define ASSERT_LE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a),(b))
    112 #define ASSERT_LT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a),(b))
    113 
    114 #define TCONCAT(a,b) TCONCAT1(a,b)
    115 #define TCONCAT1(a,b) a##b
    116 
    117 #define TEST(base,name)                                                 \
    118 class TCONCAT(_Test_,name) : public base {                              \
    119  public:                                                                \
    120   void _Run();                                                          \
    121   static void _RunIt() {                                                \
    122     TCONCAT(_Test_,name) t;                                             \
    123     t._Run();                                                           \
    124   }                                                                     \
    125 };                                                                      \
    126 bool TCONCAT(_Test_ignored_,name) =                                     \
    127   ::leveldb::test::RegisterTest(#base, #name, &TCONCAT(_Test_,name)::_RunIt); \
    128 void TCONCAT(_Test_,name)::_Run()
    129 
    130 // Register the specified test.  Typically not used directly, but
    131 // invoked via the macro expansion of TEST.
    132 extern bool RegisterTest(const char* base, const char* name, void (*func)());
    133 
    134 
    135 }  // namespace test
    136 }  // namespace leveldb
    137 
    138 #endif  // STORAGE_LEVELDB_UTIL_TESTHARNESS_H_
    139