aboutsummaryrefslogtreecommitdiffstats
path: root/gtest/test/gtest_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gtest/test/gtest_unittest.cc')
-rw-r--r--gtest/test/gtest_unittest.cc983
1 files changed, 905 insertions, 78 deletions
diff --git a/gtest/test/gtest_unittest.cc b/gtest/test/gtest_unittest.cc
index 2c08720..5c69b46 100644
--- a/gtest/test/gtest_unittest.cc
+++ b/gtest/test/gtest_unittest.cc
@@ -80,23 +80,37 @@ TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
namespace testing {
namespace internal {
-const char* FormatTimeInMillisAsSeconds(TimeInMillis ms);
+bool ShouldUseColor(bool stdout_is_tty);
+const char* FormatTimeInMillisAsSeconds(TimeInMillis ms);
bool ParseInt32Flag(const char* str, const char* flag, Int32* value);
-} // namespace internal
-} // namespace testing
+// Provides access to otherwise private parts of the TestEventListeners class
+// that are needed to test it.
+class TestEventListenersAccessor {
+ public:
+ static TestEventListener* GetRepeater(TestEventListeners* listeners) {
+ return listeners->repeater();
+ }
-using testing::internal::FormatTimeInMillisAsSeconds;
-using testing::internal::ParseInt32Flag;
+ static void SetDefaultResultPrinter(TestEventListeners* listeners,
+ TestEventListener* listener) {
+ listeners->SetDefaultResultPrinter(listener);
+ }
+ static void SetDefaultXmlGenerator(TestEventListeners* listeners,
+ TestEventListener* listener) {
+ listeners->SetDefaultXmlGenerator(listener);
+ }
-namespace testing {
+ static bool EventForwardingEnabled(const TestEventListeners& listeners) {
+ return listeners.EventForwardingEnabled();
+ }
-GTEST_DECLARE_string_(output);
-GTEST_DECLARE_string_(color);
+ static void SuppressEventForwarding(TestEventListeners* listeners) {
+ listeners->SuppressEventForwarding();
+ }
+};
-namespace internal {
-bool ShouldUseColor(bool stdout_is_tty);
} // namespace internal
} // namespace testing
@@ -104,6 +118,7 @@ using testing::AssertionFailure;
using testing::AssertionResult;
using testing::AssertionSuccess;
using testing::DoubleLE;
+using testing::EmptyTestEventListener;
using testing::FloatLE;
using testing::GTEST_FLAG(also_run_disabled_tests);
using testing::GTEST_FLAG(break_on_failure);
@@ -125,19 +140,21 @@ using testing::IsSubstring;
using testing::Message;
using testing::ScopedFakeTestPartResultReporter;
using testing::StaticAssertTypeEq;
-using testing::TPRT_FATAL_FAILURE;
-using testing::TPRT_NONFATAL_FAILURE;
-using testing::TPRT_SUCCESS;
using testing::Test;
+using testing::TestEventListeners;
+using testing::TestCase;
using testing::TestPartResult;
using testing::TestPartResultArray;
+using testing::TestProperty;
+using testing::TestResult;
using testing::UnitTest;
-using testing::internal::kMaxRandomSeed;
-using testing::internal::kTestTypeIdInGoogleTest;
+using testing::internal::AlwaysFalse;
+using testing::internal::AlwaysTrue;
using testing::internal::AppendUserMessage;
using testing::internal::CodePointToUtf8;
using testing::internal::EqFailure;
using testing::internal::FloatingPoint;
+using testing::internal::FormatTimeInMillisAsSeconds;
using testing::internal::GTestFlagSaver;
using testing::internal::GetCurrentOsStackTraceExceptTop;
using testing::internal::GetNextRandomSeed;
@@ -147,19 +164,34 @@ using testing::internal::GetTypeId;
using testing::internal::GetUnitTestImpl;
using testing::internal::Int32;
using testing::internal::Int32FromEnvOrDie;
+using testing::internal::ParseInt32Flag;
using testing::internal::ShouldRunTestOnShard;
using testing::internal::ShouldShard;
using testing::internal::ShouldUseColor;
using testing::internal::StreamableToString;
using testing::internal::String;
-using testing::internal::TestCase;
-using testing::internal::TestProperty;
-using testing::internal::TestResult;
+using testing::internal::TestEventListenersAccessor;
using testing::internal::TestResultAccessor;
using testing::internal::ThreadLocal;
+using testing::internal::UInt32;
using testing::internal::Vector;
using testing::internal::WideStringToUtf8;
+using testing::internal::kMaxRandomSeed;
using testing::internal::kTestTypeIdInGoogleTest;
+using testing::internal::scoped_ptr;
+
+class TestingVector : public Vector<int> {
+};
+
+::std::ostream& operator<<(::std::ostream& os,
+ const TestingVector& vector) {
+ os << "{ ";
+ for (int i = 0; i < vector.size(); i++) {
+ os << vector.GetElement(i) << " ";
+ }
+ os << "}";
+ return os;
+}
// This line tests that we can define tests in an unnamed namespace.
namespace {
@@ -472,6 +504,49 @@ TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
}
#endif // !GTEST_WIDE_STRING_USES_UTF16_
+// Tests the Random class.
+
+TEST(RandomDeathTest, GeneratesCrashesOnInvalidRange) {
+ testing::internal::Random random(42);
+ EXPECT_DEATH_IF_SUPPORTED(
+ random.Generate(0),
+ "Cannot generate a number in the range \\[0, 0\\)");
+ EXPECT_DEATH_IF_SUPPORTED(
+ random.Generate(testing::internal::Random::kMaxRange + 1),
+ "Generation of a number in \\[0, 2147483649\\) was requested, "
+ "but this can only generate numbers in \\[0, 2147483648\\)");
+}
+
+TEST(RandomTest, GeneratesNumbersWithinRange) {
+ const UInt32 kRange = 10000;
+ testing::internal::Random random(12345);
+ for (int i = 0; i < 10; i++) {
+ EXPECT_LT(random.Generate(kRange), kRange) << " for iteration " << i;
+ }
+
+ testing::internal::Random random2(testing::internal::Random::kMaxRange);
+ for (int i = 0; i < 10; i++) {
+ EXPECT_LT(random2.Generate(kRange), kRange) << " for iteration " << i;
+ }
+}
+
+TEST(RandomTest, RepeatsWhenReseeded) {
+ const int kSeed = 123;
+ const int kArraySize = 10;
+ const UInt32 kRange = 10000;
+ UInt32 values[kArraySize];
+
+ testing::internal::Random random(kSeed);
+ for (int i = 0; i < kArraySize; i++) {
+ values[i] = random.Generate(kRange);
+ }
+
+ random.Reseed(kSeed);
+ for (int i = 0; i < kArraySize; i++) {
+ EXPECT_EQ(values[i], random.Generate(kRange)) << " for iteration " << i;
+ }
+}
+
// Tests the Vector class template.
// Tests Vector::Clear().
@@ -615,6 +690,53 @@ TEST(VectorTest, GetElementOr) {
EXPECT_EQ('x', a.GetElementOr(2, 'x'));
}
+TEST(VectorTest, Swap) {
+ Vector<int> a;
+ a.PushBack(0);
+ a.PushBack(1);
+ a.PushBack(2);
+
+ // Swaps an element with itself.
+ a.Swap(0, 0);
+ ASSERT_EQ(0, a.GetElement(0));
+ ASSERT_EQ(1, a.GetElement(1));
+ ASSERT_EQ(2, a.GetElement(2));
+
+ // Swaps two different elements where the indices go up.
+ a.Swap(0, 1);
+ ASSERT_EQ(1, a.GetElement(0));
+ ASSERT_EQ(0, a.GetElement(1));
+ ASSERT_EQ(2, a.GetElement(2));
+
+ // Swaps two different elements where the indices go down.
+ a.Swap(2, 0);
+ ASSERT_EQ(2, a.GetElement(0));
+ ASSERT_EQ(0, a.GetElement(1));
+ ASSERT_EQ(1, a.GetElement(2));
+}
+
+TEST(VectorTest, Clone) {
+ // Clones an empty Vector.
+ Vector<int> a;
+ scoped_ptr<Vector<int> > empty(a.Clone());
+ EXPECT_EQ(0, empty->size());
+
+ // Clones a singleton.
+ a.PushBack(42);
+ scoped_ptr<Vector<int> > singleton(a.Clone());
+ ASSERT_EQ(1, singleton->size());
+ EXPECT_EQ(42, singleton->GetElement(0));
+
+ // Clones a Vector with more elements.
+ a.PushBack(43);
+ a.PushBack(44);
+ scoped_ptr<Vector<int> > big(a.Clone());
+ ASSERT_EQ(3, big->size());
+ EXPECT_EQ(42, big->GetElement(0));
+ EXPECT_EQ(43, big->GetElement(1));
+ EXPECT_EQ(44, big->GetElement(2));
+}
+
// Tests Vector::Erase().
TEST(VectorDeathTest, Erase) {
Vector<int> a;
@@ -678,23 +800,260 @@ TEST(VectorDeathTest, Erase) {
}
// Tests the GetElement accessor.
-TEST(ListDeathTest, GetElement) {
+TEST(VectorDeathTest, GetElement) {
Vector<int> a;
a.PushBack(0);
a.PushBack(1);
a.PushBack(2);
+ const Vector<int>& b = a;
- EXPECT_EQ(0, a.GetElement(0));
- EXPECT_EQ(1, a.GetElement(1));
- EXPECT_EQ(2, a.GetElement(2));
+ EXPECT_EQ(0, b.GetElement(0));
+ EXPECT_EQ(1, b.GetElement(1));
+ EXPECT_EQ(2, b.GetElement(2));
EXPECT_DEATH_IF_SUPPORTED(
- a.GetElement(3),
+ b.GetElement(3),
"Invalid Vector index 3: must be in range \\[0, 2\\]\\.");
EXPECT_DEATH_IF_SUPPORTED(
- a.GetElement(-1),
+ b.GetElement(-1),
"Invalid Vector index -1: must be in range \\[0, 2\\]\\.");
}
+// Tests the GetMutableElement accessor.
+TEST(VectorDeathTest, GetMutableElement) {
+ Vector<int> a;
+ a.PushBack(0);
+ a.PushBack(1);
+ a.PushBack(2);
+
+ EXPECT_EQ(0, a.GetMutableElement(0));
+ EXPECT_EQ(1, a.GetMutableElement(1));
+ EXPECT_EQ(2, a.GetMutableElement(2));
+
+ a.GetMutableElement(0) = 42;
+ EXPECT_EQ(42, a.GetMutableElement(0));
+ EXPECT_EQ(1, a.GetMutableElement(1));
+ EXPECT_EQ(2, a.GetMutableElement(2));
+
+ EXPECT_DEATH_IF_SUPPORTED(
+ a.GetMutableElement(3),
+ "Invalid Vector index 3: must be in range \\[0, 2\\]\\.");
+ EXPECT_DEATH_IF_SUPPORTED(
+ a.GetMutableElement(-1),
+ "Invalid Vector index -1: must be in range \\[0, 2\\]\\.");
+}
+
+TEST(VectorDeathTest, Swap) {
+ Vector<int> a;
+ a.PushBack(0);
+ a.PushBack(1);
+ a.PushBack(2);
+
+ EXPECT_DEATH_IF_SUPPORTED(
+ a.Swap(-1, 1),
+ "Invalid first swap element -1: must be in range \\[0, 2\\]");
+ EXPECT_DEATH_IF_SUPPORTED(
+ a.Swap(3, 1),
+ "Invalid first swap element 3: must be in range \\[0, 2\\]");
+ EXPECT_DEATH_IF_SUPPORTED(
+ a.Swap(1, -1),
+ "Invalid second swap element -1: must be in range \\[0, 2\\]");
+ EXPECT_DEATH_IF_SUPPORTED(
+ a.Swap(1, 3),
+ "Invalid second swap element 3: must be in range \\[0, 2\\]");
+}
+
+TEST(VectorDeathTest, ShuffleRange) {
+ Vector<int> a;
+ a.PushBack(0);
+ a.PushBack(1);
+ a.PushBack(2);
+ testing::internal::Random random(1);
+
+ EXPECT_DEATH_IF_SUPPORTED(
+ a.ShuffleRange(&random, -1, 1),
+ "Invalid shuffle range start -1: must be in range \\[0, 3\\]");
+ EXPECT_DEATH_IF_SUPPORTED(
+ a.ShuffleRange(&random, 4, 4),
+ "Invalid shuffle range start 4: must be in range \\[0, 3\\]");
+ EXPECT_DEATH_IF_SUPPORTED(
+ a.ShuffleRange(&random, 3, 2),
+ "Invalid shuffle range finish 2: must be in range \\[3, 3\\]");
+ EXPECT_DEATH_IF_SUPPORTED(
+ a.ShuffleRange(&random, 3, 4),
+ "Invalid shuffle range finish 4: must be in range \\[3, 3\\]");
+}
+
+class VectorShuffleTest : public Test {
+ protected:
+ static const int kVectorSize = 20;
+
+ VectorShuffleTest() : random_(1) {
+ for (int i = 0; i < kVectorSize; i++) {
+ vector_.PushBack(i);
+ }
+ }
+
+ static bool VectorIsCorrupt(const TestingVector& vector) {
+ if (kVectorSize != vector.size()) {
+ return true;
+ }
+
+ bool found_in_vector[kVectorSize] = { false };
+ for (int i = 0; i < vector.size(); i++) {
+ const int e = vector.GetElement(i);
+ if (e < 0 || e >= kVectorSize || found_in_vector[e]) {
+ return true;
+ }
+ found_in_vector[e] = true;
+ }
+
+ // Vector size is correct, elements' range is correct, no
+ // duplicate elements. Therefore no corruption has occurred.
+ return false;
+ }
+
+ static bool VectorIsNotCorrupt(const TestingVector& vector) {
+ return !VectorIsCorrupt(vector);
+ }
+
+ static bool RangeIsShuffled(const TestingVector& vector, int begin, int end) {
+ for (int i = begin; i < end; i++) {
+ if (i != vector.GetElement(i)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static bool RangeIsUnshuffled(
+ const TestingVector& vector, int begin, int end) {
+ return !RangeIsShuffled(vector, begin, end);
+ }
+
+ static bool VectorIsShuffled(const TestingVector& vector) {
+ return RangeIsShuffled(vector, 0, vector.size());
+ }
+
+ static bool VectorIsUnshuffled(const TestingVector& vector) {
+ return !VectorIsShuffled(vector);
+ }
+
+ testing::internal::Random random_;
+ TestingVector vector_;
+}; // class VectorShuffleTest
+
+const int VectorShuffleTest::kVectorSize;
+
+TEST_F(VectorShuffleTest, HandlesEmptyRange) {
+ // Tests an empty range at the beginning...
+ vector_.ShuffleRange(&random_, 0, 0);
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+ // ...in the middle...
+ vector_.ShuffleRange(&random_, kVectorSize/2, kVectorSize/2);
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+ // ...at the end...
+ vector_.ShuffleRange(&random_, kVectorSize - 1, kVectorSize - 1);
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+ // ...and past the end.
+ vector_.ShuffleRange(&random_, kVectorSize, kVectorSize);
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ ASSERT_PRED1(VectorIsUnshuffled, vector_);
+}
+
+TEST_F(VectorShuffleTest, HandlesRangeOfSizeOne) {
+ // Tests a size one range at the beginning...
+ vector_.ShuffleRange(&random_, 0, 1);
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+ // ...in the middle...
+ vector_.ShuffleRange(&random_, kVectorSize/2, kVectorSize/2 + 1);
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ ASSERT_PRED1(VectorIsUnshuffled, vector_);
+
+ // ...and at the end.
+ vector_.ShuffleRange(&random_, kVectorSize - 1, kVectorSize);
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ ASSERT_PRED1(VectorIsUnshuffled, vector_);
+}
+
+// Because we use our own random number generator and a fixed seed,
+// we can guarantee that the following "random" tests will succeed.
+
+TEST_F(VectorShuffleTest, ShufflesEntireVector) {
+ vector_.Shuffle(&random_);
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ EXPECT_FALSE(VectorIsUnshuffled(vector_)) << vector_;
+
+ // Tests the first and last elements in particular to ensure that
+ // there are no off-by-one problems in our shuffle algorithm.
+ EXPECT_NE(0, vector_.GetElement(0));
+ EXPECT_NE(kVectorSize - 1, vector_.GetElement(kVectorSize - 1));
+}
+
+TEST_F(VectorShuffleTest, ShufflesStartOfVector) {
+ const int kRangeSize = kVectorSize/2;
+
+ vector_.ShuffleRange(&random_, 0, kRangeSize);
+
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ EXPECT_PRED3(RangeIsShuffled, vector_, 0, kRangeSize);
+ EXPECT_PRED3(RangeIsUnshuffled, vector_, kRangeSize, kVectorSize);
+}
+
+TEST_F(VectorShuffleTest, ShufflesEndOfVector) {
+ const int kRangeSize = kVectorSize / 2;
+ vector_.ShuffleRange(&random_, kRangeSize, kVectorSize);
+
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ EXPECT_PRED3(RangeIsUnshuffled, vector_, 0, kRangeSize);
+ EXPECT_PRED3(RangeIsShuffled, vector_, kRangeSize, kVectorSize);
+}
+
+TEST_F(VectorShuffleTest, ShufflesMiddleOfVector) {
+ int kRangeSize = kVectorSize/3;
+ vector_.ShuffleRange(&random_, kRangeSize, 2*kRangeSize);
+
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ EXPECT_PRED3(RangeIsUnshuffled, vector_, 0, kRangeSize);
+ EXPECT_PRED3(RangeIsShuffled, vector_, kRangeSize, 2*kRangeSize);
+ EXPECT_PRED3(RangeIsUnshuffled, vector_, 2*kRangeSize, kVectorSize);
+}
+
+TEST_F(VectorShuffleTest, ShufflesRepeatably) {
+ TestingVector vector2;
+ for (int i = 0; i < kVectorSize; i++) {
+ vector2.PushBack(i);
+ }
+
+ random_.Reseed(1234);
+ vector_.Shuffle(&random_);
+ random_.Reseed(1234);
+ vector2.Shuffle(&random_);
+
+ ASSERT_PRED1(VectorIsNotCorrupt, vector_);
+ ASSERT_PRED1(VectorIsNotCorrupt, vector2);
+
+ for (int i = 0; i < kVectorSize; i++) {
+ EXPECT_EQ(vector_.GetElement(i), vector2.GetElement(i))
+ << " where i is " << i;
+ }
+}
+
+// Tests the size of the AssertHelper class.
+
+TEST(AssertHelperTest, AssertHelperIsSmall) {
+ // To avoid breaking clients that use lots of assertions in one
+ // function, we cannot grow the size of AssertHelper.
+ EXPECT_LE(sizeof(testing::internal::AssertHelper), sizeof(void*));
+}
+
// Tests the String class.
// Tests String's constructors.
@@ -703,19 +1062,49 @@ TEST(StringTest, Constructors) {
String s1;
// We aren't using EXPECT_EQ(NULL, s1.c_str()) because comparing
// pointers with NULL isn't supported on all platforms.
+ EXPECT_EQ(0U, s1.length());
EXPECT_TRUE(NULL == s1.c_str());
// Implicitly constructs from a C-string.
String s2 = "Hi";
+ EXPECT_EQ(2U, s2.length());
EXPECT_STREQ("Hi", s2.c_str());
// Constructs from a C-string and a length.
String s3("hello", 3);
+ EXPECT_EQ(3U, s3.length());
EXPECT_STREQ("hel", s3.c_str());
- // Copy ctor.
- String s4 = s3;
- EXPECT_STREQ("hel", s4.c_str());
+ // The empty String should be created when String is constructed with
+ // a NULL pointer and length 0.
+ EXPECT_EQ(0U, String(NULL, 0).length());
+ EXPECT_FALSE(String(NULL, 0).c_str() == NULL);
+
+ // Constructs a String that contains '\0'.
+ String s4("a\0bcd", 4);
+ EXPECT_EQ(4U, s4.length());
+ EXPECT_EQ('a', s4.c_str()[0]);
+ EXPECT_EQ('\0', s4.c_str()[1]);
+ EXPECT_EQ('b', s4.c_str()[2]);
+ EXPECT_EQ('c', s4.c_str()[3]);
+
+ // Copy ctor where the source is NULL.
+ const String null_str;
+ String s5 = null_str;
+ EXPECT_TRUE(s5.c_str() == NULL);
+
+ // Copy ctor where the source isn't NULL.
+ String s6 = s3;
+ EXPECT_EQ(3U, s6.length());
+ EXPECT_STREQ("hel", s6.c_str());
+
+ // Copy ctor where the source contains '\0'.
+ String s7 = s4;
+ EXPECT_EQ(4U, s7.length());
+ EXPECT_EQ('a', s7.c_str()[0]);
+ EXPECT_EQ('\0', s7.c_str()[1]);
+ EXPECT_EQ('b', s7.c_str()[2]);
+ EXPECT_EQ('c', s7.c_str()[3]);
}
#if GTEST_HAS_STD_STRING
@@ -724,17 +1113,22 @@ TEST(StringTest, ConvertsFromStdString) {
// An empty std::string.
const std::string src1("");
const String dest1 = src1;
+ EXPECT_EQ(0U, dest1.length());
EXPECT_STREQ("", dest1.c_str());
// A normal std::string.
const std::string src2("Hi");
const String dest2 = src2;
+ EXPECT_EQ(2U, dest2.length());
EXPECT_STREQ("Hi", dest2.c_str());
// An std::string with an embedded NUL character.
- const char src3[] = "Hello\0world.";
+ const char src3[] = "a\0b";
const String dest3 = std::string(src3, sizeof(src3));
- EXPECT_STREQ("Hello", dest3.c_str());
+ EXPECT_EQ(sizeof(src3), dest3.length());
+ EXPECT_EQ('a', dest3.c_str()[0]);
+ EXPECT_EQ('\0', dest3.c_str()[1]);
+ EXPECT_EQ('b', dest3.c_str()[2]);
}
TEST(StringTest, ConvertsToStdString) {
@@ -747,6 +1141,11 @@ TEST(StringTest, ConvertsToStdString) {
const String src2("Hi");
const std::string dest2 = src2;
EXPECT_EQ("Hi", dest2);
+
+ // A String containing a '\0'.
+ const String src3("x\0y", 3);
+ const std::string dest3 = src3;
+ EXPECT_EQ(std::string("x\0y", 3), dest3);
}
#endif // GTEST_HAS_STD_STRING
@@ -757,17 +1156,22 @@ TEST(StringTest, ConvertsFromGlobalString) {
// An empty ::string.
const ::string src1("");
const String dest1 = src1;
+ EXPECT_EQ(0U, dest1.length());
EXPECT_STREQ("", dest1.c_str());
// A normal ::string.
const ::string src2("Hi");
const String dest2 = src2;
+ EXPECT_EQ(2U, dest2.length());
EXPECT_STREQ("Hi", dest2.c_str());
// An ::string with an embedded NUL character.
- const char src3[] = "Hello\0world.";
+ const char src3[] = "x\0y";
const String dest3 = ::string(src3, sizeof(src3));
- EXPECT_STREQ("Hello", dest3.c_str());
+ EXPECT_EQ(sizeof(src3), dest3.length());
+ EXPECT_EQ('x', dest3.c_str()[0]);
+ EXPECT_EQ('\0', dest3.c_str()[1]);
+ EXPECT_EQ('y', dest3.c_str()[2]);
}
TEST(StringTest, ConvertsToGlobalString) {
@@ -780,17 +1184,14 @@ TEST(StringTest, ConvertsToGlobalString) {
const String src2("Hi");
const ::string dest2 = src2;
EXPECT_EQ("Hi", dest2);
+
+ const String src3("x\0y", 3);
+ const ::string dest3 = src3;
+ EXPECT_EQ(::string("x\0y", 3), dest3);
}
#endif // GTEST_HAS_GLOBAL_STRING
-// Tests String::ShowCString().
-TEST(StringTest, ShowCString) {
- EXPECT_STREQ("(null)", String::ShowCString(NULL));
- EXPECT_STREQ("", String::ShowCString(""));
- EXPECT_STREQ("foo", String::ShowCString("foo"));
-}
-
// Tests String::ShowCStringQuoted().
TEST(StringTest, ShowCStringQuoted) {
EXPECT_STREQ("(null)",
@@ -801,6 +1202,53 @@ TEST(StringTest, ShowCStringQuoted) {
String::ShowCStringQuoted("foo").c_str());
}
+// Tests String::empty().
+TEST(StringTest, Empty) {
+ EXPECT_TRUE(String("").empty());
+ EXPECT_FALSE(String().empty());
+ EXPECT_FALSE(String(NULL).empty());
+ EXPECT_FALSE(String("a").empty());
+ EXPECT_FALSE(String("\0", 1).empty());
+}
+
+// Tests String::Compare().
+TEST(StringTest, Compare) {
+ // NULL vs NULL.
+ EXPECT_EQ(0, String().Compare(String()));
+
+ // NULL vs non-NULL.
+ EXPECT_EQ(-1, String().Compare(String("")));
+
+ // Non-NULL vs NULL.
+ EXPECT_EQ(1, String("").Compare(String()));
+
+ // The following covers non-NULL vs non-NULL.
+
+ // "" vs "".
+ EXPECT_EQ(0, String("").Compare(String("")));
+
+ // "" vs non-"".
+ EXPECT_EQ(-1, String("").Compare(String("\0", 1)));
+ EXPECT_EQ(-1, String("").Compare(" "));
+
+ // Non-"" vs "".
+ EXPECT_EQ(1, String("a").Compare(String("")));
+
+ // The following covers non-"" vs non-"".
+
+ // Same length and equal.
+ EXPECT_EQ(0, String("a").Compare(String("a")));
+
+ // Same length and different.
+ EXPECT_EQ(-1, String("a\0b", 3).Compare(String("a\0c", 3)));
+ EXPECT_EQ(1, String("b").Compare(String("a")));
+
+ // Different lengths.
+ EXPECT_EQ(-1, String("a").Compare(String("ab")));
+ EXPECT_EQ(-1, String("a").Compare(String("a\0", 2)));
+ EXPECT_EQ(1, String("abc").Compare(String("aacd")));
+}
+
// Tests String::operator==().
TEST(StringTest, Equals) {
const String null(NULL);
@@ -818,6 +1266,9 @@ TEST(StringTest, Equals) {
EXPECT_FALSE(foo == ""); // NOLINT
EXPECT_FALSE(foo == "bar"); // NOLINT
EXPECT_TRUE(foo == "foo"); // NOLINT
+
+ const String bar("x\0y", 3);
+ EXPECT_FALSE(bar == "x");
}
// Tests String::operator!=().
@@ -837,6 +1288,17 @@ TEST(StringTest, NotEquals) {
EXPECT_TRUE(foo != ""); // NOLINT
EXPECT_TRUE(foo != "bar"); // NOLINT
EXPECT_FALSE(foo != "foo"); // NOLINT
+
+ const String bar("x\0y", 3);
+ EXPECT_TRUE(bar != "x");
+}
+
+// Tests String::length().
+TEST(StringTest, Length) {
+ EXPECT_EQ(0U, String().length());
+ EXPECT_EQ(0U, String("").length());
+ EXPECT_EQ(2U, String("ab").length());
+ EXPECT_EQ(3U, String("a\0b", 3).length());
}
// Tests String::EndsWith().
@@ -900,9 +1362,17 @@ TEST(StringTest, CanBeAssignedEmpty) {
TEST(StringTest, CanBeAssignedNonEmpty) {
const String src("hello");
String dest;
-
dest = src;
+ EXPECT_EQ(5U, dest.length());
EXPECT_STREQ("hello", dest.c_str());
+
+ const String src2("x\0y", 3);
+ String dest2;
+ dest2 = src2;
+ EXPECT_EQ(3U, dest2.length());
+ EXPECT_EQ('x', dest2.c_str()[0]);
+ EXPECT_EQ('\0', dest2.c_str()[1]);
+ EXPECT_EQ('y', dest2.c_str()[2]);
}
// Tests that a String can be assigned to itself.
@@ -913,6 +1383,40 @@ TEST(StringTest, CanBeAssignedSelf) {
EXPECT_STREQ("hello", dest.c_str());
}
+// Tests streaming a String.
+TEST(StringTest, Streams) {
+ EXPECT_EQ(StreamableToString(String()), "(null)");
+ EXPECT_EQ(StreamableToString(String("")), "");
+ EXPECT_EQ(StreamableToString(String("a\0b", 3)), "a\\0b");
+}
+
+// Tests that String::Format() works.
+TEST(StringTest, FormatWorks) {
+ // Normal case: the format spec is valid, the arguments match the
+ // spec, and the result is < 4095 characters.
+ EXPECT_STREQ("Hello, 42", String::Format("%s, %d", "Hello", 42).c_str());
+
+ // Edge case: the result is 4095 characters.
+ char buffer[4096];
+ const size_t kSize = sizeof(buffer);
+ memset(buffer, 'a', kSize - 1);
+ buffer[kSize - 1] = '\0';
+ EXPECT_STREQ(buffer, String::Format("%s", buffer).c_str());
+
+ // The result needs to be 4096 characters, exceeding Format()'s limit.
+ EXPECT_STREQ("<formatting error or buffer exceeded>",
+ String::Format("x%s", buffer).c_str());
+
+#if GTEST_OS_LINUX
+ // On Linux, invalid format spec should lead to an error message.
+ // In other environment (e.g. MSVC on Windows), String::Format() may
+ // simply ignore a bad format spec, so this assertion is run on
+ // Linux only.
+ EXPECT_STREQ("<formatting error or buffer exceeded>",
+ String::Format("%").c_str());
+#endif
+}
+
#if GTEST_OS_WINDOWS
// Tests String::ShowWideCString().
@@ -933,7 +1437,7 @@ TEST(StringTest, ShowWideCStringQuoted) {
String::ShowWideCStringQuoted(L"foo").c_str());
}
-#ifdef _WIN32_WCE
+#if GTEST_OS_WINDOWS_MOBILE
TEST(StringTest, AnsiAndUtf16Null) {
EXPECT_EQ(NULL, String::AnsiToUtf16(NULL));
EXPECT_EQ(NULL, String::Utf16ToAnsi(NULL));
@@ -956,7 +1460,7 @@ TEST(StringTest, AnsiAndUtf16ConvertPathChars) {
EXPECT_EQ(0, wcsncmp(L".:\\ \"*?", utf16, 3));
delete [] utf16;
}
-#endif // _WIN32_WCE
+#endif // GTEST_OS_WINDOWS_MOBILE
#endif // GTEST_OS_WINDOWS
@@ -1221,12 +1725,12 @@ TEST(TestPartResultTest, ConstructorWorks) {
message << static_cast<const char*>(testing::internal::kStackTraceMarker);
message << "some unimportant stack trace";
- const TestPartResult result(TPRT_NONFATAL_FAILURE,
+ const TestPartResult result(TestPartResult::kNonFatalFailure,
"some_file.cc",
42,
message.GetString().c_str());
- EXPECT_EQ(TPRT_NONFATAL_FAILURE, result.type());
+ EXPECT_EQ(TestPartResult::kNonFatalFailure, result.type());
EXPECT_STREQ("some_file.cc", result.file_name());
EXPECT_EQ(42, result.line_number());
EXPECT_STREQ(message.GetString().c_str(), result.message());
@@ -1234,13 +1738,16 @@ TEST(TestPartResultTest, ConstructorWorks) {
}
TEST(TestPartResultTest, ResultAccessorsWork) {
- const TestPartResult success(TPRT_SUCCESS, "file.cc", 42, "message");
+ const TestPartResult success(TestPartResult::kSuccess,
+ "file.cc",
+ 42,
+ "message");
EXPECT_TRUE(success.passed());
EXPECT_FALSE(success.failed());
EXPECT_FALSE(success.nonfatally_failed());
EXPECT_FALSE(success.fatally_failed());
- const TestPartResult nonfatal_failure(TPRT_NONFATAL_FAILURE,
+ const TestPartResult nonfatal_failure(TestPartResult::kNonFatalFailure,
"file.cc",
42,
"message");
@@ -1249,7 +1756,7 @@ TEST(TestPartResultTest, ResultAccessorsWork) {
EXPECT_TRUE(nonfatal_failure.nonfatally_failed());
EXPECT_FALSE(nonfatal_failure.fatally_failed());
- const TestPartResult fatal_failure(TPRT_FATAL_FAILURE,
+ const TestPartResult fatal_failure(TestPartResult::kFatalFailure,
"file.cc",
42,
"message");
@@ -1274,10 +1781,14 @@ class TestResultTest : public Test {
virtual void SetUp() {
// pr1 is for success.
- pr1 = new TestPartResult(TPRT_SUCCESS, "foo/bar.cc", 10, "Success!");
+ pr1 = new TestPartResult(TestPartResult::kSuccess,
+ "foo/bar.cc",
+ 10,
+ "Success!");
// pr2 is for fatal failure.
- pr2 = new TestPartResult(TPRT_FATAL_FAILURE, "foo/bar.cc",
+ pr2 = new TestPartResult(TestPartResult::kFatalFailure,
+ "foo/bar.cc",
-1, // This line number means "unknown"
"Failure!");
@@ -1577,7 +2088,7 @@ TEST_F(GTestFlagSaverTest, VerifyGTestFlags) {
// value. If the value argument is "", unsets the environment
// variable. The caller must ensure that both arguments are not NULL.
static void SetEnv(const char* name, const char* value) {
-#ifdef _WIN32_WCE
+#if GTEST_OS_WINDOWS_MOBILE
// Environment variables are not supported on Windows CE.
return;
#elif defined(__BORLANDC__)
@@ -1595,7 +2106,6 @@ static void SetEnv(const char* name, const char* value) {
added_env[name] = new String((Message() << name << "=" << value).GetString());
putenv(added_env[name]->c_str());
delete prev_env;
-
#elif GTEST_OS_WINDOWS // If we are on Windows proper.
_putenv((Message() << name << "=" << value).GetString().c_str());
#else
@@ -1604,10 +2114,10 @@ static void SetEnv(const char* name, const char* value) {
} else {
setenv(name, value, 1);
}
-#endif
+#endif // GTEST_OS_WINDOWS_MOBILE
}
-#ifndef _WIN32_WCE
+#if !GTEST_OS_WINDOWS_MOBILE
// Environment variables are not supported on Windows CE.
using testing::internal::Int32FromGTestEnv;
@@ -1655,7 +2165,7 @@ TEST(Int32FromGTestEnvTest, ParsesAndReturnsValidValue) {
SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "-321");
EXPECT_EQ(-321, Int32FromGTestEnv("temp", 0));
}
-#endif // !defined(_WIN32_WCE)
+#endif // !GTEST_OS_WINDOWS_MOBILE
// Tests ParseInt32Flag().
@@ -1713,7 +2223,7 @@ TEST(ParseInt32FlagTest, ParsesAndReturnsValidValue) {
// Tests that Int32FromEnvOrDie() parses the value of the var or
// returns the correct default.
// Environment variables are not supported on Windows CE.
-#ifndef _WIN32_WCE
+#if !GTEST_OS_WINDOWS_MOBILE
TEST(Int32FromEnvOrDieTest, ParsesAndReturnsValidValue) {
EXPECT_EQ(333, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "123");
@@ -1721,7 +2231,7 @@ TEST(Int32FromEnvOrDieTest, ParsesAndReturnsValidValue) {
SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "-123");
EXPECT_EQ(-123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
}
-#endif // _WIN32_WCE
+#endif // !GTEST_OS_WINDOWS_MOBILE
// Tests that Int32FromEnvOrDie() aborts with an error message
// if the variable is not an Int32.
@@ -1788,7 +2298,7 @@ TEST_F(ShouldShardTest, ReturnsFalseWhenTotalShardIsOne) {
// Tests that sharding is enabled if total_shards > 1 and
// we are not in a death test subprocess.
// Environment variables are not supported on Windows CE.
-#ifndef _WIN32_WCE
+#if !GTEST_OS_WINDOWS_MOBILE
TEST_F(ShouldShardTest, WorksWhenShardEnvVarsAreValid) {
SetEnv(index_var_, "4");
SetEnv(total_var_, "22");
@@ -1805,7 +2315,7 @@ TEST_F(ShouldShardTest, WorksWhenShardEnvVarsAreValid) {
EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
}
-#endif // _WIN32_WCE
+#endif // !GTEST_OS_WINDOWS_MOBILE
// Tests that we exit in error if the sharding values are not valid.
@@ -3151,9 +3661,9 @@ TEST_F(NoFatalFailureTest, AssertNoFatalFailureOnFatalFailure) {
DoAssertNoFatalFailureOnFails();
}
ASSERT_EQ(2, gtest_failures.size());
- EXPECT_EQ(testing::TPRT_FATAL_FAILURE,
+ EXPECT_EQ(TestPartResult::kFatalFailure,
gtest_failures.GetTestPartResult(0).type());
- EXPECT_EQ(testing::TPRT_FATAL_FAILURE,
+ EXPECT_EQ(TestPartResult::kFatalFailure,
gtest_failures.GetTestPartResult(1).type());
EXPECT_PRED_FORMAT2(testing::IsSubstring, "some fatal failure",
gtest_failures.GetTestPartResult(0).message());
@@ -3168,11 +3678,11 @@ TEST_F(NoFatalFailureTest, ExpectNoFatalFailureOnFatalFailure) {
DoExpectNoFatalFailureOnFails();
}
ASSERT_EQ(3, gtest_failures.size());
- EXPECT_EQ(testing::TPRT_FATAL_FAILURE,
+ EXPECT_EQ(TestPartResult::kFatalFailure,
gtest_failures.GetTestPartResult(0).type());
- EXPECT_EQ(testing::TPRT_NONFATAL_FAILURE,
+ EXPECT_EQ(TestPartResult::kNonFatalFailure,
gtest_failures.GetTestPartResult(1).type());
- EXPECT_EQ(testing::TPRT_NONFATAL_FAILURE,
+ EXPECT_EQ(TestPartResult::kNonFatalFailure,
gtest_failures.GetTestPartResult(2).type());
EXPECT_PRED_FORMAT2(testing::IsSubstring, "some fatal failure",
gtest_failures.GetTestPartResult(0).message());
@@ -3189,9 +3699,9 @@ TEST_F(NoFatalFailureTest, MessageIsStreamable) {
EXPECT_NO_FATAL_FAILURE(FAIL() << "foo") << "my message";
}
ASSERT_EQ(2, gtest_failures.size());
- EXPECT_EQ(testing::TPRT_NONFATAL_FAILURE,
+ EXPECT_EQ(TestPartResult::kNonFatalFailure,
gtest_failures.GetTestPartResult(0).type());
- EXPECT_EQ(testing::TPRT_NONFATAL_FAILURE,
+ EXPECT_EQ(TestPartResult::kNonFatalFailure,
gtest_failures.GetTestPartResult(1).type());
EXPECT_PRED_FORMAT2(testing::IsSubstring, "foo",
gtest_failures.GetTestPartResult(0).message());
@@ -3651,19 +4161,19 @@ TEST(HRESULTAssertionTest, Streaming) {
// Tests that the assertion macros behave like single statements.
TEST(AssertionSyntaxTest, BasicAssertionsBehavesLikeSingleStatement) {
- if (false)
+ if (AlwaysFalse())
ASSERT_TRUE(false) << "This should never be executed; "
"It's a compilation test only.";
- if (true)
+ if (AlwaysTrue())
EXPECT_FALSE(false);
else
; // NOLINT
- if (false)
+ if (AlwaysFalse())
ASSERT_LT(1, 3);
- if (false)
+ if (AlwaysFalse())
; // NOLINT
else
EXPECT_GT(3, 2) << "";
@@ -3685,26 +4195,26 @@ TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
}
TEST(AssertionSyntaxTest, ExceptionAssertionsBehavesLikeSingleStatement) {
- if (false)
+ if (AlwaysFalse())
EXPECT_THROW(ThrowNothing(), bool);
- if (true)
+ if (AlwaysTrue())
EXPECT_THROW(ThrowAnInteger(), int);
else
; // NOLINT
- if (false)
+ if (AlwaysFalse())
EXPECT_NO_THROW(ThrowAnInteger());
- if (true)
+ if (AlwaysTrue())
EXPECT_NO_THROW(ThrowNothing());
else
; // NOLINT
- if (false)
+ if (AlwaysFalse())
EXPECT_ANY_THROW(ThrowNothing());
- if (true)
+ if (AlwaysTrue())
EXPECT_ANY_THROW(ThrowAnInteger());
else
; // NOLINT
@@ -3712,23 +4222,23 @@ TEST(AssertionSyntaxTest, ExceptionAssertionsBehavesLikeSingleStatement) {
#endif // GTEST_HAS_EXCEPTIONS
TEST(AssertionSyntaxTest, NoFatalFailureAssertionsBehavesLikeSingleStatement) {
- if (false)
+ if (AlwaysFalse())
EXPECT_NO_FATAL_FAILURE(FAIL()) << "This should never be executed. "
<< "It's a compilation test only.";
else
; // NOLINT
- if (false)
+ if (AlwaysFalse())
ASSERT_NO_FATAL_FAILURE(FAIL()) << "";
else
; // NOLINT
- if (true)
+ if (AlwaysTrue())
EXPECT_NO_FATAL_FAILURE(SUCCEED());
else
; // NOLINT
- if (false)
+ if (AlwaysFalse())
; // NOLINT
else
ASSERT_NO_FATAL_FAILURE(SUCCEED());
@@ -6018,3 +6528,320 @@ TEST(HasFailureTest, WorksOutsideOfTestBody2) {
ClearCurrentTestPartResults();
EXPECT_TRUE(has_failure);
}
+
+class TestListener : public EmptyTestEventListener {
+ public:
+ TestListener() : on_start_counter_(NULL), is_destroyed_(NULL) {}
+ TestListener(int* on_start_counter, bool* is_destroyed)
+ : on_start_counter_(on_start_counter),
+ is_destroyed_(is_destroyed) {}
+
+ virtual ~TestListener() {
+ if (is_destroyed_)
+ *is_destroyed_ = true;
+ }
+
+ protected:
+ virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {
+ if (on_start_counter_ != NULL)
+ (*on_start_counter_)++;
+ }
+
+ private:
+ int* on_start_counter_;
+ bool* is_destroyed_;
+};
+
+// Tests the constructor.
+TEST(TestEventListenersTest, ConstructionWorks) {
+ TestEventListeners listeners;
+
+ EXPECT_TRUE(TestEventListenersAccessor::GetRepeater(&listeners) != NULL);
+ EXPECT_TRUE(listeners.default_result_printer() == NULL);
+ EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+}
+
+// Tests that the TestEventListeners destructor deletes all the listeners it
+// owns.
+TEST(TestEventListenersTest, DestructionWorks) {
+ bool default_result_printer_is_destroyed = false;
+ bool default_xml_printer_is_destroyed = false;
+ bool extra_listener_is_destroyed = false;
+ TestListener* default_result_printer = new TestListener(
+ NULL, &default_result_printer_is_destroyed);
+ TestListener* default_xml_printer = new TestListener(
+ NULL, &default_xml_printer_is_destroyed);
+ TestListener* extra_listener = new TestListener(
+ NULL, &extra_listener_is_destroyed);
+
+ {
+ TestEventListeners listeners;
+ TestEventListenersAccessor::SetDefaultResultPrinter(&listeners,
+ default_result_printer);
+ TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners,
+ default_xml_printer);
+ listeners.Append(extra_listener);
+ }
+ EXPECT_TRUE(default_result_printer_is_destroyed);
+ EXPECT_TRUE(default_xml_printer_is_destroyed);
+ EXPECT_TRUE(extra_listener_is_destroyed);
+}
+
+// Tests that a listener Append'ed to a TestEventListeners list starts
+// receiving events.
+TEST(TestEventListenersTest, Append) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+ {
+ TestEventListeners listeners;
+ listeners.Append(listener);
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(1, on_start_counter);
+ }
+ EXPECT_TRUE(is_destroyed);
+}
+
+// Tests that listeners receive events in the order they were appended to
+// the list, except for *End requests, which must be received in the reverse
+// order.
+class SequenceTestingListener : public EmptyTestEventListener {
+ public:
+ SequenceTestingListener(Vector<String>* vector, const char* id)
+ : vector_(vector), id_(id) {}
+
+ protected:
+ virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {
+ vector_->PushBack(GetEventDescription("OnTestProgramStart"));
+ }
+
+ virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {
+ vector_->PushBack(GetEventDescription("OnTestProgramEnd"));
+ }
+
+ virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+ int /*iteration*/) {
+ vector_->PushBack(GetEventDescription("OnTestIterationStart"));
+ }
+
+ virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+ int /*iteration*/) {
+ vector_->PushBack(GetEventDescription("OnTestIterationEnd"));
+ }
+
+ private:
+ String GetEventDescription(const char* method) {
+ Message message;
+ message << id_ << "." << method;
+ return message.GetString();
+ }
+
+ Vector<String>* vector_;
+ const char* const id_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(SequenceTestingListener);
+};
+
+TEST(EventListenerTest, AppendKeepsOrder) {
+ Vector<String> vec;
+ TestEventListeners listeners;
+ listeners.Append(new SequenceTestingListener(&vec, "1st"));
+ listeners.Append(new SequenceTestingListener(&vec, "2nd"));
+ listeners.Append(new SequenceTestingListener(&vec, "3rd"));
+
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+ *UnitTest::GetInstance());
+ ASSERT_EQ(3, vec.size());
+ EXPECT_STREQ("1st.OnTestProgramStart", vec.GetElement(0).c_str());
+ EXPECT_STREQ("2nd.OnTestProgramStart", vec.GetElement(1).c_str());
+ EXPECT_STREQ("3rd.OnTestProgramStart", vec.GetElement(2).c_str());
+
+ vec.Clear();
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramEnd(
+ *UnitTest::GetInstance());
+ ASSERT_EQ(3, vec.size());
+ EXPECT_STREQ("3rd.OnTestProgramEnd", vec.GetElement(0).c_str());
+ EXPECT_STREQ("2nd.OnTestProgramEnd", vec.GetElement(1).c_str());
+ EXPECT_STREQ("1st.OnTestProgramEnd", vec.GetElement(2).c_str());
+
+ vec.Clear();
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestIterationStart(
+ *UnitTest::GetInstance(), 0);
+ ASSERT_EQ(3, vec.size());
+ EXPECT_STREQ("1st.OnTestIterationStart", vec.GetElement(0).c_str());
+ EXPECT_STREQ("2nd.OnTestIterationStart", vec.GetElement(1).c_str());
+ EXPECT_STREQ("3rd.OnTestIterationStart", vec.GetElement(2).c_str());
+
+ vec.Clear();
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestIterationEnd(
+ *UnitTest::GetInstance(), 0);
+ ASSERT_EQ(3, vec.size());
+ EXPECT_STREQ("3rd.OnTestIterationEnd", vec.GetElement(0).c_str());
+ EXPECT_STREQ("2nd.OnTestIterationEnd", vec.GetElement(1).c_str());
+ EXPECT_STREQ("1st.OnTestIterationEnd", vec.GetElement(2).c_str());
+}
+
+// Tests that a listener removed from a TestEventListeners list stops receiving
+// events and is not deleted when the list is destroyed.
+TEST(TestEventListenersTest, Release) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ // Although Append passes the ownership of this object to the list,
+ // the following calls release it, and we need to delete it before the
+ // test ends.
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+ {
+ TestEventListeners listeners;
+ listeners.Append(listener);
+ EXPECT_EQ(listener, listeners.Release(listener));
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+ *UnitTest::GetInstance());
+ EXPECT_TRUE(listeners.Release(listener) == NULL);
+ }
+ EXPECT_EQ(0, on_start_counter);
+ EXPECT_FALSE(is_destroyed);
+ delete listener;
+}
+
+// Tests that no events are forwarded when event forwarding is disabled.
+TEST(EventListenerTest, SuppressEventForwarding) {
+ int on_start_counter = 0;
+ TestListener* listener = new TestListener(&on_start_counter, NULL);
+
+ TestEventListeners listeners;
+ listeners.Append(listener);
+ ASSERT_TRUE(TestEventListenersAccessor::EventForwardingEnabled(listeners));
+ TestEventListenersAccessor::SuppressEventForwarding(&listeners);
+ ASSERT_FALSE(TestEventListenersAccessor::EventForwardingEnabled(listeners));
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(0, on_start_counter);
+}
+
+// Tests that events generated by Google Test are not forwarded in
+// death test subprocesses.
+TEST(EventListenerDeathTest, EventsNotForwardedInDeathTestSubprecesses) {
+ EXPECT_DEATH_IF_SUPPORTED({
+ GTEST_CHECK_(TestEventListenersAccessor::EventForwardingEnabled(
+ *GetUnitTestImpl()->listeners())) << "expected failure";},
+ "expected failure");
+}
+
+// Tests that a listener installed via SetDefaultResultPrinter() starts
+// receiving events and is returned via default_result_printer() and that
+// the previous default_result_printer is removed from the list and deleted.
+TEST(EventListenerTest, default_result_printer) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+
+ TestEventListeners listeners;
+ TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
+
+ EXPECT_EQ(listener, listeners.default_result_printer());
+
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+ *UnitTest::GetInstance());
+
+ EXPECT_EQ(1, on_start_counter);
+
+ // Replacing default_result_printer with something else should remove it
+ // from the list and destroy it.
+ TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, NULL);
+
+ EXPECT_TRUE(listeners.default_result_printer() == NULL);
+ EXPECT_TRUE(is_destroyed);
+
+ // After broadcasting an event the counter is still the same, indicating
+ // the listener is not in the list anymore.
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(1, on_start_counter);
+}
+
+// Tests that the default_result_printer listener stops receiving events
+// when removed via Release and that is not owned by the list anymore.
+TEST(EventListenerTest, RemovingDefaultResultPrinterWorks) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ // Although Append passes the ownership of this object to the list,
+ // the following calls release it, and we need to delete it before the
+ // test ends.
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+ {
+ TestEventListeners listeners;
+ TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
+
+ EXPECT_EQ(listener, listeners.Release(listener));
+ EXPECT_TRUE(listeners.default_result_printer() == NULL);
+ EXPECT_FALSE(is_destroyed);
+
+ // Broadcasting events now should not affect default_result_printer.
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(0, on_start_counter);
+ }
+ // Destroying the list should not affect the listener now, too.
+ EXPECT_FALSE(is_destroyed);
+ delete listener;
+}
+
+// Tests that a listener installed via SetDefaultXmlGenerator() starts
+// receiving events and is returned via default_xml_generator() and that
+// the previous default_xml_generator is removed from the list and deleted.
+TEST(EventListenerTest, default_xml_generator) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+
+ TestEventListeners listeners;
+ TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
+
+ EXPECT_EQ(listener, listeners.default_xml_generator());
+
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+ *UnitTest::GetInstance());
+
+ EXPECT_EQ(1, on_start_counter);
+
+ // Replacing default_xml_generator with something else should remove it
+ // from the list and destroy it.
+ TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, NULL);
+
+ EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+ EXPECT_TRUE(is_destroyed);
+
+ // After broadcasting an event the counter is still the same, indicating
+ // the listener is not in the list anymore.
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(1, on_start_counter);
+}
+
+// Tests that the default_xml_generator listener stops receiving events
+// when removed via Release and that is not owned by the list anymore.
+TEST(EventListenerTest, RemovingDefaultXmlGeneratorWorks) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ // Although Append passes the ownership of this object to the list,
+ // the following calls release it, and we need to delete it before the
+ // test ends.
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+ {
+ TestEventListeners listeners;
+ TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
+
+ EXPECT_EQ(listener, listeners.Release(listener));
+ EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+ EXPECT_FALSE(is_destroyed);
+
+ // Broadcasting events now should not affect default_xml_generator.
+ TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(0, on_start_counter);
+ }
+ // Destroying the list should not affect the listener now, too.
+ EXPECT_FALSE(is_destroyed);
+ delete listener;
+}