1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/random/seed_sequences.h"
16 
17 #include <iterator>
18 #include <random>
19 
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include "absl/random/internal/nonsecure_base.h"
23 #include "absl/random/random.h"
24 namespace {
25 
TEST(SeedSequences,Examples)26 TEST(SeedSequences, Examples) {
27   {
28     absl::SeedSeq seed_seq({1, 2, 3});
29     absl::BitGen bitgen(seed_seq);
30 
31     EXPECT_NE(0, bitgen());
32   }
33   {
34     absl::BitGen engine;
35     auto seed_seq = absl::CreateSeedSeqFrom(&engine);
36     absl::BitGen bitgen(seed_seq);
37 
38     EXPECT_NE(engine(), bitgen());
39   }
40   {
41     auto seed_seq = absl::MakeSeedSeq();
42     std::mt19937 random(seed_seq);
43 
44     EXPECT_NE(0, random());
45   }
46 }
47 
TEST(CreateSeedSeqFrom,CompatibleWithStdTypes)48 TEST(CreateSeedSeqFrom, CompatibleWithStdTypes) {
49   using ExampleNonsecureURBG =
50       absl::random_internal::NonsecureURBGBase<std::minstd_rand0>;
51 
52   // Construct a URBG instance.
53   ExampleNonsecureURBG rng;
54 
55   // Construct a Seed Sequence from its variates.
56   auto seq_from_rng = absl::CreateSeedSeqFrom(&rng);
57 
58   // Ensure that another URBG can be validly constructed from the Seed Sequence.
59   std::mt19937_64{seq_from_rng};
60 }
61 
TEST(CreateSeedSeqFrom,CompatibleWithBitGenerator)62 TEST(CreateSeedSeqFrom, CompatibleWithBitGenerator) {
63   // Construct a URBG instance.
64   absl::BitGen rng;
65 
66   // Construct a Seed Sequence from its variates.
67   auto seq_from_rng = absl::CreateSeedSeqFrom(&rng);
68 
69   // Ensure that another URBG can be validly constructed from the Seed Sequence.
70   std::mt19937_64{seq_from_rng};
71 }
72 
TEST(CreateSeedSeqFrom,CompatibleWithInsecureBitGen)73 TEST(CreateSeedSeqFrom, CompatibleWithInsecureBitGen) {
74   // Construct a URBG instance.
75   absl::InsecureBitGen rng;
76 
77   // Construct a Seed Sequence from its variates.
78   auto seq_from_rng = absl::CreateSeedSeqFrom(&rng);
79 
80   // Ensure that another URBG can be validly constructed from the Seed Sequence.
81   std::mt19937_64{seq_from_rng};
82 }
83 
TEST(CreateSeedSeqFrom,CompatibleWithRawURBG)84 TEST(CreateSeedSeqFrom, CompatibleWithRawURBG) {
85   // Construct a URBG instance.
86   std::random_device urandom;
87 
88   // Construct a Seed Sequence from its variates, using 64b of seed-material.
89   auto seq_from_rng = absl::CreateSeedSeqFrom(&urandom);
90 
91   // Ensure that another URBG can be validly constructed from the Seed Sequence.
92   std::mt19937_64{seq_from_rng};
93 }
94 
95 template <typename URBG>
TestReproducibleVariateSequencesForNonsecureURBG()96 void TestReproducibleVariateSequencesForNonsecureURBG() {
97   const size_t kNumVariates = 1000;
98 
99   // Master RNG instance.
100   URBG rng;
101   // Reused for both RNG instances.
102   auto reusable_seed = absl::CreateSeedSeqFrom(&rng);
103 
104   typename URBG::result_type variates[kNumVariates];
105   {
106     URBG child(reusable_seed);
107     for (auto& variate : variates) {
108       variate = child();
109     }
110   }
111   // Ensure that variate-sequence can be "replayed" by identical RNG.
112   {
113     URBG child(reusable_seed);
114     for (auto& variate : variates) {
115       ASSERT_EQ(variate, child());
116     }
117   }
118 }
119 
TEST(CreateSeedSeqFrom,ReproducesVariateSequencesForInsecureBitGen)120 TEST(CreateSeedSeqFrom, ReproducesVariateSequencesForInsecureBitGen) {
121   TestReproducibleVariateSequencesForNonsecureURBG<absl::InsecureBitGen>();
122 }
123 
TEST(CreateSeedSeqFrom,ReproducesVariateSequencesForBitGenerator)124 TEST(CreateSeedSeqFrom, ReproducesVariateSequencesForBitGenerator) {
125   TestReproducibleVariateSequencesForNonsecureURBG<absl::BitGen>();
126 }
127 }  // namespace
128