// Copyright Catch2 Authors // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) // SPDX-License-Identifier: BSL-1.0 #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Catch { namespace { static void enforceNoDuplicateTestCases( std::vector const& tests ) { auto testInfoCmp = []( TestCaseInfo const* lhs, TestCaseInfo const* rhs ) { return *lhs < *rhs; }; std::set seenTests( testInfoCmp ); for ( auto const& test : tests ) { const auto infoPtr = &test.getTestCaseInfo(); const auto prev = seenTests.insert( infoPtr ); CATCH_ENFORCE( prev.second, "error: test case \"" << infoPtr->name << "\", with tags \"" << infoPtr->tagsAsString() << "\" already defined.\n" << "\tFirst seen at " << ( *prev.first )->lineInfo << "\n" << "\tRedefined at " << infoPtr->lineInfo ); } } static bool matchTest( TestCaseHandle const& testCase, TestSpec const& testSpec, IConfig const& config ) { return testSpec.matches( testCase.getTestCaseInfo() ) && isThrowSafe( testCase, config ); } } // end unnamed namespace std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { switch (config.runOrder()) { case TestRunOrder::Declared: return unsortedTestCases; case TestRunOrder::LexicographicallySorted: { std::vector sorted = unsortedTestCases; std::sort( sorted.begin(), sorted.end(), []( TestCaseHandle const& lhs, TestCaseHandle const& rhs ) { return lhs.getTestCaseInfo() < rhs.getTestCaseInfo(); } ); return sorted; } case TestRunOrder::Randomized: { seedRng(config); using TestWithHash = std::pair; TestCaseInfoHasher h{ config.rngSeed() }; std::vector indexed_tests; indexed_tests.reserve(unsortedTestCases.size()); for (auto const& handle : unsortedTestCases) { indexed_tests.emplace_back(h(handle.getTestCaseInfo()), handle); } std::sort( indexed_tests.begin(), indexed_tests.end(), []( TestWithHash const& lhs, TestWithHash const& rhs ) { if ( lhs.first == rhs.first ) { return lhs.second.getTestCaseInfo() < rhs.second.getTestCaseInfo(); } return lhs.first < rhs.first; } ); std::vector randomized; randomized.reserve(indexed_tests.size()); for (auto const& indexed : indexed_tests) { randomized.push_back(indexed.second); } return randomized; } } CATCH_INTERNAL_ERROR("Unknown test order value!"); } bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ) { return !testCase.getTestCaseInfo().throws() || config.allowThrows(); } std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { std::vector 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 createShard(filtered, config.shardCount(), config.shardIndex()); } std::vector const& getAllTestCasesSorted( IConfig const& config ) { return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); } void TestRegistry::registerTest(Detail::unique_ptr testInfo, Detail::unique_ptr testInvoker) { m_handles.emplace_back(testInfo.get(), testInvoker.get()); m_viewed_test_infos.push_back(testInfo.get()); m_owned_test_infos.push_back(CATCH_MOVE(testInfo)); m_invokers.push_back(CATCH_MOVE(testInvoker)); } std::vector const& TestRegistry::getAllInfos() const { return m_viewed_test_infos; } std::vector const& TestRegistry::getAllTests() const { return m_handles; } std::vector 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; } } // end namespace Catch