blob: 95d011d6d9cb68889243af1b7105aa61085e233f [file] [log] [blame]
[email protected]24c9ee52014-06-02 22:17:501// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]33596da2012-08-31 23:39:252// 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 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:
10//
11// class MyInvalidatorTestDelegate {
12// public:
13// MyInvalidatorTestDelegate() ...
14//
15// ~MyInvalidatorTestDelegate() {
16// // DestroyInvalidator() may not be explicitly called by tests.
17// DestroyInvalidator();
18// }
19//
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// }
27//
28// // Should return the Invalidator implementation. Only called after
29// // CreateInvalidator and before DestroyInvalidator.
30// MyInvalidator* GetInvalidator() {
31// ...
32// }
33//
34// // Destroy the Invalidator implementation.
35// void DestroyInvalidator() {
36// ...
37// }
38//
[email protected]2e152c32013-01-29 01:37:0139// // 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.
[email protected]33596da2012-08-31 23:39:2542// void WaitForInvalidator() {
43// ...
44// }
45//
46// // The Trigger* functions below should block until the effects of
47// // the call are visible on the current thread.
48//
[email protected]08a6f9992012-09-07 19:19:1649// // Should cause OnInvalidatorStateChange() to be called on all
50// // observers of the Invalidator implementation with the given
51// // parameters.
52// void TriggerOnInvalidatorStateChange(InvalidatorState state) {
[email protected]33596da2012-08-31 23:39:2553// ...
54// }
55//
[email protected]08a6f9992012-09-07 19:19:1656// // Should cause OnIncomingInvalidation() to be called on all
[email protected]33596da2012-08-31 23:39:2557// // observers of the Invalidator implementation with the given
58// // parameters.
[email protected]3e31fa42012-10-04 03:53:0959// void TriggerOnIncomingInvalidation(
[email protected]0d0b59d2013-02-02 00:24:4760// const ObjectIdInvalidationMap& invalidation_map) {
[email protected]33596da2012-08-31 23:39:2561// ...
62// }
[email protected]33596da2012-08-31 23:39:2563// };
64//
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.
68//
69// Then you simply #include this file as well as gtest.h and add the
70// following statement to my_sync_notifier_unittest.cc:
71//
72// INSTANTIATE_TYPED_TEST_CASE_P(
73// MyInvalidator, InvalidatorTest, MyInvalidatorTestDelegate);
74//
75// Easy!
76
[email protected]44828772014-06-06 02:56:5277#ifndef COMPONENTS_INVALIDATION_INVALIDATOR_TEST_TEMPLATE_H_
78#define COMPONENTS_INVALIDATION_INVALIDATOR_TEST_TEMPLATE_H_
[email protected]33596da2012-08-31 23:39:2579
[email protected]08a6f9992012-09-07 19:19:1680#include "base/basictypes.h"
81#include "base/compiler_specific.h"
[email protected]44828772014-06-06 02:56:5282#include "components/invalidation/fake_invalidation_handler.h"
83#include "components/invalidation/fake_invalidation_state_tracker.h"
[email protected]001bbfdc2014-07-17 19:28:4684#include "components/invalidation/invalidator.h"
85#include "components/invalidation/object_id_invalidation_map_test_util.h"
[email protected]33596da2012-08-31 23:39:2586#include "google/cacheinvalidation/include/types.h"
87#include "google/cacheinvalidation/types.pb.h"
[email protected]33596da2012-08-31 23:39:2588#include "testing/gtest/include/gtest/gtest.h"
89
90namespace syncer {
91
92template <typename InvalidatorTestDelegate>
93class 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") {
100 }
101
102 Invalidator* CreateAndInitializeInvalidator() {
[email protected]d5511232013-03-28 01:34:54103 this->delegate_.CreateInvalidator("fake_invalidator_client_id",
104 "fake_initial_state",
[email protected]33596da2012-08-31 23:39:25105 this->fake_tracker_.AsWeakPtr());
106 Invalidator* const invalidator = this->delegate_.GetInvalidator();
107
[email protected]33596da2012-08-31 23:39:25108 this->delegate_.WaitForInvalidator();
109 invalidator->UpdateCredentials("[email protected]", "fake_token");
110 this->delegate_.WaitForInvalidator();
111
112 return invalidator;
113 }
114
115 FakeInvalidationStateTracker fake_tracker_;
116 InvalidatorTestDelegate delegate_;
117
118 const invalidation::ObjectId id1;
119 const invalidation::ObjectId id2;
120 const invalidation::ObjectId id3;
121 const invalidation::ObjectId id4;
122};
123
124TYPED_TEST_CASE_P(InvalidatorTest);
125
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.
130TYPED_TEST_P(InvalidatorTest, Basic) {
131 Invalidator* const invalidator = this->CreateAndInitializeInvalidator();
132
133 FakeInvalidationHandler handler;
134
135 invalidator->RegisterHandler(&handler);
136
[email protected]163d0632013-10-04 03:51:01137 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"));
[email protected]33596da2012-08-31 23:39:25141
142 // Should be ignored since no IDs are registered to |handler|.
[email protected]163d0632013-10-04 03:51:01143 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
[email protected]08a6f9992012-09-07 19:19:16144 EXPECT_EQ(0, handler.GetInvalidationCount());
[email protected]33596da2012-08-31 23:39:25145
146 ObjectIdSet ids;
147 ids.insert(this->id1);
148 ids.insert(this->id2);
149 invalidator->UpdateRegisteredIds(&handler, ids);
150
[email protected]08a6f9992012-09-07 19:19:16151 this->delegate_.TriggerOnInvalidatorStateChange(INVALIDATIONS_ENABLED);
152 EXPECT_EQ(INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
[email protected]33596da2012-08-31 23:39:25153
[email protected]163d0632013-10-04 03:51:01154 ObjectIdInvalidationMap expected_invalidations;
155 expected_invalidations.Insert(Invalidation::Init(this->id1, 1, "1"));
156 expected_invalidations.Insert(Invalidation::Init(this->id2, 2, "2"));
[email protected]33596da2012-08-31 23:39:25157
[email protected]163d0632013-10-04 03:51:01158 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
[email protected]08a6f9992012-09-07 19:19:16159 EXPECT_EQ(1, handler.GetInvalidationCount());
[email protected]163d0632013-10-04 03:51:01160 EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap()));
[email protected]33596da2012-08-31 23:39:25161
162 ids.erase(this->id1);
163 ids.insert(this->id3);
164 invalidator->UpdateRegisteredIds(&handler, ids);
165
[email protected]163d0632013-10-04 03:51:01166 expected_invalidations = ObjectIdInvalidationMap();
167 expected_invalidations.Insert(Invalidation::Init(this->id2, 2, "2"));
168 expected_invalidations.Insert(Invalidation::Init(this->id3, 3, "3"));
[email protected]33596da2012-08-31 23:39:25169
170 // Removed object IDs should not be notified, newly-added ones should.
[email protected]163d0632013-10-04 03:51:01171 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
[email protected]08a6f9992012-09-07 19:19:16172 EXPECT_EQ(2, handler.GetInvalidationCount());
[email protected]163d0632013-10-04 03:51:01173 EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap()));
[email protected]33596da2012-08-31 23:39:25174
[email protected]08a6f9992012-09-07 19:19:16175 this->delegate_.TriggerOnInvalidatorStateChange(TRANSIENT_INVALIDATION_ERROR);
176 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR,
177 handler.GetInvalidatorState());
[email protected]33596da2012-08-31 23:39:25178
[email protected]08a6f9992012-09-07 19:19:16179 this->delegate_.TriggerOnInvalidatorStateChange(
180 INVALIDATION_CREDENTIALS_REJECTED);
181 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED,
182 handler.GetInvalidatorState());
[email protected]33596da2012-08-31 23:39:25183
184 invalidator->UnregisterHandler(&handler);
185
186 // Should be ignored since |handler| isn't registered anymore.
[email protected]163d0632013-10-04 03:51:01187 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
[email protected]08a6f9992012-09-07 19:19:16188 EXPECT_EQ(2, handler.GetInvalidationCount());
[email protected]33596da2012-08-31 23:39:25189}
190
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,
[email protected]08a6f9992012-09-07 19:19:16193// dispatch some invalidations and invalidations. Handlers that are registered
194// should get invalidations, and the ones that have registered IDs should
[email protected]33596da2012-08-31 23:39:25195// receive invalidations for those IDs.
196TYPED_TEST_P(InvalidatorTest, MultipleHandlers) {
197 Invalidator* const invalidator = this->CreateAndInitializeInvalidator();
198
199 FakeInvalidationHandler handler1;
200 FakeInvalidationHandler handler2;
201 FakeInvalidationHandler handler3;
202 FakeInvalidationHandler handler4;
203
204 invalidator->RegisterHandler(&handler1);
205 invalidator->RegisterHandler(&handler2);
206 invalidator->RegisterHandler(&handler3);
207 invalidator->RegisterHandler(&handler4);
208
209 {
210 ObjectIdSet ids;
211 ids.insert(this->id1);
212 ids.insert(this->id2);
213 invalidator->UpdateRegisteredIds(&handler1, ids);
214 }
215
216 {
217 ObjectIdSet ids;
218 ids.insert(this->id3);
219 invalidator->UpdateRegisteredIds(&handler2, ids);
220 }
221
222 // Don't register any IDs for handler3.
223
224 {
225 ObjectIdSet ids;
226 ids.insert(this->id4);
227 invalidator->UpdateRegisteredIds(&handler4, ids);
228 }
229
230 invalidator->UnregisterHandler(&handler4);
231
[email protected]08a6f9992012-09-07 19:19:16232 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());
[email protected]33596da2012-08-31 23:39:25237
238 {
[email protected]163d0632013-10-04 03:51:01239 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"));
[email protected]33596da2012-08-31 23:39:25244
[email protected]163d0632013-10-04 03:51:01245 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
246
247 ObjectIdInvalidationMap expected_invalidations;
248 expected_invalidations.Insert(Invalidation::Init(this->id1, 1, "1"));
249 expected_invalidations.Insert(Invalidation::Init(this->id2, 2, "2"));
[email protected]33596da2012-08-31 23:39:25250
[email protected]08a6f9992012-09-07 19:19:16251 EXPECT_EQ(1, handler1.GetInvalidationCount());
[email protected]163d0632013-10-04 03:51:01252 EXPECT_THAT(expected_invalidations, Eq(handler1.GetLastInvalidationMap()));
[email protected]33596da2012-08-31 23:39:25253
[email protected]163d0632013-10-04 03:51:01254 expected_invalidations = ObjectIdInvalidationMap();
255 expected_invalidations.Insert(Invalidation::Init(this->id3, 3, "3"));
[email protected]33596da2012-08-31 23:39:25256
[email protected]08a6f9992012-09-07 19:19:16257 EXPECT_EQ(1, handler2.GetInvalidationCount());
[email protected]163d0632013-10-04 03:51:01258 EXPECT_THAT(expected_invalidations, Eq(handler2.GetLastInvalidationMap()));
[email protected]33596da2012-08-31 23:39:25259
[email protected]08a6f9992012-09-07 19:19:16260 EXPECT_EQ(0, handler3.GetInvalidationCount());
261 EXPECT_EQ(0, handler4.GetInvalidationCount());
[email protected]33596da2012-08-31 23:39:25262 }
263
[email protected]08a6f9992012-09-07 19:19:16264 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());
[email protected]4d432812012-10-05 18:03:14269
270 invalidator->UnregisterHandler(&handler3);
271 invalidator->UnregisterHandler(&handler2);
272 invalidator->UnregisterHandler(&handler1);
[email protected]33596da2012-08-31 23:39:25273}
274
275// Make sure that passing an empty set to UpdateRegisteredIds clears the
276// corresponding entries for the handler.
277TYPED_TEST_P(InvalidatorTest, EmptySetUnregisters) {
278 Invalidator* const invalidator = this->CreateAndInitializeInvalidator();
279
280 FakeInvalidationHandler handler1;
281
282 // Control observer.
283 FakeInvalidationHandler handler2;
284
285 invalidator->RegisterHandler(&handler1);
286 invalidator->RegisterHandler(&handler2);
287
288 {
289 ObjectIdSet ids;
290 ids.insert(this->id1);
291 ids.insert(this->id2);
292 invalidator->UpdateRegisteredIds(&handler1, ids);
293 }
294
295 {
296 ObjectIdSet ids;
297 ids.insert(this->id3);
298 invalidator->UpdateRegisteredIds(&handler2, ids);
299 }
300
301 // Unregister the IDs for the first observer. It should not receive any
302 // further invalidations.
303 invalidator->UpdateRegisteredIds(&handler1, ObjectIdSet());
304
[email protected]08a6f9992012-09-07 19:19:16305 this->delegate_.TriggerOnInvalidatorStateChange(INVALIDATIONS_ENABLED);
306 EXPECT_EQ(INVALIDATIONS_ENABLED, handler1.GetInvalidatorState());
307 EXPECT_EQ(INVALIDATIONS_ENABLED, handler2.GetInvalidatorState());
[email protected]33596da2012-08-31 23:39:25308
309 {
[email protected]163d0632013-10-04 03:51:01310 ObjectIdInvalidationMap invalidation_map;
311 invalidation_map.Insert(Invalidation::Init(this->id1, 1, "1"));
312 invalidation_map.Insert(Invalidation::Init(this->id2, 2, "2"));
313 invalidation_map.Insert(Invalidation::Init(this->id3, 3, "3"));
314 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map);
[email protected]08a6f9992012-09-07 19:19:16315 EXPECT_EQ(0, handler1.GetInvalidationCount());
316 EXPECT_EQ(1, handler2.GetInvalidationCount());
[email protected]33596da2012-08-31 23:39:25317 }
318
[email protected]08a6f9992012-09-07 19:19:16319 this->delegate_.TriggerOnInvalidatorStateChange(TRANSIENT_INVALIDATION_ERROR);
320 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler1.GetInvalidatorState());
321 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler2.GetInvalidatorState());
[email protected]4d432812012-10-05 18:03:14322
323 invalidator->UnregisterHandler(&handler2);
324 invalidator->UnregisterHandler(&handler1);
[email protected]08a6f9992012-09-07 19:19:16325}
326
327namespace internal {
328
329// A FakeInvalidationHandler that is "bound" to a specific
330// Invalidator. This is for cross-referencing state information with
331// the bound Invalidator.
332class BoundFakeInvalidationHandler : public FakeInvalidationHandler {
333 public:
334 explicit BoundFakeInvalidationHandler(const Invalidator& invalidator);
335 virtual ~BoundFakeInvalidationHandler();
336
337 // Returns the last return value of GetInvalidatorState() on the
338 // bound invalidator from the last time the invalidator state
339 // changed.
340 InvalidatorState GetLastRetrievedState() const;
341
342 // InvalidationHandler implementation.
343 virtual void OnInvalidatorStateChange(InvalidatorState state) OVERRIDE;
344
345 private:
346 const Invalidator& invalidator_;
347 InvalidatorState last_retrieved_state_;
348
349 DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler);
350};
351
352} // namespace internal
353
354TYPED_TEST_P(InvalidatorTest, GetInvalidatorStateAlwaysCurrent) {
355 Invalidator* const invalidator = this->CreateAndInitializeInvalidator();
356
357 internal::BoundFakeInvalidationHandler handler(*invalidator);
358 invalidator->RegisterHandler(&handler);
359
360 this->delegate_.TriggerOnInvalidatorStateChange(INVALIDATIONS_ENABLED);
361 EXPECT_EQ(INVALIDATIONS_ENABLED, handler.GetInvalidatorState());
362 EXPECT_EQ(INVALIDATIONS_ENABLED, handler.GetLastRetrievedState());
363
364 this->delegate_.TriggerOnInvalidatorStateChange(TRANSIENT_INVALIDATION_ERROR);
365 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler.GetInvalidatorState());
366 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler.GetLastRetrievedState());
[email protected]4d432812012-10-05 18:03:14367
368 invalidator->UnregisterHandler(&handler);
[email protected]33596da2012-08-31 23:39:25369}
370
[email protected]33596da2012-08-31 23:39:25371REGISTER_TYPED_TEST_CASE_P(InvalidatorTest,
372 Basic, MultipleHandlers, EmptySetUnregisters,
[email protected]2e152c32013-01-29 01:37:01373 GetInvalidatorStateAlwaysCurrent);
[email protected]33596da2012-08-31 23:39:25374
375} // namespace syncer
376
[email protected]44828772014-06-06 02:56:52377#endif // COMPONENTS_INVALIDATION_INVALIDATOR_TEST_TEMPLATE_H_