GTest源码剖析——断言
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宏 的区别
EXPECT_TRUE宏和ASSERT_FALSE宏 几乎认为无区别,仅仅是参数取反而已;
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_宏
- GTEST_MESSAGE_宏定义如下:
#define GTEST_MESSAGE_(message, result_type)
GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
- 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<T, AssertionResult>::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;
}