1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "base/rand_util.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
8*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
9*635a8641SAndroid Build Coastguard Worker
10*635a8641SAndroid Build Coastguard Worker #include <algorithm>
11*635a8641SAndroid Build Coastguard Worker #include <limits>
12*635a8641SAndroid Build Coastguard Worker #include <memory>
13*635a8641SAndroid Build Coastguard Worker
14*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/time/time.h"
16*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
17*635a8641SAndroid Build Coastguard Worker
18*635a8641SAndroid Build Coastguard Worker namespace {
19*635a8641SAndroid Build Coastguard Worker
20*635a8641SAndroid Build Coastguard Worker const int kIntMin = std::numeric_limits<int>::min();
21*635a8641SAndroid Build Coastguard Worker const int kIntMax = std::numeric_limits<int>::max();
22*635a8641SAndroid Build Coastguard Worker
23*635a8641SAndroid Build Coastguard Worker } // namespace
24*635a8641SAndroid Build Coastguard Worker
TEST(RandUtilTest,RandInt)25*635a8641SAndroid Build Coastguard Worker TEST(RandUtilTest, RandInt) {
26*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::RandInt(0, 0), 0);
27*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::RandInt(kIntMin, kIntMin), kIntMin);
28*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::RandInt(kIntMax, kIntMax), kIntMax);
29*635a8641SAndroid Build Coastguard Worker
30*635a8641SAndroid Build Coastguard Worker // Check that the DCHECKS in RandInt() don't fire due to internal overflow.
31*635a8641SAndroid Build Coastguard Worker // There was a 50% chance of that happening, so calling it 40 times means
32*635a8641SAndroid Build Coastguard Worker // the chances of this passing by accident are tiny (9e-13).
33*635a8641SAndroid Build Coastguard Worker for (int i = 0; i < 40; ++i)
34*635a8641SAndroid Build Coastguard Worker base::RandInt(kIntMin, kIntMax);
35*635a8641SAndroid Build Coastguard Worker }
36*635a8641SAndroid Build Coastguard Worker
TEST(RandUtilTest,RandDouble)37*635a8641SAndroid Build Coastguard Worker TEST(RandUtilTest, RandDouble) {
38*635a8641SAndroid Build Coastguard Worker // Force 64-bit precision, making sure we're not in a 80-bit FPU register.
39*635a8641SAndroid Build Coastguard Worker volatile double number = base::RandDouble();
40*635a8641SAndroid Build Coastguard Worker EXPECT_GT(1.0, number);
41*635a8641SAndroid Build Coastguard Worker EXPECT_LE(0.0, number);
42*635a8641SAndroid Build Coastguard Worker }
43*635a8641SAndroid Build Coastguard Worker
TEST(RandUtilTest,RandBytes)44*635a8641SAndroid Build Coastguard Worker TEST(RandUtilTest, RandBytes) {
45*635a8641SAndroid Build Coastguard Worker const size_t buffer_size = 50;
46*635a8641SAndroid Build Coastguard Worker char buffer[buffer_size];
47*635a8641SAndroid Build Coastguard Worker memset(buffer, 0, buffer_size);
48*635a8641SAndroid Build Coastguard Worker base::RandBytes(buffer, buffer_size);
49*635a8641SAndroid Build Coastguard Worker std::sort(buffer, buffer + buffer_size);
50*635a8641SAndroid Build Coastguard Worker // Probability of occurrence of less than 25 unique bytes in 50 random bytes
51*635a8641SAndroid Build Coastguard Worker // is below 10^-25.
52*635a8641SAndroid Build Coastguard Worker EXPECT_GT(std::unique(buffer, buffer + buffer_size) - buffer, 25);
53*635a8641SAndroid Build Coastguard Worker }
54*635a8641SAndroid Build Coastguard Worker
55*635a8641SAndroid Build Coastguard Worker // Verify that calling base::RandBytes with an empty buffer doesn't fail.
TEST(RandUtilTest,RandBytes0)56*635a8641SAndroid Build Coastguard Worker TEST(RandUtilTest, RandBytes0) {
57*635a8641SAndroid Build Coastguard Worker base::RandBytes(nullptr, 0);
58*635a8641SAndroid Build Coastguard Worker }
59*635a8641SAndroid Build Coastguard Worker
TEST(RandUtilTest,RandBytesAsString)60*635a8641SAndroid Build Coastguard Worker TEST(RandUtilTest, RandBytesAsString) {
61*635a8641SAndroid Build Coastguard Worker std::string random_string = base::RandBytesAsString(1);
62*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1U, random_string.size());
63*635a8641SAndroid Build Coastguard Worker random_string = base::RandBytesAsString(145);
64*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(145U, random_string.size());
65*635a8641SAndroid Build Coastguard Worker char accumulator = 0;
66*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < random_string.size(); ++i)
67*635a8641SAndroid Build Coastguard Worker accumulator |= random_string[i];
68*635a8641SAndroid Build Coastguard Worker // In theory this test can fail, but it won't before the universe dies of
69*635a8641SAndroid Build Coastguard Worker // heat death.
70*635a8641SAndroid Build Coastguard Worker EXPECT_NE(0, accumulator);
71*635a8641SAndroid Build Coastguard Worker }
72*635a8641SAndroid Build Coastguard Worker
73*635a8641SAndroid Build Coastguard Worker // Make sure that it is still appropriate to use RandGenerator in conjunction
74*635a8641SAndroid Build Coastguard Worker // with std::random_shuffle().
TEST(RandUtilTest,RandGeneratorForRandomShuffle)75*635a8641SAndroid Build Coastguard Worker TEST(RandUtilTest, RandGeneratorForRandomShuffle) {
76*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(base::RandGenerator(1), 0U);
77*635a8641SAndroid Build Coastguard Worker EXPECT_LE(std::numeric_limits<ptrdiff_t>::max(),
78*635a8641SAndroid Build Coastguard Worker std::numeric_limits<int64_t>::max());
79*635a8641SAndroid Build Coastguard Worker }
80*635a8641SAndroid Build Coastguard Worker
TEST(RandUtilTest,RandGeneratorIsUniform)81*635a8641SAndroid Build Coastguard Worker TEST(RandUtilTest, RandGeneratorIsUniform) {
82*635a8641SAndroid Build Coastguard Worker // Verify that RandGenerator has a uniform distribution. This is a
83*635a8641SAndroid Build Coastguard Worker // regression test that consistently failed when RandGenerator was
84*635a8641SAndroid Build Coastguard Worker // implemented this way:
85*635a8641SAndroid Build Coastguard Worker //
86*635a8641SAndroid Build Coastguard Worker // return base::RandUint64() % max;
87*635a8641SAndroid Build Coastguard Worker //
88*635a8641SAndroid Build Coastguard Worker // A degenerate case for such an implementation is e.g. a top of
89*635a8641SAndroid Build Coastguard Worker // range that is 2/3rds of the way to MAX_UINT64, in which case the
90*635a8641SAndroid Build Coastguard Worker // bottom half of the range would be twice as likely to occur as the
91*635a8641SAndroid Build Coastguard Worker // top half. A bit of calculus care of jar@ shows that the largest
92*635a8641SAndroid Build Coastguard Worker // measurable delta is when the top of the range is 3/4ths of the
93*635a8641SAndroid Build Coastguard Worker // way, so that's what we use in the test.
94*635a8641SAndroid Build Coastguard Worker const uint64_t kTopOfRange =
95*635a8641SAndroid Build Coastguard Worker (std::numeric_limits<uint64_t>::max() / 4ULL) * 3ULL;
96*635a8641SAndroid Build Coastguard Worker const uint64_t kExpectedAverage = kTopOfRange / 2ULL;
97*635a8641SAndroid Build Coastguard Worker const uint64_t kAllowedVariance = kExpectedAverage / 50ULL; // +/- 2%
98*635a8641SAndroid Build Coastguard Worker const int kMinAttempts = 1000;
99*635a8641SAndroid Build Coastguard Worker const int kMaxAttempts = 1000000;
100*635a8641SAndroid Build Coastguard Worker
101*635a8641SAndroid Build Coastguard Worker double cumulative_average = 0.0;
102*635a8641SAndroid Build Coastguard Worker int count = 0;
103*635a8641SAndroid Build Coastguard Worker while (count < kMaxAttempts) {
104*635a8641SAndroid Build Coastguard Worker uint64_t value = base::RandGenerator(kTopOfRange);
105*635a8641SAndroid Build Coastguard Worker cumulative_average = (count * cumulative_average + value) / (count + 1);
106*635a8641SAndroid Build Coastguard Worker
107*635a8641SAndroid Build Coastguard Worker // Don't quit too quickly for things to start converging, or we may have
108*635a8641SAndroid Build Coastguard Worker // a false positive.
109*635a8641SAndroid Build Coastguard Worker if (count > kMinAttempts &&
110*635a8641SAndroid Build Coastguard Worker kExpectedAverage - kAllowedVariance < cumulative_average &&
111*635a8641SAndroid Build Coastguard Worker cumulative_average < kExpectedAverage + kAllowedVariance) {
112*635a8641SAndroid Build Coastguard Worker break;
113*635a8641SAndroid Build Coastguard Worker }
114*635a8641SAndroid Build Coastguard Worker
115*635a8641SAndroid Build Coastguard Worker ++count;
116*635a8641SAndroid Build Coastguard Worker }
117*635a8641SAndroid Build Coastguard Worker
118*635a8641SAndroid Build Coastguard Worker ASSERT_LT(count, kMaxAttempts) << "Expected average was " <<
119*635a8641SAndroid Build Coastguard Worker kExpectedAverage << ", average ended at " << cumulative_average;
120*635a8641SAndroid Build Coastguard Worker }
121*635a8641SAndroid Build Coastguard Worker
TEST(RandUtilTest,RandUint64ProducesBothValuesOfAllBits)122*635a8641SAndroid Build Coastguard Worker TEST(RandUtilTest, RandUint64ProducesBothValuesOfAllBits) {
123*635a8641SAndroid Build Coastguard Worker // This tests to see that our underlying random generator is good
124*635a8641SAndroid Build Coastguard Worker // enough, for some value of good enough.
125*635a8641SAndroid Build Coastguard Worker uint64_t kAllZeros = 0ULL;
126*635a8641SAndroid Build Coastguard Worker uint64_t kAllOnes = ~kAllZeros;
127*635a8641SAndroid Build Coastguard Worker uint64_t found_ones = kAllZeros;
128*635a8641SAndroid Build Coastguard Worker uint64_t found_zeros = kAllOnes;
129*635a8641SAndroid Build Coastguard Worker
130*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < 1000; ++i) {
131*635a8641SAndroid Build Coastguard Worker uint64_t value = base::RandUint64();
132*635a8641SAndroid Build Coastguard Worker found_ones |= value;
133*635a8641SAndroid Build Coastguard Worker found_zeros &= value;
134*635a8641SAndroid Build Coastguard Worker
135*635a8641SAndroid Build Coastguard Worker if (found_zeros == kAllZeros && found_ones == kAllOnes)
136*635a8641SAndroid Build Coastguard Worker return;
137*635a8641SAndroid Build Coastguard Worker }
138*635a8641SAndroid Build Coastguard Worker
139*635a8641SAndroid Build Coastguard Worker FAIL() << "Didn't achieve all bit values in maximum number of tries.";
140*635a8641SAndroid Build Coastguard Worker }
141*635a8641SAndroid Build Coastguard Worker
TEST(RandUtilTest,RandBytesLonger)142*635a8641SAndroid Build Coastguard Worker TEST(RandUtilTest, RandBytesLonger) {
143*635a8641SAndroid Build Coastguard Worker // Fuchsia can only retrieve 256 bytes of entropy at a time, so make sure we
144*635a8641SAndroid Build Coastguard Worker // handle longer requests than that.
145*635a8641SAndroid Build Coastguard Worker std::string random_string0 = base::RandBytesAsString(255);
146*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(255u, random_string0.size());
147*635a8641SAndroid Build Coastguard Worker std::string random_string1 = base::RandBytesAsString(1023);
148*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(1023u, random_string1.size());
149*635a8641SAndroid Build Coastguard Worker std::string random_string2 = base::RandBytesAsString(4097);
150*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(4097u, random_string2.size());
151*635a8641SAndroid Build Coastguard Worker }
152*635a8641SAndroid Build Coastguard Worker
153*635a8641SAndroid Build Coastguard Worker // Benchmark test for RandBytes(). Disabled since it's intentionally slow and
154*635a8641SAndroid Build Coastguard Worker // does not test anything that isn't already tested by the existing RandBytes()
155*635a8641SAndroid Build Coastguard Worker // tests.
TEST(RandUtilTest,DISABLED_RandBytesPerf)156*635a8641SAndroid Build Coastguard Worker TEST(RandUtilTest, DISABLED_RandBytesPerf) {
157*635a8641SAndroid Build Coastguard Worker // Benchmark the performance of |kTestIterations| of RandBytes() using a
158*635a8641SAndroid Build Coastguard Worker // buffer size of |kTestBufferSize|.
159*635a8641SAndroid Build Coastguard Worker const int kTestIterations = 10;
160*635a8641SAndroid Build Coastguard Worker const size_t kTestBufferSize = 1 * 1024 * 1024;
161*635a8641SAndroid Build Coastguard Worker
162*635a8641SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> buffer(new uint8_t[kTestBufferSize]);
163*635a8641SAndroid Build Coastguard Worker const base::TimeTicks now = base::TimeTicks::Now();
164*635a8641SAndroid Build Coastguard Worker for (int i = 0; i < kTestIterations; ++i)
165*635a8641SAndroid Build Coastguard Worker base::RandBytes(buffer.get(), kTestBufferSize);
166*635a8641SAndroid Build Coastguard Worker const base::TimeTicks end = base::TimeTicks::Now();
167*635a8641SAndroid Build Coastguard Worker
168*635a8641SAndroid Build Coastguard Worker LOG(INFO) << "RandBytes(" << kTestBufferSize << ") took: "
169*635a8641SAndroid Build Coastguard Worker << (end - now).InMicroseconds() << "µs";
170*635a8641SAndroid Build Coastguard Worker }
171