This source file includes following definitions.
- GetGUID
- GetURL
- GetKeyword
- CreateCustomSyncData
- GetAllSyncData
- contains_guid
- change_for_guid
- change_list_size
- set_erroneous
- ProcessSyncChanges
- model
- model_a
- model_b
- profile_a
- processor
- sync_processor_wrapper_
- SetUp
- TearDown
- PassProcessor
- CreateAndPassSyncErrorFactory
- CreateTestTemplateURL
- AssertEquals
- AssertEquals
- CreateTestSyncChange
- CreateInitialSyncData
- Deserialize
- CopyTemplateURL
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/search_engines/search_terms_data.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/search_engines/template_url_service_test_util.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/testing_pref_service_syncable.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/notification_service.h"
#include "extensions/common/constants.h"
#include "net/base/net_util.h"
#include "sync/api/sync_change_processor_wrapper_for_test.h"
#include "sync/api/sync_error_factory.h"
#include "sync/api/sync_error_factory_mock.h"
#include "sync/protocol/search_engine_specifics.pb.h"
#include "sync/protocol/sync.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
using base::UTF8ToUTF16;
using base::Time;
namespace {
std::string GetGUID(const syncer::SyncData& sync_data) {
return sync_data.GetSpecifics().search_engine().sync_guid();
}
std::string GetURL(const syncer::SyncData& sync_data) {
return sync_data.GetSpecifics().search_engine().url();
}
std::string GetKeyword(const syncer::SyncData& sync_data) {
return sync_data.GetSpecifics().search_engine().keyword();
}
syncer::SyncData CreateCustomSyncData(const TemplateURL& turl,
bool autogenerate_keyword,
const std::string& url,
const std::string& sync_guid) {
sync_pb::EntitySpecifics specifics;
sync_pb::SearchEngineSpecifics* se_specifics =
specifics.mutable_search_engine();
se_specifics->set_short_name(base::UTF16ToUTF8(turl.short_name()));
se_specifics->set_keyword(
autogenerate_keyword ? std::string() : base::UTF16ToUTF8(turl.keyword()));
se_specifics->set_favicon_url(turl.favicon_url().spec());
se_specifics->set_url(url);
se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace());
se_specifics->set_originating_url(turl.originating_url().spec());
se_specifics->set_date_created(turl.date_created().ToInternalValue());
se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';'));
se_specifics->set_show_in_default_list(turl.show_in_default_list());
se_specifics->set_suggestions_url(turl.suggestions_url());
se_specifics->set_prepopulate_id(turl.prepopulate_id());
se_specifics->set_autogenerate_keyword(autogenerate_keyword);
se_specifics->set_instant_url(turl.instant_url());
se_specifics->set_last_modified(turl.last_modified().ToInternalValue());
se_specifics->set_sync_guid(sync_guid);
return syncer::SyncData::CreateLocalData(turl.sync_guid(),
se_specifics->keyword(), specifics);
}
class TestChangeProcessor : public syncer::SyncChangeProcessor {
public:
TestChangeProcessor();
virtual ~TestChangeProcessor();
virtual syncer::SyncError ProcessSyncChanges(
const tracked_objects::Location& from_here,
const syncer::SyncChangeList& change_list) OVERRIDE;
virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
OVERRIDE {
return syncer::SyncDataList();
}
bool contains_guid(const std::string& guid) const {
return change_map_.count(guid) != 0;
}
syncer::SyncChange change_for_guid(const std::string& guid) const {
DCHECK(contains_guid(guid));
return change_map_.find(guid)->second;
}
size_t change_list_size() { return change_map_.size(); }
void set_erroneous(bool erroneous) { erroneous_ = erroneous; }
private:
std::map<std::string, syncer::SyncChange> change_map_;
bool erroneous_;
DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
};
TestChangeProcessor::TestChangeProcessor() : erroneous_(false) {
}
TestChangeProcessor::~TestChangeProcessor() {
}
syncer::SyncError TestChangeProcessor::ProcessSyncChanges(
const tracked_objects::Location& from_here,
const syncer::SyncChangeList& change_list) {
if (erroneous_)
return syncer::SyncError(
FROM_HERE,
syncer::SyncError::DATATYPE_ERROR,
"Some error.",
syncer::SEARCH_ENGINES);
change_map_.erase(change_map_.begin(), change_map_.end());
for (syncer::SyncChangeList::const_iterator iter = change_list.begin();
iter != change_list.end(); ++iter)
change_map_[GetGUID(iter->sync_data())] = *iter;
return syncer::SyncError();
}
}
class TemplateURLServiceSyncTest : public testing::Test {
public:
typedef TemplateURLService::SyncDataMap SyncDataMap;
TemplateURLServiceSyncTest();
virtual void SetUp() OVERRIDE;
virtual void TearDown() OVERRIDE;
TemplateURLService* model() { return test_util_a_.model(); }
TemplateURLService* model_a() { return test_util_a_.model(); }
TemplateURLService* model_b() { return model_b_.get(); }
TestingProfile* profile_a() { return test_util_a_.profile(); }
TestChangeProcessor* processor() { return sync_processor_.get(); }
scoped_ptr<syncer::SyncChangeProcessor> PassProcessor();
scoped_ptr<syncer::SyncErrorFactory> CreateAndPassSyncErrorFactory();
TemplateURL* CreateTestTemplateURL(const base::string16& keyword,
const std::string& url,
const std::string& guid = std::string(),
time_t last_mod = 100,
bool safe_for_autoreplace = false,
bool created_by_policy = false) const;
void AssertEquals(const TemplateURL& expected,
const TemplateURL& actual) const;
void AssertEquals(const syncer::SyncDataList& data1,
const syncer::SyncDataList& data2) const;
syncer::SyncChange CreateTestSyncChange(
syncer::SyncChange::SyncChangeType type,
TemplateURL* turl) const;
syncer::SyncDataList CreateInitialSyncData() const;
TemplateURL* Deserialize(const syncer::SyncData& sync_data);
TemplateURL* CopyTemplateURL(const TemplateURL* turl,
const std::string& url,
const std::string& guid);
protected:
TemplateURLServiceTestUtil test_util_a_;
scoped_ptr<TestingProfile> profile_b_;
scoped_ptr<TemplateURLService> model_b_;
scoped_ptr<TestChangeProcessor> sync_processor_;
scoped_ptr<syncer::SyncChangeProcessorWrapperForTest> sync_processor_wrapper_;
DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceSyncTest);
};
TemplateURLServiceSyncTest::TemplateURLServiceSyncTest()
: sync_processor_(new TestChangeProcessor),
sync_processor_wrapper_(new syncer::SyncChangeProcessorWrapperForTest(
sync_processor_.get())) {}
void TemplateURLServiceSyncTest::SetUp() {
test_util_a_.SetUp();
test_util_a_.ChangeModelToLoadState();
profile_b_.reset(new TestingProfile);
TemplateURLServiceFactory::GetInstance()->
RegisterUserPrefsOnBrowserContextForTest(profile_b_.get());
model_b_.reset(new TemplateURLService(profile_b_.get()));
model_b_->Load();
}
void TemplateURLServiceSyncTest::TearDown() {
test_util_a_.TearDown();
}
scoped_ptr<syncer::SyncChangeProcessor>
TemplateURLServiceSyncTest::PassProcessor() {
return sync_processor_wrapper_.PassAs<syncer::SyncChangeProcessor>();
}
scoped_ptr<syncer::SyncErrorFactory> TemplateURLServiceSyncTest::
CreateAndPassSyncErrorFactory() {
return scoped_ptr<syncer::SyncErrorFactory>(
new syncer::SyncErrorFactoryMock());
}
TemplateURL* TemplateURLServiceSyncTest::CreateTestTemplateURL(
const base::string16& keyword,
const std::string& url,
const std::string& guid,
time_t last_mod,
bool safe_for_autoreplace,
bool created_by_policy) const {
TemplateURLData data;
data.short_name = ASCIIToUTF16("unittest");
data.SetKeyword(keyword);
data.SetURL(url);
data.favicon_url = GURL("http://favicon.url");
data.safe_for_autoreplace = safe_for_autoreplace;
data.date_created = Time::FromTimeT(100);
data.last_modified = Time::FromTimeT(last_mod);
data.created_by_policy = created_by_policy;
data.prepopulate_id = 999999;
if (!guid.empty())
data.sync_guid = guid;
return new TemplateURL(NULL, data);
}
void TemplateURLServiceSyncTest::AssertEquals(const TemplateURL& expected,
const TemplateURL& actual) const {
ASSERT_EQ(expected.short_name(), actual.short_name());
ASSERT_EQ(expected.keyword(), actual.keyword());
ASSERT_EQ(expected.url(), actual.url());
ASSERT_EQ(expected.suggestions_url(), actual.suggestions_url());
ASSERT_EQ(expected.favicon_url(), actual.favicon_url());
ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list());
ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace());
ASSERT_EQ(expected.input_encodings(), actual.input_encodings());
ASSERT_EQ(expected.date_created(), actual.date_created());
ASSERT_EQ(expected.last_modified(), actual.last_modified());
}
void TemplateURLServiceSyncTest::AssertEquals(
const syncer::SyncDataList& data1,
const syncer::SyncDataList& data2) const {
SyncDataMap map1 = TemplateURLService::CreateGUIDToSyncDataMap(data1);
SyncDataMap map2 = TemplateURLService::CreateGUIDToSyncDataMap(data2);
for (SyncDataMap::const_iterator iter1 = map1.begin();
iter1 != map1.end(); iter1++) {
SyncDataMap::iterator iter2 = map2.find(iter1->first);
if (iter2 != map2.end()) {
ASSERT_EQ(GetKeyword(iter1->second), GetKeyword(iter2->second));
ASSERT_EQ(GetURL(iter1->second), GetURL(iter2->second));
map2.erase(iter2);
}
}
EXPECT_EQ(0U, map2.size());
}
syncer::SyncChange TemplateURLServiceSyncTest::CreateTestSyncChange(
syncer::SyncChange::SyncChangeType type,
TemplateURL* turl) const {
scoped_ptr<TemplateURL> scoped_turl(turl);
return syncer::SyncChange(
FROM_HERE,
type,
TemplateURLService::CreateSyncDataFromTemplateURL(*scoped_turl));
}
syncer::SyncDataList TemplateURLServiceSyncTest::CreateInitialSyncData() const {
syncer::SyncDataList list;
scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
"http://key1.com", "key1", 90));
list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com",
"key2", 90));
list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com",
"key3", 90));
list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
return list;
}
TemplateURL* TemplateURLServiceSyncTest::Deserialize(
const syncer::SyncData& sync_data) {
syncer::SyncChangeList dummy;
return TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData(NULL,
NULL, sync_data, &dummy);
}
TemplateURL* TemplateURLServiceSyncTest::CopyTemplateURL(
const TemplateURL* turl,
const std::string& url,
const std::string& guid) {
TemplateURLData data (turl->data());
data.SetURL(url);
data.date_created = Time::FromTimeT(100);
data.last_modified = Time::FromTimeT(100);
data.sync_guid = guid;
return new TemplateURL(NULL, data);
}
TEST_F(TemplateURLServiceSyncTest, SerializeDeserialize) {
scoped_ptr<TemplateURL> turl(
CreateTestTemplateURL(
ASCIIToUTF16("unittest"), "http://www.unittest.com/"));
syncer::SyncData sync_data =
TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
scoped_ptr<TemplateURL> deserialized(Deserialize(sync_data));
EXPECT_TRUE(deserialized.get());
AssertEquals(*turl, *deserialized);
}
TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataBasic) {
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com"));
syncer::SyncDataList all_sync_data =
model()->GetAllSyncData(syncer::SEARCH_ENGINES);
EXPECT_EQ(3U, all_sync_data.size());
for (syncer::SyncDataList::const_iterator iter = all_sync_data.begin();
iter != all_sync_data.end(); ++iter) {
std::string guid = GetGUID(*iter);
const TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid);
scoped_ptr<TemplateURL> deserialized(Deserialize(*iter));
AssertEquals(*service_turl, *deserialized);
}
}
TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataWithExtension) {
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key3"),
std::string(extensions::kExtensionScheme) + "://blahblahblah"));
syncer::SyncDataList all_sync_data =
model()->GetAllSyncData(syncer::SEARCH_ENGINES);
EXPECT_EQ(3U, all_sync_data.size());
for (syncer::SyncDataList::const_iterator iter = all_sync_data.begin();
iter != all_sync_data.end(); ++iter) {
std::string guid = GetGUID(*iter);
const TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid);
scoped_ptr<TemplateURL> deserialized(Deserialize(*iter));
AssertEquals(*service_turl, *deserialized);
}
}
TEST_F(TemplateURLServiceSyncTest, GetAllSyncDataNoManagedEngines) {
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
TemplateURL* managed_turl = CreateTestTemplateURL(ASCIIToUTF16("key3"),
"http://key3.com", std::string(), 100, false, true);
model()->Add(managed_turl);
syncer::SyncDataList all_sync_data =
model()->GetAllSyncData(syncer::SEARCH_ENGINES);
EXPECT_EQ(2U, all_sync_data.size());
for (syncer::SyncDataList::const_iterator iter = all_sync_data.begin();
iter != all_sync_data.end(); ++iter) {
std::string guid = GetGUID(*iter);
TemplateURL* service_turl = model()->GetTemplateURLForGUID(guid);
scoped_ptr<TemplateURL> deserialized(Deserialize(*iter));
ASSERT_FALSE(service_turl->created_by_policy());
AssertEquals(*service_turl, *deserialized);
}
}
TEST_F(TemplateURLServiceSyncTest, UniquifyKeyword) {
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com"));
scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
"http://new.com", "xyz"));
base::string16 new_keyword = model()->UniquifyKeyword(*turl, false);
EXPECT_EQ(ASCIIToUTF16("new.com"), new_keyword);
EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("new.com"), "http://new.com",
"xyz"));
turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://new.com"));
new_keyword = model()->UniquifyKeyword(*turl, false);
EXPECT_EQ(ASCIIToUTF16("key1_"), new_keyword);
EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1_"), "http://new.com"));
turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://new.com"));
new_keyword = model()->UniquifyKeyword(*turl, false);
EXPECT_EQ(ASCIIToUTF16("key1__"), new_keyword);
EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
turl.reset(
CreateTestTemplateURL(ASCIIToUTF16("unique"), "http://unique.com"));
new_keyword = model()->UniquifyKeyword(*turl, true);
EXPECT_EQ(ASCIIToUTF16("unique_"), new_keyword);
EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(new_keyword));
}
TEST_F(TemplateURLServiceSyncTest, IsLocalTemplateURLBetter) {
const struct {
time_t local_time;
time_t sync_time;
bool local_is_default;
bool local_created_by_policy;
bool expected_result;
} test_cases[] = {
{10, 100, true, false, true},
{10, 100, false, true, true},
{100, 100, false, false, false},
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
TemplateURL* local_turl = CreateTestTemplateURL(
ASCIIToUTF16("localkey"), "www.local.com", "localguid",
test_cases[i].local_time, true, test_cases[i].local_created_by_policy);
model()->Add(local_turl);
if (test_cases[i].local_is_default)
model()->SetDefaultSearchProvider(local_turl);
scoped_ptr<TemplateURL> sync_turl(CreateTestTemplateURL(
ASCIIToUTF16("synckey"), "www.sync.com", "syncguid",
test_cases[i].sync_time));
EXPECT_EQ(test_cases[i].expected_result,
model()->IsLocalTemplateURLBetter(local_turl, sync_turl.get()));
if (test_cases[i].local_is_default)
model()->SetDefaultSearchProvider(NULL);
model()->Remove(local_turl);
}
}
TEST_F(TemplateURLServiceSyncTest, ResolveSyncKeywordConflict) {
base::string16 original_turl_keyword = ASCIIToUTF16("key1");
TemplateURL* original_turl = CreateTestTemplateURL(original_turl_keyword,
"http://key1.com", std::string(), 9000);
model()->Add(original_turl);
scoped_ptr<TemplateURL> sync_turl(CreateTestTemplateURL(original_turl_keyword,
"http://new.com", "remote", 8999));
syncer::SyncChangeList changes;
model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
EXPECT_NE(original_turl_keyword, sync_turl->keyword());
EXPECT_EQ(original_turl_keyword, original_turl->keyword());
ASSERT_EQ(1U, changes.size());
EXPECT_EQ("remote", GetGUID(changes[0].sync_data()));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
changes.clear();
model()->Remove(original_turl);
original_turl = CreateTestTemplateURL(original_turl_keyword,
"http://key1.com", "local", 9000);
model()->Add(original_turl);
TemplateURLID original_id = original_turl->id();
sync_turl.reset(CreateTestTemplateURL(original_turl_keyword, "http://new.com",
std::string(), 9001));
model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
EXPECT_EQ(original_turl_keyword, sync_turl->keyword());
EXPECT_NE(original_turl_keyword, original_turl->keyword());
EXPECT_FALSE(original_turl->safe_for_autoreplace());
EXPECT_EQ(original_id, original_turl->id());
EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(original_turl_keyword));
ASSERT_EQ(1U, changes.size());
EXPECT_EQ("local", GetGUID(changes[0].sync_data()));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
changes.clear();
model()->Remove(original_turl);
original_turl = CreateTestTemplateURL(original_turl_keyword,
"http://key1.com", "local2", 9000);
model()->Add(original_turl);
sync_turl.reset(CreateTestTemplateURL(original_turl_keyword, "http://new.com",
std::string(), 9000));
model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
EXPECT_EQ(original_turl_keyword, sync_turl->keyword());
EXPECT_NE(original_turl_keyword, original_turl->keyword());
EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(original_turl_keyword));
ASSERT_EQ(1U, changes.size());
EXPECT_EQ("local2", GetGUID(changes[0].sync_data()));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
changes.clear();
model()->Remove(original_turl);
original_turl = CreateTestTemplateURL(original_turl_keyword,
"http://key1.com", std::string(), 9000, false, true);
model()->Add(original_turl);
sync_turl.reset(CreateTestTemplateURL(original_turl_keyword, "http://new.com",
"remote2", 9999));
model()->ResolveSyncKeywordConflict(sync_turl.get(), original_turl, &changes);
EXPECT_NE(original_turl_keyword, sync_turl->keyword());
EXPECT_EQ(original_turl_keyword, original_turl->keyword());
EXPECT_EQ(NULL, model()->GetTemplateURLForKeyword(sync_turl->keyword()));
ASSERT_EQ(1U, changes.size());
EXPECT_EQ("remote2", GetGUID(changes[0].sync_data()));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
changes.clear();
model()->Remove(original_turl);
}
TEST_F(TemplateURLServiceSyncTest, StartSyncEmpty) {
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, syncer::SyncDataList(),
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(0U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_EQ(0U, processor()->change_list_size());
EXPECT_EQ(0, merge_result.num_items_added());
EXPECT_EQ(0, merge_result.num_items_modified());
EXPECT_EQ(0, merge_result.num_items_deleted());
EXPECT_EQ(0, merge_result.num_items_before_association());
EXPECT_EQ(0, merge_result.num_items_after_association());
}
TEST_F(TemplateURLServiceSyncTest, MergeIntoEmpty) {
syncer::SyncDataList initial_data = CreateInitialSyncData();
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
iter != initial_data.end(); ++iter) {
std::string guid = GetGUID(*iter);
EXPECT_TRUE(model()->GetTemplateURLForGUID(guid));
}
EXPECT_EQ(0U, processor()->change_list_size());
EXPECT_EQ(3, merge_result.num_items_added());
EXPECT_EQ(0, merge_result.num_items_modified());
EXPECT_EQ(0, merge_result.num_items_deleted());
EXPECT_EQ(0, merge_result.num_items_before_association());
EXPECT_EQ(3, merge_result.num_items_after_association());
}
TEST_F(TemplateURLServiceSyncTest, MergeInAllNewData) {
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("abc.com"), "http://abc.com",
"abc"));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("def.com"), "http://def.com",
"def"));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("xyz.com"), "http://xyz.com",
"xyz"));
syncer::SyncDataList initial_data = CreateInitialSyncData();
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(6U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
iter != initial_data.end(); ++iter) {
std::string guid = GetGUID(*iter);
EXPECT_TRUE(model()->GetTemplateURLForGUID(guid));
}
EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("abc.com")));
EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("def.com")));
EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("xyz.com")));
EXPECT_EQ(3U, processor()->change_list_size());
EXPECT_TRUE(processor()->contains_guid("abc"));
EXPECT_TRUE(processor()->contains_guid("def"));
EXPECT_TRUE(processor()->contains_guid("xyz"));
EXPECT_EQ(3, merge_result.num_items_added());
EXPECT_EQ(0, merge_result.num_items_modified());
EXPECT_EQ(0, merge_result.num_items_deleted());
EXPECT_EQ(3, merge_result.num_items_before_association());
EXPECT_EQ(6, merge_result.num_items_after_association());
}
TEST_F(TemplateURLServiceSyncTest, MergeSyncIsTheSame) {
syncer::SyncDataList initial_data = CreateInitialSyncData();
for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
iter != initial_data.end(); ++iter) {
TemplateURL* converted = Deserialize(*iter);
model()->Add(converted);
}
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
iter != initial_data.end(); ++iter) {
std::string guid = GetGUID(*iter);
EXPECT_TRUE(model()->GetTemplateURLForGUID(guid));
}
EXPECT_EQ(0U, processor()->change_list_size());
EXPECT_EQ(0, merge_result.num_items_added());
EXPECT_EQ(0, merge_result.num_items_modified());
EXPECT_EQ(0, merge_result.num_items_deleted());
EXPECT_EQ(3, merge_result.num_items_before_association());
EXPECT_EQ(3, merge_result.num_items_after_association());
}
TEST_F(TemplateURLServiceSyncTest, MergeUpdateFromSync) {
syncer::SyncDataList initial_data;
TemplateURL* turl1 = CreateTestTemplateURL(ASCIIToUTF16("abc.com"),
"http://abc.com", "abc", 9000);
model()->Add(turl1);
TemplateURL* turl2 = CreateTestTemplateURL(ASCIIToUTF16("xyz.com"),
"http://xyz.com", "xyz", 9000);
model()->Add(turl2);
scoped_ptr<TemplateURL> turl1_newer(CreateTestTemplateURL(
ASCIIToUTF16("abc.com"), "http://abc.ca", "abc", 9999));
initial_data.push_back(
TemplateURLService::CreateSyncDataFromTemplateURL(*turl1_newer));
scoped_ptr<TemplateURL> turl2_older(CreateTestTemplateURL(
ASCIIToUTF16("xyz.com"), "http://xyz.ca", "xyz", 8888));
initial_data.push_back(
TemplateURLService::CreateSyncDataFromTemplateURL(*turl2_older));
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(2U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_EQ(turl1, model()->GetTemplateURLForGUID("abc"));
EXPECT_EQ("http://abc.ca", turl1->url());
EXPECT_EQ(1U, processor()->change_list_size());
ASSERT_TRUE(processor()->contains_guid("xyz"));
syncer::SyncChange change = processor()->change_for_guid("xyz");
EXPECT_TRUE(change.change_type() == syncer::SyncChange::ACTION_UPDATE);
EXPECT_EQ("http://xyz.com", GetURL(change.sync_data()));
EXPECT_EQ(0, merge_result.num_items_added());
EXPECT_EQ(1, merge_result.num_items_modified());
EXPECT_EQ(0, merge_result.num_items_deleted());
EXPECT_EQ(2, merge_result.num_items_before_association());
EXPECT_EQ(2, merge_result.num_items_after_association());
}
TEST_F(TemplateURLServiceSyncTest, MergeAddFromOlderSyncData) {
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com",
"aaa", 100));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"),
"http://expected.com", "bbb", 100));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("unique"),
"http://unique.com", "ccc"));
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES,
CreateInitialSyncData(), PassProcessor(),
CreateAndPassSyncErrorFactory());
EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
ASSERT_TRUE(processor()->contains_guid("key1"));
syncer::SyncChange key1_change = processor()->change_for_guid("key1");
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key1_change.change_type());
EXPECT_FALSE(model()->GetTemplateURLForGUID("aaa"));
const TemplateURL* key2 = model()->GetTemplateURLForGUID("key2");
ASSERT_TRUE(key2);
EXPECT_EQ(ASCIIToUTF16("key2"), key2->keyword());
EXPECT_EQ("http://expected.com", key2->url());
ASSERT_TRUE(processor()->contains_guid("key2"));
syncer::SyncChange key2_change = processor()->change_for_guid("key2");
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key2_change.change_type());
EXPECT_EQ("key2", GetKeyword(key2_change.sync_data()));
EXPECT_EQ("http://expected.com", GetURL(key2_change.sync_data()));
EXPECT_FALSE(model()->GetTemplateURLForGUID("bbb"));
EXPECT_TRUE(model()->GetTemplateURLForGUID("ccc"));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
EXPECT_EQ(3U, processor()->change_list_size());
ASSERT_TRUE(processor()->contains_guid("ccc"));
EXPECT_EQ(syncer::SyncChange::ACTION_ADD,
processor()->change_for_guid("ccc").change_type());
EXPECT_EQ(1, merge_result.num_items_added());
EXPECT_EQ(2, merge_result.num_items_modified());
EXPECT_EQ(0, merge_result.num_items_deleted());
EXPECT_EQ(3, merge_result.num_items_before_association());
EXPECT_EQ(4, merge_result.num_items_after_association());
}
TEST_F(TemplateURLServiceSyncTest, MergeAddFromNewerSyncData) {
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com",
"aaa", 10));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"),
"http://expected.com", "bbb", 10));
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("unique"),
"http://unique.com", "ccc", 10));
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES,
CreateInitialSyncData(), PassProcessor(),
CreateAndPassSyncErrorFactory());
EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
EXPECT_FALSE(model()->GetTemplateURLForGUID("aaa"));
EXPECT_FALSE(processor()->contains_guid("key1"));
EXPECT_FALSE(processor()->contains_guid("aaa"));
const TemplateURL* key2_sync = model()->GetTemplateURLForGUID("key2");
ASSERT_TRUE(key2_sync);
EXPECT_EQ(ASCIIToUTF16("key2"), key2_sync->keyword());
EXPECT_FALSE(model()->GetTemplateURLForGUID("bbb"));
EXPECT_TRUE(model()->GetTemplateURLForGUID("ccc"));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
EXPECT_EQ(1U, processor()->change_list_size());
ASSERT_TRUE(processor()->contains_guid("ccc"));
EXPECT_EQ(syncer::SyncChange::ACTION_ADD,
processor()->change_for_guid("ccc").change_type());
EXPECT_EQ(3, merge_result.num_items_added());
EXPECT_EQ(0, merge_result.num_items_modified());
EXPECT_EQ(2, merge_result.num_items_deleted());
EXPECT_EQ(3, merge_result.num_items_before_association());
EXPECT_EQ(4, merge_result.num_items_after_association());
}
TEST_F(TemplateURLServiceSyncTest, ProcessChangesEmptyModel) {
model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, syncer::SyncDataList(),
PassProcessor(), CreateAndPassSyncErrorFactory());
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com", "key1")));
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com", "key2")));
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key3")));
model()->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_EQ(0U, processor()->change_list_size());
EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
}
TEST_F(TemplateURLServiceSyncTest, ProcessChangesNoConflicts) {
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
CreateInitialSyncData(), PassProcessor(),
CreateAndPassSyncErrorFactory());
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("key4"), "http://key4.com", "key4")));
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
"key2")));
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_DELETE,
CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key3")));
model()->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_EQ(0U, processor()->change_list_size());
EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
const TemplateURL* turl = model()->GetTemplateURLForGUID("key2");
EXPECT_TRUE(turl);
EXPECT_EQ(ASCIIToUTF16("newkeyword"), turl->keyword());
EXPECT_EQ("http://new.com", turl->url());
EXPECT_FALSE(model()->GetTemplateURLForGUID("key3"));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key4"));
}
TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithConflictsSyncWins) {
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
CreateInitialSyncData(), PassProcessor(),
CreateAndPassSyncErrorFactory());
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://new.com", "aaa")));
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key1")));
model()->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_EQ(2U, processor()->change_list_size());
ASSERT_TRUE(processor()->contains_guid("key2"));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
processor()->change_for_guid("key2").change_type());
ASSERT_TRUE(processor()->contains_guid("key3"));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
processor()->change_for_guid("key3").change_type());
EXPECT_TRUE(model()->GetTemplateURLForGUID("aaa"));
EXPECT_EQ(model()->GetTemplateURLForGUID("aaa"),
model()->GetTemplateURLForKeyword(ASCIIToUTF16("key2")));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
EXPECT_EQ(model()->GetTemplateURLForGUID("key2"),
model()->GetTemplateURLForKeyword(ASCIIToUTF16("key2.com")));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
EXPECT_EQ(model()->GetTemplateURLForGUID("key1"),
model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3")));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
EXPECT_EQ(model()->GetTemplateURLForGUID("key3"),
model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3.com")));
}
TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithConflictsLocalWins) {
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
CreateInitialSyncData(), PassProcessor(),
CreateAndPassSyncErrorFactory());
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://new.com", "aaa",
10)));
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com", "key1",
10)));
model()->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_EQ(2U, processor()->change_list_size());
EXPECT_TRUE(model()->GetTemplateURLForGUID("aaa"));
EXPECT_EQ(model()->GetTemplateURLForGUID("aaa"),
model()->GetTemplateURLForKeyword(ASCIIToUTF16("new.com")));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
EXPECT_EQ(model()->GetTemplateURLForGUID("key2"),
model()->GetTemplateURLForKeyword(ASCIIToUTF16("key2")));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key1"));
EXPECT_EQ(model()->GetTemplateURLForGUID("key1"),
model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3.com")));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
EXPECT_EQ(model()->GetTemplateURLForGUID("key3"),
model()->GetTemplateURLForKeyword(ASCIIToUTF16("key3")));
ASSERT_TRUE(processor()->contains_guid("aaa"));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
processor()->change_for_guid("aaa").change_type());
ASSERT_TRUE(processor()->contains_guid("key1"));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
processor()->change_for_guid("key1").change_type());
}
TEST_F(TemplateURLServiceSyncTest, ProcessTemplateURLChange) {
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
CreateInitialSyncData(), PassProcessor(),
CreateAndPassSyncErrorFactory());
TemplateURL* new_turl =
CreateTestTemplateURL(ASCIIToUTF16("baidu"), "http://baidu.cn", "new");
model()->Add(new_turl);
EXPECT_EQ(1U, processor()->change_list_size());
ASSERT_TRUE(processor()->contains_guid("new"));
syncer::SyncChange change = processor()->change_for_guid("new");
EXPECT_EQ(syncer::SyncChange::ACTION_ADD, change.change_type());
EXPECT_EQ("baidu", GetKeyword(change.sync_data()));
EXPECT_EQ("http://baidu.cn", GetURL(change.sync_data()));
TemplateURL* existing_turl = model()->GetTemplateURLForGUID("key1");
model()->ResetTemplateURL(existing_turl, existing_turl->short_name(),
ASCIIToUTF16("k"), existing_turl->url());
EXPECT_EQ(1U, processor()->change_list_size());
ASSERT_TRUE(processor()->contains_guid("key1"));
change = processor()->change_for_guid("key1");
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
EXPECT_EQ("k", GetKeyword(change.sync_data()));
existing_turl = model()->GetTemplateURLForGUID("key2");
model()->Remove(existing_turl);
EXPECT_EQ(1U, processor()->change_list_size());
ASSERT_TRUE(processor()->contains_guid("key2"));
change = processor()->change_for_guid("key2");
EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, change.change_type());
}
TEST_F(TemplateURLServiceSyncTest, ProcessChangesWithLocalExtensions) {
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
CreateInitialSyncData(), PassProcessor(),
CreateAndPassSyncErrorFactory());
TemplateURL* extension1 = CreateTestTemplateURL(ASCIIToUTF16("keyword1"),
std::string(extensions::kExtensionScheme) + "://extension1");
model()->Add(extension1);
EXPECT_EQ(1U, processor()->change_list_size());
TemplateURL* extension2 = CreateTestTemplateURL(ASCIIToUTF16("keyword2"),
std::string(extensions::kExtensionScheme) + "://extension2");
model()->Add(extension2);
EXPECT_EQ(1U, processor()->change_list_size());
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("keyword1"), "http://aaa.com",
std::string(), 100, true)));
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("keyword2"), "http://bbb.com")));
model()->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_FALSE(model()->GetTemplateURLForHost("aaa.com") == NULL);
EXPECT_EQ(model()->GetTemplateURLForHost("aaa.com"),
model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1")));
TemplateURL* url_for_keyword2 =
model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2"));
EXPECT_NE(extension2, url_for_keyword2);
EXPECT_EQ("http://bbb.com", url_for_keyword2->url());
EXPECT_EQ(extension1,
model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1_")));
EXPECT_EQ(extension2,
model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2_")));
}
TEST_F(TemplateURLServiceSyncTest, AutogeneratedKeywordMigrated) {
syncer::SyncDataList initial_data;
scoped_ptr<TemplateURL> turl(
CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com", "key1"));
initial_data.push_back(
CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"),
"{google:baseURL}search?q={searchTerms}", "key2"));
initial_data.push_back(
CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
TemplateURL* key1 = model()->GetTemplateURLForHost("key1.com");
ASSERT_FALSE(key1 == NULL);
EXPECT_EQ(ASCIIToUTF16("key1.com"), key1->keyword());
GURL google_url(UIThreadSearchTermsData(profile_a()).GoogleBaseURLValue());
TemplateURL* key2 = model()->GetTemplateURLForHost(google_url.host());
ASSERT_FALSE(key2 == NULL);
base::string16 google_keyword(net::StripWWWFromHost(google_url));
EXPECT_EQ(google_keyword, key2->keyword());
EXPECT_GE(processor()->change_list_size(), 2U);
ASSERT_TRUE(processor()->contains_guid("key1"));
syncer::SyncChange key1_change = processor()->change_for_guid("key1");
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key1_change.change_type());
EXPECT_EQ("key1.com", GetKeyword(key1_change.sync_data()));
ASSERT_TRUE(processor()->contains_guid("key2"));
syncer::SyncChange key2_change = processor()->change_for_guid("key2");
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key2_change.change_type());
EXPECT_EQ(google_keyword, UTF8ToUTF16(GetKeyword(key2_change.sync_data())));
}
TEST_F(TemplateURLServiceSyncTest, AutogeneratedKeywordConflicts) {
base::string16 google_keyword(net::StripWWWFromHost(GURL(
UIThreadSearchTermsData(profile_a()).GoogleBaseURLValue())));
const std::string local_google_url =
"{google:baseURL}1/search?q={searchTerms}";
TemplateURL* google = CreateTestTemplateURL(google_keyword, local_google_url);
model()->Add(google);
TemplateURL* other =
CreateTestTemplateURL(ASCIIToUTF16("other.com"), "http://other.com/foo");
model()->Add(other);
syncer::SyncDataList initial_data;
scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("sync1"),
"{google:baseURL}2/search?q={searchTerms}", "sync1", 50));
initial_data.push_back(
CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
const std::string synced_other_url =
"http://other.com/search?q={searchTerms}";
turl.reset(CreateTestTemplateURL(ASCIIToUTF16("sync2"),
synced_other_url, "sync2", 150));
initial_data.push_back(
CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
const std::string local_google_guid = google->sync_guid();
const std::string local_other_guid = other->sync_guid();
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_FALSE(model()->GetTemplateURLForGUID(local_google_guid));
ASSERT_TRUE(model()->GetTemplateURLForGUID("sync1"));
EXPECT_EQ(google_keyword, model()->GetTemplateURLForGUID("sync1")->keyword());
EXPECT_FALSE(model()->GetTemplateURLForGUID(local_other_guid));
ASSERT_TRUE(model()->GetTemplateURLForGUID("sync2"));
EXPECT_EQ(ASCIIToUTF16("other.com"),
model()->GetTemplateURLForGUID("sync2")->keyword());
EXPECT_EQ(processor()->change_list_size(), 2U);
ASSERT_TRUE(processor()->contains_guid("sync1"));
syncer::SyncChange sync1_change = processor()->change_for_guid("sync1");
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, sync1_change.change_type());
EXPECT_EQ(google_keyword, UTF8ToUTF16(GetKeyword(sync1_change.sync_data())));
EXPECT_EQ(local_google_url, GetURL(sync1_change.sync_data()));
ASSERT_TRUE(processor()->contains_guid("sync2"));
syncer::SyncChange sync2_change = processor()->change_for_guid("sync2");
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, sync2_change.change_type());
EXPECT_EQ("other.com", GetKeyword(sync2_change.sync_data()));
EXPECT_EQ(synced_other_url, GetURL(sync2_change.sync_data()));
}
TEST_F(TemplateURLServiceSyncTest, TwoAutogeneratedKeywordsUsingGoogleBaseURL) {
syncer::SyncDataList initial_data;
scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
"{google:baseURL}1/search?q={searchTerms}", "key1", 50));
initial_data.push_back(
CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"),
"{google:baseURL}2/search?q={searchTerms}", "key2"));
initial_data.push_back(
CreateCustomSyncData(*turl, true, turl->url(), turl->sync_guid()));
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
base::string16 google_keyword(net::StripWWWFromHost(GURL(
UIThreadSearchTermsData(profile_a()).GoogleBaseURLValue())));
TemplateURL* keyword1 =
model()->GetTemplateURLForKeyword(google_keyword + ASCIIToUTF16("_"));
ASSERT_FALSE(keyword1 == NULL);
EXPECT_EQ("key1", keyword1->sync_guid());
TemplateURL* keyword2 = model()->GetTemplateURLForKeyword(google_keyword);
ASSERT_FALSE(keyword2 == NULL);
EXPECT_EQ("key2", keyword2->sync_guid());
EXPECT_GE(processor()->change_list_size(), 2U);
ASSERT_TRUE(processor()->contains_guid("key1"));
syncer::SyncChange key1_change = processor()->change_for_guid("key1");
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key1_change.change_type());
EXPECT_EQ(keyword1->keyword(),
base::UTF8ToUTF16(GetKeyword(key1_change.sync_data())));
ASSERT_TRUE(processor()->contains_guid("key2"));
syncer::SyncChange key2_change = processor()->change_for_guid("key2");
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, key2_change.change_type());
EXPECT_EQ(keyword2->keyword(),
base::UTF8ToUTF16(GetKeyword(key2_change.sync_data())));
}
TEST_F(TemplateURLServiceSyncTest, DuplicateEncodingsRemoved) {
syncer::SyncDataList initial_data;
TemplateURLData data;
data.short_name = ASCIIToUTF16("test");
data.SetKeyword(ASCIIToUTF16("keyword"));
data.SetURL("http://test/%s");
data.input_encodings.push_back("UTF-8");
data.input_encodings.push_back("UTF-8");
data.input_encodings.push_back("UTF-16");
data.input_encodings.push_back("UTF-8");
data.input_encodings.push_back("Big5");
data.input_encodings.push_back("UTF-16");
data.input_encodings.push_back("Big5");
data.input_encodings.push_back("Windows-1252");
data.date_created = Time::FromTimeT(100);
data.last_modified = Time::FromTimeT(100);
data.sync_guid = "keyword";
scoped_ptr<TemplateURL> turl(new TemplateURL(NULL, data));
initial_data.push_back(
TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
TemplateURL* keyword =
model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
ASSERT_FALSE(keyword == NULL);
EXPECT_EQ(4U, keyword->input_encodings().size());
EXPECT_GE(processor()->change_list_size(), 1U);
ASSERT_TRUE(processor()->contains_guid("keyword"));
syncer::SyncChange keyword_change = processor()->change_for_guid("keyword");
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, keyword_change.change_type());
EXPECT_EQ("UTF-8;UTF-16;Big5;Windows-1252", keyword_change.sync_data().
GetSpecifics().search_engine().input_encodings());
}
TEST_F(TemplateURLServiceSyncTest, MergeTwoClientsBasic) {
model_b()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
CreateInitialSyncData(), PassProcessor(),
CreateAndPassSyncErrorFactory());
scoped_ptr<syncer::SyncChangeProcessorWrapperForTest> delegate_b(
new syncer::SyncChangeProcessorWrapperForTest(model_b()));
model_a()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
model_b()->GetAllSyncData(syncer::SEARCH_ENGINES),
delegate_b.PassAs<syncer::SyncChangeProcessor>(),
CreateAndPassSyncErrorFactory());
AssertEquals(model_a()->GetAllSyncData(syncer::SEARCH_ENGINES),
model_b()->GetAllSyncData(syncer::SEARCH_ENGINES));
}
TEST_F(TemplateURLServiceSyncTest, MergeTwoClientsDupesAndConflicts) {
model_b()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
CreateInitialSyncData(), PassProcessor(),
CreateAndPassSyncErrorFactory());
model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key4"), "http://key4.com",
"key4"));
model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com",
"key2"));
model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key3"), "http://key3.com",
"key5", 10));
model_a()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key6.com",
"key6", 10));
scoped_ptr<syncer::SyncChangeProcessorWrapperForTest> delegate_b(
new syncer::SyncChangeProcessorWrapperForTest(model_b()));
model_a()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES,
model_b()->GetAllSyncData(syncer::SEARCH_ENGINES),
delegate_b.PassAs<syncer::SyncChangeProcessor>(),
CreateAndPassSyncErrorFactory());
AssertEquals(model_a()->GetAllSyncData(syncer::SEARCH_ENGINES),
model_b()->GetAllSyncData(syncer::SEARCH_ENGINES));
}
TEST_F(TemplateURLServiceSyncTest, StopSyncing) {
syncer::SyncError error =
model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES,
CreateInitialSyncData(),
PassProcessor(),
CreateAndPassSyncErrorFactory()).error();
ASSERT_FALSE(error.IsSet());
model()->StopSyncing(syncer::SEARCH_ENGINES);
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
"key2")));
error = model()->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_TRUE(error.IsSet());
EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("newkeyword")));
}
TEST_F(TemplateURLServiceSyncTest, SyncErrorOnInitialSync) {
processor()->set_erroneous(true);
syncer::SyncError error =
model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES,
CreateInitialSyncData(),
PassProcessor(),
CreateAndPassSyncErrorFactory()).error();
EXPECT_TRUE(error.IsSet());
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
"key2")));
processor()->set_erroneous(false);
error = model()->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_TRUE(error.IsSet());
EXPECT_TRUE(model()->GetTemplateURLForGUID("key2"));
EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("newkeyword")));
}
TEST_F(TemplateURLServiceSyncTest, SyncErrorOnLaterSync) {
syncer::SyncError error =
model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES,
CreateInitialSyncData(),
PassProcessor(),
CreateAndPassSyncErrorFactory()).error();
ASSERT_FALSE(error.IsSet());
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
CreateTestTemplateURL(ASCIIToUTF16("newkeyword"), "http://new.com",
"key2")));
processor()->set_erroneous(true);
error = model()->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_TRUE(error.IsSet());
}
TEST_F(TemplateURLServiceSyncTest, MergeTwiceWithSameSyncData) {
syncer::SyncDataList initial_data;
initial_data.push_back(CreateInitialSyncData()[0]);
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com",
"key1", 10));
syncer::SyncError error =
model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES,
initial_data,
PassProcessor(),
CreateAndPassSyncErrorFactory()).error();
ASSERT_FALSE(error.IsSet());
TemplateURL* key1_url = model()->GetTemplateURLForGUID("key1");
ASSERT_TRUE(key1_url);
scoped_ptr<TemplateURL> updated_turl(new TemplateURL(key1_url->profile(),
key1_url->data()));
EXPECT_EQ(Time::FromTimeT(90), updated_turl->last_modified());
scoped_ptr<TemplateURL> temp_turl(Deserialize(initial_data[0]));
TemplateURLData data(temp_turl->data());
data.short_name = ASCIIToUTF16("SomethingDifferent");
temp_turl.reset(new TemplateURL(temp_turl->profile(), data));
initial_data.clear();
initial_data.push_back(
TemplateURLService::CreateSyncDataFromTemplateURL(*temp_turl));
model()->StopSyncing(syncer::SEARCH_ENGINES);
sync_processor_wrapper_.reset(
new syncer::SyncChangeProcessorWrapperForTest(sync_processor_.get()));
error = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES,
initial_data,
PassProcessor(),
CreateAndPassSyncErrorFactory()).error();
ASSERT_FALSE(error.IsSet());
const TemplateURL* reupdated_turl = model()->GetTemplateURLForGUID("key1");
ASSERT_TRUE(reupdated_turl);
AssertEquals(*updated_turl, *reupdated_turl);
}
TEST_F(TemplateURLServiceSyncTest, SyncedDefaultGUIDArrivesFirst) {
syncer::SyncDataList initial_data = CreateInitialSyncData();
scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key2"),
"http://key2.com/{searchTerms}", "key2", 90));
initial_data[1] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
model()->SetDefaultSearchProvider(model()->GetTemplateURLForGUID("key2"));
EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
const TemplateURL* default_search = model()->GetDefaultSearchProvider();
ASSERT_TRUE(default_search);
profile_a()->GetTestingPrefService()->SetString(
prefs::kSyncedDefaultSearchProviderGUID, "newdefault");
ASSERT_EQ(default_search, model()->GetDefaultSearchProvider());
syncer::SyncChangeList changes1;
changes1.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("random"), "http://random.com",
"random")));
model()->ProcessSyncChanges(FROM_HERE, changes1);
EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
ASSERT_EQ(default_search, model()->GetDefaultSearchProvider());
syncer::SyncChangeList changes2;
changes2.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("new"), "http://new.com/{searchTerms}",
"newdefault")));
model()->ProcessSyncChanges(FROM_HERE, changes2);
EXPECT_EQ(5U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
ASSERT_NE(default_search, model()->GetDefaultSearchProvider());
ASSERT_EQ("newdefault", model()->GetDefaultSearchProvider()->sync_guid());
}
TEST_F(TemplateURLServiceSyncTest, DefaultGuidDeletedBeforeNewDSPArrives) {
syncer::SyncDataList initial_data;
scoped_ptr<TemplateURL> turl1(CreateTestTemplateURL(ASCIIToUTF16("key1"),
"http://key1.com/{searchTerms}", "key1", 90));
TemplateURLData data;
data.short_name = ASCIIToUTF16("unittest");
data.SetKeyword(ASCIIToUTF16("key2"));
data.SetURL("http://key2.com/{searchTerms}");
data.favicon_url = GURL("http://favicon.url");
data.safe_for_autoreplace = false;
data.date_created = Time::FromTimeT(100);
data.last_modified = Time::FromTimeT(100);
data.created_by_policy = false;
data.prepopulate_id = 999999;
data.sync_guid = "key2";
data.show_in_default_list = true;
scoped_ptr<TemplateURL> turl2(new TemplateURL(NULL, data));
initial_data.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(
*turl1));
initial_data.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(
*turl2));
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
model()->SetDefaultSearchProvider(model()->GetTemplateURLForGUID("key1"));
ASSERT_EQ("key1", model()->GetDefaultSearchProvider()->sync_guid());
EXPECT_EQ(2U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
const TemplateURL* default_search = model()->GetDefaultSearchProvider();
ASSERT_TRUE(default_search);
profile_a()->GetTestingPrefService()->SetString(
prefs::kSyncedDefaultSearchProviderGUID, "newdefault");
ASSERT_EQ("key1", model()->GetDefaultSearchProvider()->sync_guid());
EXPECT_EQ("newdefault", profile_a()->GetTestingPrefService()->GetString(
prefs::kSyncedDefaultSearchProviderGUID));
syncer::SyncChangeList changes1;
changes1.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_DELETE,
turl1.release()));
model()->ProcessSyncChanges(FROM_HERE, changes1);
EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("key1_")));
EXPECT_EQ(2U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_EQ("key1", model()->GetDefaultSearchProvider()->sync_guid());
EXPECT_EQ("newdefault", profile_a()->GetTestingPrefService()->GetString(
prefs::kSyncedDefaultSearchProviderGUID));
syncer::SyncChange undelete = processor()->change_for_guid("key1");
EXPECT_EQ(syncer::SyncChange::ACTION_ADD, undelete.change_type());
EXPECT_EQ("key1_",
undelete.sync_data().GetSpecifics().search_engine().keyword());
syncer::SyncChangeList changes2;
changes2.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("new"), "http://new.com/{searchTerms}",
"newdefault")));
model()->ProcessSyncChanges(FROM_HERE, changes2);
EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_EQ("newdefault", model()->GetDefaultSearchProvider()->sync_guid());
EXPECT_EQ("newdefault", profile_a()->GetTestingPrefService()->GetString(
prefs::kSyncedDefaultSearchProviderGUID));
}
TEST_F(TemplateURLServiceSyncTest, SyncedDefaultArrivesAfterStartup) {
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("what"),
"http://thewhat.com/{searchTerms}",
"initdefault"));
model()->SetDefaultSearchProvider(
model()->GetTemplateURLForGUID("initdefault"));
const TemplateURL* default_search = model()->GetDefaultSearchProvider();
ASSERT_TRUE(default_search);
profile_a()->GetTestingPrefService()->SetString(
prefs::kSyncedDefaultSearchProviderGUID, "key2");
EXPECT_EQ(default_search, model()->GetDefaultSearchProvider());
syncer::SyncDataList initial_data = CreateInitialSyncData();
scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key2"),
"http://key2.com/{searchTerms}", "key2", 90));
initial_data[1] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
ASSERT_NE(default_search, model()->GetDefaultSearchProvider());
ASSERT_EQ("key2", model()->GetDefaultSearchProvider()->sync_guid());
}
TEST_F(TemplateURLServiceSyncTest, SyncedDefaultAlreadySetOnStartup) {
const char kGUID[] = "initdefault";
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("what"),
"http://thewhat.com/{searchTerms}",
kGUID));
model()->SetDefaultSearchProvider(model()->GetTemplateURLForGUID(kGUID));
const TemplateURL* default_search = model()->GetDefaultSearchProvider();
ASSERT_TRUE(default_search);
profile_a()->GetTestingPrefService()->SetString(
prefs::kSyncedDefaultSearchProviderGUID, kGUID);
EXPECT_EQ(default_search, model()->GetDefaultSearchProvider());
syncer::SyncDataList initial_data = CreateInitialSyncData();
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
ASSERT_EQ(default_search, model()->GetDefaultSearchProvider());
}
TEST_F(TemplateURLServiceSyncTest, NewDefaultIsAlreadySynced) {
profile_a()->GetTestingPrefService()->SetString(
prefs::kSyncedDefaultSearchProviderGUID, "key2");
syncer::SyncDataList initial_data = CreateInitialSyncData();
scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key2"),
"http://key2.com/{searchTerms}", "key2", 90));
initial_data[1] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
for (syncer::SyncDataList::const_iterator iter = initial_data.begin();
iter != initial_data.end(); ++iter) {
TemplateURL* converted = Deserialize(*iter);
model()->Add(converted);
}
model()->SetDefaultSearchProvider(model()->GetTemplateURLForGUID("key1"));
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
TemplateURL* current_default = model()->GetDefaultSearchProvider();
ASSERT_TRUE(current_default);
EXPECT_EQ("key2", current_default->sync_guid());
EXPECT_EQ(ASCIIToUTF16("key2"), current_default->keyword());
}
TEST_F(TemplateURLServiceSyncTest, SyncWithManagedDefaultSearch) {
syncer::SyncDataList initial_data = CreateInitialSyncData();
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
model()->SetDefaultSearchProvider(model()->GetTemplateURLForGUID("key2"));
EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
ASSERT_FALSE(model()->is_default_search_managed());
ASSERT_TRUE(model()->GetDefaultSearchProvider());
const char kName[] = "manageddefault";
const char kSearchURL[] = "http://manageddefault.com/search?t={searchTerms}";
const char kIconURL[] = "http://manageddefault.com/icon.jpg";
const char kEncodings[] = "UTF-16;UTF-32";
const char kAlternateURL[] =
"http://manageddefault.com/search#t={searchTerms}";
const char kSearchTermsReplacementKey[] = "espv";
test_util_a_.SetManagedDefaultSearchPreferences(true, kName, kName,
kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
kSearchTermsReplacementKey);
const TemplateURL* dsp_turl = model()->GetDefaultSearchProvider();
EXPECT_TRUE(model()->is_default_search_managed());
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
CreateTestTemplateURL(ASCIIToUTF16("newkeyword"),
"http://new.com/{searchTerms}",
"newdefault")));
model()->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_EQ(4U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
profile_a()->GetTestingPrefService()->SetString(
prefs::kSyncedDefaultSearchProviderGUID,
"newdefault");
EXPECT_EQ(dsp_turl, model()->GetDefaultSearchProvider());
EXPECT_TRUE(model()->is_default_search_managed());
const TemplateURL* expected_default =
model()->GetTemplateURLForGUID("newdefault");
test_util_a_.RemoveManagedDefaultSearchPreferences();
EXPECT_EQ(expected_default, model()->GetDefaultSearchProvider());
}
TEST_F(TemplateURLServiceSyncTest, SyncMergeDeletesDefault) {
TemplateURL* default_turl = CreateTestTemplateURL(ASCIIToUTF16("key1"),
"http://key1.com/{searchTerms}", "whateverguid", 10);
model()->Add(default_turl);
model()->SetDefaultSearchProvider(default_turl);
syncer::SyncDataList initial_data = CreateInitialSyncData();
scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(ASCIIToUTF16("key1"),
"http://key1.com/{searchTerms}", "key1", 90));
initial_data[0] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
EXPECT_FALSE(model()->GetTemplateURLForGUID("whateverguid"));
EXPECT_EQ(model()->GetDefaultSearchProvider(),
model()->GetTemplateURLForGUID("key1"));
}
TEST_F(TemplateURLServiceSyncTest, LocalDefaultWinsConflict) {
const base::string16 keyword(ASCIIToUTF16("key1"));
const std::string url("http://whatever.com/{searchTerms}");
TemplateURL* default_turl = CreateTestTemplateURL(keyword,
url,
"whateverguid",
10);
model()->Add(default_turl);
model()->SetDefaultSearchProvider(default_turl);
syncer::SyncDataList initial_data = CreateInitialSyncData();
scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(keyword,
"http://key1.com/{searchTerms}", "key1", 90));
initial_data[0] = TemplateURLService::CreateSyncDataFromTemplateURL(*turl);
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
const TemplateURL* winner = model()->GetTemplateURLForGUID("key1");
ASSERT_TRUE(winner);
EXPECT_EQ(model()->GetDefaultSearchProvider(), winner);
EXPECT_EQ(keyword, winner->keyword());
EXPECT_EQ(url, winner->url());
ASSERT_TRUE(processor()->contains_guid("key1"));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
processor()->change_for_guid("key1").change_type());
EXPECT_EQ(url, GetURL(processor()->change_for_guid("key1").sync_data()));
const TemplateURL* loser = model()->GetTemplateURLForGUID("whateverguid");
ASSERT_FALSE(loser);
}
TEST_F(TemplateURLServiceSyncTest, DeleteBogusData) {
syncer::SyncDataList initial_data;
scoped_ptr<TemplateURL> turl(
CreateTestTemplateURL(ASCIIToUTF16("key1"), "http://key1.com", "key1"));
initial_data.push_back(
CreateCustomSyncData(*turl, false, std::string(), turl->sync_guid()));
turl.reset(CreateTestTemplateURL(ASCIIToUTF16("key2"), "http://key2.com"));
initial_data.push_back(
CreateCustomSyncData(*turl, false, turl->url(), std::string()));
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
EXPECT_EQ(0U, model()->GetTemplateURLs().size());
EXPECT_EQ(2U, processor()->change_list_size());
ASSERT_TRUE(processor()->contains_guid("key1"));
EXPECT_EQ(syncer::SyncChange::ACTION_DELETE,
processor()->change_for_guid("key1").change_type());
ASSERT_TRUE(processor()->contains_guid(std::string()));
EXPECT_EQ(syncer::SyncChange::ACTION_DELETE,
processor()->change_for_guid(std::string()).change_type());
}
TEST_F(TemplateURLServiceSyncTest, PreSyncDeletes) {
model()->pre_sync_deletes_.insert("key1");
model()->pre_sync_deletes_.insert("key2");
model()->pre_sync_deletes_.insert("aaa");
model()->Add(CreateTestTemplateURL(ASCIIToUTF16("whatever"),
"http://key1.com", "bbb"));
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES,
CreateInitialSyncData(), PassProcessor(),
CreateAndPassSyncErrorFactory());
EXPECT_TRUE(model()->GetTemplateURLForGUID("bbb"));
EXPECT_TRUE(model()->GetTemplateURLForGUID("key3"));
syncer::SyncChange change = processor()->change_for_guid("key1");
EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, change.change_type());
change = processor()->change_for_guid("key2");
EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, change.change_type());
EXPECT_FALSE(processor()->contains_guid("aaa"));
EXPECT_TRUE(model()->pre_sync_deletes_.empty());
EXPECT_EQ(1, merge_result.num_items_added());
EXPECT_EQ(0, merge_result.num_items_modified());
EXPECT_EQ(0, merge_result.num_items_deleted());
EXPECT_EQ(1, merge_result.num_items_before_association());
EXPECT_EQ(2, merge_result.num_items_after_association());
}
TEST_F(TemplateURLServiceSyncTest, PreSyncUpdates) {
const char* kNewKeyword = "somethingnew";
size_t default_search_provider_index = 0;
ScopedVector<TemplateURL> prepop_turls =
TemplateURLPrepopulateData::GetPrepopulatedEngines(
profile_a(), &default_search_provider_index);
ASSERT_FALSE(prepop_turls.empty());
TemplateURLData data_copy(prepop_turls[0]->data());
data_copy.last_modified = Time::FromTimeT(10);
base::string16 original_keyword = data_copy.keyword();
data_copy.SetKeyword(ASCIIToUTF16(kNewKeyword));
data_copy.safe_for_autoreplace = false;
model()->Add(new TemplateURL(prepop_turls[0]->profile(), data_copy));
base::Time pre_merge_time = base::Time::Now();
base::RunLoop().RunUntilIdle();
test_util_a_.ResetModel(true);
TemplateURL* added_turl = model()->GetTemplateURLForKeyword(
ASCIIToUTF16(kNewKeyword));
base::Time new_timestamp = added_turl->last_modified();
EXPECT_GE(new_timestamp, pre_merge_time);
ASSERT_TRUE(added_turl);
std::string sync_guid = added_turl->sync_guid();
syncer::SyncDataList initial_data;
data_copy.SetKeyword(original_keyword);
data_copy.sync_guid = sync_guid;
scoped_ptr<TemplateURL> sync_turl(
new TemplateURL(prepop_turls[0]->profile(), data_copy));
initial_data.push_back(
TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES,
initial_data, PassProcessor(), CreateAndPassSyncErrorFactory());
ASSERT_EQ(added_turl, model()->GetTemplateURLForKeyword(
ASCIIToUTF16(kNewKeyword)));
EXPECT_EQ(new_timestamp, added_turl->last_modified());
syncer::SyncChange change = processor()->change_for_guid(sync_guid);
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
EXPECT_EQ(kNewKeyword,
change.sync_data().GetSpecifics().search_engine().keyword());
EXPECT_EQ(new_timestamp, base::Time::FromInternalValue(
change.sync_data().GetSpecifics().search_engine().last_modified()));
EXPECT_EQ(0, merge_result.num_items_added());
EXPECT_EQ(0, merge_result.num_items_modified());
EXPECT_EQ(0, merge_result.num_items_deleted());
EXPECT_EQ(static_cast<int>(prepop_turls.size()),
merge_result.num_items_before_association());
EXPECT_EQ(static_cast<int>(prepop_turls.size()),
merge_result.num_items_after_association());
}
TEST_F(TemplateURLServiceSyncTest, SyncBaseURLs) {
test_util_a_.SetGoogleBaseURL(GURL("http://google.com/"));
syncer::SyncDataList initial_data;
scoped_ptr<TemplateURL> turl(CreateTestTemplateURL(
ASCIIToUTF16("google.co.uk"), "{google:baseURL}search?q={searchTerms}",
"guid"));
initial_data.push_back(
TemplateURLService::CreateSyncDataFromTemplateURL(*turl));
model()->MergeDataAndStartSyncing(syncer::SEARCH_ENGINES, initial_data,
PassProcessor(), CreateAndPassSyncErrorFactory());
TemplateURL* synced_turl = model()->GetTemplateURLForGUID("guid");
ASSERT_TRUE(synced_turl);
EXPECT_EQ(ASCIIToUTF16("google.com"), synced_turl->keyword());
EXPECT_EQ(0U, processor()->change_list_size());
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
CreateTestTemplateURL(ASCIIToUTF16("google.de"),
"{google:baseURL}search?q={searchTerms}", "guid")));
model()->ProcessSyncChanges(FROM_HERE, changes);
EXPECT_EQ(ASCIIToUTF16("google.com"), synced_turl->keyword());
EXPECT_EQ(0U, processor()->change_list_size());
test_util_a_.SetGoogleBaseURL(GURL("http://google.co.in/"));
EXPECT_EQ(ASCIIToUTF16("google.co.in"), synced_turl->keyword());
EXPECT_EQ(1U, processor()->change_list_size());
ASSERT_TRUE(processor()->contains_guid("guid"));
syncer::SyncChange change(processor()->change_for_guid("guid"));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, change.change_type());
EXPECT_EQ("google.co.in", GetKeyword(change.sync_data()));
}
TEST_F(TemplateURLServiceSyncTest, MergeInSyncTemplateURL) {
enum ExpectedTemplateURL {
LOCAL,
SYNC,
BOTH,
NEITHER,
};
const struct {
ExpectedTemplateURL conflict_winner;
ExpectedTemplateURL synced_at_start;
ExpectedTemplateURL update_sent;
ExpectedTemplateURL turl_uniquified;
ExpectedTemplateURL present_in_model;
bool keywords_conflict;
int merge_results[3];
} test_cases[] = {
{SYNC, BOTH, LOCAL, LOCAL, BOTH, true, {1, 1, 0}},
{LOCAL, BOTH, SYNC, SYNC, BOTH, true, {1, 1, 0}},
{SYNC, SYNC, NEITHER, NEITHER, SYNC, true, {1, 0, 1}},
{LOCAL, SYNC, SYNC, NEITHER, SYNC, true, {0, 1, 0}},
{NEITHER, SYNC, NEITHER, NEITHER, BOTH, false, {1, 0, 0}},
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
ASSERT_FALSE(test_cases[i].conflict_winner == BOTH);
ASSERT_FALSE(test_cases[i].synced_at_start == NEITHER);
ASSERT_FALSE(test_cases[i].synced_at_start == LOCAL);
ASSERT_FALSE(test_cases[i].update_sent == BOTH);
ASSERT_FALSE(test_cases[i].turl_uniquified == BOTH);
ASSERT_FALSE(test_cases[i].present_in_model == NEITHER);
const base::string16 local_keyword = ASCIIToUTF16("localkeyword");
const base::string16 sync_keyword = test_cases[i].keywords_conflict ?
local_keyword : ASCIIToUTF16("synckeyword");
const std::string local_url = "www.localurl.com";
const std::string sync_url = "www.syncurl.com";
const time_t local_last_modified = 100;
const time_t sync_last_modified =
test_cases[i].conflict_winner == SYNC ? 110 : 90;
const std::string local_guid = "local_guid";
const std::string sync_guid = "sync_guid";
base::string16 expected_local_keyword = local_keyword;
base::string16 expected_sync_keyword = sync_keyword;
TemplateURL* local_turl = CreateTestTemplateURL(
local_keyword, local_url, local_guid, local_last_modified);
model()->Add(local_turl);
scoped_ptr<TemplateURL> sync_turl(CreateTestTemplateURL(
sync_keyword, sync_url, sync_guid, sync_last_modified));
SyncDataMap sync_data;
if (test_cases[i].synced_at_start == SYNC ||
test_cases[i].synced_at_start == BOTH) {
sync_data[sync_turl->sync_guid()] =
TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl);
}
if (test_cases[i].synced_at_start == BOTH) {
sync_data[local_turl->sync_guid()] =
TemplateURLService::CreateSyncDataFromTemplateURL(*local_turl);
}
SyncDataMap initial_data;
initial_data[local_turl->sync_guid()] =
TemplateURLService::CreateSyncDataFromTemplateURL(*local_turl);
syncer::SyncChangeList change_list;
syncer::SyncMergeResult merge_result(syncer::SEARCH_ENGINES);
model()->MergeInSyncTemplateURL(sync_turl.get(),
sync_data,
&change_list,
&initial_data,
&merge_result);
EXPECT_EQ(test_cases[i].merge_results[0], merge_result.num_items_added());
EXPECT_EQ(test_cases[i].merge_results[1],
merge_result.num_items_modified());
EXPECT_EQ(test_cases[i].merge_results[2], merge_result.num_items_deleted());
std::string expected_update_guid;
if (test_cases[i].update_sent == LOCAL)
expected_update_guid = local_guid;
else if (test_cases[i].update_sent == SYNC)
expected_update_guid = sync_guid;
if (!expected_update_guid.empty()) {
ASSERT_EQ(1U, change_list.size());
EXPECT_EQ(expected_update_guid, GetGUID(change_list[0].sync_data()));
EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE,
change_list[0].change_type());
} else {
EXPECT_EQ(0U, change_list.size());
}
if (test_cases[i].turl_uniquified == LOCAL) {
DCHECK(test_cases[i].keywords_conflict);
expected_local_keyword = ASCIIToUTF16("localkeyword_");
}
if (test_cases[i].turl_uniquified == SYNC) {
DCHECK(test_cases[i].keywords_conflict);
expected_sync_keyword = ASCIIToUTF16("localkeyword_");
}
if (test_cases[i].present_in_model == LOCAL ||
test_cases[i].present_in_model == BOTH) {
ASSERT_TRUE(model()->GetTemplateURLForGUID(local_guid));
EXPECT_EQ(expected_local_keyword, local_turl->keyword());
EXPECT_EQ(local_url, local_turl->url());
EXPECT_EQ(local_last_modified, local_turl->last_modified().ToTimeT());
model()->Remove(model()->GetTemplateURLForGUID(local_guid));
}
if (test_cases[i].present_in_model == SYNC ||
test_cases[i].present_in_model == BOTH) {
ASSERT_TRUE(model()->GetTemplateURLForGUID(sync_guid));
EXPECT_EQ(expected_sync_keyword, sync_turl->keyword());
EXPECT_EQ(sync_url, sync_turl->url());
EXPECT_EQ(sync_last_modified, sync_turl->last_modified().ToTimeT());
model()->Remove(model()->GetTemplateURLForGUID(sync_guid));
}
}
}
TEST_F(TemplateURLServiceSyncTest, MergePrepopulatedEngine) {
scoped_ptr<TemplateURL> default_turl(
TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
syncer::SyncDataList list;
scoped_ptr<TemplateURL> sync_turl(CopyTemplateURL(default_turl.get(),
"http://wrong.url.com?q={searchTerms}", "default"));
list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, list, PassProcessor(),
CreateAndPassSyncErrorFactory());
const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
EXPECT_TRUE(result_turl);
EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
EXPECT_EQ(default_turl->short_name(), result_turl->short_name());
EXPECT_EQ(default_turl->url(), result_turl->url());
}
TEST_F(TemplateURLServiceSyncTest, AddPrepopulatedEngine) {
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, syncer::SyncDataList(), PassProcessor(),
CreateAndPassSyncErrorFactory());
scoped_ptr<TemplateURL> default_turl(
TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
TemplateURL* sync_turl = CopyTemplateURL(default_turl.get(),
"http://wrong.url.com?q={searchTerms}", "default");
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_ADD,
sync_turl));
model()->ProcessSyncChanges(FROM_HERE, changes);
const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
EXPECT_TRUE(result_turl);
EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
EXPECT_EQ(default_turl->short_name(), result_turl->short_name());
EXPECT_EQ(default_turl->url(), result_turl->url());
}
TEST_F(TemplateURLServiceSyncTest, UpdatePrepopulatedEngine) {
scoped_ptr<TemplateURL> default_turl(
TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
TemplateURLData data(default_turl->data());
data.SetURL("http://old.wrong.url.com?q={searchTerms}");
data.sync_guid = "default";
model()->Add(new TemplateURL(NULL, data));
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, syncer::SyncDataList(), PassProcessor(),
CreateAndPassSyncErrorFactory());
TemplateURL* sync_turl = CopyTemplateURL(default_turl.get(),
"http://new.wrong.url.com?q={searchTerms}", "default");
syncer::SyncChangeList changes;
changes.push_back(CreateTestSyncChange(syncer::SyncChange::ACTION_UPDATE,
sync_turl));
model()->ProcessSyncChanges(FROM_HERE, changes);
const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
EXPECT_TRUE(result_turl);
EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
EXPECT_EQ(default_turl->short_name(), result_turl->short_name());
EXPECT_EQ(default_turl->url(), result_turl->url());
}
TEST_F(TemplateURLServiceSyncTest, MergeEditedPrepopulatedEngine) {
scoped_ptr<TemplateURL> default_turl(
TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
TemplateURLData data(default_turl->data());
data.safe_for_autoreplace = false;
data.SetKeyword(ASCIIToUTF16("new_kw"));
data.short_name = ASCIIToUTF16("my name");
data.SetURL("http://wrong.url.com?q={searchTerms}");
data.date_created = Time::FromTimeT(50);
data.last_modified = Time::FromTimeT(50);
data.sync_guid = "default";
model()->Add(new TemplateURL(NULL, data));
data.date_created = Time::FromTimeT(100);
data.last_modified = Time::FromTimeT(100);
scoped_ptr<TemplateURL> sync_turl(new TemplateURL(NULL, data));
syncer::SyncDataList list;
list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, list, PassProcessor(),
CreateAndPassSyncErrorFactory());
const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
EXPECT_TRUE(result_turl);
EXPECT_EQ(ASCIIToUTF16("new_kw"), result_turl->keyword());
EXPECT_EQ(ASCIIToUTF16("my name"), result_turl->short_name());
EXPECT_EQ(default_turl->url(), result_turl->url());
}
TEST_F(TemplateURLServiceSyncTest, MergeNonEditedPrepopulatedEngine) {
scoped_ptr<TemplateURL> default_turl(
TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(NULL));
TemplateURLData data(default_turl->data());
data.safe_for_autoreplace = true;
data.SetKeyword(ASCIIToUTF16("new_kw"));
data.short_name = ASCIIToUTF16("my name");
data.SetURL("http://wrong.url.com?q={searchTerms}");
data.date_created = Time::FromTimeT(50);
data.last_modified = Time::FromTimeT(50);
data.sync_guid = "default";
model()->Add(new TemplateURL(NULL, data));
data.date_created = Time::FromTimeT(100);
data.last_modified = Time::FromTimeT(100);
scoped_ptr<TemplateURL> sync_turl(new TemplateURL(NULL, data));
syncer::SyncDataList list;
list.push_back(TemplateURLService::CreateSyncDataFromTemplateURL(*sync_turl));
syncer::SyncMergeResult merge_result = model()->MergeDataAndStartSyncing(
syncer::SEARCH_ENGINES, list, PassProcessor(),
CreateAndPassSyncErrorFactory());
const TemplateURL* result_turl = model()->GetTemplateURLForGUID("default");
EXPECT_TRUE(result_turl);
EXPECT_EQ(default_turl->keyword(), result_turl->keyword());
EXPECT_EQ(default_turl->short_name(), result_turl->short_name());
EXPECT_EQ(default_turl->url(), result_turl->url());
}