// 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/sha1.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.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/time.h"
#include "components/sync/base/unique_position.h"
#include "components/sync/model/entity_data.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 {

// 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,
  COUNT_MISMATCH = 4,
  IDS_MISMATCH = 5,
  kMaxValue = IDS_MISMATCH
};

sync_pb::EntitySpecifics GenerateSpecifics(const std::string& title,
                                           const std::string& url) {
  sync_pb::EntitySpecifics specifics;
  specifics.mutable_bookmark()->set_title(title);
  specifics.mutable_bookmark()->set_url(url);
  return specifics;
}

std::unique_ptr<sync_pb::EntityMetadata> CreateEntityMetadata(
    const std::string& server_id,
    bool is_deleted) {
  auto metadata = std::make_unique<sync_pb::EntityMetadata>();
  metadata->set_server_id(server_id);
  metadata->set_is_deleted(is_deleted);
  return metadata;
}

TEST(SyncedBookmarkTrackerTest, ShouldGetAssociatedNodes) {
  SyncedBookmarkTracker tracker(std::vector<NodeMetadataPair>(),
                                std::make_unique<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::TimeDelta::FromSeconds(1));
  const syncer::UniquePosition unique_position =
      syncer::UniquePosition::InitialPosition(
          syncer::UniquePosition::RandomSuffix());
  const sync_pb::EntitySpecifics specifics =
      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());

  bookmarks::BookmarkNode node(kId, kUrl);
  tracker.Add(kSyncId, &node, kServerVersion, kCreationTime,
              unique_position.ToProto(), specifics);
  const SyncedBookmarkTracker::Entity* entity =
      tracker.GetEntityForSyncId(kSyncId);
  ASSERT_THAT(entity, NotNull());
  EXPECT_THAT(entity->bookmark_node(), Eq(&node));
  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(unique_position));

  syncer::EntityData data;
  *data.specifics.mutable_bookmark() = specifics.bookmark();
  data.unique_position = unique_position.ToProto();
  EXPECT_TRUE(entity->MatchesDataIgnoringParent(data));
  EXPECT_THAT(tracker.GetEntityForSyncId("unknown id"), IsNull());
}

TEST(SyncedBookmarkTrackerTest, ShouldReturnNullForDisassociatedNodes) {
  SyncedBookmarkTracker tracker(std::vector<NodeMetadataPair>(),
                                std::make_unique<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::TimeDelta::FromSeconds(1));
  const sync_pb::UniquePosition unique_position;
  const sync_pb::EntitySpecifics specifics =
      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
  bookmarks::BookmarkNode node(kId, GURL());
  tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
              unique_position, specifics);
  ASSERT_THAT(tracker.GetEntityForSyncId(kSyncId), NotNull());
  tracker.Remove(kSyncId);
  EXPECT_THAT(tracker.GetEntityForSyncId(kSyncId), IsNull());
}

TEST(SyncedBookmarkTrackerTest, ShouldBuildBookmarkModelMetadata) {
  SyncedBookmarkTracker tracker(std::vector<NodeMetadataPair>(),
                                std::make_unique<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::TimeDelta::FromSeconds(1));
  const syncer::UniquePosition unique_position =
      syncer::UniquePosition::InitialPosition(
          syncer::UniquePosition::RandomSuffix());
  const sync_pb::EntitySpecifics specifics =
      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());

  bookmarks::BookmarkNode node(kId, kUrl);
  tracker.Add(kSyncId, &node, kServerVersion, kCreationTime,
              unique_position.ToProto(), 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) {
  SyncedBookmarkTracker tracker(std::vector<NodeMetadataPair>(),
                                std::make_unique<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::TimeDelta::FromSeconds(1));
  const sync_pb::UniquePosition unique_position;
  const sync_pb::EntitySpecifics specifics =
      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
  bookmarks::BookmarkNode node(kId, GURL());
  tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
              unique_position, specifics);

  EXPECT_THAT(tracker.HasLocalChanges(), Eq(false));
  tracker.IncrementSequenceNumber(kSyncId);
  EXPECT_THAT(tracker.HasLocalChanges(), Eq(true));
  // TODO(crbug.com/516866): Test HasLocalChanges after submitting commit
  // request in a separate test probably.
}

TEST(SyncedBookmarkTrackerTest, ShouldAckSequenceNumber) {
  SyncedBookmarkTracker tracker(std::vector<NodeMetadataPair>(),
                                std::make_unique<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::TimeDelta::FromSeconds(1));
  const sync_pb::UniquePosition unique_position;
  const sync_pb::EntitySpecifics specifics =
      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
  bookmarks::BookmarkNode node(kId, GURL());
  tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
              unique_position, specifics);

  // Test simple scenario of ack'ing an incrememented sequence number.
  EXPECT_THAT(tracker.HasLocalChanges(), Eq(false));
  tracker.IncrementSequenceNumber(kSyncId);
  EXPECT_THAT(tracker.HasLocalChanges(), Eq(true));
  tracker.AckSequenceNumber(kSyncId);
  EXPECT_THAT(tracker.HasLocalChanges(), Eq(false));

  // Test ack'ing of a mutliple times incremented sequence number.
  tracker.IncrementSequenceNumber(kSyncId);
  EXPECT_THAT(tracker.HasLocalChanges(), Eq(true));
  tracker.IncrementSequenceNumber(kSyncId);
  tracker.IncrementSequenceNumber(kSyncId);
  EXPECT_THAT(tracker.HasLocalChanges(), Eq(true));
  tracker.AckSequenceNumber(kSyncId);
  EXPECT_THAT(tracker.HasLocalChanges(), Eq(false));
}

TEST(SyncedBookmarkTrackerTest, ShouldUpdateUponCommitResponseWithNewId) {
  SyncedBookmarkTracker tracker(std::vector<NodeMetadataPair>(),
                                std::make_unique<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::TimeDelta::FromSeconds(1));
  const sync_pb::UniquePosition unique_position;
  const sync_pb::EntitySpecifics specifics =
      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
  bookmarks::BookmarkNode node(kId, GURL());
  tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
              unique_position, specifics);
  ASSERT_THAT(tracker.GetEntityForSyncId(kSyncId), NotNull());
  // Receive a commit response with a changed id.
  tracker.UpdateUponCommitResponse(
      kSyncId, kNewSyncId, /*acked_sequence_number=*/1, kNewServerVersion);
  // Old id shouldn't be there.
  EXPECT_THAT(tracker.GetEntityForSyncId(kSyncId), IsNull());

  const SyncedBookmarkTracker::Entity* entity =
      tracker.GetEntityForSyncId(kNewSyncId);
  ASSERT_THAT(entity, NotNull());
  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) {
  SyncedBookmarkTracker tracker(std::vector<NodeMetadataPair>(),
                                std::make_unique<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::TimeDelta::FromSeconds(1));
  const sync_pb::UniquePosition unique_position;
  const sync_pb::EntitySpecifics specifics =
      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
  bookmarks::BookmarkNode node(/*id=*/1, GURL());
  // Track a sync entity.
  tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
              unique_position, specifics);

  ASSERT_THAT(tracker.GetEntityForSyncId(kSyncId), NotNull());
  // Update the sync id.
  tracker.UpdateSyncForLocalCreationIfNeeded(kSyncId, kNewSyncId);
  // Old id shouldn't be there.
  EXPECT_THAT(tracker.GetEntityForSyncId(kSyncId), IsNull());

  const SyncedBookmarkTracker::Entity* entity =
      tracker.GetEntityForSyncId(kNewSyncId);
  ASSERT_THAT(entity, NotNull());
  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";

  const GURL kUrl("http://www.foo.com");
  bookmarks::BookmarkNode node0(/*id=*/0, kUrl);
  bookmarks::BookmarkNode node1(/*id=*/1, kUrl);

  std::vector<NodeMetadataPair> node_metadata_pairs;
  node_metadata_pairs.emplace_back(
      &node0, CreateEntityMetadata(/*server_id=*/kId0, /*is_deleted=*/false));
  node_metadata_pairs.emplace_back(
      &node1, CreateEntityMetadata(/*server_id=*/kId1, /*is_deleted=*/false));
  node_metadata_pairs.emplace_back(
      nullptr, CreateEntityMetadata(/*server_id=*/kId2, /*is_deleted=*/true));
  node_metadata_pairs.emplace_back(
      nullptr, CreateEntityMetadata(/*server_id=*/kId3, /*is_deleted=*/true));
  node_metadata_pairs.emplace_back(
      nullptr, CreateEntityMetadata(/*server_id=*/kId4, /*is_deleted=*/true));

  SyncedBookmarkTracker tracker(std::move(node_metadata_pairs),
                                std::make_unique<sync_pb::ModelTypeState>());

  sync_pb::BookmarkModelMetadata bookmark_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(bookmark_model_metadata.bookmarks_metadata().size(), Eq(5));
  EXPECT_THAT(
      bookmark_model_metadata.bookmarks_metadata(2).metadata().server_id(),
      Eq(kId2));
  EXPECT_THAT(
      bookmark_model_metadata.bookmarks_metadata(3).metadata().server_id(),
      Eq(kId3));
  EXPECT_THAT(
      bookmark_model_metadata.bookmarks_metadata(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";

  const GURL kUrl("http://www.foo.com");
  bookmarks::BookmarkNode node0(/*id=*/0, kUrl);
  bookmarks::BookmarkNode node1(/*id=*/1, kUrl);
  bookmarks::BookmarkNode node2(/*id=*/2, kUrl);
  bookmarks::BookmarkNode node3(/*id=*/3, kUrl);
  bookmarks::BookmarkNode node4(/*id=*/4, kUrl);

  std::vector<NodeMetadataPair> node_metadata_pairs;
  node_metadata_pairs.emplace_back(
      &node0, CreateEntityMetadata(/*server_id=*/kId0, /*is_deleted=*/false));
  node_metadata_pairs.emplace_back(
      &node1, CreateEntityMetadata(/*server_id=*/kId1, /*is_deleted=*/false));
  node_metadata_pairs.emplace_back(
      &node2, CreateEntityMetadata(/*server_id=*/kId2, /*is_deleted=*/false));
  node_metadata_pairs.emplace_back(
      &node3, CreateEntityMetadata(/*server_id=*/kId3, /*is_deleted=*/false));
  node_metadata_pairs.emplace_back(
      &node4, CreateEntityMetadata(/*server_id=*/kId4, /*is_deleted=*/false));

  SyncedBookmarkTracker tracker(std::move(node_metadata_pairs),
                                std::make_unique<sync_pb::ModelTypeState>());

  // Mark entities deleted in that order kId2, kId4, kId1
  tracker.MarkDeleted(kId2);
  tracker.MarkDeleted(kId4);
  tracker.MarkDeleted(kId1);

  sync_pb::BookmarkModelMetadata bookmark_model_metadata =
      tracker.BuildBookmarkModelMetadata();

  // Tombstones should be the last 3 entries in the metadata and in the same as
  // calling MarkDeleted().
  ASSERT_THAT(bookmark_model_metadata.bookmarks_metadata().size(), Eq(5));
  EXPECT_THAT(
      bookmark_model_metadata.bookmarks_metadata(2).metadata().server_id(),
      Eq(kId2));
  EXPECT_THAT(
      bookmark_model_metadata.bookmarks_metadata(3).metadata().server_id(),
      Eq(kId4));
  EXPECT_THAT(
      bookmark_model_metadata.bookmarks_metadata(4).metadata().server_id(),
      Eq(kId1));
}

TEST(SyncedBookmarkTrackerTest,
     ShouldOrderParentUpdatesBeforeChildUpdatesAndDeletionsComeLast) {
  const size_t kMaxEntries = 1000;

  // 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, base::UTF8ToUTF16("node0"));
  const bookmarks::BookmarkNode* node1 = bookmark_model->AddFolder(
      /*parent=*/node0, /*index=*/0, base::UTF8ToUTF16("node1"));
  const bookmarks::BookmarkNode* node2 = bookmark_model->AddFolder(
      /*parent=*/node1, /*index=*/0, base::UTF8ToUTF16("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.
  std::vector<NodeMetadataPair> node_metadata_pairs;
  node_metadata_pairs.emplace_back(
      node1, CreateEntityMetadata(/*server_id=*/kId1, /*is_deleted=*/false));
  node_metadata_pairs.emplace_back(
      nullptr, CreateEntityMetadata(/*server_id=*/kId3, /*is_deleted=*/true));
  node_metadata_pairs.emplace_back(
      node2, CreateEntityMetadata(/*server_id=*/kId2, /*is_deleted=*/false));
  node_metadata_pairs.emplace_back(
      node0, CreateEntityMetadata(/*server_id=*/kId0, /*is_deleted=*/false));

  SyncedBookmarkTracker tracker(std::move(node_metadata_pairs),
                                std::make_unique<sync_pb::ModelTypeState>());

  // 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(kId3);
  tracker.IncrementSequenceNumber(kId1);
  tracker.IncrementSequenceNumber(kId2);
  tracker.IncrementSequenceNumber(kId0);

  std::vector<const SyncedBookmarkTracker::Entity*> entities_with_local_change =
      tracker.GetEntitiesWithLocalChanges(kMaxEntries);

  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, ShouldMatchModelAndMetadata) {
  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, base::UTF8ToUTF16("node0"));

  sync_pb::BookmarkModelMetadata model_metadata;
  model_metadata.mutable_model_type_state()->set_initial_sync_done(true);
  // Add entries for all the permanent nodes. TestBookmarkClient creates all the
  // 3 permanent nodes.
  sync_pb::BookmarkMetadata* bookmark_metadata =
      model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->bookmark_bar_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id("BookmarkBarId");

  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->other_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id("OtherBookmarksId");

  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->mobile_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id("MobileBookmarksId");

  // Add entry for the extra node.
  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(node->id());
  bookmark_metadata->mutable_metadata()->set_server_id("NodeId");

  // Add a tombstone entry.
  sync_pb::BookmarkMetadata* tombstone =
      model_metadata.add_bookmarks_metadata();
  tombstone->mutable_metadata()->set_server_id("tombstoneId");
  tombstone->mutable_metadata()->set_is_deleted(true);

  base::HistogramTester histogram_tester;
  EXPECT_TRUE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata(
      model.get(), model_metadata));
  histogram_tester.ExpectUniqueSample(
      "Sync.BookmarksModelMetadataCorruptionReason",
      /*sample=*/ExpectedCorruptionReason::NO_CORRUPTION, /*count=*/1);
}

TEST(SyncedBookmarkTrackerTest,
     ShouldNotMatchModelAndMetadataIfMissingMobileFolder) {
  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.
  sync_pb::BookmarkMetadata* bookmark_metadata =
      model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->bookmark_bar_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id("BookmarkBarId");

  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->other_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id("OtherBookmarksId");

  base::HistogramTester histogram_tester;
  EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata(
      model.get(), model_metadata));
  histogram_tester.ExpectUniqueSample(
      "Sync.BookmarksModelMetadataCorruptionReason",
      /*sample=*/ExpectedCorruptionReason::COUNT_MISMATCH, /*count=*/1);
}

