aboutsummaryrefslogtreecommitdiffstats
path: root/gtest/test
diff options
context:
space:
mode:
authorWink Saville <wink@google.com>2010-05-29 13:00:38 -0700
committerWink Saville <wink@google.com>2010-05-29 13:00:38 -0700
commitd0332953cda33fb4f8e24ebff9c49159b69c43d6 (patch)
tree81612e8b12f590310aeb0ebf1da37b304eb7baa6 /gtest/test
parentede38fe9b9f93888e6e41afc7abb09525f44da95 (diff)
downloadexternal_protobuf-d0332953cda33fb4f8e24ebff9c49159b69c43d6.zip
external_protobuf-d0332953cda33fb4f8e24ebff9c49159b69c43d6.tar.gz
external_protobuf-d0332953cda33fb4f8e24ebff9c49159b69c43d6.tar.bz2
Add protobuf 2.3.0 sources
This is the contents of protobuf-2.3.0.tar.bz2 from http://code.google.com/p/protobuf/downloads/list. Change-Id: Idfde09ce7ef5ac027b07ee83f2674fbbed5c30b2
Diffstat (limited to 'gtest/test')
-rw-r--r--gtest/test/gtest-death-test_test.cc121
-rw-r--r--gtest/test/gtest-filepath_test.cc23
-rw-r--r--gtest/test/gtest-listener_test.cc322
-rw-r--r--gtest/test/gtest-options_test.cc8
-rw-r--r--gtest/test/gtest-port_test.cc13
-rw-r--r--gtest/test/gtest-test-part_test.cc28
-rw-r--r--gtest/test/gtest-typed-test_test.cc22
-rw-r--r--gtest/test/gtest-unittest-api_test.cc66
-rwxr-xr-xgtest/test/gtest_env_var_test.py2
-rw-r--r--gtest/test/gtest_filter_unittest_.cc10
-rw-r--r--gtest/test/gtest_repeat_test.cc10
-rwxr-xr-xgtest/test/gtest_shuffle_test.py331
-rw-r--r--gtest/test/gtest_shuffle_test_.cc104
-rw-r--r--gtest/test/gtest_stress_test.cc1
-rw-r--r--gtest/test/gtest_unittest.cc983
-rwxr-xr-xgtest/test/gtest_xml_output_unittest.py49
-rw-r--r--gtest/test/gtest_xml_output_unittest_.cc25
-rwxr-xr-xgtest/test/gtest_xml_test_utils.py48
18 files changed, 1936 insertions, 230 deletions
diff --git a/gtest/test/gtest-death-test_test.cc b/gtest/test/gtest-death-test_test.cc
index 1881139..288c70a 100644
--- a/gtest/test/gtest-death-test_test.cc
+++ b/gtest/test/gtest-death-test_test.cc
@@ -35,6 +35,9 @@
#include <gtest/gtest.h>
#include <gtest/internal/gtest-filepath.h>
+using testing::internal::AlwaysFalse;
+using testing::internal::AlwaysTrue;
+
#if GTEST_HAS_DEATH_TEST
#if GTEST_OS_WINDOWS
@@ -143,7 +146,7 @@ class MayDie {
// A member function that may die.
void MemberFunction() const {
if (should_die_) {
- GTEST_LOG_(FATAL, "death inside MayDie::MemberFunction().");
+ GTEST_LOG_(FATAL) << "death inside MayDie::MemberFunction().";
}
}
@@ -154,26 +157,26 @@ class MayDie {
// A global function that's expected to die.
void GlobalFunction() {
- GTEST_LOG_(FATAL, "death inside GlobalFunction().");
+ GTEST_LOG_(FATAL) << "death inside GlobalFunction().";
}
// A non-void function that's expected to die.
int NonVoidFunction() {
- GTEST_LOG_(FATAL, "death inside NonVoidFunction().");
+ GTEST_LOG_(FATAL) << "death inside NonVoidFunction().";
return 1;
}
// A unary function that may die.
void DieIf(bool should_die) {
if (should_die) {
- GTEST_LOG_(FATAL, "death inside DieIf().");
+ GTEST_LOG_(FATAL) << "death inside DieIf().";
}
}
// A binary function that may die.
bool DieIfLessThan(int x, int y) {
if (x < y) {
- GTEST_LOG_(FATAL, "death inside DieIfLessThan().");
+ GTEST_LOG_(FATAL) << "death inside DieIfLessThan().";
}
return true;
}
@@ -188,7 +191,7 @@ void DeathTestSubroutine() {
int DieInDebugElse12(int* sideeffect) {
if (sideeffect) *sideeffect = 12;
#ifndef NDEBUG
- GTEST_LOG_(FATAL, "debug death inside DieInDebugElse12()");
+ GTEST_LOG_(FATAL) << "debug death inside DieInDebugElse12()";
#endif // NDEBUG
return 12;
}
@@ -271,28 +274,28 @@ TEST(ExitStatusPredicateTest, KilledBySignal) {
// be followed by operator<<, and that in either case the complete text
// comprises only a single C++ statement.
TEST_F(TestForDeathTest, SingleStatement) {
- if (false)
+ if (AlwaysFalse())
// This would fail if executed; this is a compilation test only
ASSERT_DEATH(return, "");
- if (true)
+ if (AlwaysTrue())
EXPECT_DEATH(_exit(1), "");
else
// This empty "else" branch is meant to ensure that EXPECT_DEATH
// doesn't expand into an "if" statement without an "else"
;
- if (false)
+ if (AlwaysFalse())
ASSERT_DEATH(return, "") << "did not die";
- if (false)
+ if (AlwaysFalse())
;
else
EXPECT_DEATH(_exit(1), "") << 1 << 2 << 3;
}
void DieWithEmbeddedNul() {
- fprintf(stderr, "Hello%cworld.\n", '\0');
+ fprintf(stderr, "Hello%cmy null world.\n", '\0');
fflush(stderr);
_exit(1);
}
@@ -303,8 +306,8 @@ void DieWithEmbeddedNul() {
TEST_F(TestForDeathTest, EmbeddedNulInMessage) {
// TODO(wan@google.com): <regex.h> doesn't support matching strings
// with embedded NUL characters - find a way to workaround it.
- EXPECT_DEATH(DieWithEmbeddedNul(), "w.*ld");
- ASSERT_DEATH(DieWithEmbeddedNul(), "w.*ld");
+ EXPECT_DEATH(DieWithEmbeddedNul(), "my null world");
+ ASSERT_DEATH(DieWithEmbeddedNul(), "my null world");
}
#endif // GTEST_USES_PCRE
@@ -656,7 +659,11 @@ static void TestExitMacros() {
EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
ASSERT_EXIT(_exit(42), testing::ExitedWithCode(42), "");
-#if GTEST_OS_WINDOWS
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
+ // MinGW (as of MinGW 5.1.6 and MSYS 1.0.11) does not tag crashed
+ // processes with non-zero exit code and does not honor calls to
+ // SetErrorMode(SEM_NOGPFAULTERRORBOX) that are supposed to suppress
+ // error pop-ups.
EXPECT_EXIT({
testing::GTEST_FLAG(catch_exceptions) = false;
*static_cast<int*>(NULL) = 1;
@@ -668,7 +675,9 @@ static void TestExitMacros() {
*static_cast<int*>(NULL) = 1;
}, testing::ExitedWithCode(0), "") << "This failure is expected.";
}, "This failure is expected.");
+#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
+#if GTEST_OS_WINDOWS
// Of all signals effects on the process exit code, only those of SIGABRT
// are documented on Windows.
// See http://msdn.microsoft.com/en-us/library/dwwzkt4c(VS.71).aspx.
@@ -824,9 +833,10 @@ void MockDeathTestFactory::SetParameters(bool create,
// Sets test to NULL (if create_ is false) or to the address of a new
// MockDeathTest object with parameters taken from the last call
// to SetParameters (if create_ is true). Always returns true.
-bool MockDeathTestFactory::Create(const char* statement,
- const ::testing::internal::RE* regex,
- const char* file, int line,
+bool MockDeathTestFactory::Create(const char* /*statement*/,
+ const ::testing::internal::RE* /*regex*/,
+ const char* /*file*/,
+ int /*line*/,
DeathTest** test) {
test_deleted_ = false;
if (create_) {
@@ -1136,7 +1146,7 @@ using testing::internal::GetCapturedStderr;
using testing::internal::String;
// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED are still
-// defined but do not rigger failures when death tests are not available on
+// defined but do not trigger failures when death tests are not available on
// the system.
TEST(ConditionalDeathMacrosTest, WarnsWhenDeathTestsNotAvailable) {
// Empty statement will not crash, but that should not trigger a failure
@@ -1148,16 +1158,89 @@ TEST(ConditionalDeathMacrosTest, WarnsWhenDeathTestsNotAvailable) {
"Death tests are not supported on this platform"));
ASSERT_TRUE(NULL != strstr(output.c_str(), ";"));
+ // The streamed message should not be printed as there is no test failure.
+ CaptureStderr();
+ EXPECT_DEATH_IF_SUPPORTED(;, "") << "streamed message";
+ output = GetCapturedStderr();
+ ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message"));
+
CaptureStderr();
- ASSERT_DEATH_IF_SUPPORTED(;, "");
+ ASSERT_DEATH_IF_SUPPORTED(;, ""); // NOLINT
output = GetCapturedStderr();
ASSERT_TRUE(NULL != strstr(output.c_str(),
"Death tests are not supported on this platform"));
ASSERT_TRUE(NULL != strstr(output.c_str(), ";"));
+
+ CaptureStderr();
+ ASSERT_DEATH_IF_SUPPORTED(;, "") << "streamed message"; // NOLINT
+ output = GetCapturedStderr();
+ ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message"));
+}
+
+void FuncWithAssert(int* n) {
+ ASSERT_DEATH_IF_SUPPORTED(return;, "");
+ (*n)++;
}
+// Tests that ASSERT_DEATH_IF_SUPPORTED does not return from the current
+// function (as ASSERT_DEATH does) if death tests are not supported.
+TEST(ConditionalDeathMacrosTest, AssertDeatDoesNotReturnhIfUnsupported) {
+ int n = 0;
+ FuncWithAssert(&n);
+ EXPECT_EQ(1, n);
+}
#endif // GTEST_HAS_DEATH_TEST
+// Tests that the death test macros expand to code which may or may not
+// be followed by operator<<, and that in either case the complete text
+// comprises only a single C++ statement.
+//
+// The syntax should work whether death tests are available or not.
+TEST(ConditionalDeathMacrosSyntaxDeathTest, SingleStatement) {
+ if (AlwaysFalse())
+ // This would fail if executed; this is a compilation test only
+ ASSERT_DEATH_IF_SUPPORTED(return, "");
+
+ if (AlwaysTrue())
+ EXPECT_DEATH_IF_SUPPORTED(_exit(1), "");
+ else
+ // This empty "else" branch is meant to ensure that EXPECT_DEATH
+ // doesn't expand into an "if" statement without an "else"
+ ; // NOLINT
+
+ if (AlwaysFalse())
+ ASSERT_DEATH_IF_SUPPORTED(return, "") << "did not die";
+
+ if (AlwaysFalse())
+ ; // NOLINT
+ else
+ EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << 1 << 2 << 3;
+}
+
+// Tests that conditional death test macros expand to code which interacts
+// well with switch statements.
+TEST(ConditionalDeathMacrosSyntaxDeathTest, SwitchStatement) {
+// Microsoft compiler usually complains about switch statements without
+// case labels. We suppress that warning for this test.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4065)
+#endif // _MSC_VER
+
+ switch (0)
+ default:
+ ASSERT_DEATH_IF_SUPPORTED(_exit(1), "")
+ << "exit in default switch handler";
+
+ switch (0)
+ case 0:
+ EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << "exit in switch case";
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+}
+
// Tests that a test case whose name ends with "DeathTest" works fine
// on Windows.
TEST(NotADeathTest, Test) {
diff --git a/gtest/test/gtest-filepath_test.cc b/gtest/test/gtest-filepath_test.cc
index adf9746..5bc4daf 100644
--- a/gtest/test/gtest-filepath_test.cc
+++ b/gtest/test/gtest-filepath_test.cc
@@ -50,17 +50,17 @@
#include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
-#ifdef _WIN32_WCE
+#if GTEST_OS_WINDOWS_MOBILE
#include <windows.h> // NOLINT
#elif GTEST_OS_WINDOWS
#include <direct.h> // NOLINT
-#endif // _WIN32_WCE
+#endif // GTEST_OS_WINDOWS_MOBILE
namespace testing {
namespace internal {
namespace {
-#ifdef _WIN32_WCE
+#if GTEST_OS_WINDOWS_MOBILE
// TODO(wan@google.com): Move these to the POSIX adapter section in
// gtest-port.h.
@@ -81,9 +81,7 @@ int _rmdir(const char* path) {
return ret;
}
-#endif // _WIN32_WCE
-
-#ifndef _WIN32_WCE
+#else
TEST(GetCurrentDirTest, ReturnsCurrentDir) {
const FilePath original_dir = FilePath::GetCurrentDir();
@@ -103,7 +101,7 @@ TEST(GetCurrentDirTest, ReturnsCurrentDir) {
#endif
}
-#endif // _WIN32_WCE
+#endif // GTEST_OS_WINDOWS_MOBILE
TEST(IsEmptyTest, ReturnsTrueForEmptyPath) {
EXPECT_TRUE(FilePath("").IsEmpty());
@@ -156,7 +154,7 @@ TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileName) {
// RemoveFileName "" -> "./"
TEST(RemoveFileNameTest, EmptyName) {
-#ifdef _WIN32_WCE
+#if GTEST_OS_WINDOWS_MOBILE
// On Windows CE, we use the root as the current directory.
EXPECT_STREQ(GTEST_PATH_SEP_,
FilePath("").RemoveFileName().c_str());
@@ -344,12 +342,12 @@ TEST(DirectoryTest, RootOfWrongDriveDoesNotExists) {
}
#endif // GTEST_OS_WINDOWS
-#ifndef _WIN32_WCE
+#if !GTEST_OS_WINDOWS_MOBILE
// Windows CE _does_ consider an empty directory to exist.
TEST(DirectoryTest, EmptyPathDirectoryDoesNotExist) {
EXPECT_FALSE(FilePath("").DirectoryExists());
}
-#endif // ! _WIN32_WCE
+#endif // !GTEST_OS_WINDOWS_MOBILE
TEST(DirectoryTest, CurrentDirectoryExists) {
#if GTEST_OS_WINDOWS // We are on Windows.
@@ -449,9 +447,8 @@ class DirectoryCreationTest : public Test {
}
String TempDir() const {
-#ifdef _WIN32_WCE
+#if GTEST_OS_WINDOWS_MOBILE
return String("\\temp\\");
-
#elif GTEST_OS_WINDOWS
const char* temp_dir = posix::GetEnv("TEMP");
if (temp_dir == NULL || temp_dir[0] == '\0')
@@ -462,7 +459,7 @@ class DirectoryCreationTest : public Test {
return String::Format("%s\\", temp_dir);
#else
return String("/tmp/");
-#endif
+#endif // GTEST_OS_WINDOWS_MOBILE
}
void CreateTextFile(const char* filename) {
diff --git a/gtest/test/gtest-listener_test.cc b/gtest/test/gtest-listener_test.cc
new file mode 100644
index 0000000..f12f518
--- /dev/null
+++ b/gtest/test/gtest-listener_test.cc
@@ -0,0 +1,322 @@
+// Copyright 2009 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This file verifies Google Test event listeners receive events at the
+// right times.
+
+#include <gtest/gtest.h>
+
+// Indicates that this translation unit is part of Google Test's
+// implementation. It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h" // For Vector.
+#undef GTEST_IMPLEMENTATION_
+
+using ::testing::AddGlobalTestEnvironment;
+using ::testing::Environment;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestCase;
+using ::testing::TestEventListener;
+using ::testing::TestInfo;
+using ::testing::TestPartResult;
+using ::testing::UnitTest;
+using ::testing::internal::String;
+using ::testing::internal::Vector;
+
+// Used by tests to register their events.
+Vector<String>* g_events = NULL;
+
+namespace testing {
+namespace internal {
+
+class EventRecordingListener : public TestEventListener {
+ public:
+ EventRecordingListener(const char* name) : name_(name) {}
+
+ protected:
+ virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {
+ g_events->PushBack(GetFullMethodName("OnTestProgramStart"));
+ }
+
+ virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+ int iteration) {
+ Message message;
+ message << GetFullMethodName("OnTestIterationStart")
+ << "(" << iteration << ")";
+ g_events->PushBack(message.GetString());
+ }
+
+ virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {
+ g_events->PushBack(GetFullMethodName("OnEnvironmentsSetUpStart"));
+ }
+
+ virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {
+ g_events->PushBack(GetFullMethodName("OnEnvironmentsSetUpEnd"));
+ }
+
+ virtual void OnTestCaseStart(const TestCase& /*test_case*/) {
+ g_events->PushBack(GetFullMethodName("OnTestCaseStart"));
+ }
+
+ virtual void OnTestStart(const TestInfo& /*test_info*/) {
+ g_events->PushBack(GetFullMethodName("OnTestStart"));
+ }
+
+ virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {
+ g_events->PushBack(GetFullMethodName("OnTestPartResult"));
+ }
+
+ virtual void OnTestEnd(const TestInfo& /*test_info*/) {
+ g_events->PushBack(GetFullMethodName("OnTestEnd"));
+ }
+
+ virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {
+ g_events->PushBack(GetFullMethodName("OnTestCaseEnd"));
+ }
+
+ virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {
+ g_events->PushBack(GetFullMethodName("OnEnvironmentsTearDownStart"));
+ }
+
+ virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {
+ g_events->PushBack(GetFullMethodName("OnEnvironmentsTearDownEnd"));
+ }
+
+ virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+ int iteration) {
+ Message message;
+ message << GetFullMethodName("OnTestIterationEnd")
+ << "(" << iteration << ")";
+ g_events->PushBack(message.GetString());
+ }
+
+ virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {
+ g_events->PushBack(GetFullMethodName("OnTestProgramEnd"));
+ }
+
+ private:
+ String GetFullMethodName(const char* name) {
+ Message message;
+ message << name_ << "." << name;
+ return message.GetString();
+ }
+
+ String name_;
+};
+
+class EnvironmentInvocationCatcher : public Environment {
+ protected:
+ virtual void SetUp() {
+ g_events->PushBack(String("Environment::SetUp"));
+ }
+
+ virtual void TearDown() {
+ g_events->PushBack(String("Environment::TearDown"));
+ }
+};
+
+class ListenerTest : public Test {
+ protected:
+ static void SetUpTestCase() {
+ g_events->PushBack(String("ListenerTest::SetUpTestCase"));
+ }
+
+ static void TearDownTestCase() {
+ g_events->PushBack(String("ListenerTest::TearDownTestCase"));
+ }
+
+ virtual void SetUp() {
+ g_events->PushBack(String("ListenerTest::SetUp"));
+ }
+
+ virtual void TearDown() {
+ g_events->PushBack(String("ListenerTest::TearDown"));
+ }
+};
+
+TEST_F(ListenerTest, DoesFoo) {
+ // Test execution order within a test case is not guaranteed so we are not
+ // recording the test name.
+ g_events->PushBack(String("ListenerTest::* Test Body"));
+ SUCCEED(); // Triggers OnTestPartResult.
+}
+
+TEST_F(ListenerTest, DoesBar) {
+ g_events->PushBack(String("ListenerTest::* Test Body"));
+ SUCCEED(); // Triggers OnTestPartResult.
+}
+
+} // namespace internal
+
+} // namespace testing
+
+using ::testing::internal::EnvironmentInvocationCatcher;
+using ::testing::internal::EventRecordingListener;
+
+void VerifyResults(const Vector<String>& data,
+ const char* const* expected_data,
+ int expected_data_size) {
+ const int actual_size = data.size();
+ // If the following assertion fails, a new entry will be appended to
+ // data. Hence we save data.size() first.
+ EXPECT_EQ(expected_data_size, actual_size);
+
+ // Compares the common prefix.
+ const int shorter_size = expected_data_size <= actual_size ?
+ expected_data_size : actual_size;
+ int i = 0;
+ for (; i < shorter_size; ++i) {
+ ASSERT_STREQ(expected_data[i], data.GetElement(i).c_str())
+ << "at position " << i;
+ }
+
+ // Prints extra elements in the actual data.
+ for (; i < actual_size; ++i) {
+ printf(" Actual event #%d: %s\n", i, data.GetElement(i).c_str());
+ }
+}
+
+int main(int argc, char **argv) {
+ Vector<String> events;
+ g_events = &events;
+ InitGoogleTest(&argc, argv);
+
+ UnitTest::GetInstance()->listeners().Append(
+ new EventRecordingListener("1st"));
+ UnitTest::GetInstance()->listeners().Append(
+ new EventRecordingListener("2nd"));
+
+ AddGlobalTestEnvironment(new EnvironmentInvocationCatcher);
+
+ GTEST_CHECK_(events.size() == 0)
+ << "AddGlobalTestEnvironment should not generate any events itself.";
+
+ ::testing::GTEST_FLAG(repeat) = 2;
+ int ret_val = RUN_ALL_TESTS();
+
+ const char* const expected_events[] = {
+ "1st.OnTestProgramStart",
+ "2nd.OnTestProgramStart",
+ "1st.OnTestIterationStart(0)",
+ "2nd.OnTestIterationStart(0)",
+ "1st.OnEnvironmentsSetUpStart",
+ "2nd.OnEnvironmentsSetUpStart",
+ "Environment::SetUp",
+ "2nd.OnEnvironmentsSetUpEnd",
+ "1st.OnEnvironmentsSetUpEnd",
+ "1st.OnTestCaseStart",
+ "2nd.OnTestCaseStart",
+ "ListenerTest::SetUpTestCase",
+ "1st.OnTestStart",
+ "2nd.OnTestStart",
+ "ListenerTest::SetUp",
+ "ListenerTest::* Test Body",
+ "1st.OnTestPartResult",
+ "2nd.OnTestPartResult",
+ "ListenerTest::TearDown",
+ "2nd.OnTestEnd",
+ "1st.OnTestEnd",
+ "1st.OnTestStart",
+ "2nd.OnTestStart",
+ "ListenerTest::SetUp",
+ "ListenerTest::* Test Body",
+ "1st.OnTestPartResult",
+ "2nd.OnTestPartResult",
+ "ListenerTest::TearDown",
+ "2nd.OnTestEnd",
+ "1st.OnTestEnd",
+ "ListenerTest::TearDownTestCase",
+ "2nd.OnTestCaseEnd",
+ "1st.OnTestCaseEnd",
+ "1st.OnEnvironmentsTearDownStart",
+ "2nd.OnEnvironmentsTearDownStart",
+ "Environment::TearDown",
+ "2nd.OnEnvironmentsTearDownEnd",
+ "1st.OnEnvironmentsTearDownEnd",
+ "2nd.OnTestIterationEnd(0)",
+ "1st.OnTestIterationEnd(0)",
+ "1st.OnTestIterationStart(1)",
+ "2nd.OnTestIterationStart(1)",
+ "1st.OnEnvironmentsSetUpStart",
+ "2nd.OnEnvironmentsSetUpStart",
+ "Environment::SetUp",
+ "2nd.OnEnvironmentsSetUpEnd",
+ "1st.OnEnvironmentsSetUpEnd",
+ "1st.OnTestCaseStart",
+ "2nd.OnTestCaseStart",
+ "ListenerTest::SetUpTestCase",
+ "1st.OnTestStart",
+ "2nd.OnTestStart",
+ "ListenerTest::SetUp",
+ "ListenerTest::* Test Body",
+ "1st.OnTestPartResult",
+ "2nd.OnTestPartResult",
+ "ListenerTest::TearDown",
+ "2nd.OnTestEnd",
+ "1st.OnTestEnd",
+ "1st.OnTestStart",
+ "2nd.OnTestStart",
+ "ListenerTest::SetUp",
+ "ListenerTest::* Test Body",
+ "1st.OnTestPartResult",
+ "2nd.OnTestPartResult",
+ "ListenerTest::TearDown",
+ "2nd.OnTestEnd",
+ "1st.OnTestEnd",
+ "ListenerTest::TearDownTestCase",
+ "2nd.OnTestCaseEnd",
+ "1st.OnTestCaseEnd",
+ "1st.OnEnvironmentsTearDownStart",
+ "2nd.OnEnvironmentsTearDownStart",
+ "Environment::TearDown",
+ "2nd.OnEnvironmentsTearDownEnd",
+ "1st.OnEnvironmentsTearDownEnd",
+ "2nd.OnTestIterationEnd(1)",
+ "1st.OnTestIterationEnd(1)",
+ "2nd.OnTestProgramEnd",
+ "1st.OnTestProgramEnd"
+ };
+ VerifyResults(events,
+ expected_events,
+ sizeof(expected_events)/sizeof(expected_events[0]));
+
+ // We need to check manually for ad hoc test failures that happen after
+ // RUN_ALL_TESTS finishes.
+ if (UnitTest::GetInstance()->Failed())
+ ret_val = 1;
+
+ return ret_val;
+}
diff --git a/gtest/test/gtest-options_test.cc b/gtest/test/gtest-options_test.cc
index 43c6d22..31ae327 100644
--- a/gtest/test/gtest-options_test.cc
+++ b/gtest/test/gtest-options_test.cc
@@ -40,11 +40,11 @@
#include <gtest/gtest.h>
-#ifdef _WIN32_WCE
+#if GTEST_OS_WINDOWS_MOBILE
#include <windows.h>
#elif GTEST_OS_WINDOWS
#include <direct.h>
-#endif // _WIN32_WCE
+#endif // GTEST_OS_WINDOWS_MOBILE
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
@@ -130,7 +130,7 @@ TEST(XmlOutputTest, GetOutputFileFromDirectoryPath) {
TEST(OutputFileHelpersTest, GetCurrentExecutableName) {
const FilePath executable = GetCurrentExecutableName();
const char* const exe_str = executable.c_str();
-#if defined(_WIN32_WCE) || GTEST_OS_WINDOWS
+#if GTEST_OS_WINDOWS
ASSERT_TRUE(_strcmpi("gtest-options_test", exe_str) == 0 ||
_strcmpi("gtest-options-ex_test", exe_str) == 0 ||
_strcmpi("gtest_all_test", exe_str) == 0)
@@ -143,7 +143,7 @@ TEST(OutputFileHelpersTest, GetCurrentExecutableName) {
String(exe_str) == "gtest_all_test" ||
String(exe_str) == "lt-gtest_all_test")
<< "GetCurrentExecutableName() returns " << exe_str;
-#endif
+#endif // GTEST_OS_WINDOWS
}
class XmlOutputChangeDirTest : public Test {
diff --git a/gtest/test/gtest-port_test.cc b/gtest/test/gtest-port_test.cc
index d980b7c..df59f9e 100644
--- a/gtest/test/gtest-port_test.cc
+++ b/gtest/test/gtest-port_test.cc
@@ -54,16 +54,16 @@ namespace testing {
namespace internal {
TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) {
- if (false)
+ if (AlwaysFalse())
GTEST_CHECK_(false) << "This should never be executed; "
"It's a compilation test only.";
- if (true)
+ if (AlwaysTrue())
GTEST_CHECK_(true);
else
; // NOLINT
- if (false)
+ if (AlwaysFalse())
; // NOLINT
else
GTEST_CHECK_(true) << "";
@@ -133,8 +133,6 @@ TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) {
}
#endif // GTEST_OS_MAC
-#if GTEST_HAS_DEATH_TEST
-
TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
const bool a_false_condition = false;
const char regex[] =
@@ -145,9 +143,12 @@ TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
#endif // _MSC_VER
".*a_false_condition.*Extra info.*";
- EXPECT_DEATH(GTEST_CHECK_(a_false_condition) << "Extra info", regex);
+ EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(a_false_condition) << "Extra info",
+ regex);
}
+#if GTEST_HAS_DEATH_TEST
+
TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
EXPECT_EXIT({
GTEST_CHECK_(true) << "Extra info";
diff --git a/gtest/test/gtest-test-part_test.cc b/gtest/test/gtest-test-part_test.cc
index 93fe156..403c184 100644
--- a/gtest/test/gtest-test-part_test.cc
+++ b/gtest/test/gtest-test-part_test.cc
@@ -38,10 +38,6 @@ using testing::Test;
using testing::TestPartResult;
using testing::TestPartResultArray;
-using testing::TPRT_FATAL_FAILURE;
-using testing::TPRT_NONFATAL_FAILURE;
-using testing::TPRT_SUCCESS;
-
namespace {
// Tests the TestPartResult class.
@@ -50,18 +46,18 @@ namespace {
class TestPartResultTest : public Test {
protected:
TestPartResultTest()
- : r1_(TPRT_SUCCESS, "foo/bar.cc", 10, "Success!"),
- r2_(TPRT_NONFATAL_FAILURE, "foo/bar.cc", -1, "Failure!"),
- r3_(TPRT_FATAL_FAILURE, NULL, -1, "Failure!") {}
+ : r1_(TestPartResult::kSuccess, "foo/bar.cc", 10, "Success!"),
+ r2_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure!"),
+ r3_(TestPartResult::kFatalFailure, NULL, -1, "Failure!") {}
TestPartResult r1_, r2_, r3_;
};
// Tests TestPartResult::type().
TEST_F(TestPartResultTest, type) {
- EXPECT_EQ(TPRT_SUCCESS, r1_.type());
- EXPECT_EQ(TPRT_NONFATAL_FAILURE, r2_.type());
- EXPECT_EQ(TPRT_FATAL_FAILURE, r3_.type());
+ EXPECT_EQ(TestPartResult::kSuccess, r1_.type());
+ EXPECT_EQ(TestPartResult::kNonFatalFailure, r2_.type());
+ EXPECT_EQ(TestPartResult::kFatalFailure, r3_.type());
}
// Tests TestPartResult::file_name().
@@ -114,8 +110,8 @@ TEST_F(TestPartResultTest, NonfatallyFailed) {
class TestPartResultArrayTest : public Test {
protected:
TestPartResultArrayTest()
- : r1_(TPRT_NONFATAL_FAILURE, "foo/bar.cc", -1, "Failure 1"),
- r2_(TPRT_FATAL_FAILURE, "foo/bar.cc", -1, "Failure 2") {}
+ : r1_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure 1"),
+ r2_(TestPartResult::kFatalFailure, "foo/bar.cc", -1, "Failure 2") {}
const TestPartResult r1_, r2_;
};
@@ -146,8 +142,6 @@ TEST_F(TestPartResultArrayTest, ContainsGivenResultsAfterTwoAppends) {
EXPECT_STREQ("Failure 2", results.GetTestPartResult(1).message());
}
-#if GTEST_HAS_DEATH_TEST
-
typedef TestPartResultArrayTest TestPartResultArrayDeathTest;
// Tests that the program dies when GetTestPartResult() is called with
@@ -156,12 +150,10 @@ TEST_F(TestPartResultArrayDeathTest, DiesWhenIndexIsOutOfBound) {
TestPartResultArray results;
results.Append(r1_);
- EXPECT_DEATH(results.GetTestPartResult(-1), "");
- EXPECT_DEATH(results.GetTestPartResult(1), "");
+ EXPECT_DEATH_IF_SUPPORTED(results.GetTestPartResult(-1), "");
+ EXPECT_DEATH_IF_SUPPORTED(results.GetTestPartResult(1), "");
}
-#endif // GTEST_HAS_DEATH_TEST
-
// TODO(mheule@google.com): Add a test for the class HasNewFatalFailureHelper.
} // namespace
diff --git a/gtest/test/gtest-typed-test_test.cc b/gtest/test/gtest-typed-test_test.cc
index 8e86ac8..4b6e971 100644
--- a/gtest/test/gtest-typed-test_test.cc
+++ b/gtest/test/gtest-typed-test_test.cc
@@ -29,8 +29,8 @@
//
// Author: wan@google.com (Zhanyong Wan)
-#include <list>
#include <set>
+#include <vector>
#include "test/gtest-typed-test_test.h"
#include <gtest/gtest.h>
@@ -57,7 +57,9 @@ class CommonTest : public Test {
// This 'protected:' is optional. There's no harm in making all
// members of this fixture class template public.
protected:
- typedef std::list<T> List;
+ // We used to use std::list here, but switched to std::vector since
+ // MSVC's <list> doesn't compile cleanly with /W4.
+ typedef std::vector<T> Vector;
typedef std::set<int> IntSet;
CommonTest() : value_(1) {}
@@ -99,7 +101,7 @@ TYPED_TEST(CommonTest, ValuesAreCorrect) {
// Typedefs in the fixture class template can be visited via the
// "typename TestFixture::" prefix.
- typename TestFixture::List empty;
+ typename TestFixture::Vector empty;
EXPECT_EQ(0U, empty.size());
typename TestFixture::IntSet empty2;
@@ -198,24 +200,22 @@ TEST_F(TypedTestCasePStateTest, IgnoresOrderAndSpaces) {
state_.VerifyRegisteredTestNames("foo.cc", 1, tests));
}
-#if GTEST_HAS_DEATH_TEST
-
typedef TypedTestCasePStateTest TypedTestCasePStateDeathTest;
TEST_F(TypedTestCasePStateDeathTest, DetectsDuplicates) {
- EXPECT_DEATH(
+ EXPECT_DEATH_IF_SUPPORTED(
state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, A, C"),
"foo\\.cc.1.?: Test A is listed more than once\\.");
}
TEST_F(TypedTestCasePStateDeathTest, DetectsExtraTest) {
- EXPECT_DEATH(
+ EXPECT_DEATH_IF_SUPPORTED(
state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, C, D"),
"foo\\.cc.1.?: No test named D can be found in this test case\\.");
}
TEST_F(TypedTestCasePStateDeathTest, DetectsMissedTest) {
- EXPECT_DEATH(
+ EXPECT_DEATH_IF_SUPPORTED(
state_.VerifyRegisteredTestNames("foo.cc", 1, "A, C"),
"foo\\.cc.1.?: You forgot to list test B\\.");
}
@@ -224,14 +224,12 @@ TEST_F(TypedTestCasePStateDeathTest, DetectsMissedTest) {
// a run-time error if the test case has been registered.
TEST_F(TypedTestCasePStateDeathTest, DetectsTestAfterRegistration) {
state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, C");
- EXPECT_DEATH(
+ EXPECT_DEATH_IF_SUPPORTED(
state_.AddTestName("foo.cc", 2, "FooTest", "D"),
"foo\\.cc.2.?: Test D must be defined before REGISTER_TYPED_TEST_CASE_P"
"\\(FooTest, \\.\\.\\.\\)\\.");
}
-#endif // GTEST_HAS_DEATH_TEST
-
// Tests that SetUpTestCase()/TearDownTestCase(), fixture ctor/dtor,
// and SetUp()/TearDown() work correctly in type-parameterized tests.
@@ -318,7 +316,7 @@ INSTANTIATE_TYPED_TEST_CASE_P(Double, TypedTestP2, Types<double>);
// Tests that the same type-parameterized test case can be
// instantiated in different translation units linked together.
// (ContainerTest is also instantiated in gtest-typed-test_test.cc.)
-typedef Types<std::list<double>, std::set<char> > MyContainers;
+typedef Types<std::vector<double>, std::set<char> > MyContainers;
INSTANTIATE_TYPED_TEST_CASE_P(My, ContainerTest, MyContainers);
// Tests that a type-parameterized test case can be defined and
diff --git a/gtest/test/gtest-unittest-api_test.cc b/gtest/test/gtest-unittest-api_test.cc
index 658e298..7e0f8f8 100644
--- a/gtest/test/gtest-unittest-api_test.cc
+++ b/gtest/test/gtest-unittest-api_test.cc
@@ -38,21 +38,7 @@
#include <string.h> // For strcmp.
#include <algorithm>
-using ::testing::AddGlobalTestEnvironment;
-using ::testing::Environment;
using ::testing::InitGoogleTest;
-using ::testing::Test;
-using ::testing::TestInfo;
-using ::testing::TestPartResult;
-using ::testing::UnitTest;
-using ::testing::internal::TestCase;
-using ::testing::internal::TestProperty;
-
-#if GTEST_HAS_TYPED_TEST
-using ::testing::Types;
-using ::testing::internal::GetTypeName;
-using ::testing::internal::String;
-#endif // GTEST_HAS_TYPED_TEST
namespace testing {
namespace internal {
@@ -64,20 +50,20 @@ struct LessByName {
}
};
-class UnitTestAccessor {
+class UnitTestHelper {
public:
// Returns the array of pointers to all test cases sorted by the test case
// name. The caller is responsible for deleting the array.
static TestCase const** const GetSortedTestCases() {
- UnitTest* unit_test = UnitTest::GetInstance();
+ UnitTest& unit_test = *UnitTest::GetInstance();
TestCase const** const test_cases =
- new const TestCase*[unit_test->total_test_case_count()];
+ new const TestCase*[unit_test.total_test_case_count()];
- for (int i = 0; i < unit_test->total_test_case_count(); ++i)
- test_cases[i] = unit_test->GetTestCase(i);
+ for (int i = 0; i < unit_test.total_test_case_count(); ++i)
+ test_cases[i] = unit_test.GetTestCase(i);
std::sort(test_cases,
- test_cases + unit_test->total_test_case_count(),
+ test_cases + unit_test.total_test_case_count(),
LessByName<TestCase>());
return test_cases;
}
@@ -85,9 +71,9 @@ class UnitTestAccessor {
// Returns the test case by its name. The caller doesn't own the returned
// pointer.
static const TestCase* FindTestCase(const char* name) {
- UnitTest* unit_test = UnitTest::GetInstance();
- for (int i = 0; i < unit_test->total_test_case_count(); ++i) {
- const TestCase* test_case = unit_test->GetTestCase(i);
+ UnitTest& unit_test = *UnitTest::GetInstance();
+ for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+ const TestCase* test_case = unit_test.GetTestCase(i);
if (0 == strcmp(test_case->name(), name))
return test_case;
}
@@ -104,19 +90,12 @@ class UnitTestAccessor {
for (int i = 0; i < test_case->total_test_count(); ++i)
tests[i] = test_case->GetTestInfo(i);
- std::sort(tests,
- tests + test_case->total_test_count(),
+ std::sort(tests, tests + test_case->total_test_count(),
LessByName<TestInfo>());
return tests;
}
};
-// TODO(vladl@google.com): Put tests into the internal namespace after
-// UnitTest methods are published.
-} // namespace internal
-
-using internal::UnitTestAccessor;
-
#if GTEST_HAS_TYPED_TEST
template <typename T> class TestCaseWithCommentTest : public Test {};
TYPED_TEST_CASE(TestCaseWithCommentTest, Types<int>);
@@ -147,7 +126,7 @@ TEST(ApiTest, UnitTestImmutableAccessorsWork) {
EXPECT_EQ(5 + kTypedTests, unit_test->total_test_count());
EXPECT_EQ(3 + kTypedTests, unit_test->test_to_run_count());
- const TestCase** const test_cases = UnitTestAccessor::GetSortedTestCases();
+ const TestCase** const test_cases = UnitTestHelper::GetSortedTestCases();
EXPECT_STREQ("ApiTest", test_cases[0]->name());
EXPECT_STREQ("DISABLED_Test", test_cases[1]->name());
@@ -165,7 +144,7 @@ TEST(ApiTest, UnitTestImmutableAccessorsWork) {
}
TEST(ApiTest, TestCaseImmutableAccessorsWork) {
- const TestCase* test_case = UnitTestAccessor::FindTestCase("ApiTest");
+ const TestCase* test_case = UnitTestHelper::FindTestCase("ApiTest");
ASSERT_TRUE(test_case != NULL);
EXPECT_STREQ("ApiTest", test_case->name());
@@ -175,7 +154,7 @@ TEST(ApiTest, TestCaseImmutableAccessorsWork) {
EXPECT_EQ(3, test_case->test_to_run_count());
ASSERT_EQ(4, test_case->total_test_count());
- const TestInfo** tests = UnitTestAccessor::GetSortedTests(test_case);
+ const TestInfo** tests = UnitTestHelper::GetSortedTests(test_case);
EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
EXPECT_STREQ("ApiTest", tests[0]->test_case_name());
@@ -205,7 +184,7 @@ TEST(ApiTest, TestCaseImmutableAccessorsWork) {
tests = NULL;
#if GTEST_HAS_TYPED_TEST
- test_case = UnitTestAccessor::FindTestCase("TestCaseWithCommentTest/0");
+ test_case = UnitTestHelper::FindTestCase("TestCaseWithCommentTest/0");
ASSERT_TRUE(test_case != NULL);
EXPECT_STREQ("TestCaseWithCommentTest/0", test_case->name());
@@ -215,7 +194,7 @@ TEST(ApiTest, TestCaseImmutableAccessorsWork) {
EXPECT_EQ(1, test_case->test_to_run_count());
ASSERT_EQ(1, test_case->total_test_count());
- tests = UnitTestAccessor::GetSortedTests(test_case);
+ tests = UnitTestHelper::GetSortedTests(test_case);
EXPECT_STREQ("Dummy", tests[0]->name());
EXPECT_STREQ("TestCaseWithCommentTest/0", tests[0]->test_case_name());
@@ -229,7 +208,7 @@ TEST(ApiTest, TestCaseImmutableAccessorsWork) {
}
TEST(ApiTest, TestCaseDisabledAccessorsWork) {
- const TestCase* test_case = UnitTestAccessor::FindTestCase("DISABLED_Test");
+ const TestCase* test_case = UnitTestHelper::FindTestCase("DISABLED_Test");
ASSERT_TRUE(test_case != NULL);
EXPECT_STREQ("DISABLED_Test", test_case->name());
@@ -265,7 +244,7 @@ class FinalSuccessChecker : public Environment {
EXPECT_FALSE(unit_test->Failed());
ASSERT_EQ(2 + kTypedTestCases, unit_test->total_test_case_count());
- const TestCase** const test_cases = UnitTestAccessor::GetSortedTestCases();
+ const TestCase** const test_cases = UnitTestHelper::GetSortedTestCases();
EXPECT_STREQ("ApiTest", test_cases[0]->name());
EXPECT_STREQ("", test_cases[0]->comment());
@@ -298,8 +277,8 @@ class FinalSuccessChecker : public Environment {
EXPECT_FALSE(test_cases[2]->Failed());
#endif // GTEST_HAS_TYPED_TEST
- const TestCase* test_case = UnitTestAccessor::FindTestCase("ApiTest");
- const TestInfo** tests = UnitTestAccessor::GetSortedTests(test_case);
+ const TestCase* test_case = UnitTestHelper::FindTestCase("ApiTest");
+ const TestInfo** tests = UnitTestHelper::GetSortedTests(test_case);
EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
EXPECT_STREQ("ApiTest", tests[0]->test_case_name());
EXPECT_FALSE(tests[0]->should_run());
@@ -334,8 +313,8 @@ class FinalSuccessChecker : public Environment {
delete[] tests;
#if GTEST_HAS_TYPED_TEST
- test_case = UnitTestAccessor::FindTestCase("TestCaseWithCommentTest/0");
- tests = UnitTestAccessor::GetSortedTests(test_case);
+ test_case = UnitTestHelper::FindTestCase("TestCaseWithCommentTest/0");
+ tests = UnitTestHelper::GetSortedTests(test_case);
EXPECT_STREQ("Dummy", tests[0]->name());
EXPECT_STREQ("TestCaseWithCommentTest/0", tests[0]->test_case_name());
@@ -352,12 +331,13 @@ class FinalSuccessChecker : public Environment {
}
};
+} // namespace internal
} // namespace testing
int main(int argc, char **argv) {
InitGoogleTest(&argc, argv);
- AddGlobalTestEnvironment(new testing::FinalSuccessChecker());
+ AddGlobalTestEnvironment(new testing::internal::FinalSuccessChecker());
return RUN_ALL_TESTS();
}
diff --git a/gtest/test/gtest_env_var_test.py b/gtest/test/gtest_env_var_test.py
index 19fd810..f8250d4 100755
--- a/gtest/test/gtest_env_var_test.py
+++ b/gtest/test/gtest_env_var_test.py
@@ -85,7 +85,7 @@ class GTestEnvVarTest(gtest_test_utils.TestCase):
TestFlag('break_on_failure', '1', '0')
TestFlag('color', 'yes', 'auto')
TestFlag('filter', 'FooTest.Bar', '*')
- TestFlag('output', 'tmp/foo.xml', '')
+ TestFlag('output', 'xml:tmp/foo.xml', '')
TestFlag('print_time', '0', '1')
TestFlag('repeat', '999', '1')
TestFlag('throw_on_failure', '1', '0')
diff --git a/gtest/test/gtest_filter_unittest_.cc b/gtest/test/gtest_filter_unittest_.cc
index 3cbddcf..325504f 100644
--- a/gtest/test/gtest_filter_unittest_.cc
+++ b/gtest/test/gtest_filter_unittest_.cc
@@ -92,19 +92,13 @@ TEST(BazTest, DISABLED_TestC) {
// Test case HasDeathTest
TEST(HasDeathTest, Test1) {
-#if GTEST_HAS_DEATH_TEST
- EXPECT_DEATH({exit(1);},
- ".*");
-#endif // GTEST_HAS_DEATH_TEST
+ EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*");
}
// We need at least two death tests to make sure that the all death tests
// aren't on the first shard.
TEST(HasDeathTest, Test2) {
-#if GTEST_HAS_DEATH_TEST
- EXPECT_DEATH({exit(1);},
- ".*");
-#endif // GTEST_HAS_DEATH_TEST
+ EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*");
}
// Test case FoobarTest
diff --git a/gtest/test/gtest_repeat_test.cc b/gtest/test/gtest_repeat_test.cc
index 39a0601..df6868b 100644
--- a/gtest/test/gtest_repeat_test.cc
+++ b/gtest/test/gtest_repeat_test.cc
@@ -64,14 +64,14 @@ namespace {
do {\
const int expected_val = (expected);\
const int actual_val = (actual);\
- if (expected_val != actual_val) {\
+ if (::testing::internal::IsTrue(expected_val != actual_val)) {\
::std::cout << "Value of: " #actual "\n"\
<< " Actual: " << actual_val << "\n"\
<< "Expected: " #expected "\n"\
<< "Which is: " << expected_val << "\n";\
abort();\
}\
- } while(false)
+ } while(::testing::internal::AlwaysFalse())
// Used for verifying that global environment set-up and tear-down are
@@ -112,13 +112,11 @@ int g_death_test_count = 0;
TEST(BarDeathTest, ThreadSafeAndFast) {
g_death_test_count++;
-#if GTEST_HAS_DEATH_TEST
GTEST_FLAG(death_test_style) = "threadsafe";
- EXPECT_DEATH(abort(), "");
+ EXPECT_DEATH_IF_SUPPORTED(abort(), "");
GTEST_FLAG(death_test_style) = "fast";
- EXPECT_DEATH(abort(), "");
-#endif // GTEST_HAS_DEATH_TEST
+ EXPECT_DEATH_IF_SUPPORTED(abort(), "");
}
#if GTEST_HAS_PARAM_TEST
diff --git a/gtest/test/gtest_shuffle_test.py b/gtest/test/gtest_shuffle_test.py
new file mode 100755
index 0000000..a870a01
--- /dev/null
+++ b/gtest/test/gtest_shuffle_test.py
@@ -0,0 +1,331 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 Google Inc. All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Verifies that test shuffling works."""
+
+__author__ = 'wan@google.com (Zhanyong Wan)'
+
+import os
+import gtest_test_utils
+
+# Command to run the gtest_shuffle_test_ program.
+COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_shuffle_test_')
+
+# The environment variables for test sharding.
+TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
+SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
+
+TEST_FILTER = 'A*.A:A*.B:C*'
+
+ALL_TESTS = []
+ACTIVE_TESTS = []
+FILTERED_TESTS = []
+SHARDED_TESTS = []
+
+SHUFFLED_ALL_TESTS = []
+SHUFFLED_ACTIVE_TESTS = []
+SHUFFLED_FILTERED_TESTS = []
+SHUFFLED_SHARDED_TESTS = []
+
+
+def AlsoRunDisabledTestsFlag():
+ return '--gtest_also_run_disabled_tests'
+
+
+def FilterFlag(test_filter):
+ return '--gtest_filter=%s' % (test_filter,)
+
+
+def RepeatFlag(n):
+ return '--gtest_repeat=%s' % (n,)
+
+
+def ShuffleFlag():
+ return '--gtest_shuffle'
+
+
+def RandomSeedFlag(n):
+ return '--gtest_random_seed=%s' % (n,)
+
+
+def RunAndReturnOutput(extra_env, args):
+ """Runs the test program and returns its output."""
+
+ try:
+ original_env = os.environ.copy()
+ os.environ.update(extra_env)
+ return gtest_test_utils.Subprocess([COMMAND] + args).output
+ finally:
+ for key in extra_env.iterkeys():
+ if key in original_env:
+ os.environ[key] = original_env[key]
+ else:
+ del os.environ[key]
+
+
+def GetTestsForAllIterations(extra_env, args):
+ """Runs the test program and returns a list of test lists.
+
+ Args:
+ extra_env: a map from environment variables to their values
+ args: command line flags to pass to gtest_shuffle_test_
+
+ Returns:
+ A list where the i-th element is the list of tests run in the i-th
+ test iteration.
+ """
+
+ test_iterations = []
+ for line in RunAndReturnOutput(extra_env, args).split('\n'):
+ if line.startswith('----'):
+ tests = []
+ test_iterations.append(tests)
+ elif line.strip():
+ tests.append(line.strip()) # 'TestCaseName.TestName'
+
+ return test_iterations
+
+
+def GetTestCases(tests):
+ """Returns a list of test cases in the given full test names.
+
+ Args:
+ tests: a list of full test names
+
+ Returns:
+ A list of test cases from 'tests', in their original order.
+ Consecutive duplicates are removed.
+ """
+
+ test_cases = []
+ for test in tests:
+ test_case = test.split('.')[0]
+ if not test_case in test_cases:
+ test_cases.append(test_case)
+
+ return test_cases
+
+
+def CalculateTestLists():
+ """Calculates the list of tests run under different flags."""
+
+ if not ALL_TESTS:
+ ALL_TESTS.extend(
+ GetTestsForAllIterations({}, [AlsoRunDisabledTestsFlag()])[0])
+
+ if not ACTIVE_TESTS:
+ ACTIVE_TESTS.extend(GetTestsForAllIterations({}, [])[0])
+
+ if not FILTERED_TESTS:
+ FILTERED_TESTS.extend(
+ GetTestsForAllIterations({}, [FilterFlag(TEST_FILTER)])[0])
+
+ if not SHARDED_TESTS:
+ SHARDED_TESTS.extend(
+ GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+ SHARD_INDEX_ENV_VAR: '1'},
+ [])[0])
+
+ if not SHUFFLED_ALL_TESTS:
+ SHUFFLED_ALL_TESTS.extend(GetTestsForAllIterations(
+ {}, [AlsoRunDisabledTestsFlag(), ShuffleFlag(), RandomSeedFlag(1)])[0])
+
+ if not SHUFFLED_ACTIVE_TESTS:
+ SHUFFLED_ACTIVE_TESTS.extend(GetTestsForAllIterations(
+ {}, [ShuffleFlag(), RandomSeedFlag(1)])[0])
+
+ if not SHUFFLED_FILTERED_TESTS:
+ SHUFFLED_FILTERED_TESTS.extend(GetTestsForAllIterations(
+ {}, [ShuffleFlag(), RandomSeedFlag(1), FilterFlag(TEST_FILTER)])[0])
+
+ if not SHUFFLED_SHARDED_TESTS:
+ SHUFFLED_SHARDED_TESTS.extend(
+ GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+ SHARD_INDEX_ENV_VAR: '1'},
+ [ShuffleFlag(), RandomSeedFlag(1)])[0])
+
+
+class GTestShuffleUnitTest(gtest_test_utils.TestCase):
+ """Tests test shuffling."""
+
+ def setUp(self):
+ CalculateTestLists()
+
+ def testShufflePreservesNumberOfTests(self):
+ self.assertEqual(len(ALL_TESTS), len(SHUFFLED_ALL_TESTS))
+ self.assertEqual(len(ACTIVE_TESTS), len(SHUFFLED_ACTIVE_TESTS))
+ self.assertEqual(len(FILTERED_TESTS), len(SHUFFLED_FILTERED_TESTS))
+ self.assertEqual(len(SHARDED_TESTS), len(SHUFFLED_SHARDED_TESTS))
+
+ def testShuffleChangesTestOrder(self):
+ self.assert_(SHUFFLED_ALL_TESTS != ALL_TESTS, SHUFFLED_ALL_TESTS)
+ self.assert_(SHUFFLED_ACTIVE_TESTS != ACTIVE_TESTS, SHUFFLED_ACTIVE_TESTS)
+ self.assert_(SHUFFLED_FILTERED_TESTS != FILTERED_TESTS,
+ SHUFFLED_FILTERED_TESTS)
+ self.assert_(SHUFFLED_SHARDED_TESTS != SHARDED_TESTS,
+ SHUFFLED_SHARDED_TESTS)
+
+ def testShuffleChangesTestCaseOrder(self):
+ self.assert_(GetTestCases(SHUFFLED_ALL_TESTS) != GetTestCases(ALL_TESTS),
+ GetTestCases(SHUFFLED_ALL_TESTS))
+ self.assert_(
+ GetTestCases(SHUFFLED_ACTIVE_TESTS) != GetTestCases(ACTIVE_TESTS),
+ GetTestCases(SHUFFLED_ACTIVE_TESTS))
+ self.assert_(
+ GetTestCases(SHUFFLED_FILTERED_TESTS) != GetTestCases(FILTERED_TESTS),
+ GetTestCases(SHUFFLED_FILTERED_TESTS))
+ self.assert_(
+ GetTestCases(SHUFFLED_SHARDED_TESTS) != GetTestCases(SHARDED_TESTS),
+ GetTestCases(SHUFFLED_SHARDED_TESTS))
+
+ def testShuffleDoesNotRepeatTest(self):
+ for test in SHUFFLED_ALL_TESTS:
+ self.assertEqual(1, SHUFFLED_ALL_TESTS.count(test),
+ '%s appears more than once' % (test,))
+ for test in SHUFFLED_ACTIVE_TESTS:
+ self.assertEqual(1, SHUFFLED_ACTIVE_TESTS.count(test),
+ '%s appears more than once' % (test,))
+ for test in SHUFFLED_FILTERED_TESTS:
+ self.assertEqual(1, SHUFFLED_FILTERED_TESTS.count(test),
+ '%s appears more than once' % (test,))
+ for test in SHUFFLED_SHARDED_TESTS:
+ self.assertEqual(1, SHUFFLED_SHARDED_TESTS.count(test),
+ '%s appears more than once' % (test,))
+
+ def testShuffleDoesNotCreateNewTest(self):
+ for test in SHUFFLED_ALL_TESTS:
+ self.assert_(test in ALL_TESTS, '%s is an invalid test' % (test,))
+ for test in SHUFFLED_ACTIVE_TESTS:
+ self.assert_(test in ACTIVE_TESTS, '%s is an invalid test' % (test,))
+ for test in SHUFFLED_FILTERED_TESTS:
+ self.assert_(test in FILTERED_TESTS, '%s is an invalid test' % (test,))
+ for test in SHUFFLED_SHARDED_TESTS:
+ self.assert_(test in SHARDED_TESTS, '%s is an invalid test' % (test,))
+
+ def testShuffleIncludesAllTests(self):
+ for test in ALL_TESTS:
+ self.assert_(test in SHUFFLED_ALL_TESTS, '%s is missing' % (test,))
+ for test in ACTIVE_TESTS:
+ self.assert_(test in SHUFFLED_ACTIVE_TESTS, '%s is missing' % (test,))
+ for test in FILTERED_TESTS:
+ self.assert_(test in SHUFFLED_FILTERED_TESTS, '%s is missing' % (test,))
+ for test in SHARDED_TESTS:
+ self.assert_(test in SHUFFLED_SHARDED_TESTS, '%s is missing' % (test,))
+
+ def testShuffleLeavesDeathTestsAtFront(self):
+ non_death_test_found = False
+ for test in SHUFFLED_ACTIVE_TESTS:
+ if 'DeathTest.' in test:
+ self.assert_(not non_death_test_found,
+ '%s appears after a non-death test' % (test,))
+ else:
+ non_death_test_found = True
+
+ def _VerifyTestCasesDoNotInterleave(self, tests):
+ test_cases = []
+ for test in tests:
+ [test_case, _] = test.split('.')
+ if test_cases and test_cases[-1] != test_case:
+ test_cases.append(test_case)
+ self.assertEqual(1, test_cases.count(test_case),
+ 'Test case %s is not grouped together in %s' %
+ (test_case, tests))
+
+ def testShuffleDoesNotInterleaveTestCases(self):
+ self._VerifyTestCasesDoNotInterleave(SHUFFLED_ALL_TESTS)
+ self._VerifyTestCasesDoNotInterleave(SHUFFLED_ACTIVE_TESTS)
+ self._VerifyTestCasesDoNotInterleave(SHUFFLED_FILTERED_TESTS)
+ self._VerifyTestCasesDoNotInterleave(SHUFFLED_SHARDED_TESTS)
+
+ def testShuffleRestoresOrderAfterEachIteration(self):
+ # Get the test lists in all 3 iterations, using random seed 1, 2,
+ # and 3 respectively. Google Test picks a different seed in each
+ # iteration, and this test depends on the current implementation
+ # picking successive numbers. This dependency is not ideal, but
+ # makes the test much easier to write.
+ [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
+ GetTestsForAllIterations(
+ {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
+
+ # Make sure running the tests with random seed 1 gets the same
+ # order as in iteration 1 above.
+ [tests_with_seed1] = GetTestsForAllIterations(
+ {}, [ShuffleFlag(), RandomSeedFlag(1)])
+ self.assertEqual(tests_in_iteration1, tests_with_seed1)
+
+ # Make sure running the tests with random seed 2 gets the same
+ # order as in iteration 2 above. Success means that Google Test
+ # correctly restores the test order before re-shuffling at the
+ # beginning of iteration 2.
+ [tests_with_seed2] = GetTestsForAllIterations(
+ {}, [ShuffleFlag(), RandomSeedFlag(2)])
+ self.assertEqual(tests_in_iteration2, tests_with_seed2)
+
+ # Make sure running the tests with random seed 3 gets the same
+ # order as in iteration 3 above. Success means that Google Test
+ # correctly restores the test order before re-shuffling at the
+ # beginning of iteration 3.
+ [tests_with_seed3] = GetTestsForAllIterations(
+ {}, [ShuffleFlag(), RandomSeedFlag(3)])
+ self.assertEqual(tests_in_iteration3, tests_with_seed3)
+
+ def testShuffleGeneratesNewOrderInEachIteration(self):
+ [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
+ GetTestsForAllIterations(
+ {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
+
+ self.assert_(tests_in_iteration1 != tests_in_iteration2,
+ tests_in_iteration1)
+ self.assert_(tests_in_iteration1 != tests_in_iteration3,
+ tests_in_iteration1)
+ self.assert_(tests_in_iteration2 != tests_in_iteration3,
+ tests_in_iteration2)
+
+ def testShuffleShardedTestsPreservesPartition(self):
+ # If we run M tests on N shards, the same M tests should be run in
+ # total, regardless of the random seeds used by the shards.
+ [tests1] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+ SHARD_INDEX_ENV_VAR: '0'},
+ [ShuffleFlag(), RandomSeedFlag(1)])
+ [tests2] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+ SHARD_INDEX_ENV_VAR: '1'},
+ [ShuffleFlag(), RandomSeedFlag(20)])
+ [tests3] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
+ SHARD_INDEX_ENV_VAR: '2'},
+ [ShuffleFlag(), RandomSeedFlag(25)])
+ sorted_sharded_tests = tests1 + tests2 + tests3
+ sorted_sharded_tests.sort()
+ sorted_active_tests = []
+ sorted_active_tests.extend(ACTIVE_TESTS)
+ sorted_active_tests.sort()
+ self.assertEqual(sorted_active_tests, sorted_sharded_tests)
+
+if __name__ == '__main__':
+ gtest_test_utils.Main()
diff --git a/gtest/test/gtest_shuffle_test_.cc b/gtest/test/gtest_shuffle_test_.cc
new file mode 100644
index 0000000..53ecf77
--- /dev/null
+++ b/gtest/test/gtest_shuffle_test_.cc
@@ -0,0 +1,104 @@
+// Copyright 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Verifies that test shuffling works.
+
+#include <gtest/gtest.h>
+
+namespace {
+
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::Message;
+using ::testing::Test;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::UnitTest;
+using ::testing::internal::String;
+using ::testing::internal::scoped_ptr;
+
+// The test methods are empty, as the sole purpose of this program is
+// to print the test names before/after shuffling.
+
+class A : public Test {};
+TEST_F(A, A) {}
+TEST_F(A, B) {}
+
+TEST(ADeathTest, A) {}
+TEST(ADeathTest, B) {}
+TEST(ADeathTest, C) {}
+
+TEST(B, A) {}
+TEST(B, B) {}
+TEST(B, C) {}
+TEST(B, DISABLED_D) {}
+TEST(B, DISABLED_E) {}
+
+TEST(BDeathTest, A) {}
+TEST(BDeathTest, B) {}
+
+TEST(C, A) {}
+TEST(C, B) {}
+TEST(C, C) {}
+TEST(C, DISABLED_D) {}
+
+TEST(CDeathTest, A) {}
+
+TEST(DISABLED_D, A) {}
+TEST(DISABLED_D, DISABLED_B) {}
+
+// This printer prints the full test names only, starting each test
+// iteration with a "----" marker.
+class TestNamePrinter : public EmptyTestEventListener {
+ public:
+ virtual void OnTestIterationStart(const UnitTest& /* unit_test */,
+ int /* iteration */) {
+ printf("----\n");
+ }
+
+ virtual void OnTestStart(const TestInfo& test_info) {
+ printf("%s.%s\n", test_info.test_case_name(), test_info.name());
+ }
+};
+
+} // namespace
+
+int main(int argc, char **argv) {
+ InitGoogleTest(&argc, argv);
+
+ // Replaces the default printer with TestNamePrinter, which prints
+ // the test name only.
+ TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+ delete listeners.Release(listeners.default_result_printer());
+ listeners.Append(new TestNamePrinter);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/gtest/test/gtest_stress_test.cc b/gtest/test/gtest_stress_test.cc
index 57ea75a..0034bb8 100644
--- a/gtest/test/gtest_stress_test.cc
+++ b/gtest/test/gtest_stress_test.cc
@@ -46,7 +46,6 @@ namespace testing {
namespace {
using internal::String;
-using internal::TestProperty;
using internal::TestPropertyKeyIs;
using internal::Vector;
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;
+}
diff --git a/gtest/test/gtest_xml_output_unittest.py b/gtest/test/gtest_xml_output_unittest.py
index a0cd4d0..6d44929 100755
--- a/gtest/test/gtest_xml_output_unittest.py
+++ b/gtest/test/gtest_xml_output_unittest.py
@@ -44,6 +44,7 @@ import gtest_xml_test_utils
GTEST_OUTPUT_FLAG = "--gtest_output"
GTEST_DEFAULT_OUTPUT_FILE = "test_detail.xml"
+GTEST_PROGRAM_NAME = "gtest_xml_output_unittest_"
SUPPORTS_STACK_TRACES = False
@@ -53,7 +54,7 @@ else:
STACK_TRACE_TEMPLATE = ""
EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="13" failures="2" disabled="2" errors="0" time="*" name="AllTests">
+<testsuites tests="15" failures="4" disabled="2" errors="0" time="*" name="AllTests">
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" errors="0" time="*">
<testcase name="Succeeds" status="run" time="*" classname="SuccessfulTest"/>
</testsuite>
@@ -76,6 +77,20 @@ Expected: 2%(stack)s]]></failure>
</testcase>
<testcase name="DISABLED_test" status="notrun" time="*" classname="MixedResultTest"/>
</testsuite>
+ <testsuite name="XmlQuotingTest" tests="1" failures="1" disabled="0" errors="0" time="*">
+ <testcase name="OutputsCData" status="run" time="*" classname="XmlQuotingTest">
+ <failure message="Failed&#x0A;XML output: &lt;?xml encoding=&quot;utf-8&quot;&gt;&lt;top&gt;&lt;![CDATA[cdata text]]&gt;&lt;/top&gt;" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Failed
+XML output: <?xml encoding="utf-8"><top><![CDATA[cdata text]]>]]&gt;<![CDATA[</top>%(stack)s]]></failure>
+ </testcase>
+ </testsuite>
+ <testsuite name="InvalidCharactersTest" tests="1" failures="1" disabled="0" errors="0" time="*">
+ <testcase name="InvalidCharactersInMessage" status="run" time="*" classname="InvalidCharactersTest">
+ <failure message="Failed&#x0A;Invalid characters in brackets []" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
+Failed
+Invalid characters in brackets []%(stack)s]]></failure>
+ </testcase>
+ </testsuite>
<testsuite name="DisabledTest" tests="1" failures="0" disabled="1" errors="0" time="*">
<testcase name="DISABLED_test_not_run" status="notrun" time="*" classname="DisabledTest"/>
</testsuite>
@@ -108,8 +123,7 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
Runs a test program that generates a non-empty XML output, and
tests that the XML output is expected.
"""
- self._TestXmlOutput("gtest_xml_output_unittest_",
- EXPECTED_NON_EMPTY_XML, 1)
+ self._TestXmlOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY_XML, 1)
def testEmptyXmlOutput(self):
"""
@@ -142,6 +156,35 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
self.assertEquals(0, p.exit_code)
self.assert_(os.path.isfile(output_file))
+ def testSuppressedXmlOutput(self):
+ """
+ Tests that no XML file is generated if the default XML listener is
+ shut down before RUN_ALL_TESTS is invoked.
+ """
+
+ xml_path = os.path.join(gtest_test_utils.GetTempDir(),
+ GTEST_PROGRAM_NAME + "out.xml")
+ if os.path.isfile(xml_path):
+ os.remove(xml_path)
+
+ gtest_prog_path = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
+
+ command = [gtest_prog_path,
+ "%s=xml:%s" % (GTEST_OUTPUT_FLAG, xml_path),
+ "--shut_down_xml"]
+ p = gtest_test_utils.Subprocess(command)
+ if p.terminated_by_signal:
+ self.assert_(False,
+ "%s was killed by signal %d" % (gtest_prog_name, p.signal))
+ else:
+ self.assert_(p.exited)
+ self.assertEquals(1, p.exit_code,
+ "'%s' exited with code %s, which doesn't match "
+ "the expected exit code %s."
+ % (command, p.exit_code, 1))
+
+ self.assert_(not os.path.isfile(xml_path))
+
def _TestXmlOutput(self, gtest_prog_name, expected_xml, expected_exit_code):
"""
diff --git a/gtest/test/gtest_xml_output_unittest_.cc b/gtest/test/gtest_xml_output_unittest_.cc
index d7ce2c6..fc07ef4 100644
--- a/gtest/test/gtest_xml_output_unittest_.cc
+++ b/gtest/test/gtest_xml_output_unittest_.cc
@@ -40,6 +40,10 @@
#include <gtest/gtest.h>
+using ::testing::InitGoogleTest;
+using ::testing::TestEventListeners;
+using ::testing::UnitTest;
+
class SuccessfulTest : public testing::Test {
};
@@ -76,6 +80,17 @@ TEST(MixedResultTest, DISABLED_test) {
FAIL() << "Unexpected failure: Disabled test should not be run";
}
+TEST(XmlQuotingTest, OutputsCData) {
+ FAIL() << "XML output: "
+ "<?xml encoding=\"utf-8\"><top><![CDATA[cdata text]]></top>";
+}
+
+// Helps to test that invalid characters produced by test code do not make
+// it into the XML file.
+TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
+ FAIL() << "Invalid characters in brackets [\x1\x2]";
+}
+
class PropertyRecordingTest : public testing::Test {
};
@@ -118,3 +133,13 @@ TEST(NoFixtureTest, ExternalUtilityThatCallsRecordIntValuedProperty) {
TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
}
+
+int main(int argc, char** argv) {
+ InitGoogleTest(&argc, argv);
+
+ if (argc > 1 && strcmp(argv[1], "--shut_down_xml") == 0) {
+ TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+ delete listeners.Release(listeners.default_xml_generator());
+ }
+ return RUN_ALL_TESTS();
+}
diff --git a/gtest/test/gtest_xml_test_utils.py b/gtest/test/gtest_xml_test_utils.py
index 1811c40..c83c3b7 100755
--- a/gtest/test/gtest_xml_test_utils.py
+++ b/gtest/test/gtest_xml_test_utils.py
@@ -77,19 +77,29 @@ class GTestXMLTestCase(gtest_test_utils.TestCase):
expected_attributes = expected_node.attributes
actual_attributes = actual_node .attributes
- self.assertEquals(expected_attributes.length, actual_attributes.length)
+ self.assertEquals(
+ expected_attributes.length, actual_attributes.length,
+ "attribute numbers differ in element " + actual_node.tagName)
for i in range(expected_attributes.length):
expected_attr = expected_attributes.item(i)
actual_attr = actual_attributes.get(expected_attr.name)
- self.assert_(actual_attr is not None)
- self.assertEquals(expected_attr.value, actual_attr.value)
+ self.assert_(
+ actual_attr is not None,
+ "expected attribute %s not found in element %s" %
+ (expected_attr.name, actual_node.tagName))
+ self.assertEquals(expected_attr.value, actual_attr.value,
+ " values of attribute %s in element %s differ" %
+ (expected_attr.name, actual_node.tagName))
expected_children = self._GetChildren(expected_node)
actual_children = self._GetChildren(actual_node)
- self.assertEquals(len(expected_children), len(actual_children))
+ self.assertEquals(
+ len(expected_children), len(actual_children),
+ "number of child elements differ in element " + actual_node.tagName)
for child_id, child in expected_children.iteritems():
self.assert_(child_id in actual_children,
- '<%s> is not in <%s>' % (child_id, actual_children))
+ '<%s> is not in <%s> (in element %s)' %
+ (child_id, actual_children, actual_node.tagName))
self.AssertEquivalentNodes(child, actual_children[child_id])
identifying_attribute = {
@@ -103,14 +113,13 @@ class GTestXMLTestCase(gtest_test_utils.TestCase):
"""
Fetches all of the child nodes of element, a DOM Element object.
Returns them as the values of a dictionary keyed by the IDs of the
- children. For <testsuites>, <testsuite> and <testcase> elements,
- the ID is the value of their "name" attribute; for <failure>
- elements, it is the value of the "message" attribute; for CDATA
- section node, it is "detail". An exception is raised if any
- element other than the above four is encountered, if two child
- elements with the same identifying attributes are encountered, or
- if any other type of node is encountered, other than Text nodes
- containing only whitespace.
+ children. For <testsuites>, <testsuite> and <testcase> elements, the ID
+ is the value of their "name" attribute; for <failure> elements, it is
+ the value of the "message" attribute; CDATA sections and non-whitespace
+ text nodes are concatenated into a single CDATA section with ID
+ "detail". An exception is raised if any element other than the above
+ four is encountered, if two child elements with the same identifying
+ attributes are encountered, or if any other type of node is encountered.
"""
children = {}
@@ -121,11 +130,14 @@ class GTestXMLTestCase(gtest_test_utils.TestCase):
childID = child.getAttribute(self.identifying_attribute[child.tagName])
self.assert_(childID not in children)
children[childID] = child
- elif child.nodeType == Node.TEXT_NODE:
- self.assert_(child.nodeValue.isspace())
- elif child.nodeType == Node.CDATA_SECTION_NODE:
- self.assert_("detail" not in children)
- children["detail"] = child
+ elif child.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]:
+ if "detail" not in children:
+ if (child.nodeType == Node.CDATA_SECTION_NODE or
+ not child.nodeValue.isspace()):
+ children["detail"] = child.ownerDocument.createCDATASection(
+ child.nodeValue)
+ else:
+ children["detail"].nodeValue += child.nodeValue
else:
self.fail("Encountered unexpected node type %d" % child.nodeType)
return children