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