[GCM] Adding registration ID request and tests to GCM Account Mapper
[chromium-blink-merge.git] / components / gcm_driver / gcm_account_mapper_unittest.cc
blob718597937f4756fb3fd50fc363d0ef223cd09057
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"
14 namespace gcm {
16 namespace {
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";
42 return account_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 {
73 public:
74 enum LastMessageAction {
75 NONE,
76 SEND_STARTED,
77 SEND_FINISHED,
78 SEND_ACKNOWLEDGED
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);
105 void Clear();
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_; }
117 protected:
118 virtual void SendImpl(const std::string& app_id,
119 const std::string& receiver_id,
120 const GCMClient::OutgoingMessage& message) OVERRIDE;
122 private:
123 AccountMapping account_mapping_;
124 std::string last_message_id_;
125 std::string last_removed_account_id_;
126 LastMessageAction last_action_;
127 std::map<std::string, LastMessageAction> all_messages_;
128 bool registration_id_requested_;
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();
209 ++iter) {
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();
219 ++iter) {
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();
229 last_action_ = NONE;
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;
240 } // namespace
242 class GCMAccountMapperTest : public testing::Test {
243 public:
244 GCMAccountMapperTest();
245 virtual ~GCMAccountMapperTest();
247 void Restart();
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_; }
259 private:
260 CustomFakeGCMDriver gcm_driver_;
261 scoped_ptr<GCMAccountMapper> account_mapper_;
262 base::SimpleTestClock* clock_;
265 GCMAccountMapperTest::GCMAccountMapperTest() {
266 Restart();
269 GCMAccountMapperTest::~GCMAccountMapperTest() {
272 void GCMAccountMapperTest::Restart() {
273 if (account_mapper_)
274 account_mapper_->ShutdownHandler();
275 account_mapper_.reset(new GCMAccountMapper(&gcm_driver_));
276 scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock);
277 clock_ = clock.get();
278 account_mapper_->SetClockForTesting(clock.PassAs<base::Clock>());
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,
317 base::Time::Now(),
318 std::string());
319 AccountMapping account_mapping2 = MakeAccountMapping("acc_id2",
320 AccountMapping::ADDING,
321 base::Time::Now(),
322 "add_message_1");
323 account_mappings.push_back(account_mapping1);
324 account_mappings.push_back(account_mapping2);
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());
340 ++iter;
341 EXPECT_EQ(account_mapping2.account_id, iter->account_id);
342 EXPECT_EQ(account_mapping2.email, iter->email);
343 EXPECT_TRUE(account_mapping2.access_token.empty());
344 EXPECT_EQ(account_mapping2.status, iter->status);
345 EXPECT_EQ(account_mapping2.status_change_timestamp,
346 iter->status_change_timestamp);
347 EXPECT_EQ(account_mapping2.last_message_id, iter->last_message_id);
350 // Tests that account tokens are not processed until registration ID is
351 // available.
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);
483 Restart();
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,
542 "add_message_id");
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,
572 base::Time::Now(),
573 std::string());
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,
607 base::Time::Now(),
608 std::string());
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,
648 base::Time::Now(),
649 std::string());
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,
673 base::Time::Now(),
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
728 // complete.
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();
853 VerifyMappings(
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();
862 VerifyMappings(
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();
890 VerifyMappings(
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;
902 VerifyMappings(
903 expected_mappings, GetAccounts(), "Step 6, Three mapped accounts");
906 } // namespace gcm