diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h index 2b1c9782..b2214705 100644 --- a/include/gtest/gtest.h +++ b/include/gtest/gtest.h @@ -141,8 +141,12 @@ const int kMaxStackTraceDepth = 100; namespace internal { +class AssertHelper; class GTestFlagSaver; class TestCase; // A collection of related tests. +class UnitTestImpl* GetUnitTestImpl(); +void ReportFailureInUnknownLocation(TestPartResultType result_type, + const String& message); // Converts a streamable value to a String. A NULL pointer is // converted to "(null)". When the input value is a ::string, @@ -759,33 +763,6 @@ class UnitTest { // Consecutive calls will return the same object. static UnitTest* GetInstance(); - // Registers and returns a global test environment. When a test - // program is run, all global test environments will be set-up in - // the order they were registered. After all tests in the program - // have finished, all global test environments will be torn-down in - // the *reverse* order they were registered. - // - // The UnitTest object takes ownership of the given environment. - // - // This method can only be called from the main thread. - Environment* AddEnvironment(Environment* env); - - // Adds a TestPartResult to the current TestResult object. All - // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) - // eventually call this to report their results. The user code - // should use the assertion macros instead of calling this directly. - // - // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. - void AddTestPartResult(TestPartResultType result_type, - const char* file_name, - int line_number, - const internal::String& message, - const internal::String& os_stack_trace); - - // Adds a TestProperty to the current TestResult object. If the result already - // contains a property with the same key, the value will be updated. - void RecordPropertyForCurrentTest(const char* key, const char* value); - // Runs all tests in this UnitTest object and prints the result. // Returns 0 if successful, or 1 otherwise. // @@ -809,14 +786,41 @@ class UnitTest { #if GTEST_HAS_PARAM_TEST // Returns the ParameterizedTestCaseRegistry object used to keep track of // value-parameterized tests and instantiate and register them. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. internal::ParameterizedTestCaseRegistry& parameterized_test_registry(); #endif // GTEST_HAS_PARAM_TEST + private: + // Registers and returns a global test environment. When a test + // program is run, all global test environments will be set-up in + // the order they were registered. After all tests in the program + // have finished, all global test environments will be torn-down in + // the *reverse* order they were registered. + // + // The UnitTest object takes ownership of the given environment. + // + // This method can only be called from the main thread. + Environment* AddEnvironment(Environment* env); + + // Adds a TestPartResult to the current TestResult object. All + // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) + // eventually call this to report their results. The user code + // should use the assertion macros instead of calling this directly. + void AddTestPartResult(TestPartResultType result_type, + const char* file_name, + int line_number, + const internal::String& message, + const internal::String& os_stack_trace); + + // Adds a TestProperty to the current TestResult object. If the result already + // contains a property with the same key, the value will be updated. + void RecordPropertyForCurrentTest(const char* key, const char* value); + // Accessors for the implementation object. internal::UnitTestImpl* impl() { return impl_; } const internal::UnitTestImpl* impl() const { return impl_; } - private: // Gets the number of successful test cases. int successful_test_case_count() const; @@ -861,7 +865,20 @@ class UnitTest { // ScopedTrace is a friend as it needs to modify the per-thread // trace stack, which is a private member of UnitTest. + // TODO(vladl@google.com): Order all declarations according to the style + // guide after publishing of the above methods is done. friend class internal::ScopedTrace; + friend Environment* AddGlobalTestEnvironment(Environment* env); + friend internal::UnitTestImpl* internal::GetUnitTestImpl(); + friend class internal::AssertHelper; + friend class Test; + friend void internal::ReportFailureInUnknownLocation( + TestPartResultType result_type, + const internal::String& message); + // TODO(vladl@google.com): Remove these when publishing the new accessors. + friend class PrettyUnitTestResultPrinter; + friend class XmlUnitTestResultPrinter; + // Creates an empty UnitTest. UnitTest(); diff --git a/src/gtest-test-part.cc b/src/gtest-test-part.cc index 9aacd2be..49a6fe5a 100644 --- a/src/gtest-test-part.cc +++ b/src/gtest-test-part.cc @@ -44,6 +44,8 @@ namespace testing { +using internal::GetUnitTestImpl; + // Gets the summary of the failure message by omitting the stack trace // in it. internal::String TestPartResult::ExtractSummary(const char* message) { @@ -101,14 +103,13 @@ namespace internal { HasNewFatalFailureHelper::HasNewFatalFailureHelper() : has_new_fatal_failure_(false), - original_reporter_(UnitTest::GetInstance()->impl()-> + original_reporter_(GetUnitTestImpl()-> GetTestPartResultReporterForCurrentThread()) { - UnitTest::GetInstance()->impl()->SetTestPartResultReporterForCurrentThread( - this); + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); } HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { - UnitTest::GetInstance()->impl()->SetTestPartResultReporterForCurrentThread( + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( original_reporter_); } diff --git a/src/gtest.cc b/src/gtest.cc index ec176918..6e4dbfc7 100644 --- a/src/gtest.cc +++ b/src/gtest.cc @@ -565,7 +565,7 @@ ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( } void ScopedFakeTestPartResultReporter::Init() { - internal::UnitTestImpl* const impl = UnitTest::GetInstance()->impl(); + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); if (intercept_mode_ == INTERCEPT_ALL_THREADS) { old_reporter_ = impl->GetGlobalTestPartResultReporter(); impl->SetGlobalTestPartResultReporter(this); @@ -578,7 +578,7 @@ void ScopedFakeTestPartResultReporter::Init() { // The d'tor restores the test part result reporter used by Google Test // before. ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { - internal::UnitTestImpl* const impl = UnitTest::GetInstance()->impl(); + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); if (intercept_mode_ == INTERCEPT_ALL_THREADS) { impl->SetGlobalTestPartResultReporter(old_reporter_); } else { @@ -1985,6 +1985,22 @@ void Test::RecordProperty(const char* key, int value) { RecordProperty(key, value_message.GetString().c_str()); } +namespace internal { + +void ReportFailureInUnknownLocation(TestPartResultType result_type, + const String& message) { + // This function is a friend of UnitTest and as such has access to + // AddTestPartResult. + UnitTest::GetInstance()->AddTestPartResult( + result_type, + NULL, // No info about the source file where the exception occurred. + -1, // We have no info on which line caused the exception. + message, + String()); // No stack trace, either. +} + +} // namespace internal + #if GTEST_OS_WINDOWS // We are on Windows. @@ -1995,15 +2011,8 @@ static void AddExceptionThrownFailure(DWORD exception_code, message << "Exception thrown with code 0x" << std::setbase(16) << exception_code << std::setbase(10) << " in " << location << "."; - UnitTest* const unit_test = UnitTest::GetInstance(); - unit_test->AddTestPartResult( - TPRT_FATAL_FAILURE, - static_cast(NULL), - // We have no info about the source file where the exception - // occurred. - -1, // We have no info on which line caused the exception. - message.GetString(), - internal::String("")); + internal::ReportFailureInUnknownLocation(TPRT_FATAL_FAILURE, + message.GetString()); } #endif // GTEST_OS_WINDOWS @@ -2699,6 +2708,8 @@ class PrettyUnitTestResultPrinter : public UnitTestEventListenerInterface { virtual void OnUnitTestEnd(const UnitTest& unit_test); private: + static void PrintFailedTests(const UnitTest& unit_test); + internal::String test_case_name_; }; @@ -2720,11 +2731,10 @@ void PrettyUnitTestResultPrinter::OnUnitTestStart(const UnitTest& unit_test) { internal::posix::GetEnv(kTestTotalShards)); } - const internal::UnitTestImpl* const impl = unit_test.impl(); ColoredPrintf(COLOR_GREEN, "[==========] "); printf("Running %s from %s.\n", - FormatTestCount(impl->test_to_run_count()).c_str(), - FormatTestCaseCount(impl->test_case_to_run_count()).c_str()); + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); fflush(stdout); } @@ -2808,71 +2818,62 @@ void PrettyUnitTestResultPrinter::OnGlobalTearDownStart( fflush(stdout); } -namespace internal { - // Internal helper for printing the list of failed tests. -static void PrintFailedTestsPretty(const UnitTestImpl* impl) { - const int failed_test_count = impl->failed_test_count(); +void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { + const int failed_test_count = unit_test.failed_test_count(); if (failed_test_count == 0) { return; } - for (const internal::ListNode* node = impl->test_cases()->Head(); - node != NULL; node = node->next()) { - const TestCase* const tc = node->element(); - if (!tc->should_run() || (tc->failed_test_count() == 0)) { + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + const TestCase& test_case = *unit_test.GetTestCase(i); + if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { continue; } - for (const internal::ListNode* tinode = - tc->test_info_list().Head(); - tinode != NULL; tinode = tinode->next()) { - const TestInfo* const ti = tinode->element(); - if (!tc->ShouldRunTest(ti) || tc->TestPassed(ti)) { + for (int j = 0; j < test_case.total_test_count(); ++j) { + const TestInfo& test_info = *test_case.GetTestInfo(j); + if (!test_info.should_run() || test_info.result()->Passed()) { continue; } ColoredPrintf(COLOR_RED, "[ FAILED ] "); - printf("%s.%s", ti->test_case_name(), ti->name()); - if (ti->test_case_comment()[0] != '\0' || - ti->comment()[0] != '\0') { - printf(", where %s", ti->test_case_comment()); - if (ti->test_case_comment()[0] != '\0' && - ti->comment()[0] != '\0') { + printf("%s.%s", test_case.name(), test_info.name()); + if (test_case.comment()[0] != '\0' || + test_info.comment()[0] != '\0') { + printf(", where %s", test_case.comment()); + if (test_case.comment()[0] != '\0' && + test_info.comment()[0] != '\0') { printf(" and "); } } - printf("%s\n", ti->comment()); + printf("%s\n", test_info.comment()); } } } -} // namespace internal - void PrettyUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) { - const internal::UnitTestImpl* const impl = unit_test.impl(); - ColoredPrintf(COLOR_GREEN, "[==========] "); printf("%s from %s ran.", - FormatTestCount(impl->test_to_run_count()).c_str(), - FormatTestCaseCount(impl->test_case_to_run_count()).c_str()); + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); if (GTEST_FLAG(print_time)) { printf(" (%s ms total)", - internal::StreamableToString(impl->elapsed_time()).c_str()); + internal::StreamableToString(unit_test.elapsed_time()).c_str()); } printf("\n"); ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); - printf("%s.\n", FormatTestCount(impl->successful_test_count()).c_str()); + printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); - int num_failures = impl->failed_test_count(); - if (!impl->Passed()) { - const int failed_test_count = impl->failed_test_count(); + int num_failures = unit_test.failed_test_count(); + if (!unit_test.Passed()) { + const int failed_test_count = unit_test.failed_test_count(); ColoredPrintf(COLOR_RED, "[ FAILED ] "); printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); - internal::PrintFailedTestsPretty(impl); + PrintFailedTests(unit_test); printf("\n%2d FAILED %s\n", num_failures, num_failures == 1 ? "TEST" : "TESTS"); } - int num_disabled = impl->disabled_test_count(); + int num_disabled = unit_test.disabled_test_count(); if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { if (!num_failures) { printf("\n"); // Add a spacer if no FAILURE banner is displayed. @@ -2996,10 +2997,10 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener { // Prints an XML representation of a TestInfo object. static void PrintXmlTestInfo(FILE* out, const char* test_case_name, - const TestInfo* test_info); + const TestInfo& test_info); // Prints an XML representation of a TestCase object - static void PrintXmlTestCase(FILE* out, const TestCase* test_case); + static void PrintXmlTestCase(FILE* out, const TestCase& test_case); // Prints an XML summary of unit_test to output stream out. static void PrintXmlUnitTest(FILE* out, const UnitTest& unit_test); @@ -3009,7 +3010,7 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener { // When the String is not empty, it includes a space at the beginning, // to delimit this attribute from prior attributes. static internal::String TestPropertiesAsXmlAttributes( - const internal::TestResult* result); + const internal::TestResult& result); // The output file. const internal::String output_file_; @@ -3147,23 +3148,20 @@ const char* FormatTimeInMillisAsSeconds(TimeInMillis ms) { // TODO(wan): There is also value in printing properties with the plain printer. void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out, const char* test_case_name, - const TestInfo* test_info) { - const internal::TestResult * const result = test_info->result(); - const internal::List &results = result->test_part_results(); + const TestInfo& test_info) { + const internal::TestResult& result = *test_info.result(); fprintf(out, " name()).c_str(), - test_info->should_run() ? "run" : "notrun", - internal::FormatTimeInMillisAsSeconds(result->elapsed_time()), + EscapeXmlAttribute(test_info.name()).c_str(), + test_info.should_run() ? "run" : "notrun", + internal::FormatTimeInMillisAsSeconds(result.elapsed_time()), EscapeXmlAttribute(test_case_name).c_str(), TestPropertiesAsXmlAttributes(result).c_str()); int failures = 0; - for (const internal::ListNode* part_node = results.Head(); - part_node != NULL; - part_node = part_node->next()) { - const TestPartResult& part = part_node->element(); + for (int i = 0; i < result.total_part_count(); ++i) { + const TestPartResult& part = *result.GetTestPartResult(i); if (part.failed()) { const internal::String message = internal::String::Format("%s:%d\n%s", part.file_name(), @@ -3185,60 +3183,47 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out, // Prints an XML representation of a TestCase object void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out, - const TestCase* test_case) { + const TestCase& test_case) { fprintf(out, " name()).c_str(), - test_case->total_test_count(), - test_case->failed_test_count(), - test_case->disabled_test_count()); + EscapeXmlAttribute(test_case.name()).c_str(), + test_case.total_test_count(), + test_case.failed_test_count(), + test_case.disabled_test_count()); fprintf(out, "errors=\"0\" time=\"%s\">\n", - internal::FormatTimeInMillisAsSeconds(test_case->elapsed_time())); - for (const internal::ListNode* info_node = - test_case->test_info_list().Head(); - info_node != NULL; - info_node = info_node->next()) { - PrintXmlTestInfo(out, test_case->name(), info_node->element()); - } + internal::FormatTimeInMillisAsSeconds(test_case.elapsed_time())); + for (int i = 0; i < test_case.total_test_count(); ++i) + PrintXmlTestInfo(out, test_case.name(), *test_case.GetTestInfo(i)); fprintf(out, " \n"); } // Prints an XML summary of unit_test to output stream out. void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out, const UnitTest& unit_test) { - const internal::UnitTestImpl* const impl = unit_test.impl(); fprintf(out, "\n"); fprintf(out, "total_test_count(), - impl->failed_test_count(), - impl->disabled_test_count(), - internal::FormatTimeInMillisAsSeconds(impl->elapsed_time())); + unit_test.total_test_count(), + unit_test.failed_test_count(), + unit_test.disabled_test_count(), + internal::FormatTimeInMillisAsSeconds(unit_test.elapsed_time())); fprintf(out, "name=\"AllTests\">\n"); - for (const internal::ListNode* case_node = - impl->test_cases()->Head(); - case_node != NULL; - case_node = case_node->next()) { - PrintXmlTestCase(out, case_node->element()); - } + for (int i = 0; i < unit_test.total_test_case_count(); ++i) + PrintXmlTestCase(out, *unit_test.GetTestCase(i)); fprintf(out, "\n"); } // Produces a string representing the test properties in a result as space // delimited XML attributes based on the property key="value" pairs. internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( - const internal::TestResult* result) { + const internal::TestResult& result) { using internal::TestProperty; Message attributes; - const internal::List& properties = result->test_properties(); - for (const internal::ListNode* property_node = - properties.Head(); - property_node != NULL; - property_node = property_node->next()) { - const TestProperty& property = property_node->element(); + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = *result.GetTestProperty(i); attributes << " " << property.key() << "=" << "\"" << EscapeXmlAttribute(property.value()) << "\""; } @@ -4136,7 +4121,7 @@ TestInfoImpl::~TestInfoImpl() { String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test, int skip_count) { // We pass skip_count + 1 to skip this wrapper function in addition // to what the user really wants to skip. - return unit_test->impl()->CurrentOsStackTraceExceptTop(skip_count + 1); + return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); } // Returns the number of failed test parts in the given test result object. diff --git a/test/gtest-death-test_test.cc b/test/gtest-death-test_test.cc index 9dd477b2..8b2173bf 100644 --- a/test/gtest-death-test_test.cc +++ b/test/gtest-death-test_test.cc @@ -67,6 +67,7 @@ using testing::internal::DeathTest; using testing::internal::DeathTestFactory; using testing::internal::FilePath; using testing::internal::GetLastErrnoDescription; +using testing::internal::GetUnitTestImpl; using testing::internal::ParseNaturalNumber; using testing::internal::String; @@ -77,22 +78,22 @@ namespace internal { // single UnitTest object during their lifetimes. class ReplaceDeathTestFactory { public: - ReplaceDeathTestFactory(UnitTest* parent, DeathTestFactory* new_factory) - : parent_impl_(parent->impl()) { - old_factory_ = parent_impl_->death_test_factory_.release(); - parent_impl_->death_test_factory_.reset(new_factory); + explicit ReplaceDeathTestFactory(DeathTestFactory* new_factory) + : unit_test_impl_(GetUnitTestImpl()) { + old_factory_ = unit_test_impl_->death_test_factory_.release(); + unit_test_impl_->death_test_factory_.reset(new_factory); } ~ReplaceDeathTestFactory() { - parent_impl_->death_test_factory_.release(); - parent_impl_->death_test_factory_.reset(old_factory_); + unit_test_impl_->death_test_factory_.release(); + unit_test_impl_->death_test_factory_.reset(old_factory_); } private: // Prevents copying ReplaceDeathTestFactory objects. ReplaceDeathTestFactory(const ReplaceDeathTestFactory&); void operator=(const ReplaceDeathTestFactory&); - UnitTestImpl* parent_impl_; + UnitTestImpl* unit_test_impl_; DeathTestFactory* old_factory_; }; @@ -846,8 +847,7 @@ class MacroLogicDeathTest : public testing::Test { static void SetUpTestCase() { factory_ = new MockDeathTestFactory; - replacer_ = new testing::internal::ReplaceDeathTestFactory( - testing::UnitTest::GetInstance(), factory_); + replacer_ = new testing::internal::ReplaceDeathTestFactory(factory_); } static void TearDownTestCase() { @@ -959,8 +959,7 @@ TEST_F(MacroLogicDeathTest, ChildDoesNotDie) { // Returns the number of successful parts in the current test. static size_t GetSuccessfulTestPartCount() { - return testing::UnitTest::GetInstance()->impl()->current_test_result()-> - successful_part_count(); + return GetUnitTestImpl()->current_test_result()->successful_part_count(); } // Tests that a successful death test does not register a successful diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc index b1a161bb..4e430926 100644 --- a/test/gtest_unittest.cc +++ b/test/gtest_unittest.cc @@ -136,6 +136,7 @@ using testing::internal::GetCurrentOsStackTraceExceptTop; using testing::internal::GetFailedPartCount; using testing::internal::GetTestTypeId; using testing::internal::GetTypeId; +using testing::internal::GetUnitTestImpl; using testing::internal::GTestFlagSaver; using testing::internal::Int32; using testing::internal::Int32FromEnvOrDie; @@ -3600,8 +3601,7 @@ TEST(AssertionSyntaxTest, WorksWithConst) { // Returns the number of successful parts in the current test. static size_t GetSuccessfulPartCount() { - return UnitTest::GetInstance()->impl()->current_test_result()-> - successful_part_count(); + return GetUnitTestImpl()->current_test_result()->successful_part_count(); } namespace testing { @@ -4416,8 +4416,7 @@ namespace testing { class TestInfoTest : public Test { protected: static TestInfo * GetTestInfo(const char* test_name) { - return UnitTest::GetInstance()->impl()-> - GetTestCase("TestInfoTest", "", NULL, NULL)-> + return GetUnitTestImpl()->GetTestCase("TestInfoTest", "", NULL, NULL)-> GetTestInfo(test_name); }