Skip to content

Commit 09c6bd4

Browse files
committed
Report generator states for failed assertions
1 parent 997a7d4 commit 09c6bd4

16 files changed

+2719
-5
lines changed

examples/311-Gen-CustomCapture.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ TEST_CASE("Generate random doubles across different ranges",
2929
// This will take r1 by reference and r2 by value.
3030
// Note that there are no advantages for doing so in this example,
3131
// it is done only for expository purposes.
32-
auto number = Catch::Generators::generate( "custom capture generator", CATCH_INTERNAL_LINEINFO,
32+
auto number = Catch::Generators::generate( "custom capture generator", "custom definition", CATCH_INTERNAL_LINEINFO,
3333
[&r1, r2]{
3434
using namespace Catch::Generators;
3535
return makeGenerators(take(50, random(std::get<0>(r1), std::get<1>(r2))));

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ set(INTERNAL_HEADERS
111111
${SOURCES_DIR}/matchers/catch_matchers_templated.hpp
112112
${SOURCES_DIR}/matchers/catch_matchers_vector.hpp
113113
${SOURCES_DIR}/catch_message.hpp
114+
${SOURCES_DIR}/internal/catch_generator_info.hpp
114115
${SOURCES_DIR}/internal/catch_message_info.hpp
115116
${SOURCES_DIR}/internal/catch_meta.hpp
116117
${SOURCES_DIR}/internal/catch_move_and_forward.hpp
@@ -234,6 +235,7 @@ set(IMPL_SOURCES
234235
${SOURCES_DIR}/internal/catch_errno_guard.cpp
235236
${SOURCES_DIR}/internal/catch_lazy_expr.cpp
236237
${SOURCES_DIR}/internal/catch_leak_detector.cpp
238+
${SOURCES_DIR}/internal/catch_generator_info.cpp
237239
${SOURCES_DIR}/internal/catch_message_info.cpp
238240
${SOURCES_DIR}/internal/catch_polyfills.cpp
239241
${SOURCES_DIR}/internal/catch_startup_exception_registry.cpp

src/catch2/catch_all.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include <catch2/internal/catch_exception_translator_registry.hpp>
6868
#include <catch2/internal/catch_fatal_condition_handler.hpp>
6969
#include <catch2/internal/catch_floating_point_helpers.hpp>
70+
#include <catch2/internal/catch_generator_info.hpp>
7071
#include <catch2/internal/catch_istream.hpp>
7172
#include <catch2/internal/catch_lazy_expr.hpp>
7273
#include <catch2/internal/catch_leak_detector.hpp>

src/catch2/generators/catch_generators.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
#ifndef CATCH_GENERATORS_HPP_INCLUDED
99
#define CATCH_GENERATORS_HPP_INCLUDED
1010

11+
#include "catch2/interfaces/catch_interfaces_capture.hpp"
1112
#include <catch2/catch_tostring.hpp>
1213
#include <catch2/interfaces/catch_interfaces_generatortracker.hpp>
14+
#include <catch2/internal/catch_generator_info.hpp>
1315
#include <catch2/internal/catch_source_line_info.hpp>
1416
#include <catch2/internal/catch_stringref.hpp>
1517
#include <catch2/internal/catch_move_and_forward.hpp>
@@ -210,7 +212,7 @@ namespace Detail {
210212
// Note: The type after -> is weird, because VS2015 cannot parse
211213
// the expression used in the typedef inside, when it is in
212214
// return type. Yeah.
213-
auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
215+
auto generate( StringRef generatorName, StringRef definition, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
214216
using UnderlyingType = typename decltype(generatorExpression())::type;
215217

216218
IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo );
@@ -219,6 +221,7 @@ namespace Detail {
219221
}
220222

221223
auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );
224+
getResultCapture().trackGeneratorState(GeneratorInfo(definition, lineInfo, generator.currentElementAsString()));
222225
return generator.get();
223226
}
224227

@@ -227,14 +230,17 @@ namespace Detail {
227230

228231
#define GENERATE( ... ) \
229232
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
233+
INTERNAL_CATCH_STRINGIZE( __VA_ARGS__ ), \
230234
CATCH_INTERNAL_LINEINFO, \
231235
[ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
232236
#define GENERATE_COPY( ... ) \
233237
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
238+
INTERNAL_CATCH_STRINGIZE( __VA_ARGS__ ), \
234239
CATCH_INTERNAL_LINEINFO, \
235240
[=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
236241
#define GENERATE_REF( ... ) \
237242
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
243+
INTERNAL_CATCH_STRINGIZE( __VA_ARGS__ ), \
238244
CATCH_INTERNAL_LINEINFO, \
239245
[&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
240246

src/catch2/interfaces/catch_interfaces_capture.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace Catch {
2020
struct AssertionInfo;
2121
struct SectionInfo;
2222
struct SectionEndInfo;
23+
struct GeneratorInfo;
2324
struct MessageInfo;
2425
struct MessageBuilder;
2526
struct Counts;
@@ -43,6 +44,7 @@ namespace Catch {
4344
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
4445

4546
virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
47+
virtual void trackGeneratorState( GeneratorInfo info ) = 0;
4648

4749
virtual void benchmarkPreparing( StringRef name ) = 0;
4850
virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;

src/catch2/interfaces/catch_interfaces_reporter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// https://www.boost.org/LICENSE_1_0.txt)
66

77
// SPDX-License-Identifier: BSL-1.0
8+
#include "catch2/interfaces/catch_interfaces_capture.hpp"
89
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
910
#include <catch2/interfaces/catch_interfaces_config.hpp>
1011
#include <catch2/internal/catch_console_colour.hpp>
@@ -49,9 +50,11 @@ namespace Catch {
4950

5051
AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
5152
std::vector<MessageInfo> const& _infoMessages,
53+
std::vector<GeneratorInfo> const& _generatorInfos,
5254
Totals const& _totals )
5355
: assertionResult( _assertionResult ),
5456
infoMessages( _infoMessages ),
57+
generatorInfos( _generatorInfos ),
5558
totals( _totals )
5659
{
5760
assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;

src/catch2/interfaces/catch_interfaces_reporter.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
#ifndef CATCH_INTERFACES_REPORTER_HPP_INCLUDED
99
#define CATCH_INTERFACES_REPORTER_HPP_INCLUDED
1010

11+
#include "catch2/interfaces/catch_interfaces_capture.hpp"
1112
#include <catch2/catch_section_info.hpp>
1213
#include <catch2/catch_totals.hpp>
1314
#include <catch2/catch_assertion_result.hpp>
1415
#include <catch2/internal/catch_message_info.hpp>
16+
#include <catch2/internal/catch_generator_info.hpp>
1517
#include <catch2/internal/catch_stringref.hpp>
1618
#include <catch2/internal/catch_unique_ptr.hpp>
1719
#include <catch2/internal/catch_move_and_forward.hpp>
@@ -65,6 +67,7 @@ namespace Catch {
6567
struct AssertionStats {
6668
AssertionStats( AssertionResult const& _assertionResult,
6769
std::vector<MessageInfo> const& _infoMessages,
70+
std::vector<GeneratorInfo> const& _generatorInfos,
6871
Totals const& _totals );
6972

7073
AssertionStats( AssertionStats const& ) = default;
@@ -74,6 +77,7 @@ namespace Catch {
7477

7578
AssertionResult assertionResult;
7679
std::vector<MessageInfo> infoMessages;
80+
std::vector<GeneratorInfo> generatorInfos;
7781
Totals totals;
7882
};
7983

src/catch2/internal/catch_console_colour.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ namespace Catch {
5050

5151
OriginalExpression = Cyan,
5252
ReconstructedExpression = BrightYellow,
53+
GeneratorValue = Cyan,
5354

5455
SecondaryText = LightGrey,
5556
Headers = White
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
// Copyright Catch2 Authors
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// (See accompanying file LICENSE_1_0.txt or copy at
5+
// https://www.boost.org/LICENSE_1_0.txt)
6+
7+
// SPDX-License-Identifier: BSL-1.0
8+
9+
#include <catch2/internal/catch_generator_info.hpp>
10+
11+
namespace Catch {
12+
13+
GeneratorInfo::GeneratorInfo( StringRef _definition,
14+
SourceLineInfo const& _lineInfo,
15+
StringRef _currentElement ):
16+
definition( _definition ),
17+
lineInfo( _lineInfo ),
18+
currentElement( _currentElement ) {}
19+
20+
} // end namespace Catch
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
// Copyright Catch2 Authors
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// (See accompanying file LICENSE_1_0.txt or copy at
5+
// https://www.boost.org/LICENSE_1_0.txt)
6+
7+
// SPDX-License-Identifier: BSL-1.0
8+
#ifndef CATCH_GENERATOR_INFO_HPP_INCLUDED
9+
#define CATCH_GENERATOR_INFO_HPP_INCLUDED
10+
11+
#include <catch2/interfaces/catch_interfaces_capture.hpp>
12+
#include <catch2/internal/catch_source_line_info.hpp>
13+
#include <string>
14+
15+
namespace Catch {
16+
17+
struct GeneratorInfo {
18+
GeneratorInfo( StringRef _definition,
19+
SourceLineInfo const& _lineInfo,
20+
StringRef currentElement );
21+
22+
StringRef definition;
23+
SourceLineInfo lineInfo;
24+
StringRef currentElement;
25+
26+
bool operator==( GeneratorInfo const& other ) const {
27+
return definition == other.definition &&
28+
lineInfo == other.lineInfo &&
29+
currentElement == other.currentElement;
30+
}
31+
};
32+
33+
} // end namespace Catch
34+
35+
#endif // CATCH_GENERATOR_INFO_HPP_INCLUDED

src/catch2/internal/catch_run_context.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ namespace Catch {
283283
m_lastAssertionPassed = true;
284284
}
285285

286-
m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals));
286+
m_reporter->assertionEnded(AssertionStats(result, m_messages, m_generatorInfos, m_totals));
287287

288288
if (result.getResultType() != ResultWas::Warning)
289289
m_messageScopes.clear();
@@ -319,6 +319,16 @@ namespace Catch {
319319
return tracker;
320320
}
321321

322+
void RunContext::trackGeneratorState( GeneratorInfo info ) {
323+
// Avoid redundant entries, in case a generator is used within a loop.
324+
if ( std::find( m_generatorInfos.cbegin(),
325+
m_generatorInfos.cend(),
326+
info ) != m_generatorInfos.cend() )
327+
return;
328+
329+
m_generatorInfos.push_back( info );
330+
}
331+
322332
bool RunContext::testForMissingAssertions(Counts& assertions) {
323333
if (assertions.total() != 0)
324334
return false;
@@ -343,6 +353,7 @@ namespace Catch {
343353
m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
344354
m_messages.clear();
345355
m_messageScopes.clear();
356+
m_generatorInfos.clear();
346357
}
347358

348359
void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
@@ -490,6 +501,7 @@ namespace Catch {
490501
handleUnfinishedSections();
491502
m_messages.clear();
492503
m_messageScopes.clear();
504+
m_generatorInfos.clear();
493505

494506
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
495507
m_reporter->sectionEnded(testCaseSectionStats);

src/catch2/internal/catch_run_context.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef CATCH_RUN_CONTEXT_HPP_INCLUDED
99
#define CATCH_RUN_CONTEXT_HPP_INCLUDED
1010

11+
#include "catch2/interfaces/catch_interfaces_capture.hpp"
1112
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
1213
#include <catch2/internal/catch_test_registry.hpp>
1314
#include <catch2/internal/catch_fatal_condition_handler.hpp>
@@ -74,6 +75,7 @@ namespace Catch {
7475
void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
7576

7677
auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;
78+
void trackGeneratorState( GeneratorInfo info ) override;
7779

7880
void benchmarkPreparing( StringRef name ) override;
7981
void benchmarkStarting( BenchmarkInfo const& info ) override;
@@ -132,6 +134,7 @@ namespace Catch {
132134
Totals m_totals;
133135
IEventListenerPtr m_reporter;
134136
std::vector<MessageInfo> m_messages;
137+
std::vector<GeneratorInfo> m_generatorInfos;
135138
std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
136139
AssertionInfo m_lastAssertionInfo;
137140
std::vector<SectionEndInfo> m_unfinishedSections;

src/catch2/reporters/catch_reporter_console.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class ConsoleAssertionPrinter {
126126
printResultType();
127127
printOriginalExpression();
128128
printReconstructedExpression();
129+
printGeneratorStates();
129130
} else {
130131
stream << '\n';
131132
}
@@ -153,6 +154,22 @@ class ConsoleAssertionPrinter {
153154
<< '\n';
154155
}
155156
}
157+
void printGeneratorStates() const {
158+
if ( stats.generatorInfos.empty() ) {
159+
return;
160+
}
161+
162+
stream << "with " << pluralise(stats.generatorInfos.size(), "generator"_sr) << "\n";
163+
for ( auto const& info : stats.generatorInfos ) {
164+
stream << TextFlow::Column( "line:" ).indent( 2 )
165+
<< info.lineInfo.line << ": "
166+
<< "GENERATE(" << static_cast<std::string>( info.definition )
167+
<< ")\n"
168+
<< TextFlow::Column( "value: " ).indent( 2 )
169+
<< colourImpl->guardColour( Colour::GeneratorValue )
170+
<< info.currentElement << "\n";
171+
}
172+
}
156173
void printMessage() const {
157174
if (!messageLabel.empty())
158175
stream << messageLabel << ':' << '\n';

0 commit comments

Comments
 (0)