blob: 3002ca1bd6160c682bb0158560a966b3c5baec91 [file] [log] [blame]
Mohamed Amir Yosefb0664a82018-05-09 12:19:251// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/sync_bookmarks/synced_bookmark_tracker.h"
6
Mohamed Amir Yosefc80bdd02018-06-18 12:26:327#include "base/base64.h"
Pauline Leitao44f5a812019-07-30 10:49:518#include "base/guid.h"
Mohamed Amir Yosef74ec6ceca2018-07-20 15:21:229#include "base/strings/utf_string_conversions.h"
Mohamed Amir Yosef05fa2162018-11-09 22:42:2010#include "base/test/metrics/histogram_tester.h"
Mikel Astiz7eb326e2020-01-31 17:34:3911#include "base/test/scoped_feature_list.h"
Mohamed Amir Yosef74ec6ceca2018-07-20 15:21:2212#include "components/bookmarks/browser/bookmark_model.h"
Mohamed Amir Yosefb0664a82018-05-09 12:19:2513#include "components/bookmarks/browser/bookmark_node.h"
Mohamed Amir Yosefb6a54aa72018-11-09 13:34:0314#include "components/bookmarks/browser/bookmark_utils.h"
Mohamed Amir Yosef74ec6ceca2018-07-20 15:21:2215#include "components/bookmarks/test/test_bookmark_client.h"
Mohamed Amir Yosefc80bdd02018-06-18 12:26:3216#include "components/sync/base/time.h"
Mohamed Amir Yosefe1f51a22018-06-25 08:59:5717#include "components/sync/base/unique_position.h"
Mohamed Amir Yosefc80bdd02018-06-18 12:26:3218#include "components/sync/model/entity_data.h"
Mohamed Amir Yosefb0664a82018-05-09 12:19:2519#include "testing/gmock/include/gmock/gmock.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22using testing::Eq;
23using testing::IsNull;
24using testing::NotNull;
25
26namespace sync_bookmarks {
27
28namespace {
29
Mikel Astiz7eb326e2020-01-31 17:34:3930constexpr int kNumPermanentNodes = 3;
31
32const char kBookmarkBarId[] = "bookmark_bar_id";
33const char kMobileBookmarksId[] = "synced_bookmarks_id";
34const char kOtherBookmarksId[] = "other_bookmarks_id";
35
Mohamed Amir Yosef05fa2162018-11-09 22:42:2036// Redefinition of |enum CorruptionReason| in synced_bookmark_tracker.cc to be
37// used in tests.
38enum class ExpectedCorruptionReason {
39 NO_CORRUPTION = 0,
40 MISSING_SERVER_ID = 1,
41 BOOKMARK_ID_IN_TOMBSTONE = 2,
42 MISSING_BOOKMARK_ID = 3,
Mikel Astiz7eb326e2020-01-31 17:34:3943 DEPRECATED_COUNT_MISMATCH = 4,
44 DEPRECATED_IDS_MISMATCH = 5,
45 DUPLICATED_SERVER_ID = 6,
46 UNKNOWN_BOOKMARK_ID = 7,
47 UNTRACKED_BOOKMARK = 8,
48 BOOKMARK_GUID_MISMATCH = 9,
49 kMaxValue = BOOKMARK_GUID_MISMATCH
Mohamed Amir Yosef05fa2162018-11-09 22:42:2050};
51
Mohamed Amir Yosefc80bdd02018-06-18 12:26:3252sync_pb::EntitySpecifics GenerateSpecifics(const std::string& title,
53 const std::string& url) {
54 sync_pb::EntitySpecifics specifics;
Rushan Suleymanov09192192020-03-12 23:00:5955 specifics.mutable_bookmark()->set_legacy_canonicalized_title(title);
Mohamed Amir Yosefc80bdd02018-06-18 12:26:3256 specifics.mutable_bookmark()->set_url(url);
57 return specifics;
58}
59
Mikel Astiz7eb326e2020-01-31 17:34:3960sync_pb::BookmarkMetadata CreateNodeMetadata(int64_t node_id,
61 const std::string& server_id) {
62 sync_pb::BookmarkMetadata bookmark_metadata;
63 bookmark_metadata.set_id(node_id);
64 bookmark_metadata.mutable_metadata()->set_server_id(server_id);
65 return bookmark_metadata;
66}
67
68sync_pb::BookmarkMetadata CreateTombstoneMetadata(
69 const std::string& server_id) {
70 sync_pb::BookmarkMetadata bookmark_metadata;
71 bookmark_metadata.mutable_metadata()->set_server_id(server_id);
72 bookmark_metadata.mutable_metadata()->set_is_deleted(true);
73 return bookmark_metadata;
74}
75
76sync_pb::BookmarkModelMetadata CreateMetadataForPermanentNodes(
77 const bookmarks::BookmarkModel* bookmark_model) {
78 sync_pb::BookmarkModelMetadata model_metadata;
79 model_metadata.mutable_model_type_state()->set_initial_sync_done(true);
80
81 *model_metadata.add_bookmarks_metadata() =
82 CreateNodeMetadata(bookmark_model->bookmark_bar_node()->id(),
83 /*server_id=*/kBookmarkBarId);
84 *model_metadata.add_bookmarks_metadata() =
85 CreateNodeMetadata(bookmark_model->mobile_node()->id(),
86 /*server_id=*/kMobileBookmarksId);
87 *model_metadata.add_bookmarks_metadata() =
88 CreateNodeMetadata(bookmark_model->other_node()->id(),
89 /*server_id=*/kOtherBookmarksId);
90
91 CHECK_EQ(kNumPermanentNodes, model_metadata.bookmarks_metadata_size());
92 return model_metadata;
Mohamed Amir Yosef74ec6ceca2018-07-20 15:21:2293}
94
Mohamed Amir Yosefb0664a82018-05-09 12:19:2595TEST(SyncedBookmarkTrackerTest, ShouldGetAssociatedNodes) {
Mikel Astiz7eb326e2020-01-31 17:34:3996 std::unique_ptr<SyncedBookmarkTracker> tracker =
97 SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
98
Mohamed Amir Yosefb0664a82018-05-09 12:19:2599 const std::string kSyncId = "SYNC_ID";
Mohamed Amir Yosefc80bdd02018-06-18 12:26:32100 const std::string kTitle = "Title";
101 const GURL kUrl("http://www.foo.com");
Mohamed Amir Yosefb0664a82018-05-09 12:19:25102 const int64_t kId = 1;
Mohamed Amir Yosefc80bdd02018-06-18 12:26:32103 const int64_t kServerVersion = 1000;
104 const base::Time kCreationTime(base::Time::Now() -
105 base::TimeDelta::FromSeconds(1));
Mohamed Amir Yosefe1f51a22018-06-25 08:59:57106 const syncer::UniquePosition unique_position =
107 syncer::UniquePosition::InitialPosition(
108 syncer::UniquePosition::RandomSuffix());
Mohamed Amir Yosefc80bdd02018-06-18 12:26:32109 const sync_pb::EntitySpecifics specifics =
Mohamed Amir Yosef77ac6fbe2018-06-20 10:48:46110 GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
Mohamed Amir Yosefc80bdd02018-06-18 12:26:32111
Pauline Leitao44f5a812019-07-30 10:49:51112 bookmarks::BookmarkNode node(kId, base::GenerateGUID(), kUrl);
Mohamed Amir Yosefb0664a82018-05-09 12:19:25113 const SyncedBookmarkTracker::Entity* entity =
Mikel Astizf12d87912020-03-10 14:40:06114 tracker->Add(&node, kSyncId, kServerVersion, kCreationTime,
115 unique_position.ToProto(), specifics);
Mohamed Amir Yosefb0664a82018-05-09 12:19:25116 ASSERT_THAT(entity, NotNull());
117 EXPECT_THAT(entity->bookmark_node(), Eq(&node));
Mohamed Amir Yosefc80bdd02018-06-18 12:26:32118 EXPECT_THAT(entity->metadata()->server_id(), Eq(kSyncId));
119 EXPECT_THAT(entity->metadata()->server_version(), Eq(kServerVersion));
120 EXPECT_THAT(entity->metadata()->creation_time(),
121 Eq(syncer::TimeToProtoTime(kCreationTime)));
Mohamed Amir Yosefe1f51a22018-06-25 08:59:57122 EXPECT_TRUE(
123 syncer::UniquePosition::FromProto(entity->metadata()->unique_position())
124 .Equals(unique_position));
125
Mohamed Amir Yosefc80bdd02018-06-18 12:26:32126 syncer::EntityData data;
127 *data.specifics.mutable_bookmark() = specifics.bookmark();
Mohamed Amir Yosef812618f2018-07-26 13:25:49128 data.unique_position = unique_position.ToProto();
129 EXPECT_TRUE(entity->MatchesDataIgnoringParent(data));
Mikel Astiz7eb326e2020-01-31 17:34:39130 EXPECT_THAT(tracker->GetEntityForSyncId("unknown id"), IsNull());
Mohamed Amir Yosefb0664a82018-05-09 12:19:25131}
132
Mohamed Amir Yosefb2895112018-05-18 15:32:38133TEST(SyncedBookmarkTrackerTest, ShouldReturnNullForDisassociatedNodes) {
Mikel Astiz7eb326e2020-01-31 17:34:39134 std::unique_ptr<SyncedBookmarkTracker> tracker =
135 SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
136
Mohamed Amir Yosefb2895112018-05-18 15:32:38137 const std::string kSyncId = "SYNC_ID";
138 const int64_t kId = 1;
Mohamed Amir Yosefc80bdd02018-06-18 12:26:32139 const int64_t kServerVersion = 1000;
140 const base::Time kModificationTime(base::Time::Now() -
141 base::TimeDelta::FromSeconds(1));
Mohamed Amir Yosefe1f51a22018-06-25 08:59:57142 const sync_pb::UniquePosition unique_position;
Mohamed Amir Yosefc80bdd02018-06-18 12:26:32143 const sync_pb::EntitySpecifics specifics =
Mohamed Amir Yosef77ac6fbe2018-06-20 10:48:46144 GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
Pauline Leitao44f5a812019-07-30 10:49:51145 bookmarks::BookmarkNode node(kId, base::GenerateGUID(), GURL());
Mikel Astizf12d87912020-03-10 14:40:06146 const SyncedBookmarkTracker::Entity* entity =
147 tracker->Add(&node, kSyncId, kServerVersion, kModificationTime,
148 unique_position, specifics);
149 ASSERT_THAT(entity, NotNull());
150 ASSERT_THAT(tracker->GetEntityForSyncId(kSyncId), Eq(entity));
151 tracker->Remove(entity);
Mikel Astiz7eb326e2020-01-31 17:34:39152 EXPECT_THAT(tracker->GetEntityForSyncId(kSyncId), IsNull());
Mohamed Amir Yosefb2895112018-05-18 15:32:38153}
154
Mohamed Amir Yosefa0aa7ae82018-07-23 20:14:34155TEST(SyncedBookmarkTrackerTest, ShouldBuildBookmarkModelMetadata) {
Mikel Astiz7eb326e2020-01-31 17:34:39156 std::unique_ptr<SyncedBookmarkTracker> tracker =
157 SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
158
Mohamed Amir Yosefa0aa7ae82018-07-23 20:14:34159 const std::string kSyncId = "SYNC_ID";
160 const std::string kTitle = "Title";
161 const GURL kUrl("http://www.foo.com");
162 const int64_t kId = 1;
163 const int64_t kServerVersion = 1000;
164 const base::Time kCreationTime(base::Time::Now() -
165 base::TimeDelta::FromSeconds(1));
166 const syncer::UniquePosition unique_position =
167 syncer::UniquePosition::InitialPosition(
168 syncer::UniquePosition::RandomSuffix());
169 const sync_pb::EntitySpecifics specifics =
170 GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
171
Pauline Leitao44f5a812019-07-30 10:49:51172 bookmarks::BookmarkNode node(kId, base::GenerateGUID(), kUrl);
Mikel Astizf12d87912020-03-10 14:40:06173 tracker->Add(&node, kSyncId, kServerVersion, kCreationTime,
Mikel Astiz7eb326e2020-01-31 17:34:39174 unique_position.ToProto(), specifics);
Mohamed Amir Yosefa0aa7ae82018-07-23 20:14:34175
176 sync_pb::BookmarkModelMetadata bookmark_model_metadata =
Mikel Astiz7eb326e2020-01-31 17:34:39177 tracker->BuildBookmarkModelMetadata();
Mohamed Amir Yosefa0aa7ae82018-07-23 20:14:34178
179 ASSERT_THAT(bookmark_model_metadata.bookmarks_metadata().size(), Eq(1));
180 EXPECT_THAT(
181 bookmark_model_metadata.bookmarks_metadata(0).metadata().server_id(),
182 Eq(kSyncId));
183}
184
Mohamed Amir Yosef77ac6fbe2018-06-20 10:48:46185TEST(SyncedBookmarkTrackerTest,
186 ShouldRequireCommitRequestWhenSequenceNumberIsIncremented) {
Mikel Astiz7eb326e2020-01-31 17:34:39187 std::unique_ptr<SyncedBookmarkTracker> tracker =
188 SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
189
Mohamed Amir Yosef77ac6fbe2018-06-20 10:48:46190 const std::string kSyncId = "SYNC_ID";
191 const int64_t kId = 1;
192 const int64_t kServerVersion = 1000;
193 const base::Time kModificationTime(base::Time::Now() -
194 base::TimeDelta::FromSeconds(1));
Mohamed Amir Yosefe1f51a22018-06-25 08:59:57195 const sync_pb::UniquePosition unique_position;
Mohamed Amir Yosef77ac6fbe2018-06-20 10:48:46196 const sync_pb::EntitySpecifics specifics =
197 GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
Pauline Leitao44f5a812019-07-30 10:49:51198 bookmarks::BookmarkNode node(kId, base::GenerateGUID(), GURL());
Mikel Astizf12d87912020-03-10 14:40:06199 const SyncedBookmarkTracker::Entity* entity =
200 tracker->Add(&node, kSyncId, kServerVersion, kModificationTime,
201 unique_position, specifics);
Mohamed Amir Yosef77ac6fbe2018-06-20 10:48:46202
Mikel Astiz7eb326e2020-01-31 17:34:39203 EXPECT_THAT(tracker->HasLocalChanges(), Eq(false));
Mikel Astizf12d87912020-03-10 14:40:06204 tracker->IncrementSequenceNumber(entity);
Mikel Astiz7eb326e2020-01-31 17:34:39205 EXPECT_THAT(tracker->HasLocalChanges(), Eq(true));
Mohamed Amir Yosef77ac6fbe2018-06-20 10:48:46206 // TODO(crbug.com/516866): Test HasLocalChanges after submitting commit
207 // request in a separate test probably.
208}
209
Mohamed Amir Yosef88d36bf2018-08-06 18:03:48210TEST(SyncedBookmarkTrackerTest, ShouldAckSequenceNumber) {
Mikel Astiz7eb326e2020-01-31 17:34:39211 std::unique_ptr<SyncedBookmarkTracker> tracker =
212 SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
213
Mohamed Amir Yosef88d36bf2018-08-06 18:03:48214 const std::string kSyncId = "SYNC_ID";
215 const int64_t kId = 1;
216 const int64_t kServerVersion = 1000;
217 const base::Time kModificationTime(base::Time::Now() -
218 base::TimeDelta::FromSeconds(1));
219 const sync_pb::UniquePosition unique_position;
220 const sync_pb::EntitySpecifics specifics =
221 GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
Pauline Leitao44f5a812019-07-30 10:49:51222 bookmarks::BookmarkNode node(kId, base::GenerateGUID(), GURL());
Mikel Astizf12d87912020-03-10 14:40:06223 const SyncedBookmarkTracker::Entity* entity =
224 tracker->Add(&node, kSyncId, kServerVersion, kModificationTime,
225 unique_position, specifics);
Mohamed Amir Yosef88d36bf2018-08-06 18:03:48226
227 // Test simple scenario of ack'ing an incrememented sequence number.
Mikel Astiz7eb326e2020-01-31 17:34:39228 EXPECT_THAT(tracker->HasLocalChanges(), Eq(false));
Mikel Astizf12d87912020-03-10 14:40:06229 tracker->IncrementSequenceNumber(entity);
Mikel Astiz7eb326e2020-01-31 17:34:39230 EXPECT_THAT(tracker->HasLocalChanges(), Eq(true));
Mikel Astizf12d87912020-03-10 14:40:06231 tracker->AckSequenceNumber(entity);
Mikel Astiz7eb326e2020-01-31 17:34:39232 EXPECT_THAT(tracker->HasLocalChanges(), Eq(false));
Mohamed Amir Yosef88d36bf2018-08-06 18:03:48233
Mikel Astiz7eb326e2020-01-31 17:34:39234 // Test ack'ing of a multiple times incremented sequence number.
Mikel Astizf12d87912020-03-10 14:40:06235 tracker->IncrementSequenceNumber(entity);
Mikel Astiz7eb326e2020-01-31 17:34:39236 EXPECT_THAT(tracker->HasLocalChanges(), Eq(true));
Mikel Astizf12d87912020-03-10 14:40:06237 tracker->IncrementSequenceNumber(entity);
238 tracker->IncrementSequenceNumber(entity);
Mikel Astiz7eb326e2020-01-31 17:34:39239 EXPECT_THAT(tracker->HasLocalChanges(), Eq(true));
Mikel Astizf12d87912020-03-10 14:40:06240 tracker->AckSequenceNumber(entity);
Mikel Astiz7eb326e2020-01-31 17:34:39241 EXPECT_THAT(tracker->HasLocalChanges(), Eq(false));
Mohamed Amir Yosef88d36bf2018-08-06 18:03:48242}
243
Mohamed Amir Yosefc7097a12018-07-02 18:24:16244TEST(SyncedBookmarkTrackerTest, ShouldUpdateUponCommitResponseWithNewId) {
Mikel Astiz7eb326e2020-01-31 17:34:39245 std::unique_ptr<SyncedBookmarkTracker> tracker =
246 SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
247
Mohamed Amir Yosefc7097a12018-07-02 18:24:16248 const std::string kSyncId = "SYNC_ID";
249 const std::string kNewSyncId = "NEW_SYNC_ID";
250 const int64_t kId = 1;
251 const int64_t kServerVersion = 1000;
252 const int64_t kNewServerVersion = 1001;
253 const base::Time kModificationTime(base::Time::Now() -
254 base::TimeDelta::FromSeconds(1));
255 const sync_pb::UniquePosition unique_position;
256 const sync_pb::EntitySpecifics specifics =
257 GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
Pauline Leitao44f5a812019-07-30 10:49:51258 bookmarks::BookmarkNode node(kId, base::GenerateGUID(), GURL());
Mohamed Amir Yosefc7097a12018-07-02 18:24:16259 const SyncedBookmarkTracker::Entity* entity =
Mikel Astizf12d87912020-03-10 14:40:06260 tracker->Add(&node, kSyncId, kServerVersion, kModificationTime,
261 unique_position, specifics);
Mohamed Amir Yosefc7097a12018-07-02 18:24:16262 ASSERT_THAT(entity, NotNull());
Mikel Astizf12d87912020-03-10 14:40:06263
264 // Initially only the old ID should be tracked.
265 ASSERT_THAT(tracker->GetEntityForSyncId(kSyncId), Eq(entity));
266 ASSERT_THAT(tracker->GetEntityForSyncId(kNewSyncId), IsNull());
267
268 // Receive a commit response with a changed id.
269 tracker->UpdateUponCommitResponse(entity, kNewSyncId, kNewServerVersion,
270 /*acked_sequence_number=*/1);
271
272 // Old id shouldn't be there, but the new one should.
273 EXPECT_THAT(tracker->GetEntityForSyncId(kSyncId), IsNull());
274 EXPECT_THAT(tracker->GetEntityForSyncId(kNewSyncId), Eq(entity));
275
Mohamed Amir Yosefc7097a12018-07-02 18:24:16276 EXPECT_THAT(entity->metadata()->server_id(), Eq(kNewSyncId));
277 EXPECT_THAT(entity->bookmark_node(), Eq(&node));
278 EXPECT_THAT(entity->metadata()->server_version(), Eq(kNewServerVersion));
279}
280
Mohamed Amir Yosefbc7cbfb2018-10-16 10:39:45281TEST(SyncedBookmarkTrackerTest, ShouldUpdateId) {
Mikel Astiz7eb326e2020-01-31 17:34:39282 std::unique_ptr<SyncedBookmarkTracker> tracker =
283 SyncedBookmarkTracker::CreateEmpty(sync_pb::ModelTypeState());
284
Mohamed Amir Yosefbc7cbfb2018-10-16 10:39:45285 const std::string kSyncId = "SYNC_ID";
286 const std::string kNewSyncId = "NEW_SYNC_ID";
287 const int64_t kServerVersion = 1000;
288 const base::Time kModificationTime(base::Time::Now() -
289 base::TimeDelta::FromSeconds(1));
290 const sync_pb::UniquePosition unique_position;
291 const sync_pb::EntitySpecifics specifics =
292 GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
Pauline Leitao44f5a812019-07-30 10:49:51293 bookmarks::BookmarkNode node(/*id=*/1, base::GenerateGUID(), GURL());
Mohamed Amir Yosefbc7cbfb2018-10-16 10:39:45294 // Track a sync entity.
Mohamed Amir Yosefbc7cbfb2018-10-16 10:39:45295 const SyncedBookmarkTracker::Entity* entity =
Mikel Astizf12d87912020-03-10 14:40:06296 tracker->Add(&node, kSyncId, kServerVersion, kModificationTime,
297 unique_position, specifics);
298
Mohamed Amir Yosefbc7cbfb2018-10-16 10:39:45299 ASSERT_THAT(entity, NotNull());
Mikel Astizf12d87912020-03-10 14:40:06300 // Update the sync id.
301 tracker->UpdateSyncIdForLocalCreationIfNeeded(entity, kNewSyncId);
302
303 // Old id shouldn't be there, but the new one should.
304 EXPECT_THAT(tracker->GetEntityForSyncId(kSyncId), IsNull());
305 EXPECT_THAT(tracker->GetEntityForSyncId(kNewSyncId), Eq(entity));
306
Mohamed Amir Yosefbc7cbfb2018-10-16 10:39:45307 EXPECT_THAT(entity->metadata()->server_id(), Eq(kNewSyncId));
308 EXPECT_THAT(entity->bookmark_node(), Eq(&node));
309 EXPECT_THAT(entity->metadata()->server_version(), Eq(kServerVersion));
310}
311
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51312TEST(SyncedBookmarkTrackerTest,
313 ShouldMaintainTombstoneOrderBetweenCtorAndBuildBookmarkModelMetadata) {
314 // Feed a metadata batch of 5 entries to the constructor of the tracker.
315 // First 2 are for node, and the last 4 are for tombstones.
316
317 // Server ids.
318 const std::string kId0 = "id0";
319 const std::string kId1 = "id1";
320 const std::string kId2 = "id2";
321 const std::string kId3 = "id3";
322 const std::string kId4 = "id4";
323
Mikel Astiz7eb326e2020-01-31 17:34:39324 std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
325 bookmarks::TestBookmarkClient::CreateModel();
326 const bookmarks::BookmarkNode* bookmark_bar_node =
327 bookmark_model->bookmark_bar_node();
328 const bookmarks::BookmarkNode* node0 = bookmark_model->AddFolder(
329 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node0"));
330 const bookmarks::BookmarkNode* node1 = bookmark_model->AddFolder(
331 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node1"));
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51332
Mikel Astiz7eb326e2020-01-31 17:34:39333 sync_pb::BookmarkModelMetadata initial_model_metadata =
334 CreateMetadataForPermanentNodes(bookmark_model.get());
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51335
Mikel Astiz7eb326e2020-01-31 17:34:39336 *initial_model_metadata.add_bookmarks_metadata() =
337 CreateNodeMetadata(node0->id(), /*server_id=*/kId0);
338 *initial_model_metadata.add_bookmarks_metadata() =
339 CreateNodeMetadata(node1->id(), /*server_id=*/kId1);
340 *initial_model_metadata.add_bookmarks_metadata() =
341 CreateTombstoneMetadata(/*server_id=*/kId2);
342 *initial_model_metadata.add_bookmarks_metadata() =
343 CreateTombstoneMetadata(/*server_id=*/kId3);
344 *initial_model_metadata.add_bookmarks_metadata() =
345 CreateTombstoneMetadata(/*server_id=*/kId4);
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51346
Mikel Astiz7eb326e2020-01-31 17:34:39347 std::unique_ptr<SyncedBookmarkTracker> tracker =
348 SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
349 bookmark_model.get(), std::move(initial_model_metadata));
350 ASSERT_THAT(tracker, NotNull());
351
352 const sync_pb::BookmarkModelMetadata output_model_metadata =
353 tracker->BuildBookmarkModelMetadata();
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51354
355 // Tombstones should be the last 3 entries in the metadata and in the same
356 // order as given to the constructor.
Mikel Astiz7eb326e2020-01-31 17:34:39357 ASSERT_THAT(output_model_metadata.bookmarks_metadata().size(),
358 Eq(kNumPermanentNodes + 5));
359 EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 2)
360 .metadata()
361 .server_id(),
362 Eq(kId2));
363 EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 3)
364 .metadata()
365 .server_id(),
366 Eq(kId3));
367 EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 4)
368 .metadata()
369 .server_id(),
370 Eq(kId4));
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51371}
372
373TEST(SyncedBookmarkTrackerTest,
374 ShouldMaintainOrderOfMarkDeletedCallsWhenBuildBookmarkModelMetadata) {
375 // Server ids.
376 const std::string kId0 = "id0";
377 const std::string kId1 = "id1";
378 const std::string kId2 = "id2";
379 const std::string kId3 = "id3";
380 const std::string kId4 = "id4";
381
Mikel Astiz7eb326e2020-01-31 17:34:39382 std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
383 bookmarks::TestBookmarkClient::CreateModel();
384 const bookmarks::BookmarkNode* bookmark_bar_node =
385 bookmark_model->bookmark_bar_node();
386 const bookmarks::BookmarkNode* node0 = bookmark_model->AddFolder(
387 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node0"));
388 const bookmarks::BookmarkNode* node1 = bookmark_model->AddFolder(
389 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node1"));
390 const bookmarks::BookmarkNode* node2 = bookmark_model->AddFolder(
391 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node2"));
392 const bookmarks::BookmarkNode* node3 = bookmark_model->AddFolder(
393 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node3"));
394 const bookmarks::BookmarkNode* node4 = bookmark_model->AddFolder(
395 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node4"));
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51396
Mikel Astiz7eb326e2020-01-31 17:34:39397 sync_pb::BookmarkModelMetadata initial_model_metadata =
398 CreateMetadataForPermanentNodes(bookmark_model.get());
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51399
Mikel Astiz7eb326e2020-01-31 17:34:39400 *initial_model_metadata.add_bookmarks_metadata() =
401 CreateNodeMetadata(node0->id(), /*server_id=*/kId0);
402 *initial_model_metadata.add_bookmarks_metadata() =
403 CreateNodeMetadata(node1->id(), /*server_id=*/kId1);
404 *initial_model_metadata.add_bookmarks_metadata() =
405 CreateNodeMetadata(node2->id(), /*server_id=*/kId2);
406 *initial_model_metadata.add_bookmarks_metadata() =
407 CreateNodeMetadata(node3->id(), /*server_id=*/kId3);
408 *initial_model_metadata.add_bookmarks_metadata() =
409 CreateNodeMetadata(node4->id(), /*server_id=*/kId4);
410
411 std::unique_ptr<SyncedBookmarkTracker> tracker =
412 SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
413 bookmark_model.get(), std::move(initial_model_metadata));
414 ASSERT_THAT(tracker, NotNull());
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51415
416 // Mark entities deleted in that order kId2, kId4, kId1
Mikel Astizf12d87912020-03-10 14:40:06417 tracker->MarkDeleted(tracker->GetEntityForSyncId(kId2));
418 tracker->MarkDeleted(tracker->GetEntityForSyncId(kId4));
419 tracker->MarkDeleted(tracker->GetEntityForSyncId(kId1));
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51420
Mikel Astiz7eb326e2020-01-31 17:34:39421 const sync_pb::BookmarkModelMetadata output_model_metadata =
422 tracker->BuildBookmarkModelMetadata();
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51423
424 // Tombstones should be the last 3 entries in the metadata and in the same as
425 // calling MarkDeleted().
Mikel Astiz7eb326e2020-01-31 17:34:39426 ASSERT_THAT(output_model_metadata.bookmarks_metadata().size(),
427 Eq(kNumPermanentNodes + 5));
428 EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 2)
429 .metadata()
430 .server_id(),
431 Eq(kId2));
432 EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 3)
433 .metadata()
434 .server_id(),
435 Eq(kId4));
436 EXPECT_THAT(output_model_metadata.bookmarks_metadata(kNumPermanentNodes + 4)
437 .metadata()
438 .server_id(),
439 Eq(kId1));
Mohamed Amir Yosef3fd347d2018-07-18 13:37:51440}
441
Mohamed Amir Yosef74ec6ceca2018-07-20 15:21:22442TEST(SyncedBookmarkTrackerTest,
443 ShouldOrderParentUpdatesBeforeChildUpdatesAndDeletionsComeLast) {
444 const size_t kMaxEntries = 1000;
445
446 // Construct this structure:
447 // bookmark_bar
448 // |- node0
449 // |- node1
450 // |- node2
451
452 std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
453 bookmarks::TestBookmarkClient::CreateModel();
454
455 const bookmarks::BookmarkNode* bookmark_bar_node =
456 bookmark_model->bookmark_bar_node();
457 const bookmarks::BookmarkNode* node0 = bookmark_model->AddFolder(
458 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node0"));
459 const bookmarks::BookmarkNode* node1 = bookmark_model->AddFolder(
460 /*parent=*/node0, /*index=*/0, base::UTF8ToUTF16("node1"));
461 const bookmarks::BookmarkNode* node2 = bookmark_model->AddFolder(
462 /*parent=*/node1, /*index=*/0, base::UTF8ToUTF16("node2"));
463
464 // Server ids.
465 const std::string kId0 = "id0";
466 const std::string kId1 = "id1";
467 const std::string kId2 = "id2";
468 const std::string kId3 = "id3";
469
470 // Prepare the metadata with shuffled order.
Mikel Astiz7eb326e2020-01-31 17:34:39471 sync_pb::BookmarkModelMetadata model_metadata =
472 CreateMetadataForPermanentNodes(bookmark_model.get());
Mohamed Amir Yosef74ec6ceca2018-07-20 15:21:22473
Mikel Astiz7eb326e2020-01-31 17:34:39474 *model_metadata.add_bookmarks_metadata() =
475 CreateNodeMetadata(node1->id(), /*server_id=*/kId1);
476 *model_metadata.add_bookmarks_metadata() =
477 CreateTombstoneMetadata(/*server_id=*/kId3);
478 *model_metadata.add_bookmarks_metadata() =
479 CreateNodeMetadata(node2->id(), /*server_id=*/kId2);
480 *model_metadata.add_bookmarks_metadata() =
481 CreateNodeMetadata(node0->id(), /*server_id=*/kId0);
482
483 std::unique_ptr<SyncedBookmarkTracker> tracker =
484 SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
485 bookmark_model.get(), std::move(model_metadata));
486 ASSERT_THAT(tracker, NotNull());
Mohamed Amir Yosef74ec6ceca2018-07-20 15:21:22487
488 // Mark the entities that they have local changes. (in shuffled order just to
489 // verify the tracker doesn't simply maintain the order of updates similar to
490 // with deletions).
Mikel Astizf12d87912020-03-10 14:40:06491 tracker->IncrementSequenceNumber(tracker->GetEntityForSyncId(kId3));
492 tracker->IncrementSequenceNumber(tracker->GetEntityForSyncId(kId1));
493 tracker->IncrementSequenceNumber(tracker->GetEntityForSyncId(kId2));
494 tracker->IncrementSequenceNumber(tracker->GetEntityForSyncId(kId0));
Mohamed Amir Yosef74ec6ceca2018-07-20 15:21:22495
496 std::vector<const SyncedBookmarkTracker::Entity*> entities_with_local_change =
Mikel Astiz7eb326e2020-01-31 17:34:39497 tracker->GetEntitiesWithLocalChanges(kMaxEntries);
Mohamed Amir Yosef74ec6ceca2018-07-20 15:21:22498
499 ASSERT_THAT(entities_with_local_change.size(), Eq(4U));
500 // Verify updates are in parent before child order node0 --> node1 --> node2.
501 EXPECT_THAT(entities_with_local_change[0]->metadata()->server_id(), Eq(kId0));
502 EXPECT_THAT(entities_with_local_change[1]->metadata()->server_id(), Eq(kId1));
503 EXPECT_THAT(entities_with_local_change[2]->metadata()->server_id(), Eq(kId2));
504 // Verify that deletion is the last entry.
505 EXPECT_THAT(entities_with_local_change[3]->metadata()->server_id(), Eq(kId3));
506}
507
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17508TEST(SyncedBookmarkTrackerTest, ShouldMatchModelAndMetadata) {
509 std::unique_ptr<bookmarks::BookmarkModel> model =
510 bookmarks::TestBookmarkClient::CreateModel();
511
512 const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
513 const bookmarks::BookmarkNode* node = model->AddFolder(
514 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node0"));
515
Mikel Astiz7eb326e2020-01-31 17:34:39516 sync_pb::BookmarkModelMetadata model_metadata =
517 CreateMetadataForPermanentNodes(model.get());
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17518
Mohamed Amir Yoseffb617fde2019-07-16 09:08:54519 // Add entry for the managed node.
Mikel Astiz7eb326e2020-01-31 17:34:39520 *model_metadata.add_bookmarks_metadata() =
521 CreateNodeMetadata(node->id(), /*server_id=*/"NodeId");
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17522
523 // Add a tombstone entry.
Mikel Astiz7eb326e2020-01-31 17:34:39524 *model_metadata.add_bookmarks_metadata() =
525 CreateTombstoneMetadata(/*server_id=*/"tombstoneId");
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17526
Mohamed Amir Yosef05fa2162018-11-09 22:42:20527 base::HistogramTester histogram_tester;
Mikel Astiz7eb326e2020-01-31 17:34:39528
529 EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
530 model.get(), std::move(model_metadata)),
531 NotNull());
532
Mohamed Amir Yosef05fa2162018-11-09 22:42:20533 histogram_tester.ExpectUniqueSample(
534 "Sync.BookmarksModelMetadataCorruptionReason",
535 /*sample=*/ExpectedCorruptionReason::NO_CORRUPTION, /*count=*/1);
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17536}
537
Mohamed Amir Yosefb1117f742018-11-12 13:29:01538TEST(SyncedBookmarkTrackerTest,
Mikel Astiz113dc1e2018-12-18 16:58:47539 ShouldNotMatchModelAndMetadataIfMissingMobileFolder) {
Mohamed Amir Yosefb1117f742018-11-12 13:29:01540 std::unique_ptr<bookmarks::BookmarkModel> model =
541 bookmarks::TestBookmarkClient::CreateModel();
542
543 sync_pb::BookmarkModelMetadata model_metadata;
544 model_metadata.mutable_model_type_state()->set_initial_sync_done(true);
Mikel Astiz7eb326e2020-01-31 17:34:39545
Mohamed Amir Yosefb1117f742018-11-12 13:29:01546 // Add entries for all the permanent nodes except for the Mobile bookmarks
Mikel Astiz113dc1e2018-12-18 16:58:47547 // folder.
Mikel Astiz7eb326e2020-01-31 17:34:39548 *model_metadata.add_bookmarks_metadata() =
549 CreateNodeMetadata(model->bookmark_bar_node()->id(),
550 /*server_id=*/kBookmarkBarId);
551 *model_metadata.add_bookmarks_metadata() =
552 CreateNodeMetadata(model->other_node()->id(),
553 /*server_id=*/kOtherBookmarksId);
Mohamed Amir Yosefb1117f742018-11-12 13:29:01554
555 base::HistogramTester histogram_tester;
Mikel Astiz7eb326e2020-01-31 17:34:39556
557 EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
558 model.get(), std::move(model_metadata)),
559 IsNull());
560
Mohamed Amir Yosefb1117f742018-11-12 13:29:01561 histogram_tester.ExpectUniqueSample(
562 "Sync.BookmarksModelMetadataCorruptionReason",
Mikel Astiz7eb326e2020-01-31 17:34:39563 /*sample=*/ExpectedCorruptionReason::UNTRACKED_BOOKMARK, /*count=*/1);
Mohamed Amir Yosefb1117f742018-11-12 13:29:01564}
565
Mikel Astiz7eb326e2020-01-31 17:34:39566TEST(SyncedBookmarkTrackerTest,
567 ShouldNotMatchModelAndMetadataIfMissingServerId) {
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17568 std::unique_ptr<bookmarks::BookmarkModel> model =
569 bookmarks::TestBookmarkClient::CreateModel();
570
Mikel Astiz7eb326e2020-01-31 17:34:39571 sync_pb::BookmarkModelMetadata model_metadata =
572 CreateMetadataForPermanentNodes(model.get());
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17573
Mikel Astiz7eb326e2020-01-31 17:34:39574 // Remove a server ID to a permanent node.
575 model_metadata.mutable_bookmarks_metadata(0)
576 ->mutable_metadata()
577 ->clear_server_id();
Mikel Astiz113dc1e2018-12-18 16:58:47578
Mohamed Amir Yosef05fa2162018-11-09 22:42:20579 base::HistogramTester histogram_tester;
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17580
Mikel Astiz7eb326e2020-01-31 17:34:39581 EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
582 model.get(), std::move(model_metadata)),
583 IsNull());
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17584
Mikel Astiz7eb326e2020-01-31 17:34:39585 histogram_tester.ExpectUniqueSample(
Mohamed Amir Yosef05fa2162018-11-09 22:42:20586 "Sync.BookmarksModelMetadataCorruptionReason",
587 /*sample=*/ExpectedCorruptionReason::MISSING_SERVER_ID, /*count=*/1);
Mikel Astiz7eb326e2020-01-31 17:34:39588}
Mohamed Amir Yosef05fa2162018-11-09 22:42:20589
Mikel Astiz7eb326e2020-01-31 17:34:39590TEST(SyncedBookmarkTrackerTest,
591 ShouldNotMatchModelAndMetadataIfMissingLocalBookmarkId) {
592 std::unique_ptr<bookmarks::BookmarkModel> model =
593 bookmarks::TestBookmarkClient::CreateModel();
594
595 sync_pb::BookmarkModelMetadata model_metadata =
596 CreateMetadataForPermanentNodes(model.get());
597
598 const bookmarks::BookmarkNode* node = model->AddFolder(
599 /*parent=*/model->bookmark_bar_node(), /*index=*/0,
600 base::UTF8ToUTF16("node"));
601 *model_metadata.add_bookmarks_metadata() =
602 CreateNodeMetadata(node->id(), /*server_id=*/"serverid");
603
604 // Remove the local bookmark ID.
605 model_metadata.mutable_bookmarks_metadata()->rbegin()->clear_id();
606
607 base::HistogramTester histogram_tester;
608
609 EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
610 model.get(), std::move(model_metadata)),
611 IsNull());
612
613 histogram_tester.ExpectUniqueSample(
Mohamed Amir Yosef05fa2162018-11-09 22:42:20614 "Sync.BookmarksModelMetadataCorruptionReason",
615 /*sample=*/ExpectedCorruptionReason::MISSING_BOOKMARK_ID, /*count=*/1);
Mikel Astiz7eb326e2020-01-31 17:34:39616}
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17617
Mikel Astiz7eb326e2020-01-31 17:34:39618TEST(SyncedBookmarkTrackerTest,
619 ShouldNotMatchModelAndMetadataIfTombstoneHasBookmarkId) {
620 std::unique_ptr<bookmarks::BookmarkModel> model =
621 bookmarks::TestBookmarkClient::CreateModel();
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17622
Mikel Astiz7eb326e2020-01-31 17:34:39623 sync_pb::BookmarkModelMetadata model_metadata =
624 CreateMetadataForPermanentNodes(model.get());
625
626 *model_metadata.add_bookmarks_metadata() =
627 CreateTombstoneMetadata(/*server_id=*/"serverid");
628
629 // Add a node ID to the tombstone.
630 model_metadata.mutable_bookmarks_metadata()->rbegin()->set_id(1234);
631
632 base::HistogramTester histogram_tester;
633
634 EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
635 model.get(), std::move(model_metadata)),
636 IsNull());
637
638 histogram_tester.ExpectUniqueSample(
Mohamed Amir Yosef05fa2162018-11-09 22:42:20639 "Sync.BookmarksModelMetadataCorruptionReason",
640 /*sample=*/ExpectedCorruptionReason::BOOKMARK_ID_IN_TOMBSTONE,
641 /*count=*/1);
Mohamed Amir Yoseffb7986d882018-10-12 05:42:17642}
643
Mohamed Amir Yosefb6a54aa72018-11-09 13:34:03644TEST(SyncedBookmarkTrackerTest,
Mikel Astiz7eb326e2020-01-31 17:34:39645 ShouldNotMatchModelAndMetadataIfUnknownLocalBookmarkId) {
646 std::unique_ptr<bookmarks::BookmarkModel> model =
647 bookmarks::TestBookmarkClient::CreateModel();
648
649 sync_pb::BookmarkModelMetadata model_metadata =
650 CreateMetadataForPermanentNodes(model.get());
651
652 const bookmarks::BookmarkNode* node = model->AddFolder(
653 /*parent=*/model->bookmark_bar_node(), /*index=*/0,
654 base::UTF8ToUTF16("node"));
655 *model_metadata.add_bookmarks_metadata() =
656 CreateNodeMetadata(node->id(), /*server_id=*/"serverid");
657
658 // Set an arbitrary local node ID that won't match anything in BookmarkModel.
659 model_metadata.mutable_bookmarks_metadata()->rbegin()->set_id(123456);
660
661 base::HistogramTester histogram_tester;
662
663 EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
664 model.get(), std::move(model_metadata)),
665 IsNull());
666
667 histogram_tester.ExpectUniqueSample(
668 "Sync.BookmarksModelMetadataCorruptionReason",
669 /*sample=*/ExpectedCorruptionReason::UNKNOWN_BOOKMARK_ID,
670 /*count=*/1);
671}
672
673TEST(SyncedBookmarkTrackerTest, ShouldNotMatchModelAndMetadataIfGuidMismatch) {
674 base::test::ScopedFeatureList override_features;
675 override_features.InitAndEnableFeature(
676 kInvalidateBookmarkSyncMetadataIfMismatchingGuid);
677
678 std::unique_ptr<bookmarks::BookmarkModel> model =
679 bookmarks::TestBookmarkClient::CreateModel();
680
681 const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
682 const bookmarks::BookmarkNode* node0 = model->AddFolder(
683 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node0"));
684
685 sync_pb::BookmarkModelMetadata model_metadata =
686 CreateMetadataForPermanentNodes(model.get());
687 sync_pb::BookmarkMetadata* node0_metadata =
688 model_metadata.add_bookmarks_metadata();
689 *node0_metadata = CreateNodeMetadata(node0->id(), /*server_id=*/"id0");
690
691 // Set a mismatching client tag hash.
692 node0_metadata->mutable_metadata()->set_client_tag_hash("corrupthash");
693
694 base::HistogramTester histogram_tester;
695
696 EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
697 model.get(), std::move(model_metadata)),
698 IsNull());
699
700 histogram_tester.ExpectUniqueSample(
701 "Sync.BookmarksModelMetadataCorruptionReason",
702 /*sample=*/ExpectedCorruptionReason::BOOKMARK_GUID_MISMATCH, /*count=*/1);
703}
704
705TEST(SyncedBookmarkTrackerTest,
706 ShouldMatchModelAndMetadataDespiteGuidMismatch) {
707 base::test::ScopedFeatureList override_features;
708 override_features.InitAndDisableFeature(
709 kInvalidateBookmarkSyncMetadataIfMismatchingGuid);
710
711 std::unique_ptr<bookmarks::BookmarkModel> model =
712 bookmarks::TestBookmarkClient::CreateModel();
713
714 const bookmarks::BookmarkNode* bookmark_bar_node = model->bookmark_bar_node();
715 const bookmarks::BookmarkNode* node0 = model->AddFolder(
716 /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16("node0"));
717
718 sync_pb::BookmarkModelMetadata model_metadata =
719 CreateMetadataForPermanentNodes(model.get());
720 sync_pb::BookmarkMetadata* node0_metadata =
721 model_metadata.add_bookmarks_metadata();
722 *node0_metadata = CreateNodeMetadata(node0->id(), /*server_id=*/"id0");
723
724 // Set a mismatching client tag hash.
725 node0_metadata->mutable_metadata()->set_client_tag_hash("corrupthash");
726
727 base::HistogramTester histogram_tester;
728
729 EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
730 model.get(), std::move(model_metadata)),
731 NotNull());
732
733 histogram_tester.ExpectUniqueSample(
734 "Sync.BookmarkModelMetadataClientTagState",
735 /*sample=*/0, /*count=*/1);
736}
737
738TEST(SyncedBookmarkTrackerTest,
Mohamed Amir Yosefb6a54aa72018-11-09 13:34:03739 ShouldMatchModelWithUnsyncableNodesAndMetadata) {
740 // Add a managed node with an arbitrary id 100.
741 const int64_t kManagedNodeId = 100;
Mohamed Amir Yoseffb617fde2019-07-16 09:08:54742 auto owned_managed_node = std::make_unique<bookmarks::BookmarkPermanentNode>(
Pauline Leitao91f0b53a2019-07-09 10:13:54743 kManagedNodeId, bookmarks::BookmarkNode::FOLDER);
Mohamed Amir Yosefb6a54aa72018-11-09 13:34:03744 auto client = std::make_unique<bookmarks::TestBookmarkClient>();
Mikel Astizf50a3272020-03-12 08:07:00745 bookmarks::BookmarkNode* managed_node = client->EnableManagedNode();
Mohamed Amir Yosefb6a54aa72018-11-09 13:34:03746
747 std::unique_ptr<bookmarks::BookmarkModel> model =
748 bookmarks::TestBookmarkClient::CreateModelWithClient(std::move(client));
749
750 // The model should contain the managed node now.
Mohamed Amir Yoseffb617fde2019-07-16 09:08:54751 ASSERT_THAT(GetBookmarkNodeByID(model.get(), kManagedNodeId),
752 Eq(managed_node));
Mohamed Amir Yosefb6a54aa72018-11-09 13:34:03753
Mohamed Amir Yosefb6a54aa72018-11-09 13:34:03754 // Add entries for all the permanent nodes. TestBookmarkClient creates all the
755 // 3 permanent nodes.
Mikel Astiz7eb326e2020-01-31 17:34:39756 sync_pb::BookmarkModelMetadata model_metadata =
757 CreateMetadataForPermanentNodes(model.get());
Mohamed Amir Yosefb6a54aa72018-11-09 13:34:03758
Mohamed Amir Yosef05fa2162018-11-09 22:42:20759 base::HistogramTester histogram_tester;
Mikel Astiz7eb326e2020-01-31 17:34:39760 EXPECT_THAT(SyncedBookmarkTracker::CreateFromBookmarkModelAndMetadata(
761 model.get(), std::move(model_metadata)),
762 NotNull());
Mohamed Amir Yosef05fa2162018-11-09 22:42:20763 histogram_tester.ExpectUniqueSample(
764 "Sync.BookmarksModelMetadataCorruptionReason",
765 /*sample=*/ExpectedCorruptionReason::NO_CORRUPTION, /*count=*/1);
Mohamed Amir Yosefb6a54aa72018-11-09 13:34:03766}
767
Mohamed Amir Yosefb0664a82018-05-09 12:19:25768} // namespace
769
770} // namespace sync_bookmarks