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_run_context.h" 15 #include "catch_string_manip.h" 16 #include "catch_test_case_info.h" 17 18 #include <sstream> 19 20 namespace Catch { 21 sortTests(IConfig const & config,std::vector<TestCase> const & unsortedTestCases)22 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { 23 24 std::vector<TestCase> sorted = unsortedTestCases; 25 26 switch( config.runOrder() ) { 27 case RunTests::InLexicographicalOrder: 28 std::sort( sorted.begin(), sorted.end() ); 29 break; 30 case RunTests::InRandomOrder: 31 seedRng( config ); 32 std::shuffle( sorted.begin(), sorted.end(), rng() ); 33 break; 34 case RunTests::InDeclarationOrder: 35 // already in declaration order 36 break; 37 } 38 return sorted; 39 } 40 isThrowSafe(TestCase const & testCase,IConfig const & config)41 bool isThrowSafe( TestCase const& testCase, IConfig const& config ) { 42 return !testCase.throws() || config.allowThrows(); 43 } 44 matchTest(TestCase const & testCase,TestSpec const & testSpec,IConfig const & config)45 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { 46 return testSpec.matches( testCase ) && isThrowSafe( testCase, config ); 47 } 48 enforceNoDuplicateTestCases(std::vector<TestCase> const & functions)49 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { 50 std::set<TestCase> seenFunctions; 51 for( auto const& function : functions ) { 52 auto prev = seenFunctions.insert( function ); 53 CATCH_ENFORCE( prev.second, 54 "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" 55 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" 56 << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); 57 } 58 } 59 filterTests(std::vector<TestCase> const & testCases,TestSpec const & testSpec,IConfig const & config)60 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { 61 std::vector<TestCase> filtered; 62 filtered.reserve( testCases.size() ); 63 for (auto const& testCase : testCases) { 64 if ((!testSpec.hasFilters() && !testCase.isHidden()) || 65 (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) { 66 filtered.push_back(testCase); 67 } 68 } 69 return filtered; 70 } getAllTestCasesSorted(IConfig const & config)71 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { 72 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); 73 } 74 registerTest(TestCase const & testCase)75 void TestRegistry::registerTest( TestCase const& testCase ) { 76 std::string name = testCase.getTestCaseInfo().name; 77 if( name.empty() ) { 78 ReusableStringStream rss; 79 rss << "Anonymous test case " << ++m_unnamedCount; 80 return registerTest( testCase.withName( rss.str() ) ); 81 } 82 m_functions.push_back( testCase ); 83 } 84 getAllTests() const85 std::vector<TestCase> const& TestRegistry::getAllTests() const { 86 return m_functions; 87 } getAllTestsSorted(IConfig const & config) const88 std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { 89 if( m_sortedFunctions.empty() ) 90 enforceNoDuplicateTestCases( m_functions ); 91 92 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { 93 m_sortedFunctions = sortTests( config, m_functions ); 94 m_currentSortOrder = config.runOrder(); 95 } 96 return m_sortedFunctions; 97 } 98 99 100 101 /////////////////////////////////////////////////////////////////////////// TestInvokerAsFunction(void (* testAsFunction)())102 TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} 103 invoke() const104 void TestInvokerAsFunction::invoke() const { 105 m_testAsFunction(); 106 } 107 extractClassName(StringRef const & classOrQualifiedMethodName)108 std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { 109 std::string className(classOrQualifiedMethodName); 110 if( startsWith( className, '&' ) ) 111 { 112 std::size_t lastColons = className.rfind( "::" ); 113 std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); 114 if( penultimateColons == std::string::npos ) 115 penultimateColons = 1; 116 className = className.substr( penultimateColons, lastColons-penultimateColons ); 117 } 118 return className; 119 } 120 121 } // end namespace Catch 122