Introduce Catch's own RNG based on the PCG family of RNGs

In the future, we will also want to introduce our own
`uniform_int_distribution` and `uniform_real_distribution` to get
repeatable test runs across different platforms.
This commit is contained in:
Martin Hořeňovský 2019-10-06 21:47:54 +02:00
parent 319cb9e1da
commit 535da5c513
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
14 changed files with 565 additions and 23 deletions

View File

@ -7,6 +7,7 @@
*/ */
#include "catch_context.h" #include "catch_context.h"
#include "catch_common.h" #include "catch_common.h"
#include "catch_random_number_generator.h"
namespace Catch { namespace Catch {
@ -59,4 +60,11 @@ namespace Catch {
IContext::~IContext() = default; IContext::~IContext() = default;
IMutableContext::~IMutableContext() = default; IMutableContext::~IMutableContext() = default;
Context::~Context() = default; Context::~Context() = default;
SimplePcg32& rng() {
static SimplePcg32 s_rng;
return s_rng;
}
} }

View File

@ -55,6 +55,9 @@ namespace Catch {
} }
void cleanUpContext(); void cleanUpContext();
class SimplePcg32;
SimplePcg32& rng();
} }
#endif // TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED #endif // TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED

View File

@ -7,23 +7,67 @@
#include "catch_random_number_generator.h" #include "catch_random_number_generator.h"
#include "catch_context.h" #include "catch_context.h"
#include "catch_run_context.h"
#include "catch_interfaces_config.h" #include "catch_interfaces_config.h"
namespace Catch { namespace Catch {
std::mt19937& rng() { namespace {
static std::mt19937 s_rng;
return s_rng; #if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4146) // we negate uint32 during the rotate
#endif
// Safe rotr implementation thanks to John Regehr
uint32_t rotate_right(uint32_t val, uint32_t count) {
const uint32_t mask = 31;
count &= mask;
return (val >> count) | (val << (-count & mask));
} }
void seedRng( IConfig const& config ) { #if defined(_MSC_VER)
if( config.rngSeed() != 0 ) { #pragma warning(pop)
std::srand( config.rngSeed() ); #endif
rng().seed( config.rngSeed() );
}
SimplePcg32::SimplePcg32(result_type seed_) {
seed(seed_);
}
void SimplePcg32::seed(result_type seed_) {
m_state = 0;
(*this)();
m_state += seed_;
(*this)();
}
void SimplePcg32::discard(uint64_t skip) {
// We could implement this to run in O(log n) steps, but this
// should suffice for our use case.
for (uint64_t s = 0; s < skip; ++s) {
static_cast<void>((*this)());
} }
} }
unsigned int rngSeed() { SimplePcg32::result_type SimplePcg32::operator()() {
return getCurrentContext().getConfig()->rngSeed(); // prepare the output value
const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
const auto output = rotate_right(xorshifted, m_state >> 59u);
// advance state
m_state = m_state * 6364136223846793005ULL + s_inc;
return output;
}
bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
return lhs.m_state == rhs.m_state;
}
bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
return lhs.m_state != rhs.m_state;
} }
} }

View File

