catch2/include/internal/catch_test_case_registry_impl.hpp

166 lines
6.0 KiB
C++
Raw Normal View History

2011-01-07 11:22:24 +01:00
/*
* Created by Phil on 7/1/2011
* Copyright 2010 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_REGISTRY_IMPL_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
2011-01-07 11:22:24 +01:00
#include "catch_test_registry.hpp"
2012-08-14 20:30:30 +02:00
#include "catch_test_case_info.h"
#include "catch_test_spec.hpp"
#include "catch_context.h"
2011-01-07 11:22:24 +01:00
#include <vector>
#include <set>
#include <sstream>
#include <iostream>
2014-09-16 00:32:13 +02:00
#include <algorithm>
2011-01-07 11:22:24 +01:00
2012-05-16 09:02:20 +02:00
namespace Catch {
2012-05-10 22:46:46 +02:00
class TestRegistry : public ITestCaseRegistry {
struct LexSort {
bool operator() ( TestCase const& i, TestCase const& j) const { return ( i < j ); }
};
struct RandomNumberGenerator {
int operator()( int n ) const { return std::rand() % n; }
};
2011-01-07 11:22:24 +01:00
public:
2012-05-10 22:46:46 +02:00
TestRegistry() : m_unnamedCount( 0 ) {}
virtual ~TestRegistry();
virtual void registerTest( TestCase const& testCase ) {
std::string name = testCase.getTestCaseInfo().name;
if( name == "" ) {
std::ostringstream oss;
2013-03-16 21:18:52 +01:00
oss << "Anonymous test case " << ++m_unnamedCount;
return registerTest( testCase.withName( oss.str() ) );
}
2012-05-10 22:46:46 +02:00
if( m_functions.find( testCase ) == m_functions.end() ) {
m_functions.insert( testCase );
m_functionsInOrder.push_back( testCase );
if( !testCase.isHidden() )
m_nonHiddenFunctions.push_back( testCase );
2011-01-07 11:22:24 +01:00
}
2012-05-10 22:46:46 +02:00
else {
TestCase const& prev = *m_functions.find( testCase );
{
Colour colourGuard( Colour::Red );
Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
<< "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
<< "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
}
exit(1);
}
2011-01-07 11:22:24 +01:00
}
virtual std::vector<TestCase> const& getAllTests() const {
2011-01-07 11:22:24 +01:00
return m_functionsInOrder;
}
virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
return m_nonHiddenFunctions;
}
virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const {
for( std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(),
itEnd = m_functionsInOrder.end();
it != itEnd;
++it ) {
bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() );
if( includeTest != negated )
matchingTestCases.push_back( *it );
}
sortTests( config, matchingTestCases );
}
private:
static void sortTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) {
switch( config.runOrder() ) {
case RunTests::InLexicographicalOrder:
std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() );
break;
case RunTests::InRandomOrder:
{
RandomNumberGenerator rng;
std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng );
}
break;
case RunTests::InDeclarationOrder:
// already in declaration order
break;
}
}
2012-11-22 20:17:20 +01:00
std::set<TestCase> m_functions;
std::vector<TestCase> m_functionsInOrder;
std::vector<TestCase> m_nonHiddenFunctions;
size_t m_unnamedCount;
std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
2011-01-07 11:22:24 +01:00
};
2011-01-28 19:56:26 +01:00
///////////////////////////////////////////////////////////////////////////
2012-08-14 09:38:22 +02:00
class FreeFunctionTestCase : public SharedImpl<ITestCase> {
2012-05-10 22:46:46 +02:00
public:
FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
2012-08-14 09:38:22 +02:00
2012-05-10 22:46:46 +02:00
virtual void invoke() const {
2011-01-31 11:10:20 +01:00
m_fun();
2011-01-07 11:22:24 +01:00
}
2012-08-14 09:38:22 +02:00
2011-01-07 11:22:24 +01:00
private:
2012-08-14 09:38:22 +02:00
virtual ~FreeFunctionTestCase();
2011-01-31 11:10:20 +01:00
TestFunction m_fun;
2011-01-07 11:22:24 +01:00
};
inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
std::string className = classOrQualifiedMethodName;
2013-09-07 13:07:38 +02:00
if( startsWith( className, "&" ) )
{
std::size_t lastColons = className.rfind( "::" );
std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
if( penultimateColons == std::string::npos )
penultimateColons = 1;
className = className.substr( penultimateColons, lastColons-penultimateColons );
}
return className;
}
2011-01-07 11:22:24 +01:00
///////////////////////////////////////////////////////////////////////////
2013-03-16 21:18:52 +01:00
AutoReg::AutoReg( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc ) {
registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
}
2012-05-10 22:46:46 +02:00
AutoReg::~AutoReg() {}
void AutoReg::registerTestCase( ITestCase* testCase,
2013-03-16 21:18:52 +01:00
char const* classOrQualifiedMethodName,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo ) {
2013-03-16 21:18:52 +01:00
getMutableRegistryHub().registerTest
( makeTestCase( testCase,
extractClassName( classOrQualifiedMethodName ),
nameAndDesc.name,
nameAndDesc.description,
lineInfo ) );
2011-01-07 11:22:24 +01:00
}
2011-01-07 11:22:24 +01:00
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED