mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 05:59:32 +01:00 
			
		
		
		
	This should decrease the number of allocations before main is entered significantly, but complicates the code somewhat in return. Assuming I used `massif` right, doing just `SelfTest --list-tests` went from 929 allocations at "Remove gcc-4.9 from the travis builds" (2 commits up), to 614 allocations with this commit.
		
			
				
	
	
		
			120 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 *  Created by Martin on 25/07/2017
 | 
						|
 *
 | 
						|
 *  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)
 | 
						|
 */
 | 
						|
 | 
						|
#include "catch_test_case_registry_impl.h"
 | 
						|
 | 
						|
#include "catch_context.h"
 | 
						|
#include "catch_enforce.h"
 | 
						|
#include "catch_interfaces_registry_hub.h"
 | 
						|
#include "catch_random_number_generator.h"
 | 
						|
#include "catch_run_context.h"
 | 
						|
#include "catch_string_manip.h"
 | 
						|
#include "catch_test_case_info.h"
 | 
						|
 | 
						|
#include <sstream>
 | 
						|
 | 
						|
namespace Catch {
 | 
						|
 | 
						|
    std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases ) {
 | 
						|
 | 
						|
        std::vector<TestCaseHandle> sorted = unsortedTestCases;
 | 
						|
 | 
						|
        switch( config.runOrder() ) {
 | 
						|
            case RunTests::InLexicographicalOrder:
 | 
						|
                std::sort( sorted.begin(), sorted.end() );
 | 
						|
                break;
 | 
						|
            case RunTests::InRandomOrder:
 | 
						|
                seedRng( config );
 | 
						|
                std::shuffle( sorted.begin(), sorted.end(), rng() );
 | 
						|
                break;
 | 
						|
            case RunTests::InDeclarationOrder:
 | 
						|
                // already in declaration order
 | 
						|
                break;
 | 
						|
        }
 | 
						|
        return sorted;
 | 
						|
    }
 | 
						|
 | 
						|
    bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ) {
 | 
						|
        return !testCase.getTestCaseInfo().throws() || config.allowThrows();
 | 
						|
    }
 | 
						|
 | 
						|
    bool matchTest( TestCaseHandle const& testCase, TestSpec const& testSpec, IConfig const& config ) {
 | 
						|
        return testSpec.matches( testCase.getTestCaseInfo() ) && isThrowSafe( testCase, config );
 | 
						|
    }
 | 
						|
 | 
						|
    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.getTestCaseInfo().name << "\" ) already defined.\n"
 | 
						|
                    << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
 | 
						|
                    << "\tRedefined at " << function.getTestCaseInfo().lineInfo );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    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.getTestCaseInfo().isHidden()) ||
 | 
						|
                (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
 | 
						|
                filtered.push_back(testCase);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return filtered;
 | 
						|
    }
 | 
						|
    std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config ) {
 | 
						|
        return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
 | 
						|
    }
 | 
						|
 | 
						|
    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<std::unique_ptr<TestCaseInfo>> const& TestRegistry::getAllInfos() const {
 | 
						|
        return m_infos;
 | 
						|
    }
 | 
						|
 | 
						|
    std::vector<TestCaseHandle> const& TestRegistry::getAllTests() const {
 | 
						|
        return m_handles;
 | 
						|
    }
 | 
						|
    std::vector<TestCaseHandle> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
 | 
						|
        if( m_sortedFunctions.empty() )
 | 
						|
            enforceNoDuplicateTestCases( m_handles );
 | 
						|
 | 
						|
        if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
 | 
						|
            m_sortedFunctions = sortTests( config, m_handles );
 | 
						|
            m_currentSortOrder = config.runOrder();
 | 
						|
        }
 | 
						|
        return m_sortedFunctions;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    ///////////////////////////////////////////////////////////////////////////
 | 
						|
    void TestInvokerAsFunction::invoke() const {
 | 
						|
        m_testAsFunction();
 | 
						|
    }
 | 
						|
 | 
						|
    std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
 | 
						|
        std::string className(classOrQualifiedMethodName);
 | 
						|
        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;
 | 
						|
    }
 | 
						|
 | 
						|
} // end namespace Catch
 |