Alien-catch
view release on metacpan or search on metacpan
src/catch.hpp view on Meta::CPAN
#include <cstddef>
namespace Catch {
struct Counts {
Counts operator - ( Counts const& other ) const;
Counts& operator += ( Counts const& other );
std::size_t total() const;
bool allPassed() const;
bool allOk() const;
std::size_t passed = 0;
std::size_t failed = 0;
std::size_t failedButOk = 0;
};
struct Totals {
Totals operator - ( Totals const& other ) const;
Totals& operator += ( Totals const& other );
Totals delta( Totals const& prevTotals ) const;
int error = 0;
Counts assertions;
Counts testCases;
};
}
// end catch_totals.h
#include <string>
namespace Catch {
struct SectionInfo {
SectionInfo
( SourceLineInfo const& _lineInfo,
std::string const& _name );
// Deprecated
SectionInfo
( SourceLineInfo const& _lineInfo,
std::string const& _name,
std::string const& ) : SectionInfo( _lineInfo, _name ) {}
std::string name;
std::string description; // !Deprecated: this will always be empty
SourceLineInfo lineInfo;
};
struct SectionEndInfo {
SectionInfo sectionInfo;
Counts prevAssertions;
double durationInSeconds;
};
} // end namespace Catch
// end catch_section_info.h
// start catch_timer.h
#include <cstdint>
namespace Catch {
auto getCurrentNanosecondsSinceEpoch() -> uint64_t;
auto getEstimatedClockResolution() -> uint64_t;
class Timer {
uint64_t m_nanoseconds = 0;
public:
void start();
auto getElapsedNanoseconds() const -> uint64_t;
auto getElapsedMicroseconds() const -> uint64_t;
auto getElapsedMilliseconds() const -> unsigned int;
auto getElapsedSeconds() const -> double;
};
} // namespace Catch
// end catch_timer.h
#include <string>
namespace Catch {
class Section : NonCopyable {
public:
Section( SectionInfo const& info );
~Section();
// This indicates whether the section should be executed or not
explicit operator bool() const;
private:
SectionInfo m_info;
std::string m_name;
Counts m_assertions;
bool m_sectionIncluded;
Timer m_timer;
};
} // end namespace Catch
#define INTERNAL_CATCH_SECTION( ... ) \
CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
// end catch_section.h
// start catch_benchmark.h
#include <cstdint>
#include <string>
namespace Catch {
class BenchmarkLooper {
std::string m_name;
std::size_t m_count = 0;
std::size_t m_iterationsToRun = 1;
uint64_t m_resolution;
Timer m_timer;
static auto getResolution() -> uint64_t;
public:
// Keep most of this inline as it's on the code path that is being timed
BenchmarkLooper( StringRef name )
: m_name( name ),
m_resolution( getResolution() )
{
reportStart();
m_timer.start();
}
explicit operator bool() {
if( m_count < m_iterationsToRun )
return true;
return needsMoreIterations();
}
void increment() {
++m_count;
}
void reportStart();
auto needsMoreIterations() -> bool;
};
} // end namespace Catch
#define BENCHMARK( name ) \
for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() )
// end catch_benchmark.h
// start catch_interfaces_exception.h
// start catch_interfaces_registry_hub.h
#include <string>
#include <memory>
namespace Catch {
class TestCase;
struct ITestCaseRegistry;
struct IExceptionTranslatorRegistry;
struct IExceptionTranslator;
struct IReporterRegistry;
struct IReporterFactory;
struct ITagAliasRegistry;
class StartupExceptionRegistry;
using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
struct IRegistryHub {
virtual ~IRegistryHub();
virtual IReporterRegistry const& getReporterRegistry() const = 0;
virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
};
struct IMutableRegistryHub {
virtual ~IMutableRegistryHub();
virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;
virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;
virtual void registerTest( TestCase const& testInfo ) = 0;
virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
src/catch.hpp view on Meta::CPAN
return !m_resultData.message.empty();
}
std::string AssertionResult::getExpression() const {
if( isFalseTest( m_info.resultDisposition ) )
return "!(" + m_info.capturedExpression + ")";
else
return m_info.capturedExpression;
}
std::string AssertionResult::getExpressionInMacro() const {
std::string expr;
if( m_info.macroName[0] == 0 )
expr = m_info.capturedExpression;
else {
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
expr += m_info.macroName;
expr += "( ";
expr += m_info.capturedExpression;
expr += " )";
}
return expr;
}
bool AssertionResult::hasExpandedExpression() const {
return hasExpression() && getExpandedExpression() != getExpression();
}
std::string AssertionResult::getExpandedExpression() const {
std::string expr = m_resultData.reconstructExpression();
return expr.empty()
? getExpression()
: expr;
}
std::string AssertionResult::getMessage() const {
return m_resultData.message;
}
SourceLineInfo AssertionResult::getSourceInfo() const {
return m_info.lineInfo;
}
StringRef AssertionResult::getTestMacroName() const {
return m_info.macroName;
}
} // end namespace Catch
// end catch_assertionresult.cpp
// start catch_benchmark.cpp
namespace Catch {
auto BenchmarkLooper::getResolution() -> uint64_t {
return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple();
}
void BenchmarkLooper::reportStart() {
getResultCapture().benchmarkStarting( { m_name } );
}
auto BenchmarkLooper::needsMoreIterations() -> bool {
auto elapsed = m_timer.getElapsedNanoseconds();
// Exponentially increasing iterations until we're confident in our timer resolution
if( elapsed < m_resolution ) {
m_iterationsToRun *= 10;
return true;
}
getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } );
return false;
}
} // end namespace Catch
// end catch_benchmark.cpp
// start catch_capture_matchers.cpp
namespace Catch {
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
// This is the general overload that takes a any string matcher
// There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
// the Equals matcher (so the header does not mention matchers)
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) {
std::string exceptionMessage = Catch::translateActiveException();
MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
handler.handleExpr( expr );
}
} // namespace Catch
// end catch_capture_matchers.cpp
// start catch_commandline.cpp
// start catch_commandline.h
// start catch_clara.h
// Use Catch's value for console width (store Clara's off to the side, if present)
#ifdef CLARA_CONFIG_CONSOLE_WIDTH
#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
#endif
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#pragma clang diagnostic ignored "-Wshadow"
#endif
// start clara.hpp
// Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See https://github.com/philsquared/Clara for more details
// Clara v1.1.4
#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
src/catch.hpp view on Meta::CPAN
// Don't rebuild the result -- the stringification itself can cause more fatal errors
// Instead, fake a result data.
AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
tempResult.message = message;
AssertionResult result(m_lastAssertionInfo, tempResult);
assertionEnded(result);
handleUnfinishedSections();
// Recreate section for test case (as we will lose the one that was in scope)
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
Counts assertions;
assertions.failed = 1;
SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
m_reporter->sectionEnded(testCaseSectionStats);
auto const& testInfo = m_activeTestCase->getTestCaseInfo();
Totals deltaTotals;
deltaTotals.testCases.failed = 1;
deltaTotals.assertions.failed = 1;
m_reporter->testCaseEnded(TestCaseStats(testInfo,
deltaTotals,
std::string(),
std::string(),
false));
m_totals.testCases.failed++;
testGroupEnded(std::string(), m_totals, 1, 1);
m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
}
bool RunContext::lastAssertionPassed() {
return m_lastAssertionPassed;
}
void RunContext::assertionPassed() {
m_lastAssertionPassed = true;
++m_totals.assertions.passed;
resetAssertionInfo();
}
bool RunContext::aborting() const {
return m_totals.assertions.failed == static_cast<std::size_t>(m_config->abortAfter());
}
void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
m_reporter->sectionStarting(testCaseSection);
Counts prevAssertions = m_totals.assertions;
double duration = 0;
m_shouldReportUnexpected = true;
m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
seedRng(*m_config);
Timer timer;
CATCH_TRY {
if (m_reporter->getPreferences().shouldRedirectStdOut) {
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
RedirectedStdOut redirectedStdOut;
RedirectedStdErr redirectedStdErr;
timer.start();
invokeActiveTestCase();
redirectedCout += redirectedStdOut.str();
redirectedCerr += redirectedStdErr.str();
#else
OutputRedirect r(redirectedCout, redirectedCerr);
timer.start();
invokeActiveTestCase();
#endif
} else {
timer.start();
invokeActiveTestCase();
}
duration = timer.getElapsedSeconds();
} CATCH_CATCH_ANON (TestFailureException&) {
// This just means the test was aborted due to failure
} CATCH_CATCH_ALL {
// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
// are reported without translation at the point of origin.
if( m_shouldReportUnexpected ) {
AssertionReaction dummyReaction;
handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
}
}
Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions(assertions);
m_testCaseTracker->close();
handleUnfinishedSections();
m_messages.clear();
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
m_reporter->sectionEnded(testCaseSectionStats);
}
void RunContext::invokeActiveTestCase() {
FatalConditionHandler fatalConditionHandler; // Handle signals
m_activeTestCase->invoke();
fatalConditionHandler.reset();
}
void RunContext::handleUnfinishedSections() {
// If sections ended prematurely due to an exception we stored their
// infos here so we can tear them down outside the unwind process.
for (auto it = m_unfinishedSections.rbegin(),
itEnd = m_unfinishedSections.rend();
it != itEnd;
++it)
sectionEnded(*it);
m_unfinishedSections.clear();
}
void RunContext::handleExpr(
AssertionInfo const& info,
ITransientExpression const& expr,
AssertionReaction& reaction
) {
m_reporter->assertionStarting( info );
bool negated = isFalseTest( info.resultDisposition );
bool result = expr.getResult() != negated;
if( result ) {
if (!m_includeSuccessfulResults) {
assertionPassed();
}
else {
reportExpr(info, ResultWas::Ok, &expr, negated);
}
}
else {
reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
populateReaction( reaction );
}
src/catch.hpp view on Meta::CPAN
void RunContext::handleUnexpectedInflightException(
AssertionInfo const& info,
std::string const& message,
AssertionReaction& reaction
) {
m_lastAssertionInfo = info;
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
data.message = message;
AssertionResult assertionResult{ info, data };
assertionEnded( assertionResult );
populateReaction( reaction );
}
void RunContext::populateReaction( AssertionReaction& reaction ) {
reaction.shouldDebugBreak = m_config->shouldDebugBreak();
reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
}
void RunContext::handleIncomplete(
AssertionInfo const& info
) {
m_lastAssertionInfo = info;
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
AssertionResult assertionResult{ info, data };
assertionEnded( assertionResult );
}
void RunContext::handleNonExpr(
AssertionInfo const &info,
ResultWas::OfType resultType,
AssertionReaction &reaction
) {
m_lastAssertionInfo = info;
AssertionResultData data( resultType, LazyExpression( false ) );
AssertionResult assertionResult{ info, data };
assertionEnded( assertionResult );
if( !assertionResult.isOk() )
populateReaction( reaction );
}
IResultCapture& getResultCapture() {
if (auto* capture = getCurrentContext().getResultCapture())
return *capture;
else
CATCH_INTERNAL_ERROR("No result capture instance");
}
}
// end catch_run_context.cpp
// start catch_section.cpp
namespace Catch {
Section::Section( SectionInfo const& info )
: m_info( info ),
m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
{
m_timer.start();
}
Section::~Section() {
if( m_sectionIncluded ) {
SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
if( uncaught_exceptions() )
getResultCapture().sectionEndedEarly( endInfo );
else
getResultCapture().sectionEnded( endInfo );
}
}
// This indicates whether the section should be executed or not
Section::operator bool() const {
return m_sectionIncluded;
}
} // end namespace Catch
// end catch_section.cpp
// start catch_section_info.cpp
namespace Catch {
SectionInfo::SectionInfo
( SourceLineInfo const& _lineInfo,
std::string const& _name )
: name( _name ),
lineInfo( _lineInfo )
{}
} // end namespace Catch
// end catch_section_info.cpp
// start catch_session.cpp
// start catch_session.h
#include <memory>
namespace Catch {
class Session : NonCopyable {
public:
Session();
~Session() override;
void showHelp() const;
void libIdentify();
int applyCommandLine( int argc, char const * const * argv );
void useConfigData( ConfigData const& configData );
int run( int argc, char* argv[] );
#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
int run( int argc, wchar_t* const argv[] );
#endif
int run();
clara::Parser const& cli() const;
void cli( clara::Parser const& newParser );
ConfigData& configData();
Config& config();
private:
int runInternal();
src/catch.hpp view on Meta::CPAN
}
void TestSpecParser::visitChar( char c ) {
if( m_mode == None ) {
switch( c ) {
case ' ': return;
case '~': m_exclusion = true; return;
case '[': return startNewMode( Tag, ++m_pos );
case '"': return startNewMode( QuotedName, ++m_pos );
case '\\': return escape();
default: startNewMode( Name, m_pos ); break;
}
}
if( m_mode == Name ) {
if( c == ',' ) {
addPattern<TestSpec::NamePattern>();
addFilter();
}
else if( c == '[' ) {
if( subString() == "exclude:" )
m_exclusion = true;
else
addPattern<TestSpec::NamePattern>();
startNewMode( Tag, ++m_pos );
}
else if( c == '\\' )
escape();
}
else if( m_mode == EscapedName )
m_mode = Name;
else if( m_mode == QuotedName && c == '"' )
addPattern<TestSpec::NamePattern>();
else if( m_mode == Tag && c == ']' )
addPattern<TestSpec::TagPattern>();
}
void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
m_mode = mode;
m_start = start;
}
void TestSpecParser::escape() {
if( m_mode == None )
m_start = m_pos;
m_mode = EscapedName;
m_escapeChars.push_back( m_pos );
}
std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
void TestSpecParser::addFilter() {
if( !m_currentFilter.m_patterns.empty() ) {
m_testSpec.m_filters.push_back( m_currentFilter );
m_currentFilter = TestSpec::Filter();
}
}
TestSpec parseTestSpec( std::string const& arg ) {
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
}
} // namespace Catch
// end catch_test_spec_parser.cpp
// start catch_timer.cpp
#include <chrono>
static const uint64_t nanosecondsInSecond = 1000000000;
namespace Catch {
auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
}
namespace {
auto estimateClockResolution() -> uint64_t {
uint64_t sum = 0;
static const uint64_t iterations = 1000000;
auto startTime = getCurrentNanosecondsSinceEpoch();
for( std::size_t i = 0; i < iterations; ++i ) {
uint64_t ticks;
uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
do {
ticks = getCurrentNanosecondsSinceEpoch();
} while( ticks == baseTicks );
auto delta = ticks - baseTicks;
sum += delta;
// If we have been calibrating for over 3 seconds -- the clock
// is terrible and we should move on.
// TBD: How to signal that the measured resolution is probably wrong?
if (ticks > startTime + 3 * nanosecondsInSecond) {
return sum / i;
}
}
// We're just taking the mean, here. To do better we could take the std. dev and exclude outliers
// - and potentially do more iterations if there's a high variance.
return sum/iterations;
}
}
auto getEstimatedClockResolution() -> uint64_t {
static auto s_resolution = estimateClockResolution();
return s_resolution;
}
void Timer::start() {
m_nanoseconds = getCurrentNanosecondsSinceEpoch();
}
auto Timer::getElapsedNanoseconds() const -> uint64_t {
return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;
}
auto Timer::getElapsedMicroseconds() const -> uint64_t {
return getElapsedNanoseconds()/1000;
}
auto Timer::getElapsedMilliseconds() const -> unsigned int {
return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
}
auto Timer::getElapsedSeconds() const -> double {
return getElapsedMicroseconds()/1000000.0;
}
} // namespace Catch
// end catch_timer.cpp
// start catch_tostring.cpp
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wexit-time-destructors"
# pragma clang diagnostic ignored "-Wglobal-constructors"
#endif
// Enable specific decls locally
#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
#endif
#include <cmath>
#include <iomanip>
namespace Catch {
namespace Detail {
const std::string unprintableString = "{?}";
namespace {
const int hexThreshold = 255;
struct Endianness {
enum Arch { Big, Little };
static Arch which() {
union _{
int asInt;
char asChar[sizeof (int)];
} u;
u.asInt = 1;
return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
}
};
}
std::string rawMemoryToString( const void *object, std::size_t size ) {
// Reverse order for little endian architectures
int i = 0, end = static_cast<int>( size ), inc = 1;
if( Endianness::which() == Endianness::Little ) {
i = end-1;
end = inc = -1;
}
unsigned char const *bytes = static_cast<unsigned char const *>(object);
ReusableStringStream rss;
rss << "0x" << std::setfill('0') << std::hex;
for( ; i != end; i += inc )
rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
return rss.str();
}
}
template<typename T>
std::string fpToString( T value, int precision ) {
if (std::isnan(value)) {
( run in 1.739 second using v1.01-cache-2.11-cpan-acebb50784d )