Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / google_apis / gcm / engine / gcm_store_impl_unittest.cc
blob9b748552faffbfb07d6ab03ec4f76281a9ce2b2b
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"
7 #include <string>
8 #include <vector>
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"
24 namespace gcm {
26 namespace {
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 {
45 public:
46 GCMStoreImplTest();
47 ~GCMStoreImplTest() override;
49 scoped_ptr<GCMStoreImpl> BuildGCMStore();
50 void LoadGCMStore(
51 GCMStoreImpl* gcm_store, scoped_ptr<GCMStore::LoadResult>* result_dst);
53 std::string GetNextPersistentId();
55 void PumpLoop();
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);
63 protected:
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")),
87 task_runner_,
88 make_scoped_ptr<Encryptor>(new FakeEncryptor)));
91 void GCMStoreImplTest::LoadGCMStore(
92 GCMStoreImpl* gcm_store, scoped_ptr<GCMStore::LoadResult>* result_dst) {
93 gcm_store->Load(
94 GCMStore::CREATE_IF_MISSING,
95 base::Bind(&GCMStoreImplTest::LoadCallback,
96 base::Unretained(this),
97 result_dst));
98 PumpLoop();
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;
142 gcm_store->Load(
143 GCMStore::DO_NOT_CREATE,
144 base::Bind(&GCMStoreImplTest::LoadWithoutCheckCallback,
145 base::Unretained(this),
146 &load_result));
147 PumpLoop();
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(
159 kDeviceId,
160 kDeviceToken,
161 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
162 PumpLoop();
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(
182 last_checkin_time,
183 accounts,
184 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
185 PumpLoop();
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(
194 "last_checkin_time",
195 "gibberish",
196 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
197 PumpLoop();
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(
216 settings,
217 digest,
218 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
219 PumpLoop();
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.
228 settings.clear();
229 settings["checkin_interval"] = "54321";
230 settings["registration_url"] = "http://registration.google.com";
231 digest = "digest2";
233 gcm_store->SetGServicesSettings(
234 settings,
235 digest,
236 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
237 PumpLoop();
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(
254 kAppName,
255 registration,
256 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
257 PumpLoop();
259 // Add one registration with multiple senders.
260 std::string registration2 = "sender1,sender2=registration2";
261 gcm_store->AddRegistration(
262 kAppName2,
263 registration2,
264 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
265 PumpLoop();
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(
279 kAppName2,
280 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
281 PumpLoop();
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)));
305 PumpLoop();
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(
315 persistent_ids,
316 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
317 PumpLoop();
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(),
343 MCSMessage(message),
344 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
345 PumpLoop();
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(
364 persistent_ids,
365 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
366 PumpLoop();
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)));
389 PumpLoop();
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(),
396 MCSMessage(message),
397 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
398 PumpLoop();
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(
417 persistent_ids,
418 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
419 PumpLoop();
420 gcm_store->RemoveOutgoingMessages(
421 persistent_ids,
422 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
423 PumpLoop();
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),
448 MCSMessage(message),
449 base::Bind(&GCMStoreImplTest::UpdateCallback,
450 base::Unretained(this))));
451 PumpLoop();
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),
461 MCSMessage(message),
462 base::Bind(&GCMStoreImplTest::UpdateCallback,
463 base::Unretained(this))));
464 PumpLoop();
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),
478 MCSMessage(message),
479 base::Bind(&GCMStoreImplTest::UpdateCallback,
480 base::Unretained(this))));
481 PumpLoop();
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)));
490 PumpLoop();
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),
500 MCSMessage(message),
501 base::Bind(&GCMStoreImplTest::UpdateCallback,
502 base::Unretained(this))));
503 PumpLoop();
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(
531 account_mapping1,
532 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
533 PumpLoop();
534 gcm_store->AddAccountMapping(
535 account_mapping2,
536 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
537 PumpLoop();
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);
552 ++iter;
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)));
564 PumpLoop();
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(
591 scope1,
592 heartbeat1,
593 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
594 PumpLoop();
595 gcm_store->AddHeartbeatInterval(
596 scope2,
597 heartbeat2,
598 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
599 PumpLoop();
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(
613 scope2,
614 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
615 PumpLoop();
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)));
635 PumpLoop();
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),
645 MCSMessage(message),
646 base::Bind(&GCMStoreImplTest::UpdateCallback,
647 base::Unretained(this))));
648 PumpLoop();
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);
657 gcm_store->Close();
658 PumpLoop();
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)));
673 PumpLoop();
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",
682 "gibberish",
683 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
684 PumpLoop();
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(
698 kAppName,
699 instance_id_data,
700 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
701 PumpLoop();
703 std::string instance_id_data2("Hello Instance ID");
704 gcm_store->AddInstanceIDData(
705 kAppName2,
706 instance_id_data2,
707 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
708 PumpLoop();
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(
722 kAppName,
723 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
724 PumpLoop();
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]);
735 } // namespace
737 } // namespace gcm