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#include "components/gcm_driver/gcm_account_mapper.h" 6 7#include "base/test/simple_test_clock.h" 8#include "base/time/time.h" 9#include "components/gcm_driver/fake_gcm_driver.h" 10#include "google_apis/gcm/engine/account_mapping.h" 11#include "google_apis/gcm/engine/gcm_store.h" 12#include "testing/gtest/include/gtest/gtest.h" 13 14namespace gcm { 15 16namespace { 17 18const char kGCMAccountMapperSenderId[] = "745476177629"; 19const char kGCMAccountMapperAppId[] = "com.google.android.gms"; 20const char kRegistrationId[] = "reg_id"; 21 22AccountMapping MakeAccountMapping(const std::string& account_id, 23 AccountMapping::MappingStatus status, 24 const base::Time& status_change_timestamp, 25 const std::string& last_message_id) { 26 AccountMapping account_mapping; 27 account_mapping.account_id = account_id; 28 account_mapping.email = account_id + "@gmail.com"; 29 // account_mapping.access_token intentionally left empty. 30 account_mapping.status = status; 31 account_mapping.status_change_timestamp = status_change_timestamp; 32 account_mapping.last_message_id = last_message_id; 33 return account_mapping; 34} 35 36GCMClient::AccountTokenInfo MakeAccountTokenInfo( 37 const std::string& account_id) { 38 GCMClient::AccountTokenInfo account_token; 39 account_token.account_id = account_id; 40 account_token.email = account_id + "@gmail.com"; 41 account_token.access_token = account_id + "_token"; 42 return account_token; 43} 44 45void VerifyMappings(const GCMAccountMapper::AccountMappings& expected_mappings, 46 const GCMAccountMapper::AccountMappings& actual_mappings, 47 const std::string& verification_info) { 48 EXPECT_EQ(expected_mappings.size(), actual_mappings.size()) 49 << "Verification Info: " << verification_info; 50 GCMAccountMapper::AccountMappings::const_iterator expected_iter = 51 expected_mappings.begin(); 52 GCMAccountMapper::AccountMappings::const_iterator actual_iter = 53 actual_mappings.begin(); 54 for (; expected_iter != expected_mappings.end() && 55 actual_iter != actual_mappings.end(); 56 ++expected_iter, ++actual_iter) { 57 EXPECT_EQ(expected_iter->email, actual_iter->email) 58 << "Verification Info: " << verification_info 59 << "; Account ID of expected: " << expected_iter->account_id; 60 EXPECT_EQ(expected_iter->account_id, actual_iter->account_id) 61 << "Verification Info: " << verification_info; 62 EXPECT_EQ(expected_iter->status, actual_iter->status) 63 << "Verification Info: " << verification_info 64 << "; Account ID of expected: " << expected_iter->account_id; 65 EXPECT_EQ(expected_iter->status_change_timestamp, 66 actual_iter->status_change_timestamp) 67 << "Verification Info: " << verification_info 68 << "; Account ID of expected: " << expected_iter->account_id; 69 } 70} 71 72class CustomFakeGCMDriver : public FakeGCMDriver { 73 public: 74 enum LastMessageAction { 75 NONE, 76 SEND_STARTED, 77 SEND_FINISHED, 78 SEND_ACKNOWLEDGED 79 }; 80 81 CustomFakeGCMDriver(); 82 virtual ~CustomFakeGCMDriver(); 83 84 virtual void UpdateAccountMapping( 85 const AccountMapping& account_mapping) OVERRIDE; 86 virtual void RemoveAccountMapping(const std::string& account_id) OVERRIDE; 87 virtual void AddAppHandler(const std::string& app_id, 88 GCMAppHandler* handler) OVERRIDE; 89 virtual void RemoveAppHandler(const std::string& app_id) OVERRIDE; 90 virtual void RegisterImpl( 91 const std::string& app_id, 92 const std::vector<std::string>& sender_ids) OVERRIDE; 93 94 void CompleteRegister(const std::string& registration_id, 95 GCMClient::Result result); 96 void CompleteSend(const std::string& message_id, GCMClient::Result result); 97 void AcknowledgeSend(const std::string& message_id); 98 void MessageSendError(const std::string& message_id); 99 100 void CompleteSendAllMessages(); 101 void AcknowledgeSendAllMessages(); 102 103 void SetLastMessageAction(const std::string& message_id, 104 LastMessageAction action); 105 void Clear(); 106 107 const AccountMapping& last_account_mapping() const { 108 return account_mapping_; 109 } 110 const std::string& last_message_id() const { return last_message_id_; } 111 const std::string& last_removed_account_id() const { 112 return last_removed_account_id_; 113 } 114 LastMessageAction last_action() const { return last_action_; } 115 bool registration_id_requested() const { return registration_id_requested_; } 116 117 protected: 118 virtual void SendImpl(const std::string& app_id, 119 const std::string& receiver_id, 120 const GCMClient::OutgoingMessage& message) OVERRIDE; 121 122 private: 123 AccountMapping account_mapping_; 124 std::string last_message_id_; 125 std::string last_removed_account_id_; 126 LastMessageAction last_action_; 127 std::map<std::string, LastMessageAction> all_messages_; 128 bool registration_id_requested_; 129}; 130 131CustomFakeGCMDriver::CustomFakeGCMDriver() 132 : last_action_(NONE), registration_id_requested_(false) { 133} 134 135CustomFakeGCMDriver::~CustomFakeGCMDriver() { 136} 137 138void CustomFakeGCMDriver::UpdateAccountMapping( 139 const AccountMapping& account_mapping) { 140 account_mapping_.email = account_mapping.email; 141 account_mapping_.account_id = account_mapping.account_id; 142 account_mapping_.access_token = account_mapping.access_token; 143 account_mapping_.status = account_mapping.status; 144 account_mapping_.status_change_timestamp = 145 account_mapping.status_change_timestamp; 146 account_mapping_.last_message_id = account_mapping.last_message_id; 147} 148 149void CustomFakeGCMDriver::RemoveAccountMapping(const std::string& account_id) { 150 last_removed_account_id_ = account_id; 151} 152 153void CustomFakeGCMDriver::AddAppHandler(const std::string& app_id, 154 GCMAppHandler* handler) { 155 GCMDriver::AddAppHandler(app_id, handler); 156} 157 158void CustomFakeGCMDriver::RemoveAppHandler(const std::string& app_id) { 159 GCMDriver::RemoveAppHandler(app_id); 160} 161 162void CustomFakeGCMDriver::RegisterImpl( 163 const std::string& app_id, 164 const std::vector<std::string>& sender_ids) { 165 DCHECK_EQ(kGCMAccountMapperAppId, app_id); 166 DCHECK_EQ(1u, sender_ids.size()); 167 DCHECK_EQ(kGCMAccountMapperSenderId, sender_ids[0]); 168 registration_id_requested_ = true; 169} 170 171void CustomFakeGCMDriver::CompleteRegister(const std::string& registration_id, 172 GCMClient::Result result) { 173 RegisterFinished(kGCMAccountMapperAppId, registration_id, result); 174} 175 176void CustomFakeGCMDriver::CompleteSend(const std::string& message_id, 177 GCMClient::Result result) { 178 SendFinished(kGCMAccountMapperAppId, message_id, result); 179 SetLastMessageAction(message_id, SEND_FINISHED); 180} 181 182void CustomFakeGCMDriver::AcknowledgeSend(const std::string& message_id) { 183 GetAppHandler(kGCMAccountMapperAppId) 184 ->OnSendAcknowledged(kGCMAccountMapperAppId, message_id); 185 SetLastMessageAction(message_id, SEND_ACKNOWLEDGED); 186} 187 188void CustomFakeGCMDriver::MessageSendError(const std::string& message_id) { 189 GCMClient::SendErrorDetails send_error; 190 send_error.message_id = message_id; 191 send_error.result = GCMClient::TTL_EXCEEDED; 192 GetAppHandler(kGCMAccountMapperAppId) 193 ->OnSendError(kGCMAccountMapperAppId, send_error); 194} 195 196void CustomFakeGCMDriver::SendImpl(const std::string& app_id, 197 const std::string& receiver_id, 198 const GCMClient::OutgoingMessage& message) { 199 DCHECK_EQ(kGCMAccountMapperAppId, app_id); 200 DCHECK_EQ(kGCMAccountMapperSenderId, receiver_id); 201 202 SetLastMessageAction(message.id, SEND_STARTED); 203} 204 205void CustomFakeGCMDriver::CompleteSendAllMessages() { 206 for (std::map<std::string, LastMessageAction>::const_iterator iter = 207 all_messages_.begin(); 208 iter != all_messages_.end(); 209 ++iter) { 210 if (iter->second == SEND_STARTED) 211 CompleteSend(iter->first, GCMClient::SUCCESS); 212 } 213} 214 215void CustomFakeGCMDriver::AcknowledgeSendAllMessages() { 216 for (std::map<std::string, LastMessageAction>::const_iterator iter = 217 all_messages_.begin(); 218 iter != all_messages_.end(); 219 ++iter) { 220 if (iter->second == SEND_FINISHED) 221 AcknowledgeSend(iter->first); 222 } 223} 224 225void CustomFakeGCMDriver::Clear() { 226 account_mapping_ = AccountMapping(); 227 last_message_id_.clear(); 228 last_removed_account_id_.clear(); 229 last_action_ = NONE; 230 registration_id_requested_ = false; 231} 232 233void CustomFakeGCMDriver::SetLastMessageAction(const std::string& message_id, 234 LastMessageAction action) { 235 last_action_ = action; 236 last_message_id_ = message_id; 237 all_messages_[message_id] = action; 238} 239 240} // namespace 241 242class GCMAccountMapperTest : public testing::Test { 243 public: 244 GCMAccountMapperTest(); 245 virtual ~GCMAccountMapperTest(); 246 247 void Restart(); 248 249 const GCMAccountMapper::AccountMappings& GetAccounts() const { 250 return account_mapper_->accounts_; 251 } 252 253 GCMAccountMapper* mapper() { return account_mapper_.get(); } 254 255 CustomFakeGCMDriver& gcm_driver() { return gcm_driver_; } 256 257 base::SimpleTestClock* clock() { return clock_; } 258 259 private: 260 CustomFakeGCMDriver gcm_driver_; 261 scoped_ptr<GCMAccountMapper> account_mapper_; 262 base::SimpleTestClock* clock_; 263}; 264 265GCMAccountMapperTest::GCMAccountMapperTest() { 266 Restart(); 267} 268 269GCMAccountMapperTest::~GCMAccountMapperTest() { 270} 271 272void GCMAccountMapperTest::Restart() { 273 if (account_mapper_) 274 account_mapper_->ShutdownHandler(); 275 account_mapper_.reset(new GCMAccountMapper(&gcm_driver_)); 276 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); 277 clock_ = clock.get(); 278 account_mapper_->SetClockForTesting(clock.PassAs<base::Clock>()); 279} 280 281// Tests the initialization of account mappings (from the store) when empty. 282// It also checks that initialization triggers registration ID request. 283TEST_F(GCMAccountMapperTest, InitializeAccountMappingsEmpty) { 284 EXPECT_FALSE(gcm_driver().registration_id_requested()); 285 mapper()->Initialize(GCMAccountMapper::AccountMappings()); 286 EXPECT_TRUE(GetAccounts().empty()); 287 EXPECT_TRUE(gcm_driver().registration_id_requested()); 288} 289 290// Tests that registration is retried, when new tokens are delivered and in no 291// other circumstances. 292TEST_F(GCMAccountMapperTest, RegistrationRetryUponFailure) { 293 mapper()->Initialize(GCMAccountMapper::AccountMappings()); 294 EXPECT_TRUE(gcm_driver().registration_id_requested()); 295 gcm_driver().Clear(); 296 297 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::UNKNOWN_ERROR); 298 EXPECT_FALSE(gcm_driver().registration_id_requested()); 299 gcm_driver().Clear(); 300 301 std::vector<GCMClient::AccountTokenInfo> account_tokens; 302 account_tokens.push_back(MakeAccountTokenInfo("acc_id2")); 303 mapper()->SetAccountTokens(account_tokens); 304 EXPECT_TRUE(gcm_driver().registration_id_requested()); 305 gcm_driver().Clear(); 306 307 gcm_driver().CompleteRegister(kRegistrationId, 308 GCMClient::ASYNC_OPERATION_PENDING); 309 EXPECT_FALSE(gcm_driver().registration_id_requested()); 310} 311 312// Tests the initialization of account mappings (from the store). 313TEST_F(GCMAccountMapperTest, InitializeAccountMappings) { 314 GCMAccountMapper::AccountMappings account_mappings; 315 AccountMapping account_mapping1 = MakeAccountMapping("acc_id1", 316 AccountMapping::MAPPED, 317 base::Time::Now(), 318 std::string()); 319 AccountMapping account_mapping2 = MakeAccountMapping("acc_id2", 320 AccountMapping::ADDING, 321 base::Time::Now(), 322 "add_message_1"); 323 account_mappings.push_back(account_mapping1); 324 account_mappings.push_back(account_mapping2); 325 326 mapper()->Initialize(account_mappings); 327 328 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 329 EXPECT_EQ(2UL, mappings.size()); 330 GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin(); 331 332 EXPECT_EQ(account_mapping1.account_id, iter->account_id); 333 EXPECT_EQ(account_mapping1.email, iter->email); 334 EXPECT_TRUE(account_mapping1.access_token.empty()); 335 EXPECT_EQ(account_mapping1.status, iter->status); 336 EXPECT_EQ(account_mapping1.status_change_timestamp, 337 iter->status_change_timestamp); 338 EXPECT_TRUE(account_mapping1.last_message_id.empty()); 339 340 ++iter; 341 EXPECT_EQ(account_mapping2.account_id, iter->account_id); 342 EXPECT_EQ(account_mapping2.email, iter->email); 343 EXPECT_TRUE(account_mapping2.access_token.empty()); 344 EXPECT_EQ(account_mapping2.status, iter->status); 345 EXPECT_EQ(account_mapping2.status_change_timestamp, 346 iter->status_change_timestamp); 347 EXPECT_EQ(account_mapping2.last_message_id, iter->last_message_id); 348} 349 350// Tests that account tokens are not processed until registration ID is 351// available. 352TEST_F(GCMAccountMapperTest, SetAccountTokensOnlyWorksWithRegisterationId) { 353 // Start with empty list. 354 mapper()->Initialize(GCMAccountMapper::AccountMappings()); 355 356 std::vector<GCMClient::AccountTokenInfo> account_tokens; 357 account_tokens.push_back(MakeAccountTokenInfo("acc_id")); 358 mapper()->SetAccountTokens(account_tokens); 359 360 EXPECT_TRUE(GetAccounts().empty()); 361 362 account_tokens.clear(); 363 account_tokens.push_back(MakeAccountTokenInfo("acc_id1")); 364 account_tokens.push_back(MakeAccountTokenInfo("acc_id2")); 365 mapper()->SetAccountTokens(account_tokens); 366 367 EXPECT_TRUE(GetAccounts().empty()); 368 369 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 370 371 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 372 EXPECT_EQ(2UL, mappings.size()); 373 EXPECT_EQ("acc_id1", mappings[0].account_id); 374 EXPECT_EQ("acc_id2", mappings[1].account_id); 375} 376 377// Tests the part where a new account is added with a token, to the point when 378// GCM message is sent. 379TEST_F(GCMAccountMapperTest, AddMappingToMessageSent) { 380 mapper()->Initialize(GCMAccountMapper::AccountMappings()); 381 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 382 383 std::vector<GCMClient::AccountTokenInfo> account_tokens; 384 GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo("acc_id"); 385 account_tokens.push_back(account_token); 386 mapper()->SetAccountTokens(account_tokens); 387 388 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 389 EXPECT_EQ(1UL, mappings.size()); 390 GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin(); 391 EXPECT_EQ("acc_id", iter->account_id); 392 EXPECT_EQ("acc_id@gmail.com", iter->email); 393 EXPECT_EQ("acc_id_token", iter->access_token); 394 EXPECT_EQ(AccountMapping::NEW, iter->status); 395 EXPECT_EQ(base::Time(), iter->status_change_timestamp); 396 397 EXPECT_TRUE(!gcm_driver().last_message_id().empty()); 398} 399 400// Tests the part where GCM message is successfully queued. 401TEST_F(GCMAccountMapperTest, AddMappingMessageQueued) { 402 mapper()->Initialize(GCMAccountMapper::AccountMappings()); 403 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 404 405 std::vector<GCMClient::AccountTokenInfo> account_tokens; 406 GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo("acc_id"); 407 account_tokens.push_back(account_token); 408 mapper()->SetAccountTokens(account_tokens); 409 410 clock()->SetNow(base::Time::Now()); 411 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS); 412 413 EXPECT_EQ(account_token.email, gcm_driver().last_account_mapping().email); 414 EXPECT_EQ(account_token.account_id, 415 gcm_driver().last_account_mapping().account_id); 416 EXPECT_EQ(account_token.access_token, 417 gcm_driver().last_account_mapping().access_token); 418 EXPECT_EQ(AccountMapping::ADDING, gcm_driver().last_account_mapping().status); 419 EXPECT_EQ(clock()->Now(), 420 gcm_driver().last_account_mapping().status_change_timestamp); 421 EXPECT_EQ(gcm_driver().last_message_id(), 422 gcm_driver().last_account_mapping().last_message_id); 423 424 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 425 GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin(); 426 EXPECT_EQ(account_token.email, iter->email); 427 EXPECT_EQ(account_token.account_id, iter->account_id); 428 EXPECT_EQ(account_token.access_token, iter->access_token); 429 EXPECT_EQ(AccountMapping::ADDING, iter->status); 430 EXPECT_EQ(clock()->Now(), iter->status_change_timestamp); 431 EXPECT_EQ(gcm_driver().last_message_id(), iter->last_message_id); 432} 433 434// Tests status change from ADDING to MAPPED (Message is acknowledged). 435TEST_F(GCMAccountMapperTest, AddMappingMessageAcknowledged) { 436 mapper()->Initialize(GCMAccountMapper::AccountMappings()); 437 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 438 439 std::vector<GCMClient::AccountTokenInfo> account_tokens; 440 GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo("acc_id"); 441 account_tokens.push_back(account_token); 442 mapper()->SetAccountTokens(account_tokens); 443 444 clock()->SetNow(base::Time::Now()); 445 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS); 446 clock()->SetNow(base::Time::Now()); 447 gcm_driver().AcknowledgeSend(gcm_driver().last_message_id()); 448 449 EXPECT_EQ(account_token.email, gcm_driver().last_account_mapping().email); 450 EXPECT_EQ(account_token.account_id, 451 gcm_driver().last_account_mapping().account_id); 452 EXPECT_EQ(account_token.access_token, 453 gcm_driver().last_account_mapping().access_token); 454 EXPECT_EQ(AccountMapping::MAPPED, gcm_driver().last_account_mapping().status); 455 EXPECT_EQ(clock()->Now(), 456 gcm_driver().last_account_mapping().status_change_timestamp); 457 EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id.empty()); 458 459 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 460 GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin(); 461 EXPECT_EQ(account_token.email, iter->email); 462 EXPECT_EQ(account_token.account_id, iter->account_id); 463 EXPECT_EQ(account_token.access_token, iter->access_token); 464 EXPECT_EQ(AccountMapping::MAPPED, iter->status); 465 EXPECT_EQ(clock()->Now(), iter->status_change_timestamp); 466 EXPECT_TRUE(iter->last_message_id.empty()); 467} 468 469// Tests status change form ADDING to MAPPED (When message was acknowledged, 470// after Chrome was restarted). 471TEST_F(GCMAccountMapperTest, AddMappingMessageAckedAfterRestart) { 472 mapper()->Initialize(GCMAccountMapper::AccountMappings()); 473 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 474 475 std::vector<GCMClient::AccountTokenInfo> account_tokens; 476 GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo("acc_id"); 477 account_tokens.push_back(account_token); 478 mapper()->SetAccountTokens(account_tokens); 479 480 clock()->SetNow(base::Time::Now()); 481 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS); 482 483 Restart(); 484 GCMAccountMapper::AccountMappings stored_mappings; 485 stored_mappings.push_back(gcm_driver().last_account_mapping()); 486 mapper()->Initialize(stored_mappings); 487 488 clock()->SetNow(base::Time::Now()); 489 gcm_driver().AcknowledgeSend(gcm_driver().last_message_id()); 490 491 EXPECT_EQ(account_token.email, gcm_driver().last_account_mapping().email); 492 EXPECT_EQ(account_token.account_id, 493 gcm_driver().last_account_mapping().account_id); 494 EXPECT_EQ(account_token.access_token, 495 gcm_driver().last_account_mapping().access_token); 496 EXPECT_EQ(AccountMapping::MAPPED, gcm_driver().last_account_mapping().status); 497 EXPECT_EQ(clock()->Now(), 498 gcm_driver().last_account_mapping().status_change_timestamp); 499 EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id.empty()); 500 501 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 502 GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin(); 503 EXPECT_EQ(account_token.email, iter->email); 504 EXPECT_EQ(account_token.account_id, iter->account_id); 505 EXPECT_EQ(account_token.access_token, iter->access_token); 506 EXPECT_EQ(AccountMapping::MAPPED, iter->status); 507 EXPECT_EQ(clock()->Now(), iter->status_change_timestamp); 508 EXPECT_TRUE(iter->last_message_id.empty()); 509} 510 511// Tests a case when ADD message times out for a new account. 512TEST_F(GCMAccountMapperTest, AddMappingMessageSendErrorForNewAccount) { 513 mapper()->Initialize(GCMAccountMapper::AccountMappings()); 514 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 515 516 std::vector<GCMClient::AccountTokenInfo> account_tokens; 517 GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo("acc_id"); 518 account_tokens.push_back(account_token); 519 mapper()->SetAccountTokens(account_tokens); 520 521 clock()->SetNow(base::Time::Now()); 522 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS); 523 524 clock()->SetNow(base::Time::Now()); 525 std::string old_message_id = gcm_driver().last_message_id(); 526 gcm_driver().MessageSendError(old_message_id); 527 528 // No new message is sent because of the send error, as the token is stale. 529 // Because the account was new, the entry should be deleted. 530 EXPECT_EQ(old_message_id, gcm_driver().last_message_id()); 531 EXPECT_EQ(account_token.account_id, gcm_driver().last_removed_account_id()); 532 EXPECT_TRUE(GetAccounts().empty()); 533} 534 535/// Tests a case when ADD message times out for a MAPPED account. 536TEST_F(GCMAccountMapperTest, AddMappingMessageSendErrorForMappedAccount) { 537 // Start with one account that is mapped. 538 base::Time status_change_timestamp = base::Time::Now(); 539 AccountMapping mapping = MakeAccountMapping("acc_id", 540 AccountMapping::MAPPED, 541 status_change_timestamp, 542 "add_message_id"); 543 544 GCMAccountMapper::AccountMappings stored_mappings; 545 stored_mappings.push_back(mapping); 546 mapper()->Initialize(stored_mappings); 547 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 548 549 clock()->SetNow(base::Time::Now()); 550 gcm_driver().MessageSendError("add_message_id"); 551 552 // No new message is sent because of the send error, as the token is stale. 553 // Because the account was new, the entry should be deleted. 554 EXPECT_TRUE(gcm_driver().last_message_id().empty()); 555 556 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 557 GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin(); 558 EXPECT_EQ(mapping.email, iter->email); 559 EXPECT_EQ(mapping.account_id, iter->account_id); 560 EXPECT_EQ(mapping.access_token, iter->access_token); 561 EXPECT_EQ(AccountMapping::MAPPED, iter->status); 562 EXPECT_EQ(status_change_timestamp, iter->status_change_timestamp); 563 EXPECT_TRUE(iter->last_message_id.empty()); 564} 565 566// Tests that a missing token for an account will trigger removing of that 567// account. This test goes only until the message is passed to GCM. 568TEST_F(GCMAccountMapperTest, RemoveMappingToMessageSent) { 569 // Start with one account that is mapped. 570 AccountMapping mapping = MakeAccountMapping("acc_id", 571 AccountMapping::MAPPED, 572 base::Time::Now(), 573 std::string()); 574 575 GCMAccountMapper::AccountMappings stored_mappings; 576 stored_mappings.push_back(mapping); 577 mapper()->Initialize(stored_mappings); 578 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 579 clock()->SetNow(base::Time::Now()); 580 581 mapper()->SetAccountTokens(std::vector<GCMClient::AccountTokenInfo>()); 582 583 EXPECT_EQ(mapping.account_id, gcm_driver().last_account_mapping().account_id); 584 EXPECT_EQ(mapping.email, gcm_driver().last_account_mapping().email); 585 EXPECT_EQ(AccountMapping::REMOVING, 586 gcm_driver().last_account_mapping().status); 587 EXPECT_EQ(clock()->Now(), 588 gcm_driver().last_account_mapping().status_change_timestamp); 589 EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id.empty()); 590 591 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 592 GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin(); 593 EXPECT_EQ(mapping.email, iter->email); 594 EXPECT_EQ(mapping.account_id, iter->account_id); 595 EXPECT_EQ(mapping.access_token, iter->access_token); 596 EXPECT_EQ(AccountMapping::REMOVING, iter->status); 597 EXPECT_EQ(clock()->Now(), iter->status_change_timestamp); 598 EXPECT_TRUE(iter->last_message_id.empty()); 599} 600 601// Tests that a missing token for an account will trigger removing of that 602// account. This test goes until the message is queued by GCM. 603TEST_F(GCMAccountMapperTest, RemoveMappingMessageQueued) { 604 // Start with one account that is mapped. 605 AccountMapping mapping = MakeAccountMapping("acc_id", 606 AccountMapping::MAPPED, 607 base::Time::Now(), 608 std::string()); 609 610 GCMAccountMapper::AccountMappings stored_mappings; 611 stored_mappings.push_back(mapping); 612 mapper()->Initialize(stored_mappings); 613 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 614 clock()->SetNow(base::Time::Now()); 615 base::Time status_change_timestamp = clock()->Now(); 616 617 mapper()->SetAccountTokens(std::vector<GCMClient::AccountTokenInfo>()); 618 clock()->SetNow(base::Time::Now()); 619 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS); 620 621 EXPECT_EQ(mapping.account_id, gcm_driver().last_account_mapping().account_id); 622 EXPECT_EQ(mapping.email, gcm_driver().last_account_mapping().email); 623 EXPECT_EQ(AccountMapping::REMOVING, 624 gcm_driver().last_account_mapping().status); 625 EXPECT_EQ(status_change_timestamp, 626 gcm_driver().last_account_mapping().status_change_timestamp); 627 EXPECT_TRUE(!gcm_driver().last_account_mapping().last_message_id.empty()); 628 629 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 630 GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin(); 631 EXPECT_EQ(mapping.email, iter->email); 632 EXPECT_EQ(mapping.account_id, iter->account_id); 633 EXPECT_EQ(mapping.access_token, iter->access_token); 634 EXPECT_EQ(AccountMapping::REMOVING, iter->status); 635 EXPECT_EQ(status_change_timestamp, iter->status_change_timestamp); 636 EXPECT_EQ(gcm_driver().last_account_mapping().last_message_id, 637 iter->last_message_id); 638} 639 640// Tests that a missing token for an account will trigger removing of that 641// account. This test goes until the message is acknowledged by GCM. 642// This is a complete success scenario for account removal, and it end with 643// account mapping being completely gone. 644TEST_F(GCMAccountMapperTest, RemoveMappingMessageAcknowledged) { 645 // Start with one account that is mapped. 646 AccountMapping mapping = MakeAccountMapping("acc_id", 647 AccountMapping::MAPPED, 648 base::Time::Now(), 649 std::string()); 650 651 GCMAccountMapper::AccountMappings stored_mappings; 652 stored_mappings.push_back(mapping); 653 mapper()->Initialize(stored_mappings); 654 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 655 clock()->SetNow(base::Time::Now()); 656 657 mapper()->SetAccountTokens(std::vector<GCMClient::AccountTokenInfo>()); 658 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS); 659 gcm_driver().AcknowledgeSend(gcm_driver().last_message_id()); 660 661 EXPECT_EQ(mapping.account_id, gcm_driver().last_removed_account_id()); 662 663 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 664 EXPECT_TRUE(mappings.empty()); 665} 666 667// Tests that account removing proceeds, when a removing message is acked after 668// Chrome was restarted. 669TEST_F(GCMAccountMapperTest, RemoveMappingMessageAckedAfterRestart) { 670 // Start with one account that is mapped. 671 AccountMapping mapping = MakeAccountMapping("acc_id", 672 AccountMapping::REMOVING, 673 base::Time::Now(), 674 "remove_message_id"); 675 676 GCMAccountMapper::AccountMappings stored_mappings; 677 stored_mappings.push_back(mapping); 678 mapper()->Initialize(stored_mappings); 679 680 gcm_driver().AcknowledgeSend("remove_message_id"); 681 682 EXPECT_EQ(mapping.account_id, gcm_driver().last_removed_account_id()); 683 684 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 685 EXPECT_TRUE(mappings.empty()); 686} 687 688// Tests that account removing proceeds, when a removing message is acked after 689// Chrome was restarted. 690TEST_F(GCMAccountMapperTest, RemoveMappingMessageSendError) { 691 // Start with one account that is mapped. 692 base::Time status_change_timestamp = base::Time::Now(); 693 AccountMapping mapping = MakeAccountMapping("acc_id", 694 AccountMapping::REMOVING, 695 status_change_timestamp, 696 "remove_message_id"); 697 698 GCMAccountMapper::AccountMappings stored_mappings; 699 stored_mappings.push_back(mapping); 700 mapper()->Initialize(stored_mappings); 701 702 clock()->SetNow(base::Time::Now()); 703 gcm_driver().MessageSendError("remove_message_id"); 704 705 EXPECT_TRUE(gcm_driver().last_removed_account_id().empty()); 706 707 EXPECT_EQ(mapping.account_id, gcm_driver().last_account_mapping().account_id); 708 EXPECT_EQ(mapping.email, gcm_driver().last_account_mapping().email); 709 EXPECT_EQ(AccountMapping::REMOVING, 710 gcm_driver().last_account_mapping().status); 711 EXPECT_EQ(status_change_timestamp, 712 gcm_driver().last_account_mapping().status_change_timestamp); 713 // Message is not persisted, until send is completed. 714 EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id.empty()); 715 716 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 717 GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin(); 718 EXPECT_EQ(mapping.email, iter->email); 719 EXPECT_EQ(mapping.account_id, iter->account_id); 720 EXPECT_TRUE(iter->access_token.empty()); 721 EXPECT_EQ(AccountMapping::REMOVING, iter->status); 722 EXPECT_EQ(status_change_timestamp, iter->status_change_timestamp); 723 EXPECT_TRUE(iter->last_message_id.empty()); 724} 725 726// Tests that, if a new token arrives when the adding message is in progress 727// no new message is sent and account mapper still waits for the first one to 728// complete. 729TEST_F(GCMAccountMapperTest, TokenIsRefreshedWhenAdding) { 730 mapper()->Initialize(GCMAccountMapper::AccountMappings()); 731 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 732 733 clock()->SetNow(base::Time::Now()); 734 std::vector<GCMClient::AccountTokenInfo> account_tokens; 735 GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo("acc_id"); 736 account_tokens.push_back(account_token); 737 mapper()->SetAccountTokens(account_tokens); 738 DCHECK_EQ(CustomFakeGCMDriver::SEND_STARTED, gcm_driver().last_action()); 739 740 clock()->SetNow(base::Time::Now()); 741 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS); 742 DCHECK_EQ(CustomFakeGCMDriver::SEND_FINISHED, gcm_driver().last_action()); 743 744 // Providing another token and clearing status. 745 gcm_driver().Clear(); 746 mapper()->SetAccountTokens(account_tokens); 747 DCHECK_EQ(CustomFakeGCMDriver::NONE, gcm_driver().last_action()); 748} 749 750// Tests that, if a new token arrives when a removing message is in progress 751// a new adding message is sent and while account mapping status is changed to 752// mapped. If the original Removing message arrives it is discarded. 753TEST_F(GCMAccountMapperTest, TokenIsRefreshedWhenRemoving) { 754 // Start with one account that is mapped. 755 AccountMapping mapping = MakeAccountMapping( 756 "acc_id", AccountMapping::MAPPED, base::Time::Now(), std::string()); 757 758 GCMAccountMapper::AccountMappings stored_mappings; 759 stored_mappings.push_back(mapping); 760 mapper()->Initialize(stored_mappings); 761 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 762 clock()->SetNow(base::Time::Now()); 763 764 // Remove the token to trigger a remove message to be sent 765 mapper()->SetAccountTokens(std::vector<GCMClient::AccountTokenInfo>()); 766 EXPECT_EQ(CustomFakeGCMDriver::SEND_STARTED, gcm_driver().last_action()); 767 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS); 768 EXPECT_EQ(CustomFakeGCMDriver::SEND_FINISHED, gcm_driver().last_action()); 769 770 std::string remove_message_id = gcm_driver().last_message_id(); 771 gcm_driver().Clear(); 772 773 // The account mapping for acc_id is now in status REMOVING. 774 // Adding the token for that account. 775 clock()->SetNow(base::Time::Now()); 776 std::vector<GCMClient::AccountTokenInfo> account_tokens; 777 GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo("acc_id"); 778 account_tokens.push_back(account_token); 779 mapper()->SetAccountTokens(account_tokens); 780 DCHECK_EQ(CustomFakeGCMDriver::SEND_STARTED, gcm_driver().last_action()); 781 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS); 782 EXPECT_EQ(CustomFakeGCMDriver::SEND_FINISHED, gcm_driver().last_action()); 783 784 std::string add_message_id = gcm_driver().last_message_id(); 785 786 // A remove message confirmation arrives now, but should be ignored. 787 gcm_driver().AcknowledgeSend(remove_message_id); 788 789 GCMAccountMapper::AccountMappings mappings = GetAccounts(); 790 GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin(); 791 EXPECT_EQ(mapping.email, iter->email); 792 EXPECT_EQ(mapping.account_id, iter->account_id); 793 EXPECT_FALSE(iter->access_token.empty()); 794 EXPECT_EQ(AccountMapping::MAPPED, iter->status); 795 // Status change timestamp is set to very long time ago, to make sure the next 796 // round of mapping picks it up. 797 EXPECT_EQ(base::Time(), iter->status_change_timestamp); 798 EXPECT_EQ(add_message_id, iter->last_message_id); 799} 800 801// Tests adding/removing works for multiple accounts, after a restart and when 802// tokens are periodically delierverd. 803TEST_F(GCMAccountMapperTest, MultipleAccountMappings) { 804 clock()->SetNow(base::Time::Now()); 805 base::Time half_hour_ago = clock()->Now() - base::TimeDelta::FromMinutes(30); 806 GCMAccountMapper::AccountMappings stored_mappings; 807 stored_mappings.push_back(MakeAccountMapping( 808 "acc_id_0", AccountMapping::ADDING, half_hour_ago, "acc_id_0_msg")); 809 stored_mappings.push_back(MakeAccountMapping( 810 "acc_id_1", AccountMapping::MAPPED, half_hour_ago, "acc_id_1_msg")); 811 stored_mappings.push_back(MakeAccountMapping( 812 "acc_id_2", AccountMapping::REMOVING, half_hour_ago, "acc_id_2_msg")); 813 814 mapper()->Initialize(stored_mappings); 815 gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS); 816 817 GCMAccountMapper::AccountMappings expected_mappings(stored_mappings); 818 819 // Finish messages after a restart. 820 clock()->SetNow(base::Time::Now()); 821 gcm_driver().AcknowledgeSend(expected_mappings[0].last_message_id); 822 expected_mappings[0].status_change_timestamp = clock()->Now(); 823 expected_mappings[0].status = AccountMapping::MAPPED; 824 expected_mappings[0].last_message_id.clear(); 825 826 clock()->SetNow(base::Time::Now()); 827 gcm_driver().AcknowledgeSend(expected_mappings[1].last_message_id); 828 expected_mappings[1].status_change_timestamp = clock()->Now(); 829 expected_mappings[1].status = AccountMapping::MAPPED; 830 expected_mappings[1].last_message_id.clear(); 831 832 // Upon success last element is removed. 833 clock()->SetNow(base::Time::Now()); 834 gcm_driver().AcknowledgeSend(expected_mappings[2].last_message_id); 835 expected_mappings.pop_back(); 836 837 VerifyMappings(expected_mappings, GetAccounts(), "Step 1, After restart"); 838 839 // One of accounts gets removed. 840 std::vector<GCMClient::AccountTokenInfo> account_tokens; 841 account_tokens.push_back(MakeAccountTokenInfo("acc_id_0")); 842 843 // Advance a day to make sure existing mappings will be reported. 844 clock()->SetNow(clock()->Now() + base::TimeDelta::FromDays(1)); 845 mapper()->SetAccountTokens(account_tokens); 846 847 expected_mappings[0].status = AccountMapping::MAPPED; 848 expected_mappings[1].status = AccountMapping::REMOVING; 849 expected_mappings[1].status_change_timestamp = clock()->Now(); 850 851 gcm_driver().CompleteSendAllMessages(); 852 853 VerifyMappings( 854 expected_mappings, GetAccounts(), "Step 2, One account is being removed"); 855 856 clock()->SetNow(clock()->Now() + base::TimeDelta::FromSeconds(5)); 857 gcm_driver().AcknowledgeSendAllMessages(); 858 859 expected_mappings[0].status_change_timestamp = clock()->Now(); 860 expected_mappings.pop_back(); 861 862 VerifyMappings( 863 expected_mappings, GetAccounts(), "Step 3, Removing completed"); 864 865 account_tokens.clear(); 866 account_tokens.push_back(MakeAccountTokenInfo("acc_id_0")); 867 account_tokens.push_back(MakeAccountTokenInfo("acc_id_3")); 868 account_tokens.push_back(MakeAccountTokenInfo("acc_id_4")); 869 870 // Advance a day to make sure existing mappings will be reported. 871 clock()->SetNow(clock()->Now() + base::TimeDelta::FromDays(1)); 872 mapper()->SetAccountTokens(account_tokens); 873 874 // Mapping from acc_id_0 still in position 0 875 expected_mappings.push_back(MakeAccountMapping( 876 "acc_id_3", AccountMapping::NEW, base::Time(), std::string())); 877 expected_mappings.push_back(MakeAccountMapping( 878 "acc_id_4", AccountMapping::NEW, base::Time(), std::string())); 879 880 VerifyMappings(expected_mappings, GetAccounts(), "Step 4, Two new accounts"); 881 882 clock()->SetNow(clock()->Now() + base::TimeDelta::FromSeconds(1)); 883 gcm_driver().CompleteSendAllMessages(); 884 885 expected_mappings[1].status = AccountMapping::ADDING; 886 expected_mappings[1].status_change_timestamp = clock()->Now(); 887 expected_mappings[2].status = AccountMapping::ADDING; 888 expected_mappings[2].status_change_timestamp = clock()->Now(); 889 890 VerifyMappings( 891 expected_mappings, GetAccounts(), "Step 5, Two accounts being added"); 892 893 clock()->SetNow(clock()->Now() + base::TimeDelta::FromSeconds(5)); 894 gcm_driver().AcknowledgeSendAllMessages(); 895 896 expected_mappings[0].status_change_timestamp = clock()->Now(); 897 expected_mappings[1].status_change_timestamp = clock()->Now(); 898 expected_mappings[1].status = AccountMapping::MAPPED; 899 expected_mappings[2].status_change_timestamp = clock()->Now(); 900 expected_mappings[2].status = AccountMapping::MAPPED; 901 902 VerifyMappings( 903 expected_mappings, GetAccounts(), "Step 6, Three mapped accounts"); 904} 905 906} // namespace gcm 907