Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: chrome/browser/notifier/chrome_notifier_service_unittest.cc

Issue 11745024: Synced Notification Sync Change Processor (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/memory/scoped_ptr.h"
8 #include "chrome/browser/notifier/chrome_notifier_service.h"
9 #include "chrome/browser/notifier/synced_notification.h"
10 #include "sync/api/sync_change.h"
11 #include "sync/api/sync_change_processor.h"
12 #include "sync/api/sync_error_factory.h"
13 #include "sync/api/sync_error_factory_mock.h"
14 #include "sync/protocol/sync.pb.h"
15 #include "sync/protocol/synced_notification_specifics.pb.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using namespace sync_pb;
19 using namespace syncer;
20
21 namespace {
22
23
dcheng 2013/01/07 20:42:10 Extra newline. Please remove.
Pete Williamson 2013/01/18 18:58:39 Done.
24 const char MY_APP_ID[] = "fboilmbenheemaomgaeehigklolhkhnf";
dcheng 2013/01/07 20:42:10 Wrong naming convention.
Pete Williamson 2013/01/18 18:58:39 Done.
25 const char COALESCING_KEY[] = "foo";
26 const unsigned long long FAKE_CREATION_TIME = 42;
27
28 // Extract notification id from syncer::SyncData.
29 std::string GetId(const SyncData& sync_data) {
30 SyncedNotificationSpecifics specifics = sync_data.GetSpecifics().
31 synced_notification();
32 return specifics.coalesced_notification().notification(0).external_id();
33 }
34
35 // Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
36 // back up to Sync.
37 class TestChangeProcessor : public SyncChangeProcessor {
38 public:
39 TestChangeProcessor() { }
40 virtual ~TestChangeProcessor() { }
41
42 // Store a copy of all the changes passed in so we can examine them later.
43 virtual SyncError ProcessSyncChanges(
44 const tracked_objects::Location& from_here,
45 const SyncChangeList& change_list) {
46 change_map_.erase(change_map_.begin(), change_map_.end());
47 for (SyncChangeList::const_iterator iter = change_list.begin();
48 iter != change_list.end(); ++iter) {
49 // Put the data into the change tracking map.
50 change_map_[GetId(iter->sync_data())] = *iter;
51 }
52
53 return SyncError();
54 }
55
56 size_t change_list_size() { return change_map_.size(); }
57
58 bool ContainsId(const std::string& id) {
59 return change_map_.find(id) != change_map_.end();
60 }
61
62 SyncChange GetChangeById(const std::string& id) {
63 DCHECK(ContainsId(id));
64 return change_map_[id];
65 }
66
67 private:
68 // Track the changes received in ProcessSyncChanges.
69 std::map<std::string, SyncChange> change_map_;
70
71 DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
72 };
73
74 class SyncChangeProcessorDelegate : public SyncChangeProcessor {
75 public:
76 explicit SyncChangeProcessorDelegate(SyncChangeProcessor* recipient)
77 : recipient_(recipient) {
78 DCHECK(recipient_);
79 }
80 virtual ~SyncChangeProcessorDelegate() {}
81
82 // syncer::SyncChangeProcessor implementation.
83 virtual SyncError ProcessSyncChanges(
84 const tracked_objects::Location& from_here,
85 const SyncChangeList& change_list) OVERRIDE {
86 return recipient_->ProcessSyncChanges(from_here, change_list);
87 }
88
89 private:
90 // The recipient of all sync changes.
91 SyncChangeProcessor* recipient_;
92
93 DISALLOW_COPY_AND_ASSIGN(SyncChangeProcessorDelegate);
94 };
95
96 } // namespace
97
98 class ChromeNotifierServiceTest : public testing::Test {
99
100 public:
101 ChromeNotifierServiceTest()
102 : sync_processor_(new TestChangeProcessor),
103 sync_processor_delegate_(new SyncChangeProcessorDelegate(
104 sync_processor_.get())) {}
105 ~ChromeNotifierServiceTest() {}
106
107 // Methods from testing::Test.
108
109 virtual void SetUp() {
110 }
111
112 virtual void TearDown() {
113 }
114
115 TestChangeProcessor* processor() { return sync_processor_.get(); }
116
117 scoped_ptr<SyncChangeProcessor> PassProcessor() {
118 return sync_processor_delegate_.PassAs<SyncChangeProcessor>();
119 }
120
121 SyncedNotification* CreateNotification(const std::string& message,
122 const std::string& external_id) {
123 SyncData sync_data = CreateSyncData(message, external_id);
124 // Set enough fields in sync_data, including specifics, for our tests
125 // to pass.
126 return new SyncedNotification(sync_data);
127 }
128
129 // Helper to create syncer::SyncChange.
130 static SyncChange CreateSyncChange(
131 SyncChange::SyncChangeType type,
132 SyncedNotification* notification) {
133 // Take control of the notification to clean it up after we create data
134 // out of it.
135 scoped_ptr<SyncedNotification> scoped_notif(notification);
136 return SyncChange(
137 FROM_HERE,
138 type,
139 ChromeNotifierService::CreateSyncDataFromNotification(*notification));
140 }
141
142 // Helper to create syncer::SyncData.
143 static SyncData CreateSyncData(const std::string& message,
144 const std::string& external_id) {
145
146 // CreateLocalData makes a copy of this, so this can safely live
147 // on the stack.
148 EntitySpecifics entity_specifics;
149
150 // Get a writeable pointer to the sync notifications specifics inside the
151 // entity specifics.
152 SyncedNotificationSpecifics* specifics =
153 entity_specifics.mutable_synced_notification();
154
155 // Fill out as much of SyncedNotificationSpecifics as the tests need.
156
157 // Set the layout type to Title and Subtext.
158 specifics->mutable_coalesced_notification()->
159 mutable_render_info()->
160 mutable_layout()->
161 set_layout_type(RenderInfo_Layout_LayoutType_TITLE_AND_SUBTEXT);
162 // Set the APP_ID field in the ID.
163 specifics->mutable_coalesced_notification()->
164 mutable_id()->
165 set_app_id(MY_APP_ID);
166 // Set the coalescing key in the ID.
167 specifics->mutable_coalesced_notification()->
168 mutable_id()->
169 set_coalescing_key(COALESCING_KEY);
170 // Set the title (of a title and subtext).
171 specifics->mutable_coalesced_notification()->
172 mutable_render_info()->
173 mutable_layout()->
174 mutable_title_and_subtext_data()->
175 set_title(message);
176 // Set the creation time.
177 specifics->mutable_coalesced_notification()->
178 set_creation_time_msec(FAKE_CREATION_TIME);
179 // Set the first notification, including external ID.
180 specifics->mutable_coalesced_notification()->
181 add_notification();
182 specifics->mutable_coalesced_notification()->
183 mutable_notification(0)->set_external_id(external_id);
184
185
186 SyncData sync_data = SyncData::CreateLocalData(
187 "syncer::SYNCED_NOTIFICATIONS",
188 "ChromeNotifierServiceUnitTest",
189 entity_specifics);
190
191 return sync_data;
192 }
193
194 private:
195 scoped_ptr<TestChangeProcessor> sync_processor_;
196 scoped_ptr<SyncChangeProcessorDelegate> sync_processor_delegate_;
197
198 DISALLOW_COPY_AND_ASSIGN(ChromeNotifierServiceTest);
199 };
200
201 // Create a Notification, convert it to SyncData and convert it back.
202 TEST_F(ChromeNotifierServiceTest, NotificationToSyncDataToNotification) {
203 // TODO(petewil): Make this more robust when I add more properties to
204 // the notification.
205 scoped_ptr<SyncedNotification> notif1(CreateNotification("1", "11"));
206 SyncData sync_data =
207 ChromeNotifierService::CreateSyncDataFromNotification(*notif1);
208 scoped_ptr<SyncedNotification> notif2(
209 ChromeNotifierService::CreateNotificationFromSyncData(sync_data));
210 EXPECT_TRUE(notif2.get());
211 EXPECT_TRUE(notif1->Equals(*notif2));
212 }
213
214
215 // Model assocation: We have no local data, and no remote data.
216 TEST_F(ChromeNotifierServiceTest, ModelAssocBothEmpty) {
217 ChromeNotifierService notifier;
218
219 notifier.MergeDataAndStartSyncing(
220 SYNCED_NOTIFICATIONS,
221 SyncDataList(), // Empty.
222 PassProcessor(),
223 scoped_ptr<SyncErrorFactory>(new SyncErrorFactoryMock()));
224
225 EXPECT_EQ(0U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
226 EXPECT_EQ(0U, processor()->change_list_size());}
227
228 // Process sync changes when there is no local data.
229 TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesEmptyModel) {
230 // We initially have no data.
231 ChromeNotifierService notifier;
232
233 notifier.MergeDataAndStartSyncing(
234 SYNCED_NOTIFICATIONS,
235 SyncDataList(),
236 PassProcessor(),
237 scoped_ptr<SyncErrorFactory>(new SyncErrorFactoryMock()));
238
239 // Set up a bunch of ADDs.
240 SyncChangeList changes;
241 changes.push_back(CreateSyncChange(
242 SyncChange::ACTION_ADD, CreateNotification("1", "11")));
243 changes.push_back(CreateSyncChange(
244 SyncChange::ACTION_ADD, CreateNotification("2", "22")));
245 changes.push_back(CreateSyncChange(
246 SyncChange::ACTION_ADD, CreateNotification("3", "33")));
247
248 notifier.ProcessSyncChanges(FROM_HERE, changes);
249
250 EXPECT_EQ(3U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
251 }
252
253 // Model has some notifications, some of them are local only. Sync has some
254 // notifications. No items match up.
255 TEST_F(ChromeNotifierServiceTest, LocalRemoteBothNonEmptyNoOverlap) {
256 ChromeNotifierService notifier;
257
258 // Create some local fake data.
259 SyncedNotification* n1 = CreateNotification("1", "11");
260 notifier.Add(n1);
261 SyncedNotification* n2 = CreateNotification("2", "22");
262 notifier.Add(n2);
263 SyncedNotification* n3 = CreateNotification("3", "33");
264 notifier.Add(n3);
265
266 // Create some remote fake data.
267 SyncDataList initial_data;
268 SyncData s1 = CreateSyncData("4", "44");
269 initial_data.push_back(s1);
270 initial_data.push_back(CreateSyncData("5", "55"));
271 initial_data.push_back(CreateSyncData("6", "66"));
272 initial_data.push_back(CreateSyncData("7", "77"));
273
274 // Merge the local and remote data.
275 notifier.MergeDataAndStartSyncing(
276 SYNCED_NOTIFICATIONS,
277 initial_data,
278 PassProcessor(),
279 scoped_ptr<SyncErrorFactory>(new SyncErrorFactoryMock()));
280
281 // Ensure the array now has all local and remote notifications.
282 EXPECT_EQ(7U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
283 for (SyncDataList::const_iterator iter = initial_data.begin();
284 iter != initial_data.end(); ++iter) {
285 scoped_ptr<SyncedNotification> notif1(
286 ChromeNotifierService::CreateNotificationFromSyncData(*iter));
287 // TODO(petewil): Revisit this when we expand the protobuf more.
288 const std::string& value = notif1->title();
289 const SyncedNotification* notif2 = notifier.GetNotification(value);
290 EXPECT_TRUE(NULL != notif2);
291 EXPECT_TRUE(notif1->Equals(*notif2));
292 }
293 EXPECT_TRUE(notifier.GetNotification(n1->title()));
294 EXPECT_TRUE(notifier.GetNotification(n2->title()));
295 EXPECT_TRUE(notifier.GetNotification(n3->title()));
296
297 // Verify the changes made it up to the remote service.
298 EXPECT_EQ(3U, processor()->change_list_size());
299 EXPECT_TRUE(processor()->ContainsId(n1->get_first_external_id()));
300 EXPECT_EQ(SyncChange::ACTION_ADD, processor()->GetChangeById(
301 n1->get_first_external_id()).change_type());
302 EXPECT_FALSE(processor()->ContainsId("44"));
303 EXPECT_TRUE(processor()->ContainsId(n3->get_first_external_id()));
304 EXPECT_EQ(SyncChange::ACTION_ADD, processor()->GetChangeById(
305 n3->get_first_external_id()).change_type());
306 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698