diff --git a/src/random.h b/src/random.h --- a/src/random.h +++ b/src/random.h @@ -70,11 +70,27 @@ * Thread-safe. */ void GetRandBytes(uint8_t *buf, int num) noexcept; +/** + * Generate a uniform random integer in the range [0..range). + * Precondition: range > 0 + */ uint64_t GetRand(uint64_t nMax) noexcept; -std::chrono::microseconds -GetRandMicros(std::chrono::microseconds duration_max) noexcept; -std::chrono::milliseconds -GetRandMillis(std::chrono::milliseconds duration_max) noexcept; +/** + * Generate a uniform random duration in the range [0..max). + * Precondition: max.count() > 0 + */ +template +D GetRandomDuration(typename std::common_type::type max) noexcept { + // Having the compiler infer the template argument from the function + // argument is dangerous, because the desired return value generally has a + // different type than the function argument. So std::common_type is used to + // force the call site to specify the type of the return value. + + assert(max.count() > 0); + return D{GetRand(max.count())}; +}; +constexpr auto GetRandMicros = GetRandomDuration; +constexpr auto GetRandMillis = GetRandomDuration; int GetRandInt(int nMax) noexcept; uint256 GetRandHash() noexcept; diff --git a/src/random.cpp b/src/random.cpp --- a/src/random.cpp +++ b/src/random.cpp @@ -642,16 +642,6 @@ return FastRandomContext(g_mock_deterministic_tests).randrange(nMax); } -std::chrono::microseconds -GetRandMicros(std::chrono::microseconds duration_max) noexcept { - return std::chrono::microseconds{GetRand(duration_max.count())}; -} - -std::chrono::milliseconds -GetRandMillis(std::chrono::milliseconds duration_max) noexcept { - return std::chrono::milliseconds{GetRand(duration_max.count())}; -} - int GetRandInt(int nMax) noexcept { return GetRand(nMax); } diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -28,6 +28,10 @@ uint64_t{10393729187455219830U}); BOOST_CHECK_EQUAL(GetRandInt(std::numeric_limits::max()), int{769702006}); + BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), + 2917185654); + BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), + 2144374); } BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); @@ -49,6 +53,10 @@ uint64_t{10393729187455219830U}); BOOST_CHECK(GetRandInt(std::numeric_limits::max()) != int{769702006}); + BOOST_CHECK(GetRandMicros(std::chrono::hours{1}) != + std::chrono::microseconds{2917185654}); + BOOST_CHECK(GetRandMillis(std::chrono::hours{1}) != + std::chrono::milliseconds{2144374}); } { FastRandomContext ctx3, ctx4;