mirror of
https://github.com/catchorg/Catch2.git
synced 2025-08-03 13:55:39 +02:00
Added TestCaseInfoHasher and tests. (#2394)
Test case hashing includes tags and class name As the hasher involves more code now, it was split out into its own file and it got its own set of tests. Closes #2304
This commit is contained in:
@@ -157,6 +157,7 @@ set(INTERNAL_HEADERS
|
||||
${SOURCES_DIR}/internal/catch_wildcard_pattern.hpp
|
||||
${SOURCES_DIR}/internal/catch_windows_h_proxy.hpp
|
||||
${SOURCES_DIR}/internal/catch_xmlwriter.hpp
|
||||
${SOURCES_DIR}/internal/catch_test_case_info_hasher.hpp
|
||||
)
|
||||
set(IMPL_SOURCES
|
||||
${SOURCES_DIR}/catch_approx.cpp
|
||||
@@ -213,6 +214,7 @@ set(IMPL_SOURCES
|
||||
${SOURCES_DIR}/catch_version.cpp
|
||||
${SOURCES_DIR}/internal/catch_wildcard_pattern.cpp
|
||||
${SOURCES_DIR}/internal/catch_xmlwriter.cpp
|
||||
${SOURCES_DIR}/internal/catch_test_case_info_hasher.cpp
|
||||
)
|
||||
set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
|
||||
|
||||
|
@@ -95,6 +95,7 @@
|
||||
#include <catch2/internal/catch_stringref.hpp>
|
||||
#include <catch2/internal/catch_tag_alias_registry.hpp>
|
||||
#include <catch2/internal/catch_template_test_registry.hpp>
|
||||
#include <catch2/internal/catch_test_case_info_hasher.hpp>
|
||||
#include <catch2/internal/catch_test_case_registry_impl.hpp>
|
||||
#include <catch2/internal/catch_test_case_tracker.hpp>
|
||||
#include <catch2/internal/catch_test_failure_exception.hpp>
|
||||
|
31
src/catch2/internal/catch_test_case_info_hasher.cpp
Normal file
31
src/catch2/internal/catch_test_case_info_hasher.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <catch2/catch_test_case_info.hpp>
|
||||
#include <catch2/internal/catch_test_case_info_hasher.hpp>
|
||||
|
||||
namespace Catch {
|
||||
TestCaseInfoHasher::TestCaseInfoHasher( hash_t seed ): m_seed( seed ) {}
|
||||
|
||||
uint32_t TestCaseInfoHasher::operator()( TestCaseInfo const& t ) const {
|
||||
// FNV-1a hash algorithm that is designed for uniqueness:
|
||||
const hash_t prime = 1099511628211u;
|
||||
hash_t hash = 14695981039346656037u;
|
||||
for ( const char c : t.name ) {
|
||||
hash ^= c;
|
||||
hash *= prime;
|
||||
}
|
||||
for ( const char c : t.className ) {
|
||||
hash ^= c;
|
||||
hash *= prime;
|
||||
}
|
||||
for ( const Tag& tag : t.tags ) {
|
||||
for ( const char c : tag.original ) {
|
||||
hash ^= c;
|
||||
hash *= prime;
|
||||
}
|
||||
}
|
||||
hash ^= m_seed;
|
||||
hash *= prime;
|
||||
const uint32_t low{ static_cast<uint32_t>( hash ) };
|
||||
const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };
|
||||
return low * high;
|
||||
}
|
||||
} // namespace Catch
|
22
src/catch2/internal/catch_test_case_info_hasher.hpp
Normal file
22
src/catch2/internal/catch_test_case_info_hasher.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED
|
||||
#define CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
struct TestCaseInfo;
|
||||
|
||||
class TestCaseInfoHasher {
|
||||
public:
|
||||
using hash_t = std::uint64_t;
|
||||
TestCaseInfoHasher( hash_t seed );
|
||||
uint32_t operator()( TestCaseInfo const& t ) const;
|
||||
|
||||
private:
|
||||
hash_t m_seed;
|
||||
};
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#endif /* CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED */
|
@@ -16,38 +16,13 @@
|
||||
#include <catch2/catch_test_case_info.hpp>
|
||||
#include <catch2/catch_test_spec.hpp>
|
||||
#include <catch2/internal/catch_move_and_forward.hpp>
|
||||
#include <catch2/internal/catch_test_case_info_hasher.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
namespace Catch {
|
||||
|
||||
namespace {
|
||||
struct TestHasher {
|
||||
using hash_t = uint64_t;
|
||||
|
||||
explicit TestHasher( hash_t hashSuffix ):
|
||||
m_hashSuffix( hashSuffix ) {}
|
||||
|
||||
uint64_t m_hashSuffix;
|
||||
|
||||
uint32_t operator()( TestCaseInfo const& t ) const {
|
||||
// FNV-1a hash with multiplication fold.
|
||||
const hash_t prime = 1099511628211u;
|
||||
hash_t hash = 14695981039346656037u;
|
||||
for (const char c : t.name) {
|
||||
hash ^= c;
|
||||
hash *= prime;
|
||||
}
|
||||
hash ^= m_hashSuffix;
|
||||
hash *= prime;
|
||||
const uint32_t low{ static_cast<uint32_t>(hash) };
|
||||
const uint32_t high{ static_cast<uint32_t>(hash >> 32) };
|
||||
return low * high;
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases ) {
|
||||
switch (config.runOrder()) {
|
||||
case TestRunOrder::Declared:
|
||||
@@ -66,9 +41,9 @@ namespace {
|
||||
}
|
||||
case TestRunOrder::Randomized: {
|
||||
seedRng(config);
|
||||
using TestWithHash = std::pair<TestHasher::hash_t, TestCaseHandle>;
|
||||
using TestWithHash = std::pair<TestCaseInfoHasher::hash_t, TestCaseHandle>;
|
||||
|
||||
TestHasher h{ config.rngSeed() };
|
||||
TestCaseInfoHasher h{ config.rngSeed() };
|
||||
std::vector<TestWithHash> indexed_tests;
|
||||
indexed_tests.reserve(unsortedTestCases.size());
|
||||
|
||||
|
Reference in New Issue
Block a user