1 /* 2 * Created by Martin on 25/07/2017 3 * 4 * Distributed under the Boost Software License, Version 1.0. (See accompanying 5 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 */ 7 8 #include "catch_test_case_registry_impl.h" 9 10 #include "catch_context.h" 11 #include "catch_enforce.h" 12 #include "catch_interfaces_registry_hub.h" 13 #include "catch_random_number_generator.h" 14 #include "catch_string_manip.h" 15 #include "catch_test_case_info.h" 16 17 #include <sstream> 18 19 namespace Catch { 20 sortTests(IConfig const & config,std::vector<TestCase> const & unsortedTestCases)21 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { 22 23 std::vector<TestCase> sorted = unsortedTestCases; 24 25 switch( config.runOrder() ) { 26 case RunTests::InLexicographicalOrder: 27 std::sort( sorted.begin(), sorted.end() ); 28 break; 29 case RunTests::InRandomOrder: 30 seedRng( config ); 31 RandomNumberGenerator::shuffle( sorted ); 32 break; 33 case RunTests::InDeclarationOrder: 34 // already in declaration order 35 break; 36 } 37 return sorted; 38 } matchTest(TestCase const & testCase,TestSpec const & testSpec,IConfig const & config)39 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { 40 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); 41 } 42 enforceNoDuplicateTestCases(std::vector<TestCase> const & functions)43 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { 44 std::set<TestCase> seenFunctions; 45 for( auto const& function : functions ) { 46 auto prev = seenFunctions.insert( function ); 47 CATCH_ENFORCE( prev.second, 48 "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" 49 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" 50 << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); 51 } 52 } 53 filterTests(std::vector<TestCase> const & testCases,TestSpec const & testSpec,IConfig const & config)54 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { 55 std::vector<TestCase> filtered; 56 filtered.reserve( testCases.size() ); 57 for( auto const& testCase : testCases ) 58 if( matchTest( testCase, testSpec, config ) ) 59 filtered.push_back( testCase ); 60 return filtered; 61 } getAllTestCasesSorted(IConfig const & config)62 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { 63 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); 64 } 65 registerTest(TestCase const & testCase)66 void TestRegistry::registerTest( TestCase const& testCase ) { 67 std::string name = testCase.getTestCaseInfo().name; 68 if( name.empty() ) { 69 ReusableStringStream rss; 70 rss << "Anonymous test case " << ++m_unnamedCount; 71 return registerTest( testCase.withName( rss.str() ) ); 72 } 73 m_functions.push_back( testCase ); 74 } 75 getAllTests() const76 std::vector<TestCase> const& TestRegistry::getAllTests() const { 77 return m_functions; 78 } getAllTestsSorted(IConfig const & config) const79 std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { 80 if( m_sortedFunctions.empty() ) 81 enforceNoDuplicateTestCases( m_functions ); 82 83 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { 84 m_sortedFunctions = sortTests( config, m_functions ); 85 m_currentSortOrder = config.runOrder(); 86 } 87 return m_sortedFunctions; 88 } 89 90 91 92 /////////////////////////////////////////////////////////////////////////// TestInvokerAsFunction(void (* testAsFunction)())93 TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} 94 invoke() const95 void TestInvokerAsFunction::invoke() const { 96 m_testAsFunction(); 97 } 98 extractClassName(StringRef const & classOrQualifiedMethodName)99 std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { 100 std::string className = classOrQualifiedMethodName; 101 if( startsWith( className, '&' ) ) 102 { 103 std::size_t lastColons = className.rfind( "::" ); 104 std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); 105 if( penultimateColons == std::string::npos ) 106 penultimateColons = 1; 107 className = className.substr( penultimateColons, lastColons-penultimateColons ); 108 } 109 return className; 110 } 111 112 } // end namespace Catch 113