GTest源码剖析(七)——断言

GTest源码剖析——断言

  • GTest源码剖析断言
    • ASSERT_TRUE宏
      • 1 ASSERT_TRUE宏 和 EXPECT_TRUE宏 的区别
      • 11 GTEST_MESSAGE_宏
        • 12 AssertHelper类
      • 2 ASSERT_TRUE宏的实现
        • 21 AssertionResult类

1 ASSERT_TRUE宏

ASSERT_TRUE宏和ASSERT_FALSE宏几乎认为无区别,仅仅是参数取反而已。

ASSERT_*宏定义如下:


#define ASSERT_TRUE(condition) 
  GTEST_TEST_BOOLEAN_((condition), #condition, false, true, GTEST_FATAL_FAILURE_)

#define ASSERT_FALSE(condition) 
  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, GTEST_FATAL_FAILURE_)

1.1 ASSERT_TRUE宏 和 EXPECT_TRUE宏 的区别

  1. EXPECT_TRUE宏和ASSERT_FALSE宏 几乎认为无区别,仅仅是参数取反而已;

  2. EXPECT_TRUE宏和ASSERT_FALSE宏 均使用GTEST_TEST_BOOLEAN_宏;
    两者的区别仅仅是第五个参数不同
    EXPECT_TRUE的参数是GTEST_NONFATAL_FAILURE_,而ASSERT_TRUE的参数是GTEST_FATAL_FAILURE_

EXPECT_*宏定义如下:


#define EXPECT_TRUE(condition) 
  GTEST_TEST_BOOLEAN_((condition), #condition, false, true,GTEST_NONFATAL_FAILURE_)

#define EXPECT_FALSE(condition) 
  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, GTEST_NONFATAL_FAILURE_)

3.对比一下 GTEST_FATAL_FAILURE_宏 和 GTEST_NONFATAL_FAILURE_宏 的区别可以发现,两者均使用GTEST_MESSAGE_宏,
区别在于使用了不同的TestPartResult的枚举值。

宏定义如下:


#define GTEST_FATAL_FAILURE_(message) 
  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)

#define GTEST_NONFATAL_FAILURE_(message) 
  GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)

TestPartResult类定义如下,仅仅是定义了三个枚举值而已。


class GTEST_API_ TestPartResult 
{
public:
  enum Type 
  {
    kSuccess,          // Succeeded.
    kNonFatalFailure,  // Failed but the test can continue.
    kFatalFailure      // Failed and the test should be terminated.
  };

1.1.1 GTEST_MESSAGE_宏

  1. GTEST_MESSAGE_宏定义如下:

#define GTEST_MESSAGE_(message, result_type) 
  GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
  1. GTEST_MESSAGE_AT_宏定义如下:

#define GTEST_MESSAGE_AT_(file, line, message, result_type) 
  ::testing::internal::AssertHelper(result_type, file, line, message) 
    = ::testing::Message()

1.1.2 AssertHelper类

重载了void operator=(const Message& message) const;利用它把断言的结果信息添加到TestResult中。


class GTEST_API_ AssertHelper 
{
public:
  AssertHelper(TestPartResult::Type type, const char* file, int line, const char* message);
  ~AssertHelper();

  void operator=(const Message& message) const;

private:
  struct AssertHelperData 
  {
    AssertHelperData(TestPartResult::Type t,
                     const char* srcfile,
                     int line_num,
                     const char* msg)
        : type(t), file(srcfile), line(line_num), message(msg) { }

    TestPartResult::Type const type;
    const char* const file;
    int const line;
    std::string const message;

   private:
    GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
  };

  AssertHelperData* const data_;

  GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
};


// AssertHelper constructor.
AssertHelper::AssertHelper(TestPartResult::Type type,
                           const char* file,
                           int line,
                           const char* message)
    : data_(new AssertHelperData(type, file, line, message)) 
{
}

AssertHelper::~AssertHelper() 
{
  delete data_;
}

// Message assignment, for assertion streaming support.
void AssertHelper::operator=(const Message& message) const 
{
  UnitTest::GetInstance()->
    AddTestPartResult(data_->type, data_->file, data_->line,
                      AppendUserMessage(data_->message, message),
                      UnitTest::GetInstance()->impl()
                      ->CurrentOsStackTraceExceptTop(1)
                      // Skips the stack frame for this function itself.
                      );  // NOLINT
}

UnitTest::AddTestPartResult

void UnitTest::AddTestPartResult(
    TestPartResult::Type result_type,
    const char* file_name,
    int line_number,
    const std::string& message,
    const std::string& os_stack_trace) 
{
  Message msg;
  msg << message;

  internal::MutexLock lock(&mutex_);
  if (impl_->gtest_trace_stack().size() > 0) 
  {
    msg << "\n" << GTEST_NAME_ << " trace:";

    for (int i = static_cast<int>(impl_->gtest_trace_stack().size()); i > 0; --i) 
    {
      const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
      msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
          << " " << trace.message;
    }
  }
}

1.2 ASSERT_TRUE宏的实现


#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) 

  GTEST_AMBIGUOUS_ELSE_BLOCKER_ 
  if (const ::testing::AssertionResult gtest_ar_ = 
      ::testing::AssertionResult(expression)) 
    ; 
  else 
    fail(::testing::internal::GetBoolAssertionFailureMessage(
        gtest_ar_, text, #actual, #expected).c_str())

1.2.1 AssertionResult类

class GTEST_API_ AssertionResult 
{
public:
  AssertionResult(const AssertionResult& other);

  GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)

  template <typename T>
  explicit AssertionResult(
      const T& success,
      typename internal::EnableIf<
          !internal::ImplicitlyConvertible::value>::type*
          /*enabler*/ = NULL)
      : success_(success) {}

  GTEST_DISABLE_MSC_WARNINGS_POP_()

  // Assignment operator.
  AssertionResult& operator=(AssertionResult other) 
  {
    swap(other);
    return *this;
  }

  operator bool() const { return success_; } 

  AssertionResult operator!() const;

  const char* message() const 
  {
    return message_.get() != NULL ?  message_->c_str() : "";
  }

  template <typename T> AssertionResult& operator<<(const T& value) 
  {
    AppendMessage(Message() << value);
    return *this;
  }

  AssertionResult& operator<<(std::ostream& (*basic_manipulator)(::std::ostream& stream)) 
  {
    AppendMessage(Message() << basic_manipulator);
    return *this;
  }

private:
  void AppendMessage(const Message& a_message) 
  {
    if (message_.get() == NULL)
      message_.reset(new ::std::string);
    message_->append(a_message.GetString().c_str());
  }

  void swap(AssertionResult& other);

  internal::scoped_ptr< ::std::string> message_;
};

AssertionResult::AssertionResult(const AssertionResult& other)
    : success_(other.success_),
      message_(other.message_.get() != NULL ?
               new ::std::string(*other.message_) :
               static_cast< ::std::string*>(NULL)) 
{
}

void AssertionResult::swap(AssertionResult& other) 
{
  using std::swap;
  swap(success_, other.success_);
  swap(message_, other.message_);
}

AssertionResult AssertionResult::operator!() const 
{
  AssertionResult negation(!success_);
  if (message_.get() != NULL)
    negation << *message_;

  return negation;
}

你可能感兴趣的:(GTest)