blob: dc4a8419c03b34adcec3ed5247ee355a427f60f8 [file] [log] [blame]
[email protected]f7deb90a2014-06-12 22:50:541// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]e85797c2013-05-10 19:26:162// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]dbbec3a2013-06-29 01:45:095// This class defines tests that implementations of InvalidationService should
[email protected]e85797c2013-05-10 19:26:166// pass in order to be conformant. Here's how you use it to test your
7// implementation.
8//
[email protected]dbbec3a2013-06-29 01:45:099// Say your class is called MyInvalidationService. Then you need to define a
10// class called MyInvalidationServiceTestDelegate in
[email protected]e85797c2013-05-10 19:26:1611// my_invalidation_frontend_unittest.cc like this:
12//
[email protected]dbbec3a2013-06-29 01:45:0913// class MyInvalidationServiceTestDelegate {
[email protected]e85797c2013-05-10 19:26:1614// public:
[email protected]dbbec3a2013-06-29 01:45:0915// MyInvalidationServiceTestDelegate() ...
[email protected]e85797c2013-05-10 19:26:1616//
[email protected]dbbec3a2013-06-29 01:45:0917// ~MyInvalidationServiceTestDelegate() {
[email protected]e85797c2013-05-10 19:26:1618// // DestroyInvalidator() may not be explicitly called by tests.
19// DestroyInvalidator();
20// }
21//
[email protected]dbbec3a2013-06-29 01:45:0922// // Create the InvalidationService implementation with the given params.
23// void CreateInvalidationService() {
[email protected]e85797c2013-05-10 19:26:1624// ...
25// }
26//
[email protected]dbbec3a2013-06-29 01:45:0927// // Should return the InvalidationService implementation. Only called
[email protected]e85797c2013-05-10 19:26:1628// // after CreateInvalidator and before DestroyInvalidator.
[email protected]dbbec3a2013-06-29 01:45:0929// MyInvalidationService* GetInvalidationService() {
[email protected]e85797c2013-05-10 19:26:1630// ...
31// }
32//
[email protected]dbbec3a2013-06-29 01:45:0933// // Destroy the InvalidationService implementation.
34// void DestroyInvalidationService() {
[email protected]e85797c2013-05-10 19:26:1635// ...
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
[email protected]dbbec3a2013-06-29 01:45:0942// // observers of the InvalidationService implementation with the given
[email protected]e85797c2013-05-10 19:26:1643// // parameters.
44// void TriggerOnInvalidatorStateChange(InvalidatorState state) {
45// ...
46// }
47//
48// // Should cause OnIncomingInvalidation() to be called on all
[email protected]dbbec3a2013-06-29 01:45:0949// // observers of the InvalidationService implementation with the given
[email protected]e85797c2013-05-10 19:26:1650// // parameters.
51// void TriggerOnIncomingInvalidation(
52// const ObjectIdInvalidationMap& invalidation_map) {
53// ...
54// }
55// };
56//
[email protected]dbbec3a2013-06-29 01:45:0957// The InvalidationServiceTest test harness will have a member variable of
[email protected]e85797c2013-05-10 19:26:1658// 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(
[email protected]dbbec3a2013-06-29 01:45:0965// MyInvalidationService,
66// InvalidationServiceTest,
[email protected]e85797c2013-05-10 19:26:1667// MyInvalidatorTestDelegate);
68//
69// Easy!
70
[email protected]f7deb90a2014-06-12 22:50:5471#ifndef COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_
72#define COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_
[email protected]e85797c2013-05-10 19:26:1673
74#include "base/basictypes.h"
75#include "base/compiler_specific.h"
[email protected]51766bf2014-07-24 01:13:4776#include "components/invalidation/ack_handle.h"
[email protected]44828772014-06-06 02:56:5277#include "components/invalidation/fake_invalidation_handler.h"
[email protected]51766bf2014-07-24 01:13:4778#include "components/invalidation/invalidation.h"
[email protected]7315c962014-05-09 23:17:4779#include "components/invalidation/invalidation_service.h"
[email protected]001bbfdc2014-07-17 19:28:4680#include "components/invalidation/object_id_invalidation_map.h"
81#include "components/invalidation/object_id_invalidation_map_test_util.h"
[email protected]e85797c2013-05-10 19:26:1682#include "google/cacheinvalidation/include/types.h"
83#include "google/cacheinvalidation/types.pb.h"
[email protected]e85797c2013-05-10 19:26:1684#include "testing/gtest/include/gtest/gtest.h"
85
86template <typename InvalidatorTestDelegate>
[email protected]dbbec3a2013-06-29 01:45:0987class InvalidationServiceTest : public testing::Test {
[email protected]e85797c2013-05-10 19:26:1688 protected:
[email protected]dbbec3a2013-06-29 01:45:0989 InvalidationServiceTest()
[email protected]e85797c2013-05-10 19:26:1690 : id1(ipc::invalidation::ObjectSource::CHROME_SYNC, "BOOKMARK"),
91 id2(ipc::invalidation::ObjectSource::CHROME_SYNC, "PREFERENCE"),
92 id3(ipc::invalidation::ObjectSource::CHROME_SYNC, "AUTOFILL"),
[email protected]c56ab9022013-07-12 03:10:0893 id4(ipc::invalidation::ObjectSource::CHROME_PUSH_MESSAGING,
94 "PUSH_MESSAGE") {
[email protected]e85797c2013-05-10 19:26:1695 }
96
[email protected]dbbec3a2013-06-29 01:45:0997 invalidation::InvalidationService*
98 CreateAndInitializeInvalidationService() {
99 this->delegate_.CreateInvalidationService();
100 return this->delegate_.GetInvalidationService();
[email protected]e85797c2013-05-10 19:26:16101 }
102
[email protected]e85797c2013-05-10 19:26:16103 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
[email protected]dbbec3a2013-06-29 01:45:09111TYPED_TEST_CASE_P(InvalidationServiceTest);
[email protected]e85797c2013-05-10 19:26:16112
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.
[email protected]dbbec3a2013-06-29 01:45:09117TYPED_TEST_P(InvalidationServiceTest, Basic) {
118 invalidation::InvalidationService* const invalidator =
119 this->CreateAndInitializeInvalidationService();
[email protected]e85797c2013-05-10 19:26:16120
121 syncer::FakeInvalidationHandler handler;
122
123 invalidator->RegisterInvalidationHandler(&handler);
124
[email protected]163d0632013-10-04 03:51:01125 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"));
[email protected]e85797c2013-05-10 19:26:16129
130 // Should be ignored since no IDs are registered to |handler|.
[email protected]163d0632013-10-04 03:51:01131 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
[email protected]e85797c2013-05-10 19:26:16132 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
[email protected]163d0632013-10-04 03:51:01143 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"));
[email protected]e85797c2013-05-10 19:26:16146
[email protected]163d0632013-10-04 03:51:01147 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
[email protected]e85797c2013-05-10 19:26:16148 EXPECT_EQ(1, handler.GetInvalidationCount());
[email protected]163d0632013-10-04 03:51:01149 EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap()));
[email protected]e85797c2013-05-10 19:26:16150
151 ids.erase(this->id1);
152 ids.insert(this->id3);
153 invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
154
[email protected]163d0632013-10-04 03:51:01155 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"));
[email protected]e85797c2013-05-10 19:26:16158
159 // Removed object IDs should not be notified, newly-added ones should.
[email protected]163d0632013-10-04 03:51:01160 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
[email protected]e85797c2013-05-10 19:26:16161 EXPECT_EQ(2, handler.GetInvalidationCount());
[email protected]163d0632013-10-04 03:51:01162 EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap()));
[email protected]e85797c2013-05-10 19:26:16163
164 this->delegate_.TriggerOnInvalidatorStateChange(
165 syncer::TRANSIENT_INVALIDATION_ERROR);
166 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
167 handler.GetInvalidatorState());
168
169 this->delegate_.TriggerOnInvalidatorStateChange(
[email protected]dbbec3a2013-06-29 01:45:09170 syncer::INVALIDATIONS_ENABLED);
171 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED,
[email protected]e85797c2013-05-10 19:26:16172 handler.GetInvalidatorState());
173
174 invalidator->UnregisterInvalidationHandler(&handler);
175
176 // Should be ignored since |handler| isn't registered anymore.
[email protected]163d0632013-10-04 03:51:01177 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
[email protected]e85797c2013-05-10 19:26:16178 EXPECT_EQ(2, handler.GetInvalidationCount());
179}
180
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.
[email protected]dbbec3a2013-06-29 01:45:09186TYPED_TEST_P(InvalidationServiceTest, MultipleHandlers) {
187 invalidation::InvalidationService* const invalidator =
188 this->CreateAndInitializeInvalidationService();
[email protected]e85797c2013-05-10 19:26:16189
190 syncer::FakeInvalidationHandler handler1;
191 syncer::FakeInvalidationHandler handler2;
192 syncer::FakeInvalidationHandler handler3;
193 syncer::FakeInvalidationHandler handler4;
194
195 invalidator->RegisterInvalidationHandler(&handler1);
196 invalidator->RegisterInvalidationHandler(&handler2);
197 invalidator->RegisterInvalidationHandler(&handler3);
198 invalidator->RegisterInvalidationHandler(&handler4);
199
200 {
201 syncer::ObjectIdSet ids;
202 ids.insert(this->id1);
203 ids.insert(this->id2);
204 invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
205 }
206
207 {
208 syncer::ObjectIdSet ids;
209 ids.insert(this->id3);
210 invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
211 }
212
213 // Don't register any IDs for handler3.
214
215 {
216 syncer::ObjectIdSet ids;
217 ids.insert(this->id4);
218 invalidator->UpdateRegisteredInvalidationIds(&handler4, ids);
219 }
220
221 invalidator->UnregisterInvalidationHandler(&handler4);
222
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());
230
231 {
[email protected]163d0632013-10-04 03:51:01232 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);
[email protected]e85797c2013-05-10 19:26:16238
[email protected]163d0632013-10-04 03:51:01239 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"));
[email protected]e85797c2013-05-10 19:26:16244
245 EXPECT_EQ(1, handler1.GetInvalidationCount());
[email protected]163d0632013-10-04 03:51:01246 EXPECT_THAT(expected_invalidations, Eq(handler1.GetLastInvalidationMap()));
[email protected]e85797c2013-05-10 19:26:16247
[email protected]163d0632013-10-04 03:51:01248 expected_invalidations = syncer::ObjectIdInvalidationMap();
249 expected_invalidations.Insert(
250 syncer::Invalidation::Init(this->id3, 3, "3"));
[email protected]e85797c2013-05-10 19:26:16251
252 EXPECT_EQ(1, handler2.GetInvalidationCount());
[email protected]163d0632013-10-04 03:51:01253 EXPECT_THAT(expected_invalidations, Eq(handler2.GetLastInvalidationMap()));
[email protected]e85797c2013-05-10 19:26:16254
255 EXPECT_EQ(0, handler3.GetInvalidationCount());
256 EXPECT_EQ(0, handler4.GetInvalidationCount());
257 }
258
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());
269
270 invalidator->UnregisterInvalidationHandler(&handler3);
271 invalidator->UnregisterInvalidationHandler(&handler2);
272 invalidator->UnregisterInvalidationHandler(&handler1);
273}
274
275// Make sure that passing an empty set to UpdateRegisteredInvalidationIds clears
276// the corresponding entries for the handler.
[email protected]dbbec3a2013-06-29 01:45:09277TYPED_TEST_P(InvalidationServiceTest, EmptySetUnregisters) {
278 invalidation::InvalidationService* const invalidator =
279 this->CreateAndInitializeInvalidationService();
[email protected]e85797c2013-05-10 19:26:16280
281 syncer::FakeInvalidationHandler handler1;
282
283 // Control observer.
284 syncer::FakeInvalidationHandler handler2;
285
286 invalidator->RegisterInvalidationHandler(&handler1);
287 invalidator->RegisterInvalidationHandler(&handler2);
288
289 {
290 syncer::ObjectIdSet ids;
291 ids.insert(this->id1);
292 ids.insert(this->id2);
293 invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
294 }
295
296 {
297 syncer::ObjectIdSet ids;
298 ids.insert(this->id3);
299 invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
300 }
301
302 // Unregister the IDs for the first observer. It should not receive any
303 // further invalidations.
304 invalidator->UpdateRegisteredInvalidationIds(&handler1,
305 syncer::ObjectIdSet());
306
307 this->delegate_.TriggerOnInvalidatorStateChange(
308 syncer::INVALIDATIONS_ENABLED);
309 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
310 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
311
312 {
[email protected]163d0632013-10-04 03:51:01313 syncer::ObjectIdInvalidationMap invalidation_map;
314 invalidation_map.Insert(syncer::Invalidation::Init(this->id1, 1, "1"));
315 invalidation_map.Insert(syncer::Invalidation::Init(this->id2, 2, "2"));
316 invalidation_map.Insert(syncer::Invalidation::Init(this->id3, 3, "3"));
317 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
[email protected]e85797c2013-05-10 19:26:16318 EXPECT_EQ(0, handler1.GetInvalidationCount());
319 EXPECT_EQ(1, handler2.GetInvalidationCount());
320 }
321
322 this->delegate_.TriggerOnInvalidatorStateChange(
323 syncer::TRANSIENT_INVALIDATION_ERROR);
324 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
325 handler1.GetInvalidatorState());
326 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
327 handler2.GetInvalidatorState());
328
329 invalidator->UnregisterInvalidationHandler(&handler2);
330 invalidator->UnregisterInvalidationHandler(&handler1);
331}
332
333namespace internal {
334
335// A FakeInvalidationHandler that is "bound" to a specific
[email protected]dbbec3a2013-06-29 01:45:09336// InvalidationService. This is for cross-referencing state information with
337// the bound InvalidationService.
[email protected]e85797c2013-05-10 19:26:16338class BoundFakeInvalidationHandler : public syncer::FakeInvalidationHandler {
339 public:
340 explicit BoundFakeInvalidationHandler(
[email protected]dbbec3a2013-06-29 01:45:09341 const invalidation::InvalidationService& invalidator);
dcheng00ea022b2014-10-21 11:24:56342 ~BoundFakeInvalidationHandler() override;
[email protected]e85797c2013-05-10 19:26:16343
344 // Returns the last return value of GetInvalidatorState() on the
345 // bound invalidator from the last time the invalidator state
346 // changed.
347 syncer::InvalidatorState GetLastRetrievedState() const;
348
349 // InvalidationHandler implementation.
dcheng00ea022b2014-10-21 11:24:56350 void OnInvalidatorStateChange(syncer::InvalidatorState state) override;
[email protected]e85797c2013-05-10 19:26:16351
352 private:
[email protected]dbbec3a2013-06-29 01:45:09353 const invalidation::InvalidationService& invalidator_;
[email protected]e85797c2013-05-10 19:26:16354 syncer::InvalidatorState last_retrieved_state_;
355
356 DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler);
357};
358
359} // namespace internal
360
[email protected]dbbec3a2013-06-29 01:45:09361TYPED_TEST_P(InvalidationServiceTest, GetInvalidatorStateAlwaysCurrent) {
362 invalidation::InvalidationService* const invalidator =
363 this->CreateAndInitializeInvalidationService();
[email protected]e85797c2013-05-10 19:26:16364
365 internal::BoundFakeInvalidationHandler handler(*invalidator);
366 invalidator->RegisterInvalidationHandler(&handler);
367
368 this->delegate_.TriggerOnInvalidatorStateChange(
369 syncer::INVALIDATIONS_ENABLED);
370 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
371 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetLastRetrievedState());
372
373 this->delegate_.TriggerOnInvalidatorStateChange(
374 syncer::TRANSIENT_INVALIDATION_ERROR);
375 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
376 handler.GetInvalidatorState());
377 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
378 handler.GetLastRetrievedState());
379
380 invalidator->UnregisterInvalidationHandler(&handler);
381}
382
[email protected]dbbec3a2013-06-29 01:45:09383REGISTER_TYPED_TEST_CASE_P(InvalidationServiceTest,
[email protected]e85797c2013-05-10 19:26:16384 Basic, MultipleHandlers, EmptySetUnregisters,
385 GetInvalidatorStateAlwaysCurrent);
386
[email protected]f7deb90a2014-06-12 22:50:54387#endif // COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_