1 // Copyright (c) 2012 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.
7 #include "base/gtest_prod_util.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/browser/notifications/notification.h"
13 #include "chrome/browser/notifications/notification_test_util.h"
14 #include "chrome/browser/notifications/notification_ui_manager.h"
15 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
16 #include "chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h"
17 #include "chrome/browser/notifications/sync_notifier/synced_notification.h"
18 #include "chrome/browser/prefs/browser_prefs.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/test/base/testing_pref_service_syncable.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "components/user_prefs/pref_registry_syncable.h"
24 #include "content/public/test/test_browser_thread_bundle.h"
25 #include "sync/api/sync_change.h"
26 #include "sync/api/sync_change_processor.h"
27 #include "sync/api/sync_error_factory.h"
28 #include "sync/api/sync_error_factory_mock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "ui/message_center/message_center_util.h"
32 using sync_pb::SyncedNotificationSpecifics;
33 using sync_pb::EntitySpecifics;
34 using syncer::SyncData;
35 using syncer::SyncChange;
36 using syncer::SyncChangeList;
37 using syncer::SyncDataList;
38 using syncer::SYNCED_NOTIFICATIONS;
39 using notifier::SyncedNotification;
40 using notifier::ChromeNotifierService;
44 // Extract notification id from syncer::SyncData.
45 std::string GetNotificationId(const SyncData& sync_data) {
46 SyncedNotificationSpecifics specifics = sync_data.GetSpecifics().
47 synced_notification();
49 return specifics.coalesced_notification().key();
56 // Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
58 class TestChangeProcessor : public syncer::SyncChangeProcessor {
60 TestChangeProcessor() { }
61 virtual ~TestChangeProcessor() { }
63 // Store a copy of all the changes passed in so we can examine them later.
64 virtual syncer::SyncError ProcessSyncChanges(
65 const tracked_objects::Location& from_here,
66 const SyncChangeList& change_list) OVERRIDE {
68 for (SyncChangeList::const_iterator iter = change_list.begin();
69 iter != change_list.end(); ++iter) {
70 // Put the data into the change tracking map.
71 change_map_[GetNotificationId(iter->sync_data())] = *iter;
74 return syncer::SyncError();
77 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
79 return syncer::SyncDataList();
82 size_t change_list_size() { return change_map_.size(); }
84 bool ContainsId(const std::string& id) {
85 return change_map_.find(id) != change_map_.end();
88 SyncChange GetChangeById(const std::string& id) {
89 EXPECT_TRUE(ContainsId(id));
90 return change_map_[id];
94 // Track the changes received in ProcessSyncChanges.
95 std::map<std::string, SyncChange> change_map_;
97 DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
100 class SyncChangeProcessorDelegate : public syncer::SyncChangeProcessor {
102 explicit SyncChangeProcessorDelegate(SyncChangeProcessor* recipient)
103 : recipient_(recipient) {
104 EXPECT_TRUE(recipient_);
106 virtual ~SyncChangeProcessorDelegate() {}
108 // syncer::SyncChangeProcessor implementation.
109 virtual syncer::SyncError ProcessSyncChanges(
110 const tracked_objects::Location& from_here,
111 const SyncChangeList& change_list) OVERRIDE {
112 return recipient_->ProcessSyncChanges(from_here, change_list);
115 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
117 return recipient_->GetAllSyncData(type);
121 // The recipient of all sync changes.
122 SyncChangeProcessor* recipient_;
124 DISALLOW_COPY_AND_ASSIGN(SyncChangeProcessorDelegate);
127 class ChromeNotifierServiceTest : public testing::Test {
129 ChromeNotifierServiceTest()
130 : sync_processor_(new TestChangeProcessor),
131 sync_processor_delegate_(new SyncChangeProcessorDelegate(
132 sync_processor_.get())) {}
133 virtual ~ChromeNotifierServiceTest() {}
135 // Methods from testing::Test.
136 virtual void SetUp() {
137 // Prevent test code from trying to go to the network.
138 ChromeNotifierService::set_avoid_bitmap_fetching_for_test(true);
139 notification_manager_.reset(new StubNotificationUIManager(GURL(
140 kSyncedNotificationsWelcomeOrigin)));
142 // Set up a profile for the unit tests to use.
143 profile_.reset(new TestingProfile());
146 virtual void TearDown() {
147 notification_manager_.reset();
150 StubNotificationUIManager* notification_manager() {
151 return notification_manager_.get();
154 TestChangeProcessor* processor() {
155 return static_cast<TestChangeProcessor*>(sync_processor_.get());
158 scoped_ptr<syncer::SyncChangeProcessor> PassProcessor() {
159 return sync_processor_delegate_.Pass();
162 SyncedNotification* CreateNotification(
163 const std::string& title,
164 const std::string& text,
165 const std::string& app_icon_url,
166 const std::string& image_url,
167 const std::string& app_id,
168 const std::string& key,
169 sync_pb::CoalescedSyncedNotification_ReadState read_state) {
170 SyncData sync_data = CreateSyncData(title, text, app_icon_url, image_url,
171 app_id, key, read_state);
172 // Set enough fields in sync_data, including specifics, for our tests
174 return new SyncedNotification(sync_data);
177 // Helper to create syncer::SyncChange.
178 static SyncChange CreateSyncChange(
179 SyncChange::SyncChangeType type,
180 SyncedNotification* notification) {
181 // Take control of the notification to clean it up after we create data
183 scoped_ptr<SyncedNotification> scoped_notification(notification);
187 ChromeNotifierService::CreateSyncDataFromNotification(*notification));
191 scoped_ptr<TestingProfile> profile_;
194 scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
195 scoped_ptr<syncer::SyncChangeProcessor> sync_processor_delegate_;
196 scoped_ptr<StubNotificationUIManager> notification_manager_;
197 content::TestBrowserThreadBundle thread_bundle_;
199 DISALLOW_COPY_AND_ASSIGN(ChromeNotifierServiceTest);
202 // TODO(petewil): Add more tests as I add functionalty. Tests are based on
203 // chrome/browser/extensions/app_notification_manager_sync_unittest.cc
205 // Create a Notification, convert it to SyncData and convert it back.
206 TEST_F(ChromeNotifierServiceTest, NotificationToSyncDataToNotification) {
207 scoped_ptr<SyncedNotification> notification1(
208 CreateNotification(kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1,
211 ChromeNotifierService::CreateSyncDataFromNotification(*notification1);
212 scoped_ptr<SyncedNotification> notification2(
213 ChromeNotifierService::CreateNotificationFromSyncData(sync_data));
214 EXPECT_TRUE(notification2.get());
215 EXPECT_TRUE(notification1->EqualsIgnoringReadState(*notification2));
216 EXPECT_EQ(notification1->GetReadState(), notification2->GetReadState());
219 // Model assocation: We have no local data, and no remote data.
220 TEST_F(ChromeNotifierServiceTest, ModelAssocBothEmpty) {
222 ChromeNotifierService notifier(profile_.get(), notification_manager());
224 notifier.MergeDataAndStartSyncing(
225 SYNCED_NOTIFICATIONS,
226 SyncDataList(), // Empty.
228 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
230 EXPECT_EQ(0U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
231 EXPECT_EQ(0U, processor()->change_list_size());
234 // Process sync changes when there is no local data.
235 TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesEmptyModel) {
236 // We initially have no data.
237 ChromeNotifierService notifier(profile_.get(), notification_manager());
238 notifier.set_avoid_bitmap_fetching_for_test(true);
240 notifier.MergeDataAndStartSyncing(
241 SYNCED_NOTIFICATIONS,
244 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
246 // Set up a bunch of ADDs.
247 SyncChangeList changes;
248 changes.push_back(CreateSyncChange(
249 SyncChange::ACTION_ADD, CreateNotification(
250 kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread)));
251 changes.push_back(CreateSyncChange(
252 SyncChange::ACTION_ADD, CreateNotification(
253 kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread)));
254 changes.push_back(CreateSyncChange(
255 SyncChange::ACTION_ADD, CreateNotification(
256 kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kUnread)));
258 notifier.ProcessSyncChanges(FROM_HERE, changes);
260 EXPECT_EQ(3U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
261 // TODO(petewil): verify that the list entries have expected values to make
262 // this test more robust.
265 // Process sync changes when there is no local data.
266 TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesNonEmptyModel) {
267 ChromeNotifierService notifier(profile_.get(), notification_manager());
268 notifier.set_avoid_bitmap_fetching_for_test(true);
270 // Create some local fake data.
271 scoped_ptr<SyncedNotification> n1(CreateNotification(
272 kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
273 notifier.AddForTest(n1.Pass());
274 scoped_ptr<SyncedNotification> n2(CreateNotification(
275 kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
276 notifier.AddForTest(n2.Pass());
277 scoped_ptr<SyncedNotification> n3(CreateNotification(
278 kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kUnread));
279 notifier.AddForTest(n3.Pass());
281 notifier.MergeDataAndStartSyncing(
282 SYNCED_NOTIFICATIONS,
285 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
287 // Set up some ADDs, some UPDATES, and some DELETEs
288 SyncChangeList changes;
289 changes.push_back(CreateSyncChange(
290 SyncChange::ACTION_ADD, CreateNotification(
291 kTitle4, kText4, kIconUrl4, kImageUrl4, kAppId4, kKey4, kUnread)));
292 changes.push_back(CreateSyncChange(
293 SyncChange::ACTION_UPDATE, CreateNotification(
294 kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kRead)));
295 changes.push_back(CreateSyncChange(
296 SyncChange::ACTION_DELETE, CreateNotification(
297 kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kDismissed)));
299 // Simulate incoming new notifications at runtime.
300 notifier.ProcessSyncChanges(FROM_HERE, changes);
302 // We should find notifications 1, 2, and 4, but not 3.
303 EXPECT_EQ(3U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
304 EXPECT_TRUE(notifier.FindNotificationById(kKey1));
305 EXPECT_TRUE(notifier.FindNotificationById(kKey2));
306 EXPECT_FALSE(notifier.FindNotificationById(kKey3));
307 EXPECT_TRUE(notifier.FindNotificationById(kKey4));
309 // Verify that the first run preference is now set to false.
310 bool first_run = notifier.profile()->GetPrefs()->GetBoolean(
311 prefs::kSyncedNotificationFirstRun);
312 EXPECT_NE(true, first_run);
315 // Process sync changes that arrive before the change they are supposed to
317 TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesOutOfOrder) {
318 ChromeNotifierService notifier(profile_.get(), notification_manager());
319 notifier.set_avoid_bitmap_fetching_for_test(true);
321 // Create some local fake data.
322 scoped_ptr<SyncedNotification> n1(CreateNotification(
323 kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
324 notifier.AddForTest(n1.Pass());
325 scoped_ptr<SyncedNotification> n2(CreateNotification(
326 kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
327 notifier.AddForTest(n2.Pass());
328 scoped_ptr<SyncedNotification> n3(CreateNotification(
329 kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kUnread));
330 notifier.AddForTest(n3.Pass());
332 notifier.MergeDataAndStartSyncing(
333 SYNCED_NOTIFICATIONS,
336 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
338 SyncChangeList changes;
339 // UPDATE a notification we have not seen an add for.
340 changes.push_back(CreateSyncChange(
341 SyncChange::ACTION_UPDATE, CreateNotification(
342 kTitle4, kText4, kIconUrl4, kImageUrl4, kAppId4, kKey4, kUnread)));
343 // ADD a notification that we already have.
344 changes.push_back(CreateSyncChange(
345 SyncChange::ACTION_ADD, CreateNotification(
346 kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kRead)));
347 // DELETE a notification we have not seen yet.
348 changes.push_back(CreateSyncChange(
349 SyncChange::ACTION_DELETE, CreateNotification(
350 kTitle5, kText5, kIconUrl5, kImageUrl5, kAppId5, kKey5, kDismissed)));
352 // Simulate incoming new notifications at runtime.
353 notifier.ProcessSyncChanges(FROM_HERE, changes);
355 // We should find notifications 1, 2, 3, and 4, but not 5.
356 EXPECT_EQ(4U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
357 EXPECT_TRUE(notifier.FindNotificationById(kKey1));
358 EXPECT_TRUE(notifier.FindNotificationById(kKey2));
359 EXPECT_TRUE(notifier.FindNotificationById(kKey3));
360 EXPECT_TRUE(notifier.FindNotificationById(kKey4));
361 EXPECT_FALSE(notifier.FindNotificationById(kKey5));
365 // Model has some notifications, some of them are local only. Sync has some
366 // notifications. No items match up.
367 TEST_F(ChromeNotifierServiceTest, LocalRemoteBothNonEmptyNoOverlap) {
368 ChromeNotifierService notifier(profile_.get(), notification_manager());
369 notifier.set_avoid_bitmap_fetching_for_test(true);
371 // Create some local fake data.
372 scoped_ptr<SyncedNotification> n1(CreateNotification(
373 kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
374 notifier.AddForTest(n1.Pass());
375 scoped_ptr<SyncedNotification> n2(CreateNotification(
376 kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
377 notifier.AddForTest(n2.Pass());
378 scoped_ptr<SyncedNotification> n3(CreateNotification(
379 kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kUnread));
380 notifier.AddForTest(n3.Pass());
382 // Create some remote fake data.
383 SyncDataList initial_data;
384 initial_data.push_back(CreateSyncData(kTitle4, kText4, kIconUrl4, kImageUrl4,
385 kAppId4, kKey4, kUnread));
386 initial_data.push_back(CreateSyncData(kTitle5, kText5, kIconUrl5, kImageUrl5,
387 kAppId5, kKey5, kUnread));
388 initial_data.push_back(CreateSyncData(kTitle6, kText6, kIconUrl6, kImageUrl6,
389 kAppId6, kKey6, kUnread));
390 initial_data.push_back(CreateSyncData(kTitle7, kText7, kIconUrl7, kImageUrl7,
391 kAppId7, kKey7, kUnread));
393 // Merge the local and remote data.
394 notifier.MergeDataAndStartSyncing(
395 SYNCED_NOTIFICATIONS,
398 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
400 // Ensure the local store now has all local and remote notifications.
401 EXPECT_EQ(7U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
402 EXPECT_TRUE(notifier.FindNotificationById(kKey1));
403 EXPECT_TRUE(notifier.FindNotificationById(kKey2));
404 EXPECT_TRUE(notifier.FindNotificationById(kKey3));
405 EXPECT_TRUE(notifier.FindNotificationById(kKey4));
406 EXPECT_TRUE(notifier.FindNotificationById(kKey5));
407 EXPECT_TRUE(notifier.FindNotificationById(kKey6));
408 EXPECT_TRUE(notifier.FindNotificationById(kKey7));
410 // Test the type conversion and construction functions.
411 for (SyncDataList::const_iterator iter = initial_data.begin();
412 iter != initial_data.end(); ++iter) {
413 scoped_ptr<SyncedNotification> notification1(
414 ChromeNotifierService::CreateNotificationFromSyncData(*iter));
415 // TODO(petewil): Revisit this when we add version info to notifications.
416 const std::string& key = notification1->GetKey();
417 const SyncedNotification* notification2 =
418 notifier.FindNotificationById(key);
419 EXPECT_TRUE(NULL != notification2);
420 EXPECT_TRUE(notification1->EqualsIgnoringReadState(*notification2));
421 EXPECT_EQ(notification1->GetReadState(), notification2->GetReadState());
423 EXPECT_TRUE(notifier.FindNotificationById(kKey1));
424 EXPECT_TRUE(notifier.FindNotificationById(kKey2));
425 EXPECT_TRUE(notifier.FindNotificationById(kKey3));
428 // Test the local store having the read bit unset, the remote store having
430 TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyReadMismatch1) {
431 ChromeNotifierService notifier(profile_.get(), notification_manager());
432 notifier.set_avoid_bitmap_fetching_for_test(true);
434 // Create some local fake data.
435 scoped_ptr<SyncedNotification> n1(CreateNotification(
436 kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
437 notifier.AddForTest(n1.Pass());
438 scoped_ptr<SyncedNotification> n2(CreateNotification(
439 kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
440 notifier.AddForTest(n2.Pass());
442 // Create some remote fake data, item 1 matches except for the read state.
443 syncer::SyncDataList initial_data;
444 initial_data.push_back(CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
445 kAppId1, kKey1, kDismissed));
446 // Merge the local and remote data.
447 notifier.MergeDataAndStartSyncing(
448 syncer::SYNCED_NOTIFICATIONS,
451 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
453 // Ensure the local store still has only two notifications, and the read
454 // state of the first is now read.
455 EXPECT_EQ(2U, notifier.GetAllSyncData(syncer::SYNCED_NOTIFICATIONS).size());
456 SyncedNotification* notification1 =
457 notifier.FindNotificationById(kKey1);
458 EXPECT_FALSE(NULL == notification1);
459 EXPECT_EQ(SyncedNotification::kDismissed, notification1->GetReadState());
460 EXPECT_TRUE(notifier.FindNotificationById(kKey2));
461 EXPECT_FALSE(notifier.FindNotificationById(kKey3));
463 // Make sure that the notification manager was told to dismiss the
465 EXPECT_EQ(std::string(kKey1), notification_manager()->dismissed_id());
467 // Ensure no new data will be sent to the remote store for notification1.
468 EXPECT_EQ(0U, processor()->change_list_size());
469 EXPECT_FALSE(processor()->ContainsId(kKey1));
472 // Test when the local store has the read bit set, and the remote store has
474 TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyReadMismatch2) {
475 ChromeNotifierService notifier(profile_.get(), notification_manager());
476 notifier.set_avoid_bitmap_fetching_for_test(true);
478 // Create some local fake data.
479 scoped_ptr<SyncedNotification> n1(CreateNotification(
480 kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kDismissed));
481 notifier.AddForTest(n1.Pass());
482 scoped_ptr<SyncedNotification> n2(CreateNotification(
483 kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
484 notifier.AddForTest(n2.Pass());
486 // Create some remote fake data, item 1 matches except for the read state.
487 syncer::SyncDataList initial_data;
488 initial_data.push_back(CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
489 kAppId1, kKey1, kUnread));
490 // Merge the local and remote data.
491 notifier.MergeDataAndStartSyncing(
492 syncer::SYNCED_NOTIFICATIONS,
495 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
497 // Ensure the local store still has only two notifications, and the read
498 // state of the first is now read.
499 EXPECT_EQ(2U, notifier.GetAllSyncData(syncer::SYNCED_NOTIFICATIONS).size());
500 SyncedNotification* notification1 =
501 notifier.FindNotificationById(kKey1);
502 EXPECT_FALSE(NULL == notification1);
503 EXPECT_EQ(SyncedNotification::kDismissed, notification1->GetReadState());
504 EXPECT_TRUE(notifier.FindNotificationById(kKey2));
505 EXPECT_FALSE(notifier.FindNotificationById(kKey3));
507 // Ensure the new data will be sent to the remote store for notification1.
508 EXPECT_EQ(1U, processor()->change_list_size());
509 EXPECT_TRUE(processor()->ContainsId(kKey1));
510 EXPECT_EQ(SyncChange::ACTION_UPDATE, processor()->GetChangeById(
511 kKey1).change_type());
514 // We have a notification in the local store, we get an updated version
515 // of the same notification remotely, it should take precedence.
516 TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyWithUpdate) {
517 ChromeNotifierService notifier(profile_.get(), notification_manager());
519 // Create some local fake data.
520 scoped_ptr<SyncedNotification> n1(CreateNotification(
521 kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kDismissed));
522 notifier.AddForTest(n1.Pass());
524 // Create some remote fake data, item 1 matches the ID, but has different data
525 syncer::SyncDataList initial_data;
526 initial_data.push_back(CreateSyncData(kTitle2, kText2, kIconUrl2, kImageUrl2,
527 kAppId1, kKey1, kUnread));
528 // Merge the local and remote data.
529 notifier.MergeDataAndStartSyncing(
530 syncer::SYNCED_NOTIFICATIONS,
533 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
535 // Ensure the local store still has only one notification
536 EXPECT_EQ(1U, notifier.GetAllSyncData(syncer::SYNCED_NOTIFICATIONS).size());
537 SyncedNotification* notification1 =
538 notifier.FindNotificationById(kKey1);
540 EXPECT_FALSE(NULL == notification1);
541 EXPECT_EQ(SyncedNotification::kUnread, notification1->GetReadState());
542 EXPECT_EQ(std::string(kTitle2), notification1->GetTitle());
544 // Ensure no new data will be sent to the remote store for notification1.
545 EXPECT_EQ(0U, processor()->change_list_size());
546 EXPECT_FALSE(processor()->ContainsId(kKey1));
549 TEST_F(ChromeNotifierServiceTest, ServiceEnabledTest) {
550 ChromeNotifierService notifier(profile_.get(), notification_manager());
551 std::set<std::string>::iterator iter;
552 std::string first_synced_notification_service_id(
553 kFirstSyncedNotificationServiceId);
555 // Create some local fake data.
556 scoped_ptr<SyncedNotification> n1(CreateNotification(
557 kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
558 notifier.AddForTest(n1.Pass());
560 // Enable the service and ensure the service is in the list.
561 // Initially the service starts in the disabled state.
562 notifier.OnSyncedNotificationServiceEnabled(kFirstSyncedNotificationServiceId,
564 iter = find(notifier.enabled_sending_services_.begin(),
565 notifier.enabled_sending_services_.end(),
566 first_synced_notification_service_id);
567 EXPECT_NE(notifier.enabled_sending_services_.end(), iter);
568 // TODO(petewil): Verify Display gets called too.
570 // Disable the service and ensure it is gone from the list and the
571 // notification_manager.
572 notifier.OnSyncedNotificationServiceEnabled(kFirstSyncedNotificationServiceId,
574 iter = find(notifier.enabled_sending_services_.begin(),
575 notifier.enabled_sending_services_.end(),
576 first_synced_notification_service_id);
577 EXPECT_EQ(notifier.enabled_sending_services_.end(), iter);
578 EXPECT_EQ(notification_manager()->dismissed_id(), std::string(kKey1));
582 TEST_F(ChromeNotifierServiceTest, AddNewSendingServicesTest) {
583 // This test will see if we get a new sending service after the first
584 // notification for that service.
585 ChromeNotifierService notifier(profile_.get(), notification_manager());
586 notifier.set_avoid_bitmap_fetching_for_test(true);
588 // We initially have no data.
589 EXPECT_EQ(0U, notifier.enabled_sending_services_.size());
590 EXPECT_EQ(0U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
593 SyncChangeList changes;
595 CreateSyncChange(SyncChange::ACTION_ADD,
596 CreateNotification(kTitle1,
600 kFirstSyncedNotificationServiceId,
604 notifier.ProcessSyncChanges(FROM_HERE, changes);
606 EXPECT_EQ(1U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
608 // Verify that the first synced notification service is enabled in memory.
609 std::set<std::string>::iterator iter;
610 std::string first_notification_service_id(kFirstSyncedNotificationServiceId);
611 iter = find(notifier.enabled_sending_services_.begin(),
612 notifier.enabled_sending_services_.end(),
613 first_notification_service_id);
615 EXPECT_NE(notifier.enabled_sending_services_.end(), iter);
617 // We should have gotten the synced notification and a welcome notification.
618 EXPECT_EQ(2U, notification_manager()->added_notifications());
619 EXPECT_TRUE(notification_manager()->welcomed());
623 CreateSyncChange(SyncChange::ACTION_ADD,
624 CreateNotification(kTitle2,
628 kFirstSyncedNotificationServiceId,
631 notifier.ProcessSyncChanges(FROM_HERE, changes);
633 // But adding another notification should not cause another welcome.
634 EXPECT_EQ(3U, notification_manager()->added_notifications());
637 TEST_F(ChromeNotifierServiceTest, CheckInitializedServicesTest) {
638 // This test will see if we get a new sending service after the first
639 // notification for that service.
640 ChromeNotifierService notifier(profile_.get(), notification_manager());
641 notifier.set_avoid_bitmap_fetching_for_test(true);
643 // Initialize but do not enable the sending service.
644 notifier.initialized_sending_services_.insert(
645 kFirstSyncedNotificationServiceId);
646 ASSERT_EQ(0U, notifier.enabled_sending_services_.size());
647 ASSERT_EQ(1U, notifier.initialized_sending_services_.size());
649 // We initially have no data.
650 EXPECT_EQ(0U, notifier.enabled_sending_services_.size());
651 EXPECT_EQ(0U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
654 std::string first_synced_notification_service_id(
655 kFirstSyncedNotificationServiceId);
657 SyncChangeList changes;
659 CreateSyncChange(SyncChange::ACTION_ADD,
660 CreateNotification(kTitle1,
664 kFirstSyncedNotificationServiceId,
668 notifier.ProcessSyncChanges(FROM_HERE, changes);
670 // Since we added to |initialized_sending_services_| before receiving the
671 // synced notification, we should not have enabled this service while
672 // processing the sync change.
673 EXPECT_EQ(0U, notifier.enabled_sending_services_.size());
674 EXPECT_EQ(0U, notification_manager()->added_notifications());
677 TEST_F(ChromeNotifierServiceTest, CheckFindAppInfo) {
678 ChromeNotifierService notifier(profile_.get(), notification_manager());
679 notifier.set_avoid_bitmap_fetching_for_test(true);
681 SyncedNotificationAppInfo* app_info =
682 notifier.FindAppInfo(kFirstSyncedNotificationServiceId);
683 EXPECT_TRUE(app_info != NULL);
686 } // namespace notifier