From bad0fb51f836a8d155fb2034980721aa36917fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 14 Apr 2020 16:39:45 +0200 Subject: [PATCH] Refactor implementation of hashed random order test sorting --- .../catch_test_case_registry_impl.cpp | 88 +++++++++++-------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/include/internal/catch_test_case_registry_impl.cpp b/include/internal/catch_test_case_registry_impl.cpp index 94e35e3a..065f70bd 100644 --- a/include/internal/catch_test_case_registry_impl.cpp +++ b/include/internal/catch_test_case_registry_impl.cpp @@ -16,63 +16,75 @@ #include "catch_test_case_info.h" #include -#include -#include #include namespace Catch { - struct HashTest { - explicit HashTest( Catch::SimplePcg32& rng ) { - basis = rng(); - basis <<= 32; - basis |= rng(); - } - - uint64_t basis; - - uint64_t operator()( TestCase 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; + namespace { + struct TestHasher { + explicit TestHasher(Catch::SimplePcg32& rng) { + basis = rng(); + basis <<= 32; + basis |= rng(); } - return hash; - } - }; + + uint64_t basis; + + uint64_t operator()(TestCase 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 unnamed namespace + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { switch( config.runOrder() ) { + case RunTests::InDeclarationOrder: + // already in declaration order + break; + 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; + TestHasher h( rng() ); + + using hashedTest = std::pair; + std::vector indexed_tests; indexed_tests.reserve( unsortedTestCases.size() ); - std::transform( unsortedTestCases.begin(), unsortedTestCases.end(), - std::back_inserter( indexed_tests ), - [&]( TestCase const& t ) { - return std::make_tuple( h(t), t.name, &t ); - } ); - std::sort( indexed_tests.begin(), indexed_tests.end() ); + + for (auto const& testCase : unsortedTestCases) { + indexed_tests.emplace_back(h(testCase), &testCase); + } + + std::sort(indexed_tests.begin(), indexed_tests.end(), + [](hashedTest const& lhs, hashedTest const& rhs) { + if (lhs.first == rhs.first) { + return lhs.second->name < rhs.second->name; + } + return lhs.first < rhs.first; + }); + std::vector sorted; - sorted.reserve( unsortedTestCases.size() ); - std::transform( indexed_tests.begin(), indexed_tests.end(), - std::back_inserter( sorted ), - []( std::tuple const& t ) { - return *std::get<2>( t ); - } ); + sorted.reserve( indexed_tests.size() ); + + for (auto const& hashed : indexed_tests) { + sorted.emplace_back(*hashed.second); + } + return sorted; } - case RunTests::InDeclarationOrder: - // already in declaration order - break; } return unsortedTestCases; }