summaryrefslogtreecommitdiff
path: root/src/mongo/platform/random_test.cpp
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2019-10-02 04:42:39 +0000
committerevergreen <evergreen@mongodb.com>2019-10-02 04:42:39 +0000
commit96da177c6ae7b7ed0f29983ad033d8a59524b0b2 (patch)
tree87a713b2be96453134555b1856e5f7dea07a1b0f /src/mongo/platform/random_test.cpp
parent059656a32ed8ed7e780c4b12bb3c4e101c1f90f4 (diff)
downloadmongo-96da177c6ae7b7ed0f29983ad033d8a59524b0b2.tar.gz
SERVER-43641 upgrade random.h
Respecify PseudoRandom and SecureRandom as template instances of a `mongo::RandomBase<Urbg>` (Urbg is a UniformRandomBitGenerator). They will only vary in which algorithm they use for their source bits, and should otherwise support the same exact operations (e.g. `nextCanonicalDouble`). Fix range and stats errors in the implementations of those RandomBase methods, and specify them in terms of the vetted `<random>` facilities. Test uniformity of nextInt32(max), which uses an inappropriate ( x % max) operation. Verify that refactor fixes this issue. Just keep a shared urandom file descriptor open. SecureRandom add fill, remove create, fix callers Obsoletes SERVER-43643 Re: SecureRandom 8kiB buffering
Diffstat (limited to 'src/mongo/platform/random_test.cpp')
-rw-r--r--src/mongo/platform/random_test.cpp47
1 files changed, 41 insertions, 6 deletions
diff --git a/src/mongo/platform/random_test.cpp b/src/mongo/platform/random_test.cpp
index ee82a89490f..c3271f8b926 100644
--- a/src/mongo/platform/random_test.cpp
+++ b/src/mongo/platform/random_test.cpp
@@ -134,13 +134,13 @@ TEST(RandomTest, NextCanonicalDistinctValues) {
}
/**
- * Test that nextCanonicalDouble() always returns values between 0 and 1.
+ * Test that nextCanonicalDouble() is at least very likely to return values in [0,1).
*/
TEST(RandomTest, NextCanonicalWithinRange) {
PseudoRandom prng(10);
- for (int i = 0; i < 100; i++) {
+ for (size_t i = 0; i < 1'000'000; ++i) {
double next = prng.nextCanonicalDouble();
- ASSERT_LTE(0.0, next);
+ ASSERT_GTE(next, 0.0);
ASSERT_LT(next, 1.0);
}
}
@@ -211,12 +211,47 @@ TEST(RandomTest, NextInt64InRange) {
}
}
+/**
+ * Test uniformity of nextInt32(max)
+ */
+TEST(RandomTest, NextInt32Uniformity) {
+ PseudoRandom prng(10);
+ /* Break the range into sections. */
+ /* Check that all sections get roughly equal # of hits */
+ constexpr int32_t kMax = (int32_t{3} << 29) - 1;
+ constexpr size_t kBuckets = 64;
+ constexpr size_t kNIter = 1'000'000;
+ constexpr double mu = kNIter / kBuckets;
+ constexpr double muSqInv = 1. / (mu * mu);
+ std::vector<size_t> hist(kBuckets);
+ for (size_t i = 0; i < kNIter; ++i) {
+ auto next = prng.nextInt32(kMax);
+ ASSERT_GTE(next, 0);
+ ASSERT_LTE(next, kMax);
+ ++hist[double(next) * kBuckets / (kMax + 1)];
+ }
+ if (kDebugBuild) {
+ for (size_t i = 0; i < hist.size(); ++i) {
+ double dev = std::pow(std::pow((hist[i] - mu) / mu, 2), .5);
+ unittest::log() << format(FMT_STRING(" [{:4}] count:{:4}, dev:{:6f}, {}"),
+ i,
+ hist[i],
+ dev,
+ std::string(hist[i] / 256, '*'));
+ }
+ }
+ for (size_t i = 0; i < hist.size(); ++i) {
+ double dev = std::pow(std::pow(hist[i] - mu, 2) * muSqInv, .5);
+ ASSERT_LT(dev, 0.1) << format(FMT_STRING("hist[{}]={}, mu={}"), i, hist[i], mu);
+ }
+}
+
TEST(RandomTest, Secure1) {
- auto a = SecureRandom::create();
- auto b = SecureRandom::create();
+ auto a = SecureRandom();
+ auto b = SecureRandom();
for (int i = 0; i < 100; i++) {
- ASSERT_NOT_EQUALS(a->nextInt64(), b->nextInt64());
+ ASSERT_NOT_EQUALS(a.nextInt64(), b.nextInt64());
}
}
} // namespace mongo