From bad778caa39a88b7c11b159e20730aeec4fd711e Mon Sep 17 00:00:00 2001 From: vladlosev Date: Tue, 20 Oct 2009 21:03:10 +0000 Subject: 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. --- Makefile.am | 4 +- include/gtest/gtest.h | 146 ++++++++++++++++++++++------- include/gtest/internal/gtest-internal.h | 16 +++- include/gtest/internal/gtest-tuple.h | 21 +++-- include/gtest/internal/gtest-tuple.h.pump | 12 +-- scons/SConscript | 1 + src/gtest.cc | 40 +++++++- test/gtest-tuple_test.cc | 42 ++++++++- test/gtest_stress_test.cc | 148 ++++++++++++++++++++++++++---- test/gtest_unittest.cc | 132 ++++++++++++++++++++++++++ 10 files changed, 485 insertions(+), 77 deletions(-) diff --git a/Makefile.am b/Makefile.am index 3a9233d..ec3e5ee 100644 --- a/Makefile.am +++ b/Makefile.am @@ -276,7 +276,9 @@ test_gtest_sole_header_test_LDADD = lib/libgtest_main.la TESTS += test/gtest_stress_test check_PROGRAMS += test/gtest_stress_test test_gtest_stress_test_SOURCES = test/gtest_stress_test.cc -test_gtest_stress_test_LDADD = lib/libgtest.la +test_gtest_stress_test_CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS) +test_gtest_stress_test_LDADD = $(PTHREAD_LIBS) $(PTHREAD_CFLAGS) \ + lib/libgtest.la TESTS += test/gtest-test-part_test check_PROGRAMS += test/gtest-test-part_test diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h index 9be15fb..33e2f7f 100644 --- a/include/gtest/gtest.h +++ b/include/gtest/gtest.h @@ -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 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(); } - // Returns the assertion's failure message. - const char* failure_message() const { return failure_message_.c_str(); } + // Streams a custom failure message into this object. + template AssertionResult& operator<<(const T& value); private: - // The default constructor. It is used when the assertion succeeded. - AssertionResult() {} - - // The constructor used when the assertion failed. - explicit AssertionResult(const internal::String& failure_message); - - // Stores the assertion's failure message. - internal::String failure_message_; -}; + // No implementation - we want AssertionResult to be + // copy-constructible but not assignable. + void operator=(const AssertionResult& other); + + // 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 message_; +}; // class AssertionResult + +// Streams a custom failure message into this object. +template +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::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_) diff --git a/include/gtest/internal/gtest-internal.h b/include/gtest/internal/gtest-internal.h index 7033b0c..08cf67d 100644 --- a/include/gtest/internal/gtest-internal.h +++ b/include/gtest/internal/gtest-internal.h @@ -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_ \ diff --git a/include/gtest/internal/gtest-tuple.h b/include/gtest/internal/gtest-tuple.h index 86b200b..c201f5c 100644 --- a/include/gtest/internal/gtest-tuple.h +++ b/include/gtest/internal/gtest-tuple.h @@ -183,7 +183,7 @@ class GTEST_1_TUPLE_(T) { public: template 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 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 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 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 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 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 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 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 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 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, diff --git a/include/gtest/internal/gtest-tuple.h.pump b/include/gtest/internal/gtest-tuple.h.pump index 12821d8..9e42423 100644 --- a/include/gtest/internal/gtest-tuple.h.pump +++ b/include/gtest/internal/gtest-tuple.h.pump @@ -39,11 +39,11 @@ $$ This meta comment fixes auto-indentation in Emacs. }} #include // 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 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)]] {} diff --git a/scons/SConscript b/scons/SConscript index 60745f2..e1ccb7e 100644 --- a/scons/SConscript +++ b/scons/SConscript @@ -279,6 +279,7 @@ if BUILD_TESTS: GtestTest(env_with_exceptions, 'gtest_output_test_', gtest_ex) GtestTest(env_with_exceptions, 'gtest_throw_on_failure_ex_test', gtest_ex) GtestTest(env_with_threads, 'gtest-death-test_test', gtest_main) + GtestTest(env_with_threads, 'gtest_stress_test', gtest) GtestTest(env_less_optimized, 'gtest_env_var_test_', gtest) GtestTest(env_less_optimized, 'gtest_uninitialized_test_', gtest) GtestTest(env_use_own_tuple, 'gtest-tuple_test', gtest_use_own_tuple_main) diff --git a/src/gtest.cc b/src/gtest.cc index 55f03ce..5efb5ba 100644 --- a/src/gtest.cc +++ b/src/gtest.cc @@ -952,21 +952,37 @@ String FormatForFailureMessage(wchar_t wchar) { } // namespace internal -// AssertionResult constructor. -AssertionResult::AssertionResult(const internal::String& failure_message) - : failure_message_(failure_message) { +// AssertionResult constructors. +// Used in EXPECT_TRUE/FALSE(assertion_result). +AssertionResult::AssertionResult(const AssertionResult& other) + : success_(other.success_), + message_(other.message_.get() != NULL ? + new internal::String(*other.message_) : + static_cast(NULL)) { } +// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. +AssertionResult AssertionResult::operator!() const { + AssertionResult negation(!success_); + if (message_.get() != NULL) + negation << *message_; + return negation; +} // Makes a successful assertion result. AssertionResult AssertionSuccess() { - return AssertionResult(); + return AssertionResult(true); } +// Makes a failed assertion result. +AssertionResult AssertionFailure() { + return AssertionResult(false); +} // Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << message. AssertionResult AssertionFailure(const Message& message) { - return AssertionResult(message.GetString()); + return AssertionFailure() << message; } namespace internal { @@ -1008,6 +1024,20 @@ AssertionResult EqFailure(const char* expected_expression, return AssertionFailure(msg); } +// 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) { + const char* actual_message = assertion_result.message(); + Message msg; + msg << "Value of: " << expression_text + << "\n Actual: " << actual_predicate_value; + if (actual_message[0] != '\0') + msg << " (" << actual_message << ")"; + msg << "\nExpected: " << expected_predicate_value; + return msg.GetString(); +} // Helper function for implementing ASSERT_NEAR. AssertionResult DoubleNearPredFormat(const char* expr1, diff --git a/test/gtest-tuple_test.cc b/test/gtest-tuple_test.cc index 3829118..ca5232e 100644 --- a/test/gtest-tuple_test.cc +++ b/test/gtest-tuple_test.cc @@ -135,12 +135,44 @@ TEST(ReferenceFieldTest, IsAliasOfReferencedVariable) { << "Changing a reference field should update the underlying variable."; } -// Tests tuple's default constructor. -TEST(TupleConstructorTest, DefaultConstructor) { - // We are just testing that the following compiles. +// Tests that tuple's default constructor default initializes each field. +// This test needs to compile without generating warnings. +TEST(TupleConstructorTest, DefaultConstructorDefaultInitializesEachField) { + // The TR1 report requires that tuple's default constructor default + // initializes each field, even if it's a primitive type. If the + // implementation forgets to do this, this test will catch it by + // generating warnings about using uninitialized variables (assuming + // a decent compiler). + tuple<> empty; - tuple one_field; - tuple three_fields; + + tuple a1, b1; + b1 = a1; + EXPECT_EQ(0, get<0>(b1)); + + tuple a2, b2; + b2 = a2; + EXPECT_EQ(0, get<0>(b2)); + EXPECT_EQ(0.0, get<1>(b2)); + + tuple a3, b3; + b3 = a3; + EXPECT_EQ(0.0, get<0>(b3)); + EXPECT_EQ('\0', get<1>(b3)); + EXPECT_EQ(NULL, get<2>(b3)); + + tuple a10, b10; + b10 = a10; + EXPECT_EQ(0, get<0>(b10)); + EXPECT_EQ(0, get<1>(b10)); + EXPECT_EQ(0, get<2>(b10)); + EXPECT_EQ(0, get<3>(b10)); + EXPECT_EQ(0, get<4>(b10)); + EXPECT_EQ(0, get<5>(b10)); + EXPECT_EQ(0, get<6>(b10)); + EXPECT_EQ(0, get<7>(b10)); + EXPECT_EQ(0, get<8>(b10)); + EXPECT_EQ(0, get<9>(b10)); } // Tests constructing a tuple from its fields. diff --git a/test/gtest_stress_test.cc b/test/gtest_stress_test.cc index 0034bb8..75d6268 100644 --- a/test/gtest_stress_test.cc +++ b/test/gtest_stress_test.cc @@ -32,9 +32,10 @@ // Tests that SCOPED_TRACE() and various Google Test assertions can be // used in a large number of threads concurrently. -#include #include +#include + // We must define this macro in order to #include // gtest-internal-inl.h. This is how Google Test prevents a user from // accidentally depending on its internal implementation. @@ -42,6 +43,8 @@ #include "src/gtest-internal-inl.h" #undef GTEST_IMPLEMENTATION_ +#if GTEST_IS_THREADSAFE + namespace testing { namespace { @@ -49,6 +52,20 @@ using internal::String; using internal::TestPropertyKeyIs; using internal::Vector; +// In order to run tests in this file, for platforms where Google Test is +// thread safe, implement ThreadWithParam with the following interface: +// +// template class ThreadWithParam { +// public: +// // Creates the thread. The thread should execute thread_func(param) when +// // started by a call to Start(). +// ThreadWithParam(void (*thread_func)(T), T param); +// // Starts the thread. +// void Start(); +// // Waits for the thread to finish. +// void Join(); +// }; + // How many threads to create? const int kThreadCount = 50; @@ -77,7 +94,7 @@ void ExpectKeyAndValueWereRecordedForId(const Vector& properties, // Calls a large number of Google Test assertions, where exactly one of them // will fail. void ManyAsserts(int id) { - ::std::cout << "Thread #" << id << " running...\n"; + GTEST_LOG_(INFO) << "Thread #" << id << " running..."; SCOPED_TRACE(Message() << "Thread #" << id); @@ -104,41 +121,125 @@ void ManyAsserts(int id) { } } +void CheckTestFailureCount(int expected_failures) { + const TestInfo* const info = UnitTest::GetInstance()->current_test_info(); + const TestResult* const result = info->result(); + GTEST_CHECK_(expected_failures == result->total_part_count()) + << "Logged " << result->total_part_count() << " failures " + << " vs. " << expected_failures << " expected"; +} + // Tests using SCOPED_TRACE() and Google Test assertions in many threads // concurrently. TEST(StressTest, CanUseScopedTraceAndAssertionsInManyThreads) { - // TODO(wan): when Google Test is made thread-safe, run - // ManyAsserts() in many threads here. + ThreadWithParam* threads[kThreadCount] = {}; + for (int i = 0; i != kThreadCount; i++) { + // Creates a thread to run the ManyAsserts() function. + threads[i] = new ThreadWithParam(&ManyAsserts, i); + + // Starts the thread. + threads[i]->Start(); + } + + // At this point, we have many threads running. + + for (int i = 0; i != kThreadCount; i++) { + // We block until the thread is done. + threads[i]->Join(); + delete threads[i]; + threads[i] = NULL; + } + + // Ensures that kThreadCount*kThreadCount failures have been reported. + const TestInfo* const info = UnitTest::GetInstance()->current_test_info(); + const TestResult* const result = info->result(); + + Vector properties; + // We have no access to the TestResult's list of properties but we can + // copy them one by one. + for (int i = 0; i < result->test_property_count(); ++i) + properties.PushBack(result->GetTestProperty(i)); + + EXPECT_EQ(kThreadCount * 2 + 1, result->test_property_count()) + << "String and int values recorded on each thread, " + << "as well as one shared_key"; + for (int i = 0; i < kThreadCount; ++i) { + ExpectKeyAndValueWereRecordedForId(properties, i, "string"); + ExpectKeyAndValueWereRecordedForId(properties, i, "int"); + } + CheckTestFailureCount(kThreadCount*kThreadCount); +} + +void FailingThread(bool is_fatal) { + if (is_fatal) + FAIL() << "Fatal failure in some other thread. " + << "(This failure is expected.)"; + else + ADD_FAILURE() << "Non-fatal failure in some other thread. " + << "(This failure is expected.)"; +} + +void GenerateFatalFailureInAnotherThread(bool is_fatal) { + ThreadWithParam thread(&FailingThread, is_fatal); + thread.Start(); + thread.Join(); } TEST(NoFatalFailureTest, ExpectNoFatalFailureIgnoresFailuresInOtherThreads) { - // TODO(mheule@google.com): Test this works correctly when Google - // Test is made thread-safe. + EXPECT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true)); + // We should only have one failure (the one from + // GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE + // should succeed. + CheckTestFailureCount(1); } +void AssertNoFatalFailureIgnoresFailuresInOtherThreads() { + ASSERT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true)); +} TEST(NoFatalFailureTest, AssertNoFatalFailureIgnoresFailuresInOtherThreads) { - // TODO(mheule@google.com): Test this works correctly when Google - // Test is made thread-safe. + // Using a subroutine, to make sure, that the test continues. + AssertNoFatalFailureIgnoresFailuresInOtherThreads(); + // We should only have one failure (the one from + // GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE + // should succeed. + CheckTestFailureCount(1); } TEST(FatalFailureTest, ExpectFatalFailureIgnoresFailuresInOtherThreads) { - // TODO(mheule@google.com): Test this works correctly when Google - // Test is made thread-safe. + // This statement should fail, since the current thread doesn't generate a + // fatal failure, only another one does. + EXPECT_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true), "expected"); + CheckTestFailureCount(2); } TEST(FatalFailureOnAllThreadsTest, ExpectFatalFailureOnAllThreads) { - // TODO(wan@google.com): Test this works correctly when Google Test - // is made thread-safe. + // This statement should succeed, because failures in all threads are + // considered. + EXPECT_FATAL_FAILURE_ON_ALL_THREADS( + GenerateFatalFailureInAnotherThread(true), "expected"); + CheckTestFailureCount(0); + // We need to add a failure, because main() checks that there are failures. + // But when only this test is run, we shouldn't have any failures. + ADD_FAILURE() << "This is an expected non-fatal failure."; } TEST(NonFatalFailureTest, ExpectNonFatalFailureIgnoresFailuresInOtherThreads) { - // TODO(mheule@google.com): Test this works correctly when Google - // Test is made thread-safe. + // This statement should fail, since the current thread doesn't generate a + // fatal failure, only another one does. + EXPECT_NONFATAL_FAILURE(GenerateFatalFailureInAnotherThread(false), + "expected"); + CheckTestFailureCount(2); } TEST(NonFatalFailureOnAllThreadsTest, ExpectNonFatalFailureOnAllThreads) { - // TODO(wan@google.com): Test this works correctly when Google Test - // is made thread-safe. + // This statement should succeed, because failures in all threads are + // considered. + EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS( + GenerateFatalFailureInAnotherThread(false), "expected"); + CheckTestFailureCount(0); + // We need to add a failure, because main() checks that there are failures, + // But when only this test is run, we shouldn't have any failures. + ADD_FAILURE() << "This is an expected non-fatal failure."; } } // namespace @@ -147,5 +248,20 @@ TEST(NonFatalFailureOnAllThreadsTest, ExpectNonFatalFailureOnAllThreads) { int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); + const int result = RUN_ALL_TESTS(); // Expected to fail. + GTEST_CHECK_(result == 1) << "RUN_ALL_TESTS() did not fail as expected"; + + printf("\nPASS\n"); + return 0; +} + +#else +TEST(StressTest, + DISABLED_ThreadSafetyTestsAreSkippedWhenGoogleTestIsNotThreadSafe) { +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } +#endif // GTEST_IS_THREADSAFE diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc index 5c69b46..98f3a8b 100644 --- a/test/gtest_unittest.cc +++ b/test/gtest_unittest.cc @@ -2418,6 +2418,25 @@ AssertionResult AssertIsEven(const char* expr, int n) { return AssertionFailure(msg); } +// A predicate function that returns AssertionResult for use in +// EXPECT/ASSERT_TRUE/FALSE. +AssertionResult ResultIsEven(int n) { + if (IsEven(n)) + return AssertionSuccess() << n << " is even"; + else + return AssertionFailure() << n << " is odd"; +} + +// A predicate function that returns AssertionResult but gives no +// explanation why it succeeds. Needed for testing that +// EXPECT/ASSERT_FALSE handles such functions correctly. +AssertionResult ResultIsEvenNoExplanation(int n) { + if (IsEven(n)) + return AssertionSuccess(); + else + return AssertionFailure() << n << " is odd"; +} + // A predicate-formatter functor that asserts the argument is an even // number. struct AssertIsEvenFunctor { @@ -3786,6 +3805,20 @@ TEST(AssertionTest, ASSERT_TRUE) { "2 < 1"); } +// Tests ASSERT_TRUE(predicate) for predicates returning AssertionResult. +TEST(AssertionTest, AssertTrueWithAssertionResult) { + ASSERT_TRUE(ResultIsEven(2)); + EXPECT_FATAL_FAILURE(ASSERT_TRUE(ResultIsEven(3)), + "Value of: ResultIsEven(3)\n" + " Actual: false (3 is odd)\n" + "Expected: true"); + ASSERT_TRUE(ResultIsEvenNoExplanation(2)); + EXPECT_FATAL_FAILURE(ASSERT_TRUE(ResultIsEvenNoExplanation(3)), + "Value of: ResultIsEvenNoExplanation(3)\n" + " Actual: false (3 is odd)\n" + "Expected: true"); +} + // Tests ASSERT_FALSE. TEST(AssertionTest, ASSERT_FALSE) { ASSERT_FALSE(2 < 1); // NOLINT @@ -3795,6 +3828,20 @@ TEST(AssertionTest, ASSERT_FALSE) { "Expected: false"); } +// Tests ASSERT_FALSE(predicate) for predicates returning AssertionResult. +TEST(AssertionTest, AssertFalseWithAssertionResult) { + ASSERT_FALSE(ResultIsEven(3)); + EXPECT_FATAL_FAILURE(ASSERT_FALSE(ResultIsEven(2)), + "Value of: ResultIsEven(2)\n" + " Actual: true (2 is even)\n" + "Expected: false"); + ASSERT_FALSE(ResultIsEvenNoExplanation(3)); + EXPECT_FATAL_FAILURE(ASSERT_FALSE(ResultIsEvenNoExplanation(2)), + "Value of: ResultIsEvenNoExplanation(2)\n" + " Actual: true\n" + "Expected: false"); +} + #ifdef __BORLANDC__ // Restores warnings after previous "#pragma option push" supressed them #pragma option pop @@ -4336,6 +4383,20 @@ TEST(ExpectTest, EXPECT_TRUE) { "2 > 3"); } +// Tests EXPECT_TRUE(predicate) for predicates returning AssertionResult. +TEST(ExpectTest, ExpectTrueWithAssertionResult) { + EXPECT_TRUE(ResultIsEven(2)); + EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(ResultIsEven(3)), + "Value of: ResultIsEven(3)\n" + " Actual: false (3 is odd)\n" + "Expected: true"); + EXPECT_TRUE(ResultIsEvenNoExplanation(2)); + EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(ResultIsEvenNoExplanation(3)), + "Value of: ResultIsEvenNoExplanation(3)\n" + " Actual: false (3 is odd)\n" + "Expected: true"); +} + // Tests EXPECT_FALSE. TEST(ExpectTest, EXPECT_FALSE) { EXPECT_FALSE(2 < 1); // NOLINT @@ -4347,6 +4408,20 @@ TEST(ExpectTest, EXPECT_FALSE) { "2 < 3"); } +// Tests EXPECT_FALSE(predicate) for predicates returning AssertionResult. +TEST(ExpectTest, ExpectFalseWithAssertionResult) { + EXPECT_FALSE(ResultIsEven(3)); + EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(ResultIsEven(2)), + "Value of: ResultIsEven(2)\n" + " Actual: true (2 is even)\n" + "Expected: false"); + EXPECT_FALSE(ResultIsEvenNoExplanation(3)); + EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(ResultIsEvenNoExplanation(2)), + "Value of: ResultIsEvenNoExplanation(2)\n" + " Actual: true\n" + "Expected: false"); +} + #ifdef __BORLANDC__ // Restores warnings after previous "#pragma option push" supressed them #pragma option pop @@ -4952,6 +5027,63 @@ TEST_F(TestLifeCycleTest, Test2) { } // namespace +// Tests that the copy constructor works when it is NOT optimized away by +// the compiler. +TEST(AssertionResultTest, CopyConstructorWorksWhenNotOptimied) { + // Checks that the copy constructor doesn't try to dereference NULL pointers + // in the source object. + AssertionResult r1 = AssertionSuccess(); + AssertionResult r2 = r1; + // The following line is added to prevent the compiler from optimizing + // away the constructor call. + r1 << "abc"; + + AssertionResult r3 = r1; + EXPECT_EQ(static_cast(r3), static_cast(r1)); + EXPECT_STREQ("abc", r1.message()); +} + +// Tests that AssertionSuccess and AssertionFailure construct +// AssertionResult objects as expected. +TEST(AssertionResultTest, ConstructionWorks) { + AssertionResult r1 = AssertionSuccess(); + EXPECT_TRUE(r1); + EXPECT_STREQ("", r1.message()); + + AssertionResult r2 = AssertionSuccess() << "abc"; + EXPECT_TRUE(r2); + EXPECT_STREQ("abc", r2.message()); + + AssertionResult r3 = AssertionFailure(); + EXPECT_FALSE(r3); + EXPECT_STREQ("", r3.message()); + + AssertionResult r4 = AssertionFailure() << "def"; + EXPECT_FALSE(r4); + EXPECT_STREQ("def", r4.message()); + + AssertionResult r5 = AssertionFailure(Message() << "ghi"); + EXPECT_FALSE(r5); + EXPECT_STREQ("ghi", r5.message()); +} + +// Tests that the negation fips the predicate result but keeps the message. +TEST(AssertionResultTest, NegationWorks) { + AssertionResult r1 = AssertionSuccess() << "abc"; + EXPECT_FALSE(!r1); + EXPECT_STREQ("abc", (!r1).message()); + + AssertionResult r2 = AssertionFailure() << "def"; + EXPECT_TRUE(!r2); + EXPECT_STREQ("def", (!r2).message()); +} + +TEST(AssertionResultTest, StreamingWorks) { + AssertionResult r = AssertionSuccess(); + r << "abc" << 'd' << 0 << true; + EXPECT_STREQ("abcd0true", r.message()); +} + // Tests streaming a user type whose definition and operator << are // both in the global namespace. class Base { -- cgit v0.12