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.
5 #include "components/metrics/metrics_state_manager.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/prefs/testing_pref_service.h"
13 #include "components/metrics/client_info.h"
14 #include "components/metrics/metrics_pref_names.h"
15 #include "components/metrics/metrics_service.h"
16 #include "components/metrics/metrics_switches.h"
17 #include "components/variations/caching_permuted_entropy_provider.h"
18 #include "components/variations/pref_names.h"
19 #include "testing/gtest/include/gtest/gtest.h"
23 class MetricsStateManagerTest
: public testing::Test
{
25 MetricsStateManagerTest() : is_metrics_reporting_enabled_(false) {
26 MetricsService::RegisterPrefs(prefs_
.registry());
29 scoped_ptr
<MetricsStateManager
> CreateStateManager() {
30 return MetricsStateManager::Create(
32 base::Bind(&MetricsStateManagerTest::is_metrics_reporting_enabled
,
33 base::Unretained(this)),
34 base::Bind(&MetricsStateManagerTest::MockStoreClientInfoBackup
,
35 base::Unretained(this)),
36 base::Bind(&MetricsStateManagerTest::LoadFakeClientInfoBackup
,
37 base::Unretained(this))).Pass();
40 // Sets metrics reporting as enabled for testing.
41 void EnableMetricsReporting() {
42 is_metrics_reporting_enabled_
= true;
46 TestingPrefServiceSimple prefs_
;
48 // Last ClientInfo stored by the MetricsStateManager via
49 // MockStoreClientInfoBackup.
50 scoped_ptr
<ClientInfo
> stored_client_info_backup_
;
52 // If set, will be returned via LoadFakeClientInfoBackup if requested by the
53 // MetricsStateManager.
54 scoped_ptr
<ClientInfo
> fake_client_info_backup_
;
57 bool is_metrics_reporting_enabled() const {
58 return is_metrics_reporting_enabled_
;
61 // Stores the |client_info| in |stored_client_info_backup_| for verification
62 // by the tests later.
63 void MockStoreClientInfoBackup(const ClientInfo
& client_info
) {
64 stored_client_info_backup_
.reset(new ClientInfo
);
65 stored_client_info_backup_
->client_id
= client_info
.client_id
;
66 stored_client_info_backup_
->installation_date
=
67 client_info
.installation_date
;
68 stored_client_info_backup_
->reporting_enabled_date
=
69 client_info
.reporting_enabled_date
;
71 // Respect the contract that storing an empty client_id voids the existing
72 // backup (required for the last section of the ForceClientIdCreation test
74 if (client_info
.client_id
.empty())
75 fake_client_info_backup_
.reset();
78 // Hands out a copy of |fake_client_info_backup_| if it is set.
79 scoped_ptr
<ClientInfo
> LoadFakeClientInfoBackup() {
80 if (!fake_client_info_backup_
)
81 return scoped_ptr
<ClientInfo
>();
83 scoped_ptr
<ClientInfo
> backup_copy(new ClientInfo
);
84 backup_copy
->client_id
= fake_client_info_backup_
->client_id
;
85 backup_copy
->installation_date
=
86 fake_client_info_backup_
->installation_date
;
87 backup_copy
->reporting_enabled_date
=
88 fake_client_info_backup_
->reporting_enabled_date
;
89 return backup_copy
.Pass();
92 bool is_metrics_reporting_enabled_
;
94 DISALLOW_COPY_AND_ASSIGN(MetricsStateManagerTest
);
97 // Ensure the ClientId is formatted as expected.
98 TEST_F(MetricsStateManagerTest
, ClientIdCorrectlyFormatted
) {
99 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
100 state_manager
->ForceClientIdCreation();
102 const std::string client_id
= state_manager
->client_id();
103 EXPECT_EQ(36U, client_id
.length());
105 for (size_t i
= 0; i
< client_id
.length(); ++i
) {
106 char current
= client_id
[i
];
107 if (i
== 8 || i
== 13 || i
== 18 || i
== 23)
108 EXPECT_EQ('-', current
);
110 EXPECT_TRUE(isxdigit(current
));
114 TEST_F(MetricsStateManagerTest
, EntropySourceUsed_Low
) {
115 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
116 state_manager
->CreateEntropyProvider();
117 EXPECT_EQ(MetricsStateManager::ENTROPY_SOURCE_LOW
,
118 state_manager
->entropy_source_returned());
121 TEST_F(MetricsStateManagerTest
, EntropySourceUsed_High
) {
122 EnableMetricsReporting();
123 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
124 state_manager
->CreateEntropyProvider();
125 EXPECT_EQ(MetricsStateManager::ENTROPY_SOURCE_HIGH
,
126 state_manager
->entropy_source_returned());
129 TEST_F(MetricsStateManagerTest
, LowEntropySource0NotReset
) {
130 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
132 // Get the low entropy source once, to initialize it.
133 state_manager
->GetLowEntropySource();
135 // Now, set it to 0 and ensure it doesn't get reset.
136 state_manager
->low_entropy_source_
= 0;
137 EXPECT_EQ(0, state_manager
->GetLowEntropySource());
138 // Call it another time, just to make sure.
139 EXPECT_EQ(0, state_manager
->GetLowEntropySource());
142 TEST_F(MetricsStateManagerTest
,
143 PermutedEntropyCacheClearedWhenLowEntropyReset
) {
144 const PrefService::Preference
* low_entropy_pref
=
145 prefs_
.FindPreference(prefs::kMetricsLowEntropySource
);
146 const char* kCachePrefName
=
147 variations::prefs::kVariationsPermutedEntropyCache
;
148 int low_entropy_value
= -1;
150 // First, generate an initial low entropy source value.
152 EXPECT_TRUE(low_entropy_pref
->IsDefaultValue());
154 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
155 state_manager
->GetLowEntropySource();
157 EXPECT_FALSE(low_entropy_pref
->IsDefaultValue());
158 EXPECT_TRUE(low_entropy_pref
->GetValue()->GetAsInteger(&low_entropy_value
));
161 // Now, set a dummy value in the permuted entropy cache pref and verify that
162 // another call to GetLowEntropySource() doesn't clobber it when
163 // --reset-variation-state wasn't specified.
165 prefs_
.SetString(kCachePrefName
, "test");
167 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
168 state_manager
->GetLowEntropySource();
170 EXPECT_EQ("test", prefs_
.GetString(kCachePrefName
));
171 EXPECT_EQ(low_entropy_value
,
172 prefs_
.GetInteger(prefs::kMetricsLowEntropySource
));
175 // Verify that the cache does get reset if --reset-variations-state is passed.
177 base::CommandLine::ForCurrentProcess()->AppendSwitch(
178 switches::kResetVariationState
);
180 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
181 state_manager
->GetLowEntropySource();
183 EXPECT_TRUE(prefs_
.GetString(kCachePrefName
).empty());
187 // Check that setting the kMetricsResetIds pref to true causes the client id to
188 // be reset. We do not check that the low entropy source is reset because we
189 // cannot ensure that metrics state manager won't generate the same id again.
190 TEST_F(MetricsStateManagerTest
, ResetMetricsIDs
) {
191 // Set an initial client id in prefs. It should not be possible for the
192 // metrics state manager to generate this id randomly.
193 const std::string kInitialClientId
= "initial client id";
194 prefs_
.SetString(prefs::kMetricsClientID
, kInitialClientId
);
196 // Make sure the initial client id isn't reset by the metrics state manager.
198 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
199 state_manager
->ForceClientIdCreation();
200 EXPECT_EQ(kInitialClientId
, state_manager
->client_id());
203 // Set the reset pref to cause the IDs to be reset.
204 prefs_
.SetBoolean(prefs::kMetricsResetIds
, true);
206 // Cause the actual reset to happen.
208 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
209 state_manager
->ForceClientIdCreation();
210 EXPECT_NE(kInitialClientId
, state_manager
->client_id());
212 state_manager
->GetLowEntropySource();
214 EXPECT_FALSE(prefs_
.GetBoolean(prefs::kMetricsResetIds
));
217 EXPECT_NE(kInitialClientId
, prefs_
.GetString(prefs::kMetricsClientID
));
220 TEST_F(MetricsStateManagerTest
, ForceClientIdCreation
) {
221 const int64 kFakeInstallationDate
= 12345;
222 prefs_
.SetInt64(prefs::kInstallDate
, kFakeInstallationDate
);
224 const int64 test_begin_time
= base::Time::Now().ToTimeT();
226 // Holds ClientInfo from previous scoped test for extra checks.
227 scoped_ptr
<ClientInfo
> previous_client_info
;
230 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
232 // client_id shouldn't be auto-generated if metrics reporting is not
234 EXPECT_EQ(std::string(), state_manager
->client_id());
235 EXPECT_EQ(0, prefs_
.GetInt64(prefs::kMetricsReportingEnabledTimestamp
));
237 // Confirm that the initial ForceClientIdCreation call creates the client id
238 // and backs it up via MockStoreClientInfoBackup.
239 EXPECT_FALSE(stored_client_info_backup_
);
240 state_manager
->ForceClientIdCreation();
241 EXPECT_NE(std::string(), state_manager
->client_id());
242 EXPECT_GE(prefs_
.GetInt64(prefs::kMetricsReportingEnabledTimestamp
),
245 ASSERT_TRUE(stored_client_info_backup_
);
246 EXPECT_EQ(state_manager
->client_id(),
247 stored_client_info_backup_
->client_id
);
248 EXPECT_EQ(kFakeInstallationDate
,
249 stored_client_info_backup_
->installation_date
);
250 EXPECT_EQ(prefs_
.GetInt64(prefs::kMetricsReportingEnabledTimestamp
),
251 stored_client_info_backup_
->reporting_enabled_date
);
253 previous_client_info
= stored_client_info_backup_
.Pass();
256 EnableMetricsReporting();
259 EXPECT_FALSE(stored_client_info_backup_
);
261 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
263 // client_id should be auto-obtained from the constructor when metrics
264 // reporting is enabled.
265 EXPECT_EQ(previous_client_info
->client_id
, state_manager
->client_id());
267 // The backup should also be refreshed when the client id re-initialized.
268 ASSERT_TRUE(stored_client_info_backup_
);
269 EXPECT_EQ(previous_client_info
->client_id
,
270 stored_client_info_backup_
->client_id
);
271 EXPECT_EQ(kFakeInstallationDate
,
272 stored_client_info_backup_
->installation_date
);
273 EXPECT_EQ(previous_client_info
->reporting_enabled_date
,
274 stored_client_info_backup_
->reporting_enabled_date
);
276 // Re-forcing client id creation shouldn't cause another backup and
277 // shouldn't affect the existing client id.
278 stored_client_info_backup_
.reset();
279 state_manager
->ForceClientIdCreation();
280 EXPECT_FALSE(stored_client_info_backup_
);
281 EXPECT_EQ(previous_client_info
->client_id
, state_manager
->client_id());
284 const int64 kBackupInstallationDate
= 1111;
285 const int64 kBackupReportingEnabledDate
= 2222;
286 const char kBackupClientId
[] = "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE";
287 fake_client_info_backup_
.reset(new ClientInfo
);
288 fake_client_info_backup_
->client_id
= kBackupClientId
;
289 fake_client_info_backup_
->installation_date
= kBackupInstallationDate
;
290 fake_client_info_backup_
->reporting_enabled_date
=
291 kBackupReportingEnabledDate
;
294 // The existence of a backup should result in the same behaviour as
295 // before if we already have a client id.
297 EXPECT_FALSE(stored_client_info_backup_
);
299 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
300 EXPECT_EQ(previous_client_info
->client_id
, state_manager
->client_id());
302 // The backup should also be refreshed when the client id re-initialized.
303 ASSERT_TRUE(stored_client_info_backup_
);
304 EXPECT_EQ(previous_client_info
->client_id
,
305 stored_client_info_backup_
->client_id
);
306 EXPECT_EQ(kFakeInstallationDate
,
307 stored_client_info_backup_
->installation_date
);
308 EXPECT_EQ(previous_client_info
->reporting_enabled_date
,
309 stored_client_info_backup_
->reporting_enabled_date
);
310 stored_client_info_backup_
.reset();
313 prefs_
.ClearPref(prefs::kMetricsClientID
);
314 prefs_
.ClearPref(prefs::kMetricsReportingEnabledTimestamp
);
317 // The backup should kick in if the client id has gone missing. It should
318 // replace remaining and missing dates as well.
320 EXPECT_FALSE(stored_client_info_backup_
);
322 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
323 EXPECT_EQ(kBackupClientId
, state_manager
->client_id());
324 EXPECT_EQ(kBackupInstallationDate
, prefs_
.GetInt64(prefs::kInstallDate
));
325 EXPECT_EQ(kBackupReportingEnabledDate
,
326 prefs_
.GetInt64(prefs::kMetricsReportingEnabledTimestamp
));
328 EXPECT_TRUE(stored_client_info_backup_
);
329 stored_client_info_backup_
.reset();
332 const char kNoDashesBackupClientId
[] = "AAAAAAAABBBBCCCCDDDDEEEEEEEEEEEE";
333 fake_client_info_backup_
.reset(new ClientInfo
);
334 fake_client_info_backup_
->client_id
= kNoDashesBackupClientId
;
336 prefs_
.ClearPref(prefs::kInstallDate
);
337 prefs_
.ClearPref(prefs::kMetricsClientID
);
338 prefs_
.ClearPref(prefs::kMetricsReportingEnabledTimestamp
);
341 // When running the backup from old-style client ids, dashes should be
342 // re-added. And missing dates in backup should be replaced by Time::Now().
344 EXPECT_FALSE(stored_client_info_backup_
);
346 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
347 EXPECT_EQ(kBackupClientId
, state_manager
->client_id());
348 EXPECT_GE(prefs_
.GetInt64(prefs::kInstallDate
), test_begin_time
);
349 EXPECT_GE(prefs_
.GetInt64(prefs::kMetricsReportingEnabledTimestamp
),
352 EXPECT_TRUE(stored_client_info_backup_
);
353 previous_client_info
= stored_client_info_backup_
.Pass();
356 prefs_
.SetBoolean(prefs::kMetricsResetIds
, true);
359 // Upon request to reset metrics ids, the existing backup should not be
362 EXPECT_FALSE(stored_client_info_backup_
);
364 scoped_ptr
<MetricsStateManager
> state_manager(CreateStateManager());
366 // A brand new client id should have been generated.
367 EXPECT_NE(std::string(), state_manager
->client_id());
368 EXPECT_NE(previous_client_info
->client_id
, state_manager
->client_id());
370 // The installation date should not have been affected.
371 EXPECT_EQ(previous_client_info
->installation_date
,
372 prefs_
.GetInt64(prefs::kInstallDate
));
374 // The metrics-reporting-enabled date will be reset to Now().
375 EXPECT_GE(prefs_
.GetInt64(prefs::kMetricsReportingEnabledTimestamp
),
376 previous_client_info
->reporting_enabled_date
);
378 stored_client_info_backup_
.reset();
382 } // namespace metrics