1 // Copyright 2014 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/metrics/metrics_state_manager.h"
6
7 #include <ctype.h>
8 #include <string>
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/prefs/testing_pref_service.h"
13 #include "components/metrics/metrics_pref_names.h"
14 #include "components/metrics/metrics_switches.h"
15 #include "components/variations/caching_permuted_entropy_provider.h"
16 #include "components/variations/pref_names.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace metrics {
20
21 class MetricsStateManagerTest : public testing::Test {
22 public:
MetricsStateManagerTest()23 MetricsStateManagerTest() : is_metrics_reporting_enabled_(false) {
24 MetricsStateManager::RegisterPrefs(prefs_.registry());
25 }
26
CreateStateManager()27 scoped_ptr<MetricsStateManager> CreateStateManager() {
28 return MetricsStateManager::Create(
29 &prefs_,
30 base::Bind(&MetricsStateManagerTest::is_metrics_reporting_enabled,
31 base::Unretained(this))).Pass();
32 }
33
34 // Sets metrics reporting as enabled for testing.
EnableMetricsReporting()35 void EnableMetricsReporting() {
36 is_metrics_reporting_enabled_ = true;
37 }
38
39 protected:
40 TestingPrefServiceSimple prefs_;
41
42 private:
is_metrics_reporting_enabled() const43 bool is_metrics_reporting_enabled() const {
44 return is_metrics_reporting_enabled_;
45 }
46
47 bool is_metrics_reporting_enabled_;
48
49 DISALLOW_COPY_AND_ASSIGN(MetricsStateManagerTest);
50 };
51
52 // Ensure the ClientId is formatted as expected.
TEST_F(MetricsStateManagerTest,ClientIdCorrectlyFormatted)53 TEST_F(MetricsStateManagerTest, ClientIdCorrectlyFormatted) {
54 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
55 state_manager->ForceClientIdCreation();
56
57 const std::string client_id = state_manager->client_id();
58 EXPECT_EQ(36U, client_id.length());
59
60 for (size_t i = 0; i < client_id.length(); ++i) {
61 char current = client_id[i];
62 if (i == 8 || i == 13 || i == 18 || i == 23)
63 EXPECT_EQ('-', current);
64 else
65 EXPECT_TRUE(isxdigit(current));
66 }
67 }
68
TEST_F(MetricsStateManagerTest,EntropySourceUsed_Low)69 TEST_F(MetricsStateManagerTest, EntropySourceUsed_Low) {
70 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
71 state_manager->CreateEntropyProvider();
72 EXPECT_EQ(MetricsStateManager::ENTROPY_SOURCE_LOW,
73 state_manager->entropy_source_returned());
74 }
75
TEST_F(MetricsStateManagerTest,EntropySourceUsed_High)76 TEST_F(MetricsStateManagerTest, EntropySourceUsed_High) {
77 EnableMetricsReporting();
78 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
79 state_manager->CreateEntropyProvider();
80 EXPECT_EQ(MetricsStateManager::ENTROPY_SOURCE_HIGH,
81 state_manager->entropy_source_returned());
82 }
83
TEST_F(MetricsStateManagerTest,LowEntropySource0NotReset)84 TEST_F(MetricsStateManagerTest, LowEntropySource0NotReset) {
85 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
86
87 // Get the low entropy source once, to initialize it.
88 state_manager->GetLowEntropySource();
89
90 // Now, set it to 0 and ensure it doesn't get reset.
91 state_manager->low_entropy_source_ = 0;
92 EXPECT_EQ(0, state_manager->GetLowEntropySource());
93 // Call it another time, just to make sure.
94 EXPECT_EQ(0, state_manager->GetLowEntropySource());
95 }
96
TEST_F(MetricsStateManagerTest,PermutedEntropyCacheClearedWhenLowEntropyReset)97 TEST_F(MetricsStateManagerTest,
98 PermutedEntropyCacheClearedWhenLowEntropyReset) {
99 const PrefService::Preference* low_entropy_pref =
100 prefs_.FindPreference(prefs::kMetricsLowEntropySource);
101 const char* kCachePrefName = prefs::kVariationsPermutedEntropyCache;
102 int low_entropy_value = -1;
103
104 // First, generate an initial low entropy source value.
105 {
106 EXPECT_TRUE(low_entropy_pref->IsDefaultValue());
107
108 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
109 state_manager->GetLowEntropySource();
110
111 EXPECT_FALSE(low_entropy_pref->IsDefaultValue());
112 EXPECT_TRUE(low_entropy_pref->GetValue()->GetAsInteger(&low_entropy_value));
113 }
114
115 // Now, set a dummy value in the permuted entropy cache pref and verify that
116 // another call to GetLowEntropySource() doesn't clobber it when
117 // --reset-variation-state wasn't specified.
118 {
119 prefs_.SetString(kCachePrefName, "test");
120
121 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
122 state_manager->GetLowEntropySource();
123
124 EXPECT_EQ("test", prefs_.GetString(kCachePrefName));
125 EXPECT_EQ(low_entropy_value,
126 prefs_.GetInteger(prefs::kMetricsLowEntropySource));
127 }
128
129 // Verify that the cache does get reset if --reset-variations-state is passed.
130 {
131 CommandLine::ForCurrentProcess()->AppendSwitch(
132 switches::kResetVariationState);
133
134 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
135 state_manager->GetLowEntropySource();
136
137 EXPECT_TRUE(prefs_.GetString(kCachePrefName).empty());
138 }
139 }
140
141 // Check that setting the kMetricsResetIds pref to true causes the client id to
142 // be reset. We do not check that the low entropy source is reset because we
143 // cannot ensure that metrics state manager won't generate the same id again.
TEST_F(MetricsStateManagerTest,ResetMetricsIDs)144 TEST_F(MetricsStateManagerTest, ResetMetricsIDs) {
145 // Set an initial client id in prefs. It should not be possible for the
146 // metrics state manager to generate this id randomly.
147 const std::string kInitialClientId = "initial client id";
148 prefs_.SetString(prefs::kMetricsClientID, kInitialClientId);
149
150 // Make sure the initial client id isn't reset by the metrics state manager.
151 {
152 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
153 state_manager->ForceClientIdCreation();
154 EXPECT_EQ(kInitialClientId, state_manager->client_id());
155 }
156
157 // Set the reset pref to cause the IDs to be reset.
158 prefs_.SetBoolean(prefs::kMetricsResetIds, true);
159
160 // Cause the actual reset to happen.
161 {
162 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager());
163 state_manager->ForceClientIdCreation();
164 EXPECT_NE(kInitialClientId, state_manager->client_id());
165
166 state_manager->GetLowEntropySource();
167
168 EXPECT_FALSE(prefs_.GetBoolean(prefs::kMetricsResetIds));
169 }
170
171 EXPECT_NE(kInitialClientId, prefs_.GetString(prefs::kMetricsClientID));
172 }
173
174 } // namespace metrics
175