Roll src/third_party/WebKit 9f7fb92:f103b33 (svn 202621:202622)
[chromium-blink-merge.git] / components / invalidation / impl / invalidator_test_template.h
blobcf43a8bfd31905f950a8bd9474b3fac1347b24fe
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 Invalidator should pass in
6 // order to be conformant. Here's how you use it to test your implementation.
7 //
8 // Say your class is called MyInvalidator. Then you need to define a class
9 // called MyInvalidatorTestDelegate in my_sync_notifier_unittest.cc like this:
11 // class MyInvalidatorTestDelegate {
12 // public:
13 // MyInvalidatorTestDelegate() ...
15 // ~MyInvalidatorTestDelegate() {
16 // // DestroyInvalidator() may not be explicitly called by tests.
17 // DestroyInvalidator();
18 // }
20 // // Create the Invalidator implementation with the given parameters.
21 // void CreateInvalidator(
22 // const std::string& initial_state,
23 // const base::WeakPtr<InvalidationStateTracker>&
24 // invalidation_state_tracker) {
25 // ...
26 // }
28 // // Should return the Invalidator implementation. Only called after
29 // // CreateInvalidator and before DestroyInvalidator.
30 // MyInvalidator* GetInvalidator() {
31 // ...
32 // }
34 // // Destroy the Invalidator implementation.
35 // void DestroyInvalidator() {
36 // ...
37 // }
39 // // Called after a call to SetUniqueId(), or UpdateCredentials() on the
40 // // Invalidator implementation. Should block until the effects of the
41 // // call are visible on the current thread.
42 // void WaitForInvalidator() {
43 // ...
44 // }
46 // // The Trigger* functions below should block until the effects of
47 // // the call are visible on the current thread.
49 // // Should cause OnInvalidatorStateChange() to be called on all
50 // // observers of the Invalidator implementation with the given
51 // // parameters.
52 // void TriggerOnInvalidatorStateChange(InvalidatorState state) {
53 // ...
54 // }
56 // // Should cause OnIncomingInvalidation() to be called on all
57 // // observers of the Invalidator implementation with the given
58 // // parameters.
59 // void TriggerOnIncomingInvalidation(
60 // const ObjectIdInvalidationMap& invalidation_map) {
61 // ...
62 // }
63 // };
65 // The InvalidatorTest test harness will have a member variable of
66 // this delegate type and will call its functions in the various
67 // tests.
69 // Then you simply #include this file as well as gtest.h and add the
70 // following statement to my_sync_notifier_unittest.cc:
72 // INSTANTIATE_TYPED_TEST_CASE_P(
73 // MyInvalidator, InvalidatorTest, MyInvalidatorTestDelegate);
75 // Easy!
77 #ifndef COMPONENTS_INVALIDATION_IMPL_INVALIDATOR_TEST_TEMPLATE_H_
78 #define COMPONENTS_INVALIDATION_IMPL_INVALIDATOR_TEST_TEMPLATE_H_
80 #include "base/basictypes.h"
81 #include "base/compiler_specific.h"
82 #include "components/invalidation/impl/fake_invalidation_handler.h"
83 #include "components/invalidation/impl/fake_invalidation_state_tracker.h"
84 #include "components/invalidation/impl/invalidator.h"
85 #include "components/invalidation/impl/object_id_invalidation_map_test_util.h"
86 #include "google/cacheinvalidation/include/types.h"
87 #include "google/cacheinvalidation/types.pb.h"
88 #include "testing/gtest/include/gtest/gtest.h"
90 namespace syncer {
92 template <typename InvalidatorTestDelegate>
93 class InvalidatorTest : public testing::Test {
94 protected:
95 InvalidatorTest()
96 : id1(ipc::invalidation::ObjectSource::TEST, "a"),
97 id2(ipc::invalidation::ObjectSource::TEST, "b"),
98 id3(ipc::invalidation::ObjectSource::TEST, "c"),
99 id4(ipc::invalidation::ObjectSource::TEST, "d") {
102 Invalidator* CreateAndInitializeInvalidator() {
103 this->delegate_.CreateInvalidator("fake_invalidator_client_id",
104 "fake_initial_state",
105 this->fake_tracker_.AsWeakPtr());
106 Invalidator* const invalidator = this->delegate_.GetInvalidator();
108 this->delegate_.WaitForInvalidator();
109 invalidator->UpdateCredentials("foo@bar.com", "fake_token");
110 this->delegate_.WaitForInvalidator();
112 return invalidator;
115 FakeInvalidationStateTracker fake_tracker_;
116 InvalidatorTestDelegate delegate_;
118 const invalidation::ObjectId id1;
119 const invalidation::ObjectId id2;
120 const invalidation::ObjectId id3;
121 const invalidation::ObjectId id4;
124 TYPED_TEST_CASE_P(InvalidatorTest);
126 // Initialize the invalidator, register a handler, register some IDs for that
127 // handler, and then unregister the handler, dispatching invalidations in
128 // between. The handler should only see invalidations when its registered and
129 // its IDs are registered.
130 TYPED_TEST_P(InvalidatorTest, Basic) {
131 Invalidator* const invalidator = this->CreateAndInitializeInvalidator();
133 FakeInvalidationHandler handler;
135 invalidator->RegisterHandler(&handler);
137 ObjectIdInvalidationMap invalidation_map;
138 invalidation_map.Insert(Invalidation::Init(this->id1, 1, "1"));
139 invalidation_map.Insert(Invalidation::Init(this->id2, 2, "2"));
140 invalidation_map.Insert(Invalidation::Init(this->id3, 3, "3"));
142 // Should be ignored since no IDs are registered to |handler|.
143 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
144 EXPECT_EQ(0, handler.GetInvalidationCount());
146 ObjectIdSet ids;
147 ids.insert(this->id1);
148 ids.insert(this->id2);
149 EXPECT_TRUE(invalidator->UpdateRegisteredIds(&handler, ids));
151 this->delegate_.TriggerOnInvalidatorStateChange(INVALIDATIONS_ENABLED);
152 EXPECT_EQ(INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
154 ObjectIdInvalidationMap expected_invalidations;
155 expected_invalidations.Insert(Invalidation::Init(this->id1, 1, "1"));
156 expected_invalidations.Insert(Invalidation::Init(this->id2, 2, "2"));
158 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
159 EXPECT_EQ(1, handler.GetInvalidationCount());
160 EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap()));
162 ids.erase(this->id1);
163 ids.insert(this->id3);
164 EXPECT_TRUE(invalidator->UpdateRegisteredIds(&handler, ids));
166 expected_invalidations = ObjectIdInvalidationMap();
167 expected_invalidations.Insert(Invalidation::Init(this->id2, 2, "2"));
168 expected_invalidations.Insert(Invalidation::Init(this->id3, 3, "3"));
170 // Removed object IDs should not be notified, newly-added ones should.
171 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
172 EXPECT_EQ(2, handler.GetInvalidationCount());
173 EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap()));
175 this->delegate_.TriggerOnInvalidatorStateChange(TRANSIENT_INVALIDATION_ERROR);
176 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR,
177 handler.GetInvalidatorState());
179 this->delegate_.TriggerOnInvalidatorStateChange(
180 INVALIDATION_CREDENTIALS_REJECTED);
181 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED,
182 handler.GetInvalidatorState());
184 invalidator->UnregisterHandler(&handler);
186 // Should be ignored since |handler| isn't registered anymore.
187 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
188 EXPECT_EQ(2, handler.GetInvalidationCount());
191 // Register handlers and some IDs for those handlers, register a handler with
192 // no IDs, and register a handler with some IDs but unregister it. Then,
193 // dispatch some invalidations and invalidations. Handlers that are registered
194 // should get invalidations, and the ones that have registered IDs should
195 // receive invalidations for those IDs.
196 TYPED_TEST_P(InvalidatorTest, MultipleHandlers) {
197 Invalidator* const invalidator = this->CreateAndInitializeInvalidator();
199 FakeInvalidationHandler handler1;
200 FakeInvalidationHandler handler2;
201 FakeInvalidationHandler handler3;
202 FakeInvalidationHandler handler4;
204 invalidator->RegisterHandler(&handler1);
205 invalidator->RegisterHandler(&handler2);
206 invalidator->RegisterHandler(&handler3);
207 invalidator->RegisterHandler(&handler4);
210 ObjectIdSet ids;
211 ids.insert(this->id1);
212 ids.insert(this->id2);
213 EXPECT_TRUE(invalidator->UpdateRegisteredIds(&handler1, ids));
217 ObjectIdSet ids;
218 ids.insert(this->id3);
219 EXPECT_TRUE(invalidator->UpdateRegisteredIds(&handler2, ids));
222 // Don't register any IDs for handler3.
225 ObjectIdSet ids;
226 ids.insert(this->id4);
227 EXPECT_TRUE(invalidator->UpdateRegisteredIds(&handler4, ids));
230 invalidator->UnregisterHandler(&handler4);
232 this->delegate_.TriggerOnInvalidatorStateChange(INVALIDATIONS_ENABLED);
233 EXPECT_EQ(INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
234 EXPECT_EQ(INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
235 EXPECT_EQ(INVALIDATIONS_ENABLED, handler3.GetInvalidatorState());
236 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler4.GetInvalidatorState());
239 ObjectIdInvalidationMap invalidation_map;
240 invalidation_map.Insert(Invalidation::Init(this->id1, 1, "1"));
241 invalidation_map.Insert(Invalidation::Init(this->id2, 2, "2"));
242 invalidation_map.Insert(Invalidation::Init(this->id3, 3, "3"));
243 invalidation_map.Insert(Invalidation::Init(this->id4, 4, "4"));
245 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
247 ObjectIdInvalidationMap expected_invalidations;
248 expected_invalidations.Insert(Invalidation::Init(this->id1, 1, "1"));
249 expected_invalidations.Insert(Invalidation::Init(this->id2, 2, "2"));
251 EXPECT_EQ(1, handler1.GetInvalidationCount());
252 EXPECT_THAT(expected_invalidations, Eq(handler1.GetLastInvalidationMap()));
254 expected_invalidations = ObjectIdInvalidationMap();
255 expected_invalidations.Insert(Invalidation::Init(this->id3, 3, "3"));
257 EXPECT_EQ(1, handler2.GetInvalidationCount());
258 EXPECT_THAT(expected_invalidations, Eq(handler2.GetLastInvalidationMap()));
260 EXPECT_EQ(0, handler3.GetInvalidationCount());
261 EXPECT_EQ(0, handler4.GetInvalidationCount());
264 this->delegate_.TriggerOnInvalidatorStateChange(TRANSIENT_INVALIDATION_ERROR);
265 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler1.GetInvalidatorState());
266 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler2.GetInvalidatorState());
267 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler3.GetInvalidatorState());
268 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler4.GetInvalidatorState());
270 invalidator->UnregisterHandler(&handler3);
271 invalidator->UnregisterHandler(&handler2);
272 invalidator->UnregisterHandler(&handler1);
275 // Multiple registrations by different handlers on the same object ID should
276 // return false.
277 TYPED_TEST_P(InvalidatorTest, MultipleRegistrations) {
278 Invalidator* const invalidator = this->CreateAndInitializeInvalidator();
280 FakeInvalidationHandler handler1;
281 FakeInvalidationHandler handler2;
283 invalidator->RegisterHandler(&handler1);
284 invalidator->RegisterHandler(&handler2);
286 // Registering both handlers for the same ObjectId. First call should succeed,
287 // second should fail.
288 ObjectIdSet ids;
289 ids.insert(this->id1);
290 EXPECT_TRUE(invalidator->UpdateRegisteredIds(&handler1, ids));
291 EXPECT_FALSE(invalidator->UpdateRegisteredIds(&handler2, ids));
293 invalidator->UnregisterHandler(&handler2);
294 invalidator->UnregisterHandler(&handler1);
297 // Make sure that passing an empty set to UpdateRegisteredIds clears the
298 // corresponding entries for the handler.
299 TYPED_TEST_P(InvalidatorTest, EmptySetUnregisters) {
300 Invalidator* const invalidator = this->CreateAndInitializeInvalidator();
302 FakeInvalidationHandler handler1;
304 // Control observer.
305 FakeInvalidationHandler handler2;
307 invalidator->RegisterHandler(&handler1);
308 invalidator->RegisterHandler(&handler2);
311 ObjectIdSet ids;
312 ids.insert(this->id1);
313 ids.insert(this->id2);
314 EXPECT_TRUE(invalidator->UpdateRegisteredIds(&handler1, ids));
318 ObjectIdSet ids;
319 ids.insert(this->id3);
320 EXPECT_TRUE(invalidator->UpdateRegisteredIds(&handler2, ids));
323 // Unregister the IDs for the first observer. It should not receive any
324 // further invalidations.
325 EXPECT_TRUE(invalidator->UpdateRegisteredIds(&handler1, ObjectIdSet()));
327 this->delegate_.TriggerOnInvalidatorStateChange(INVALIDATIONS_ENABLED);
328 EXPECT_EQ(INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
329 EXPECT_EQ(INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
332 ObjectIdInvalidationMap invalidation_map;
333 invalidation_map.Insert(Invalidation::Init(this->id1, 1, "1"));
334 invalidation_map.Insert(Invalidation::Init(this->id2, 2, "2"));
335 invalidation_map.Insert(Invalidation::Init(this->id3, 3, "3"));
336 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
337 EXPECT_EQ(0, handler1.GetInvalidationCount());
338 EXPECT_EQ(1, handler2.GetInvalidationCount());
341 this->delegate_.TriggerOnInvalidatorStateChange(TRANSIENT_INVALIDATION_ERROR);
342 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler1.GetInvalidatorState());
343 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler2.GetInvalidatorState());
345 invalidator->UnregisterHandler(&handler2);
346 invalidator->UnregisterHandler(&handler1);
349 namespace internal {
351 // A FakeInvalidationHandler that is "bound" to a specific
352 // Invalidator. This is for cross-referencing state information with
353 // the bound Invalidator.
354 class BoundFakeInvalidationHandler : public FakeInvalidationHandler {
355 public:
356 explicit BoundFakeInvalidationHandler(const Invalidator& invalidator);
357 ~BoundFakeInvalidationHandler() override;
359 // Returns the last return value of GetInvalidatorState() on the
360 // bound invalidator from the last time the invalidator state
361 // changed.
362 InvalidatorState GetLastRetrievedState() const;
364 // InvalidationHandler implementation.
365 void OnInvalidatorStateChange(InvalidatorState state) override;
367 private:
368 const Invalidator& invalidator_;
369 InvalidatorState last_retrieved_state_;
371 DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler);
374 } // namespace internal
376 TYPED_TEST_P(InvalidatorTest, GetInvalidatorStateAlwaysCurrent) {
377 Invalidator* const invalidator = this->CreateAndInitializeInvalidator();
379 internal::BoundFakeInvalidationHandler handler(*invalidator);
380 invalidator->RegisterHandler(&handler);
382 this->delegate_.TriggerOnInvalidatorStateChange(INVALIDATIONS_ENABLED);
383 EXPECT_EQ(INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
384 EXPECT_EQ(INVALIDATIONS_ENABLED, handler.GetLastRetrievedState());
386 this->delegate_.TriggerOnInvalidatorStateChange(TRANSIENT_INVALIDATION_ERROR);
387 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler.GetInvalidatorState());
388 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler.GetLastRetrievedState());
390 invalidator->UnregisterHandler(&handler);
393 REGISTER_TYPED_TEST_CASE_P(InvalidatorTest,
394 Basic,
395 MultipleHandlers,
396 MultipleRegistrations,
397 EmptySetUnregisters,
398 GetInvalidatorStateAlwaysCurrent);
400 } // namespace syncer
402 #endif // COMPONENTS_INVALIDATION_IMPL_INVALIDATOR_TEST_TEMPLATE_H_