| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/metrics/metrics_service.h" | 5 #include "components/variations/synthetic_trial_registry.h" |
| 6 | 6 |
| 7 #include <stdint.h> | |
| 8 | |
| 9 #include <algorithm> | |
| 10 #include <memory> | |
| 11 #include <string> | |
| 12 | |
| 13 #include "base/bind.h" | |
| 14 #include "base/macros.h" | |
| 15 #include "base/message_loop/message_loop.h" | |
| 16 #include "base/metrics/metrics_hashes.h" | |
| 17 #include "base/metrics/statistics_recorder.h" | |
| 18 #include "base/metrics/user_metrics.h" | |
| 19 #include "base/stl_util.h" | |
| 20 #include "base/strings/string16.h" | |
| 21 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
| 22 #include "base/test/scoped_feature_list.h" | |
| 23 #include "base/test/test_simple_task_runner.h" | |
| 24 #include "base/threading/platform_thread.h" | |
| 25 #include "base/threading/thread_task_runner_handle.h" | |
| 26 #include "components/metrics/client_info.h" | |
| 27 #include "components/metrics/environment_recorder.h" | |
| 28 #include "components/metrics/metrics_log.h" | |
| 29 #include "components/metrics/metrics_pref_names.h" | |
| 30 #include "components/metrics/metrics_state_manager.h" | |
| 31 #include "components/metrics/metrics_upload_scheduler.h" | |
| 32 #include "components/metrics/test_enabled_state_provider.h" | |
| 33 #include "components/metrics/test_metrics_provider.h" | |
| 34 #include "components/metrics/test_metrics_service_client.h" | |
| 35 #include "components/prefs/testing_pref_service.h" | |
| 36 #include "components/variations/active_field_trials.h" | 8 #include "components/variations/active_field_trials.h" |
| 37 #include "components/variations/metrics_util.h" | 9 #include "components/variations/metrics_util.h" |
| 38 #include "components/variations/synthetic_trials_active_group_id_provider.h" | 10 #include "components/variations/synthetic_trials_active_group_id_provider.h" |
| 39 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 40 #include "third_party/zlib/google/compression_utils.h" | |
| 41 | 12 |
| 42 namespace metrics { | 13 namespace variations { |
| 43 | 14 |
| 44 namespace { | 15 namespace { |
| 45 | 16 |
| 46 void StoreNoClientInfoBackup(const ClientInfo& /* client_info */) { | 17 class SyntheticTrialRegistryTest : public ::testing::Test { |
| 47 } | |
| 48 | |
| 49 std::unique_ptr<ClientInfo> ReturnNoBackup() { | |
| 50 return std::unique_ptr<ClientInfo>(); | |
| 51 } | |
| 52 | |
| 53 class TestMetricsService : public MetricsService { | |
| 54 public: | 18 public: |
| 55 TestMetricsService(MetricsStateManager* state_manager, | 19 // Returns true if there is a synthetic trial in the given vector that matches |
| 56 MetricsServiceClient* client, | 20 // the given trial name and trial group; returns false otherwise. |
| 57 PrefService* local_state) | 21 bool HasSyntheticTrial(const std::vector<ActiveGroupId>& synthetic_trials, |
| 58 : MetricsService(state_manager, client, local_state) {} | 22 const std::string& trial_name, |
| 59 ~TestMetricsService() override {} | 23 const std::string& trial_group) { |
| 60 | 24 uint32_t trial_name_hash = metrics::HashName(trial_name); |
| 61 using MetricsService::log_manager; | 25 uint32_t trial_group_hash = metrics::HashName(trial_group); |
| 62 using MetricsService::log_store; | 26 for (const ActiveGroupId& trial : synthetic_trials) { |
| 63 | 27 if (trial.name == trial_name_hash && trial.group == trial_group_hash) |
| 64 private: | 28 return true; |
| 65 DISALLOW_COPY_AND_ASSIGN(TestMetricsService); | |
| 66 }; | |
| 67 | |
| 68 class TestMetricsLog : public MetricsLog { | |
| 69 public: | |
| 70 TestMetricsLog(const std::string& client_id, | |
| 71 int session_id, | |
| 72 MetricsServiceClient* client, | |
| 73 PrefService* local_state) | |
| 74 : MetricsLog(client_id, | |
| 75 session_id, | |
| 76 MetricsLog::ONGOING_LOG, | |
| 77 client, | |
| 78 local_state) {} | |
| 79 | |
| 80 ~TestMetricsLog() override {} | |
| 81 | |
| 82 private: | |
| 83 DISALLOW_COPY_AND_ASSIGN(TestMetricsLog); | |
| 84 }; | |
| 85 | |
| 86 class MetricsServiceTest : public testing::Test { | |
| 87 public: | |
| 88 MetricsServiceTest() | |
| 89 : task_runner_(new base::TestSimpleTaskRunner), | |
| 90 task_runner_handle_(task_runner_), | |
| 91 enabled_state_provider_(new TestEnabledStateProvider(false, false)) { | |
| 92 base::SetRecordActionTaskRunner(task_runner_); | |
| 93 MetricsService::RegisterPrefs(testing_local_state_.registry()); | |
| 94 } | |
| 95 | |
| 96 ~MetricsServiceTest() override { | |
| 97 MetricsService::SetExecutionPhase(ExecutionPhase::UNINITIALIZED_PHASE, | |
| 98 GetLocalState()); | |
| 99 } | |
| 100 | |
| 101 MetricsStateManager* GetMetricsStateManager() { | |
| 102 // Lazy-initialize the metrics_state_manager so that it correctly reads the | |
| 103 // stability state from prefs after tests have a chance to initialize it. | |
| 104 if (!metrics_state_manager_) { | |
| 105 metrics_state_manager_ = MetricsStateManager::Create( | |
| 106 GetLocalState(), enabled_state_provider_.get(), base::string16(), | |
| 107 base::Bind(&StoreNoClientInfoBackup), base::Bind(&ReturnNoBackup)); | |
| 108 } | 29 } |
| 109 return metrics_state_manager_.get(); | 30 return false; |
| 110 } | |
| 111 | |
| 112 PrefService* GetLocalState() { return &testing_local_state_; } | |
| 113 | |
| 114 // Sets metrics reporting as enabled for testing. | |
| 115 void EnableMetricsReporting() { | |
| 116 enabled_state_provider_->set_consent(true); | |
| 117 enabled_state_provider_->set_enabled(true); | |
| 118 } | 31 } |
| 119 | 32 |
| 120 // Waits until base::TimeTicks::Now() no longer equals |value|. This should | 33 // Waits until base::TimeTicks::Now() no longer equals |value|. This should |
| 121 // take between 1-15ms per the documented resolution of base::TimeTicks. | 34 // take between 1-15ms per the documented resolution of base::TimeTicks. |
| 122 void WaitUntilTimeChanges(const base::TimeTicks& value) { | 35 void WaitUntilTimeChanges(const base::TimeTicks& value) { |
| 123 while (base::TimeTicks::Now() == value) { | 36 while (base::TimeTicks::Now() == value) { |
| 124 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); | 37 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); |
| 125 } | 38 } |
| 126 } | 39 } |
| 127 | |
| 128 // Returns true if there is a synthetic trial in the given vector that matches | |
| 129 // the given trial name and trial group; returns false otherwise. | |
| 130 bool HasSyntheticTrial( | |
| 131 const std::vector<variations::ActiveGroupId>& synthetic_trials, | |
| 132 const std::string& trial_name, | |
| 133 const std::string& trial_group) { | |
| 134 uint32_t trial_name_hash = HashName(trial_name); | |
| 135 uint32_t trial_group_hash = HashName(trial_group); | |
| 136 for (const variations::ActiveGroupId& trial : synthetic_trials) { | |
| 137 if (trial.name == trial_name_hash && trial.group == trial_group_hash) | |
| 138 return true; | |
| 139 } | |
| 140 return false; | |
| 141 } | |
| 142 | |
| 143 // Finds a histogram with the specified |name_hash| in |histograms|. | |
| 144 const base::HistogramBase* FindHistogram( | |
| 145 const base::StatisticsRecorder::Histograms& histograms, | |
| 146 uint64_t name_hash) { | |
| 147 for (const base::HistogramBase* histogram : histograms) { | |
| 148 if (name_hash == base::HashMetricName(histogram->histogram_name())) | |
| 149 return histogram; | |
| 150 } | |
| 151 return nullptr; | |
| 152 } | |
| 153 | |
| 154 // Checks whether |uma_log| contains any histograms that are not flagged | |
| 155 // with kUmaStabilityHistogramFlag. Stability logs should only contain such | |
| 156 // histograms. | |
| 157 void CheckForNonStabilityHistograms( | |
| 158 const ChromeUserMetricsExtension& uma_log) { | |
| 159 const int kStabilityFlags = base::HistogramBase::kUmaStabilityHistogramFlag; | |
| 160 base::StatisticsRecorder::Histograms histograms; | |
| 161 base::StatisticsRecorder::GetHistograms(&histograms); | |
| 162 for (int i = 0; i < uma_log.histogram_event_size(); ++i) { | |
| 163 const uint64_t hash = uma_log.histogram_event(i).name_hash(); | |
| 164 | |
| 165 const base::HistogramBase* histogram = FindHistogram(histograms, hash); | |
| 166 EXPECT_TRUE(histogram) << hash; | |
| 167 | |
| 168 EXPECT_EQ(kStabilityFlags, histogram->flags() & kStabilityFlags) << hash; | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 protected: | |
| 173 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; | |
| 174 base::ThreadTaskRunnerHandle task_runner_handle_; | |
| 175 base::test::ScopedFeatureList feature_list_; | |
| 176 | |
| 177 private: | |
| 178 std::unique_ptr<TestEnabledStateProvider> enabled_state_provider_; | |
| 179 TestingPrefServiceSimple testing_local_state_; | |
| 180 std::unique_ptr<MetricsStateManager> metrics_state_manager_; | |
| 181 | |
| 182 DISALLOW_COPY_AND_ASSIGN(MetricsServiceTest); | |
| 183 }; | 40 }; |
| 184 | 41 |
| 185 } // namespace | 42 } // namespace |
| 186 | 43 |
| 187 TEST_F(MetricsServiceTest, InitialStabilityLogAfterCleanShutDown) { | 44 TEST_F(SyntheticTrialRegistryTest, RegisterSyntheticTrial) { |
| 188 EnableMetricsReporting(); | 45 SyntheticTrialRegistry registry; |
| 189 GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, true); | |
| 190 | |
| 191 TestMetricsServiceClient client; | |
| 192 TestMetricsService service( | |
| 193 GetMetricsStateManager(), &client, GetLocalState()); | |
| 194 | |
| 195 TestMetricsProvider* test_provider = new TestMetricsProvider(); | |
| 196 service.RegisterMetricsProvider( | |
| 197 std::unique_ptr<MetricsProvider>(test_provider)); | |
| 198 | |
| 199 service.InitializeMetricsRecordingState(); | |
| 200 | |
| 201 // No initial stability log should be generated. | |
| 202 EXPECT_FALSE(service.has_unsent_logs()); | |
| 203 | |
| 204 // Ensure that HasInitialStabilityMetrics() is always called on providers, | |
| 205 // for consistency, even if other conditions already indicate their presence. | |
| 206 EXPECT_TRUE(test_provider->has_initial_stability_metrics_called()); | |
| 207 | |
| 208 // The test provider should not have been called upon to provide initial | |
| 209 // stability nor regular stability metrics. | |
| 210 EXPECT_FALSE(test_provider->provide_initial_stability_metrics_called()); | |
| 211 EXPECT_FALSE(test_provider->provide_stability_metrics_called()); | |
| 212 } | |
| 213 | |
| 214 TEST_F(MetricsServiceTest, InitialStabilityLogAtProviderRequest) { | |
| 215 EnableMetricsReporting(); | |
| 216 | |
| 217 // Save an existing system profile to prefs, to correspond to what would be | |
| 218 // saved from a previous session. | |
| 219 TestMetricsServiceClient client; | |
| 220 TestMetricsLog log("client", 1, &client, GetLocalState()); | |
| 221 log.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(), | |
| 222 std::vector<variations::ActiveGroupId>(), 0, 0); | |
| 223 | |
| 224 // Record stability build time and version from previous session, so that | |
| 225 // stability metrics (including exited cleanly flag) won't be cleared. | |
| 226 EnvironmentRecorder(GetLocalState()) | |
| 227 .SetBuildtimeAndVersion(MetricsLog::GetBuildTime(), | |
| 228 client.GetVersionString()); | |
| 229 | |
| 230 // Set the clean exit flag, as that will otherwise cause a stabilty | |
| 231 // log to be produced, irrespective provider requests. | |
| 232 GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, true); | |
| 233 | |
| 234 TestMetricsService service( | |
| 235 GetMetricsStateManager(), &client, GetLocalState()); | |
| 236 // Add a metrics provider that requests a stability log. | |
| 237 TestMetricsProvider* test_provider = new TestMetricsProvider(); | |
| 238 test_provider->set_has_initial_stability_metrics(true); | |
| 239 service.RegisterMetricsProvider( | |
| 240 std::unique_ptr<MetricsProvider>(test_provider)); | |
| 241 | |
| 242 service.InitializeMetricsRecordingState(); | |
| 243 | |
| 244 // The initial stability log should be generated and persisted in unsent logs. | |
| 245 MetricsLogStore* log_store = service.log_store(); | |
| 246 EXPECT_TRUE(log_store->has_unsent_logs()); | |
| 247 EXPECT_FALSE(log_store->has_staged_log()); | |
| 248 | |
| 249 // Ensure that HasInitialStabilityMetrics() is always called on providers, | |
| 250 // for consistency, even if other conditions already indicate their presence. | |
| 251 EXPECT_TRUE(test_provider->has_initial_stability_metrics_called()); | |
| 252 | |
| 253 // The test provider should have been called upon to provide initial | |
| 254 // stability and regular stability metrics. | |
| 255 EXPECT_TRUE(test_provider->provide_initial_stability_metrics_called()); | |
| 256 EXPECT_TRUE(test_provider->provide_stability_metrics_called()); | |
| 257 | |
| 258 // Stage the log and retrieve it. | |
| 259 log_store->StageNextLog(); | |
| 260 EXPECT_TRUE(log_store->has_staged_log()); | |
| 261 | |
| 262 std::string uncompressed_log; | |
| 263 EXPECT_TRUE( | |
| 264 compression::GzipUncompress(log_store->staged_log(), &uncompressed_log)); | |
| 265 | |
| 266 ChromeUserMetricsExtension uma_log; | |
| 267 EXPECT_TRUE(uma_log.ParseFromString(uncompressed_log)); | |
| 268 | |
| 269 EXPECT_TRUE(uma_log.has_client_id()); | |
| 270 EXPECT_TRUE(uma_log.has_session_id()); | |
| 271 EXPECT_TRUE(uma_log.has_system_profile()); | |
| 272 EXPECT_EQ(0, uma_log.user_action_event_size()); | |
| 273 EXPECT_EQ(0, uma_log.omnibox_event_size()); | |
| 274 EXPECT_EQ(0, uma_log.profiler_event_size()); | |
| 275 EXPECT_EQ(0, uma_log.perf_data_size()); | |
| 276 CheckForNonStabilityHistograms(uma_log); | |
| 277 | |
| 278 // As there wasn't an unclean shutdown, this log has zero crash count. | |
| 279 EXPECT_EQ(0, uma_log.system_profile().stability().crash_count()); | |
| 280 } | |
| 281 | |
| 282 TEST_F(MetricsServiceTest, InitialStabilityLogAfterCrash) { | |
| 283 EnableMetricsReporting(); | |
| 284 GetLocalState()->ClearPref(prefs::kStabilityExitedCleanly); | |
| 285 | |
| 286 // Set up prefs to simulate restarting after a crash. | |
| 287 | |
| 288 // Save an existing system profile to prefs, to correspond to what would be | |
| 289 // saved from a previous session. | |
| 290 TestMetricsServiceClient client; | |
| 291 TestMetricsLog log("client", 1, &client, GetLocalState()); | |
| 292 log.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(), | |
| 293 std::vector<variations::ActiveGroupId>(), 0, 0); | |
| 294 | |
| 295 // Record stability build time and version from previous session, so that | |
| 296 // stability metrics (including exited cleanly flag) won't be cleared. | |
| 297 EnvironmentRecorder(GetLocalState()) | |
| 298 .SetBuildtimeAndVersion(MetricsLog::GetBuildTime(), | |
| 299 client.GetVersionString()); | |
| 300 | |
| 301 GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, false); | |
| 302 | |
| 303 TestMetricsService service( | |
| 304 GetMetricsStateManager(), &client, GetLocalState()); | |
| 305 // Add a provider. | |
| 306 TestMetricsProvider* test_provider = new TestMetricsProvider(); | |
| 307 service.RegisterMetricsProvider( | |
| 308 std::unique_ptr<MetricsProvider>(test_provider)); | |
| 309 service.InitializeMetricsRecordingState(); | |
| 310 | |
| 311 // The initial stability log should be generated and persisted in unsent logs. | |
| 312 MetricsLogStore* log_store = service.log_store(); | |
| 313 EXPECT_TRUE(log_store->has_unsent_logs()); | |
| 314 EXPECT_FALSE(log_store->has_staged_log()); | |
| 315 | |
| 316 // Ensure that HasInitialStabilityMetrics() is always called on providers, | |
| 317 // for consistency, even if other conditions already indicate their presence. | |
| 318 EXPECT_TRUE(test_provider->has_initial_stability_metrics_called()); | |
| 319 | |
| 320 // The test provider should have been called upon to provide initial | |
| 321 // stability and regular stability metrics. | |
| 322 EXPECT_TRUE(test_provider->provide_initial_stability_metrics_called()); | |
| 323 EXPECT_TRUE(test_provider->provide_stability_metrics_called()); | |
| 324 | |
| 325 // Stage the log and retrieve it. | |
| 326 log_store->StageNextLog(); | |
| 327 EXPECT_TRUE(log_store->has_staged_log()); | |
| 328 | |
| 329 std::string uncompressed_log; | |
| 330 EXPECT_TRUE( | |
| 331 compression::GzipUncompress(log_store->staged_log(), &uncompressed_log)); | |
| 332 | |
| 333 ChromeUserMetricsExtension uma_log; | |
| 334 EXPECT_TRUE(uma_log.ParseFromString(uncompressed_log)); | |
| 335 | |
| 336 EXPECT_TRUE(uma_log.has_client_id()); | |
| 337 EXPECT_TRUE(uma_log.has_session_id()); | |
| 338 EXPECT_TRUE(uma_log.has_system_profile()); | |
| 339 EXPECT_EQ(0, uma_log.user_action_event_size()); | |
| 340 EXPECT_EQ(0, uma_log.omnibox_event_size()); | |
| 341 EXPECT_EQ(0, uma_log.profiler_event_size()); | |
| 342 EXPECT_EQ(0, uma_log.perf_data_size()); | |
| 343 CheckForNonStabilityHistograms(uma_log); | |
| 344 | |
| 345 EXPECT_EQ(1, uma_log.system_profile().stability().crash_count()); | |
| 346 } | |
| 347 | |
| 348 TEST_F(MetricsServiceTest, RegisterSyntheticTrial) { | |
| 349 TestMetricsServiceClient client; | |
| 350 MetricsService service(GetMetricsStateManager(), &client, GetLocalState()); | |
| 351 | 46 |
| 352 // Add two synthetic trials and confirm that they show up in the list. | 47 // Add two synthetic trials and confirm that they show up in the list. |
| 353 variations::SyntheticTrialGroup trial1(HashName("TestTrial1"), | 48 SyntheticTrialGroup trial1(metrics::HashName("TestTrial1"), |
| 354 HashName("Group1")); | 49 metrics::HashName("Group1")); |
| 355 service.RegisterSyntheticFieldTrial(trial1); | 50 registry.RegisterSyntheticFieldTrial(trial1); |
| 356 | 51 |
| 357 variations::SyntheticTrialGroup trial2(HashName("TestTrial2"), | 52 SyntheticTrialGroup trial2(metrics::HashName("TestTrial2"), |
| 358 HashName("Group2")); | 53 metrics::HashName("Group2")); |
| 359 service.RegisterSyntheticFieldTrial(trial2); | 54 registry.RegisterSyntheticFieldTrial(trial2); |
| 360 // Ensure that time has advanced by at least a tick before proceeding. | 55 // Ensure that time has advanced by at least a tick before proceeding. |
| 361 WaitUntilTimeChanges(base::TimeTicks::Now()); | 56 WaitUntilTimeChanges(base::TimeTicks::Now()); |
| 362 | 57 |
| 363 service.log_manager_.BeginLoggingWithLog(std::unique_ptr<MetricsLog>( | |
| 364 new MetricsLog("clientID", 1, MetricsLog::INITIAL_STABILITY_LOG, &client, | |
| 365 GetLocalState()))); | |
| 366 // Save the time when the log was started (it's okay for this to be greater | 58 // Save the time when the log was started (it's okay for this to be greater |
| 367 // than the time recorded by the above call since it's used to ensure the | 59 // than the time recorded by the above call since it's used to ensure the |
| 368 // value changes). | 60 // value changes). |
| 369 const base::TimeTicks begin_log_time = base::TimeTicks::Now(); | 61 const base::TimeTicks begin_log_time = base::TimeTicks::Now(); |
| 370 | 62 |
| 371 std::vector<variations::ActiveGroupId> synthetic_trials; | 63 std::vector<ActiveGroupId> synthetic_trials; |
| 372 service.GetSyntheticFieldTrialsOlderThan(base::TimeTicks::Now(), | 64 registry.GetSyntheticFieldTrialsOlderThan(base::TimeTicks::Now(), |
| 373 &synthetic_trials); | 65 &synthetic_trials); |
| 374 EXPECT_EQ(2U, synthetic_trials.size()); | 66 EXPECT_EQ(2U, synthetic_trials.size()); |
| 375 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "Group1")); | 67 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "Group1")); |
| 376 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2")); | 68 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2")); |
| 377 | 69 |
| 378 // Ensure that time has advanced by at least a tick before proceeding. | 70 // Ensure that time has advanced by at least a tick before proceeding. |
| 379 WaitUntilTimeChanges(begin_log_time); | 71 WaitUntilTimeChanges(begin_log_time); |
| 380 | 72 |
| 381 // Change the group for the first trial after the log started. | 73 // Change the group for the first trial after the log started. |
| 382 variations::SyntheticTrialGroup trial3(HashName("TestTrial1"), | 74 SyntheticTrialGroup trial3(metrics::HashName("TestTrial1"), |
| 383 HashName("Group2")); | 75 metrics::HashName("Group2")); |
| 384 service.RegisterSyntheticFieldTrial(trial3); | 76 registry.RegisterSyntheticFieldTrial(trial3); |
| 385 service.GetSyntheticFieldTrialsOlderThan(begin_log_time, &synthetic_trials); | 77 registry.GetSyntheticFieldTrialsOlderThan(begin_log_time, &synthetic_trials); |
| 386 EXPECT_EQ(1U, synthetic_trials.size()); | 78 EXPECT_EQ(1U, synthetic_trials.size()); |
| 387 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2")); | 79 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2")); |
| 388 | 80 |
| 389 // Add a new trial after the log started and confirm that it doesn't show up. | 81 // Add a new trial after the log started and confirm that it doesn't show up. |
| 390 variations::SyntheticTrialGroup trial4(HashName("TestTrial3"), | 82 SyntheticTrialGroup trial4(metrics::HashName("TestTrial3"), |
| 391 HashName("Group3")); | 83 metrics::HashName("Group3")); |
| 392 service.RegisterSyntheticFieldTrial(trial4); | 84 registry.RegisterSyntheticFieldTrial(trial4); |
| 393 service.GetSyntheticFieldTrialsOlderThan(begin_log_time, &synthetic_trials); | 85 registry.GetSyntheticFieldTrialsOlderThan(begin_log_time, &synthetic_trials); |
| 394 EXPECT_EQ(1U, synthetic_trials.size()); | 86 EXPECT_EQ(1U, synthetic_trials.size()); |
| 395 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2")); | 87 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2")); |
| 396 | 88 |
| 397 // Ensure that time has advanced by at least a tick before proceeding. | 89 // Ensure that time has advanced by at least a tick before proceeding. |
| 398 WaitUntilTimeChanges(base::TimeTicks::Now()); | 90 WaitUntilTimeChanges(base::TimeTicks::Now()); |
| 399 | 91 |
| 400 // Start a new log and ensure all three trials appear in it. | 92 // Start a new log and ensure all three trials appear in it. |
| 401 service.log_manager_.FinishCurrentLog(service.log_store()); | 93 registry.GetSyntheticFieldTrialsOlderThan(base::TimeTicks::Now(), |
| 402 service.log_manager_.BeginLoggingWithLog( | 94 &synthetic_trials); |
| 403 std::unique_ptr<MetricsLog>(new MetricsLog( | |
| 404 "clientID", 1, MetricsLog::ONGOING_LOG, &client, GetLocalState()))); | |
| 405 service.GetSyntheticFieldTrialsOlderThan( | |
| 406 service.log_manager_.current_log()->creation_time(), &synthetic_trials); | |
| 407 EXPECT_EQ(3U, synthetic_trials.size()); | 95 EXPECT_EQ(3U, synthetic_trials.size()); |
| 408 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "Group2")); | 96 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "Group2")); |
| 409 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2")); | 97 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2")); |
| 410 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial3", "Group3")); | 98 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial3", "Group3")); |
| 411 service.log_manager_.FinishCurrentLog(service.log_store()); | |
| 412 } | 99 } |
| 413 | 100 |
| 414 TEST_F(MetricsServiceTest, RegisterSyntheticMultiGroupFieldTrial) { | 101 TEST_F(SyntheticTrialRegistryTest, RegisterSyntheticMultiGroupFieldTrial) { |
| 415 TestMetricsServiceClient client; | 102 SyntheticTrialRegistry registry; |
| 416 MetricsService service(GetMetricsStateManager(), &client, GetLocalState()); | |
| 417 | 103 |
| 418 // Register a synthetic trial TestTrial1 with groups A and B. | 104 // Register a synthetic trial TestTrial1 with groups A and B. |
| 419 uint32_t trial_name_hash = HashName("TestTrial1"); | 105 uint32_t trial_name_hash = metrics::HashName("TestTrial1"); |
| 420 std::vector<uint32_t> group_name_hashes = {HashName("A"), HashName("B")}; | 106 std::vector<uint32_t> group_name_hashes = {metrics::HashName("A"), |
| 421 service.RegisterSyntheticMultiGroupFieldTrial(trial_name_hash, | 107 metrics::HashName("B")}; |
| 422 group_name_hashes); | 108 registry.RegisterSyntheticMultiGroupFieldTrial(trial_name_hash, |
| 109 group_name_hashes); |
| 423 // Ensure that time has advanced by at least a tick before proceeding. | 110 // Ensure that time has advanced by at least a tick before proceeding. |
| 424 WaitUntilTimeChanges(base::TimeTicks::Now()); | 111 WaitUntilTimeChanges(base::TimeTicks::Now()); |
| 425 | 112 |
| 426 service.log_manager_.BeginLoggingWithLog(std::unique_ptr<MetricsLog>( | 113 std::vector<ActiveGroupId> synthetic_trials; |
| 427 new MetricsLog("clientID", 1, MetricsLog::INITIAL_STABILITY_LOG, &client, | 114 registry.GetSyntheticFieldTrialsOlderThan(base::TimeTicks::Now(), |
| 428 GetLocalState()))); | 115 &synthetic_trials); |
| 429 | |
| 430 std::vector<variations::ActiveGroupId> synthetic_trials; | |
| 431 service.GetSyntheticFieldTrialsOlderThan(base::TimeTicks::Now(), | |
| 432 &synthetic_trials); | |
| 433 EXPECT_EQ(2U, synthetic_trials.size()); | 116 EXPECT_EQ(2U, synthetic_trials.size()); |
| 434 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "A")); | 117 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "A")); |
| 435 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "B")); | 118 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "B")); |
| 436 | 119 |
| 437 // Change the group for the trial to a single group. | 120 // Change the group for the trial to a single group. |
| 438 group_name_hashes = {HashName("X")}; | 121 group_name_hashes = {metrics::HashName("X")}; |
| 439 service.RegisterSyntheticMultiGroupFieldTrial(trial_name_hash, | 122 registry.RegisterSyntheticMultiGroupFieldTrial(trial_name_hash, |
| 440 group_name_hashes); | 123 group_name_hashes); |
| 441 // Ensure that time has advanced by at least a tick before proceeding. | 124 // Ensure that time has advanced by at least a tick before proceeding. |
| 442 WaitUntilTimeChanges(base::TimeTicks::Now()); | 125 WaitUntilTimeChanges(base::TimeTicks::Now()); |
| 443 | 126 |
| 444 service.GetSyntheticFieldTrialsOlderThan(base::TimeTicks::Now(), | 127 registry.GetSyntheticFieldTrialsOlderThan(base::TimeTicks::Now(), |
| 445 &synthetic_trials); | 128 &synthetic_trials); |
| 446 EXPECT_EQ(1U, synthetic_trials.size()); | 129 EXPECT_EQ(1U, synthetic_trials.size()); |
| 447 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "X")); | 130 EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "X")); |
| 448 | 131 |
| 449 // Register a trial with no groups, which should effectively remove the trial. | 132 // Register a trial with no groups, which should effectively remove the trial. |
| 450 group_name_hashes.clear(); | 133 group_name_hashes.clear(); |
| 451 service.RegisterSyntheticMultiGroupFieldTrial(trial_name_hash, | 134 registry.RegisterSyntheticMultiGroupFieldTrial(trial_name_hash, |
| 452 group_name_hashes); | 135 group_name_hashes); |
| 453 // Ensure that time has advanced by at least a tick before proceeding. | 136 // Ensure that time has advanced by at least a tick before proceeding. |
| 454 WaitUntilTimeChanges(base::TimeTicks::Now()); | 137 WaitUntilTimeChanges(base::TimeTicks::Now()); |
| 455 | 138 |
| 456 service.GetSyntheticFieldTrialsOlderThan(base::TimeTicks::Now(), | 139 registry.GetSyntheticFieldTrialsOlderThan(base::TimeTicks::Now(), |
| 457 &synthetic_trials); | 140 &synthetic_trials); |
| 458 service.log_manager_.FinishCurrentLog(service.log_store()); | |
| 459 } | 141 } |
| 460 | 142 |
| 461 TEST_F(MetricsServiceTest, | 143 TEST_F(SyntheticTrialRegistryTest, GetSyntheticFieldTrialActiveGroups) { |
| 462 MetricsProviderOnRecordingDisabledCalledOnInitialStop) { | 144 SyntheticTrialRegistry registry; |
| 463 TestMetricsServiceClient client; | |
| 464 TestMetricsService service( | |
| 465 GetMetricsStateManager(), &client, GetLocalState()); | |
| 466 | |
| 467 TestMetricsProvider* test_provider = new TestMetricsProvider(); | |
| 468 service.RegisterMetricsProvider( | |
| 469 std::unique_ptr<MetricsProvider>(test_provider)); | |
| 470 | |
| 471 service.InitializeMetricsRecordingState(); | |
| 472 service.Stop(); | |
| 473 | |
| 474 EXPECT_TRUE(test_provider->on_recording_disabled_called()); | |
| 475 } | |
| 476 | |
| 477 TEST_F(MetricsServiceTest, MetricsProvidersInitialized) { | |
| 478 TestMetricsServiceClient client; | |
| 479 TestMetricsService service( | |
| 480 GetMetricsStateManager(), &client, GetLocalState()); | |
| 481 | |
| 482 TestMetricsProvider* test_provider = new TestMetricsProvider(); | |
| 483 service.RegisterMetricsProvider( | |
| 484 std::unique_ptr<MetricsProvider>(test_provider)); | |
| 485 | |
| 486 service.InitializeMetricsRecordingState(); | |
| 487 | |
| 488 EXPECT_TRUE(test_provider->init_called()); | |
| 489 } | |
| 490 | |
| 491 TEST_F(MetricsServiceTest, SplitRotation) { | |
| 492 TestMetricsServiceClient client; | |
| 493 TestMetricsService service(GetMetricsStateManager(), &client, | |
| 494 GetLocalState()); | |
| 495 service.InitializeMetricsRecordingState(); | |
| 496 service.Start(); | |
| 497 // Rotation loop should create a log and mark state as idle. | |
| 498 // Upload loop should start upload or be restarted. | |
| 499 // The independent-metrics upload job will be started and always be a task. | |
| 500 task_runner_->RunPendingTasks(); | |
| 501 // Rotation loop should terminated due to being idle. | |
| 502 // Upload loop should start uploading if it isn't already. | |
| 503 task_runner_->RunPendingTasks(); | |
| 504 EXPECT_TRUE(client.uploader()->is_uploading()); | |
| 505 EXPECT_EQ(1U, task_runner_->NumPendingTasks()); | |
| 506 service.OnApplicationNotIdle(); | |
| 507 EXPECT_TRUE(client.uploader()->is_uploading()); | |
| 508 EXPECT_EQ(2U, task_runner_->NumPendingTasks()); | |
| 509 // Log generation should be suppressed due to unsent log. | |
| 510 // Idle state should not be reset. | |
| 511 task_runner_->RunPendingTasks(); | |
| 512 EXPECT_TRUE(client.uploader()->is_uploading()); | |
| 513 EXPECT_EQ(2U, task_runner_->NumPendingTasks()); | |
| 514 // Make sure idle state was not reset. | |
| 515 task_runner_->RunPendingTasks(); | |
| 516 EXPECT_TRUE(client.uploader()->is_uploading()); | |
| 517 EXPECT_EQ(2U, task_runner_->NumPendingTasks()); | |
| 518 // Upload should not be rescheduled, since there are no other logs. | |
| 519 client.uploader()->CompleteUpload(200); | |
| 520 EXPECT_FALSE(client.uploader()->is_uploading()); | |
| 521 EXPECT_EQ(2U, task_runner_->NumPendingTasks()); | |
| 522 // Running should generate a log, restart upload loop, and mark idle. | |
| 523 task_runner_->RunPendingTasks(); | |
| 524 EXPECT_FALSE(client.uploader()->is_uploading()); | |
| 525 EXPECT_EQ(3U, task_runner_->NumPendingTasks()); | |
| 526 // Upload should start, and rotation loop should idle out. | |
| 527 task_runner_->RunPendingTasks(); | |
| 528 EXPECT_TRUE(client.uploader()->is_uploading()); | |
| 529 EXPECT_EQ(1U, task_runner_->NumPendingTasks()); | |
| 530 // Uploader should reschedule when there is another log available. | |
| 531 service.PushExternalLog("Blah"); | |
| 532 client.uploader()->CompleteUpload(200); | |
| 533 EXPECT_FALSE(client.uploader()->is_uploading()); | |
| 534 EXPECT_EQ(2U, task_runner_->NumPendingTasks()); | |
| 535 // Upload should start. | |
| 536 task_runner_->RunPendingTasks(); | |
| 537 EXPECT_TRUE(client.uploader()->is_uploading()); | |
| 538 EXPECT_EQ(1U, task_runner_->NumPendingTasks()); | |
| 539 } | |
| 540 | |
| 541 TEST_F(MetricsServiceTest, GetSyntheticFieldTrialActiveGroups) { | |
| 542 TestMetricsServiceClient client; | |
| 543 MetricsService service(GetMetricsStateManager(), &client, GetLocalState()); | |
| 544 | 145 |
| 545 // Instantiate and setup the corresponding singleton observer which tracks the | 146 // Instantiate and setup the corresponding singleton observer which tracks the |
| 546 // creation of all SyntheticTrialGroups. | 147 // creation of all SyntheticTrialGroups. |
| 547 service.AddSyntheticTrialObserver( | 148 registry.AddSyntheticTrialObserver( |
| 548 variations::SyntheticTrialsActiveGroupIdProvider::GetInstance()); | 149 SyntheticTrialsActiveGroupIdProvider::GetInstance()); |
| 549 | 150 |
| 550 // Add two synthetic trials and confirm that they show up in the list. | 151 // Add two synthetic trials and confirm that they show up in the list. |
| 551 variations::SyntheticTrialGroup trial1(HashName("TestTrial1"), | 152 SyntheticTrialGroup trial1(metrics::HashName("TestTrial1"), |
| 552 HashName("Group1")); | 153 metrics::HashName("Group1")); |
| 553 service.RegisterSyntheticFieldTrial(trial1); | 154 registry.RegisterSyntheticFieldTrial(trial1); |
| 554 | 155 |
| 555 variations::SyntheticTrialGroup trial2(HashName("TestTrial2"), | 156 SyntheticTrialGroup trial2(metrics::HashName("TestTrial2"), |
| 556 HashName("Group2")); | 157 metrics::HashName("Group2")); |
| 557 service.RegisterSyntheticFieldTrial(trial2); | 158 registry.RegisterSyntheticFieldTrial(trial2); |
| 558 | 159 |
| 559 // Ensure that time has advanced by at least a tick before proceeding. | 160 // Ensure that time has advanced by at least a tick before proceeding. |
| 560 WaitUntilTimeChanges(base::TimeTicks::Now()); | 161 WaitUntilTimeChanges(base::TimeTicks::Now()); |
| 561 | 162 |
| 562 // Now get the list of currently active groups. | 163 // Now get the list of currently active groups. |
| 563 std::vector<std::string> output; | 164 std::vector<std::string> output; |
| 564 variations::GetSyntheticTrialGroupIdsAsString(&output); | 165 GetSyntheticTrialGroupIdsAsString(&output); |
| 565 EXPECT_EQ(2U, output.size()); | 166 EXPECT_EQ(2U, output.size()); |
| 566 | 167 |
| 567 std::string trial1_hash = | 168 std::string trial1_hash = |
| 568 base::StringPrintf("%x-%x", trial1.id.name, trial1.id.group); | 169 base::StringPrintf("%x-%x", trial1.id.name, trial1.id.group); |
| 569 EXPECT_TRUE(base::ContainsValue(output, trial1_hash)); | 170 EXPECT_TRUE(base::ContainsValue(output, trial1_hash)); |
| 570 | 171 |
| 571 std::string trial2_hash = | 172 std::string trial2_hash = |
| 572 base::StringPrintf("%x-%x", trial2.id.name, trial2.id.group); | 173 base::StringPrintf("%x-%x", trial2.id.name, trial2.id.group); |
| 573 EXPECT_TRUE(base::ContainsValue(output, trial2_hash)); | 174 EXPECT_TRUE(base::ContainsValue(output, trial2_hash)); |
| 574 } | 175 } |
| 575 | 176 |
| 576 } // namespace metrics | 177 } // namespace variations |
| OLD | NEW |