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

Side by Side Diff: chrome/browser/invalidation/invalidation_service_test_template.h

Issue 17911005: Merge 208347 "Revert 208315 "Make use of InvalidationService"" (Closed) Base URL: svn://svn.chromium.org/chrome/branches/1547/src/
Patch Set: Created 7 years, 5 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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 // This class defines tests that implementations of InvalidationService should
6 // pass in order to be conformant. Here's how you use it to test your
7 // implementation.
8 //
9 // Say your class is called MyInvalidationService. Then you need to define a
10 // class called MyInvalidationServiceTestDelegate in
11 // my_invalidation_frontend_unittest.cc like this:
12 //
13 // class MyInvalidationServiceTestDelegate {
14 // public:
15 // MyInvalidationServiceTestDelegate() ...
16 //
17 // ~MyInvalidationServiceTestDelegate() {
18 // // DestroyInvalidator() may not be explicitly called by tests.
19 // DestroyInvalidator();
20 // }
21 //
22 // // Create the InvalidationService implementation with the given params.
23 // void CreateInvalidationService() {
24 // ...
25 // }
26 //
27 // // Should return the InvalidationService implementation. Only called
28 // // after CreateInvalidator and before DestroyInvalidator.
29 // MyInvalidationService* GetInvalidationService() {
30 // ...
31 // }
32 //
33 // // Destroy the InvalidationService implementation.
34 // void DestroyInvalidationService() {
35 // ...
36 // }
37 //
38 // // The Trigger* functions below should block until the effects of
39 // // the call are visible on the current thread.
40 //
41 // // Should cause OnInvalidatorStateChange() to be called on all
42 // // observers of the InvalidationService implementation with the given
43 // // parameters.
44 // void TriggerOnInvalidatorStateChange(InvalidatorState state) {
45 // ...
46 // }
47 //
48 // // Should cause OnIncomingInvalidation() to be called on all
49 // // observers of the InvalidationService implementation with the given
50 // // parameters.
51 // void TriggerOnIncomingInvalidation(
52 // const ObjectIdInvalidationMap& invalidation_map) {
53 // ...
54 // }
55 // };
56 //
57 // The InvalidationServiceTest test harness will have a member variable of
58 // this delegate type and will call its functions in the various
59 // tests.
60 //
61 // Then you simply #include this file as well as gtest.h and add the
62 // following statement to my_sync_notifier_unittest.cc:
63 //
64 // INSTANTIATE_TYPED_TEST_CASE_P(
65 // MyInvalidationService,
66 // InvalidationServiceTest,
67 // MyInvalidatorTestDelegate);
68 //
69 // Easy!
70
71 #ifndef CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_
72 #define CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_
73
74 #include "base/basictypes.h"
75 #include "base/compiler_specific.h"
76 #include "chrome/browser/invalidation/invalidation_service.h"
77 #include "google/cacheinvalidation/include/types.h"
78 #include "google/cacheinvalidation/types.pb.h"
79 #include "sync/notifier/fake_invalidation_handler.h"
80 #include "sync/notifier/object_id_invalidation_map.h"
81 #include "sync/notifier/object_id_invalidation_map_test_util.h"
82 #include "testing/gtest/include/gtest/gtest.h"
83
84 template <typename InvalidatorTestDelegate>
85 class InvalidationServiceTest : public testing::Test {
86 protected:
87 // Note: The IDs defined below must be valid. Otherwise they won't make it
88 // through the round-trip to ModelTypeInvalidationMap and back that the
89 // AndroidInvalidation test requires.
90 InvalidationServiceTest()
91 : id1(ipc::invalidation::ObjectSource::CHROME_SYNC, "BOOKMARK"),
92 id2(ipc::invalidation::ObjectSource::CHROME_SYNC, "PREFERENCE"),
93 id3(ipc::invalidation::ObjectSource::CHROME_SYNC, "AUTOFILL"),
94 id4(ipc::invalidation::ObjectSource::CHROME_SYNC, "EXPERIMENTS") {
95 }
96
97 invalidation::InvalidationService*
98 CreateAndInitializeInvalidationService() {
99 this->delegate_.CreateInvalidationService();
100 return this->delegate_.GetInvalidationService();
101 }
102
103 InvalidatorTestDelegate delegate_;
104
105 const invalidation::ObjectId id1;
106 const invalidation::ObjectId id2;
107 const invalidation::ObjectId id3;
108 const invalidation::ObjectId id4;
109 };
110
111 TYPED_TEST_CASE_P(InvalidationServiceTest);
112
113 // Initialize the invalidator, register a handler, register some IDs for that
114 // handler, and then unregister the handler, dispatching invalidations in
115 // between. The handler should only see invalidations when its registered and
116 // its IDs are registered.
117 TYPED_TEST_P(InvalidationServiceTest, Basic) {
118 invalidation::InvalidationService* const invalidator =
119 this->CreateAndInitializeInvalidationService();
120
121 syncer::FakeInvalidationHandler handler;
122
123 invalidator->RegisterInvalidationHandler(&handler);
124
125 syncer::ObjectIdInvalidationMap states;
126 states[this->id1].payload = "1";
127 states[this->id2].payload = "2";
128 states[this->id3].payload = "3";
129
130 // Should be ignored since no IDs are registered to |handler|.
131 this->delegate_.TriggerOnIncomingInvalidation(states);
132 EXPECT_EQ(0, handler.GetInvalidationCount());
133
134 syncer::ObjectIdSet ids;
135 ids.insert(this->id1);
136 ids.insert(this->id2);
137 invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
138
139 this->delegate_.TriggerOnInvalidatorStateChange(
140 syncer::INVALIDATIONS_ENABLED);
141 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
142
143 syncer::ObjectIdInvalidationMap expected_states;
144 expected_states[this->id1].payload = "1";
145 expected_states[this->id2].payload = "2";
146
147 this->delegate_.TriggerOnIncomingInvalidation(states);
148 EXPECT_EQ(1, handler.GetInvalidationCount());
149 EXPECT_THAT(expected_states, Eq(handler.GetLastInvalidationMap()));
150
151 ids.erase(this->id1);
152 ids.insert(this->id3);
153 invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
154
155 expected_states.erase(this->id1);
156 expected_states[this->id3].payload = "3";
157
158 // Removed object IDs should not be notified, newly-added ones should.
159 this->delegate_.TriggerOnIncomingInvalidation(states);
160 EXPECT_EQ(2, handler.GetInvalidationCount());
161 EXPECT_THAT(expected_states, Eq(handler.GetLastInvalidationMap()));
162
163 this->delegate_.TriggerOnInvalidatorStateChange(
164 syncer::TRANSIENT_INVALIDATION_ERROR);
165 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
166 handler.GetInvalidatorState());
167
168 this->delegate_.TriggerOnInvalidatorStateChange(
169 syncer::INVALIDATIONS_ENABLED);
170 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED,
171 handler.GetInvalidatorState());
172
173 invalidator->UnregisterInvalidationHandler(&handler);
174
175 // Should be ignored since |handler| isn't registered anymore.
176 this->delegate_.TriggerOnIncomingInvalidation(states);
177 EXPECT_EQ(2, handler.GetInvalidationCount());
178 }
179
180 // Register handlers and some IDs for those handlers, register a handler with
181 // no IDs, and register a handler with some IDs but unregister it. Then,
182 // dispatch some invalidations and invalidations. Handlers that are registered
183 // should get invalidations, and the ones that have registered IDs should
184 // receive invalidations for those IDs.
185 TYPED_TEST_P(InvalidationServiceTest, MultipleHandlers) {
186 invalidation::InvalidationService* const invalidator =
187 this->CreateAndInitializeInvalidationService();
188
189 syncer::FakeInvalidationHandler handler1;
190 syncer::FakeInvalidationHandler handler2;
191 syncer::FakeInvalidationHandler handler3;
192 syncer::FakeInvalidationHandler handler4;
193
194 invalidator->RegisterInvalidationHandler(&handler1);
195 invalidator->RegisterInvalidationHandler(&handler2);
196 invalidator->RegisterInvalidationHandler(&handler3);
197 invalidator->RegisterInvalidationHandler(&handler4);
198
199 {
200 syncer::ObjectIdSet ids;
201 ids.insert(this->id1);
202 ids.insert(this->id2);
203 invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
204 }
205
206 {
207 syncer::ObjectIdSet ids;
208 ids.insert(this->id3);
209 invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
210 }
211
212 // Don't register any IDs for handler3.
213
214 {
215 syncer::ObjectIdSet ids;
216 ids.insert(this->id4);
217 invalidator->UpdateRegisteredInvalidationIds(&handler4, ids);
218 }
219
220 invalidator->UnregisterInvalidationHandler(&handler4);
221
222 this->delegate_.TriggerOnInvalidatorStateChange(
223 syncer::INVALIDATIONS_ENABLED);
224 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
225 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
226 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler3.GetInvalidatorState());
227 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
228 handler4.GetInvalidatorState());
229
230 {
231 syncer::ObjectIdInvalidationMap states;
232 states[this->id1].payload = "1";
233 states[this->id2].payload = "2";
234 states[this->id3].payload = "3";
235 states[this->id4].payload = "4";
236 this->delegate_.TriggerOnIncomingInvalidation(states);
237
238 syncer::ObjectIdInvalidationMap expected_states;
239 expected_states[this->id1].payload = "1";
240 expected_states[this->id2].payload = "2";
241
242 EXPECT_EQ(1, handler1.GetInvalidationCount());
243 EXPECT_THAT(expected_states, Eq(handler1.GetLastInvalidationMap()));
244
245 expected_states.clear();
246 expected_states[this->id3].payload = "3";
247
248 EXPECT_EQ(1, handler2.GetInvalidationCount());
249 EXPECT_THAT(expected_states, Eq(handler2.GetLastInvalidationMap()));
250
251 EXPECT_EQ(0, handler3.GetInvalidationCount());
252 EXPECT_EQ(0, handler4.GetInvalidationCount());
253 }
254
255 this->delegate_.TriggerOnInvalidatorStateChange(
256 syncer::TRANSIENT_INVALIDATION_ERROR);
257 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
258 handler1.GetInvalidatorState());
259 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
260 handler2.GetInvalidatorState());
261 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
262 handler3.GetInvalidatorState());
263 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
264 handler4.GetInvalidatorState());
265
266 invalidator->UnregisterInvalidationHandler(&handler3);
267 invalidator->UnregisterInvalidationHandler(&handler2);
268 invalidator->UnregisterInvalidationHandler(&handler1);
269 }
270
271 // Make sure that passing an empty set to UpdateRegisteredInvalidationIds clears
272 // the corresponding entries for the handler.
273 TYPED_TEST_P(InvalidationServiceTest, EmptySetUnregisters) {
274 invalidation::InvalidationService* const invalidator =
275 this->CreateAndInitializeInvalidationService();
276
277 syncer::FakeInvalidationHandler handler1;
278
279 // Control observer.
280 syncer::FakeInvalidationHandler handler2;
281
282 invalidator->RegisterInvalidationHandler(&handler1);
283 invalidator->RegisterInvalidationHandler(&handler2);
284
285 {
286 syncer::ObjectIdSet ids;
287 ids.insert(this->id1);
288 ids.insert(this->id2);
289 invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
290 }
291
292 {
293 syncer::ObjectIdSet ids;
294 ids.insert(this->id3);
295 invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
296 }
297
298 // Unregister the IDs for the first observer. It should not receive any
299 // further invalidations.
300 invalidator->UpdateRegisteredInvalidationIds(&handler1,
301 syncer::ObjectIdSet());
302
303 this->delegate_.TriggerOnInvalidatorStateChange(
304 syncer::INVALIDATIONS_ENABLED);
305 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
306 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
307
308 {
309 syncer::ObjectIdInvalidationMap states;
310 states[this->id1].payload = "1";
311 states[this->id2].payload = "2";
312 states[this->id3].payload = "3";
313 this->delegate_.TriggerOnIncomingInvalidation(states);
314 EXPECT_EQ(0, handler1.GetInvalidationCount());
315 EXPECT_EQ(1, handler2.GetInvalidationCount());
316 }
317
318 this->delegate_.TriggerOnInvalidatorStateChange(
319 syncer::TRANSIENT_INVALIDATION_ERROR);
320 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
321 handler1.GetInvalidatorState());
322 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
323 handler2.GetInvalidatorState());
324
325 invalidator->UnregisterInvalidationHandler(&handler2);
326 invalidator->UnregisterInvalidationHandler(&handler1);
327 }
328
329 namespace internal {
330
331 // A FakeInvalidationHandler that is "bound" to a specific
332 // InvalidationService. This is for cross-referencing state information with
333 // the bound InvalidationService.
334 class BoundFakeInvalidationHandler : public syncer::FakeInvalidationHandler {
335 public:
336 explicit BoundFakeInvalidationHandler(
337 const invalidation::InvalidationService& invalidator);
338 virtual ~BoundFakeInvalidationHandler();
339
340 // Returns the last return value of GetInvalidatorState() on the
341 // bound invalidator from the last time the invalidator state
342 // changed.
343 syncer::InvalidatorState GetLastRetrievedState() const;
344
345 // InvalidationHandler implementation.
346 virtual void OnInvalidatorStateChange(
347 syncer::InvalidatorState state) OVERRIDE;
348
349 private:
350 const invalidation::InvalidationService& invalidator_;
351 syncer::InvalidatorState last_retrieved_state_;
352
353 DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler);
354 };
355
356 } // namespace internal
357
358 TYPED_TEST_P(InvalidationServiceTest, GetInvalidatorStateAlwaysCurrent) {
359 invalidation::InvalidationService* const invalidator =
360 this->CreateAndInitializeInvalidationService();
361
362 internal::BoundFakeInvalidationHandler handler(*invalidator);
363 invalidator->RegisterInvalidationHandler(&handler);
364
365 this->delegate_.TriggerOnInvalidatorStateChange(
366 syncer::INVALIDATIONS_ENABLED);
367 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
368 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetLastRetrievedState());
369
370 this->delegate_.TriggerOnInvalidatorStateChange(
371 syncer::TRANSIENT_INVALIDATION_ERROR);
372 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
373 handler.GetInvalidatorState());
374 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
375 handler.GetLastRetrievedState());
376
377 invalidator->UnregisterInvalidationHandler(&handler);
378 }
379
380 REGISTER_TYPED_TEST_CASE_P(InvalidationServiceTest,
381 Basic, MultipleHandlers, EmptySetUnregisters,
382 GetInvalidatorStateAlwaysCurrent);
383
384 #endif // CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698