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:
Tester(const char * f,int l)50   Tester(const char* f, int l) : ok_(true), fname_(f), line_(l) {}
51 
~Tester()52   ~Tester() {
53     if (!ok_) {
54       fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str());
55       exit(1);
56     }
57   }
58 
Is(bool b,const char * msg)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 
IsOk(const Status & s)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