| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 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 // | |
| 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 // } | |
| 45 // | |
| 46 // // The Trigger* functions below should block until the effects of | |
| 47 // // the call are visible on the current thread. | |
| 48 // | |
| 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 // } | |
| 55 // | |
| 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 // }; | |
| 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 | |
| 77 #ifndef COMPONENTS_INVALIDATION_INVALIDATOR_TEST_TEMPLATE_H_ | |
| 78 #define COMPONENTS_INVALIDATION_INVALIDATOR_TEST_TEMPLATE_H_ | |
| 79 | |
| 80 #include "base/basictypes.h" | |
| 81 #include "base/compiler_specific.h" | |
| 82 #include "components/invalidation/fake_invalidation_handler.h" | |
| 83 #include "components/invalidation/fake_invalidation_state_tracker.h" | |
| 84 #include "google/cacheinvalidation/include/types.h" | |
| 85 #include "google/cacheinvalidation/types.pb.h" | |
| 86 #include "sync/internal_api/public/base/object_id_invalidation_map_test_util.h" | |
| 87 #include "sync/notifier/invalidator.h" | |
| 88 #include "testing/gtest/include/gtest/gtest.h" | |
| 89 | |
| 90 namespace syncer { | |
| 91 | |
| 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") { | |
| 100 } | |
| 101 | |
| 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(); | |
| 107 | |
| 108 this->delegate_.WaitForInvalidator(); | |
| 109 invalidator->UpdateCredentials("foo@bar.com", "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 | |
| 124 TYPED_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. | |
| 130 TYPED_TEST_P(InvalidatorTest, Basic) { | |
| 131 Invalidator* const invalidator = this->CreateAndInitializeInvalidator(); | |
| 132 | |
| 133 FakeInvalidationHandler handler; | |
| 134 | |
| 135 invalidator->RegisterHandler(&handler); | |
| 136 | |
| 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")); | |
| 141 | |
| 142 // Should be ignored since no IDs are registered to |handler|. | |
| 143 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map); | |
| 144 EXPECT_EQ(0, handler.GetInvalidationCount()); | |
| 145 | |
| 146 ObjectIdSet ids; | |
| 147 ids.insert(this->id1); | |
| 148 ids.insert(this->id2); | |
| 149 invalidator->UpdateRegisteredIds(&handler, ids); | |
| 150 | |
| 151 this->delegate_.TriggerOnInvalidatorStateChange(INVALIDATIONS_ENABLED); | |
| 152 EXPECT_EQ(INVALIDATIONS_ENABLED, handler.GetInvalidatorState()); | |
| 153 | |
| 154 ObjectIdInvalidationMap expected_invalidations; | |
| 155 expected_invalidations.Insert(Invalidation::Init(this->id1, 1, "1")); | |
| 156 expected_invalidations.Insert(Invalidation::Init(this->id2, 2, "2")); | |
| 157 | |
| 158 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map); | |
| 159 EXPECT_EQ(1, handler.GetInvalidationCount()); | |
| 160 EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap())); | |
| 161 | |
| 162 ids.erase(this->id1); | |
| 163 ids.insert(this->id3); | |
| 164 invalidator->UpdateRegisteredIds(&handler, ids); | |
| 165 | |
| 166 expected_invalidations = ObjectIdInvalidationMap(); | |
| 167 expected_invalidations.Insert(Invalidation::Init(this->id2, 2, "2")); | |
| 168 expected_invalidations.Insert(Invalidation::Init(this->id3, 3, "3")); | |
| 169 | |
| 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())); | |
| 174 | |
| 175 this->delegate_.TriggerOnInvalidatorStateChange(TRANSIENT_INVALIDATION_ERROR); | |
| 176 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, | |
| 177 handler.GetInvalidatorState()); | |
| 178 | |
| 179 this->delegate_.TriggerOnInvalidatorStateChange( | |
| 180 INVALIDATION_CREDENTIALS_REJECTED); | |
| 181 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, | |
| 182 handler.GetInvalidatorState()); | |
| 183 | |
| 184 invalidator->UnregisterHandler(&handler); | |
| 185 | |
| 186 // Should be ignored since |handler| isn't registered anymore. | |
| 187 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map); | |
| 188 EXPECT_EQ(2, handler.GetInvalidationCount()); | |
| 189 } | |
| 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, | |
| 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(); | |
| 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 | |
| 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()); | |
| 237 | |
| 238 { | |
| 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")); | |
| 244 | |
| 245 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")); | |
| 250 | |
| 251 EXPECT_EQ(1, handler1.GetInvalidationCount()); | |
| 252 EXPECT_THAT(expected_invalidations, Eq(handler1.GetLastInvalidationMap())); | |
| 253 | |
| 254 expected_invalidations = ObjectIdInvalidationMap(); | |
| 255 expected_invalidations.Insert(Invalidation::Init(this->id3, 3, "3")); | |
| 256 | |
| 257 EXPECT_EQ(1, handler2.GetInvalidationCount()); | |
| 258 EXPECT_THAT(expected_invalidations, Eq(handler2.GetLastInvalidationMap())); | |
| 259 | |
| 260 EXPECT_EQ(0, handler3.GetInvalidationCount()); | |
| 261 EXPECT_EQ(0, handler4.GetInvalidationCount()); | |
| 262 } | |
| 263 | |
| 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()); | |
| 269 | |
| 270 invalidator->UnregisterHandler(&handler3); | |
| 271 invalidator->UnregisterHandler(&handler2); | |
| 272 invalidator->UnregisterHandler(&handler1); | |
| 273 } | |
| 274 | |
| 275 // Make sure that passing an empty set to UpdateRegisteredIds clears the | |
| 276 // corresponding entries for the handler. | |
| 277 TYPED_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 | |
| 305 this->delegate_.TriggerOnInvalidatorStateChange(INVALIDATIONS_ENABLED); | |
| 306 EXPECT_EQ(INVALIDATIONS_ENABLED, handler1.GetInvalidatorState()); | |
| 307 EXPECT_EQ(INVALIDATIONS_ENABLED, handler2.GetInvalidatorState()); | |
| 308 | |
| 309 { | |
| 310 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); | |
| 315 EXPECT_EQ(0, handler1.GetInvalidationCount()); | |
| 316 EXPECT_EQ(1, handler2.GetInvalidationCount()); | |
| 317 } | |
| 318 | |
| 319 this->delegate_.TriggerOnInvalidatorStateChange(TRANSIENT_INVALIDATION_ERROR); | |
| 320 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler1.GetInvalidatorState()); | |
| 321 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, handler2.GetInvalidatorState()); | |
| 322 | |
| 323 invalidator->UnregisterHandler(&handler2); | |
| 324 invalidator->UnregisterHandler(&handler1); | |
| 325 } | |
| 326 | |
| 327 namespace 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. | |
| 332 class 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 | |
| 354 TYPED_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()); | |
| 367 | |
| 368 invalidator->UnregisterHandler(&handler); | |
| 369 } | |
| 370 | |
| 371 REGISTER_TYPED_TEST_CASE_P(InvalidatorTest, | |
| 372 Basic, MultipleHandlers, EmptySetUnregisters, | |
| 373 GetInvalidatorStateAlwaysCurrent); | |
| 374 | |
| 375 } // namespace syncer | |
| 376 | |
| 377 #endif // COMPONENTS_INVALIDATION_INVALIDATOR_TEST_TEMPLATE_H_ | |
| OLD | NEW |