catch2/include/internal/catch_test_case_tracker.h
Martin Hořeňovský 9500ded83b
Improved generator tracking
* Successive executions of the same `GENERATE` macro (e.g. because
of a for loop) no longer lead to multiple nested generators.
* The same line can now contain multiple `GENERATE` macros without
issues.

Fixes #1913
2020-06-01 19:06:51 +02:00

165 lines
4.6 KiB
C++

/*
* Created by Phil Nash on 23/7/2013
* Copyright 2013 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)
*/
#ifndef TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
#include "catch_compiler_capabilities.h"
#include "catch_common.h"
#include <string>
#include <vector>
#include <memory>
namespace Catch {
namespace TestCaseTracking {
struct NameAndLocation {
std::string name;
SourceLineInfo location;
NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
return lhs.name == rhs.name
&& lhs.location == rhs.location;
}
};
struct ITracker;
using ITrackerPtr = std::shared_ptr<ITracker>;
struct ITracker {
virtual ~ITracker();
// static queries
virtual NameAndLocation const& nameAndLocation() const = 0;
// dynamic queries
virtual bool isComplete() const = 0; // Successfully completed or failed
virtual bool isSuccessfullyCompleted() const = 0;
virtual bool isOpen() const = 0; // Started but not complete
virtual bool hasChildren() const = 0;
virtual ITracker& parent() = 0;
// actions
virtual void close() = 0; // Successfully complete
virtual void fail() = 0;
virtual void markAsNeedingAnotherRun() = 0;
virtual void addChild( ITrackerPtr const& child ) = 0;
virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0;
virtual void openChild() = 0;
// Debug/ checking
virtual bool isSectionTracker() const = 0;
virtual bool isGeneratorTracker() const = 0;
};
class TrackerContext {
enum RunState {
NotStarted,
Executing,
CompletedCycle
};
ITrackerPtr m_rootTracker;
ITracker* m_currentTracker = nullptr;
RunState m_runState = NotStarted;
public:
ITracker& startRun();
void endRun();
void startCycle();
void completeCycle();
bool completedCycle() const;
ITracker& currentTracker();
void setCurrentTracker( ITracker* tracker );
};
class TrackerBase : public ITracker {
protected:
enum CycleState {
NotStarted,
Executing,
ExecutingChildren,
NeedsAnotherRun,
CompletedSuccessfully,
Failed
};
using Children = std::vector<ITrackerPtr>;
NameAndLocation m_nameAndLocation;
TrackerContext& m_ctx;
ITracker* m_parent;
Children m_children;
CycleState m_runState = NotStarted;
public:
TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
NameAndLocation const& nameAndLocation() const override;
bool isComplete() const override;
bool isSuccessfullyCompleted() const override;
bool isOpen() const override;
bool hasChildren() const override;
void addChild( ITrackerPtr const& child ) override;
ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override;
ITracker& parent() override;
void openChild() override;
bool isSectionTracker() const override;
bool isGeneratorTracker() const override;
void open();
void close() override;
void fail() override;
void markAsNeedingAnotherRun() override;
private:
void moveToParent();
void moveToThis();
};
class SectionTracker : public TrackerBase {
std::vector<std::string> m_filters;
std::string m_trimmed_name;
public:
SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
bool isSectionTracker() const override;
bool isComplete() const override;
static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
void tryOpen();
void addInitialFilters( std::vector<std::string> const& filters );
void addNextFilters( std::vector<std::string> const& filters );
};
} // namespace TestCaseTracking
using TestCaseTracking::ITracker;
using TestCaseTracking::TrackerContext;
using TestCaseTracking::SectionTracker;
} // namespace Catch
#endif // TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED