// Copyright 2014 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/engine_impl/directory_update_handler.h"

#include <stdint.h>

#include <set>
#include <string>
#include <utility>

#include "base/compiler_specific.h"
#include "base/stl_util.h"
#include "base/test/scoped_task_environment.h"
#include "components/sync/engine_impl/cycle/directory_type_debug_info_emitter.h"
#include "components/sync/engine_impl/cycle/status_controller.h"
#include "components/sync/engine_impl/syncer_proto_util.h"
#include "components/sync/engine_impl/test_entry_factory.h"
#include "components/sync/protocol/sync.pb.h"
#include "components/sync/syncable/directory.h"
#include "components/sync/syncable/entry.h"
#include "components/sync/syncable/mutable_entry.h"
#include "components/sync/syncable/syncable_model_neutral_write_transaction.h"
#include "components/sync/syncable/syncable_proto_util.h"
#include "components/sync/syncable/syncable_read_transaction.h"
#include "components/sync/syncable/syncable_write_transaction.h"
#include "components/sync/test/engine/fake_model_worker.h"
#include "components/sync/test/engine/test_directory_setter_upper.h"
#include "components/sync/test/engine/test_id_factory.h"
#include "components/sync/test/engine/test_syncable_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace syncer {

using syncable::Id;
using syncable::UNITTEST;

static const int64_t kDefaultVersion = 1000;

// A test harness for tests that focus on processing updates.
//
// Update processing is what occurs when we first download updates.  It converts
// the received protobuf message into information in the syncable::Directory.
// Any invalid or redundant updates will be dropped at this point.
class DirectoryUpdateHandlerProcessUpdateTest : public ::testing::Test {
 public:
  DirectoryUpdateHandlerProcessUpdateTest()
      : ui_worker_(new FakeModelWorker(GROUP_UI)) {}

  ~DirectoryUpdateHandlerProcessUpdateTest() override {}

  void SetUp() override { dir_maker_.SetUp(); }

  void TearDown() override { dir_maker_.TearDown(); }

  syncable::Directory* dir() { return dir_maker_.directory(); }

 protected:
  std::unique_ptr<sync_pb::SyncEntity> CreateUpdate(const std::string& id,
                                                    const std::string& parent,
                                                    const ModelType& type);

  // This exists mostly to give tests access to the protected member function.
  // Warning: This takes the syncable directory lock.
  void UpdateSyncEntities(DirectoryUpdateHandler* handler,
                          const SyncEntityList& applicable_updates,
                          StatusController* status);

  // Another function to access private member functions.
  void UpdateProgressMarkers(DirectoryUpdateHandler* handler,
                             const sync_pb::DataTypeProgressMarker& progress);

  scoped_refptr<FakeModelWorker> ui_worker() { return ui_worker_; }

  bool EntryExists(const std::string& id) {
    syncable::ReadTransaction trans(FROM_HERE, dir());
    syncable::Entry e(&trans, syncable::GET_BY_ID, Id::CreateFromServerId(id));
    return e.good() && !e.GetIsDel();
  }

  bool TypeRootExists(ModelType model_type) {
    return dir()->InitialSyncEndedForType(model_type);
  }

 protected:
  // Used in the construction of DirectoryTypeDebugInfoEmitters.
  base::ObserverList<TypeDebugInfoObserver>::Unchecked type_observers_;

 private:
  // Needed to initialize the directory.
  base::test::ScopedTaskEnvironment task_environment_;
  TestDirectorySetterUpper dir_maker_;
  scoped_refptr<FakeModelWorker> ui_worker_;
};

std::unique_ptr<sync_pb::SyncEntity>
DirectoryUpdateHandlerProcessUpdateTest::CreateUpdate(const std::string& id,
                                                      const std::string& parent,
                                                      const ModelType& type) {
  std::unique_ptr<sync_pb::SyncEntity> e(new sync_pb::SyncEntity());
  e->set_id_string(id);
  e->set_parent_id_string(parent);
  e->set_non_unique_name(id);
  e->set_name(id);
  e->set_version(kDefaultVersion);
  AddDefaultFieldValue(type, e->mutable_specifics());
  return e;
}

void DirectoryUpdateHandlerProcessUpdateTest::UpdateSyncEntities(
    DirectoryUpdateHandler* handler,
    const SyncEntityList& applicable_updates,
    StatusController* status) {
  syncable::ModelNeutralWriteTransaction trans(FROM_HERE, UNITTEST, dir());
  // We pick is_initial_sync arbitrarily as it has only impact on counters.
  handler->UpdateSyncEntities(&trans, applicable_updates,
                              /*is_initial_sync=*/true, status);
}

void DirectoryUpdateHandlerProcessUpdateTest::UpdateProgressMarkers(
    DirectoryUpdateHandler* handler,
    const sync_pb::DataTypeProgressMarker& progress) {
  handler->UpdateProgressMarker(progress);
}

static const char kCacheGuid[] = "IrcjZ2jyzHDV9Io4+zKcXQ==";

// Test that the bookmark tag is set on newly downloaded items.
TEST_F(DirectoryUpdateHandlerProcessUpdateTest, NewBookmarkTag) {
  DirectoryTypeDebugInfoEmitter emitter(BOOKMARKS, &type_observers_);
  DirectoryUpdateHandler handler(dir(), BOOKMARKS, ui_worker(), &emitter);
  sync_pb::GetUpdatesResponse gu_response;
  StatusController status;

  // Add a bookmark item to the update message.
  std::string root = Id::GetRoot().GetServerId();
  Id server_id = Id::CreateFromServerId("b1");
  std::unique_ptr<sync_pb::SyncEntity> e =
      CreateUpdate(SyncableIdToProto(server_id), root, BOOKMARKS);
  e->set_originator_cache_guid(
      std::string(kCacheGuid, base::size(kCacheGuid) - 1));
  Id client_id = Id::CreateFromClientString("-2");
  e->set_originator_client_item_id(client_id.GetServerId());
  e->set_position_in_parent(0);

  // Add it to the applicable updates list.
  SyncEntityList bookmark_updates;
  bookmark_updates.push_back(e.get());

  // Process the update.
  UpdateSyncEntities(&handler, bookmark_updates, &status);

  syncable::ReadTransaction trans(FROM_HERE, dir());
  syncable::Entry entry(&trans, syncable::GET_BY_ID, server_id);
  ASSERT_TRUE(entry.good());
  EXPECT_TRUE(UniquePosition::IsValidSuffix(entry.GetUniqueBookmarkTag()));
  EXPECT_TRUE(entry.GetServerUniquePosition().IsValid());

  // If this assertion fails, that might indicate that the algorithm used to
  // generate bookmark tags has been modified.  This could have implications for
  // bookmark ordering.  Please make sure you know what you're doing if you
  // intend to make such a change.
  EXPECT_EQ("6wHRAb3kbnXV5GHrejp4/c1y5tw=", entry.GetUniqueBookmarkTag());
}

// Test the receipt of a type root node.
TEST_F(DirectoryUpdateHandlerProcessUpdateTest,
       ReceiveServerCreatedBookmarkFolders) {
  DirectoryTypeDebugInfoEmitter emitter(BOOKMARKS, &type_observers_);
  DirectoryUpdateHandler handler(dir(), BOOKMARKS, ui_worker(), &emitter);
  sync_pb::GetUpdatesResponse gu_response;
  StatusController status;

  // Create an update that mimics the bookmark root.
  Id server_id = Id::CreateFromServerId("xyz");
  std::string root = Id::GetRoot().GetServerId();
  std::unique_ptr<sync_pb::SyncEntity> e =
      CreateUpdate(SyncableIdToProto(server_id), root, BOOKMARKS);
  e->set_server_defined_unique_tag("google_chrome_bookmarks");
  e->set_folder(true);

  // Add it to the applicable updates list.
  SyncEntityList bookmark_updates;
  bookmark_updates.push_back(e.get());

  EXPECT_FALSE(SyncerProtoUtil::ShouldMaintainPosition(*e));

  // Process it.
  UpdateSyncEntities(&handler, bookmark_updates, &status);

  // Verify the results.
  syncable::ReadTransaction trans(FROM_HERE, dir());
  syncable::Entry entry(&trans, syncable::GET_BY_ID, server_id);
  ASSERT_TRUE(entry.good());

  EXPECT_FALSE(entry.ShouldMaintainPosition());
  EXPECT_FALSE(entry.GetUniquePosition().IsValid());
  EXPECT_FALSE(entry.GetServerUniquePosition().IsValid());
  EXPECT_TRUE(entry.GetUniqueBookmarkTag().empty());
}

// Test the receipt of a non-bookmark item.
TEST_F(DirectoryUpdateHandlerProcessUpdateTest, ReceiveNonBookmarkItem) {
  DirectoryTypeDebugInfoEmitter emitter(AUTOFILL, &type_observers_);
  DirectoryUpdateHandler handler(dir(), AUTOFILL, ui_worker(), &emitter);
  sync_pb::GetUpdatesResponse gu_response;
  StatusController status;

  std::string root = Id::GetRoot().GetServerId();
  Id server_id = Id::CreateFromServerId("xyz");
  std::unique_ptr<sync_pb::SyncEntity> e =
      CreateUpdate(SyncableIdToProto(server_id), root, AUTOFILL);
  e->set_server_defined_unique_tag("9PGRuKdX5sHyGMB17CvYTXuC43I=");

  // Add it to the applicable updates list.
  SyncEntityList autofill_updates;
  autofill_updates.push_back(e.get());

  EXPECT_FALSE(SyncerProtoUtil::ShouldMaintainPosition(*e));

  // Process it.
  UpdateSyncEntities(&handler, autofill_updates, &status);

  syncable::ReadTransaction trans(FROM_HERE, dir());
  syncable::Entry entry(&trans, syncable::GET_BY_ID, server_id);
  ASSERT_TRUE(entry.good());

  EXPECT_FALSE(entry.ShouldMaintainPosition());
  EXPECT_FALSE(entry.GetUniquePosition().IsValid());
  EXPECT_FALSE(entry.GetServerUniquePosition().IsValid());
  EXPECT_TRUE(entry.GetUniqueBookmarkTag().empty());
}

// Tests the setting of progress markers.
TEST_F(DirectoryUpdateHandlerProcessUpdateTest, ProcessNewProgressMarkers) {
  DirectoryTypeDebugInfoEmitter emitter(BOOKMARKS, &type_observers_);
  DirectoryUpdateHandler handler(dir(), BOOKMARKS, ui_worker(), &emitter);

  sync_pb::DataTypeProgressMarker progress;
  progress.set_data_type_id(GetSpecificsFieldNumberFromModelType(BOOKMARKS));
  progress.set_token("token");

  UpdateProgressMarkers(&handler, progress);

  sync_pb::DataTypeProgressMarker saved;
  dir()->GetDownloadProgress(BOOKMARKS, &saved);

  EXPECT_EQ(progress.token(), saved.token());
  EXPECT_EQ(progress.data_type_id(), saved.data_type_id());
}

TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByVersion) {
  DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_);
  DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker(),
                                 &emitter);
  StatusController status;

  sync_pb::DataTypeProgressMarker progress;
  progress.set_data_type_id(
      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
  progress.set_token("token");
  progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 10);

  sync_pb::DataTypeContext context;
  context.set_data_type_id(
      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
  context.set_context("context");
  context.set_version(1);

  std::unique_ptr<sync_pb::SyncEntity> e1 =
      CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "",
                   SYNCED_NOTIFICATIONS);

  std::unique_ptr<sync_pb::SyncEntity> e2 =
      CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "",
                   SYNCED_NOTIFICATIONS);
  e2->set_version(kDefaultVersion + 100);

  // Add to the applicable updates list.
  SyncEntityList updates;
  updates.push_back(e1.get());
  updates.push_back(e2.get());

  // Process and apply updates.
  EXPECT_EQ(
      SyncerError::SYNCER_OK,
      handler.ProcessGetUpdatesResponse(progress, context, updates, &status)
          .value());
  handler.ApplyUpdates(&status);

  // Verify none is deleted because they are unapplied during GC.
  EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS));
  EXPECT_TRUE(EntryExists(e1->id_string()));
  EXPECT_TRUE(EntryExists(e2->id_string()));

  // Process and apply again. Old entry is deleted but not root.
  progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 20);
  EXPECT_EQ(SyncerError::SYNCER_OK,
            handler
                .ProcessGetUpdatesResponse(progress, context, SyncEntityList(),
                                           &status)
                .value());
  handler.ApplyUpdates(&status);
  EXPECT_FALSE(EntryExists(e1->id_string()));
  EXPECT_TRUE(EntryExists(e2->id_string()));
}

// Create 2 entries, one is 15-days-old, another is 5-days-old. Check if sync
// will delete 15-days-old entry when server set expired age is 10 days.
TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByAge) {
  DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_);
  DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker(),
                                 &emitter);
  StatusController status;

  sync_pb::DataTypeProgressMarker progress;
  progress.set_data_type_id(
      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
  progress.set_token("token");
  progress.mutable_gc_directive()->set_age_watermark_in_days(20);

  sync_pb::DataTypeContext context;
  context.set_data_type_id(
      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
  context.set_context("context");
  context.set_version(1);

  std::unique_ptr<sync_pb::SyncEntity> e1 =
      CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "",
                   SYNCED_NOTIFICATIONS);
  e1->set_mtime(
      TimeToProtoTime(base::Time::Now() - base::TimeDelta::FromDays(15)));

  std::unique_ptr<sync_pb::SyncEntity> e2 =
      CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "",
                   SYNCED_NOTIFICATIONS);
  e2->set_mtime(
      TimeToProtoTime(base::Time::Now() - base::TimeDelta::FromDays(5)));

  // Add to the applicable updates list.
  SyncEntityList updates;
  updates.push_back(e1.get());
  updates.push_back(e2.get());

  // Process and apply updates.
  EXPECT_EQ(
      SyncerError::SYNCER_OK,
      handler.ProcessGetUpdatesResponse(progress, context, updates, &status)
          .value());
  handler.ApplyUpdates(&status);

  // Verify none is deleted because they are unapplied during GC.
  EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS));
  EXPECT_TRUE(EntryExists(e1->id_string()));
  EXPECT_TRUE(EntryExists(e2->id_string()));

  // Process and apply again. 15-days-old entry is deleted but not 5-days-old
  // entry.
  progress.mutable_gc_directive()->set_age_watermark_in_days(10);
  EXPECT_EQ(SyncerError::SYNCER_OK,
            handler
                .ProcessGetUpdatesResponse(progress, context, SyncEntityList(),
                                           &status)
                .value());
  handler.ApplyUpdates(&status);
  EXPECT_FALSE(EntryExists(e1->id_string()));
  EXPECT_TRUE(EntryExists(e2->id_string()));
}

// Create 3 entries, one is 15-days-old, one is 10-days-old, another is
// 5-days-old. Check if sync will delete 15-days-old entry when server set
// max_number_of_items is 2.
TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByItemLimit) {
  DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_);
  DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker(),
                                 &emitter);
  StatusController status;

  sync_pb::DataTypeProgressMarker progress;
  progress.set_data_type_id(
      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
  progress.set_token("token");
  progress.mutable_gc_directive()->set_max_number_of_items(3);

  sync_pb::DataTypeContext context;
  context.set_data_type_id(
      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
  context.set_context("context");
  context.set_version(1);

  std::unique_ptr<sync_pb::SyncEntity> e1 =
      CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "",
                   SYNCED_NOTIFICATIONS);
  e1->set_mtime(
      TimeToProtoTime(base::Time::Now() - base::TimeDelta::FromDays(15)));

  std::unique_ptr<sync_pb::SyncEntity> e2 =
      CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "",
                   SYNCED_NOTIFICATIONS);
  e2->set_mtime(
      TimeToProtoTime(base::Time::Now() - base::TimeDelta::FromDays(5)));

  std::unique_ptr<sync_pb::SyncEntity> e3 =
      CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e3")), "",
                   SYNCED_NOTIFICATIONS);
  e3->set_mtime(
      TimeToProtoTime(base::Time::Now() - base::TimeDelta::FromDays(10)));

  // Add to the applicable updates list.
  SyncEntityList updates;
  updates.push_back(e1.get());
  updates.push_back(e2.get());
  updates.push_back(e3.get());

  // Process and apply updates.
  EXPECT_EQ(
      SyncerError::SYNCER_OK,
      handler.ProcessGetUpdatesResponse(progress, context, updates, &status)
          .value());
  handler.ApplyUpdates(&status);

  // Verify none is deleted because they are unapplied during GC.
  EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS));
  EXPECT_TRUE(EntryExists(e1->id_string()));
  EXPECT_TRUE(EntryExists(e2->id_string()));

  // Process and apply again. 15-days-old entry is deleted.
  progress.mutable_gc_directive()->set_max_number_of_items(2);
  EXPECT_EQ(SyncerError::SYNCER_OK,
            handler
                .ProcessGetUpdatesResponse(progress, context, SyncEntityList(),
                                           &status)
                .value());
  handler.ApplyUpdates(&status);
  EXPECT_FALSE(EntryExists(e1->id_string()));
  EXPECT_TRUE(EntryExists(e2->id_string()));
  EXPECT_TRUE(EntryExists(e3->id_string()));
}

