// // random_test.cpp // shared_random_generator-test // // Created by Sam Jaffe on 8/14/20. // Copyright © 2020 Sam Jaffe. All rights reserved. // #include "shared_random_generator/random_impl.h" #include "shared_random_generator/random.h" #include struct mock_random_impl : engine::detail::random_impl { MOCK_METHOD1(exclusive, uint32_t(uint32_t)); MOCK_METHOD2(exclusive, double(double, double)); MOCK_METHOD2(inclusive, double(double, double)); }; TEST(RandomTest, PassesThroughExclusiveIntegerCall) { auto mock = std::make_shared(); engine::random_number_generator generator{mock}; EXPECT_CALL(*mock, exclusive(10)).Times(1); generator.exclusive(10); } TEST(RandomTest, PassesThroughExclusiveDoubleCall) { auto mock = std::make_shared(); engine::random_number_generator generator{mock}; EXPECT_CALL(*mock, exclusive(1.0, 10.0)).Times(1); generator.exclusive(1.0, 10.0); } TEST(RandomTest, PassesThroughInclusiveDoubleCall) { auto mock = std::make_shared(); engine::random_number_generator generator{mock}; EXPECT_CALL(*mock, inclusive(1.0, 10.0)).Times(1); generator.inclusive(1.0, 10.0); } class kahan_summation { private: double sum_{0.0}; double carry_{0.0}; public: kahan_summation() = default; kahan_summation & operator+=(double d); explicit operator double() const { return sum_; } }; kahan_summation & kahan_summation::operator+=(double num) { double const yield = num - carry_; double const total = sum_ + yield; carry_ = (total - sum_) - yield; sum_ = total; return *this; } TEST(DefaultRandomTest, RandomDistributionIntIsUniform) { engine::random_number_generator generator{}; kahan_summation sum{}; size_t const iters = 2000000; for (size_t i = 0; i < iters; ++i) { // All values from 0 - 100 are allowable sum += generator.exclusive(101); } // Expected result is (0+99)/2 +/- 0.1% EXPECT_THAT(double(sum) / iters, testing::DoubleNear(50, 0.05)); } TEST(DefaultRandomTest, RandomDistributionDblIsUniform) { engine::random_number_generator generator{}; kahan_summation sum{}; size_t const iters = 2000000; for (size_t i = 0; i < iters; ++i) { // All values from 0 - 99 are allowable sum += generator.exclusive(0.0, 100.0); } // Expected result is [0.0, 100.0) +/- 0.1% EXPECT_THAT(double(sum) / iters, testing::DoubleNear(50, 0.05)); } TEST(DefaultRandomTest, InclusiveRangeMayIncludeValue) { engine::random_number_generator generator{}; EXPECT_THAT(generator.inclusive(1.0, 1.0), testing::DoubleNear(1.0, 1E-6)); } TEST(DefaultRandomTest, RandomDistributionDblInclIsUniform) { engine::random_number_generator generator{}; kahan_summation sum{}; size_t const iters = 2000000; for (size_t i = 0; i < iters; ++i) { // All values in [0.0, 100.0] are allowable sum += generator.inclusive(0.0, 100.0); } // Expected result is (0+100)/2 +/- 0.1% EXPECT_THAT(double(sum) / iters, testing::DoubleNear(50, 0.05)); }