123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/gcm_driver/gcm_account_mapper.h"
- #include <memory>
- #include <utility>
- #include "base/bind.h"
- #include "base/test/simple_test_clock.h"
- #include "base/time/time.h"
- #include "components/gcm_driver/fake_gcm_driver.h"
- #include "google_apis/gcm/engine/account_mapping.h"
- #include "google_apis/gcm/engine/gcm_store.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace gcm {
- namespace {
- const char kGCMAccountMapperSenderId[] = "745476177629";
- const char kGCMAccountMapperSendTo[] = "google.com";
- const char kRegistrationId[] = "reg_id";
- const char kEmbeddedAppIdKey[] = "gcmb";
- const char kTestAppId[] = "test_app_id";
- const char kTestDataKey[] = "data_key";
- const char kTestDataValue[] = "data_value";
- const char kTestCollapseKey[] = "test_collapse_key";
- const char kTestSenderId[] = "test_sender_id";
- AccountMapping MakeAccountMapping(const CoreAccountId& account_id,
- AccountMapping::MappingStatus status,
- const base::Time& status_change_timestamp,
- const std::string& last_message_id) {
- AccountMapping account_mapping;
- account_mapping.account_id = account_id;
- account_mapping.email = account_id.ToString() + "@gmail.com";
- // account_mapping.access_token intentionally left empty.
- account_mapping.status = status;
- account_mapping.status_change_timestamp = status_change_timestamp;
- account_mapping.last_message_id = last_message_id;
- return account_mapping;
- }
- GCMClient::AccountTokenInfo MakeAccountTokenInfo(
- const CoreAccountId& account_id) {
- GCMClient::AccountTokenInfo account_token;
- account_token.account_id = account_id;
- account_token.email = account_id.ToString() + "@gmail.com";
- account_token.access_token = account_id.ToString() + "_token";
- return account_token;
- }
- void VerifyMappings(const GCMAccountMapper::AccountMappings& expected_mappings,
- const GCMAccountMapper::AccountMappings& actual_mappings,
- const std::string& verification_info) {
- EXPECT_EQ(expected_mappings.size(), actual_mappings.size())
- << "Verification Info: " << verification_info;
- auto expected_iter = expected_mappings.begin();
- auto actual_iter = actual_mappings.begin();
- for (; expected_iter != expected_mappings.end() &&
- actual_iter != actual_mappings.end();
- ++expected_iter, ++actual_iter) {
- EXPECT_EQ(expected_iter->email, actual_iter->email)
- << "Verification Info: " << verification_info
- << "; Account ID of expected: " << expected_iter->account_id;
- EXPECT_EQ(expected_iter->account_id, actual_iter->account_id)
- << "Verification Info: " << verification_info;
- EXPECT_EQ(expected_iter->status, actual_iter->status)
- << "Verification Info: " << verification_info
- << "; Account ID of expected: " << expected_iter->account_id;
- EXPECT_EQ(expected_iter->status_change_timestamp,
- actual_iter->status_change_timestamp)
- << "Verification Info: " << verification_info
- << "; Account ID of expected: " << expected_iter->account_id;
- }
- }
- class CustomFakeGCMDriver : public FakeGCMDriver {
- public:
- enum LastMessageAction {
- NONE,
- SEND_STARTED,
- SEND_FINISHED,
- SEND_ACKNOWLEDGED
- };
- CustomFakeGCMDriver();
- ~CustomFakeGCMDriver() override;
- // GCMDriver implementation:
- void UpdateAccountMapping(const AccountMapping& account_mapping) override;
- void RemoveAccountMapping(const CoreAccountId& account_id) override;
- void RegisterImpl(const std::string& app_id,
- const std::vector<std::string>& sender_ids) override;
- void CompleteRegister(const std::string& registration_id,
- GCMClient::Result result);
- void CompleteSend(const std::string& message_id, GCMClient::Result result);
- void AcknowledgeSend(const std::string& message_id);
- void MessageSendError(const std::string& message_id);
- void CompleteSendAllMessages();
- void AcknowledgeSendAllMessages();
- void SetLastMessageAction(const std::string& message_id,
- LastMessageAction action);
- void Clear();
- const AccountMapping& last_account_mapping() const {
- return account_mapping_;
- }
- const std::string& last_message_id() const { return last_message_id_; }
- const CoreAccountId& last_removed_account_id() const {
- return last_removed_account_id_;
- }
- LastMessageAction last_action() const { return last_action_; }
- bool registration_id_requested() const { return registration_id_requested_; }
- protected:
- void SendImpl(const std::string& app_id,
- const std::string& receiver_id,
- const OutgoingMessage& message) override;
- private:
- AccountMapping account_mapping_;
- std::string last_message_id_;
- CoreAccountId last_removed_account_id_;
- LastMessageAction last_action_;
- std::map<std::string, LastMessageAction> all_messages_;
- bool registration_id_requested_;
- };
- CustomFakeGCMDriver::CustomFakeGCMDriver()
- : last_action_(NONE), registration_id_requested_(false) {
- }
- CustomFakeGCMDriver::~CustomFakeGCMDriver() {
- }
- void CustomFakeGCMDriver::UpdateAccountMapping(
- const AccountMapping& account_mapping) {
- account_mapping_.email = account_mapping.email;
- account_mapping_.account_id = account_mapping.account_id;
- account_mapping_.access_token = account_mapping.access_token;
- account_mapping_.status = account_mapping.status;
- account_mapping_.status_change_timestamp =
- account_mapping.status_change_timestamp;
- account_mapping_.last_message_id = account_mapping.last_message_id;
- }
- void CustomFakeGCMDriver::RemoveAccountMapping(
- const CoreAccountId& account_id) {
- last_removed_account_id_ = account_id;
- }
- void CustomFakeGCMDriver::RegisterImpl(
- const std::string& app_id,
- const std::vector<std::string>& sender_ids) {
- DCHECK_EQ(kGCMAccountMapperAppId, app_id);
- DCHECK_EQ(1u, sender_ids.size());
- DCHECK_EQ(kGCMAccountMapperSenderId, sender_ids[0]);
- registration_id_requested_ = true;
- }
- void CustomFakeGCMDriver::CompleteRegister(const std::string& registration_id,
- GCMClient::Result result) {
- RegisterFinished(kGCMAccountMapperAppId, registration_id, result);
- }
- void CustomFakeGCMDriver::CompleteSend(const std::string& message_id,
- GCMClient::Result result) {
- SendFinished(kGCMAccountMapperAppId, message_id, result);
- SetLastMessageAction(message_id, SEND_FINISHED);
- }
- void CustomFakeGCMDriver::AcknowledgeSend(const std::string& message_id) {
- GCMAppHandler* handler = GetAppHandler(kGCMAccountMapperAppId);
- if (handler)
- handler->OnSendAcknowledged(kGCMAccountMapperAppId, message_id);
- SetLastMessageAction(message_id, SEND_ACKNOWLEDGED);
- }
- void CustomFakeGCMDriver::MessageSendError(const std::string& message_id) {
- GCMAppHandler* handler = GetAppHandler(kGCMAccountMapperAppId);
- if (!handler)
- return;
- GCMClient::SendErrorDetails send_error;
- send_error.message_id = message_id;
- send_error.result = GCMClient::TTL_EXCEEDED;
- handler->OnSendError(kGCMAccountMapperAppId, send_error);
- }
- void CustomFakeGCMDriver::SendImpl(const std::string& app_id,
- const std::string& receiver_id,
- const OutgoingMessage& message) {
- DCHECK_EQ(kGCMAccountMapperAppId, app_id);
- DCHECK_EQ(kGCMAccountMapperSendTo, receiver_id);
- SetLastMessageAction(message.id, SEND_STARTED);
- }
- void CustomFakeGCMDriver::CompleteSendAllMessages() {
- for (std::map<std::string, LastMessageAction>::const_iterator iter =
- all_messages_.begin();
- iter != all_messages_.end();
- ++iter) {
- if (iter->second == SEND_STARTED)
- CompleteSend(iter->first, GCMClient::SUCCESS);
- }
- }
- void CustomFakeGCMDriver::AcknowledgeSendAllMessages() {
- for (std::map<std::string, LastMessageAction>::const_iterator iter =
- all_messages_.begin();
- iter != all_messages_.end();
- ++iter) {
- if (iter->second == SEND_FINISHED)
- AcknowledgeSend(iter->first);
- }
- }
- void CustomFakeGCMDriver::Clear() {
- account_mapping_ = AccountMapping();
- last_message_id_.clear();
- last_removed_account_id_ = CoreAccountId();
- last_action_ = NONE;
- registration_id_requested_ = false;
- }
- void CustomFakeGCMDriver::SetLastMessageAction(const std::string& message_id,
- LastMessageAction action) {
- last_action_ = action;
- last_message_id_ = message_id;
- all_messages_[message_id] = action;
- }
- } // namespace
- class GCMAccountMapperTest : public testing::Test {
- public:
- const CoreAccountId kAccountId;
- const CoreAccountId kAccountId1;
- const CoreAccountId kAccountId2;
- const CoreAccountId kAccountId3;
- const CoreAccountId kAccountId4;
- GCMAccountMapperTest();
- ~GCMAccountMapperTest() override;
- void Restart();
- void Initialize(const GCMAccountMapper::AccountMappings mappings);
- const GCMAccountMapper::AccountMappings& GetAccounts() const {
- return account_mapper_->accounts_;
- }
- void MessageReceived(const std::string& app_id,
- const IncomingMessage& message);
- GCMAccountMapper* mapper() { return account_mapper_.get(); }
- CustomFakeGCMDriver& gcm_driver() { return gcm_driver_; }
- base::SimpleTestClock* clock() { return &clock_; }
- const std::string& last_received_app_id() const {
- return last_received_app_id_;
- }
- const IncomingMessage& last_received_message() const {
- return last_received_message_;
- }
- private:
- CustomFakeGCMDriver gcm_driver_;
- std::unique_ptr<GCMAccountMapper> account_mapper_;
- base::SimpleTestClock clock_;
- std::string last_received_app_id_;
- IncomingMessage last_received_message_;
- };
- GCMAccountMapperTest::GCMAccountMapperTest()
- : kAccountId("acc_id"),
- kAccountId1("acc_id1"),
- kAccountId2("acc_id2"),
- kAccountId3("acc_id3"),
- kAccountId4("acc_id4") {
- Restart();
- }
- GCMAccountMapperTest::~GCMAccountMapperTest() {
- }
- void GCMAccountMapperTest::Restart() {
- if (account_mapper_)
- account_mapper_->ShutdownHandler();
- gcm_driver_.RemoveAppHandler(kGCMAccountMapperAppId);
- account_mapper_ = std::make_unique<GCMAccountMapper>(&gcm_driver_);
- account_mapper_->SetClockForTesting(&clock_);
- }
- void GCMAccountMapperTest::Initialize(
- const GCMAccountMapper::AccountMappings mappings) {
- mapper()->Initialize(
- mappings, base::BindRepeating(&GCMAccountMapperTest::MessageReceived,
- base::Unretained(this)));
- }
- void GCMAccountMapperTest::MessageReceived(const std::string& app_id,
- const IncomingMessage& message) {
- last_received_app_id_ = app_id;
- last_received_message_ = message;
- }
- // Tests the initialization of account mappings (from the store) when empty.
- // It also checks that initialization triggers registration ID request.
- TEST_F(GCMAccountMapperTest, InitializeAccountMappingsEmpty) {
- EXPECT_FALSE(gcm_driver().registration_id_requested());
- Initialize(GCMAccountMapper::AccountMappings());
- EXPECT_TRUE(GetAccounts().empty());
- EXPECT_TRUE(gcm_driver().registration_id_requested());
- }
- // Tests that registration is retried, when new tokens are delivered and in no
- // other circumstances.
- TEST_F(GCMAccountMapperTest, RegistrationRetryUponFailure) {
- Initialize(GCMAccountMapper::AccountMappings());
- EXPECT_TRUE(gcm_driver().registration_id_requested());
- gcm_driver().Clear();
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::UNKNOWN_ERROR);
- EXPECT_FALSE(gcm_driver().registration_id_requested());
- gcm_driver().Clear();
- std::vector<GCMClient::AccountTokenInfo> account_tokens;
- account_tokens.push_back(MakeAccountTokenInfo(kAccountId2));
- mapper()->SetAccountTokens(account_tokens);
- EXPECT_TRUE(gcm_driver().registration_id_requested());
- gcm_driver().Clear();
- gcm_driver().CompleteRegister(kRegistrationId,
- GCMClient::ASYNC_OPERATION_PENDING);
- EXPECT_FALSE(gcm_driver().registration_id_requested());
- }
- // Tests the initialization of account mappings (from the store).
- TEST_F(GCMAccountMapperTest, InitializeAccountMappings) {
- GCMAccountMapper::AccountMappings account_mappings;
- AccountMapping account_mapping1 = MakeAccountMapping(
- kAccountId1, AccountMapping::MAPPED, base::Time::Now(), std::string());
- AccountMapping account_mapping2 = MakeAccountMapping(
- kAccountId2, AccountMapping::ADDING, base::Time::Now(), "add_message_1");
- account_mappings.push_back(account_mapping1);
- account_mappings.push_back(account_mapping2);
- Initialize(account_mappings);
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- EXPECT_EQ(2UL, mappings.size());
- GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin();
- EXPECT_EQ(account_mapping1.account_id, iter->account_id);
- EXPECT_EQ(account_mapping1.email, iter->email);
- EXPECT_TRUE(account_mapping1.access_token.empty());
- EXPECT_EQ(account_mapping1.status, iter->status);
- EXPECT_EQ(account_mapping1.status_change_timestamp,
- iter->status_change_timestamp);
- EXPECT_TRUE(account_mapping1.last_message_id.empty());
- ++iter;
- EXPECT_EQ(account_mapping2.account_id, iter->account_id);
- EXPECT_EQ(account_mapping2.email, iter->email);
- EXPECT_TRUE(account_mapping2.access_token.empty());
- EXPECT_EQ(account_mapping2.status, iter->status);
- EXPECT_EQ(account_mapping2.status_change_timestamp,
- iter->status_change_timestamp);
- EXPECT_EQ(account_mapping2.last_message_id, iter->last_message_id);
- }
- // Tests that account tokens are not processed until registration ID is
- // available.
- TEST_F(GCMAccountMapperTest, SetAccountTokensOnlyWorksWithRegisterationId) {
- // Start with empty list.
- Initialize(GCMAccountMapper::AccountMappings());
- std::vector<GCMClient::AccountTokenInfo> account_tokens;
- account_tokens.push_back(MakeAccountTokenInfo(kAccountId));
- mapper()->SetAccountTokens(account_tokens);
- EXPECT_TRUE(GetAccounts().empty());
- account_tokens.clear();
- account_tokens.push_back(MakeAccountTokenInfo(kAccountId1));
- account_tokens.push_back(MakeAccountTokenInfo(kAccountId2));
- mapper()->SetAccountTokens(account_tokens);
- EXPECT_TRUE(GetAccounts().empty());
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- EXPECT_EQ(2UL, mappings.size());
- EXPECT_EQ(kAccountId1, mappings[0].account_id);
- EXPECT_EQ(kAccountId2, mappings[1].account_id);
- }
- // Tests the part where a new account is added with a token, to the point when
- // GCM message is sent.
- TEST_F(GCMAccountMapperTest, AddMappingToMessageSent) {
- Initialize(GCMAccountMapper::AccountMappings());
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- std::vector<GCMClient::AccountTokenInfo> account_tokens;
- GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo(kAccountId);
- account_tokens.push_back(account_token);
- mapper()->SetAccountTokens(account_tokens);
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- EXPECT_EQ(1UL, mappings.size());
- GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin();
- EXPECT_EQ(kAccountId, iter->account_id);
- EXPECT_EQ("acc_id@gmail.com", iter->email);
- EXPECT_EQ("acc_id_token", iter->access_token);
- EXPECT_EQ(AccountMapping::NEW, iter->status);
- EXPECT_EQ(base::Time(), iter->status_change_timestamp);
- EXPECT_TRUE(!gcm_driver().last_message_id().empty());
- }
- // Tests the part where GCM message is successfully queued.
- TEST_F(GCMAccountMapperTest, AddMappingMessageQueued) {
- Initialize(GCMAccountMapper::AccountMappings());
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- std::vector<GCMClient::AccountTokenInfo> account_tokens;
- GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo(kAccountId);
- account_tokens.push_back(account_token);
- mapper()->SetAccountTokens(account_tokens);
- clock()->SetNow(base::Time::Now());
- gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS);
- EXPECT_EQ(account_token.email, gcm_driver().last_account_mapping().email);
- EXPECT_EQ(account_token.account_id,
- gcm_driver().last_account_mapping().account_id);
- EXPECT_EQ(account_token.access_token,
- gcm_driver().last_account_mapping().access_token);
- EXPECT_EQ(AccountMapping::ADDING, gcm_driver().last_account_mapping().status);
- EXPECT_EQ(clock()->Now(),
- gcm_driver().last_account_mapping().status_change_timestamp);
- EXPECT_EQ(gcm_driver().last_message_id(),
- gcm_driver().last_account_mapping().last_message_id);
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin();
- EXPECT_EQ(account_token.email, iter->email);
- EXPECT_EQ(account_token.account_id, iter->account_id);
- EXPECT_EQ(account_token.access_token, iter->access_token);
- EXPECT_EQ(AccountMapping::ADDING, iter->status);
- EXPECT_EQ(clock()->Now(), iter->status_change_timestamp);
- EXPECT_EQ(gcm_driver().last_message_id(), iter->last_message_id);
- }
- // Tests status change from ADDING to MAPPED (Message is acknowledged).
- TEST_F(GCMAccountMapperTest, AddMappingMessageAcknowledged) {
- Initialize(GCMAccountMapper::AccountMappings());
- gcm_driver().AddAppHandler(kGCMAccountMapperAppId, mapper());
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- std::vector<GCMClient::AccountTokenInfo> account_tokens;
- GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo(kAccountId);
- account_tokens.push_back(account_token);
- mapper()->SetAccountTokens(account_tokens);
- clock()->SetNow(base::Time::Now());
- gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS);
- clock()->SetNow(base::Time::Now());
- gcm_driver().AcknowledgeSend(gcm_driver().last_message_id());
- EXPECT_EQ(account_token.email, gcm_driver().last_account_mapping().email);
- EXPECT_EQ(account_token.account_id,
- gcm_driver().last_account_mapping().account_id);
- EXPECT_EQ(account_token.access_token,
- gcm_driver().last_account_mapping().access_token);
- EXPECT_EQ(AccountMapping::MAPPED, gcm_driver().last_account_mapping().status);
- EXPECT_EQ(clock()->Now(),
- gcm_driver().last_account_mapping().status_change_timestamp);
- EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id.empty());
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin();
- EXPECT_EQ(account_token.email, iter->email);
- EXPECT_EQ(account_token.account_id, iter->account_id);
- EXPECT_EQ(account_token.access_token, iter->access_token);
- EXPECT_EQ(AccountMapping::MAPPED, iter->status);
- EXPECT_EQ(clock()->Now(), iter->status_change_timestamp);
- EXPECT_TRUE(iter->last_message_id.empty());
- }
- // Tests status change form ADDING to MAPPED (When message was acknowledged,
- // after Chrome was restarted).
- TEST_F(GCMAccountMapperTest, AddMappingMessageAckedAfterRestart) {
- Initialize(GCMAccountMapper::AccountMappings());
- gcm_driver().AddAppHandler(kGCMAccountMapperAppId, mapper());
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- std::vector<GCMClient::AccountTokenInfo> account_tokens;
- GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo(kAccountId);
- account_tokens.push_back(account_token);
- mapper()->SetAccountTokens(account_tokens);
- clock()->SetNow(base::Time::Now());
- gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS);
- Restart();
- GCMAccountMapper::AccountMappings stored_mappings;
- stored_mappings.push_back(gcm_driver().last_account_mapping());
- Initialize(stored_mappings);
- gcm_driver().AddAppHandler(kGCMAccountMapperAppId, mapper());
- clock()->SetNow(base::Time::Now());
- gcm_driver().AcknowledgeSend(gcm_driver().last_message_id());
- EXPECT_EQ(account_token.email, gcm_driver().last_account_mapping().email);
- EXPECT_EQ(account_token.account_id,
- gcm_driver().last_account_mapping().account_id);
- EXPECT_EQ(account_token.access_token,
- gcm_driver().last_account_mapping().access_token);
- EXPECT_EQ(AccountMapping::MAPPED, gcm_driver().last_account_mapping().status);
- EXPECT_EQ(clock()->Now(),
- gcm_driver().last_account_mapping().status_change_timestamp);
- EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id.empty());
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin();
- EXPECT_EQ(account_token.email, iter->email);
- EXPECT_EQ(account_token.account_id, iter->account_id);
- EXPECT_EQ(account_token.access_token, iter->access_token);
- EXPECT_EQ(AccountMapping::MAPPED, iter->status);
- EXPECT_EQ(clock()->Now(), iter->status_change_timestamp);
- EXPECT_TRUE(iter->last_message_id.empty());
- }
- // Tests a case when ADD message times out for a new account.
- TEST_F(GCMAccountMapperTest, AddMappingMessageSendErrorForNewAccount) {
- Initialize(GCMAccountMapper::AccountMappings());
- gcm_driver().AddAppHandler(kGCMAccountMapperAppId, mapper());
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- std::vector<GCMClient::AccountTokenInfo> account_tokens;
- GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo(kAccountId);
- account_tokens.push_back(account_token);
- mapper()->SetAccountTokens(account_tokens);
- clock()->SetNow(base::Time::Now());
- gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS);
- clock()->SetNow(base::Time::Now());
- std::string old_message_id = gcm_driver().last_message_id();
- gcm_driver().MessageSendError(old_message_id);
- // No new message is sent because of the send error, as the token is stale.
- // Because the account was new, the entry should be deleted.
- EXPECT_EQ(old_message_id, gcm_driver().last_message_id());
- EXPECT_EQ(account_token.account_id, gcm_driver().last_removed_account_id());
- EXPECT_TRUE(GetAccounts().empty());
- }
- /// Tests a case when ADD message times out for a MAPPED account.
- TEST_F(GCMAccountMapperTest, AddMappingMessageSendErrorForMappedAccount) {
- // Start with one account that is mapped.
- base::Time status_change_timestamp = base::Time::Now();
- AccountMapping mapping =
- MakeAccountMapping(kAccountId, AccountMapping::MAPPED,
- status_change_timestamp, "add_message_id");
- GCMAccountMapper::AccountMappings stored_mappings;
- stored_mappings.push_back(mapping);
- Initialize(stored_mappings);
- gcm_driver().AddAppHandler(kGCMAccountMapperAppId, mapper());
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- clock()->SetNow(base::Time::Now());
- gcm_driver().MessageSendError("add_message_id");
- // No new message is sent because of the send error, as the token is stale.
- // Because the account was new, the entry should be deleted.
- EXPECT_TRUE(gcm_driver().last_message_id().empty());
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin();
- EXPECT_EQ(mapping.email, iter->email);
- EXPECT_EQ(mapping.account_id, iter->account_id);
- EXPECT_EQ(mapping.access_token, iter->access_token);
- EXPECT_EQ(AccountMapping::MAPPED, iter->status);
- EXPECT_EQ(status_change_timestamp, iter->status_change_timestamp);
- EXPECT_TRUE(iter->last_message_id.empty());
- }
- // Tests that a missing token for an account will trigger removing of that
- // account. This test goes only until the message is passed to GCM.
- TEST_F(GCMAccountMapperTest, RemoveMappingToMessageSent) {
- // Start with one account that is mapped.
- AccountMapping mapping = MakeAccountMapping(
- kAccountId, AccountMapping::MAPPED, base::Time::Now(), std::string());
- GCMAccountMapper::AccountMappings stored_mappings;
- stored_mappings.push_back(mapping);
- Initialize(stored_mappings);
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- clock()->SetNow(base::Time::Now());
- mapper()->SetAccountTokens(std::vector<GCMClient::AccountTokenInfo>());
- EXPECT_EQ(mapping.account_id, gcm_driver().last_account_mapping().account_id);
- EXPECT_EQ(mapping.email, gcm_driver().last_account_mapping().email);
- EXPECT_EQ(AccountMapping::REMOVING,
- gcm_driver().last_account_mapping().status);
- EXPECT_EQ(clock()->Now(),
- gcm_driver().last_account_mapping().status_change_timestamp);
- EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id.empty());
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin();
- EXPECT_EQ(mapping.email, iter->email);
- EXPECT_EQ(mapping.account_id, iter->account_id);
- EXPECT_EQ(mapping.access_token, iter->access_token);
- EXPECT_EQ(AccountMapping::REMOVING, iter->status);
- EXPECT_EQ(clock()->Now(), iter->status_change_timestamp);
- EXPECT_TRUE(iter->last_message_id.empty());
- }
- // Tests that a missing token for an account will trigger removing of that
- // account. This test goes until the message is queued by GCM.
- TEST_F(GCMAccountMapperTest, RemoveMappingMessageQueued) {
- // Start with one account that is mapped.
- AccountMapping mapping = MakeAccountMapping(
- kAccountId, AccountMapping::MAPPED, base::Time::Now(), std::string());
- GCMAccountMapper::AccountMappings stored_mappings;
- stored_mappings.push_back(mapping);
- Initialize(stored_mappings);
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- clock()->SetNow(base::Time::Now());
- base::Time status_change_timestamp = clock()->Now();
- mapper()->SetAccountTokens(std::vector<GCMClient::AccountTokenInfo>());
- clock()->SetNow(base::Time::Now());
- gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS);
- EXPECT_EQ(mapping.account_id, gcm_driver().last_account_mapping().account_id);
- EXPECT_EQ(mapping.email, gcm_driver().last_account_mapping().email);
- EXPECT_EQ(AccountMapping::REMOVING,
- gcm_driver().last_account_mapping().status);
- EXPECT_EQ(status_change_timestamp,
- gcm_driver().last_account_mapping().status_change_timestamp);
- EXPECT_TRUE(!gcm_driver().last_account_mapping().last_message_id.empty());
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin();
- EXPECT_EQ(mapping.email, iter->email);
- EXPECT_EQ(mapping.account_id, iter->account_id);
- EXPECT_EQ(mapping.access_token, iter->access_token);
- EXPECT_EQ(AccountMapping::REMOVING, iter->status);
- EXPECT_EQ(status_change_timestamp, iter->status_change_timestamp);
- EXPECT_EQ(gcm_driver().last_account_mapping().last_message_id,
- iter->last_message_id);
- }
- // Tests that a missing token for an account will trigger removing of that
- // account. This test goes until the message is acknowledged by GCM.
- // This is a complete success scenario for account removal, and it end with
- // account mapping being completely gone.
- TEST_F(GCMAccountMapperTest, RemoveMappingMessageAcknowledged) {
- // Start with one account that is mapped.
- AccountMapping mapping = MakeAccountMapping(
- kAccountId, AccountMapping::MAPPED, base::Time::Now(), std::string());
- GCMAccountMapper::AccountMappings stored_mappings;
- stored_mappings.push_back(mapping);
- Initialize(stored_mappings);
- gcm_driver().AddAppHandler(kGCMAccountMapperAppId, mapper());
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- clock()->SetNow(base::Time::Now());
- mapper()->SetAccountTokens(std::vector<GCMClient::AccountTokenInfo>());
- gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS);
- gcm_driver().AcknowledgeSend(gcm_driver().last_message_id());
- EXPECT_EQ(mapping.account_id, gcm_driver().last_removed_account_id());
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- EXPECT_TRUE(mappings.empty());
- }
- // Tests that account removing proceeds, when a removing message is acked after
- // Chrome was restarted.
- TEST_F(GCMAccountMapperTest, RemoveMappingMessageAckedAfterRestart) {
- // Start with one account that is mapped.
- AccountMapping mapping =
- MakeAccountMapping(kAccountId, AccountMapping::REMOVING,
- base::Time::Now(), "remove_message_id");
- GCMAccountMapper::AccountMappings stored_mappings;
- stored_mappings.push_back(mapping);
- Initialize(stored_mappings);
- gcm_driver().AddAppHandler(kGCMAccountMapperAppId, mapper());
- gcm_driver().AcknowledgeSend("remove_message_id");
- EXPECT_EQ(mapping.account_id, gcm_driver().last_removed_account_id());
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- EXPECT_TRUE(mappings.empty());
- }
- // Tests that account removing proceeds, when a removing message is acked after
- // Chrome was restarted.
- TEST_F(GCMAccountMapperTest, RemoveMappingMessageSendError) {
- // Start with one account that is mapped.
- base::Time status_change_timestamp = base::Time::Now();
- AccountMapping mapping =
- MakeAccountMapping(kAccountId, AccountMapping::REMOVING,
- status_change_timestamp, "remove_message_id");
- GCMAccountMapper::AccountMappings stored_mappings;
- stored_mappings.push_back(mapping);
- Initialize(stored_mappings);
- gcm_driver().AddAppHandler(kGCMAccountMapperAppId, mapper());
- clock()->SetNow(base::Time::Now());
- gcm_driver().MessageSendError("remove_message_id");
- EXPECT_TRUE(gcm_driver().last_removed_account_id().empty());
- EXPECT_EQ(mapping.account_id, gcm_driver().last_account_mapping().account_id);
- EXPECT_EQ(mapping.email, gcm_driver().last_account_mapping().email);
- EXPECT_EQ(AccountMapping::REMOVING,
- gcm_driver().last_account_mapping().status);
- EXPECT_EQ(status_change_timestamp,
- gcm_driver().last_account_mapping().status_change_timestamp);
- // Message is not persisted, until send is completed.
- EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id.empty());
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin();
- EXPECT_EQ(mapping.email, iter->email);
- EXPECT_EQ(mapping.account_id, iter->account_id);
- EXPECT_TRUE(iter->access_token.empty());
- EXPECT_EQ(AccountMapping::REMOVING, iter->status);
- EXPECT_EQ(status_change_timestamp, iter->status_change_timestamp);
- EXPECT_TRUE(iter->last_message_id.empty());
- }
- // Tests that, if a new token arrives when the adding message is in progress
- // no new message is sent and account mapper still waits for the first one to
- // complete.
- TEST_F(GCMAccountMapperTest, TokenIsRefreshedWhenAdding) {
- Initialize(GCMAccountMapper::AccountMappings());
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- clock()->SetNow(base::Time::Now());
- std::vector<GCMClient::AccountTokenInfo> account_tokens;
- GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo(kAccountId);
- account_tokens.push_back(account_token);
- mapper()->SetAccountTokens(account_tokens);
- DCHECK_EQ(CustomFakeGCMDriver::SEND_STARTED, gcm_driver().last_action());
- clock()->SetNow(base::Time::Now());
- gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS);
- DCHECK_EQ(CustomFakeGCMDriver::SEND_FINISHED, gcm_driver().last_action());
- // Providing another token and clearing status.
- gcm_driver().Clear();
- mapper()->SetAccountTokens(account_tokens);
- DCHECK_EQ(CustomFakeGCMDriver::NONE, gcm_driver().last_action());
- }
- // Tests that, if a new token arrives when a removing message is in progress
- // a new adding message is sent and while account mapping status is changed to
- // mapped. If the original Removing message arrives it is discarded.
- TEST_F(GCMAccountMapperTest, TokenIsRefreshedWhenRemoving) {
- // Start with one account that is mapped.
- AccountMapping mapping = MakeAccountMapping(
- kAccountId, AccountMapping::MAPPED, base::Time::Now(), std::string());
- GCMAccountMapper::AccountMappings stored_mappings;
- stored_mappings.push_back(mapping);
- Initialize(stored_mappings);
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- clock()->SetNow(base::Time::Now());
- // Remove the token to trigger a remove message to be sent
- mapper()->SetAccountTokens(std::vector<GCMClient::AccountTokenInfo>());
- EXPECT_EQ(CustomFakeGCMDriver::SEND_STARTED, gcm_driver().last_action());
- gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS);
- EXPECT_EQ(CustomFakeGCMDriver::SEND_FINISHED, gcm_driver().last_action());
- std::string remove_message_id = gcm_driver().last_message_id();
- gcm_driver().Clear();
- // The account mapping for acc_id is now in status REMOVING.
- // Adding the token for that account.
- clock()->SetNow(base::Time::Now());
- std::vector<GCMClient::AccountTokenInfo> account_tokens;
- GCMClient::AccountTokenInfo account_token = MakeAccountTokenInfo(kAccountId);
- account_tokens.push_back(account_token);
- mapper()->SetAccountTokens(account_tokens);
- DCHECK_EQ(CustomFakeGCMDriver::SEND_STARTED, gcm_driver().last_action());
- gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS);
- EXPECT_EQ(CustomFakeGCMDriver::SEND_FINISHED, gcm_driver().last_action());
- std::string add_message_id = gcm_driver().last_message_id();
- // A remove message confirmation arrives now, but should be ignored.
- gcm_driver().AcknowledgeSend(remove_message_id);
- GCMAccountMapper::AccountMappings mappings = GetAccounts();
- GCMAccountMapper::AccountMappings::const_iterator iter = mappings.begin();
- EXPECT_EQ(mapping.email, iter->email);
- EXPECT_EQ(mapping.account_id, iter->account_id);
- EXPECT_FALSE(iter->access_token.empty());
- EXPECT_EQ(AccountMapping::MAPPED, iter->status);
- // Status change timestamp is set to very long time ago, to make sure the next
- // round of mapping picks it up.
- EXPECT_EQ(base::Time(), iter->status_change_timestamp);
- EXPECT_EQ(add_message_id, iter->last_message_id);
- }
- // Tests adding/removing works for multiple accounts, after a restart and when
- // tokens are periodically delierverd.
- TEST_F(GCMAccountMapperTest, MultipleAccountMappings) {
- clock()->SetNow(base::Time::Now());
- base::Time half_hour_ago = clock()->Now() - base::Minutes(30);
- GCMAccountMapper::AccountMappings stored_mappings;
- stored_mappings.push_back(MakeAccountMapping(
- kAccountId, AccountMapping::ADDING, half_hour_ago, "acc_id_msg"));
- stored_mappings.push_back(MakeAccountMapping(
- kAccountId1, AccountMapping::MAPPED, half_hour_ago, "acc_id_1_msg"));
- stored_mappings.push_back(MakeAccountMapping(
- kAccountId2, AccountMapping::REMOVING, half_hour_ago, "acc_id_2_msg"));
- Initialize(stored_mappings);
- gcm_driver().AddAppHandler(kGCMAccountMapperAppId, mapper());
- gcm_driver().CompleteRegister(kRegistrationId, GCMClient::SUCCESS);
- GCMAccountMapper::AccountMappings expected_mappings(stored_mappings);
- // Finish messages after a restart.
- clock()->SetNow(base::Time::Now());
- gcm_driver().AcknowledgeSend(expected_mappings[0].last_message_id);
- expected_mappings[0].status_change_timestamp = clock()->Now();
- expected_mappings[0].status = AccountMapping::MAPPED;
- expected_mappings[0].last_message_id.clear();
- clock()->SetNow(base::Time::Now());
- gcm_driver().AcknowledgeSend(expected_mappings[1].last_message_id);
- expected_mappings[1].status_change_timestamp = clock()->Now();
- expected_mappings[1].status = AccountMapping::MAPPED;
- expected_mappings[1].last_message_id.clear();
- // Upon success last element is removed.
- clock()->SetNow(base::Time::Now());
- gcm_driver().AcknowledgeSend(expected_mappings[2].last_message_id);
- expected_mappings.pop_back();
- VerifyMappings(expected_mappings, GetAccounts(), "Step 1, After restart");
- // One of accounts gets removed.
- std::vector<GCMClient::AccountTokenInfo> account_tokens;
- account_tokens.push_back(MakeAccountTokenInfo(kAccountId));
- // Advance a day to make sure existing mappings will be reported.
- clock()->SetNow(clock()->Now() + base::Days(1));
- mapper()->SetAccountTokens(account_tokens);
- expected_mappings[0].status = AccountMapping::MAPPED;
- expected_mappings[1].status = AccountMapping::REMOVING;
- expected_mappings[1].status_change_timestamp = clock()->Now();
- gcm_driver().CompleteSendAllMessages();
- VerifyMappings(
- expected_mappings, GetAccounts(), "Step 2, One account is being removed");
- clock()->SetNow(clock()->Now() + base::Seconds(5));
- gcm_driver().AcknowledgeSendAllMessages();
- expected_mappings[0].status_change_timestamp = clock()->Now();
- expected_mappings.pop_back();
- VerifyMappings(
- expected_mappings, GetAccounts(), "Step 3, Removing completed");
- account_tokens.clear();
- account_tokens.push_back(MakeAccountTokenInfo(kAccountId));
- account_tokens.push_back(MakeAccountTokenInfo(kAccountId3));
- account_tokens.push_back(MakeAccountTokenInfo(kAccountId4));
- // Advance a day to make sure existing mappings will be reported.
- clock()->SetNow(clock()->Now() + base::Days(1));
- mapper()->SetAccountTokens(account_tokens);
- // Mapping from acc_id_0 still in position 0
- expected_mappings.push_back(MakeAccountMapping(
- kAccountId3, AccountMapping::NEW, base::Time(), std::string()));
- expected_mappings.push_back(MakeAccountMapping(
- kAccountId4, AccountMapping::NEW, base::Time(), std::string()));
- VerifyMappings(expected_mappings, GetAccounts(), "Step 4, Two new accounts");
- clock()->SetNow(clock()->Now() + base::Seconds(1));
- gcm_driver().CompleteSendAllMessages();
- expected_mappings[1].status = AccountMapping::ADDING;
- expected_mappings[1].status_change_timestamp = clock()->Now();
- expected_mappings[2].status = AccountMapping::ADDING;
- expected_mappings[2].status_change_timestamp = clock()->Now();
- VerifyMappings(
- expected_mappings, GetAccounts(), "Step 5, Two accounts being added");
- clock()->SetNow(clock()->Now() + base::Seconds(5));
- gcm_driver().AcknowledgeSendAllMessages();
- expected_mappings[0].status_change_timestamp = clock()->Now();
- expected_mappings[1].status_change_timestamp = clock()->Now();
- expected_mappings[1].status = AccountMapping::MAPPED;
- expected_mappings[2].status_change_timestamp = clock()->Now();
- expected_mappings[2].status = AccountMapping::MAPPED;
- VerifyMappings(
- expected_mappings, GetAccounts(), "Step 6, Three mapped accounts");
- }
- TEST_F(GCMAccountMapperTest, DispatchMessageSentToGaiaID) {
- Initialize(GCMAccountMapper::AccountMappings());
- gcm_driver().AddAppHandler(kGCMAccountMapperAppId, mapper());
- IncomingMessage message;
- message.data[kEmbeddedAppIdKey] = kTestAppId;
- message.data[kTestDataKey] = kTestDataValue;
- message.collapse_key = kTestCollapseKey;
- message.sender_id = kTestSenderId;
- mapper()->OnMessage(kGCMAccountMapperAppId, message);
- EXPECT_EQ(kTestAppId, last_received_app_id());
- EXPECT_EQ(1UL, last_received_message().data.size());
- auto it = last_received_message().data.find(kTestDataKey);
- EXPECT_TRUE(it != last_received_message().data.end());
- EXPECT_EQ(kTestDataValue, it->second);
- EXPECT_EQ(kTestCollapseKey, last_received_message().collapse_key);
- EXPECT_EQ(kTestSenderId, last_received_message().sender_id);
- }
- } // namespace gcm
|