diff --git a/src/catch2/internal/catch_test_case_registry_impl.cpp b/src/catch2/internal/catch_test_case_registry_impl.cpp index ab324a36..7d16fb50 100644 --- a/src/catch2/internal/catch_test_case_registry_impl.cpp +++ b/src/catch2/internal/catch_test_case_registry_impl.cpp @@ -16,27 +16,70 @@ #include #include +#include +#include +#include #include namespace Catch { - std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { - - std::vector 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; +namespace { + struct HashTest { + explicit HashTest(SimplePcg32& rng) { + basis = rng(); + basis <<= 32; + basis |= rng(); } - return sorted; + + uint64_t basis; + + uint64_t operator()(TestCaseInfo const& t) const { + // Modified FNV-1a hash + static constexpr uint64_t prime = 1099511628211; + uint64_t hash = basis; + for (const char c : t.name) { + hash ^= c; + hash *= prime; + } + return hash; + } + }; +} // end anonymous namespace + + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + switch (config.runOrder()) { + case RunTests::InDeclarationOrder: + return unsortedTestCases; + + case RunTests::InLexicographicalOrder: { + std::vector sorted = unsortedTestCases; + std::sort(sorted.begin(), sorted.end()); + return sorted; + } + case RunTests::InRandomOrder: { + seedRng(config); + HashTest h(rng()); + 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()); + + 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 ) {