testharness.h raw

   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_
 142