blob: 3c25d34bc887180619b7c8511e63fe545f301ef6 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/sync_bookmarks/parent_guid_preprocessing.h"
#include <memory>
#include "base/uuid.h"
#include "components/bookmarks/browser/bookmark_node.h"
#include "components/bookmarks/browser/bookmark_uuids.h"
#include "components/sync/protocol/bookmark_specifics.pb.h"
#include "components/sync/protocol/data_type_state.pb.h"
#include "components/sync/protocol/entity_data.h"
#include "components/sync/protocol/entity_specifics.pb.h"
#include "components/sync_bookmarks/bookmark_model_view.h"
#include "components/sync_bookmarks/synced_bookmark_tracker.h"
#include "components/sync_bookmarks/test_bookmark_model_view.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace sync_bookmarks {
namespace {
using testing::Eq;
TEST(ParentGuidPreprocessingTest, ShouldReturnGuidForSyncIdIncludedInUpdates) {
const std::string kId1 = "sync_id1";
const std::string kId2 = "sync_id2";
const std::string kGuid1 = "guid1";
const std::string kGuid2 = "guid2";
syncer::UpdateResponseDataList updates;
updates.emplace_back();
updates.back().entity.id = kId1;
updates.back().entity.specifics.mutable_bookmark()->set_guid(kGuid1);
updates.emplace_back();
updates.back().entity.id = kId2;
updates.back().entity.specifics.mutable_bookmark()->set_guid(kGuid2);
EXPECT_THAT(GetGuidForSyncIdInUpdatesForTesting(updates, kId1), Eq(kGuid1));
EXPECT_THAT(GetGuidForSyncIdInUpdatesForTesting(updates, kId2), Eq(kGuid2));
}
TEST(ParentGuidPreprocessingTest,
ShouldReturnInvalidGuidForSyncIdMissingInUpdates) {
const std::string kId1 = "sync_id1";
const std::string kGuid1 = "guid1";
syncer::UpdateResponseDataList updates;
EXPECT_THAT(GetGuidForSyncIdInUpdatesForTesting(updates, "missing_id"),
Eq(""));
updates.emplace_back();
updates.back().entity.id = kId1;
updates.back().entity.specifics.mutable_bookmark()->set_guid(kGuid1);
ASSERT_THAT(GetGuidForSyncIdInUpdatesForTesting(updates, kId1), Eq(kGuid1));
EXPECT_THAT(GetGuidForSyncIdInUpdatesForTesting(updates, "missing_id"),
Eq(""));
}
TEST(ParentGuidPreprocessingTest, ShouldReturnGuidForPermanentFolders) {
const std::string kBookmarkBarId = "id1";
const std::string kMobileBookmarksId = "id2";
const std::string kOtherBookmarksId = "id3";
// Permanent folders may not include their GUIDs.
syncer::UpdateResponseDataList updates;
updates.emplace_back();
updates.back().entity.id = kBookmarkBarId;
updates.back().entity.server_defined_unique_tag = "bookmark_bar";
updates.emplace_back();
updates.back().entity.id = kMobileBookmarksId;
updates.back().entity.server_defined_unique_tag = "synced_bookmarks";
updates.emplace_back();
updates.back().entity.id = kOtherBookmarksId;
updates.back().entity.server_defined_unique_tag = "other_bookmarks";
EXPECT_THAT(GetGuidForSyncIdInUpdatesForTesting(updates, kBookmarkBarId),
Eq(bookmarks::kBookmarkBarNodeUuid));
EXPECT_THAT(GetGuidForSyncIdInUpdatesForTesting(updates, kMobileBookmarksId),
Eq(bookmarks::kMobileBookmarksNodeUuid));
EXPECT_THAT(GetGuidForSyncIdInUpdatesForTesting(updates, kOtherBookmarksId),
Eq(bookmarks::kOtherBookmarksNodeUuid));
}
TEST(ParentGuidPreprocessingTest, ShouldPopulateParentGuidInInitialUpdates) {
const std::string kBookmarkBarId = "bookmark_bar_id";
const std::string kParentFolderId = "parent_folder_id";
const std::string kParentFolderUuid =
base::Uuid::GenerateRandomV4().AsLowercaseString();
// Populate updates representing:
// bookmark_bar
// |- folder 1
// |- folder 2
syncer::UpdateResponseDataList updates;
updates.emplace_back();
updates.back().entity.id = kBookmarkBarId;
updates.back().entity.server_defined_unique_tag = "bookmark_bar";
updates.emplace_back();
updates.back().entity.id = kParentFolderId;
updates.back().entity.legacy_parent_id = kBookmarkBarId;
updates.back().entity.specifics.mutable_bookmark()->set_guid(
kParentFolderUuid);
updates.emplace_back();
updates.back().entity.legacy_parent_id = kParentFolderId;
updates.back().entity.specifics.mutable_bookmark()->set_guid("child_guid");
PopulateParentGuidInSpecifics(/*tracker=*/nullptr, &updates);
EXPECT_THAT(updates[0].entity.specifics.bookmark().parent_guid(), Eq(""));
EXPECT_THAT(updates[1].entity.specifics.bookmark().parent_guid(),
Eq(bookmarks::kBookmarkBarNodeUuid));
EXPECT_THAT(updates[2].entity.specifics.bookmark().parent_guid(),
Eq(kParentFolderUuid));
}
TEST(ParentGuidPreprocessingTest,
ShouldNotOverridePreexistingParentGuidInSpecifics) {
const std::string kBookmarkBarId = "bookmark_bar_id";
const std::string kFolderId = "folder_id";
const std::string kFolderUuid =
base::Uuid::GenerateRandomV4().AsLowercaseString();
const std::string kParentUuidInSpecifics =
base::Uuid::GenerateRandomV4().AsLowercaseString();
// Populate updates representing:
// bookmark_bar
// |- folder 1
// |- folder 2
syncer::UpdateResponseDataList updates;
updates.emplace_back();
updates.back().entity.id = kBookmarkBarId;
updates.back().entity.server_defined_unique_tag = "bookmark_bar";
updates.emplace_back();
updates.back().entity.id = kFolderId;
updates.back().entity.legacy_parent_id = kBookmarkBarId;
updates.back().entity.specifics.mutable_bookmark()->set_guid(kFolderUuid);
updates.back().entity.specifics.mutable_bookmark()->set_parent_guid(
kParentUuidInSpecifics);
// Although |parent_id| points to bookmarks bar, the |parent_guid| field
// should prevail.
ASSERT_THAT(GetGuidForSyncIdInUpdatesForTesting(updates, kBookmarkBarId),
Eq(bookmarks::kBookmarkBarNodeUuid));
PopulateParentGuidInSpecifics(/*tracker=*/nullptr, &updates);
EXPECT_THAT(updates[1].entity.specifics.bookmark().parent_guid(),
Eq(kParentUuidInSpecifics));
}
TEST(ParentGuidPreprocessingTest,
ShouldPopulateParentGuidInIncrementalUpdates) {
const std::string kSyncId = "id1";
const std::string kBookmarkBarId = "bookmark_bar_id";
std::unique_ptr<SyncedBookmarkTracker> tracker =
SyncedBookmarkTracker::CreateEmpty(sync_pb::DataTypeState());
// Non-empty specifics are needed for SyncedBookmarkTracker::Add(), with
// unique position populated.
sync_pb::EntitySpecifics fake_specifics;
fake_specifics.mutable_bookmark()->mutable_unique_position();
// BookmarkModelView is used here to pass DCHECKs that require that permanent
// folders are tracked.
TestBookmarkModelView bookmark_model;
tracker->Add(bookmark_model.bookmark_bar_node(), /*sync_id=*/kBookmarkBarId,
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
/*specifics=*/fake_specifics);
tracker->Add(bookmark_model.other_node(), /*sync_id=*/"other_node_id",
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
/*specifics=*/fake_specifics);
tracker->Add(bookmark_model.mobile_node(), /*sync_id=*/"mobile_node_id",
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
/*specifics=*/fake_specifics);
// Add one regular (non-permanent) node.
bookmarks::BookmarkNode tracked_node(/*id=*/1, base::Uuid::GenerateRandomV4(),
GURL());
tracker->Add(&tracked_node, kSyncId,
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
/*specifics=*/fake_specifics);
syncer::UpdateResponseDataList updates;
updates.emplace_back();
updates.back().entity.legacy_parent_id = kSyncId;
updates.back().entity.specifics.mutable_bookmark()->set_guid("guid1");
updates.emplace_back();
updates.back().entity.legacy_parent_id = kBookmarkBarId;
updates.back().entity.specifics.mutable_bookmark()->set_guid("guid2");
PopulateParentGuidInSpecifics(tracker.get(), &updates);
EXPECT_THAT(updates[0].entity.specifics.bookmark().parent_guid(),
Eq(tracked_node.uuid().AsLowercaseString()));
EXPECT_THAT(updates[1].entity.specifics.bookmark().parent_guid(),
Eq(bookmarks::kBookmarkBarNodeUuid));
}
TEST(ParentGuidPreprocessingTest,
ShouldPopulateWithFakeGuidIfParentSetButUnknown) {
// Fork of the private constant in the .cc file.
const std::string kInvalidParentUuid = "220a410e-37b9-5bbc-8674-ea982459f940";
const std::string kParentFolderId = "parent_folder_id";
const std::string kParentFolderUuid =
base::Uuid::GenerateRandomV4().AsLowercaseString();
// Populate updates representing:
// |- folder with unknown parent
syncer::UpdateResponseDataList updates;
updates.emplace_back();
updates.back().entity.id = kParentFolderId;
updates.back().entity.legacy_parent_id = "some_unknown_parent";
updates.back().entity.specifics.mutable_bookmark()->set_guid(
kParentFolderUuid);
PopulateParentGuidInSpecifics(/*tracker=*/nullptr, &updates);
EXPECT_THAT(updates[0].entity.specifics.bookmark().parent_guid(),
Eq(kInvalidParentUuid));
}
} // namespace
} // namespace sync_bookmarks