Skip to content

Commit

Permalink
Merge pull request #2163 from catchorg/devel-list-outputs-to-out-flag
Browse files Browse the repository at this point in the history
The output of --list-* flags obeys -o flag
  • Loading branch information
horenmar committed Jan 27, 2021
2 parents ba81505 + 971b1fc commit b435e39
Show file tree
Hide file tree
Showing 26 changed files with 2,177 additions and 171 deletions.
2 changes: 1 addition & 1 deletion src/catch2/catch_session.cpp
Expand Up @@ -48,7 +48,7 @@ namespace Catch {
// doesn't compile without a std::move call. However, this causes
// a warning on newer platforms. Thus, we have to work around
// it a bit and downcast the pointer manually.
auto ret = Detail::unique_ptr<IStreamingReporter>(new ListeningReporter);
auto ret = Detail::unique_ptr<IStreamingReporter>(new ListeningReporter(config));
auto& multi = static_cast<ListeningReporter&>(*ret);
auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
for (auto const& listener : listeners) {
Expand Down
106 changes: 1 addition & 105 deletions src/catch2/interfaces/catch_interfaces_reporter.cpp
Expand Up @@ -11,34 +11,15 @@
#include <catch2/internal/catch_console_width.hpp>
#include <catch2/catch_message.hpp>
#include <catch2/internal/catch_list.hpp>
#include <catch2/internal/catch_textflow.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/catch_test_case_info.hpp>
#include <catch2/internal/catch_textflow.hpp>
#include <catch2/reporters/catch_reporter_helpers.hpp>

#include <algorithm>
#include <iomanip>

namespace Catch {

namespace {
void listTestNamesOnly( std::vector<TestCaseHandle> 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 ) {}

Expand Down Expand Up @@ -127,89 +108,4 @@ namespace Catch {

void IStreamingReporter::fatalErrorEncountered( StringRef ) {}

void IStreamingReporter::listReporters(std::vector<ReporterDescription> const& descriptions, IConfig const& config) {
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 (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;
}

void IStreamingReporter::listTests(std::vector<TestCaseHandle> const& tests, IConfig const& config) {
// 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 (config.verbosity() == Verbosity::Quiet) {
listTestNamesOnly(tests);
return;
}

if (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 (config.verbosity() >= Verbosity::High) {
Catch::cout() << TextFlow::Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << std::endl;
}
if (!testCaseInfo.tags.empty() && config.verbosity() > Verbosity::Quiet) {
Catch::cout() << TextFlow::Column(testCaseInfo.tagsAsString()).indent(6) << '\n';
}
}

if (!config.hasTestFilters()) {
Catch::cout() << pluralise(tests.size(), "test case") << '\n' << std::endl;
} else {
Catch::cout() << pluralise(tests.size(), "matching test case") << '\n' << std::endl;
}
}

void IStreamingReporter::listTags(std::vector<TagInfo> const& tags, IConfig const& config) {
if (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;
}

} // end namespace Catch
11 changes: 8 additions & 3 deletions src/catch2/interfaces/catch_interfaces_reporter.hpp
Expand Up @@ -176,7 +176,12 @@ namespace Catch {
protected:
//! Derived classes can set up their preferences here
ReporterPreferences m_preferences;
//! The test run's config as filled in from CLI and defaults
IConfig const* m_config;

public:
IStreamingReporter( IConfig const* config ): m_config( config ) {}

virtual ~IStreamingReporter() = default;

// Implementing class must also provide the following static methods:
Expand Down Expand Up @@ -217,11 +222,11 @@ namespace Catch {
virtual void fatalErrorEncountered( StringRef name );

//! Writes out information about provided reporters using reporter-specific format
virtual void listReporters(std::vector<ReporterDescription> const& descriptions, IConfig const& config);
virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0;
//! Writes out information about provided tests using reporter-specific format
virtual void listTests(std::vector<TestCaseHandle> const& tests, IConfig const& config);
virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0;
//! Writes out information about the provided tags using reporter-specific format
virtual void listTags(std::vector<TagInfo> const& tags, IConfig const& config);
virtual void listTags(std::vector<TagInfo> const& tags) = 0;

};
using IStreamingReporterPtr = Detail::unique_ptr<IStreamingReporter>;
Expand Down
10 changes: 5 additions & 5 deletions src/catch2/internal/catch_list.cpp
Expand Up @@ -24,7 +24,7 @@ namespace Catch {
void listTests(IStreamingReporter& reporter, IConfig const& config) {
auto const& testSpec = config.testSpec();
auto matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
reporter.listTests(matchedTestCases, config);
reporter.listTests(matchedTestCases);
}

void listTags(IStreamingReporter& reporter, IConfig const& config) {
Expand All @@ -46,10 +46,10 @@ namespace Catch {
infos.push_back(std::move(tagc.second));
}

reporter.listTags(infos, config);
reporter.listTags(infos);
}

void listReporters(IStreamingReporter& reporter, IConfig const& config) {
void listReporters(IStreamingReporter& reporter) {
std::vector<ReporterDescription> descriptions;

IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
Expand All @@ -58,7 +58,7 @@ namespace Catch {
descriptions.push_back({ fac.first, fac.second->getDescription() });
}

reporter.listReporters(descriptions, config);
reporter.listReporters(descriptions);
}

} // end anonymous namespace
Expand Down Expand Up @@ -96,7 +96,7 @@ namespace Catch {
}
if (config.listReporters()) {
listed = true;
listReporters(reporter, config);
listReporters(reporter);
}
return listed;
}
Expand Down
135 changes: 127 additions & 8 deletions src/catch2/reporters/catch_reporter_combined_tu.cpp
Expand Up @@ -21,13 +21,40 @@
#include <catch2/interfaces/catch_interfaces_config.hpp>
#include <catch2/internal/catch_console_width.hpp>
#include <catch2/internal/catch_errno_guard.hpp>

#include <catch2/internal/catch_textflow.hpp>
#include <catch2/internal/catch_stream.hpp>
#include <catch2/internal/catch_string_manip.hpp>
#include <catch2/internal/catch_console_colour.hpp>
#include <catch2/catch_tostring.hpp>
#include <catch2/catch_test_case_info.hpp>

#include <algorithm>
#include <cfloat>
#include <cstdio>
#include <ostream>
#include <iomanip>

namespace Catch {

namespace {
void listTestNamesOnly(std::ostream& out,
std::vector<TestCaseHandle> 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.
Expand Down Expand Up @@ -89,6 +116,101 @@ namespace Catch {
return out;
}

void
defaultListReporters( std::ostream& out,
std::vector<ReporterDescription> 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<TagInfo> 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<TestCaseHandle> 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


Expand All @@ -100,13 +222,10 @@ namespace Catch {
bool EventListenerBase::assertionEnded( AssertionStats const& ) {
return false;
}
void
EventListenerBase::listReporters( std::vector<ReporterDescription> const&,
IConfig const& ) {}
void EventListenerBase::listTests( std::vector<TestCaseHandle> const&,
IConfig const& ) {}
void EventListenerBase::listTags( std::vector<TagInfo> const&,
IConfig const& ) {}
void EventListenerBase::listReporters(
std::vector<ReporterDescription> const& ) {}
void EventListenerBase::listTests( std::vector<TestCaseHandle> const& ) {}
void EventListenerBase::listTags( std::vector<TagInfo> const& ) {}
void EventListenerBase::noMatchingTestCases( std::string const& ) {}
void EventListenerBase::testRunStarting( TestRunInfo const& ) {}
void EventListenerBase::testGroupStarting( GroupInfo const& ) {}
Expand Down
16 changes: 16 additions & 0 deletions src/catch2/reporters/catch_reporter_cumulative_base.cpp
Expand Up @@ -6,6 +6,7 @@

// SPDX-License-Identifier: BSL-1.0
#include <catch2/reporters/catch_reporter_cumulative_base.hpp>
#include <catch2/reporters/catch_reporter_helpers.hpp>

#include <algorithm>
#include <cassert>
Expand Down Expand Up @@ -110,4 +111,19 @@ namespace Catch {
testRunEndedCumulative();
}

void CumulativeReporterBase::listReporters(std::vector<ReporterDescription> const& descriptions) {
defaultListReporters(stream, descriptions, m_config->verbosity());
}

void CumulativeReporterBase::listTests(std::vector<TestCaseHandle> const& tests) {
defaultListTests(stream,
tests,
m_config->hasTestFilters(),
m_config->verbosity());
}

void CumulativeReporterBase::listTags(std::vector<TagInfo> const& tags) {
defaultListTags( stream, tags, m_config->hasTestFilters() );
}

} // end namespace Catch

0 comments on commit b435e39

Please sign in to comment.