Implements support for AssertionResult in Boolean assertions such as EXPECT_TRUE; Fixes Google Tests's tuple implementation to default-initialize its fields in the default constructor (by Zhanyong Wan); Populates gtest_stress_test.cc with actual tests.

This commit is contained in:
vladlosev
2009-10-20 21:03:10 +00:00
parent 060804deb8
commit bad778caa3
10 changed files with 483 additions and 75 deletions

View File

@@ -177,63 +177,145 @@ String StreamableToString(const T& streamable) {
// A class for indicating whether an assertion was successful. When
// the assertion wasn't successful, the AssertionResult object
// remembers a non-empty message that described how it failed.
// remembers a non-empty message that describes how it failed.
//
// This class is useful for defining predicate-format functions to be
// used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
//
// The constructor of AssertionResult is private. To create an
// instance of this class, use one of the factory functions
// To create an instance of this class, use one of the factory functions
// (AssertionSuccess() and AssertionFailure()).
//
// For example, in order to be able to write:
// This class is useful for two purposes:
// 1. Defining predicate functions to be used with Boolean test assertions
// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
// 2. Defining predicate-format functions to be
// used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
//
// For example, if you define IsEven predicate:
//
// testing::AssertionResult IsEven(int n) {
// if ((n % 2) == 0)
// return testing::AssertionSuccess();
// else
// return testing::AssertionFailure() << n << " is odd";
// }
//
// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
// will print the message
//
// Value of: IsEven(Fib(5))
// Actual: false (5 is odd)
// Expected: true
//
// instead of a more opaque
//
// Value of: IsEven(Fib(5))
// Actual: false
// Expected: true
//
// in case IsEven is a simple Boolean predicate.
//
// If you expect your predicate to be reused and want to support informative
// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
// about half as often as positive ones in our tests), supply messages for
// both success and failure cases:
//
// testing::AssertionResult IsEven(int n) {
// if ((n % 2) == 0)
// return testing::AssertionSuccess() << n << " is even";
// else
// return testing::AssertionFailure() << n << " is odd";
// }
//
// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
//
// Value of: IsEven(Fib(6))
// Actual: true (8 is even)
// Expected: false
//
// NB: Predicates that support negative Boolean assertions have reduced
// performance in positive ones so be careful not to use them in tests
// that have lots (tens of thousands) of positive Boolean assertions.
//
// To use this class with EXPECT_PRED_FORMAT assertions such as:
//
// // Verifies that Foo() returns an even number.
// EXPECT_PRED_FORMAT1(IsEven, Foo());
//
// you just need to define:
// you need to define:
//
// testing::AssertionResult IsEven(const char* expr, int n) {
// if ((n % 2) == 0) return testing::AssertionSuccess();
//
// Message msg;
// msg << "Expected: " << expr << " is even\n"
// << " Actual: it's " << n;
// return testing::AssertionFailure(msg);
// if ((n % 2) == 0)
// return testing::AssertionSuccess();
// else
// return testing::AssertionFailure()
// << "Expected: " << expr << " is even\n Actual: it's " << n;
// }
//
// If Foo() returns 5, you will see the following message:
//
// Expected: Foo() is even
// Actual: it's 5
//
class AssertionResult {
public:
// Declares factory functions for making successful and failed
// assertion results as friends.
friend AssertionResult AssertionSuccess();
friend AssertionResult AssertionFailure(const Message&);
// Copy constructor.
// Used in EXPECT_TRUE/FALSE(assertion_result).
AssertionResult(const AssertionResult& other);
// Used in the EXPECT_TRUE/FALSE(bool_expression).
explicit AssertionResult(bool success) : success_(success) {}
// Returns true iff the assertion succeeded.
operator bool() const { return failure_message_.c_str() == NULL; } // NOLINT
operator bool() const { return success_; } // NOLINT
// Returns the assertion's failure message.
const char* failure_message() const { return failure_message_.c_str(); }
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
AssertionResult operator!() const;
// Returns the text streamed into this AssertionResult. Test assertions
// use it when they fail (i.e., the predicate's outcome doesn't match the
// assertion's expectation). When nothing has been streamed into the
// object, returns an empty string.
const char* message() const {
return message_.get() != NULL && message_->c_str() != NULL ?
message_->c_str() : "";
}
// TODO(vladl@google.com): Remove this after making sure no clients use it.
// Deprecated; please use message() instead.
const char* failure_message() const { return message(); }
// Streams a custom failure message into this object.
template <typename T> AssertionResult& operator<<(const T& value);
private:
// The default constructor. It is used when the assertion succeeded.
AssertionResult() {}
// No implementation - we want AssertionResult to be
// copy-constructible but not assignable.
void operator=(const AssertionResult& other);
// The constructor used when the assertion failed.
explicit AssertionResult(const internal::String& failure_message);
// Stores result of the assertion predicate.
bool success_;
// Stores the message describing the condition in case the expectation
// construct is not satisfied with the predicate's outcome.
// Referenced via a pointer to avoid taking too much stack frame space
// with test assertions.
internal::scoped_ptr<internal::String> message_;
}; // class AssertionResult
// Stores the assertion's failure message.
internal::String failure_message_;
};
// Streams a custom failure message into this object.
template <typename T>
AssertionResult& AssertionResult::operator<<(const T& value) {
Message msg;
if (message_.get() != NULL)
msg << *message_;
msg << value;
message_.reset(new internal::String(msg.GetString()));
return *this;
}
// Makes a successful assertion result.
AssertionResult AssertionSuccess();
// Makes a failed assertion result.
AssertionResult AssertionFailure();
// Makes a failed assertion result with the given failure message.
// Deprecated; use AssertionFailure() << msg.
AssertionResult AssertionFailure(const Message& msg);
// The abstract class that all tests inherit from.
@@ -1603,7 +1685,9 @@ const T* TestWithParam<T>::parameter_ = NULL;
#define ASSERT_ANY_THROW(statement) \
GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
// Boolean assertions.
// Boolean assertions. Condition can be either a Boolean expression or an
// AssertionResult. For more information on how to use AssertionResult with
// these macros see comments on that class.
#define EXPECT_TRUE(condition) \
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
GTEST_NONFATAL_FAILURE_)

