| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 | 
							- #include "catch_run_context.h"
 
- #include "catch_compiler_capabilities.h"
 
- #include "catch_context.h"
 
- #include "catch_enforce.h"
 
- #include "catch_random_number_generator.h"
 
- #include "catch_stream.h"
 
- #include "catch_output_redirect.h"
 
- #include <cassert>
 
- #include <algorithm>
 
- #include <sstream>
 
- namespace Catch {
 
-     namespace Generators {
 
-         struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
 
-             GeneratorBasePtr m_generator;
 
-             GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
 
-             :   TrackerBase( nameAndLocation, ctx, parent )
 
-             {}
 
-             ~GeneratorTracker();
 
-             static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
 
-                 std::shared_ptr<GeneratorTracker> tracker;
 
-                 ITracker& currentTracker = ctx.currentTracker();
 
-                 // Under specific circumstances, the generator we want
 
-                 // to acquire is also the current tracker. If this is
 
-                 // the case, we have to avoid looking through current
 
-                 // tracker's children, and instead return the current
 
-                 // tracker.
 
-                 // A case where this check is important is e.g.
 
-                 //     for (int i = 0; i < 5; ++i) {
 
-                 //         int n = GENERATE(1, 2);
 
-                 //     }
 
-                 //
 
-                 // without it, the code above creates 5 nested generators.
 
-                 if (currentTracker.nameAndLocation() == nameAndLocation) {
 
-                     auto thisTracker = currentTracker.parent().findChild(nameAndLocation);
 
-                     assert(thisTracker);
 
-                     assert(thisTracker->isGeneratorTracker());
 
-                     tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker);
 
-                 } else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
 
-                     assert( childTracker );
 
-                     assert( childTracker->isGeneratorTracker() );
 
-                     tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
 
-                 } else {
 
-                     tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker );
 
-                     currentTracker.addChild( tracker );
 
-                 }
 
-                 if( !tracker->isComplete() ) {
 
-                     tracker->open();
 
-                 }
 
-                 return *tracker;
 
-             }
 
-             // TrackerBase interface
 
-             bool isGeneratorTracker() const override { return true; }
 
-             auto hasGenerator() const -> bool override {
 
-                 return !!m_generator;
 
-             }
 
-             void close() override {
 
-                 TrackerBase::close();
 
-                 // If a generator has a child (it is followed by a section)
 
-                 // and none of its children have started, then we must wait
 
-                 // until later to start consuming its values.
 
-                 // This catches cases where `GENERATE` is placed between two
 
-                 // `SECTION`s.
 
-                 // **The check for m_children.empty cannot be removed**.
 
-                 // doing so would break `GENERATE` _not_ followed by `SECTION`s.
 
-                 const bool should_wait_for_child = [&]() {
 
-                     // No children -> nobody to wait for
 
-                     if ( m_children.empty() ) {
 
-                         return false;
 
-                     }
 
-                     // If at least one child started executing, don't wait
 
-                     if ( std::find_if(
 
-                              m_children.begin(),
 
-                              m_children.end(),
 
-                              []( TestCaseTracking::ITrackerPtr tracker ) {
 
-                                  return tracker->hasStarted();
 
-                              } ) != m_children.end() ) {
 
-                         return false;
 
-                     }
 
-                     // No children have started. We need to check if they _can_
 
-                     // start, and thus we should wait for them, or they cannot
 
-                     // start (due to filters), and we shouldn't wait for them
 
-                     auto* parent = m_parent;
 
-                     // This is safe: there is always at least one section
 
-                     // tracker in a test case tracking tree
 
-                     while ( !parent->isSectionTracker() ) {
 
-                         parent = &( parent->parent() );
 
-                     }
 
-                     assert( parent &&
 
-                             "Missing root (test case) level section" );
 
-                     auto const& parentSection =
 
-                         static_cast<SectionTracker&>( *parent );
 
-                     auto const& filters = parentSection.getFilters();
 
-                     // No filters -> no restrictions on running sections
 
-                     if ( filters.empty() ) {
 
-                         return true;
 
-                     }
 
-                     for ( auto const& child : m_children ) {
 
-                         if ( child->isSectionTracker() &&
 
-                              std::find( filters.begin(),
 
-                                         filters.end(),
 
-                                         static_cast<SectionTracker&>( *child )
 
-                                             .trimmedName() ) !=
 
-                                  filters.end() ) {
 
-                             return true;
 
-                         }
 
-                     }
 
-                     return false;
 
-                 }();
 
-                 // This check is a bit tricky, because m_generator->next()
 
-                 // has a side-effect, where it consumes generator's current
 
-                 // value, but we do not want to invoke the side-effect if
 
-                 // this generator is still waiting for any child to start.
 
-                 if ( should_wait_for_child ||
 
-                      ( m_runState == CompletedSuccessfully &&
 
-                        m_generator->next() ) ) {
 
-                     m_children.clear();
 
-                     m_runState = Executing;
 
-                 }
 
-             }
 
