xref: /aosp_15_r20/external/abseil-cpp/absl/random/internal/nonsecure_base_test.cc (revision 9356374a3709195abf420251b3e825997ff56c0f)
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/internal/nonsecure_base.h"
16 
17 #include <algorithm>
18 #include <cstdint>
19 #include <iostream>
20 #include <memory>
21 #include <random>
22 #include <sstream>
23 
24 #include "gtest/gtest.h"
25 #include "absl/random/distributions.h"
26 #include "absl/random/random.h"
27 #include "absl/strings/str_cat.h"
28 
29 namespace {
30 
31 using ExampleNonsecureURBG =
32     absl::random_internal::NonsecureURBGBase<std::mt19937>;
33 
34 template <typename T>
Use(const T &)35 void Use(const T&) {}
36 
37 }  // namespace
38 
TEST(NonsecureURBGBase,DefaultConstructorIsValid)39 TEST(NonsecureURBGBase, DefaultConstructorIsValid) {
40   ExampleNonsecureURBG urbg;
41 }
42 
43 // Ensure that the recommended template-instantiations are valid.
TEST(RecommendedTemplates,CanBeConstructed)44 TEST(RecommendedTemplates, CanBeConstructed) {
45   absl::BitGen default_generator;
46   absl::InsecureBitGen insecure_generator;
47 }
48 
TEST(RecommendedTemplates,CanDiscardValues)49 TEST(RecommendedTemplates, CanDiscardValues) {
50   absl::BitGen default_generator;
51   absl::InsecureBitGen insecure_generator;
52 
53   default_generator.discard(5);
54   insecure_generator.discard(5);
55 }
56 
TEST(NonsecureURBGBase,StandardInterface)57 TEST(NonsecureURBGBase, StandardInterface) {
58   // Names after definition of [rand.req.urbg] in C++ standard.
59   // e us a value of E
60   // v is a lvalue of E
61   // x, y are possibly const values of E
62   // s is a value of T
63   // q is a value satisfying requirements of seed_sequence
64   // z is a value of type unsigned long long
65   // os is a some specialization of basic_ostream
66   // is is a some specialization of basic_istream
67 
68   using E = absl::random_internal::NonsecureURBGBase<std::minstd_rand>;
69 
70   using T = typename E::result_type;
71 
72   static_assert(!std::is_copy_constructible<E>::value,
73                 "NonsecureURBGBase should not be copy constructible");
74 
75   static_assert(!absl::is_copy_assignable<E>::value,
76                 "NonsecureURBGBase should not be copy assignable");
77 
78   static_assert(std::is_move_constructible<E>::value,
79                 "NonsecureURBGBase should be move constructible");
80 
81   static_assert(absl::is_move_assignable<E>::value,
82                 "NonsecureURBGBase should be move assignable");
83 
84   static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,
85                 "return type of operator() must be result_type");
86 
87   {
88     const E x, y;
89     Use(x);
90     Use(y);
91 
92     static_assert(std::is_same<decltype(x == y), bool>::value,
93                   "return type of operator== must be bool");
94 
95     static_assert(std::is_same<decltype(x != y), bool>::value,
96                   "return type of operator== must be bool");
97   }
98 
99   E e;
100   std::seed_seq q{1, 2, 3};
101 
102   E{};
103   E{q};
104 
105   // Copy constructor not supported.
106   // E{x};
107 
108   // result_type seed constructor not supported.
109   // E{T{1}};
110 
111   // Move constructors are supported.
112   {
113     E tmp(q);
114     E m = std::move(tmp);
115     E n(std::move(m));
116     EXPECT_TRUE(e != n);
117   }
118 
119   // Comparisons work.
120   {
121     // MSVC emits error 2718 when using EXPECT_EQ(e, x)
122     //  * actual parameter with __declspec(align('#')) won't be aligned
123     E a(q);
124     E b(q);
125 
126     EXPECT_TRUE(a != e);
127     EXPECT_TRUE(a == b);
128 
129     a();
130     EXPECT_TRUE(a != b);
131   }
132 
133   // e.seed(s) not supported.
134 
135   // [rand.req.eng] specifies the parameter as 'unsigned long long'
136   // e.discard(unsigned long long) is supported.
137   unsigned long long z = 1;  // NOLINT(runtime/int)
138   e.discard(z);
139 }
140 
TEST(NonsecureURBGBase,SeedSeqConstructorIsValid)141 TEST(NonsecureURBGBase, SeedSeqConstructorIsValid) {
142   std::seed_seq seq;
143   ExampleNonsecureURBG rbg(seq);
144 }
145 
TEST(NonsecureURBGBase,CompatibleWithDistributionUtils)146 TEST(NonsecureURBGBase, CompatibleWithDistributionUtils) {
147   ExampleNonsecureURBG rbg;
148 
149   absl::Uniform(rbg, 0, 100);
150   absl::Uniform(rbg, 0.5, 0.7);
151   absl::Poisson<uint32_t>(rbg);
152   absl::Exponential<float>(rbg);
153 }
154 
TEST(NonsecureURBGBase,CompatibleWithStdDistributions)155 TEST(NonsecureURBGBase, CompatibleWithStdDistributions) {
156   ExampleNonsecureURBG rbg;
157 
158   // Cast to void to suppress [[nodiscard]] warnings
159   static_cast<void>(std::uniform_int_distribution<uint32_t>(0, 100)(rbg));
160   static_cast<void>(std::uniform_real_distribution<float>()(rbg));
161   static_cast<void>(std::bernoulli_distribution(0.2)(rbg));
162 }
163 
TEST(NonsecureURBGBase,ConsecutiveDefaultInstancesYieldUniqueVariates)164 TEST(NonsecureURBGBase, ConsecutiveDefaultInstancesYieldUniqueVariates) {
165   const size_t kNumSamples = 128;
166 
167   ExampleNonsecureURBG rbg1;
168   ExampleNonsecureURBG rbg2;
169 
170   for (size_t i = 0; i < kNumSamples; i++) {
171     EXPECT_NE(rbg1(), rbg2());
172   }
173 }
174 
TEST(NonsecureURBGBase,EqualSeedSequencesYieldEqualVariates)175 TEST(NonsecureURBGBase, EqualSeedSequencesYieldEqualVariates) {
176   std::seed_seq seq;
177 
178   ExampleNonsecureURBG rbg1(seq);
179   ExampleNonsecureURBG rbg2(seq);
180 
181   // ExampleNonsecureURBG rbg3({1, 2, 3});  // Should not compile.
182 
183   for (uint32_t i = 0; i < 1000; i++) {
184     EXPECT_EQ(rbg1(), rbg2());
185   }
186 
187   rbg1.discard(100);
188   rbg2.discard(100);
189 
190   // The sequences should continue after discarding
191   for (uint32_t i = 0; i < 1000; i++) {
192     EXPECT_EQ(rbg1(), rbg2());
193   }
194 }
195 
TEST(RandenPoolSeedSeqTest,SeederWorksForU32)196 TEST(RandenPoolSeedSeqTest, SeederWorksForU32) {
197   absl::random_internal::RandenPoolSeedSeq seeder;
198 
199   uint32_t state[2] = {0, 0};
200   seeder.generate(std::begin(state), std::end(state));
201   EXPECT_FALSE(state[0] == 0 && state[1] == 0);
202 }
203 
TEST(RandenPoolSeedSeqTest,SeederWorksForU64)204 TEST(RandenPoolSeedSeqTest, SeederWorksForU64) {
205   absl::random_internal::RandenPoolSeedSeq seeder;
206 
207   uint64_t state[2] = {0, 0};
208   seeder.generate(std::begin(state), std::end(state));
209   EXPECT_FALSE(state[0] == 0 && state[1] == 0);
210   EXPECT_FALSE((state[0] >> 32) == 0 && (state[1] >> 32) == 0);
211 }
212 
TEST(RandenPoolSeedSeqTest,SeederWorksForS32)213 TEST(RandenPoolSeedSeqTest, SeederWorksForS32) {
214   absl::random_internal::RandenPoolSeedSeq seeder;
215 
216   int32_t state[2] = {0, 0};
217   seeder.generate(std::begin(state), std::end(state));
218   EXPECT_FALSE(state[0] == 0 && state[1] == 0);
219 }
220 
TEST(RandenPoolSeedSeqTest,SeederWorksForVector)221 TEST(RandenPoolSeedSeqTest, SeederWorksForVector) {
222   absl::random_internal::RandenPoolSeedSeq seeder;
223 
224   std::vector<uint32_t> state(2);
225   seeder.generate(std::begin(state), std::end(state));
226   EXPECT_FALSE(state[0] == 0 && state[1] == 0);
227 }
228