12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/sync_bookmarks/synced_bookmark_tracker.h"
- #include "base/base64.h"
- #include "base/guid.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "base/test/scoped_feature_list.h"
- #include "components/bookmarks/browser/bookmark_model.h"
- #include "components/bookmarks/browser/bookmark_node.h"
- #include "components/bookmarks/browser/bookmark_utils.h"
- #include "components/bookmarks/test/test_bookmark_client.h"
- #include "components/sync/base/client_tag_hash.h"
- #include "components/sync/base/time.h"
- #include "components/sync/base/unique_position.h"
- #include "components/sync/protocol/bookmark_model_metadata.pb.h"
- #include "components/sync/protocol/entity_data.h"
- #include "components/sync/protocol/entity_specifics.pb.h"
- #include "components/sync/protocol/model_type_state.pb.h"
- #include "components/sync_bookmarks/switches.h"
- #include "components/sync_bookmarks/synced_bookmark_tracker_entity.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using testing::Eq;
- using testing::IsNull;
- using testing::NotNull;
- namespace sync_bookmarks {
- namespace {
- constexpr int kNumPermanentNodes = 3;
- const char kBookmarkBarId[] = "bookmark_bar_id";
- const char kMobileBookmarksId[] = "synced_bookmarks_id";
- const char kOtherBookmarksId[] = "other_bookmarks_id";
- // Redefinition of |enum CorruptionReason| in synced_bookmark_tracker.cc to be
- // used in tests.
- enum class ExpectedCorruptionReason {
- NO_CORRUPTION = 0,
- MISSING_SERVER_ID = 1,
- BOOKMARK_ID_IN_TOMBSTONE = 2,
- MISSING_BOOKMARK_ID = 3,
- DEPRECATED_COUNT_MISMATCH = 4,
- DEPRECATED_IDS_MISMATCH = 5,
- DUPLICATED_SERVER_ID = 6,
- UNKNOWN_BOOKMARK_ID = 7,
- UNTRACKED_BOOKMARK = 8,
- BOOKMARK_GUID_MISMATCH = 9,
- DUPLICATED_CLIENT_TAG_HASH = 10,
- TRACKED_MANAGED_NODE = 11,
- MISSING_CLIENT_TAG_HASH = 12,
- MISSING_FAVICON_HASH = 13,
- kMaxValue = MISSING_FAVICON_HASH
- };
- sync_pb::EntitySpecifics GenerateSpecifics(const std::string& title,
- const std::string& url) {
- sync_pb::EntitySpecifics specifics;
- specifics.mutable_bookmark()->set_legacy_canonicalized_title(title);
- specifics.mutable_bookmark()->set_url(url);
- *specifics.mutable_bookmark()->mutable_unique_position() =
- syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto();
- return specifics;
- }
- // |node| must not be nullptr.
- sync_pb::BookmarkMetadata CreateNodeMetadata(
- const bookmarks::BookmarkNode* node,
- const std::string& server_id) {
- sync_pb::BookmarkMetadata bookmark_metadata;
- bookmark_metadata.set_id(node->id());
- bookmark_metadata.mutable_metadata()->set_server_id(server_id);
- bookmark_metadata.mutable_metadata()->set_client_tag_hash(
- syncer::ClientTagHash::FromUnhashed(syncer::BOOKMARKS,
- node->guid().AsLowercaseString())
- .value());
- // Required by the validation logic.
- if (!node->is_folder()) {
- bookmark_metadata.mutable_metadata()->set_bookmark_favicon_hash(123);
- }
- return bookmark_metadata;
- }
- sync_pb::BookmarkMetadata CreateTombstoneMetadata(
- const std::string& server_id,
- const syncer::ClientTagHash& client_tag_hash) {
- sync_pb::BookmarkMetadata bookmark_metadata;
- bookmark_metadata.mutable_metadata()->set_server_id(server_id);
- bookmark_metadata.mutable_metadata()->set_is_deleted(true);
- bookmark_metadata.mutable_metadata()->set_sequence_number(1);
- bookmark_metadata.mutable_metadata()->set_client_tag_hash(
- client_tag_hash.value());
- return bookmark_metadata;
- }
- sync_pb::BookmarkModelMetadata CreateMetadataForPermanentNodes(
- const bookmarks::BookmarkModel* bookmark_model) {
- sync_pb::BookmarkModelMetadata model_metadata;
- model_metadata.mutable_model_type_state()->set_initial_sync_done(true);
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(bookmark_model->bookmark_bar_node(),
- /*server_id=*/kBookmarkBarId);
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(bookmark_model->mobile_node(),
- /*server_id=*/kMobileBookmarksId);
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(bookmark_model->other_node(),
- /*server_id=*/kOtherBookmarksId);
- CHECK_EQ(kNumPermanentNodes, model_metadata.bookmarks_metadata_size());
- return model_metadata;
- }
- TEST(SyncedBookmarkTrackerTest, ShouldAddEntity) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- const std::string kSyncId = "SYNC_ID";
- const std::string kTitle = "Title";
- const GURL kUrl("http://www.foo.com");
- const int64_t kId = 1;
- const base::GUID kGuid = base::GUID::GenerateRandomV4();
- const int64_t kServerVersion = 1000;
- const base::Time kCreationTime(base::Time::Now() - base::Seconds(1));
- const sync_pb::EntitySpecifics specifics =
- GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, kGuid, kUrl);
- const SyncedBookmarkTrackerEntity* entity =
- tracker->Add(&node, kSyncId, kServerVersion, kCreationTime, specifics);
- ASSERT_THAT(entity, NotNull());
- EXPECT_THAT(entity->bookmark_node(), Eq(&node));
- EXPECT_THAT(entity->GetClientTagHash(),
- Eq(syncer::ClientTagHash::FromUnhashed(
- syncer::BOOKMARKS, kGuid.AsLowercaseString())));
- EXPECT_THAT(entity->metadata().server_id(), Eq(kSyncId));
- EXPECT_THAT(entity->metadata().server_version(), Eq(kServerVersion));
- EXPECT_THAT(entity->metadata().creation_time(),
- Eq(syncer::TimeToProtoTime(kCreationTime)));
- EXPECT_TRUE(
- syncer::UniquePosition::FromProto(entity->metadata().unique_position())
- .Equals(syncer::UniquePosition::FromProto(
- specifics.bookmark().unique_position())));
- EXPECT_THAT(tracker->GetEntityForSyncId(kSyncId), Eq(entity));
- EXPECT_THAT(tracker->GetEntityForBookmarkNode(&node), Eq(entity));
- EXPECT_THAT(
- tracker->GetEntityForClientTagHash(syncer::ClientTagHash::FromUnhashed(
- syncer::BOOKMARKS, kGuid.AsLowercaseString())),
- Eq(entity));
- syncer::EntityData data;
- *data.specifics.mutable_bookmark() = specifics.bookmark();
- EXPECT_TRUE(entity->MatchesData(data));
- EXPECT_THAT(tracker->GetEntityForSyncId("unknown id"), IsNull());
- }
- TEST(SyncedBookmarkTrackerTest, ShouldRemoveEntity) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- const std::string kSyncId = "SYNC_ID";
- const int64_t kId = 1;
- const base::GUID kGuid = base::GUID::GenerateRandomV4();
- const int64_t kServerVersion = 1000;
- const base::Time kModificationTime(base::Time::Now() - base::Seconds(1));
- const sync_pb::EntitySpecifics specifics =
- GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, kGuid, GURL());
- const SyncedBookmarkTrackerEntity* entity = tracker->Add(
- &node, kSyncId, kServerVersion, kModificationTime, specifics);
- ASSERT_THAT(entity, NotNull());
- ASSERT_THAT(tracker->GetEntityForSyncId(kSyncId), Eq(entity));
- ASSERT_THAT(tracker->GetEntityForBookmarkNode(&node), Eq(entity));
- ASSERT_THAT(
- tracker->GetEntityForClientTagHash(syncer::ClientTagHash::FromUnhashed(
- syncer::BOOKMARKS, kGuid.AsLowercaseString())),
- Eq(entity));
- tracker->Remove(entity);
- EXPECT_THAT(tracker->GetEntityForSyncId(kSyncId), IsNull());
- EXPECT_THAT(tracker->GetEntityForBookmarkNode(&node), IsNull());
- EXPECT_THAT(
- tracker->GetEntityForClientTagHash(syncer::ClientTagHash::FromUnhashed(
- syncer::BOOKMARKS, kGuid.AsLowercaseString())),
- IsNull());
- }
- TEST(SyncedBookmarkTrackerTest, ShouldBuildBookmarkModelMetadata) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- const std::string kSyncId = "SYNC_ID";
- const std::string kTitle = "Title";
- const GURL kUrl("http://www.foo.com");
- const int64_t kId = 1;
- const int64_t kServerVersion = 1000;
- const base::Time kCreationTime(base::Time::Now() - base::Seconds(1));
- const sync_pb::EntitySpecifics specifics =
- GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, base::GUID::GenerateRandomV4(), kUrl);
- tracker->Add(&node, kSyncId, kServerVersion, kCreationTime, specifics);
- sync_pb::BookmarkModelMetadata bookmark_model_metadata =
- tracker->BuildBookmarkModelMetadata();
- ASSERT_THAT(bookmark_model_metadata.bookmarks_metadata().size(), Eq(1));
- EXPECT_THAT(
- bookmark_model_metadata.bookmarks_metadata(0).metadata().server_id(),
- Eq(kSyncId));
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldRequireCommitRequestWhenSequenceNumberIsIncremented) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- const std::string kSyncId = "SYNC_ID";
- const int64_t kId = 1;
- const int64_t kServerVersion = 1000;
- const base::Time kModificationTime(base::Time::Now() - base::Seconds(1));
- const sync_pb::EntitySpecifics specifics =
- GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, base::GUID::GenerateRandomV4(), GURL());
- const SyncedBookmarkTrackerEntity* entity = tracker->Add(
- &node, kSyncId, kServerVersion, kModificationTime, specifics);
- EXPECT_THAT(tracker->HasLocalChanges(), Eq(false));
- tracker->IncrementSequenceNumber(entity);
- EXPECT_THAT(tracker->HasLocalChanges(), Eq(true));
- }
- TEST(SyncedBookmarkTrackerTest, ShouldAckSequenceNumber) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- const std::string kSyncId = "SYNC_ID";
- const int64_t kId = 1;
- const int64_t kServerVersion = 1000;
- const base::Time kModificationTime(base::Time::Now() - base::Seconds(1));
- const sync_pb::EntitySpecifics specifics =
- GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, base::GUID::GenerateRandomV4(), GURL());
- const SyncedBookmarkTrackerEntity* entity = tracker->Add(
- &node, kSyncId, kServerVersion, kModificationTime, specifics);
- // Test simple scenario of ack'ing an incrememented sequence number.
- EXPECT_THAT(tracker->HasLocalChanges(), Eq(false));
- tracker->IncrementSequenceNumber(entity);
- EXPECT_THAT(tracker->HasLocalChanges(), Eq(true));
- tracker->AckSequenceNumber(entity);
- EXPECT_THAT(tracker->HasLocalChanges(), Eq(false));
- // Test ack'ing of a multiple times incremented sequence number.
- tracker->IncrementSequenceNumber(entity);
- EXPECT_THAT(tracker->HasLocalChanges(), Eq(true));
- tracker->IncrementSequenceNumber(entity);
- tracker->IncrementSequenceNumber(entity);
- EXPECT_THAT(tracker->HasLocalChanges(), Eq(true));
- tracker->AckSequenceNumber(entity);
- EXPECT_THAT(tracker->HasLocalChanges(), Eq(false));
- }
- TEST(SyncedBookmarkTrackerTest, ShouldUpdateUponCommitResponseWithNewId) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- const std::string kSyncId = "SYNC_ID";
- const std::string kNewSyncId = "NEW_SYNC_ID";
- const int64_t kId = 1;
- const int64_t kServerVersion = 1000;
- const int64_t kNewServerVersion = 1001;
- const base::Time kModificationTime(base::Time::Now() - base::Seconds(1));
- const sync_pb::EntitySpecifics specifics =
- GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, base::GUID::GenerateRandomV4(), GURL());
- const SyncedBookmarkTrackerEntity* entity = tracker->Add(
- &node, kSyncId, kServerVersion, kModificationTime, specifics);
- ASSERT_THAT(entity, NotNull());
- // Initially only the old ID should be tracked.
- ASSERT_THAT(tracker->GetEntityForSyncId(kSyncId), Eq(entity));
- ASSERT_THAT(tracker->GetEntityForSyncId(kNewSyncId), IsNull());
- // Receive a commit response with a changed id.
- tracker->UpdateUponCommitResponse(entity, kNewSyncId, kNewServerVersion,
- /*acked_sequence_number=*/1);
- // Old id shouldn't be there, but the new one should.
- EXPECT_THAT(tracker->GetEntityForSyncId(kSyncId), IsNull());
- EXPECT_THAT(tracker->GetEntityForSyncId(kNewSyncId), Eq(entity));
- EXPECT_THAT(entity->metadata().server_id(), Eq(kNewSyncId));
- EXPECT_THAT(entity->bookmark_node(), Eq(&node));
- EXPECT_THAT(entity->metadata().server_version(), Eq(kNewServerVersion));
- }
- TEST(SyncedBookmarkTrackerTest, ShouldUpdateId) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- const std::string kSyncId = "SYNC_ID";
- const std::string kNewSyncId = "NEW_SYNC_ID";
- const int64_t kServerVersion = 1000;
- const base::Time kModificationTime(base::Time::Now() - base::Seconds(1));
- const sync_pb::EntitySpecifics specifics =
- GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(/*id=*/1, base::GUID::GenerateRandomV4(),
- GURL());
- // Track a sync entity.
- const SyncedBookmarkTrackerEntity* entity = tracker->Add(
- &node, kSyncId, kServerVersion, kModificationTime, specifics);
- ASSERT_THAT(entity, NotNull());
- // Update the sync id.
- tracker->UpdateSyncIdIfNeeded(entity, kNewSyncId);
- // Old id shouldn't be there, but the new one should.
- EXPECT_THAT(tracker->GetEntityForSyncId(kSyncId), IsNull());
- EXPECT_THAT(tracker->GetEntityForSyncId(kNewSyncId), Eq(entity));
- EXPECT_THAT(entity->metadata().server_id(), Eq(kNewSyncId));
- EXPECT_THAT(entity->bookmark_node(), Eq(&node));
- EXPECT_THAT(entity->metadata().server_version(), Eq(kServerVersion));
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldMaintainTombstoneOrderBetweenCtorAndBuildBookmarkModelMetadata) {
- // Feed a metadata batch of 5 entries to the constructor of the tracker.
- // First 2 are for node, and the last 4 are for tombstones.
- // Server ids.
- const std::string kId0 = "id0";
- const std::string kId1 = "id1";
- const std::string kId2 = "id2";
- const std::string kId3 = "id3";
- const std::string kId4 = "id4";
- std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
- bookmarks::TestBookmarkClient::CreateModel();
- const bookmarks::BookmarkNode* bookmark_bar_node =
- bookmark_model->bookmark_bar_node();
- const bookmarks::BookmarkNode* node0 = bookmark_model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node0");
- const bookmarks::BookmarkNode* node1 = bookmark_model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node1");
- sync_pb::BookmarkModelMetadata initial_model_metadata =
- CreateMetadataForPermanentNodes(bookmark_model.get());
- *initial_model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node0, /*server_id=*/kId0);
- *initial_model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node1, /*server_id=*/kId1);
- *initial_model_metadata.add_bookmarks_metadata() = CreateTombstoneMetadata(
- /*server_id=*/kId2, syncer::ClientTagHash::FromHashed("clienttaghash2"));
- *initial_model_metadata.add_bookmarks_metadata() = CreateTombstoneMetadata(
- /*server_id=*/kId3, syncer::ClientTagHash::FromHashed("clienttaghash3"));
- *initial_model_metadata.add_bookmarks_metadata() = CreateTombstoneMetadata(
- /*server_id=*/kId4, syncer::ClientTagHash::FromHashed("clienttaghash4"));
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- bookmark_model.get(), std::move(initial_model_metadata));
- ASSERT_THAT(tracker, NotNull());
- const sync_pb::BookmarkModelMetadata output_model_metadata =
- tracker->BuildBookmarkModelMetadata();
- // Tombstones should be the last 3 entries in the metadata and in the same
- // order as given to the constructor.
- ASSERT_THAT(output_model_metadata.bookmarks_metadata().size(),
- Eq(kNumPermanentNodes + 5));
- EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 2)
- .metadata()
- .server_id(),
- Eq(kId2));
- EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 3)
- .metadata()
- .server_id(),
- Eq(kId3));
- EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 4)
- .metadata()
- .server_id(),
- Eq(kId4));
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldMaintainOrderOfMarkDeletedCallsWhenBuildBookmarkModelMetadata) {
- // Server ids.
- const std::string kId0 = "id0";
- const std::string kId1 = "id1";
- const std::string kId2 = "id2";
- const std::string kId3 = "id3";
- const std::string kId4 = "id4";
- std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
- bookmarks::TestBookmarkClient::CreateModel();
- const bookmarks::BookmarkNode* bookmark_bar_node =
- bookmark_model->bookmark_bar_node();
- const bookmarks::BookmarkNode* node0 = bookmark_model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node0");
- const bookmarks::BookmarkNode* node1 = bookmark_model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node1");
- const bookmarks::BookmarkNode* node2 = bookmark_model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node2");
- const bookmarks::BookmarkNode* node3 = bookmark_model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node3");
- const bookmarks::BookmarkNode* node4 = bookmark_model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node4");
- sync_pb::BookmarkModelMetadata initial_model_metadata =
- CreateMetadataForPermanentNodes(bookmark_model.get());
- *initial_model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node0, /*server_id=*/kId0);
- *initial_model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node1, /*server_id=*/kId1);
- *initial_model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node2, /*server_id=*/kId2);
- *initial_model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node3, /*server_id=*/kId3);
- *initial_model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node4, /*server_id=*/kId4);
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- bookmark_model.get(), std::move(initial_model_metadata));
- ASSERT_THAT(tracker, NotNull());
- // Mark entities deleted in that order kId2, kId4, kId1
- tracker->MarkDeleted(tracker->GetEntityForSyncId(kId2));
- tracker->MarkDeleted(tracker->GetEntityForSyncId(kId4));
- tracker->MarkDeleted(tracker->GetEntityForSyncId(kId1));
- const sync_pb::BookmarkModelMetadata output_model_metadata =
- tracker->BuildBookmarkModelMetadata();
- // Tombstones should be the last 3 entries in the metadata and in the same as
- // calling MarkDeleted().
- ASSERT_THAT(output_model_metadata.bookmarks_metadata().size(),
- Eq(kNumPermanentNodes + 5));
- EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 2)
- .metadata()
- .server_id(),
- Eq(kId2));
- EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 3)
- .metadata()
- .server_id(),
- Eq(kId4));
- EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 4)
- .metadata()
- .server_id(),
- Eq(kId1));
- }
- TEST(SyncedBookmarkTrackerTest, ShouldMarkDeleted) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- const std::string kSyncId = "SYNC_ID";
- const int64_t kId = 1;
- const base::GUID kGuid = base::GUID::GenerateRandomV4();
- const int64_t kServerVersion = 1000;
- const base::Time kModificationTime(base::Time::Now() - base::Seconds(1));
- const sync_pb::EntitySpecifics specifics =
- GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, kGuid, GURL());
- const SyncedBookmarkTrackerEntity* entity = tracker->Add(
- &node, kSyncId, kServerVersion, kModificationTime, specifics);
- ASSERT_THAT(tracker->TrackedUncommittedTombstonesCount(), Eq(0U));
- ASSERT_THAT(tracker->GetEntityForSyncId(kSyncId), Eq(entity));
- ASSERT_THAT(tracker->GetEntityForBookmarkNode(&node), Eq(entity));
- ASSERT_THAT(
- tracker->GetEntityForClientTagHash(syncer::ClientTagHash::FromUnhashed(
- syncer::BOOKMARKS, kGuid.AsLowercaseString())),
- Eq(entity));
- ASSERT_FALSE(entity->metadata().is_deleted());
- ASSERT_THAT(entity->bookmark_node(), Eq(&node));
- // Delete the bookmark, leading to a pending deletion (local tombstone).
- tracker->MarkDeleted(entity);
- EXPECT_THAT(tracker->TrackedUncommittedTombstonesCount(), Eq(1U));
- EXPECT_THAT(tracker->GetEntityForSyncId(kSyncId), Eq(entity));
- EXPECT_THAT(tracker->GetEntityForBookmarkNode(&node), IsNull());
- EXPECT_THAT(
- tracker->GetEntityForClientTagHash(syncer::ClientTagHash::FromUnhashed(
- syncer::BOOKMARKS, kGuid.AsLowercaseString())),
- Eq(entity));
- EXPECT_TRUE(entity->metadata().is_deleted());
- EXPECT_THAT(entity->bookmark_node(), IsNull());
- }
- TEST(SyncedBookmarkTrackerTest, ShouldUndeleteTombstone) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- const std::string kSyncId = "SYNC_ID";
- const int64_t kId = 1;
- const base::GUID kGuid = base::GUID::GenerateRandomV4();
- const int64_t kServerVersion = 1000;
- const base::Time kModificationTime(base::Time::Now() - base::Seconds(1));
- const sync_pb::EntitySpecifics specifics =
- GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, kGuid, GURL());
- const SyncedBookmarkTrackerEntity* entity = tracker->Add(
- &node, kSyncId, kServerVersion, kModificationTime, specifics);
- ASSERT_THAT(tracker->TrackedUncommittedTombstonesCount(), Eq(0U));
- ASSERT_THAT(tracker->GetEntityForSyncId(kSyncId), Eq(entity));
- // Delete the bookmark, leading to a pending deletion (local tombstone).
- tracker->MarkDeleted(entity);
- ASSERT_THAT(entity->bookmark_node(), IsNull());
- ASSERT_TRUE(entity->metadata().is_deleted());
- ASSERT_THAT(tracker->TrackedUncommittedTombstonesCount(), Eq(1U));
- ASSERT_THAT(tracker->GetEntityForBookmarkNode(&node), IsNull());
- ASSERT_THAT(
- tracker->GetEntityForClientTagHash(syncer::ClientTagHash::FromUnhashed(
- syncer::BOOKMARKS, kGuid.AsLowercaseString())),
- Eq(entity));
- // Undelete it.
- tracker->UndeleteTombstoneForBookmarkNode(entity, &node);
- EXPECT_THAT(entity->bookmark_node(), NotNull());
- EXPECT_FALSE(entity->metadata().is_deleted());
- EXPECT_THAT(tracker->TrackedUncommittedTombstonesCount(), Eq(0U));
- ASSERT_THAT(tracker->GetEntityForBookmarkNode(&node), Eq(entity));
- EXPECT_THAT(
- tracker->GetEntityForClientTagHash(syncer::ClientTagHash::FromUnhashed(
- syncer::BOOKMARKS, kGuid.AsLowercaseString())),
- Eq(entity));
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldOrderParentUpdatesBeforeChildUpdatesAndDeletionsComeLast) {
- // Construct this structure:
- // bookmark_bar
- // |- node0
- // |- node1
- // |- node2
- std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
- bookmarks::TestBookmarkClient::CreateModel();
- const bookmarks::BookmarkNode* bookmark_bar_node =
- bookmark_model->bookmark_bar_node();
- const bookmarks::BookmarkNode* node0 = bookmark_model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node0");
- const bookmarks::BookmarkNode* node1 = bookmark_model->AddFolder(
- /*parent=*/node0, /*index=*/0, u"node1");
- const bookmarks::BookmarkNode* node2 = bookmark_model->AddFolder(
- /*parent=*/node1, /*index=*/0, u"node2");
- // Server ids.
- const std::string kId0 = "id0";
- const std::string kId1 = "id1";
- const std::string kId2 = "id2";
- const std::string kId3 = "id3";
- // Prepare the metadata with shuffled order.
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(bookmark_model.get());
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node1, /*server_id=*/kId1);
- *model_metadata.add_bookmarks_metadata() = CreateTombstoneMetadata(
- /*server_id=*/kId3, syncer::ClientTagHash::FromHashed("clienttaghash3"));
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node2, /*server_id=*/kId2);
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node0, /*server_id=*/kId0);
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- bookmark_model.get(), std::move(model_metadata));
- ASSERT_THAT(tracker, NotNull());
- // Mark the entities that they have local changes. (in shuffled order just to
- // verify the tracker doesn't simply maintain the order of updates similar to
- // with deletions).
- tracker->IncrementSequenceNumber(tracker->GetEntityForSyncId(kId3));
- tracker->IncrementSequenceNumber(tracker->GetEntityForSyncId(kId1));
- tracker->IncrementSequenceNumber(tracker->GetEntityForSyncId(kId2));
- tracker->IncrementSequenceNumber(tracker->GetEntityForSyncId(kId0));
- std::vector<const SyncedBookmarkTrackerEntity*> entities_with_local_change =
- tracker->GetEntitiesWithLocalChanges();
- ASSERT_THAT(entities_with_local_change.size(), Eq(4U));
- // Verify updates are in parent before child order node0 --> node1 --> node2.
- EXPECT_THAT(entities_with_local_change[0]->metadata().server_id(), Eq(kId0));
- EXPECT_THAT(entities_with_local_change[1]->metadata().server_id(), Eq(kId1));
- EXPECT_THAT(entities_with_local_change[2]->metadata().server_id(), Eq(kId2));
- // Verify that deletion is the last entry.
- EXPECT_THAT(entities_with_local_change[3]->metadata().server_id(), Eq(kId3));
- }
- TEST(SyncedBookmarkTrackerTest, ShouldNotInvalidateMetadata) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
- const bookmarks::BookmarkNode* node = model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node0");
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- // Add entry for the managed node.
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node, /*server_id=*/"NodeId");
- // Add a tombstone entry.
- *model_metadata.add_bookmarks_metadata() = CreateTombstoneMetadata(
- /*server_id=*/"tombstoneId",
- syncer::ClientTagHash::FromHashed("clienttaghash"));
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- NotNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::NO_CORRUPTION,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest, ShouldNotRequireClientTagsForPermanentNodes) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- // Clear the client tag hash field in metadata, which is irrelevant for
- // permanent nodes (and some older versions of the browser didn't populate).
- for (sync_pb::BookmarkMetadata& bookmark_metadata :
- *model_metadata.mutable_bookmarks_metadata()) {
- bookmark_metadata.mutable_metadata()->clear_client_tag_hash();
- }
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata));
- ASSERT_THAT(tracker, NotNull());
- EXPECT_THAT(tracker->GetEntityForSyncId(kBookmarkBarId), NotNull());
- EXPECT_THAT(tracker->GetEntityForSyncId(kMobileBookmarksId), NotNull());
- EXPECT_THAT(tracker->GetEntityForSyncId(kOtherBookmarksId), NotNull());
- }
- TEST(SyncedBookmarkTrackerTest, ShouldInvalidateMetadataIfMissingMobileFolder) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::BookmarkModelMetadata model_metadata;
- model_metadata.mutable_model_type_state()->set_initial_sync_done(true);
- // Add entries for all the permanent nodes except for the Mobile bookmarks
- // folder.
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(model->bookmark_bar_node(),
- /*server_id=*/kBookmarkBarId);
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(model->other_node(),
- /*server_id=*/kOtherBookmarksId);
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- IsNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::UNTRACKED_BOOKMARK,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest, ShouldInvalidateMetadataIfMissingServerId) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- // Remove a server ID to a permanent node.
- model_metadata.mutable_bookmarks_metadata(0)
- ->mutable_metadata()
- ->clear_server_id();
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- IsNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::MISSING_SERVER_ID,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldInvalidateMetadataIfMissingLocalBookmarkId) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- const bookmarks::BookmarkNode* node = model->AddFolder(
- /*parent=*/model->bookmark_bar_node(), /*index=*/0, u"node");
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node, /*server_id=*/"serverid");
- // Remove the local bookmark ID.
- model_metadata.mutable_bookmarks_metadata()->rbegin()->clear_id();
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- IsNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::MISSING_BOOKMARK_ID,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldInvalidateMetadataIfTombstoneHasBookmarkId) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- *model_metadata.add_bookmarks_metadata() = CreateTombstoneMetadata(
- /*server_id=*/"serverid",
- syncer::ClientTagHash::FromHashed("clienttaghash"));
- // Add a node ID to the tombstone.
- model_metadata.mutable_bookmarks_metadata()->rbegin()->set_id(1234);
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- IsNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::BOOKMARK_ID_IN_TOMBSTONE,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldInvalidateMetadataIfUnknownLocalBookmarkId) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- const bookmarks::BookmarkNode* node = model->AddFolder(
- /*parent=*/model->bookmark_bar_node(), /*index=*/0, u"node");
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(node, /*server_id=*/"serverid");
- // Set an arbitrary local node ID that won't match anything in BookmarkModel.
- model_metadata.mutable_bookmarks_metadata()->rbegin()->set_id(123456);
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- IsNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::UNKNOWN_BOOKMARK_ID,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest, ShouldInvalidateMetadataIfGuidMismatch) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
- const bookmarks::BookmarkNode* node0 = model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node0");
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- sync_pb::BookmarkMetadata* node0_metadata =
- model_metadata.add_bookmarks_metadata();
- *node0_metadata = CreateNodeMetadata(node0, /*server_id=*/"id0");
- // Set a mismatching client tag hash.
- node0_metadata->mutable_metadata()->set_client_tag_hash("corrupthash");
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- IsNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::BOOKMARK_GUID_MISMATCH,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldInvalidateMetadataIfTombstoneHasDuplicatedClientTagHash) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
- const bookmarks::BookmarkNode* node0 = model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node0");
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- sync_pb::BookmarkMetadata* node0_metadata =
- model_metadata.add_bookmarks_metadata();
- *node0_metadata = CreateNodeMetadata(node0, /*server_id=*/"id0");
- const syncer::ClientTagHash client_tag_hash =
- syncer::ClientTagHash::FromUnhashed(syncer::BOOKMARKS,
- node0->guid().AsLowercaseString());
- node0_metadata->mutable_metadata()->set_client_tag_hash(
- client_tag_hash.value());
- // Add the duplicate tombstone with a different server id but same client tag
- // hash.
- sync_pb::BookmarkMetadata* tombstone_metadata =
- model_metadata.add_bookmarks_metadata();
- *tombstone_metadata = CreateTombstoneMetadata(
- "id1", syncer::ClientTagHash::FromHashed("clienttaghash1"));
- tombstone_metadata->mutable_metadata()->set_client_tag_hash(
- client_tag_hash.value());
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- IsNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::DUPLICATED_CLIENT_TAG_HASH,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldInvalidateMetadataIfMissingClientTagHash) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
- const bookmarks::BookmarkNode* node0 = model->AddFolder(
- /*parent=*/bookmark_bar_node, /*index=*/0, u"node0");
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- sync_pb::BookmarkMetadata* node0_metadata =
- model_metadata.add_bookmarks_metadata();
- *node0_metadata = CreateNodeMetadata(node0, /*server_id=*/"id0");
- node0_metadata->mutable_metadata()->clear_client_tag_hash();
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- IsNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::MISSING_CLIENT_TAG_HASH,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldInvalidateMetadataIfUnsyncableNodeIsTracked) {
- auto client = std::make_unique<bookmarks::TestBookmarkClient>();
- bookmarks::BookmarkNode* managed_node = client->EnableManagedNode();
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModelWithClient(std::move(client));
- // The model should contain the managed node now.
- ASSERT_THAT(GetBookmarkNodeByID(model.get(), managed_node->id()),
- Eq(managed_node));
- // Add entries for all the permanent nodes. TestBookmarkClient creates all the
- // 3 permanent nodes.
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- // Add unsyncable node to metadata.
- *model_metadata.add_bookmarks_metadata() =
- CreateNodeMetadata(managed_node,
- /*server_id=*/"server_id");
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- IsNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::TRACKED_MANAGED_NODE,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest, ShouldInvalidateMetadataIfMissingFaviconHash) {
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
- const bookmarks::BookmarkNode* node0 =
- model->AddURL(/*parent=*/bookmark_bar_node, /*index=*/0, u"Title",
- GURL("http://www.url.com"));
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- sync_pb::BookmarkMetadata* node0_metadata =
- model_metadata.add_bookmarks_metadata();
- *node0_metadata = CreateNodeMetadata(node0, /*server_id=*/"id0");
- node0_metadata->mutable_metadata()->clear_bookmark_favicon_hash();
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- IsNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::MISSING_FAVICON_HASH,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldMatchModelWithUnsyncableNodesAndMetadata) {
- auto client = std::make_unique<bookmarks::TestBookmarkClient>();
- bookmarks::BookmarkNode* managed_node = client->EnableManagedNode();
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModelWithClient(std::move(client));
- // The model should contain the managed node now.
- ASSERT_THAT(GetBookmarkNodeByID(model.get(), managed_node->id()),
- Eq(managed_node));
- // Add entries for all the permanent nodes. TestBookmarkClient creates all the
- // 3 permanent nodes.
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- base::HistogramTester histogram_tester;
- EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata)),
- NotNull());
- histogram_tester.ExpectUniqueSample(
- "Sync.BookmarksModelMetadataCorruptionReason",
- /*sample=*/ExpectedCorruptionReason::NO_CORRUPTION,
- /*expected_bucket_count=*/1);
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldPopulateFaviconHashForNewlyAddedEntities) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- const std::string kSyncId = "SYNC_ID";
- const std::string kTitle = "Title";
- const GURL kUrl("http://www.foo.com");
- const int64_t kId = 1;
- const int64_t kServerVersion = 1000;
- const base::Time kCreationTime = base::Time::Now();
- const std::string kFaviconPngBytes = "fakefaviconbytes";
- sync_pb::EntitySpecifics specifics = GenerateSpecifics(kTitle, kUrl.spec());
- specifics.mutable_bookmark()->set_favicon(kFaviconPngBytes);
- bookmarks::BookmarkNode node(kId, base::GUID::GenerateRandomV4(), kUrl);
- const SyncedBookmarkTrackerEntity* entity =
- tracker->Add(&node, kSyncId, kServerVersion, kCreationTime, specifics);
- EXPECT_TRUE(entity->metadata().has_bookmark_favicon_hash());
- EXPECT_TRUE(entity->MatchesFaviconHash(kFaviconPngBytes));
- EXPECT_FALSE(entity->MatchesFaviconHash("otherhash"));
- }
- TEST(SyncedBookmarkTrackerTest, ShouldPopulateFaviconHashUponUpdate) {
- const std::string kSyncId = "SYNC_ID";
- const std::string kTitle = "Title";
- const GURL kUrl("http://www.foo.com");
- const int64_t kServerVersion = 1000;
- const base::Time kModificationTime = base::Time::Now();
- const std::string kFaviconPngBytes = "fakefaviconbytes";
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
- const bookmarks::BookmarkNode* node =
- model->AddURL(/*parent=*/bookmark_bar_node, /*index=*/0, u"Title",
- GURL("http://www.url.com"));
- sync_pb::BookmarkModelMetadata model_metadata =
- CreateMetadataForPermanentNodes(model.get());
- // Add entry for the URL node.
- *model_metadata.add_bookmarks_metadata() = CreateNodeMetadata(node, kSyncId);
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), std::move(model_metadata));
- ASSERT_THAT(tracker, NotNull());
- const SyncedBookmarkTrackerEntity* entity =
- tracker->GetEntityForSyncId(kSyncId);
- ASSERT_THAT(entity, NotNull());
- ASSERT_FALSE(entity->MatchesFaviconHash(kFaviconPngBytes));
- sync_pb::EntitySpecifics specifics = GenerateSpecifics(kTitle, kUrl.spec());
- specifics.mutable_bookmark()->set_favicon(kFaviconPngBytes);
- tracker->Update(entity, kServerVersion, kModificationTime, specifics);
- EXPECT_TRUE(entity->metadata().has_bookmark_favicon_hash());
- EXPECT_TRUE(entity->MatchesFaviconHash(kFaviconPngBytes));
- EXPECT_FALSE(entity->MatchesFaviconHash("otherhash"));
- }
- TEST(SyncedBookmarkTrackerTest, ShouldNotReuploadEntitiesAfterMergeAndRestart) {
- base::test::ScopedFeatureList override_features;
- override_features.InitAndEnableFeature(switches::kSyncReuploadBookmarks);
- const std::string kTitle = "Title";
- const GURL kUrl("http://www.foo.com");
- sync_pb::ModelTypeState model_type_state;
- model_type_state.set_initial_sync_done(true);
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(model_type_state);
- tracker->SetBookmarksReuploaded();
- std::unique_ptr<bookmarks::BookmarkModel> model =
- bookmarks::TestBookmarkClient::CreateModel();
- const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
- const bookmarks::BookmarkNode* node =
- model->AddURL(/*parent=*/bookmark_bar_node, /*index=*/0,
- base::UTF8ToUTF16(kTitle), kUrl);
- const sync_pb::EntitySpecifics specifics =
- GenerateSpecifics(kTitle, kUrl.spec());
- tracker->Add(node, /*sync_id=*/"id", /*server_version=*/0,
- /*creation_time=*/base::Time::Now(), specifics);
- sync_pb::EntitySpecifics permanent_specifics;
- permanent_specifics.mutable_bookmark();
- // Add permanent nodes to tracker.
- tracker->Add(model->bookmark_bar_node(), kBookmarkBarId, /*server_version=*/0,
- /*creation_time=*/base::Time::Now(), permanent_specifics);
- tracker->Add(model->other_node(), kOtherBookmarksId, /*server_version=*/0,
- /*creation_time=*/base::Time::Now(), permanent_specifics);
- tracker->Add(model->mobile_node(), kMobileBookmarksId, /*server_version=*/0,
- /*creation_time=*/base::Time::Now(), permanent_specifics);
- ASSERT_FALSE(tracker->HasLocalChanges());
- // Simulate browser restart.
- tracker = SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- model.get(), tracker->BuildBookmarkModelMetadata());
- ASSERT_THAT(tracker, NotNull());
- EXPECT_FALSE(tracker->HasLocalChanges());
- EXPECT_EQ(4u, tracker->TrackedEntitiesCountForTest());
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldReportZeroIgnoredUpdateDueToMissingParentForNewTracker) {
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- EXPECT_THAT(tracker->GetNumIgnoredUpdatesDueToMissingParentForTest(), Eq(0));
- EXPECT_THAT(
- tracker->GetMaxVersionAmongIgnoredUpdatesDueToMissingParentForTest(),
- Eq(absl::nullopt));
- const sync_pb::BookmarkModelMetadata bookmark_model_metadata =
- tracker->BuildBookmarkModelMetadata();
- EXPECT_TRUE(
- bookmark_model_metadata.has_num_ignored_updates_due_to_missing_parent());
- EXPECT_THAT(
- bookmark_model_metadata.num_ignored_updates_due_to_missing_parent(),
- Eq(0));
- EXPECT_FALSE(
- bookmark_model_metadata
- .has_max_version_among_ignored_updates_due_to_missing_parent());
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldResetReuploadFlagOnDisabledFeatureToggle) {
- base::test::ScopedFeatureList override_features;
- override_features.InitAndDisableFeature(switches::kSyncReuploadBookmarks);
- const std::string kTitle = "Title";
- const GURL kUrl("http://www.foo.com");
- std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::ModelTypeState model_type_state;
- model_type_state.set_initial_sync_done(true);
- sync_pb::BookmarkModelMetadata initial_model_metadata =
- CreateMetadataForPermanentNodes(bookmark_model.get());
- initial_model_metadata.set_bookmarks_hierarchy_fields_reuploaded(true);
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- bookmark_model.get(), std::move(initial_model_metadata));
- ASSERT_THAT(tracker, NotNull());
- EXPECT_FALSE(tracker->BuildBookmarkModelMetadata()
- .bookmarks_hierarchy_fields_reuploaded());
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldRestoreZeroIgnoredUpdateDueToMissingParent) {
- std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::BookmarkModelMetadata bookmark_model_metadata =
- CreateMetadataForPermanentNodes(bookmark_model.get());
- bookmark_model_metadata.set_num_ignored_updates_due_to_missing_parent(0);
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- bookmark_model.get(), std::move(bookmark_model_metadata));
- ASSERT_THAT(tracker, NotNull());
- EXPECT_THAT(tracker->GetNumIgnoredUpdatesDueToMissingParentForTest(), Eq(0));
- EXPECT_THAT(
- tracker->GetMaxVersionAmongIgnoredUpdatesDueToMissingParentForTest(),
- Eq(absl::nullopt));
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldRestoreUnknownIgnoredUpdateDueToMissingParent) {
- std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::BookmarkModelMetadata bookmark_model_metadata =
- CreateMetadataForPermanentNodes(bookmark_model.get());
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- bookmark_model.get(), std::move(bookmark_model_metadata));
- ASSERT_THAT(tracker, NotNull());
- EXPECT_THAT(tracker->GetNumIgnoredUpdatesDueToMissingParentForTest(),
- Eq(absl::nullopt));
- EXPECT_THAT(
- tracker->GetMaxVersionAmongIgnoredUpdatesDueToMissingParentForTest(),
- Eq(absl::nullopt));
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldRestoreNonZeroIgnoredUpdateDueToMissingParent) {
- const int64_t kIgnoredUpdates = 7;
- const int64_t kServerVersion = 123;
- std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::BookmarkModelMetadata bookmark_model_metadata =
- CreateMetadataForPermanentNodes(bookmark_model.get());
- bookmark_model_metadata.set_num_ignored_updates_due_to_missing_parent(
- kIgnoredUpdates);
- bookmark_model_metadata
- .set_max_version_among_ignored_updates_due_to_missing_parent(
- kServerVersion);
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- bookmark_model.get(), std::move(bookmark_model_metadata));
- ASSERT_THAT(tracker, NotNull());
- EXPECT_THAT(tracker->GetNumIgnoredUpdatesDueToMissingParentForTest(),
- Eq(kIgnoredUpdates));
- EXPECT_THAT(
- tracker->GetMaxVersionAmongIgnoredUpdatesDueToMissingParentForTest(),
- Eq(kServerVersion));
- }
- TEST(SyncedBookmarkTrackerTest, ShouldRecordIgnoredUpdateDueToMissingParent) {
- const int64_t kServerVersion = 123;
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
- ASSERT_THAT(tracker->GetNumIgnoredUpdatesDueToMissingParentForTest(), Eq(0));
- ASSERT_THAT(
- tracker->GetMaxVersionAmongIgnoredUpdatesDueToMissingParentForTest(),
- Eq(absl::nullopt));
- tracker->RecordIgnoredServerUpdateDueToMissingParent(kServerVersion);
- EXPECT_THAT(tracker->GetNumIgnoredUpdatesDueToMissingParentForTest(), Eq(1));
- EXPECT_THAT(
- tracker->GetMaxVersionAmongIgnoredUpdatesDueToMissingParentForTest(),
- Eq(kServerVersion));
- const sync_pb::BookmarkModelMetadata bookmark_model_metadata =
- tracker->BuildBookmarkModelMetadata();
- EXPECT_THAT(
- bookmark_model_metadata.num_ignored_updates_due_to_missing_parent(),
- Eq(1));
- EXPECT_THAT(bookmark_model_metadata
- .max_version_among_ignored_updates_due_to_missing_parent(),
- Eq(kServerVersion));
- }
- TEST(SyncedBookmarkTrackerTest,
- ShouldPartiallyRecordIgnoredUpdateDueToMissingParentIfCounterUnknown) {
- const int64_t kServerVersion = 123;
- std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
- bookmarks::TestBookmarkClient::CreateModel();
- sync_pb::BookmarkModelMetadata bookmark_model_metadata =
- CreateMetadataForPermanentNodes(bookmark_model.get());
- std::unique_ptr<SyncedBookmarkTracker> tracker =
- SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
- bookmark_model.get(), std::move(bookmark_model_metadata));
- ASSERT_THAT(tracker, NotNull());
- ASSERT_THAT(tracker->GetNumIgnoredUpdatesDueToMissingParentForTest(),
- Eq(absl::nullopt));
- ASSERT_THAT(
- tracker->GetMaxVersionAmongIgnoredUpdatesDueToMissingParentForTest(),
- Eq(absl::nullopt));
- tracker->RecordIgnoredServerUpdateDueToMissingParent(kServerVersion);
- EXPECT_THAT(tracker->GetNumIgnoredUpdatesDueToMissingParentForTest(),
- Eq(absl::nullopt));
- EXPECT_THAT(
- tracker->GetMaxVersionAmongIgnoredUpdatesDueToMissingParentForTest(),
- Eq(kServerVersion));
- }
- } // namespace
- } // namespace sync_bookmarks
|