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

Unified Diff: components/history/core/browser/typed_url_syncable_service_unittest.cc

Issue 1324383002: [Sync] Add initial merging logic for typed urls syncable service (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: histogram.h -> histogram_macro.h Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « components/history/core/browser/typed_url_syncable_service.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698