xref: /aosp_15_r20/external/abseil-cpp/absl/random/internal/seed_material_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/seed_material.h"
16 
17 #include <bitset>
18 #include <cstdlib>
19 #include <cstring>
20 #include <random>
21 
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 
25 #ifdef __ANDROID__
26 // Android assert messages only go to system log, so death tests cannot inspect
27 // the message for matching.
28 #define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
29   EXPECT_DEATH_IF_SUPPORTED(statement, ".*")
30 #else
31 #define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
32   EXPECT_DEATH_IF_SUPPORTED(statement, regex)
33 #endif
34 
35 namespace {
36 
37 using testing::Each;
38 using testing::ElementsAre;
39 using testing::Eq;
40 using testing::Ne;
41 using testing::Pointwise;
42 
TEST(SeedBitsToBlocks,VerifyCases)43 TEST(SeedBitsToBlocks, VerifyCases) {
44   EXPECT_EQ(0, absl::random_internal::SeedBitsToBlocks(0));
45   EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(1));
46   EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(31));
47   EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(32));
48   EXPECT_EQ(2, absl::random_internal::SeedBitsToBlocks(33));
49   EXPECT_EQ(4, absl::random_internal::SeedBitsToBlocks(127));
50   EXPECT_EQ(4, absl::random_internal::SeedBitsToBlocks(128));
51   EXPECT_EQ(5, absl::random_internal::SeedBitsToBlocks(129));
52 }
53 
TEST(ReadSeedMaterialFromOSEntropy,SuccessiveReadsAreDistinct)54 TEST(ReadSeedMaterialFromOSEntropy, SuccessiveReadsAreDistinct) {
55   constexpr size_t kSeedMaterialSize = 64;
56   uint32_t seed_material_1[kSeedMaterialSize] = {};
57   uint32_t seed_material_2[kSeedMaterialSize] = {};
58 
59   EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy(
60       absl::Span<uint32_t>(seed_material_1, kSeedMaterialSize)));
61   EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy(
62       absl::Span<uint32_t>(seed_material_2, kSeedMaterialSize)));
63 
64   EXPECT_THAT(seed_material_1, Pointwise(Ne(), seed_material_2));
65 }
66 
TEST(ReadSeedMaterialFromOSEntropy,ReadZeroBytesIsNoOp)67 TEST(ReadSeedMaterialFromOSEntropy, ReadZeroBytesIsNoOp) {
68   uint32_t seed_material[32] = {};
69   std::memset(seed_material, 0xAA, sizeof(seed_material));
70   EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy(
71       absl::Span<uint32_t>(seed_material, 0)));
72 
73   EXPECT_THAT(seed_material, Each(Eq(0xAAAAAAAA)));
74 }
75 
TEST(ReadSeedMaterialFromOSEntropy,NullPtrVectorArgument)76 TEST(ReadSeedMaterialFromOSEntropy, NullPtrVectorArgument) {
77 #ifdef NDEBUG
78   EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromOSEntropy(
79       absl::Span<uint32_t>(nullptr, 32)));
80 #else
81   bool result;
82   ABSL_EXPECT_DEATH_IF_SUPPORTED(
83       result = absl::random_internal::ReadSeedMaterialFromOSEntropy(
84           absl::Span<uint32_t>(nullptr, 32)),
85       "!= nullptr");
86   (void)result;  // suppress unused-variable warning
87 #endif
88 }
89 
TEST(ReadSeedMaterialFromURBG,SeedMaterialEqualsVariateSequence)90 TEST(ReadSeedMaterialFromURBG, SeedMaterialEqualsVariateSequence) {
91   // Two default-constructed instances of std::mt19937_64 are guaranteed to
92   // produce equal variate-sequences.
93   std::mt19937 urbg_1;
94   std::mt19937 urbg_2;
95   constexpr size_t kSeedMaterialSize = 1024;
96   uint32_t seed_material[kSeedMaterialSize] = {};
97 
98   EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromURBG(
99       &urbg_1, absl::Span<uint32_t>(seed_material, kSeedMaterialSize)));
100   for (uint32_t seed : seed_material) {
101     EXPECT_EQ(seed, urbg_2());
102   }
103 }
104 
TEST(ReadSeedMaterialFromURBG,ReadZeroBytesIsNoOp)105 TEST(ReadSeedMaterialFromURBG, ReadZeroBytesIsNoOp) {
106   std::mt19937_64 urbg;
107   uint32_t seed_material[32];
108   std::memset(seed_material, 0xAA, sizeof(seed_material));
109   EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromURBG(
110       &urbg, absl::Span<uint32_t>(seed_material, 0)));
111 
112   EXPECT_THAT(seed_material, Each(Eq(0xAAAAAAAA)));
113 }
114 
TEST(ReadSeedMaterialFromURBG,NullUrbgArgument)115 TEST(ReadSeedMaterialFromURBG, NullUrbgArgument) {
116   constexpr size_t kSeedMaterialSize = 32;
117   uint32_t seed_material[kSeedMaterialSize];
118 #ifdef NDEBUG
119   EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromURBG<std::mt19937_64>(
120       nullptr, absl::Span<uint32_t>(seed_material, kSeedMaterialSize)));
121 #else
122   bool result;
123   ABSL_EXPECT_DEATH_IF_SUPPORTED(
124       result = absl::random_internal::ReadSeedMaterialFromURBG<std::mt19937_64>(
125           nullptr, absl::Span<uint32_t>(seed_material, kSeedMaterialSize)),
126       "!= nullptr");
127   (void)result;  // suppress unused-variable warning
128 #endif
129 }
130 
TEST(ReadSeedMaterialFromURBG,NullPtrVectorArgument)131 TEST(ReadSeedMaterialFromURBG, NullPtrVectorArgument) {
132   std::mt19937_64 urbg;
133 #ifdef NDEBUG
134   EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromURBG(
135       &urbg, absl::Span<uint32_t>(nullptr, 32)));
136 #else
137   bool result;
138   ABSL_EXPECT_DEATH_IF_SUPPORTED(
139       result = absl::random_internal::ReadSeedMaterialFromURBG(
140           &urbg, absl::Span<uint32_t>(nullptr, 32)),
141       "!= nullptr");
142   (void)result;  // suppress unused-variable warning
143 #endif
144 }
145 
146 // The avalanche effect is a desirable cryptographic property of hashes in which
147 // changing a single bit in the input causes each bit of the output to be
148 // changed with probability near 50%.
149 //
150 // https://en.wikipedia.org/wiki/Avalanche_effect
151 
TEST(MixSequenceIntoSeedMaterial,AvalancheEffectTestOneBitLong)152 TEST(MixSequenceIntoSeedMaterial, AvalancheEffectTestOneBitLong) {
153   std::vector<uint32_t> seed_material = {1, 2, 3, 4, 5, 6, 7, 8};
154 
155   // For every 32-bit number with exactly one bit set, verify the avalanche
156   // effect holds.  In order to reduce flakiness of tests, accept values
157   // anywhere in the range of 30%-70%.
158   for (uint32_t v = 1; v != 0; v <<= 1) {
159     std::vector<uint32_t> seed_material_copy = seed_material;
160     absl::random_internal::MixIntoSeedMaterial(
161         absl::Span<uint32_t>(&v, 1),
162         absl::Span<uint32_t>(seed_material_copy.data(),
163                              seed_material_copy.size()));
164 
165     uint32_t changed_bits = 0;
166     for (size_t i = 0; i < seed_material.size(); i++) {
167       std::bitset<sizeof(uint32_t) * 8> bitset(seed_material[i] ^
168                                                seed_material_copy[i]);
169       changed_bits += bitset.count();
170     }
171 
172     EXPECT_LE(changed_bits, 0.7 * sizeof(uint32_t) * 8 * seed_material.size());
173     EXPECT_GE(changed_bits, 0.3 * sizeof(uint32_t) * 8 * seed_material.size());
174   }
175 }
176 
TEST(MixSequenceIntoSeedMaterial,AvalancheEffectTestOneBitShort)177 TEST(MixSequenceIntoSeedMaterial, AvalancheEffectTestOneBitShort) {
178   std::vector<uint32_t> seed_material = {1};
179 
180   // For every 32-bit number with exactly one bit set, verify the avalanche
181   // effect holds.  In order to reduce flakiness of tests, accept values
182   // anywhere in the range of 30%-70%.
183   for (uint32_t v = 1; v != 0; v <<= 1) {
184     std::vector<uint32_t> seed_material_copy = seed_material;
185     absl::random_internal::MixIntoSeedMaterial(
186         absl::Span<uint32_t>(&v, 1),
187         absl::Span<uint32_t>(seed_material_copy.data(),
188                              seed_material_copy.size()));
189 
190     uint32_t changed_bits = 0;
191     for (size_t i = 0; i < seed_material.size(); i++) {
192       std::bitset<sizeof(uint32_t) * 8> bitset(seed_material[i] ^
193                                                seed_material_copy[i]);
194       changed_bits += bitset.count();
195     }
196 
197     EXPECT_LE(changed_bits, 0.7 * sizeof(uint32_t) * 8 * seed_material.size());
198     EXPECT_GE(changed_bits, 0.3 * sizeof(uint32_t) * 8 * seed_material.size());
199   }
200 }
201 
202 }  // namespace
203