TEST_F(DirectoryUpdateHandlerProcessUpdateTest, ContextVersion) {
  DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_);
  DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker(),
                                 &emitter);
  StatusController status;
  int field_number = GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS);

  sync_pb::DataTypeProgressMarker progress;
  progress.set_data_type_id(
      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
  progress.set_token("token");

  sync_pb::DataTypeContext old_context;
  old_context.set_version(1);
  old_context.set_context("data");
  old_context.set_data_type_id(field_number);

  std::unique_ptr<sync_pb::SyncEntity> e1 =
      CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "",
                   SYNCED_NOTIFICATIONS);

  SyncEntityList updates;
  updates.push_back(e1.get());

  // The first response should be processed fine.
  EXPECT_EQ(
      SyncerError::SYNCER_OK,
      handler.ProcessGetUpdatesResponse(progress, old_context, updates, &status)
          .value());
  handler.ApplyUpdates(&status);

  // The PREFERENCES root should be auto-created.
  EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS));

  EXPECT_TRUE(EntryExists(e1->id_string()));

  {
    sync_pb::DataTypeContext dir_context;
    syncable::ReadTransaction trans(FROM_HERE, dir());
    trans.directory()->GetDataTypeContext(&trans, SYNCED_NOTIFICATIONS,
                                          &dir_context);
    EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString());
  }

  sync_pb::DataTypeContext new_context;
  new_context.set_version(0);
  new_context.set_context("old");
  new_context.set_data_type_id(field_number);

  std::unique_ptr<sync_pb::SyncEntity> e2 =
      CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "",
                   SYNCED_NOTIFICATIONS);
  updates.clear();
  updates.push_back(e2.get());

  // The second response, with an old context version, should result in an
  // error and the updates should be dropped.
  EXPECT_EQ(
      SyncerError::DATATYPE_TRIGGERED_RETRY,
      handler.ProcessGetUpdatesResponse(progress, new_context, updates, &status)
          .value());
  handler.ApplyUpdates(&status);

  EXPECT_FALSE(EntryExists(e2->id_string()));

  {
    sync_pb::DataTypeContext dir_context;
    syncable::ReadTransaction trans(FROM_HERE, dir());
    trans.directory()->GetDataTypeContext(&trans, SYNCED_NOTIFICATIONS,
                                          &dir_context);
    EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString());
  }
}

// Tests that IsInitialSyncEnded value is updated by ApplyUpdates, but not by
// ProcessGetUpdatesResponse.
TEST_F(DirectoryUpdateHandlerProcessUpdateTest, IsInitialSyncEnded) {
  DirectoryTypeDebugInfoEmitter emitter(AUTOFILL, &type_observers_);
  DirectoryUpdateHandler handler(dir(), AUTOFILL, ui_worker(), &emitter);
  StatusController status;

  EXPECT_FALSE(handler.IsInitialSyncEnded());

  sync_pb::DataTypeProgressMarker progress;
  progress.set_data_type_id(GetSpecificsFieldNumberFromModelType(AUTOFILL));
  progress.set_token("token");
  progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 10);

  std::unique_ptr<sync_pb::SyncEntity> e = CreateUpdate(
      SyncableIdToProto(Id::CreateFromServerId("e1")), "", AUTOFILL);

  SyncEntityList updates;
  updates.push_back(e.get());

  handler.ProcessGetUpdatesResponse(progress, sync_pb::DataTypeContext(),
                                    updates, &status);

  EXPECT_FALSE(handler.IsInitialSyncEnded());

  handler.ApplyUpdates(&status);
  EXPECT_TRUE(handler.IsInitialSyncEnded());
}

// A test harness for tests that focus on applying updates.
//
// Update application is performed when we want to take updates that were
// previously downloaded, processed, and stored in our syncable::Directory
// and use them to update our local state (both the Directory's local state
// and the model's local state, though these tests focus only on the Directory's
// local state).
//
// This is kept separate from the update processing test in part for historical
// reasons, and in part because these tests may require a bit more infrastrcture
// in the future.  Update application should happen on a different thread a lot
// of the time so these tests may end up requiring more infrastructure than the
// update processing tests.  Currently, we're bypassing most of those issues by
// using FakeModelWorkers, so there's not much difference between the two test
// harnesses.
class DirectoryUpdateHandlerApplyUpdateTest : public ::testing::Test {
 public:
  DirectoryUpdateHandlerApplyUpdateTest()
      : ui_worker_(new FakeModelWorker(GROUP_UI)),
        password_worker_(new FakeModelWorker(GROUP_PASSWORD)),
        passive_worker_(new FakeModelWorker(GROUP_PASSIVE)),
        bookmarks_emitter_(BOOKMARKS, &type_observers_),
        passwords_emitter_(PASSWORDS, &type_observers_),
        articles_emitter_(DEPRECATED_ARTICLES, &type_observers_) {}

  void SetUp() override {
    dir_maker_.SetUp();
    entry_factory_ = std::make_unique<TestEntryFactory>(directory());

    update_handler_map_.insert(std::make_pair(
        BOOKMARKS,
        std::make_unique<DirectoryUpdateHandler>(
            directory(), BOOKMARKS, ui_worker_, &bookmarks_emitter_)));
    update_handler_map_.insert(std::make_pair(
        PASSWORDS,
        std::make_unique<DirectoryUpdateHandler>(
            directory(), PASSWORDS, password_worker_, &passwords_emitter_)));
  }

