OLD | NEW |
1 // Copyright 2017 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/doodle/doodle_service.h" | 5 #include "components/doodle/doodle_service.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 DoodleServiceTest() | 68 DoodleServiceTest() |
69 : task_runner_(new base::TestMockTimeTaskRunner()), | 69 : task_runner_(new base::TestMockTimeTaskRunner()), |
70 task_runner_handle_(task_runner_), | 70 task_runner_handle_(task_runner_), |
71 tick_clock_(task_runner_->GetMockTickClock()), | 71 tick_clock_(task_runner_->GetMockTickClock()), |
72 fetcher_(nullptr), | 72 fetcher_(nullptr), |
73 expiry_timer_(nullptr) { | 73 expiry_timer_(nullptr) { |
74 DoodleService::RegisterProfilePrefs(pref_service_.registry()); | 74 DoodleService::RegisterProfilePrefs(pref_service_.registry()); |
75 | 75 |
76 task_runner_->FastForwardBy(base::TimeDelta::FromHours(12345)); | 76 task_runner_->FastForwardBy(base::TimeDelta::FromHours(12345)); |
77 | 77 |
78 RecreateService(); | 78 // Set the minimum refresh interval to 0 by default, so tests don't have to |
| 79 // worry about it. The tests that care set it explicitly. |
| 80 RecreateServiceWithZeroRefreshInterval(); |
79 } | 81 } |
80 | 82 |
81 void DestroyService() { service_ = nullptr; } | 83 void DestroyService() { service_ = nullptr; } |
82 | 84 |
83 void RecreateService() { | 85 void RecreateServiceWithZeroRefreshInterval() { |
| 86 RecreateService(/*min_refresh_interval=*/base::TimeDelta()); |
| 87 } |
| 88 |
| 89 void RecreateService(base::Optional<base::TimeDelta> refresh_interval) { |
84 auto expiry_timer = base::MakeUnique<base::OneShotTimer>(tick_clock_.get()); | 90 auto expiry_timer = base::MakeUnique<base::OneShotTimer>(tick_clock_.get()); |
85 expiry_timer->SetTaskRunner(task_runner_); | 91 expiry_timer->SetTaskRunner(task_runner_); |
86 expiry_timer_ = expiry_timer.get(); | 92 expiry_timer_ = expiry_timer.get(); |
87 | 93 |
88 auto fetcher = base::MakeUnique<FakeDoodleFetcher>(); | 94 auto fetcher = base::MakeUnique<FakeDoodleFetcher>(); |
89 fetcher_ = fetcher.get(); | 95 fetcher_ = fetcher.get(); |
90 | 96 |
91 service_ = base::MakeUnique<DoodleService>( | 97 service_ = base::MakeUnique<DoodleService>( |
92 &pref_service_, std::move(fetcher), std::move(expiry_timer), | 98 &pref_service_, std::move(fetcher), std::move(expiry_timer), |
93 task_runner_->GetMockClock(), task_runner_->GetMockTickClock()); | 99 task_runner_->GetMockClock(), task_runner_->GetMockTickClock(), |
| 100 refresh_interval); |
94 } | 101 } |
95 | 102 |
96 DoodleService* service() { return service_.get(); } | 103 DoodleService* service() { return service_.get(); } |
97 FakeDoodleFetcher* fetcher() { return fetcher_; } | 104 FakeDoodleFetcher* fetcher() { return fetcher_; } |
98 | 105 |
99 base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); } | 106 base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); } |
100 | 107 |
101 private: | 108 private: |
102 TestingPrefServiceSimple pref_service_; | 109 TestingPrefServiceSimple pref_service_; |
103 | 110 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 // Load some doodle config. | 154 // Load some doodle config. |
148 service()->Refresh(); | 155 service()->Refresh(); |
149 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); | 156 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
150 config.large_image.url = GURL("https://doodle.com/doodle.jpg"); | 157 config.large_image.url = GURL("https://doodle.com/doodle.jpg"); |
151 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 158 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
152 base::TimeDelta::FromHours(1), config); | 159 base::TimeDelta::FromHours(1), config); |
153 ASSERT_THAT(service()->config(), Eq(config)); | 160 ASSERT_THAT(service()->config(), Eq(config)); |
154 | 161 |
155 // Re-create the service. It should have persisted the config, and load it | 162 // Re-create the service. It should have persisted the config, and load it |
156 // again automatically. | 163 // again automatically. |
157 RecreateService(); | 164 RecreateServiceWithZeroRefreshInterval(); |
158 EXPECT_THAT(service()->config(), Eq(config)); | 165 EXPECT_THAT(service()->config(), Eq(config)); |
159 } | 166 } |
160 | 167 |
161 TEST_F(DoodleServiceTest, PersistsExpiryDate) { | 168 TEST_F(DoodleServiceTest, PersistsExpiryDate) { |
162 // Load some doodle config. | 169 // Load some doodle config. |
163 service()->Refresh(); | 170 service()->Refresh(); |
164 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); | 171 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
165 config.large_image.url = GURL("https://doodle.com/doodle.jpg"); | 172 config.large_image.url = GURL("https://doodle.com/doodle.jpg"); |
166 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 173 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
167 base::TimeDelta::FromHours(1), config); | 174 base::TimeDelta::FromHours(1), config); |
168 ASSERT_THAT(service()->config(), Eq(config)); | 175 ASSERT_THAT(service()->config(), Eq(config)); |
169 | 176 |
170 // Destroy the service, and let some time pass. | 177 // Destroy the service, and let some time pass. |
171 DestroyService(); | 178 DestroyService(); |
172 task_runner()->FastForwardBy(base::TimeDelta::FromMinutes(15)); | 179 task_runner()->FastForwardBy(base::TimeDelta::FromMinutes(15)); |
173 | 180 |
174 // Remove the abandoned expiry task from the task runner. | 181 // Remove the abandoned expiry task from the task runner. |
175 ASSERT_THAT(task_runner()->GetPendingTaskCount(), Eq(1u)); | 182 ASSERT_THAT(task_runner()->GetPendingTaskCount(), Eq(1u)); |
176 task_runner()->ClearPendingTasks(); | 183 task_runner()->ClearPendingTasks(); |
177 | 184 |
178 // Re-create the service. The persisted config should have been loaded again. | 185 // Re-create the service. The persisted config should have been loaded again. |
179 RecreateService(); | 186 RecreateServiceWithZeroRefreshInterval(); |
180 EXPECT_THAT(service()->config(), Eq(config)); | 187 EXPECT_THAT(service()->config(), Eq(config)); |
181 | 188 |
182 // Its time-to-live should have been updated. | 189 // Its time-to-live should have been updated. |
183 EXPECT_THAT(task_runner()->GetPendingTaskCount(), Eq(1u)); | 190 EXPECT_THAT(task_runner()->GetPendingTaskCount(), Eq(1u)); |
184 EXPECT_THAT(task_runner()->NextPendingTaskDelay(), | 191 EXPECT_THAT(task_runner()->NextPendingTaskDelay(), |
185 Eq(base::TimeDelta::FromMinutes(45))); | 192 Eq(base::TimeDelta::FromMinutes(45))); |
186 } | 193 } |
187 | 194 |
188 TEST_F(DoodleServiceTest, PersistedConfigExpires) { | 195 TEST_F(DoodleServiceTest, PersistedConfigExpires) { |
189 // Load some doodle config. | 196 // Load some doodle config. |
190 service()->Refresh(); | 197 service()->Refresh(); |
191 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); | 198 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
192 config.large_image.url = GURL("https://doodle.com/doodle.jpg"); | 199 config.large_image.url = GURL("https://doodle.com/doodle.jpg"); |
193 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 200 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
194 base::TimeDelta::FromHours(1), config); | 201 base::TimeDelta::FromHours(1), config); |
195 ASSERT_THAT(service()->config(), Eq(config)); | 202 ASSERT_THAT(service()->config(), Eq(config)); |
196 | 203 |
197 // Destroy the service, and let enough time pass so that the config expires. | 204 // Destroy the service, and let enough time pass so that the config expires. |
198 DestroyService(); | 205 DestroyService(); |
199 task_runner()->FastForwardBy(base::TimeDelta::FromHours(1)); | 206 task_runner()->FastForwardBy(base::TimeDelta::FromHours(1)); |
200 | 207 |
201 // Re-create the service. The persisted config should have been discarded | 208 // Re-create the service. The persisted config should have been discarded |
202 // because it is expired. | 209 // because it is expired. |
203 RecreateService(); | 210 RecreateServiceWithZeroRefreshInterval(); |
204 EXPECT_THAT(service()->config(), Eq(base::nullopt)); | 211 EXPECT_THAT(service()->config(), Eq(base::nullopt)); |
205 } | 212 } |
206 | 213 |
| 214 TEST_F(DoodleServiceTest, RespectsMinRefreshInterval) { |
| 215 // Create a service with the default refresh interval. |
| 216 RecreateService(/*min_refresh_interval=*/base::nullopt); |
| 217 |
| 218 // Load some doodle config. |
| 219 service()->Refresh(); |
| 220 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
| 221 config.large_image.url = GURL("https://doodle.com/doodle.jpg"); |
| 222 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 223 base::TimeDelta::FromHours(1), config); |
| 224 ASSERT_THAT(service()->config(), Eq(config)); |
| 225 |
| 226 // Let some time pass (less than the refresh interval). |
| 227 task_runner()->FastForwardBy(base::TimeDelta::FromMinutes(10)); |
| 228 |
| 229 // Request a refresh. This should get ignored. |
| 230 service()->Refresh(); |
| 231 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(0u)); |
| 232 |
| 233 // Let more time pass, so we get past the refresh interval. |
| 234 task_runner()->FastForwardBy(base::TimeDelta::FromMinutes(6)); |
| 235 |
| 236 // Now the refresh request should be honored again. |
| 237 service()->Refresh(); |
| 238 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); |
| 239 } |
| 240 |
207 TEST_F(DoodleServiceTest, CallsObserverOnConfigReceived) { | 241 TEST_F(DoodleServiceTest, CallsObserverOnConfigReceived) { |
208 StrictMock<MockDoodleObserver> observer; | 242 StrictMock<MockDoodleObserver> observer; |
209 service()->AddObserver(&observer); | 243 service()->AddObserver(&observer); |
210 | 244 |
211 ASSERT_THAT(service()->config(), Eq(base::nullopt)); | 245 ASSERT_THAT(service()->config(), Eq(base::nullopt)); |
212 | 246 |
213 // Request a refresh of the doodle config. | 247 // Request a refresh of the doodle config. |
214 service()->Refresh(); | 248 service()->Refresh(); |
215 // The request should have arrived at the fetcher. | 249 // The request should have arrived at the fetcher. |
216 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); | 250 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 ASSERT_THAT(service()->config(), Eq(base::nullopt)); | 455 ASSERT_THAT(service()->config(), Eq(base::nullopt)); |
422 | 456 |
423 // The outcome should have been recorded, but not the time - we only record | 457 // The outcome should have been recorded, but not the time - we only record |
424 // that for successful downloads. | 458 // that for successful downloads. |
425 histograms.ExpectUniqueSample("Doodle.ConfigDownloadOutcome", | 459 histograms.ExpectUniqueSample("Doodle.ConfigDownloadOutcome", |
426 5, // OUTCOME_DOWNLOAD_ERROR | 460 5, // OUTCOME_DOWNLOAD_ERROR |
427 1); | 461 1); |
428 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0); | 462 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0); |
429 } | 463 } |
430 | 464 |
| 465 TEST_F(DoodleServiceTest, RecordsMetricsForEarlyRefreshRequest) { |
| 466 // Create a service with some refresh interval. |
| 467 RecreateService(/*min_refresh_interval=*/base::TimeDelta::FromMinutes(10)); |
| 468 |
| 469 // Load a doodle config as usual. |
| 470 service()->Refresh(); |
| 471 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
| 472 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 473 base::TimeDelta::FromHours(1), config); |
| 474 ASSERT_THAT(service()->config(), Eq(config)); |
| 475 |
| 476 base::HistogramTester histograms; |
| 477 |
| 478 // Request a refresh before the min refresh interval has passed. |
| 479 task_runner()->FastForwardBy(base::TimeDelta::FromMinutes(5)); |
| 480 service()->Refresh(); |
| 481 |
| 482 // This should not have resulted in a request. |
| 483 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(0u)); |
| 484 |
| 485 // The outcome should still have been recorded, but not the time - we only |
| 486 // record that for successful downloads. |
| 487 histograms.ExpectUniqueSample("Doodle.ConfigDownloadOutcome", |
| 488 7, // OUTCOME_REFRESH_INTERVAL_NOT_PASSED |
| 489 1); |
| 490 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0); |
| 491 } |
| 492 |
431 TEST_F(DoodleServiceTest, DoesNotRecordMetricsAtStartup) { | 493 TEST_F(DoodleServiceTest, DoesNotRecordMetricsAtStartup) { |
432 // Creating the service should not emit any histogram samples. | 494 // Creating the service should not emit any histogram samples. |
433 base::HistogramTester histograms; | 495 base::HistogramTester histograms; |
434 RecreateService(); | 496 RecreateServiceWithZeroRefreshInterval(); |
435 ASSERT_THAT(service()->config(), Eq(base::nullopt)); | 497 ASSERT_THAT(service()->config(), Eq(base::nullopt)); |
436 histograms.ExpectTotalCount("Doodle.ConfigDownloadOutcome", 0); | 498 histograms.ExpectTotalCount("Doodle.ConfigDownloadOutcome", 0); |
437 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0); | 499 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0); |
438 } | 500 } |
439 | 501 |
440 TEST_F(DoodleServiceTest, DoesNotRecordMetricsAtStartupWithConfig) { | 502 TEST_F(DoodleServiceTest, DoesNotRecordMetricsAtStartupWithConfig) { |
441 // Load a doodle config as usual. | 503 // Load a doodle config as usual. |
442 service()->Refresh(); | 504 service()->Refresh(); |
443 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); | 505 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
444 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 506 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
445 base::TimeDelta::FromHours(1), config); | 507 base::TimeDelta::FromHours(1), config); |
446 ASSERT_THAT(service()->config(), Eq(config)); | 508 ASSERT_THAT(service()->config(), Eq(config)); |
447 | 509 |
448 // Recreating the service should not emit any histogram samples, even though | 510 // Recreating the service should not emit any histogram samples, even though |
449 // a config gets loaded. | 511 // a config gets loaded. |
450 base::HistogramTester histograms; | 512 base::HistogramTester histograms; |
451 RecreateService(); | 513 RecreateServiceWithZeroRefreshInterval(); |
452 ASSERT_THAT(service()->config(), Eq(config)); | 514 ASSERT_THAT(service()->config(), Eq(config)); |
453 histograms.ExpectTotalCount("Doodle.ConfigDownloadOutcome", 0); | 515 histograms.ExpectTotalCount("Doodle.ConfigDownloadOutcome", 0); |
454 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0); | 516 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0); |
455 } | 517 } |
456 | 518 |
457 TEST_F(DoodleServiceTest, DoesNotRecordMetricsWhenConfigExpires) { | 519 TEST_F(DoodleServiceTest, DoesNotRecordMetricsWhenConfigExpires) { |
458 // Load some doodle config. | 520 // Load some doodle config. |
459 service()->Refresh(); | 521 service()->Refresh(); |
460 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); | 522 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
461 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 523 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
462 base::TimeDelta::FromHours(1), config); | 524 base::TimeDelta::FromHours(1), config); |
463 ASSERT_THAT(service()->config(), Eq(config)); | 525 ASSERT_THAT(service()->config(), Eq(config)); |
464 | 526 |
465 base::HistogramTester histograms; | 527 base::HistogramTester histograms; |
466 | 528 |
467 // Fast-forward time so that the config expires. | 529 // Fast-forward time so that the config expires. |
468 task_runner()->FastForwardBy(base::TimeDelta::FromHours(1)); | 530 task_runner()->FastForwardBy(base::TimeDelta::FromHours(1)); |
469 ASSERT_THAT(service()->config(), Eq(base::nullopt)); | 531 ASSERT_THAT(service()->config(), Eq(base::nullopt)); |
470 | 532 |
471 // This should not have resulted in any metrics being emitted. | 533 // This should not have resulted in any metrics being emitted. |
472 histograms.ExpectTotalCount("Doodle.ConfigDownloadOutcome", 0); | 534 histograms.ExpectTotalCount("Doodle.ConfigDownloadOutcome", 0); |
473 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0); | 535 histograms.ExpectTotalCount("Doodle.ConfigDownloadTime", 0); |
474 } | 536 } |
475 | 537 |
476 } // namespace doodle | 538 } // namespace doodle |
OLD | NEW |