Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / invalidation / invalidation_service_test_template.h
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 "components/invalidation/invalidation_service.h"
77 #include "content/public/test/test_browser_thread_bundle.h"
78 #include "google/cacheinvalidation/include/types.h"
79 #include "google/cacheinvalidation/types.pb.h"
80 #include "sync/internal_api/public/base/ack_handle.h"
81 #include "sync/internal_api/public/base/invalidation.h"
82 #include "sync/internal_api/public/base/object_id_invalidation_map_test_util.h"
83 #include "sync/notifier/fake_invalidation_handler.h"
84 #include "sync/notifier/object_id_invalidation_map.h"
85 #include "testing/gtest/include/gtest/gtest.h"
86
87 template <typename InvalidatorTestDelegate>
88 class InvalidationServiceTest : public testing::Test {
89  protected:
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_PUSH_MESSAGING,
95             "PUSH_MESSAGE") {
96   }
97
98   invalidation::InvalidationService*
99   CreateAndInitializeInvalidationService() {
100     this->delegate_.CreateInvalidationService();
101     return this->delegate_.GetInvalidationService();
102   }
103
104   content::TestBrowserThreadBundle thread_bundle_;
105   InvalidatorTestDelegate delegate_;
106
107   const invalidation::ObjectId id1;
108   const invalidation::ObjectId id2;
109   const invalidation::ObjectId id3;
110   const invalidation::ObjectId id4;
111 };
112
113 TYPED_TEST_CASE_P(InvalidationServiceTest);
114
115 // Initialize the invalidator, register a handler, register some IDs for that
116 // handler, and then unregister the handler, dispatching invalidations in
117 // between.  The handler should only see invalidations when its registered and
118 // its IDs are registered.
119 TYPED_TEST_P(InvalidationServiceTest, Basic) {
120   invalidation::InvalidationService* const invalidator =
121       this->CreateAndInitializeInvalidationService();
122
123   syncer::FakeInvalidationHandler handler;
124
125   invalidator->RegisterInvalidationHandler(&handler);
126
127   syncer::ObjectIdInvalidationMap invalidation_map;
128   invalidation_map.Insert(syncer::Invalidation::Init(this->id1, 1, "1"));
129   invalidation_map.Insert(syncer::Invalidation::Init(this->id2, 2, "2"));
130   invalidation_map.Insert(syncer::Invalidation::Init(this->id3, 3, "3"));
131
132   // Should be ignored since no IDs are registered to |handler|.
133   this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
134   EXPECT_EQ(0, handler.GetInvalidationCount());
135
136   syncer::ObjectIdSet ids;
137   ids.insert(this->id1);
138   ids.insert(this->id2);
139   invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
140
141   this->delegate_.TriggerOnInvalidatorStateChange(
142       syncer::INVALIDATIONS_ENABLED);
143   EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
144
145   syncer::ObjectIdInvalidationMap expected_invalidations;
146   expected_invalidations.Insert(syncer::Invalidation::Init(this->id1, 1, "1"));
147   expected_invalidations.Insert(syncer::Invalidation::Init(this->id2, 2, "2"));
148
149   this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
150   EXPECT_EQ(1, handler.GetInvalidationCount());
151   EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap()));
152
153   ids.erase(this->id1);
154   ids.insert(this->id3);
155   invalidator->UpdateRegisteredInvalidationIds(&handler, ids);
156
157   expected_invalidations = syncer::ObjectIdInvalidationMap();
158   expected_invalidations.Insert(syncer::Invalidation::Init(this->id2, 2, "2"));
159   expected_invalidations.Insert(syncer::Invalidation::Init(this->id3, 3, "3"));
160
161   // Removed object IDs should not be notified, newly-added ones should.
162   this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
163   EXPECT_EQ(2, handler.GetInvalidationCount());
164   EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap()));
165
166   this->delegate_.TriggerOnInvalidatorStateChange(
167       syncer::TRANSIENT_INVALIDATION_ERROR);
168   EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
169             handler.GetInvalidatorState());
170
171   this->delegate_.TriggerOnInvalidatorStateChange(
172       syncer::INVALIDATIONS_ENABLED);
173   EXPECT_EQ(syncer::INVALIDATIONS_ENABLED,
174             handler.GetInvalidatorState());
175
176   invalidator->UnregisterInvalidationHandler(&handler);
177
178   // Should be ignored since |handler| isn't registered anymore.
179   this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
180   EXPECT_EQ(2, handler.GetInvalidationCount());
181 }
182
183 // Register handlers and some IDs for those handlers, register a handler with
184 // no IDs, and register a handler with some IDs but unregister it.  Then,
185 // dispatch some invalidations and invalidations.  Handlers that are registered
186 // should get invalidations, and the ones that have registered IDs should
187 // receive invalidations for those IDs.
188 TYPED_TEST_P(InvalidationServiceTest, MultipleHandlers) {
189   invalidation::InvalidationService* const invalidator =
190       this->CreateAndInitializeInvalidationService();
191
192   syncer::FakeInvalidationHandler handler1;
193   syncer::FakeInvalidationHandler handler2;
194   syncer::FakeInvalidationHandler handler3;
195   syncer::FakeInvalidationHandler handler4;
196
197   invalidator->RegisterInvalidationHandler(&handler1);
198   invalidator->RegisterInvalidationHandler(&handler2);
199   invalidator->RegisterInvalidationHandler(&handler3);
200   invalidator->RegisterInvalidationHandler(&handler4);
201
202   {
203     syncer::ObjectIdSet ids;
204     ids.insert(this->id1);
205     ids.insert(this->id2);
206     invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
207   }
208
209   {
210     syncer::ObjectIdSet ids;
211     ids.insert(this->id3);
212     invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
213   }
214
215   // Don't register any IDs for handler3.
216
217   {
218     syncer::ObjectIdSet ids;
219     ids.insert(this->id4);
220     invalidator->UpdateRegisteredInvalidationIds(&handler4, ids);
221   }
222
223   invalidator->UnregisterInvalidationHandler(&handler4);
224
225   this->delegate_.TriggerOnInvalidatorStateChange(
226       syncer::INVALIDATIONS_ENABLED);
227   EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
228   EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
229   EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler3.GetInvalidatorState());
230   EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
231             handler4.GetInvalidatorState());
232
233   {
234     syncer::ObjectIdInvalidationMap invalidation_map;
235     invalidation_map.Insert(syncer::Invalidation::Init(this->id1, 1, "1"));
236     invalidation_map.Insert(syncer::Invalidation::Init(this->id2, 2, "2"));
237     invalidation_map.Insert(syncer::Invalidation::Init(this->id3, 3, "3"));
238     invalidation_map.Insert(syncer::Invalidation::Init(this->id4, 4, "4"));
239     this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
240
241     syncer::ObjectIdInvalidationMap expected_invalidations;
242     expected_invalidations.Insert(
243         syncer::Invalidation::Init(this->id1, 1, "1"));
244     expected_invalidations.Insert(
245         syncer::Invalidation::Init(this->id2, 2, "2"));
246
247     EXPECT_EQ(1, handler1.GetInvalidationCount());
248     EXPECT_THAT(expected_invalidations, Eq(handler1.GetLastInvalidationMap()));
249
250     expected_invalidations = syncer::ObjectIdInvalidationMap();
251     expected_invalidations.Insert(
252         syncer::Invalidation::Init(this->id3, 3, "3"));
253
254     EXPECT_EQ(1, handler2.GetInvalidationCount());
255     EXPECT_THAT(expected_invalidations, Eq(handler2.GetLastInvalidationMap()));
256
257     EXPECT_EQ(0, handler3.GetInvalidationCount());
258     EXPECT_EQ(0, handler4.GetInvalidationCount());
259   }
260
261   this->delegate_.TriggerOnInvalidatorStateChange(
262       syncer::TRANSIENT_INVALIDATION_ERROR);
263   EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
264             handler1.GetInvalidatorState());
265   EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
266             handler2.GetInvalidatorState());
267   EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
268             handler3.GetInvalidatorState());
269   EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
270             handler4.GetInvalidatorState());
271
272   invalidator->UnregisterInvalidationHandler(&handler3);
273   invalidator->UnregisterInvalidationHandler(&handler2);
274   invalidator->UnregisterInvalidationHandler(&handler1);
275 }
276
277 // Make sure that passing an empty set to UpdateRegisteredInvalidationIds clears
278 // the corresponding entries for the handler.
279 TYPED_TEST_P(InvalidationServiceTest, EmptySetUnregisters) {
280   invalidation::InvalidationService* const invalidator =
281       this->CreateAndInitializeInvalidationService();
282
283   syncer::FakeInvalidationHandler handler1;
284
285   // Control observer.
286   syncer::FakeInvalidationHandler handler2;
287
288   invalidator->RegisterInvalidationHandler(&handler1);
289   invalidator->RegisterInvalidationHandler(&handler2);
290
291   {
292     syncer::ObjectIdSet ids;
293     ids.insert(this->id1);
294     ids.insert(this->id2);
295     invalidator->UpdateRegisteredInvalidationIds(&handler1, ids);
296   }
297
298   {
299     syncer::ObjectIdSet ids;
300     ids.insert(this->id3);
301     invalidator->UpdateRegisteredInvalidationIds(&handler2, ids);
302   }
303
304   // Unregister the IDs for the first observer. It should not receive any
305   // further invalidations.
306   invalidator->UpdateRegisteredInvalidationIds(&handler1,
307                                                syncer::ObjectIdSet());
308
309   this->delegate_.TriggerOnInvalidatorStateChange(
310       syncer::INVALIDATIONS_ENABLED);
311   EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
312   EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
313
314   {
315     syncer::ObjectIdInvalidationMap invalidation_map;
316     invalidation_map.Insert(syncer::Invalidation::Init(this->id1, 1, "1"));
317     invalidation_map.Insert(syncer::Invalidation::Init(this->id2, 2, "2"));
318     invalidation_map.Insert(syncer::Invalidation::Init(this->id3, 3, "3"));
319     this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
320     EXPECT_EQ(0, handler1.GetInvalidationCount());
321     EXPECT_EQ(1, handler2.GetInvalidationCount());
322   }
323
324   this->delegate_.TriggerOnInvalidatorStateChange(
325       syncer::TRANSIENT_INVALIDATION_ERROR);
326   EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
327             handler1.GetInvalidatorState());
328   EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
329             handler2.GetInvalidatorState());
330
331   invalidator->UnregisterInvalidationHandler(&handler2);
332   invalidator->UnregisterInvalidationHandler(&handler1);
333 }
334
335 namespace internal {
336
337 // A FakeInvalidationHandler that is "bound" to a specific
338 // InvalidationService.  This is for cross-referencing state information with
339 // the bound InvalidationService.
340 class BoundFakeInvalidationHandler : public syncer::FakeInvalidationHandler {
341  public:
342   explicit BoundFakeInvalidationHandler(
343       const invalidation::InvalidationService& invalidator);
344   virtual ~BoundFakeInvalidationHandler();
345
346   // Returns the last return value of GetInvalidatorState() on the
347   // bound invalidator from the last time the invalidator state
348   // changed.
349   syncer::InvalidatorState GetLastRetrievedState() const;
350
351   // InvalidationHandler implementation.
352   virtual void OnInvalidatorStateChange(
353       syncer::InvalidatorState state) OVERRIDE;
354
355  private:
356   const invalidation::InvalidationService& invalidator_;
357   syncer::InvalidatorState last_retrieved_state_;
358
359   DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler);
360 };
361
362 }  // namespace internal
363
364 TYPED_TEST_P(InvalidationServiceTest, GetInvalidatorStateAlwaysCurrent) {
365   invalidation::InvalidationService* const invalidator =
366       this->CreateAndInitializeInvalidationService();
367
368   internal::BoundFakeInvalidationHandler handler(*invalidator);
369   invalidator->RegisterInvalidationHandler(&handler);
370
371   this->delegate_.TriggerOnInvalidatorStateChange(
372       syncer::INVALIDATIONS_ENABLED);
373   EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
374   EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetLastRetrievedState());
375
376   this->delegate_.TriggerOnInvalidatorStateChange(
377       syncer::TRANSIENT_INVALIDATION_ERROR);
378   EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
379             handler.GetInvalidatorState());
380   EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR,
381             handler.GetLastRetrievedState());
382
383   invalidator->UnregisterInvalidationHandler(&handler);
384 }
385
386 REGISTER_TYPED_TEST_CASE_P(InvalidationServiceTest,
387                            Basic, MultipleHandlers, EmptySetUnregisters,
388                            GetInvalidatorStateAlwaysCurrent);
389
390 #endif  // CHROME_BROWSER_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_