OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "base/memory/scoped_ptr.h" | |
6 #include "base/string_util.h" | |
7 #include "base/time.h" | |
8 #include "base/utf_string_conversions.h" | |
9 #include "chrome/browser/search_engines/template_url.h" | |
10 #include "chrome/browser/search_engines/template_url_service.h" | |
11 #include "chrome/browser/sync/protocol/search_engine_specifics.pb.h" | |
12 #include "chrome/test/base/testing_browser_process_test.h" | |
13 #include "chrome/test/base/testing_profile.h" | |
14 | |
15 using base::Time; | |
16 | |
17 namespace { | |
18 | |
19 // Extract the GUID from a search engine SyncData. | |
20 std::string GetGUID(const SyncData& sync_data) { | |
21 return sync_data.GetSpecifics().GetExtension( | |
22 sync_pb::search_engine).sync_guid(); | |
23 } | |
24 | |
25 // Extract the keyword from a search engine SyncData. | |
26 std::string GetURL(const SyncData& sync_data) { | |
27 return sync_data.GetSpecifics().GetExtension( | |
28 sync_pb::search_engine).url(); | |
29 } | |
30 | |
31 // Extract the keyword from a search engine SyncData. | |
32 std::string GetKeyword(const SyncData& sync_data) { | |
33 return sync_data.GetSpecifics().GetExtension( | |
34 sync_pb::search_engine).keyword(); | |
35 } | |
36 | |
37 // Dummy SyncChangeProcessor used to help review what SyncChanges are pushed | |
38 // back up to Sync. | |
39 class TestChangeProcessor : public SyncChangeProcessor { | |
40 public: | |
41 TestChangeProcessor() : erroneous_(false) { | |
42 } | |
43 virtual ~TestChangeProcessor() { } | |
44 | |
45 // Store a copy of all the changes passed in so we can examine them later. | |
46 virtual SyncError ProcessSyncChanges( | |
47 const tracked_objects::Location& from_here, | |
48 const SyncChangeList& change_list) { | |
49 if (erroneous_) | |
50 return SyncError(FROM_HERE, "Some error.", syncable::SEARCH_ENGINES); | |
51 | |
52 change_map_.erase(change_map_.begin(), change_map_.end()); | |
53 for (SyncChangeList::const_iterator iter = change_list.begin(); | |
54 iter != change_list.end(); ++iter) { | |
55 change_map_[GetGUID(iter->sync_data())] = *iter; | |
56 } | |
57 | |
58 return SyncError(); | |
59 } | |
60 | |
61 bool ContainsGUID(const std::string& guid) { | |
62 return change_map_.find(guid) != change_map_.end(); | |
63 } | |
64 | |
65 SyncChange GetChangeByGUID(const std::string& guid) { | |
66 DCHECK(ContainsGUID(guid)); | |
67 return change_map_[guid]; | |
68 } | |
69 | |
70 int change_list_size() { return change_map_.size(); } | |
71 | |
72 void set_erroneous(bool erroneous) { erroneous_ = erroneous; } | |
73 | |
74 private: | |
75 // Track the changes received in ProcessSyncChanges. | |
76 std::map<std::string, SyncChange> change_map_; | |
77 bool erroneous_; | |
78 | |
79 DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor); | |
80 }; | |
81 | |
82 class TemplateURLServiceSyncTest : public TestingBrowserProcessTest { | |
83 public: | |
84 typedef TemplateURLService::SyncDataMap SyncDataMap; | |
85 | |
86 TemplateURLServiceSyncTest() {} | |
87 | |
88 virtual void SetUp() { | |
89 profile_a_.reset(new TestingProfile); | |
90 model_a_.reset(new TemplateURLService(profile_a_.get())); | |
91 model_a_->Load(); | |
92 profile_b_.reset(new TestingProfile); | |
93 model_b_.reset(new TemplateURLService(profile_b_.get())); | |
94 model_b_->Load(); | |
95 } | |
96 | |
97 virtual void TearDown() { } | |
98 | |
99 TemplateURLService* model() { return model_a_.get(); } | |
100 // For readability, we redefine an accessor for Model A for use in tests that | |
101 // involve syncing two models. | |
102 TemplateURLService* model_a() { return model_a_.get(); } | |
103 TemplateURLService* model_b() { return model_b_.get(); } | |
104 TestChangeProcessor* processor() { return &processor_; } | |
105 | |
106 // Create a TemplateURL with some test values. The caller owns the returned | |
107 // TemplateURL*. | |
108 TemplateURL* CreateTestTemplateURL() const { | |
109 TemplateURL* turl = new TemplateURL(); | |
110 turl->SetURL("http://www.unittest.com/", 0, 0); | |
111 turl->set_keyword(ASCIIToUTF16("unittest")); | |
112 turl->set_short_name(ASCIIToUTF16("unittest")); | |
113 turl->set_safe_for_autoreplace(true); | |
114 GURL favicon_url("http://favicon.url"); | |
115 turl->SetFaviconURL(favicon_url); | |
116 turl->set_date_created(Time::FromTimeT(100)); | |
117 turl->set_last_modified(Time::FromTimeT(100)); | |
118 turl->SetPrepopulateId(999999); | |
119 return turl; | |
120 } | |
121 | |
122 // Convenience helpers for creating TemplateURLs with specific fields. | |
123 TemplateURL* CreateTestTemplateURL(std::string keyword, | |
124 std::string url) const { | |
125 TemplateURL* turl = CreateTestTemplateURL(); | |
126 turl->set_keyword(UTF8ToUTF16(keyword)); | |
127 turl->SetURL(url, 0, 0); | |
128 return turl; | |
129 } | |
130 | |
131 TemplateURL* CreateTestTemplateURL(std::string keyword, | |
132 std::string url, | |
133 std::string guid) const { | |
134 TemplateURL* turl = CreateTestTemplateURL(keyword, url); | |
135 if (!guid.empty()) | |
136 turl->set_sync_guid(guid); | |
137 return turl; | |
138 } | |
139 | |
140 TemplateURL* CreateTestTemplateURL(std::string keyword, | |
141 std::string url, | |
142 std::string guid, | |
143 time_t last_mod) const { | |
144 TemplateURL* turl = CreateTestTemplateURL(keyword, url, guid); | |
145 turl->set_last_modified(Time::FromTimeT(last_mod)); | |
146 return turl; | |
147 } | |
148 | |
149 // Verifies the two TemplateURLs are equal. | |
150 // TODO(stevet): Share this with TemplateURLServiceTest. | |
151 void AssertEquals(const TemplateURL& expected, | |
152 const TemplateURL& actual) const { | |
153 ASSERT_TRUE(TemplateURLRef::SameUrlRefs(expected.url(), actual.url())); | |
154 ASSERT_TRUE(TemplateURLRef::SameUrlRefs(expected.suggestions_url(), | |
155 actual.suggestions_url())); | |
156 ASSERT_EQ(expected.keyword(), actual.keyword()); | |
157 ASSERT_EQ(expected.short_name(), actual.short_name()); | |
158 ASSERT_EQ(JoinString(expected.input_encodings(), ';'), | |
159 JoinString(actual.input_encodings(), ';')); | |
160 ASSERT_TRUE(expected.GetFaviconURL() == actual.GetFaviconURL()); | |
161 ASSERT_EQ(expected.id(), actual.id()); | |
162 ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace()); | |
163 ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list()); | |
164 ASSERT_TRUE(expected.date_created() == actual.date_created()); | |
165 ASSERT_TRUE(expected.last_modified() == actual.last_modified()); | |
166 } | |
167 | |
168 // Expect that two SyncDataLists have equal contents, in terms of the | |
169 // sync_guid, keyword, and url fields. | |
170 void AssertEquals(const SyncDataList& data1, | |
171 const SyncDataList& data2) const { | |
172 SyncDataMap map1 = TemplateURLService::CreateGUIDToSyncDataMap(data1); | |
173 SyncDataMap map2 = TemplateURLService::CreateGUIDToSyncDataMap(data2); | |
174 | |
175 for (SyncDataMap::const_iterator iter1 = map1.begin(); | |
176 iter1 != map1.end(); iter1++) { | |
177 SyncDataMap::iterator iter2 = map2.find(iter1->first); | |
178 if (iter2 != map2.end()) { | |
179 ASSERT_EQ(GetKeyword(iter1->second), GetKeyword(iter2->second)); | |
180 ASSERT_EQ(GetURL(iter1->second), GetURL(iter2->second)); | |
181 map2.erase(iter2); | |
182 } | |
183 } | |
184 EXPECT_EQ(0U, map2.size()); | |
185 } | |
186 | |
187 // Convenience helper for creating SyncChanges. | |
188 SyncChange CreateTestSyncChange(SyncChange::SyncChangeType type, | |
189 TemplateURL* turl) const { | |
190 return SyncChange(type, | |
191 TemplateURLService::CreateSyncDataFromTemplateURL(*turl)); | |
192 } | |
193 | |
194 // Helper that creates some initial sync data. We cheat a little by specifying | |
195 // GUIDs for easy identification later. We also make the last_modified times | |
196 // slightly older than CreateTestTemplateURL's default, to test conflict | |
197 // resolution. | |
198 SyncDataList CreateInitialSyncData() const { | |
199 SyncDataList list; | |
200 | |
201 scoped_ptr<TemplateURL> turl( | |
202 CreateTestTemplateURL("key1", "http://key1.com", "key1", 90)); | |
203 list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl)); | |
204 turl.reset(CreateTestTemplateURL("key2", "http://key2.com", "key2", 90)); | |
205 list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl)); | |
206 turl.reset(CreateTestTemplateURL("key3", "http://key3.com", "key3", 90)); | |
207 list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl)); | |
208 | |
209 return list; | |
210 } | |
211 | |
212 protected: | |
213 // We keep two TemplateURLServices to test syncing between them. | |
214 scoped_ptr<TestingProfile> profile_a_; | |
215 scoped_ptr<TemplateURLService> model_a_; | |
216 scoped_ptr<TestingProfile> profile_b_; | |
217 scoped_ptr<TemplateURLService> model_b_; | |
218 | |
219 // Our dummy ChangeProcessor used to inspect changes pushed to Sync. | |
220 TestChangeProcessor processor_; | |
221 | |
222 DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceSyncTest); | |
223 }; | |
224 | |
225 } // namespace | |
226 | |
227 TEST_F(TemplateURLServiceSyncTest, SerializeDeserialize) { | |
228 // Create a TemplateURL and convert it into a sync specific type. | |
229 scoped_ptr<TemplateURL> turl(CreateTestTemplateURL()); | |
230 SyncData sync_data = TemplateURLService::CreateSyncDataFromTemplateURL(*turl); | |
231 // Convert the specifics back to a TemplateURL. | |
232 scoped_ptr<TemplateURL> deserialized( | |
233 TemplateURLService::CreateTemplateURLFromSyncData(sync_data)); | |
234 EXPECT_TRUE(deserialized.get()); | |
235 // Ensure that the original and the deserialized TURLs are equal in values. | |
236 AssertEquals(*turl, *deserialized); | |
237 } | |
238 | |
239 TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataBasic) { | |
240 model()->Add(CreateTestTemplateURL("key1", "http://key1.com")); | |
241 model()->Add(CreateTestTemplateURL("key2", "http://key2.com")); | |
242 model()->Add(CreateTestTemplateURL("key3", "http://key3.com")); | |
243 SyncDataList all_sync_data = | |
244 model()->GetAllSyncData(syncable::SEARCH_ENGINES); | |
245 | |
246 EXPECT_EQ(3U, all_sync_data.size()); | |
247 | |
248 for (SyncDataList::const_iterator iter = all_sync_data.begin(); | |
249 iter != all_sync_data.end(); ++iter) { | |
250 std::string guid = GetGUID(*iter); | |
251 const TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid); | |
252 const TemplateURL* deserialized = | |
253 TemplateURLService::CreateTemplateURLFromSyncData(*iter); | |
254 AssertEquals(*service_turl, *deserialized); | |
255 } | |
256 } | |
257 | |
258 TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataNoExtensions) { | |
259 model()->Add(CreateTestTemplateURL("key1", "http://key1.com")); | |
260 model()->Add(CreateTestTemplateURL("key2", "http://key2.com")); | |
261 model()->Add(CreateTestTemplateURL( | |
262 "key3", "chrome-extension://blahblahblah")); | |
263 SyncDataList all_sync_data = | |
264 model()->GetAllSyncData(syncable::SEARCH_ENGINES); | |
265 | |
266 EXPECT_EQ(2U, all_sync_data.size()); | |
267 | |
268 for (SyncDataList::const_iterator iter = all_sync_data.begin(); | |
269 iter != all_sync_data.end(); ++iter) { | |
270 std::string guid = GetGUID(*iter); | |
271 const TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid); | |
272 const TemplateURL* deserialized = | |
273 TemplateURLService::CreateTemplateURLFromSyncData(*iter); | |
274 AssertEquals(*service_turl, *deserialized); | |
275 } | |
276 } | |
277 | |
278 TEST_F(TemplateURLServiceSyncTest, UniquifyKeyword) { | |
279 model()->Add(CreateTestTemplateURL("key1", "http://key1.com")); | |
280 // Create a key that conflicts with something in the model. | |
281 scoped_ptr<TemplateURL> turl(CreateTestTemplateURL("key1", | |
282 "http://new.com", | |
283 "xyz")); | |
284 string16 new_keyword = model()->UniquifyKeyword(*turl); | |
285 | |
286 EXPECT_EQ(UTF8ToUTF16("new.com"), new_keyword); | |
287 EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword)); | |
288 | |
289 turl->set_keyword(new_keyword); | |
290 model()->Add(turl.release()); | |
291 // Test a second collision. This time it should be resolved by actually | |
292 // modifying the original keyword, since the autogenerated keyword is already | |
293 // used. | |
294 turl.reset(CreateTestTemplateURL("key1", "http://new.com")); | |
295 new_keyword = model()->UniquifyKeyword(*turl); | |
296 | |
297 EXPECT_EQ(UTF8ToUTF16("key1_"), new_keyword); | |
298 EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword)); | |
299 | |
300 turl->set_keyword(new_keyword); | |
301 model()->Add(turl.release()); | |
302 // Test a third collision. This should collide on both the autogenerated | |
303 // keyword and the first uniquification attempt. | |
304 turl.reset(CreateTestTemplateURL("key1", "http://new.com")); | |
305 new_keyword = model()->UniquifyKeyword(*turl); | |
306 | |
307 EXPECT_EQ(UTF8ToUTF16("key1__"), new_keyword); | |
308 EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword)); | |
309 } | |
310 | |
311 TEST_F(TemplateURLServiceSyncTest, ResolveSyncKeywordConflict) { | |
312 TemplateURL* original_turl = | |
313 CreateTestTemplateURL("key1", "http://key1.com", "", 9000); | |
314 string16 original_turl_keyword = original_turl->keyword(); | |
315 model()->Add(original_turl); | |
316 | |
317 // Create a key that does not conflict with something in the model. | |
318 scoped_ptr<TemplateURL> sync_turl(CreateTestTemplateURL("unique", | |
319 "http://new.com")); | |
320 string16 sync_keyword = sync_turl->keyword(); | |
321 SyncChangeList changes; | |
322 | |
323 // No conflict, no TURLs changed, no changes. | |
324 EXPECT_FALSE(model()->ResolveSyncKeywordConflict(sync_turl.get(), changes)); | |
325 EXPECT_EQ(original_turl_keyword, original_turl->keyword()); | |
326 EXPECT_EQ(sync_keyword, sync_turl->keyword()); | |
327 EXPECT_EQ(0U, changes.size()); | |
328 | |
329 // Change sync keyword to something that conflicts, and make it older. | |
330 // Conflict, sync keyword is uniquified, and a SyncChange is added. | |
331 sync_turl->set_keyword(original_turl->keyword()); | |
332 sync_turl->set_last_modified(Time::FromTimeT(8999)); | |
333 EXPECT_TRUE(model()->ResolveSyncKeywordConflict(sync_turl.get(), changes)); | |
334 EXPECT_NE(sync_keyword, sync_turl->keyword()); | |
335 EXPECT_EQ(original_turl_keyword, original_turl->keyword()); | |
336 EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(sync_turl->keyword())); | |
337 EXPECT_EQ(1U, changes.size()); | |
338 changes.clear(); | |
339 | |
340 // Sync is newer. Original TemplateURL keyword is uniquified, no SyncChange | |
341 // is added. | |
342 sync_turl->set_keyword(original_turl->keyword()); | |
343 sync_keyword = sync_turl->keyword(); | |
344 sync_turl->set_last_modified(Time::FromTimeT(9001)); | |
345 EXPECT_TRUE(model()->ResolveSyncKeywordConflict(sync_turl.get(), changes)); | |
346 EXPECT_EQ(sync_keyword, sync_turl->keyword()); | |
347 EXPECT_NE(original_turl_keyword, original_turl->keyword()); | |
348 EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(sync_turl->keyword())); | |
349 EXPECT_EQ(0U, changes.size()); | |
350 | |
351 // Equal times. Same result as above. Sync left alone, original uniquified so | |
352 // sync_turl can fit. | |
353 sync_turl->set_keyword(original_turl->keyword()); | |
354 sync_keyword = sync_turl->keyword(); | |
355 // Note that we have to reset original_turl's last_modified time as it was | |
356 // modified above. | |
357 original_turl->set_last_modified(Time::FromTimeT(9000)); | |
358 sync_turl->set_last_modified(Time::FromTimeT(9000)); | |
359 EXPECT_TRUE(model()->ResolveSyncKeywordConflict(sync_turl.get(), changes)); | |
360 EXPECT_EQ(sync_keyword, sync_turl->keyword()); | |
361 EXPECT_NE(original_turl_keyword, original_turl->keyword()); | |
362 EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(sync_turl->keyword())); | |
363 EXPECT_EQ(0U, changes.size()); | |
364 } | |
365 | |
366 TEST_F(TemplateURLServiceSyncTest, FindDuplicateOfSyncTemplateURL) { | |
367 TemplateURL* original_turl = | |
368 CreateTestTemplateURL("key1", "http://key1.com"); | |
369 model()->Add(original_turl); | |
370 | |
371 // No matches at all. | |
372 scoped_ptr<TemplateURL> sync_turl( | |
373 CreateTestTemplateURL("key2", "http://key2.com")); | |
374 EXPECT_EQ(NULL, model()->FindDuplicateOfSyncTemplateURL(*sync_turl)); | |
375 | |
376 // URL matches, but not keyword. No dupe. | |
377 sync_turl->SetURL("http://key1.com", 0 , 0); | |
378 EXPECT_EQ(NULL, model()->FindDuplicateOfSyncTemplateURL(*sync_turl)); | |
379 | |
380 // Keyword matches, but not URL. No dupe. | |
381 sync_turl->SetURL("http://key2.com", 0 , 0); | |
382 sync_turl->set_keyword(UTF8ToUTF16("key1")); | |
383 EXPECT_EQ(NULL, model()->FindDuplicateOfSyncTemplateURL(*sync_turl)); | |
384 | |
385 // Duplicate. | |
386 sync_turl->SetURL("http://key1.com", 0 , 0); | |
387 const TemplateURL* dupe_turl = | |
388 model()->FindDuplicateOfSyncTemplateURL(*sync_turl); | |
389 ASSERT_TRUE(dupe_turl); | |
390 EXPECT_EQ(dupe_turl->keyword(), sync_turl->keyword()); | |
391 EXPECT_EQ(dupe_turl->url()->url(), sync_turl->url()->url()); | |
392 } | |
393 | |
394 TEST_F(TemplateURLServiceSyncTest, MergeSyncAndLocalURLDuplicates) { | |
395 TemplateURL* original_turl = | |
396 CreateTestTemplateURL("key1", "http://key1.com", "", 9000); | |
397 model()->Add(original_turl); | |
398 TemplateURL* sync_turl = | |
399 CreateTestTemplateURL("key1", "http://key1.com", "", 9001); | |
400 SyncChangeList changes; | |
401 | |
402 // The sync TemplateURL is newer. It should replace the original TemplateURL. | |
403 model()->MergeSyncAndLocalURLDuplicates(sync_turl, original_turl, changes); | |
404 EXPECT_EQ(sync_turl, model()->GetTemplateURLForKeyword(sync_turl->keyword())); | |
405 EXPECT_EQ(0U, changes.size()); | |
406 | |
407 // The sync TemplateURL is older. The existing TemplateURL should win and a | |
408 // SyncChange should be added to the list. | |
409 TemplateURL* sync_turl2 = | |
410 CreateTestTemplateURL("key1", "http://key1.com", "", 8999); | |
411 model()->MergeSyncAndLocalURLDuplicates(sync_turl2, sync_turl, changes); | |
412 EXPECT_EQ(sync_turl, | |
413 model()->GetTemplateURLForKeyword(sync_turl2->keyword())); | |
414 EXPECT_EQ(1U, changes.size()); | |
415 } | |
416 | |
417 TEST_F(TemplateURLServiceSyncTest, StartSyncEmpty) { | |
418 model()->MergeDataAndStartSyncing( | |
419 syncable::SEARCH_ENGINES, | |
420 SyncDataList(), // Empty. | |
421 processor()); | |
422 | |
423 EXPECT_EQ(0U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
424 EXPECT_EQ(0, processor()->change_list_size()); | |
425 } | |
426 | |
427 TEST_F(TemplateURLServiceSyncTest, MergeIntoEmpty) { | |
428 SyncDataList initial_data = CreateInitialSyncData(); | |
429 | |
430 model()->MergeDataAndStartSyncing( | |
431 syncable::SEARCH_ENGINES, | |
432 initial_data, | |
433 processor()); | |
434 | |
435 EXPECT_EQ(3U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
436 // We expect the model to have accepted all of the initial sync data. Search | |
437 // through the model using the GUIDs to ensure that they're present. | |
438 for (SyncDataList::const_iterator iter = initial_data.begin(); | |
439 iter != initial_data.end(); ++iter) { | |
440 std::string guid = GetGUID(*iter); | |
441 EXPECT_TRUE(model()->GetTemplateURLForGUID(guid)); | |
442 } | |
443 | |
444 EXPECT_EQ(0, processor()->change_list_size()); | |
445 } | |
446 | |
447 TEST_F(TemplateURLServiceSyncTest, MergeInAllNewData) { | |
448 model()->Add(CreateTestTemplateURL( | |
449 "google.com", "http://google.com", "abc")); | |
450 model()->Add(CreateTestTemplateURL("yahoo.com", "http://yahoo.com", "def")); | |
451 model()->Add(CreateTestTemplateURL("bing.com", "http://bing.com", "xyz")); | |
452 SyncDataList initial_data = CreateInitialSyncData(); | |
453 | |
454 model()->MergeDataAndStartSyncing( | |
455 syncable::SEARCH_ENGINES, | |
456 initial_data, | |
457 processor()); | |
458 | |
459 EXPECT_EQ(6U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
460 // We expect the model to have accepted all of the initial sync data. Search | |
461 // through the model using the GUIDs to ensure that they're present. | |
462 for (SyncDataList::const_iterator iter = initial_data.begin(); | |
463 iter != initial_data.end(); ++iter) { | |
464 std::string guid = GetGUID(*iter); | |
465 EXPECT_TRUE(model()->GetTemplateURLForGUID(guid)); | |
466 } | |
467 // All the original TemplateURLs should also remain in the model. | |
468 EXPECT_TRUE(model()->GetTemplateURLForKeyword(UTF8ToUTF16("google.com"))); | |
469 EXPECT_TRUE(model()->GetTemplateURLForKeyword(UTF8ToUTF16("yahoo.com"))); | |
470 EXPECT_TRUE(model()->GetTemplateURLForKeyword(UTF8ToUTF16("bing.com"))); | |
471 // Ensure that Sync received the expected changes. | |
472 EXPECT_EQ(3, processor()->change_list_size()); | |
473 EXPECT_TRUE(processor()->ContainsGUID("abc")); | |
474 EXPECT_TRUE(processor()->ContainsGUID("def")); | |
475 EXPECT_TRUE(processor()->ContainsGUID("xyz")); | |
476 } | |
477 | |
478 TEST_F(TemplateURLServiceSyncTest, MergeSyncIsTheSame) { | |
479 // The local data is the same as the sync data merged in. i.e. - There have | |
480 // been no changes since the last time we synced. Even the last_modified | |
481 // timestamps are the same. | |
482 SyncDataList initial_data = CreateInitialSyncData(); | |
483 for (SyncDataList::const_iterator iter = initial_data.begin(); | |
484 iter != initial_data.end(); ++iter) { | |
485 TemplateURL* converted = | |
486 TemplateURLService::CreateTemplateURLFromSyncData(*iter); | |
487 model()->Add(converted); | |
488 } | |
489 | |
490 model()->MergeDataAndStartSyncing( | |
491 syncable::SEARCH_ENGINES, | |
492 initial_data, | |
493 processor()); | |
494 | |
495 EXPECT_EQ(3U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
496 for (SyncDataList::const_iterator iter = initial_data.begin(); | |
497 iter != initial_data.end(); ++iter) { | |
498 std::string guid = GetGUID(*iter); | |
499 EXPECT_TRUE(model()->GetTemplateURLForGUID(guid)); | |
500 } | |
501 EXPECT_EQ(0, processor()->change_list_size()); | |
502 } | |
503 | |
504 TEST_F(TemplateURLServiceSyncTest, MergeUpdateFromSync) { | |
505 // The local data is the same as the sync data merged in, but timestamps have | |
506 // changed. Ensure the right fields are merged in. | |
507 SyncDataList initial_data; | |
508 TemplateURL* turl1 = CreateTestTemplateURL( | |
509 "google.com", "http://google.com", "abc", 9000); | |
510 model()->Add(turl1); | |
511 TemplateURL* turl2 = CreateTestTemplateURL( | |
512 "bing.com", "http://bing.com", "xyz", 9000); | |
513 model()->Add(turl2); | |
514 | |
515 TemplateURL turl1_newer(*turl1); | |
516 turl1_newer.set_last_modified(Time::FromTimeT(9999)); | |
517 turl1_newer.SetURL("http://google.ca", 0, 0); | |
518 initial_data.push_back( | |
519 TemplateURLService::CreateSyncDataFromTemplateURL(turl1_newer)); | |
520 | |
521 TemplateURL turl2_older(*turl2); | |
522 turl2_older.set_last_modified(Time::FromTimeT(8888)); | |
523 turl2_older.SetURL("http://bing.ca", 0, 0); | |
524 initial_data.push_back( | |
525 TemplateURLService::CreateSyncDataFromTemplateURL(turl2_older)); | |
526 | |
527 model()->MergeDataAndStartSyncing( | |
528 syncable::SEARCH_ENGINES, | |
529 initial_data, | |
530 processor()); | |
531 | |
532 // Both were local updates, so we expect the same count. | |
533 EXPECT_EQ(2U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
534 | |
535 // Check that the first replaced the initial Google TemplateURL. | |
536 EXPECT_EQ(turl1, model()->GetTemplateURLForGUID("abc")); | |
537 EXPECT_EQ("http://google.ca", turl1->url()->url()); | |
538 | |
539 // Check that the second produced an upstream update to the Bing TemplateURL. | |
540 EXPECT_EQ(1, processor()->change_list_size()); | |
541 ASSERT_TRUE(processor()->ContainsGUID("xyz")); | |
542 SyncChange change = processor()->GetChangeByGUID("xyz"); | |
543 EXPECT_TRUE(change.change_type() == SyncChange::ACTION_UPDATE); | |
544 EXPECT_EQ("http://bing.com", GetURL(change.sync_data())); | |
545 } | |
546 | |
547 TEST_F(TemplateURLServiceSyncTest, MergeAddFromOlderSyncData) { | |
548 // GUIDs all differ, so this is data to be added from Sync, but the timestamps | |
549 // from Sync are older. Set up the local data so that one is a dupe, one has a | |
550 // conflicting keyword, and the last has no conflicts (a clean ADD). | |
551 SyncDataList initial_data = CreateInitialSyncData(); | |
552 TemplateURL* turl = TemplateURLService::CreateTemplateURLFromSyncData( | |
553 initial_data.at(0)); | |
554 ASSERT_TRUE(turl); | |
555 turl->set_sync_guid("aaa"); | |
556 turl->set_last_modified(Time::FromTimeT(100)); | |
557 model()->Add(turl); // dupe | |
558 | |
559 turl = TemplateURLService::CreateTemplateURLFromSyncData( | |
560 initial_data.at(1)); | |
561 ASSERT_TRUE(turl); | |
562 turl->SetURL("http://expected.com", 0, 0); | |
563 turl->set_sync_guid("bbb"); | |
564 turl->set_last_modified(Time::FromTimeT(100)); | |
565 model()->Add(turl); // keyword conflict | |
566 | |
567 model()->Add(CreateTestTemplateURL( | |
568 "unique", "http://unique.com", "ccc")); // add | |
569 | |
570 model()->MergeDataAndStartSyncing( | |
571 syncable::SEARCH_ENGINES, | |
572 initial_data, | |
573 processor()); | |
574 | |
575 // The dupe results in a merge. The other two should be added to the model. | |
576 EXPECT_EQ(5U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
577 | |
578 // The key1 duplicate results in the local copy winning. Ensure that Sync's | |
579 // copy was not added, and the local copy is pushed upstream to Sync as an | |
580 // update. The local copy should have received the sync data's GUID. | |
581 EXPECT_TRUE(model()->GetTemplateURLForGUID("key1")); | |
582 // Check changes for the UPDATE. | |
583 ASSERT_TRUE(processor()->ContainsGUID("key1")); | |
584 SyncChange key1_change = processor()->GetChangeByGUID("key1"); | |
585 EXPECT_EQ(SyncChange::ACTION_UPDATE, key1_change.change_type()); | |
586 EXPECT_FALSE(model()->GetTemplateURLForGUID("aaa")); | |
587 | |
588 // The key2 keyword conflict results in the local copy winning, so ensure it | |
589 // retains the original keyword, and that an update to the sync copy is pushed | |
590 // upstream to Sync. Both TemplateURLs should be found locally, however. | |
591 const TemplateURL* key2 = model()->GetTemplateURLForGUID("bbb"); | |
592 EXPECT_TRUE(key2); | |
593 EXPECT_EQ(UTF8ToUTF16("key2"), key2->keyword()); | |
594 EXPECT_TRUE(model()->GetTemplateURLForGUID("key2")); | |
595 // Check changes for the UPDATE. | |
596 ASSERT_TRUE(processor()->ContainsGUID("key2")); | |
597 SyncChange key2_change = processor()->GetChangeByGUID("key2"); | |
598 EXPECT_EQ(SyncChange::ACTION_UPDATE, key2_change.change_type()); | |
599 EXPECT_EQ("key2.com", GetKeyword(key2_change.sync_data())); | |
600 | |
601 // The last TemplateURL should have had no conflicts and was just added. It | |
602 // should not have replaced the third local TemplateURL. | |
603 EXPECT_TRUE(model()->GetTemplateURLForGUID("ccc")); | |
604 EXPECT_TRUE(model()->GetTemplateURLForGUID("key3")); | |
605 | |
606 // Two UPDATEs and two ADDs. | |
607 EXPECT_EQ(4, processor()->change_list_size()); | |
608 // Two ADDs should be pushed up to Sync. | |
609 ASSERT_TRUE(processor()->ContainsGUID("bbb")); | |
610 EXPECT_EQ(SyncChange::ACTION_ADD, | |
611 processor()->GetChangeByGUID("bbb").change_type()); | |
612 ASSERT_TRUE(processor()->ContainsGUID("ccc")); | |
613 EXPECT_EQ(SyncChange::ACTION_ADD, | |
614 processor()->GetChangeByGUID("ccc").change_type()); | |
615 } | |
616 | |
617 TEST_F(TemplateURLServiceSyncTest, MergeAddFromNewerSyncData) { | |
618 // GUIDs all differ, so this is data to be added from Sync, but the timestamps | |
619 // from Sync are newer. Set up the local data so that one is a dupe, one has a | |
620 // conflicting keyword, and the last has no conflicts (a clean ADD). | |
621 SyncDataList initial_data = CreateInitialSyncData(); | |
622 TemplateURL* turl = TemplateURLService::CreateTemplateURLFromSyncData( | |
623 initial_data.at(0)); | |
624 ASSERT_TRUE(turl); | |
625 turl->set_sync_guid("aaa"); | |
626 turl->set_last_modified(Time::FromTimeT(10)); | |
627 model()->Add(turl); // dupe | |
628 | |
629 turl = TemplateURLService::CreateTemplateURLFromSyncData( | |
630 initial_data.at(1)); | |
631 ASSERT_TRUE(turl); | |
632 turl->SetURL("http://expected.com", 0, 0); | |
633 turl->set_sync_guid("bbb"); | |
634 turl->set_last_modified(Time::FromTimeT(10)); | |
635 model()->Add(turl); // keyword conflict | |
636 | |
637 model()->Add(CreateTestTemplateURL( | |
638 "unique", "http://unique.com", "ccc", 10)); // add | |
639 | |
640 model()->MergeDataAndStartSyncing( | |
641 syncable::SEARCH_ENGINES, | |
642 initial_data, | |
643 processor()); | |
644 | |
645 // The dupe results in a merge. The other two should be added to the model. | |
646 EXPECT_EQ(5U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
647 | |
648 // The key1 duplicate results in Sync's copy winning. Ensure that Sync's | |
649 // copy replaced the local copy. | |
650 EXPECT_TRUE(model()->GetTemplateURLForGUID("key1")); | |
651 EXPECT_FALSE(model()->GetTemplateURLForGUID("aaa")); | |
652 | |
653 // The key2 keyword conflict results in Sync's copy winning, so ensure it | |
654 // retains the original keyword. The local copy should get a uniquified | |
655 // keyword. Both TemplateURLs should be found locally. | |
656 const TemplateURL* key2_sync = model()->GetTemplateURLForGUID("key2"); | |
657 EXPECT_TRUE(key2_sync); | |
658 EXPECT_EQ(UTF8ToUTF16("key2"), key2_sync->keyword()); | |
659 const TemplateURL* key2_local = model()->GetTemplateURLForGUID("bbb"); | |
660 EXPECT_TRUE(key2_local); | |
661 EXPECT_EQ(UTF8ToUTF16("expected.com"), key2_local->keyword()); | |
662 | |
663 // The last TemplateURL should have had no conflicts and was just added. It | |
664 // should not have replaced the third local TemplateURL. | |
665 EXPECT_TRUE(model()->GetTemplateURLForGUID("ccc")); | |
666 EXPECT_TRUE(model()->GetTemplateURLForGUID("key3")); | |
667 | |
668 // Two ADDs. | |
669 EXPECT_EQ(2, processor()->change_list_size()); | |
670 // Two ADDs should be pushed up to Sync. | |
671 ASSERT_TRUE(processor()->ContainsGUID("bbb")); | |
672 EXPECT_EQ(SyncChange::ACTION_ADD, | |
673 processor()->GetChangeByGUID("bbb").change_type()); | |
674 ASSERT_TRUE(processor()->ContainsGUID("ccc")); | |
675 EXPECT_EQ(SyncChange::ACTION_ADD, | |
676 processor()->GetChangeByGUID("ccc").change_type()); | |
677 } | |
678 | |
679 TEST_F(TemplateURLServiceSyncTest, ProcessChangesEmptyModel) { | |
680 // We initially have no data. | |
681 model()->MergeDataAndStartSyncing( | |
682 syncable::SEARCH_ENGINES, | |
683 SyncDataList(), | |
684 processor()); | |
685 | |
686 // Set up a bunch of ADDs. | |
687 SyncChangeList changes; | |
688 changes.push_back(CreateTestSyncChange( | |
689 SyncChange::ACTION_ADD, | |
690 CreateTestTemplateURL("key1", "http://key1.com", "key1"))); | |
691 changes.push_back(CreateTestSyncChange( | |
692 SyncChange::ACTION_ADD, | |
693 CreateTestTemplateURL("key2", "http://key2.com", "key2"))); | |
694 changes.push_back(CreateTestSyncChange( | |
695 SyncChange::ACTION_ADD, | |
696 CreateTestTemplateURL("key3", "http://key3.com", "key3"))); | |
697 | |
698 model()->ProcessSyncChanges(FROM_HERE, changes); | |
699 | |
700 EXPECT_EQ(3U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
701 EXPECT_EQ(0, processor()->change_list_size()); | |
702 EXPECT_TRUE(model()->GetTemplateURLForGUID("key1")); | |
703 EXPECT_TRUE(model()->GetTemplateURLForGUID("key2")); | |
704 EXPECT_TRUE(model()->GetTemplateURLForGUID("key3")); | |
705 } | |
706 | |
707 TEST_F(TemplateURLServiceSyncTest, ProcessChangesNoConflicts) { | |
708 model()->MergeDataAndStartSyncing( | |
709 syncable::SEARCH_ENGINES, | |
710 CreateInitialSyncData(), | |
711 processor()); | |
712 | |
713 // Process different types of changes, without conflicts. | |
714 SyncChangeList changes; | |
715 changes.push_back(CreateTestSyncChange( | |
716 SyncChange::ACTION_ADD, | |
717 CreateTestTemplateURL("key4", "http://key4.com", "key4"))); | |
718 changes.push_back(CreateTestSyncChange( | |
719 SyncChange::ACTION_UPDATE, | |
720 CreateTestTemplateURL("newkeyword", "http://new.com", "key2"))); | |
721 changes.push_back(CreateTestSyncChange( | |
722 SyncChange::ACTION_DELETE, | |
723 CreateTestTemplateURL("key3", "http://key3.com", "key3"))); | |
724 | |
725 model()->ProcessSyncChanges(FROM_HERE, changes); | |
726 | |
727 // Add one, remove one, update one, so the number shouldn't change. | |
728 EXPECT_EQ(3U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
729 EXPECT_EQ(0, processor()->change_list_size()); | |
730 EXPECT_TRUE(model()->GetTemplateURLForGUID("key1")); | |
731 EXPECT_TRUE(model()->GetTemplateURLForGUID("key2")); | |
732 const TemplateURL* turl = model()->GetTemplateURLForGUID("key2"); | |
733 EXPECT_TRUE(turl); | |
734 EXPECT_EQ(UTF8ToUTF16("newkeyword"), turl->keyword()); | |
735 EXPECT_EQ("http://new.com", turl->url()->url()); | |
736 EXPECT_FALSE(model()->GetTemplateURLForGUID("key3")); | |
737 EXPECT_TRUE(model()->GetTemplateURLForGUID("key4")); | |
738 } | |
739 | |
740 TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithConflictsSyncWins) { | |
741 model()->MergeDataAndStartSyncing( | |
742 syncable::SEARCH_ENGINES, | |
743 CreateInitialSyncData(), | |
744 processor()); | |
745 | |
746 // Process different types of changes, with conflicts. Note that all this data | |
747 // has a newer timestamp, so Sync will win in these scenarios. | |
748 SyncChangeList changes; | |
749 changes.push_back(CreateTestSyncChange( | |
750 SyncChange::ACTION_ADD, | |
751 CreateTestTemplateURL("key2", "http://new.com", "aaa"))); | |
752 changes.push_back(CreateTestSyncChange( | |
753 SyncChange::ACTION_UPDATE, | |
754 CreateTestTemplateURL("key3", "http://key3.com", "key1"))); | |
755 | |
756 model()->ProcessSyncChanges(FROM_HERE, changes); | |
757 | |
758 // Add one, update one, so we're up to 4. | |
759 EXPECT_EQ(4U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
760 // Sync is always newer here, so it should always win (i.e. - local changes, | |
761 // nothing pushed to Sync). | |
762 EXPECT_EQ(0, processor()->change_list_size()); | |
763 | |
764 // aaa conflicts with key2 and wins, forcing key2's keyword to update. | |
765 EXPECT_TRUE(model()->GetTemplateURLForGUID("aaa")); | |
766 EXPECT_EQ(model()->GetTemplateURLForGUID("aaa"), | |
767 model()->GetTemplateURLForKeyword(UTF8ToUTF16("key2"))); | |
768 EXPECT_TRUE(model()->GetTemplateURLForGUID("key2")); | |
769 EXPECT_EQ(model()->GetTemplateURLForGUID("key2"), | |
770 model()->GetTemplateURLForKeyword(UTF8ToUTF16("key2.com"))); | |
771 // key1 update conflicts with key3 and wins, forcing key3's keyword to update. | |
772 EXPECT_TRUE(model()->GetTemplateURLForGUID("key1")); | |
773 EXPECT_EQ(model()->GetTemplateURLForGUID("key1"), | |
774 model()->GetTemplateURLForKeyword(UTF8ToUTF16("key3"))); | |
775 EXPECT_TRUE(model()->GetTemplateURLForGUID("key3")); | |
776 EXPECT_EQ(model()->GetTemplateURLForGUID("key3"), | |
777 model()->GetTemplateURLForKeyword(UTF8ToUTF16("key3.com"))); | |
778 } | |
779 | |
780 TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithConflictsLocalWins) { | |
781 model()->MergeDataAndStartSyncing( | |
782 syncable::SEARCH_ENGINES, | |
783 CreateInitialSyncData(), | |
784 processor()); | |
785 | |
786 // Process different types of changes, with conflicts. Note that all this data | |
787 // has an older timestamp, so the local data will win in these scenarios. | |
788 SyncChangeList changes; | |
789 changes.push_back(CreateTestSyncChange( | |
790 SyncChange::ACTION_ADD, | |
791 CreateTestTemplateURL("key2", "http://new.com", "aaa", 10))); | |
792 changes.push_back(CreateTestSyncChange( | |
793 SyncChange::ACTION_UPDATE, | |
794 CreateTestTemplateURL("key3", "http://key3.com", "key1", 10))); | |
795 | |
796 model()->ProcessSyncChanges(FROM_HERE, changes); | |
797 | |
798 // Add one, update one, so we're up to 4. | |
799 EXPECT_EQ(4U, model()->GetAllSyncData(syncable::SEARCH_ENGINES).size()); | |
800 // Local data wins twice so two updates are pushed up to Sync. | |
801 EXPECT_EQ(2, processor()->change_list_size()); | |
802 | |
803 // aaa conflicts with key2 and loses, forcing it's keyword to update. | |
804 EXPECT_TRUE(model()->GetTemplateURLForGUID("aaa")); | |
805 EXPECT_EQ(model()->GetTemplateURLForGUID("aaa"), | |
806 model()->GetTemplateURLForKeyword(UTF8ToUTF16("new.com"))); | |
807 EXPECT_TRUE(model()->GetTemplateURLForGUID("key2")); | |
808 EXPECT_EQ(model()->GetTemplateURLForGUID("key2"), | |
809 model()->GetTemplateURLForKeyword(UTF8ToUTF16("key2"))); | |
810 // key1 update conflicts with key3 and loses, forcing key1's keyword to | |
811 // update. | |
812 EXPECT_TRUE(model()->GetTemplateURLForGUID("key1")); | |
813 EXPECT_EQ(model()->GetTemplateURLForGUID("key1"), | |
814 model()->GetTemplateURLForKeyword(UTF8ToUTF16("key3.com"))); | |
815 EXPECT_TRUE(model()->GetTemplateURLForGUID("key3")); | |
816 EXPECT_EQ(model()->GetTemplateURLForGUID("key3"), | |
817 model()->GetTemplateURLForKeyword(UTF8ToUTF16("key3"))); | |
818 | |
819 ASSERT_TRUE(processor()->ContainsGUID("aaa")); | |
820 EXPECT_EQ(SyncChange::ACTION_UPDATE, | |
821 processor()->GetChangeByGUID("aaa").change_type()); | |
822 ASSERT_TRUE(processor()->ContainsGUID("key1")); | |
823 EXPECT_EQ(SyncChange::ACTION_UPDATE, | |
824 processor()->GetChangeByGUID("key1").change_type()); | |
825 } | |
826 | |
827 TEST_F(TemplateURLServiceSyncTest, ProcessTemplateURLChange) { | |
828 // Ensure that ProcessTemplateURLChange is called and pushes the correct | |
829 // changes to Sync whenever local changes are made to TemplateURLs. | |
830 model()->MergeDataAndStartSyncing( | |
831 syncable::SEARCH_ENGINES, | |
832 CreateInitialSyncData(), | |
833 processor()); | |
834 | |
835 // Add a new search engine. | |
836 TemplateURL* new_turl = | |
837 CreateTestTemplateURL("baidu", "http://baidu.cn", "new"); | |
838 model()->Add(new_turl); | |
839 EXPECT_EQ(1, processor()->change_list_size()); | |
840 ASSERT_TRUE(processor()->ContainsGUID("new")); | |
841 SyncChange change = processor()->GetChangeByGUID("new"); | |
842 EXPECT_EQ(SyncChange::ACTION_ADD, change.change_type()); | |
843 EXPECT_EQ("baidu", GetKeyword(change.sync_data())); | |
844 EXPECT_EQ("http://baidu.cn", GetURL(change.sync_data())); | |
845 | |
846 // Change a keyword. | |
847 const TemplateURL* existing_turl = model()->GetTemplateURLForGUID("key1"); | |
848 model()->ResetTemplateURL(existing_turl, | |
849 existing_turl->short_name(), | |
850 UTF8ToUTF16("k"), | |
851 existing_turl->url()->url()); | |
852 EXPECT_EQ(1, processor()->change_list_size()); | |
853 ASSERT_TRUE(processor()->ContainsGUID("key1")); | |
854 change = processor()->GetChangeByGUID("key1"); | |
855 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type()); | |
856 EXPECT_EQ("k", GetKeyword(change.sync_data())); | |
857 | |
858 // Remove an existing search engine. | |
859 existing_turl = model()->GetTemplateURLForGUID("key2"); | |
860 model()->Remove(existing_turl); | |
861 EXPECT_EQ(1, processor()->change_list_size()); | |
862 ASSERT_TRUE(processor()->ContainsGUID("key2")); | |
863 change = processor()->GetChangeByGUID("key2"); | |
864 EXPECT_EQ(SyncChange::ACTION_DELETE, change.change_type()); | |
865 } | |
866 | |
867 TEST_F(TemplateURLServiceSyncTest, MergeTwoClientsBasic) { | |
868 // Start off B with some empty data. | |
869 model_b()->MergeDataAndStartSyncing( | |
870 syncable::SEARCH_ENGINES, | |
871 CreateInitialSyncData(), | |
872 processor()); | |
873 | |
874 // Merge A and B. All of B's data should transfer over to A, which initially | |
875 // has no data. | |
876 model_a()->MergeDataAndStartSyncing( | |
877 syncable::SEARCH_ENGINES, | |
878 model_b()->GetAllSyncData(syncable::SEARCH_ENGINES), | |
879 model_b()); | |
880 | |
881 // They should be consistent. | |
882 AssertEquals(model_a()->GetAllSyncData(syncable::SEARCH_ENGINES), | |
883 model_b()->GetAllSyncData(syncable::SEARCH_ENGINES)); | |
884 } | |
885 | |
886 TEST_F(TemplateURLServiceSyncTest, MergeTwoClientsDupesAndConflicts) { | |
887 // Start off B with some empty data. | |
888 model_b()->MergeDataAndStartSyncing( | |
889 syncable::SEARCH_ENGINES, | |
890 CreateInitialSyncData(), | |
891 processor()); | |
892 | |
893 // Set up A so we have some interesting duplicates and conflicts. | |
894 model_a()->Add(CreateTestTemplateURL( | |
895 "key4", "http://key4.com", "key4")); // Added | |
896 model_a()->Add(CreateTestTemplateURL( | |
897 "key2", "http://key2.com", "key2")); // Merge - Copy of key2. | |
898 model_a()->Add(CreateTestTemplateURL( | |
899 "key3", "http://key3.com", "key5", 10)); // Merge - Dupe of key3. | |
900 model_a()->Add(CreateTestTemplateURL( | |
901 "key1", "http://key6.com", "key6", 10)); // Keyword conflict with key1 | |
902 | |
903 // Merge A and B. | |
904 model_a()->MergeDataAndStartSyncing( | |
905 syncable::SEARCH_ENGINES, | |
906 model_b()->GetAllSyncData(syncable::SEARCH_ENGINES), | |
907 model_b()); | |
908 | |
909 // They should be consistent. | |
910 AssertEquals(model_a()->GetAllSyncData(syncable::SEARCH_ENGINES), | |
911 model_b()->GetAllSyncData(syncable::SEARCH_ENGINES)); | |
912 } | |
913 | |
914 TEST_F(TemplateURLServiceSyncTest, StopSyncing) { | |
915 SyncError error = model()->MergeDataAndStartSyncing( | |
916 syncable::SEARCH_ENGINES, | |
917 CreateInitialSyncData(), | |
918 processor()); | |
919 ASSERT_FALSE(error.IsSet()); | |
920 model()->StopSyncing(syncable::SEARCH_ENGINES); | |
921 | |
922 SyncChangeList changes; | |
923 changes.push_back(CreateTestSyncChange( | |
924 SyncChange::ACTION_UPDATE, | |
925 CreateTestTemplateURL("newkeyword", "http://new.com", "key2"))); | |
926 error = model()->ProcessSyncChanges(FROM_HERE, changes); | |
927 EXPECT_TRUE(error.IsSet()); | |
928 | |
929 // Ensure that the sync changes were not accepted. | |
930 EXPECT_TRUE(model()->GetTemplateURLForGUID("key2")); | |
931 EXPECT_FALSE(model()->GetTemplateURLForKeyword(UTF8ToUTF16("newkeyword"))); | |
932 } | |
933 | |
934 TEST_F(TemplateURLServiceSyncTest, SyncErrorOnInitialSync) { | |
935 processor()->set_erroneous(true); | |
936 SyncError error = model()->MergeDataAndStartSyncing( | |
937 syncable::SEARCH_ENGINES, | |
938 CreateInitialSyncData(), | |
939 processor()); | |
940 EXPECT_TRUE(error.IsSet()); | |
941 | |
942 // Ensure that if the initial merge was erroneous, then subsequence attempts | |
943 // to push data into the local model are rejected, since the model was never | |
944 // successfully associated with Sync in the first place. | |
945 SyncChangeList changes; | |
946 changes.push_back(CreateTestSyncChange( | |
947 SyncChange::ACTION_UPDATE, | |
948 CreateTestTemplateURL("newkeyword", "http://new.com", "key2"))); | |
949 processor()->set_erroneous(false); | |
950 error = model()->ProcessSyncChanges(FROM_HERE, changes); | |
951 EXPECT_TRUE(error.IsSet()); | |
952 | |
953 // Ensure that the sync changes were not accepted. | |
954 EXPECT_TRUE(model()->GetTemplateURLForGUID("key2")); | |
955 EXPECT_FALSE(model()->GetTemplateURLForKeyword(UTF8ToUTF16("newkeyword"))); | |
956 } | |
957 | |
958 TEST_F(TemplateURLServiceSyncTest, SyncErrorOnLaterSync) { | |
959 // Ensure that if the SyncProcessor succeeds in the initial merge, but fails | |
960 // in future ProcessSyncChanges, we still return an error. | |
961 SyncError error = model()->MergeDataAndStartSyncing( | |
962 syncable::SEARCH_ENGINES, | |
963 CreateInitialSyncData(), | |
964 processor()); | |
965 ASSERT_FALSE(error.IsSet()); | |
966 | |
967 SyncChangeList changes; | |
968 changes.push_back(CreateTestSyncChange( | |
969 SyncChange::ACTION_UPDATE, | |
970 CreateTestTemplateURL("newkeyword", "http://new.com", "key2"))); | |
971 processor()->set_erroneous(true); | |
972 error = model()->ProcessSyncChanges(FROM_HERE, changes); | |
973 EXPECT_TRUE(error.IsSet()); | |
974 } | |
OLD | NEW |