xref: /aosp_15_r20/external/cronet/components/metrics/entropy_state_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 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 #include "components/metrics/entropy_state.h"
6 
7 #include <string>
8 
9 #include "base/command_line.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "components/metrics/metrics_pref_names.h"
13 #include "components/metrics/metrics_service.h"
14 #include "components/metrics/metrics_switches.h"
15 #include "components/prefs/testing_pref_service.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace metrics {
19 
20 class EntropyStateTest : public testing::Test {
21  public:
EntropyStateTest()22   EntropyStateTest() { MetricsService::RegisterPrefs(prefs_.registry()); }
23 
24   EntropyStateTest(const EntropyStateTest&) = delete;
25   EntropyStateTest& operator=(const EntropyStateTest&) = delete;
26 
27  protected:
28   TestingPrefServiceSimple prefs_;
29 };
30 
TEST_F(EntropyStateTest,LowEntropySourceNotReset)31 TEST_F(EntropyStateTest, LowEntropySourceNotReset) {
32   EntropyState entropy_state(&prefs_);
33   // Get the low entropy source once, to initialize it.
34   entropy_state.GetLowEntropySource();
35 
36   // Now, set it to 0 and ensure it doesn't get reset.
37   entropy_state.low_entropy_source_ = 0;
38   EXPECT_EQ(0, entropy_state.GetLowEntropySource());
39   // Call it another time, just to make sure.
40   EXPECT_EQ(0, entropy_state.GetLowEntropySource());
41 }
42 
TEST_F(EntropyStateTest,PseudoLowEntropySourceNotReset)43 TEST_F(EntropyStateTest, PseudoLowEntropySourceNotReset) {
44   EntropyState entropy_state(&prefs_);
45   // Get the pseudo low entropy source once, to initialize it.
46   entropy_state.GetPseudoLowEntropySource();
47 
48   // Now, set it to 0 and ensure it doesn't get reset.
49   entropy_state.pseudo_low_entropy_source_ = 0;
50   EXPECT_EQ(0, entropy_state.GetPseudoLowEntropySource());
51   // Call it another time, just to make sure.
52   EXPECT_EQ(0, entropy_state.GetPseudoLowEntropySource());
53 }
54 
TEST_F(EntropyStateTest,HaveNoLowEntropySource)55 TEST_F(EntropyStateTest, HaveNoLowEntropySource) {
56   EntropyState entropy_state(&prefs_);
57   // If we have none of the new, old, or pseudo low entropy sources stored in
58   // prefs, then the new source should be created...
59   int new_low_source = entropy_state.GetLowEntropySource();
60   EXPECT_TRUE(EntropyState::IsValidLowEntropySource(new_low_source))
61       << new_low_source;
62   int pseudo_low_source = entropy_state.GetPseudoLowEntropySource();
63   EXPECT_TRUE(EntropyState::IsValidLowEntropySource(pseudo_low_source))
64       << pseudo_low_source;
65   // ...but the old source should not...
66   EXPECT_EQ(EntropyState::kLowEntropySourceNotSet,
67             entropy_state.GetOldLowEntropySource());
68   // ...and the high entropy source should include the *new* low entropy source.
69   std::string high_source = entropy_state.GetHighEntropySource(
70       "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
71   EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(new_low_source),
72                              base::CompareCase::SENSITIVE))
73       << high_source;
74 }
75 
TEST_F(EntropyStateTest,HaveOnlyNewLowEntropySource)76 TEST_F(EntropyStateTest, HaveOnlyNewLowEntropySource) {
77   // If we have the new low entropy sources stored in prefs, but not the old
78   // one...
79   const int new_low_source = 1234;
80   prefs_.SetInteger(prefs::kMetricsLowEntropySource, new_low_source);
81 
82   EntropyState entropy_state(&prefs_);
83   // ...then the new source should be loaded...
84   EXPECT_EQ(new_low_source, entropy_state.GetLowEntropySource());
85   // ...but the old source should not be created...
86   EXPECT_EQ(EntropyState::kLowEntropySourceNotSet,
87             entropy_state.GetOldLowEntropySource());
88   // ...and the high entropy source should include the *new* low entropy source.
89   std::string high_source = entropy_state.GetHighEntropySource(
90       "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
91   EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(new_low_source),
92                              base::CompareCase::SENSITIVE))
93       << high_source;
94 }
95 
TEST_F(EntropyStateTest,HaveOnlyOldLowEntropySource)96 TEST_F(EntropyStateTest, HaveOnlyOldLowEntropySource) {
97   // If we have the old low entropy sources stored in prefs, but not the new
98   // one...
99   const int old_low_source = 5678;
100   prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, old_low_source);
101 
102   // ...then the new source should be created...
103   EntropyState entropy_state(&prefs_);
104 
105   int new_low_source = entropy_state.GetLowEntropySource();
106   EXPECT_TRUE(EntropyState::IsValidLowEntropySource(new_low_source))
107       << new_low_source;
108   // ...and the old source should be loaded...
109   EXPECT_EQ(old_low_source, entropy_state.GetOldLowEntropySource());
110   // ...and the high entropy source should include the *old* low entropy source.
111   std::string high_source = entropy_state.GetHighEntropySource(
112       "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
113   EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(old_low_source),
114                              base::CompareCase::SENSITIVE))
115       << high_source;
116 }
117 
TEST_F(EntropyStateTest,HaveAllLowEntropySources)118 TEST_F(EntropyStateTest, HaveAllLowEntropySources) {
119   // If we have all three of new, old, and pseudo low entropy sources in
120   // prefs...
121   const int new_low_source = 1234;
122   const int old_low_source = 5678;
123   const int pseudo_low_source = 4321;
124   prefs_.SetInteger(prefs::kMetricsLowEntropySource, new_low_source);
125   prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, old_low_source);
126   prefs_.SetInteger(prefs::kMetricsPseudoLowEntropySource, pseudo_low_source);
127 
128   // ...then all three should be loaded...
129   EntropyState entropy_state(&prefs_);
130 
131   EXPECT_EQ(new_low_source, entropy_state.GetLowEntropySource());
132   EXPECT_EQ(old_low_source, entropy_state.GetOldLowEntropySource());
133   EXPECT_EQ(pseudo_low_source, entropy_state.GetPseudoLowEntropySource());
134   // ...and the high entropy source should include the *old* low entropy source.
135   std::string high_source = entropy_state.GetHighEntropySource(
136       "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
137   EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(old_low_source),
138                              base::CompareCase::SENSITIVE))
139       << high_source;
140 }
141 
TEST_F(EntropyStateTest,CorruptNewLowEntropySources)142 TEST_F(EntropyStateTest, CorruptNewLowEntropySources) {
143   EntropyState entropy_state(&prefs_);
144   const int corrupt_sources[] = {-12345, -1, 8000, 12345};
145   for (int corrupt_source : corrupt_sources) {
146     // If the new low entropy source has been corrupted...
147     EXPECT_FALSE(EntropyState::IsValidLowEntropySource(corrupt_source))
148         << corrupt_source;
149     prefs_.SetInteger(prefs::kMetricsLowEntropySource, corrupt_source);
150     // ...then a new source should be created.
151     int loaded_source = entropy_state.GetLowEntropySource();
152     EXPECT_TRUE(EntropyState::IsValidLowEntropySource(loaded_source))
153         << loaded_source;
154   }
155 }
156 
TEST_F(EntropyStateTest,CorruptOldLowEntropySources)157 TEST_F(EntropyStateTest, CorruptOldLowEntropySources) {
158   EntropyState entropy_state(&prefs_);
159   const int corrupt_sources[] = {-12345, -1, 8000, 12345};
160   for (int corrupt_source : corrupt_sources) {
161     // If the old low entropy source has been corrupted...
162     EXPECT_FALSE(EntropyState::IsValidLowEntropySource(corrupt_source))
163         << corrupt_source;
164     prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, corrupt_source);
165     // ...then it should be ignored.
166     EXPECT_EQ(EntropyState::kLowEntropySourceNotSet,
167               entropy_state.GetOldLowEntropySource());
168   }
169 }
170 
171 #if BUILDFLAG(IS_CHROMEOS_LACROS)
TEST_F(EntropyStateTest,ClearPrefs)172 TEST_F(EntropyStateTest, ClearPrefs) {
173   // On Lacros we expect that there will be no clearing of prefs.
174   prefs_.SetInteger(prefs::kMetricsLowEntropySource, 1234);
175   prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, 5678);
176   prefs_.SetInteger(prefs::kMetricsPseudoLowEntropySource, 4321);
177   prefs_.SetString(prefs::kMetricsLimitedEntropyRandomizationSource,
178                    "00000000000000000000000000000001");
179 
180   EntropyState::ClearPrefs(&prefs_);
181 
182   EXPECT_TRUE(prefs_.HasPrefPath(prefs::kMetricsLowEntropySource));
183   EXPECT_TRUE(prefs_.HasPrefPath(prefs::kMetricsOldLowEntropySource));
184   EXPECT_TRUE(prefs_.HasPrefPath(prefs::kMetricsPseudoLowEntropySource));
185   EXPECT_TRUE(
186       prefs_.HasPrefPath(prefs::kMetricsLimitedEntropyRandomizationSource));
187 }
188 
TEST_F(EntropyStateTest,SetExternalPrefs)189 TEST_F(EntropyStateTest, SetExternalPrefs) {
190   prefs_.ClearPref(prefs::kMetricsLowEntropySource);
191   prefs_.ClearPref(prefs::kMetricsOldLowEntropySource);
192   prefs_.ClearPref(prefs::kMetricsPseudoLowEntropySource);
193   prefs_.ClearPref(prefs::kMetricsLimitedEntropyRandomizationSource);
194 
195   std::string limited_entropy_randomization_source =
196       "00000000000000000000000000000001";
197   EntropyState::SetExternalPrefs(&prefs_, 1234, 4567, 3456,
198                                  limited_entropy_randomization_source);
199 
200   EXPECT_EQ(prefs_.GetInteger(prefs::kMetricsLowEntropySource), 1234);
201   EXPECT_EQ(prefs_.GetInteger(prefs::kMetricsOldLowEntropySource), 4567);
202   EXPECT_EQ(prefs_.GetInteger(prefs::kMetricsPseudoLowEntropySource), 3456);
203   EXPECT_EQ(prefs_.GetString(prefs::kMetricsLimitedEntropyRandomizationSource),
204             limited_entropy_randomization_source);
205 }
206 
TEST_F(EntropyStateTest,SetEmptyStringToLimitedEntropyRandomizationSource)207 TEST_F(EntropyStateTest, SetEmptyStringToLimitedEntropyRandomizationSource) {
208   prefs_.ClearPref(prefs::kMetricsLimitedEntropyRandomizationSource);
209 
210   EntropyState::SetExternalPrefs(&prefs_, 1234, 4567, 3456, std::string_view());
211 
212   EXPECT_FALSE(
213       prefs_.HasPrefPath(prefs::kMetricsLimitedEntropyRandomizationSource));
214 }
215 
216 #else
217 
TEST_F(EntropyStateTest,ClearPrefs)218 TEST_F(EntropyStateTest, ClearPrefs) {
219   prefs_.SetInteger(prefs::kMetricsLowEntropySource, 1234);
220   prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, 5678);
221   prefs_.SetInteger(prefs::kMetricsPseudoLowEntropySource, 4321);
222   prefs_.SetString(prefs::kMetricsLimitedEntropyRandomizationSource,
223                    "00000000000000000000000000000001");
224 
225   EntropyState::ClearPrefs(&prefs_);
226 
227   EXPECT_FALSE(prefs_.HasPrefPath(prefs::kMetricsLowEntropySource));
228   EXPECT_FALSE(prefs_.HasPrefPath(prefs::kMetricsOldLowEntropySource));
229   EXPECT_FALSE(prefs_.HasPrefPath(prefs::kMetricsPseudoLowEntropySource));
230   EXPECT_FALSE(
231       prefs_.HasPrefPath(prefs::kMetricsLimitedEntropyRandomizationSource));
232 }
233 #endif
234 
TEST_F(EntropyStateTest,ClearingPrefWillNotResetValuesDuringSession)235 TEST_F(EntropyStateTest, ClearingPrefWillNotResetValuesDuringSession) {
236   // Setting test values in prefs;
237   prefs_.SetInteger(prefs::kMetricsLowEntropySource, 1234);
238   prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, 5678);
239   prefs_.SetInteger(prefs::kMetricsPseudoLowEntropySource, 4321);
240   prefs_.SetString(prefs::kMetricsLimitedEntropyRandomizationSource,
241                    "00000000000000000000000000000001");
242   EntropyState entropy_state(&prefs_);
243 
244   // Generates all managed values. This should load the values from prefs.
245   auto low = entropy_state.GetLowEntropySource();
246   auto old_low = entropy_state.GetOldLowEntropySource();
247   auto pseudo_low = entropy_state.GetPseudoLowEntropySource();
248   auto high = entropy_state.GetHighEntropySource(
249       "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
250   auto limited = entropy_state.GetLimitedEntropyRandomizationSource();
251 
252   EntropyState::ClearPrefs(&prefs_);
253 
254   // Clearing values in prefs should not result in returning different values.
255   EXPECT_EQ(low, entropy_state.GetLowEntropySource());
256   EXPECT_EQ(old_low, entropy_state.GetOldLowEntropySource());
257   EXPECT_EQ(pseudo_low, entropy_state.GetPseudoLowEntropySource());
258   EXPECT_EQ(high, entropy_state.GetHighEntropySource(
259                       "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF"));
260   EXPECT_EQ(limited, entropy_state.GetLimitedEntropyRandomizationSource());
261 }
262 
TEST_F(EntropyStateTest,GenerateLimitedEntropyRandomizationSourceWhenNotAvailable)263 TEST_F(EntropyStateTest,
264        GenerateLimitedEntropyRandomizationSourceWhenNotAvailable) {
265   // Pref for limited entropy randomization source is unset.
266   EXPECT_FALSE(
267       prefs_.HasPrefPath(prefs::kMetricsLimitedEntropyRandomizationSource));
268 
269   // Generate a new limited entropy randomization source.
270   EntropyState entropy_state(&prefs_);
271   entropy_state.GetLimitedEntropyRandomizationSource();
272 
273   // There should be a generated value and it should be stored in prefs.
274   auto getter_value = entropy_state.GetLimitedEntropyRandomizationSource();
275   auto pref_value =
276       prefs_.GetString(prefs::kMetricsLimitedEntropyRandomizationSource);
277   EXPECT_NE("", getter_value);
278   EXPECT_EQ(getter_value, pref_value);
279 }
280 
TEST_F(EntropyStateTest,LoadLimitedEntropyRandomizationSourceFromPref)281 TEST_F(EntropyStateTest, LoadLimitedEntropyRandomizationSourceFromPref) {
282   // There is a previously generated limited entropy randomization source stored
283   // in prefs.
284   auto* test_value = "00000000000000000000000000000001";
285   prefs_.SetString(prefs::kMetricsLimitedEntropyRandomizationSource,
286                    test_value);
287 
288   // This should load the previous value from prefs.
289   EntropyState entropy_state(&prefs_);
290   entropy_state.GetLimitedEntropyRandomizationSource();
291 
292   // Verify that the previous value was returned.
293   EXPECT_EQ(test_value, entropy_state.GetLimitedEntropyRandomizationSource());
294   // Verify that the value stored in prefs is not altered.
295   EXPECT_EQ(test_value,
296             prefs_.GetString(prefs::kMetricsLimitedEntropyRandomizationSource));
297 }
298 
TEST_F(EntropyStateTest,LimitedEntropyRandomizationSourceNotReset)299 TEST_F(EntropyStateTest, LimitedEntropyRandomizationSourceNotReset) {
300   EntropyState entropy_state(&prefs_);
301 
302   // Attempts to generate the limited entropy randomization source twice.
303   auto first_call_value = entropy_state.GetLimitedEntropyRandomizationSource();
304   auto second_call_value = entropy_state.GetLimitedEntropyRandomizationSource();
305 
306   // The generated value should not be empty.
307   EXPECT_NE("", first_call_value);
308   // The values returned from the two calls should be identical.
309   EXPECT_EQ(first_call_value, second_call_value);
310 }
311 
TEST_F(EntropyStateTest,ResetLimitedEntropyRandomizationSourceThroughCmdLine)312 TEST_F(EntropyStateTest, ResetLimitedEntropyRandomizationSourceThroughCmdLine) {
313   // Setup a command line flag to reset the variations state.
314   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
315   command_line->AppendSwitch(switches::kResetVariationState);
316   // ...and store a previously generated limited entropy randomization source
317   // value in prefs.
318   auto* test_value = "00000000000000000000000000000001";
319   prefs_.SetString(prefs::kMetricsLimitedEntropyRandomizationSource,
320                    test_value);
321 
322   // Attempts to generate a limited entropy randomization source value.
323   EntropyState entropy_state(&prefs_);
324   entropy_state.GetLimitedEntropyRandomizationSource();
325 
326   // The generated value should not be the one in prefs initially.
327   EXPECT_NE(test_value, entropy_state.GetLimitedEntropyRandomizationSource());
328   // There should be a new value, and the new value should overwrite the one in
329   // prefs initially.
330   EXPECT_EQ(entropy_state.GetLimitedEntropyRandomizationSource(),
331             prefs_.GetString(prefs::kMetricsLimitedEntropyRandomizationSource));
332 }
333 
TEST_F(EntropyStateTest,ValidLimitedEntropyRandomizationSource)334 TEST_F(EntropyStateTest, ValidLimitedEntropyRandomizationSource) {
335   const char* test_values[] = {
336       "00000000000000000000000000000001",
337       "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
338       "0123456789ABCDEF0123456789ABCDEF",
339   };
340   for (auto* test_value : test_values) {
341     EXPECT_TRUE(
342         EntropyState::IsValidLimitedEntropyRandomizationSource(test_value))
343         << "Expect EntropyState::IsValidLimitedEntropyRandomizationSource("
344         << test_value << ") to be true.";
345   }
346 }
347 
TEST_F(EntropyStateTest,InvalidLimitedEntropyRandomizationSource)348 TEST_F(EntropyStateTest, InvalidLimitedEntropyRandomizationSource) {
349   const char* test_values[] = {
350       // The empty string is not a valid limited entropy randomization source.
351       "",
352       // A value with all zero is a not a valid `base::UnguessableToken`.
353       "00000000000000000000000000000000",
354       // Not a hex string representing 128 bits.
355       "1234",
356       // A string with valid length of 128 bits but 'X' is not a hex value.
357       "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
358       // A invalid hex string because of the lower case letters.
359       "0123456789abcdef0123456789abcdef",
360   };
361   for (auto* test_value : test_values) {
362     EXPECT_FALSE(
363         EntropyState::IsValidLimitedEntropyRandomizationSource(test_value))
364         << "Expect EntropyState::IsValidLimitedEntropyRandomizationSource("
365         << test_value << ") to be false.";
366   }
367 }
368 
369 }  // namespace metrics
370