- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / search_engines / template_url_service_sync_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/memory/scoped_ptr.h"
6 #include "base/memory/scoped_vector.h"
7 #include "base/run_loop.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/time/time.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/search_engines/search_terms_data.h"
13 #include "chrome/browser/search_engines/template_url.h"
14 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
15 #include "chrome/browser/search_engines/template_url_service.h"
16 #include "chrome/browser/search_engines/template_url_service_factory.h"
17 #include "chrome/browser/search_engines/template_url_service_test_util.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/common/url_constants.h"
20 #include "chrome/test/base/testing_pref_service_syncable.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "content/public/browser/notification_service.h"
23 #include "extensions/common/constants.h"
24 #include "net/base/net_util.h"
25 #include "sync/api/sync_error_factory.h"
26 #include "sync/api/sync_error_factory_mock.h"
27 #include "sync/protocol/search_engine_specifics.pb.h"
28 #include "sync/protocol/sync.pb.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30
31 using base::Time;
32
33 namespace {
34
35 // Extract the GUID from a search engine syncer::SyncData.
36 std::string GetGUID(const syncer::SyncData& sync_data) {
37   return sync_data.GetSpecifics().search_engine().sync_guid();
38 }
39
40 // Extract the URL from a search engine syncer::SyncData.
41 std::string GetURL(const syncer::SyncData& sync_data) {
42   return sync_data.GetSpecifics().search_engine().url();
43 }
44
45 // Extract the keyword from a search engine syncer::SyncData.
46 std::string GetKeyword(const syncer::SyncData& sync_data) {
47   return sync_data.GetSpecifics().search_engine().keyword();
48 }
49
50 // Much like TemplateURLService::CreateSyncDataFromTemplateURL(), but allows the
51 // caller to override the keyword, URL, or GUID fields with empty strings, in
52 // order to create custom data that should be handled specially when synced to a
53 // client.
54 syncer::SyncData CreateCustomSyncData(const TemplateURL& turl,
55                               bool autogenerate_keyword,
56                               const std::string& url,
57                               const std::string& sync_guid) {
58   sync_pb::EntitySpecifics specifics;
59   sync_pb::SearchEngineSpecifics* se_specifics =
60       specifics.mutable_search_engine();
61   se_specifics->set_short_name(UTF16ToUTF8(turl.short_name()));
62   se_specifics->set_keyword(
63       autogenerate_keyword ? std::string() : UTF16ToUTF8(turl.keyword()));
64   se_specifics->set_favicon_url(turl.favicon_url().spec());
65   se_specifics->set_url(url);
66   se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace());
67   se_specifics->set_originating_url(turl.originating_url().spec());
68   se_specifics->set_date_created(turl.date_created().ToInternalValue());
69   se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';'));
70   se_specifics->set_show_in_default_list(turl.show_in_default_list());
71   se_specifics->set_suggestions_url(turl.suggestions_url());
72   se_specifics->set_prepopulate_id(turl.prepopulate_id());
73   se_specifics->set_autogenerate_keyword(autogenerate_keyword);
74   se_specifics->set_instant_url(turl.instant_url());
75   se_specifics->set_last_modified(turl.last_modified().ToInternalValue());
76   se_specifics->set_sync_guid(sync_guid);
77   return syncer::SyncData::CreateLocalData(turl.sync_guid(),  // Must be valid!
78                                    se_specifics->keyword(), specifics);
79 }
80
81
82 // TestChangeProcessor --------------------------------------------------------
83
84 // Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
85 // back up to Sync.
86 class TestChangeProcessor : public syncer::SyncChangeProcessor {
87  public:
88   TestChangeProcessor();
89   virtual ~TestChangeProcessor();
90
91   // Store a copy of all the changes passed in so we can examine them later.
92   virtual syncer::SyncError ProcessSyncChanges(
93       const tracked_objects::Location& from_here,
94       const syncer::SyncChangeList& change_list) OVERRIDE;
95
96   virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
97       OVERRIDE {
98     return syncer::SyncDataList();
99   }
100
101   bool contains_guid(const std::string& guid) const {
102     return change_map_.count(guid) != 0;
103   }
104
105   syncer::SyncChange change_for_guid(const std::string& guid) const {
106     DCHECK(contains_guid(guid));
107     return change_map_.find(guid)->second;
108   }
109
110   size_t change_list_size() { return change_map_.size(); }
111
112   void set_erroneous(bool erroneous) { erroneous_ = erroneous; }
113
114  private:
115   // Track the changes received in ProcessSyncChanges.
116   std::map<std::string, syncer::SyncChange> change_map_;
117   bool erroneous_;
118
119   DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
120 };
121
122 TestChangeProcessor::TestChangeProcessor() : erroneous_(false) {
123 }
124
125 TestChangeProcessor::~TestChangeProcessor() {
126 }
127
128 syncer::SyncError TestChangeProcessor::ProcessSyncChanges(
129     const tracked_objects::Location& from_here,
130     const syncer::SyncChangeList& change_list) {
131   if (erroneous_)
132     return syncer::SyncError(
133         FROM_HERE,
134         syncer::SyncError::DATATYPE_ERROR,
135         "Some error.",
136         syncer::SEARCH_ENGINES);
137
138   change_map_.erase(change_map_.begin(), change_map_.end());
139   for (syncer::SyncChangeList::const_iterator iter = change_list.begin();
140       iter != change_list.end(); ++iter)
141     change_map_[GetGUID(iter->sync_data())] = *iter;
142   return syncer::SyncError();
143 }
144
145
146 // SyncChangeProcessorDelegate ------------------------------------------------
147
148 class SyncChangeProcessorDelegate : public syncer::SyncChangeProcessor {
149  public:
150   explicit SyncChangeProcessorDelegate(syncer::SyncChangeProcessor* recipient);
151   virtual ~SyncChangeProcessorDelegate();
152
153   // syncer::SyncChangeProcessor implementation.
154   virtual syncer::SyncError ProcessSyncChanges(
155       const tracked_objects::Location& from_here,
156       const syncer::SyncChangeList& change_list) OVERRIDE;
157
158   virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
159       OVERRIDE {
160     return recipient_->GetAllSyncData(type);
161   }
162
163  private:
164   // The recipient of all sync changes.
165   syncer::SyncChangeProcessor* recipient_;
166
167   DISALLOW_COPY_AND_ASSIGN(SyncChangeProcessorDelegate);
168 };
169
170 SyncChangeProcessorDelegate::SyncChangeProcessorDelegate(
171     syncer::SyncChangeProcessor* recipient)
172     : recipient_(recipient) {
173   DCHECK(recipient_);
174 }
175
176 SyncChangeProcessorDelegate::~SyncChangeProcessorDelegate() {
177 }
178
179 syncer::SyncError SyncChangeProcessorDelegate::ProcessSyncChanges(
180     const tracked_objects::Location& from_here,
181     const syncer::SyncChangeList& change_list) {
182   return recipient_->ProcessSyncChanges(from_here, change_list);
183 }
184
185 }  // namespace
186
187
188 // TemplateURLServiceSyncTest -------------------------------------------------
189
190 class TemplateURLServiceSyncTest : public testing::Test {
191  public:
192   typedef TemplateURLService::SyncDataMap SyncDataMap;
193
194   TemplateURLServiceSyncTest();
195
196   virtual void SetUp() OVERRIDE;
197   virtual void TearDown() OVERRIDE;
198
199   TemplateURLService* model() { return test_util_a_.model(); }
200   // For readability, we redefine an accessor for Model A for use in tests that
201   // involve syncing two models.
202   TemplateURLService* model_a() { return test_util_a_.model(); }
203   TemplateURLService* model_b() { return model_b_.get(); }
204   TestingProfile* profile_a() { return test_util_a_.profile(); }
205   TestChangeProcessor* processor() { return sync_processor_.get(); }
206   scoped_ptr<syncer::SyncChangeProcessor> PassProcessor();
207   scoped_ptr<syncer::SyncErrorFactory> CreateAndPassSyncErrorFactory();
208
209   // Create a TemplateURL with some test values. The caller owns the returned
210   // TemplateURL*.
211   TemplateURL* CreateTestTemplateURL(const string16& keyword,
212                                      const std::string& url,
213                                      const std::string& guid = std::string(),
214                                      time_t last_mod = 100,
215                                      bool safe_for_autoreplace = false,
216                                      bool created_by_policy = false) const;
217
218   // Verifies the two TemplateURLs are equal.
219   // TODO(stevet): Share this with TemplateURLServiceTest.
220   void AssertEquals(const TemplateURL& expected,
221                     const TemplateURL& actual) const;
222
223   // Expect that two syncer::SyncDataLists have equal contents, in terms of the
224   // sync_guid, keyword, and url fields.
225   void AssertEquals(const syncer::SyncDataList& data1,
226                     const syncer::SyncDataList& data2) const;
227
228   // Convenience helper for creating SyncChanges. Takes ownership of |turl|.
229   syncer::SyncChange CreateTestSyncChange(
230       syncer::SyncChange::SyncChangeType type,
231       TemplateURL* turl) const;
232
233   // Helper that creates some initial sync data. We cheat a little by specifying
234   // GUIDs for easy identification later. We also make the last_modified times
235   // slightly older than CreateTestTemplateURL's default, to test conflict
236   // resolution.
237   syncer::SyncDataList CreateInitialSyncData() const;
238
239   // Syntactic sugar.
240   TemplateURL* Deserialize(const syncer::SyncData& sync_data);
241
242   // Creates a new TemplateURL copying the fields of |turl| but replacing
243   // the |url| and |guid| and initializing the date_created and last_modified
244   // timestamps to a default value of 100. The caller owns the returned
245   // TemplateURL*.
246   TemplateURL* CopyTemplateURL(const TemplateURL* turl,
247                                const std::string& url,
248                                const std::string& guid);
249
250  protected:
251   // We keep two TemplateURLServices to test syncing between them.
252   TemplateURLServiceTestUtil test_util_a_;
253   scoped_ptr<TestingProfile> profile_b_;
254   scoped_ptr<TemplateURLService> model_b_;
255
256   // Our dummy ChangeProcessor used to inspect changes pushed to Sync.
257   scoped_ptr<TestChangeProcessor> sync_processor_;
258   scoped_ptr<SyncChangeProcessorDelegate> sync_processor_delegate_;
259
260   DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceSyncTest);
261 };
262
263 TemplateURLServiceSyncTest::TemplateURLServiceSyncTest()
264     : sync_processor_(new TestChangeProcessor),
265       sync_processor_delegate_(new SyncChangeProcessorDelegate(
266           sync_processor_.get())) {
267 }
268
269 void TemplateURLServiceSyncTest::SetUp() {
270   test_util_a_.SetUp();
271   // Use ChangeToLoadState() instead of VerifyLoad() so we don't actually pull
272   // in the prepopulate data, which the sync tests don't care about (and would
273   // just foul them up).
274   test_util_a_.ChangeModelToLoadState();
275   profile_b_.reset(new TestingProfile);
276   TemplateURLServiceFactory::GetInstance()->RegisterUserPrefsOnBrowserContext(
277       profile_b_.get());
278   model_b_.reset(new TemplateURLService(profile_b_.get()));
279   model_b_->Load();
280 }
281
282 void TemplateURLServiceSyncTest::TearDown() {
283   test_util_a_.TearDown();
284 }
285
286 scoped_ptr<syncer::SyncChangeProcessor>
287 TemplateURLServiceSyncTest::PassProcessor() {
288   return sync_processor_delegate_.PassAs<syncer::SyncChangeProcessor>();
289 }
290
291 scoped_ptr<syncer::SyncErrorFactory> TemplateURLServiceSyncTest::
292     CreateAndPassSyncErrorFactory() {
293   return scoped_ptr<syncer::SyncErrorFactory>(
294       new syncer::SyncErrorFactoryMock());
295 }
296
297 TemplateURL* TemplateURLServiceSyncTest::CreateTestTemplateURL(
298     const string16& keyword,
299     const std::string& url,
300     const std::string& guid,
301     time_t last_mod,
302     bool safe_for_autoreplace,
303     bool created_by_policy) const {
304   TemplateURLData data;
305   data.short_name = ASCIIToUTF16("unittest");
306   data.SetKeyword(keyword);
307   data.SetURL(url);
308   data.favicon_url = GURL("http://favicon.url");
309   data.safe_for_autoreplace = safe_for_autoreplace;
310   data.date_created = Time::FromTimeT(100);
311   data.last_modified = Time::FromTimeT(last_mod);
312   data.created_by_policy = created_by_policy;
313   data.prepopulate_id = 999999;
314   if (!guid.empty())
315     data.sync_guid = guid;
316   return new TemplateURL(NULL, data);
317 }
318
319 void TemplateURLServiceSyncTest::AssertEquals(const TemplateURL& expected,
320                                               const TemplateURL& actual) const {
321   ASSERT_EQ(expected.short_name(), actual.short_name());
322   ASSERT_EQ(expected.keyword(), actual.keyword());
323   ASSERT_EQ(expected.url(), actual.url());
324   ASSERT_EQ(expected.suggestions_url(), actual.suggestions_url());
325   ASSERT_EQ(expected.favicon_url(), actual.favicon_url());
326   ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list());
327   ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace());
328   ASSERT_EQ(expected.input_encodings(), actual.input_encodings());
329   ASSERT_EQ(expected.date_created(), actual.date_created());
330   ASSERT_EQ(expected.last_modified(), actual.last_modified());
331 }
332
333 void TemplateURLServiceSyncTest::AssertEquals(
334     const syncer::SyncDataList& data1,
335     const syncer::SyncDataList& data2) const {
336   SyncDataMap map1 = TemplateURLService::CreateGUIDToSyncDataMap(data1);
337   SyncDataMap map2 = TemplateURLService::CreateGUIDToSyncDataMap(data2);
338
339   for (SyncDataMap::const_iterator iter1 = map1.begin();
340       iter1 != map1.end(); iter1++) {
341     SyncDataMap::iterator iter2 = map2.find(iter1->first);
342     if (iter2 != map2.end()) {
343       ASSERT_EQ(GetKeyword(iter1->second), GetKeyword(iter2->second));
344       ASSERT_EQ(GetURL(iter1->second), GetURL(iter2->second));
345       map2.erase(iter2);
346     }
347   }
348   EXPECT_EQ(0U, map2.size());
349 }
350
351 syncer::SyncChange TemplateURLServiceSyncTest::CreateTestSyncChange(
352     syncer::SyncChange::SyncChangeType type,
353     TemplateURL* turl) const {
354   // We take control of the TemplateURL so make sure it's cleaned up after
355   // we create data out of it.
356   scoped_ptr<TemplateURL> scoped_turl(turl);
357   return syncer::SyncChange(
358       FROM_HERE,
359       type,
360       TemplateURLService::CreateSyncDataFromTemplateURL(*scoped_turl));
361 }
362
363 syncer::SyncDataList TemplateURLServiceSyncTest::CreateInitialSyncData() const {
364   syncer::SyncDataList list;
365
366   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
367       "http://key1.com", "key1", 90));
368   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
369   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com",
370                                    "key2", 90));
371   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
372   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com",
373                                    "key3", 90));
374   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
375
376   return list;
377 }
378
379 TemplateURL* TemplateURLServiceSyncTest::Deserialize(
380     const syncer::SyncData& sync_data) {
381   syncer::SyncChangeList dummy;
382   return TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData(NULL,
383       NULL, sync_data, &dummy);
384 }
385
386 TemplateURL* TemplateURLServiceSyncTest::CopyTemplateURL(
387     const TemplateURL* turl,
388     const std::string& url,
389     const std::string& guid) {
390   TemplateURLData data (turl->data());
391   data.SetURL(url);
392   data.date_created = Time::FromTimeT(100);
393   data.last_modified = Time::FromTimeT(100);
394   data.sync_guid = guid;
395   return new TemplateURL(NULL, data);
396 }
397
398 // Actual tests ---------------------------------------------------------------
399
400 TEST_F(TemplateURLServiceSyncTest, SerializeDeserialize) {
401   // Create a TemplateURL and convert it into a sync specific type.
402   scoped_ptr<TemplateURL> turl(
403       CreateTestTemplateURL(
404           ASCIIToUTF16("unittest"), "http://www.unittest.com/"));
405   syncer::SyncData sync_data =
406       TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
407   // Convert the specifics back to a TemplateURL.
408   scoped_ptr<TemplateURL> deserialized(Deserialize(sync_data));
409   EXPECT_TRUE(deserialized.get());
410   // Ensure that the original and the deserialized TURLs are equal in values.
411   AssertEquals(*turl, *deserialized);
412 }
413
414 TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataBasic) {
415   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
416   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
417   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com"));
418   syncer::SyncDataList all_sync_data =
419       model()->GetAllSyncData(syncer::SEARCH_ENGINES);
420
421   EXPECT_EQ(3U, all_sync_data.size());
422
423   for (syncer::SyncDataList::const_iterator iter = all_sync_data.begin();
424       iter != all_sync_data.end(); ++iter) {
425     std::string guid = GetGUID(*iter);
426     const TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid);
427     scoped_ptr<TemplateURL> deserialized(Deserialize(*iter));
428     AssertEquals(*service_turl, *deserialized);
429   }
430 }
431
432 TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataWithExtension) {
433   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
434   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
435   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key3"),
436       std::string(extensions::kExtensionScheme) + "://blahblahblah"));
437   syncer::SyncDataList all_sync_data =
438       model()->GetAllSyncData(syncer::SEARCH_ENGINES);
439
440   EXPECT_EQ(3U, all_sync_data.size());
441
442   for (syncer::SyncDataList::const_iterator iter = all_sync_data.begin();
443       iter != all_sync_data.end(); ++iter) {
444     std::string guid = GetGUID(*iter);
445     const TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid);
446     scoped_ptr<TemplateURL> deserialized(Deserialize(*iter));
447     AssertEquals(*service_turl, *deserialized);
448   }
449 }
450
451 TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataNoManagedEngines) {
452   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
453   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
454   TemplateURL* managed_turl = CreateTestTemplateURL(ASCIIToUTF16("key3"),
455       "http://key3.com", std::string(), 100, false, true);
456   model()->Add(managed_turl);
457   syncer::SyncDataList all_sync_data =
458       model()->GetAllSyncData(syncer::SEARCH_ENGINES);
459
460   EXPECT_EQ(2U, all_sync_data.size());
461
462   for (syncer::SyncDataList::const_iterator iter = all_sync_data.begin();
463       iter != all_sync_data.end(); ++iter) {
464     std::string guid = GetGUID(*iter);
465     TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid);
466     scoped_ptr<TemplateURL> deserialized(Deserialize(*iter));
467     ASSERT_FALSE(service_turl->created_by_policy());
468     AssertEquals(*service_turl, *deserialized);
469   }
470 }
471
472 TEST_F(TemplateURLServiceSyncTest, UniquifyKeyword) {
473   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
474   // Create a key that conflicts with something in the model.
475   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
476                                                      "http://new.com", "xyz"));
477   string16 new_keyword = model()->UniquifyKeyword(*turl, false);
478   EXPECT_EQ(ASCIIToUTF16("new.com"), new_keyword);
479   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
480   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("new.com"), "http://new.com",
481                                      "xyz"));
482
483   // Test a second collision. This time it should be resolved by actually
484   // modifying the original keyword, since the autogenerated keyword is already
485   // used.
486   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://new.com"));
487   new_keyword = model()->UniquifyKeyword(*turl, false);
488   EXPECT_EQ(ASCIIToUTF16("key1_"), new_keyword);
489   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
490   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1_"), "http://new.com"));
491
492   // Test a third collision. This should collide on both the autogenerated
493   // keyword and the first uniquification attempt.
494   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://new.com"));
495   new_keyword = model()->UniquifyKeyword(*turl, false);
496   EXPECT_EQ(ASCIIToUTF16("key1__"), new_keyword);
497   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
498
499   // If we force the method, it should uniquify the keyword even if it is
500   // currently unique, and skip the host-based autogenerated keyword.
501   turl.reset(
502       CreateTestTemplateURL(ASCIIToUTF16("unique"), "http://unique.com"));
503   new_keyword = model()->UniquifyKeyword(*turl, true);
504   EXPECT_EQ(ASCIIToUTF16("unique_"), new_keyword);
505   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
506 }
507
508 TEST_F(TemplateURLServiceSyncTest, IsLocalTemplateURLBetter) {
509   // Test some edge cases of this function.
510   const struct {
511     time_t local_time;
512     time_t sync_time;
513     bool local_is_default;
514     bool local_created_by_policy;
515     bool expected_result;
516   } test_cases[] = {
517     // Sync is better by timestamp but local is Default.
518     {10, 100, true, false, true},
519     // Sync is better by timestamp but local is Create by Policy.
520     {10, 100, false, true, true},
521     // Tie. Sync wins.
522     {100, 100, false, false, false},
523   };
524
525   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
526     TemplateURL* local_turl = CreateTestTemplateURL(
527         ASCIIToUTF16("localkey"), "www.local.com", "localguid",
528         test_cases[i].local_time, true, test_cases[i].local_created_by_policy);
529     model()->Add(local_turl);
530     if (test_cases[i].local_is_default)
531       model()->SetDefaultSearchProvider(local_turl);
532
533     scoped_ptr<TemplateURL> sync_turl(CreateTestTemplateURL(
534           ASCIIToUTF16("synckey"), "www.sync.com", "syncguid",
535           test_cases[i].sync_time));
536     EXPECT_EQ(test_cases[i].expected_result,
537         model()->IsLocalTemplateURLBetter(local_turl, sync_turl.get()));
538
539     // Undo the changes.
540     if (test_cases[i].local_is_default)
541       model()->SetDefaultSearchProvider(NULL);
542     model()->Remove(local_turl);
543   }
544 }
545
546 TEST_F(TemplateURLServiceSyncTest, ResolveSyncKeywordConflict) {
547   // This tests cases where neither the sync nor the local TemplateURL are
548   // marked safe_for_autoreplace.
549
550   // Create a keyword that conflicts, and make it older.  Sync keyword is
551   // uniquified, and a syncer::SyncChange is added.
552   string16 original_turl_keyword = ASCIIToUTF16("key1");
553   TemplateURL* original_turl = CreateTestTemplateURL(original_turl_keyword,
554       "http://key1.com", std::string(), 9000);
555   model()->Add(original_turl);
556   scoped_ptr<TemplateURL> sync_turl(CreateTestTemplateURL(original_turl_keyword,
557       "http://new.com", "remote", 8999));
558   syncer::SyncChangeList changes;
559   model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
560   EXPECT_NE(original_turl_keyword, sync_turl->keyword());
561   EXPECT_EQ(original_turl_keyword, original_turl->keyword());
562   ASSERT_EQ(1U, changes.size());
563   EXPECT_EQ("remote", GetGUID(changes[0].sync_data()));
564   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
565   changes.clear();
566   model()->Remove(original_turl);
567
568   // Sync is newer.  Original TemplateURL keyword is uniquified.  A SyncChange
569   // is added (which in a normal run would be deleted by PruneSyncChanges() when
570   // the local GUID doesn't appear in the sync GUID list).  Also ensure that
571   // this does not change the safe_for_autoreplace flag or the TemplateURLID in
572   // the original.
573   original_turl = CreateTestTemplateURL(original_turl_keyword,
574                                         "http://key1.com", "local", 9000);
575   model()->Add(original_turl);
576   TemplateURLID original_id = original_turl->id();
577   sync_turl.reset(CreateTestTemplateURL(original_turl_keyword, "http://new.com",
578                                         std::string(), 9001));
579   model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
580   EXPECT_EQ(original_turl_keyword, sync_turl->keyword());
581   EXPECT_NE(original_turl_keyword, original_turl->keyword());
582   EXPECT_FALSE(original_turl->safe_for_autoreplace());
583   EXPECT_EQ(original_id, original_turl->id());
584   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(original_turl_keyword));
585   ASSERT_EQ(1U, changes.size());
586   EXPECT_EQ("local", GetGUID(changes[0].sync_data()));
587   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
588   changes.clear();
589   model()->Remove(original_turl);
590
591   // Equal times. Same result as above. Sync left alone, original uniquified so
592   // sync_turl can fit.
593   original_turl = CreateTestTemplateURL(original_turl_keyword,
594                                         "http://key1.com", "local2", 9000);
595   model()->Add(original_turl);
596   sync_turl.reset(CreateTestTemplateURL(original_turl_keyword, "http://new.com",
597                                         std::string(), 9000));
598   model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
599   EXPECT_EQ(original_turl_keyword, sync_turl->keyword());
600   EXPECT_NE(original_turl_keyword, original_turl->keyword());
601   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(original_turl_keyword));
602   ASSERT_EQ(1U, changes.size());
603   EXPECT_EQ("local2", GetGUID(changes[0].sync_data()));
604   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
605   changes.clear();
606   model()->Remove(original_turl);
607
608   // Sync is newer, but original TemplateURL is created by policy, so it wins.
609   // Sync keyword is uniquified, and a syncer::SyncChange is added.
610   original_turl = CreateTestTemplateURL(original_turl_keyword,
611       "http://key1.com", std::string(), 9000, false, true);
612   model()->Add(original_turl);
613   sync_turl.reset(CreateTestTemplateURL(original_turl_keyword, "http://new.com",
614                                         "remote2", 9999));
615   model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
616   EXPECT_NE(original_turl_keyword, sync_turl->keyword());
617   EXPECT_EQ(original_turl_keyword, original_turl->keyword());
618   EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(sync_turl->keyword()));
619   ASSERT_EQ(1U, changes.size());
620   EXPECT_EQ("remote2", GetGUID(changes[0].sync_data()));
621   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
622   changes.clear();
623   model()->Remove(original_turl);
624 }
625
626 TEST_F(TemplateURLServiceSyncTest, StartSyncEmpty) {
627   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
628       syncer::SEARCH_ENGINES, syncer::SyncDataList(),
629       PassProcessor(), CreateAndPassSyncErrorFactory());
630
631   EXPECT_EQ(0U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
632   EXPECT_EQ(0U, processor()->change_list_size());
633   EXPECT_EQ(0, merge_result.num_items_added());
634   EXPECT_EQ(0, merge_result.num_items_modified());
635   EXPECT_EQ(0, merge_result.num_items_deleted());
636   EXPECT_EQ(0, merge_result.num_items_before_association());
637   EXPECT_EQ(0, merge_result.num_items_after_association());
638 }
639
640 TEST_F(TemplateURLServiceSyncTest, MergeIntoEmpty) {
641   syncer::SyncDataList initial_data = CreateInitialSyncData();
642
643   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
644       syncer::SEARCH_ENGINES, initial_data,
645       PassProcessor(), CreateAndPassSyncErrorFactory());
646
647   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
648   // We expect the model to have accepted all of the initial sync data. Search
649   // through the model using the GUIDs to ensure that they're present.
650   for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
651       iter != initial_data.end(); ++iter) {
652     std::string guid = GetGUID(*iter);
653     EXPECT_TRUE(model()->GetTemplateURLForGUID(guid));
654   }
655
656   EXPECT_EQ(0U, processor()->change_list_size());
657
658   // Locally the three new TemplateURL's should have been added.
659   EXPECT_EQ(3, merge_result.num_items_added());
660   EXPECT_EQ(0, merge_result.num_items_modified());
661   EXPECT_EQ(0, merge_result.num_items_deleted());
662   EXPECT_EQ(0, merge_result.num_items_before_association());
663   EXPECT_EQ(3, merge_result.num_items_after_association());
664 }
665
666 TEST_F(TemplateURLServiceSyncTest, MergeInAllNewData) {
667   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("abc.com"), "http://abc.com",
668                                      "abc"));
669   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("def.com"), "http://def.com",
670                                      "def"));
671   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("xyz.com"), "http://xyz.com",
672                                      "xyz"));
673   syncer::SyncDataList initial_data = CreateInitialSyncData();
674
675   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
676       syncer::SEARCH_ENGINES, initial_data,
677       PassProcessor(), CreateAndPassSyncErrorFactory());
678
679   EXPECT_EQ(6U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
680   // We expect the model to have accepted all of the initial sync data. Search
681   // through the model using the GUIDs to ensure that they're present.
682   for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
683       iter != initial_data.end(); ++iter) {
684     std::string guid = GetGUID(*iter);
685     EXPECT_TRUE(model()->GetTemplateURLForGUID(guid));
686   }
687   // All the original TemplateURLs should also remain in the model.
688   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("abc.com")));
689   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("def.com")));
690   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("xyz.com")));
691   // Ensure that Sync received the expected changes.
692   EXPECT_EQ(3U, processor()->change_list_size());
693   EXPECT_TRUE(processor()->contains_guid("abc"));
694   EXPECT_TRUE(processor()->contains_guid("def"));
695   EXPECT_TRUE(processor()->contains_guid("xyz"));
696
697   // Locally the three new TemplateURL's should have been added.
698   EXPECT_EQ(3, merge_result.num_items_added());
699   EXPECT_EQ(0, merge_result.num_items_modified());
700   EXPECT_EQ(0, merge_result.num_items_deleted());
701   EXPECT_EQ(3, merge_result.num_items_before_association());
702   EXPECT_EQ(6, merge_result.num_items_after_association());
703 }
704
705 TEST_F(TemplateURLServiceSyncTest, MergeSyncIsTheSame) {
706   // The local data is the same as the sync data merged in. i.e. - There have
707   // been no changes since the last time we synced. Even the last_modified
708   // timestamps are the same.
709   syncer::SyncDataList initial_data = CreateInitialSyncData();
710   for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
711       iter != initial_data.end(); ++iter) {
712     TemplateURL* converted = Deserialize(*iter);
713     model()->Add(converted);
714   }
715
716   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
717       syncer::SEARCH_ENGINES, initial_data,
718       PassProcessor(), CreateAndPassSyncErrorFactory());
719
720   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
721   for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
722       iter != initial_data.end(); ++iter) {
723     std::string guid = GetGUID(*iter);
724     EXPECT_TRUE(model()->GetTemplateURLForGUID(guid));
725   }
726   EXPECT_EQ(0U, processor()->change_list_size());
727
728   // Locally everything should remain the same.
729   EXPECT_EQ(0, merge_result.num_items_added());
730   EXPECT_EQ(0, merge_result.num_items_modified());
731   EXPECT_EQ(0, merge_result.num_items_deleted());
732   EXPECT_EQ(3, merge_result.num_items_before_association());
733   EXPECT_EQ(3, merge_result.num_items_after_association());
734 }
735
736 TEST_F(TemplateURLServiceSyncTest, MergeUpdateFromSync) {
737   // The local data is the same as the sync data merged in, but timestamps have
738   // changed. Ensure the right fields are merged in.
739   syncer::SyncDataList initial_data;
740   TemplateURL* turl1 = CreateTestTemplateURL(ASCIIToUTF16("abc.com"),
741                                              "http://abc.com", "abc", 9000);
742   model()->Add(turl1);
743   TemplateURL* turl2 = CreateTestTemplateURL(ASCIIToUTF16("xyz.com"),
744                                              "http://xyz.com", "xyz", 9000);
745   model()->Add(turl2);
746
747   scoped_ptr<TemplateURL> turl1_newer(CreateTestTemplateURL(
748       ASCIIToUTF16("abc.com"), "http://abc.ca", "abc", 9999));
749   initial_data.push_back(
750       TemplateURLService::CreateSyncDataFromTemplateURL(*turl1_newer));
751
752   scoped_ptr<TemplateURL> turl2_older(CreateTestTemplateURL(
753       ASCIIToUTF16("xyz.com"), "http://xyz.ca", "xyz", 8888));
754   initial_data.push_back(
755       TemplateURLService::CreateSyncDataFromTemplateURL(*turl2_older));
756
757   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
758       syncer::SEARCH_ENGINES, initial_data,
759       PassProcessor(), CreateAndPassSyncErrorFactory());
760
761   // Both were local updates, so we expect the same count.
762   EXPECT_EQ(2U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
763
764   // Check that the first replaced the initial abc TemplateURL.
765   EXPECT_EQ(turl1, model()->GetTemplateURLForGUID("abc"));
766   EXPECT_EQ("http://abc.ca", turl1->url());
767
768   // Check that the second produced an upstream update to the xyz TemplateURL.
769   EXPECT_EQ(1U, processor()->change_list_size());
770   ASSERT_TRUE(processor()->contains_guid("xyz"));
771   syncer::SyncChange change = processor()->change_for_guid("xyz");
772   EXPECT_TRUE(change.change_type() == syncer::SyncChange::ACTION_UPDATE);
773   EXPECT_EQ("http://xyz.com", GetURL(change.sync_data()));
774
775   // Locally only the older item should have been modified.
776   EXPECT_EQ(0, merge_result.num_items_added());
777   EXPECT_EQ(1, merge_result.num_items_modified());
778   EXPECT_EQ(0, merge_result.num_items_deleted());
779   EXPECT_EQ(2, merge_result.num_items_before_association());
780   EXPECT_EQ(2, merge_result.num_items_after_association());
781 }
782
783 TEST_F(TemplateURLServiceSyncTest, MergeAddFromOlderSyncData) {
784   // GUIDs all differ, so this is data to be added from Sync, but the timestamps
785   // from Sync are older. Set up the local data so that one is a dupe, one has a
786   // conflicting keyword, and the last has no conflicts (a clean ADD).
787   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com",
788                                      "aaa", 100));  // dupe
789
790   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"),
791       "http://expected.com", "bbb", 100));  // keyword conflict
792
793   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("unique"),
794                                      "http://unique.com", "ccc"));  // add
795
796   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
797       syncer::SEARCH_ENGINES,
798       CreateInitialSyncData(), PassProcessor(),
799       CreateAndPassSyncErrorFactory());
800
801   // The dupe and conflict results in merges, as local values are always merged
802   // with sync values if there is a keyword conflict. The unique keyword should
803   // be added.
804   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
805
806   // The key1 duplicate results in the local copy winning. Ensure that Sync's
807   // copy was not added, and the local copy is pushed upstream to Sync as an
808   // update. The local copy should have received the sync data's GUID.
809   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
810   // Check changes for the UPDATE.
811   ASSERT_TRUE(processor()->contains_guid("key1"));
812   syncer::SyncChange key1_change = processor()->change_for_guid("key1");
813   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key1_change.change_type());
814   // The local sync_guid should no longer be found.
815   EXPECT_FALSE(model()->GetTemplateURLForGUID("aaa"));
816
817   // The key2 keyword conflict results in a merge, with the values of the local
818   // copy winning, so ensure it retains the original URL, and that an update to
819   // the sync guid is pushed upstream to Sync.
820   const TemplateURL* key2 = model()->GetTemplateURLForGUID("key2");
821   ASSERT_TRUE(key2);
822   EXPECT_EQ(ASCIIToUTF16("key2"), key2->keyword());
823   EXPECT_EQ("http://expected.com", key2->url());
824   // Check changes for the UPDATE.
825   ASSERT_TRUE(processor()->contains_guid("key2"));
826   syncer::SyncChange key2_change = processor()->change_for_guid("key2");
827   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key2_change.change_type());
828   EXPECT_EQ("key2", GetKeyword(key2_change.sync_data()));
829   EXPECT_EQ("http://expected.com", GetURL(key2_change.sync_data()));
830   // The local sync_guid should no longer be found.
831   EXPECT_FALSE(model()->GetTemplateURLForGUID("bbb"));
832
833   // The last TemplateURL should have had no conflicts and was just added. It
834   // should not have replaced the third local TemplateURL.
835   EXPECT_TRUE(model()->GetTemplateURLForGUID("ccc"));
836   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
837
838   // Two UPDATEs and one ADD.
839   EXPECT_EQ(3U, processor()->change_list_size());
840   // One ADDs should be pushed up to Sync.
841   ASSERT_TRUE(processor()->contains_guid("ccc"));
842   EXPECT_EQ(syncer::SyncChange::ACTION_ADD,
843             processor()->change_for_guid("ccc").change_type());
844
845   // All the sync items had new guids, but only one doesn't conflict and is
846   // added. The other two conflicting cases result in local modifications
847   // to override the local guids but preserve the local data.
848   EXPECT_EQ(1, merge_result.num_items_added());
849   EXPECT_EQ(2, merge_result.num_items_modified());
850   EXPECT_EQ(0, merge_result.num_items_deleted());
851   EXPECT_EQ(3, merge_result.num_items_before_association());
852   EXPECT_EQ(4, merge_result.num_items_after_association());
853 }
854
855 TEST_F(TemplateURLServiceSyncTest, MergeAddFromNewerSyncData) {
856   // GUIDs all differ, so Sync may overtake some entries, but the timestamps
857   // from Sync are newer. Set up the local data so that one is a dupe, one has a
858   // conflicting keyword, and the last has no conflicts (a clean ADD).
859   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com",
860                                      "aaa", 10));  // dupe
861
862   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"),
863       "http://expected.com", "bbb", 10));  // keyword conflict
864
865   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("unique"),
866                                      "http://unique.com", "ccc", 10));  // add
867
868   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
869       syncer::SEARCH_ENGINES,
870       CreateInitialSyncData(), PassProcessor(),
871       CreateAndPassSyncErrorFactory());
872
873   // The dupe and keyword conflict results in merges. The unique keyword be
874   // added to the model.
875   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
876
877   // The key1 duplicate results in Sync's copy winning. Ensure that Sync's
878   // copy replaced the local copy.
879   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
880   EXPECT_FALSE(model()->GetTemplateURLForGUID("aaa"));
881   EXPECT_FALSE(processor()->contains_guid("key1"));
882   EXPECT_FALSE(processor()->contains_guid("aaa"));
883
884   // The key2 keyword conflict results in Sync's copy winning, so ensure it
885   // retains the original keyword and is added. The local copy should be
886   // removed.
887   const TemplateURL* key2_sync = model()->GetTemplateURLForGUID("key2");
888   ASSERT_TRUE(key2_sync);
889   EXPECT_EQ(ASCIIToUTF16("key2"), key2_sync->keyword());
890   EXPECT_FALSE(model()->GetTemplateURLForGUID("bbb"));
891
892   // The last TemplateURL should have had no conflicts and was just added. It
893   // should not have replaced the third local TemplateURL.
894   EXPECT_TRUE(model()->GetTemplateURLForGUID("ccc"));
895   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
896
897   // One ADD.
898   EXPECT_EQ(1U, processor()->change_list_size());
899   // One ADDs should be pushed up to Sync.
900   ASSERT_TRUE(processor()->contains_guid("ccc"));
901   EXPECT_EQ(syncer::SyncChange::ACTION_ADD,
902             processor()->change_for_guid("ccc").change_type());
903
904   // One of the sync items is added directly without conflict. The other two
905   // conflict but are newer than the local items so are added while the local
906   // is deleted.
907   EXPECT_EQ(3, merge_result.num_items_added());
908   EXPECT_EQ(0, merge_result.num_items_modified());
909   EXPECT_EQ(2, merge_result.num_items_deleted());
910   EXPECT_EQ(3, merge_result.num_items_before_association());
911   EXPECT_EQ(4, merge_result.num_items_after_association());
912 }
913
914 TEST_F(TemplateURLServiceSyncTest, ProcessChangesEmptyModel) {
915   // We initially have no data.
916   model()->MergeDataAndStartSyncing(
917       syncer::SEARCH_ENGINES, syncer::SyncDataList(),
918       PassProcessor(), CreateAndPassSyncErrorFactory());
919
920   // Set up a bunch of ADDs.
921   syncer::SyncChangeList changes;
922   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
923       CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com", "key1")));
924   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
925       CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com", "key2")));
926   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
927       CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key3")));
928
929   model()->ProcessSyncChanges(FROM_HERE, changes);
930
931   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
932   EXPECT_EQ(0U, processor()->change_list_size());
933   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
934   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
935   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
936 }
937
938 TEST_F(TemplateURLServiceSyncTest, ProcessChangesNoConflicts) {
939   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
940                                     CreateInitialSyncData(), PassProcessor(),
941                                     CreateAndPassSyncErrorFactory());
942
943   // Process different types of changes, without conflicts.
944   syncer::SyncChangeList changes;
945   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
946       CreateTestTemplateURL(ASCIIToUTF16("key4"), "http://key4.com", "key4")));
947   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
948       CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
949                             "key2")));
950   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_DELETE,
951       CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key3")));
952
953   model()->ProcessSyncChanges(FROM_HERE, changes);
954
955   // Add one, remove one, update one, so the number shouldn't change.
956   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
957   EXPECT_EQ(0U, processor()->change_list_size());
958   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
959   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
960   const TemplateURL* turl = model()->GetTemplateURLForGUID("key2");
961   EXPECT_TRUE(turl);
962   EXPECT_EQ(ASCIIToUTF16("newkeyword"), turl->keyword());
963   EXPECT_EQ("http://new.com", turl->url());
964   EXPECT_FALSE(model()->GetTemplateURLForGUID("key3"));
965   EXPECT_TRUE(model()->GetTemplateURLForGUID("key4"));
966 }
967
968 TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithConflictsSyncWins) {
969   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
970                                     CreateInitialSyncData(), PassProcessor(),
971                                     CreateAndPassSyncErrorFactory());
972
973   // Process different types of changes, with conflicts. Note that all this data
974   // has a newer timestamp, so Sync will win in these scenarios.
975   syncer::SyncChangeList changes;
976   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
977       CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://new.com", "aaa")));
978   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
979       CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key1")));
980
981   model()->ProcessSyncChanges(FROM_HERE, changes);
982
983   // Add one, update one, so we're up to 4.
984   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
985   // Sync is always newer here, so it should always win.  We should create
986   // SyncChanges for the changes to the local entities, since they're synced
987   // too.
988   EXPECT_EQ(2U, processor()->change_list_size());
989   ASSERT_TRUE(processor()->contains_guid("key2"));
990   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
991             processor()->change_for_guid("key2").change_type());
992   ASSERT_TRUE(processor()->contains_guid("key3"));
993   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
994             processor()->change_for_guid("key3").change_type());
995
996   // aaa conflicts with key2 and wins, forcing key2's keyword to update.
997   EXPECT_TRUE(model()->GetTemplateURLForGUID("aaa"));
998   EXPECT_EQ(model()->GetTemplateURLForGUID("aaa"),
999             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key2")));
1000   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
1001   EXPECT_EQ(model()->GetTemplateURLForGUID("key2"),
1002             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key2.com")));
1003   // key1 update conflicts with key3 and wins, forcing key3's keyword to update.
1004   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
1005   EXPECT_EQ(model()->GetTemplateURLForGUID("key1"),
1006             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3")));
1007   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
1008   EXPECT_EQ(model()->GetTemplateURLForGUID("key3"),
1009             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3.com")));
1010 }
1011
1012 TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithConflictsLocalWins) {
1013   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
1014                                     CreateInitialSyncData(), PassProcessor(),
1015                                     CreateAndPassSyncErrorFactory());
1016
1017   // Process different types of changes, with conflicts. Note that all this data
1018   // has an older timestamp, so the local data will win in these scenarios.
1019   syncer::SyncChangeList changes;
1020   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
1021       CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://new.com", "aaa",
1022                             10)));
1023   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
1024       CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key1",
1025                             10)));
1026
1027   model()->ProcessSyncChanges(FROM_HERE, changes);
1028
1029   // Add one, update one, so we're up to 4.
1030   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1031   // Local data wins twice so two updates are pushed up to Sync.
1032   EXPECT_EQ(2U, processor()->change_list_size());
1033
1034   // aaa conflicts with key2 and loses, forcing it's keyword to update.
1035   EXPECT_TRUE(model()->GetTemplateURLForGUID("aaa"));
1036   EXPECT_EQ(model()->GetTemplateURLForGUID("aaa"),
1037             model()->GetTemplateURLForKeyword(ASCIIToUTF16("new.com")));
1038   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
1039   EXPECT_EQ(model()->GetTemplateURLForGUID("key2"),
1040             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key2")));
1041   // key1 update conflicts with key3 and loses, forcing key1's keyword to
1042   // update.
1043   EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
1044   EXPECT_EQ(model()->GetTemplateURLForGUID("key1"),
1045             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3.com")));
1046   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
1047   EXPECT_EQ(model()->GetTemplateURLForGUID("key3"),
1048             model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3")));
1049
1050   ASSERT_TRUE(processor()->contains_guid("aaa"));
1051   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
1052             processor()->change_for_guid("aaa").change_type());
1053   ASSERT_TRUE(processor()->contains_guid("key1"));
1054   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
1055             processor()->change_for_guid("key1").change_type());
1056 }
1057
1058 TEST_F(TemplateURLServiceSyncTest, ProcessTemplateURLChange) {
1059   // Ensure that ProcessTemplateURLChange is called and pushes the correct
1060   // changes to Sync whenever local changes are made to TemplateURLs.
1061   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
1062                                     CreateInitialSyncData(), PassProcessor(),
1063                                     CreateAndPassSyncErrorFactory());
1064
1065   // Add a new search engine.
1066   TemplateURL* new_turl =
1067       CreateTestTemplateURL(ASCIIToUTF16("baidu"), "http://baidu.cn", "new");
1068   model()->Add(new_turl);
1069   EXPECT_EQ(1U, processor()->change_list_size());
1070   ASSERT_TRUE(processor()->contains_guid("new"));
1071   syncer::SyncChange change = processor()->change_for_guid("new");
1072   EXPECT_EQ(syncer::SyncChange::ACTION_ADD, change.change_type());
1073   EXPECT_EQ("baidu", GetKeyword(change.sync_data()));
1074   EXPECT_EQ("http://baidu.cn", GetURL(change.sync_data()));
1075
1076   // Change a keyword.
1077   TemplateURL* existing_turl = model()->GetTemplateURLForGUID("key1");
1078   model()->ResetTemplateURL(existing_turl, existing_turl->short_name(),
1079                             ASCIIToUTF16("k"), existing_turl->url());
1080   EXPECT_EQ(1U, processor()->change_list_size());
1081   ASSERT_TRUE(processor()->contains_guid("key1"));
1082   change = processor()->change_for_guid("key1");
1083   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
1084   EXPECT_EQ("k", GetKeyword(change.sync_data()));
1085
1086   // Remove an existing search engine.
1087   existing_turl = model()->GetTemplateURLForGUID("key2");
1088   model()->Remove(existing_turl);
1089   EXPECT_EQ(1U, processor()->change_list_size());
1090   ASSERT_TRUE(processor()->contains_guid("key2"));
1091   change = processor()->change_for_guid("key2");
1092   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, change.change_type());
1093 }
1094
1095 TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithLocalExtensions) {
1096   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
1097                                     CreateInitialSyncData(), PassProcessor(),
1098                                     CreateAndPassSyncErrorFactory());
1099
1100   // Add some extension keywords locally.
1101   TemplateURL* extension1 = CreateTestTemplateURL(ASCIIToUTF16("keyword1"),
1102       std::string(extensions::kExtensionScheme) + "://extension1");
1103   model()->Add(extension1);
1104   EXPECT_EQ(1U, processor()->change_list_size());
1105   TemplateURL* extension2 = CreateTestTemplateURL(ASCIIToUTF16("keyword2"),
1106       std::string(extensions::kExtensionScheme) + "://extension2");
1107   model()->Add(extension2);
1108   EXPECT_EQ(1U, processor()->change_list_size());
1109
1110   // Create some sync changes that will conflict with the extension keywords.
1111   syncer::SyncChangeList changes;
1112   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
1113     CreateTestTemplateURL(ASCIIToUTF16("keyword1"), "http://aaa.com",
1114                           std::string(), 100, true)));
1115   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
1116     CreateTestTemplateURL(ASCIIToUTF16("keyword2"), "http://bbb.com")));
1117   model()->ProcessSyncChanges(FROM_HERE, changes);
1118
1119   // The existing extension keywords should be uniquified.
1120   EXPECT_FALSE(model()->GetTemplateURLForHost("aaa.com") == NULL);
1121   EXPECT_EQ(model()->GetTemplateURLForHost("aaa.com"),
1122             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1")));
1123   TemplateURL* url_for_keyword2 =
1124       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2"));
1125   EXPECT_NE(extension2, url_for_keyword2);
1126   EXPECT_EQ("http://bbb.com", url_for_keyword2->url());
1127
1128   // Replaced extension keywords should be uniquified.
1129   EXPECT_EQ(extension1,
1130             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1_")));
1131   EXPECT_EQ(extension2,
1132             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2_")));
1133 }
1134
1135 TEST_F(TemplateURLServiceSyncTest, AutogeneratedKeywordMigrated) {
1136   // Create a couple of sync entries with autogenerated keywords.
1137   syncer::SyncDataList initial_data;
1138   scoped_ptr<TemplateURL> turl(
1139       CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com", "key1"));
1140   initial_data.push_back(
1141       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
1142   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"),
1143       "{google:baseURL}search?q={searchTerms}", "key2"));
1144   initial_data.push_back(
1145       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
1146
1147   // Now try to sync the data locally.
1148   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1149       PassProcessor(), CreateAndPassSyncErrorFactory());
1150
1151   // Both entries should have been added, with explicit keywords.
1152   TemplateURL* key1 = model()->GetTemplateURLForHost("key1.com");
1153   ASSERT_FALSE(key1 == NULL);
1154   EXPECT_EQ(ASCIIToUTF16("key1.com"), key1->keyword());
1155   GURL google_url(UIThreadSearchTermsData(profile_a()).GoogleBaseURLValue());
1156   TemplateURL* key2 = model()->GetTemplateURLForHost(google_url.host());
1157   ASSERT_FALSE(key2 == NULL);
1158   string16 google_keyword(net::StripWWWFromHost(google_url));
1159   EXPECT_EQ(google_keyword, key2->keyword());
1160
1161   // We should also have gotten some corresponding UPDATEs pushed upstream.
1162   EXPECT_GE(processor()->change_list_size(), 2U);
1163   ASSERT_TRUE(processor()->contains_guid("key1"));
1164   syncer::SyncChange key1_change = processor()->change_for_guid("key1");
1165   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key1_change.change_type());
1166   EXPECT_EQ("key1.com", GetKeyword(key1_change.sync_data()));
1167   ASSERT_TRUE(processor()->contains_guid("key2"));
1168   syncer::SyncChange key2_change = processor()->change_for_guid("key2");
1169   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key2_change.change_type());
1170   EXPECT_EQ(google_keyword, UTF8ToUTF16(GetKeyword(key2_change.sync_data())));
1171 }
1172
1173 TEST_F(TemplateURLServiceSyncTest, AutogeneratedKeywordConflicts) {
1174   // Sync brings in some autogenerated keywords, but the generated keywords we
1175   // try to create conflict with ones in the model.
1176   string16 google_keyword(net::StripWWWFromHost(GURL(
1177       UIThreadSearchTermsData(profile_a()).GoogleBaseURLValue())));
1178   const std::string local_google_url =
1179       "{google:baseURL}1/search?q={searchTerms}";
1180   TemplateURL* google = CreateTestTemplateURL(google_keyword, local_google_url);
1181   model()->Add(google);
1182   TemplateURL* other =
1183       CreateTestTemplateURL(ASCIIToUTF16("other.com"), "http://other.com/foo");
1184   model()->Add(other);
1185   syncer::SyncDataList initial_data;
1186   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("sync1"),
1187       "{google:baseURL}2/search?q={searchTerms}", "sync1", 50));
1188   initial_data.push_back(
1189       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
1190   const std::string synced_other_url =
1191       "http://other.com/search?q={searchTerms}";
1192   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("sync2"),
1193       synced_other_url, "sync2", 150));
1194   initial_data.push_back(
1195       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
1196
1197   // Before we merge the data, grab the local sync_guids so we can ensure that
1198   // they've been replaced.
1199   const std::string local_google_guid = google->sync_guid();
1200   const std::string local_other_guid = other->sync_guid();
1201
1202   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1203       PassProcessor(), CreateAndPassSyncErrorFactory());
1204
1205   // In this case, the conflicts should be handled just like any other keyword
1206   // conflicts -- the later-modified TemplateURL is assumed to be authoritative.
1207   // Since the initial TemplateURLs were local only, they should be merged with
1208   // the sync TemplateURLs (GUIDs transferred over).
1209   EXPECT_FALSE(model()->GetTemplateURLForGUID(local_google_guid));
1210   ASSERT_TRUE(model()->GetTemplateURLForGUID("sync1"));
1211   EXPECT_EQ(google_keyword, model()->GetTemplateURLForGUID("sync1")->keyword());
1212   EXPECT_FALSE(model()->GetTemplateURLForGUID(local_other_guid));
1213   ASSERT_TRUE(model()->GetTemplateURLForGUID("sync2"));
1214   EXPECT_EQ(ASCIIToUTF16("other.com"),
1215             model()->GetTemplateURLForGUID("sync2")->keyword());
1216
1217   // Both synced URLs should have associated UPDATEs, since both needed their
1218   // keywords to be generated.
1219   EXPECT_EQ(processor()->change_list_size(), 2U);
1220   ASSERT_TRUE(processor()->contains_guid("sync1"));
1221   syncer::SyncChange sync1_change = processor()->change_for_guid("sync1");
1222   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, sync1_change.change_type());
1223   EXPECT_EQ(google_keyword, UTF8ToUTF16(GetKeyword(sync1_change.sync_data())));
1224   EXPECT_EQ(local_google_url, GetURL(sync1_change.sync_data()));
1225   ASSERT_TRUE(processor()->contains_guid("sync2"));
1226   syncer::SyncChange sync2_change = processor()->change_for_guid("sync2");
1227   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, sync2_change.change_type());
1228   EXPECT_EQ("other.com", GetKeyword(sync2_change.sync_data()));
1229   EXPECT_EQ(synced_other_url, GetURL(sync2_change.sync_data()));
1230 }
1231
1232 TEST_F(TemplateURLServiceSyncTest, TwoAutogeneratedKeywordsUsingGoogleBaseURL) {
1233   // Sync brings in two autogenerated keywords and both use Google base URLs.
1234   // We make the first older so that it will get renamed once before the second
1235   // and then again once after (when we resolve conflicts for the second).
1236   syncer::SyncDataList initial_data;
1237   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
1238       "{google:baseURL}1/search?q={searchTerms}", "key1", 50));
1239   initial_data.push_back(
1240       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
1241   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"),
1242       "{google:baseURL}2/search?q={searchTerms}", "key2"));
1243   initial_data.push_back(
1244       CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
1245   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1246       PassProcessor(), CreateAndPassSyncErrorFactory());
1247
1248   // We should still have coalesced the updates to one each.
1249   string16 google_keyword(net::StripWWWFromHost(GURL(
1250       UIThreadSearchTermsData(profile_a()).GoogleBaseURLValue())));
1251   TemplateURL* keyword1 =
1252       model()->GetTemplateURLForKeyword(google_keyword + ASCIIToUTF16("_"));
1253   ASSERT_FALSE(keyword1 == NULL);
1254   EXPECT_EQ("key1", keyword1->sync_guid());
1255   TemplateURL* keyword2 = model()->GetTemplateURLForKeyword(google_keyword);
1256   ASSERT_FALSE(keyword2 == NULL);
1257   EXPECT_EQ("key2", keyword2->sync_guid());
1258
1259   EXPECT_GE(processor()->change_list_size(), 2U);
1260   ASSERT_TRUE(processor()->contains_guid("key1"));
1261   syncer::SyncChange key1_change = processor()->change_for_guid("key1");
1262   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key1_change.change_type());
1263   EXPECT_EQ(keyword1->keyword(),
1264             UTF8ToUTF16(GetKeyword(key1_change.sync_data())));
1265   ASSERT_TRUE(processor()->contains_guid("key2"));
1266   syncer::SyncChange key2_change = processor()->change_for_guid("key2");
1267   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key2_change.change_type());
1268   EXPECT_EQ(keyword2->keyword(),
1269             UTF8ToUTF16(GetKeyword(key2_change.sync_data())));
1270 }
1271
1272 TEST_F(TemplateURLServiceSyncTest, DuplicateEncodingsRemoved) {
1273   // Create a sync entry with duplicate encodings.
1274   syncer::SyncDataList initial_data;
1275
1276   TemplateURLData data;
1277   data.short_name = ASCIIToUTF16("test");
1278   data.SetKeyword(ASCIIToUTF16("keyword"));
1279   data.SetURL("http://test/%s");
1280   data.input_encodings.push_back("UTF-8");
1281   data.input_encodings.push_back("UTF-8");
1282   data.input_encodings.push_back("UTF-16");
1283   data.input_encodings.push_back("UTF-8");
1284   data.input_encodings.push_back("Big5");
1285   data.input_encodings.push_back("UTF-16");
1286   data.input_encodings.push_back("Big5");
1287   data.input_encodings.push_back("Windows-1252");
1288   data.date_created = Time::FromTimeT(100);
1289   data.last_modified = Time::FromTimeT(100);
1290   data.sync_guid = "keyword";
1291   scoped_ptr<TemplateURL> turl(new TemplateURL(NULL, data));
1292   initial_data.push_back(
1293       TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
1294
1295   // Now try to sync the data locally.
1296   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1297       PassProcessor(), CreateAndPassSyncErrorFactory());
1298
1299   // The entry should have been added, with duplicate encodings removed.
1300   TemplateURL* keyword =
1301       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
1302   ASSERT_FALSE(keyword == NULL);
1303   EXPECT_EQ(4U, keyword->input_encodings().size());
1304
1305   // We should also have gotten a corresponding UPDATE pushed upstream.
1306   EXPECT_GE(processor()->change_list_size(), 1U);
1307   ASSERT_TRUE(processor()->contains_guid("keyword"));
1308   syncer::SyncChange keyword_change = processor()->change_for_guid("keyword");
1309   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, keyword_change.change_type());
1310   EXPECT_EQ("UTF-8;UTF-16;Big5;Windows-1252", keyword_change.sync_data().
1311       GetSpecifics().search_engine().input_encodings());
1312 }
1313
1314 TEST_F(TemplateURLServiceSyncTest, MergeTwoClientsBasic) {
1315   // Start off B with some empty data.
1316   model_b()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
1317                                       CreateInitialSyncData(), PassProcessor(),
1318                                       CreateAndPassSyncErrorFactory());
1319
1320   // Merge A and B. All of B's data should transfer over to A, which initially
1321   // has no data.
1322   scoped_ptr<SyncChangeProcessorDelegate> delegate_b(
1323       new SyncChangeProcessorDelegate(model_b()));
1324   model_a()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
1325       model_b()->GetAllSyncData(syncer::SEARCH_ENGINES),
1326       delegate_b.PassAs<syncer::SyncChangeProcessor>(),
1327       CreateAndPassSyncErrorFactory());
1328
1329   // They should be consistent.
1330   AssertEquals(model_a()->GetAllSyncData(syncer::SEARCH_ENGINES),
1331                model_b()->GetAllSyncData(syncer::SEARCH_ENGINES));
1332 }
1333
1334 TEST_F(TemplateURLServiceSyncTest, MergeTwoClientsDupesAndConflicts) {
1335   // Start off B with some empty data.
1336   model_b()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
1337                                       CreateInitialSyncData(), PassProcessor(),
1338                                       CreateAndPassSyncErrorFactory());
1339
1340   // Set up A so we have some interesting duplicates and conflicts.
1341   model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key4"), "http://key4.com",
1342                                        "key4"));  // Added
1343   model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com",
1344                                        "key2"));  // Merge - Copy of key2.
1345   model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com",
1346                                        "key5", 10));  // Merge - Dupe of key3.
1347   model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key6.com",
1348                                        "key6", 10));  // Conflict with key1
1349
1350   // Merge A and B.
1351   scoped_ptr<SyncChangeProcessorDelegate> delegate_b(
1352       new SyncChangeProcessorDelegate(model_b()));
1353   model_a()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
1354       model_b()->GetAllSyncData(syncer::SEARCH_ENGINES),
1355       delegate_b.PassAs<syncer::SyncChangeProcessor>(),
1356       CreateAndPassSyncErrorFactory());
1357
1358   // They should be consistent.
1359   AssertEquals(model_a()->GetAllSyncData(syncer::SEARCH_ENGINES),
1360                model_b()->GetAllSyncData(syncer::SEARCH_ENGINES));
1361 }
1362
1363 TEST_F(TemplateURLServiceSyncTest, StopSyncing) {
1364   syncer::SyncError error =
1365       model()->MergeDataAndStartSyncing(
1366           syncer::SEARCH_ENGINES,
1367           CreateInitialSyncData(),
1368           PassProcessor(),
1369           CreateAndPassSyncErrorFactory()).error();
1370   ASSERT_FALSE(error.IsSet());
1371   model()->StopSyncing(syncer::SEARCH_ENGINES);
1372
1373   syncer::SyncChangeList changes;
1374   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
1375       CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
1376                             "key2")));
1377   error = model()->ProcessSyncChanges(FROM_HERE, changes);
1378   EXPECT_TRUE(error.IsSet());
1379
1380   // Ensure that the sync changes were not accepted.
1381   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
1382   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("newkeyword")));
1383 }
1384
1385 TEST_F(TemplateURLServiceSyncTest, SyncErrorOnInitialSync) {
1386   processor()->set_erroneous(true);
1387   syncer::SyncError error =
1388       model()->MergeDataAndStartSyncing(
1389           syncer::SEARCH_ENGINES,
1390           CreateInitialSyncData(),
1391           PassProcessor(),
1392           CreateAndPassSyncErrorFactory()).error();
1393   EXPECT_TRUE(error.IsSet());
1394
1395   // Ensure that if the initial merge was erroneous, then subsequence attempts
1396   // to push data into the local model are rejected, since the model was never
1397   // successfully associated with Sync in the first place.
1398   syncer::SyncChangeList changes;
1399   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
1400       CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
1401                             "key2")));
1402   processor()->set_erroneous(false);
1403   error = model()->ProcessSyncChanges(FROM_HERE, changes);
1404   EXPECT_TRUE(error.IsSet());
1405
1406   // Ensure that the sync changes were not accepted.
1407   EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
1408   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("newkeyword")));
1409 }
1410
1411 TEST_F(TemplateURLServiceSyncTest, SyncErrorOnLaterSync) {
1412   // Ensure that if the SyncProcessor succeeds in the initial merge, but fails
1413   // in future ProcessSyncChanges, we still return an error.
1414   syncer::SyncError error =
1415       model()->MergeDataAndStartSyncing(
1416           syncer::SEARCH_ENGINES,
1417           CreateInitialSyncData(),
1418           PassProcessor(),
1419           CreateAndPassSyncErrorFactory()).error();
1420   ASSERT_FALSE(error.IsSet());
1421
1422   syncer::SyncChangeList changes;
1423   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
1424       CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
1425                             "key2")));
1426   processor()->set_erroneous(true);
1427   error = model()->ProcessSyncChanges(FROM_HERE, changes);
1428   EXPECT_TRUE(error.IsSet());
1429 }
1430
1431 TEST_F(TemplateURLServiceSyncTest, MergeTwiceWithSameSyncData) {
1432   // Ensure that a second merge with the same data as the first does not
1433   // actually update the local data.
1434   syncer::SyncDataList initial_data;
1435   initial_data.push_back(CreateInitialSyncData()[0]);
1436
1437   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com",
1438                                      "key1", 10));  // earlier
1439
1440   syncer::SyncError error =
1441       model()->MergeDataAndStartSyncing(
1442           syncer::SEARCH_ENGINES,
1443           initial_data,
1444           PassProcessor(),
1445           CreateAndPassSyncErrorFactory()).error();
1446   ASSERT_FALSE(error.IsSet());
1447
1448   // We should have updated the original TemplateURL with Sync's version.
1449   // Keep a copy of it so we can compare it after we re-merge.
1450   TemplateURL* key1_url = model()->GetTemplateURLForGUID("key1");
1451   ASSERT_TRUE(key1_url);
1452   scoped_ptr<TemplateURL> updated_turl(new TemplateURL(key1_url->profile(),
1453                                                        key1_url->data()));
1454   EXPECT_EQ(Time::FromTimeT(90), updated_turl->last_modified());
1455
1456   // Modify a single field of the initial data. This should not be updated in
1457   // the second merge, as the last_modified timestamp remains the same.
1458   scoped_ptr<TemplateURL> temp_turl(Deserialize(initial_data[0]));
1459   TemplateURLData data(temp_turl->data());
1460   data.short_name = ASCIIToUTF16("SomethingDifferent");
1461   temp_turl.reset(new TemplateURL(temp_turl->profile(), data));
1462   initial_data.clear();
1463   initial_data.push_back(
1464       TemplateURLService::CreateSyncDataFromTemplateURL(*temp_turl));
1465
1466   // Remerge the data again. This simulates shutting down and syncing again
1467   // at a different time, but the cloud data has not changed.
1468   model()->StopSyncing(syncer::SEARCH_ENGINES);
1469   sync_processor_delegate_.reset(new SyncChangeProcessorDelegate(
1470       sync_processor_.get()));
1471   error = model()->MergeDataAndStartSyncing(
1472       syncer::SEARCH_ENGINES,
1473       initial_data,
1474       PassProcessor(),
1475       CreateAndPassSyncErrorFactory()).error();
1476   ASSERT_FALSE(error.IsSet());
1477
1478   // Check that the TemplateURL was not modified.
1479   const TemplateURL* reupdated_turl = model()->GetTemplateURLForGUID("key1");
1480   ASSERT_TRUE(reupdated_turl);
1481   AssertEquals(*updated_turl, *reupdated_turl);
1482 }
1483
1484 TEST_F(TemplateURLServiceSyncTest, SyncedDefaultGUIDArrivesFirst) {
1485   syncer::SyncDataList initial_data = CreateInitialSyncData();
1486   // The default search provider should support replacement.
1487   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key2"),
1488       "http://key2.com/{searchTerms}", "key2", 90));
1489   initial_data[1] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
1490   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1491       PassProcessor(), CreateAndPassSyncErrorFactory());
1492   model()->SetDefaultSearchProvider(model()->GetTemplateURLForGUID("key2"));
1493
1494   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1495   const TemplateURL* default_search = model()->GetDefaultSearchProvider();
1496   ASSERT_TRUE(default_search);
1497
1498   // Change kSyncedDefaultSearchProviderGUID to a GUID that does not exist in
1499   // the model yet. Ensure that the default has not changed in any way.
1500   profile_a()->GetTestingPrefService()->SetString(
1501       prefs::kSyncedDefaultSearchProviderGUID, "newdefault");
1502
1503   ASSERT_EQ(default_search, model()->GetDefaultSearchProvider());
1504
1505   // Bring in a random new search engine with a different GUID. Ensure that
1506   // it doesn't change the default.
1507   syncer::SyncChangeList changes1;
1508   changes1.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
1509       CreateTestTemplateURL(ASCIIToUTF16("random"), "http://random.com",
1510                             "random")));
1511   model()->ProcessSyncChanges(FROM_HERE, changes1);
1512
1513   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1514   ASSERT_EQ(default_search, model()->GetDefaultSearchProvider());
1515
1516   // Finally, bring in the expected entry with the right GUID. Ensure that
1517   // the default has changed to the new search engine.
1518   syncer::SyncChangeList changes2;
1519   changes2.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
1520       CreateTestTemplateURL(ASCIIToUTF16("new"), "http://new.com/{searchTerms}",
1521                             "newdefault")));
1522   model()->ProcessSyncChanges(FROM_HERE, changes2);
1523
1524   EXPECT_EQ(5U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1525   ASSERT_NE(default_search, model()->GetDefaultSearchProvider());
1526   ASSERT_EQ("newdefault", model()->GetDefaultSearchProvider()->sync_guid());
1527 }
1528
1529 TEST_F(TemplateURLServiceSyncTest, DefaultGuidDeletedBeforeNewDSPArrives) {
1530   syncer::SyncDataList initial_data;
1531   // The default search provider should support replacement.
1532   scoped_ptr<TemplateURL> turl1(CreateTestTemplateURL(ASCIIToUTF16("key1"),
1533       "http://key1.com/{searchTerms}", "key1", 90));
1534   // Create a second default search provider for the
1535   // FindNewDefaultSearchProvider method to find.
1536   TemplateURLData data;
1537   data.short_name = ASCIIToUTF16("unittest");
1538   data.SetKeyword(ASCIIToUTF16("key2"));
1539   data.SetURL("http://key2.com/{searchTerms}");
1540   data.favicon_url = GURL("http://favicon.url");
1541   data.safe_for_autoreplace = false;
1542   data.date_created = Time::FromTimeT(100);
1543   data.last_modified = Time::FromTimeT(100);
1544   data.created_by_policy = false;
1545   data.prepopulate_id = 999999;
1546   data.sync_guid = "key2";
1547   data.show_in_default_list = true;
1548   scoped_ptr<TemplateURL> turl2(new TemplateURL(NULL, data));
1549   initial_data.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(
1550       *turl1));
1551   initial_data.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(
1552       *turl2));
1553   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1554       PassProcessor(), CreateAndPassSyncErrorFactory());
1555   model()->SetDefaultSearchProvider(model()->GetTemplateURLForGUID("key1"));
1556   ASSERT_EQ("key1", model()->GetDefaultSearchProvider()->sync_guid());
1557
1558   EXPECT_EQ(2U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1559   const TemplateURL* default_search = model()->GetDefaultSearchProvider();
1560   ASSERT_TRUE(default_search);
1561
1562   // Change kSyncedDefaultSearchProviderGUID to a GUID that does not exist in
1563   // the model yet. Ensure that the default has not changed in any way.
1564   profile_a()->GetTestingPrefService()->SetString(
1565       prefs::kSyncedDefaultSearchProviderGUID, "newdefault");
1566
1567   ASSERT_EQ("key1", model()->GetDefaultSearchProvider()->sync_guid());
1568   EXPECT_EQ("newdefault", profile_a()->GetTestingPrefService()->GetString(
1569       prefs::kSyncedDefaultSearchProviderGUID));
1570
1571   // Simulate a situation where an ACTION_DELETE on the default arrives before
1572   // the new default search provider entry. This should fail to delete the
1573   // target entry, and instead send up an "undelete" to the server, after
1574   // further uniquifying the keyword to avoid infinite sync loops. The synced
1575   // default GUID should not be changed so that when the expected default entry
1576   // arrives, it can still be set as the default.
1577   syncer::SyncChangeList changes1;
1578   changes1.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_DELETE,
1579                                           turl1.release()));
1580   model()->ProcessSyncChanges(FROM_HERE, changes1);
1581
1582   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("key1_")));
1583   EXPECT_EQ(2U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1584   EXPECT_EQ("key1", model()->GetDefaultSearchProvider()->sync_guid());
1585   EXPECT_EQ("newdefault", profile_a()->GetTestingPrefService()->GetString(
1586       prefs::kSyncedDefaultSearchProviderGUID));
1587   syncer::SyncChange undelete = processor()->change_for_guid("key1");
1588   EXPECT_EQ(syncer::SyncChange::ACTION_ADD, undelete.change_type());
1589   EXPECT_EQ("key1_",
1590             undelete.sync_data().GetSpecifics().search_engine().keyword());
1591
1592   // Finally, bring in the expected entry with the right GUID. Ensure that
1593   // the default has changed to the new search engine.
1594   syncer::SyncChangeList changes2;
1595   changes2.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
1596       CreateTestTemplateURL(ASCIIToUTF16("new"), "http://new.com/{searchTerms}",
1597                             "newdefault")));
1598   model()->ProcessSyncChanges(FROM_HERE, changes2);
1599
1600   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1601   EXPECT_EQ("newdefault", model()->GetDefaultSearchProvider()->sync_guid());
1602   EXPECT_EQ("newdefault", profile_a()->GetTestingPrefService()->GetString(
1603       prefs::kSyncedDefaultSearchProviderGUID));
1604 }
1605
1606 TEST_F(TemplateURLServiceSyncTest, SyncedDefaultArrivesAfterStartup) {
1607   // Start with the default set to something in the model before we start
1608   // syncing.
1609   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("what"),
1610                                      "http://thewhat.com/{searchTerms}",
1611                                      "initdefault"));
1612   model()->SetDefaultSearchProvider(
1613       model()->GetTemplateURLForGUID("initdefault"));
1614
1615   const TemplateURL* default_search = model()->GetDefaultSearchProvider();
1616   ASSERT_TRUE(default_search);
1617
1618   // Set kSyncedDefaultSearchProviderGUID to something that is not yet in
1619   // the model but is expected in the initial sync. Ensure that this doesn't
1620   // change our default since we're not quite syncing yet.
1621   profile_a()->GetTestingPrefService()->SetString(
1622       prefs::kSyncedDefaultSearchProviderGUID, "key2");
1623
1624   EXPECT_EQ(default_search, model()->GetDefaultSearchProvider());
1625
1626   // Now sync the initial data, which will include the search engine entry
1627   // destined to become the new default.
1628   syncer::SyncDataList initial_data = CreateInitialSyncData();
1629   // The default search provider should support replacement.
1630   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key2"),
1631       "http://key2.com/{searchTerms}", "key2", 90));
1632   initial_data[1] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
1633
1634   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1635       PassProcessor(), CreateAndPassSyncErrorFactory());
1636
1637   // Ensure that the new default has been set.
1638   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1639   ASSERT_NE(default_search, model()->GetDefaultSearchProvider());
1640   ASSERT_EQ("key2", model()->GetDefaultSearchProvider()->sync_guid());
1641 }
1642
1643 TEST_F(TemplateURLServiceSyncTest, SyncedDefaultAlreadySetOnStartup) {
1644   // Start with the default set to something in the model before we start
1645   // syncing.
1646   const char kGUID[] = "initdefault";
1647   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("what"),
1648                                      "http://thewhat.com/{searchTerms}",
1649                                      kGUID));
1650   model()->SetDefaultSearchProvider(model()->GetTemplateURLForGUID(kGUID));
1651
1652   const TemplateURL* default_search = model()->GetDefaultSearchProvider();
1653   ASSERT_TRUE(default_search);
1654
1655   // Set kSyncedDefaultSearchProviderGUID to the current default.
1656   profile_a()->GetTestingPrefService()->SetString(
1657       prefs::kSyncedDefaultSearchProviderGUID, kGUID);
1658
1659   EXPECT_EQ(default_search, model()->GetDefaultSearchProvider());
1660
1661   // Now sync the initial data.
1662   syncer::SyncDataList initial_data = CreateInitialSyncData();
1663   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1664       PassProcessor(), CreateAndPassSyncErrorFactory());
1665
1666   // Ensure that the new entries were added and the default has not changed.
1667   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1668   ASSERT_EQ(default_search, model()->GetDefaultSearchProvider());
1669 }
1670
1671 TEST_F(TemplateURLServiceSyncTest, NewDefaultIsAlreadySynced) {
1672   // Ensure that if the synced DSP pref changed to another synced entry (as
1673   // opposed to coming in as a new entry), it gets reset correctly.
1674   // Start by setting kSyncedDefaultSearchProviderGUID to the entry that should
1675   // end up as the default. Note that this must be done before the initial
1676   // entries are added as otherwise this call will set the DSP immediately.
1677   profile_a()->GetTestingPrefService()->SetString(
1678       prefs::kSyncedDefaultSearchProviderGUID, "key2");
1679
1680   syncer::SyncDataList initial_data = CreateInitialSyncData();
1681   // Ensure that our candidate default supports replacement.
1682   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key2"),
1683       "http://key2.com/{searchTerms}", "key2", 90));
1684   initial_data[1] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
1685   for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
1686       iter != initial_data.end(); ++iter) {
1687     TemplateURL* converted = Deserialize(*iter);
1688     model()->Add(converted);
1689   }
1690
1691   // Set the initial default to something other than the desired default.
1692   model()->SetDefaultSearchProvider(model()->GetTemplateURLForGUID("key1"));
1693
1694   // Merge in the same data (i.e. already synced entries).
1695   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1696       PassProcessor(), CreateAndPassSyncErrorFactory());
1697
1698   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1699   TemplateURL* current_default = model()->GetDefaultSearchProvider();
1700   ASSERT_TRUE(current_default);
1701   EXPECT_EQ("key2", current_default->sync_guid());
1702   EXPECT_EQ(ASCIIToUTF16("key2"), current_default->keyword());
1703 }
1704
1705 TEST_F(TemplateURLServiceSyncTest, SyncWithManagedDefaultSearch) {
1706   // First start off with a few entries and make sure we can set an unmanaged
1707   // default search provider.
1708   syncer::SyncDataList initial_data = CreateInitialSyncData();
1709   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1710       PassProcessor(), CreateAndPassSyncErrorFactory());
1711   model()->SetDefaultSearchProvider(model()->GetTemplateURLForGUID("key2"));
1712
1713   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1714   ASSERT_FALSE(model()->is_default_search_managed());
1715   ASSERT_TRUE(model()->GetDefaultSearchProvider());
1716
1717   // Change the default search provider to a managed one.
1718   const char kName[] = "manageddefault";
1719   const char kSearchURL[] = "http://manageddefault.com/search?t={searchTerms}";
1720   const char kIconURL[] = "http://manageddefault.com/icon.jpg";
1721   const char kEncodings[] = "UTF-16;UTF-32";
1722   const char kAlternateURL[] =
1723       "http://manageddefault.com/search#t={searchTerms}";
1724   const char kSearchTermsReplacementKey[] = "espv";
1725   test_util_a_.SetManagedDefaultSearchPreferences(true, kName, kName,
1726       kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
1727       kSearchTermsReplacementKey);
1728   const TemplateURL* dsp_turl = model()->GetDefaultSearchProvider();
1729
1730   EXPECT_TRUE(model()->is_default_search_managed());
1731
1732   // Add a new entry from Sync. It should still sync in despite the default
1733   // being managed.
1734   syncer::SyncChangeList changes;
1735   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
1736       CreateTestTemplateURL(ASCIIToUTF16("newkeyword"),
1737                             "http://new.com/{searchTerms}",
1738                             "newdefault")));
1739   model()->ProcessSyncChanges(FROM_HERE, changes);
1740
1741   EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1742
1743   // Change kSyncedDefaultSearchProviderGUID to point to the new entry and
1744   // ensure that the DSP remains managed.
1745   profile_a()->GetTestingPrefService()->SetString(
1746       prefs::kSyncedDefaultSearchProviderGUID,
1747       "newdefault");
1748
1749   EXPECT_EQ(dsp_turl, model()->GetDefaultSearchProvider());
1750   EXPECT_TRUE(model()->is_default_search_managed());
1751
1752   // Go unmanaged. Ensure that the DSP changes to the expected pending entry
1753   // from Sync.
1754   const TemplateURL* expected_default =
1755       model()->GetTemplateURLForGUID("newdefault");
1756   test_util_a_.RemoveManagedDefaultSearchPreferences();
1757
1758   EXPECT_EQ(expected_default, model()->GetDefaultSearchProvider());
1759 }
1760
1761 TEST_F(TemplateURLServiceSyncTest, SyncMergeDeletesDefault) {
1762   // If the value from Sync is a duplicate of the local default and is newer, it
1763   // should safely replace the local value and set as the new default.
1764   TemplateURL* default_turl = CreateTestTemplateURL(ASCIIToUTF16("key1"),
1765       "http://key1.com/{searchTerms}", "whateverguid", 10);
1766   model()->Add(default_turl);
1767   model()->SetDefaultSearchProvider(default_turl);
1768
1769   syncer::SyncDataList initial_data = CreateInitialSyncData();
1770   // The key1 entry should be a duplicate of the default.
1771   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
1772       "http://key1.com/{searchTerms}", "key1", 90));
1773   initial_data[0] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
1774
1775   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1776       PassProcessor(), CreateAndPassSyncErrorFactory());
1777
1778   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1779   EXPECT_FALSE(model()->GetTemplateURLForGUID("whateverguid"));
1780   EXPECT_EQ(model()->GetDefaultSearchProvider(),
1781             model()->GetTemplateURLForGUID("key1"));
1782 }
1783
1784 TEST_F(TemplateURLServiceSyncTest, LocalDefaultWinsConflict) {
1785   // We expect that the local default always wins keyword conflict resolution.
1786   const string16 keyword(ASCIIToUTF16("key1"));
1787   const std::string url("http://whatever.com/{searchTerms}");
1788   TemplateURL* default_turl = CreateTestTemplateURL(keyword,
1789                                                     url,
1790                                                     "whateverguid",
1791                                                     10);
1792   model()->Add(default_turl);
1793   model()->SetDefaultSearchProvider(default_turl);
1794
1795   syncer::SyncDataList initial_data = CreateInitialSyncData();
1796   // The key1 entry should be different from the default but conflict in the
1797   // keyword.
1798   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(keyword,
1799       "http://key1.com/{searchTerms}", "key1", 90));
1800   initial_data[0] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
1801
1802   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1803       PassProcessor(), CreateAndPassSyncErrorFactory());
1804
1805   // Since the local default was not yet synced, it should be merged with the
1806   // conflicting TemplateURL. However, its values should have been preserved
1807   // since it would have won conflict resolution due to being the default.
1808   EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
1809   const TemplateURL* winner = model()->GetTemplateURLForGUID("key1");
1810   ASSERT_TRUE(winner);
1811   EXPECT_EQ(model()->GetDefaultSearchProvider(), winner);
1812   EXPECT_EQ(keyword, winner->keyword());
1813   EXPECT_EQ(url, winner->url());
1814   ASSERT_TRUE(processor()->contains_guid("key1"));
1815   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
1816             processor()->change_for_guid("key1").change_type());
1817   EXPECT_EQ(url, GetURL(processor()->change_for_guid("key1").sync_data()));
1818
1819   // There is no loser, as the two were merged together. The local sync_guid
1820   // should no longer be found in the model.
1821   const TemplateURL* loser = model()->GetTemplateURLForGUID("whateverguid");
1822   ASSERT_FALSE(loser);
1823 }
1824
1825 TEST_F(TemplateURLServiceSyncTest, DeleteBogusData) {
1826   // Create a couple of bogus entries to sync.
1827   syncer::SyncDataList initial_data;
1828   scoped_ptr<TemplateURL> turl(
1829       CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com", "key1"));
1830   initial_data.push_back(
1831       CreateCustomSyncData(*turl, false, std::string(), turl->sync_guid()));
1832   turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
1833   initial_data.push_back(
1834       CreateCustomSyncData(*turl, false, turl->url(), std::string()));
1835
1836   // Now try to sync the data locally.
1837   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1838       PassProcessor(), CreateAndPassSyncErrorFactory());
1839
1840   // Nothing should have been added, and both bogus entries should be marked for
1841   // deletion.
1842   EXPECT_EQ(0U, model()->GetTemplateURLs().size());
1843   EXPECT_EQ(2U, processor()->change_list_size());
1844   ASSERT_TRUE(processor()->contains_guid("key1"));
1845   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE,
1846             processor()->change_for_guid("key1").change_type());
1847   ASSERT_TRUE(processor()->contains_guid(std::string()));
1848   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE,
1849             processor()->change_for_guid(std::string()).change_type());
1850 }
1851
1852 TEST_F(TemplateURLServiceSyncTest, PreSyncDeletes) {
1853   model()->pre_sync_deletes_.insert("key1");
1854   model()->pre_sync_deletes_.insert("key2");
1855   model()->pre_sync_deletes_.insert("aaa");
1856   model()->Add(CreateTestTemplateURL(ASCIIToUTF16("whatever"),
1857       "http://key1.com", "bbb"));
1858   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
1859       syncer::SEARCH_ENGINES,
1860       CreateInitialSyncData(), PassProcessor(),
1861       CreateAndPassSyncErrorFactory());
1862
1863   // We expect the model to have GUIDs {bbb, key3} after our initial merge.
1864   EXPECT_TRUE(model()->GetTemplateURLForGUID("bbb"));
1865   EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
1866   syncer::SyncChange change = processor()->change_for_guid("key1");
1867   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, change.change_type());
1868   change = processor()->change_for_guid("key2");
1869   EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, change.change_type());
1870   // "aaa" should have been pruned out on account of not being from Sync.
1871   EXPECT_FALSE(processor()->contains_guid("aaa"));
1872   // The set of pre-sync deletes should be cleared so they're not reused if
1873   // MergeDataAndStartSyncing gets called again.
1874   EXPECT_TRUE(model()->pre_sync_deletes_.empty());
1875
1876   // Those sync items deleted via pre-sync-deletes should not get added. The
1877   // remaining sync item (key3) should though.
1878   EXPECT_EQ(1, merge_result.num_items_added());
1879   EXPECT_EQ(0, merge_result.num_items_modified());
1880   EXPECT_EQ(0, merge_result.num_items_deleted());
1881   EXPECT_EQ(1, merge_result.num_items_before_association());
1882   EXPECT_EQ(2, merge_result.num_items_after_association());
1883 }
1884
1885 TEST_F(TemplateURLServiceSyncTest, PreSyncUpdates) {
1886   const char* kNewKeyword = "somethingnew";
1887   // Fetch the prepopulate search engines so we know what they are.
1888   size_t default_search_provider_index = 0;
1889   ScopedVector<TemplateURL> prepop_turls =
1890       TemplateURLPrepopulateData::GetPrepopulatedEngines(
1891           profile_a(), &default_search_provider_index);
1892
1893   // We have to prematurely exit this test if for some reason this machine does
1894   // not have any prepopulate TemplateURLs.
1895   ASSERT_FALSE(prepop_turls.empty());
1896
1897   // Create a copy of the first TemplateURL with a really old timestamp and a
1898   // new keyword. Add it to the model.
1899   TemplateURLData data_copy(prepop_turls[0]->data());
1900   data_copy.last_modified = Time::FromTimeT(10);
1901   string16 original_keyword = data_copy.keyword();
1902   data_copy.SetKeyword(ASCIIToUTF16(kNewKeyword));
1903   // Set safe_for_autoreplace to false so our keyword survives.
1904   data_copy.safe_for_autoreplace = false;
1905   model()->Add(new TemplateURL(prepop_turls[0]->profile(), data_copy));
1906
1907   // Merge the prepopulate search engines.
1908   base::Time pre_merge_time = base::Time::Now();
1909   base::RunLoop().RunUntilIdle();
1910   test_util_a_.ResetModel(true);
1911
1912   // The newly added search engine should have been safely merged, with an
1913   // updated time.
1914   TemplateURL* added_turl = model()->GetTemplateURLForKeyword(
1915       ASCIIToUTF16(kNewKeyword));
1916   base::Time new_timestamp = added_turl->last_modified();
1917   EXPECT_GE(new_timestamp, pre_merge_time);
1918   ASSERT_TRUE(added_turl);
1919   std::string sync_guid = added_turl->sync_guid();
1920
1921   // Bring down a copy of the prepopulate engine from Sync with the old values,
1922   // including the old timestamp and the same GUID. Ensure that it loses
1923   // conflict resolution against the local value, and an update is sent to the
1924   // server. The new timestamp should be preserved.
1925   syncer::SyncDataList initial_data;
1926   data_copy.SetKeyword(original_keyword);
1927   data_copy.sync_guid = sync_guid;
1928   scoped_ptr<TemplateURL> sync_turl(
1929       new TemplateURL(prepop_turls[0]->profile(), data_copy));
1930   initial_data.push_back(
1931       TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
1932
1933   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
1934       syncer::SEARCH_ENGINES,
1935       initial_data, PassProcessor(), CreateAndPassSyncErrorFactory());
1936
1937   ASSERT_EQ(added_turl, model()->GetTemplateURLForKeyword(
1938       ASCIIToUTF16(kNewKeyword)));
1939   EXPECT_EQ(new_timestamp, added_turl->last_modified());
1940   syncer::SyncChange change = processor()->change_for_guid(sync_guid);
1941   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
1942   EXPECT_EQ(kNewKeyword,
1943             change.sync_data().GetSpecifics().search_engine().keyword());
1944   EXPECT_EQ(new_timestamp, base::Time::FromInternalValue(
1945       change.sync_data().GetSpecifics().search_engine().last_modified()));
1946
1947   // All the sync data is old, so nothing should change locally.
1948   EXPECT_EQ(0, merge_result.num_items_added());
1949   EXPECT_EQ(0, merge_result.num_items_modified());
1950   EXPECT_EQ(0, merge_result.num_items_deleted());
1951   EXPECT_EQ(static_cast<int>(prepop_turls.size()),
1952             merge_result.num_items_before_association());
1953   EXPECT_EQ(static_cast<int>(prepop_turls.size()),
1954             merge_result.num_items_after_association());
1955 }
1956
1957 TEST_F(TemplateURLServiceSyncTest, SyncBaseURLs) {
1958   // Verify that bringing in a remote TemplateURL that uses Google base URLs
1959   // causes it to get a local keyword that matches the local base URL.
1960   test_util_a_.SetGoogleBaseURL(GURL("http://google.com/"));
1961   syncer::SyncDataList initial_data;
1962   scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(
1963       ASCIIToUTF16("google.co.uk"), "{google:baseURL}search?q={searchTerms}",
1964       "guid"));
1965   initial_data.push_back(
1966       TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
1967   model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
1968       PassProcessor(), CreateAndPassSyncErrorFactory());
1969   TemplateURL* synced_turl = model()->GetTemplateURLForGUID("guid");
1970   ASSERT_TRUE(synced_turl);
1971   EXPECT_EQ(ASCIIToUTF16("google.com"), synced_turl->keyword());
1972   EXPECT_EQ(0U, processor()->change_list_size());
1973
1974   // Remote updates to this URL's keyword should be silently ignored.
1975   syncer::SyncChangeList changes;
1976   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
1977       CreateTestTemplateURL(ASCIIToUTF16("google.de"),
1978           "{google:baseURL}search?q={searchTerms}", "guid")));
1979   model()->ProcessSyncChanges(FROM_HERE, changes);
1980   EXPECT_EQ(ASCIIToUTF16("google.com"), synced_turl->keyword());
1981   EXPECT_EQ(0U, processor()->change_list_size());
1982
1983   // A local change to the Google base URL should update the keyword and
1984   // generate a sync change.
1985   test_util_a_.SetGoogleBaseURL(GURL("http://google.co.in/"));
1986   EXPECT_EQ(ASCIIToUTF16("google.co.in"), synced_turl->keyword());
1987   EXPECT_EQ(1U, processor()->change_list_size());
1988   ASSERT_TRUE(processor()->contains_guid("guid"));
1989   syncer::SyncChange change(processor()->change_for_guid("guid"));
1990   EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
1991   EXPECT_EQ("google.co.in", GetKeyword(change.sync_data()));
1992 }
1993
1994 TEST_F(TemplateURLServiceSyncTest, MergeInSyncTemplateURL) {
1995   // An enumeration used to indicate which TemplateURL test value is expected
1996   // for a particular test result.
1997   enum ExpectedTemplateURL {
1998     LOCAL,
1999     SYNC,
2000     BOTH,
2001     NEITHER,
2002   };
2003
2004   // Sets up and executes a MergeInSyncTemplateURL test given a number of
2005   // expected start and end states:
2006   //  * |conflict_winner| denotes which TemplateURL should win the
2007   //    conflict.
2008   //  * |synced_at_start| denotes which of the TemplateURLs should known
2009   //    to Sync.
2010   //  * |update_sent| denotes which TemplateURL should have an
2011   //    ACTION_UPDATE sent to the server after the merge.
2012   //  * |turl_uniquified| denotes which TemplateURL should have its
2013   //    keyword updated after the merge.
2014   //  * |present_in_model| denotes which TemplateURL should be found in
2015   //    the model after the merge.
2016   //  * If |keywords_conflict| is true, the TemplateURLs are set up with
2017   //    the same keyword.
2018   const struct {
2019     ExpectedTemplateURL conflict_winner;
2020     ExpectedTemplateURL synced_at_start;
2021     ExpectedTemplateURL update_sent;
2022     ExpectedTemplateURL turl_uniquified;
2023     ExpectedTemplateURL present_in_model;
2024     bool keywords_conflict;
2025     int merge_results[3];  // in Added, Modified, Deleted order.
2026   } test_cases[] = {
2027     // Both are synced and the new sync entry is better: Local is uniquified and
2028     // UPDATE sent. Sync is added.
2029     {SYNC, BOTH, LOCAL, LOCAL, BOTH, true, {1, 1, 0}},
2030     // Both are synced and the local entry is better: Sync is uniquified and
2031     // added to the model. An UPDATE is sent for it.
2032     {LOCAL, BOTH, SYNC, SYNC, BOTH, true, {1, 1, 0}},
2033     // Local was not known to Sync and the new sync entry is better: Sync is
2034     // added. Local is removed. No updates.
2035     {SYNC, SYNC, NEITHER, NEITHER, SYNC, true, {1, 0, 1}},
2036     // Local was not known to sync and the local entry is better: Local is
2037     // updated with sync GUID, Sync is not added. UPDATE sent for Sync.
2038     {LOCAL, SYNC, SYNC, NEITHER, SYNC, true, {0, 1, 0}},
2039     // No conflicting keyword. Both should be added with their original
2040     // keywords, with no updates sent. Note that MergeDataAndStartSyncing is
2041     // responsible for creating the ACTION_ADD for the local TemplateURL.
2042     {NEITHER, SYNC, NEITHER, NEITHER, BOTH, false, {1, 0, 0}},
2043   };
2044
2045   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
2046     // Assert all the valid states of ExpectedTemplateURLs.
2047     ASSERT_FALSE(test_cases[i].conflict_winner == BOTH);
2048     ASSERT_FALSE(test_cases[i].synced_at_start == NEITHER);
2049     ASSERT_FALSE(test_cases[i].synced_at_start == LOCAL);
2050     ASSERT_FALSE(test_cases[i].update_sent == BOTH);
2051     ASSERT_FALSE(test_cases[i].turl_uniquified == BOTH);
2052     ASSERT_FALSE(test_cases[i].present_in_model == NEITHER);
2053
2054     const string16 local_keyword = ASCIIToUTF16("localkeyword");
2055     const string16 sync_keyword = test_cases[i].keywords_conflict ?
2056         local_keyword : ASCIIToUTF16("synckeyword");
2057     const std::string local_url = "www.localurl.com";
2058     const std::string sync_url = "www.syncurl.com";
2059     const time_t local_last_modified = 100;
2060     const time_t sync_last_modified =
2061         test_cases[i].conflict_winner == SYNC ? 110 : 90;
2062     const std::string local_guid = "local_guid";
2063     const std::string sync_guid = "sync_guid";
2064
2065     // Initialize expectations.
2066     string16 expected_local_keyword = local_keyword;
2067     string16 expected_sync_keyword = sync_keyword;
2068
2069     // Create the data and run the actual test.
2070     TemplateURL* local_turl = CreateTestTemplateURL(
2071         local_keyword, local_url, local_guid, local_last_modified);
2072     model()->Add(local_turl);
2073     scoped_ptr<TemplateURL> sync_turl(CreateTestTemplateURL(
2074         sync_keyword, sync_url, sync_guid, sync_last_modified));
2075
2076     SyncDataMap sync_data;
2077     if (test_cases[i].synced_at_start == SYNC ||
2078         test_cases[i].synced_at_start == BOTH) {
2079       sync_data[sync_turl->sync_guid()] =
2080           TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl);
2081     }
2082     if (test_cases[i].synced_at_start == BOTH) {
2083       sync_data[local_turl->sync_guid()] =
2084           TemplateURLService::CreateSyncDataFromTemplateURL(*local_turl);
2085     }
2086     SyncDataMap initial_data;
2087     initial_data[local_turl->sync_guid()] =
2088         TemplateURLService::CreateSyncDataFromTemplateURL(*local_turl);
2089
2090     syncer::SyncChangeList change_list;
2091     syncer::SyncMergeResult merge_result(syncer::SEARCH_ENGINES);
2092     model()->MergeInSyncTemplateURL(sync_turl.get(),
2093                                     sync_data,
2094                                     &change_list,
2095                                     &initial_data,
2096                                     &merge_result);
2097
2098     // Verify the merge results were set appropriately.
2099     EXPECT_EQ(test_cases[i].merge_results[0], merge_result.num_items_added());
2100     EXPECT_EQ(test_cases[i].merge_results[1],
2101               merge_result.num_items_modified());
2102     EXPECT_EQ(test_cases[i].merge_results[2], merge_result.num_items_deleted());
2103
2104     // Check for expected updates, if any.
2105     std::string expected_update_guid;
2106     if (test_cases[i].update_sent == LOCAL)
2107       expected_update_guid = local_guid;
2108     else if (test_cases[i].update_sent == SYNC)
2109       expected_update_guid = sync_guid;
2110     if (!expected_update_guid.empty()) {
2111       ASSERT_EQ(1U, change_list.size());
2112       EXPECT_EQ(expected_update_guid, GetGUID(change_list[0].sync_data()));
2113       EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
2114                 change_list[0].change_type());
2115     } else {
2116       EXPECT_EQ(0U, change_list.size());
2117     }
2118
2119     // Adjust the expectations based on the expectation enums.
2120     if (test_cases[i].turl_uniquified == LOCAL) {
2121       DCHECK(test_cases[i].keywords_conflict);
2122       expected_local_keyword = ASCIIToUTF16("localkeyword_");
2123     }
2124     if (test_cases[i].turl_uniquified == SYNC) {
2125       DCHECK(test_cases[i].keywords_conflict);
2126       expected_sync_keyword = ASCIIToUTF16("localkeyword_");
2127     }
2128
2129     // Check for TemplateURLs expected in the model. Note that this is checked
2130     // by GUID rather than the initial pointer, as a merge could occur (the
2131     // Sync TemplateURL overtakes the local one). Also remove the present
2132     // TemplateURL when done so the next test case starts with a clean slate.
2133     if (test_cases[i].present_in_model == LOCAL ||
2134         test_cases[i].present_in_model == BOTH) {
2135       ASSERT_TRUE(model()->GetTemplateURLForGUID(local_guid));
2136       EXPECT_EQ(expected_local_keyword, local_turl->keyword());
2137       EXPECT_EQ(local_url, local_turl->url());
2138       EXPECT_EQ(local_last_modified, local_turl->last_modified().ToTimeT());
2139       model()->Remove(model()->GetTemplateURLForGUID(local_guid));
2140     }
2141     if (test_cases[i].present_in_model == SYNC ||
2142         test_cases[i].present_in_model == BOTH) {
2143       ASSERT_TRUE(model()->GetTemplateURLForGUID(sync_guid));
2144       EXPECT_EQ(expected_sync_keyword, sync_turl->keyword());
2145       EXPECT_EQ(sync_url, sync_turl->url());
2146       EXPECT_EQ(sync_last_modified, sync_turl->last_modified().ToTimeT());
2147       model()->Remove(model()->GetTemplateURLForGUID(sync_guid));
2148     }
2149   }  // for
2150 }
2151
2152 TEST_F(TemplateURLServiceSyncTest, MergePrepopulatedEngine) {
2153   scoped_ptr<TemplateURL> default_turl(
2154       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
2155
2156   // Merge with an initial list containing a prepopulated engine with a wrong
2157   // URL.
2158   syncer::SyncDataList list;
2159   scoped_ptr<TemplateURL> sync_turl(CopyTemplateURL(default_turl.get(),
2160       "http://wrong.url.com?q={searchTerms}", "default"));
2161   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
2162   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
2163       syncer::SEARCH_ENGINES, list, PassProcessor(),
2164       CreateAndPassSyncErrorFactory());
2165
2166   const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
2167   EXPECT_TRUE(result_turl);
2168   EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
2169   EXPECT_EQ(default_turl->short_name(), result_turl->short_name());
2170   EXPECT_EQ(default_turl->url(), result_turl->url());
2171 }
2172
2173 TEST_F(TemplateURLServiceSyncTest, AddPrepopulatedEngine) {
2174   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
2175       syncer::SEARCH_ENGINES, syncer::SyncDataList(), PassProcessor(),
2176       CreateAndPassSyncErrorFactory());
2177
2178   scoped_ptr<TemplateURL> default_turl(
2179       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
2180   TemplateURL* sync_turl = CopyTemplateURL(default_turl.get(),
2181       "http://wrong.url.com?q={searchTerms}", "default");
2182
2183   // Add a prepopulated engine with a wrong URL.
2184   syncer::SyncChangeList changes;
2185   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
2186                                          sync_turl));
2187   model()->ProcessSyncChanges(FROM_HERE, changes);
2188
2189   const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
2190   EXPECT_TRUE(result_turl);
2191   EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
2192   EXPECT_EQ(default_turl->short_name(), result_turl->short_name());
2193   EXPECT_EQ(default_turl->url(), result_turl->url());
2194 }
2195
2196 TEST_F(TemplateURLServiceSyncTest, UpdatePrepopulatedEngine) {
2197   scoped_ptr<TemplateURL> default_turl(
2198       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
2199
2200   TemplateURLData data(default_turl->data());
2201   data.SetURL("http://old.wrong.url.com?q={searchTerms}");
2202   data.sync_guid = "default";
2203   model()->Add(new TemplateURL(NULL, data));
2204
2205   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
2206       syncer::SEARCH_ENGINES, syncer::SyncDataList(), PassProcessor(),
2207       CreateAndPassSyncErrorFactory());
2208
2209   TemplateURL* sync_turl = CopyTemplateURL(default_turl.get(),
2210       "http://new.wrong.url.com?q={searchTerms}", "default");
2211
2212   // Update the engine in the model, which is prepopulated, with a new one.
2213   // Both have wrong URLs, but it should still get corrected.
2214   syncer::SyncChangeList changes;
2215   changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
2216                                          sync_turl));
2217   model()->ProcessSyncChanges(FROM_HERE, changes);
2218
2219   const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
2220   EXPECT_TRUE(result_turl);
2221   EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
2222   EXPECT_EQ(default_turl->short_name(), result_turl->short_name());
2223   EXPECT_EQ(default_turl->url(), result_turl->url());
2224 }
2225
2226 TEST_F(TemplateURLServiceSyncTest, MergeEditedPrepopulatedEngine) {
2227   scoped_ptr<TemplateURL> default_turl(
2228       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
2229
2230   TemplateURLData data(default_turl->data());
2231   data.safe_for_autoreplace = false;
2232   data.SetKeyword(ASCIIToUTF16("new_kw"));
2233   data.short_name = ASCIIToUTF16("my name");
2234   data.SetURL("http://wrong.url.com?q={searchTerms}");
2235   data.date_created = Time::FromTimeT(50);
2236   data.last_modified = Time::FromTimeT(50);
2237   data.sync_guid = "default";
2238   model()->Add(new TemplateURL(NULL, data));
2239
2240   data.date_created = Time::FromTimeT(100);
2241   data.last_modified = Time::FromTimeT(100);
2242   scoped_ptr<TemplateURL> sync_turl(new TemplateURL(NULL, data));
2243   syncer::SyncDataList list;
2244   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
2245   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
2246       syncer::SEARCH_ENGINES, list, PassProcessor(),
2247       CreateAndPassSyncErrorFactory());
2248
2249   const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
2250   EXPECT_TRUE(result_turl);
2251   EXPECT_EQ(ASCIIToUTF16("new_kw"), result_turl->keyword());
2252   EXPECT_EQ(ASCIIToUTF16("my name"), result_turl->short_name());
2253   EXPECT_EQ(default_turl->url(), result_turl->url());
2254 }
2255
2256 TEST_F(TemplateURLServiceSyncTest, MergeNonEditedPrepopulatedEngine) {
2257   scoped_ptr<TemplateURL> default_turl(
2258       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
2259
2260   TemplateURLData data(default_turl->data());
2261   data.safe_for_autoreplace = true;  // Can be replaced with built-in values.
2262   data.SetKeyword(ASCIIToUTF16("new_kw"));
2263   data.short_name = ASCIIToUTF16("my name");
2264   data.SetURL("http://wrong.url.com?q={searchTerms}");
2265   data.date_created = Time::FromTimeT(50);
2266   data.last_modified = Time::FromTimeT(50);
2267   data.sync_guid = "default";
2268   model()->Add(new TemplateURL(NULL, data));
2269
2270   data.date_created = Time::FromTimeT(100);
2271   data.last_modified = Time::FromTimeT(100);
2272   scoped_ptr<TemplateURL> sync_turl(new TemplateURL(NULL, data));
2273   syncer::SyncDataList list;
2274   list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
2275   syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
2276       syncer::SEARCH_ENGINES, list, PassProcessor(),
2277       CreateAndPassSyncErrorFactory());
2278
2279   const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
2280   EXPECT_TRUE(result_turl);
2281   EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
2282   EXPECT_EQ(default_turl->short_name(), result_turl->short_name());
2283   EXPECT_EQ(default_turl->url(), result_turl->url());
2284 }