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