| 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 #include <cstddef> | |
| 6 #include <set> | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/compiler_specific.h" | |
| 10 #include "base/message_loop.h" | |
| 11 #include "google/cacheinvalidation/include/invalidation-client.h" | |
| 12 #include "google/cacheinvalidation/include/types.h" | |
| 13 #include "jingle/notifier/listener/fake_push_client.h" | |
| 14 #include "sync/internal_api/public/util/weak_handle.h" | |
| 15 #include "sync/notifier/chrome_invalidation_client.h" | |
| 16 #include "sync/notifier/fake_invalidation_state_tracker.h" | |
| 17 #include "sync/notifier/invalidation_util.h" | |
| 18 #include "testing/gtest/include/gtest/gtest.h" | |
| 19 | |
| 20 namespace syncer { | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 using invalidation::AckHandle; | |
| 25 using invalidation::ObjectId; | |
| 26 | |
| 27 const char kClientId[] = "client_id"; | |
| 28 const char kClientInfo[] = "client_info"; | |
| 29 | |
| 30 const char kState[] = "state"; | |
| 31 const char kNewState[] = "new_state"; | |
| 32 | |
| 33 const char kPayload1[] = "payload1"; | |
| 34 const char kPayload2[] = "payload2"; | |
| 35 | |
| 36 const int64 kMinVersion = FakeInvalidationStateTracker::kMinVersion; | |
| 37 const int64 kVersion1 = 1LL; | |
| 38 const int64 kVersion2 = 2LL; | |
| 39 | |
| 40 const int kChromeSyncSourceId = 1004; | |
| 41 | |
| 42 struct AckHandleLessThan { | |
| 43 bool operator()(const AckHandle& lhs, const AckHandle& rhs) const { | |
| 44 return lhs.handle_data() < rhs.handle_data(); | |
| 45 } | |
| 46 }; | |
| 47 | |
| 48 typedef std::set<AckHandle, AckHandleLessThan> AckHandleSet; | |
| 49 | |
| 50 // Fake invalidation::InvalidationClient implementation that keeps | |
| 51 // track of registered IDs and acked handles. | |
| 52 class FakeInvalidationClient : public invalidation::InvalidationClient { | |
| 53 public: | |
| 54 FakeInvalidationClient() : started_(false) {} | |
| 55 virtual ~FakeInvalidationClient() {} | |
| 56 | |
| 57 const ObjectIdSet& GetRegisteredIds() const { | |
| 58 return registered_ids_; | |
| 59 } | |
| 60 | |
| 61 void ClearAckedHandles() { | |
| 62 acked_handles_.clear(); | |
| 63 } | |
| 64 | |
| 65 bool IsAckedHandle(const AckHandle& ack_handle) const { | |
| 66 return (acked_handles_.find(ack_handle) != acked_handles_.end()); | |
| 67 } | |
| 68 | |
| 69 // invalidation::InvalidationClient implementation. | |
| 70 | |
| 71 virtual void Start() OVERRIDE { | |
| 72 started_ = true; | |
| 73 } | |
| 74 | |
| 75 virtual void Stop() OVERRIDE { | |
| 76 started_ = false; | |
| 77 } | |
| 78 | |
| 79 virtual void Register(const ObjectId& object_id) OVERRIDE { | |
| 80 if (!started_) { | |
| 81 ADD_FAILURE(); | |
| 82 return; | |
| 83 } | |
| 84 registered_ids_.insert(object_id); | |
| 85 } | |
| 86 | |
| 87 virtual void Register( | |
| 88 const invalidation::vector<ObjectId>& object_ids) OVERRIDE { | |
| 89 if (!started_) { | |
| 90 ADD_FAILURE(); | |
| 91 return; | |
| 92 } | |
| 93 registered_ids_.insert(object_ids.begin(), object_ids.end()); | |
| 94 } | |
| 95 | |
| 96 virtual void Unregister(const ObjectId& object_id) OVERRIDE { | |
| 97 if (!started_) { | |
| 98 ADD_FAILURE(); | |
| 99 return; | |
| 100 } | |
| 101 registered_ids_.erase(object_id); | |
| 102 } | |
| 103 | |
| 104 virtual void Unregister( | |
| 105 const invalidation::vector<ObjectId>& object_ids) OVERRIDE { | |
| 106 if (!started_) { | |
| 107 ADD_FAILURE(); | |
| 108 return; | |
| 109 } | |
| 110 for (invalidation::vector<ObjectId>::const_iterator | |
| 111 it = object_ids.begin(); it != object_ids.end(); ++it) { | |
| 112 registered_ids_.erase(*it); | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 virtual void Acknowledge(const AckHandle& ack_handle) OVERRIDE { | |
| 117 if (!started_) { | |
| 118 ADD_FAILURE(); | |
| 119 return; | |
| 120 } | |
| 121 acked_handles_.insert(ack_handle); | |
| 122 } | |
| 123 | |
| 124 private: | |
| 125 bool started_; | |
| 126 ObjectIdSet registered_ids_; | |
| 127 AckHandleSet acked_handles_; | |
| 128 }; | |
| 129 | |
| 130 // Fake listener tkat keeps track of invalidation counts, payloads, | |
| 131 // and state. | |
| 132 class FakeListener : public ChromeInvalidationClient::Listener { | |
| 133 public: | |
| 134 FakeListener() : reason_(TRANSIENT_NOTIFICATION_ERROR) {} | |
| 135 virtual ~FakeListener() {} | |
| 136 | |
| 137 int GetInvalidationCount(const ObjectId& id) const { | |
| 138 ObjectIdCountMap::const_iterator it = invalidation_counts_.find(id); | |
| 139 return (it == invalidation_counts_.end()) ? 0 : it->second; | |
| 140 } | |
| 141 | |
| 142 std::string GetPayload(const ObjectId& id) const { | |
| 143 ObjectIdStateMap::const_iterator it = states_.find(id); | |
| 144 return (it == states_.end()) ? "" : it->second.payload; | |
| 145 } | |
| 146 | |
| 147 // NO_NOTIFICATION_ERROR is the enabled state. | |
| 148 NotificationsDisabledReason GetNotificationsDisabledReason() const { | |
| 149 return reason_; | |
| 150 } | |
| 151 | |
| 152 // ChromeInvalidationClient::Listener implementation. | |
| 153 | |
| 154 virtual void OnInvalidate(const ObjectIdStateMap& id_state_map) OVERRIDE { | |
| 155 for (ObjectIdStateMap::const_iterator it = id_state_map.begin(); | |
| 156 it != id_state_map.end(); ++it) { | |
| 157 ++invalidation_counts_[it->first]; | |
| 158 states_[it->first] = it->second; | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 virtual void OnNotificationsEnabled() { | |
| 163 reason_ = NO_NOTIFICATION_ERROR; | |
| 164 } | |
| 165 | |
| 166 virtual void OnNotificationsDisabled(NotificationsDisabledReason reason) { | |
| 167 reason_ = reason; | |
| 168 } | |
| 169 | |
| 170 private: | |
| 171 typedef std::map<ObjectId, int, ObjectIdLessThan> ObjectIdCountMap; | |
| 172 ObjectIdCountMap invalidation_counts_; | |
| 173 ObjectIdStateMap states_; | |
| 174 NotificationsDisabledReason reason_; | |
| 175 }; | |
| 176 | |
| 177 invalidation::InvalidationClient* CreateFakeInvalidationClient( | |
| 178 FakeInvalidationClient** fake_invalidation_client, | |
| 179 invalidation::SystemResources* resources, | |
| 180 int client_type, | |
| 181 const invalidation::string& client_name, | |
| 182 const invalidation::string& application_name, | |
| 183 invalidation::InvalidationListener* listener) { | |
| 184 *fake_invalidation_client = new FakeInvalidationClient(); | |
| 185 return *fake_invalidation_client; | |
| 186 } | |
| 187 | |
| 188 class ChromeInvalidationClientTest : public testing::Test { | |
| 189 protected: | |
| 190 ChromeInvalidationClientTest() | |
| 191 : kBookmarksId_(kChromeSyncSourceId, "BOOKMARK"), | |
| 192 kPreferencesId_(kChromeSyncSourceId, "PREFERENCE"), | |
| 193 kExtensionsId_(kChromeSyncSourceId, "EXTENSION"), | |
| 194 kAppsId_(kChromeSyncSourceId, "APP"), | |
| 195 fake_push_client_(new notifier::FakePushClient()), | |
| 196 fake_invalidation_client_(NULL), | |
| 197 client_(scoped_ptr<notifier::PushClient>(fake_push_client_)) {} | |
| 198 | |
| 199 virtual void SetUp() { | |
| 200 StartClient(); | |
| 201 | |
| 202 registered_ids_.insert(kBookmarksId_); | |
| 203 registered_ids_.insert(kPreferencesId_); | |
| 204 client_.UpdateRegisteredIds(registered_ids_); | |
| 205 } | |
| 206 | |
| 207 virtual void TearDown() { | |
| 208 StopClient(); | |
| 209 } | |
| 210 | |
| 211 // Restart client without re-registering IDs. | |
| 212 void RestartClient() { | |
| 213 StopClient(); | |
| 214 StartClient(); | |
| 215 } | |
| 216 | |
| 217 int GetInvalidationCount(const ObjectId& id) const { | |
| 218 return fake_listener_.GetInvalidationCount(id); | |
| 219 } | |
| 220 | |
| 221 std::string GetPayload(const ObjectId& id) const { | |
| 222 return fake_listener_.GetPayload(id); | |
| 223 } | |
| 224 | |
| 225 NotificationsDisabledReason GetNotificationsDisabledReason() const { | |
| 226 return fake_listener_.GetNotificationsDisabledReason(); | |
| 227 } | |
| 228 | |
| 229 int64 GetMaxVersion(const ObjectId& id) const { | |
| 230 return fake_tracker_.GetMaxVersion(id); | |
| 231 } | |
| 232 | |
| 233 std::string GetInvalidationState() const { | |
| 234 return fake_tracker_.GetInvalidationState(); | |
| 235 } | |
| 236 | |
| 237 ObjectIdSet GetRegisteredIds() const { | |
| 238 return fake_invalidation_client_->GetRegisteredIds(); | |
| 239 } | |
| 240 | |
| 241 // |payload| can be NULL. | |
| 242 void FireInvalidate(const ObjectId& object_id, | |
| 243 int64 version, const char* payload) { | |
| 244 invalidation::Invalidation inv; | |
| 245 if (payload) { | |
| 246 inv = invalidation::Invalidation(object_id, version, payload); | |
| 247 } else { | |
| 248 inv = invalidation::Invalidation(object_id, version); | |
| 249 } | |
| 250 const AckHandle ack_handle("fakedata"); | |
| 251 fake_invalidation_client_->ClearAckedHandles(); | |
| 252 client_.Invalidate(fake_invalidation_client_, inv, ack_handle); | |
| 253 EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle)); | |
| 254 // Pump message loop to trigger | |
| 255 // InvalidationStateTracker::SetMaxVersion(). | |
| 256 message_loop_.RunAllPending(); | |
| 257 } | |
| 258 | |
| 259 // |payload| can be NULL, but not |type_name|. | |
| 260 void FireInvalidateUnknownVersion(const ObjectId& object_id) { | |
| 261 const AckHandle ack_handle("fakedata_unknown"); | |
| 262 fake_invalidation_client_->ClearAckedHandles(); | |
| 263 client_.InvalidateUnknownVersion(fake_invalidation_client_, object_id, | |
| 264 ack_handle); | |
| 265 EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle)); | |
| 266 } | |
| 267 | |
| 268 void FireInvalidateAll() { | |
| 269 const AckHandle ack_handle("fakedata_all"); | |
| 270 fake_invalidation_client_->ClearAckedHandles(); | |
| 271 client_.InvalidateAll(fake_invalidation_client_, ack_handle); | |
| 272 EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle)); | |
| 273 } | |
| 274 | |
| 275 void WriteState(const std::string& new_state) { | |
| 276 client_.WriteState(new_state); | |
| 277 // Pump message loop to trigger | |
| 278 // InvalidationStateTracker::WriteState(). | |
| 279 message_loop_.RunAllPending(); | |
| 280 } | |
| 281 | |
| 282 void EnableNotifications() { | |
| 283 fake_push_client_->EnableNotifications(); | |
| 284 } | |
| 285 | |
| 286 void DisableNotifications(notifier::NotificationsDisabledReason reason) { | |
| 287 fake_push_client_->DisableNotifications(reason); | |
| 288 } | |
| 289 | |
| 290 const ObjectId kBookmarksId_; | |
| 291 const ObjectId kPreferencesId_; | |
| 292 const ObjectId kExtensionsId_; | |
| 293 const ObjectId kAppsId_; | |
| 294 | |
| 295 ObjectIdSet registered_ids_; | |
| 296 | |
| 297 private: | |
| 298 void StartClient() { | |
| 299 fake_invalidation_client_ = NULL; | |
| 300 client_.Start(base::Bind(&CreateFakeInvalidationClient, | |
| 301 &fake_invalidation_client_), | |
| 302 kClientId, kClientInfo, kState, | |
| 303 InvalidationVersionMap(), | |
| 304 MakeWeakHandle(fake_tracker_.AsWeakPtr()), | |
| 305 &fake_listener_); | |
| 306 DCHECK(fake_invalidation_client_); | |
| 307 } | |
| 308 | |
| 309 void StopClient() { | |
| 310 // client_.StopForTest() stops the invalidation scheduler, which | |
| 311 // deletes any pending tasks without running them. Some tasks | |
| 312 // "run and delete" another task, so they must be run in order to | |
| 313 // avoid leaking the inner task. client_.StopForTest() does not | |
| 314 // schedule any tasks, so it's both necessary and sufficient to | |
| 315 // drain the task queue before calling it. | |
| 316 message_loop_.RunAllPending(); | |
| 317 fake_invalidation_client_ = NULL; | |
| 318 client_.StopForTest(); | |
| 319 } | |
| 320 | |
| 321 MessageLoop message_loop_; | |
| 322 | |
| 323 FakeListener fake_listener_; | |
| 324 FakeInvalidationStateTracker fake_tracker_; | |
| 325 notifier::FakePushClient* const fake_push_client_; | |
| 326 | |
| 327 protected: | |
| 328 // Tests need to access these directly. | |
| 329 FakeInvalidationClient* fake_invalidation_client_; | |
| 330 ChromeInvalidationClient client_; | |
| 331 }; | |
| 332 | |
| 333 // Write a new state to the client. It should propagate to the | |
| 334 // tracker. | |
| 335 TEST_F(ChromeInvalidationClientTest, WriteState) { | |
| 336 WriteState(kNewState); | |
| 337 | |
| 338 EXPECT_EQ(kNewState, GetInvalidationState()); | |
| 339 } | |
| 340 | |
| 341 // Invalidation tests. | |
| 342 | |
| 343 // Fire an invalidation without a payload. It should be processed, | |
| 344 // the payload should remain empty, and the version should be updated. | |
| 345 TEST_F(ChromeInvalidationClientTest, InvalidateNoPayload) { | |
| 346 const ObjectId& id = kBookmarksId_; | |
| 347 | |
| 348 FireInvalidate(id, kVersion1, NULL); | |
| 349 | |
| 350 EXPECT_EQ(1, GetInvalidationCount(id)); | |
| 351 EXPECT_EQ("", GetPayload(id)); | |
| 352 EXPECT_EQ(kVersion1, GetMaxVersion(id)); | |
| 353 } | |
| 354 | |
| 355 // Fire an invalidation with an empty payload. It should be | |
| 356 // processed, the payload should remain empty, and the version should | |
| 357 // be updated. | |
| 358 TEST_F(ChromeInvalidationClientTest, InvalidateEmptyPayload) { | |
| 359 const ObjectId& id = kBookmarksId_; | |
| 360 | |
| 361 FireInvalidate(id, kVersion1, ""); | |
| 362 | |
| 363 EXPECT_EQ(1, GetInvalidationCount(id)); | |
| 364 EXPECT_EQ("", GetPayload(id)); | |
| 365 EXPECT_EQ(kVersion1, GetMaxVersion(id)); | |
| 366 } | |
| 367 | |
| 368 // Fire an invalidation with a payload. It should be processed, and | |
| 369 // both the payload and the version should be updated. | |
| 370 TEST_F(ChromeInvalidationClientTest, InvalidateWithPayload) { | |
| 371 const ObjectId& id = kPreferencesId_; | |
| 372 | |
| 373 FireInvalidate(id, kVersion1, kPayload1); | |
| 374 | |
| 375 EXPECT_EQ(1, GetInvalidationCount(id)); | |
| 376 EXPECT_EQ(kPayload1, GetPayload(id)); | |
| 377 EXPECT_EQ(kVersion1, GetMaxVersion(id)); | |
| 378 } | |
| 379 | |
| 380 // Fire an invalidation with a payload. It should still be processed, | |
| 381 // and both the payload and the version should be updated. | |
| 382 TEST_F(ChromeInvalidationClientTest, InvalidateUnregistered) { | |
| 383 const ObjectId kUnregisteredId( | |
| 384 kChromeSyncSourceId, "unregistered"); | |
| 385 const ObjectId& id = kUnregisteredId; | |
| 386 | |
| 387 EXPECT_EQ(0, GetInvalidationCount(id)); | |
| 388 EXPECT_EQ("", GetPayload(id)); | |
| 389 EXPECT_EQ(kMinVersion, GetMaxVersion(id)); | |
| 390 | |
| 391 FireInvalidate(id, kVersion1, NULL); | |
| 392 | |
| 393 EXPECT_EQ(1, GetInvalidationCount(id)); | |
| 394 EXPECT_EQ("", GetPayload(id)); | |
| 395 EXPECT_EQ(kVersion1, GetMaxVersion(id)); | |
| 396 } | |
| 397 | |
| 398 // Fire an invalidation, then fire another one with a lower version. | |
| 399 // The first one should be processed and should update the payload and | |
| 400 // version, but the second one shouldn't. | |
| 401 TEST_F(ChromeInvalidationClientTest, InvalidateVersion) { | |
| 402 const ObjectId& id = kPreferencesId_; | |
| 403 | |
| 404 FireInvalidate(id, kVersion2, kPayload2); | |
| 405 | |
| 406 EXPECT_EQ(1, GetInvalidationCount(id)); | |
| 407 EXPECT_EQ(kPayload2, GetPayload(id)); | |
| 408 EXPECT_EQ(kVersion2, GetMaxVersion(id)); | |
| 409 | |
| 410 FireInvalidate(id, kVersion1, kPayload1); | |
| 411 | |
| 412 EXPECT_EQ(1, GetInvalidationCount(id)); | |
| 413 EXPECT_EQ(kPayload2, GetPayload(id)); | |
| 414 EXPECT_EQ(kVersion2, GetMaxVersion(id)); | |
| 415 } | |
| 416 | |
| 417 // Fire an invalidation with an unknown version twice. It shouldn't | |
| 418 // update the payload or version either time, but it should still be | |
| 419 // processed. | |
| 420 TEST_F(ChromeInvalidationClientTest, InvalidateUnknownVersion) { | |
| 421 const ObjectId& id = kBookmarksId_; | |
| 422 | |
| 423 FireInvalidateUnknownVersion(id); | |
| 424 | |
| 425 EXPECT_EQ(1, GetInvalidationCount(id)); | |
| 426 EXPECT_EQ("", GetPayload(id)); | |
| 427 EXPECT_EQ(kMinVersion, GetMaxVersion(id)); | |
| 428 | |
| 429 FireInvalidateUnknownVersion(id); | |
| 430 | |
| 431 EXPECT_EQ(2, GetInvalidationCount(id)); | |
| 432 EXPECT_EQ("", GetPayload(id)); | |
| 433 EXPECT_EQ(kMinVersion, GetMaxVersion(id)); | |
| 434 } | |
| 435 | |
| 436 // Fire an invalidation for all enabled IDs. It shouldn't update the | |
| 437 // payload or version, but it should still invalidate the IDs. | |
| 438 TEST_F(ChromeInvalidationClientTest, InvalidateAll) { | |
| 439 FireInvalidateAll(); | |
| 440 | |
| 441 for (ObjectIdSet::const_iterator it = registered_ids_.begin(); | |
| 442 it != registered_ids_.end(); ++it) { | |
| 443 EXPECT_EQ(1, GetInvalidationCount(*it)); | |
| 444 EXPECT_EQ("", GetPayload(*it)); | |
| 445 EXPECT_EQ(kMinVersion, GetMaxVersion(*it)); | |
| 446 } | |
| 447 } | |
| 448 | |
| 449 // Comprehensive test of various scenarios for multiple IDs. | |
| 450 TEST_F(ChromeInvalidationClientTest, InvalidateMultipleIds) { | |
| 451 FireInvalidate(kBookmarksId_, 3, NULL); | |
| 452 | |
| 453 EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_)); | |
| 454 EXPECT_EQ("", GetPayload(kBookmarksId_)); | |
| 455 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_)); | |
| 456 | |
| 457 FireInvalidate(kExtensionsId_, 2, NULL); | |
| 458 | |
| 459 EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_)); | |
| 460 EXPECT_EQ("", GetPayload(kExtensionsId_)); | |
| 461 EXPECT_EQ(2, GetMaxVersion(kExtensionsId_)); | |
| 462 | |
| 463 // Invalidations with lower version numbers should be ignored. | |
| 464 | |
| 465 FireInvalidate(kBookmarksId_, 1, NULL); | |
| 466 | |
| 467 EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_)); | |
| 468 EXPECT_EQ("", GetPayload(kBookmarksId_)); | |
| 469 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_)); | |
| 470 | |
| 471 FireInvalidate(kExtensionsId_, 1, NULL); | |
| 472 | |
| 473 EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_)); | |
| 474 EXPECT_EQ("", GetPayload(kExtensionsId_)); | |
| 475 EXPECT_EQ(2, GetMaxVersion(kExtensionsId_)); | |
| 476 | |
| 477 // InvalidateAll shouldn't change any version state. | |
| 478 | |
| 479 FireInvalidateAll(); | |
| 480 | |
| 481 EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_)); | |
| 482 EXPECT_EQ("", GetPayload(kBookmarksId_)); | |
| 483 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_)); | |
| 484 | |
| 485 EXPECT_EQ(1, GetInvalidationCount(kPreferencesId_)); | |
| 486 EXPECT_EQ("", GetPayload(kPreferencesId_)); | |
| 487 EXPECT_EQ(kMinVersion, GetMaxVersion(kPreferencesId_)); | |
| 488 | |
| 489 EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_)); | |
| 490 EXPECT_EQ("", GetPayload(kExtensionsId_)); | |
| 491 EXPECT_EQ(2, GetMaxVersion(kExtensionsId_)); | |
| 492 | |
| 493 // Invalidations with higher version numbers should be processed. | |
| 494 | |
| 495 FireInvalidate(kPreferencesId_, 5, NULL); | |
| 496 EXPECT_EQ(2, GetInvalidationCount(kPreferencesId_)); | |
| 497 EXPECT_EQ("", GetPayload(kPreferencesId_)); | |
| 498 EXPECT_EQ(5, GetMaxVersion(kPreferencesId_)); | |
| 499 | |
| 500 FireInvalidate(kExtensionsId_, 3, NULL); | |
| 501 EXPECT_EQ(2, GetInvalidationCount(kExtensionsId_)); | |
| 502 EXPECT_EQ("", GetPayload(kExtensionsId_)); | |
| 503 EXPECT_EQ(3, GetMaxVersion(kExtensionsId_)); | |
| 504 | |
| 505 FireInvalidate(kBookmarksId_, 4, NULL); | |
| 506 EXPECT_EQ(3, GetInvalidationCount(kBookmarksId_)); | |
| 507 EXPECT_EQ("", GetPayload(kBookmarksId_)); | |
| 508 EXPECT_EQ(4, GetMaxVersion(kBookmarksId_)); | |
| 509 } | |
| 510 | |
| 511 // Registration tests. | |
| 512 | |
| 513 // With IDs already registered, enable notifications then ready the | |
| 514 // client. The IDs should be registered only after the client is | |
| 515 // readied. | |
| 516 TEST_F(ChromeInvalidationClientTest, RegisterEnableReady) { | |
| 517 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 518 | |
| 519 EnableNotifications(); | |
| 520 | |
| 521 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 522 | |
| 523 client_.Ready(fake_invalidation_client_); | |
| 524 | |
| 525 EXPECT_EQ(registered_ids_, GetRegisteredIds()); | |
| 526 } | |
| 527 | |
| 528 // With IDs already registered, ready the client then enable | |
| 529 // notifications. The IDs should be registered after the client is | |
| 530 // readied. | |
| 531 TEST_F(ChromeInvalidationClientTest, RegisterReadyEnable) { | |
| 532 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 533 | |
| 534 client_.Ready(fake_invalidation_client_); | |
| 535 | |
| 536 EXPECT_EQ(registered_ids_, GetRegisteredIds()); | |
| 537 | |
| 538 EnableNotifications(); | |
| 539 | |
| 540 EXPECT_EQ(registered_ids_, GetRegisteredIds()); | |
| 541 } | |
| 542 | |
| 543 // Unregister the IDs, enable notifications, re-register the IDs, then | |
| 544 // ready the client. The IDs should be registered only after the | |
| 545 // client is readied. | |
| 546 TEST_F(ChromeInvalidationClientTest, EnableRegisterReady) { | |
| 547 client_.UpdateRegisteredIds(ObjectIdSet()); | |
| 548 | |
| 549 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 550 | |
| 551 EnableNotifications(); | |
| 552 | |
| 553 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 554 | |
| 555 client_.UpdateRegisteredIds(registered_ids_); | |
| 556 | |
| 557 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 558 | |
| 559 client_.Ready(fake_invalidation_client_); | |
| 560 | |
| 561 EXPECT_EQ(registered_ids_, GetRegisteredIds()); | |
| 562 } | |
| 563 | |
| 564 // Unregister the IDs, enable notifications, ready the client, then | |
| 565 // re-register the IDs. The IDs should be registered only after the | |
| 566 // client is readied. | |
| 567 TEST_F(ChromeInvalidationClientTest, EnableReadyRegister) { | |
| 568 client_.UpdateRegisteredIds(ObjectIdSet()); | |
| 569 | |
| 570 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 571 | |
| 572 EnableNotifications(); | |
| 573 | |
| 574 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 575 | |
| 576 client_.Ready(fake_invalidation_client_); | |
| 577 | |
| 578 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 579 | |
| 580 client_.UpdateRegisteredIds(registered_ids_); | |
| 581 | |
| 582 EXPECT_EQ(registered_ids_, GetRegisteredIds()); | |
| 583 } | |
| 584 | |
| 585 // Unregister the IDs, ready the client, enable notifications, then | |
| 586 // re-register the IDs. The IDs should be registered only after the | |
| 587 // client is readied. | |
| 588 TEST_F(ChromeInvalidationClientTest, ReadyEnableRegister) { | |
| 589 client_.UpdateRegisteredIds(ObjectIdSet()); | |
| 590 | |
| 591 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 592 | |
| 593 EnableNotifications(); | |
| 594 | |
| 595 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 596 | |
| 597 client_.Ready(fake_invalidation_client_); | |
| 598 | |
| 599 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 600 | |
| 601 client_.UpdateRegisteredIds(registered_ids_); | |
| 602 | |
| 603 EXPECT_EQ(registered_ids_, GetRegisteredIds()); | |
| 604 } | |
| 605 | |
| 606 // Unregister the IDs, ready the client, re-register the IDs, then | |
| 607 // enable notifications. The IDs should be registered only after the | |
| 608 // client is readied. | |
| 609 // | |
| 610 // This test is important: see http://crbug.com/139424. | |
| 611 TEST_F(ChromeInvalidationClientTest, ReadyRegisterEnable) { | |
| 612 client_.UpdateRegisteredIds(ObjectIdSet()); | |
| 613 | |
| 614 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 615 | |
| 616 client_.Ready(fake_invalidation_client_); | |
| 617 | |
| 618 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 619 | |
| 620 client_.UpdateRegisteredIds(registered_ids_); | |
| 621 | |
| 622 EXPECT_EQ(registered_ids_, GetRegisteredIds()); | |
| 623 | |
| 624 EnableNotifications(); | |
| 625 | |
| 626 EXPECT_EQ(registered_ids_, GetRegisteredIds()); | |
| 627 } | |
| 628 | |
| 629 // With IDs already registered, ready the client, restart the client, | |
| 630 // then re-ready it. The IDs should still be registered. | |
| 631 TEST_F(ChromeInvalidationClientTest, RegisterTypesPreserved) { | |
| 632 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 633 | |
| 634 client_.Ready(fake_invalidation_client_); | |
| 635 | |
| 636 EXPECT_EQ(registered_ids_, GetRegisteredIds()); | |
| 637 | |
| 638 RestartClient(); | |
| 639 | |
| 640 EXPECT_TRUE(GetRegisteredIds().empty()); | |
| 641 | |
| 642 client_.Ready(fake_invalidation_client_); | |
| 643 | |
| 644 EXPECT_EQ(registered_ids_, GetRegisteredIds()); | |
| 645 } | |
| 646 | |
| 647 // Without readying the client, disable notifications, then enable | |
| 648 // them. The listener should still think notifications are disabled. | |
| 649 TEST_F(ChromeInvalidationClientTest, EnableNotificationsNotReady) { | |
| 650 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, | |
| 651 GetNotificationsDisabledReason()); | |
| 652 | |
| 653 DisableNotifications( | |
| 654 notifier::TRANSIENT_NOTIFICATION_ERROR); | |
| 655 | |
| 656 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, | |
| 657 GetNotificationsDisabledReason()); | |
| 658 | |
| 659 DisableNotifications( | |
| 660 notifier::NOTIFICATION_CREDENTIALS_REJECTED); | |
| 661 | |
| 662 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED, | |
| 663 GetNotificationsDisabledReason()); | |
| 664 | |
| 665 EnableNotifications(); | |
| 666 | |
| 667 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, | |
| 668 GetNotificationsDisabledReason()); | |
| 669 } | |
| 670 | |
| 671 // Enable notifications then Ready the invalidation client. The | |
| 672 // listener should then be ready. | |
| 673 TEST_F(ChromeInvalidationClientTest, EnableNotificationsThenReady) { | |
| 674 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, GetNotificationsDisabledReason()); | |
| 675 | |
| 676 EnableNotifications(); | |
| 677 | |
| 678 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, GetNotificationsDisabledReason()); | |
| 679 | |
| 680 client_.Ready(fake_invalidation_client_); | |
| 681 | |
| 682 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason()); | |
| 683 } | |
| 684 | |
| 685 // Ready the invalidation client then enable notifications. The | |
| 686 // listener should then be ready. | |
| 687 TEST_F(ChromeInvalidationClientTest, ReadyThenEnableNotifications) { | |
| 688 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, GetNotificationsDisabledReason()); | |
| 689 | |
| 690 client_.Ready(fake_invalidation_client_); | |
| 691 | |
| 692 EXPECT_EQ(TRANSIENT_NOTIFICATION_ERROR, GetNotificationsDisabledReason()); | |
| 693 | |
| 694 EnableNotifications(); | |
| 695 | |
| 696 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason()); | |
| 697 } | |
| 698 | |
| 699 // Enable notifications and ready the client. Then disable | |
| 700 // notifications with an auth error and re-enable notifications. The | |
| 701 // listener should go into an auth error mode and then back out. | |
| 702 TEST_F(ChromeInvalidationClientTest, PushClientAuthError) { | |
| 703 EnableNotifications(); | |
| 704 client_.Ready(fake_invalidation_client_); | |
| 705 | |
| 706 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason()); | |
| 707 | |
| 708 DisableNotifications( | |
| 709 notifier::NOTIFICATION_CREDENTIALS_REJECTED); | |
| 710 | |
| 711 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED, | |
| 712 GetNotificationsDisabledReason()); | |
| 713 | |
| 714 EnableNotifications(); | |
| 715 | |
| 716 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason()); | |
| 717 } | |
| 718 | |
| 719 // Enable notifications and ready the client. Then simulate an auth | |
| 720 // error from the invalidation client. Simulate some notification | |
| 721 // events, then re-ready the client. The listener should go into an | |
| 722 // auth error mode and come out of it only after the client is ready. | |
| 723 TEST_F(ChromeInvalidationClientTest, InvalidationClientAuthError) { | |
| 724 EnableNotifications(); | |
| 725 client_.Ready(fake_invalidation_client_); | |
| 726 | |
| 727 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason()); | |
| 728 | |
| 729 client_.InformError( | |
| 730 fake_invalidation_client_, | |
| 731 invalidation::ErrorInfo( | |
| 732 invalidation::ErrorReason::AUTH_FAILURE, | |
| 733 false /* is_transient */, | |
| 734 "auth error", | |
| 735 invalidation::ErrorContext())); | |
| 736 | |
| 737 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED, | |
| 738 GetNotificationsDisabledReason()); | |
| 739 | |
| 740 DisableNotifications( | |
| 741 notifier::TRANSIENT_NOTIFICATION_ERROR); | |
| 742 | |
| 743 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED, | |
| 744 GetNotificationsDisabledReason()); | |
| 745 | |
| 746 DisableNotifications( | |
| 747 notifier::TRANSIENT_NOTIFICATION_ERROR); | |
| 748 | |
| 749 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED, | |
| 750 GetNotificationsDisabledReason()); | |
| 751 | |
| 752 EnableNotifications(); | |
| 753 | |
| 754 EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED, | |
| 755 GetNotificationsDisabledReason()); | |
| 756 | |
| 757 client_.Ready(fake_invalidation_client_); | |
| 758 | |
| 759 EXPECT_EQ(NO_NOTIFICATION_ERROR, GetNotificationsDisabledReason()); | |
| 760 } | |
| 761 | |
| 762 } // namespace | |
| 763 | |
| 764 } // namespace syncer | |
| OLD | NEW |