@ -7,17 +7,52 @@
#ifndef TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
#define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED #define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
#include <algorithm> #include <cstdint>
#include <random>
namespace Catch { namespace Catch {
struct IConfig; // This is a simple implementation of C++11 Uniform Random Number
// Generator. It does not provide all operators, because Catch2
std::mt19937& rng(); // does not use it, but it should behave as expected inside stdlib's
void seedRng( IConfig const& config ); // distributions.
unsigned int rngSeed(); // The implementation is based on the PCG family (http://pcg-random.org)
class SimplePcg32 {
using state_type = std::uint64_t;
public:
using result_type = std::uint32_t;
static constexpr result_type min() {
return 0;
}
static constexpr result_type max() {
return static_cast<result_type>(-1);
} }
// Provide some default initial state for the default constructor
SimplePcg32():SimplePcg32(0xed743cc4U) {}
explicit SimplePcg32(result_type seed_);
void seed(result_type seed_);
void discard(uint64_t skip);
result_type operator()();
private:
friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
// In theory we also need operator<< and operator>>
// In practice we do not use them, so we will skip them for now
std::uint64_t m_state;
// This part of the state determines which "stream" of the numbers
// is chosen -- we take it as a constant for Catch2, so we only
// need to deal with seeding the main state.
// Picked by reading 8 bytes from `/dev/random` :-)
static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
};
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED #endif // TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED

View File

@ -506,4 +506,16 @@ namespace Catch {
else else
CATCH_INTERNAL_ERROR("No result capture instance"); CATCH_INTERNAL_ERROR("No result capture instance");
} }
void seedRng(IConfig const& config) {
if (config.rngSeed() != 0) {
std::srand(config.rngSeed());
rng().seed(config.rngSeed());
}
}
unsigned int rngSeed() {
return getCurrentContext().getConfig()->rngSeed();
}
} }

View File

@ -151,6 +151,8 @@ namespace Catch {
bool m_includeSuccessfulResults; bool m_includeSuccessfulResults;
}; };
void seedRng(IConfig const& config);
unsigned int rngSeed();
} // end namespace Catch } // end namespace Catch
#endif // TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED

View File

@ -11,6 +11,7 @@
#include "catch_enforce.h" #include "catch_enforce.h"
#include "catch_interfaces_registry_hub.h" #include "catch_interfaces_registry_hub.h"
#include "catch_random_number_generator.h" #include "catch_random_number_generator.h"
#include "catch_run_context.h"
#include "catch_string_manip.h" #include "catch_string_manip.h"
#include "catch_test_case_info.h" #include "catch_test_case_info.h"

View File

