diff --git a/src/catch2/interfaces/catch_interfaces_reporter.cpp b/src/catch2/interfaces/catch_interfaces_reporter.cpp index a2a8bebfe5..29fafecfd3 100644 --- a/src/catch2/interfaces/catch_interfaces_reporter.cpp +++ b/src/catch2/interfaces/catch_interfaces_reporter.cpp @@ -11,34 +11,15 @@ #include #include #include -#include #include #include -#include +#include #include #include namespace Catch { - namespace { - void listTestNamesOnly( std::vector const& tests ) { - for ( auto const& test : tests ) { - auto const& testCaseInfo = test.getTestCaseInfo(); - - if ( startsWith( testCaseInfo.name, '#' ) ) { - Catch::cout() << '"' << testCaseInfo.name << '"'; - } else { - Catch::cout() << testCaseInfo.name; - } - - Catch::cout() << '\n'; - } - Catch::cout() << std::flush; - } - } // end unnamed namespace - - ReporterConfig::ReporterConfig( IConfig const* _fullConfig ) : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} @@ -128,89 +109,19 @@ namespace Catch { void IStreamingReporter::fatalErrorEncountered( StringRef ) {} void IStreamingReporter::listReporters(std::vector const& descriptions) { - Catch::cout() << "Available reporters:\n"; - const auto maxNameLen = std::max_element(descriptions.begin(), descriptions.end(), - [](ReporterDescription const& lhs, ReporterDescription const& rhs) { return lhs.name.size() < rhs.name.size(); }) - ->name.size(); - - for (auto const& desc : descriptions) { - if (m_config->verbosity() == Verbosity::Quiet) { - Catch::cout() - << TextFlow::Column(desc.name) - .indent(2) - .width(5 + maxNameLen) << '\n'; - } else { - Catch::cout() - << TextFlow::Column(desc.name + ":") - .indent(2) - .width(5 + maxNameLen) - + TextFlow::Column(desc.description) - .initialIndent(0) - .indent(2) - .width(CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8) - << '\n'; - } - } - Catch::cout() << std::endl; + defaultListReporters( + Catch::cout(), descriptions, m_config->verbosity() ); } void IStreamingReporter::listTests(std::vector const& tests) { - // We special case this to provide the equivalent of old - // `--list-test-names-only`, which could then be used by the - // `--input-file` option. - if (m_config->verbosity() == Verbosity::Quiet) { - listTestNamesOnly(tests); - return; - } - - if (m_config->hasTestFilters()) { - Catch::cout() << "Matching test cases:\n"; - } else { - Catch::cout() << "All available test cases:\n"; - } - - for (auto const& test : tests) { - auto const& testCaseInfo = test.getTestCaseInfo(); - Colour::Code colour = testCaseInfo.isHidden() - ? Colour::SecondaryText - : Colour::None; - Colour colourGuard(colour); - - Catch::cout() << TextFlow::Column(testCaseInfo.name).initialIndent(2).indent(4) << '\n'; - if (m_config->verbosity() >= Verbosity::High) { - Catch::cout() << TextFlow::Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << std::endl; - } - if ( !testCaseInfo.tags.empty() && - m_config->verbosity() > Verbosity::Quiet ) { - Catch::cout() << TextFlow::Column(testCaseInfo.tagsAsString()).indent(6) << '\n'; - } - } - - if (m_config->hasTestFilters()) { - Catch::cout() << pluralise(tests.size(), "matching test case") << '\n' << std::endl; - } else { - Catch::cout() << pluralise(tests.size(), "test case") << '\n' << std::endl; - } + defaultListTests( Catch::cout(), + tests, + m_config->hasTestFilters(), + m_config->verbosity() ); } void IStreamingReporter::listTags(std::vector const& tags) { - if (m_config->hasTestFilters()) { - Catch::cout() << "Tags for matching test cases:\n"; - } else { - Catch::cout() << "All available tags:\n"; - } - - for (auto const& tagCount : tags) { - ReusableStringStream rss; - rss << " " << std::setw(2) << tagCount.count << " "; - auto str = rss.str(); - auto wrapper = TextFlow::Column(tagCount.all()) - .initialIndent(0) - .indent(str.size()) - .width(CATCH_CONFIG_CONSOLE_WIDTH - 10); - Catch::cout() << str << wrapper << '\n'; - } - Catch::cout() << pluralise(tags.size(), "tag") << '\n' << std::endl; + defaultListTags( Catch::cout(), tags, m_config->hasTestFilters() ); } } // end namespace Catch diff --git a/src/catch2/reporters/catch_reporter_combined_tu.cpp b/src/catch2/reporters/catch_reporter_combined_tu.cpp index 0a15c09836..25a52e9dac 100644 --- a/src/catch2/reporters/catch_reporter_combined_tu.cpp +++ b/src/catch2/reporters/catch_reporter_combined_tu.cpp @@ -21,13 +21,40 @@ #include #include #include - +#include +#include +#include +#include +#include +#include + +#include #include #include #include +#include namespace Catch { + namespace { + void listTestNamesOnly(std::ostream& out, + std::vector const& tests) { + for (auto const& test : tests) { + auto const& testCaseInfo = test.getTestCaseInfo(); + + if (startsWith(testCaseInfo.name, '#')) { + out << '"' << testCaseInfo.name << '"'; + } else { + out << testCaseInfo.name; + } + + out << '\n'; + } + out << std::flush; + } + } // end unnamed namespace + + // Because formatting using c++ streams is stateful, drop down to C is // required Alternatively we could use stringstream, but its performance // is... not good. @@ -89,6 +116,101 @@ namespace Catch { return out; } + void + defaultListReporters( std::ostream& out, + std::vector const& descriptions, + Verbosity verbosity ) { + out << "Available reporters:\n"; + const auto maxNameLen = + std::max_element( descriptions.begin(), + descriptions.end(), + []( ReporterDescription const& lhs, + ReporterDescription const& rhs ) { + return lhs.name.size() < rhs.name.size(); + } ) + ->name.size(); + + for ( auto const& desc : descriptions ) { + if ( verbosity == Verbosity::Quiet ) { + out << TextFlow::Column( desc.name ) + .indent( 2 ) + .width( 5 + maxNameLen ) + << '\n'; + } else { + out << TextFlow::Column( desc.name + ":" ) + .indent( 2 ) + .width( 5 + maxNameLen ) + + TextFlow::Column( desc.description ) + .initialIndent( 0 ) + .indent( 2 ) + .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 ) + << '\n'; + } + } + out << '\n' << std::flush; + } + + void defaultListTags( std::ostream& out, + std::vector const& tags, + bool isFiltered ) { + if ( isFiltered ) { + out << "Tags for matching test cases:\n"; + } else { + out << "All available tags:\n"; + } + + for ( auto const& tagCount : tags ) { + ReusableStringStream rss; + rss << " " << std::setw( 2 ) << tagCount.count << " "; + auto str = rss.str(); + auto wrapper = TextFlow::Column( tagCount.all() ) + .initialIndent( 0 ) + .indent( str.size() ) + .width( CATCH_CONFIG_CONSOLE_WIDTH - 10 ); + out << str << wrapper << '\n'; + } + out << pluralise( tags.size(), "tag" ) << '\n' << std::endl; + } + + void defaultListTests(std::ostream& out, std::vector const& tests, bool isFiltered, Verbosity verbosity) { + // We special case this to provide the equivalent of old + // `--list-test-names-only`, which could then be used by the + // `--input-file` option. + if (verbosity == Verbosity::Quiet) { + listTestNamesOnly(out, tests); + return; + } + + if (isFiltered) { + out << "Matching test cases:\n"; + } else { + out << "All available test cases:\n"; + } + + for (auto const& test : tests) { + auto const& testCaseInfo = test.getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard(colour); + + out << TextFlow::Column(testCaseInfo.name).initialIndent(2).indent(4) << '\n'; + if (verbosity >= Verbosity::High) { + out << TextFlow::Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << std::endl; + } + if (!testCaseInfo.tags.empty() && + verbosity > Verbosity::Quiet) { + out << TextFlow::Column(testCaseInfo.tagsAsString()).indent(6) << '\n'; + } + } + + if (isFiltered) { + out << pluralise(tests.size(), "matching test case") << '\n' << std::endl; + } else { + out << pluralise(tests.size(), "test case") << '\n' << std::endl; + } + } + } // namespace Catch diff --git a/src/catch2/reporters/catch_reporter_helpers.hpp b/src/catch2/reporters/catch_reporter_helpers.hpp index c86863baa1..d16d92f207 100644 --- a/src/catch2/reporters/catch_reporter_helpers.hpp +++ b/src/catch2/reporters/catch_reporter_helpers.hpp @@ -12,9 +12,13 @@ #include #include +#include +#include + namespace Catch { struct IConfig; + class TestCaseHandle; // Returns double formatted as %.3f (format expected on output) std::string getFormattedDuration( double duration ); @@ -31,6 +35,42 @@ namespace Catch { friend std::ostream& operator<<( std::ostream& out, lineOfChars value ); }; + /** + * Lists reporter descriptions to the provided stream in user-friendly + * format + * + * Used as the default listing implementation by the first party reporter + * bases. The output should be backwards compatible with the output of + * Catch2 v2 binaries. + */ + void + defaultListReporters( std::ostream& out, + std::vector const& descriptions, + Verbosity verbosity ); + + /** + * Lists tag information to the provided stream in user-friendly format + * + * Used as the default listing implementation by the first party reporter + * bases. The output should be backwards compatible with the output of + * Catch2 v2 binaries. + */ + void defaultListTags( std::ostream& out, std::vector const& tags, bool isFiltered ); + + /** + * Lists test case information to the provided stream in user-friendly + * format + * + * Used as the default listing implementation by the first party reporter + * bases. The output is backwards compatible with the output of Catch2 + * v2 binaries, and also supports the format specific to the old + * `--list-test-names-only` option, for people who used it in integrations. + */ + void defaultListTests( std::ostream& out, + std::vector const& tests, + bool isFiltered, + Verbosity verbosity ); + } // end namespace Catch #endif // CATCH_REPORTER_HELPERS_HPP_INCLUDED