| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ZIRCON_TOOLS_KAZOO_TEST_H_ |
| #define ZIRCON_TOOLS_KAZOO_TEST_H_ |
| |
| #include <string.h> |
| |
| #include <sstream> |
| #include <string> |
| |
| // This is a minimal googletest-like testing framework. It's originally derived |
| // from Ninja's src/test.h. You might prefer that one if you have different |
| // tradeoffs (in particular, if you don't need to stream message to assertion |
| // failures, Ninja's is a bit simpler.) |
| namespace testing { |
| |
| class Test { |
| public: |
| Test() : failed_(false) {} |
| virtual ~Test() {} |
| virtual void SetUp() {} |
| virtual void TearDown() {} |
| virtual void Run() = 0; |
| |
| bool Failed() const { return failed_; } |
| |
| private: |
| friend class TestResult; |
| |
| bool failed_; |
| }; |
| |
| extern testing::Test* g_current_test; |
| |
| class TestResult { |
| public: |
| TestResult(bool condition, const char* error) : condition_(condition), error_(error) { |
| if (!condition) |
| g_current_test->failed_ = true; |
| } |
| |
| // For _EQ so we can print both sides. |
| template <class T, class U> |
| TestResult(bool condition, const char* error, const T& left, const U& right) |
| : TestResult(condition, error) { |
| std::stringstream lss; |
| lss << left; |
| left_ = lss.str(); |
| |
| std::stringstream rss; |
| rss << right; |
| right_ = rss.str(); |
| } |
| |
| operator bool() const { return condition_; } |
| const char* error() const { return error_; } |
| const std::string& left() const { return left_; } |
| const std::string& right() const { return right_; } |
| |
| private: |
| bool condition_; |
| const char* error_; |
| std::string left_; |
| std::string right_; |
| }; |
| |
| class Message { |
| public: |
| Message() {} |
| ~Message() { printf("%s\n\n", ss_.str().c_str()); } |
| |
| template <typename T> |
| inline Message& operator<<(const T& val) { |
| ss_ << val; |
| return *this; |
| } |
| |
| private: |
| std::stringstream ss_; |
| }; |
| |
| class AssertHelper { |
| public: |
| AssertHelper(const char* file, int line, const TestResult& test_result) |
| : file_(file), |
| line_(line), |
| error_(test_result.error()), |
| left_(test_result.left()), |
| right_(test_result.right()) {} |
| |
| void operator=(const Message& message) const { |
| printf("\n*** FAILURE %s:%d: %s\n", file_, line_, error_); |
| if (!left_.empty() || !right_.empty()) { |
| printf("LHS:\n-----\n%s\n-----\nRHS:\n-----\n%s\n-----\n", left_.c_str(), right_.c_str()); |
| } |
| } |
| |
| private: |
| const char* file_; |
| int line_; |
| const char* error_; |
| std::string left_; |
| std::string right_; |
| }; |
| |
| } // namespace testing |
| |
| void RegisterTest(testing::Test* (*)(), const char*); |
| |
| #define TEST_F_(x, y, name) \ |
| struct y : public x { \ |
| static testing::Test* Create() { return testing::g_current_test = new y; } \ |
| virtual void Run(); \ |
| }; \ |
| struct Register##y { \ |
| Register##y() { RegisterTest(y::Create, name); } \ |
| }; \ |
| Register##y g_register_##y; \ |
| void y::Run() |
| |
| #define TEST_F(x, y) TEST_F_(x, x##y, #x "." #y) |
| #define TEST(x, y) TEST_F_(testing::Test, x##y, #x "." #y) |
| |
| #define FRIEND_TEST(x, y) friend class x##y |
| |
| // Some compilers emit a warning if nested "if" statements are followed by an |
| // "else" statement and braces are not used to explicitly disambiguate the |
| // "else" binding. This leads to problems with code like: |
| // |
| // if (something) |
| // ASSERT_TRUE(condition) << "Some message"; |
| #define TEST_AMBIGUOUS_ELSE_BLOCKER_ \ |
| switch (0) \ |
| case 0: \ |
| default: |
| |
| #define TEST_ASSERT_(expression, on_failure) \ |
| TEST_AMBIGUOUS_ELSE_BLOCKER_ \ |
| if (const ::testing::TestResult test_result = (expression)) \ |
| ; \ |
| else \ |
| on_failure(test_result) |
| |
| #define TEST_NONFATAL_FAILURE_(message) \ |
| ::testing::AssertHelper(__FILE__, __LINE__, message) = ::testing::Message() |
| |
| #define TEST_FATAL_FAILURE_(message) \ |
| return ::testing::AssertHelper(__FILE__, __LINE__, message) = ::testing::Message() |
| |
| #define EXPECT_EQ(a, b) \ |
| do { \ |
| const auto& _a = (a); \ |
| const auto& _b = (b); \ |
| TEST_ASSERT_(::testing::TestResult(_a == _b, #a " == " #b, _a, _b), TEST_NONFATAL_FAILURE_); \ |
| } while (false) |
| |
| #define EXPECT_NE(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(a != b, #a " != " #b), TEST_NONFATAL_FAILURE_) |
| |
| #define EXPECT_LT(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(a < b, #a " < " #b), TEST_NONFATAL_FAILURE_) |
| |
| #define EXPECT_GT(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(a > b, #a " > " #b), TEST_NONFATAL_FAILURE_) |
| |
| #define EXPECT_LE(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(a <= b, #a " <= " #b), TEST_NONFATAL_FAILURE_) |
| |
| #define EXPECT_GE(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(a >= b, #a " >= " #b), TEST_NONFATAL_FAILURE_) |
| |
| #define EXPECT_TRUE(a) \ |
| TEST_ASSERT_(::testing::TestResult(static_cast<bool>(a), #a), TEST_NONFATAL_FAILURE_) |
| |
| #define EXPECT_FALSE(a) \ |
| TEST_ASSERT_(::testing::TestResult(!static_cast<bool>(a), #a), TEST_NONFATAL_FAILURE_) |
| |
| #define EXPECT_STREQ(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(strcmp(a, b) == 0, #a " str== " #b), TEST_NONFATAL_FAILURE_) |
| |
| #define ASSERT_EQ(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(a == b, #a " == " #b), TEST_FATAL_FAILURE_) |
| |
| #define ASSERT_NE(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(a != b, #a " != " #b), TEST_FATAL_FAILURE_) |
| |
| #define ASSERT_LT(a, b) TEST_ASSERT_(::testing::TestResult(a < b, #a " < " #b), TEST_FATAL_FAILURE_) |
| |
| #define ASSERT_GT(a, b) TEST_ASSERT_(::testing::TestResult(a > b, #a " > " #b), TEST_FATAL_FAILURE_) |
| |
| #define ASSERT_LE(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(a <= b, #a " <= " #b), TEST_FATAL_FAILURE_) |
| |
| #define ASSERT_GE(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(a >= b, #a " >= " #b), TEST_FATAL_FAILURE_) |
| |
| #define ASSERT_TRUE(a) \ |
| TEST_ASSERT_(::testing::TestResult(static_cast<bool>(a), #a), TEST_FATAL_FAILURE_) |
| |
| #define ASSERT_FALSE(a) \ |
| TEST_ASSERT_(::testing::TestResult(!static_cast<bool>(a), #a), TEST_FATAL_FAILURE_) |
| |
| #define ASSERT_STREQ(a, b) \ |
| TEST_ASSERT_(::testing::TestResult(strcmp(a, b) == 0, #a " str== " #b), TEST_FATAL_FAILURE_) |
| |
| #endif // ZIRCON_TOOLS_KAZOO_TEST_H_ |