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