-             // IGeneratorTracker interface
 
-             auto getGenerator() const -> GeneratorBasePtr const& override {
 
-                 return m_generator;
 
-             }
 
-             void setGenerator( GeneratorBasePtr&& generator ) override {
 
-                 m_generator = std::move( generator );
 
-             }
 
-         };
 
-         GeneratorTracker::~GeneratorTracker() {}
 
-     }
 
-     RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
 
-     :   m_runInfo(_config->name()),
 
-         m_context(getCurrentMutableContext()),
 
-         m_config(_config),
 
-         m_reporter(std::move(reporter)),
 
-         m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
 
-         m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
 
-     {
 
-         m_context.setRunner(this);
 
-         m_context.setConfig(m_config);
 
-         m_context.setResultCapture(this);
 
-         m_reporter->testRunStarting(m_runInfo);
 
-     }
 
-     RunContext::~RunContext() {
 
-         m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
 
-     }
 
-     void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
 
-         m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
 
-     }
 
-     void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {
 
-         m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
 
-     }
 
-     Totals RunContext::runTest(TestCase const& testCase) {
 
-         Totals prevTotals = m_totals;
 
-         std::string redirectedCout;
 
-         std::string redirectedCerr;
 
-         auto const& testInfo = testCase.getTestCaseInfo();
 
-         m_reporter->testCaseStarting(testInfo);
 
-         m_activeTestCase = &testCase;
 
-         ITracker& rootTracker = m_trackerContext.startRun();
 
-         assert(rootTracker.isSectionTracker());
 
-         static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
 
-         do {
 
-             m_trackerContext.startCycle();
 
-             m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
 
-             runCurrentTest(redirectedCout, redirectedCerr);
 
-         } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
 
-         Totals deltaTotals = m_totals.delta(prevTotals);
 
-         if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
 
-             deltaTotals.assertions.failed++;
 
-             deltaTotals.testCases.passed--;
 
-             deltaTotals.testCases.failed++;
 
-         }
 
-         m_totals.testCases += deltaTotals.testCases;
 
-         m_reporter->testCaseEnded(TestCaseStats(testInfo,
 
-                                   deltaTotals,
 
-                                   redirectedCout,
 
-                                   redirectedCerr,
 
-                                   aborting()));
 
-         m_activeTestCase = nullptr;
 
-         m_testCaseTracker = nullptr;
 
-         return deltaTotals;
 
-     }
 
-     IConfigPtr RunContext::config() const {
 
-         return m_config;
 
-     }
 
-     IStreamingReporter& RunContext::reporter() const {
 
-         return *m_reporter;
 
-     }
 
-     void RunContext::assertionEnded(AssertionResult const & result) {
 
-         if (result.getResultType() == ResultWas::Ok) {
 
-             m_totals.assertions.passed++;
 
-             m_lastAssertionPassed = true;
 
-         } else if (!result.isOk()) {
 
-             m_lastAssertionPassed = false;
 
-             if( m_activeTestCase->getTestCaseInfo().okToFail() )
 
-                 m_totals.assertions.failedButOk++;
 
-             else
 
-                 m_totals.assertions.failed++;
 
-         }
 
-         else {
 
-             m_lastAssertionPassed = true;
 
-         }
 
-         // We have no use for the return value (whether messages should be cleared), because messages were made scoped
 
-         // and should be let to clear themselves out.
 
-         static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
 
-         if (result.getResultType() != ResultWas::Warning)
 
-             m_messageScopes.clear();
 
-         // Reset working state
 
-         resetAssertionInfo();
 
-         m_lastResult = result;
 
-     }
 
-     void RunContext::resetAssertionInfo() {
 
-         m_lastAssertionInfo.macroName = StringRef();
 
-         m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
 
-     }
 
-     bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {
 
-         ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
 
-         if (!sectionTracker.isOpen())
 
-             return false;
 
-         m_activeSections.push_back(§ionTracker);
 
-         m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
 
-         m_reporter->sectionStarting(sectionInfo);
 
-         assertions = m_totals.assertions;
 
-         return true;
 
-     }
 
-     auto RunContext::acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
 
-         using namespace Generators;
 
-         GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext,
 
-                                                               TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) );
 
-         m_lastAssertionInfo.lineInfo = lineInfo;
 
-         return tracker;
 
-     }
 
-     bool RunContext::testForMissingAssertions(Counts& assertions) {
 
-         if (assertions.total() != 0)
 
-             return false;
 
-         if (!m_config->warnAboutMissingAssertions())
 
-             return false;
 
-         if (m_trackerContext.currentTracker().hasChildren())
 
-             return false;
 
-         m_totals.assertions.failed++;
 
-         assertions.failed++;
 
-         return true;
 
-     }
 