  void TearDown() override { dir_maker_.TearDown(); }

  const UpdateCounters& GetBookmarksUpdateCounters() {
    return bookmarks_emitter_.GetUpdateCounters();
  }

  const UpdateCounters& GetPasswordsUpdateCounters() {
    return passwords_emitter_.GetUpdateCounters();
  }

  const UpdateCounters& GetArticlesUpdateCounters() {
    return articles_emitter_.GetUpdateCounters();
  }

 protected:
  void ApplyBookmarkUpdates(StatusController* status) {
    update_handler_map_.find(BOOKMARKS)->second->ApplyUpdates(status);
  }

  void ApplyPasswordUpdates(StatusController* status) {
    update_handler_map_.find(PASSWORDS)->second->ApplyUpdates(status);
  }

  TestEntryFactory* entry_factory() { return entry_factory_.get(); }

  syncable::Directory* directory() { return dir_maker_.directory(); }

 private:
  // Needed to initialize the directory.
  base::test::ScopedTaskEnvironment task_environment_;
  TestDirectorySetterUpper dir_maker_;
  std::unique_ptr<TestEntryFactory> entry_factory_;

  scoped_refptr<FakeModelWorker> ui_worker_;
  scoped_refptr<FakeModelWorker> password_worker_;
  scoped_refptr<FakeModelWorker> passive_worker_;

  base::ObserverList<TypeDebugInfoObserver>::Unchecked type_observers_;
  DirectoryTypeDebugInfoEmitter bookmarks_emitter_;
  DirectoryTypeDebugInfoEmitter passwords_emitter_;
  DirectoryTypeDebugInfoEmitter articles_emitter_;

  std::map<ModelType, std::unique_ptr<UpdateHandler>> update_handler_map_;
};

namespace {
sync_pb::EntitySpecifics DefaultBookmarkSpecifics() {
  sync_pb::EntitySpecifics result;
  AddDefaultFieldValue(BOOKMARKS, &result);
  return result;
}
}  // namespace

// Test update application for a few bookmark items.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SimpleBookmark) {
  StatusController status;

  std::string root_server_id = Id::GetRoot().GetServerId();
  int64_t parent_handle =
      entry_factory()->CreateUnappliedNewBookmarkItemWithParent(
          "parent", DefaultBookmarkSpecifics(), root_server_id);
  int64_t child_handle =
      entry_factory()->CreateUnappliedNewBookmarkItemWithParent(
          "child", DefaultBookmarkSpecifics(), "parent");

  ApplyBookmarkUpdates(&status);

  const UpdateCounters& counter = GetBookmarksUpdateCounters();
  EXPECT_EQ(0, counter.num_encryption_conflict_application_failures)
      << "Simple update shouldn't result in conflicts";
  EXPECT_EQ(0, counter.num_hierarchy_conflict_application_failures)
      << "Simple update shouldn't result in conflicts";
  EXPECT_EQ(2, counter.num_updates_applied)
      << "All items should have been successfully applied";

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());

    syncable::Entry parent(&trans, syncable::GET_BY_HANDLE, parent_handle);
    syncable::Entry child(&trans, syncable::GET_BY_HANDLE, child_handle);

    ASSERT_TRUE(parent.good());
    ASSERT_TRUE(child.good());

    EXPECT_FALSE(parent.GetIsUnsynced());
    EXPECT_FALSE(parent.GetIsUnappliedUpdate());
    EXPECT_FALSE(child.GetIsUnsynced());
    EXPECT_FALSE(child.GetIsUnappliedUpdate());
  }
}

// Test that the applicator can handle updates delivered out of order.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, BookmarkChildrenBeforeParent) {
  // Start with some bookmarks whose parents are unknown.
  std::string root_server_id = Id::GetRoot().GetServerId();
  int64_t a_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent(
      "a_child_created_first", DefaultBookmarkSpecifics(), "parent");
  int64_t x_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent(
      "x_child_created_first", DefaultBookmarkSpecifics(), "parent");

  // Update application will fail.
  StatusController status1;
  ApplyBookmarkUpdates(&status1);
  EXPECT_EQ(0, status1.num_updates_applied());
  EXPECT_EQ(2, status1.num_hierarchy_conflicts());

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());

    syncable::Entry a(&trans, syncable::GET_BY_HANDLE, a_handle);
    syncable::Entry x(&trans, syncable::GET_BY_HANDLE, x_handle);

    ASSERT_TRUE(a.good());
    ASSERT_TRUE(x.good());

    EXPECT_TRUE(a.GetIsUnappliedUpdate());
    EXPECT_TRUE(x.GetIsUnappliedUpdate());
  }

  // Now add their parent and a few siblings.
  entry_factory()->CreateUnappliedNewBookmarkItemWithParent(
      "parent", DefaultBookmarkSpecifics(), root_server_id);
  entry_factory()->CreateUnappliedNewBookmarkItemWithParent(
      "a_child_created_second", DefaultBookmarkSpecifics(), "parent");
  entry_factory()->CreateUnappliedNewBookmarkItemWithParent(
      "x_child_created_second", DefaultBookmarkSpecifics(), "parent");

  // Update application will succeed.
  StatusController status2;
  ApplyBookmarkUpdates(&status2);
  EXPECT_EQ(5, status2.num_updates_applied())
      << "All updates should have been successfully applied";

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());

    syncable::Entry a(&trans, syncable::GET_BY_HANDLE, a_handle);
    syncable::Entry x(&trans, syncable::GET_BY_HANDLE, x_handle);

    ASSERT_TRUE(a.good());
    ASSERT_TRUE(x.good());

    EXPECT_FALSE(a.GetIsUnappliedUpdate());
    EXPECT_FALSE(x.GetIsUnappliedUpdate());
  }
}