View File

@@ -299,6 +299,11 @@ AssertionResult EqFailure(const char* expected_expression,
const String& actual_value,
bool ignoring_case);
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
String GetBoolAssertionFailureMessage(const AssertionResult& assertion_result,
const char* expression_text,
const char* actual_predicate_value,
const char* expected_predicate_value);
// This template class represents an IEEE floating-point number
// (either single-precision or double-precision, depending on the
@@ -858,12 +863,17 @@ class Random {
fail(gtest_msg)
#define GTEST_TEST_BOOLEAN_(boolexpr, booltext, actual, expected, fail) \
// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
// either a boolean expression or an AssertionResult. text is a textual
// represenation of expression as it was passed into the EXPECT_TRUE.
#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::IsTrue(boolexpr)) \
if (const ::testing::AssertionResult gtest_ar_ = \
::testing::AssertionResult(expression)) \
; \
else \
fail("Value of: " booltext "\n Actual: " #actual "\nExpected: " #expected)
fail(::testing::internal::GetBoolAssertionFailureMessage(\
gtest_ar_, text, #actual, #expected).c_str())
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \

View File

@@ -183,7 +183,7 @@ class GTEST_1_TUPLE_(T) {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : f0_() {}
explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
@@ -215,7 +215,7 @@ class GTEST_2_TUPLE_(T) {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : f0_(), f1_() {}
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
f1_(f1) {}
@@ -258,7 +258,7 @@ class GTEST_3_TUPLE_(T) {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : f0_(), f1_(), f2_() {}
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
@@ -295,7 +295,7 @@ class GTEST_4_TUPLE_(T) {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : f0_(), f1_(), f2_(), f3_() {}
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
@@ -336,7 +336,7 @@ class GTEST_5_TUPLE_(T) {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
@@ -380,7 +380,7 @@ class GTEST_6_TUPLE_(T) {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
@@ -427,7 +427,7 @@ class GTEST_7_TUPLE_(T) {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
@@ -476,7 +476,7 @@ class GTEST_8_TUPLE_(T) {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
@@ -528,7 +528,7 @@ class GTEST_9_TUPLE_(T) {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
@@ -582,7 +582,8 @@ class tuple {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
f9_() {}
explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,

View File

@@ -39,11 +39,11 @@ $$ This meta comment fixes auto-indentation in Emacs. }}
#include <utility> // For ::std::pair.
// The compiler used in Symbian 5th Edition (__S60_50__) has a bug
// that prevents us from declaring the tuple template as a friend (it
// complains that tuple is redefined). This hack bypasses the bug by
// declaring the members that should otherwise be private as public.
#if defined(__SYMBIAN32__) && __S60_50__
// The compiler used in Symbian has a bug that prevents us from declaring the
// tuple template as a friend (it complains that tuple is redefined). This
// hack bypasses the bug by declaring the members that should otherwise be
// private as public.
#if defined(__SYMBIAN32__)
#define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
#else
#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
@@ -140,7 +140,7 @@ class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
public:
template <int k> friend class gtest_internal::Get;
tuple() {}
tuple() : $for m, [[f$(m)_()]] {}
explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
$for m, [[f$(m)_(f$m)]] {}