• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "base/rand_util.h"
11 
12 #include <stddef.h>
13 #include <stdint.h>
14 
15 #include <algorithm>
16 #include <cmath>
17 #include <limits>
18 #include <memory>
19 #include <vector>
20 
21 #include "base/containers/span.h"
22 #include "base/logging.h"
23 #include "base/time/time.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 
26 namespace base {
27 
28 namespace {
29 
30 const int kIntMin = std::numeric_limits<int>::min();
31 const int kIntMax = std::numeric_limits<int>::max();
32 
33 }  // namespace
34 
TEST(RandUtilTest,RandInt)35 TEST(RandUtilTest, RandInt) {
36   EXPECT_EQ(base::RandInt(0, 0), 0);
37   EXPECT_EQ(base::RandInt(kIntMin, kIntMin), kIntMin);
38   EXPECT_EQ(base::RandInt(kIntMax, kIntMax), kIntMax);
39 
40   // Check that the DCHECKS in RandInt() don't fire due to internal overflow.
41   // There was a 50% chance of that happening, so calling it 40 times means
42   // the chances of this passing by accident are tiny (9e-13).
43   for (int i = 0; i < 40; ++i)
44     base::RandInt(kIntMin, kIntMax);
45 }
46 
TEST(RandUtilTest,RandDouble)47 TEST(RandUtilTest, RandDouble) {
48   // Force 64-bit precision, making sure we're not in a 80-bit FPU register.
49   volatile double number = base::RandDouble();
50   EXPECT_GT(1.0, number);
51   EXPECT_LE(0.0, number);
52 }
53 
TEST(RandUtilTest,RandFloat)54 TEST(RandUtilTest, RandFloat) {
55   // Force 32-bit precision, making sure we're not in an 80-bit FPU register.
56   volatile float number = base::RandFloat();
57   EXPECT_GT(1.f, number);
58   EXPECT_LE(0.f, number);
59 }
60 
TEST(RandUtilTest,RandTimeDelta)61 TEST(RandUtilTest, RandTimeDelta) {
62   {
63     const auto delta =
64         base::RandTimeDelta(-base::Seconds(2), -base::Seconds(1));
65     EXPECT_GE(delta, -base::Seconds(2));
66     EXPECT_LT(delta, -base::Seconds(1));
67   }
68 
69   {
70     const auto delta = base::RandTimeDelta(-base::Seconds(2), base::Seconds(2));
71     EXPECT_GE(delta, -base::Seconds(2));
72     EXPECT_LT(delta, base::Seconds(2));
73   }
74 
75   {
76     const auto delta = base::RandTimeDelta(base::Seconds(1), base::Seconds(2));
77     EXPECT_GE(delta, base::Seconds(1));
78     EXPECT_LT(delta, base::Seconds(2));
79   }
80 }
81 
TEST(RandUtilTest,RandTimeDeltaUpTo)82 TEST(RandUtilTest, RandTimeDeltaUpTo) {
83   const auto delta = base::RandTimeDeltaUpTo(base::Seconds(2));
84   EXPECT_FALSE(delta.is_negative());
85   EXPECT_LT(delta, base::Seconds(2));
86 }
87 
TEST(RandUtilTest,BitsToOpenEndedUnitInterval)88 TEST(RandUtilTest, BitsToOpenEndedUnitInterval) {
89   // Force 64-bit precision, making sure we're not in an 80-bit FPU register.
90   volatile double all_zeros = BitsToOpenEndedUnitInterval(0x0);
91   EXPECT_EQ(0.0, all_zeros);
92 
93   // Force 64-bit precision, making sure we're not in an 80-bit FPU register.
94   volatile double smallest_nonzero = BitsToOpenEndedUnitInterval(0x1);
95   EXPECT_LT(0.0, smallest_nonzero);
96 
97   for (uint64_t i = 0x2; i < 0x10; ++i) {
98     // Force 64-bit precision, making sure we're not in an 80-bit FPU register.
99     volatile double number = BitsToOpenEndedUnitInterval(i);
100     EXPECT_EQ(i * smallest_nonzero, number);
101   }
102 
103   // Force 64-bit precision, making sure we're not in an 80-bit FPU register.
104   volatile double all_ones = BitsToOpenEndedUnitInterval(UINT64_MAX);
105   EXPECT_GT(1.0, all_ones);
106 }
107 
TEST(RandUtilTest,BitsToOpenEndedUnitIntervalF)108 TEST(RandUtilTest, BitsToOpenEndedUnitIntervalF) {
109   // Force 32-bit precision, making sure we're not in an 80-bit FPU register.
110   volatile float all_zeros = BitsToOpenEndedUnitIntervalF(0x0);
111   EXPECT_EQ(0.f, all_zeros);
112 
113   // Force 32-bit precision, making sure we're not in an 80-bit FPU register.
114   volatile float smallest_nonzero = BitsToOpenEndedUnitIntervalF(0x1);
115   EXPECT_LT(0.f, smallest_nonzero);
116 
117   for (uint64_t i = 0x2; i < 0x10; ++i) {
118     // Force 32-bit precision, making sure we're not in an 80-bit FPU register.
119     volatile float number = BitsToOpenEndedUnitIntervalF(i);
120     EXPECT_EQ(i * smallest_nonzero, number);
121   }
122 
123   // Force 32-bit precision, making sure we're not in an 80-bit FPU register.
124   volatile float all_ones = BitsToOpenEndedUnitIntervalF(UINT64_MAX);
125   EXPECT_GT(1.f, all_ones);
126 }
127 
TEST(RandUtilTest,RandBytes)128 TEST(RandUtilTest, RandBytes) {
129   const size_t buffer_size = 50;
130   uint8_t buffer[buffer_size];
131   memset(buffer, 0, buffer_size);
132   base::RandBytes(buffer);
133   std::sort(buffer, buffer + buffer_size);
134   // Probability of occurrence of less than 25 unique bytes in 50 random bytes
135   // is below 10^-25.
136   EXPECT_GT(std::unique(buffer, buffer + buffer_size) - buffer, 25);
137 }
138 
139 // Verify that calling base::RandBytes with an empty buffer doesn't fail.
TEST(RandUtilTest,RandBytes0)140 TEST(RandUtilTest, RandBytes0) {
141   base::RandBytes(span<uint8_t>());
142 }
143 
TEST(RandUtilTest,RandBytesAsVector)144 TEST(RandUtilTest, RandBytesAsVector) {
145   std::vector<uint8_t> random_vec = base::RandBytesAsVector(0);
146   EXPECT_TRUE(random_vec.empty());
147   random_vec = base::RandBytesAsVector(1);
148   EXPECT_EQ(1U, random_vec.size());
149   random_vec = base::RandBytesAsVector(145);
150   EXPECT_EQ(145U, random_vec.size());
151   char accumulator = 0;
152   for (auto i : random_vec) {
153     accumulator |= i;
154   }
155   // In theory this test can fail, but it won't before the universe dies of
156   // heat death.
157   EXPECT_NE(0, accumulator);
158 }
159 
TEST(RandUtilTest,RandBytesAsString)160 TEST(RandUtilTest, RandBytesAsString) {
161   std::string random_string = base::RandBytesAsString(1);
162   EXPECT_EQ(1U, random_string.size());
163   random_string = base::RandBytesAsString(145);
164   EXPECT_EQ(145U, random_string.size());
165   char accumulator = 0;
166   for (auto i : random_string)
167     accumulator |= i;
168   // In theory this test can fail, but it won't before the universe dies of
169   // heat death.
170   EXPECT_NE(0, accumulator);
171 }
172 
173 // Make sure that it is still appropriate to use RandGenerator in conjunction
174 // with std::random_shuffle().
TEST(RandUtilTest,RandGeneratorForRandomShuffle)175 TEST(RandUtilTest, RandGeneratorForRandomShuffle) {
176   EXPECT_EQ(base::RandGenerator(1), 0U);
177   EXPECT_LE(std::numeric_limits<ptrdiff_t>::max(),
178             std::numeric_limits<int64_t>::max());
179 }
180 
TEST(RandUtilTest,RandGeneratorIsUniform)181 TEST(RandUtilTest, RandGeneratorIsUniform) {
182   // Verify that RandGenerator has a uniform distribution. This is a
183   // regression test that consistently failed when RandGenerator was
184   // implemented this way:
185   //
186   //   return base::RandUint64() % max;
187   //
188   // A degenerate case for such an implementation is e.g. a top of
189   // range that is 2/3rds of the way to MAX_UINT64, in which case the
190   // bottom half of the range would be twice as likely to occur as the
191   // top half. A bit of calculus care of jar@ shows that the largest
192   // measurable delta is when the top of the range is 3/4ths of the
193   // way, so that's what we use in the test.
194   constexpr uint64_t kTopOfRange =
195       (std::numeric_limits<uint64_t>::max() / 4ULL) * 3ULL;
196   constexpr double kExpectedAverage = static_cast<double>(kTopOfRange / 2);
197   constexpr double kAllowedVariance = kExpectedAverage / 50.0;  // +/- 2%
198   constexpr int kMinAttempts = 1000;
199   constexpr int kMaxAttempts = 1000000;
200 
201   double cumulative_average = 0.0;
202   int count = 0;
203   while (count < kMaxAttempts) {
204     uint64_t value = base::RandGenerator(kTopOfRange);
205     cumulative_average = (count * cumulative_average + value) / (count + 1);
206 
207     // Don't quit too quickly for things to start converging, or we may have
208     // a false positive.
209     if (count > kMinAttempts &&
210         kExpectedAverage - kAllowedVariance < cumulative_average &&
211         cumulative_average < kExpectedAverage + kAllowedVariance) {
212       break;
213     }
214 
215     ++count;
216   }
217 
218   ASSERT_LT(count, kMaxAttempts) << "Expected average was " << kExpectedAverage
219                                  << ", average ended at " << cumulative_average;
220 }
221 
TEST(RandUtilTest,RandUint64ProducesBothValuesOfAllBits)222 TEST(RandUtilTest, RandUint64ProducesBothValuesOfAllBits) {
223   // This tests to see that our underlying random generator is good
224   // enough, for some value of good enough.
225   uint64_t kAllZeros = 0ULL;
226   uint64_t kAllOnes = ~kAllZeros;
227   uint64_t found_ones = kAllZeros;
228   uint64_t found_zeros = kAllOnes;
229 
230   for (size_t i = 0; i < 1000; ++i) {
231     uint64_t value = base::RandUint64();
232     found_ones |= value;
233     found_zeros &= value;
234 
235     if (found_zeros == kAllZeros && found_ones == kAllOnes)
236       return;
237   }
238 
239   FAIL() << "Didn't achieve all bit values in maximum number of tries.";
240 }
241 
TEST(RandUtilTest,RandBytesLonger)242 TEST(RandUtilTest, RandBytesLonger) {
243   // Fuchsia can only retrieve 256 bytes of entropy at a time, so make sure we
244   // handle longer requests than that.
245   std::string random_string0 = base::RandBytesAsString(255);
246   EXPECT_EQ(255u, random_string0.size());
247   std::string random_string1 = base::RandBytesAsString(1023);
248   EXPECT_EQ(1023u, random_string1.size());
249   std::string random_string2 = base::RandBytesAsString(4097);
250   EXPECT_EQ(4097u, random_string2.size());
251 }
252 
253 // Benchmark test for RandBytes().  Disabled since it's intentionally slow and
254 // does not test anything that isn't already tested by the existing RandBytes()
255 // tests.
TEST(RandUtilTest,DISABLED_RandBytesPerf)256 TEST(RandUtilTest, DISABLED_RandBytesPerf) {
257   // Benchmark the performance of |kTestIterations| of RandBytes() using a
258   // buffer size of |kTestBufferSize|.
259   const int kTestIterations = 10;
260   const size_t kTestBufferSize = 1 * 1024 * 1024;
261 
262   std::array<uint8_t, kTestBufferSize> buffer;
263   const base::TimeTicks now = base::TimeTicks::Now();
264   for (int i = 0; i < kTestIterations; ++i) {
265     base::RandBytes(buffer);
266   }
267   const base::TimeTicks end = base::TimeTicks::Now();
268 
269   LOG(INFO) << "RandBytes(" << kTestBufferSize
270             << ") took: " << (end - now).InMicroseconds() << "µs";
271 }
272 
TEST(RandUtilTest,InsecureRandomGeneratorProducesBothValuesOfAllBits)273 TEST(RandUtilTest, InsecureRandomGeneratorProducesBothValuesOfAllBits) {
274   // This tests to see that our underlying random generator is good
275   // enough, for some value of good enough.
276   uint64_t kAllZeros = 0ULL;
277   uint64_t kAllOnes = ~kAllZeros;
278   uint64_t found_ones = kAllZeros;
279   uint64_t found_zeros = kAllOnes;
280 
281   InsecureRandomGenerator generator;
282 
283   for (size_t i = 0; i < 1000; ++i) {
284     uint64_t value = generator.RandUint64();
285     found_ones |= value;
286     found_zeros &= value;
287 
288     if (found_zeros == kAllZeros && found_ones == kAllOnes)
289       return;
290   }
291 
292   FAIL() << "Didn't achieve all bit values in maximum number of tries.";
293 }
294 
295 namespace {
296 
297 constexpr double kXp1Percent = -2.33;
298 constexpr double kXp99Percent = 2.33;
299 
ChiSquaredCriticalValue(double nu,double x_p)300 double ChiSquaredCriticalValue(double nu, double x_p) {
301   // From "The Art Of Computer Programming" (TAOCP), Volume 2, Section 3.3.1,
302   // Table 1. This is the asymptotic value for nu > 30, up to O(1 / sqrt(nu)).
303   return nu + sqrt(2. * nu) * x_p + 2. / 3. * (x_p * x_p) - 2. / 3.;
304 }
305 
ExtractBits(uint64_t value,int from_bit,int num_bits)306 int ExtractBits(uint64_t value, int from_bit, int num_bits) {
307   return (value >> from_bit) & ((1 << num_bits) - 1);
308 }
309 
310 // Performs a Chi-Squared test on a subset of |num_bits| extracted starting from
311 // |from_bit| in the generated value.
312 //
313 // See TAOCP, Volume 2, Section 3.3.1, and
314 // https://en.wikipedia.org/wiki/Pearson%27s_chi-squared_test for details.
315 //
316 // This is only one of the many, many random number generator test we could do,
317 // but they are cumbersome, as they are typically very slow, and expected to
318 // fail from time to time, due to their probabilistic nature.
319 //
320 // The generator we use has however been vetted with the BigCrush test suite
321 // from Marsaglia, so this should suffice as a smoke test that our
322 // implementation is wrong.
ChiSquaredTest(InsecureRandomGenerator & gen,size_t n,int from_bit,int num_bits)323 bool ChiSquaredTest(InsecureRandomGenerator& gen,
324                     size_t n,
325                     int from_bit,
326                     int num_bits) {
327   const int range = 1 << num_bits;
328   CHECK_EQ(static_cast<int>(n % range), 0) << "Makes computations simpler";
329   std::vector<size_t> samples(range, 0);
330 
331   // Count how many samples pf each value are found. All buckets should be
332   // almost equal if the generator is suitably uniformly random.
333   for (size_t i = 0; i < n; i++) {
334     int sample = ExtractBits(gen.RandUint64(), from_bit, num_bits);
335     samples[sample] += 1;
336   }
337 
338   // Compute the Chi-Squared statistic, which is:
339   // \Sum_{k=0}^{range-1} \frac{(count - expected)^2}{expected}
340   double chi_squared = 0.;
341   double expected_count = n / range;
342   for (size_t sample_count : samples) {
343     double deviation = sample_count - expected_count;
344     chi_squared += (deviation * deviation) / expected_count;
345   }
346 
347   // The generator should produce numbers that are not too far of (chi_squared
348   // lower than a given quantile), but not too close to the ideal distribution
349   // either (chi_squared is too low).
350   //
351   // See The Art Of Computer Programming, Volume 2, Section 3.3.1 for details.
352   return chi_squared > ChiSquaredCriticalValue(range - 1, kXp1Percent) &&
353          chi_squared < ChiSquaredCriticalValue(range - 1, kXp99Percent);
354 }
355 
356 }  // namespace
357 
TEST(RandUtilTest,InsecureRandomGeneratorChiSquared)358 TEST(RandUtilTest, InsecureRandomGeneratorChiSquared) {
359   constexpr int kIterations = 50;
360 
361   // Specifically test the low bits, which are usually weaker in random number
362   // generators. We don't use them for the 32 bit number generation, but let's
363   // make sure they are still suitable.
364   for (int start_bit : {1, 2, 3, 8, 12, 20, 32, 48, 54}) {
365     int pass_count = 0;
366     for (int i = 0; i < kIterations; i++) {
367       size_t samples = 1 << 16;
368       InsecureRandomGenerator gen;
369       // Fix the seed to make the test non-flaky.
370       gen.ReseedForTesting(kIterations + 1);
371       bool pass = ChiSquaredTest(gen, samples, start_bit, 8);
372       pass_count += pass;
373     }
374 
375     // We exclude 1% on each side, so we expect 98% of tests to pass, meaning 98
376     // * kIterations / 100. However this is asymptotic, so add a bit of leeway.
377     int expected_pass_count = (kIterations * 98) / 100;
378     EXPECT_GE(pass_count, expected_pass_count - ((kIterations * 2) / 100))
379         << "For start_bit = " << start_bit;
380   }
381 }
382 
TEST(RandUtilTest,InsecureRandomGeneratorRandDouble)383 TEST(RandUtilTest, InsecureRandomGeneratorRandDouble) {
384   InsecureRandomGenerator gen;
385 
386   for (int i = 0; i < 1000; i++) {
387     volatile double x = gen.RandDouble();
388     EXPECT_GE(x, 0.);
389     EXPECT_LT(x, 1.);
390   }
391 }
392 
TEST(RandUtilTest,MetricsSubSampler)393 TEST(RandUtilTest, MetricsSubSampler) {
394   MetricsSubSampler sub_sampler;
395   int true_count = 0;
396   int false_count = 0;
397   for (int i = 0; i < 1000; ++i) {
398     if (sub_sampler.ShouldSample(0.5)) {
399       ++true_count;
400     } else {
401       ++false_count;
402     }
403   }
404 
405   // Validate that during normal operation MetricsSubSampler::ShouldSample()
406   // does not always give the same result. It's technically possible to fail
407   // this test during normal operation but if the sampling is realistic it
408   // should happen about once every 2^999 times (the likelihood of the [1,999]
409   // results being the same as [0], which can be either). This should not make
410   // this test flaky in the eyes of automated testing.
411   EXPECT_GT(true_count, 0);
412   EXPECT_GT(false_count, 0);
413 }
414 
TEST(RandUtilTest,MetricsSubSamplerTestingSupport)415 TEST(RandUtilTest, MetricsSubSamplerTestingSupport) {
416   MetricsSubSampler sub_sampler;
417 
418   // ScopedAlwaysSampleForTesting makes ShouldSample() return true with
419   // any probability.
420   {
421     MetricsSubSampler::ScopedAlwaysSampleForTesting always_sample;
422     for (int i = 0; i < 100; ++i) {
423       EXPECT_TRUE(sub_sampler.ShouldSample(0));
424       EXPECT_TRUE(sub_sampler.ShouldSample(0.5));
425       EXPECT_TRUE(sub_sampler.ShouldSample(1));
426     }
427   }
428 
429   // ScopedNeverSampleForTesting makes ShouldSample() return true with
430   // any probability.
431   {
432     MetricsSubSampler::ScopedNeverSampleForTesting always_sample;
433     for (int i = 0; i < 100; ++i) {
434       EXPECT_FALSE(sub_sampler.ShouldSample(0));
435       EXPECT_FALSE(sub_sampler.ShouldSample(0.5));
436       EXPECT_FALSE(sub_sampler.ShouldSample(1));
437     }
438   }
439 }
440 
441 }  // namespace base
442