| Index: components/history/core/browser/typed_url_syncable_service_unittest.cc
|
| diff --git a/components/history/core/browser/typed_url_syncable_service_unittest.cc b/components/history/core/browser/typed_url_syncable_service_unittest.cc
|
| index bbdceba8c567117e8793ebca0d34dc7f845fa7d3..26e8b2f2737efdcfe90a3436d6ae52840647be05 100644
|
| --- a/components/history/core/browser/typed_url_syncable_service_unittest.cc
|
| +++ b/components/history/core/browser/typed_url_syncable_service_unittest.cc
|
| @@ -28,24 +28,101 @@ using history::URLRows;
|
| using history::VisitRow;
|
| using history::VisitVector;
|
|
|
| +namespace history {
|
| +
|
| namespace {
|
|
|
| -// Constants used to limit size of visits processed.
|
| +// Constants used to limit size of visits processed. See
|
| +// equivalent constants in typed_url_syncable_service.cc for descriptions.
|
| const int kMaxTypedUrlVisits = 100;
|
| +const int kVisitThrottleThreshold = 10;
|
| +const int kVisitThrottleMultiple = 10;
|
|
|
| // Visits with this timestamp are treated as expired.
|
| -const int EXPIRED_VISIT = -1;
|
| +const int kExpiredVisit = -1;
|
| +
|
| +// Helper constants for tests.
|
| +const char kTitle[] = "pie";
|
| +const char kURL[] = "http://pie.com/";
|
| +
|
| +bool URLsEqual(URLRow& row, sync_pb::TypedUrlSpecifics& specifics) {
|
| + return ((row.url().spec().compare(specifics.url()) == 0) &&
|
| + (base::UTF16ToUTF8(row.title()).compare(specifics.title()) == 0) &&
|
| + (row.hidden() == specifics.hidden()));
|
| +}
|
| +
|
| +void AddNewestVisit(ui::PageTransition transition,
|
| + int64 visit_time,
|
| + URLRow* url,
|
| + VisitVector* visits) {
|
| + base::Time time = base::Time::FromInternalValue(visit_time);
|
| + visits->insert(visits->begin(), VisitRow(url->id(), time, 0, transition, 0));
|
| +
|
| + if (transition == ui::PAGE_TRANSITION_TYPED) {
|
| + url->set_typed_count(url->typed_count() + 1);
|
| + }
|
| +
|
| + url->set_last_visit(time);
|
| + url->set_visit_count(visits->size());
|
| +}
|
| +
|
| +void AddOldestVisit(ui::PageTransition transition,
|
| + int64 visit_time,
|
| + URLRow* url,
|
| + VisitVector* visits) {
|
| + base::Time time = base::Time::FromInternalValue(visit_time);
|
| + visits->push_back(VisitRow(url->id(), time, 0, transition, 0));
|
| +
|
| + if (transition == ui::PAGE_TRANSITION_TYPED) {
|
| + url->set_typed_count(url->typed_count() + 1);
|
| + }
|
| +
|
| + url->set_visit_count(visits->size());
|
| +}
|
| +
|
| +// Create a new row object and the typed visit çorresponding with the time at
|
| +// |last_visit| in the |visits| vector.
|
| +URLRow MakeTypedUrlRow(const std::string& url,
|
| + const std::string& title,
|
| + int typed_count,
|
| + int64 last_visit,
|
| + bool hidden,
|
| + VisitVector* visits) {
|
| + DCHECK(visits->empty());
|
| +
|
| + // Give each URL a unique ID, to mimic the behavior of the real database.
|
| + static int unique_url_id = 0;
|
| + GURL gurl(url);
|
| + URLRow history_url(gurl, ++unique_url_id);
|
| + history_url.set_title(base::UTF8ToUTF16(title));
|
| + history_url.set_typed_count(typed_count);
|
| + history_url.set_hidden(hidden);
|
|
|
| -// TestHistoryBackend ----------------------------------------------------------
|
| + base::Time last_visit_time = base::Time::FromInternalValue(last_visit);
|
| + history_url.set_last_visit(last_visit_time);
|
| +
|
| + VisitVector::iterator first = visits->begin();
|
| + if (typed_count > 0) {
|
| + // Add a typed visit for time |last_visit|.
|
| + visits->insert(first, VisitRow(history_url.id(), last_visit_time, 0,
|
| + ui::PAGE_TRANSITION_TYPED, 0));
|
| + } else {
|
| + // Add a non-typed visit for time |last_visit|.
|
| + visits->insert(first, VisitRow(history_url.id(), last_visit_time, 0,
|
| + ui::PAGE_TRANSITION_RELOAD, 0));
|
| + }
|
| +
|
| + history_url.set_visit_count(visits->size());
|
| + return history_url;
|
| +}
|
|
|
| class TestHistoryBackend : public HistoryBackend {
|
| public:
|
| TestHistoryBackend() : HistoryBackend(nullptr, nullptr,
|
| base::ThreadTaskRunnerHandle::Get()) {}
|
|
|
| - // HistoryBackend test implementation.
|
| bool IsExpiredVisitTime(const base::Time& time) override {
|
| - return time.ToInternalValue() == EXPIRED_VISIT;
|
| + return time.ToInternalValue() == kExpiredVisit;
|
| }
|
|
|
| bool GetMostRecentVisitsForURL(URLID id,
|
| @@ -60,7 +137,29 @@ class TestHistoryBackend : public HistoryBackend {
|
| return true;
|
| }
|
|
|
| + bool GetAllTypedURLs(URLRows* urls) override {
|
| + for (std::map<GURL, URLRow>::const_iterator it = local_typed_urls_.begin();
|
| + it != local_typed_urls_.end(); ++it) {
|
| + urls->push_back(it->second);
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + bool GetURL(const GURL& url, history::URLRow* url_row) override;
|
| + size_t UpdateURLs(const history::URLRows& urls) override;
|
| + bool AddVisits(const GURL& url,
|
| + const std::vector<history::VisitInfo>& visits,
|
| + history::VisitSource visit_source) override;
|
| + bool RemoveVisits(const VisitVector& visits) override;
|
| +
|
| // Helpers.
|
| + void SetBackendTypedUrls(URLRows* urls) {
|
| + for (URLRows::const_iterator url = urls->begin(); url != urls->end();
|
| + ++url) {
|
| + local_typed_urls_[url->url()] = *url;
|
| + }
|
| + }
|
| +
|
| void SetVisitsForUrl(URLID id, VisitVector* visits) {
|
| if (!local_db_visits_[id].empty()) {
|
| local_db_visits_[id].clear();
|
| @@ -73,59 +172,63 @@ class TestHistoryBackend : public HistoryBackend {
|
|
|
| void DeleteVisitsForUrl(const URLID& id) { local_db_visits_.erase(id); }
|
|
|
| + const std::map<URLID, URLRow>& updated_urls() const { return updated_urls_; }
|
| +
|
| + const std::map<GURL, std::vector<history::VisitInfo>>& added_visits() const {
|
| + return added_visits_;
|
| + }
|
| +
|
| private:
|
| ~TestHistoryBackend() override {}
|
|
|
| + // Mock of urls in local db.
|
| + std::map<GURL, URLRow> local_typed_urls_;
|
| // Mock of visit table in local db.
|
| - std::map<URLID, VisitVector> local_db_visits_;
|
| + std::map<URLID, history::VisitVector> local_db_visits_;
|
| +
|
| + std::map<GURL, URLRow> added_urls_;
|
| + std::map<URLID, URLRow> updated_urls_;
|
| + std::map<GURL, std::vector<history::VisitInfo>> added_visits_;
|
| + history::VisitVector removed_visits_;
|
| };
|
|
|
| -} // namespace
|
| +bool TestHistoryBackend::GetURL(const GURL& url, history::URLRow* url_row) {
|
| + std::map<GURL, URLRow>::iterator it = local_typed_urls_.find(url);
|
| + if (it != local_typed_urls_.end()) {
|
| + url_row = &it->second;
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
|
|
| -namespace history {
|
| +size_t TestHistoryBackend::UpdateURLs(const history::URLRows& urls) {
|
| + for (URLRows::const_iterator it = urls.begin(); it != urls.end(); ++it) {
|
| + updated_urls_[it->id()] = (*it);
|
| + }
|
|
|
| -// TypedUrlSyncableServiceTest -------------------------------------------------
|
| + return urls.size();
|
| +}
|
|
|
| -class TypedUrlSyncableServiceTest : public testing::Test {
|
| - public:
|
| - // Create a new row object and add a typed visit to the |visits| vector.
|
| - // Note that the real history db returns visits in reverse chronological
|
| - // order, so |visits| is treated this way. If the newest (first) visit
|
| - // in visits does not match |last_visit|, then a typed visit for this
|
| - // time is prepended to the front (or if |last_visit| is too old, it is
|
| - // set equal to the time of the newest visit).
|
| - static URLRow MakeTypedUrlRow(const char* url,
|
| - const char* title,
|
| - int typed_count,
|
| - int64 last_visit,
|
| - bool hidden,
|
| - VisitVector* visits);
|
| -
|
| - static void AddNewestVisit(URLRow* url,
|
| - VisitVector* visits,
|
| - ui::PageTransition transition,
|
| - int64 visit_time);
|
| -
|
| - static void AddOldestVisit(URLRow* url,
|
| - VisitVector* visits,
|
| - ui::PageTransition transition,
|
| - int64 visit_time);
|
| -
|
| - static bool URLsEqual(URLRow& row, sync_pb::TypedUrlSpecifics& specifics) {
|
| - return ((row.url().spec().compare(specifics.url()) == 0) &&
|
| - (base::UTF16ToUTF8(row.title()).compare(specifics.title()) == 0) &&
|
| - (row.hidden() == specifics.hidden()));
|
| - }
|
| +bool TestHistoryBackend::AddVisits(
|
| + const GURL& url,
|
| + const std::vector<history::VisitInfo>& visits,
|
| + history::VisitSource visit_source) {
|
| + DCHECK_EQ(visit_source, history::SOURCE_SYNCED);
|
| + added_visits_[url] = visits;
|
| + return true;
|
| +}
|
|
|
| - bool InitiateServerState(unsigned int num_typed_urls,
|
| - unsigned int num_reload_urls,
|
| - URLRows* rows,
|
| - std::vector<VisitVector>* visit_vectors,
|
| - const std::vector<const char*>& urls);
|
| +bool TestHistoryBackend::RemoveVisits(const VisitVector& visits) {
|
| + removed_visits_.clear();
|
| + removed_visits_.insert(removed_visits_.end(), visits.begin(), visits.end());
|
| + return true;
|
| +}
|
|
|
| - protected:
|
| - TypedUrlSyncableServiceTest() {}
|
| +} // namespace
|
|
|
| +class TypedUrlSyncableServiceTest : public testing::Test {
|
| + public:
|
| + TypedUrlSyncableServiceTest() {}
|
| ~TypedUrlSyncableServiceTest() override {}
|
|
|
| void SetUp() override {
|
| @@ -135,100 +238,71 @@ class TypedUrlSyncableServiceTest : public testing::Test {
|
| fake_change_processor_.reset(new syncer::FakeSyncChangeProcessor);
|
| }
|
|
|
| + // Starts sync for |typed_url_sync_service_| with |initial_data| as the
|
| + // initial sync data.
|
| + void StartSyncing(const syncer::SyncDataList& initial_data);
|
| +
|
| + // Builds a set of url rows and visit vectors based on |num_typed_urls| and
|
| + // |num_reload_urls|, and |urls|. The rows are stored into |rows|, the visit
|
| + // vectors in |visit_vectors|, and the changes are pushed into the history
|
| + // backend.
|
| + // Returns true if sync receives the proper number of changes, false
|
| + // otherwise.
|
| + bool BuildAndPushLocalChanges(unsigned int num_typed_urls,
|
| + unsigned int num_reload_urls,
|
| + const std::vector<std::string>& urls,
|
| + URLRows* rows,
|
| + std::vector<VisitVector>* visit_vectors);
|
| +
|
| + // Fills |urls| with the set of synced urls within |typed_url_sync_service_|.
|
| + void GetSyncedUrls(std::set<GURL>* urls) const;
|
| +
|
| + // Fills |specifics| with the sync data for |url| and |visits|.
|
| + static void WriteToTypedUrlSpecifics(const URLRow& url,
|
| + const VisitVector& visits,
|
| + sync_pb::TypedUrlSpecifics* specifics);
|
| +
|
| + // Helper to call TypedUrlSyncableService's MergeURLs method.
|
| + static TypedUrlSyncableService::MergeResult MergeUrls(
|
| + const sync_pb::TypedUrlSpecifics& typed_url,
|
| + const history::URLRow& url,
|
| + history::VisitVector* visits,
|
| + history::URLRow* new_url,
|
| + std::vector<history::VisitInfo>* new_visits);
|
| +
|
| + protected:
|
| base::MessageLoop message_loop_;
|
| - scoped_refptr<HistoryBackend> fake_history_backend_;
|
| + scoped_refptr<TestHistoryBackend> fake_history_backend_;
|
| scoped_ptr<TypedUrlSyncableService> typed_url_sync_service_;
|
| scoped_ptr<syncer::FakeSyncChangeProcessor> fake_change_processor_;
|
| };
|
|
|
| -URLRow TypedUrlSyncableServiceTest::MakeTypedUrlRow(const char* url,
|
| - const char* title,
|
| - int typed_count,
|
| - int64 last_visit,
|
| - bool hidden,
|
| - VisitVector* visits) {
|
| - DCHECK(visits->empty());
|
| -
|
| - // Give each URL a unique ID, to mimic the behavior of the real database.
|
| - static int unique_url_id = 0;
|
| - GURL gurl(url);
|
| - URLRow history_url(gurl, ++unique_url_id);
|
| - history_url.set_title(base::UTF8ToUTF16(title));
|
| - history_url.set_typed_count(typed_count);
|
| - history_url.set_hidden(hidden);
|
| -
|
| - base::Time last_visit_time = base::Time::FromInternalValue(last_visit);
|
| - history_url.set_last_visit(last_visit_time);
|
| -
|
| - VisitVector::iterator first = visits->begin();
|
| - if (typed_count > 0) {
|
| - // Add a typed visit for time |last_visit|.
|
| - visits->insert(first,
|
| - VisitRow(history_url.id(), last_visit_time, 0,
|
| - ui::PAGE_TRANSITION_TYPED, 0));
|
| - } else {
|
| - // Add a non-typed visit for time |last_visit|.
|
| - visits->insert(first,
|
| - VisitRow(history_url.id(), last_visit_time, 0,
|
| - ui::PAGE_TRANSITION_RELOAD, 0));
|
| - }
|
| -
|
| - history_url.set_visit_count(visits->size());
|
| - return history_url;
|
| -}
|
| -
|
| -void TypedUrlSyncableServiceTest::AddNewestVisit(URLRow* url,
|
| - VisitVector* visits,
|
| - ui::PageTransition transition,
|
| - int64 visit_time) {
|
| - base::Time time = base::Time::FromInternalValue(visit_time);
|
| - visits->insert(visits->begin(),
|
| - VisitRow(url->id(), time, 0, transition, 0));
|
| -
|
| - if (transition == ui::PAGE_TRANSITION_TYPED) {
|
| - url->set_typed_count(url->typed_count() + 1);
|
| - }
|
| -
|
| - url->set_last_visit(time);
|
| - url->set_visit_count(visits->size());
|
| -}
|
| -
|
| -void TypedUrlSyncableServiceTest::AddOldestVisit(URLRow* url,
|
| - VisitVector* visits,
|
| - ui::PageTransition transition,
|
| - int64 visit_time) {
|
| - base::Time time = base::Time::FromInternalValue(visit_time);
|
| - visits->push_back(VisitRow(url->id(), time, 0, transition, 0));
|
| -
|
| - if (transition == ui::PAGE_TRANSITION_TYPED) {
|
| - url->set_typed_count(url->typed_count() + 1);
|
| - }
|
| -
|
| - url->set_visit_count(visits->size());
|
| -}
|
| -
|
| -bool TypedUrlSyncableServiceTest::InitiateServerState(
|
| - unsigned int num_typed_urls,
|
| - unsigned int num_reload_urls,
|
| - URLRows* rows,
|
| - std::vector<VisitVector>* visit_vectors,
|
| - const std::vector<const char*>& urls) {
|
| - unsigned int total_urls = num_typed_urls + num_reload_urls;
|
| - DCHECK(urls.size() >= total_urls);
|
| - if (!typed_url_sync_service_.get())
|
| - return false;
|
| +void TypedUrlSyncableServiceTest::StartSyncing(
|
| + const syncer::SyncDataList& initial_data) {
|
| + DCHECK(fake_change_processor_.get());
|
|
|
| // Set change processor.
|
| syncer::SyncMergeResult result =
|
| typed_url_sync_service_->MergeDataAndStartSyncing(
|
| - syncer::TYPED_URLS,
|
| - syncer::SyncDataList(),
|
| + syncer::TYPED_URLS, initial_data,
|
| scoped_ptr<syncer::SyncChangeProcessor>(
|
| new syncer::SyncChangeProcessorWrapperForTest(
|
| fake_change_processor_.get())),
|
| scoped_ptr<syncer::SyncErrorFactory>(
|
| new syncer::SyncErrorFactoryMock()));
|
| EXPECT_FALSE(result.error().IsSet()) << result.error().message();
|
| +}
|
| +
|
| +bool TypedUrlSyncableServiceTest::BuildAndPushLocalChanges(
|
| + unsigned int num_typed_urls,
|
| + unsigned int num_reload_urls,
|
| + const std::vector<std::string>& urls,
|
| + URLRows* rows,
|
| + std::vector<VisitVector>* visit_vectors) {
|
| + unsigned int total_urls = num_typed_urls + num_reload_urls;
|
| + DCHECK(urls.size() >= total_urls);
|
| + if (!typed_url_sync_service_.get())
|
| + return false;
|
|
|
| if (total_urls) {
|
| // Create new URL rows, populate the mock backend with its visits, and
|
| @@ -241,35 +315,62 @@ bool TypedUrlSyncableServiceTest::InitiateServerState(
|
| visit_vectors->push_back(visits);
|
| rows->push_back(MakeTypedUrlRow(
|
| urls[i], "pie", typed, i + 3, false, &visit_vectors->back()));
|
| - static_cast<TestHistoryBackend*>(fake_history_backend_.get())->
|
| - SetVisitsForUrl(rows->back().id(), &visit_vectors->back());
|
| + fake_history_backend_->SetVisitsForUrl(rows->back().id(),
|
| + &visit_vectors->back());
|
| changed_urls.push_back(rows->back());
|
| }
|
|
|
| typed_url_sync_service_->OnUrlsModified(&changed_urls);
|
| }
|
| +
|
| // Check that communication with sync was successful.
|
| if (num_typed_urls != fake_change_processor_->changes().size())
|
| return false;
|
| return true;
|
| }
|
|
|
| -TEST_F(TypedUrlSyncableServiceTest, AddLocalTypedUrlAndSync) {
|
| +void TypedUrlSyncableServiceTest::GetSyncedUrls(std::set<GURL>* urls) const {
|
| + return typed_url_sync_service_->GetSyncedUrls(urls);
|
| +}
|
| +
|
| +// Static.
|
| +void TypedUrlSyncableServiceTest::WriteToTypedUrlSpecifics(
|
| + const URLRow& url,
|
| + const VisitVector& visits,
|
| + sync_pb::TypedUrlSpecifics* specifics) {
|
| + TypedUrlSyncableService::WriteToTypedUrlSpecifics(url, visits, specifics);
|
| +}
|
| +
|
| +// Static.
|
| +TypedUrlSyncableService::MergeResult TypedUrlSyncableServiceTest::MergeUrls(
|
| + const sync_pb::TypedUrlSpecifics& typed_url,
|
| + const history::URLRow& url,
|
| + history::VisitVector* visits,
|
| + history::URLRow* new_url,
|
| + std::vector<history::VisitInfo>* new_visits) {
|
| + return TypedUrlSyncableService::MergeUrls(typed_url, url, visits, new_url,
|
| + new_visits);
|
| +}
|
| +
|
| +// Create a local typed URL with one TYPED visit after sync has started. Check
|
| +// that sync is sent an ADD change for the new URL.
|
| +TEST_F(TypedUrlSyncableServiceTest, AddLocalTypedUrl) {
|
| // Create a local typed URL (simulate a typed visit) that is not already
|
| // in sync. Check that sync is sent an ADD change for the existing URL.
|
| URLRows url_rows;
|
| std::vector<VisitVector> visit_vectors;
|
| - std::vector<const char*> urls;
|
| - urls.push_back("http://pie.com/");
|
| + std::vector<std::string> urls;
|
| + urls.push_back(kURL);
|
|
|
| - ASSERT_TRUE(InitiateServerState(1, 0, &url_rows, &visit_vectors, urls));
|
| + StartSyncing(syncer::SyncDataList());
|
| + ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
|
|
|
| URLRow url_row = url_rows.front();
|
| VisitVector visits = visit_vectors.front();
|
|
|
| // Check change processor.
|
| - const syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| - ASSERT_EQ(1u, changes.size());
|
| + syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| + ASSERT_EQ(1U, changes.size());
|
| ASSERT_TRUE(changes[0].IsValid());
|
| EXPECT_EQ(syncer::TYPED_URLS, changes[0].sync_data().GetDataType());
|
| EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
|
| @@ -287,19 +388,22 @@ TEST_F(TypedUrlSyncableServiceTest, AddLocalTypedUrlAndSync) {
|
|
|
| // Check that in-memory representation of sync state is accurate.
|
| std::set<GURL> sync_state;
|
| - typed_url_sync_service_.get()->GetSyncedUrls(&sync_state);
|
| + GetSyncedUrls(&sync_state);
|
| EXPECT_FALSE(sync_state.empty());
|
| - EXPECT_EQ(1u, sync_state.size());
|
| + EXPECT_EQ(1U, sync_state.size());
|
| EXPECT_TRUE(sync_state.end() != sync_state.find(url_row.url()));
|
| }
|
|
|
| -TEST_F(TypedUrlSyncableServiceTest, UpdateLocalTypedUrlAndSync) {
|
| +// Update a local typed URL that is already synced. Check that sync is sent an
|
| +// UPDATE for the existing url, but RELOAD visits aren't synced.
|
| +TEST_F(TypedUrlSyncableServiceTest, UpdateLocalTypedUrl) {
|
| URLRows url_rows;
|
| std::vector<VisitVector> visit_vectors;
|
| - std::vector<const char*> urls;
|
| - urls.push_back("http://pie.com/");
|
| + std::vector<std::string> urls;
|
| + urls.push_back(kURL);
|
|
|
| - ASSERT_TRUE(InitiateServerState(1, 0, &url_rows, &visit_vectors, urls));
|
| + StartSyncing(syncer::SyncDataList());
|
| + ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
|
| syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| changes.clear();
|
|
|
| @@ -308,15 +412,16 @@ TEST_F(TypedUrlSyncableServiceTest, UpdateLocalTypedUrlAndSync) {
|
| VisitVector visits = visit_vectors.front();
|
|
|
| URLRows changed_urls;
|
| - AddNewestVisit(&url_row, &visits, ui::PAGE_TRANSITION_TYPED, 7);
|
| - static_cast<TestHistoryBackend*>(fake_history_backend_.get())->
|
| - SetVisitsForUrl(url_row.id(), &visits);
|
| + AddNewestVisit(ui::PAGE_TRANSITION_TYPED, 7, &url_row, &visits);
|
| + AddNewestVisit(ui::PAGE_TRANSITION_RELOAD, 8, &url_row, &visits);
|
| + AddNewestVisit(ui::PAGE_TRANSITION_LINK, 9, &url_row, &visits);
|
| + fake_history_backend_->SetVisitsForUrl(url_row.id(), &visits);
|
| changed_urls.push_back(url_row);
|
|
|
| // Notify typed url sync service of the update.
|
| typed_url_sync_service_->OnUrlsModified(&changed_urls);
|
|
|
| - ASSERT_EQ(1u, changes.size());
|
| + ASSERT_EQ(1U, changes.size());
|
| ASSERT_TRUE(changes[0].IsValid());
|
| EXPECT_EQ(syncer::TYPED_URLS, changes[0].sync_data().GetDataType());
|
| EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
|
| @@ -325,34 +430,76 @@ TEST_F(TypedUrlSyncableServiceTest, UpdateLocalTypedUrlAndSync) {
|
| changes[0].sync_data().GetSpecifics().typed_url();
|
|
|
| EXPECT_TRUE(URLsEqual(url_row, url_specifics));
|
| - ASSERT_EQ(2, url_specifics.visits_size());
|
| - ASSERT_EQ(static_cast<const int>(visits.size()), url_specifics.visits_size());
|
| + ASSERT_EQ(3, url_specifics.visits_size());
|
| + ASSERT_EQ(static_cast<const int>(visits.size()) - 1,
|
| + url_specifics.visits_size());
|
|
|
| // Check that each visit has been translated/communicated correctly.
|
| // Note that the specifics record visits in chronological order, and the
|
| // visits from the db are in reverse chronological order.
|
| - EXPECT_EQ(visits[0].visit_time.ToInternalValue(), url_specifics.visits(1));
|
| + EXPECT_EQ(visits[0].visit_time.ToInternalValue(), url_specifics.visits(2));
|
| EXPECT_EQ(static_cast<const int>(visits[0].transition),
|
| - url_specifics.visit_transitions(1));
|
| - EXPECT_EQ(visits[1].visit_time.ToInternalValue(), url_specifics.visits(0));
|
| - EXPECT_EQ(static_cast<const int>(visits[1].transition),
|
| + url_specifics.visit_transitions(2));
|
| + EXPECT_EQ(visits[2].visit_time.ToInternalValue(), url_specifics.visits(1));
|
| + EXPECT_EQ(static_cast<const int>(visits[2].transition),
|
| + url_specifics.visit_transitions(0));
|
| + EXPECT_EQ(visits[3].visit_time.ToInternalValue(), url_specifics.visits(0));
|
| + EXPECT_EQ(static_cast<const int>(visits[3].transition),
|
| url_specifics.visit_transitions(0));
|
|
|
| // Check that in-memory representation of sync state is accurate.
|
| std::set<GURL> sync_state;
|
| - typed_url_sync_service_.get()->GetSyncedUrls(&sync_state);
|
| + GetSyncedUrls(&sync_state);
|
| EXPECT_FALSE(sync_state.empty());
|
| - EXPECT_EQ(1u, sync_state.size());
|
| + EXPECT_EQ(1U, sync_state.size());
|
| EXPECT_TRUE(sync_state.end() != sync_state.find(url_row.url()));
|
| }
|
|
|
| -TEST_F(TypedUrlSyncableServiceTest, LinkVisitLocalTypedUrlAndSync) {
|
| +// Append a RELOAD visit to a typed url that is already synced. Check that sync
|
| +// does not receive any updates.
|
| +TEST_F(TypedUrlSyncableServiceTest, ReloadVisitLocalTypedUrl) {
|
| URLRows url_rows;
|
| std::vector<VisitVector> visit_vectors;
|
| - std::vector<const char*> urls;
|
| - urls.push_back("http://pie.com/");
|
| + std::vector<std::string> urls;
|
| + urls.push_back(kURL);
|
| +
|
| + StartSyncing(syncer::SyncDataList());
|
| + ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
|
| + syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| + changes.clear();
|
| +
|
| + // Update the URL row, adding another typed visit to the visit vector.
|
| + URLRow url_row = url_rows.front();
|
| + VisitVector visits = visit_vectors.front();
|
|
|
| - ASSERT_TRUE(InitiateServerState(1, 0, &url_rows, &visit_vectors, urls));
|
| + URLRows changed_urls;
|
| + AddNewestVisit(ui::PAGE_TRANSITION_RELOAD, 7, &url_row, &visits);
|
| + fake_history_backend_->SetVisitsForUrl(url_row.id(), &visits);
|
| + changed_urls.push_back(url_row);
|
| +
|
| + // Notify typed url sync service of the update.
|
| + typed_url_sync_service_->OnUrlVisited(ui::PAGE_TRANSITION_RELOAD, &url_row);
|
| +
|
| + ASSERT_EQ(0U, changes.size());
|
| +
|
| + // Check that in-memory representation of sync state is accurate.
|
| + std::set<GURL> sync_state;
|
| + GetSyncedUrls(&sync_state);
|
| + EXPECT_FALSE(sync_state.empty());
|
| + EXPECT_EQ(1U, sync_state.size());
|
| + EXPECT_TRUE(sync_state.end() != sync_state.find(url_row.url()));
|
| +}
|
| +
|
| +// Appends a LINK visit to an existing typed url. Check that sync does not
|
| +// receive any changes.
|
| +TEST_F(TypedUrlSyncableServiceTest, LinkVisitLocalTypedUrl) {
|
| + URLRows url_rows;
|
| + std::vector<VisitVector> visit_vectors;
|
| + std::vector<std::string> urls;
|
| + urls.push_back(kURL);
|
| +
|
| + StartSyncing(syncer::SyncDataList());
|
| + ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
|
| syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| changes.clear();
|
|
|
| @@ -360,9 +507,8 @@ TEST_F(TypedUrlSyncableServiceTest, LinkVisitLocalTypedUrlAndSync) {
|
| VisitVector visits = visit_vectors.front();
|
|
|
| // Update the URL row, adding a non-typed visit to the visit vector.
|
| - AddNewestVisit(&url_row, &visits, ui::PAGE_TRANSITION_LINK, 6);
|
| - static_cast<TestHistoryBackend*>(fake_history_backend_.get())->
|
| - SetVisitsForUrl(url_row.id(), &visits);
|
| + AddNewestVisit(ui::PAGE_TRANSITION_LINK, 6, &url_row, &visits);
|
| + fake_history_backend_->SetVisitsForUrl(url_row.id(), &visits);
|
|
|
| ui::PageTransition transition = ui::PAGE_TRANSITION_LINK;
|
| // Notify typed url sync service of non-typed visit, expect no change.
|
| @@ -370,13 +516,16 @@ TEST_F(TypedUrlSyncableServiceTest, LinkVisitLocalTypedUrlAndSync) {
|
| ASSERT_EQ(0u, changes.size());
|
| }
|
|
|
| -TEST_F(TypedUrlSyncableServiceTest, TypedVisitLocalTypedUrlAndSync) {
|
| +// Appends a series of LINK visits followed by a TYPED one to an existing typed
|
| +// url. Check that sync receives an UPDATE with the newest visit data.
|
| +TEST_F(TypedUrlSyncableServiceTest, TypedVisitLocalTypedUrl) {
|
| URLRows url_rows;
|
| std::vector<VisitVector> visit_vectors;
|
| - std::vector<const char*> urls;
|
| - urls.push_back("http://pie.com/");
|
| + std::vector<std::string> urls;
|
| + urls.push_back(kURL);
|
|
|
| - ASSERT_TRUE(InitiateServerState(1, 0, &url_rows, &visit_vectors, urls));
|
| + StartSyncing(syncer::SyncDataList());
|
| + ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
|
| syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| changes.clear();
|
|
|
| @@ -384,17 +533,16 @@ TEST_F(TypedUrlSyncableServiceTest, TypedVisitLocalTypedUrlAndSync) {
|
| VisitVector visits = visit_vectors.front();
|
|
|
| // Update the URL row, adding another typed visit to the visit vector.
|
| - AddOldestVisit(&url_row, &visits, ui::PAGE_TRANSITION_LINK, 1);
|
| - AddNewestVisit(&url_row, &visits, ui::PAGE_TRANSITION_LINK, 6);
|
| - AddNewestVisit(&url_row, &visits, ui::PAGE_TRANSITION_TYPED, 7);
|
| - static_cast<TestHistoryBackend*>(fake_history_backend_.get())->
|
| - SetVisitsForUrl(url_row.id(), &visits);
|
| + AddOldestVisit(ui::PAGE_TRANSITION_LINK, 1, &url_row, &visits);
|
| + AddNewestVisit(ui::PAGE_TRANSITION_LINK, 6, &url_row, &visits);
|
| + AddNewestVisit(ui::PAGE_TRANSITION_TYPED, 7, &url_row, &visits);
|
| + fake_history_backend_->SetVisitsForUrl(url_row.id(), &visits);
|
|
|
| // Notify typed url sync service of typed visit.
|
| ui::PageTransition transition = ui::PAGE_TRANSITION_TYPED;
|
| typed_url_sync_service_->OnUrlVisited(transition, &url_row);
|
|
|
| - ASSERT_EQ(1u, changes.size());
|
| + ASSERT_EQ(1U, changes.size());
|
| ASSERT_TRUE(changes[0].IsValid());
|
| EXPECT_EQ(syncer::TYPED_URLS, changes[0].sync_data().GetDataType());
|
| EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
|
| @@ -418,29 +566,32 @@ TEST_F(TypedUrlSyncableServiceTest, TypedVisitLocalTypedUrlAndSync) {
|
|
|
| // Check that in-memory representation of sync state is accurate.
|
| std::set<GURL> sync_state;
|
| - typed_url_sync_service_.get()->GetSyncedUrls(&sync_state);
|
| + GetSyncedUrls(&sync_state);
|
| EXPECT_FALSE(sync_state.empty());
|
| - EXPECT_EQ(1u, sync_state.size());
|
| + EXPECT_EQ(1U, sync_state.size());
|
| EXPECT_TRUE(sync_state.end() != sync_state.find(url_row.url()));
|
| }
|
|
|
| -TEST_F(TypedUrlSyncableServiceTest, DeleteLocalTypedUrlAndSync) {
|
| +// Delete several (but not all) local typed urls. Check that sync receives the
|
| +// DELETE changes, and the non-deleted urls remain synced.
|
| +TEST_F(TypedUrlSyncableServiceTest, DeleteLocalTypedUrl) {
|
| URLRows url_rows;
|
| std::vector<VisitVector> visit_vectors;
|
| - std::vector<const char*> urls;
|
| + std::vector<std::string> urls;
|
| urls.push_back("http://pie.com/");
|
| urls.push_back("http://cake.com/");
|
| urls.push_back("http://google.com/");
|
| urls.push_back("http://foo.com/");
|
| urls.push_back("http://bar.com/");
|
|
|
| - ASSERT_TRUE(InitiateServerState(4, 1, &url_rows, &visit_vectors, urls));
|
| + StartSyncing(syncer::SyncDataList());
|
| + ASSERT_TRUE(BuildAndPushLocalChanges(4, 1, urls, &url_rows, &visit_vectors));
|
| syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| changes.clear();
|
|
|
| // Check that in-memory representation of sync state is accurate.
|
| std::set<GURL> sync_state;
|
| - typed_url_sync_service_.get()->GetSyncedUrls(&sync_state);
|
| + GetSyncedUrls(&sync_state);
|
| EXPECT_FALSE(sync_state.empty());
|
| EXPECT_EQ(4u, sync_state.size());
|
|
|
| @@ -449,14 +600,12 @@ TEST_F(TypedUrlSyncableServiceTest, DeleteLocalTypedUrlAndSync) {
|
| // which urls were typed and synced, and should be deleted.
|
| url_rows[0].set_typed_count(0);
|
| VisitVector visits;
|
| - static_cast<TestHistoryBackend*>(fake_history_backend_.get())->
|
| - SetVisitsForUrl(url_rows[0].id(), &visits);
|
| + fake_history_backend_->SetVisitsForUrl(url_rows[0].id(), &visits);
|
|
|
| // Delete some urls from backend and create deleted row vector.
|
| URLRows rows;
|
| for (size_t i = 0; i < 3u; ++i) {
|
| - static_cast<TestHistoryBackend*>(fake_history_backend_.get())->
|
| - DeleteVisitsForUrl(url_rows[i].id());
|
| + fake_history_backend_->DeleteVisitsForUrl(url_rows[i].id());
|
| rows.push_back(url_rows[i]);
|
| }
|
|
|
| @@ -475,35 +624,37 @@ TEST_F(TypedUrlSyncableServiceTest, DeleteLocalTypedUrlAndSync) {
|
|
|
| // Check that in-memory representation of sync state is accurate.
|
| std::set<GURL> sync_state_deleted;
|
| - typed_url_sync_service_.get()->GetSyncedUrls(&sync_state_deleted);
|
| + GetSyncedUrls(&sync_state_deleted);
|
| ASSERT_EQ(1u, sync_state_deleted.size());
|
| EXPECT_TRUE(sync_state_deleted.end() !=
|
| sync_state_deleted.find(url_rows[3].url()));
|
| }
|
|
|
| -TEST_F(TypedUrlSyncableServiceTest, DeleteAllLocalTypedUrlAndSync) {
|
| +// Delete all local typed urls. Check that sync receives them all the DELETE
|
| +// changes, and that the sync state afterwards is empty.
|
| +TEST_F(TypedUrlSyncableServiceTest, DeleteAllLocalTypedUrl) {
|
| URLRows url_rows;
|
| std::vector<VisitVector> visit_vectors;
|
| - std::vector<const char*> urls;
|
| + std::vector<std::string> urls;
|
| urls.push_back("http://pie.com/");
|
| urls.push_back("http://cake.com/");
|
| urls.push_back("http://google.com/");
|
| urls.push_back("http://foo.com/");
|
| urls.push_back("http://bar.com/");
|
|
|
| - ASSERT_TRUE(InitiateServerState(4, 1, &url_rows, &visit_vectors, urls));
|
| + StartSyncing(syncer::SyncDataList());
|
| + ASSERT_TRUE(BuildAndPushLocalChanges(4, 1, urls, &url_rows, &visit_vectors));
|
| syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| changes.clear();
|
|
|
| // Check that in-memory representation of sync state is accurate.
|
| std::set<GURL> sync_state;
|
| - typed_url_sync_service_.get()->GetSyncedUrls(&sync_state);
|
| + GetSyncedUrls(&sync_state);
|
| EXPECT_EQ(4u, sync_state.size());
|
|
|
| // Delete urls from backend.
|
| for (size_t i = 0; i < 4u; ++ i) {
|
| - static_cast<TestHistoryBackend*>(fake_history_backend_.get())->
|
| - DeleteVisitsForUrl(url_rows[i].id());
|
| + fake_history_backend_->DeleteVisitsForUrl(url_rows[i].id());
|
| }
|
| // Delete urls with |all_history| flag set.
|
| bool all_history = true;
|
| @@ -519,17 +670,21 @@ TEST_F(TypedUrlSyncableServiceTest, DeleteAllLocalTypedUrlAndSync) {
|
| }
|
| // Check that in-memory representation of sync state is accurate.
|
| std::set<GURL> sync_state_deleted;
|
| - typed_url_sync_service_.get()->GetSyncedUrls(&sync_state_deleted);
|
| + GetSyncedUrls(&sync_state_deleted);
|
| EXPECT_TRUE(sync_state_deleted.empty());
|
| }
|
|
|
| -TEST_F(TypedUrlSyncableServiceTest, MaxVisitLocalTypedUrlAndSync) {
|
| +// Saturate the visits for a typed url with both TYPED and LINK navigations.
|
| +// Check that no more than kMaxTypedURLVisits are synced, and that LINK visits
|
| +// are dropped rather than TYPED ones.
|
| +TEST_F(TypedUrlSyncableServiceTest, MaxVisitLocalTypedUrl) {
|
| URLRows url_rows;
|
| std::vector<VisitVector> visit_vectors;
|
| - std::vector<const char*> urls;
|
| - urls.push_back("http://pie.com/");
|
| + std::vector<std::string> urls;
|
| + urls.push_back(kURL);
|
|
|
| - ASSERT_TRUE(InitiateServerState(0, 1, &url_rows, &visit_vectors, urls));
|
| + StartSyncing(syncer::SyncDataList());
|
| + ASSERT_TRUE(BuildAndPushLocalChanges(0, 1, urls, &url_rows, &visit_vectors));
|
|
|
| URLRow url_row = url_rows.front();
|
| VisitVector visits;
|
| @@ -538,28 +693,28 @@ TEST_F(TypedUrlSyncableServiceTest, MaxVisitLocalTypedUrlAndSync) {
|
| // non-typed visits are expected to be skipped.
|
| int i = 1;
|
| for (; i <= kMaxTypedUrlVisits - 20; ++i)
|
| - AddNewestVisit(&url_row, &visits, ui::PAGE_TRANSITION_TYPED, i);
|
| + AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
|
| for (; i <= kMaxTypedUrlVisits; ++i)
|
| - AddNewestVisit(&url_row, &visits, ui::PAGE_TRANSITION_LINK, i);
|
| + AddNewestVisit(ui::PAGE_TRANSITION_LINK, i, &url_row, &visits);
|
| for (; i <= kMaxTypedUrlVisits + 10; ++i)
|
| - AddNewestVisit(&url_row, &visits, ui::PAGE_TRANSITION_TYPED, i);
|
| + AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
|
|
|
| - static_cast<TestHistoryBackend*>(fake_history_backend_.get())->
|
| - SetVisitsForUrl(url_row.id(), &visits);
|
| + fake_history_backend_->SetVisitsForUrl(url_row.id(), &visits);
|
|
|
| // Notify typed url sync service of typed visit.
|
| ui::PageTransition transition = ui::PAGE_TRANSITION_TYPED;
|
| typed_url_sync_service_->OnUrlVisited(transition, &url_row);
|
|
|
| - const syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| - ASSERT_EQ(1u, changes.size());
|
| + syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| + ASSERT_EQ(1U, changes.size());
|
| ASSERT_TRUE(changes[0].IsValid());
|
| + ASSERT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
|
| sync_pb::TypedUrlSpecifics url_specifics =
|
| changes[0].sync_data().GetSpecifics().typed_url();
|
| ASSERT_EQ(kMaxTypedUrlVisits, url_specifics.visits_size());
|
|
|
| // Check that each visit has been translated/communicated correctly.
|
| - // Note that the specifics record visits in chronological order, and the
|
| + // Note that the specifics records visits in chronological order, and the
|
| // visits from the db are in reverse chronological order.
|
| int num_typed_visits_synced = 0;
|
| int num_other_visits_synced = 0;
|
| @@ -575,35 +730,274 @@ TEST_F(TypedUrlSyncableServiceTest, MaxVisitLocalTypedUrlAndSync) {
|
| EXPECT_EQ(10, num_other_visits_synced);
|
| }
|
|
|
| -TEST_F(TypedUrlSyncableServiceTest, ThrottleVisitLocalTypedUrlSync) {
|
| +// Add enough visits to trigger throttling of updates to a typed url. Check that
|
| +// sync does not receive an update until the proper throttle interval has been
|
| +// reached.
|
| +TEST_F(TypedUrlSyncableServiceTest, ThrottleVisitLocalTypedUrl) {
|
| URLRows url_rows;
|
| std::vector<VisitVector> visit_vectors;
|
| - std::vector<const char*> urls;
|
| - urls.push_back("http://pie.com/");
|
| + std::vector<std::string> urls;
|
| + urls.push_back(kURL);
|
|
|
| - ASSERT_TRUE(InitiateServerState(0, 1, &url_rows, &visit_vectors, urls));
|
| + StartSyncing(syncer::SyncDataList());
|
| + ASSERT_TRUE(BuildAndPushLocalChanges(0, 1, urls, &url_rows, &visit_vectors));
|
|
|
| URLRow url_row = url_rows.front();
|
| VisitVector visits;
|
|
|
| // Add enough visits to the url so that typed count is above the throttle
|
| // limit, and not right on the interval that gets synced.
|
| - for (int i = 1; i < 42; ++i)
|
| - AddNewestVisit(&url_row, &visits, ui::PAGE_TRANSITION_TYPED, i);
|
| -
|
| - static_cast<TestHistoryBackend*>(fake_history_backend_.get())->
|
| - SetVisitsForUrl(url_row.id(), &visits);
|
| + int i = 1;
|
| + for (; i < kVisitThrottleThreshold + kVisitThrottleMultiple / 2; ++i)
|
| + AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
|
| + fake_history_backend_->SetVisitsForUrl(url_row.id(), &visits);
|
|
|
| // Notify typed url sync service of typed visit.
|
| ui::PageTransition transition = ui::PAGE_TRANSITION_TYPED;
|
| typed_url_sync_service_->OnUrlVisited(transition, &url_row);
|
|
|
| // Should throttle, so sync and local cache should not update.
|
| - const syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| + syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| ASSERT_EQ(0u, changes.size());
|
| std::set<GURL> sync_state;
|
| - typed_url_sync_service_.get()->GetSyncedUrls(&sync_state);
|
| + GetSyncedUrls(&sync_state);
|
| EXPECT_TRUE(sync_state.empty());
|
| +
|
| + for (; i % kVisitThrottleMultiple != 1; ++i)
|
| + AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
|
| + --i; // Account for the increment before the condition ends.
|
| + fake_history_backend_->SetVisitsForUrl(url_row.id(), &visits);
|
| +
|
| + // Notify typed url sync service of typed visit.
|
| + typed_url_sync_service_->OnUrlVisited(transition, &url_row);
|
| +
|
| + ASSERT_EQ(1u, changes.size());
|
| + ASSERT_TRUE(changes[0].IsValid());
|
| + ASSERT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
|
| + sync_pb::TypedUrlSpecifics url_specifics =
|
| + changes[0].sync_data().GetSpecifics().typed_url();
|
| + ASSERT_EQ(i, url_specifics.visits_size());
|
| +
|
| + GetSyncedUrls(&sync_state);
|
| + EXPECT_FALSE(sync_state.empty());
|
| +}
|
| +
|
| +// Add a typed url locally and one to sync with the same data. Starting sync
|
| +// should result in no changes.
|
| +TEST_F(TypedUrlSyncableServiceTest, MergeUrlNoChange) {
|
| + // Add a url to backend.
|
| + VisitVector visits;
|
| + URLRow row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
|
| + URLRows url_rows;
|
| + url_rows.push_back(row);
|
| + fake_history_backend_->SetVisitsForUrl(row.id(), &visits);
|
| + fake_history_backend_->SetBackendTypedUrls(&url_rows);
|
| +
|
| + // Create the same data in sync.
|
| + syncer::SyncDataList initial_sync_data;
|
| + sync_pb::EntitySpecifics entity_specifics;
|
| + sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
|
| + WriteToTypedUrlSpecifics(row, visits, typed_url);
|
| + syncer::SyncData data =
|
| + syncer::SyncData::CreateLocalData(kURL, kTitle, entity_specifics);
|
| +
|
| + initial_sync_data.push_back(data);
|
| + StartSyncing(initial_sync_data);
|
| + syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| + EXPECT_TRUE(changes.empty());
|
| +
|
| + // Check that the local cache was is still correct.
|
| + std::set<GURL> sync_state;
|
| + GetSyncedUrls(&sync_state);
|
| + EXPECT_FALSE(sync_state.empty());
|
| + EXPECT_EQ(sync_state.count(row.url()), 1U);
|
| +}
|
| +
|
| +// Starting sync with no sync data should just push the local url to sync.
|
| +TEST_F(TypedUrlSyncableServiceTest, MergeUrlEmptySync) {
|
| + // Add a url to backend.
|
| + VisitVector visits;
|
| + URLRow row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
|
| + URLRows url_rows;
|
| + url_rows.push_back(row);
|
| + fake_history_backend_->SetVisitsForUrl(row.id(), &visits);
|
| + fake_history_backend_->SetBackendTypedUrls(&url_rows);
|
| +
|
| + StartSyncing(syncer::SyncDataList());
|
| +
|
| + // Check that the local cache is still correct.
|
| + std::set<GURL> sync_state;
|
| + GetSyncedUrls(&sync_state);
|
| + EXPECT_FALSE(sync_state.empty());
|
| + EXPECT_EQ(sync_state.count(row.url()), 1U);
|
| +
|
| + // Check that the server was updated correctly.
|
| + syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| + ASSERT_EQ(1U, changes.size());
|
| + ASSERT_TRUE(changes[0].IsValid());
|
| + EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
|
| + sync_pb::TypedUrlSpecifics url_specifics =
|
| + changes[0].sync_data().GetSpecifics().typed_url();
|
| + ASSERT_EQ(1, url_specifics.visits_size());
|
| + EXPECT_EQ(3, url_specifics.visits(0));
|
| + ASSERT_EQ(1, url_specifics.visit_transitions_size());
|
| + EXPECT_EQ(static_cast<const int>(visits[0].transition),
|
| + url_specifics.visit_transitions(0));
|
| +}
|
| +
|
| +// Starting sync with no local data should just push the synced url into the
|
| +// backend.
|
| +TEST_F(TypedUrlSyncableServiceTest, MergeUrlEmptyLocal) {
|
| + // Create the sync data.
|
| + VisitVector visits;
|
| + URLRow row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
|
| + syncer::SyncDataList initial_sync_data;
|
| + sync_pb::EntitySpecifics entity_specifics;
|
| + sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
|
| + WriteToTypedUrlSpecifics(row, visits, typed_url);
|
| + syncer::SyncData data =
|
| + syncer::SyncData::CreateLocalData(kURL, kTitle, entity_specifics);
|
| +
|
| + initial_sync_data.push_back(data);
|
| + StartSyncing(initial_sync_data);
|
| + syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| + EXPECT_TRUE(changes.empty());
|
| +
|
| + // Check that the local cache is updated correctly.
|
| + std::set<GURL> sync_state;
|
| + GetSyncedUrls(&sync_state);
|
| + EXPECT_FALSE(sync_state.empty());
|
| + EXPECT_EQ(sync_state.count(row.url()), 1U);
|
| +
|
| + // Check that the backend was updated correctly.
|
| + base::Time server_time = base::Time::FromInternalValue(3);
|
| + const std::map<GURL, std::vector<history::VisitInfo>>& added_visits =
|
| + fake_history_backend_->added_visits();
|
| + ASSERT_EQ(1U, added_visits.size());
|
| + ASSERT_NE(added_visits.end(), added_visits.find(GURL(kURL)));
|
| + ASSERT_EQ(1U, added_visits.find(GURL(kURL))->second.size());
|
| + EXPECT_EQ(server_time, added_visits.find(GURL(kURL))->second[0].first);
|
| + EXPECT_EQ(visits[0].transition,
|
| + added_visits.find(GURL(kURL))->second[0].second);
|
| +}
|
| +
|
| +// Add a url to the local and sync data before sync begins, with the sync data
|
| +// having more recent visits. Check that starting sync updates the backend
|
| +// with the sync visit, while the older local visit is not pushed to sync.
|
| +// The title should be updated to the sync version due to the more recent
|
| +// timestamp.
|
| +TEST_F(TypedUrlSyncableServiceTest, MergeUrlOldLocal) {
|
| + const char kTitle2[] = "pie2";
|
| + // Add a url to backend.
|
| + VisitVector visits;
|
| + URLRow local_row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
|
| + URLRows url_rows;
|
| + url_rows.push_back(local_row);
|
| + fake_history_backend_->SetVisitsForUrl(local_row.id(), &visits);
|
| + fake_history_backend_->SetBackendTypedUrls(&url_rows);
|
| +
|
| + // Create sync data for the same url with a more recent visit.
|
| + VisitVector server_visits;
|
| + URLRow server_row =
|
| + MakeTypedUrlRow(kURL, kTitle2, 1, 6, false, &server_visits);
|
| + syncer::SyncDataList initial_sync_data;
|
| + sync_pb::EntitySpecifics entity_specifics;
|
| + sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
|
| + WriteToTypedUrlSpecifics(server_row, server_visits, typed_url);
|
| + syncer::SyncData data =
|
| + syncer::SyncData::CreateLocalData(kURL, kTitle2, entity_specifics);
|
| +
|
| + initial_sync_data.push_back(data);
|
| + StartSyncing(initial_sync_data);
|
| +
|
| + // Check that the local cache was updated correctly.
|
| + std::set<GURL> sync_state;
|
| + GetSyncedUrls(&sync_state);
|
| + EXPECT_FALSE(sync_state.empty());
|
| +
|
| + // Check that the backend was updated correctly.
|
| + base::Time server_time = base::Time::FromInternalValue(6);
|
| + const std::map<GURL, std::vector<history::VisitInfo>>& added_visits =
|
| + fake_history_backend_->added_visits();
|
| + ASSERT_EQ(1U, added_visits.size());
|
| + ASSERT_NE(added_visits.end(), added_visits.find(GURL(kURL)));
|
| + ASSERT_EQ(1U, added_visits.find(GURL(kURL))->second.size());
|
| + EXPECT_EQ(server_time, added_visits.find(GURL(kURL))->second[0].first);
|
| + EXPECT_EQ(server_visits[0].transition,
|
| + added_visits.find(GURL(kURL))->second[0].second);
|
| + EXPECT_EQ(kTitle2, base::UTF16ToUTF8(fake_history_backend_->updated_urls()
|
| + .find(local_row.id())
|
| + ->second.title()));
|
| +
|
| + // Check that the server was updated correctly.
|
| + // The local history visit should not be added to sync because it is older
|
| + // than sync's oldest visit.
|
| + syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| + ASSERT_EQ(1U, changes.size());
|
| + ASSERT_TRUE(changes[0].IsValid());
|
| + sync_pb::TypedUrlSpecifics url_specifics =
|
| + changes[0].sync_data().GetSpecifics().typed_url();
|
| + ASSERT_EQ(1, url_specifics.visits_size());
|
| + EXPECT_EQ(6, url_specifics.visits(0));
|
| + ASSERT_EQ(1, url_specifics.visit_transitions_size());
|
| + EXPECT_EQ(static_cast<const int>(visits[0].transition),
|
| + url_specifics.visit_transitions(0));
|
| +}
|
| +
|
| +// Add a url to the local and sync data before sync begins, with the local data
|
| +// having more recent visits. Check that starting sync updates the sync
|
| +// with the local visits, while the older sync visit is not pushed to the
|
| +// backend. Sync's title should be updated to the local version due to the more
|
| +// recent timestamp.
|
| +TEST_F(TypedUrlSyncableServiceTest, MergeUrlOldSync) {
|
| + const char kTitle2[] = "pie2";
|
| +
|
| + // Add a url to backend.
|
| + VisitVector visits;
|
| + URLRow local_row = MakeTypedUrlRow(kURL, kTitle2, 1, 3, false, &visits);
|
| + URLRows url_rows;
|
| + url_rows.push_back(local_row);
|
| + fake_history_backend_->SetVisitsForUrl(local_row.id(), &visits);
|
| + fake_history_backend_->SetBackendTypedUrls(&url_rows);
|
| +
|
| + // Create sync data for the same url with an older visit.
|
| + VisitVector server_visits;
|
| + URLRow server_row =
|
| + MakeTypedUrlRow(kURL, kTitle, 1, 2, false, &server_visits);
|
| + syncer::SyncDataList initial_sync_data;
|
| + sync_pb::EntitySpecifics entity_specifics;
|
| + sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
|
| + WriteToTypedUrlSpecifics(server_row, server_visits, typed_url);
|
| + syncer::SyncData data =
|
| + syncer::SyncData::CreateLocalData(kURL, kTitle, entity_specifics);
|
| +
|
| + initial_sync_data.push_back(data);
|
| + StartSyncing(initial_sync_data);
|
| +
|
| + // Check that the local cache was updated correctly.
|
| + std::set<GURL> sync_state;
|
| + GetSyncedUrls(&sync_state);
|
| + EXPECT_FALSE(sync_state.empty());
|
| +
|
| + // Check that the backend was not updated.
|
| + const std::map<GURL, std::vector<history::VisitInfo>>& added_visits =
|
| + fake_history_backend_->added_visits();
|
| + ASSERT_EQ(0U, added_visits.size());
|
| +
|
| + // Check that the server was updated correctly.
|
| + // The local history visit should not be added to sync because it is older
|
| + // than sync's oldest visit.
|
| + syncer::SyncChangeList& changes = fake_change_processor_->changes();
|
| + ASSERT_EQ(1U, changes.size());
|
| + ASSERT_TRUE(changes[0].IsValid());
|
| + sync_pb::TypedUrlSpecifics url_specifics =
|
| + changes[0].sync_data().GetSpecifics().typed_url();
|
| + ASSERT_EQ(1, url_specifics.visits_size());
|
| + EXPECT_EQ(3, url_specifics.visits(0));
|
| + EXPECT_EQ(kTitle2, url_specifics.title());
|
| + ASSERT_EQ(1, url_specifics.visit_transitions_size());
|
| + EXPECT_EQ(static_cast<const int>(visits[0].transition),
|
| + url_specifics.visit_transitions(0));
|
| }
|
|
|
| } // namespace history
|
|
|