diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/gtest-tuple_test.cc | 42 | ||||
-rw-r--r-- | test/gtest_stress_test.cc | 148 | ||||
-rw-r--r-- | test/gtest_unittest.cc | 132 |
3 files changed, 301 insertions, 21 deletions
diff --git a/test/gtest-tuple_test.cc b/test/gtest-tuple_test.cc index 3829118e..ca5232ee 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<int> one_field; - tuple<double, char, bool*> three_fields; + + tuple<int> a1, b1; + b1 = a1; + EXPECT_EQ(0, get<0>(b1)); + + tuple<int, double> a2, b2; + b2 = a2; + EXPECT_EQ(0, get<0>(b2)); + EXPECT_EQ(0.0, get<1>(b2)); + + tuple<double, char, bool*> a3, b3; + b3 = a3; + EXPECT_EQ(0.0, get<0>(b3)); + EXPECT_EQ('\0', get<1>(b3)); + EXPECT_EQ(NULL, get<2>(b3)); + + tuple<int, int, int, int, int, int, int, int, int, int> 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 0034bb84..75d6268e 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 <iostream> #include <gtest/gtest.h> +#include <iostream> + // 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 <typename T> 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<TestProperty>& 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<int>* threads[kThreadCount] = {}; + for (int i = 0; i != kThreadCount; i++) { + // Creates a thread to run the ManyAsserts() function. + threads[i] = new ThreadWithParam<int>(&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<TestProperty> 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<bool> 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 5c69b463..98f3a8b4 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<bool>(r3), static_cast<bool>(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 { |