| OLD | NEW |
| (Empty) |
| 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. | |
| 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 COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_ | |
| 72 #define COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_ | |
| 73 | |
| 74 #include "base/basictypes.h" | |
| 75 #include "base/compiler_specific.h" | |
| 76 #include "components/invalidation/ack_handle.h" | |
| 77 #include "components/invalidation/fake_invalidation_handler.h" | |
| 78 #include "components/invalidation/invalidation.h" | |
| 79 #include "components/invalidation/invalidation_service.h" | |
| 80 #include "components/invalidation/object_id_invalidation_map.h" | |
| 81 #include "components/invalidation/object_id_invalidation_map_test_util.h" | |
| 82 #include "google/cacheinvalidation/include/types.h" | |
| 83 #include "google/cacheinvalidation/types.pb.h" | |
| 84 #include "testing/gtest/include/gtest/gtest.h" | |
| 85 | |
| 86 template <typename InvalidatorTestDelegate> | |
| 87 class InvalidationServiceTest : public testing::Test { | |
| 88 protected: | |
| 89 InvalidationServiceTest() | |
| 90 : id1(ipc::invalidation::ObjectSource::CHROME_SYNC, "BOOKMARK"), | |
| 91 id2(ipc::invalidation::ObjectSource::CHROME_SYNC, "PREFERENCE"), | |
| 92 id3(ipc::invalidation::ObjectSource::CHROME_SYNC, "AUTOFILL"), | |
| 93 id4(ipc::invalidation::ObjectSource::CHROME_PUSH_MESSAGING, | |
| 94 "PUSH_MESSAGE") { | |
| 95 } | |
| 96 | |
| 97 invalidation::InvalidationService* | |
| 98 CreateAndInitializeInvalidationService() { | |
| 99 this->delegate_.CreateInvalidationService(); | |
| 100 return this->delegate_.GetInvalidationService(); | |
| 101 } | |
| 102 | |
| 103 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 | |
| 111 TYPED_TEST_CASE_P(InvalidationServiceTest); | |
| 112 | |
| 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. | |
| 117 TYPED_TEST_P(InvalidationServiceTest, Basic) { | |
| 118 invalidation::InvalidationService* const invalidator = | |
| 119 this->CreateAndInitializeInvalidationService(); | |
| 120 | |
| 121 syncer::FakeInvalidationHandler handler; | |
| 122 | |
| 123 invalidator->RegisterInvalidationHandler(&handler); | |
| 124 | |
| 125 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")); | |
| 129 | |
| 130 // Should be ignored since no IDs are registered to |handler|. | |
| 131 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map); | |
| 132 EXPECT_EQ(0, handler.GetInvalidationCount()); | |
| 133 | |
| 134 syncer::ObjectIdSet ids; | |
| 135 ids.insert(this->id1); | |
| 136 ids.insert(this->id2); | |
| 137 EXPECT_TRUE(invalidator->UpdateRegisteredInvalidationIds(&handler, ids)); | |
| 138 | |
| 139 this->delegate_.TriggerOnInvalidatorStateChange( | |
| 140 syncer::INVALIDATIONS_ENABLED); | |
| 141 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState()); | |
| 142 | |
| 143 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")); | |
| 146 | |
| 147 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map); | |
| 148 EXPECT_EQ(1, handler.GetInvalidationCount()); | |
| 149 EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap())); | |
| 150 | |
| 151 ids.erase(this->id1); | |
| 152 ids.insert(this->id3); | |
| 153 EXPECT_TRUE(invalidator->UpdateRegisteredInvalidationIds(&handler, ids)); | |
| 154 | |
| 155 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")); | |
| 158 | |
| 159 // Removed object IDs should not be notified, newly-added ones should. | |
| 160 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map); | |
| 161 EXPECT_EQ(2, handler.GetInvalidationCount()); | |
| 162 EXPECT_THAT(expected_invalidations, Eq(handler.GetLastInvalidationMap())); | |
| 163 | |
| 164 this->delegate_.TriggerOnInvalidatorStateChange( | |
| 165 syncer::TRANSIENT_INVALIDATION_ERROR); | |
| 166 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR, | |
| 167 handler.GetInvalidatorState()); | |
| 168 | |
| 169 this->delegate_.TriggerOnInvalidatorStateChange( | |
| 170 syncer::INVALIDATIONS_ENABLED); | |
| 171 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, | |
| 172 handler.GetInvalidatorState()); | |
| 173 | |
| 174 invalidator->UnregisterInvalidationHandler(&handler); | |
| 175 | |
| 176 // Should be ignored since |handler| isn't registered anymore. | |
| 177 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map); | |
| 178 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. | |
| 186 TYPED_TEST_P(InvalidationServiceTest, MultipleHandlers) { | |
| 187 invalidation::InvalidationService* const invalidator = | |
| 188 this->CreateAndInitializeInvalidationService(); | |
| 189 | |
| 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 EXPECT_TRUE(invalidator->UpdateRegisteredInvalidationIds(&handler1, ids)); | |
| 205 } | |
| 206 | |
| 207 { | |
| 208 syncer::ObjectIdSet ids; | |
| 209 ids.insert(this->id3); | |
| 210 EXPECT_TRUE(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 EXPECT_TRUE(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 { | |
| 232 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); | |
| 238 | |
| 239 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")); | |
| 244 | |
| 245 EXPECT_EQ(1, handler1.GetInvalidationCount()); | |
| 246 EXPECT_THAT(expected_invalidations, Eq(handler1.GetLastInvalidationMap())); | |
| 247 | |
| 248 expected_invalidations = syncer::ObjectIdInvalidationMap(); | |
| 249 expected_invalidations.Insert( | |
| 250 syncer::Invalidation::Init(this->id3, 3, "3")); | |
| 251 | |
| 252 EXPECT_EQ(1, handler2.GetInvalidationCount()); | |
| 253 EXPECT_THAT(expected_invalidations, Eq(handler2.GetLastInvalidationMap())); | |
| 254 | |
| 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 // Multiple registrations by different handlers on the same object ID should | |
| 276 // return false. | |
| 277 TYPED_TEST_P(InvalidationServiceTest, MultipleRegistrations) { | |
| 278 invalidation::InvalidationService* const invalidator = | |
| 279 this->CreateAndInitializeInvalidationService(); | |
| 280 | |
| 281 syncer::FakeInvalidationHandler handler1; | |
| 282 syncer::FakeInvalidationHandler handler2; | |
| 283 | |
| 284 invalidator->RegisterInvalidationHandler(&handler1); | |
| 285 invalidator->RegisterInvalidationHandler(&handler2); | |
| 286 | |
| 287 // Registering both handlers for the same ObjectId. First call should succeed, | |
| 288 // second should fail. | |
| 289 syncer::ObjectIdSet ids; | |
| 290 ids.insert(this->id1); | |
| 291 EXPECT_TRUE(invalidator->UpdateRegisteredInvalidationIds(&handler1, ids)); | |
| 292 EXPECT_FALSE(invalidator->UpdateRegisteredInvalidationIds(&handler2, ids)); | |
| 293 | |
| 294 invalidator->UnregisterInvalidationHandler(&handler2); | |
| 295 invalidator->UnregisterInvalidationHandler(&handler1); | |
| 296 } | |
| 297 | |
| 298 // Make sure that passing an empty set to UpdateRegisteredInvalidationIds clears | |
| 299 // the corresponding entries for the handler. | |
| 300 TYPED_TEST_P(InvalidationServiceTest, EmptySetUnregisters) { | |
| 301 invalidation::InvalidationService* const invalidator = | |
| 302 this->CreateAndInitializeInvalidationService(); | |
| 303 | |
| 304 syncer::FakeInvalidationHandler handler1; | |
| 305 | |
| 306 // Control observer. | |
| 307 syncer::FakeInvalidationHandler handler2; | |
| 308 | |
| 309 invalidator->RegisterInvalidationHandler(&handler1); | |
| 310 invalidator->RegisterInvalidationHandler(&handler2); | |
| 311 | |
| 312 { | |
| 313 syncer::ObjectIdSet ids; | |
| 314 ids.insert(this->id1); | |
| 315 ids.insert(this->id2); | |
| 316 EXPECT_TRUE(invalidator->UpdateRegisteredInvalidationIds(&handler1, ids)); | |
| 317 } | |
| 318 | |
| 319 { | |
| 320 syncer::ObjectIdSet ids; | |
| 321 ids.insert(this->id3); | |
| 322 EXPECT_TRUE(invalidator->UpdateRegisteredInvalidationIds(&handler2, ids)); | |
| 323 } | |
| 324 | |
| 325 // Unregister the IDs for the first observer. It should not receive any | |
| 326 // further invalidations. | |
| 327 EXPECT_TRUE(invalidator->UpdateRegisteredInvalidationIds( | |
| 328 &handler1, syncer::ObjectIdSet())); | |
| 329 | |
| 330 this->delegate_.TriggerOnInvalidatorStateChange( | |
| 331 syncer::INVALIDATIONS_ENABLED); | |
| 332 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler1.GetInvalidatorState()); | |
| 333 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler2.GetInvalidatorState()); | |
| 334 | |
| 335 { | |
| 336 syncer::ObjectIdInvalidationMap invalidation_map; | |
| 337 invalidation_map.Insert(syncer::Invalidation::Init(this->id1, 1, "1")); | |
| 338 invalidation_map.Insert(syncer::Invalidation::Init(this->id2, 2, "2")); | |
| 339 invalidation_map.Insert(syncer::Invalidation::Init(this->id3, 3, "3")); | |
| 340 this->delegate_.TriggerOnIncomingInvalidation(invalidation_map); | |
| 341 EXPECT_EQ(0, handler1.GetInvalidationCount()); | |
| 342 EXPECT_EQ(1, handler2.GetInvalidationCount()); | |
| 343 } | |
| 344 | |
| 345 this->delegate_.TriggerOnInvalidatorStateChange( | |
| 346 syncer::TRANSIENT_INVALIDATION_ERROR); | |
| 347 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR, | |
| 348 handler1.GetInvalidatorState()); | |
| 349 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR, | |
| 350 handler2.GetInvalidatorState()); | |
| 351 | |
| 352 invalidator->UnregisterInvalidationHandler(&handler2); | |
| 353 invalidator->UnregisterInvalidationHandler(&handler1); | |
| 354 } | |
| 355 | |
| 356 namespace internal { | |
| 357 | |
| 358 // A FakeInvalidationHandler that is "bound" to a specific | |
| 359 // InvalidationService. This is for cross-referencing state information with | |
| 360 // the bound InvalidationService. | |
| 361 class BoundFakeInvalidationHandler : public syncer::FakeInvalidationHandler { | |
| 362 public: | |
| 363 explicit BoundFakeInvalidationHandler( | |
| 364 const invalidation::InvalidationService& invalidator); | |
| 365 ~BoundFakeInvalidationHandler() override; | |
| 366 | |
| 367 // Returns the last return value of GetInvalidatorState() on the | |
| 368 // bound invalidator from the last time the invalidator state | |
| 369 // changed. | |
| 370 syncer::InvalidatorState GetLastRetrievedState() const; | |
| 371 | |
| 372 // InvalidationHandler implementation. | |
| 373 void OnInvalidatorStateChange(syncer::InvalidatorState state) override; | |
| 374 | |
| 375 private: | |
| 376 const invalidation::InvalidationService& invalidator_; | |
| 377 syncer::InvalidatorState last_retrieved_state_; | |
| 378 | |
| 379 DISALLOW_COPY_AND_ASSIGN(BoundFakeInvalidationHandler); | |
| 380 }; | |
| 381 | |
| 382 } // namespace internal | |
| 383 | |
| 384 TYPED_TEST_P(InvalidationServiceTest, GetInvalidatorStateAlwaysCurrent) { | |
| 385 invalidation::InvalidationService* const invalidator = | |
| 386 this->CreateAndInitializeInvalidationService(); | |
| 387 | |
| 388 internal::BoundFakeInvalidationHandler handler(*invalidator); | |
| 389 invalidator->RegisterInvalidationHandler(&handler); | |
| 390 | |
| 391 this->delegate_.TriggerOnInvalidatorStateChange( | |
| 392 syncer::INVALIDATIONS_ENABLED); | |
| 393 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetInvalidatorState()); | |
| 394 EXPECT_EQ(syncer::INVALIDATIONS_ENABLED, handler.GetLastRetrievedState()); | |
| 395 | |
| 396 this->delegate_.TriggerOnInvalidatorStateChange( | |
| 397 syncer::TRANSIENT_INVALIDATION_ERROR); | |
| 398 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR, | |
| 399 handler.GetInvalidatorState()); | |
| 400 EXPECT_EQ(syncer::TRANSIENT_INVALIDATION_ERROR, | |
| 401 handler.GetLastRetrievedState()); | |
| 402 | |
| 403 invalidator->UnregisterInvalidationHandler(&handler); | |
| 404 } | |
| 405 | |
| 406 REGISTER_TYPED_TEST_CASE_P(InvalidationServiceTest, | |
| 407 Basic, | |
| 408 MultipleHandlers, | |
| 409 MultipleRegistrations, | |
| 410 EmptySetUnregisters, | |
| 411 GetInvalidatorStateAlwaysCurrent); | |
| 412 | |
| 413 #endif // COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_TEST_TEMPLATE_H_ | |
| OLD | NEW |