// Try to apply changes on an item that is both IS_UNSYNCED and
// IS_UNAPPLIED_UPDATE.  Conflict resolution should be performed.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SimpleBookmarkConflict) {
  int64_t handle = entry_factory()->CreateUnappliedAndUnsyncedBookmarkItem("x");

  int original_server_version = -10;
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle);
    original_server_version = e.GetServerVersion();
    ASSERT_NE(original_server_version, e.GetBaseVersion());
    EXPECT_TRUE(e.GetIsUnsynced());
  }

  StatusController status;
  ApplyBookmarkUpdates(&status);

  const UpdateCounters& counters = GetBookmarksUpdateCounters();
  EXPECT_EQ(1, counters.num_server_overwrites)
      << "Unsynced and unapplied item conflict should be resolved";
  EXPECT_EQ(0, counters.num_updates_applied)
      << "Update should not be applied; we should override the server.";

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle);
    ASSERT_TRUE(e.good());
    EXPECT_EQ(original_server_version, e.GetServerVersion());
    EXPECT_EQ(original_server_version, e.GetBaseVersion());
    EXPECT_FALSE(e.GetIsUnappliedUpdate());

    // The unsynced flag will remain set until we successfully commit the item.
    EXPECT_TRUE(e.GetIsUnsynced());
  }
}

// Create a simple conflict that is also a hierarchy conflict.  If we were to
// follow the normal "server wins" logic, we'd end up violating hierarchy
// constraints.  The hierarchy conflict must take precedence.  We can not allow
// the update to be applied.  The item must remain in the conflict state.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, HierarchyAndSimpleConflict) {
  // Create a simply-conflicting item.  It will start with valid parent ids.
  int64_t handle = entry_factory()->CreateUnappliedAndUnsyncedBookmarkItem(
      "orphaned_by_server");
  {
    // Manually set the SERVER_PARENT_ID to bad value.
    // A bad parent indicates a hierarchy conflict.
    syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory());
    syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle);
    ASSERT_TRUE(entry.good());

    entry.PutServerParentId(TestIdFactory::MakeServer("bogus_parent"));
  }

  StatusController status;
  ApplyBookmarkUpdates(&status);

  const UpdateCounters& counters = GetBookmarksUpdateCounters();
  EXPECT_EQ(0, counters.num_updates_applied);
  EXPECT_EQ(0, counters.num_server_overwrites);
  EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures);

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle);
    ASSERT_TRUE(e.good());
    EXPECT_TRUE(e.GetIsUnappliedUpdate());
    EXPECT_TRUE(e.GetIsUnsynced());
  }
}

// Attempt to apply an udpate that would create a bookmark folder loop.  This
// application should fail.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, BookmarkFolderLoop) {
  // Item 'X' locally has parent of 'root'.  Server is updating it to have
  // parent of 'Y'.

  // Create it as a child of root node.
  int64_t handle = entry_factory()->CreateSyncedItem("X", BOOKMARKS, true);

  {
    syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory());
    syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle);
    ASSERT_TRUE(entry.good());

    // Re-parent from root to "Y"
    entry.PutServerVersion(entry_factory()->GetNextRevision());
    entry.PutIsUnappliedUpdate(true);
    entry.PutServerParentId(TestIdFactory::MakeServer("Y"));
  }

  // Item 'Y' is child of 'X'.
  entry_factory()->CreateUnsyncedItem(TestIdFactory::MakeServer("Y"),
                                      TestIdFactory::MakeServer("X"), "Y", true,
                                      BOOKMARKS, nullptr);

  // If the server's update were applied, we would have X be a child of Y, and Y
  // as a child of X.  That's a directory loop.  The UpdateApplicator should
  // prevent the update from being applied and note that this is a hierarchy
  // conflict.

  StatusController status;
  ApplyBookmarkUpdates(&status);

  // This should count as a hierarchy conflict.
  const UpdateCounters& counters = GetBookmarksUpdateCounters();
  EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures);

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle);
    ASSERT_TRUE(e.good());
    EXPECT_TRUE(e.GetIsUnappliedUpdate());
    EXPECT_FALSE(e.GetIsUnsynced());
  }
}

// Test update application where the update has been orphaned by a local folder
// deletion.  The update application attempt should fail.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, HierarchyConflictDeletedParent) {
  // Create a locally deleted parent item.
  int64_t parent_handle;
  entry_factory()->CreateUnsyncedItem(Id::CreateFromServerId("parent"),
                                      TestIdFactory::root(), "parent", true,
                                      BOOKMARKS, &parent_handle);
  {
    syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory());
    syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE,
                                 parent_handle);
    entry.PutIsDel(true);
  }

  // Create an incoming child from the server.
  int64_t child_handle = entry_factory()->CreateUnappliedNewItemWithParent(
      "child", DefaultBookmarkSpecifics(), "parent");

  // The server's update may seem valid to some other client, but on this client
  // that new item's parent no longer exists.  The update should not be applied
  // and the update applicator should indicate this is a hierarchy conflict.

  StatusController status;
  ApplyBookmarkUpdates(&status);
  const UpdateCounters& counters = GetBookmarksUpdateCounters();
  EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures);

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry child(&trans, syncable::GET_BY_HANDLE, child_handle);
    ASSERT_TRUE(child.good());
    EXPECT_TRUE(child.GetIsUnappliedUpdate());
    EXPECT_FALSE(child.GetIsUnsynced());
  }
}

