| 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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 private: | 48 private: |
| 49 std::vector<FinishedCallback> callbacks_; | 49 std::vector<FinishedCallback> callbacks_; |
| 50 }; | 50 }; |
| 51 | 51 |
| 52 class MockDoodleObserver : public DoodleService::Observer { | 52 class MockDoodleObserver : public DoodleService::Observer { |
| 53 public: | 53 public: |
| 54 MOCK_METHOD1(OnDoodleConfigUpdated, | 54 MOCK_METHOD1(OnDoodleConfigUpdated, |
| 55 void(const base::Optional<DoodleConfig>&)); | 55 void(const base::Optional<DoodleConfig>&)); |
| 56 }; | 56 }; |
| 57 | 57 |
| 58 DoodleConfig CreateConfig(DoodleType type) { |
| 59 return DoodleConfig(type, DoodleImage(GURL("https://doodle.com/image.jpg"))); |
| 60 } |
| 61 |
| 58 } // namespace | 62 } // namespace |
| 59 | 63 |
| 60 class DoodleServiceTest : public testing::Test { | 64 class DoodleServiceTest : public testing::Test { |
| 61 public: | 65 public: |
| 62 DoodleServiceTest() | 66 DoodleServiceTest() |
| 63 : fetcher_(nullptr), | 67 : fetcher_(nullptr), |
| 64 task_runner_(new base::TestMockTimeTaskRunner()), | 68 task_runner_(new base::TestMockTimeTaskRunner()), |
| 65 task_runner_handle_(task_runner_), | 69 task_runner_handle_(task_runner_), |
| 66 tick_clock_(task_runner_->GetMockTickClock()), | 70 tick_clock_(task_runner_->GetMockTickClock()), |
| 67 expiry_timer_(nullptr) { | 71 expiry_timer_(nullptr) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 98 | 102 |
| 99 TEST_F(DoodleServiceTest, FetchesConfigOnRefresh) { | 103 TEST_F(DoodleServiceTest, FetchesConfigOnRefresh) { |
| 100 ASSERT_THAT(service()->config(), Eq(base::nullopt)); | 104 ASSERT_THAT(service()->config(), Eq(base::nullopt)); |
| 101 | 105 |
| 102 // Request a refresh of the doodle config. | 106 // Request a refresh of the doodle config. |
| 103 service()->Refresh(); | 107 service()->Refresh(); |
| 104 // The request should have arrived at the fetcher. | 108 // The request should have arrived at the fetcher. |
| 105 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); | 109 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); |
| 106 | 110 |
| 107 // Serve it (with an arbitrary config). | 111 // Serve it (with an arbitrary config). |
| 108 DoodleConfig config; | 112 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
| 109 config.doodle_type = DoodleType::SIMPLE; | |
| 110 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 113 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 111 base::TimeDelta::FromHours(1), config); | 114 base::TimeDelta::FromHours(1), config); |
| 112 | 115 |
| 113 // The config should be available. | 116 // The config should be available. |
| 114 EXPECT_THAT(service()->config(), Eq(config)); | 117 EXPECT_THAT(service()->config(), Eq(config)); |
| 115 | 118 |
| 116 // Request a refresh again. | 119 // Request a refresh again. |
| 117 service()->Refresh(); | 120 service()->Refresh(); |
| 118 // The request should have arrived at the fetcher again. | 121 // The request should have arrived at the fetcher again. |
| 119 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); | 122 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); |
| 120 | 123 |
| 121 // Serve it with a different config. | 124 // Serve it with a different config. |
| 122 DoodleConfig other_config; | 125 DoodleConfig other_config = CreateConfig(DoodleType::SLIDESHOW); |
| 123 other_config.doodle_type = DoodleType::SLIDESHOW; | |
| 124 DCHECK(config != other_config); | 126 DCHECK(config != other_config); |
| 125 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 127 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 126 base::TimeDelta::FromHours(1), other_config); | 128 base::TimeDelta::FromHours(1), other_config); |
| 127 | 129 |
| 128 // The config should have been updated. | 130 // The config should have been updated. |
| 129 EXPECT_THAT(service()->config(), Eq(other_config)); | 131 EXPECT_THAT(service()->config(), Eq(other_config)); |
| 130 } | 132 } |
| 131 | 133 |
| 132 TEST_F(DoodleServiceTest, CallsObserverOnConfigReceived) { | 134 TEST_F(DoodleServiceTest, CallsObserverOnConfigReceived) { |
| 133 StrictMock<MockDoodleObserver> observer; | 135 StrictMock<MockDoodleObserver> observer; |
| 134 service()->AddObserver(&observer); | 136 service()->AddObserver(&observer); |
| 135 | 137 |
| 136 ASSERT_THAT(service()->config(), Eq(base::nullopt)); | 138 ASSERT_THAT(service()->config(), Eq(base::nullopt)); |
| 137 | 139 |
| 138 // Request a refresh of the doodle config. | 140 // Request a refresh of the doodle config. |
| 139 service()->Refresh(); | 141 service()->Refresh(); |
| 140 // The request should have arrived at the fetcher. | 142 // The request should have arrived at the fetcher. |
| 141 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); | 143 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); |
| 142 | 144 |
| 143 // Serve it (with an arbitrary config). The observer should get notified. | 145 // Serve it (with an arbitrary config). The observer should get notified. |
| 144 DoodleConfig config; | 146 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
| 145 config.doodle_type = DoodleType::SIMPLE; | |
| 146 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(config))); | 147 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(config))); |
| 147 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 148 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 148 base::TimeDelta::FromHours(1), config); | 149 base::TimeDelta::FromHours(1), config); |
| 149 | 150 |
| 150 // Remove the observer before the service gets destroyed. | 151 // Remove the observer before the service gets destroyed. |
| 151 service()->RemoveObserver(&observer); | 152 service()->RemoveObserver(&observer); |
| 152 } | 153 } |
| 153 | 154 |
| 154 TEST_F(DoodleServiceTest, CallsObserverOnConfigRemoved) { | 155 TEST_F(DoodleServiceTest, CallsObserverOnConfigRemoved) { |
| 155 // Load some doodle config. | 156 // Load some doodle config. |
| 156 service()->Refresh(); | 157 service()->Refresh(); |
| 157 DoodleConfig config; | 158 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
| 158 config.doodle_type = DoodleType::SIMPLE; | |
| 159 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 159 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 160 base::TimeDelta::FromHours(1), config); | 160 base::TimeDelta::FromHours(1), config); |
| 161 ASSERT_THAT(service()->config(), Eq(config)); | 161 ASSERT_THAT(service()->config(), Eq(config)); |
| 162 | 162 |
| 163 // Register an observer and request a refresh. | 163 // Register an observer and request a refresh. |
| 164 StrictMock<MockDoodleObserver> observer; | 164 StrictMock<MockDoodleObserver> observer; |
| 165 service()->AddObserver(&observer); | 165 service()->AddObserver(&observer); |
| 166 service()->Refresh(); | 166 service()->Refresh(); |
| 167 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); | 167 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); |
| 168 | 168 |
| 169 // Serve the request with an empty doodle config. The observer should get | 169 // Serve the request with an empty doodle config. The observer should get |
| 170 // notified. | 170 // notified. |
| 171 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(base::nullopt))); | 171 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(base::nullopt))); |
| 172 fetcher()->ServeAllCallbacks(DoodleState::NO_DOODLE, base::TimeDelta(), | 172 fetcher()->ServeAllCallbacks(DoodleState::NO_DOODLE, base::TimeDelta(), |
| 173 base::nullopt); | 173 base::nullopt); |
| 174 | 174 |
| 175 // Remove the observer before the service gets destroyed. | 175 // Remove the observer before the service gets destroyed. |
| 176 service()->RemoveObserver(&observer); | 176 service()->RemoveObserver(&observer); |
| 177 } | 177 } |
| 178 | 178 |
| 179 TEST_F(DoodleServiceTest, CallsObserverOnConfigUpdated) { | 179 TEST_F(DoodleServiceTest, CallsObserverOnConfigUpdated) { |
| 180 // Load some doodle config. | 180 // Load some doodle config. |
| 181 service()->Refresh(); | 181 service()->Refresh(); |
| 182 DoodleConfig config; | 182 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
| 183 config.doodle_type = DoodleType::SIMPLE; | |
| 184 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 183 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 185 base::TimeDelta::FromHours(1), config); | 184 base::TimeDelta::FromHours(1), config); |
| 186 ASSERT_THAT(service()->config(), Eq(config)); | 185 ASSERT_THAT(service()->config(), Eq(config)); |
| 187 | 186 |
| 188 // Register an observer and request a refresh. | 187 // Register an observer and request a refresh. |
| 189 StrictMock<MockDoodleObserver> observer; | 188 StrictMock<MockDoodleObserver> observer; |
| 190 service()->AddObserver(&observer); | 189 service()->AddObserver(&observer); |
| 191 service()->Refresh(); | 190 service()->Refresh(); |
| 192 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); | 191 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); |
| 193 | 192 |
| 194 // Serve the request with a different doodle config. The observer should get | 193 // Serve the request with a different doodle config. The observer should get |
| 195 // notified. | 194 // notified. |
| 196 DoodleConfig other_config; | 195 DoodleConfig other_config = CreateConfig(DoodleType::SLIDESHOW); |
| 197 other_config.doodle_type = DoodleType::SLIDESHOW; | |
| 198 DCHECK(config != other_config); | 196 DCHECK(config != other_config); |
| 199 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(other_config))); | 197 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(other_config))); |
| 200 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 198 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 201 base::TimeDelta::FromHours(1), other_config); | 199 base::TimeDelta::FromHours(1), other_config); |
| 202 | 200 |
| 203 // Remove the observer before the service gets destroyed. | 201 // Remove the observer before the service gets destroyed. |
| 204 service()->RemoveObserver(&observer); | 202 service()->RemoveObserver(&observer); |
| 205 } | 203 } |
| 206 | 204 |
| 207 TEST_F(DoodleServiceTest, DoesNotCallObserverIfConfigEquivalent) { | 205 TEST_F(DoodleServiceTest, DoesNotCallObserverIfConfigEquivalent) { |
| 208 // Load some doodle config. | 206 // Load some doodle config. |
| 209 service()->Refresh(); | 207 service()->Refresh(); |
| 210 DoodleConfig config; | 208 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
| 211 config.doodle_type = DoodleType::SIMPLE; | |
| 212 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 209 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 213 base::TimeDelta::FromHours(1), config); | 210 base::TimeDelta::FromHours(1), config); |
| 214 ASSERT_THAT(service()->config(), Eq(config)); | 211 ASSERT_THAT(service()->config(), Eq(config)); |
| 215 | 212 |
| 216 // Register an observer and request a refresh. | 213 // Register an observer and request a refresh. |
| 217 StrictMock<MockDoodleObserver> observer; | 214 StrictMock<MockDoodleObserver> observer; |
| 218 service()->AddObserver(&observer); | 215 service()->AddObserver(&observer); |
| 219 service()->Refresh(); | 216 service()->Refresh(); |
| 220 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); | 217 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); |
| 221 | 218 |
| 222 // Serve the request with an equivalent doodle config. The observer should | 219 // Serve the request with an equivalent doodle config. The observer should |
| 223 // *not* get notified. | 220 // *not* get notified. |
| 224 DoodleConfig equivalent_config; | 221 DoodleConfig equivalent_config = CreateConfig(DoodleType::SIMPLE); |
| 225 equivalent_config.doodle_type = DoodleType::SIMPLE; | |
| 226 DCHECK(config == equivalent_config); | 222 DCHECK(config == equivalent_config); |
| 227 fetcher()->ServeAllCallbacks( | 223 fetcher()->ServeAllCallbacks( |
| 228 DoodleState::AVAILABLE, base::TimeDelta::FromHours(1), equivalent_config); | 224 DoodleState::AVAILABLE, base::TimeDelta::FromHours(1), equivalent_config); |
| 229 | 225 |
| 230 // Remove the observer before the service gets destroyed. | 226 // Remove the observer before the service gets destroyed. |
| 231 service()->RemoveObserver(&observer); | 227 service()->RemoveObserver(&observer); |
| 232 } | 228 } |
| 233 | 229 |
| 234 TEST_F(DoodleServiceTest, CallsObserverWhenConfigExpires) { | 230 TEST_F(DoodleServiceTest, CallsObserverWhenConfigExpires) { |
| 235 // Load some doodle config. | 231 // Load some doodle config. |
| 236 service()->Refresh(); | 232 service()->Refresh(); |
| 237 DoodleConfig config; | 233 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
| 238 config.doodle_type = DoodleType::SIMPLE; | |
| 239 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 234 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 240 base::TimeDelta::FromHours(1), config); | 235 base::TimeDelta::FromHours(1), config); |
| 241 ASSERT_THAT(service()->config(), Eq(config)); | 236 ASSERT_THAT(service()->config(), Eq(config)); |
| 242 | 237 |
| 243 // Make sure the task arrived at the timer's task runner. | 238 // Make sure the task arrived at the timer's task runner. |
| 244 ASSERT_THAT(task_runner()->GetPendingTaskCount(), Eq(1u)); | 239 ASSERT_THAT(task_runner()->GetPendingTaskCount(), Eq(1u)); |
| 245 EXPECT_THAT(task_runner()->NextPendingTaskDelay(), | 240 EXPECT_THAT(task_runner()->NextPendingTaskDelay(), |
| 246 Eq(base::TimeDelta::FromHours(1))); | 241 Eq(base::TimeDelta::FromHours(1))); |
| 247 | 242 |
| 248 // Register an observer. | 243 // Register an observer. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 260 | 255 |
| 261 TEST_F(DoodleServiceTest, DisregardsAlreadyExpiredConfigs) { | 256 TEST_F(DoodleServiceTest, DisregardsAlreadyExpiredConfigs) { |
| 262 StrictMock<MockDoodleObserver> observer; | 257 StrictMock<MockDoodleObserver> observer; |
| 263 service()->AddObserver(&observer); | 258 service()->AddObserver(&observer); |
| 264 | 259 |
| 265 ASSERT_THAT(service()->config(), Eq(base::nullopt)); | 260 ASSERT_THAT(service()->config(), Eq(base::nullopt)); |
| 266 | 261 |
| 267 // Load an already-expired config. This should have no effect; in particular | 262 // Load an already-expired config. This should have no effect; in particular |
| 268 // no call to the observer. | 263 // no call to the observer. |
| 269 service()->Refresh(); | 264 service()->Refresh(); |
| 270 DoodleConfig config; | 265 DoodleConfig config = CreateConfig(DoodleType::SIMPLE); |
| 271 config.doodle_type = DoodleType::SIMPLE; | |
| 272 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 266 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 273 base::TimeDelta::FromSeconds(0), config); | 267 base::TimeDelta::FromSeconds(0), config); |
| 274 EXPECT_THAT(service()->config(), Eq(base::nullopt)); | 268 EXPECT_THAT(service()->config(), Eq(base::nullopt)); |
| 275 | 269 |
| 276 // Load a doodle config as usual. Nothing to see here. | 270 // Load a doodle config as usual. Nothing to see here. |
| 277 service()->Refresh(); | 271 service()->Refresh(); |
| 278 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(config))); | 272 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(config))); |
| 279 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 273 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 280 base::TimeDelta::FromHours(1), config); | 274 base::TimeDelta::FromHours(1), config); |
| 281 ASSERT_THAT(service()->config(), Eq(config)); | 275 ASSERT_THAT(service()->config(), Eq(config)); |
| 282 | 276 |
| 283 // Now load an expired config again. The cached one should go away. | 277 // Now load an expired config again. The cached one should go away. |
| 284 service()->Refresh(); | 278 service()->Refresh(); |
| 285 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(base::nullopt))); | 279 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(base::nullopt))); |
| 286 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, | 280 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, |
| 287 base::TimeDelta::FromSeconds(0), config); | 281 base::TimeDelta::FromSeconds(0), config); |
| 288 | 282 |
| 289 // Remove the observer before the service gets destroyed. | 283 // Remove the observer before the service gets destroyed. |
| 290 service()->RemoveObserver(&observer); | 284 service()->RemoveObserver(&observer); |
| 291 } | 285 } |
| 292 | 286 |
| 293 } // namespace doodle | 287 } // namespace doodle |
| OLD | NEW |