/* * 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_string_manip.h" #include "catch_test_case_info.h" #include <sstream> namespace Catch { std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { std::vector<TestCase> 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 matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); } void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { std::set<TestCase> seenFunctions; for( auto const& function : functions ) { auto prev = seenFunctions.insert( function ); CATCH_ENFORCE( prev.second, "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); } } std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { std::vector<TestCase> filtered; filtered.reserve( testCases.size() ); for( auto const& testCase : testCases ) if( matchTest( testCase, testSpec, config ) ) filtered.push_back( testCase ); return filtered; } std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); } void TestRegistry::registerTest( TestCase const& testCase ) { std::string name = testCase.getTestCaseInfo().name; if( name.empty() ) { ReusableStringStream rss; rss << "Anonymous test case " << ++m_unnamedCount; return registerTest( testCase.withName( rss.str() ) ); } m_functions.push_back( testCase ); } std::vector<TestCase> const& TestRegistry::getAllTests() const { return m_functions; } std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { if( m_sortedFunctions.empty() ) enforceNoDuplicateTestCases( m_functions ); if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { m_sortedFunctions = sortTests( config, m_functions ); m_currentSortOrder = config.runOrder(); } return m_sortedFunctions; } /////////////////////////////////////////////////////////////////////////// TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} 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