TEST(SyncedBookmarkTrackerTest, ShouldNotMatchModelAndCorruptedMetadata) {
  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 3 permanent nodes only. TestBookmarkClient creates all the
  // 4 permanent nodes.
  sync_pb::BookmarkMetadata* bookmark_metadata =
      model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->bookmark_bar_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id("BookmarkBarId");

  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->mobile_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id("MobileBookmarksId");

  base::HistogramTester histogram_tester;
  // The entry for the Other bookmarks is missing.
  EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata(
      model.get(), model_metadata));
  histogram_tester.ExpectBucketCount(
      "Sync.BookmarksModelMetadataCorruptionReason",
      /*sample=*/ExpectedCorruptionReason::COUNT_MISMATCH, /*count=*/1);

  // The entry for the Other bookmarks is missing a server id.
  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->other_node()->id());
  EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata(
      model.get(), model_metadata));

  histogram_tester.ExpectBucketCount(
      "Sync.BookmarksModelMetadataCorruptionReason",
      /*sample=*/ExpectedCorruptionReason::MISSING_SERVER_ID, /*count=*/1);

  // The entry for the Other bookmarks is missing a node id.
  bookmark_metadata->clear_id();
  bookmark_metadata->mutable_metadata()->set_server_id("OtherBookmarksId");
  EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata(
      model.get(), model_metadata));
  histogram_tester.ExpectBucketCount(
      "Sync.BookmarksModelMetadataCorruptionReason",
      /*sample=*/ExpectedCorruptionReason::MISSING_BOOKMARK_ID, /*count=*/1);

  // The entry for the Other bookmarks is having a wrong node id.
  bookmark_metadata->set_id(model->other_node()->id() + 1000);
  EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata(
      model.get(), model_metadata));
  histogram_tester.ExpectBucketCount(
      "Sync.BookmarksModelMetadataCorruptionReason",
      /*sample=*/ExpectedCorruptionReason::IDS_MISMATCH, /*count=*/1);

  // A tombstone shouldn't have a node id.
  sync_pb::BookmarkMetadata* tombstone =
      model_metadata.add_bookmarks_metadata();
  tombstone->mutable_metadata()->set_server_id("tombstoneId");
  tombstone->mutable_metadata()->set_is_deleted(true);
  tombstone->set_id(10);
  EXPECT_FALSE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata(
      model.get(), model_metadata));
  histogram_tester.ExpectBucketCount(
      "Sync.BookmarksModelMetadataCorruptionReason",
      /*sample=*/ExpectedCorruptionReason::BOOKMARK_ID_IN_TOMBSTONE,
      /*count=*/1);
}

