1 // Copyright 2014 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.
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
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:
13 // class MyInvalidationServiceTestDelegate {
15 // MyInvalidationServiceTestDelegate() ...
17 // ~MyInvalidationServiceTestDelegate() {
18 // // DestroyInvalidator() may not be explicitly called by tests.
19 // DestroyInvalidator();
22 // // Create the InvalidationService implementation with the given params.
23 // void CreateInvalidationService() {
27 // // Should return the InvalidationService implementation. Only called
28 // // after CreateInvalidator and before DestroyInvalidator.
29 // MyInvalidationService* GetInvalidationService() {
33 // // Destroy the InvalidationService implementation.
34 // void DestroyInvalidationService() {
38 // // The Trigger* functions below should block until the effects of
39 // // the call are visible on the current thread.
41 // // Should cause OnInvalidatorStateChange() to be called on all
42 // // observers of the InvalidationService implementation with the given
44 // void TriggerOnInvalidatorStateChange(InvalidatorState state) {
48 // // Should cause OnIncomingInvalidation() to be called on all
49 // // observers of the InvalidationService implementation with the given
51 // void TriggerOnIncomingInvalidation(
52 // const ObjectIdInvalidationMap& invalidation_map) {
57 // The InvalidationServiceTest test harness will have a member variable of
58 // this delegate type and will call its functions in the various
61 // Then you simply #include this file as well as gtest.h and add the
62 // following statement to my_sync_notifier_unittest.cc:
64 // INSTANTIATE_TYPED_TEST_CASE_P(
65 // MyInvalidationService,
66 // InvalidationServiceTest,
67 // MyInvalidatorTestDelegate);
71 #ifndef COMPONENTS_INVALIDATION_IMPL_INVALIDATION_SERVICE_TEST_TEMPLATE_H_
72 #define COMPONENTS_INVALIDATION_IMPL_INVALIDATION_SERVICE_TEST_TEMPLATE_H_
74 #include "base/basictypes.h"
75 #include "base/compiler_specific.h"
76 #include "components/invalidation/impl/fake_invalidation_handler.h"
77 #include "components/invalidation/impl/object_id_invalidation_map_test_util.h"
78 #include "components/invalidation/public/ack_handle.h"
79 #include "components/invalidation/public/invalidation.h"
80 #include "components/invalidation/public/invalidation_service.h"
81 #include "components/invalidation/public/object_id_invalidation_map.h"
82 #include "google/cacheinvalidation/include/types.h"
83 #include "google/cacheinvalidation/types.pb.h"
84 #include "testing/gtest/include/gtest/gtest.h"
86 template <typename InvalidatorTestDelegate
>
87 class InvalidationServiceTest
: public testing::Test
{
89 InvalidationServiceTest()
90 : id1(ipc::invalidation::ObjectSource::CHROME_SYNC
, "BOOKMARK"),
91 id2(ipc::invalidation::ObjectSource::CHROME_SYNC
, "PREFERENCE"),
92 id3(ipc::invalidation::ObjectSource::CHROME_SYNC
, "AUTOFILL"),
93 id4(ipc::invalidation::ObjectSource::CHROME_PUSH_MESSAGING
,
97 invalidation::InvalidationService
*
98 CreateAndInitializeInvalidationService() {
99 this->delegate_
.CreateInvalidationService();
100 return this->delegate_
.GetInvalidationService();
103 InvalidatorTestDelegate delegate_
;
105 const invalidation::ObjectId id1
;
106 const invalidation::ObjectId id2
;
107 const invalidation::ObjectId id3
;
108 const invalidation::ObjectId id4
;
111 TYPED_TEST_CASE_P(InvalidationServiceTest
);
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();
121 syncer::FakeInvalidationHandler handler
;
123 invalidator
->RegisterInvalidationHandler(&handler
);
125 syncer::ObjectIdInvalidationMap invalidation_map
;
126 invalidation_map
.Insert(syncer::Invalidation::Init(this->id1
, 1, "1"));
127 invalidation_map
.Insert(syncer::Invalidation::Init(this->id2
, 2, "2"));
128 invalidation_map
.Insert(syncer::Invalidation::Init(this->id3
, 3, "3"));
130 // Should be ignored since no IDs are registered to |handler|.
131 this->delegate_
.TriggerOnIncomingInvalidation(invalidation_map
);
132 EXPECT_EQ(0, handler
.GetInvalidationCount());
134 syncer::ObjectIdSet ids
;
135 ids
.insert(this->id1
);
136 ids
.insert(this->id2
);
137 EXPECT_TRUE(invalidator
->UpdateRegisteredInvalidationIds(&handler
, ids
));
139 this->delegate_
.TriggerOnInvalidatorStateChange(
140 syncer::INVALIDATIONS_ENABLED
);
141 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED
, handler
.GetInvalidatorState());
143 syncer::ObjectIdInvalidationMap expected_invalidations
;
144 expected_invalidations
.Insert(syncer::Invalidation::Init(this->id1
, 1, "1"));
145 expected_invalidations
.Insert(syncer::Invalidation::Init(this->id2
, 2, "2"));
147 this->delegate_
.TriggerOnIncomingInvalidation(invalidation_map
);
148 EXPECT_EQ(1, handler
.GetInvalidationCount());
149 EXPECT_THAT(expected_invalidations
, Eq(handler
.GetLastInvalidationMap()));
151 ids
.erase(this->id1
);
152 ids
.insert(this->id3
);
153 EXPECT_TRUE(invalidator
->UpdateRegisteredInvalidationIds(&handler
, ids
));
155 expected_invalidations
= syncer::ObjectIdInvalidationMap();
156 expected_invalidations
.Insert(syncer::Invalidation::Init(this->id2
, 2, "2"));
157 expected_invalidations
.Insert(syncer::Invalidation::Init(this->id3
, 3, "3"));
159 // Removed object IDs should not be notified, newly-added ones should.
160 this->delegate_
.TriggerOnIncomingInvalidation(invalidation_map
);
161 EXPECT_EQ(2, handler
.GetInvalidationCount());
162 EXPECT_THAT(expected_invalidations
, Eq(handler
.GetLastInvalidationMap()));
164 this->delegate_
.TriggerOnInvalidatorStateChange(
165 syncer::TRANSIENT_INVALIDATION_ERROR
);
166 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR
,
167 handler
.GetInvalidatorState());
169 this->delegate_
.TriggerOnInvalidatorStateChange(
170 syncer::INVALIDATIONS_ENABLED
);
171 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED
,
172 handler
.GetInvalidatorState());
174 invalidator
->UnregisterInvalidationHandler(&handler
);
176 // Should be ignored since |handler| isn't registered anymore.
177 this->delegate_
.TriggerOnIncomingInvalidation(invalidation_map
);
178 EXPECT_EQ(2, handler
.GetInvalidationCount());
181 // Register handlers and some IDs for those handlers, register a handler with
182 // no IDs, and register a handler with some IDs but unregister it. Then,
183 // dispatch some invalidations and invalidations. Handlers that are registered
184 // should get invalidations, and the ones that have registered IDs should
185 // receive invalidations for those IDs.
186 TYPED_TEST_P(InvalidationServiceTest
, MultipleHandlers
) {
187 invalidation::InvalidationService
* const invalidator
=
188 this->CreateAndInitializeInvalidationService();
190 syncer::FakeInvalidationHandler handler1
;
191 syncer::FakeInvalidationHandler handler2
;
192 syncer::FakeInvalidationHandler handler3
;
193 syncer::FakeInvalidationHandler handler4
;
195 invalidator
->RegisterInvalidationHandler(&handler1
);
196 invalidator
->RegisterInvalidationHandler(&handler2
);
197 invalidator
->RegisterInvalidationHandler(&handler3
);
198 invalidator
->RegisterInvalidationHandler(&handler4
);
201 syncer::ObjectIdSet ids
;
202 ids
.insert(this->id1
);
203 ids
.insert(this->id2
);
204 EXPECT_TRUE(invalidator
->UpdateRegisteredInvalidationIds(&handler1
, ids
));
208 syncer::ObjectIdSet ids
;
209 ids
.insert(this->id3
);
210 EXPECT_TRUE(invalidator
->UpdateRegisteredInvalidationIds(&handler2
, ids
));
213 // Don't register any IDs for handler3.
216 syncer::ObjectIdSet ids
;
217 ids
.insert(this->id4
);
218 EXPECT_TRUE(invalidator
->UpdateRegisteredInvalidationIds(&handler4
, ids
));
221 invalidator
->UnregisterInvalidationHandler(&handler4
);
223 this->delegate_
.TriggerOnInvalidatorStateChange(
224 syncer::INVALIDATIONS_ENABLED
);
225 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED
, handler1
.GetInvalidatorState());
226 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED
, handler2
.GetInvalidatorState());
227 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED
, handler3
.GetInvalidatorState());
228 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR
,
229 handler4
.GetInvalidatorState());
232 syncer::ObjectIdInvalidationMap invalidation_map
;
233 invalidation_map
.Insert(syncer::Invalidation::Init(this->id1
, 1, "1"));
234 invalidation_map
.Insert(syncer::Invalidation::Init(this->id2
, 2, "2"));
235 invalidation_map
.Insert(syncer::Invalidation::Init(this->id3
, 3, "3"));
236 invalidation_map
.Insert(syncer::Invalidation::Init(this->id4
, 4, "4"));
237 this->delegate_
.TriggerOnIncomingInvalidation(invalidation_map
);
239 syncer::ObjectIdInvalidationMap expected_invalidations
;
240 expected_invalidations
.Insert(
241 syncer::Invalidation::Init(this->id1
, 1, "1"));
242 expected_invalidations
.Insert(
243 syncer::Invalidation::Init(this->id2
, 2, "2"));
245 EXPECT_EQ(1, handler1
.GetInvalidationCount());
246 EXPECT_THAT(expected_invalidations
, Eq(handler1
.GetLastInvalidationMap()));
248 expected_invalidations
= syncer::ObjectIdInvalidationMap();
249 expected_invalidations
.Insert(
250 syncer::Invalidation::Init(this->id3
, 3, "3"));
252 EXPECT_EQ(1, handler2
.GetInvalidationCount());
253 EXPECT_THAT(expected_invalidations
, Eq(handler2
.GetLastInvalidationMap()));
255 EXPECT_EQ(0, handler3
.GetInvalidationCount());
256 EXPECT_EQ(0, handler4
.GetInvalidationCount());
259 this->delegate_
.TriggerOnInvalidatorStateChange(
260 syncer::TRANSIENT_INVALIDATION_ERROR
);
261 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR
,
262 handler1
.GetInvalidatorState());
263 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR
,
264 handler2
.GetInvalidatorState());
265 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR
,
266 handler3
.GetInvalidatorState());
267 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR
,
268 handler4
.GetInvalidatorState());
270 invalidator
->UnregisterInvalidationHandler(&handler3
);
271 invalidator
->UnregisterInvalidationHandler(&handler2
);
272 invalidator
->UnregisterInvalidationHandler(&handler1
);
275 // Multiple registrations by different handlers on the same object ID should
277 TYPED_TEST_P(InvalidationServiceTest
, MultipleRegistrations
) {
278 invalidation::InvalidationService
* const invalidator
=
279 this->CreateAndInitializeInvalidationService();
281 syncer::FakeInvalidationHandler handler1
;
282 syncer::FakeInvalidationHandler handler2
;
284 invalidator
->RegisterInvalidationHandler(&handler1
);
285 invalidator
->RegisterInvalidationHandler(&handler2
);
287 // Registering both handlers for the same ObjectId. First call should succeed,
288 // second should fail.
289 syncer::ObjectIdSet ids
;
290 ids
.insert(this->id1
);
291 EXPECT_TRUE(invalidator
->UpdateRegisteredInvalidationIds(&handler1
, ids
));
292 EXPECT_FALSE(invalidator
->UpdateRegisteredInvalidationIds(&handler2
, ids
));
294 invalidator
->UnregisterInvalidationHandler(&handler2
);
295 invalidator
->UnregisterInvalidationHandler(&handler1
);
298 // Make sure that passing an empty set to UpdateRegisteredInvalidationIds clears
299 // the corresponding entries for the handler.
300 TYPED_TEST_P(InvalidationServiceTest
, EmptySetUnregisters
) {
301 invalidation::InvalidationService
* const invalidator
=
302 this->CreateAndInitializeInvalidationService();
304 syncer::FakeInvalidationHandler handler1
;
307 syncer::FakeInvalidationHandler handler2
;
309 invalidator
->RegisterInvalidationHandler(&handler1
);
310 invalidator
->RegisterInvalidationHandler(&handler2
);
313 syncer::ObjectIdSet ids
;
314 ids
.insert(this->id1
);
315 ids
.insert(this->id2
);
316 EXPECT_TRUE(invalidator
->UpdateRegisteredInvalidationIds(&handler1
, ids
));
320 syncer::ObjectIdSet ids
;
321 ids
.insert(this->id3
);
322 EXPECT_TRUE(invalidator
->UpdateRegisteredInvalidationIds(&handler2
, ids
));
325 // Unregister the IDs for the first observer. It should not receive any
326 // further invalidations.
327 EXPECT_TRUE(invalidator
->UpdateRegisteredInvalidationIds(
328 &handler1
, syncer::ObjectIdSet()));
330 this->delegate_
.TriggerOnInvalidatorStateChange(
331 syncer::INVALIDATIONS_ENABLED
);
332 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED
, handler1
.GetInvalidatorState());
333 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED
, handler2
.GetInvalidatorState());
336 syncer::ObjectIdInvalidationMap invalidation_map
;
337 invalidation_map
.Insert(syncer::Invalidation::Init(this->id1
, 1, "1"));
338 invalidation_map
.Insert(syncer::Invalidation::Init(this->id2
, 2, "2"));
339 invalidation_map
.Insert(syncer::Invalidation::Init(this->id3
, 3, "3"));
340 this->delegate_
.TriggerOnIncomingInvalidation(invalidation_map
);
341 EXPECT_EQ(0, handler1
.GetInvalidationCount());
342 EXPECT_EQ(1, handler2
.GetInvalidationCount());
345 this->delegate_
.TriggerOnInvalidatorStateChange(
346 syncer::TRANSIENT_INVALIDATION_ERROR
);
347 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR
,
348 handler1
.GetInvalidatorState());
349 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR
,
350 handler2
.GetInvalidatorState());
352 invalidator
->UnregisterInvalidationHandler(&handler2
);
353 invalidator
->UnregisterInvalidationHandler(&handler1
);
358 // A FakeInvalidationHandler that is "bound" to a specific
359 // InvalidationService. This is for cross-referencing state information with
360 // the bound InvalidationService.
361 class BoundFakeInvalidationHandler
: public syncer::FakeInvalidationHandler
{
363 explicit BoundFakeInvalidationHandler(
364 const invalidation::InvalidationService
& invalidator
);
365 ~BoundFakeInvalidationHandler() override
;
367 // Returns the last return value of GetInvalidatorState() on the
368 // bound invalidator from the last time the invalidator state
370 syncer::InvalidatorState
GetLastRetrievedState() const;
372 // InvalidationHandler implementation.
373 void OnInvalidatorStateChange(syncer::InvalidatorState state
) override
;
376 const invalidation::InvalidationService
& invalidator_
;
377 syncer::InvalidatorState last_retrieved_state_
;
379 DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler
);
382 } // namespace internal
384 TYPED_TEST_P(InvalidationServiceTest
, GetInvalidatorStateAlwaysCurrent
) {
385 invalidation::InvalidationService
* const invalidator
=
386 this->CreateAndInitializeInvalidationService();
388 internal::BoundFakeInvalidationHandler
handler(*invalidator
);
389 invalidator
->RegisterInvalidationHandler(&handler
);
391 this->delegate_
.TriggerOnInvalidatorStateChange(
392 syncer::INVALIDATIONS_ENABLED
);
393 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED
, handler
.GetInvalidatorState());
394 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED
, handler
.GetLastRetrievedState());
396 this->delegate_
.TriggerOnInvalidatorStateChange(
397 syncer::TRANSIENT_INVALIDATION_ERROR
);
398 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR
,
399 handler
.GetInvalidatorState());
400 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR
,
401 handler
.GetLastRetrievedState());
403 invalidator
->UnregisterInvalidationHandler(&handler
);
406 REGISTER_TYPED_TEST_CASE_P(InvalidationServiceTest
,
409 MultipleRegistrations
,
411 GetInvalidatorStateAlwaysCurrent
);
413 #endif // COMPONENTS_INVALIDATION_IMPL_INVALIDATION_SERVICE_TEST_TEMPLATE_H_