// Attempt to apply an update that deletes a folder where the folder has
// locally-created children.  The update application should fail.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest,
       HierarchyConflictDeleteNonEmptyDirectory) {
  // Create a server-deleted folder as a child of root node.
  int64_t parent_handle =
      entry_factory()->CreateSyncedItem("parent", BOOKMARKS, true);
  {
    syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory());
    syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE,
                                 parent_handle);
    ASSERT_TRUE(entry.good());

    // Delete it on the server.
    entry.PutServerVersion(entry_factory()->GetNextRevision());
    entry.PutIsUnappliedUpdate(true);
    entry.PutServerParentId(TestIdFactory::root());
    entry.PutServerIsDel(true);
  }

  // Create a local child of the server-deleted directory.
  entry_factory()->CreateUnsyncedItem(TestIdFactory::MakeServer("child"),
                                      TestIdFactory::MakeServer("parent"),
                                      "child", false, BOOKMARKS, nullptr);

  // The server's request to delete the directory must be ignored, otherwise our
  // unsynced new child would be orphaned.  This is a hierarchy conflict.

  StatusController status;
  ApplyBookmarkUpdates(&status);

  // This should count as a hierarchy conflict.
  const UpdateCounters& counters = GetBookmarksUpdateCounters();
  EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures);

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry parent(&trans, syncable::GET_BY_HANDLE, parent_handle);
    ASSERT_TRUE(parent.good());
    EXPECT_TRUE(parent.GetIsUnappliedUpdate());
    EXPECT_FALSE(parent.GetIsUnsynced());
  }
}

// Attempt to apply updates where the updated item's parent is not known to this
// client.  The update application attempt should fail.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, HierarchyConflictUnknownParent) {
  // We shouldn't be able to do anything with either of these items.
  int64_t x_handle = entry_factory()->CreateUnappliedNewItemWithParent(
      "some_item", DefaultBookmarkSpecifics(), "unknown_parent");
  int64_t y_handle = entry_factory()->CreateUnappliedNewItemWithParent(
      "some_other_item", DefaultBookmarkSpecifics(), "some_item");

  StatusController status;
  ApplyBookmarkUpdates(&status);

  const UpdateCounters& counters = GetBookmarksUpdateCounters();
  EXPECT_EQ(2, counters.num_hierarchy_conflict_application_failures)
      << "All updates with an unknown ancestors should be in conflict";
  EXPECT_EQ(0, counters.num_updates_applied)
      << "No item with an unknown ancestor should be applied";

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry x(&trans, syncable::GET_BY_HANDLE, x_handle);
    syncable::Entry y(&trans, syncable::GET_BY_HANDLE, y_handle);
    ASSERT_TRUE(x.good());
    ASSERT_TRUE(y.good());
    EXPECT_TRUE(x.GetIsUnappliedUpdate());
    EXPECT_TRUE(y.GetIsUnappliedUpdate());
    EXPECT_FALSE(x.GetIsUnsynced());
    EXPECT_FALSE(y.GetIsUnsynced());
  }
}

// Attempt application of a mix of items.  Some update application attempts will
// fail due to hierarchy conflicts.  Others should succeed.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, ItemsBothKnownAndUnknown) {
  // See what happens when there's a mixture of good and bad updates.
  std::string root_server_id = Id::GetRoot().GetServerId();
  int64_t u1_handle = entry_factory()->CreateUnappliedNewItemWithParent(
      "first_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent");
  int64_t k1_handle = entry_factory()->CreateUnappliedNewItemWithParent(
      "first_known_item", DefaultBookmarkSpecifics(), root_server_id);
  int64_t u2_handle = entry_factory()->CreateUnappliedNewItemWithParent(
      "second_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent");
  int64_t k2_handle = entry_factory()->CreateUnappliedNewItemWithParent(
      "second_known_item", DefaultBookmarkSpecifics(), "first_known_item");
  int64_t k3_handle = entry_factory()->CreateUnappliedNewItemWithParent(
      "third_known_item", DefaultBookmarkSpecifics(), "fourth_known_item");
  int64_t k4_handle = entry_factory()->CreateUnappliedNewItemWithParent(
      "fourth_known_item", DefaultBookmarkSpecifics(), root_server_id);

  StatusController status;
  ApplyBookmarkUpdates(&status);

  const UpdateCounters& counters = GetBookmarksUpdateCounters();
  EXPECT_EQ(2, counters.num_hierarchy_conflict_application_failures)
      << "The updates with unknown ancestors should be in conflict";
  EXPECT_EQ(4, counters.num_updates_applied)
      << "The updates with known ancestors should be successfully applied";

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry u1(&trans, syncable::GET_BY_HANDLE, u1_handle);
    syncable::Entry u2(&trans, syncable::GET_BY_HANDLE, u2_handle);
    syncable::Entry k1(&trans, syncable::GET_BY_HANDLE, k1_handle);
    syncable::Entry k2(&trans, syncable::GET_BY_HANDLE, k2_handle);
    syncable::Entry k3(&trans, syncable::GET_BY_HANDLE, k3_handle);
    syncable::Entry k4(&trans, syncable::GET_BY_HANDLE, k4_handle);
    ASSERT_TRUE(u1.good());
    ASSERT_TRUE(u2.good());
    ASSERT_TRUE(k1.good());
    ASSERT_TRUE(k2.good());
    ASSERT_TRUE(k3.good());
    ASSERT_TRUE(k4.good());
    EXPECT_TRUE(u1.GetIsUnappliedUpdate());
    EXPECT_TRUE(u2.GetIsUnappliedUpdate());
    EXPECT_FALSE(k1.GetIsUnappliedUpdate());
    EXPECT_FALSE(k2.GetIsUnappliedUpdate());
    EXPECT_FALSE(k3.GetIsUnappliedUpdate());
    EXPECT_FALSE(k4.GetIsUnappliedUpdate());
  }
}

