diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f69d3166..341da85c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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}) diff --git a/src/catch2/generators/catch_generators_random.cpp b/src/catch2/generators/catch_generators_random.cpp new file mode 100644 index 00000000..57ad1745 --- /dev/null +++ b/src/catch2/generators/catch_generators_random.cpp @@ -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 + +#include + +std::uint32_t Catch::Generators::Detail::getSeed() { return sharedRng()(); } diff --git a/src/catch2/generators/catch_generators_random.hpp b/src/catch2/generators/catch_generators_random.hpp index 11e997ca..15043211 100644 --- a/src/catch2/generators/catch_generators_random.hpp +++ b/src/catch2/generators/catch_generators_random.hpp @@ -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 class RandomFloatingGenerator final : public IGenerator { - Catch::SimplePcg32& m_rng; + Catch::SimplePcg32 m_rng; std::uniform_real_distribution 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(next()); } @@ -41,13 +46,12 @@ public: template class RandomIntegerGenerator final : public IGenerator { - Catch::SimplePcg32& m_rng; + Catch::SimplePcg32 m_rng; std::uniform_int_distribution 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(next()); } @@ -68,7 +72,7 @@ std::enable_if_t::value && !std::is_same::value, GeneratorWrapper> random(T a, T b) { return GeneratorWrapper( - Catch::Detail::make_unique>(a, b) + Catch::Detail::make_unique>(a, b, Detail::getSeed()) ); } @@ -77,7 +81,7 @@ std::enable_if_t::value, GeneratorWrapper> random(T a, T b) { return GeneratorWrapper( - Catch::Detail::make_unique>(a, b) + Catch::Detail::make_unique>(a, b, Detail::getSeed()) ); } diff --git a/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp b/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp index 7793e970..3ad20453 100644 --- a/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp @@ -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 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 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(); + } + } +}