mirror of
https://github.com/catchorg/Catch2.git
synced 2025-08-16 20:25:40 +02:00
Do not copy around TestCaseInfo
Now a `TEST_CASE` macro should create a single TestCaseInfo and then it should never be copied around. This, together with latter changes, should significantly decrease the number of allocations made before `main` is even entered.
This commit is contained in:
@@ -15,13 +15,15 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class TestCase;
|
||||
class TestCaseHandle;
|
||||
struct TestCaseInfo;
|
||||
struct ITestCaseRegistry;
|
||||
struct IExceptionTranslatorRegistry;
|
||||
struct IExceptionTranslator;
|
||||
struct IReporterRegistry;
|
||||
struct IReporterFactory;
|
||||
struct ITagAliasRegistry;
|
||||
struct ITestInvoker;
|
||||
struct IMutableEnumValuesRegistry;
|
||||
|
||||
class StartupExceptionRegistry;
|
||||
@@ -44,7 +46,7 @@ namespace Catch {
|
||||
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 registerTest(std::unique_ptr<TestCaseInfo>&& testInfo, std::unique_ptr<ITestInvoker>&& invoker) = 0;
|
||||
virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
|
||||
virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
|
||||
virtual void registerStartupException() noexcept = 0;
|
||||
|
@@ -76,7 +76,7 @@ namespace Catch {
|
||||
std::string const& _stdOut,
|
||||
std::string const& _stdErr,
|
||||
bool _aborting )
|
||||
: testInfo( _testInfo ),
|
||||
: testInfo( &_testInfo ),
|
||||
totals( _totals ),
|
||||
stdOut( _stdOut ),
|
||||
stdErr( _stdErr ),
|
||||
@@ -141,14 +141,15 @@ namespace Catch {
|
||||
Catch::cout() << std::endl;
|
||||
}
|
||||
|
||||
void IStreamingReporter::listTests(std::vector<TestCase> const& tests, Config const& config) {
|
||||
void IStreamingReporter::listTests(std::vector<TestCaseHandle> const& tests, Config const& config) {
|
||||
if (config.hasTestFilters())
|
||||
Catch::cout() << "Matching test cases:\n";
|
||||
else {
|
||||
Catch::cout() << "All available test cases:\n";
|
||||
}
|
||||
|
||||
for (auto const& testCaseInfo : tests) {
|
||||
for (auto const& test : tests) {
|
||||
auto const& testCaseInfo = test.getTestCaseInfo();
|
||||
Colour::Code colour = testCaseInfo.isHidden()
|
||||
? Colour::SecondaryText
|
||||
: Colour::None;
|
||||
|
@@ -128,7 +128,7 @@ namespace Catch {
|
||||
TestCaseStats& operator = ( TestCaseStats && ) = default;
|
||||
virtual ~TestCaseStats();
|
||||
|
||||
TestCaseInfo testInfo;
|
||||
TestCaseInfo const * testInfo;
|
||||
Totals totals;
|
||||
std::string stdOut;
|
||||
std::string stdErr;
|
||||
@@ -217,7 +217,7 @@ namespace Catch {
|
||||
virtual void noMatchingTestCases( std::string const& spec ) = 0;
|
||||
|
||||
virtual void reportInvalidArguments(std::string const&) {}
|
||||
|
||||
|
||||
virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
|
||||
virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
|
||||
|
||||
@@ -250,7 +250,7 @@ namespace Catch {
|
||||
|
||||
// Listing support
|
||||
virtual void listReporters(std::vector<ReporterDescription> const& descriptions, Config const& config);
|
||||
virtual void listTests(std::vector<TestCase> const& tests, Config const& config);
|
||||
virtual void listTests(std::vector<TestCaseHandle> const& tests, Config const& config);
|
||||
virtual void listTags(std::vector<TagInfo> const& tags, Config const& config);
|
||||
|
||||
};
|
||||
|
@@ -19,19 +19,19 @@ namespace Catch {
|
||||
virtual ~ITestInvoker();
|
||||
};
|
||||
|
||||
class TestCase;
|
||||
class TestCaseHandle;
|
||||
struct IConfig;
|
||||
|
||||
struct ITestCaseRegistry {
|
||||
virtual ~ITestCaseRegistry();
|
||||
virtual std::vector<TestCase> const& getAllTests() const = 0;
|
||||
virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
|
||||
virtual std::vector<TestCaseHandle> const& getAllTests() const = 0;
|
||||
virtual std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const = 0;
|
||||
};
|
||||
|
||||
bool isThrowSafe( TestCase const& testCase, IConfig const& config );
|
||||
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
||||
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
|
||||
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
|
||||
bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config );
|
||||
bool matchTest( TestCaseHandle const& testCase, TestSpec const& testSpec, IConfig const& config );
|
||||
std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config );
|
||||
std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config );
|
||||
|
||||
}
|
||||
|
||||
|
@@ -36,7 +36,7 @@ namespace Catch {
|
||||
|
||||
void listTags(IStreamingReporter& reporter, Config const& config) {
|
||||
TestSpec testSpec = config.testSpec();
|
||||
std::vector<TestCase> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
|
||||
std::vector<TestCaseHandle> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
|
||||
|
||||
std::map<std::string, TagInfo> tagCounts;
|
||||
for (auto const& testCase : matchedTestCases) {
|
||||
|
@@ -93,7 +93,7 @@ namespace Catch {
|
||||
std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
|
||||
const char* className = class_getName( cls );
|
||||
|
||||
getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
|
||||
getMutableRegistryHub().registerTest( makeTestCaseInfo( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
|
||||
noTestMethods++;
|
||||
}
|
||||
}
|
||||
|
@@ -49,8 +49,8 @@ namespace Catch {
|
||||
void registerListener( IReporterFactoryPtr const& factory ) override {
|
||||
m_reporterRegistry.registerListener( factory );
|
||||
}
|
||||
void registerTest( TestCase const& testInfo ) override {
|
||||
m_testCaseRegistry.registerTest( testInfo );
|
||||
void registerTest( std::unique_ptr<TestCaseInfo>&& testInfo, std::unique_ptr<ITestInvoker>&& invoker ) override {
|
||||
m_testCaseRegistry.registerTest( std::move(testInfo), std::move(invoker) );
|
||||
}
|
||||
void registerTranslator( const IExceptionTranslator* translator ) override {
|
||||
m_exceptionTranslatorRegistry.registerTranslator( translator );
|
||||
|
@@ -93,7 +93,7 @@ namespace Catch {
|
||||
m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
|
||||
}
|
||||
|
||||
Totals RunContext::runTest(TestCase const& testCase) {
|
||||
Totals RunContext::runTest(TestCaseHandle const& testCase) {
|
||||
Totals prevTotals = m_totals;
|
||||
|
||||
std::string redirectedCout;
|
||||
|
@@ -44,7 +44,7 @@ namespace Catch {
|
||||
void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
|
||||
void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );
|
||||
|
||||
Totals runTest(TestCase const& testCase);
|
||||
Totals runTest(TestCaseHandle const& testCase);
|
||||
|
||||
IConfigPtr config() const;
|
||||
IStreamingReporter& reporter() const;
|
||||
@@ -133,7 +133,7 @@ namespace Catch {
|
||||
|
||||
TestRunInfo m_runInfo;
|
||||
IMutableContext& m_context;
|
||||
TestCase const* m_activeTestCase = nullptr;
|
||||
TestCaseHandle const* m_activeTestCase = nullptr;
|
||||
ITracker* m_testCaseTracker = nullptr;
|
||||
Option<AssertionResult> m_lastResult;
|
||||
|
||||
|
@@ -72,7 +72,7 @@ namespace Catch {
|
||||
|
||||
if (m_matches.empty() && invalidArgs.empty()) {
|
||||
for (auto const& test : allTestCases)
|
||||
if (!test.isHidden())
|
||||
if (!test.getTestCaseInfo().isHidden())
|
||||
m_tests.emplace(&test);
|
||||
} else {
|
||||
for (auto const& match : m_matches)
|
||||
@@ -88,7 +88,7 @@ namespace Catch {
|
||||
if (!m_context.aborting())
|
||||
totals += m_context.runTest(*testCase);
|
||||
else
|
||||
m_context.reporter().skipTest(*testCase);
|
||||
m_context.reporter().skipTest(testCase->getTestCaseInfo());
|
||||
}
|
||||
|
||||
for (auto const& match : m_matches) {
|
||||
@@ -108,7 +108,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
private:
|
||||
using Tests = std::set<TestCase const*>;
|
||||
using Tests = std::set<TestCaseHandle const*>;
|
||||
|
||||
std::shared_ptr<Config> m_config;
|
||||
RunContext m_context;
|
||||
@@ -117,11 +117,11 @@ namespace Catch {
|
||||
};
|
||||
|
||||
void applyFilenamesAsTags(Catch::IConfig const& config) {
|
||||
auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
|
||||
for (auto& testCase : tests) {
|
||||
auto tags = testCase.tags;
|
||||
for (auto const& testCase : getAllTestCasesSorted(config)) {
|
||||
// Yeah, sue me. This will be removed soon.
|
||||
auto& testInfo = const_cast<TestCaseInfo&>(testCase.getTestCaseInfo());
|
||||
|
||||
std::string filename = testCase.lineInfo.file;
|
||||
std::string filename = testInfo.lineInfo.file;
|
||||
auto lastSlash = filename.find_last_of("\\/");
|
||||
if (lastSlash != std::string::npos) {
|
||||
filename.erase(0, lastSlash);
|
||||
@@ -133,8 +133,9 @@ namespace Catch {
|
||||
filename.erase(lastDot);
|
||||
}
|
||||
|
||||
auto tags = testInfo.tags;
|
||||
tags.push_back(std::move(filename));
|
||||
setTags(testCase, tags);
|
||||
setTags(testInfo, tags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -53,10 +53,10 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
TestCase makeTestCase( ITestInvoker* _testCase,
|
||||
std::string const& _className,
|
||||
NameAndTags const& nameAndTags,
|
||||
SourceLineInfo const& _lineInfo )
|
||||
std::unique_ptr<TestCaseInfo>
|
||||
makeTestCaseInfo(std::string const& _className,
|
||||
NameAndTags const& nameAndTags,
|
||||
SourceLineInfo const& _lineInfo )
|
||||
{
|
||||
bool isHidden = false;
|
||||
|
||||
@@ -95,8 +95,8 @@ namespace Catch {
|
||||
tags.push_back( "." );
|
||||
}
|
||||
|
||||
TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, tags, _lineInfo );
|
||||
return TestCase( _testCase, std::move(info) );
|
||||
return std::make_unique<TestCaseInfo>(static_cast<std::string>(nameAndTags.name),
|
||||
_className, tags, _lineInfo);
|
||||
}
|
||||
|
||||
void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
|
||||
@@ -155,26 +155,18 @@ namespace Catch {
|
||||
}
|
||||
|
||||
|
||||
TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}
|
||||
|
||||
|
||||
void TestCase::invoke() const {
|
||||
test->invoke();
|
||||
bool TestCaseHandle::operator == ( TestCaseHandle const& rhs ) const {
|
||||
return m_invoker == rhs.m_invoker
|
||||
&& m_info->name == rhs.m_info->name
|
||||
&& m_info->className == rhs.m_info->className;
|
||||
}
|
||||
|
||||
bool TestCase::operator == ( TestCase const& other ) const {
|
||||
return test.get() == other.test.get() &&
|
||||
name == other.name &&
|
||||
className == other.className;
|
||||
bool TestCaseHandle::operator < ( TestCaseHandle const& rhs ) const {
|
||||
return m_info->name < rhs.m_info->name;
|
||||
}
|
||||
|
||||
bool TestCase::operator < ( TestCase const& other ) const {
|
||||
return name < other.name;
|
||||
}
|
||||
|
||||
TestCaseInfo const& TestCase::getTestCaseInfo() const
|
||||
{
|
||||
return *this;
|
||||
TestCaseInfo const& TestCaseHandle::getTestCaseInfo() const {
|
||||
return *m_info;
|
||||
}
|
||||
|
||||
} // end namespace Catch
|
||||
|
@@ -24,7 +24,7 @@ namespace Catch {
|
||||
|
||||
struct ITestInvoker;
|
||||
|
||||
struct TestCaseInfo {
|
||||
struct TestCaseInfo : NonCopyable {
|
||||
enum SpecialProperties{
|
||||
None = 0,
|
||||
IsHidden = 1 << 1,
|
||||
@@ -57,24 +57,24 @@ namespace Catch {
|
||||
SpecialProperties properties;
|
||||
};
|
||||
|
||||
class TestCase : public TestCaseInfo {
|
||||
class TestCaseHandle {
|
||||
TestCaseInfo* m_info;
|
||||
ITestInvoker* m_invoker;
|
||||
public:
|
||||
TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) :
|
||||
m_info(info), m_invoker(invoker) {}
|
||||
|
||||
TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
|
||||
|
||||
void invoke() const;
|
||||
void invoke() const {
|
||||
m_invoker->invoke();
|
||||
}
|
||||
|
||||
TestCaseInfo const& getTestCaseInfo() const;
|
||||
|
||||
bool operator == ( TestCase const& other ) const;
|
||||
bool operator < ( TestCase const& other ) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ITestInvoker> test;
|
||||
bool operator== ( TestCaseHandle const& rhs ) const;
|
||||
bool operator < ( TestCaseHandle const& rhs ) const;
|
||||
};
|
||||
|
||||
TestCase makeTestCase( ITestInvoker* testCase,
|
||||
std::string const& className,
|
||||
std::unique_ptr<TestCaseInfo> makeTestCaseInfo( std::string const& className,
|
||||
NameAndTags const& nameAndTags,
|
||||
SourceLineInfo const& lineInfo );
|
||||
}
|
||||
|
@@ -19,9 +19,9 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
|
||||
std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases ) {
|
||||
|
||||
std::vector<TestCase> sorted = unsortedTestCases;
|
||||
std::vector<TestCaseHandle> sorted = unsortedTestCases;
|
||||
|
||||
switch( config.runOrder() ) {
|
||||
case RunTests::InLexicographicalOrder:
|
||||
@@ -38,53 +38,55 @@ namespace Catch {
|
||||
return sorted;
|
||||
}
|
||||
|
||||
bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {
|
||||
return !testCase.throws() || config.allowThrows();
|
||||
bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ) {
|
||||
return !testCase.getTestCaseInfo().throws() || config.allowThrows();
|
||||
}
|
||||
|
||||
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
|
||||
return testSpec.matches( testCase ) && isThrowSafe( testCase, config );
|
||||
bool matchTest( TestCaseHandle const& testCase, TestSpec const& testSpec, IConfig const& config ) {
|
||||
return testSpec.matches( testCase.getTestCaseInfo() ) && isThrowSafe( testCase, config );
|
||||
}
|
||||
|
||||
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
|
||||
std::set<TestCase> seenFunctions;
|
||||
void enforceNoDuplicateTestCases( std::vector<TestCaseHandle> const& functions ) {
|
||||
std::set<TestCaseHandle> seenFunctions;
|
||||
for( auto const& function : functions ) {
|
||||
auto prev = seenFunctions.insert( function );
|
||||
CATCH_ENFORCE( prev.second,
|
||||
"error: TEST_CASE( \"" << function.name << "\" ) already defined.\n"
|
||||
"error: TEST_CASE( \"" << function.getTestCaseInfo().name << "\" ) already defined.\n"
|
||||
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
|
||||
<< "\tRedefined at " << function.getTestCaseInfo().lineInfo );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
|
||||
std::vector<TestCase> filtered;
|
||||
std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
|
||||
std::vector<TestCaseHandle> filtered;
|
||||
filtered.reserve( testCases.size() );
|
||||
for (auto const& testCase : testCases) {
|
||||
if ((!testSpec.hasFilters() && !testCase.isHidden()) ||
|
||||
if ((!testSpec.hasFilters() && !testCase.getTestCaseInfo().isHidden()) ||
|
||||
(testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
|
||||
filtered.push_back(testCase);
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
|
||||
std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config ) {
|
||||
return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
|
||||
}
|
||||
|
||||
void TestRegistry::registerTest( TestCase const& testCase ) {
|
||||
m_functions.push_back( testCase );
|
||||
void TestRegistry::registerTest(std::unique_ptr<TestCaseInfo> testInfo, std::unique_ptr<ITestInvoker> testInvoker) {
|
||||
m_handles.emplace_back(testInfo.get(), testInvoker.get());
|
||||
m_infos.push_back(std::move(testInfo));
|
||||
m_invokers.push_back(std::move(testInvoker));
|
||||
}
|
||||
|
||||
std::vector<TestCase> const& TestRegistry::getAllTests() const {
|
||||
return m_functions;
|
||||
std::vector<TestCaseHandle> const& TestRegistry::getAllTests() const {
|
||||
return m_handles;
|
||||
}
|
||||
std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
|
||||
std::vector<TestCaseHandle> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
|
||||
if( m_sortedFunctions.empty() )
|
||||
enforceNoDuplicateTestCases( m_functions );
|
||||
enforceNoDuplicateTestCases( m_handles );
|
||||
|
||||
if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
|
||||
m_sortedFunctions = sortTests( config, m_functions );
|
||||
m_sortedFunctions = sortTests( config, m_handles );
|
||||
m_currentSortOrder = config.runOrder();
|
||||
}
|
||||
return m_sortedFunctions;
|
||||
@@ -93,8 +95,6 @@ namespace Catch {
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
|
||||
|
||||
void TestInvokerAsFunction::invoke() const {
|
||||
m_testAsFunction();
|
||||
}
|
||||
|
@@ -15,44 +15,47 @@
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <ios>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
class TestCase;
|
||||
class TestCaseHandle;
|
||||
struct IConfig;
|
||||
|
||||
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
|
||||
std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases );
|
||||
|
||||
bool isThrowSafe( TestCase const& testCase, IConfig const& config );
|
||||
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
|
||||
bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config );
|
||||
bool matchTest( TestCaseHandle const& testCase, TestSpec const& testSpec, IConfig const& config );
|
||||
|
||||
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
|
||||
void enforceNoDuplicateTestCases( std::vector<TestCaseHandle> const& functions );
|
||||
|
||||
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
|
||||
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
|
||||
std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config );
|
||||
std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config );
|
||||
|
||||
class TestRegistry : public ITestCaseRegistry {
|
||||
public:
|
||||
virtual ~TestRegistry() = default;
|
||||
|
||||
virtual void registerTest( TestCase const& testCase );
|
||||
virtual void registerTest( std::unique_ptr<TestCaseInfo> testInfo, std::unique_ptr<ITestInvoker> testInvoker );
|
||||
|
||||
std::vector<TestCase> const& getAllTests() const override;
|
||||
std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override;
|
||||
std::vector<TestCaseHandle> const& getAllTests() const override;
|
||||
std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const override;
|
||||
|
||||
private:
|
||||
std::vector<TestCase> m_functions;
|
||||
std::vector<std::unique_ptr<TestCaseInfo>> m_infos;
|
||||
std::vector<std::unique_ptr<ITestInvoker>> m_invokers;
|
||||
std::vector<TestCaseHandle> m_handles;
|
||||
mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
|
||||
mutable std::vector<TestCase> m_sortedFunctions;
|
||||
mutable std::vector<TestCaseHandle> m_sortedFunctions;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TestInvokerAsFunction : public ITestInvoker {
|
||||
void(*m_testAsFunction)();
|
||||
class TestInvokerAsFunction final : public ITestInvoker {
|
||||
using TestType = void(*)();
|
||||
TestType m_testAsFunction;
|
||||
public:
|
||||
TestInvokerAsFunction( void(*testAsFunction)() ) noexcept;
|
||||
TestInvokerAsFunction(TestType testAsFunction) noexcept:
|
||||
m_testAsFunction(testAsFunction) {}
|
||||
|
||||
void invoke() const override;
|
||||
};
|
||||
|
@@ -12,19 +12,19 @@
|
||||
|
||||
namespace Catch {
|
||||
|
||||
auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* {
|
||||
return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
|
||||
std::unique_ptr<ITestInvoker> makeTestInvoker( void(*testAsFunction)() ) {
|
||||
return std::make_unique<TestInvokerAsFunction>( testAsFunction );
|
||||
}
|
||||
|
||||
AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
|
||||
AutoReg::AutoReg( std::unique_ptr<ITestInvoker> invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
|
||||
CATCH_TRY {
|
||||
getMutableRegistryHub()
|
||||
.registerTest(
|
||||
makeTestCase(
|
||||
invoker,
|
||||
makeTestCaseInfo(
|
||||
extractClassName( classOrMethod ),
|
||||
nameAndTags,
|
||||
lineInfo));
|
||||
lineInfo),
|
||||
std::move(invoker));
|
||||
} CATCH_CATCH_ALL {
|
||||
// Do not throw when constructing global objects, instead register the exception to be processed later
|
||||
getMutableRegistryHub().registerStartupException();
|
||||
|
@@ -15,6 +15,8 @@
|
||||
#include "catch_preprocessor.hpp"
|
||||
#include "catch_meta.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
template<typename C>
|
||||
@@ -29,11 +31,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;
|
||||
std::unique_ptr<ITestInvoker> makeTestInvoker( void(*testAsFunction)() );
|
||||
|
||||
template<typename C>
|
||||
auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
|
||||
return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod );
|
||||
std::unique_ptr<ITestInvoker> makeTestInvoker( void (C::*testAsMethod)() ) {
|
||||
return std::make_unique<TestInvokerAsMethod<C>>( testAsMethod );
|
||||
}
|
||||
|
||||
struct NameAndTags {
|
||||
@@ -45,7 +47,7 @@ struct NameAndTags {
|
||||
};
|
||||
|
||||
struct AutoReg : NonCopyable {
|
||||
AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
|
||||
AutoReg( std::unique_ptr<ITestInvoker> invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
|
||||
};
|
||||
|
||||
} // end namespace Catch
|
||||
|
@@ -84,13 +84,13 @@ namespace Catch {
|
||||
return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );
|
||||
}
|
||||
|
||||
TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const
|
||||
TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCaseHandle> const& testCases, IConfig const& config ) const
|
||||
{
|
||||
Matches matches( m_filters.size() );
|
||||
std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){
|
||||
std::vector<TestCase const*> currentMatches;
|
||||
std::vector<TestCaseHandle const*> currentMatches;
|
||||
for( auto const& test : testCases )
|
||||
if( isThrowSafe( test, config ) && filter.matches( test ) )
|
||||
if( isThrowSafe( test, config ) && filter.matches( test.getTestCaseInfo() ) )
|
||||
currentMatches.emplace_back( &test );
|
||||
return FilterMatch{ filter.name(), currentMatches };
|
||||
} );
|
||||
|
@@ -63,14 +63,14 @@ namespace Catch {
|
||||
public:
|
||||
struct FilterMatch {
|
||||
std::string name;
|
||||
std::vector<TestCase const*> tests;
|
||||
std::vector<TestCaseHandle const*> tests;
|
||||
};
|
||||
using Matches = std::vector<FilterMatch>;
|
||||
using vectorStrings = std::vector<std::string>;
|
||||
|
||||
bool hasFilters() const;
|
||||
bool matches( TestCaseInfo const& testCase ) const;
|
||||
Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const;
|
||||
Matches matchesByFilter( std::vector<TestCaseHandle> const& testCases, IConfig const& config ) const;
|
||||
const vectorStrings & getInvalidArgs() const;
|
||||
|
||||
private:
|
||||
|
@@ -41,7 +41,7 @@ namespace Catch {
|
||||
} else {
|
||||
stream << "FAIL";
|
||||
}
|
||||
stream << ' ' << _testCaseStats.testInfo.name << '\n';
|
||||
stream << ' ' << _testCaseStats.testInfo->name << '\n';
|
||||
StreamingReporterBase::testCaseEnded( _testCaseStats );
|
||||
}
|
||||
|
||||
|
@@ -45,7 +45,7 @@ namespace Catch {
|
||||
void noMatchingTestCases(std::string const&) override {}
|
||||
|
||||
void reportInvalidArguments(std::string const&) override {}
|
||||
|
||||
|
||||
void testRunStarting(TestRunInfo const& _testRunInfo) override {
|
||||
currentTestRunInfo = _testRunInfo;
|
||||
}
|
||||
@@ -55,7 +55,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
void testCaseStarting(TestCaseInfo const& _testInfo) override {
|
||||
currentTestCaseInfo = _testInfo;
|
||||
currentTestCaseInfo = &_testInfo;
|
||||
}
|
||||
void sectionStarting(SectionInfo const& _sectionInfo) override {
|
||||
m_sectionStack.push_back(_sectionInfo);
|
||||
@@ -65,13 +65,13 @@ namespace Catch {
|
||||
m_sectionStack.pop_back();
|
||||
}
|
||||
void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
|
||||
currentTestCaseInfo.reset();
|
||||
currentTestCaseInfo = nullptr;
|
||||
}
|
||||
void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override {
|
||||
currentGroupInfo.reset();
|
||||
}
|
||||
void testRunEnded(TestRunStats const& /* _testRunStats */) override {
|
||||
currentTestCaseInfo.reset();
|
||||
currentTestCaseInfo = nullptr;
|
||||
currentGroupInfo.reset();
|
||||
currentTestRunInfo.reset();
|
||||
}
|
||||
@@ -86,7 +86,7 @@ namespace Catch {
|
||||
|
||||
LazyStat<TestRunInfo> currentTestRunInfo;
|
||||
LazyStat<GroupInfo> currentGroupInfo;
|
||||
LazyStat<TestCaseInfo> currentTestCaseInfo;
|
||||
TestCaseInfo const* currentTestCaseInfo;
|
||||
|
||||
std::vector<SectionInfo> m_sectionStack;
|
||||
ReporterPreferences m_reporterPrefs;
|
||||
@@ -261,7 +261,7 @@ namespace Catch {
|
||||
|
||||
// Event listeners should not use the default listing impl
|
||||
void listReporters(std::vector<ReporterDescription> const&, Config const&) override {}
|
||||
void listTests(std::vector<TestCase> const&, Config const&) override {}
|
||||
void listTests(std::vector<TestCaseHandle> const&, Config const&) override {}
|
||||
void listTags(std::vector<TagInfo> const&, Config const&) override {}
|
||||
};
|
||||
|
||||
|
@@ -159,10 +159,10 @@ namespace Catch {
|
||||
assert( testCaseNode.children.size() == 1 );
|
||||
SectionNode const& rootSection = *testCaseNode.children.front();
|
||||
|
||||
std::string className = stats.testInfo.className;
|
||||
std::string className = stats.testInfo->className;
|
||||
|
||||
if( className.empty() ) {
|
||||
className = fileNameTag(stats.testInfo.tags);
|
||||
className = fileNameTag(stats.testInfo->tags);
|
||||
if ( className.empty() )
|
||||
className = "global";
|
||||
}
|
||||
|
@@ -163,7 +163,7 @@ namespace Catch {
|
||||
m_reporter->listReporters(descriptions, config);
|
||||
}
|
||||
|
||||
void ListeningReporter::listTests(std::vector<TestCase> const& tests, Config const& config) {
|
||||
void ListeningReporter::listTests(std::vector<TestCaseHandle> const& tests, Config const& config) {
|
||||
for (auto const& listener : m_listeners) {
|
||||
listener->listTests(tests, config);
|
||||
}
|
||||
|
@@ -55,7 +55,7 @@ namespace Catch {
|
||||
bool isMulti() const override;
|
||||
|
||||
void listReporters(std::vector<ReporterDescription> const& descriptions, Config const& config) override;
|
||||
void listTests(std::vector<TestCase> const& tests, Config const& config) override;
|
||||
void listTests(std::vector<TestCaseHandle> const& tests, Config const& config) override;
|
||||
void listTags(std::vector<TagInfo> const& tags, Config const& config) override;
|
||||
|
||||
|
||||
|
@@ -58,7 +58,7 @@ namespace Catch {
|
||||
void writeGroup(TestGroupNode const& groupNode) {
|
||||
std::map<std::string, TestGroupNode::ChildNodes> testsPerFile;
|
||||
for(auto const& child : groupNode.children)
|
||||
testsPerFile[child->value.testInfo.lineInfo.file].push_back(child);
|
||||
testsPerFile[child->value.testInfo->lineInfo.file].push_back(child);
|
||||
|
||||
for(auto const& kv : testsPerFile)
|
||||
writeTestFile(kv.first.c_str(), kv.second);
|
||||
@@ -77,7 +77,7 @@ namespace Catch {
|
||||
// test case itself. That section may have 0-n nested sections
|
||||
assert(testCaseNode.children.size() == 1);
|
||||
SectionNode const& rootSection = *testCaseNode.children.front();
|
||||
writeSection("", rootSection, testCaseNode.value.testInfo.okToFail());
|
||||
writeSection("", rootSection, testCaseNode.value.testInfo->okToFail());
|
||||
}
|
||||
|
||||
void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail) {
|
||||
|
@@ -152,16 +152,17 @@ namespace Catch {
|
||||
|
||||
void testCaseEnded( TestCaseStats const& testCaseStats ) override {
|
||||
StreamingReporterBase::testCaseEnded( testCaseStats );
|
||||
auto const& testCaseInfo = *testCaseStats.testInfo;
|
||||
if( !testCaseStats.stdOut.empty() )
|
||||
stream << "##teamcity[testStdOut name='"
|
||||
<< escape( testCaseStats.testInfo.name )
|
||||
<< escape( testCaseInfo.name )
|
||||
<< "' out='" << escape( testCaseStats.stdOut ) << "']\n";
|
||||
if( !testCaseStats.stdErr.empty() )
|
||||
stream << "##teamcity[testStdErr name='"
|
||||
<< escape( testCaseStats.testInfo.name )
|
||||
<< escape(testCaseInfo.name )
|
||||
<< "' out='" << escape( testCaseStats.stdErr ) << "']\n";
|
||||
stream << "##teamcity[testFinished name='"
|
||||
<< escape( testCaseStats.testInfo.name ) << "' duration='"
|
||||
<< escape(testCaseInfo.name ) << "' duration='"
|
||||
<< m_testTimer.getElapsedMilliseconds() << "']\n";
|
||||
stream.flush();
|
||||
}
|
||||
|
@@ -277,7 +277,7 @@ namespace Catch {
|
||||
}
|
||||
}
|
||||
|
||||
void XmlReporter::listTests(std::vector<TestCase> const& tests, Config const&) {
|
||||
void XmlReporter::listTests(std::vector<TestCaseHandle> const& tests, Config const&) {
|
||||
auto outerTag = m_xml.scopedElement("MatchingTests");
|
||||
for (auto const& test : tests) {
|
||||
auto innerTag = m_xml.scopedElement("TestCase");
|
||||
|
@@ -58,7 +58,7 @@ namespace Catch {
|
||||
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
||||
|
||||
void listReporters(std::vector<ReporterDescription> const& descriptions, Config const& config) override;
|
||||
void listTests(std::vector<TestCase> const& tests, Config const& config) override;
|
||||
void listTests(std::vector<TestCaseHandle> const& tests, Config const& config) override;
|
||||
void listTags(std::vector<TagInfo> const& tags, Config const& config) override;
|
||||
|
||||
private:
|
||||
|
Reference in New Issue
Block a user