Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / google_apis / gcm / engine / gcm_store_impl_unittest.cc
blob66177d261edab2f05b0a1edf29918ba1594de914
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/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"
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";
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 {
44 public:
45 GCMStoreImplTest();
46 ~GCMStoreImplTest() override;
48 scoped_ptr<GCMStoreImpl> BuildGCMStore();
50 std::string GetNextPersistentId();
52 void PumpLoop();
54 void LoadCallback(scoped_ptr<GCMStore::LoadResult>* result_dst,
55 scoped_ptr<GCMStore::LoadResult> result);
56 void UpdateCallback(bool success);
58 protected:
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();
93 run_loop_->Quit();
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));
107 PumpLoop();
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));
122 PumpLoop();
124 gcm_store->SetDeviceCredentials(
125 kDeviceId,
126 kDeviceToken,
127 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
128 PumpLoop();
130 gcm_store = BuildGCMStore().Pass();
131 gcm_store->Load(base::Bind(
132 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
133 PumpLoop();
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));
144 PumpLoop();
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(
152 last_checkin_time,
153 accounts,
154 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
155 PumpLoop();
157 gcm_store = BuildGCMStore().Pass();
158 gcm_store->Load(base::Bind(
159 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
160 PumpLoop();
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(
166 "last_checkin_time",
167 "gibberish",
168 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
169 PumpLoop();
171 gcm_store = BuildGCMStore().Pass();
172 gcm_store->Load(base::Bind(
173 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
174 PumpLoop();
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));
183 PumpLoop();
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(
192 settings,
193 digest,
194 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
195 PumpLoop();
197 gcm_store = BuildGCMStore().Pass();
198 gcm_store->Load(base::Bind(
199 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
200 PumpLoop();
202 ASSERT_EQ(settings, load_result->gservices_settings);
203 ASSERT_EQ(digest, load_result->gservices_digest);
205 // Remove some, and add some.
206 settings.clear();
207 settings["checkin_interval"] = "54321";
208 settings["registration_url"] = "http://registration.google.com";
209 digest = "digest2";
211 gcm_store->SetGServicesSettings(
212 settings,
213 digest,
214 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
215 PumpLoop();
217 gcm_store = BuildGCMStore().Pass();
218 gcm_store->Load(base::Bind(
219 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
220 PumpLoop();
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));
231 PumpLoop();
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(
238 "app1",
239 registration1,
240 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
241 PumpLoop();
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(
249 "app2",
250 registration2,
251 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
252 PumpLoop();
254 gcm_store = BuildGCMStore().Pass();
255 gcm_store->Load(base::Bind(
256 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
257 PumpLoop();
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(
278 "app2",
279 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
280 PumpLoop();
282 gcm_store = BuildGCMStore().Pass();
283 gcm_store->Load(base::Bind(
284 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
285 PumpLoop();
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));
304 PumpLoop();
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)));
312 PumpLoop();
315 gcm_store = BuildGCMStore().Pass();
316 gcm_store->Load(base::Bind(
317 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
318 PumpLoop();
320 ASSERT_EQ(persistent_ids, load_result->incoming_messages);
321 ASSERT_TRUE(load_result->outgoing_messages.empty());
323 gcm_store->RemoveIncomingMessages(
324 persistent_ids,
325 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
326 PumpLoop();
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));
332 PumpLoop();
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));
345 PumpLoop();
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(),
356 MCSMessage(message),
357 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
358 PumpLoop();
361 gcm_store = BuildGCMStore().Pass();
362 gcm_store->Load(base::Bind(
363 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
364 PumpLoop();
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(
379 persistent_ids,
380 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
381 PumpLoop();
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));
387 PumpLoop();
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));
399 PumpLoop();
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)));
408 PumpLoop();
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(),
415 MCSMessage(message),
416 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
417 PumpLoop();
420 gcm_store = BuildGCMStore().Pass();
421 gcm_store->Load(base::Bind(
422 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
423 PumpLoop();
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(
438 persistent_ids,
439 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
440 PumpLoop();
441 gcm_store->RemoveOutgoingMessages(
442 persistent_ids,
443 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
444 PumpLoop();
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));
451 PumpLoop();
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),
464 &load_result));
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),
473 MCSMessage(message),
474 base::Bind(&GCMStoreImplTest::UpdateCallback,
475 base::Unretained(this))));
476 PumpLoop();
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),
486 MCSMessage(message),
487 base::Bind(&GCMStoreImplTest::UpdateCallback,
488 base::Unretained(this))));
489 PumpLoop();
492 // Tear down and restore the database.
493 gcm_store = BuildGCMStore().Pass();
494 gcm_store->Load(base::Bind(&GCMStoreImplTest::LoadCallback,
495 base::Unretained(this),
496 &load_result));
497 PumpLoop();
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),
506 MCSMessage(message),
507 base::Bind(&GCMStoreImplTest::UpdateCallback,
508 base::Unretained(this))));
509 PumpLoop();
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)));
518 PumpLoop();
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),
528 MCSMessage(message),
529 base::Bind(&GCMStoreImplTest::UpdateCallback,
530 base::Unretained(this))));
531 PumpLoop();
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(
560 account_mapping1,
561 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
562 PumpLoop();
563 gcm_store->AddAccountMapping(
564 account_mapping2,
565 base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
566 PumpLoop();
568 gcm_store = BuildGCMStore().Pass();
569 gcm_store->Load(base::Bind(
570 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
571 PumpLoop();
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);
583 ++iter;
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)));
595 PumpLoop();
597 gcm_store = BuildGCMStore().Pass();
598 gcm_store->Load(base::Bind(
599 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
600 PumpLoop();
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),
621 &load_result));
622 PumpLoop();
623 gcm_store->Destroy(base::Bind(&GCMStoreImplTest::UpdateCallback,
624 base::Unretained(this)));
625 PumpLoop();
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),
635 MCSMessage(message),
636 base::Bind(&GCMStoreImplTest::UpdateCallback,
637 base::Unretained(this))));
638 PumpLoop();
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),
647 &load_result));
648 PumpLoop();
650 gcm_store->Close();
651 PumpLoop();
653 gcm_store->Load(base::Bind(&GCMStoreImplTest::LoadCallback,
654 base::Unretained(this),
655 &load_result));
656 PumpLoop();
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));
664 PumpLoop();
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)));
671 PumpLoop();
673 gcm_store = BuildGCMStore().Pass();
674 gcm_store->Load(base::Bind(
675 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
676 PumpLoop();
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 gcm_store->Load(base::Bind(
688 &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
689 PumpLoop();
690 EXPECT_EQ(base::Time(), load_result->last_token_fetch_time);
693 } // namespace
695 } // namespace gcm