catch_run_context.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. #include "catch_run_context.h"
  2. #include "catch_compiler_capabilities.h"
  3. #include "catch_context.h"
  4. #include "catch_enforce.h"
  5. #include "catch_random_number_generator.h"
  6. #include "catch_stream.h"
  7. #include "catch_output_redirect.h"
  8. #include <cassert>
  9. #include <algorithm>
  10. #include <sstream>
  11. namespace Catch {
  12. namespace Generators {
  13. struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
  14. GeneratorBasePtr m_generator;
  15. GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
  16. : TrackerBase( nameAndLocation, ctx, parent )
  17. {}
  18. ~GeneratorTracker();
  19. static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
  20. std::shared_ptr<GeneratorTracker> tracker;
  21. ITracker& currentTracker = ctx.currentTracker();
  22. // Under specific circumstances, the generator we want
  23. // to acquire is also the current tracker. If this is
  24. // the case, we have to avoid looking through current
  25. // tracker's children, and instead return the current
  26. // tracker.
  27. // A case where this check is important is e.g.
  28. // for (int i = 0; i < 5; ++i) {
  29. // int n = GENERATE(1, 2);
  30. // }
  31. //
  32. // without it, the code above creates 5 nested generators.
  33. if (currentTracker.nameAndLocation() == nameAndLocation) {
  34. auto thisTracker = currentTracker.parent().findChild(nameAndLocation);
  35. assert(thisTracker);
  36. assert(thisTracker->isGeneratorTracker());
  37. tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker);
  38. } else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
  39. assert( childTracker );
  40. assert( childTracker->isGeneratorTracker() );
  41. tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
  42. } else {
  43. tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );
  44. currentTracker.addChild( tracker );
  45. }
  46. if( !tracker->isComplete() ) {
  47. tracker->open();
  48. }
  49. return *tracker;
  50. }
  51. // TrackerBase interface
  52. bool isGeneratorTracker() const override { return true; }
  53. auto hasGenerator() const -> bool override {
  54. return !!m_generator;
  55. }
  56. void close() override {
  57. TrackerBase::close();
  58. // If a generator has a child (it is followed by a section)
  59. // and none of its children have started, then we must wait
  60. // until later to start consuming its values.
  61. // This catches cases where `GENERATE` is placed between two
  62. // `SECTION`s.
  63. // **The check for m_children.empty cannot be removed**.
  64. // doing so would break `GENERATE` _not_ followed by `SECTION`s.
  65. const bool should_wait_for_child = [&]() {
  66. // No children -> nobody to wait for
  67. if ( m_children.empty() ) {
  68. return false;
  69. }
  70. // If at least one child started executing, don't wait
  71. if ( std::find_if(
  72. m_children.begin(),
  73. m_children.end(),
  74. []( TestCaseTracking::ITrackerPtr tracker ) {
  75. return tracker->hasStarted();
  76. } ) != m_children.end() ) {
  77. return false;
  78. }
  79. // No children have started. We need to check if they _can_
  80. // start, and thus we should wait for them, or they cannot
  81. // start (due to filters), and we shouldn't wait for them
  82. auto* parent = m_parent;
  83. // This is safe: there is always at least one section
  84. // tracker in a test case tracking tree
  85. while ( !parent->isSectionTracker() ) {
  86. parent = &( parent->parent() );
  87. }
  88. assert( parent &&
  89. "Missing root (test case) level section" );
  90. auto const& parentSection =
  91. static_cast<SectionTracker&>( *parent );
  92. auto const& filters = parentSection.getFilters();
  93. // No filters -> no restrictions on running sections
  94. if ( filters.empty() ) {
  95. return true;
  96. }
  97. for ( auto const& child : m_children ) {
  98. if ( child->isSectionTracker() &&
  99. std::find( filters.begin(),
  100. filters.end(),
  101. static_cast<SectionTracker&>( *child )
  102. .trimmedName() ) !=
  103. filters.end() ) {
  104. return true;
  105. }
  106. }
  107. return false;
  108. }();
  109. // This check is a bit tricky, because m_generator->next()
  110. // has a side-effect, where it consumes generator's current
  111. // value, but we do not want to invoke the side-effect if
  112. // this generator is still waiting for any child to start.
  113. if ( should_wait_for_child ||
  114. ( m_runState == CompletedSuccessfully &&
  115. m_generator->next() ) ) {
  116. m_children.clear();
  117. m_runState = Executing;
  118. }
  119. }
  120. // IGeneratorTracker interface
  121. auto getGenerator() const -> GeneratorBasePtr const& override {
  122. return m_generator;
  123. }
  124. void setGenerator( GeneratorBasePtr&& generator ) override {
  125. m_generator = std::move( generator );
  126. }
  127. };
  128. GeneratorTracker::~GeneratorTracker() {}
  129. }
  130. RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
  131. : m_runInfo(_config->name()),
  132. m_context(getCurrentMutableContext()),
  133. m_config(_config),
  134. m_reporter(std::move(reporter)),
  135. m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
  136. m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
  137. {
  138. m_context.setRunner(this);
  139. m_context.setConfig(m_config);
  140. m_context.setResultCapture(this);
  141. m_reporter->testRunStarting(m_runInfo);
  142. }
  143. RunContext::~RunContext() {
  144. m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
  145. }
  146. void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
  147. m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
  148. }
  149. void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {
  150. m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
  151. }
  152. Totals RunContext::runTest(TestCase const& testCase) {
  153. Totals prevTotals = m_totals;
  154. std::string redirectedCout;
  155. std::string redirectedCerr;
  156. auto const& testInfo = testCase.getTestCaseInfo();
  157. m_reporter->testCaseStarting(testInfo);
  158. m_activeTestCase = &testCase;
  159. ITracker& rootTracker = m_trackerContext.startRun();
  160. assert(rootTracker.isSectionTracker());
  161. static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
  162. do {
  163. m_trackerContext.startCycle();
  164. m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
  165. runCurrentTest(redirectedCout, redirectedCerr);
  166. } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
  167. Totals deltaTotals = m_totals.delta(prevTotals);
  168. if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
  169. deltaTotals.assertions.failed++;
  170. deltaTotals.testCases.passed--;
  171. deltaTotals.testCases.failed++;
  172. }
  173. m_totals.testCases += deltaTotals.testCases;
  174. m_reporter->testCaseEnded(TestCaseStats(testInfo,
  175. deltaTotals,
  176. redirectedCout,
  177. redirectedCerr,
  178. aborting()));
  179. m_activeTestCase = nullptr;
  180. m_testCaseTracker = nullptr;
  181. return deltaTotals;
  182. }
  183. IConfigPtr RunContext::config() const {
  184. return m_config;
  185. }
  186. IStreamingReporter& RunContext::reporter() const {
  187. return *m_reporter;
  188. }
  189. void RunContext::assertionEnded(AssertionResult const & result) {
  190. if (result.getResultType() == ResultWas::Ok) {
  191. m_totals.assertions.passed++;
  192. m_lastAssertionPassed = true;
  193. } else if (!result.isOk()) {
  194. m_lastAssertionPassed = false;
  195. if( m_activeTestCase->getTestCaseInfo().okToFail() )
  196. m_totals.assertions.failedButOk++;
  197. else
  198. m_totals.assertions.failed++;
  199. }
  200. else {
  201. m_lastAssertionPassed = true;
  202. }
  203. // We have no use for the return value (whether messages should be cleared), because messages were made scoped
  204. // and should be let to clear themselves out.
  205. static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
  206. if (result.getResultType() != ResultWas::Warning)
  207. m_messageScopes.clear();
  208. // Reset working state
  209. resetAssertionInfo();
  210. m_lastResult = result;
  211. }
  212. void RunContext::resetAssertionInfo() {
  213. m_lastAssertionInfo.macroName = StringRef();
  214. m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
  215. }
  216. bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {
  217. ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
  218. if (!sectionTracker.isOpen())
  219. return false;
  220. m_activeSections.push_back(&sectionTracker);
  221. m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
  222. m_reporter->sectionStarting(sectionInfo);
  223. assertions = m_totals.assertions;
  224. return true;
  225. }
  226. auto RunContext::acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
  227. using namespace Generators;
  228. GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext,
  229. TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) );
  230. m_lastAssertionInfo.lineInfo = lineInfo;
  231. return tracker;
  232. }
  233. bool RunContext::testForMissingAssertions(Counts& assertions) {
  234. if (assertions.total() != 0)
  235. return false;
  236. if (!m_config->warnAboutMissingAssertions())
  237. return false;
  238. if (m_trackerContext.currentTracker().hasChildren())
  239. return false;
  240. m_totals.assertions.failed++;
  241. assertions.failed++;
  242. return true;
  243. }
  244. void RunContext::sectionEnded(SectionEndInfo const & endInfo) {
  245. Counts assertions = m_totals.assertions - endInfo.prevAssertions;
  246. bool missingAssertions = testForMissingAssertions(assertions);
  247. if (!m_activeSections.empty()) {
  248. m_activeSections.back()->close();
  249. m_activeSections.pop_back();
  250. }
  251. m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
  252. m_messages.clear();
  253. m_messageScopes.clear();
  254. }
  255. void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
  256. if (m_unfinishedSections.empty())
  257. m_activeSections.back()->fail();
  258. else
  259. m_activeSections.back()->close();
  260. m_activeSections.pop_back();
  261. m_unfinishedSections.push_back(endInfo);
  262. }
  263. #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
  264. void RunContext::benchmarkPreparing(std::string const& name) {
  265. m_reporter->benchmarkPreparing(name);
  266. }
  267. void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
  268. m_reporter->benchmarkStarting( info );
  269. }
  270. void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
  271. m_reporter->benchmarkEnded( stats );
  272. }
  273. void RunContext::benchmarkFailed(std::string const & error) {
  274. m_reporter->benchmarkFailed(error);
  275. }
  276. #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
  277. void RunContext::pushScopedMessage(MessageInfo const & message) {
  278. m_messages.push_back(message);
  279. }
  280. void RunContext::popScopedMessage(MessageInfo const & message) {
  281. m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
  282. }
  283. void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
  284. m_messageScopes.emplace_back( builder );
  285. }
  286. std::string RunContext::getCurrentTestName() const {
  287. return m_activeTestCase
  288. ? m_activeTestCase->getTestCaseInfo().name
  289. : std::string();
  290. }
  291. const AssertionResult * RunContext::getLastResult() const {
  292. return &(*m_lastResult);
  293. }
  294. void RunContext::exceptionEarlyReported() {
  295. m_shouldReportUnexpected = false;
  296. }
  297. void RunContext::handleFatalErrorCondition( StringRef message ) {
  298. // First notify reporter that bad things happened
  299. m_reporter->fatalErrorEncountered(message);
  300. // Don't rebuild the result -- the stringification itself can cause more fatal errors
  301. // Instead, fake a result data.
  302. AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
  303. tempResult.message = static_cast<std::string>(message);
  304. AssertionResult result(m_lastAssertionInfo, tempResult);
  305. assertionEnded(result);
  306. handleUnfinishedSections();
  307. // Recreate section for test case (as we will lose the one that was in scope)
  308. auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
  309. SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
  310. Counts assertions;
  311. assertions.failed = 1;
  312. SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
  313. m_reporter->sectionEnded(testCaseSectionStats);
  314. auto const& testInfo = m_activeTestCase->getTestCaseInfo();
  315. Totals deltaTotals;
  316. deltaTotals.testCases.failed = 1;
  317. deltaTotals.assertions.failed = 1;
  318. m_reporter->testCaseEnded(TestCaseStats(testInfo,
  319. deltaTotals,
  320. std::string(),
  321. std::string(),
  322. false));
  323. m_totals.testCases.failed++;
  324. testGroupEnded(std::string(), m_totals, 1, 1);
  325. m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
  326. }
  327. bool RunContext::lastAssertionPassed() {
  328. return m_lastAssertionPassed;
  329. }
  330. void RunContext::assertionPassed() {
  331. m_lastAssertionPassed = true;
  332. ++m_totals.assertions.passed;
  333. resetAssertionInfo();
  334. m_messageScopes.clear();
  335. }
  336. bool RunContext::aborting() const {
  337. return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());
  338. }
  339. void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
  340. auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
  341. SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
  342. m_reporter->sectionStarting(testCaseSection);
  343. Counts prevAssertions = m_totals.assertions;
  344. double duration = 0;
  345. m_shouldReportUnexpected = true;
  346. m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
  347. seedRng(*m_config);
  348. Timer timer;
  349. CATCH_TRY {
  350. if (m_reporter->getPreferences().shouldRedirectStdOut) {
  351. #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
  352. RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
  353. timer.start();
  354. invokeActiveTestCase();
  355. #else
  356. OutputRedirect r(redirectedCout, redirectedCerr);
  357. timer.start();
  358. invokeActiveTestCase();
  359. #endif
  360. } else {
  361. timer.start();
  362. invokeActiveTestCase();
  363. }
  364. duration = timer.getElapsedSeconds();
  365. } CATCH_CATCH_ANON (TestFailureException&) {
  366. // This just means the test was aborted due to failure
  367. } CATCH_CATCH_ALL {
  368. // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
  369. // are reported without translation at the point of origin.
  370. if( m_shouldReportUnexpected ) {
  371. AssertionReaction dummyReaction;
  372. handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
  373. }
  374. }
  375. Counts assertions = m_totals.assertions - prevAssertions;
  376. bool missingAssertions = testForMissingAssertions(assertions);
  377. m_testCaseTracker->close();
  378. handleUnfinishedSections();
  379. m_messages.clear();
  380. m_messageScopes.clear();
  381. SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
  382. m_reporter->sectionEnded(testCaseSectionStats);
  383. }
  384. void RunContext::invokeActiveTestCase() {
  385. FatalConditionHandlerGuard _(&m_fatalConditionhandler);
  386. m_activeTestCase->invoke();
  387. }
  388. void RunContext::handleUnfinishedSections() {
  389. // If sections ended prematurely due to an exception we stored their
  390. // infos here so we can tear them down outside the unwind process.
  391. for (auto it = m_unfinishedSections.rbegin(),
  392. itEnd = m_unfinishedSections.rend();
  393. it != itEnd;
  394. ++it)
  395. sectionEnded(*it);
  396. m_unfinishedSections.clear();
  397. }
  398. void RunContext::handleExpr(
  399. AssertionInfo const& info,
  400. ITransientExpression const& expr,
  401. AssertionReaction& reaction
  402. ) {
  403. m_reporter->assertionStarting( info );
  404. bool negated = isFalseTest( info.resultDisposition );
  405. bool result = expr.getResult() != negated;
  406. if( result ) {
  407. if (!m_includeSuccessfulResults) {
  408. assertionPassed();
  409. }
  410. else {
  411. reportExpr(info, ResultWas::Ok, &expr, negated);
  412. }
  413. }
  414. else {
  415. reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
  416. populateReaction( reaction );
  417. }
  418. }
  419. void RunContext::reportExpr(
  420. AssertionInfo const &info,
  421. ResultWas::OfType resultType,
  422. ITransientExpression const *expr,
  423. bool negated ) {
  424. m_lastAssertionInfo = info;
  425. AssertionResultData data( resultType, LazyExpression( negated ) );
  426. AssertionResult assertionResult{ info, data };
  427. assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
  428. assertionEnded( assertionResult );
  429. }
  430. void RunContext::handleMessage(
  431. AssertionInfo const& info,
  432. ResultWas::OfType resultType,
  433. StringRef const& message,
  434. AssertionReaction& reaction
  435. ) {
  436. m_reporter->assertionStarting( info );
  437. m_lastAssertionInfo = info;
  438. AssertionResultData data( resultType, LazyExpression( false ) );
  439. data.message = static_cast<std::string>(message);
  440. AssertionResult assertionResult{ m_lastAssertionInfo, data };
  441. assertionEnded( assertionResult );
  442. if( !assertionResult.isOk() )
  443. populateReaction( reaction );
  444. }
  445. void RunContext::handleUnexpectedExceptionNotThrown(
  446. AssertionInfo const& info,
  447. AssertionReaction& reaction
  448. ) {
  449. handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
  450. }
  451. void RunContext::handleUnexpectedInflightException(
  452. AssertionInfo const& info,
  453. std::string const& message,
  454. AssertionReaction& reaction
  455. ) {
  456. m_lastAssertionInfo = info;
  457. AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
  458. data.message = message;
  459. AssertionResult assertionResult{ info, data };
  460. assertionEnded( assertionResult );
  461. populateReaction( reaction );
  462. }
  463. void RunContext::populateReaction( AssertionReaction& reaction ) {
  464. reaction.shouldDebugBreak = m_config->shouldDebugBreak();
  465. reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
  466. }
  467. void RunContext::handleIncomplete(
  468. AssertionInfo const& info
  469. ) {
  470. m_lastAssertionInfo = info;
  471. AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
  472. data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
  473. AssertionResult assertionResult{ info, data };
  474. assertionEnded( assertionResult );
  475. }
  476. void RunContext::handleNonExpr(
  477. AssertionInfo const &info,
  478. ResultWas::OfType resultType,
  479. AssertionReaction &reaction
  480. ) {
  481. m_lastAssertionInfo = info;
  482. AssertionResultData data( resultType, LazyExpression( false ) );
  483. AssertionResult assertionResult{ info, data };
  484. assertionEnded( assertionResult );
  485. if( !assertionResult.isOk() )
  486. populateReaction( reaction );
  487. }
  488. IResultCapture& getResultCapture() {
  489. if (auto* capture = getCurrentContext().getResultCapture())
  490. return *capture;
  491. else
  492. CATCH_INTERNAL_ERROR("No result capture instance");
  493. }
  494. void seedRng(IConfig const& config) {
  495. if (config.rngSeed() != 0) {
  496. std::srand(config.rngSeed());
  497. rng().seed(config.rngSeed());
  498. }
  499. }
  500. unsigned int rngSeed() {
  501. return getCurrentContext().getConfig()->rngSeed();
  502. }
  503. }