TEST(SyncedBookmarkTrackerTest,
     ShouldMatchModelWithUnsyncableNodesAndMetadata) {
  // Add a managed node with an arbitrary id 100.
  const int64_t kManagedNodeId = 100;
  bookmarks::BookmarkPermanentNodeList extra_nodes;
  extra_nodes.push_back(
      std::make_unique<bookmarks::BookmarkPermanentNode>(kManagedNodeId));
  bookmarks::BookmarkPermanentNode* extra_node = extra_nodes.back().get();
  auto client = std::make_unique<bookmarks::TestBookmarkClient>();
  client->SetExtraNodesToLoad(std::move(extra_nodes));

  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(), kManagedNodeId), Eq(extra_node));

  sync_pb::BookmarkModelMetadata model_metadata;
  model_metadata.mutable_model_type_state()->set_initial_sync_done(true);
  // Add entries for all the permanent nodes. TestBookmarkClient creates all the
  // 3 permanent nodes.
  sync_pb::BookmarkMetadata* bookmark_metadata =
      model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->bookmark_bar_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id("BookmarkBarId");

  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->other_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id("OtherBookmarksId");

  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(model->mobile_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id("MobileBookmarksId");

  base::HistogramTester histogram_tester;
  EXPECT_TRUE(SyncedBookmarkTracker::BookmarkModelMatchesMetadata(
      model.get(), model_metadata));
  histogram_tester.ExpectUniqueSample(
      "Sync.BookmarksModelMetadataCorruptionReason",
      /*sample=*/ExpectedCorruptionReason::NO_CORRUPTION, /*count=*/1);
}

}  // namespace

}  // namespace sync_bookmarks
