/ src / leveldb / util / testharness.h
testharness.h
  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  
 11  #include <sstream>
 12  
 13  #include "leveldb/status.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  int RunAllTests();
 31  
 32  // Return the directory to use for temporary storage.
 33  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  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) : ok_(true), fname_(f), line_(l) {}
 51  
 52    ~Tester() {
 53      if (!ok_) {
 54        fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str());
 55        exit(1);
 56      }
 57    }
 58  
 59    Tester& Is(bool b, const char* msg) {
 60      if (!b) {
 61        ss_ << " Assertion failure " << msg;
 62        ok_ = false;
 63      }
 64      return *this;
 65    }
 66  
 67    Tester& IsOk(const Status& s) {
 68      if (!s.ok()) {
 69        ss_ << " " << s.ToString();
 70        ok_ = false;
 71      }
 72      return *this;
 73    }
 74  
 75  #define BINARY_OP(name, op)                          \
 76    template <class X, class Y>                        \
 77    Tester& name(const X& x, const Y& y) {             \
 78      if (!(x op y)) {                                 \
 79        ss_ << " failed: " << x << (" " #op " ") << y; \
 80        ok_ = false;                                   \
 81      }                                                \
 82      return *this;                                    \
 83    }
 84  
 85    BINARY_OP(IsEq, ==)
 86    BINARY_OP(IsNe, !=)
 87    BINARY_OP(IsGe, >=)
 88    BINARY_OP(IsGt, >)
 89    BINARY_OP(IsLe, <=)
 90    BINARY_OP(IsLt, <)
 91  #undef BINARY_OP
 92  
 93    // Attach the specified value to the error message if an error has occurred
 94    template <class V>
 95    Tester& operator<<(const V& value) {
 96      if (!ok_) {
 97        ss_ << " " << value;
 98      }
 99      return *this;
100    }
101  };
102  
103  #define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c)
104  #define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s))
105  #define ASSERT_EQ(a, b) \
106    ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a), (b))
107  #define ASSERT_NE(a, b) \
108    ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a), (b))
109  #define ASSERT_GE(a, b) \
110    ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a), (b))
111  #define ASSERT_GT(a, b) \
112    ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a), (b))
113  #define ASSERT_LE(a, b) \
114    ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a), (b))
115  #define ASSERT_LT(a, b) \
116    ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a), (b))
117  
118  #define TCONCAT(a, b) TCONCAT1(a, b)
119  #define TCONCAT1(a, b) a##b
120  
121  #define TEST(base, name)                                              \
122    class TCONCAT(_Test_, name) : public base {                         \
123     public:                                                            \
124      void _Run();                                                      \
125      static void _RunIt() {                                            \
126        TCONCAT(_Test_, name) t;                                        \
127        t._Run();                                                       \
128      }                                                                 \
129    };                                                                  \
130    bool TCONCAT(_Test_ignored_, name) = ::leveldb::test::RegisterTest( \
131        #base, #name, &TCONCAT(_Test_, name)::_RunIt);                  \
132    void TCONCAT(_Test_, name)::_Run()
133  
134  // Register the specified test.  Typically not used directly, but
135  // invoked via the macro expansion of TEST.
136  bool RegisterTest(const char* base, const char* name, void (*func)());
137  
138  }  // namespace test
139  }  // namespace leveldb
140  
141  #endif  // STORAGE_LEVELDB_UTIL_TESTHARNESS_H_