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 virtual ~GCMStoreImplTest();
48 scoped_ptr
<GCMStore
> 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
<GCMStore
> GCMStoreImplTest::BuildGCMStore() {
76 return scoped_ptr
<GCMStore
>(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
<GCMStore
> 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
);
165 TEST_F(GCMStoreImplTest
, GServicesSettings_ProtocolV2
) {
166 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
167 scoped_ptr
<GCMStore::LoadResult
> load_result
;
168 gcm_store
->Load(base::Bind(
169 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
172 std::map
<std::string
, std::string
> settings
;
173 settings
["checkin_interval"] = "12345";
174 settings
["mcs_port"] = "438";
175 settings
["checkin_url"] = "http://checkin.google.com";
176 std::string digest
= "digest1";
178 gcm_store
->SetGServicesSettings(
181 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
184 gcm_store
= BuildGCMStore().Pass();
185 gcm_store
->Load(base::Bind(
186 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
189 ASSERT_EQ(settings
, load_result
->gservices_settings
);
190 ASSERT_EQ(digest
, load_result
->gservices_digest
);
192 // Remove some, and add some.
194 settings
["checkin_interval"] = "54321";
195 settings
["registration_url"] = "http://registration.google.com";
198 gcm_store
->SetGServicesSettings(
201 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
204 gcm_store
= BuildGCMStore().Pass();
205 gcm_store
->Load(base::Bind(
206 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
209 ASSERT_EQ(settings
, load_result
->gservices_settings
);
210 ASSERT_EQ(digest
, load_result
->gservices_digest
);
213 TEST_F(GCMStoreImplTest
, Registrations
) {
214 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
215 scoped_ptr
<GCMStore::LoadResult
> load_result
;
216 gcm_store
->Load(base::Bind(
217 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
220 // Add one registration with one sender.
221 linked_ptr
<RegistrationInfo
> registration1(new RegistrationInfo
);
222 registration1
->sender_ids
.push_back("sender1");
223 registration1
->registration_id
= "registration1";
224 gcm_store
->AddRegistration(
227 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
230 // Add one registration with multiple senders.
231 linked_ptr
<RegistrationInfo
> registration2(new RegistrationInfo
);
232 registration2
->sender_ids
.push_back("sender2_1");
233 registration2
->sender_ids
.push_back("sender2_2");
234 registration2
->registration_id
= "registration2";
235 gcm_store
->AddRegistration(
238 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
241 gcm_store
= BuildGCMStore().Pass();
242 gcm_store
->Load(base::Bind(
243 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
246 ASSERT_EQ(2u, load_result
->registrations
.size());
247 ASSERT_TRUE(load_result
->registrations
.find("app1") !=
248 load_result
->registrations
.end());
249 EXPECT_EQ(registration1
->registration_id
,
250 load_result
->registrations
["app1"]->registration_id
);
251 ASSERT_EQ(1u, load_result
->registrations
["app1"]->sender_ids
.size());
252 EXPECT_EQ(registration1
->sender_ids
[0],
253 load_result
->registrations
["app1"]->sender_ids
[0]);
254 ASSERT_TRUE(load_result
->registrations
.find("app2") !=
255 load_result
->registrations
.end());
256 EXPECT_EQ(registration2
->registration_id
,
257 load_result
->registrations
["app2"]->registration_id
);
258 ASSERT_EQ(2u, load_result
->registrations
["app2"]->sender_ids
.size());
259 EXPECT_EQ(registration2
->sender_ids
[0],
260 load_result
->registrations
["app2"]->sender_ids
[0]);
261 EXPECT_EQ(registration2
->sender_ids
[1],
262 load_result
->registrations
["app2"]->sender_ids
[1]);
264 gcm_store
->RemoveRegistration(
266 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
269 gcm_store
= BuildGCMStore().Pass();
270 gcm_store
->Load(base::Bind(
271 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
274 ASSERT_EQ(1u, load_result
->registrations
.size());
275 ASSERT_TRUE(load_result
->registrations
.find("app1") !=
276 load_result
->registrations
.end());
277 EXPECT_EQ(registration1
->registration_id
,
278 load_result
->registrations
["app1"]->registration_id
);
279 ASSERT_EQ(1u, load_result
->registrations
["app1"]->sender_ids
.size());
280 EXPECT_EQ(registration1
->sender_ids
[0],
281 load_result
->registrations
["app1"]->sender_ids
[0]);
284 // Verify saving some incoming messages, reopening the directory, and then
285 // removing those incoming messages.
286 TEST_F(GCMStoreImplTest
, IncomingMessages
) {
287 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
288 scoped_ptr
<GCMStore::LoadResult
> load_result
;
289 gcm_store
->Load(base::Bind(
290 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
293 std::vector
<std::string
> persistent_ids
;
294 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
295 persistent_ids
.push_back(GetNextPersistentId());
296 gcm_store
->AddIncomingMessage(
297 persistent_ids
.back(),
298 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
302 gcm_store
= BuildGCMStore().Pass();
303 gcm_store
->Load(base::Bind(
304 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
307 ASSERT_EQ(persistent_ids
, load_result
->incoming_messages
);
308 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
310 gcm_store
->RemoveIncomingMessages(
312 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
315 gcm_store
= BuildGCMStore().Pass();
316 load_result
->incoming_messages
.clear();
317 gcm_store
->Load(base::Bind(
318 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
321 ASSERT_TRUE(load_result
->incoming_messages
.empty());
322 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
325 // Verify saving some outgoing messages, reopening the directory, and then
326 // removing those outgoing messages.
327 TEST_F(GCMStoreImplTest
, OutgoingMessages
) {
328 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
329 scoped_ptr
<GCMStore::LoadResult
> load_result
;
330 gcm_store
->Load(base::Bind(
331 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
334 std::vector
<std::string
> persistent_ids
;
335 const int kNumPersistentIds
= 10;
336 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
337 persistent_ids
.push_back(GetNextPersistentId());
338 mcs_proto::DataMessageStanza message
;
339 message
.set_from(kAppName
+ persistent_ids
.back());
340 message
.set_category(kCategoryName
+ persistent_ids
.back());
341 gcm_store
->AddOutgoingMessage(
342 persistent_ids
.back(),
344 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
348 gcm_store
= BuildGCMStore().Pass();
349 gcm_store
->Load(base::Bind(
350 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
353 ASSERT_TRUE(load_result
->incoming_messages
.empty());
354 ASSERT_EQ(load_result
->outgoing_messages
.size(), persistent_ids
.size());
355 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
356 std::string id
= persistent_ids
[i
];
357 ASSERT_TRUE(load_result
->outgoing_messages
[id
].get());
358 const mcs_proto::DataMessageStanza
* message
=
359 reinterpret_cast<mcs_proto::DataMessageStanza
*>(
360 load_result
->outgoing_messages
[id
].get());
361 ASSERT_EQ(message
->from(), kAppName
+ id
);
362 ASSERT_EQ(message
->category(), kCategoryName
+ id
);
365 gcm_store
->RemoveOutgoingMessages(
367 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
370 gcm_store
= BuildGCMStore().Pass();
371 load_result
->outgoing_messages
.clear();
372 gcm_store
->Load(base::Bind(
373 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
376 ASSERT_TRUE(load_result
->incoming_messages
.empty());
377 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
380 // Verify incoming and outgoing messages don't conflict.
381 TEST_F(GCMStoreImplTest
, IncomingAndOutgoingMessages
) {
382 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
383 scoped_ptr
<GCMStore::LoadResult
> load_result
;
384 gcm_store
->Load(base::Bind(
385 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
388 std::vector
<std::string
> persistent_ids
;
389 const int kNumPersistentIds
= 10;
390 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
391 persistent_ids
.push_back(GetNextPersistentId());
392 gcm_store
->AddIncomingMessage(
393 persistent_ids
.back(),
394 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
397 mcs_proto::DataMessageStanza message
;
398 message
.set_from(kAppName
+ persistent_ids
.back());
399 message
.set_category(kCategoryName
+ persistent_ids
.back());
400 gcm_store
->AddOutgoingMessage(
401 persistent_ids
.back(),
403 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
407 gcm_store
= BuildGCMStore().Pass();
408 gcm_store
->Load(base::Bind(
409 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
412 ASSERT_EQ(persistent_ids
, load_result
->incoming_messages
);
413 ASSERT_EQ(load_result
->outgoing_messages
.size(), persistent_ids
.size());
414 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
415 std::string id
= persistent_ids
[i
];
416 ASSERT_TRUE(load_result
->outgoing_messages
[id
].get());
417 const mcs_proto::DataMessageStanza
* message
=
418 reinterpret_cast<mcs_proto::DataMessageStanza
*>(
419 load_result
->outgoing_messages
[id
].get());
420 ASSERT_EQ(message
->from(), kAppName
+ id
);
421 ASSERT_EQ(message
->category(), kCategoryName
+ id
);
424 gcm_store
->RemoveIncomingMessages(
426 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
428 gcm_store
->RemoveOutgoingMessages(
430 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
433 gcm_store
= BuildGCMStore().Pass();
434 load_result
->incoming_messages
.clear();
435 load_result
->outgoing_messages
.clear();
436 gcm_store
->Load(base::Bind(
437 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
440 ASSERT_TRUE(load_result
->incoming_messages
.empty());
441 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
444 // Test that per-app message limits are enforced, persisted across restarts,
445 // and updated as messages are removed.
446 TEST_F(GCMStoreImplTest
, PerAppMessageLimits
) {
447 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
448 scoped_ptr
<GCMStore::LoadResult
> load_result
;
449 gcm_store
->Load(base::Bind(&GCMStoreImplTest::LoadCallback
,
450 base::Unretained(this),
453 // Add the initial (below app limit) messages.
454 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
455 mcs_proto::DataMessageStanza message
;
456 message
.set_from(kAppName
);
457 message
.set_category(kCategoryName
);
458 EXPECT_TRUE(gcm_store
->AddOutgoingMessage(
459 base::IntToString(i
),
461 base::Bind(&GCMStoreImplTest::UpdateCallback
,
462 base::Unretained(this))));
466 // Attempting to add some more should fail.
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_FALSE(gcm_store
->AddOutgoingMessage(
472 base::IntToString(i
+ kNumMessagesPerApp
),
474 base::Bind(&GCMStoreImplTest::UpdateCallback
,
475 base::Unretained(this))));
479 // Tear down and restore the database.
480 gcm_store
= BuildGCMStore().Pass();
481 gcm_store
->Load(base::Bind(&GCMStoreImplTest::LoadCallback
,
482 base::Unretained(this),
486 // Adding more messages should still fail.
487 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
488 mcs_proto::DataMessageStanza message
;
489 message
.set_from(kAppName
);
490 message
.set_category(kCategoryName
);
491 EXPECT_FALSE(gcm_store
->AddOutgoingMessage(
492 base::IntToString(i
+ kNumMessagesPerApp
),
494 base::Bind(&GCMStoreImplTest::UpdateCallback
,
495 base::Unretained(this))));
499 // Remove the existing messages.
500 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
501 gcm_store
->RemoveOutgoingMessage(
502 base::IntToString(i
),
503 base::Bind(&GCMStoreImplTest::UpdateCallback
,
504 base::Unretained(this)));
508 // Successfully add new messages.
509 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
510 mcs_proto::DataMessageStanza message
;
511 message
.set_from(kAppName
);
512 message
.set_category(kCategoryName
);
513 EXPECT_TRUE(gcm_store
->AddOutgoingMessage(
514 base::IntToString(i
+ kNumMessagesPerApp
),
516 base::Bind(&GCMStoreImplTest::UpdateCallback
,
517 base::Unretained(this))));
522 TEST_F(GCMStoreImplTest
, AccountMapping
) {
523 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
524 scoped_ptr
<GCMStore::LoadResult
> load_result
;
525 gcm_store
->Load(base::Bind(
526 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
528 // Add account mappings.
529 AccountMapping account_mapping1
;
530 account_mapping1
.account_id
= "account_id_1";
531 account_mapping1
.email
= "account_id_1@gmail.com";
532 account_mapping1
.access_token
= "account_token1";
533 account_mapping1
.status
= AccountMapping::ADDING
;
534 account_mapping1
.status_change_timestamp
= base::Time();
535 account_mapping1
.last_message_type
= AccountMapping::MSG_ADD
;
536 account_mapping1
.last_message_id
= "message_1";
538 AccountMapping account_mapping2
;
539 account_mapping2
.account_id
= "account_id_2";
540 account_mapping2
.email
= "account_id_2@gmail.com";
541 account_mapping2
.access_token
= "account_token1";
542 account_mapping2
.status
= AccountMapping::REMOVING
;
543 account_mapping2
.status_change_timestamp
=
544 base::Time::FromInternalValue(1305734521259935LL);
545 account_mapping2
.last_message_type
= AccountMapping::MSG_REMOVE
;
546 account_mapping2
.last_message_id
= "message_2";
548 gcm_store
->AddAccountMapping(
550 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
552 gcm_store
->AddAccountMapping(
554 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
557 gcm_store
= BuildGCMStore().Pass();
558 gcm_store
->Load(base::Bind(
559 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
562 EXPECT_EQ(2UL, load_result
->account_mappings
.size());
563 GCMStore::AccountMappingMap::iterator iter
=
564 load_result
->account_mappings
.begin();
565 EXPECT_EQ("account_id_1", iter
->first
);
566 EXPECT_EQ(account_mapping1
.account_id
, iter
->second
.account_id
);
567 EXPECT_EQ(account_mapping1
.email
, iter
->second
.email
);
568 EXPECT_TRUE(iter
->second
.access_token
.empty());
569 EXPECT_EQ(AccountMapping::ADDING
, iter
->second
.status
);
570 EXPECT_EQ(account_mapping1
.status_change_timestamp
,
571 iter
->second
.status_change_timestamp
);
572 EXPECT_EQ(account_mapping1
.last_message_type
, iter
->second
.last_message_type
);
573 EXPECT_EQ(account_mapping1
.last_message_id
, iter
->second
.last_message_id
);
575 EXPECT_EQ("account_id_2", iter
->first
);
576 EXPECT_EQ(account_mapping2
.account_id
, iter
->second
.account_id
);
577 EXPECT_EQ(account_mapping2
.email
, iter
->second
.email
);
578 EXPECT_TRUE(iter
->second
.access_token
.empty());
579 EXPECT_EQ(AccountMapping::REMOVING
, iter
->second
.status
);
580 EXPECT_EQ(account_mapping2
.status_change_timestamp
,
581 iter
->second
.status_change_timestamp
);
582 EXPECT_EQ(account_mapping2
.last_message_type
, iter
->second
.last_message_type
);
583 EXPECT_EQ(account_mapping2
.last_message_id
, iter
->second
.last_message_id
);
585 gcm_store
->RemoveAccountMapping(
586 account_mapping1
.account_id
,
587 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
590 gcm_store
= BuildGCMStore().Pass();
591 gcm_store
->Load(base::Bind(
592 &GCMStoreImplTest::LoadCallback
, base::Unretained(this), &load_result
));
595 EXPECT_EQ(1UL, load_result
->account_mappings
.size());
596 iter
= load_result
->account_mappings
.begin();
597 EXPECT_EQ("account_id_2", iter
->first
);
598 EXPECT_EQ(account_mapping2
.account_id
, iter
->second
.account_id
);
599 EXPECT_EQ(account_mapping2
.email
, iter
->second
.email
);
600 EXPECT_TRUE(iter
->second
.access_token
.empty());
601 EXPECT_EQ(AccountMapping::REMOVING
, iter
->second
.status
);
602 EXPECT_EQ(account_mapping2
.status_change_timestamp
,
603 iter
->second
.status_change_timestamp
);
604 EXPECT_EQ(account_mapping2
.last_message_type
, iter
->second
.last_message_type
);
605 EXPECT_EQ(account_mapping2
.last_message_id
, iter
->second
.last_message_id
);
608 // When the database is destroyed, all database updates should fail. At the
609 // same time, they per-app message counts should not go up, as failures should
610 // result in decrementing the counts.
611 TEST_F(GCMStoreImplTest
, AddMessageAfterDestroy
) {
612 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
613 scoped_ptr
<GCMStore::LoadResult
> load_result
;
614 gcm_store
->Load(base::Bind(&GCMStoreImplTest::LoadCallback
,
615 base::Unretained(this),
618 gcm_store
->Destroy(base::Bind(&GCMStoreImplTest::UpdateCallback
,
619 base::Unretained(this)));
622 expected_success_
= false;
623 for (int i
= 0; i
< kNumMessagesPerApp
* 2; ++i
) {
624 mcs_proto::DataMessageStanza message
;
625 message
.set_from(kAppName
);
626 message
.set_category(kCategoryName
);
627 // Because all adds are failing, none should hit the per-app message limits.
628 EXPECT_TRUE(gcm_store
->AddOutgoingMessage(
629 base::IntToString(i
),
631 base::Bind(&GCMStoreImplTest::UpdateCallback
,
632 base::Unretained(this))));
637 TEST_F(GCMStoreImplTest
, ReloadAfterClose
) {
638 scoped_ptr
<GCMStore
> gcm_store(BuildGCMStore());
639 scoped_ptr
<GCMStore::LoadResult
> load_result
;
640 gcm_store
->Load(base::Bind(&GCMStoreImplTest::LoadCallback
,
641 base::Unretained(this),
648 gcm_store
->Load(base::Bind(&GCMStoreImplTest::LoadCallback
,
649 base::Unretained(this),