LCOV - code coverage report
Current view: top level - test/cctest - test-random-number-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 71 77 92.2 %
Date: 2019-04-17 Functions: 36 37 97.3 %

          Line data    Source code
       1             : // Copyright 2013 the V8 project authors. All rights reserved.
       2             : // Redistribution and use in source and binary forms, with or without
       3             : // modification, are permitted provided that the following conditions are
       4             : // met:
       5             : //
       6             : //     * Redistributions of source code must retain the above copyright
       7             : //       notice, this list of conditions and the following disclaimer.
       8             : //     * Redistributions in binary form must reproduce the above
       9             : //       copyright notice, this list of conditions and the following
      10             : //       disclaimer in the documentation and/or other materials provided
      11             : //       with the distribution.
      12             : //     * Neither the name of Google Inc. nor the names of its
      13             : //       contributors may be used to endorse or promote products derived
      14             : //       from this software without specific prior written permission.
      15             : //
      16             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      17             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      18             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      19             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      20             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      22             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             : 
      28             : #include "src/flags.h"
      29             : #include "src/isolate.h"
      30             : #include "src/v8.h"
      31             : #include "test/cctest/cctest.h"
      32             : 
      33             : #include "src/base/utils/random-number-generator.h"
      34             : 
      35             : namespace v8 {
      36             : namespace internal {
      37             : 
      38             : static const int64_t kRandomSeeds[] = {-1, 1, 42, 100, 1234567890, 987654321};
      39             : 
      40             : 
      41       26644 : TEST(RandomSeedFlagIsUsed) {
      42          65 :   for (unsigned n = 0; n < arraysize(kRandomSeeds); ++n) {
      43          30 :     FLAG_random_seed = static_cast<int>(kRandomSeeds[n]);
      44             :     v8::Isolate::CreateParams create_params;
      45          30 :     create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
      46          30 :     v8::Isolate* i = v8::Isolate::New(create_params);
      47             :     v8::base::RandomNumberGenerator& rng =
      48          30 :         *reinterpret_cast<Isolate*>(i)->random_number_generator();
      49          30 :     CHECK_EQ(kRandomSeeds[n], rng.initial_seed());
      50          30 :     i->Dispose();
      51             :   }
      52           5 : }
      53             : 
      54             : 
      55             : // Chi squared for getting m 0s out of n bits.
      56           0 : double ChiSquared(int m, int n) {
      57       41120 :   double ys_minus_np1 = (m - n / 2.0);
      58       41120 :   double chi_squared_1 = ys_minus_np1 * ys_minus_np1 * 2.0 / n;
      59       41120 :   double ys_minus_np2 = ((n - m) - n / 2.0);
      60       41120 :   double chi_squared_2 = ys_minus_np2 * ys_minus_np2 * 2.0 / n;
      61       41120 :   return chi_squared_1 + chi_squared_2;
      62             : }
      63             : 
      64             : 
      65             : // Test for correlations between recent bits from the PRNG, or bits that are
      66             : // biased.
      67         160 : void RandomBitCorrelation(int random_bit) {
      68         160 :   FLAG_random_seed = 31415926;
      69             :   v8::Isolate::CreateParams create_params;
      70         160 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
      71         160 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
      72             :   Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
      73         160 :   v8::base::RandomNumberGenerator* rng = i_isolate->random_number_generator();
      74             : #ifdef DEBUG
      75             :   const int kHistory = 2;
      76             :   const int kRepeats = 1000;
      77             : #else
      78             :   const int kHistory = 8;
      79             :   const int kRepeats = 10000;
      80             : #endif
      81             :   uint32_t history[kHistory];
      82             :   // The predictor bit is either constant 0 or 1, or one of the bits from the
      83             :   // history.
      84       11040 :   for (int predictor_bit = -2; predictor_bit < 32; predictor_bit++) {
      85             :     // The predicted bit is one of the bits from the PRNG.
      86       87360 :     for (int ago = 0; ago < kHistory; ago++) {
      87             :       // We don't want to check whether each bit predicts itself.
      88       41280 :       if (ago == 0 && predictor_bit == random_bit) continue;
      89             : 
      90             :       // Enter the new random value into the history
      91      410080 :       for (int i = ago; i >= 0; i--) {
      92      184480 :         history[i] = bit_cast<uint32_t>(rng->NextInt());
      93             :       }
      94             : 
      95             :       // Find out how many of the bits are the same as the prediction bit.
      96             :       int m = 0;
      97   822441120 :       for (int i = 0; i < kRepeats; i++) {
      98   822400000 :         v8::HandleScope scope(isolate);
      99             :         uint32_t random = bit_cast<uint32_t>(rng->NextInt());
     100   411200000 :         for (int j = ago - 1; j >= 0; j--) history[j + 1] = history[j];
     101   411200000 :         history[0] = random;
     102             : 
     103             :         int predicted;
     104   411200000 :         if (predictor_bit >= 0) {
     105   408000000 :           predicted = (history[ago] >> predictor_bit) & 1;
     106             :         } else {
     107     3200000 :           predicted = predictor_bit == -2 ? 0 : 1;
     108             :         }
     109   411200000 :         int bit = (random >> random_bit) & 1;
     110   411200000 :         if (bit == predicted) m++;
     111             :       }
     112             : 
     113             :       // Chi squared analysis for k = 2 (2, states: same/not-same) and one
     114             :       // degree of freedom (k - 1).
     115             :       double chi_squared = ChiSquared(m, kRepeats);
     116       41120 :       if (chi_squared > 24) {
     117           0 :         int percent = static_cast<int>(m * 100.0 / kRepeats);
     118           0 :         if (predictor_bit < 0) {
     119           0 :           PrintF("Bit %d is %d %d%% of the time\n", random_bit,
     120           0 :                  predictor_bit == -2 ? 0 : 1, percent);
     121             :         } else {
     122             :           PrintF("Bit %d is the same as bit %d %d ago %d%% of the time\n",
     123           0 :                  random_bit, predictor_bit, ago, percent);
     124             :         }
     125             :       }
     126             : 
     127             :       // For 1 degree of freedom this corresponds to 1 in a million.  We are
     128             :       // running ~8000 tests, so that would be surprising.
     129       41120 :       CHECK_LE(chi_squared, 24);
     130             : 
     131             :       // If the predictor bit is a fixed 0 or 1 then it makes no sense to
     132             :       // repeat the test with a different age.
     133       41120 :       if (predictor_bit < 0) break;
     134             :     }
     135             :   }
     136         160 :   isolate->Dispose();
     137         160 : }
     138             : 
     139             : 
     140             : #define TEST_RANDOM_BIT(BIT) \
     141             :   TEST(RandomBitCorrelations##BIT) { RandomBitCorrelation(BIT); }
     142             : 
     143       26644 : TEST_RANDOM_BIT(0)
     144       26644 : TEST_RANDOM_BIT(1)
     145       26644 : TEST_RANDOM_BIT(2)
     146       26644 : TEST_RANDOM_BIT(3)
     147       26644 : TEST_RANDOM_BIT(4)
     148       26644 : TEST_RANDOM_BIT(5)
     149       26644 : TEST_RANDOM_BIT(6)
     150       26644 : TEST_RANDOM_BIT(7)
     151       26644 : TEST_RANDOM_BIT(8)
     152       26644 : TEST_RANDOM_BIT(9)
     153       26644 : TEST_RANDOM_BIT(10)
     154       26644 : TEST_RANDOM_BIT(11)
     155       26644 : TEST_RANDOM_BIT(12)
     156       26644 : TEST_RANDOM_BIT(13)
     157       26644 : TEST_RANDOM_BIT(14)
     158       26644 : TEST_RANDOM_BIT(15)
     159       26644 : TEST_RANDOM_BIT(16)
     160       26644 : TEST_RANDOM_BIT(17)
     161       26644 : TEST_RANDOM_BIT(18)
     162       26644 : TEST_RANDOM_BIT(19)
     163       26644 : TEST_RANDOM_BIT(20)
     164       26644 : TEST_RANDOM_BIT(21)
     165       26644 : TEST_RANDOM_BIT(22)
     166       26644 : TEST_RANDOM_BIT(23)
     167       26644 : TEST_RANDOM_BIT(24)
     168       26644 : TEST_RANDOM_BIT(25)
     169       26644 : TEST_RANDOM_BIT(26)
     170       26644 : TEST_RANDOM_BIT(27)
     171       26644 : TEST_RANDOM_BIT(28)
     172       26644 : TEST_RANDOM_BIT(29)
     173       26644 : TEST_RANDOM_BIT(30)
     174       26644 : TEST_RANDOM_BIT(31)
     175             : 
     176             : #undef TEST_RANDOM_BIT
     177             : 
     178             : }  // namespace internal
     179       79917 : }  // namespace v8

Generated by: LCOV version 1.10