mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 13:26:10 +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_wildcard_pattern.cpp
|
||||||
${SOURCES_DIR}/internal/catch_xmlwriter.cpp
|
${SOURCES_DIR}/internal/catch_xmlwriter.cpp
|
||||||
${SOURCES_DIR}/internal/catch_test_case_info_hasher.cpp
|
${SOURCES_DIR}/internal/catch_test_case_info_hasher.cpp
|
||||||
|
${SOURCES_DIR}/generators/catch_generators_random.cpp
|
||||||
)
|
)
|
||||||
set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
|
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 Catch {
|
||||||
namespace Generators {
|
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>
|
template <typename Float>
|
||||||
class RandomFloatingGenerator final : public IGenerator<Float> {
|
class RandomFloatingGenerator final : public IGenerator<Float> {
|
||||||
Catch::SimplePcg32& m_rng;
|
Catch::SimplePcg32 m_rng;
|
||||||
std::uniform_real_distribution<Float> m_dist;
|
std::uniform_real_distribution<Float> m_dist;
|
||||||
Float m_current_number;
|
Float m_current_number;
|
||||||
public:
|
public:
|
||||||
|
RandomFloatingGenerator( Float a, Float b, std::uint32_t seed ):
|
||||||
RandomFloatingGenerator(Float a, Float b):
|
m_rng(seed),
|
||||||
m_rng(sharedRng()),
|
|
||||||
m_dist(a, b) {
|
m_dist(a, b) {
|
||||||
static_cast<void>(next());
|
static_cast<void>(next());
|
||||||
}
|
}
|
||||||
@ -41,13 +46,12 @@ public:
|
|||||||
|
|
||||||
template <typename Integer>
|
template <typename Integer>
|
||||||
class RandomIntegerGenerator final : public IGenerator<Integer> {
|
class RandomIntegerGenerator final : public IGenerator<Integer> {
|
||||||
Catch::SimplePcg32& m_rng;
|
Catch::SimplePcg32 m_rng;
|
||||||
std::uniform_int_distribution<Integer> m_dist;
|
std::uniform_int_distribution<Integer> m_dist;
|
||||||
Integer m_current_number;
|
Integer m_current_number;
|
||||||
public:
|
public:
|
||||||
|
RandomIntegerGenerator( Integer a, Integer b, std::uint32_t seed ):
|
||||||
RandomIntegerGenerator(Integer a, Integer b):
|
m_rng(seed),
|
||||||
m_rng(sharedRng()),
|
|
||||||
m_dist(a, b) {
|
m_dist(a, b) {
|
||||||
static_cast<void>(next());
|
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>>
|
GeneratorWrapper<T>>
|
||||||
random(T a, T b) {
|
random(T a, T b) {
|
||||||
return GeneratorWrapper<T>(
|
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>>
|
GeneratorWrapper<T>>
|
||||||
random(T a, T b) {
|
random(T a, T b) {
|
||||||
return GeneratorWrapper<T>(
|
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 );
|
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