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 "google_apis/gcm/engine/gcm_store_impl.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/files/file_path.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/run_loop.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "google_apis/gcm/base/fake_encryptor.h"
19 #include "google_apis/gcm/base/mcs_message.h"
20 #include "google_apis/gcm/base/mcs_util.h"
21 #include "google_apis/gcm/protocol/mcs.pb.h"
22 #include "testing/gtest/include/gtest/gtest.h"
28 // Number of persistent ids to use in tests.
29 const int kNumPersistentIds
= 10;
31 // Number of per-app messages in tests.
32 const int kNumMessagesPerApp
= 20;
34 // App name for testing.
35 const char kAppName
[] = "my_app";
37 // Category name for testing.
38 const char kCategoryName
[] = "my_category";
40 const uint64 kDeviceId
= 22;
41 const uint64 kDeviceToken
= 55;
43 class GCMStoreImplTest
: public testing::Test
{
46 ~GCMStoreImplTest() override
;
48 scoped_ptr
<GCMStoreImpl
> BuildGCMStore();
50 std::string
GetNextPersistentId();
54 void LoadCallback(scoped_ptr
<GCMStore::LoadResult
>* result_dst
,
55 scoped_ptr
<GCMStore::LoadResult
> result
);
56 void UpdateCallback(bool success
);
59 base::MessageLoop message_loop_
;
60 base::ScopedTempDir temp_directory_
;
61 bool expected_success_
;
62 uint64 next_persistent_id_
;
63 scoped_ptr
<base::RunLoop
> run_loop_
;
66 GCMStoreImplTest::GCMStoreImplTest()
67 : expected_success_(true),
68 next_persistent_id_(base::Time::Now().ToInternalValue()) {
69 EXPECT_TRUE(temp_directory_
.CreateUniqueTempDir());
70 run_loop_
.reset(new base::RunLoop());
73 GCMStoreImplTest::~GCMStoreImplTest() {}
75 scoped_ptr
<GCMStoreImpl
> GCMStoreImplTest::BuildGCMStore() {
76 return scoped_ptr
<GCMStoreImpl
>(new GCMStoreImpl(
77 temp_directory_
.path(),
78 message_loop_
.message_loop_proxy(),
79 make_scoped_ptr
<Encryptor
>(new FakeEncryptor
)));
82 std::string
GCMStoreImplTest::GetNextPersistentId() {
83 return base::Uint64ToString(next_persistent_id_
++);
86 void GCMStoreImplTest::PumpLoop() { message_loop_
.RunUntilIdle(); }
88 void GCMStoreImplTest::LoadCallback(
89 scoped_ptr
<GCMStore::LoadResult
>* result_dst
,
90 scoped_ptr
<GCMStore::LoadResult
> result
) {
91 ASSERT_TRUE(result
->success
);
92 *result_dst
= result
.Pass();
94 run_loop_
.reset(new base::RunLoop());
97 void GCMStoreImplTest::UpdateCallback(bool success
) {
98 ASSERT_EQ(expected_success_
, success
);
101 // Verify creating a new database and loading it.
102 TEST_F(GCMStoreImplTest
, LoadNew
) {
103 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
104 scoped_ptr
<GCMStore::LoadResult
> load_result
;
105 gcm_store
->Load(base::Bind(
106 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
109 EXPECT_EQ(0U, load_result
->device_android_id
);
110 EXPECT_EQ(0U, load_result
->device_security_token
);
111 EXPECT_TRUE(load_result
->incoming_messages
.empty());
112 EXPECT_TRUE(load_result
->outgoing_messages
.empty());
113 EXPECT_TRUE(load_result
->gservices_settings
.empty());
114 EXPECT_EQ(base::Time::FromInternalValue(0LL), load_result
->last_checkin_time
);
117 TEST_F(GCMStoreImplTest
, DeviceCredentials
) {
118 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
119 scoped_ptr
<GCMStore::LoadResult
> load_result
;
120 gcm_store
->Load(base::Bind(
121 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
124 gcm_store
->SetDeviceCredentials(
127 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
130 gcm_store
= BuildGCMStore().Pass();
131 gcm_store
->Load(base::Bind(
132 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
135 ASSERT_EQ(kDeviceId
, load_result
->device_android_id
);
136 ASSERT_EQ(kDeviceToken
, load_result
->device_security_token
);
139 TEST_F(GCMStoreImplTest
, LastCheckinInfo
) {
140 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
141 scoped_ptr
<GCMStore::LoadResult
> load_result
;
142 gcm_store
->Load(base::Bind(
143 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
146 base::Time last_checkin_time
= base::Time::Now();
147 std::set
<std::string
> accounts
;
148 accounts
.insert("test_user1@gmail.com");
149 accounts
.insert("test_user2@gmail.com");
151 gcm_store
->SetLastCheckinInfo(
154 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
157 gcm_store
= BuildGCMStore().Pass();
158 gcm_store
->Load(base::Bind(
159 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
161 ASSERT_EQ(last_checkin_time
, load_result
->last_checkin_time
);
162 ASSERT_EQ(accounts
, load_result
->last_checkin_accounts
);
164 // Negative cases, where the value read is gibberish.
165 gcm_store
->SetValueForTesting(
168 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
171 gcm_store
= BuildGCMStore().Pass();
172 gcm_store
->Load(base::Bind(
173 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
175 EXPECT_EQ(base::Time(), load_result
->last_checkin_time
);
178 TEST_F(GCMStoreImplTest
, GServicesSettings_ProtocolV2
) {
179 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
180 scoped_ptr
<GCMStore::LoadResult
> load_result
;
181 gcm_store
->Load(base::Bind(
182 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
185 std::map
<std::string
, std::string
> settings
;
186 settings
["checkin_interval"] = "12345";
187 settings
["mcs_port"] = "438";
188 settings
["checkin_url"] = "http://checkin.google.com";
189 std::string digest
= "digest1";
191 gcm_store
->SetGServicesSettings(
194 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
197 gcm_store
= BuildGCMStore().Pass();
198 gcm_store
->Load(base::Bind(
199 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
202 ASSERT_EQ(settings
, load_result
->gservices_settings
);
203 ASSERT_EQ(digest
, load_result
->gservices_digest
);
205 // Remove some, and add some.
207 settings
["checkin_interval"] = "54321";
208 settings
["registration_url"] = "http://registration.google.com";
211 gcm_store
->SetGServicesSettings(
214 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
217 gcm_store
= BuildGCMStore().Pass();
218 gcm_store
->Load(base::Bind(
219 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
222 ASSERT_EQ(settings
, load_result
->gservices_settings
);
223 ASSERT_EQ(digest
, load_result
->gservices_digest
);
226 TEST_F(GCMStoreImplTest
, Registrations
) {
227 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
228 scoped_ptr
<GCMStore::LoadResult
> load_result
;
229 gcm_store
->Load(base::Bind(
230 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
233 // Add one registration with one sender.
234 linked_ptr
<RegistrationInfo
> registration1(new RegistrationInfo
);
235 registration1
->sender_ids
.push_back("sender1");
236 registration1
->registration_id
= "registration1";
237 gcm_store
->AddRegistration(
240 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
243 // Add one registration with multiple senders.
244 linked_ptr
<RegistrationInfo
> registration2(new RegistrationInfo
);
245 registration2
->sender_ids
.push_back("sender2_1");
246 registration2
->sender_ids
.push_back("sender2_2");
247 registration2
->registration_id
= "registration2";
248 gcm_store
->AddRegistration(
251 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
254 gcm_store
= BuildGCMStore().Pass();
255 gcm_store
->Load(base::Bind(
256 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
259 ASSERT_EQ(2u, load_result
->registrations
.size());
260 ASSERT_TRUE(load_result
->registrations
.find("app1") !=
261 load_result
->registrations
.end());
262 EXPECT_EQ(registration1
->registration_id
,
263 load_result
->registrations
["app1"]->registration_id
);
264 ASSERT_EQ(1u, load_result
->registrations
["app1"]->sender_ids
.size());
265 EXPECT_EQ(registration1
->sender_ids
[0],
266 load_result
->registrations
["app1"]->sender_ids
[0]);
267 ASSERT_TRUE(load_result
->registrations
.find("app2") !=
268 load_result
->registrations
.end());
269 EXPECT_EQ(registration2
->registration_id
,
270 load_result
->registrations
["app2"]->registration_id
);
271 ASSERT_EQ(2u, load_result
->registrations
["app2"]->sender_ids
.size());
272 EXPECT_EQ(registration2
->sender_ids
[0],
273 load_result
->registrations
["app2"]->sender_ids
[0]);
274 EXPECT_EQ(registration2
->sender_ids
[1],
275 load_result
->registrations
["app2"]->sender_ids
[1]);
277 gcm_store
->RemoveRegistration(
279 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
282 gcm_store
= BuildGCMStore().Pass();
283 gcm_store
->Load(base::Bind(
284 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
287 ASSERT_EQ(1u, load_result
->registrations
.size());
288 ASSERT_TRUE(load_result
->registrations
.find("app1") !=
289 load_result
->registrations
.end());
290 EXPECT_EQ(registration1
->registration_id
,
291 load_result
->registrations
["app1"]->registration_id
);
292 ASSERT_EQ(1u, load_result
->registrations
["app1"]->sender_ids
.size());
293 EXPECT_EQ(registration1
->sender_ids
[0],
294 load_result
->registrations
["app1"]->sender_ids
[0]);
297 // Verify saving some incoming messages, reopening the directory, and then
298 // removing those incoming messages.
299 TEST_F(GCMStoreImplTest
, IncomingMessages
) {
300 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
301 scoped_ptr
<GCMStore::LoadResult
> load_result
;
302 gcm_store
->Load(base::Bind(
303 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
306 std::vector
<std::string
> persistent_ids
;
307 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
308 persistent_ids
.push_back(GetNextPersistentId());
309 gcm_store
->AddIncomingMessage(
310 persistent_ids
.back(),
311 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
315 gcm_store
= BuildGCMStore().Pass();
316 gcm_store
->Load(base::Bind(
317 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
320 ASSERT_EQ(persistent_ids
, load_result
->incoming_messages
);
321 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
323 gcm_store
->RemoveIncomingMessages(
325 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
328 gcm_store
= BuildGCMStore().Pass();
329 load_result
->incoming_messages
.clear();
330 gcm_store
->Load(base::Bind(
331 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
334 ASSERT_TRUE(load_result
->incoming_messages
.empty());
335 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
338 // Verify saving some outgoing messages, reopening the directory, and then
339 // removing those outgoing messages.
340 TEST_F(GCMStoreImplTest
, OutgoingMessages
) {
341 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
342 scoped_ptr
<GCMStore::LoadResult
> load_result
;
343 gcm_store
->Load(base::Bind(
344 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
347 std::vector
<std::string
> persistent_ids
;
348 const int kNumPersistentIds
= 10;
349 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
350 persistent_ids
.push_back(GetNextPersistentId());
351 mcs_proto::DataMessageStanza message
;
352 message
.set_from(kAppName
+ persistent_ids
.back());
353 message
.set_category(kCategoryName
+ persistent_ids
.back());
354 gcm_store
->AddOutgoingMessage(
355 persistent_ids
.back(),
357 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
361 gcm_store
= BuildGCMStore().Pass();
362 gcm_store
->Load(base::Bind(
363 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
366 ASSERT_TRUE(load_result
->incoming_messages
.empty());
367 ASSERT_EQ(load_result
->outgoing_messages
.size(), persistent_ids
.size());
368 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
369 std::string id
= persistent_ids
[i
];
370 ASSERT_TRUE(load_result
->outgoing_messages
[id
].get());
371 const mcs_proto::DataMessageStanza
* message
=
372 reinterpret_cast<mcs_proto::DataMessageStanza
*>(
373 load_result
->outgoing_messages
[id
].get());
374 ASSERT_EQ(message
->from(), kAppName
+ id
);
375 ASSERT_EQ(message
->category(), kCategoryName
+ id
);
378 gcm_store
->RemoveOutgoingMessages(
380 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
383 gcm_store
= BuildGCMStore().Pass();
384 load_result
->outgoing_messages
.clear();
385 gcm_store
->Load(base::Bind(
386 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
389 ASSERT_TRUE(load_result
->incoming_messages
.empty());
390 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
393 // Verify incoming and outgoing messages don't conflict.
394 TEST_F(GCMStoreImplTest
, IncomingAndOutgoingMessages
) {
395 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
396 scoped_ptr
<GCMStore::LoadResult
> load_result
;
397 gcm_store
->Load(base::Bind(
398 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
401 std::vector
<std::string
> persistent_ids
;
402 const int kNumPersistentIds
= 10;
403 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
404 persistent_ids
.push_back(GetNextPersistentId());
405 gcm_store
->AddIncomingMessage(
406 persistent_ids
.back(),
407 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
410 mcs_proto::DataMessageStanza message
;
411 message
.set_from(kAppName
+ persistent_ids
.back());
412 message
.set_category(kCategoryName
+ persistent_ids
.back());
413 gcm_store
->AddOutgoingMessage(
414 persistent_ids
.back(),
416 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
420 gcm_store
= BuildGCMStore().Pass();
421 gcm_store
->Load(base::Bind(
422 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
425 ASSERT_EQ(persistent_ids
, load_result
->incoming_messages
);
426 ASSERT_EQ(load_result
->outgoing_messages
.size(), persistent_ids
.size());
427 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
428 std::string id
= persistent_ids
[i
];
429 ASSERT_TRUE(load_result
->outgoing_messages
[id
].get());
430 const mcs_proto::DataMessageStanza
* message
=
431 reinterpret_cast<mcs_proto::DataMessageStanza
*>(
432 load_result
->outgoing_messages
[id
].get());
433 ASSERT_EQ(message
->from(), kAppName
+ id
);
434 ASSERT_EQ(message
->category(), kCategoryName
+ id
);
437 gcm_store
->RemoveIncomingMessages(
439 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
441 gcm_store
->RemoveOutgoingMessages(
443 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
446 gcm_store
= BuildGCMStore().Pass();
447 load_result
->incoming_messages
.clear();
448 load_result
->outgoing_messages
.clear();
449 gcm_store
->Load(base::Bind(
450 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
453 ASSERT_TRUE(load_result
->incoming_messages
.empty());
454 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
457 // Test that per-app message limits are enforced, persisted across restarts,
458 // and updated as messages are removed.
459 TEST_F(GCMStoreImplTest
, PerAppMessageLimits
) {
460 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
461 scoped_ptr
<GCMStore::LoadResult
> load_result
;
462 gcm_store
->Load(base::Bind(&GCMStoreImplTest::LoadCallback
,
463 base::Unretained(this),
466 // Add the initial (below app limit) messages.
467 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
468 mcs_proto::DataMessageStanza message
;
469 message
.set_from(kAppName
);
470 message
.set_category(kCategoryName
);
471 EXPECT_TRUE(gcm_store
->AddOutgoingMessage(
472 base::IntToString(i
),
474 base::Bind(&GCMStoreImplTest::UpdateCallback
,
475 base::Unretained(this))));
479 // Attempting to add some more should fail.
480 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
481 mcs_proto::DataMessageStanza message
;
482 message
.set_from(kAppName
);
483 message
.set_category(kCategoryName
);
484 EXPECT_FALSE(gcm_store
->AddOutgoingMessage(
485 base::IntToString(i
+ kNumMessagesPerApp
),
487 base::Bind(&GCMStoreImplTest::UpdateCallback
,
488 base::Unretained(this))));
492 // Tear down and restore the database.
493 gcm_store
= BuildGCMStore().Pass();
494 gcm_store
->Load(base::Bind(&GCMStoreImplTest::LoadCallback
,
495 base::Unretained(this),
499 // Adding more messages should still fail.
500 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
501 mcs_proto::DataMessageStanza message
;
502 message
.set_from(kAppName
);
503 message
.set_category(kCategoryName
);
504 EXPECT_FALSE(gcm_store
->AddOutgoingMessage(
505 base::IntToString(i
+ kNumMessagesPerApp
),
507 base::Bind(&GCMStoreImplTest::UpdateCallback
,
508 base::Unretained(this))));
512 // Remove the existing messages.
513 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
514 gcm_store
->RemoveOutgoingMessage(
515 base::IntToString(i
),
516 base::Bind(&GCMStoreImplTest::UpdateCallback
,
517 base::Unretained(this)));
521 // Successfully add new messages.
522 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
523 mcs_proto::DataMessageStanza message
;
524 message
.set_from(kAppName
);
525 message
.set_category(kCategoryName
);
526 EXPECT_TRUE(gcm_store
->AddOutgoingMessage(
527 base::IntToString(i
+ kNumMessagesPerApp
),
529 base::Bind(&GCMStoreImplTest::UpdateCallback
,
530 base::Unretained(this))));
535 TEST_F(GCMStoreImplTest
, AccountMapping
) {
536 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
537 scoped_ptr
<GCMStore::LoadResult
> load_result
;
538 gcm_store
->Load(base::Bind(
539 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
541 // Add account mappings.
542 AccountMapping account_mapping1
;
543 account_mapping1
.account_id
= "account_id_1";
544 account_mapping1
.email
= "account_id_1@gmail.com";
545 account_mapping1
.access_token
= "account_token1";
546 account_mapping1
.status
= AccountMapping::ADDING
;
547 account_mapping1
.status_change_timestamp
= base::Time();
548 account_mapping1
.last_message_id
= "message_1";
550 AccountMapping account_mapping2
;
551 account_mapping2
.account_id
= "account_id_2";
552 account_mapping2
.email
= "account_id_2@gmail.com";
553 account_mapping2
.access_token
= "account_token1";
554 account_mapping2
.status
= AccountMapping::REMOVING
;
555 account_mapping2
.status_change_timestamp
=
556 base::Time::FromInternalValue(1305734521259935LL);
557 account_mapping2
.last_message_id
= "message_2";
559 gcm_store
->AddAccountMapping(
561 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
563 gcm_store
->AddAccountMapping(
565 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
568 gcm_store
= BuildGCMStore().Pass();
569 gcm_store
->Load(base::Bind(
570 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
573 EXPECT_EQ(2UL, load_result
->account_mappings
.size());
574 GCMStore::AccountMappings::iterator iter
=
575 load_result
->account_mappings
.begin();
576 EXPECT_EQ(account_mapping1
.account_id
, iter
->account_id
);
577 EXPECT_EQ(account_mapping1
.email
, iter
->email
);
578 EXPECT_TRUE(iter
->access_token
.empty());
579 EXPECT_EQ(AccountMapping::ADDING
, iter
->status
);
580 EXPECT_EQ(account_mapping1
.status_change_timestamp
,
581 iter
->status_change_timestamp
);
582 EXPECT_EQ(account_mapping1
.last_message_id
, iter
->last_message_id
);
584 EXPECT_EQ(account_mapping2
.account_id
, iter
->account_id
);
585 EXPECT_EQ(account_mapping2
.email
, iter
->email
);
586 EXPECT_TRUE(iter
->access_token
.empty());
587 EXPECT_EQ(AccountMapping::REMOVING
, iter
->status
);
588 EXPECT_EQ(account_mapping2
.status_change_timestamp
,
589 iter
->status_change_timestamp
);
590 EXPECT_EQ(account_mapping2
.last_message_id
, iter
->last_message_id
);
592 gcm_store
->RemoveAccountMapping(
593 account_mapping1
.account_id
,
594 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
597 gcm_store
= BuildGCMStore().Pass();
598 gcm_store
->Load(base::Bind(
599 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
602 EXPECT_EQ(1UL, load_result
->account_mappings
.size());
603 iter
= load_result
->account_mappings
.begin();
604 EXPECT_EQ(account_mapping2
.account_id
, iter
->account_id
);
605 EXPECT_EQ(account_mapping2
.email
, iter
->email
);
606 EXPECT_TRUE(iter
->access_token
.empty());
607 EXPECT_EQ(AccountMapping::REMOVING
, iter
->status
);
608 EXPECT_EQ(account_mapping2
.status_change_timestamp
,
609 iter
->status_change_timestamp
);
610 EXPECT_EQ(account_mapping2
.last_message_id
, iter
->last_message_id
);
613 // When the database is destroyed, all database updates should fail. At the
614 // same time, they per-app message counts should not go up, as failures should
615 // result in decrementing the counts.
616 TEST_F(GCMStoreImplTest
, AddMessageAfterDestroy
) {
617 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
618 scoped_ptr
<GCMStore::LoadResult
> load_result
;
619 gcm_store
->Load(base::Bind(&GCMStoreImplTest::LoadCallback
,
620 base::Unretained(this),
623 gcm_store
->Destroy(base::Bind(&GCMStoreImplTest::UpdateCallback
,
624 base::Unretained(this)));
627 expected_success_
= false;
628 for (int i
= 0; i
< kNumMessagesPerApp
* 2; ++i
) {
629 mcs_proto::DataMessageStanza message
;
630 message
.set_from(kAppName
);
631 message
.set_category(kCategoryName
);
632 // Because all adds are failing, none should hit the per-app message limits.
633 EXPECT_TRUE(gcm_store
->AddOutgoingMessage(
634 base::IntToString(i
),
636 base::Bind(&GCMStoreImplTest::UpdateCallback
,
637 base::Unretained(this))));
642 TEST_F(GCMStoreImplTest
, ReloadAfterClose
) {
643 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
644 scoped_ptr
<GCMStore::LoadResult
> load_result
;
645 gcm_store
->Load(base::Bind(&GCMStoreImplTest::LoadCallback
,
646 base::Unretained(this),
653 gcm_store
->Load(base::Bind(&GCMStoreImplTest::LoadCallback
,
654 base::Unretained(this),
659 TEST_F(GCMStoreImplTest
, LastTokenFetchTime
) {
660 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
661 scoped_ptr
<GCMStore::LoadResult
> load_result
;
662 gcm_store
->Load(base::Bind(
663 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
665 EXPECT_EQ(base::Time(), load_result
->last_token_fetch_time
);
667 base::Time last_token_fetch_time
= base::Time::Now();
668 gcm_store
->SetLastTokenFetchTime(
669 last_token_fetch_time
,
670 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
673 gcm_store
= BuildGCMStore().Pass();
674 gcm_store
->Load(base::Bind(
675 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
677 EXPECT_EQ(last_token_fetch_time
, load_result
->last_token_fetch_time
);
679 // Negative cases, where the value read is gibberish.
680 gcm_store
->SetValueForTesting(
681 "last_token_fetch_time",
683 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
686 gcm_store
= BuildGCMStore().Pass();
687 gcm_store
->Load(base::Bind(
688 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
690 EXPECT_EQ(base::Time(), load_result
->last_token_fetch_time
);