Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / synced_notifications_private / synced_notifications_shim_unittest.cc
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.
4
5 #include "chrome/browser/extensions/api/synced_notifications_private/synced_notifications_shim.h"
6
7 #include "base/json/json_writer.h"
8 #include "extensions/browser/event_router.h"
9 #include "sync/api/fake_sync_change_processor.h"
10 #include "sync/api/sync_change.h"
11 #include "sync/api/sync_error_factory.h"
12 #include "sync/protocol/sync.pb.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 using namespace extensions;
16 using namespace extensions::api;
17
18 namespace {
19
20 // Builds a SyncData for the specified |type| based on |key|.
21 syncer::SyncData BuildData(syncer::ModelType type, const std::string& key) {
22   sync_pb::EntitySpecifics specifics;
23   if (type == syncer::SYNCED_NOTIFICATIONS) {
24     specifics.mutable_synced_notification()
25         ->mutable_coalesced_notification()
26         ->set_key(key);
27   } else {
28     specifics.mutable_synced_notification_app_info()
29         ->add_synced_notification_app_info()
30         ->add_app_id(key);
31   }
32   syncer::SyncData data = syncer::SyncData::CreateLocalData(
33       key, key, specifics);
34   return data;
35 }
36
37 // Builds a SyncChange with an update to the specified |type| based on |key|.
38 syncer::SyncChange BuildChange(syncer::ModelType type, const std::string& key) {
39   syncer::SyncChangeList change_list;
40   syncer::SyncData data = BuildData(type, key);
41   return syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, data);
42 }
43
44 // Verifies that the specifics within |data| match the serialized specifics
45 // within |serialized|.
46 testing::AssertionResult DataSpecificsMatch(const syncer::SyncData& data,
47                                             const std::string& serialized) {
48   if (data.GetDataType() == syncer::SYNCED_NOTIFICATIONS) {
49     const sync_pb::SyncedNotificationSpecifics& proto =
50         data.GetSpecifics().synced_notification();
51     if (serialized != proto.SerializeAsString())
52       return testing::AssertionFailure() << "Notification specifics mismatch";
53   } else {
54     const sync_pb::SyncedNotificationAppInfoSpecifics& proto =
55         data.GetSpecifics().synced_notification_app_info();
56     if (serialized != proto.SerializeAsString())
57       return testing::AssertionFailure() << "App info specifics mismatch";
58   }
59   return testing::AssertionSuccess();
60 }
61
62 // Verifies that the update within |change| matchs the serialized specifics
63 // within |serialized|.
64 testing::AssertionResult ChangeSpecificsMatch(const syncer::SyncChange& change,
65                                               const std::string& serialized) {
66   if (change.change_type() != syncer::SyncChange::ACTION_UPDATE)
67     return testing::AssertionFailure() << "Invalid change type";
68   return DataSpecificsMatch(change.sync_data(), serialized);
69 }
70
71 class SyncedNotificationsShimTest : public testing::Test {
72  public:
73   SyncedNotificationsShimTest();
74   ~SyncedNotificationsShimTest() override;
75
76   // Starts sync for both sync types.
77   void StartSync();
78   // Starts sync for the specified datatype |type|.
79   void StartSync(syncer::ModelType type);
80
81   // Transfers ownership of the last event received.
82   scoped_ptr<Event> GetLastEvent();
83
84   // Records that a refresh has been requested.
85   void RequestRefresh();
86
87   SyncedNotificationsShim* shim() { return &shim_; }
88   syncer::FakeSyncChangeProcessor* notification_processor() {
89     return notification_processor_;
90   }
91   syncer::FakeSyncChangeProcessor* app_info_processor() {
92     return app_info_processor_;
93   }
94   bool refresh_requested() const { return refresh_requested_; }
95
96  private:
97   void EventCallback(scoped_ptr<Event> event);
98
99   // Shim being tested.
100   SyncedNotificationsShim shim_;
101
102   syncer::FakeSyncChangeProcessor* notification_processor_;
103   syncer::FakeSyncChangeProcessor* app_info_processor_;
104
105   // The last event fired by the shim.
106   scoped_ptr<Event> last_event_fired_;
107
108   // Whether a refresh has been requested;
109   bool refresh_requested_;
110 };
111
112 SyncedNotificationsShimTest::SyncedNotificationsShimTest()
113     : shim_(base::Bind(&SyncedNotificationsShimTest::EventCallback,
114                        base::Unretained(this)),
115             base::Bind(&SyncedNotificationsShimTest::RequestRefresh,
116                        base::Unretained(this))),
117       notification_processor_(NULL),
118       app_info_processor_(NULL),
119       refresh_requested_(false) {}
120
121 SyncedNotificationsShimTest::~SyncedNotificationsShimTest() {}
122
123 void SyncedNotificationsShimTest::EventCallback(scoped_ptr<Event> event) {
124   ASSERT_FALSE(last_event_fired_);
125   last_event_fired_ = event.Pass();
126 }
127
128 void SyncedNotificationsShimTest::RequestRefresh() {
129   ASSERT_FALSE(refresh_requested_);
130   refresh_requested_ = true;
131 }
132
133 scoped_ptr<Event> SyncedNotificationsShimTest::GetLastEvent() {
134   return last_event_fired_.Pass();
135 }
136
137 void SyncedNotificationsShimTest::StartSync() {
138   StartSync(syncer::SYNCED_NOTIFICATIONS);
139   StartSync(syncer::SYNCED_NOTIFICATION_APP_INFO);
140   GetLastEvent();
141 }
142
143 void SyncedNotificationsShimTest::StartSync(syncer::ModelType type) {
144   scoped_ptr<syncer::FakeSyncChangeProcessor> change_processor(
145       new syncer::FakeSyncChangeProcessor());
146   if (type == syncer::SYNCED_NOTIFICATIONS)
147     notification_processor_ = change_processor.get();
148   else
149     app_info_processor_ = change_processor.get();
150   syncer::SyncDataList sync_data;
151   shim_.MergeDataAndStartSyncing(
152       type, sync_data, change_processor.Pass(), nullptr);
153 }
154
155 // Starting sync should fire the sync started event, but only after both types
156 // have started.
157 TEST_F(SyncedNotificationsShimTest, StartSync) {
158   EXPECT_FALSE(shim()->IsSyncReady());
159   StartSync(syncer::SYNCED_NOTIFICATIONS);
160   EXPECT_FALSE(shim()->IsSyncReady());
161   EXPECT_FALSE(GetLastEvent());
162
163   StartSync(syncer::SYNCED_NOTIFICATION_APP_INFO);
164   EXPECT_TRUE(shim()->IsSyncReady());
165
166   scoped_ptr<Event> event = GetLastEvent();
167   ASSERT_TRUE(event);
168   EXPECT_EQ(synced_notifications_private::OnSyncStartup::kEventName,
169             event->event_name);
170
171   EXPECT_TRUE(notification_processor()->changes().empty());
172   EXPECT_TRUE(app_info_processor()->changes().empty());
173 }
174
175 // A sync update should fire the OnDataChanges event with the updated
176 // notification.
177 TEST_F(SyncedNotificationsShimTest, ProcessSyncChangesSingleNotification) {
178   StartSync();
179   syncer::SyncChangeList change_list;
180   change_list.push_back(BuildChange(syncer::SYNCED_NOTIFICATIONS, "key"));
181   shim()->ProcessSyncChanges(FROM_HERE, change_list);
182   scoped_ptr<Event> event = GetLastEvent();
183   ASSERT_TRUE(event);
184   EXPECT_EQ(synced_notifications_private::OnDataChanges::kEventName,
185             event->event_name);
186   ASSERT_TRUE(event->event_args);
187   EXPECT_EQ(1U, event->event_args->GetSize());
188
189   base::ListValue* args = NULL;
190   ASSERT_TRUE(event->event_args->GetList(0, &args));
191   EXPECT_EQ(1U, args->GetSize());
192   base::DictionaryValue* sync_change_value = NULL;
193   ASSERT_TRUE(args->GetDictionary(0, &sync_change_value));
194   scoped_ptr<synced_notifications_private::SyncChange> sync_change =
195       synced_notifications_private::SyncChange::FromValue(*sync_change_value);
196   ASSERT_TRUE(sync_change);
197   EXPECT_TRUE(ChangeSpecificsMatch(change_list[0],
198                                    sync_change->data.data_item));
199   EXPECT_EQ(synced_notifications_private::CHANGE_TYPE_UPDATED,
200             sync_change->change_type);
201 }
202
203 // Verify that multiple notification updates can be sent in one event.
204 TEST_F(SyncedNotificationsShimTest, ProcessSyncChangesMultipleNotification) {
205   StartSync();
206   syncer::SyncChangeList change_list;
207   change_list.push_back(BuildChange(syncer::SYNCED_NOTIFICATIONS, "key"));
208   change_list.push_back(BuildChange(syncer::SYNCED_NOTIFICATIONS, "key2"));
209   shim()->ProcessSyncChanges(FROM_HERE, change_list);
210   scoped_ptr<Event> event = GetLastEvent();
211   ASSERT_TRUE(event);
212   EXPECT_EQ(synced_notifications_private::OnDataChanges::kEventName,
213             event->event_name);
214   ASSERT_TRUE(event->event_args);
215   base::ListValue* args = NULL;
216   ASSERT_TRUE(event->event_args->GetList(0, &args));
217   EXPECT_EQ(2U, args->GetSize());
218
219   base::DictionaryValue* sync_change_value = NULL;
220   ASSERT_TRUE(args->GetDictionary(0, &sync_change_value));
221   scoped_ptr<synced_notifications_private::SyncChange> sync_change =
222       synced_notifications_private::SyncChange::FromValue(*sync_change_value);
223   ASSERT_TRUE(sync_change);
224   EXPECT_TRUE(ChangeSpecificsMatch(change_list[0],
225                                    sync_change->data.data_item));
226   EXPECT_EQ(synced_notifications_private::CHANGE_TYPE_UPDATED,
227             sync_change->change_type);
228
229   ASSERT_TRUE(args->GetDictionary(1, &sync_change_value));
230   sync_change =
231       synced_notifications_private::SyncChange::FromValue(*sync_change_value);
232   ASSERT_TRUE(sync_change);
233   EXPECT_TRUE(ChangeSpecificsMatch(change_list[1],
234                                    sync_change->data.data_item));
235   EXPECT_EQ(synced_notifications_private::CHANGE_TYPE_UPDATED,
236             sync_change->change_type);
237 }
238
239 // Verify AppInfo updates trigger OnDataChanges events.
240 TEST_F(SyncedNotificationsShimTest, ProcessSyncChangeAppInfo) {
241   StartSync();
242   syncer::SyncChangeList change_list;
243   change_list.push_back(
244       BuildChange(syncer::SYNCED_NOTIFICATION_APP_INFO, "key"));
245   shim()->ProcessSyncChanges(FROM_HERE, change_list);
246   scoped_ptr<Event> event = GetLastEvent();
247   ASSERT_TRUE(event);
248   EXPECT_EQ(synced_notifications_private::OnDataChanges::kEventName,
249             event->event_name);
250   ASSERT_TRUE(event->event_args);
251   EXPECT_EQ(1U, event->event_args->GetSize());
252
253   base::ListValue* args = NULL;
254   ASSERT_TRUE(event->event_args->GetList(0, &args));
255   EXPECT_EQ(1U, args->GetSize());
256   base::DictionaryValue* sync_change_value = NULL;
257   ASSERT_TRUE(args->GetDictionary(0, &sync_change_value));
258   scoped_ptr<synced_notifications_private::SyncChange> sync_change =
259       synced_notifications_private::SyncChange::FromValue(*sync_change_value);
260   ASSERT_TRUE(sync_change);
261   EXPECT_TRUE(ChangeSpecificsMatch(change_list[0],
262                                    sync_change->data.data_item));
263   EXPECT_EQ(synced_notifications_private::CHANGE_TYPE_UPDATED,
264             sync_change->change_type);
265 }
266
267 // Attempt to get the initial sync data both before and after sync starts.
268 TEST_F(SyncedNotificationsShimTest, GetInitialData) {
269   std::vector<linked_ptr<synced_notifications_private::SyncData> > data;
270   EXPECT_FALSE(shim()->GetInitialData(
271       synced_notifications_private::SYNC_DATA_TYPE_SYNCED_NOTIFICATION, &data));
272   EXPECT_FALSE(shim()->GetInitialData(
273       synced_notifications_private::SYNC_DATA_TYPE_APP_INFO, &data));
274
275   StartSync();
276
277   EXPECT_TRUE(shim()->GetInitialData(
278       synced_notifications_private::SYNC_DATA_TYPE_SYNCED_NOTIFICATION, &data));
279   EXPECT_TRUE(data.empty());
280   EXPECT_TRUE(shim()->GetInitialData(
281       synced_notifications_private::SYNC_DATA_TYPE_APP_INFO, &data));
282   EXPECT_TRUE(data.empty());
283
284   notification_processor()->data().push_back(BuildData(
285       syncer::SYNCED_NOTIFICATIONS, "notif_key"));
286   EXPECT_TRUE(shim()->GetInitialData(
287       synced_notifications_private::SYNC_DATA_TYPE_SYNCED_NOTIFICATION, &data));
288   EXPECT_EQ(1U, data.size());
289   EXPECT_TRUE(DataSpecificsMatch(notification_processor()->data()[0],
290                                  data[0]->data_item));
291
292   data.clear();
293   app_info_processor()->data().push_back(BuildData(
294       syncer::SYNCED_NOTIFICATION_APP_INFO, "app_key"));
295   EXPECT_TRUE(shim()->GetInitialData(
296       synced_notifications_private::SYNC_DATA_TYPE_APP_INFO, &data));
297   EXPECT_EQ(1U, data.size());
298   EXPECT_TRUE(DataSpecificsMatch(app_info_processor()->data()[0],
299                                  data[0]->data_item));
300 }
301
302 // Verify that notification updates are properly handled.
303 TEST_F(SyncedNotificationsShimTest, UpdateNotification) {
304   syncer::SyncData data =
305       BuildData(syncer::SYNCED_NOTIFICATIONS, "notif_key");
306   std::string serialized =
307       data.GetSpecifics().synced_notification().SerializeAsString();
308   EXPECT_FALSE(shim()->UpdateNotification(serialized));
309
310   StartSync();
311
312   EXPECT_FALSE(shim()->UpdateNotification("gibberish"));
313   EXPECT_TRUE(notification_processor()->changes().empty());
314
315   EXPECT_TRUE(shim()->UpdateNotification(serialized));
316   EXPECT_EQ(1U, notification_processor()->changes().size());
317   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
318             notification_processor()->changes()[0].change_type());
319   EXPECT_EQ(syncer::SYNCED_NOTIFICATIONS,
320             notification_processor()->changes()[0].sync_data().GetDataType());
321   EXPECT_EQ(serialized,
322             notification_processor()
323                 ->changes()[0]
324                 .sync_data()
325                 .GetSpecifics()
326                 .synced_notification()
327                 .SerializeAsString());
328 }
329
330 // Verify that SetRenderContext updates the datatype context properly.
331 TEST_F(SyncedNotificationsShimTest, SetRenderContext) {
332   const std::string kContext = "context";
333   EXPECT_FALSE(shim()->SetRenderContext(
334       synced_notifications_private::REFRESH_REQUEST_REFRESH_NEEDED, kContext));
335   EXPECT_FALSE(refresh_requested());
336
337   StartSync();
338
339   EXPECT_TRUE(shim()->SetRenderContext(
340       synced_notifications_private::REFRESH_REQUEST_REFRESH_NEEDED, kContext));
341   EXPECT_EQ(kContext, notification_processor()->context());
342   EXPECT_TRUE(refresh_requested());
343 }
344
345 }  // namespace