Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The output of --list-* flags obeys -o flag #2163

Merged
merged 5 commits into from Jan 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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