| // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. See the AUTHORS file for names of contributors. |
| |
| #ifndef STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ |
| #define STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <sstream> |
| #include "leveldb/env.h" |
| #include "leveldb/slice.h" |
| #include "util/random.h" |
| |
| namespace leveldb { |
| namespace test { |
| |
| // Run some of the tests registered by the TEST() macro. If the |
| // environment variable "LEVELDB_TESTS" is not set, runs all tests. |
| // Otherwise, runs only the tests whose name contains the value of |
| // "LEVELDB_TESTS" as a substring. E.g., suppose the tests are: |
| // TEST(Foo, Hello) { ... } |
| // TEST(Foo, World) { ... } |
| // LEVELDB_TESTS=Hello will run the first test |
| // LEVELDB_TESTS=o will run both tests |
| // LEVELDB_TESTS=Junk will run no tests |
| // |
| // Returns 0 if all tests pass. |
| // Dies or returns a non-zero value if some test fails. |
| extern int RunAllTests(); |
| |
| // Return the directory to use for temporary storage. |
| extern std::string TmpDir(); |
| |
| // Return a randomization seed for this run. Typically returns the |
| // same number on repeated invocations of this binary, but automated |
| // runs may be able to vary the seed. |
| extern int RandomSeed(); |
| |
| // An instance of Tester is allocated to hold temporary state during |
| // the execution of an assertion. |
| class Tester { |
| private: |
| bool ok_; |
| const char* fname_; |
| int line_; |
| std::stringstream ss_; |
| |
| public: |
| Tester(const char* f, int l) |
| : ok_(true), fname_(f), line_(l) { |
| } |
| |
| ~Tester() { |
| if (!ok_) { |
| fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str()); |
| exit(1); |
| } |
| } |
| |
| Tester& Is(bool b, const char* msg) { |
| if (!b) { |
| ss_ << " Assertion failure " << msg; |
| ok_ = false; |
| } |
| return *this; |
| } |
| |
| Tester& IsOk(const Status& s) { |
| if (!s.ok()) { |
| ss_ << " " << s.ToString(); |
| ok_ = false; |
| } |
| return *this; |
| } |
| |
| #define BINARY_OP(name,op) \ |
| template <class X, class Y> \ |
| Tester& name(const X& x, const Y& y) { \ |
| if (! (x op y)) { \ |
| ss_ << " failed: " << x << (" " #op " ") << y; \ |
| ok_ = false; \ |
| } \ |
| return *this; \ |
| } |
| |
| BINARY_OP(IsEq, ==) |
| BINARY_OP(IsNe, !=) |
| BINARY_OP(IsGe, >=) |
| BINARY_OP(IsGt, >) |
| BINARY_OP(IsLe, <=) |
| BINARY_OP(IsLt, <) |
| #undef BINARY_OP |
| |
| // Attach the specified value to the error message if an error has occurred |
| template <class V> |
| Tester& operator<<(const V& value) { |
| if (!ok_) { |
| ss_ << " " << value; |
| } |
| return *this; |
| } |
| }; |
| |
| #define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c) |
| #define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s)) |
| #define ASSERT_EQ(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a),(b)) |
| #define ASSERT_NE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a),(b)) |
| #define ASSERT_GE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a),(b)) |
| #define ASSERT_GT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a),(b)) |
| #define ASSERT_LE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a),(b)) |
| #define ASSERT_LT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a),(b)) |
| |
| #define TCONCAT(a,b) TCONCAT1(a,b) |
| #define TCONCAT1(a,b) a##b |
| |
| #define TEST(base,name) \ |
| class TCONCAT(_Test_,name) : public base { \ |
| public: \ |
| void _Run(); \ |
| static void _RunIt() { \ |
| TCONCAT(_Test_,name) t; \ |
| t._Run(); \ |
| } \ |
| }; \ |
| bool TCONCAT(_Test_ignored_,name) = \ |
| ::leveldb::test::RegisterTest(#base, #name, &TCONCAT(_Test_,name)::_RunIt); \ |
| void TCONCAT(_Test_,name)::_Run() |
| |
| // Register the specified test. Typically not used directly, but |
| // invoked via the macro expansion of TEST. |
| extern bool RegisterTest(const char* base, const char* name, void (*func)()); |
| |
| |
| } // namespace test |
| } // namespace leveldb |
| |
| #endif // STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ |