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/strings/string_number_conversions.h"
16 #include "base/test/test_simple_task_runner.h"
17 #include "base/thread_task_runner_handle.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";
36 const char kAppName2
[] = "my_app_2";
38 // Category name for testing.
39 const char kCategoryName
[] = "my_category";
41 const uint64 kDeviceId
= 22;
42 const uint64 kDeviceToken
= 55;
44 class GCMStoreImplTest
: public testing::Test
{
47 ~GCMStoreImplTest() override
;
49 scoped_ptr
<GCMStoreImpl
> BuildGCMStore();
51 GCMStoreImpl
* gcm_store
, scoped_ptr
<GCMStore::LoadResult
>* result_dst
);
53 std::string
GetNextPersistentId();
57 void LoadCallback(scoped_ptr
<GCMStore::LoadResult
>* result_dst
,
58 scoped_ptr
<GCMStore::LoadResult
> result
);
59 void LoadWithoutCheckCallback(scoped_ptr
<GCMStore::LoadResult
>* result_dst
,
60 scoped_ptr
<GCMStore::LoadResult
> result
);
61 void UpdateCallback(bool success
);
64 scoped_refptr
<base::TestSimpleTaskRunner
> task_runner_
;
65 base::ThreadTaskRunnerHandle task_runner_handle_
;
66 base::ScopedTempDir temp_directory_
;
67 bool expected_success_
;
68 uint64 next_persistent_id_
;
71 GCMStoreImplTest::GCMStoreImplTest()
72 : task_runner_(new base::TestSimpleTaskRunner()),
73 task_runner_handle_(task_runner_
),
74 expected_success_(true),
75 next_persistent_id_(base::Time::Now().ToInternalValue()) {
76 EXPECT_TRUE(temp_directory_
.CreateUniqueTempDir());
79 GCMStoreImplTest::~GCMStoreImplTest() {}
81 scoped_ptr
<GCMStoreImpl
> GCMStoreImplTest::BuildGCMStore() {
82 return scoped_ptr
<GCMStoreImpl
>(new GCMStoreImpl(
83 // Pass an non-existent directory as store path to match the exact
84 // behavior in the production code. Currently GCMStoreImpl checks if
85 // the directory exist or not to determine the store existence.
86 temp_directory_
.path().Append(FILE_PATH_LITERAL("GCM Store")),
88 make_scoped_ptr
<Encryptor
>(new FakeEncryptor
)));
91 void GCMStoreImplTest::LoadGCMStore(
92 GCMStoreImpl
* gcm_store
, scoped_ptr
<GCMStore::LoadResult
>* result_dst
) {
94 GCMStore::CREATE_IF_MISSING
,
95 base::Bind(&GCMStoreImplTest::LoadCallback
,
96 base::Unretained(this),
101 std::string
GCMStoreImplTest::GetNextPersistentId() {
102 return base::Uint64ToString(next_persistent_id_
++);
105 void GCMStoreImplTest::PumpLoop() { task_runner_
->RunUntilIdle(); }
107 void GCMStoreImplTest::LoadCallback(
108 scoped_ptr
<GCMStore::LoadResult
>* result_dst
,
109 scoped_ptr
<GCMStore::LoadResult
> result
) {
110 ASSERT_TRUE(result
->success
);
111 LoadWithoutCheckCallback(result_dst
, result
.Pass());
114 void GCMStoreImplTest::LoadWithoutCheckCallback(
115 scoped_ptr
<GCMStore::LoadResult
>* result_dst
,
116 scoped_ptr
<GCMStore::LoadResult
> result
) {
117 *result_dst
= result
.Pass();
120 void GCMStoreImplTest::UpdateCallback(bool success
) {
121 ASSERT_EQ(expected_success_
, success
);
124 // Verify creating a new database and loading it.
125 TEST_F(GCMStoreImplTest
, LoadNew
) {
126 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
127 scoped_ptr
<GCMStore::LoadResult
> load_result
;
128 LoadGCMStore(gcm_store
.get(), &load_result
);
130 EXPECT_EQ(0U, load_result
->device_android_id
);
131 EXPECT_EQ(0U, load_result
->device_security_token
);
132 EXPECT_TRUE(load_result
->incoming_messages
.empty());
133 EXPECT_TRUE(load_result
->outgoing_messages
.empty());
134 EXPECT_TRUE(load_result
->gservices_settings
.empty());
135 EXPECT_EQ(base::Time::FromInternalValue(0LL), load_result
->last_checkin_time
);
138 // Verify new database is not created when DO_NOT_CREATE_NEW_STORE is passed.
139 TEST_F(GCMStoreImplTest
, LoadWithoutCreatingNewStore
) {
140 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
141 scoped_ptr
<GCMStore::LoadResult
> load_result
;
143 GCMStore::DO_NOT_CREATE
,
144 base::Bind(&GCMStoreImplTest::LoadWithoutCheckCallback
,
145 base::Unretained(this),
149 EXPECT_FALSE(load_result
->success
);
150 EXPECT_TRUE(load_result
->store_does_not_exist
);
153 TEST_F(GCMStoreImplTest
, DeviceCredentials
) {
154 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
155 scoped_ptr
<GCMStore::LoadResult
> load_result
;
156 LoadGCMStore(gcm_store
.get(), &load_result
);
158 gcm_store
->SetDeviceCredentials(
161 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
164 gcm_store
= BuildGCMStore().Pass();
165 LoadGCMStore(gcm_store
.get(), &load_result
);
167 ASSERT_EQ(kDeviceId
, load_result
->device_android_id
);
168 ASSERT_EQ(kDeviceToken
, load_result
->device_security_token
);
171 TEST_F(GCMStoreImplTest
, LastCheckinInfo
) {
172 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
173 scoped_ptr
<GCMStore::LoadResult
> load_result
;
174 LoadGCMStore(gcm_store
.get(), &load_result
);
176 base::Time last_checkin_time
= base::Time::Now();
177 std::set
<std::string
> accounts
;
178 accounts
.insert("test_user1@gmail.com");
179 accounts
.insert("test_user2@gmail.com");
181 gcm_store
->SetLastCheckinInfo(
184 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
187 gcm_store
= BuildGCMStore().Pass();
188 LoadGCMStore(gcm_store
.get(), &load_result
);
189 ASSERT_EQ(last_checkin_time
, load_result
->last_checkin_time
);
190 ASSERT_EQ(accounts
, load_result
->last_checkin_accounts
);
192 // Negative cases, where the value read is gibberish.
193 gcm_store
->SetValueForTesting(
196 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
199 gcm_store
= BuildGCMStore().Pass();
200 LoadGCMStore(gcm_store
.get(), &load_result
);
201 EXPECT_EQ(base::Time(), load_result
->last_checkin_time
);
204 TEST_F(GCMStoreImplTest
, GServicesSettings_ProtocolV2
) {
205 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
206 scoped_ptr
<GCMStore::LoadResult
> load_result
;
207 LoadGCMStore(gcm_store
.get(), &load_result
);
209 std::map
<std::string
, std::string
> settings
;
210 settings
["checkin_interval"] = "12345";
211 settings
["mcs_port"] = "438";
212 settings
["checkin_url"] = "http://checkin.google.com";
213 std::string digest
= "digest1";
215 gcm_store
->SetGServicesSettings(
218 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
221 gcm_store
= BuildGCMStore().Pass();
222 LoadGCMStore(gcm_store
.get(), &load_result
);
224 ASSERT_EQ(settings
, load_result
->gservices_settings
);
225 ASSERT_EQ(digest
, load_result
->gservices_digest
);
227 // Remove some, and add some.
229 settings
["checkin_interval"] = "54321";
230 settings
["registration_url"] = "http://registration.google.com";
233 gcm_store
->SetGServicesSettings(
236 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
239 gcm_store
= BuildGCMStore().Pass();
240 LoadGCMStore(gcm_store
.get(), &load_result
);
242 ASSERT_EQ(settings
, load_result
->gservices_settings
);
243 ASSERT_EQ(digest
, load_result
->gservices_digest
);
246 TEST_F(GCMStoreImplTest
, Registrations
) {
247 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
248 scoped_ptr
<GCMStore::LoadResult
> load_result
;
249 LoadGCMStore(gcm_store
.get(), &load_result
);
251 // Add one registration with one sender.
252 std::string registration
= "sender1=registration1";
253 gcm_store
->AddRegistration(
256 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
259 // Add one registration with multiple senders.
260 std::string registration2
= "sender1,sender2=registration2";
261 gcm_store
->AddRegistration(
264 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
267 gcm_store
= BuildGCMStore().Pass();
268 LoadGCMStore(gcm_store
.get(), &load_result
);
270 ASSERT_EQ(2u, load_result
->registrations
.size());
271 ASSERT_TRUE(load_result
->registrations
.find(kAppName
) !=
272 load_result
->registrations
.end());
273 EXPECT_EQ(registration
, load_result
->registrations
[kAppName
]);
274 ASSERT_TRUE(load_result
->registrations
.find(kAppName2
) !=
275 load_result
->registrations
.end());
276 EXPECT_EQ(registration2
, load_result
->registrations
[kAppName2
]);
278 gcm_store
->RemoveRegistration(
280 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
283 gcm_store
= BuildGCMStore().Pass();
284 LoadGCMStore(gcm_store
.get(), &load_result
);
286 ASSERT_EQ(1u, load_result
->registrations
.size());
287 ASSERT_TRUE(load_result
->registrations
.find(kAppName
) !=
288 load_result
->registrations
.end());
289 EXPECT_EQ(registration
, load_result
->registrations
[kAppName
]);
292 // Verify saving some incoming messages, reopening the directory, and then
293 // removing those incoming messages.
294 TEST_F(GCMStoreImplTest
, IncomingMessages
) {
295 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
296 scoped_ptr
<GCMStore::LoadResult
> load_result
;
297 LoadGCMStore(gcm_store
.get(), &load_result
);
299 std::vector
<std::string
> persistent_ids
;
300 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
301 persistent_ids
.push_back(GetNextPersistentId());
302 gcm_store
->AddIncomingMessage(
303 persistent_ids
.back(),
304 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
308 gcm_store
= BuildGCMStore().Pass();
309 LoadGCMStore(gcm_store
.get(), &load_result
);
311 ASSERT_EQ(persistent_ids
, load_result
->incoming_messages
);
312 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
314 gcm_store
->RemoveIncomingMessages(
316 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
319 gcm_store
= BuildGCMStore().Pass();
320 load_result
->incoming_messages
.clear();
321 LoadGCMStore(gcm_store
.get(), &load_result
);
323 ASSERT_TRUE(load_result
->incoming_messages
.empty());
324 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
327 // Verify saving some outgoing messages, reopening the directory, and then
328 // removing those outgoing messages.
329 TEST_F(GCMStoreImplTest
, OutgoingMessages
) {
330 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
331 scoped_ptr
<GCMStore::LoadResult
> load_result
;
332 LoadGCMStore(gcm_store
.get(), &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 LoadGCMStore(gcm_store
.get(), &load_result
);
351 ASSERT_TRUE(load_result
->incoming_messages
.empty());
352 ASSERT_EQ(load_result
->outgoing_messages
.size(), persistent_ids
.size());
353 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
354 std::string id
= persistent_ids
[i
];
355 ASSERT_TRUE(load_result
->outgoing_messages
[id
].get());
356 const mcs_proto::DataMessageStanza
* message
=
357 reinterpret_cast<mcs_proto::DataMessageStanza
*>(
358 load_result
->outgoing_messages
[id
].get());
359 ASSERT_EQ(message
->from(), kAppName
+ id
);
360 ASSERT_EQ(message
->category(), kCategoryName
+ id
);
363 gcm_store
->RemoveOutgoingMessages(
365 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
368 gcm_store
= BuildGCMStore().Pass();
369 load_result
->outgoing_messages
.clear();
370 LoadGCMStore(gcm_store
.get(), &load_result
);
372 ASSERT_TRUE(load_result
->incoming_messages
.empty());
373 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
376 // Verify incoming and outgoing messages don't conflict.
377 TEST_F(GCMStoreImplTest
, IncomingAndOutgoingMessages
) {
378 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
379 scoped_ptr
<GCMStore::LoadResult
> load_result
;
380 LoadGCMStore(gcm_store
.get(), &load_result
);
382 std::vector
<std::string
> persistent_ids
;
383 const int kNumPersistentIds
= 10;
384 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
385 persistent_ids
.push_back(GetNextPersistentId());
386 gcm_store
->AddIncomingMessage(
387 persistent_ids
.back(),
388 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
391 mcs_proto::DataMessageStanza message
;
392 message
.set_from(kAppName
+ persistent_ids
.back());
393 message
.set_category(kCategoryName
+ persistent_ids
.back());
394 gcm_store
->AddOutgoingMessage(
395 persistent_ids
.back(),
397 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
401 gcm_store
= BuildGCMStore().Pass();
402 LoadGCMStore(gcm_store
.get(), &load_result
);
404 ASSERT_EQ(persistent_ids
, load_result
->incoming_messages
);
405 ASSERT_EQ(load_result
->outgoing_messages
.size(), persistent_ids
.size());
406 for (int i
= 0; i
< kNumPersistentIds
; ++i
) {
407 std::string id
= persistent_ids
[i
];
408 ASSERT_TRUE(load_result
->outgoing_messages
[id
].get());
409 const mcs_proto::DataMessageStanza
* message
=
410 reinterpret_cast<mcs_proto::DataMessageStanza
*>(
411 load_result
->outgoing_messages
[id
].get());
412 ASSERT_EQ(message
->from(), kAppName
+ id
);
413 ASSERT_EQ(message
->category(), kCategoryName
+ id
);
416 gcm_store
->RemoveIncomingMessages(
418 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
420 gcm_store
->RemoveOutgoingMessages(
422 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
425 gcm_store
= BuildGCMStore().Pass();
426 load_result
->incoming_messages
.clear();
427 load_result
->outgoing_messages
.clear();
428 LoadGCMStore(gcm_store
.get(), &load_result
);
430 ASSERT_TRUE(load_result
->incoming_messages
.empty());
431 ASSERT_TRUE(load_result
->outgoing_messages
.empty());
434 // Test that per-app message limits are enforced, persisted across restarts,
435 // and updated as messages are removed.
436 TEST_F(GCMStoreImplTest
, PerAppMessageLimits
) {
437 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
438 scoped_ptr
<GCMStore::LoadResult
> load_result
;
439 LoadGCMStore(gcm_store
.get(), &load_result
);
441 // Add the initial (below app limit) messages.
442 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
443 mcs_proto::DataMessageStanza message
;
444 message
.set_from(kAppName
);
445 message
.set_category(kCategoryName
);
446 EXPECT_TRUE(gcm_store
->AddOutgoingMessage(
447 base::IntToString(i
),
449 base::Bind(&GCMStoreImplTest::UpdateCallback
,
450 base::Unretained(this))));
454 // Attempting to add some more should fail.
455 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
456 mcs_proto::DataMessageStanza message
;
457 message
.set_from(kAppName
);
458 message
.set_category(kCategoryName
);
459 EXPECT_FALSE(gcm_store
->AddOutgoingMessage(
460 base::IntToString(i
+ kNumMessagesPerApp
),
462 base::Bind(&GCMStoreImplTest::UpdateCallback
,
463 base::Unretained(this))));
467 // Tear down and restore the database.
468 gcm_store
= BuildGCMStore().Pass();
469 LoadGCMStore(gcm_store
.get(), &load_result
);
471 // Adding more messages should still fail.
472 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
473 mcs_proto::DataMessageStanza message
;
474 message
.set_from(kAppName
);
475 message
.set_category(kCategoryName
);
476 EXPECT_FALSE(gcm_store
->AddOutgoingMessage(
477 base::IntToString(i
+ kNumMessagesPerApp
),
479 base::Bind(&GCMStoreImplTest::UpdateCallback
,
480 base::Unretained(this))));
484 // Remove the existing messages.
485 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
486 gcm_store
->RemoveOutgoingMessage(
487 base::IntToString(i
),
488 base::Bind(&GCMStoreImplTest::UpdateCallback
,
489 base::Unretained(this)));
493 // Successfully add new messages.
494 for (int i
= 0; i
< kNumMessagesPerApp
; ++i
) {
495 mcs_proto::DataMessageStanza message
;
496 message
.set_from(kAppName
);
497 message
.set_category(kCategoryName
);
498 EXPECT_TRUE(gcm_store
->AddOutgoingMessage(
499 base::IntToString(i
+ kNumMessagesPerApp
),
501 base::Bind(&GCMStoreImplTest::UpdateCallback
,
502 base::Unretained(this))));
507 TEST_F(GCMStoreImplTest
, AccountMapping
) {
508 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
509 scoped_ptr
<GCMStore::LoadResult
> load_result
;
510 LoadGCMStore(gcm_store
.get(), &load_result
);
512 // Add account mappings.
513 AccountMapping account_mapping1
;
514 account_mapping1
.account_id
= "account_id_1";
515 account_mapping1
.email
= "account_id_1@gmail.com";
516 account_mapping1
.access_token
= "account_token1";
517 account_mapping1
.status
= AccountMapping::ADDING
;
518 account_mapping1
.status_change_timestamp
= base::Time();
519 account_mapping1
.last_message_id
= "message_1";
521 AccountMapping account_mapping2
;
522 account_mapping2
.account_id
= "account_id_2";
523 account_mapping2
.email
= "account_id_2@gmail.com";
524 account_mapping2
.access_token
= "account_token1";
525 account_mapping2
.status
= AccountMapping::REMOVING
;
526 account_mapping2
.status_change_timestamp
=
527 base::Time::FromInternalValue(1305734521259935LL);
528 account_mapping2
.last_message_id
= "message_2";
530 gcm_store
->AddAccountMapping(
532 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
534 gcm_store
->AddAccountMapping(
536 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
539 gcm_store
= BuildGCMStore().Pass();
540 LoadGCMStore(gcm_store
.get(), &load_result
);
542 EXPECT_EQ(2UL, load_result
->account_mappings
.size());
543 GCMStore::AccountMappings::iterator iter
=
544 load_result
->account_mappings
.begin();
545 EXPECT_EQ(account_mapping1
.account_id
, iter
->account_id
);
546 EXPECT_EQ(account_mapping1
.email
, iter
->email
);
547 EXPECT_TRUE(iter
->access_token
.empty());
548 EXPECT_EQ(AccountMapping::ADDING
, iter
->status
);
549 EXPECT_EQ(account_mapping1
.status_change_timestamp
,
550 iter
->status_change_timestamp
);
551 EXPECT_EQ(account_mapping1
.last_message_id
, iter
->last_message_id
);
553 EXPECT_EQ(account_mapping2
.account_id
, iter
->account_id
);
554 EXPECT_EQ(account_mapping2
.email
, iter
->email
);
555 EXPECT_TRUE(iter
->access_token
.empty());
556 EXPECT_EQ(AccountMapping::REMOVING
, iter
->status
);
557 EXPECT_EQ(account_mapping2
.status_change_timestamp
,
558 iter
->status_change_timestamp
);
559 EXPECT_EQ(account_mapping2
.last_message_id
, iter
->last_message_id
);
561 gcm_store
->RemoveAccountMapping(
562 account_mapping1
.account_id
,
563 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
566 gcm_store
= BuildGCMStore().Pass();
567 LoadGCMStore(gcm_store
.get(), &load_result
);
569 EXPECT_EQ(1UL, load_result
->account_mappings
.size());
570 iter
= load_result
->account_mappings
.begin();
571 EXPECT_EQ(account_mapping2
.account_id
, iter
->account_id
);
572 EXPECT_EQ(account_mapping2
.email
, iter
->email
);
573 EXPECT_TRUE(iter
->access_token
.empty());
574 EXPECT_EQ(AccountMapping::REMOVING
, iter
->status
);
575 EXPECT_EQ(account_mapping2
.status_change_timestamp
,
576 iter
->status_change_timestamp
);
577 EXPECT_EQ(account_mapping2
.last_message_id
, iter
->last_message_id
);
580 TEST_F(GCMStoreImplTest
, HeartbeatInterval
) {
581 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
582 scoped_ptr
<GCMStore::LoadResult
> load_result
;
583 LoadGCMStore(gcm_store
.get(), &load_result
);
585 std::string scope1
= "scope1";
586 std::string scope2
= "scope2";
587 int heartbeat1
= 120 * 1000;
588 int heartbeat2
= 360 * 1000;
590 gcm_store
->AddHeartbeatInterval(
593 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
595 gcm_store
->AddHeartbeatInterval(
598 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
601 gcm_store
= BuildGCMStore().Pass();
602 LoadGCMStore(gcm_store
.get(), &load_result
);
604 EXPECT_EQ(2UL, load_result
->heartbeat_intervals
.size());
605 ASSERT_TRUE(load_result
->heartbeat_intervals
.find(scope1
) !=
606 load_result
->heartbeat_intervals
.end());
607 EXPECT_EQ(heartbeat1
, load_result
->heartbeat_intervals
[scope1
]);
608 ASSERT_TRUE(load_result
->heartbeat_intervals
.find(scope2
) !=
609 load_result
->heartbeat_intervals
.end());
610 EXPECT_EQ(heartbeat2
, load_result
->heartbeat_intervals
[scope2
]);
612 gcm_store
->RemoveHeartbeatInterval(
614 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
617 gcm_store
= BuildGCMStore().Pass();
618 LoadGCMStore(gcm_store
.get(), &load_result
);
620 EXPECT_EQ(1UL, load_result
->heartbeat_intervals
.size());
621 ASSERT_TRUE(load_result
->heartbeat_intervals
.find(scope1
) !=
622 load_result
->heartbeat_intervals
.end());
623 EXPECT_EQ(heartbeat1
, load_result
->heartbeat_intervals
[scope1
]);
626 // When the database is destroyed, all database updates should fail. At the
627 // same time, they per-app message counts should not go up, as failures should
628 // result in decrementing the counts.
629 TEST_F(GCMStoreImplTest
, AddMessageAfterDestroy
) {
630 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
631 scoped_ptr
<GCMStore::LoadResult
> load_result
;
632 LoadGCMStore(gcm_store
.get(), &load_result
);
633 gcm_store
->Destroy(base::Bind(&GCMStoreImplTest::UpdateCallback
,
634 base::Unretained(this)));
637 expected_success_
= false;
638 for (int i
= 0; i
< kNumMessagesPerApp
* 2; ++i
) {
639 mcs_proto::DataMessageStanza message
;
640 message
.set_from(kAppName
);
641 message
.set_category(kCategoryName
);
642 // Because all adds are failing, none should hit the per-app message limits.
643 EXPECT_TRUE(gcm_store
->AddOutgoingMessage(
644 base::IntToString(i
),
646 base::Bind(&GCMStoreImplTest::UpdateCallback
,
647 base::Unretained(this))));
652 TEST_F(GCMStoreImplTest
, ReloadAfterClose
) {
653 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
654 scoped_ptr
<GCMStore::LoadResult
> load_result
;
655 LoadGCMStore(gcm_store
.get(), &load_result
);
660 LoadGCMStore(gcm_store
.get(), &load_result
);
663 TEST_F(GCMStoreImplTest
, LastTokenFetchTime
) {
664 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
665 scoped_ptr
<GCMStore::LoadResult
> load_result
;
666 LoadGCMStore(gcm_store
.get(), &load_result
);
667 EXPECT_EQ(base::Time(), load_result
->last_token_fetch_time
);
669 base::Time last_token_fetch_time
= base::Time::Now();
670 gcm_store
->SetLastTokenFetchTime(
671 last_token_fetch_time
,
672 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
675 gcm_store
= BuildGCMStore().Pass();
676 LoadGCMStore(gcm_store
.get(), &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 LoadGCMStore(gcm_store
.get(), &load_result
);
688 EXPECT_EQ(base::Time(), load_result
->last_token_fetch_time
);
691 TEST_F(GCMStoreImplTest
, InstanceIDData
) {
692 scoped_ptr
<GCMStoreImpl
> gcm_store(BuildGCMStore());
693 scoped_ptr
<GCMStore::LoadResult
> load_result
;
694 LoadGCMStore(gcm_store
.get(), &load_result
);
696 std::string
instance_id_data("Foo");
697 gcm_store
->AddInstanceIDData(
700 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
703 std::string
instance_id_data2("Hello Instance ID");
704 gcm_store
->AddInstanceIDData(
707 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
710 gcm_store
= BuildGCMStore().Pass();
711 LoadGCMStore(gcm_store
.get(), &load_result
);
713 ASSERT_EQ(2u, load_result
->instance_id_data
.size());
714 ASSERT_TRUE(load_result
->instance_id_data
.find(kAppName
) !=
715 load_result
->instance_id_data
.end());
716 ASSERT_TRUE(load_result
->instance_id_data
.find(kAppName2
) !=
717 load_result
->instance_id_data
.end());
718 EXPECT_EQ(instance_id_data
, load_result
->instance_id_data
[kAppName
]);
719 EXPECT_EQ(instance_id_data2
, load_result
->instance_id_data
[kAppName2
]);
721 gcm_store
->RemoveInstanceIDData(
723 base::Bind(&GCMStoreImplTest::UpdateCallback
, base::Unretained(this)));
726 gcm_store
= BuildGCMStore().Pass();
727 LoadGCMStore(gcm_store
.get(), &load_result
);
729 ASSERT_EQ(1u, load_result
->instance_id_data
.size());
730 ASSERT_TRUE(load_result
->instance_id_data
.find(kAppName2
) !=
731 load_result
->instance_id_data
.end());
732 EXPECT_EQ(instance_id_data2
, load_result
->instance_id_data
[kAppName2
]);