// Attempt application of password upates where the passphrase is known.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, DecryptablePassword) {
  // Decryptable password updates should be applied.
  Cryptographer* cryptographer;
  {
    // Storing the cryptographer separately is bad, but for this test we
    // know it's safe.
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
  }

  KeyParams params = {KeyDerivationParams::CreateForPbkdf2(), "foobar"};
  cryptographer->AddKey(params);

  sync_pb::EntitySpecifics specifics;
  sync_pb::PasswordSpecificsData data;
  data.set_origin("http://example.com");

  cryptographer->Encrypt(data,
                         specifics.mutable_password()->mutable_encrypted());
  int64_t handle =
      entry_factory()->CreateUnappliedNewItem("item", specifics, false);

  StatusController status;
  ApplyPasswordUpdates(&status);

  const UpdateCounters& counters = GetPasswordsUpdateCounters();
  EXPECT_EQ(1, counters.num_updates_applied)
      << "The updates that can be decrypted should be applied";

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle);
    ASSERT_TRUE(e.good());
    EXPECT_FALSE(e.GetIsUnappliedUpdate());
    EXPECT_FALSE(e.GetIsUnsynced());
  }
}

// Attempt application of encrypted items when the passphrase is not known.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, UndecryptableData) {
  // Undecryptable updates should not be applied.
  sync_pb::EntitySpecifics encrypted_bookmark;
  encrypted_bookmark.mutable_encrypted();
  AddDefaultFieldValue(BOOKMARKS, &encrypted_bookmark);
  std::string root_server_id = Id::GetRoot().GetServerId();
  int64_t folder_handle = entry_factory()->CreateUnappliedNewItemWithParent(
      "folder", encrypted_bookmark, root_server_id);
  int64_t bookmark_handle = entry_factory()->CreateUnappliedNewItem(
      "item2", encrypted_bookmark, false);
  sync_pb::EntitySpecifics encrypted_password;
  encrypted_password.mutable_password();
  int64_t password_handle = entry_factory()->CreateUnappliedNewItem(
      "item3", encrypted_password, false);

  StatusController status;
  ApplyBookmarkUpdates(&status);
  ApplyPasswordUpdates(&status);

  const UpdateCounters& bm_counters = GetBookmarksUpdateCounters();
  EXPECT_EQ(2, bm_counters.num_encryption_conflict_application_failures)
      << "Updates that can't be decrypted should be in encryption conflict";
  EXPECT_EQ(0, bm_counters.num_updates_applied)
      << "No update that can't be decrypted should be applied";

  const UpdateCounters& pw_counters = GetPasswordsUpdateCounters();
  EXPECT_EQ(1, pw_counters.num_encryption_conflict_application_failures)
      << "Updates that can't be decrypted should be in encryption conflict";
  EXPECT_EQ(0, pw_counters.num_updates_applied)
      << "No update that can't be decrypted should be applied";

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry folder(&trans, syncable::GET_BY_HANDLE, folder_handle);
    syncable::Entry bm(&trans, syncable::GET_BY_HANDLE, bookmark_handle);
    syncable::Entry pw(&trans, syncable::GET_BY_HANDLE, password_handle);
    ASSERT_TRUE(folder.good());
    ASSERT_TRUE(bm.good());
    ASSERT_TRUE(pw.good());
    EXPECT_TRUE(folder.GetIsUnappliedUpdate());
    EXPECT_TRUE(bm.GetIsUnappliedUpdate());
    EXPECT_TRUE(pw.GetIsUnappliedUpdate());
  }
}

// Test a mix of decryptable and undecryptable updates.
TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SomeUndecryptablePassword) {
  Cryptographer* cryptographer;

  int64_t decryptable_handle = -1;
  int64_t undecryptable_handle = -1;

  // Only decryptable password updates should be applied.
  {
    sync_pb::EntitySpecifics specifics;
    sync_pb::PasswordSpecificsData data;
    data.set_origin("http://example.com/1");
    {
      syncable::ReadTransaction trans(FROM_HERE, directory());
      cryptographer = directory()->GetCryptographer(&trans);

      KeyParams params = {KeyDerivationParams::CreateForPbkdf2(), "foobar"};
      cryptographer->AddKey(params);

      cryptographer->Encrypt(data,
                             specifics.mutable_password()->mutable_encrypted());
    }
    decryptable_handle =
        entry_factory()->CreateUnappliedNewItem("item1", specifics, false);
  }
  {
    // Create a new cryptographer, independent of the one in the cycle.
    Cryptographer other_cryptographer(cryptographer->encryptor());
    KeyParams params = {KeyDerivationParams::CreateForPbkdf2(), "bazqux"};
    other_cryptographer.AddKey(params);

    sync_pb::EntitySpecifics specifics;
    sync_pb::PasswordSpecificsData data;
    data.set_origin("http://example.com/2");

    other_cryptographer.Encrypt(
        data, specifics.mutable_password()->mutable_encrypted());
    undecryptable_handle =
        entry_factory()->CreateUnappliedNewItem("item2", specifics, false);
  }

  StatusController status;
  ApplyPasswordUpdates(&status);

  const UpdateCounters& counters = GetPasswordsUpdateCounters();
  EXPECT_EQ(1, counters.num_encryption_conflict_application_failures)
      << "The updates that can't be decrypted should be in encryption "
      << "conflict";
  EXPECT_EQ(1, counters.num_updates_applied)
      << "The undecryptable password update shouldn't be applied";

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    syncable::Entry e1(&trans, syncable::GET_BY_HANDLE, decryptable_handle);
    syncable::Entry e2(&trans, syncable::GET_BY_HANDLE, undecryptable_handle);
    ASSERT_TRUE(e1.good());
    ASSERT_TRUE(e2.good());
    EXPECT_FALSE(e1.GetIsUnappliedUpdate());
    EXPECT_TRUE(e2.GetIsUnappliedUpdate());
  }
}

}  // namespace syncer
