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.
5 #include "components/gcm_driver/gcm_account_mapper.h"
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"
18 const char kGCMAccountMapperSenderId
[] = "745476177629";
19 const char kRegistrationId
[] = "reg_id";
21 AccountMapping
MakeAccountMapping(const std::string
& account_id
,
22 AccountMapping::MappingStatus status
,
23 const base::Time
& status_change_timestamp
,
24 const std::string
& last_message_id
) {
25 AccountMapping account_mapping
;
26 account_mapping
.account_id
= account_id
;
27 account_mapping
.email
= account_id
+ "@gmail.com";
28 // account_mapping.access_token intentionally left empty.
29 account_mapping
.status
= status
;
30 account_mapping
.status_change_timestamp
= status_change_timestamp
;
31 account_mapping
.last_message_id
= last_message_id
;
32 return account_mapping
;
35 GCMClient::AccountTokenInfo
MakeAccountTokenInfo(
36 const std::string
& account_id
) {
37 GCMClient::AccountTokenInfo account_token
;
38 account_token
.account_id
= account_id
;
39 account_token
.email
= account_id
+ "@gmail.com";
40 account_token
.access_token
= account_id
+ "_token";
44 void VerifyMappings(const GCMAccountMapper::AccountMappings
& expected_mappings
,
45 const GCMAccountMapper::AccountMappings
& actual_mappings
,
46 const std::string
& verification_info
) {
47 EXPECT_EQ(expected_mappings
.size(), actual_mappings
.size())
48 << "Verification Info: " << verification_info
;
49 GCMAccountMapper::AccountMappings::const_iterator expected_iter
=
50 expected_mappings
.begin();
51 GCMAccountMapper::AccountMappings::const_iterator actual_iter
=
52 actual_mappings
.begin();
53 for (; expected_iter
!= expected_mappings
.end() &&
54 actual_iter
!= actual_mappings
.end();
55 ++expected_iter
, ++actual_iter
) {
56 EXPECT_EQ(expected_iter
->email
, actual_iter
->email
)
57 << "Verification Info: " << verification_info
58 << "; Account ID of expected: " << expected_iter
->account_id
;
59 EXPECT_EQ(expected_iter
->account_id
, actual_iter
->account_id
)
60 << "Verification Info: " << verification_info
;
61 EXPECT_EQ(expected_iter
->status
, actual_iter
->status
)
62 << "Verification Info: " << verification_info
63 << "; Account ID of expected: " << expected_iter
->account_id
;
64 EXPECT_EQ(expected_iter
->status_change_timestamp
,
65 actual_iter
->status_change_timestamp
)
66 << "Verification Info: " << verification_info
67 << "; Account ID of expected: " << expected_iter
->account_id
;
71 class CustomFakeGCMDriver
: public FakeGCMDriver
{
73 enum LastMessageAction
{
80 CustomFakeGCMDriver();
81 ~CustomFakeGCMDriver() override
;
83 void UpdateAccountMapping(const AccountMapping
& account_mapping
) override
;
84 void RemoveAccountMapping(const std::string
& account_id
) override
;
85 void AddAppHandler(const std::string
& app_id
,
86 GCMAppHandler
* handler
) override
;
87 void RemoveAppHandler(const std::string
& app_id
) override
;
88 void RegisterImpl(const std::string
& app_id
,
89 const std::vector
<std::string
>& sender_ids
) override
;
91 void CompleteRegister(const std::string
& registration_id
,
92 GCMClient::Result result
);
93 void CompleteSend(const std::string
& message_id
, GCMClient::Result result
);
94 void AcknowledgeSend(const std::string
& message_id
);
95 void MessageSendError(const std::string
& message_id
);
97 void CompleteSendAllMessages();
98 void AcknowledgeSendAllMessages();
100 void SetLastMessageAction(const std::string
& message_id
,
101 LastMessageAction action
);
104 const AccountMapping
& last_account_mapping() const {
105 return account_mapping_
;
107 const std::string
& last_message_id() const { return last_message_id_
; }
108 const std::string
& last_removed_account_id() const {
109 return last_removed_account_id_
;
111 LastMessageAction
last_action() const { return last_action_
; }
112 bool registration_id_requested() const { return registration_id_requested_
; }
115 void SendImpl(const std::string
& app_id
,
116 const std::string
& receiver_id
,
117 const GCMClient::OutgoingMessage
& message
) override
;
120 AccountMapping account_mapping_
;
121 std::string last_message_id_
;
122 std::string last_removed_account_id_
;
123 LastMessageAction last_action_
;
124 std::map
<std::string
, LastMessageAction
> all_messages_
;
125 bool registration_id_requested_
;
128 CustomFakeGCMDriver::CustomFakeGCMDriver()
129 : last_action_(NONE
), registration_id_requested_(false) {
132 CustomFakeGCMDriver::~CustomFakeGCMDriver() {
135 void CustomFakeGCMDriver::UpdateAccountMapping(
136 const AccountMapping
& account_mapping
) {
137 account_mapping_
.email
= account_mapping
.email
;
138 account_mapping_
.account_id
= account_mapping
.account_id
;
139 account_mapping_
.access_token
= account_mapping
.access_token
;
140 account_mapping_
.status
= account_mapping
.status
;
141 account_mapping_
.status_change_timestamp
=
142 account_mapping
.status_change_timestamp
;
143 account_mapping_
.last_message_id
= account_mapping
.last_message_id
;
146 void CustomFakeGCMDriver::RemoveAccountMapping(const std::string
& account_id
) {
147 last_removed_account_id_
= account_id
;
150 void CustomFakeGCMDriver::AddAppHandler(const std::string
& app_id
,
151 GCMAppHandler
* handler
) {
152 GCMDriver::AddAppHandler(app_id
, handler
);
155 void CustomFakeGCMDriver::RemoveAppHandler(const std::string
& app_id
) {
156 GCMDriver::RemoveAppHandler(app_id
);
159 void CustomFakeGCMDriver::RegisterImpl(
160 const std::string
& app_id
,
161 const std::vector
<std::string
>& sender_ids
) {
162 DCHECK_EQ(kGCMAccountMapperAppId
, app_id
);
163 DCHECK_EQ(1u, sender_ids
.size());
164 DCHECK_EQ(kGCMAccountMapperSenderId
, sender_ids
[0]);
165 registration_id_requested_
= true;
168 void CustomFakeGCMDriver::CompleteRegister(const std::string
& registration_id
,
169 GCMClient::Result result
) {
170 RegisterFinished(kGCMAccountMapperAppId
, registration_id
, result
);
173 void CustomFakeGCMDriver::CompleteSend(const std::string
& message_id
,
174 GCMClient::Result result
) {
175 SendFinished(kGCMAccountMapperAppId
, message_id
, result
);
176 SetLastMessageAction(message_id
, SEND_FINISHED
);
179 void CustomFakeGCMDriver::AcknowledgeSend(const std::string
& message_id
) {
180 GetAppHandler(kGCMAccountMapperAppId
)
181 ->OnSendAcknowledged(kGCMAccountMapperAppId
, message_id
);
182 SetLastMessageAction(message_id
, SEND_ACKNOWLEDGED
);
185 void CustomFakeGCMDriver::MessageSendError(const std::string
& message_id
) {
186 GCMClient::SendErrorDetails send_error
;
187 send_error
.message_id
= message_id
;
188 send_error
.result
= GCMClient::TTL_EXCEEDED
;
189 GetAppHandler(kGCMAccountMapperAppId
)
190 ->OnSendError(kGCMAccountMapperAppId
, send_error
);
193 void CustomFakeGCMDriver::SendImpl(const std::string
& app_id
,
194 const std::string
& receiver_id
,
195 const GCMClient::OutgoingMessage
& message
) {
196 DCHECK_EQ(kGCMAccountMapperAppId
, app_id
);
197 DCHECK_EQ(kGCMAccountMapperSenderId
, receiver_id
);
199 SetLastMessageAction(message
.id
, SEND_STARTED
);
202 void CustomFakeGCMDriver::CompleteSendAllMessages() {
203 for (std::map
<std::string
, LastMessageAction
>::const_iterator iter
=
204 all_messages_
.begin();
205 iter
!= all_messages_
.end();
207 if (iter
->second
== SEND_STARTED
)
208 CompleteSend(iter
->first
, GCMClient::SUCCESS
);
212 void CustomFakeGCMDriver::AcknowledgeSendAllMessages() {
213 for (std::map
<std::string
, LastMessageAction
>::const_iterator iter
=
214 all_messages_
.begin();
215 iter
!= all_messages_
.end();
217 if (iter
->second
== SEND_FINISHED
)
218 AcknowledgeSend(iter
->first
);
222 void CustomFakeGCMDriver::Clear() {
223 account_mapping_
= AccountMapping();
224 last_message_id_
.clear();
225 last_removed_account_id_
.clear();
227 registration_id_requested_
= false;
230 void CustomFakeGCMDriver::SetLastMessageAction(const std::string
& message_id
,
231 LastMessageAction action
) {
232 last_action_
= action
;
233 last_message_id_
= message_id
;
234 all_messages_
[message_id
] = action
;
239 class GCMAccountMapperTest
: public testing::Test
{
241 GCMAccountMapperTest();
242 ~GCMAccountMapperTest() override
;
246 const GCMAccountMapper::AccountMappings
& GetAccounts() const {
247 return account_mapper_
->accounts_
;
250 GCMAccountMapper
* mapper() { return account_mapper_
.get(); }
252 CustomFakeGCMDriver
& gcm_driver() { return gcm_driver_
; }
254 base::SimpleTestClock
* clock() { return clock_
; }
257 CustomFakeGCMDriver gcm_driver_
;
258 scoped_ptr
<GCMAccountMapper
> account_mapper_
;
259 base::SimpleTestClock
* clock_
;
262 GCMAccountMapperTest::GCMAccountMapperTest() {
266 GCMAccountMapperTest::~GCMAccountMapperTest() {
269 void GCMAccountMapperTest::Restart() {
271 account_mapper_
->ShutdownHandler();
272 gcm_driver_
.RemoveAppHandler(kGCMAccountMapperAppId
);
273 account_mapper_
.reset(new GCMAccountMapper(&gcm_driver_
));
274 scoped_ptr
<base::SimpleTestClock
> clock(new base::SimpleTestClock
);
275 clock_
= clock
.get();
276 account_mapper_
->SetClockForTesting(clock
.Pass());
279 // Tests the initialization of account mappings (from the store) when empty.
280 // It also checks that initialization triggers registration ID request.
281 TEST_F(GCMAccountMapperTest
, InitializeAccountMappingsEmpty
) {
282 EXPECT_FALSE(gcm_driver().registration_id_requested());
283 mapper()->Initialize(GCMAccountMapper::AccountMappings());
284 EXPECT_TRUE(GetAccounts().empty());
285 EXPECT_TRUE(gcm_driver().registration_id_requested());
288 // Tests that registration is retried, when new tokens are delivered and in no
289 // other circumstances.
290 TEST_F(GCMAccountMapperTest
, RegistrationRetryUponFailure
) {
291 mapper()->Initialize(GCMAccountMapper::AccountMappings());
292 EXPECT_TRUE(gcm_driver().registration_id_requested());
293 gcm_driver().Clear();
295 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::UNKNOWN_ERROR
);
296 EXPECT_FALSE(gcm_driver().registration_id_requested());
297 gcm_driver().Clear();
299 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
300 account_tokens
.push_back(MakeAccountTokenInfo("acc_id2"));
301 mapper()->SetAccountTokens(account_tokens
);
302 EXPECT_TRUE(gcm_driver().registration_id_requested());
303 gcm_driver().Clear();
305 gcm_driver().CompleteRegister(kRegistrationId
,
306 GCMClient::ASYNC_OPERATION_PENDING
);
307 EXPECT_FALSE(gcm_driver().registration_id_requested());
310 // Tests the initialization of account mappings (from the store).
311 TEST_F(GCMAccountMapperTest
, InitializeAccountMappings
) {
312 GCMAccountMapper::AccountMappings account_mappings
;
313 AccountMapping account_mapping1
= MakeAccountMapping("acc_id1",
314 AccountMapping::MAPPED
,
317 AccountMapping account_mapping2
= MakeAccountMapping("acc_id2",
318 AccountMapping::ADDING
,
321 account_mappings
.push_back(account_mapping1
);
322 account_mappings
.push_back(account_mapping2
);
324 mapper()->Initialize(account_mappings
);
326 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
327 EXPECT_EQ(2UL, mappings
.size());
328 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
330 EXPECT_EQ(account_mapping1
.account_id
, iter
->account_id
);
331 EXPECT_EQ(account_mapping1
.email
, iter
->email
);
332 EXPECT_TRUE(account_mapping1
.access_token
.empty());
333 EXPECT_EQ(account_mapping1
.status
, iter
->status
);
334 EXPECT_EQ(account_mapping1
.status_change_timestamp
,
335 iter
->status_change_timestamp
);
336 EXPECT_TRUE(account_mapping1
.last_message_id
.empty());
339 EXPECT_EQ(account_mapping2
.account_id
, iter
->account_id
);
340 EXPECT_EQ(account_mapping2
.email
, iter
->email
);
341 EXPECT_TRUE(account_mapping2
.access_token
.empty());
342 EXPECT_EQ(account_mapping2
.status
, iter
->status
);
343 EXPECT_EQ(account_mapping2
.status_change_timestamp
,
344 iter
->status_change_timestamp
);
345 EXPECT_EQ(account_mapping2
.last_message_id
, iter
->last_message_id
);
348 // Tests that account tokens are not processed until registration ID is
350 TEST_F(GCMAccountMapperTest
, SetAccountTokensOnlyWorksWithRegisterationId
) {
351 // Start with empty list.
352 mapper()->Initialize(GCMAccountMapper::AccountMappings());
354 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
355 account_tokens
.push_back(MakeAccountTokenInfo("acc_id"));
356 mapper()->SetAccountTokens(account_tokens
);
358 EXPECT_TRUE(GetAccounts().empty());
360 account_tokens
.clear();
361 account_tokens
.push_back(MakeAccountTokenInfo("acc_id1"));
362 account_tokens
.push_back(MakeAccountTokenInfo("acc_id2"));
363 mapper()->SetAccountTokens(account_tokens
);
365 EXPECT_TRUE(GetAccounts().empty());
367 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
369 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
370 EXPECT_EQ(2UL, mappings
.size());
371 EXPECT_EQ("acc_id1", mappings
[0].account_id
);
372 EXPECT_EQ("acc_id2", mappings
[1].account_id
);
375 // Tests the part where a new account is added with a token, to the point when
376 // GCM message is sent.
377 TEST_F(GCMAccountMapperTest
, AddMappingToMessageSent
) {
378 mapper()->Initialize(GCMAccountMapper::AccountMappings());
379 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
381 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
382 GCMClient::AccountTokenInfo account_token
= MakeAccountTokenInfo("acc_id");
383 account_tokens
.push_back(account_token
);
384 mapper()->SetAccountTokens(account_tokens
);
386 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
387 EXPECT_EQ(1UL, mappings
.size());
388 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
389 EXPECT_EQ("acc_id", iter
->account_id
);
390 EXPECT_EQ("acc_id@gmail.com", iter
->email
);
391 EXPECT_EQ("acc_id_token", iter
->access_token
);
392 EXPECT_EQ(AccountMapping::NEW
, iter
->status
);
393 EXPECT_EQ(base::Time(), iter
->status_change_timestamp
);
395 EXPECT_TRUE(!gcm_driver().last_message_id().empty());
398 // Tests the part where GCM message is successfully queued.
399 TEST_F(GCMAccountMapperTest
, AddMappingMessageQueued
) {
400 mapper()->Initialize(GCMAccountMapper::AccountMappings());
401 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
403 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
404 GCMClient::AccountTokenInfo account_token
= MakeAccountTokenInfo("acc_id");
405 account_tokens
.push_back(account_token
);
406 mapper()->SetAccountTokens(account_tokens
);
408 clock()->SetNow(base::Time::Now());
409 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
411 EXPECT_EQ(account_token
.email
, gcm_driver().last_account_mapping().email
);
412 EXPECT_EQ(account_token
.account_id
,
413 gcm_driver().last_account_mapping().account_id
);
414 EXPECT_EQ(account_token
.access_token
,
415 gcm_driver().last_account_mapping().access_token
);
416 EXPECT_EQ(AccountMapping::ADDING
, gcm_driver().last_account_mapping().status
);
417 EXPECT_EQ(clock()->Now(),
418 gcm_driver().last_account_mapping().status_change_timestamp
);
419 EXPECT_EQ(gcm_driver().last_message_id(),
420 gcm_driver().last_account_mapping().last_message_id
);
422 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
423 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
424 EXPECT_EQ(account_token
.email
, iter
->email
);
425 EXPECT_EQ(account_token
.account_id
, iter
->account_id
);
426 EXPECT_EQ(account_token
.access_token
, iter
->access_token
);
427 EXPECT_EQ(AccountMapping::ADDING
, iter
->status
);
428 EXPECT_EQ(clock()->Now(), iter
->status_change_timestamp
);
429 EXPECT_EQ(gcm_driver().last_message_id(), iter
->last_message_id
);
432 // Tests status change from ADDING to MAPPED (Message is acknowledged).
433 TEST_F(GCMAccountMapperTest
, AddMappingMessageAcknowledged
) {
434 mapper()->Initialize(GCMAccountMapper::AccountMappings());
435 gcm_driver().AddAppHandler(kGCMAccountMapperAppId
, mapper());
436 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
438 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
439 GCMClient::AccountTokenInfo account_token
= MakeAccountTokenInfo("acc_id");
440 account_tokens
.push_back(account_token
);
441 mapper()->SetAccountTokens(account_tokens
);
443 clock()->SetNow(base::Time::Now());
444 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
445 clock()->SetNow(base::Time::Now());
446 gcm_driver().AcknowledgeSend(gcm_driver().last_message_id());
448 EXPECT_EQ(account_token
.email
, gcm_driver().last_account_mapping().email
);
449 EXPECT_EQ(account_token
.account_id
,
450 gcm_driver().last_account_mapping().account_id
);
451 EXPECT_EQ(account_token
.access_token
,
452 gcm_driver().last_account_mapping().access_token
);
453 EXPECT_EQ(AccountMapping::MAPPED
, gcm_driver().last_account_mapping().status
);
454 EXPECT_EQ(clock()->Now(),
455 gcm_driver().last_account_mapping().status_change_timestamp
);
456 EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id
.empty());
458 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
459 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
460 EXPECT_EQ(account_token
.email
, iter
->email
);
461 EXPECT_EQ(account_token
.account_id
, iter
->account_id
);
462 EXPECT_EQ(account_token
.access_token
, iter
->access_token
);
463 EXPECT_EQ(AccountMapping::MAPPED
, iter
->status
);
464 EXPECT_EQ(clock()->Now(), iter
->status_change_timestamp
);
465 EXPECT_TRUE(iter
->last_message_id
.empty());
468 // Tests status change form ADDING to MAPPED (When message was acknowledged,
469 // after Chrome was restarted).
470 TEST_F(GCMAccountMapperTest
, AddMappingMessageAckedAfterRestart
) {
471 mapper()->Initialize(GCMAccountMapper::AccountMappings());
472 gcm_driver().AddAppHandler(kGCMAccountMapperAppId
, mapper());
473 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
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
);
480 clock()->SetNow(base::Time::Now());
481 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
484 GCMAccountMapper::AccountMappings stored_mappings
;
485 stored_mappings
.push_back(gcm_driver().last_account_mapping());
486 mapper()->Initialize(stored_mappings
);
487 gcm_driver().AddAppHandler(kGCMAccountMapperAppId
, mapper());
489 clock()->SetNow(base::Time::Now());
490 gcm_driver().AcknowledgeSend(gcm_driver().last_message_id());
492 EXPECT_EQ(account_token
.email
, gcm_driver().last_account_mapping().email
);
493 EXPECT_EQ(account_token
.account_id
,
494 gcm_driver().last_account_mapping().account_id
);
495 EXPECT_EQ(account_token
.access_token
,
496 gcm_driver().last_account_mapping().access_token
);
497 EXPECT_EQ(AccountMapping::MAPPED
, gcm_driver().last_account_mapping().status
);
498 EXPECT_EQ(clock()->Now(),
499 gcm_driver().last_account_mapping().status_change_timestamp
);
500 EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id
.empty());
502 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
503 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
504 EXPECT_EQ(account_token
.email
, iter
->email
);
505 EXPECT_EQ(account_token
.account_id
, iter
->account_id
);
506 EXPECT_EQ(account_token
.access_token
, iter
->access_token
);
507 EXPECT_EQ(AccountMapping::MAPPED
, iter
->status
);
508 EXPECT_EQ(clock()->Now(), iter
->status_change_timestamp
);
509 EXPECT_TRUE(iter
->last_message_id
.empty());
512 // Tests a case when ADD message times out for a new account.
513 TEST_F(GCMAccountMapperTest
, AddMappingMessageSendErrorForNewAccount
) {
514 mapper()->Initialize(GCMAccountMapper::AccountMappings());
515 gcm_driver().AddAppHandler(kGCMAccountMapperAppId
, mapper());
516 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
518 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
519 GCMClient::AccountTokenInfo account_token
= MakeAccountTokenInfo("acc_id");
520 account_tokens
.push_back(account_token
);
521 mapper()->SetAccountTokens(account_tokens
);
523 clock()->SetNow(base::Time::Now());
524 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
526 clock()->SetNow(base::Time::Now());
527 std::string old_message_id
= gcm_driver().last_message_id();
528 gcm_driver().MessageSendError(old_message_id
);
530 // No new message is sent because of the send error, as the token is stale.
531 // Because the account was new, the entry should be deleted.
532 EXPECT_EQ(old_message_id
, gcm_driver().last_message_id());
533 EXPECT_EQ(account_token
.account_id
, gcm_driver().last_removed_account_id());
534 EXPECT_TRUE(GetAccounts().empty());
537 /// Tests a case when ADD message times out for a MAPPED account.
538 TEST_F(GCMAccountMapperTest
, AddMappingMessageSendErrorForMappedAccount
) {
539 // Start with one account that is mapped.
540 base::Time status_change_timestamp
= base::Time::Now();
541 AccountMapping mapping
= MakeAccountMapping("acc_id",
542 AccountMapping::MAPPED
,
543 status_change_timestamp
,
546 GCMAccountMapper::AccountMappings stored_mappings
;
547 stored_mappings
.push_back(mapping
);
548 mapper()->Initialize(stored_mappings
);
549 gcm_driver().AddAppHandler(kGCMAccountMapperAppId
, mapper());
550 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
552 clock()->SetNow(base::Time::Now());
553 gcm_driver().MessageSendError("add_message_id");
555 // No new message is sent because of the send error, as the token is stale.
556 // Because the account was new, the entry should be deleted.
557 EXPECT_TRUE(gcm_driver().last_message_id().empty());
559 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
560 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
561 EXPECT_EQ(mapping
.email
, iter
->email
);
562 EXPECT_EQ(mapping
.account_id
, iter
->account_id
);
563 EXPECT_EQ(mapping
.access_token
, iter
->access_token
);
564 EXPECT_EQ(AccountMapping::MAPPED
, iter
->status
);
565 EXPECT_EQ(status_change_timestamp
, iter
->status_change_timestamp
);
566 EXPECT_TRUE(iter
->last_message_id
.empty());
569 // Tests that a missing token for an account will trigger removing of that
570 // account. This test goes only until the message is passed to GCM.
571 TEST_F(GCMAccountMapperTest
, RemoveMappingToMessageSent
) {
572 // Start with one account that is mapped.
573 AccountMapping mapping
= MakeAccountMapping("acc_id",
574 AccountMapping::MAPPED
,
578 GCMAccountMapper::AccountMappings stored_mappings
;
579 stored_mappings
.push_back(mapping
);
580 mapper()->Initialize(stored_mappings
);
581 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
582 clock()->SetNow(base::Time::Now());
584 mapper()->SetAccountTokens(std::vector
<GCMClient::AccountTokenInfo
>());
586 EXPECT_EQ(mapping
.account_id
, gcm_driver().last_account_mapping().account_id
);
587 EXPECT_EQ(mapping
.email
, gcm_driver().last_account_mapping().email
);
588 EXPECT_EQ(AccountMapping::REMOVING
,
589 gcm_driver().last_account_mapping().status
);
590 EXPECT_EQ(clock()->Now(),
591 gcm_driver().last_account_mapping().status_change_timestamp
);
592 EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id
.empty());
594 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
595 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
596 EXPECT_EQ(mapping
.email
, iter
->email
);
597 EXPECT_EQ(mapping
.account_id
, iter
->account_id
);
598 EXPECT_EQ(mapping
.access_token
, iter
->access_token
);
599 EXPECT_EQ(AccountMapping::REMOVING
, iter
->status
);
600 EXPECT_EQ(clock()->Now(), iter
->status_change_timestamp
);
601 EXPECT_TRUE(iter
->last_message_id
.empty());
604 // Tests that a missing token for an account will trigger removing of that
605 // account. This test goes until the message is queued by GCM.
606 TEST_F(GCMAccountMapperTest
, RemoveMappingMessageQueued
) {
607 // Start with one account that is mapped.
608 AccountMapping mapping
= MakeAccountMapping("acc_id",
609 AccountMapping::MAPPED
,
613 GCMAccountMapper::AccountMappings stored_mappings
;
614 stored_mappings
.push_back(mapping
);
615 mapper()->Initialize(stored_mappings
);
616 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
617 clock()->SetNow(base::Time::Now());
618 base::Time status_change_timestamp
= clock()->Now();
620 mapper()->SetAccountTokens(std::vector
<GCMClient::AccountTokenInfo
>());
621 clock()->SetNow(base::Time::Now());
622 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
624 EXPECT_EQ(mapping
.account_id
, gcm_driver().last_account_mapping().account_id
);
625 EXPECT_EQ(mapping
.email
, gcm_driver().last_account_mapping().email
);
626 EXPECT_EQ(AccountMapping::REMOVING
,
627 gcm_driver().last_account_mapping().status
);
628 EXPECT_EQ(status_change_timestamp
,
629 gcm_driver().last_account_mapping().status_change_timestamp
);
630 EXPECT_TRUE(!gcm_driver().last_account_mapping().last_message_id
.empty());
632 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
633 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
634 EXPECT_EQ(mapping
.email
, iter
->email
);
635 EXPECT_EQ(mapping
.account_id
, iter
->account_id
);
636 EXPECT_EQ(mapping
.access_token
, iter
->access_token
);
637 EXPECT_EQ(AccountMapping::REMOVING
, iter
->status
);
638 EXPECT_EQ(status_change_timestamp
, iter
->status_change_timestamp
);
639 EXPECT_EQ(gcm_driver().last_account_mapping().last_message_id
,
640 iter
->last_message_id
);
643 // Tests that a missing token for an account will trigger removing of that
644 // account. This test goes until the message is acknowledged by GCM.
645 // This is a complete success scenario for account removal, and it end with
646 // account mapping being completely gone.
647 TEST_F(GCMAccountMapperTest
, RemoveMappingMessageAcknowledged
) {
648 // Start with one account that is mapped.
649 AccountMapping mapping
= MakeAccountMapping("acc_id",
650 AccountMapping::MAPPED
,
654 GCMAccountMapper::AccountMappings stored_mappings
;
655 stored_mappings
.push_back(mapping
);
656 mapper()->Initialize(stored_mappings
);
657 gcm_driver().AddAppHandler(kGCMAccountMapperAppId
, mapper());
658 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
659 clock()->SetNow(base::Time::Now());
661 mapper()->SetAccountTokens(std::vector
<GCMClient::AccountTokenInfo
>());
662 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
663 gcm_driver().AcknowledgeSend(gcm_driver().last_message_id());
665 EXPECT_EQ(mapping
.account_id
, gcm_driver().last_removed_account_id());
667 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
668 EXPECT_TRUE(mappings
.empty());
671 // Tests that account removing proceeds, when a removing message is acked after
672 // Chrome was restarted.
673 TEST_F(GCMAccountMapperTest
, RemoveMappingMessageAckedAfterRestart
) {
674 // Start with one account that is mapped.
675 AccountMapping mapping
= MakeAccountMapping("acc_id",
676 AccountMapping::REMOVING
,
678 "remove_message_id");
680 GCMAccountMapper::AccountMappings stored_mappings
;
681 stored_mappings
.push_back(mapping
);
682 mapper()->Initialize(stored_mappings
);
683 gcm_driver().AddAppHandler(kGCMAccountMapperAppId
, mapper());
685 gcm_driver().AcknowledgeSend("remove_message_id");
687 EXPECT_EQ(mapping
.account_id
, gcm_driver().last_removed_account_id());
689 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
690 EXPECT_TRUE(mappings
.empty());
693 // Tests that account removing proceeds, when a removing message is acked after
694 // Chrome was restarted.
695 TEST_F(GCMAccountMapperTest
, RemoveMappingMessageSendError
) {
696 // Start with one account that is mapped.
697 base::Time status_change_timestamp
= base::Time::Now();
698 AccountMapping mapping
= MakeAccountMapping("acc_id",
699 AccountMapping::REMOVING
,
700 status_change_timestamp
,
701 "remove_message_id");
703 GCMAccountMapper::AccountMappings stored_mappings
;
704 stored_mappings
.push_back(mapping
);
705 mapper()->Initialize(stored_mappings
);
706 gcm_driver().AddAppHandler(kGCMAccountMapperAppId
, mapper());
708 clock()->SetNow(base::Time::Now());
709 gcm_driver().MessageSendError("remove_message_id");
711 EXPECT_TRUE(gcm_driver().last_removed_account_id().empty());
713 EXPECT_EQ(mapping
.account_id
, gcm_driver().last_account_mapping().account_id
);
714 EXPECT_EQ(mapping
.email
, gcm_driver().last_account_mapping().email
);
715 EXPECT_EQ(AccountMapping::REMOVING
,
716 gcm_driver().last_account_mapping().status
);
717 EXPECT_EQ(status_change_timestamp
,
718 gcm_driver().last_account_mapping().status_change_timestamp
);
719 // Message is not persisted, until send is completed.
720 EXPECT_TRUE(gcm_driver().last_account_mapping().last_message_id
.empty());
722 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
723 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
724 EXPECT_EQ(mapping
.email
, iter
->email
);
725 EXPECT_EQ(mapping
.account_id
, iter
->account_id
);
726 EXPECT_TRUE(iter
->access_token
.empty());
727 EXPECT_EQ(AccountMapping::REMOVING
, iter
->status
);
728 EXPECT_EQ(status_change_timestamp
, iter
->status_change_timestamp
);
729 EXPECT_TRUE(iter
->last_message_id
.empty());
732 // Tests that, if a new token arrives when the adding message is in progress
733 // no new message is sent and account mapper still waits for the first one to
735 TEST_F(GCMAccountMapperTest
, TokenIsRefreshedWhenAdding
) {
736 mapper()->Initialize(GCMAccountMapper::AccountMappings());
737 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
739 clock()->SetNow(base::Time::Now());
740 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
741 GCMClient::AccountTokenInfo account_token
= MakeAccountTokenInfo("acc_id");
742 account_tokens
.push_back(account_token
);
743 mapper()->SetAccountTokens(account_tokens
);
744 DCHECK_EQ(CustomFakeGCMDriver::SEND_STARTED
, gcm_driver().last_action());
746 clock()->SetNow(base::Time::Now());
747 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
748 DCHECK_EQ(CustomFakeGCMDriver::SEND_FINISHED
, gcm_driver().last_action());
750 // Providing another token and clearing status.
751 gcm_driver().Clear();
752 mapper()->SetAccountTokens(account_tokens
);
753 DCHECK_EQ(CustomFakeGCMDriver::NONE
, gcm_driver().last_action());
756 // Tests that, if a new token arrives when a removing message is in progress
757 // a new adding message is sent and while account mapping status is changed to
758 // mapped. If the original Removing message arrives it is discarded.
759 TEST_F(GCMAccountMapperTest
, TokenIsRefreshedWhenRemoving
) {
760 // Start with one account that is mapped.
761 AccountMapping mapping
= MakeAccountMapping(
762 "acc_id", AccountMapping::MAPPED
, base::Time::Now(), std::string());
764 GCMAccountMapper::AccountMappings stored_mappings
;
765 stored_mappings
.push_back(mapping
);
766 mapper()->Initialize(stored_mappings
);
767 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
768 clock()->SetNow(base::Time::Now());
770 // Remove the token to trigger a remove message to be sent
771 mapper()->SetAccountTokens(std::vector
<GCMClient::AccountTokenInfo
>());
772 EXPECT_EQ(CustomFakeGCMDriver::SEND_STARTED
, gcm_driver().last_action());
773 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
774 EXPECT_EQ(CustomFakeGCMDriver::SEND_FINISHED
, gcm_driver().last_action());
776 std::string remove_message_id
= gcm_driver().last_message_id();
777 gcm_driver().Clear();
779 // The account mapping for acc_id is now in status REMOVING.
780 // Adding the token for that account.
781 clock()->SetNow(base::Time::Now());
782 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
783 GCMClient::AccountTokenInfo account_token
= MakeAccountTokenInfo("acc_id");
784 account_tokens
.push_back(account_token
);
785 mapper()->SetAccountTokens(account_tokens
);
786 DCHECK_EQ(CustomFakeGCMDriver::SEND_STARTED
, gcm_driver().last_action());
787 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
788 EXPECT_EQ(CustomFakeGCMDriver::SEND_FINISHED
, gcm_driver().last_action());
790 std::string add_message_id
= gcm_driver().last_message_id();
792 // A remove message confirmation arrives now, but should be ignored.
793 gcm_driver().AcknowledgeSend(remove_message_id
);
795 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
796 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
797 EXPECT_EQ(mapping
.email
, iter
->email
);
798 EXPECT_EQ(mapping
.account_id
, iter
->account_id
);
799 EXPECT_FALSE(iter
->access_token
.empty());
800 EXPECT_EQ(AccountMapping::MAPPED
, iter
->status
);
801 // Status change timestamp is set to very long time ago, to make sure the next
802 // round of mapping picks it up.
803 EXPECT_EQ(base::Time(), iter
->status_change_timestamp
);
804 EXPECT_EQ(add_message_id
, iter
->last_message_id
);
807 // Tests adding/removing works for multiple accounts, after a restart and when
808 // tokens are periodically delierverd.
809 TEST_F(GCMAccountMapperTest
, MultipleAccountMappings
) {
810 clock()->SetNow(base::Time::Now());
811 base::Time half_hour_ago
= clock()->Now() - base::TimeDelta::FromMinutes(30);
812 GCMAccountMapper::AccountMappings stored_mappings
;
813 stored_mappings
.push_back(MakeAccountMapping(
814 "acc_id_0", AccountMapping::ADDING
, half_hour_ago
, "acc_id_0_msg"));
815 stored_mappings
.push_back(MakeAccountMapping(
816 "acc_id_1", AccountMapping::MAPPED
, half_hour_ago
, "acc_id_1_msg"));
817 stored_mappings
.push_back(MakeAccountMapping(
818 "acc_id_2", AccountMapping::REMOVING
, half_hour_ago
, "acc_id_2_msg"));
820 mapper()->Initialize(stored_mappings
);
821 gcm_driver().AddAppHandler(kGCMAccountMapperAppId
, mapper());
822 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
824 GCMAccountMapper::AccountMappings
expected_mappings(stored_mappings
);
826 // Finish messages after a restart.
827 clock()->SetNow(base::Time::Now());
828 gcm_driver().AcknowledgeSend(expected_mappings
[0].last_message_id
);
829 expected_mappings
[0].status_change_timestamp
= clock()->Now();
830 expected_mappings
[0].status
= AccountMapping::MAPPED
;
831 expected_mappings
[0].last_message_id
.clear();
833 clock()->SetNow(base::Time::Now());
834 gcm_driver().AcknowledgeSend(expected_mappings
[1].last_message_id
);
835 expected_mappings
[1].status_change_timestamp
= clock()->Now();
836 expected_mappings
[1].status
= AccountMapping::MAPPED
;
837 expected_mappings
[1].last_message_id
.clear();
839 // Upon success last element is removed.
840 clock()->SetNow(base::Time::Now());
841 gcm_driver().AcknowledgeSend(expected_mappings
[2].last_message_id
);
842 expected_mappings
.pop_back();
844 VerifyMappings(expected_mappings
, GetAccounts(), "Step 1, After restart");
846 // One of accounts gets removed.
847 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
848 account_tokens
.push_back(MakeAccountTokenInfo("acc_id_0"));
850 // Advance a day to make sure existing mappings will be reported.
851 clock()->SetNow(clock()->Now() + base::TimeDelta::FromDays(1));
852 mapper()->SetAccountTokens(account_tokens
);
854 expected_mappings
[0].status
= AccountMapping::MAPPED
;
855 expected_mappings
[1].status
= AccountMapping::REMOVING
;
856 expected_mappings
[1].status_change_timestamp
= clock()->Now();
858 gcm_driver().CompleteSendAllMessages();
861 expected_mappings
, GetAccounts(), "Step 2, One account is being removed");
863 clock()->SetNow(clock()->Now() + base::TimeDelta::FromSeconds(5));
864 gcm_driver().AcknowledgeSendAllMessages();
866 expected_mappings
[0].status_change_timestamp
= clock()->Now();
867 expected_mappings
.pop_back();
870 expected_mappings
, GetAccounts(), "Step 3, Removing completed");
872 account_tokens
.clear();
873 account_tokens
.push_back(MakeAccountTokenInfo("acc_id_0"));
874 account_tokens
.push_back(MakeAccountTokenInfo("acc_id_3"));
875 account_tokens
.push_back(MakeAccountTokenInfo("acc_id_4"));
877 // Advance a day to make sure existing mappings will be reported.
878 clock()->SetNow(clock()->Now() + base::TimeDelta::FromDays(1));
879 mapper()->SetAccountTokens(account_tokens
);
881 // Mapping from acc_id_0 still in position 0
882 expected_mappings
.push_back(MakeAccountMapping(
883 "acc_id_3", AccountMapping::NEW
, base::Time(), std::string()));
884 expected_mappings
.push_back(MakeAccountMapping(
885 "acc_id_4", AccountMapping::NEW
, base::Time(), std::string()));
887 VerifyMappings(expected_mappings
, GetAccounts(), "Step 4, Two new accounts");
889 clock()->SetNow(clock()->Now() + base::TimeDelta::FromSeconds(1));
890 gcm_driver().CompleteSendAllMessages();
892 expected_mappings
[1].status
= AccountMapping::ADDING
;
893 expected_mappings
[1].status_change_timestamp
= clock()->Now();
894 expected_mappings
[2].status
= AccountMapping::ADDING
;
895 expected_mappings
[2].status_change_timestamp
= clock()->Now();
898 expected_mappings
, GetAccounts(), "Step 5, Two accounts being added");
900 clock()->SetNow(clock()->Now() + base::TimeDelta::FromSeconds(5));
901 gcm_driver().AcknowledgeSendAllMessages();
903 expected_mappings
[0].status_change_timestamp
= clock()->Now();
904 expected_mappings
[1].status_change_timestamp
= clock()->Now();
905 expected_mappings
[1].status
= AccountMapping::MAPPED
;
906 expected_mappings
[2].status_change_timestamp
= clock()->Now();
907 expected_mappings
[2].status
= AccountMapping::MAPPED
;
910 expected_mappings
, GetAccounts(), "Step 6, Three mapped accounts");