Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: components/doodle/doodle_service_unittest.cc

Issue 2729923003: [Doodle] Automatically expire Doodles after their TTL (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/test/simple_test_tick_clock.h"
15 #include "base/test/test_simple_task_runner.h"
13 #include "base/time/time.h" 16 #include "base/time/time.h"
14 #include "testing/gmock/include/gmock/gmock.h" 17 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
16 19
17 using testing::Eq; 20 using testing::Eq;
18 using testing::StrictMock; 21 using testing::StrictMock;
19 22
20 namespace doodle { 23 namespace doodle {
21 24
22 namespace { 25 namespace {
(...skipping 25 matching lines...) Expand all
48 class MockDoodleObserver : public DoodleService::Observer { 51 class MockDoodleObserver : public DoodleService::Observer {
49 public: 52 public:
50 MOCK_METHOD1(OnDoodleConfigUpdated, 53 MOCK_METHOD1(OnDoodleConfigUpdated,
51 void(const base::Optional<DoodleConfig>&)); 54 void(const base::Optional<DoodleConfig>&));
52 }; 55 };
53 56
54 } // namespace 57 } // namespace
55 58
56 class DoodleServiceTest : public testing::Test { 59 class DoodleServiceTest : public testing::Test {
57 public: 60 public:
58 DoodleServiceTest() : fetcher_(nullptr) { 61 DoodleServiceTest() : fetcher_(nullptr) {
fhorschig 2017/03/02 20:12:59 expiry_timer_(nullptr)?
Marc Treib 2017/03/03 10:06:58 Indeed, thanks!
62 tick_clock_.SetNowTicks(base::TimeTicks::UnixEpoch() +
63 base::TimeDelta::FromDays(5000));
64 task_runner_ = new base::TestSimpleTaskRunner();
fhorschig 2017/03/02 20:12:59 any reason you don't initialize this earlier? (ini
Marc Treib 2017/03/03 10:06:57 Nope. Done.
65
66 auto expiry_timer = base::MakeUnique<base::OneShotTimer>(&tick_clock_);
67 expiry_timer->SetTaskRunner(task_runner_);
68 expiry_timer_ = expiry_timer.get();
69
59 auto fetcher = base::MakeUnique<FakeDoodleFetcher>(); 70 auto fetcher = base::MakeUnique<FakeDoodleFetcher>();
60 fetcher_ = fetcher.get(); 71 fetcher_ = fetcher.get();
61 service_ = base::MakeUnique<DoodleService>(std::move(fetcher)); 72
73 service_ = base::MakeUnique<DoodleService>(std::move(fetcher),
74 std::move(expiry_timer));
62 } 75 }
63 76
64 DoodleService* service() { return service_.get(); } 77 DoodleService* service() { return service_.get(); }
65 FakeDoodleFetcher* fetcher() { return fetcher_; } 78 FakeDoodleFetcher* fetcher() { return fetcher_; }
66 79
67 base::TimeDelta some_time() const { return base::TimeDelta::FromHours(1); } 80 base::TestSimpleTaskRunner* task_runner() { return task_runner_.get(); }
81
82 base::TimeDelta SomeTime() const { return base::TimeDelta::FromHours(1); }
fhorschig 2017/03/02 20:12:59 When it was lower_case, it used to be pretty clear
Marc Treib 2017/03/03 10:06:58 I don't know what you mean by "implementation deta
68 83
69 private: 84 private:
85 // Weak, owned by the service.
86 FakeDoodleFetcher* fetcher_;
87
88 base::SimpleTestTickClock tick_clock_;
89 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
90 // Weak, owned by the service.
91 base::OneShotTimer* expiry_timer_;
fhorschig 2017/03/02 20:12:59 nitty nit: Would be nice to visually group the wea
Marc Treib 2017/03/03 10:06:58 To me, the "logical" grouping (clock + task_runner
92
70 std::unique_ptr<DoodleService> service_; 93 std::unique_ptr<DoodleService> service_;
71 FakeDoodleFetcher* fetcher_;
72 }; 94 };
73 95
74 TEST_F(DoodleServiceTest, FetchesConfigOnRefresh) { 96 TEST_F(DoodleServiceTest, FetchesConfigOnRefresh) {
75 ASSERT_THAT(service()->config(), Eq(base::nullopt)); 97 ASSERT_THAT(service()->config(), Eq(base::nullopt));
76 98
77 // Request a refresh of the doodle config. 99 // Request a refresh of the doodle config.
78 service()->Refresh(); 100 service()->Refresh();
79 // The request should have arrived at the fetcher. 101 // The request should have arrived at the fetcher.
80 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); 102 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u));
81 103
82 // Serve it (with an arbitrary config). 104 // Serve it (with an arbitrary config).
83 DoodleConfig config; 105 DoodleConfig config;
84 config.doodle_type = DoodleType::SIMPLE; 106 config.doodle_type = DoodleType::SIMPLE;
85 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, some_time(), config); 107 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, SomeTime(), config);
86 108
87 // The config should be available. 109 // The config should be available.
88 EXPECT_THAT(service()->config(), Eq(config)); 110 EXPECT_THAT(service()->config(), Eq(config));
89 111
90 // Request a refresh again. 112 // Request a refresh again.
91 service()->Refresh(); 113 service()->Refresh();
92 // The request should have arrived at the fetcher again. 114 // The request should have arrived at the fetcher again.
93 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); 115 EXPECT_THAT(fetcher()->num_pending_callbacks(), Eq(1u));
94 116
95 // Serve it with a different config. 117 // Serve it with a different config.
96 DoodleConfig other_config; 118 DoodleConfig other_config;
97 other_config.doodle_type = DoodleType::SLIDESHOW; 119 other_config.doodle_type = DoodleType::SLIDESHOW;
98 DCHECK(config != other_config); 120 DCHECK(config != other_config);
99 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, some_time(), 121 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, SomeTime(),
100 other_config); 122 other_config);
101 123
102 // The config should have been updated. 124 // The config should have been updated.
103 EXPECT_THAT(service()->config(), Eq(other_config)); 125 EXPECT_THAT(service()->config(), Eq(other_config));
104 } 126 }
105 127
106 TEST_F(DoodleServiceTest, CallsObserverOnConfigReceived) { 128 TEST_F(DoodleServiceTest, CallsObserverOnConfigReceived) {
107 StrictMock<MockDoodleObserver> observer; 129 StrictMock<MockDoodleObserver> observer;
108 service()->AddObserver(&observer); 130 service()->AddObserver(&observer);
109 131
110 ASSERT_THAT(service()->config(), Eq(base::nullopt)); 132 ASSERT_THAT(service()->config(), Eq(base::nullopt));
111 133
112 // Request a refresh of the doodle config. 134 // Request a refresh of the doodle config.
113 service()->Refresh(); 135 service()->Refresh();
114 // The request should have arrived at the fetcher. 136 // The request should have arrived at the fetcher.
115 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); 137 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u));
116 138
117 // Serve it (with an arbitrary config). The observer should get notified. 139 // Serve it (with an arbitrary config). The observer should get notified.
118 DoodleConfig config; 140 DoodleConfig config;
119 config.doodle_type = DoodleType::SIMPLE; 141 config.doodle_type = DoodleType::SIMPLE;
120 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(config))); 142 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(config)));
121 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, some_time(), config); 143 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, SomeTime(), config);
122 144
123 // Remove the observer before the service gets destroyed. 145 // Remove the observer before the service gets destroyed.
124 service()->RemoveObserver(&observer); 146 service()->RemoveObserver(&observer);
125 } 147 }
126 148
127 TEST_F(DoodleServiceTest, CallsObserverOnConfigRemoved) { 149 TEST_F(DoodleServiceTest, CallsObserverOnConfigRemoved) {
128 // Load some doodle config. 150 // Load some doodle config.
129 service()->Refresh(); 151 service()->Refresh();
130 DoodleConfig config; 152 DoodleConfig config;
131 config.doodle_type = DoodleType::SIMPLE; 153 config.doodle_type = DoodleType::SIMPLE;
132 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, some_time(), config); 154 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, SomeTime(), config);
133 ASSERT_THAT(service()->config(), Eq(config)); 155 ASSERT_THAT(service()->config(), Eq(config));
134 156
135 // Register an observer and request a refresh. 157 // Register an observer and request a refresh.
136 StrictMock<MockDoodleObserver> observer; 158 StrictMock<MockDoodleObserver> observer;
137 service()->AddObserver(&observer); 159 service()->AddObserver(&observer);
138 service()->Refresh(); 160 service()->Refresh();
139 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); 161 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u));
140 162
141 // Serve the request with an empty doodle config. The observer should get 163 // Serve the request with an empty doodle config. The observer should get
142 // notified. 164 // notified.
143 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(base::nullopt))); 165 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(base::nullopt)));
144 fetcher()->ServeAllCallbacks(DoodleState::NO_DOODLE, base::TimeDelta(), 166 fetcher()->ServeAllCallbacks(DoodleState::NO_DOODLE, base::TimeDelta(),
145 base::nullopt); 167 base::nullopt);
146 168
147 // Remove the observer before the service gets destroyed. 169 // Remove the observer before the service gets destroyed.
148 service()->RemoveObserver(&observer); 170 service()->RemoveObserver(&observer);
149 } 171 }
150 172
151 TEST_F(DoodleServiceTest, CallsObserverOnConfigUpdated) { 173 TEST_F(DoodleServiceTest, CallsObserverOnConfigUpdated) {
152 // Load some doodle config. 174 // Load some doodle config.
153 service()->Refresh(); 175 service()->Refresh();
154 DoodleConfig config; 176 DoodleConfig config;
155 config.doodle_type = DoodleType::SIMPLE; 177 config.doodle_type = DoodleType::SIMPLE;
156 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, some_time(), config); 178 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, SomeTime(), config);
157 ASSERT_THAT(service()->config(), Eq(config)); 179 ASSERT_THAT(service()->config(), Eq(config));
158 180
159 // Register an observer and request a refresh. 181 // Register an observer and request a refresh.
160 StrictMock<MockDoodleObserver> observer; 182 StrictMock<MockDoodleObserver> observer;
161 service()->AddObserver(&observer); 183 service()->AddObserver(&observer);
162 service()->Refresh(); 184 service()->Refresh();
163 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); 185 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u));
164 186
165 // Serve the request with a different doodle config. The observer should get 187 // Serve the request with a different doodle config. The observer should get
166 // notified. 188 // notified.
167 DoodleConfig other_config; 189 DoodleConfig other_config;
168 other_config.doodle_type = DoodleType::SLIDESHOW; 190 other_config.doodle_type = DoodleType::SLIDESHOW;
169 DCHECK(config != other_config); 191 DCHECK(config != other_config);
170 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(other_config))); 192 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(other_config)));
171 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, some_time(), 193 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, SomeTime(),
172 other_config); 194 other_config);
173 195
174 // Remove the observer before the service gets destroyed. 196 // Remove the observer before the service gets destroyed.
175 service()->RemoveObserver(&observer); 197 service()->RemoveObserver(&observer);
176 } 198 }
177 199
178 TEST_F(DoodleServiceTest, DoesNotCallObserverWhenConfigEquivalent) { 200 TEST_F(DoodleServiceTest, DoesNotCallObserverIfConfigEquivalent) {
179 // Load some doodle config. 201 // Load some doodle config.
180 service()->Refresh(); 202 service()->Refresh();
181 DoodleConfig config; 203 DoodleConfig config;
182 config.doodle_type = DoodleType::SIMPLE; 204 config.doodle_type = DoodleType::SIMPLE;
183 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, some_time(), config); 205 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, SomeTime(), config);
184 ASSERT_THAT(service()->config(), Eq(config)); 206 ASSERT_THAT(service()->config(), Eq(config));
185 207
186 // Register an observer and request a refresh. 208 // Register an observer and request a refresh.
187 StrictMock<MockDoodleObserver> observer; 209 StrictMock<MockDoodleObserver> observer;
188 service()->AddObserver(&observer); 210 service()->AddObserver(&observer);
189 service()->Refresh(); 211 service()->Refresh();
190 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u)); 212 ASSERT_THAT(fetcher()->num_pending_callbacks(), Eq(1u));
191 213
192 // Serve the request with an equivalent doodle config. The observer should 214 // Serve the request with an equivalent doodle config. The observer should
193 // *not* get notified. 215 // *not* get notified.
194 DoodleConfig equivalent_config; 216 DoodleConfig equivalent_config;
195 equivalent_config.doodle_type = DoodleType::SIMPLE; 217 equivalent_config.doodle_type = DoodleType::SIMPLE;
196 DCHECK(config == equivalent_config); 218 DCHECK(config == equivalent_config);
197 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, some_time(), 219 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, SomeTime(),
198 equivalent_config); 220 equivalent_config);
199 221
200 // Remove the observer before the service gets destroyed. 222 // Remove the observer before the service gets destroyed.
201 service()->RemoveObserver(&observer); 223 service()->RemoveObserver(&observer);
202 } 224 }
203 225
226 TEST_F(DoodleServiceTest, CallsObserverWhenConfigExpires) {
227 // Load some doodle config.
228 service()->Refresh();
229 DoodleConfig config;
230 config.doodle_type = DoodleType::SIMPLE;
231 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, SomeTime(), config);
232 ASSERT_THAT(service()->config(), Eq(config));
233
234 // Make sure the task arrived at the timer's task runner.
235 ASSERT_THAT(task_runner()->NumPendingTasks(), Eq(1u));
236 EXPECT_THAT(task_runner()->NextPendingTaskDelay(), Eq(SomeTime()));
237
238 // Register an observer.
239 StrictMock<MockDoodleObserver> observer;
240 service()->AddObserver(&observer);
241
242 // Run the expiry task. The observer should get notified that there's no
243 // config anymore.
244 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(base::nullopt)));
245 task_runner()->RunPendingTasks();
Marc Treib 2017/03/02 18:51:02 So, this is the famous and amazing TestSimpleTaskR
fhorschig 2017/03/02 20:12:59 What about TestMockTimeTaskRunner. As far as I kno
Marc Treib 2017/03/03 10:06:58 D'oh, forgot about that one again. Thanks for the
246
247 // Remove the observer before the service gets destroyed.
248 service()->RemoveObserver(&observer);
249 }
250
251 TEST_F(DoodleServiceTest, DisregardsAlreadyExpiredConfigs) {
252 StrictMock<MockDoodleObserver> observer;
253 service()->AddObserver(&observer);
254
255 ASSERT_THAT(service()->config(), Eq(base::nullopt));
256
257 // Load an already-expired config. This should have no effect; in particular
258 // no call to the observer.
259 service()->Refresh();
260 DoodleConfig config;
261 config.doodle_type = DoodleType::SIMPLE;
262 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE,
263 base::TimeDelta::FromSeconds(0), config);
264 EXPECT_THAT(service()->config(), Eq(base::nullopt));
265
266 // Load a doodle config as usual. Nothing to see here.
267 service()->Refresh();
268 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(config)));
269 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE, SomeTime(), config);
270 ASSERT_THAT(service()->config(), Eq(config));
271
272 // Now load an expired config again. The cached one should go away.
273 service()->Refresh();
274 EXPECT_CALL(observer, OnDoodleConfigUpdated(Eq(base::nullopt)));
275 fetcher()->ServeAllCallbacks(DoodleState::AVAILABLE,
276 base::TimeDelta::FromSeconds(0), config);
277
278 // Remove the observer before the service gets destroyed.
279 service()->RemoveObserver(&observer);
280 }
281
204 } // namespace doodle 282 } // namespace doodle
OLDNEW
« components/doodle/doodle_service.cc ('K') | « components/doodle/doodle_service.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698