blob: af9fe3ec1baa5d211f783a14a35274805fed998f [file] [log] [blame]
holte2a1a5472015-01-15 00:42:381// Copyright 2015 The Chromium Authors. All rights reserved.
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/rappor/rappor_prefs.h"
6
avif57136c12015-12-25 23:27:457#include <stdint.h>
8
holte2a1a5472015-01-15 00:42:389#include "base/base64.h"
avif57136c12015-12-25 23:27:4510#include "base/macros.h"
Devlin Cronin69228f42018-06-01 17:25:1011#include "base/test/metrics/histogram_tester.h"
brettwf00b9b42016-02-01 22:11:3812#include "components/prefs/testing_pref_service.h"
holte2a1a5472015-01-15 00:42:3813#include "components/rappor/byte_vector_utils.h"
14#include "components/rappor/proto/rappor_metric.pb.h"
15#include "components/rappor/rappor_pref_names.h"
16#include "testing/gtest/include/gtest/gtest.h"
17
18namespace rappor {
19
20namespace internal {
21
22namespace {
23
24// Convert a secret to base 64 and store it in preferences.
25void StoreSecret(const std::string& secret,
26 TestingPrefServiceSimple* test_prefs) {
27 std::string secret_base64;
28 base::Base64Encode(secret, &secret_base64);
29 test_prefs->SetString(prefs::kRapporSecret, secret_base64);
30}
31
32// Verify that the current value of the secret pref matches the loaded secret.
33void ExpectConsistentSecret(const TestingPrefServiceSimple& test_prefs,
34 const std::string& loaded_secret) {
35 std::string pref = test_prefs.GetString(prefs::kRapporSecret);
36 std::string decoded_pref;
37 EXPECT_TRUE(base::Base64Decode(pref, &decoded_pref));
38 EXPECT_EQ(loaded_secret, decoded_pref);
39}
40
41} // namespace
42
43class RapporPrefsTest : public testing::Test {
44 public:
45 RapporPrefsTest() {
46 RegisterPrefs(test_prefs_.registry());
47 }
48
49 protected:
50 base::HistogramTester tester_;
51 TestingPrefServiceSimple test_prefs_;
52
53 DISALLOW_COPY_AND_ASSIGN(RapporPrefsTest);
54};
55
56TEST_F(RapporPrefsTest, EmptyCohort) {
57 test_prefs_.ClearPref(prefs::kRapporCohortSeed);
58 // Loaded cohort should have been rerolled into a valid number.
59 int32_t cohort = LoadCohort(&test_prefs_);
60 tester_.ExpectUniqueSample(kLoadCohortHistogramName, LOAD_EMPTY_VALUE, 1);
61 EXPECT_GE(cohort, 0);
62 EXPECT_LT(cohort, RapporParameters::kMaxCohorts);
63 // The preferences should be consistent with the loaded value.
64 int32_t pref = test_prefs_.GetInteger(prefs::kRapporCohortSeed);
65 EXPECT_EQ(pref, cohort);
66}
67
68TEST_F(RapporPrefsTest, LoadCohort) {
69 test_prefs_.SetInteger(prefs::kRapporCohortSeed, 1);
70 // Loading the valid cohort should just retrieve it.
71 int32_t cohort = LoadCohort(&test_prefs_);
72 tester_.ExpectUniqueSample(kLoadCohortHistogramName, LOAD_SUCCESS, 1);
73 EXPECT_EQ(1, cohort);
74 // The preferences should be consistent with the loaded value.
75 int32_t pref = test_prefs_.GetInteger(prefs::kRapporCohortSeed);
76 EXPECT_EQ(pref, cohort);
77}
78
79TEST_F(RapporPrefsTest, CorruptCohort) {
80 // Set an invalid cohort value in the preference.
81 test_prefs_.SetInteger(prefs::kRapporCohortSeed, -10);
82 // Loaded cohort should have been rerolled into a valid number.
83 int32_t cohort = LoadCohort(&test_prefs_);
84 tester_.ExpectUniqueSample(kLoadCohortHistogramName, LOAD_CORRUPT_VALUE, 1);
85 EXPECT_GE(cohort, 0);
86 EXPECT_LT(cohort, RapporParameters::kMaxCohorts);
87 // The preferences should be consistent with the loaded value.
88 int32_t pref = test_prefs_.GetInteger(prefs::kRapporCohortSeed);
89 EXPECT_EQ(pref, cohort);
90}
91
92TEST_F(RapporPrefsTest, EmptySecret) {
93 test_prefs_.ClearPref(prefs::kRapporSecret);
94 // Loaded secret should be rerolled from empty.
95 std::string secret2 = LoadSecret(&test_prefs_);
96 tester_.ExpectUniqueSample(kLoadSecretHistogramName, LOAD_EMPTY_VALUE, 1);
97 EXPECT_EQ(HmacByteVectorGenerator::kEntropyInputSize, secret2.size());
98 // The stored preference should also be updated.
99 ExpectConsistentSecret(test_prefs_, secret2);
100}
101
102TEST_F(RapporPrefsTest, LoadSecret) {
103 std::string secret1 = HmacByteVectorGenerator::GenerateEntropyInput();
104 StoreSecret(secret1, &test_prefs_);
105 // Secret should load successfully.
106 std::string secret2 = LoadSecret(&test_prefs_);
107 tester_.ExpectUniqueSample(kLoadSecretHistogramName, LOAD_SUCCESS, 1);
108 EXPECT_EQ(secret1, secret2);
109 // The stored preference should also be unchanged.
110 ExpectConsistentSecret(test_prefs_, secret2);
111}
112
113TEST_F(RapporPrefsTest, CorruptSecret) {
114 // Store an invalid secret in the preferences that won't decode as base64.
115 test_prefs_.SetString(prefs::kRapporSecret, "!!INVALID!!");
116 // We should have rerolled a new secret.
117 std::string secret2 = LoadSecret(&test_prefs_);
118 tester_.ExpectUniqueSample(kLoadSecretHistogramName, LOAD_CORRUPT_VALUE, 1);
119 EXPECT_EQ(HmacByteVectorGenerator::kEntropyInputSize, secret2.size());
120 // The stored preference should also be updated.
121 ExpectConsistentSecret(test_prefs_, secret2);
122}
123
124TEST_F(RapporPrefsTest, DecodableCorruptSecret) {
125 // Store an invalid secret in the preferences that will decode as base64.
126 std::string secret1 = "!!INVALID!!";
127 StoreSecret(secret1, &test_prefs_);
128 // We should have rerolled a new secret.
129 std::string secret2 = LoadSecret(&test_prefs_);
130 tester_.ExpectUniqueSample(kLoadSecretHistogramName, LOAD_CORRUPT_VALUE, 1);
131 EXPECT_NE(secret1, secret2);
132 EXPECT_EQ(HmacByteVectorGenerator::kEntropyInputSize, secret2.size());
133 // The stored preference should also be updated.
134 ExpectConsistentSecret(test_prefs_, secret2);
135}
136
137} // namespace internal
138
139} // namespace rappor