mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-22 19:33:29 +01:00
Make Random*Generators be seedable
This is a necessary step to fix issue with combining multiple random generators in one test case, with different section nesting.
This commit is contained in:
parent
359cd6187d
commit
7a2a6c632f
@ -222,6 +222,7 @@ set(IMPL_SOURCES
|
||||
${SOURCES_DIR}/internal/catch_wildcard_pattern.cpp
|
||||
${SOURCES_DIR}/internal/catch_xmlwriter.cpp
|
||||
${SOURCES_DIR}/internal/catch_test_case_info_hasher.cpp
|
||||
${SOURCES_DIR}/generators/catch_generators_random.cpp
|
||||
)
|
||||
set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
|
||||
|
||||
|
13
src/catch2/generators/catch_generators_random.cpp
Normal file
13
src/catch2/generators/catch_generators_random.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
// Copyright Catch2 Authors
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#include <catch2/generators/catch_generators_random.hpp>
|
||||
|
||||
#include <catch2/internal/catch_context.hpp>
|
||||
|
||||
std::uint32_t Catch::Generators::Detail::getSeed() { return sharedRng()(); }
|
@ -16,16 +16,21 @@
|
||||
|
||||
namespace Catch {
|
||||
namespace Generators {
|
||||
namespace Detail {
|
||||
// Returns a suitable seed for a random floating generator based off
|
||||
// the primary internal rng. It does so by taking current value from
|
||||
// the rng and returning it as the seed.
|
||||
std::uint32_t getSeed();
|
||||
}
|
||||
|
||||
template <typename Float>
|
||||
class RandomFloatingGenerator final : public IGenerator<Float> {
|
||||
Catch::SimplePcg32& m_rng;
|
||||
Catch::SimplePcg32 m_rng;
|
||||
std::uniform_real_distribution<Float> m_dist;
|
||||
Float m_current_number;
|
||||
public:
|
||||
|
||||
RandomFloatingGenerator(Float a, Float b):
|
||||
m_rng(sharedRng()),
|
||||
RandomFloatingGenerator( Float a, Float b, std::uint32_t seed ):
|
||||
m_rng(seed),
|
||||
m_dist(a, b) {
|
||||
static_cast<void>(next());
|
||||
}
|
||||
@ -41,13 +46,12 @@ public:
|
||||
|
||||
template <typename Integer>
|
||||
class RandomIntegerGenerator final : public IGenerator<Integer> {
|
||||
Catch::SimplePcg32& m_rng;
|
||||
Catch::SimplePcg32 m_rng;
|
||||
std::uniform_int_distribution<Integer> m_dist;
|
||||
Integer m_current_number;
|
||||
public:
|
||||
|
||||
RandomIntegerGenerator(Integer a, Integer b):
|
||||
m_rng(sharedRng()),
|
||||
RandomIntegerGenerator( Integer a, Integer b, std::uint32_t seed ):
|
||||
m_rng(seed),
|
||||
m_dist(a, b) {
|
||||
static_cast<void>(next());
|
||||
}
|
||||
@ -68,7 +72,7 @@ std::enable_if_t<std::is_integral<T>::value && !std::is_same<T, bool>::value,
|
||||
GeneratorWrapper<T>>
|
||||
random(T a, T b) {
|
||||
return GeneratorWrapper<T>(
|
||||
Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b)
|
||||
Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed())
|
||||
);
|
||||
}
|
||||
|
||||
@ -77,7 +81,7 @@ std::enable_if_t<std::is_floating_point<T>::value,
|
||||
GeneratorWrapper<T>>
|
||||
random(T a, T b) {
|
||||
return GeneratorWrapper<T>(
|
||||
Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b)
|
||||
Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b, Detail::getSeed())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -511,3 +511,26 @@ TEST_CASE( "Generator element stringification is cached",
|
||||
|
||||
REQUIRE( generator.stringificationCalls() == 1 );
|
||||
}
|
||||
|
||||
TEST_CASE( "Random generators can be seeded", "[generators][approvals]" ) {
|
||||
SECTION( "Integer generator" ) {
|
||||
using Catch::Generators::RandomIntegerGenerator;
|
||||
RandomIntegerGenerator<int> rng1( 0, 100, 0x1234 ),
|
||||
rng2( 0, 100, 0x1234 );
|
||||
|
||||
for ( size_t i = 0; i < 10; ++i ) {
|
||||
REQUIRE( rng1.get() == rng2.get() );
|
||||
rng1.next(); rng2.next();
|
||||
}
|
||||
}
|
||||
SECTION("Float generator") {
|
||||
using Catch::Generators::RandomFloatingGenerator;
|
||||
RandomFloatingGenerator<double> rng1( 0., 100., 0x1234 ),
|
||||
rng2( 0., 100., 0x1234 );
|
||||
for ( size_t i = 0; i < 10; ++i ) {
|
||||
REQUIRE( rng1.get() == rng2.get() );
|
||||
rng1.next();
|
||||
rng2.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user