5dddca5be2f4328cdcb018122fbe1b4c99d3cf87
[platform/framework/web/crosswalk.git] / src / chrome / browser / notifications / sync_notifier / chrome_notifier_service_unittest.cc
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.
4
5 #include <map>
6
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"
31
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;
41
42 namespace {
43
44 // Extract notification id from syncer::SyncData.
45 std::string GetNotificationId(const SyncData& sync_data) {
46   SyncedNotificationSpecifics specifics = sync_data.GetSpecifics().
47       synced_notification();
48
49   return specifics.coalesced_notification().key();
50 }
51
52 }  // namespace
53
54 namespace notifier {
55
56 // Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
57 // back up to Sync.
58 class TestChangeProcessor : public syncer::SyncChangeProcessor {
59  public:
60   TestChangeProcessor() { }
61   virtual ~TestChangeProcessor() { }
62
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 {
67     change_map_.clear();
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;
72     }
73
74     return syncer::SyncError();
75   }
76
77   virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
78       OVERRIDE {
79     return syncer::SyncDataList();
80   }
81
82   size_t change_list_size() { return change_map_.size(); }
83
84   bool ContainsId(const std::string& id) {
85     return change_map_.find(id) != change_map_.end();
86   }
87
88   SyncChange GetChangeById(const std::string& id) {
89     EXPECT_TRUE(ContainsId(id));
90     return change_map_[id];
91   }
92
93  private:
94   // Track the changes received in ProcessSyncChanges.
95   std::map<std::string, SyncChange> change_map_;
96
97   DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
98 };
99
100 class SyncChangeProcessorDelegate : public syncer::SyncChangeProcessor {
101  public:
102   explicit SyncChangeProcessorDelegate(SyncChangeProcessor* recipient)
103       : recipient_(recipient) {
104     EXPECT_TRUE(recipient_);
105   }
106   virtual ~SyncChangeProcessorDelegate() {}
107
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);
113   }
114
115   virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
116       OVERRIDE {
117     return recipient_->GetAllSyncData(type);
118   }
119
120  private:
121   // The recipient of all sync changes.
122   SyncChangeProcessor* recipient_;
123
124   DISALLOW_COPY_AND_ASSIGN(SyncChangeProcessorDelegate);
125 };
126
127 class ChromeNotifierServiceTest : public testing::Test {
128  public:
129   ChromeNotifierServiceTest()
130       : sync_processor_(new TestChangeProcessor),
131         sync_processor_delegate_(new SyncChangeProcessorDelegate(
132             sync_processor_.get())) {}
133   virtual ~ChromeNotifierServiceTest() {}
134
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)));
141
142     // Set up a profile for the unit tests to use.
143     profile_.reset(new TestingProfile());
144   }
145
146   virtual void TearDown() {
147     notification_manager_.reset();
148   }
149
150   StubNotificationUIManager* notification_manager() {
151     return notification_manager_.get();
152   }
153
154   TestChangeProcessor* processor() {
155     return static_cast<TestChangeProcessor*>(sync_processor_.get());
156   }
157
158   scoped_ptr<syncer::SyncChangeProcessor> PassProcessor() {
159     return sync_processor_delegate_.Pass();
160   }
161
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
173     // to pass.
174     return new SyncedNotification(sync_data);
175   }
176
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
182     // out of it.
183     scoped_ptr<SyncedNotification> scoped_notification(notification);
184     return SyncChange(
185         FROM_HERE,
186         type,
187         ChromeNotifierService::CreateSyncDataFromNotification(*notification));
188   }
189
190  protected:
191   scoped_ptr<TestingProfile> profile_;
192
193  private:
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_;
198
199   DISALLOW_COPY_AND_ASSIGN(ChromeNotifierServiceTest);
200 };
201
202 // TODO(petewil): Add more tests as I add functionalty.  Tests are based on
203 // chrome/browser/extensions/app_notification_manager_sync_unittest.cc
204
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,
209                          kKey1, kUnread));
210   SyncData sync_data =
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());
217 }
218
219 // Model assocation:  We have no local data, and no remote data.
220 TEST_F(ChromeNotifierServiceTest, ModelAssocBothEmpty) {
221
222   ChromeNotifierService notifier(profile_.get(), notification_manager());
223
224   notifier.MergeDataAndStartSyncing(
225       SYNCED_NOTIFICATIONS,
226       SyncDataList(),  // Empty.
227       PassProcessor(),
228       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
229
230   EXPECT_EQ(0U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
231   EXPECT_EQ(0U, processor()->change_list_size());
232 }
233
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);
239
240   notifier.MergeDataAndStartSyncing(
241       SYNCED_NOTIFICATIONS,
242       SyncDataList(),
243       PassProcessor(),
244       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
245
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)));
257
258   notifier.ProcessSyncChanges(FROM_HERE, changes);
259
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.
263 }
264
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);
269
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());
280
281   notifier.MergeDataAndStartSyncing(
282       SYNCED_NOTIFICATIONS,
283       SyncDataList(),
284       PassProcessor(),
285       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
286
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)));
298
299   // Simulate incoming new notifications at runtime.
300   notifier.ProcessSyncChanges(FROM_HERE, changes);
301
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));
308
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);
313 }
314
315 // Process sync changes that arrive before the change they are supposed to
316 // modify.
317 TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesOutOfOrder) {
318   ChromeNotifierService notifier(profile_.get(), notification_manager());
319   notifier.set_avoid_bitmap_fetching_for_test(true);
320
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());
331
332   notifier.MergeDataAndStartSyncing(
333       SYNCED_NOTIFICATIONS,
334       SyncDataList(),
335       PassProcessor(),
336       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
337
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)));
351
352   // Simulate incoming new notifications at runtime.
353   notifier.ProcessSyncChanges(FROM_HERE, changes);
354
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));
362 }
363
364
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);
370
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());
381
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));
392
393   // Merge the local and remote data.
394   notifier.MergeDataAndStartSyncing(
395       SYNCED_NOTIFICATIONS,
396       initial_data,
397       PassProcessor(),
398       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
399
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));
409
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());
422   }
423   EXPECT_TRUE(notifier.FindNotificationById(kKey1));
424   EXPECT_TRUE(notifier.FindNotificationById(kKey2));
425   EXPECT_TRUE(notifier.FindNotificationById(kKey3));
426 }
427
428 // Test the local store having the read bit unset, the remote store having
429 // it set.
430 TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyReadMismatch1) {
431   ChromeNotifierService notifier(profile_.get(), notification_manager());
432   notifier.set_avoid_bitmap_fetching_for_test(true);
433
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());
441
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,
449       initial_data,
450       PassProcessor(),
451       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
452
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));
462
463   // Make sure that the notification manager was told to dismiss the
464   // notification.
465   EXPECT_EQ(std::string(kKey1), notification_manager()->dismissed_id());
466
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));
470 }
471
472 // Test when the local store has the read bit set, and the remote store has
473 // it unset.
474 TEST_F(ChromeNotifierServiceTest, ModelAssocBothNonEmptyReadMismatch2) {
475   ChromeNotifierService notifier(profile_.get(), notification_manager());
476   notifier.set_avoid_bitmap_fetching_for_test(true);
477
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());
485
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,
493       initial_data,
494       PassProcessor(),
495       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
496
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));
506
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());
512 }
513
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());
518
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());
523
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,
531       initial_data,
532       PassProcessor(),
533       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
534
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);
539
540   EXPECT_FALSE(NULL == notification1);
541   EXPECT_EQ(SyncedNotification::kUnread, notification1->GetReadState());
542   EXPECT_EQ(std::string(kTitle2), notification1->GetTitle());
543
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));
547 }
548
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);
554
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());
559
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,
563                                               true);
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.
569
570   // Disable the service and ensure it is gone from the list and the
571   // notification_manager.
572   notifier.OnSyncedNotificationServiceEnabled(kFirstSyncedNotificationServiceId,
573                                               false);
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));
579
580 }
581
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);
587
588   // We initially have no data.
589   EXPECT_EQ(0U, notifier.enabled_sending_services_.size());
590   EXPECT_EQ(0U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
591
592   // Set up an ADD.
593   SyncChangeList changes;
594   changes.push_back(
595       CreateSyncChange(SyncChange::ACTION_ADD,
596                        CreateNotification(kTitle1,
597                                           kText1,
598                                           kIconUrl1,
599                                           kImageUrl1,
600                                           kFirstSyncedNotificationServiceId,
601                                           kKey1,
602                                           kUnread)));
603
604   notifier.ProcessSyncChanges(FROM_HERE, changes);
605
606   EXPECT_EQ(1U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
607
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);
614
615   EXPECT_NE(notifier.enabled_sending_services_.end(), iter);
616
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());
620
621   changes.clear();
622   changes.push_back(
623       CreateSyncChange(SyncChange::ACTION_ADD,
624                        CreateNotification(kTitle2,
625                                           kText2,
626                                           kIconUrl2,
627                                           kImageUrl2,
628                                           kFirstSyncedNotificationServiceId,
629                                           kKey2,
630                                           kUnread)));
631   notifier.ProcessSyncChanges(FROM_HERE, changes);
632
633   // But adding another notification should not cause another welcome.
634   EXPECT_EQ(3U, notification_manager()->added_notifications());
635 }
636
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);
642
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());
648
649   // We initially have no data.
650   EXPECT_EQ(0U, notifier.enabled_sending_services_.size());
651   EXPECT_EQ(0U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
652
653   // Set up an ADD.
654   std::string first_synced_notification_service_id(
655       kFirstSyncedNotificationServiceId);
656
657   SyncChangeList changes;
658   changes.push_back(
659       CreateSyncChange(SyncChange::ACTION_ADD,
660                        CreateNotification(kTitle1,
661                                           kText1,
662                                           kIconUrl1,
663                                           kImageUrl1,
664                                           kFirstSyncedNotificationServiceId,
665                                           kKey1,
666                                           kUnread)));
667
668   notifier.ProcessSyncChanges(FROM_HERE, changes);
669
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());
675 }
676
677 TEST_F(ChromeNotifierServiceTest, CheckFindAppInfo) {
678   ChromeNotifierService notifier(profile_.get(), notification_manager());
679   notifier.set_avoid_bitmap_fetching_for_test(true);
680
681   SyncedNotificationAppInfo* app_info =
682       notifier.FindAppInfo(kFirstSyncedNotificationServiceId);
683   EXPECT_TRUE(app_info != NULL);
684 }
685
686 }  // namespace notifier