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/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" 20 21namespace metrics { 22 23class MetricsStateManagerTest : public testing::Test { 24 public: 25 MetricsStateManagerTest() : is_metrics_reporting_enabled_(false) { 26 MetricsService::RegisterPrefs(prefs_.registry()); 27 } 28 29 scoped_ptr<MetricsStateManager> CreateStateManager() { 30 return MetricsStateManager::Create( 31 &prefs_, 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(); 38 } 39 40 // Sets metrics reporting as enabled for testing. 41 void EnableMetricsReporting() { 42 is_metrics_reporting_enabled_ = true; 43 } 44 45 protected: 46 TestingPrefServiceSimple prefs_; 47 48 // Last ClientInfo stored by the MetricsStateManager via 49 // MockStoreClientInfoBackup. 50 scoped_ptr<ClientInfo> stored_client_info_backup_; 51 52 // If set, will be returned via LoadFakeClientInfoBackup if requested by the 53 // MetricsStateManager. 54 scoped_ptr<ClientInfo> fake_client_info_backup_; 55 56 private: 57 bool is_metrics_reporting_enabled() const { 58 return is_metrics_reporting_enabled_; 59 } 60 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; 70 71 // Respect the contract that storing an empty client_id voids the existing 72 // backup (required for the last section of the ForceClientIdCreation test 73 // below). 74 if (client_info.client_id.empty()) 75 fake_client_info_backup_.reset(); 76 } 77 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>(); 82 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(); 90 } 91 92 bool is_metrics_reporting_enabled_; 93 94 DISALLOW_COPY_AND_ASSIGN(MetricsStateManagerTest); 95}; 96 97// Ensure the ClientId is formatted as expected. 98TEST_F(MetricsStateManagerTest, ClientIdCorrectlyFormatted) { 99 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 100 state_manager->ForceClientIdCreation(); 101 102 const std::string client_id = state_manager->client_id(); 103 EXPECT_EQ(36U, client_id.length()); 104 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); 109 else 110 EXPECT_TRUE(isxdigit(current)); 111 } 112} 113 114TEST_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()); 119} 120 121TEST_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()); 127} 128 129TEST_F(MetricsStateManagerTest, LowEntropySource0NotReset) { 130 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 131 132 // Get the low entropy source once, to initialize it. 133 state_manager->GetLowEntropySource(); 134 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()); 140} 141 142TEST_F(MetricsStateManagerTest, 143 PermutedEntropyCacheClearedWhenLowEntropyReset) { 144 const PrefService::Preference* low_entropy_pref = 145 prefs_.FindPreference(prefs::kMetricsLowEntropySource); 146 const char* kCachePrefName = prefs::kVariationsPermutedEntropyCache; 147 int low_entropy_value = -1; 148 149 // First, generate an initial low entropy source value. 150 { 151 EXPECT_TRUE(low_entropy_pref->IsDefaultValue()); 152 153 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 154 state_manager->GetLowEntropySource(); 155 156 EXPECT_FALSE(low_entropy_pref->IsDefaultValue()); 157 EXPECT_TRUE(low_entropy_pref->GetValue()->GetAsInteger(&low_entropy_value)); 158 } 159 160 // Now, set a dummy value in the permuted entropy cache pref and verify that 161 // another call to GetLowEntropySource() doesn't clobber it when 162 // --reset-variation-state wasn't specified. 163 { 164 prefs_.SetString(kCachePrefName, "test"); 165 166 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 167 state_manager->GetLowEntropySource(); 168 169 EXPECT_EQ("test", prefs_.GetString(kCachePrefName)); 170 EXPECT_EQ(low_entropy_value, 171 prefs_.GetInteger(prefs::kMetricsLowEntropySource)); 172 } 173 174 // Verify that the cache does get reset if --reset-variations-state is passed. 175 { 176 CommandLine::ForCurrentProcess()->AppendSwitch( 177 switches::kResetVariationState); 178 179 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 180 state_manager->GetLowEntropySource(); 181 182 EXPECT_TRUE(prefs_.GetString(kCachePrefName).empty()); 183 } 184} 185 186// Check that setting the kMetricsResetIds pref to true causes the client id to 187// be reset. We do not check that the low entropy source is reset because we 188// cannot ensure that metrics state manager won't generate the same id again. 189TEST_F(MetricsStateManagerTest, ResetMetricsIDs) { 190 // Set an initial client id in prefs. It should not be possible for the 191 // metrics state manager to generate this id randomly. 192 const std::string kInitialClientId = "initial client id"; 193 prefs_.SetString(prefs::kMetricsClientID, kInitialClientId); 194 195 // Make sure the initial client id isn't reset by the metrics state manager. 196 { 197 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 198 state_manager->ForceClientIdCreation(); 199 EXPECT_EQ(kInitialClientId, state_manager->client_id()); 200 } 201 202 // Set the reset pref to cause the IDs to be reset. 203 prefs_.SetBoolean(prefs::kMetricsResetIds, true); 204 205 // Cause the actual reset to happen. 206 { 207 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 208 state_manager->ForceClientIdCreation(); 209 EXPECT_NE(kInitialClientId, state_manager->client_id()); 210 211 state_manager->GetLowEntropySource(); 212 213 EXPECT_FALSE(prefs_.GetBoolean(prefs::kMetricsResetIds)); 214 } 215 216 EXPECT_NE(kInitialClientId, prefs_.GetString(prefs::kMetricsClientID)); 217} 218 219TEST_F(MetricsStateManagerTest, ForceClientIdCreation) { 220 const int64 kFakeInstallationDate = 12345; 221 prefs_.SetInt64(prefs::kInstallDate, kFakeInstallationDate); 222 223 const int64 test_begin_time = base::Time::Now().ToTimeT(); 224 225 // Holds ClientInfo from previous scoped test for extra checks. 226 scoped_ptr<ClientInfo> previous_client_info; 227 228 { 229 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 230 231 // client_id shouldn't be auto-generated if metrics reporting is not 232 // enabled. 233 EXPECT_EQ(std::string(), state_manager->client_id()); 234 EXPECT_EQ(0, prefs_.GetInt64(prefs::kMetricsReportingEnabledTimestamp)); 235 236 // Confirm that the initial ForceClientIdCreation call creates the client id 237 // and backs it up via MockStoreClientInfoBackup. 238 EXPECT_FALSE(stored_client_info_backup_); 239 state_manager->ForceClientIdCreation(); 240 EXPECT_NE(std::string(), state_manager->client_id()); 241 EXPECT_GE(prefs_.GetInt64(prefs::kMetricsReportingEnabledTimestamp), 242 test_begin_time); 243 244 ASSERT_TRUE(stored_client_info_backup_); 245 EXPECT_EQ(state_manager->client_id(), 246 stored_client_info_backup_->client_id); 247 EXPECT_EQ(kFakeInstallationDate, 248 stored_client_info_backup_->installation_date); 249 EXPECT_EQ(prefs_.GetInt64(prefs::kMetricsReportingEnabledTimestamp), 250 stored_client_info_backup_->reporting_enabled_date); 251 252 previous_client_info = stored_client_info_backup_.Pass(); 253 } 254 255 EnableMetricsReporting(); 256 257 { 258 EXPECT_FALSE(stored_client_info_backup_); 259 260 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 261 262 // client_id should be auto-obtained from the constructor when metrics 263 // reporting is enabled. 264 EXPECT_EQ(previous_client_info->client_id, state_manager->client_id()); 265 266 // The backup should also be refreshed when the client id re-initialized. 267 ASSERT_TRUE(stored_client_info_backup_); 268 EXPECT_EQ(previous_client_info->client_id, 269 stored_client_info_backup_->client_id); 270 EXPECT_EQ(kFakeInstallationDate, 271 stored_client_info_backup_->installation_date); 272 EXPECT_EQ(previous_client_info->reporting_enabled_date, 273 stored_client_info_backup_->reporting_enabled_date); 274 275 // Re-forcing client id creation shouldn't cause another backup and 276 // shouldn't affect the existing client id. 277 stored_client_info_backup_.reset(); 278 state_manager->ForceClientIdCreation(); 279 EXPECT_FALSE(stored_client_info_backup_); 280 EXPECT_EQ(previous_client_info->client_id, state_manager->client_id()); 281 } 282 283 const int64 kBackupInstallationDate = 1111; 284 const int64 kBackupReportingEnabledDate = 2222; 285 const char kBackupClientId[] = "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE"; 286 fake_client_info_backup_.reset(new ClientInfo); 287 fake_client_info_backup_->client_id = kBackupClientId; 288 fake_client_info_backup_->installation_date = kBackupInstallationDate; 289 fake_client_info_backup_->reporting_enabled_date = 290 kBackupReportingEnabledDate; 291 292 { 293 // The existence of a backup should result in the same behaviour as 294 // before if we already have a client id. 295 296 EXPECT_FALSE(stored_client_info_backup_); 297 298 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 299 EXPECT_EQ(previous_client_info->client_id, state_manager->client_id()); 300 301 // The backup should also be refreshed when the client id re-initialized. 302 ASSERT_TRUE(stored_client_info_backup_); 303 EXPECT_EQ(previous_client_info->client_id, 304 stored_client_info_backup_->client_id); 305 EXPECT_EQ(kFakeInstallationDate, 306 stored_client_info_backup_->installation_date); 307 EXPECT_EQ(previous_client_info->reporting_enabled_date, 308 stored_client_info_backup_->reporting_enabled_date); 309 stored_client_info_backup_.reset(); 310 } 311 312 prefs_.ClearPref(prefs::kMetricsClientID); 313 prefs_.ClearPref(prefs::kMetricsReportingEnabledTimestamp); 314 315 { 316 // The backup should kick in if the client id has gone missing. It should 317 // replace remaining and missing dates as well. 318 319 EXPECT_FALSE(stored_client_info_backup_); 320 321 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 322 EXPECT_EQ(kBackupClientId, state_manager->client_id()); 323 EXPECT_EQ(kBackupInstallationDate, prefs_.GetInt64(prefs::kInstallDate)); 324 EXPECT_EQ(kBackupReportingEnabledDate, 325 prefs_.GetInt64(prefs::kMetricsReportingEnabledTimestamp)); 326 327 EXPECT_TRUE(stored_client_info_backup_); 328 stored_client_info_backup_.reset(); 329 } 330 331 const char kNoDashesBackupClientId[] = "AAAAAAAABBBBCCCCDDDDEEEEEEEEEEEE"; 332 fake_client_info_backup_.reset(new ClientInfo); 333 fake_client_info_backup_->client_id = kNoDashesBackupClientId; 334 335 prefs_.ClearPref(prefs::kInstallDate); 336 prefs_.ClearPref(prefs::kMetricsClientID); 337 prefs_.ClearPref(prefs::kMetricsReportingEnabledTimestamp); 338 339 { 340 // When running the backup from old-style client ids, dashes should be 341 // re-added. And missing dates in backup should be replaced by Time::Now(). 342 343 EXPECT_FALSE(stored_client_info_backup_); 344 345 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 346 EXPECT_EQ(kBackupClientId, state_manager->client_id()); 347 EXPECT_GE(prefs_.GetInt64(prefs::kInstallDate), test_begin_time); 348 EXPECT_GE(prefs_.GetInt64(prefs::kMetricsReportingEnabledTimestamp), 349 test_begin_time); 350 351 EXPECT_TRUE(stored_client_info_backup_); 352 previous_client_info = stored_client_info_backup_.Pass(); 353 } 354 355 prefs_.SetBoolean(prefs::kMetricsResetIds, true); 356 357 { 358 // Upon request to reset metrics ids, the existing backup should not be 359 // restored. 360 361 EXPECT_FALSE(stored_client_info_backup_); 362 363 scoped_ptr<MetricsStateManager> state_manager(CreateStateManager()); 364 365 // A brand new client id should have been generated. 366 EXPECT_NE(std::string(), state_manager->client_id()); 367 EXPECT_NE(previous_client_info->client_id, state_manager->client_id()); 368 369 // The installation date should not have been affected. 370 EXPECT_EQ(previous_client_info->installation_date, 371 prefs_.GetInt64(prefs::kInstallDate)); 372 373 // The metrics-reporting-enabled date will be reset to Now(). 374 EXPECT_GE(prefs_.GetInt64(prefs::kMetricsReportingEnabledTimestamp), 375 previous_client_info->reporting_enabled_date); 376 377 stored_client_info_backup_.reset(); 378 } 379} 380 381} // namespace metrics 382