-     void RunContext::sectionEnded(SectionEndInfo const & endInfo) {
 
-         Counts assertions = m_totals.assertions - endInfo.prevAssertions;
 
-         bool missingAssertions = testForMissingAssertions(assertions);
 
-         if (!m_activeSections.empty()) {
 
-             m_activeSections.back()->close();
 
-             m_activeSections.pop_back();
 
-         }
 
-         m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
 
-         m_messages.clear();
 
-         m_messageScopes.clear();
 
-     }
 
-     void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
 
-         if (m_unfinishedSections.empty())
 
-             m_activeSections.back()->fail();
 
-         else
 
-             m_activeSections.back()->close();
 
-         m_activeSections.pop_back();
 
-         m_unfinishedSections.push_back(endInfo);
 
-     }
 
- #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
 
-     void RunContext::benchmarkPreparing(std::string const& name) {
 
-         m_reporter->benchmarkPreparing(name);
 
-     }
 
-     void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
 
-         m_reporter->benchmarkStarting( info );
 
-     }
 
-     void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
 
-         m_reporter->benchmarkEnded( stats );
 
-     }
 
-     void RunContext::benchmarkFailed(std::string const & error) {
 
-         m_reporter->benchmarkFailed(error);
 
-     }
 
- #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
 
-     void RunContext::pushScopedMessage(MessageInfo const & message) {
 
-         m_messages.push_back(message);
 
-     }
 
-     void RunContext::popScopedMessage(MessageInfo const & message) {
 
-         m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
 
-     }
 
-     void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
 
-         m_messageScopes.emplace_back( builder );
 
-     }
 
-     std::string RunContext::getCurrentTestName() const {
 
-         return m_activeTestCase
 
-             ? m_activeTestCase->getTestCaseInfo().name
 
-             : std::string();
 
-     }
 
-     const AssertionResult * RunContext::getLastResult() const {
 
-         return &(*m_lastResult);
 
-     }
 
-     void RunContext::exceptionEarlyReported() {
 
-         m_shouldReportUnexpected = false;
 
-     }
 
-     void RunContext::handleFatalErrorCondition( StringRef message ) {
 
-         // First notify reporter that bad things happened
 
-         m_reporter->fatalErrorEncountered(message);
 
-         // 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 = static_cast<std::string>(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();
 
-         m_messageScopes.clear();
 
-     }
 
-     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)
 
-                 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
 
-                 timer.start();
 
-                 invokeActiveTestCase();
 
- #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();
 
-         m_messageScopes.clear();
 
-         SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
 
-         m_reporter->sectionEnded(testCaseSectionStats);
 
-     }
 
-     void RunContext::invokeActiveTestCase() {
 
-         FatalConditionHandlerGuard _(&m_fatalConditionhandler);
 
-         m_activeTestCase->invoke();
 
-     }
 
-     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 );
 
-         }
 
-     }
 
-     void RunContext::reportExpr(
 
-             AssertionInfo const &info,
 
-             ResultWas::OfType resultType,
 
-             ITransientExpression const *expr,
 
-             bool negated ) {
 
-         m_lastAssertionInfo = info;
 
-         AssertionResultData data( resultType, LazyExpression( negated ) );
 
-         AssertionResult assertionResult{ info, data };
 
-         assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
 
-         assertionEnded( assertionResult );
 
-     }
 
-     void RunContext::handleMessage(
 
-             AssertionInfo const& info,
 
-             ResultWas::OfType resultType,
 
-             StringRef const& message,
 
-             AssertionReaction& reaction
 
-     ) {
 
-         m_reporter->assertionStarting( info );
 
-         m_lastAssertionInfo = info;
 
-         AssertionResultData data( resultType, LazyExpression( false ) );
 
-         data.message = static_cast<std::string>(message);
 
-         AssertionResult assertionResult{ m_lastAssertionInfo, data };
 
-         assertionEnded( assertionResult );
 
-         if( !assertionResult.isOk() )
 
-             populateReaction( reaction );
 
-     }
 
-     void RunContext::handleUnexpectedExceptionNotThrown(
 
-             AssertionInfo const& info,
 
-             AssertionReaction& reaction
 
-     ) {
 
-         handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
 
-     }
 
-     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");
 
-     }
 
-     void seedRng(IConfig const& config) {
 
-         if (config.rngSeed() != 0) {
 
-             std::srand(config.rngSeed());
 
-             rng().seed(config.rngSeed());
 
-         }
 
-     }
 
-     unsigned int rngSeed() {
 
-         return getCurrentContext().getConfig()->rngSeed();
 
-     }
 
- }
 
 
  |