diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index a932e686..836dbc3a 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -1018,6 +1018,23 @@ class EmptyTestEventListener : public TestEventListener { void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {} }; +class XmlUnitTestResultPrinter : public EmptyTestEventListener { + public: + XmlUnitTestResultPrinter(const char* output_file); + + XmlUnitTestResultPrinter(std::ostream* output_stream); + + XmlUnitTestResultPrinter(const XmlUnitTestResultPrinter&) = delete; + XmlUnitTestResultPrinter& operator=(const XmlUnitTestResultPrinter&) = delete; + + void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; + void ListTestsMatchingFilter(const std::vector& test_suites); + + private: + const std::string output_file_; + std::ostream* output_stream_; +}; + // TestEventListeners lets users add listeners to track events in Google Test. class GTEST_API_ TestEventListeners { public: diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index 99b22ed3..649e109f 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -3897,10 +3897,7 @@ void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, // This class generates an XML output file. class XmlUnitTestResultPrinter : public EmptyTestEventListener { public: - explicit XmlUnitTestResultPrinter(const char* output_file); - - void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; - void ListTestsMatchingFilter(const std::vector& test_suites); + XmlUnitTestResultPrinter() = delete; // Prints an XML summary of all unit tests. static void PrintXmlTestsList(std::ostream* stream, @@ -3982,40 +3979,9 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener { static void OutputXmlTestProperties(std::ostream* stream, const TestResult& result); - // The output file. - const std::string output_file_; - - XmlUnitTestResultPrinter(const XmlUnitTestResultPrinter&) = delete; - XmlUnitTestResultPrinter& operator=(const XmlUnitTestResultPrinter&) = delete; + friend ::testing::XmlUnitTestResultPrinter; }; -// Creates a new XmlUnitTestResultPrinter. -XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) - : output_file_(output_file) { - if (output_file_.empty()) { - GTEST_LOG_(FATAL) << "XML output file may not be null"; - } -} - -// Called after the unit test ends. -void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, - int /*iteration*/) { - FILE* xmlout = OpenFileForWriting(output_file_); - std::stringstream stream; - PrintXmlUnitTest(&stream, unit_test); - fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); - fclose(xmlout); -} - -void XmlUnitTestResultPrinter::ListTestsMatchingFilter( - const std::vector& test_suites) { - FILE* xmlout = OpenFileForWriting(output_file_); - std::stringstream stream; - PrintXmlTestsList(&stream, test_suites); - fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); - fclose(xmlout); -} - // Returns an XML-escaped copy of the input string str. If is_attribute // is true, the text is meant to appear as an attribute value, and // normalizable whitespace is preserved by replacing it with character @@ -5145,6 +5111,59 @@ void TestEventListeners::SuppressEventForwarding(bool suppress) { repeater_->set_forwarding_enabled(!suppress); } +// Creates a new XmlUnitTestResultPrinter. +XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) + : output_file_(output_file) { + if (output_file_.empty()) { + GTEST_LOG_(FATAL) << "XML output file may not be null"; + } +} + +// Creates a new XmlUnitTestResultPrinter. +XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(std::ostream* output_stream) + : output_stream_(output_stream) { + if (!output_stream->good()) { + GTEST_LOG_(FATAL) << "XML output is not good"; + } +} + +// Called after the unit test ends. +void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + FILE* xmlout = 0; + if(!output_stream_) { + xmlout = internal::OpenFileForWriting(output_file_); + output_stream_ = new std::stringstream; + } + + internal::XmlUnitTestResultPrinter::PrintXmlUnitTest(output_stream_, unit_test); + + if(xmlout) { + fprintf(xmlout, "%s", internal::StringStreamToString(static_cast(output_stream_)).c_str()); + fclose(xmlout); + delete output_stream_; + output_stream_ = 0; + } +} + +void XmlUnitTestResultPrinter::ListTestsMatchingFilter( + const std::vector& test_suites) { + FILE* xmlout = 0; + if(!output_stream_) { + xmlout = internal::OpenFileForWriting(output_file_); + output_stream_ = new std::stringstream; + } + + internal::XmlUnitTestResultPrinter::PrintXmlTestsList(output_stream_, test_suites); + + if(xmlout) { + fprintf(xmlout, "%s", internal::StringStreamToString(static_cast(output_stream_)).c_str()); + fclose(xmlout); + delete output_stream_; + output_stream_ = 0; + } +} + // class UnitTest // Gets the singleton UnitTest object. The first time this method is @@ -5630,7 +5649,7 @@ void UnitTestImpl::ConfigureXmlOutput() { const std::string& output_format = UnitTestOptions::GetOutputFormat(); #if GTEST_HAS_FILE_SYSTEM if (output_format == "xml") { - listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( + listeners()->SetDefaultXmlGenerator(new ::testing::XmlUnitTestResultPrinter( UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); } else if (output_format == "json") { listeners()->SetDefaultXmlGenerator(new JsonUnitTestResultPrinter( @@ -6206,9 +6225,7 @@ void UnitTestImpl::ListTestsMatchingFilter() { UnitTestOptions::GetAbsolutePathToOutputFile().c_str()); std::stringstream stream; if (output_format == "xml") { - XmlUnitTestResultPrinter( - UnitTestOptions::GetAbsolutePathToOutputFile().c_str()) - .PrintXmlTestsList(&stream, test_suites_); + XmlUnitTestResultPrinter::PrintXmlTestsList(&stream, test_suites_); } else if (output_format == "json") { JsonUnitTestResultPrinter( UnitTestOptions::GetAbsolutePathToOutputFile().c_str())