@@ -3498,6 +3498,125 @@ std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(
34983498// </testsuite>
34993499// </testsuites>
35003500
3501+ class TapUnitTestResultPrinter : public EmptyTestEventListener {
3502+ public:
3503+ TapUnitTestResultPrinter ();
3504+ explicit TapUnitTestResultPrinter (const char * output_file);
3505+ virtual void OnTestIterationEnd (const UnitTest& unit_test, int iteration);
3506+
3507+ private:
3508+ static void PrintTapUnitTest (::std::ostream* stream,
3509+ const UnitTest& unit_test);
3510+ static void PrintTapTestCase (int * count,
3511+ ::std::ostream* stream,
3512+ const TestCase& test_case);
3513+ static void OutputTapTestInfo (int * count,
3514+ ::std::ostream* stream,
3515+ const char * test_case_name,
3516+ const TestInfo& test_info);
3517+ static void OutputTapComment (::std::ostream* stream, const char * comment);
3518+
3519+ const std::string output_file_;
3520+ GTEST_DISALLOW_COPY_AND_ASSIGN_ (TapUnitTestResultPrinter);
3521+ };
3522+
3523+ TapUnitTestResultPrinter::TapUnitTestResultPrinter () {}
3524+
3525+ TapUnitTestResultPrinter::TapUnitTestResultPrinter (const char * output_file)
3526+ : output_file_(output_file) {
3527+ if (output_file_.c_str () == NULL || output_file_.empty ()) {
3528+ fprintf (stderr, " TAP output file may not be null\n " );
3529+ fflush (stderr);
3530+ exit (EXIT_FAILURE);
3531+ }
3532+ }
3533+
3534+ void TapUnitTestResultPrinter::OnTestIterationEnd (const UnitTest& unit_test,
3535+ int /* iteration*/ ) {
3536+ FILE* tapout = stdout;
3537+
3538+ if (!output_file_.empty ()) {
3539+ FilePath output_file (output_file_);
3540+ FilePath output_dir (output_file.RemoveFileName ());
3541+
3542+ tapout = NULL ;
3543+ if (output_dir.CreateDirectoriesRecursively ())
3544+ tapout = posix::FOpen (output_file_.c_str (), " w" );
3545+
3546+ if (tapout == NULL ) {
3547+ fprintf (stderr, " Unable to open file \" %s\"\n " , output_file_.c_str ());
3548+ fflush (stderr);
3549+ exit (EXIT_FAILURE);
3550+ }
3551+ }
3552+
3553+ std::stringstream stream;
3554+ PrintTapUnitTest (&stream, unit_test);
3555+ fprintf (tapout, " %s" , StringStreamToString (&stream).c_str ());
3556+ fflush (tapout);
3557+
3558+ if (tapout != stdout)
3559+ fclose (tapout);
3560+ }
3561+
3562+ void TapUnitTestResultPrinter::PrintTapUnitTest (std::ostream* stream,
3563+ const UnitTest& unit_test) {
3564+ *stream << " TAP version 13\n " ;
3565+ *stream << " 1.." << unit_test.reportable_test_count () << " \n " ;
3566+
3567+ int count = 1 ;
3568+ for (int i = 0 ; i < unit_test.total_test_case_count (); ++i) {
3569+ const TestCase& test_case = *unit_test.GetTestCase (i);
3570+ if (test_case.reportable_test_count () > 0 )
3571+ PrintTapTestCase (&count, stream, test_case);
3572+ }
3573+
3574+ *stream << " # failures: " << unit_test.failed_test_count () << " \n " ;
3575+ }
3576+
3577+ void TapUnitTestResultPrinter::PrintTapTestCase (int * count,
3578+ std::ostream* stream,
3579+ const TestCase& test_case) {
3580+ for (int i = 0 ; i < test_case.total_test_count (); ++i) {
3581+ const TestInfo& test_info = *test_case.GetTestInfo (i);
3582+ if (test_info.is_reportable ())
3583+ OutputTapTestInfo (count, stream, test_case.name (), test_info);
3584+ }
3585+ }
3586+
3587+ void TapUnitTestResultPrinter::OutputTapTestInfo (int * count,
3588+ ::std::ostream* stream,
3589+ const char * test_case_name,
3590+ const TestInfo& test_info) {
3591+ const TestResult& result = *test_info.result ();
3592+ const char * status = result.Passed () ? " ok" : " not ok" ;
3593+
3594+ *stream << status << " " << *count << " - " <<
3595+ test_case_name << " ." << test_info.name () << " \n " ;
3596+ *stream << " ---\n " ;
3597+ *stream << " duration_ms: " <<
3598+ FormatTimeInMillisAsSeconds (result.elapsed_time ()) << " \n " ;
3599+ *stream << " ...\n " ;
3600+
3601+ for (int i = 0 ; i < result.total_part_count (); ++i) {
3602+ const TestPartResult& part = result.GetTestPartResult (i);
3603+ OutputTapComment (stream, part.message ());
3604+ }
3605+
3606+ *count += 1 ;
3607+ }
3608+
3609+ void TapUnitTestResultPrinter::OutputTapComment (::std::ostream* stream,
3610+ const char * comment) {
3611+ const char * start = comment;
3612+ while (const char * end = strchr (start, ' \n ' )) {
3613+ *stream << " # " << std::string (start, end) << " \n " ;
3614+ start = end + 1 ;
3615+ }
3616+ if (*start)
3617+ *stream << " # " << start << " \n " ;
3618+ }
3619+
35013620// Formats the given time in milliseconds as seconds.
35023621std::string FormatTimeInMillisAsSeconds (TimeInMillis ms) {
35033622 ::std::stringstream ss;
@@ -4314,7 +4433,7 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
43144433#endif
43154434 // Will be overridden by the flag before first use.
43164435 catch_exceptions_ (false ) {
4317- listeners ()->SetDefaultResultPrinter (new PrettyUnitTestResultPrinter );
4436+ listeners ()->SetDefaultResultPrinter (new TapUnitTestResultPrinter );
43184437}
43194438
43204439UnitTestImpl::~UnitTestImpl () {
@@ -4365,6 +4484,9 @@ void UnitTestImpl::ConfigureXmlOutput() {
43654484 if (output_format == " xml" ) {
43664485 listeners ()->SetDefaultXmlGenerator (new XmlUnitTestResultPrinter (
43674486 UnitTestOptions::GetAbsolutePathToOutputFile ().c_str ()));
4487+ } else if (output_format == " tap" ) {
4488+ listeners ()->SetDefaultXmlGenerator (new TapUnitTestResultPrinter (
4489+ UnitTestOptions::GetAbsolutePathToOutputFile ().c_str ()));
43684490 } else if (output_format != " " ) {
43694491 printf (" WARNING: unrecognized output format \" %s\" ignored.\n " ,
43704492 output_format.c_str ());
0 commit comments