@ -21,6 +21,7 @@ set(TEST_SOURCES
${SELF_TEST_DIR}/IntrospectiveTests/GeneratorsImpl.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/GeneratorsImpl.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/InternalBenchmark.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/InternalBenchmark.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/RandomNumberGeneration.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/Tag.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/Tag.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/StringManip.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/StringManip.tests.cpp

View File

@ -276,6 +276,10 @@ Tricky.tests.cpp:<line number>: passed: true
Tricky.tests.cpp:<line number>: passed: std::vector<int>{1, 2} == std::vector<int>{1, 2} for: { 1, 2 } == { 1, 2 } Tricky.tests.cpp:<line number>: passed: std::vector<int>{1, 2} == std::vector<int>{1, 2} for: { 1, 2 } == { 1, 2 }
Tricky.tests.cpp:<line number>: passed: a for: 0x<hex digits> Tricky.tests.cpp:<line number>: passed: a for: 0x<hex digits>
Tricky.tests.cpp:<line number>: passed: a == &foo for: 0x<hex digits> == 0x<hex digits> Tricky.tests.cpp:<line number>: passed: a == &foo for: 0x<hex digits> == 0x<hex digits>
RandomNumberGeneration.tests.cpp:<line number>: passed: SimplePcg32{} == SimplePcg32{} for: {?} == {?}
RandomNumberGeneration.tests.cpp:<line number>: passed: SimplePcg32{ 0 } != SimplePcg32{} for: {?} != {?}
RandomNumberGeneration.tests.cpp:<line number>: passed: !(SimplePcg32{ 1 } == SimplePcg32{ 2 }) for: !({?} == {?})
RandomNumberGeneration.tests.cpp:<line number>: passed: !(SimplePcg32{ 1 } != SimplePcg32{ 1 }) for: !({?} != {?})
Approx.tests.cpp:<line number>: passed: td == Approx(10.0) for: StrongDoubleTypedef(10) == Approx( 10.0 ) Approx.tests.cpp:<line number>: passed: td == Approx(10.0) for: StrongDoubleTypedef(10) == Approx( 10.0 )
Approx.tests.cpp:<line number>: passed: Approx(10.0) == td for: Approx( 10.0 ) == StrongDoubleTypedef(10) Approx.tests.cpp:<line number>: passed: Approx(10.0) == td for: Approx( 10.0 ) == StrongDoubleTypedef(10)
Approx.tests.cpp:<line number>: passed: td != Approx(11.0) for: StrongDoubleTypedef(10) != Approx( 11.0 ) Approx.tests.cpp:<line number>: passed: td != Approx(11.0) for: StrongDoubleTypedef(10) != Approx( 11.0 )
@ -731,6 +735,51 @@ Condition.tests.cpp:<line number>: passed: data.str_hello < "hellp" for: "hello"
Condition.tests.cpp:<line number>: passed: data.str_hello < "zebra" for: "hello" < "zebra" Condition.tests.cpp:<line number>: passed: data.str_hello < "zebra" for: "hello" < "zebra"
Condition.tests.cpp:<line number>: passed: data.str_hello > "hellm" for: "hello" > "hellm" Condition.tests.cpp:<line number>: passed: data.str_hello > "hellm" for: "hello" > "hellm"
Condition.tests.cpp:<line number>: passed: data.str_hello > "a" for: "hello" > "a" Condition.tests.cpp:<line number>: passed: data.str_hello > "a" for: "hello" > "a"
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 4242248763 (0x<hex digits>)
==
4242248763 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1867888929 (0x<hex digits>)
==
1867888929 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1276619030 (0x<hex digits>)
==
1276619030 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1911218783 (0x<hex digits>)
==
1911218783 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1827115164 (0x<hex digits>)
==
1827115164 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1472234645 (0x<hex digits>)
==
1472234645 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 868832940 (0x<hex digits>)
==
868832940 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 570883446 (0x<hex digits>)
==
570883446 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 889299803 (0x<hex digits>)
==
889299803 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 4261393167 (0x<hex digits>)
==
4261393167 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 1472234645 (0x<hex digits>)
==
1472234645 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 868832940 (0x<hex digits>)
==
868832940 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 570883446 (0x<hex digits>)
==
570883446 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 889299803 (0x<hex digits>)
==
889299803 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: passed: rng() == 0x<hex digits> for: 4261393167 (0x<hex digits>)
==
4261393167 (0x<hex digits>)
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section one' Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section one'
Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section two' Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Message from section two'
CmdLine.tests.cpp:<line number>: passed: spec.hasFilters() == false for: false == false CmdLine.tests.cpp:<line number>: passed: spec.hasFilters() == false for: false == false

View File

@ -1380,6 +1380,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 301 | 227 passed | 70 failed | 4 failed as expected test cases: 303 | 229 passed | 70 failed | 4 failed as expected
assertions: 1570 | 1418 passed | 131 failed | 21 failed as expected assertions: 1589 | 1437 passed | 131 failed | 21 failed as expected

View File

@ -2179,6 +2179,32 @@ Tricky.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
0x<hex digits> == 0x<hex digits> 0x<hex digits> == 0x<hex digits>
-------------------------------------------------------------------------------
Comparison ops
-------------------------------------------------------------------------------
RandomNumberGeneration.tests.cpp:<line number>
...............................................................................
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( SimplePcg32{} == SimplePcg32{} )
with expansion:
{?} == {?}
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( SimplePcg32{ 0 } != SimplePcg32{} )
with expansion:
{?} != {?}
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( SimplePcg32{ 1 } == SimplePcg32{ 2 } )
with expansion:
!({?} == {?})
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( SimplePcg32{ 1 } != SimplePcg32{ 1 } )
with expansion:
!({?} != {?})
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Comparison with explicitly convertible types Comparison with explicitly convertible types
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -5494,6 +5520,125 @@ Condition.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
"hello" > "a" "hello" > "a"
-------------------------------------------------------------------------------
Our PCG implementation provides expected results for known seeds
Default seeded
-------------------------------------------------------------------------------
RandomNumberGeneration.tests.cpp:<line number>
...............................................................................
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
4242248763 (0x<hex digits>)
==
4242248763 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
1867888929 (0x<hex digits>)
==
1867888929 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
1276619030 (0x<hex digits>)
==
1276619030 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
1911218783 (0x<hex digits>)
==
1911218783 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
1827115164 (0x<hex digits>)
==
1827115164 (0x<hex digits>)
-------------------------------------------------------------------------------
Our PCG implementation provides expected results for known seeds
Specific seed
-------------------------------------------------------------------------------
RandomNumberGeneration.tests.cpp:<line number>
...............................................................................
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
1472234645 (0x<hex digits>)
==
1472234645 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
868832940 (0x<hex digits>)
==
868832940 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
570883446 (0x<hex digits>)
==
570883446 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
889299803 (0x<hex digits>)
==
889299803 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
4261393167 (0x<hex digits>)
==
4261393167 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
1472234645 (0x<hex digits>)
==
1472234645 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
868832940 (0x<hex digits>)
==
868832940 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
570883446 (0x<hex digits>)
==
570883446 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
889299803 (0x<hex digits>)
==
889299803 (0x<hex digits>)
RandomNumberGeneration.tests.cpp:<line number>: PASSED:
REQUIRE( rng() == 0x<hex digits> )
with expansion:
4261393167 (0x<hex digits>)
==
4261393167 (0x<hex digits>)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Output from all sections is reported Output from all sections is reported
one one
@ -12565,6 +12710,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 301 | 211 passed | 86 failed | 4 failed as expected test cases: 303 | 213 passed | 86 failed | 4 failed as expected
assertions: 1587 | 1418 passed | 148 failed | 21 failed as expected assertions: 1606 | 1437 passed | 148 failed | 21 failed as expected

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact <testsuitesloose text artifact
> >
<testsuite name="<exe-name>" errors="17" failures="132" tests="1588" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="132" tests="1607" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties> <properties>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/> <property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
@ -242,6 +242,7 @@ Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Character pretty printing/Low ASCII" time="{duration}"/> <testcase classname="<exe-name>.global" name="Character pretty printing/Low ASCII" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Commas in various macros are allowed" time="{duration}"/> <testcase classname="<exe-name>.global" name="Commas in various macros are allowed" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Comparing function pointers" time="{duration}"/> <testcase classname="<exe-name>.global" name="Comparing function pointers" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Comparison ops" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Comparison with explicitly convertible types" time="{duration}"/> <testcase classname="<exe-name>.global" name="Comparison with explicitly convertible types" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Comparisons between ints where one side is computed" time="{duration}"/> <testcase classname="<exe-name>.global" name="Comparisons between ints where one side is computed" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" time="{duration}"/> <testcase classname="<exe-name>.global" name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" time="{duration}"/>
@ -577,6 +578,8 @@ Condition.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="Ordering comparison checks that should succeed" time="{duration}"/> <testcase classname="<exe-name>.global" name="Ordering comparison checks that should succeed" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Our PCG implementation provides expected results for known seeds/Default seeded" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Our PCG implementation provides expected results for known seeds/Specific seed" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Output from all sections is reported/one" time="{duration}"> <testcase classname="<exe-name>.global" name="Output from all sections is reported/one" time="{duration}">
<failure type="FAIL"> <failure type="FAIL">
Message from section one Message from section one

View File

@ -2529,6 +2529,41 @@ Nor would this
</Expression> </Expression>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Comparison ops" tags="[rng]" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
SimplePcg32{} == SimplePcg32{}
</Original>
<Expanded>
{?} == {?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
SimplePcg32{ 0 } != SimplePcg32{}
</Original>
<Expanded>
{?} != {?}
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
!(SimplePcg32{ 1 } == SimplePcg32{ 2 })
</Original>
<Expanded>
!({?} == {?})
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
!(SimplePcg32{ 1 } != SimplePcg32{ 1 })
</Original>
<Expanded>
!({?} != {?})
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Comparison with explicitly convertible types" tags="[Approx]" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" > <TestCase name="Comparison with explicitly convertible types" tags="[Approx]" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
<Original> <Original>
@ -6728,6 +6763,165 @@ Nor would this
</Expression> </Expression>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Our PCG implementation provides expected results for known seeds" tags="[rng]" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Section name="Default seeded" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
4242248763 (0x<hex digits>)
==
4242248763 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
1867888929 (0x<hex digits>)
==
1867888929 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
1276619030 (0x<hex digits>)
==
1276619030 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
1911218783 (0x<hex digits>)
==
1911218783 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
1827115164 (0x<hex digits>)
==
1827115164 (0x<hex digits>)
</Expanded>
</Expression>
<OverallResults successes="5" failures="0" expectedFailures="0"/>
</Section>
<Section name="Specific seed" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
1472234645 (0x<hex digits>)
==
1472234645 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
868832940 (0x<hex digits>)
==
868832940 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
570883446 (0x<hex digits>)
==
570883446 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
889299803 (0x<hex digits>)
==
889299803 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
4261393167 (0x<hex digits>)
==
4261393167 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
1472234645 (0x<hex digits>)
==
1472234645 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
868832940 (0x<hex digits>)
==
868832940 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
570883446 (0x<hex digits>)
==
570883446 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
889299803 (0x<hex digits>)
==
889299803 (0x<hex digits>)
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/RandomNumberGeneration.tests.cpp" >
<Original>
rng() == 0x<hex digits>
</Original>
<Expanded>
4261393167 (0x<hex digits>)
==
4261393167 (0x<hex digits>)
</Expanded>
</Expression>
<OverallResults successes="10" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Output from all sections is reported" tags="[.][failing][messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" > <TestCase name="Output from all sections is reported" tags="[.][failing][messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
<Section name="one" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" > <Section name="one" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
<Failure filename="projects/<exe-name>/UsageTests/Message.tests.cpp" > <Failure filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
@ -14923,7 +15117,7 @@ loose text artifact
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="1418" failures="149" expectedFailures="21"/> <OverallResults successes="1437" failures="149" expectedFailures="21"/>
</Group> </Group>
<OverallResults successes="1418" failures="148" expectedFailures="21"/> <OverallResults successes="1437" failures="148" expectedFailures="21"/>
</Catch> </Catch>

View File

@ -0,0 +1,45 @@
/*
* Created by Martin on 06/10/2019.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "catch.hpp"
#include "internal/catch_random_number_generator.h"
TEST_CASE("Our PCG implementation provides expected results for known seeds", "[rng]") {
Catch::SimplePcg32 rng;
SECTION("Default seeded") {
REQUIRE(rng() == 0xfcdb943b);
REQUIRE(rng() == 0x6f55b921);
REQUIRE(rng() == 0x4c17a916);
REQUIRE(rng() == 0x71eae25f);
REQUIRE(rng() == 0x6ce7909c);
}
SECTION("Specific seed") {
rng.seed(0xabcd1234);
REQUIRE(rng() == 0x57c08495);
REQUIRE(rng() == 0x33c956ac);
REQUIRE(rng() == 0x2206fd76);
REQUIRE(rng() == 0x3501a35b);
REQUIRE(rng() == 0xfdffb30f);
// Also check repeated output after reseeding
rng.seed(0xabcd1234);
REQUIRE(rng() == 0x57c08495);
REQUIRE(rng() == 0x33c956ac);
REQUIRE(rng() == 0x2206fd76);
REQUIRE(rng() == 0x3501a35b);
REQUIRE(rng() == 0xfdffb30f);
}
}
TEST_CASE("Comparison ops", "[rng]") {
using Catch::SimplePcg32;
REQUIRE(SimplePcg32{} == SimplePcg32{});
REQUIRE(SimplePcg32{ 0 } != SimplePcg32{});
REQUIRE_FALSE(SimplePcg32{ 1 } == SimplePcg32{ 2 });
REQUIRE_FALSE(SimplePcg32{ 1 } != SimplePcg32{ 1 });
}