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

Side by Side Diff: chrome/browser/search_engines/template_url_service_sync_unittest.cc

Issue 7670007: Revert 96969 - Implement SyncableServices in TemplateURLService. Add related unittests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 4 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 | Annotate | Revision Log
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « chrome/browser/search_engines/template_url_service.cc ('k') | chrome/browser/search_engines/template_url_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698