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 kGCMAccountMapperAppId
[] = "com.google.android.gms";
20 const char kRegistrationId
[] = "reg_id";
22 AccountMapping
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
;
36 GCMClient::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";
45 void 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
;
72 class CustomFakeGCMDriver
: public FakeGCMDriver
{
74 enum LastMessageAction
{
81 CustomFakeGCMDriver();
82 virtual ~CustomFakeGCMDriver();
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
;
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
);
100 void CompleteSendAllMessages();
101 void AcknowledgeSendAllMessages();
103 void SetLastMessageAction(const std::string
& message_id
,
104 LastMessageAction action
);
107 const AccountMapping
& last_account_mapping() const {
108 return account_mapping_
;
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_
;
114 LastMessageAction
last_action() const { return last_action_
; }
115 bool registration_id_requested() const { return registration_id_requested_
; }
118 virtual void SendImpl(const std::string
& app_id
,
119 const std::string
& receiver_id
,
120 const GCMClient::OutgoingMessage
& message
) OVERRIDE
;
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_
;
131 CustomFakeGCMDriver::CustomFakeGCMDriver()
132 : last_action_(NONE
), registration_id_requested_(false) {
135 CustomFakeGCMDriver::~CustomFakeGCMDriver() {
138 void 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
;
149 void CustomFakeGCMDriver::RemoveAccountMapping(const std::string
& account_id
) {
150 last_removed_account_id_
= account_id
;
153 void CustomFakeGCMDriver::AddAppHandler(const std::string
& app_id
,
154 GCMAppHandler
* handler
) {
155 GCMDriver::AddAppHandler(app_id
, handler
);
158 void CustomFakeGCMDriver::RemoveAppHandler(const std::string
& app_id
) {
159 GCMDriver::RemoveAppHandler(app_id
);
162 void 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;
171 void CustomFakeGCMDriver::CompleteRegister(const std::string
& registration_id
,
172 GCMClient::Result result
) {
173 RegisterFinished(kGCMAccountMapperAppId
, registration_id
, result
);
176 void CustomFakeGCMDriver::CompleteSend(const std::string
& message_id
,
177 GCMClient::Result result
) {
178 SendFinished(kGCMAccountMapperAppId
, message_id
, result
);
179 SetLastMessageAction(message_id
, SEND_FINISHED
);
182 void CustomFakeGCMDriver::AcknowledgeSend(const std::string
& message_id
) {
183 GetAppHandler(kGCMAccountMapperAppId
)
184 ->OnSendAcknowledged(kGCMAccountMapperAppId
, message_id
);
185 SetLastMessageAction(message_id
, SEND_ACKNOWLEDGED
);
188 void 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
);
196 void 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
);
202 SetLastMessageAction(message
.id
, SEND_STARTED
);
205 void CustomFakeGCMDriver::CompleteSendAllMessages() {
206 for (std::map
<std::string
, LastMessageAction
>::const_iterator iter
=
207 all_messages_
.begin();
208 iter
!= all_messages_
.end();
210 if (iter
->second
== SEND_STARTED
)
211 CompleteSend(iter
->first
, GCMClient::SUCCESS
);
215 void CustomFakeGCMDriver::AcknowledgeSendAllMessages() {
216 for (std::map
<std::string
, LastMessageAction
>::const_iterator iter
=
217 all_messages_
.begin();
218 iter
!= all_messages_
.end();
220 if (iter
->second
== SEND_FINISHED
)
221 AcknowledgeSend(iter
->first
);
225 void CustomFakeGCMDriver::Clear() {
226 account_mapping_
= AccountMapping();
227 last_message_id_
.clear();
228 last_removed_account_id_
.clear();
230 registration_id_requested_
= false;
233 void 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
;
242 class GCMAccountMapperTest
: public testing::Test
{
244 GCMAccountMapperTest();
245 virtual ~GCMAccountMapperTest();
249 const GCMAccountMapper::AccountMappings
& GetAccounts() const {
250 return account_mapper_
->accounts_
;
253 GCMAccountMapper
* mapper() { return account_mapper_
.get(); }
255 CustomFakeGCMDriver
& gcm_driver() { return gcm_driver_
; }
257 base::SimpleTestClock
* clock() { return clock_
; }
260 CustomFakeGCMDriver gcm_driver_
;
261 scoped_ptr
<GCMAccountMapper
> account_mapper_
;
262 base::SimpleTestClock
* clock_
;
265 GCMAccountMapperTest::GCMAccountMapperTest() {
269 GCMAccountMapperTest::~GCMAccountMapperTest() {
272 void GCMAccountMapperTest::Restart() {
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
>());
281 // Tests the initialization of account mappings (from the store) when empty.
282 // It also checks that initialization triggers registration ID request.
283 TEST_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());
290 // Tests that registration is retried, when new tokens are delivered and in no
291 // other circumstances.
292 TEST_F(GCMAccountMapperTest
, RegistrationRetryUponFailure
) {
293 mapper()->Initialize(GCMAccountMapper::AccountMappings());
294 EXPECT_TRUE(gcm_driver().registration_id_requested());
295 gcm_driver().Clear();
297 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::UNKNOWN_ERROR
);
298 EXPECT_FALSE(gcm_driver().registration_id_requested());
299 gcm_driver().Clear();
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();
307 gcm_driver().CompleteRegister(kRegistrationId
,
308 GCMClient::ASYNC_OPERATION_PENDING
);
309 EXPECT_FALSE(gcm_driver().registration_id_requested());
312 // Tests the initialization of account mappings (from the store).
313 TEST_F(GCMAccountMapperTest
, InitializeAccountMappings
) {
314 GCMAccountMapper::AccountMappings account_mappings
;
315 AccountMapping account_mapping1
= MakeAccountMapping("acc_id1",
316 AccountMapping::MAPPED
,
319 AccountMapping account_mapping2
= MakeAccountMapping("acc_id2",
320 AccountMapping::ADDING
,
323 account_mappings
.push_back(account_mapping1
);
324 account_mappings
.push_back(account_mapping2
);
326 mapper()->Initialize(account_mappings
);
328 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
329 EXPECT_EQ(2UL, mappings
.size());
330 GCMAccountMapper::AccountMappings::const_iterator iter
= mappings
.begin();
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());
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
);
350 // Tests that account tokens are not processed until registration ID is
352 TEST_F(GCMAccountMapperTest
, SetAccountTokensOnlyWorksWithRegisterationId
) {
353 // Start with empty list.
354 mapper()->Initialize(GCMAccountMapper::AccountMappings());
356 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
357 account_tokens
.push_back(MakeAccountTokenInfo("acc_id"));
358 mapper()->SetAccountTokens(account_tokens
);
360 EXPECT_TRUE(GetAccounts().empty());
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
);
367 EXPECT_TRUE(GetAccounts().empty());
369 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
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
);
377 // Tests the part where a new account is added with a token, to the point when
378 // GCM message is sent.
379 TEST_F(GCMAccountMapperTest
, AddMappingToMessageSent
) {
380 mapper()->Initialize(GCMAccountMapper::AccountMappings());
381 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
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
);
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
);
397 EXPECT_TRUE(!gcm_driver().last_message_id().empty());
400 // Tests the part where GCM message is successfully queued.
401 TEST_F(GCMAccountMapperTest
, AddMappingMessageQueued
) {
402 mapper()->Initialize(GCMAccountMapper::AccountMappings());
403 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
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
);
410 clock()->SetNow(base::Time::Now());
411 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
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
);
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
);
434 // Tests status change from ADDING to MAPPED (Message is acknowledged).
435 TEST_F(GCMAccountMapperTest
, AddMappingMessageAcknowledged
) {
436 mapper()->Initialize(GCMAccountMapper::AccountMappings());
437 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
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
);
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());
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());
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());
469 // Tests status change form ADDING to MAPPED (When message was acknowledged,
470 // after Chrome was restarted).
471 TEST_F(GCMAccountMapperTest
, AddMappingMessageAckedAfterRestart
) {
472 mapper()->Initialize(GCMAccountMapper::AccountMappings());
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
);
488 clock()->SetNow(base::Time::Now());
489 gcm_driver().AcknowledgeSend(gcm_driver().last_message_id());
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());
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());
511 // Tests a case when ADD message times out for a new account.
512 TEST_F(GCMAccountMapperTest
, AddMappingMessageSendErrorForNewAccount
) {
513 mapper()->Initialize(GCMAccountMapper::AccountMappings());
514 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
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
);
521 clock()->SetNow(base::Time::Now());
522 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
524 clock()->SetNow(base::Time::Now());
525 std::string old_message_id
= gcm_driver().last_message_id();
526 gcm_driver().MessageSendError(old_message_id
);
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());
535 /// Tests a case when ADD message times out for a MAPPED account.
536 TEST_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
,
544 GCMAccountMapper::AccountMappings stored_mappings
;
545 stored_mappings
.push_back(mapping
);
546 mapper()->Initialize(stored_mappings
);
547 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
549 clock()->SetNow(base::Time::Now());
550 gcm_driver().MessageSendError("add_message_id");
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());
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());
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.
568 TEST_F(GCMAccountMapperTest
, RemoveMappingToMessageSent
) {
569 // Start with one account that is mapped.
570 AccountMapping mapping
= MakeAccountMapping("acc_id",
571 AccountMapping::MAPPED
,
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());
581 mapper()->SetAccountTokens(std::vector
<GCMClient::AccountTokenInfo
>());
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());
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());
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.
603 TEST_F(GCMAccountMapperTest
, RemoveMappingMessageQueued
) {
604 // Start with one account that is mapped.
605 AccountMapping mapping
= MakeAccountMapping("acc_id",
606 AccountMapping::MAPPED
,
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();
617 mapper()->SetAccountTokens(std::vector
<GCMClient::AccountTokenInfo
>());
618 clock()->SetNow(base::Time::Now());
619 gcm_driver().CompleteSend(gcm_driver().last_message_id(), GCMClient::SUCCESS
);
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());
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
);
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.
644 TEST_F(GCMAccountMapperTest
, RemoveMappingMessageAcknowledged
) {
645 // Start with one account that is mapped.
646 AccountMapping mapping
= MakeAccountMapping("acc_id",
647 AccountMapping::MAPPED
,
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());
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());
661 EXPECT_EQ(mapping
.account_id
, gcm_driver().last_removed_account_id());
663 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
664 EXPECT_TRUE(mappings
.empty());
667 // Tests that account removing proceeds, when a removing message is acked after
668 // Chrome was restarted.
669 TEST_F(GCMAccountMapperTest
, RemoveMappingMessageAckedAfterRestart
) {
670 // Start with one account that is mapped.
671 AccountMapping mapping
= MakeAccountMapping("acc_id",
672 AccountMapping::REMOVING
,
674 "remove_message_id");
676 GCMAccountMapper::AccountMappings stored_mappings
;
677 stored_mappings
.push_back(mapping
);
678 mapper()->Initialize(stored_mappings
);
680 gcm_driver().AcknowledgeSend("remove_message_id");
682 EXPECT_EQ(mapping
.account_id
, gcm_driver().last_removed_account_id());
684 GCMAccountMapper::AccountMappings mappings
= GetAccounts();
685 EXPECT_TRUE(mappings
.empty());
688 // Tests that account removing proceeds, when a removing message is acked after
689 // Chrome was restarted.
690 TEST_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");
698 GCMAccountMapper::AccountMappings stored_mappings
;
699 stored_mappings
.push_back(mapping
);
700 mapper()->Initialize(stored_mappings
);
702 clock()->SetNow(base::Time::Now());
703 gcm_driver().MessageSendError("remove_message_id");
705 EXPECT_TRUE(gcm_driver().last_removed_account_id().empty());
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());
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());
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
729 TEST_F(GCMAccountMapperTest
, TokenIsRefreshedWhenAdding
) {
730 mapper()->Initialize(GCMAccountMapper::AccountMappings());
731 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
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());
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());
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());
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.
753 TEST_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());
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());
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());
770 std::string remove_message_id
= gcm_driver().last_message_id();
771 gcm_driver().Clear();
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());
784 std::string add_message_id
= gcm_driver().last_message_id();
786 // A remove message confirmation arrives now, but should be ignored.
787 gcm_driver().AcknowledgeSend(remove_message_id
);
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
);
801 // Tests adding/removing works for multiple accounts, after a restart and when
802 // tokens are periodically delierverd.
803 TEST_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"));
814 mapper()->Initialize(stored_mappings
);
815 gcm_driver().CompleteRegister(kRegistrationId
, GCMClient::SUCCESS
);
817 GCMAccountMapper::AccountMappings
expected_mappings(stored_mappings
);
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();
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();
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();
837 VerifyMappings(expected_mappings
, GetAccounts(), "Step 1, After restart");
839 // One of accounts gets removed.
840 std::vector
<GCMClient::AccountTokenInfo
> account_tokens
;
841 account_tokens
.push_back(MakeAccountTokenInfo("acc_id_0"));
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
);
847 expected_mappings
[0].status
= AccountMapping::MAPPED
;
848 expected_mappings
[1].status
= AccountMapping::REMOVING
;
849 expected_mappings
[1].status_change_timestamp
= clock()->Now();
851 gcm_driver().CompleteSendAllMessages();
854 expected_mappings
, GetAccounts(), "Step 2, One account is being removed");
856 clock()->SetNow(clock()->Now() + base::TimeDelta::FromSeconds(5));
857 gcm_driver().AcknowledgeSendAllMessages();
859 expected_mappings
[0].status_change_timestamp
= clock()->Now();
860 expected_mappings
.pop_back();
863 expected_mappings
, GetAccounts(), "Step 3, Removing completed");
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"));
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
);
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()));
880 VerifyMappings(expected_mappings
, GetAccounts(), "Step 4, Two new accounts");
882 clock()->SetNow(clock()->Now() + base::TimeDelta::FromSeconds(1));
883 gcm_driver().CompleteSendAllMessages();
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();
891 expected_mappings
, GetAccounts(), "Step 5, Two accounts being added");
893 clock()->SetNow(clock()->Now() + base::TimeDelta::FromSeconds(5));
894 gcm_driver().AcknowledgeSendAllMessages();
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
;
903 expected_mappings
, GetAccounts(), "Step 6, Three mapped accounts");