// Copyright 2012 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.

// Unit tests for the SyncApi. Note that a lot of the underlying
// functionality is provided by the Syncable layer, which has its own
// unit tests. We'll test SyncApi specific things in this harness.

#include <cstddef>
#include <map>

#include "base/basictypes.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/values_test_util.h"
#include "base/values.h"
#include "google_apis/gaia/gaia_constants.h"
#include "sync/engine/sync_scheduler.h"
#include "sync/internal_api/public/base/attachment_id_proto.h"
#include "sync/internal_api/public/base/cancelation_signal.h"
#include "sync/internal_api/public/base/model_type_test_util.h"
#include "sync/internal_api/public/change_record.h"
#include "sync/internal_api/public/engine/model_safe_worker.h"
#include "sync/internal_api/public/engine/polling_constants.h"
#include "sync/internal_api/public/events/protocol_event.h"
#include "sync/internal_api/public/http_post_provider_factory.h"
#include "sync/internal_api/public/http_post_provider_interface.h"
#include "sync/internal_api/public/read_node.h"
#include "sync/internal_api/public/read_transaction.h"
#include "sync/internal_api/public/test/test_entry_factory.h"
#include "sync/internal_api/public/test/test_internal_components_factory.h"
#include "sync/internal_api/public/test/test_user_share.h"
#include "sync/internal_api/public/write_node.h"
#include "sync/internal_api/public/write_transaction.h"
#include "sync/internal_api/sync_encryption_handler_impl.h"
#include "sync/internal_api/sync_manager_impl.h"
#include "sync/internal_api/syncapi_internal.h"
#include "sync/js/js_backend.h"
#include "sync/js/js_event_handler.h"
#include "sync/js/js_test_util.h"
#include "sync/protocol/bookmark_specifics.pb.h"
#include "sync/protocol/encryption.pb.h"
#include "sync/protocol/extension_specifics.pb.h"
#include "sync/protocol/password_specifics.pb.h"
#include "sync/protocol/preference_specifics.pb.h"
#include "sync/protocol/proto_value_conversions.h"
#include "sync/protocol/sync.pb.h"
#include "sync/sessions/sync_session.h"
#include "sync/syncable/directory.h"
#include "sync/syncable/entry.h"
#include "sync/syncable/mutable_entry.h"
#include "sync/syncable/nigori_util.h"
#include "sync/syncable/syncable_id.h"
#include "sync/syncable/syncable_read_transaction.h"
#include "sync/syncable/syncable_util.h"
#include "sync/syncable/syncable_write_transaction.h"
#include "sync/test/callback_counter.h"
#include "sync/test/engine/fake_model_worker.h"
#include "sync/test/engine/fake_sync_scheduler.h"
#include "sync/test/engine/test_id_factory.h"
#include "sync/test/fake_encryptor.h"
#include "sync/util/cryptographer.h"
#include "sync/util/extensions_activity.h"
#include "sync/util/test_unrecoverable_error_handler.h"
#include "sync/util/time.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

using base::ExpectDictStringValue;
using testing::_;
using testing::DoAll;
using testing::InSequence;
using testing::Return;
using testing::SaveArg;
using testing::StrictMock;

namespace syncer {

using sessions::SyncSessionSnapshot;
using syncable::GET_BY_HANDLE;
using syncable::IS_DEL;
using syncable::IS_UNSYNCED;
using syncable::NON_UNIQUE_NAME;
using syncable::SPECIFICS;
using syncable::kEncryptedString;

namespace {

// Makes a non-folder child of the root node.  Returns the id of the
// newly-created node.
int64 MakeNode(UserShare* share,
               ModelType model_type,
               const std::string& client_tag) {
  WriteTransaction trans(FROM_HERE, share);
  ReadNode root_node(&trans);
  root_node.InitByRootLookup();
  WriteNode node(&trans);
  WriteNode::InitUniqueByCreationResult result =
      node.InitUniqueByCreation(model_type, root_node, client_tag);
  EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
  node.SetIsFolder(false);
  return node.GetId();
}

// Makes a folder child of a non-root node. Returns the id of the
// newly-created node.
int64 MakeFolderWithParent(UserShare* share,
                           ModelType model_type,
                           int64 parent_id,
                           BaseNode* predecessor) {
  WriteTransaction trans(FROM_HERE, share);
  ReadNode parent_node(&trans);
  EXPECT_EQ(BaseNode::INIT_OK, parent_node.InitByIdLookup(parent_id));
  WriteNode node(&trans);
  EXPECT_TRUE(node.InitBookmarkByCreation(parent_node, predecessor));
  node.SetIsFolder(true);
  return node.GetId();
}

int64 MakeBookmarkWithParent(UserShare* share,
                             int64 parent_id,
                             BaseNode* predecessor) {
  WriteTransaction trans(FROM_HERE, share);
  ReadNode parent_node(&trans);
  EXPECT_EQ(BaseNode::INIT_OK, parent_node.InitByIdLookup(parent_id));
  WriteNode node(&trans);
  EXPECT_TRUE(node.InitBookmarkByCreation(parent_node, predecessor));
  return node.GetId();
}

// Creates the "synced" root node for a particular datatype. We use the syncable
// methods here so that the syncer treats these nodes as if they were already
// received from the server.
int64 MakeServerNodeForType(UserShare* share,
                            ModelType model_type) {
  sync_pb::EntitySpecifics specifics;
  AddDefaultFieldValue(model_type, &specifics);
  syncable::WriteTransaction trans(
      FROM_HERE, syncable::UNITTEST, share->directory.get());
  // Attempt to lookup by nigori tag.
  std::string type_tag = ModelTypeToRootTag(model_type);
  syncable::Id node_id = syncable::Id::CreateFromServerId(type_tag);
  syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
                               node_id);
  EXPECT_TRUE(entry.good());
  entry.PutBaseVersion(1);
  entry.PutServerVersion(1);
  entry.PutIsUnappliedUpdate(false);
  entry.PutServerParentId(syncable::GetNullId());
  entry.PutServerIsDir(true);
  entry.PutIsDir(true);
  entry.PutServerSpecifics(specifics);
  entry.PutUniqueServerTag(type_tag);
  entry.PutNonUniqueName(type_tag);
  entry.PutIsDel(false);
  entry.PutSpecifics(specifics);
  return entry.GetMetahandle();
}

// Simulates creating a "synced" node as a child of the root datatype node.
int64 MakeServerNode(UserShare* share, ModelType model_type,
                     const std::string& client_tag,
                     const std::string& hashed_tag,
                     const sync_pb::EntitySpecifics& specifics) {
  syncable::WriteTransaction trans(
      FROM_HERE, syncable::UNITTEST, share->directory.get());
  syncable::Entry root_entry(&trans, syncable::GET_TYPE_ROOT, model_type);
  EXPECT_TRUE(root_entry.good());
  syncable::Id root_id = root_entry.GetId();
  syncable::Id node_id = syncable::Id::CreateFromServerId(client_tag);
  syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM,
                               node_id);
  EXPECT_TRUE(entry.good());
  entry.PutBaseVersion(1);
  entry.PutServerVersion(1);
  entry.PutIsUnappliedUpdate(false);
  entry.PutServerParentId(root_id);
  entry.PutParentId(root_id);
  entry.PutServerIsDir(false);
  entry.PutIsDir(false);
  entry.PutServerSpecifics(specifics);
  entry.PutNonUniqueName(client_tag);
  entry.PutUniqueClientTag(hashed_tag);
  entry.PutIsDel(false);
  entry.PutSpecifics(specifics);
  return entry.GetMetahandle();
}

}  // namespace

class SyncApiTest : public testing::Test {
 public:
  virtual void SetUp() {
    test_user_share_.SetUp();
  }

  virtual void TearDown() {
    test_user_share_.TearDown();
  }

 protected:
  // Create an entry with the given |model_type|, |client_tag| and
  // |attachment_metadata|.
  void CreateEntryWithAttachmentMetadata(
      const ModelType& model_type,
      const std::string& client_tag,
      const sync_pb::AttachmentMetadata& attachment_metadata);

  // Attempts to load the entry specified by |model_type| and |client_tag| and
  // returns the lookup result code.
  BaseNode::InitByLookupResult LookupEntryByClientTag(
      const ModelType& model_type,
      const std::string& client_tag);

  // Replace the entry specified by |model_type| and |client_tag| with a
  // tombstone.
  void ReplaceWithTombstone(const ModelType& model_type,
                            const std::string& client_tag);

  // Save changes to the Directory, destroy it then reload it.
  bool ReloadDir();

  UserShare* user_share();
  syncable::Directory* dir();
  SyncEncryptionHandler* encryption_handler();

 private:
  base::MessageLoop message_loop_;
  TestUserShare test_user_share_;
};

UserShare* SyncApiTest::user_share() {
  return test_user_share_.user_share();
}

syncable::Directory* SyncApiTest::dir() {
  return test_user_share_.user_share()->directory.get();
}

SyncEncryptionHandler* SyncApiTest::encryption_handler() {
  return test_user_share_.encryption_handler();
}

bool SyncApiTest::ReloadDir() {
  return test_user_share_.Reload();
}

void SyncApiTest::CreateEntryWithAttachmentMetadata(
    const ModelType& model_type,
    const std::string& client_tag,
    const sync_pb::AttachmentMetadata& attachment_metadata) {
  syncer::WriteTransaction trans(FROM_HERE, user_share());
  syncer::ReadNode root_node(&trans);
  root_node.InitByRootLookup();
  syncer::WriteNode node(&trans);
  ASSERT_EQ(node.InitUniqueByCreation(model_type, root_node, client_tag),
            syncer::WriteNode::INIT_SUCCESS);
  node.SetAttachmentMetadata(attachment_metadata);
}

BaseNode::InitByLookupResult SyncApiTest::LookupEntryByClientTag(
    const ModelType& model_type,
    const std::string& client_tag) {
  syncer::ReadTransaction trans(FROM_HERE, user_share());
  syncer::ReadNode node(&trans);
  return node.InitByClientTagLookup(model_type, client_tag);
}

void SyncApiTest::ReplaceWithTombstone(const ModelType& model_type,
                                       const std::string& client_tag) {
  syncer::WriteTransaction trans(FROM_HERE, user_share());
  syncer::WriteNode node(&trans);
  ASSERT_EQ(node.InitByClientTagLookup(model_type, client_tag),
            syncer::WriteNode::INIT_OK);
  node.Tombstone();
}

TEST_F(SyncApiTest, SanityCheckTest) {
  {
    ReadTransaction trans(FROM_HERE, user_share());
    EXPECT_TRUE(trans.GetWrappedTrans());
  }
  {
    WriteTransaction trans(FROM_HERE, user_share());
    EXPECT_TRUE(trans.GetWrappedTrans());
  }
  {
    // No entries but root should exist
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode node(&trans);
    // Metahandle 1 can be root, sanity check 2
    EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD, node.InitByIdLookup(2));
  }
}

TEST_F(SyncApiTest, BasicTagWrite) {
  {
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode root_node(&trans);
    root_node.InitByRootLookup();
    EXPECT_EQ(root_node.GetFirstChildId(), 0);
  }

  ignore_result(MakeNode(user_share(), BOOKMARKS, "testtag"));

  {
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, "testtag"));

    ReadNode root_node(&trans);
    root_node.InitByRootLookup();
    EXPECT_NE(node.GetId(), 0);
    EXPECT_EQ(node.GetId(), root_node.GetFirstChildId());
  }
}

TEST_F(SyncApiTest, ModelTypesSiloed) {
  {
    WriteTransaction trans(FROM_HERE, user_share());
    ReadNode root_node(&trans);
    root_node.InitByRootLookup();
    EXPECT_EQ(root_node.GetFirstChildId(), 0);
  }

  ignore_result(MakeNode(user_share(), BOOKMARKS, "collideme"));
  ignore_result(MakeNode(user_share(), PREFERENCES, "collideme"));
  ignore_result(MakeNode(user_share(), AUTOFILL, "collideme"));

  {
    ReadTransaction trans(FROM_HERE, user_share());

    ReadNode bookmarknode(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              bookmarknode.InitByClientTagLookup(BOOKMARKS,
                  "collideme"));

    ReadNode prefnode(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              prefnode.InitByClientTagLookup(PREFERENCES,
                  "collideme"));

    ReadNode autofillnode(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              autofillnode.InitByClientTagLookup(AUTOFILL,
                  "collideme"));

    EXPECT_NE(bookmarknode.GetId(), prefnode.GetId());
    EXPECT_NE(autofillnode.GetId(), prefnode.GetId());
    EXPECT_NE(bookmarknode.GetId(), autofillnode.GetId());
  }
}

TEST_F(SyncApiTest, ReadMissingTagsFails) {
  {
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD,
              node.InitByClientTagLookup(BOOKMARKS,
                  "testtag"));
  }
  {
    WriteTransaction trans(FROM_HERE, user_share());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD,
              node.InitByClientTagLookup(BOOKMARKS,
                  "testtag"));
  }
}

// TODO(chron): Hook this all up to the server and write full integration tests
//              for update->undelete behavior.
TEST_F(SyncApiTest, TestDeleteBehavior) {
  int64 node_id;
  int64 folder_id;
  std::string test_title("test1");

  {
    WriteTransaction trans(FROM_HERE, user_share());
    ReadNode root_node(&trans);
    root_node.InitByRootLookup();

    // we'll use this spare folder later
    WriteNode folder_node(&trans);
    EXPECT_TRUE(folder_node.InitBookmarkByCreation(root_node, NULL));
    folder_id = folder_node.GetId();

    WriteNode wnode(&trans);
    WriteNode::InitUniqueByCreationResult result =
        wnode.InitUniqueByCreation(BOOKMARKS, root_node, "testtag");
    EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
    wnode.SetIsFolder(false);
    wnode.SetTitle(test_title);

    node_id = wnode.GetId();
  }

  // Ensure we can delete something with a tag.
  {
    WriteTransaction trans(FROM_HERE, user_share());
    WriteNode wnode(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              wnode.InitByClientTagLookup(BOOKMARKS,
                  "testtag"));
    EXPECT_FALSE(wnode.GetIsFolder());
    EXPECT_EQ(wnode.GetTitle(), test_title);

    wnode.Tombstone();
  }

  // Lookup of a node which was deleted should return failure,
  // but have found some data about the node.
  {
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_IS_DEL,
              node.InitByClientTagLookup(BOOKMARKS,
                  "testtag"));
    // Note that for proper function of this API this doesn't need to be
    // filled, we're checking just to make sure the DB worked in this test.
    EXPECT_EQ(node.GetTitle(), test_title);
  }

  {
    WriteTransaction trans(FROM_HERE, user_share());
    ReadNode folder_node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, folder_node.InitByIdLookup(folder_id));

    WriteNode wnode(&trans);
    // This will undelete the tag.
    WriteNode::InitUniqueByCreationResult result =
        wnode.InitUniqueByCreation(BOOKMARKS, folder_node, "testtag");
    EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
    EXPECT_EQ(wnode.GetIsFolder(), false);
    EXPECT_EQ(wnode.GetParentId(), folder_node.GetId());
    EXPECT_EQ(wnode.GetId(), node_id);
    EXPECT_NE(wnode.GetTitle(), test_title);  // Title should be cleared
    wnode.SetTitle(test_title);
  }

  // Now look up should work.
  {
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS,
                    "testtag"));
    EXPECT_EQ(node.GetTitle(), test_title);
    EXPECT_EQ(node.GetModelType(), BOOKMARKS);
  }
}

TEST_F(SyncApiTest, WriteAndReadPassword) {
  KeyParams params = {"localhost", "username", "passphrase"};
  {
    ReadTransaction trans(FROM_HERE, user_share());
    trans.GetCryptographer()->AddKey(params);
  }
  {
    WriteTransaction trans(FROM_HERE, user_share());
    ReadNode root_node(&trans);
    root_node.InitByRootLookup();

    WriteNode password_node(&trans);
    WriteNode::InitUniqueByCreationResult result =
        password_node.InitUniqueByCreation(PASSWORDS,
                                           root_node, "foo");
    EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
    sync_pb::PasswordSpecificsData data;
    data.set_password_value("secret");
    password_node.SetPasswordSpecifics(data);
  }
  {
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode root_node(&trans);
    root_node.InitByRootLookup();

    ReadNode password_node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              password_node.InitByClientTagLookup(PASSWORDS, "foo"));
    const sync_pb::PasswordSpecificsData& data =
        password_node.GetPasswordSpecifics();
    EXPECT_EQ("secret", data.password_value());
  }
}

TEST_F(SyncApiTest, WriteEncryptedTitle) {
  KeyParams params = {"localhost", "username", "passphrase"};
  {
    ReadTransaction trans(FROM_HERE, user_share());
    trans.GetCryptographer()->AddKey(params);
  }
  encryption_handler()->EnableEncryptEverything();
  int bookmark_id;
  {
    WriteTransaction trans(FROM_HERE, user_share());
    ReadNode root_node(&trans);
    root_node.InitByRootLookup();

    WriteNode bookmark_node(&trans);
    ASSERT_TRUE(bookmark_node.InitBookmarkByCreation(root_node, NULL));
    bookmark_id = bookmark_node.GetId();
    bookmark_node.SetTitle("foo");

    WriteNode pref_node(&trans);
    WriteNode::InitUniqueByCreationResult result =
        pref_node.InitUniqueByCreation(PREFERENCES, root_node, "bar");
    ASSERT_EQ(WriteNode::INIT_SUCCESS, result);
    pref_node.SetTitle("bar");
  }
  {
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode root_node(&trans);
    root_node.InitByRootLookup();

    ReadNode bookmark_node(&trans);
    ASSERT_EQ(BaseNode::INIT_OK, bookmark_node.InitByIdLookup(bookmark_id));
    EXPECT_EQ("foo", bookmark_node.GetTitle());
    EXPECT_EQ(kEncryptedString,
              bookmark_node.GetEntry()->GetNonUniqueName());

    ReadNode pref_node(&trans);
    ASSERT_EQ(BaseNode::INIT_OK,
              pref_node.InitByClientTagLookup(PREFERENCES,
                                              "bar"));
    EXPECT_EQ(kEncryptedString, pref_node.GetTitle());
  }
}

TEST_F(SyncApiTest, BaseNodeSetSpecifics) {
  int64 child_id = MakeNode(user_share(), BOOKMARKS, "testtag");
  WriteTransaction trans(FROM_HERE, user_share());
  WriteNode node(&trans);
  EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(child_id));

  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_bookmark()->set_url("http://www.google.com");

  EXPECT_NE(entity_specifics.SerializeAsString(),
            node.GetEntitySpecifics().SerializeAsString());
  node.SetEntitySpecifics(entity_specifics);
  EXPECT_EQ(entity_specifics.SerializeAsString(),
            node.GetEntitySpecifics().SerializeAsString());
}

TEST_F(SyncApiTest, BaseNodeSetSpecificsPreservesUnknownFields) {
  int64 child_id = MakeNode(user_share(), BOOKMARKS, "testtag");
  WriteTransaction trans(FROM_HERE, user_share());
  WriteNode node(&trans);
  EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(child_id));
  EXPECT_TRUE(node.GetEntitySpecifics().unknown_fields().empty());

  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_bookmark()->set_url("http://www.google.com");
  entity_specifics.mutable_unknown_fields()->AddFixed32(5, 100);
  node.SetEntitySpecifics(entity_specifics);
  EXPECT_FALSE(node.GetEntitySpecifics().unknown_fields().empty());

  entity_specifics.mutable_unknown_fields()->Clear();
  node.SetEntitySpecifics(entity_specifics);
  EXPECT_FALSE(node.GetEntitySpecifics().unknown_fields().empty());
}

TEST_F(SyncApiTest, EmptyTags) {
  WriteTransaction trans(FROM_HERE, user_share());
  ReadNode root_node(&trans);
  root_node.InitByRootLookup();
  WriteNode node(&trans);
  std::string empty_tag;
  WriteNode::InitUniqueByCreationResult result =
      node.InitUniqueByCreation(TYPED_URLS, root_node, empty_tag);
  EXPECT_NE(WriteNode::INIT_SUCCESS, result);
  EXPECT_EQ(BaseNode::INIT_FAILED_PRECONDITION,
            node.InitByClientTagLookup(TYPED_URLS, empty_tag));
}

// Test counting nodes when the type's root node has no children.
TEST_F(SyncApiTest, GetTotalNodeCountEmpty) {
  int64 type_root = MakeServerNodeForType(user_share(), BOOKMARKS);
  {
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode type_root_node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              type_root_node.InitByIdLookup(type_root));
    EXPECT_EQ(1, type_root_node.GetTotalNodeCount());
  }
}

// Test counting nodes when there is one child beneath the type's root.
TEST_F(SyncApiTest, GetTotalNodeCountOneChild) {
  int64 type_root = MakeServerNodeForType(user_share(), BOOKMARKS);
  int64 parent = MakeFolderWithParent(user_share(), BOOKMARKS, type_root, NULL);
  {
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode type_root_node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              type_root_node.InitByIdLookup(type_root));
    EXPECT_EQ(2, type_root_node.GetTotalNodeCount());
    ReadNode parent_node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              parent_node.InitByIdLookup(parent));
    EXPECT_EQ(1, parent_node.GetTotalNodeCount());
  }
}

// Test counting nodes when there are multiple children beneath the type root,
// and one of those children has children of its own.
TEST_F(SyncApiTest, GetTotalNodeCountMultipleChildren) {
  int64 type_root = MakeServerNodeForType(user_share(), BOOKMARKS);
  int64 parent = MakeFolderWithParent(user_share(), BOOKMARKS, type_root, NULL);
  ignore_result(MakeFolderWithParent(user_share(), BOOKMARKS, type_root, NULL));
  int64 child1 = MakeFolderWithParent(user_share(), BOOKMARKS, parent, NULL);
  ignore_result(MakeBookmarkWithParent(user_share(), parent, NULL));
  ignore_result(MakeBookmarkWithParent(user_share(), child1, NULL));

  {
    ReadTransaction trans(FROM_HERE, user_share());
    ReadNode type_root_node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              type_root_node.InitByIdLookup(type_root));
    EXPECT_EQ(6, type_root_node.GetTotalNodeCount());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByIdLookup(parent));
    EXPECT_EQ(4, node.GetTotalNodeCount());
  }
}

// Verify that Directory keeps track of which attachments are referenced by
// which entries.
TEST_F(SyncApiTest, AttachmentLinking) {
  // Add an entry with an attachment.
  std::string tag1("some tag");
  syncer::AttachmentId attachment_id(syncer::AttachmentId::Create());
  sync_pb::AttachmentMetadata attachment_metadata;
  sync_pb::AttachmentMetadataRecord* record = attachment_metadata.add_record();
  *record->mutable_id() = attachment_id.GetProto();
  ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id.GetProto()));
  CreateEntryWithAttachmentMetadata(PREFERENCES, tag1, attachment_metadata);

  // See that the directory knows it's linked.
  ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id.GetProto()));

  // Add a second entry referencing the same attachment.
  std::string tag2("some other tag");
  CreateEntryWithAttachmentMetadata(PREFERENCES, tag2, attachment_metadata);

  // See that the directory knows it's still linked.
  ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id.GetProto()));

  // Tombstone the first entry.
  ReplaceWithTombstone(syncer::PREFERENCES, tag1);

  // See that the attachment is still considered linked because the entry hasn't
  // been purged from the Directory.
  ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id.GetProto()));

  // Save changes and see that the entry is truly gone.
  ASSERT_TRUE(dir()->SaveChanges());
  ASSERT_EQ(LookupEntryByClientTag(PREFERENCES, tag1),
            syncer::WriteNode::INIT_FAILED_ENTRY_NOT_GOOD);

  // However, the attachment is still linked.
  ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id.GetProto()));

  // Save, destroy, and recreate the directory.  See that it's still linked.
  ASSERT_TRUE(ReloadDir());
  ASSERT_TRUE(dir()->IsAttachmentLinked(attachment_id.GetProto()));

  // Tombstone the second entry, save changes, see that it's truly gone.
  ReplaceWithTombstone(syncer::PREFERENCES, tag2);
  ASSERT_TRUE(dir()->SaveChanges());
  ASSERT_EQ(LookupEntryByClientTag(PREFERENCES, tag2),
            syncer::WriteNode::INIT_FAILED_ENTRY_NOT_GOOD);

  // Finally, the attachment is no longer linked.
  ASSERT_FALSE(dir()->IsAttachmentLinked(attachment_id.GetProto()));
}

namespace {

class TestHttpPostProviderInterface : public HttpPostProviderInterface {
 public:
  ~TestHttpPostProviderInterface() override {}

  void SetExtraRequestHeaders(const char* headers) override {}
  void SetURL(const char* url, int port) override {}
  void SetPostPayload(const char* content_type,
                      int content_length,
                      const char* content) override {}
  bool MakeSynchronousPost(int* error_code, int* response_code) override {
    return false;
  }
  int GetResponseContentLength() const override { return 0; }
  const char* GetResponseContent() const override { return ""; }
  const std::string GetResponseHeaderValue(
      const std::string& name) const override {
    return std::string();
  }
  void Abort() override {}
};

class TestHttpPostProviderFactory : public HttpPostProviderFactory {
 public:
  ~TestHttpPostProviderFactory() override {}
  void Init(const std::string& user_agent) override {}
  HttpPostProviderInterface* Create() override {
    return new TestHttpPostProviderInterface();
  }
  void Destroy(HttpPostProviderInterface* http) override {
    delete static_cast<TestHttpPostProviderInterface*>(http);
  }
};

class SyncManagerObserverMock : public SyncManager::Observer {
 public:
  MOCK_METHOD1(OnSyncCycleCompleted,
               void(const SyncSessionSnapshot&));  // NOLINT
  MOCK_METHOD4(OnInitializationComplete,
               void(const WeakHandle<JsBackend>&,
                    const WeakHandle<DataTypeDebugInfoListener>&,
                    bool,
                    syncer::ModelTypeSet));  // NOLINT
  MOCK_METHOD1(OnConnectionStatusChange, void(ConnectionStatus));  // NOLINT
  MOCK_METHOD1(OnUpdatedToken, void(const std::string&));  // NOLINT
  MOCK_METHOD1(OnActionableError, void(const SyncProtocolError&));  // NOLINT
  MOCK_METHOD1(OnMigrationRequested, void(syncer::ModelTypeSet));  // NOLINT
  MOCK_METHOD1(OnProtocolEvent, void(const ProtocolEvent&));  // NOLINT
};

class SyncEncryptionHandlerObserverMock
    : public SyncEncryptionHandler::Observer {
 public:
  MOCK_METHOD2(OnPassphraseRequired,
               void(PassphraseRequiredReason,
                    const sync_pb::EncryptedData&));  // NOLINT
  MOCK_METHOD0(OnPassphraseAccepted, void());  // NOLINT
  MOCK_METHOD2(OnBootstrapTokenUpdated,
               void(const std::string&, BootstrapTokenType type));  // NOLINT
  MOCK_METHOD2(OnEncryptedTypesChanged,
               void(ModelTypeSet, bool));  // NOLINT
  MOCK_METHOD0(OnEncryptionComplete, void());  // NOLINT
  MOCK_METHOD1(OnCryptographerStateChanged, void(Cryptographer*));  // NOLINT
  MOCK_METHOD2(OnPassphraseTypeChanged, void(PassphraseType,
                                             base::Time));  // NOLINT
};

}  // namespace

class SyncManagerTest : public testing::Test,
                        public SyncManager::ChangeDelegate {
 protected:
  enum NigoriStatus {
    DONT_WRITE_NIGORI,
    WRITE_TO_NIGORI
  };

  enum EncryptionStatus {
    UNINITIALIZED,
    DEFAULT_ENCRYPTION,
    FULL_ENCRYPTION
  };

  SyncManagerTest()
      : sync_manager_("Test sync manager") {
    switches_.encryption_method =
        InternalComponentsFactory::ENCRYPTION_KEYSTORE;
  }

  virtual ~SyncManagerTest() {
  }

  // Test implementation.
  void SetUp() {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

    extensions_activity_ = new ExtensionsActivity();

    SyncCredentials credentials;
    credentials.email = "foo@bar.com";
    credentials.sync_token = "sometoken";
    OAuth2TokenService::ScopeSet scope_set;
    scope_set.insert(GaiaConstants::kChromeSyncOAuth2Scope);
    credentials.scope_set = scope_set;

    sync_manager_.AddObserver(&manager_observer_);
    EXPECT_CALL(manager_observer_, OnInitializationComplete(_, _, _, _)).
        WillOnce(DoAll(SaveArg<0>(&js_backend_),
            SaveArg<2>(&initialization_succeeded_)));

    EXPECT_FALSE(js_backend_.IsInitialized());

    std::vector<scoped_refptr<ModelSafeWorker> > workers;
    ModelSafeRoutingInfo routing_info;
    GetModelSafeRoutingInfo(&routing_info);

    // This works only because all routing info types are GROUP_PASSIVE.
    // If we had types in other groups, we would need additional workers
    // to support them.
    scoped_refptr<ModelSafeWorker> worker = new FakeModelWorker(GROUP_PASSIVE);
    workers.push_back(worker);

    SyncManager::InitArgs args;
    args.database_location = temp_dir_.path();
    args.service_url = GURL("https://example.com/");
    args.post_factory =
        scoped_ptr<HttpPostProviderFactory>(new TestHttpPostProviderFactory());
    args.workers = workers;
    args.extensions_activity = extensions_activity_.get(),
    args.change_delegate = this;
    args.credentials = credentials;
    args.invalidator_client_id = "fake_invalidator_client_id";
    args.internal_components_factory.reset(GetFactory());
    args.encryptor = &encryptor_;
    args.unrecoverable_error_handler.reset(new TestUnrecoverableErrorHandler);
    args.cancelation_signal = &cancelation_signal_;
    sync_manager_.Init(&args);

    sync_manager_.GetEncryptionHandler()->AddObserver(&encryption_observer_);

    EXPECT_TRUE(js_backend_.IsInitialized());
    EXPECT_EQ(InternalComponentsFactory::STORAGE_ON_DISK,
              storage_used_);

    if (initialization_succeeded_) {
      for (ModelSafeRoutingInfo::iterator i = routing_info.begin();
           i != routing_info.end(); ++i) {
        type_roots_[i->first] = MakeServerNodeForType(
            sync_manager_.GetUserShare(), i->first);
      }
    }

    PumpLoop();
  }

  void TearDown() {
    sync_manager_.RemoveObserver(&manager_observer_);
    sync_manager_.ShutdownOnSyncThread(STOP_SYNC);
    PumpLoop();
  }

  void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) {
    (*out)[NIGORI] = GROUP_PASSIVE;
    (*out)[DEVICE_INFO] = GROUP_PASSIVE;
    (*out)[EXPERIMENTS] = GROUP_PASSIVE;
    (*out)[BOOKMARKS] = GROUP_PASSIVE;
    (*out)[THEMES] = GROUP_PASSIVE;
    (*out)[SESSIONS] = GROUP_PASSIVE;
    (*out)[PASSWORDS] = GROUP_PASSIVE;
    (*out)[PREFERENCES] = GROUP_PASSIVE;
    (*out)[PRIORITY_PREFERENCES] = GROUP_PASSIVE;
    (*out)[ARTICLES] = GROUP_PASSIVE;
  }

  ModelTypeSet GetEnabledTypes() {
    ModelSafeRoutingInfo routing_info;
    GetModelSafeRoutingInfo(&routing_info);
    return GetRoutingInfoTypes(routing_info);
  }

  virtual void OnChangesApplied(
      ModelType model_type,
      int64 model_version,
      const BaseTransaction* trans,
      const ImmutableChangeRecordList& changes) override {}

  virtual void OnChangesComplete(ModelType model_type) override {}

  // Helper methods.
  bool SetUpEncryption(NigoriStatus nigori_status,
                       EncryptionStatus encryption_status) {
    UserShare* share = sync_manager_.GetUserShare();

    // We need to create the nigori node as if it were an applied server update.
    int64 nigori_id = GetIdForDataType(NIGORI);
    if (nigori_id == kInvalidId)
      return false;

    // Set the nigori cryptographer information.
    if (encryption_status == FULL_ENCRYPTION)
      sync_manager_.GetEncryptionHandler()->EnableEncryptEverything();

    WriteTransaction trans(FROM_HERE, share);
    Cryptographer* cryptographer = trans.GetCryptographer();
    if (!cryptographer)
      return false;
    if (encryption_status != UNINITIALIZED) {
      KeyParams params = {"localhost", "dummy", "foobar"};
      cryptographer->AddKey(params);
    } else {
      DCHECK_NE(nigori_status, WRITE_TO_NIGORI);
    }
    if (nigori_status == WRITE_TO_NIGORI) {
      sync_pb::NigoriSpecifics nigori;
      cryptographer->GetKeys(nigori.mutable_encryption_keybag());
      share->directory->GetNigoriHandler()->UpdateNigoriFromEncryptedTypes(
          &nigori,
          trans.GetWrappedTrans());
      WriteNode node(&trans);
      EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(nigori_id));
      node.SetNigoriSpecifics(nigori);
    }
    return cryptographer->is_ready();
  }

  int64 GetIdForDataType(ModelType type) {
    if (type_roots_.count(type) == 0)
      return 0;
    return type_roots_[type];
  }

  void PumpLoop() {
    message_loop_.RunUntilIdle();
  }

  void SetJsEventHandler(const WeakHandle<JsEventHandler>& event_handler) {
    js_backend_.Call(FROM_HERE, &JsBackend::SetJsEventHandler,
                     event_handler);
    PumpLoop();
  }

  // Looks up an entry by client tag and resets IS_UNSYNCED value to false.
  // Returns true if entry was previously unsynced, false if IS_UNSYNCED was
  // already false.
  bool ResetUnsyncedEntry(ModelType type,
                          const std::string& client_tag) {
    UserShare* share = sync_manager_.GetUserShare();
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::UNITTEST, share->directory.get());
    const std::string hash = syncable::GenerateSyncableHash(type, client_tag);
    syncable::MutableEntry entry(&trans, syncable::GET_BY_CLIENT_TAG,
                                 hash);
    EXPECT_TRUE(entry.good());
    if (!entry.GetIsUnsynced())
      return false;
    entry.PutIsUnsynced(false);
    return true;
  }

  virtual InternalComponentsFactory* GetFactory() {
    return new TestInternalComponentsFactory(
        GetSwitches(), InternalComponentsFactory::STORAGE_IN_MEMORY,
        &storage_used_);
  }

  // Returns true if we are currently encrypting all sync data.  May
  // be called on any thread.
  bool EncryptEverythingEnabledForTest() {
    return sync_manager_.GetEncryptionHandler()->EncryptEverythingEnabled();
  }

  // Gets the set of encrypted types from the cryptographer
  // Note: opens a transaction.  May be called from any thread.
  ModelTypeSet GetEncryptedTypes() {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    return GetEncryptedTypesWithTrans(&trans);
  }

  ModelTypeSet GetEncryptedTypesWithTrans(BaseTransaction* trans) {
    return trans->GetDirectory()->GetNigoriHandler()->
        GetEncryptedTypes(trans->GetWrappedTrans());
  }

  void SimulateInvalidatorEnabledForTest(bool is_enabled) {
    DCHECK(sync_manager_.thread_checker_.CalledOnValidThread());
    sync_manager_.SetInvalidatorEnabled(is_enabled);
  }

  void SetProgressMarkerForType(ModelType type, bool set) {
    if (set) {
      sync_pb::DataTypeProgressMarker marker;
      marker.set_token("token");
      marker.set_data_type_id(GetSpecificsFieldNumberFromModelType(type));
      sync_manager_.directory()->SetDownloadProgress(type, marker);
    } else {
      sync_pb::DataTypeProgressMarker marker;
      sync_manager_.directory()->SetDownloadProgress(type, marker);
    }
  }

  InternalComponentsFactory::Switches GetSwitches() const {
    return switches_;
  }

 private:
  // Needed by |sync_manager_|.
  base::MessageLoop message_loop_;
  // Needed by |sync_manager_|.
  base::ScopedTempDir temp_dir_;
  // Sync Id's for the roots of the enabled datatypes.
  std::map<ModelType, int64> type_roots_;
  scoped_refptr<ExtensionsActivity> extensions_activity_;

 protected:
  FakeEncryptor encryptor_;
  SyncManagerImpl sync_manager_;
  CancelationSignal cancelation_signal_;
  WeakHandle<JsBackend> js_backend_;
  bool initialization_succeeded_;
  StrictMock<SyncManagerObserverMock> manager_observer_;
  StrictMock<SyncEncryptionHandlerObserverMock> encryption_observer_;
  InternalComponentsFactory::Switches switches_;
  InternalComponentsFactory::StorageOption storage_used_;
};

TEST_F(SyncManagerTest, GetAllNodesForTypeTest) {
  ModelSafeRoutingInfo routing_info;
  GetModelSafeRoutingInfo(&routing_info);
  sync_manager_.StartSyncingNormally(routing_info);

  scoped_ptr<base::ListValue> node_list(
      sync_manager_.GetAllNodesForType(syncer::PREFERENCES));

  // Should have one node: the type root node.
  ASSERT_EQ(1U, node_list->GetSize());

  const base::DictionaryValue* first_result;
  ASSERT_TRUE(node_list->GetDictionary(0, &first_result));
  EXPECT_TRUE(first_result->HasKey("ID"));
  EXPECT_TRUE(first_result->HasKey("NON_UNIQUE_NAME"));
}

TEST_F(SyncManagerTest, RefreshEncryptionReady) {
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));

  sync_manager_.GetEncryptionHandler()->Init();
  PumpLoop();

  const ModelTypeSet encrypted_types = GetEncryptedTypes();
  EXPECT_TRUE(encrypted_types.Has(PASSWORDS));
  EXPECT_FALSE(EncryptEverythingEnabledForTest());

  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByIdLookup(GetIdForDataType(NIGORI)));
    sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics();
    EXPECT_TRUE(nigori.has_encryption_keybag());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());
    EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encryption_keybag()));
  }
}

// Attempt to refresh encryption when nigori not downloaded.
TEST_F(SyncManagerTest, RefreshEncryptionNotReady) {
  // Don't set up encryption (no nigori node created).

  // Should fail. Triggers an OnPassphraseRequired because the cryptographer
  // is not ready.
  EXPECT_CALL(encryption_observer_, OnPassphraseRequired(_, _)).Times(1);
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));
  sync_manager_.GetEncryptionHandler()->Init();
  PumpLoop();

  const ModelTypeSet encrypted_types = GetEncryptedTypes();
  EXPECT_TRUE(encrypted_types.Has(PASSWORDS));  // Hardcoded.
  EXPECT_FALSE(EncryptEverythingEnabledForTest());
}

// Attempt to refresh encryption when nigori is empty.
TEST_F(SyncManagerTest, RefreshEncryptionEmptyNigori) {
  EXPECT_TRUE(SetUpEncryption(DONT_WRITE_NIGORI, DEFAULT_ENCRYPTION));
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete()).Times(1);
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));

  // Should write to nigori.
  sync_manager_.GetEncryptionHandler()->Init();
  PumpLoop();

  const ModelTypeSet encrypted_types = GetEncryptedTypes();
  EXPECT_TRUE(encrypted_types.Has(PASSWORDS));  // Hardcoded.
  EXPECT_FALSE(EncryptEverythingEnabledForTest());

  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByIdLookup(GetIdForDataType(NIGORI)));
    sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics();
    EXPECT_TRUE(nigori.has_encryption_keybag());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());
    EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encryption_keybag()));
  }
}

TEST_F(SyncManagerTest, EncryptDataTypesWithNoData) {
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  EXPECT_CALL(encryption_observer_,
              OnEncryptedTypesChanged(
                  HasModelTypes(EncryptableUserTypes()), true));
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  sync_manager_.GetEncryptionHandler()->EnableEncryptEverything();
  EXPECT_TRUE(EncryptEverythingEnabledForTest());
}

TEST_F(SyncManagerTest, EncryptDataTypesWithData) {
  size_t batch_size = 5;
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));

  // Create some unencrypted unsynced data.
  int64 folder = MakeFolderWithParent(sync_manager_.GetUserShare(),
                                      BOOKMARKS,
                                      GetIdForDataType(BOOKMARKS),
                                      NULL);
  // First batch_size nodes are children of folder.
  size_t i;
  for (i = 0; i < batch_size; ++i) {
    MakeBookmarkWithParent(sync_manager_.GetUserShare(), folder, NULL);
  }
  // Next batch_size nodes are a different type and on their own.
  for (; i < 2*batch_size; ++i) {
    MakeNode(sync_manager_.GetUserShare(), SESSIONS,
             base::StringPrintf("%" PRIuS "", i));
  }
  // Last batch_size nodes are a third type that will not need encryption.
  for (; i < 3*batch_size; ++i) {
    MakeNode(sync_manager_.GetUserShare(), THEMES,
             base::StringPrintf("%" PRIuS "", i));
  }

  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    EXPECT_TRUE(GetEncryptedTypesWithTrans(&trans).Equals(
        SyncEncryptionHandler::SensitiveTypes()));
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        BOOKMARKS,
        false /* not encrypted */));
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        SESSIONS,
        false /* not encrypted */));
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        THEMES,
        false /* not encrypted */));
  }

  EXPECT_CALL(encryption_observer_,
              OnEncryptedTypesChanged(
                  HasModelTypes(EncryptableUserTypes()), true));
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  sync_manager_.GetEncryptionHandler()->EnableEncryptEverything();
  EXPECT_TRUE(EncryptEverythingEnabledForTest());
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    EXPECT_TRUE(GetEncryptedTypesWithTrans(&trans).Equals(
        EncryptableUserTypes()));
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        BOOKMARKS,
        true /* is encrypted */));
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        SESSIONS,
        true /* is encrypted */));
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        THEMES,
        true /* is encrypted */));
  }

  // Trigger's a ReEncryptEverything with new passphrase.
  testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_,
              OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
  sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
      "new_passphrase", true);
  EXPECT_TRUE(EncryptEverythingEnabledForTest());
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    EXPECT_TRUE(GetEncryptedTypesWithTrans(&trans).Equals(
        EncryptableUserTypes()));
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        BOOKMARKS,
        true /* is encrypted */));
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        SESSIONS,
        true /* is encrypted */));
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        THEMES,
        true /* is encrypted */));
  }
  // Calling EncryptDataTypes with an empty encrypted types should not trigger
  // a reencryption and should just notify immediately.
  testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN)).Times(0);
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted()).Times(0);
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete()).Times(0);
  sync_manager_.GetEncryptionHandler()->EnableEncryptEverything();
}

// Test that when there are no pending keys and the cryptographer is not
// initialized, we add a key based on the current GAIA password.
// (case 1 in SyncManager::SyncInternal::SetEncryptionPassphrase)
TEST_F(SyncManagerTest, SetInitialGaiaPass) {
  EXPECT_FALSE(SetUpEncryption(DONT_WRITE_NIGORI, UNINITIALIZED));
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
      "new_passphrase",
      false);
  EXPECT_EQ(IMPLICIT_PASSPHRASE,
            sync_manager_.GetEncryptionHandler()->GetPassphraseType());
  EXPECT_FALSE(EncryptEverythingEnabledForTest());
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node.InitTypeRoot(NIGORI));
    sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics();
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());
    EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encryption_keybag()));
  }
}

// Test that when there are no pending keys and we have on the old GAIA
// password, we update and re-encrypt everything with the new GAIA password.
// (case 1 in SyncManager::SyncInternal::SetEncryptionPassphrase)
TEST_F(SyncManagerTest, UpdateGaiaPass) {
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  Cryptographer verifier(&encryptor_);
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    std::string bootstrap_token;
    cryptographer->GetBootstrapToken(&bootstrap_token);
    verifier.Bootstrap(bootstrap_token);
  }
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
      "new_passphrase",
      false);
  EXPECT_EQ(IMPLICIT_PASSPHRASE,
            sync_manager_.GetEncryptionHandler()->GetPassphraseType());
  EXPECT_FALSE(EncryptEverythingEnabledForTest());
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());
    // Verify the default key has changed.
    sync_pb::EncryptedData encrypted;
    cryptographer->GetKeys(&encrypted);
    EXPECT_FALSE(verifier.CanDecrypt(encrypted));
  }
}

// Sets a new explicit passphrase. This should update the bootstrap token
// and re-encrypt everything.
// (case 2 in SyncManager::SyncInternal::SetEncryptionPassphrase)
TEST_F(SyncManagerTest, SetPassphraseWithPassword) {
  Cryptographer verifier(&encryptor_);
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    // Store the default (soon to be old) key.
    Cryptographer* cryptographer = trans.GetCryptographer();
    std::string bootstrap_token;
    cryptographer->GetBootstrapToken(&bootstrap_token);
    verifier.Bootstrap(bootstrap_token);

    ReadNode root_node(&trans);
    root_node.InitByRootLookup();

    WriteNode password_node(&trans);
    WriteNode::InitUniqueByCreationResult result =
        password_node.InitUniqueByCreation(PASSWORDS,
                                           root_node, "foo");
    EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
    sync_pb::PasswordSpecificsData data;
    data.set_password_value("secret");
    password_node.SetPasswordSpecifics(data);
  }
    EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_,
      OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
  sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
      "new_passphrase",
      true);
  EXPECT_EQ(CUSTOM_PASSPHRASE,
            sync_manager_.GetEncryptionHandler()->GetPassphraseType());
  EXPECT_FALSE(EncryptEverythingEnabledForTest());
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());
    // Verify the default key has changed.
    sync_pb::EncryptedData encrypted;
    cryptographer->GetKeys(&encrypted);
    EXPECT_FALSE(verifier.CanDecrypt(encrypted));

    ReadNode password_node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              password_node.InitByClientTagLookup(PASSWORDS,
                                                  "foo"));
    const sync_pb::PasswordSpecificsData& data =
        password_node.GetPasswordSpecifics();
    EXPECT_EQ("secret", data.password_value());
  }
}

// Manually set the pending keys in the cryptographer/nigori to reflect the data
// being encrypted with a new (unprovided) GAIA password, then supply the
// password.
// (case 7 in SyncManager::SyncInternal::SetDecryptionPassphrase)
TEST_F(SyncManagerTest, SupplyPendingGAIAPass) {
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  Cryptographer other_cryptographer(&encryptor_);
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    std::string bootstrap_token;
    cryptographer->GetBootstrapToken(&bootstrap_token);
    other_cryptographer.Bootstrap(bootstrap_token);

    // Now update the nigori to reflect the new keys, and update the
    // cryptographer to have pending keys.
    KeyParams params = {"localhost", "dummy", "passphrase2"};
    other_cryptographer.AddKey(params);
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node.InitTypeRoot(NIGORI));
    sync_pb::NigoriSpecifics nigori;
    other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
    cryptographer->SetPendingKeys(nigori.encryption_keybag());
    EXPECT_TRUE(cryptographer->has_pending_keys());
    node.SetNigoriSpecifics(nigori);
  }
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  sync_manager_.GetEncryptionHandler()->SetDecryptionPassphrase("passphrase2");
  EXPECT_EQ(IMPLICIT_PASSPHRASE,
            sync_manager_.GetEncryptionHandler()->GetPassphraseType());
  EXPECT_FALSE(EncryptEverythingEnabledForTest());
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());
    // Verify we're encrypting with the new key.
    sync_pb::EncryptedData encrypted;
    cryptographer->GetKeys(&encrypted);
    EXPECT_TRUE(other_cryptographer.CanDecrypt(encrypted));
  }
}

// Manually set the pending keys in the cryptographer/nigori to reflect the data
// being encrypted with an old (unprovided) GAIA password. Attempt to supply
// the current GAIA password and verify the bootstrap token is updated. Then
// supply the old GAIA password, and verify we re-encrypt all data with the
// new GAIA password.
// (cases 4 and 5 in SyncManager::SyncInternal::SetEncryptionPassphrase)
TEST_F(SyncManagerTest, SupplyPendingOldGAIAPass) {
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  Cryptographer other_cryptographer(&encryptor_);
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    std::string bootstrap_token;
    cryptographer->GetBootstrapToken(&bootstrap_token);
    other_cryptographer.Bootstrap(bootstrap_token);

    // Now update the nigori to reflect the new keys, and update the
    // cryptographer to have pending keys.
    KeyParams params = {"localhost", "dummy", "old_gaia"};
    other_cryptographer.AddKey(params);
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node.InitTypeRoot(NIGORI));
    sync_pb::NigoriSpecifics nigori;
    other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
    node.SetNigoriSpecifics(nigori);
    cryptographer->SetPendingKeys(nigori.encryption_keybag());

    // other_cryptographer now contains all encryption keys, and is encrypting
    // with the newest gaia.
    KeyParams new_params = {"localhost", "dummy", "new_gaia"};
    other_cryptographer.AddKey(new_params);
  }
  // The bootstrap token should have been updated. Save it to ensure it's based
  // on the new GAIA password.
  std::string bootstrap_token;
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN))
      .WillOnce(SaveArg<0>(&bootstrap_token));
  EXPECT_CALL(encryption_observer_, OnPassphraseRequired(_,_));
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
      "new_gaia",
      false);
  EXPECT_EQ(IMPLICIT_PASSPHRASE,
            sync_manager_.GetEncryptionHandler()->GetPassphraseType());
  EXPECT_FALSE(EncryptEverythingEnabledForTest());
  testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_initialized());
    EXPECT_FALSE(cryptographer->is_ready());
    // Verify we're encrypting with the new key, even though we have pending
    // keys.
    sync_pb::EncryptedData encrypted;
    other_cryptographer.GetKeys(&encrypted);
    EXPECT_TRUE(cryptographer->CanDecrypt(encrypted));
  }
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
      "old_gaia",
      false);
  EXPECT_EQ(IMPLICIT_PASSPHRASE,
            sync_manager_.GetEncryptionHandler()->GetPassphraseType());
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());

    // Verify we're encrypting with the new key.
    sync_pb::EncryptedData encrypted;
    other_cryptographer.GetKeys(&encrypted);
    EXPECT_TRUE(cryptographer->CanDecrypt(encrypted));

    // Verify the saved bootstrap token is based on the new gaia password.
    Cryptographer temp_cryptographer(&encryptor_);
    temp_cryptographer.Bootstrap(bootstrap_token);
    EXPECT_TRUE(temp_cryptographer.CanDecrypt(encrypted));
  }
}

// Manually set the pending keys in the cryptographer/nigori to reflect the data
// being encrypted with an explicit (unprovided) passphrase, then supply the
// passphrase.
// (case 9 in SyncManager::SyncInternal::SetDecryptionPassphrase)
TEST_F(SyncManagerTest, SupplyPendingExplicitPass) {
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  Cryptographer other_cryptographer(&encryptor_);
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    std::string bootstrap_token;
    cryptographer->GetBootstrapToken(&bootstrap_token);
    other_cryptographer.Bootstrap(bootstrap_token);

    // Now update the nigori to reflect the new keys, and update the
    // cryptographer to have pending keys.
    KeyParams params = {"localhost", "dummy", "explicit"};
    other_cryptographer.AddKey(params);
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node.InitTypeRoot(NIGORI));
    sync_pb::NigoriSpecifics nigori;
    other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
    cryptographer->SetPendingKeys(nigori.encryption_keybag());
    EXPECT_TRUE(cryptographer->has_pending_keys());
    nigori.set_keybag_is_frozen(true);
    node.SetNigoriSpecifics(nigori);
  }
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_,
              OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
  EXPECT_CALL(encryption_observer_, OnPassphraseRequired(_, _));
  EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));
  sync_manager_.GetEncryptionHandler()->Init();
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  sync_manager_.GetEncryptionHandler()->SetDecryptionPassphrase("explicit");
  EXPECT_EQ(CUSTOM_PASSPHRASE,
            sync_manager_.GetEncryptionHandler()->GetPassphraseType());
  EXPECT_FALSE(EncryptEverythingEnabledForTest());
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());
    // Verify we're encrypting with the new key.
    sync_pb::EncryptedData encrypted;
    cryptographer->GetKeys(&encrypted);
    EXPECT_TRUE(other_cryptographer.CanDecrypt(encrypted));
  }
}

// Manually set the pending keys in the cryptographer/nigori to reflect the data
// being encrypted with a new (unprovided) GAIA password, then supply the
// password as a user-provided password.
// This is the android case 7/8.
TEST_F(SyncManagerTest, SupplyPendingGAIAPassUserProvided) {
  EXPECT_FALSE(SetUpEncryption(DONT_WRITE_NIGORI, UNINITIALIZED));
  Cryptographer other_cryptographer(&encryptor_);
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    // Now update the nigori to reflect the new keys, and update the
    // cryptographer to have pending keys.
    KeyParams params = {"localhost", "dummy", "passphrase"};
    other_cryptographer.AddKey(params);
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node.InitTypeRoot(NIGORI));
    sync_pb::NigoriSpecifics nigori;
    other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
    node.SetNigoriSpecifics(nigori);
    cryptographer->SetPendingKeys(nigori.encryption_keybag());
    EXPECT_FALSE(cryptographer->is_ready());
  }
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
      "passphrase",
      false);
  EXPECT_EQ(IMPLICIT_PASSPHRASE,
            sync_manager_.GetEncryptionHandler()->GetPassphraseType());
  EXPECT_FALSE(EncryptEverythingEnabledForTest());
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());
  }
}

TEST_F(SyncManagerTest, SetPassphraseWithEmptyPasswordNode) {
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  int64 node_id = 0;
  std::string tag = "foo";
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode root_node(&trans);
    root_node.InitByRootLookup();

    WriteNode password_node(&trans);
    WriteNode::InitUniqueByCreationResult result =
        password_node.InitUniqueByCreation(PASSWORDS, root_node, tag);
    EXPECT_EQ(WriteNode::INIT_SUCCESS, result);
    node_id = password_node.GetId();
  }
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_,
      OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
  sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
      "new_passphrase",
      true);
  EXPECT_EQ(CUSTOM_PASSPHRASE,
            sync_manager_.GetEncryptionHandler()->GetPassphraseType());
  EXPECT_FALSE(EncryptEverythingEnabledForTest());
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode password_node(&trans);
    EXPECT_EQ(BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY,
              password_node.InitByClientTagLookup(PASSWORDS,
                                                  tag));
  }
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode password_node(&trans);
    EXPECT_EQ(BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY,
              password_node.InitByIdLookup(node_id));
  }
}

// Friended by WriteNode, so can't be in an anonymouse namespace.
TEST_F(SyncManagerTest, EncryptBookmarksWithLegacyData) {
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  std::string title;
  SyncAPINameToServerName("Google", &title);
  std::string url = "http://www.google.com";
  std::string raw_title2 = "..";  // An invalid cosmo title.
  std::string title2;
  SyncAPINameToServerName(raw_title2, &title2);
  std::string url2 = "http://www.bla.com";

  // Create a bookmark using the legacy format.
  int64 node_id1 = MakeNode(sync_manager_.GetUserShare(),
      BOOKMARKS,
      "testtag");
  int64 node_id2 = MakeNode(sync_manager_.GetUserShare(),
      BOOKMARKS,
      "testtag2");
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(node_id1));

    sync_pb::EntitySpecifics entity_specifics;
    entity_specifics.mutable_bookmark()->set_url(url);
    node.SetEntitySpecifics(entity_specifics);

    // Set the old style title.
    syncable::MutableEntry* node_entry = node.entry_;
    node_entry->PutNonUniqueName(title);

    WriteNode node2(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node2.InitByIdLookup(node_id2));

    sync_pb::EntitySpecifics entity_specifics2;
    entity_specifics2.mutable_bookmark()->set_url(url2);
    node2.SetEntitySpecifics(entity_specifics2);

    // Set the old style title.
    syncable::MutableEntry* node_entry2 = node2.entry_;
    node_entry2->PutNonUniqueName(title2);
  }

  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(node_id1));
    EXPECT_EQ(BOOKMARKS, node.GetModelType());
    EXPECT_EQ(title, node.GetTitle());
    EXPECT_EQ(title, node.GetBookmarkSpecifics().title());
    EXPECT_EQ(url, node.GetBookmarkSpecifics().url());

    ReadNode node2(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node2.InitByIdLookup(node_id2));
    EXPECT_EQ(BOOKMARKS, node2.GetModelType());
    // We should de-canonicalize the title in GetTitle(), but the title in the
    // specifics should be stored in the server legal form.
    EXPECT_EQ(raw_title2, node2.GetTitle());
    EXPECT_EQ(title2, node2.GetBookmarkSpecifics().title());
    EXPECT_EQ(url2, node2.GetBookmarkSpecifics().url());
  }

  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        BOOKMARKS,
        false /* not encrypted */));
  }

  EXPECT_CALL(encryption_observer_,
              OnEncryptedTypesChanged(
                  HasModelTypes(EncryptableUserTypes()), true));
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  sync_manager_.GetEncryptionHandler()->EnableEncryptEverything();
  EXPECT_TRUE(EncryptEverythingEnabledForTest());

  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    EXPECT_TRUE(GetEncryptedTypesWithTrans(&trans).Equals(
        EncryptableUserTypes()));
    EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest(
        trans.GetWrappedTrans(),
        BOOKMARKS,
        true /* is encrypted */));

    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(node_id1));
    EXPECT_EQ(BOOKMARKS, node.GetModelType());
    EXPECT_EQ(title, node.GetTitle());
    EXPECT_EQ(title, node.GetBookmarkSpecifics().title());
    EXPECT_EQ(url, node.GetBookmarkSpecifics().url());

    ReadNode node2(&trans);
    EXPECT_EQ(BaseNode::INIT_OK, node2.InitByIdLookup(node_id2));
    EXPECT_EQ(BOOKMARKS, node2.GetModelType());
    // We should de-canonicalize the title in GetTitle(), but the title in the
    // specifics should be stored in the server legal form.
    EXPECT_EQ(raw_title2, node2.GetTitle());
    EXPECT_EQ(title2, node2.GetBookmarkSpecifics().title());
    EXPECT_EQ(url2, node2.GetBookmarkSpecifics().url());
  }
}

// Create a bookmark and set the title/url, then verify the data was properly
// set. This replicates the unique way bookmarks have of creating sync nodes.
// See BookmarkChangeProcessor::PlaceSyncNode(..).
TEST_F(SyncManagerTest, CreateLocalBookmark) {
  std::string title = "title";
  std::string url = "url";
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode bookmark_root(&trans);
    ASSERT_EQ(BaseNode::INIT_OK, bookmark_root.InitTypeRoot(BOOKMARKS));
    WriteNode node(&trans);
    ASSERT_TRUE(node.InitBookmarkByCreation(bookmark_root, NULL));
    node.SetIsFolder(false);
    node.SetTitle(title);

    sync_pb::BookmarkSpecifics bookmark_specifics(node.GetBookmarkSpecifics());
    bookmark_specifics.set_url(url);
    node.SetBookmarkSpecifics(bookmark_specifics);
  }
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode bookmark_root(&trans);
    ASSERT_EQ(BaseNode::INIT_OK, bookmark_root.InitTypeRoot(BOOKMARKS));
    int64 child_id = bookmark_root.GetFirstChildId();

    ReadNode node(&trans);
    ASSERT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(child_id));
    EXPECT_FALSE(node.GetIsFolder());
    EXPECT_EQ(title, node.GetTitle());
    EXPECT_EQ(url, node.GetBookmarkSpecifics().url());
  }
}

// Verifies WriteNode::UpdateEntryWithEncryption does not make unnecessary
// changes.
TEST_F(SyncManagerTest, UpdateEntryWithEncryption) {
  std::string client_tag = "title";
  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_bookmark()->set_url("url");
  entity_specifics.mutable_bookmark()->set_title("title");
  MakeServerNode(sync_manager_.GetUserShare(), BOOKMARKS, client_tag,
                 syncable::GenerateSyncableHash(BOOKMARKS,
                                                client_tag),
                 entity_specifics);
  // New node shouldn't start off unsynced.
  EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
  // Manually change to the same data. Should not set is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    node.SetEntitySpecifics(entity_specifics);
  }
  EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));

  // Encrypt the datatatype, should set is_unsynced.
  EXPECT_CALL(encryption_observer_,
              OnEncryptedTypesChanged(
                  HasModelTypes(EncryptableUserTypes()), true));
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, FULL_ENCRYPTION));

  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, true));
  sync_manager_.GetEncryptionHandler()->Init();
  PumpLoop();
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    const syncable::Entry* node_entry = node.GetEntry();
    const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
    EXPECT_TRUE(specifics.has_encrypted());
    EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());
    EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
        specifics.encrypted()));
  }
  EXPECT_TRUE(ResetUnsyncedEntry(BOOKMARKS, client_tag));

  // Set a new passphrase. Should set is_unsynced.
  testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_,
      OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
  sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
      "new_passphrase",
      true);
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    const syncable::Entry* node_entry = node.GetEntry();
    const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
    EXPECT_TRUE(specifics.has_encrypted());
    EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->is_ready());
    EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
        specifics.encrypted()));
  }
  EXPECT_TRUE(ResetUnsyncedEntry(BOOKMARKS, client_tag));

  // Force a re-encrypt everything. Should not set is_unsynced.
  testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, true));

  sync_manager_.GetEncryptionHandler()->Init();
  PumpLoop();

  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    const syncable::Entry* node_entry = node.GetEntry();
    const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
    EXPECT_TRUE(specifics.has_encrypted());
    EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
        specifics.encrypted()));
  }
  EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));

  // Manually change to the same data. Should not set is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    node.SetEntitySpecifics(entity_specifics);
    const syncable::Entry* node_entry = node.GetEntry();
    const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
    EXPECT_TRUE(specifics.has_encrypted());
    EXPECT_FALSE(node_entry->GetIsUnsynced());
    EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
        specifics.encrypted()));
  }
  EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));

  // Manually change to different data. Should set is_unsynced.
  {
    entity_specifics.mutable_bookmark()->set_url("url2");
    entity_specifics.mutable_bookmark()->set_title("title2");
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    node.SetEntitySpecifics(entity_specifics);
    const syncable::Entry* node_entry = node.GetEntry();
    const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
    EXPECT_TRUE(specifics.has_encrypted());
    EXPECT_TRUE(node_entry->GetIsUnsynced());
    EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
    Cryptographer* cryptographer = trans.GetCryptographer();
    EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
                    specifics.encrypted()));
  }
}

// Passwords have their own handling for encryption. Verify it does not result
// in unnecessary writes via SetEntitySpecifics.
TEST_F(SyncManagerTest, UpdatePasswordSetEntitySpecificsNoChange) {
  std::string client_tag = "title";
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  sync_pb::EntitySpecifics entity_specifics;
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    sync_pb::PasswordSpecificsData data;
    data.set_password_value("secret");
    cryptographer->Encrypt(
        data,
        entity_specifics.mutable_password()->
            mutable_encrypted());
  }
  MakeServerNode(sync_manager_.GetUserShare(), PASSWORDS, client_tag,
                 syncable::GenerateSyncableHash(PASSWORDS,
                                                client_tag),
                 entity_specifics);
  // New node shouldn't start off unsynced.
  EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));

  // Manually change to the same data via SetEntitySpecifics. Should not set
  // is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(PASSWORDS, client_tag));
    node.SetEntitySpecifics(entity_specifics);
  }
  EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));
}

// Passwords have their own handling for encryption. Verify it does not result
// in unnecessary writes via SetPasswordSpecifics.
TEST_F(SyncManagerTest, UpdatePasswordSetPasswordSpecifics) {
  std::string client_tag = "title";
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  sync_pb::EntitySpecifics entity_specifics;
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    sync_pb::PasswordSpecificsData data;
    data.set_password_value("secret");
    cryptographer->Encrypt(
        data,
        entity_specifics.mutable_password()->
            mutable_encrypted());
  }
  MakeServerNode(sync_manager_.GetUserShare(), PASSWORDS, client_tag,
                 syncable::GenerateSyncableHash(PASSWORDS,
                                                client_tag),
                 entity_specifics);
  // New node shouldn't start off unsynced.
  EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));

  // Manually change to the same data via SetPasswordSpecifics. Should not set
  // is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(PASSWORDS, client_tag));
    node.SetPasswordSpecifics(node.GetPasswordSpecifics());
  }
  EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));

  // Manually change to different data. Should set is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(PASSWORDS, client_tag));
    Cryptographer* cryptographer = trans.GetCryptographer();
    sync_pb::PasswordSpecificsData data;
    data.set_password_value("secret2");
    cryptographer->Encrypt(
        data,
        entity_specifics.mutable_password()->mutable_encrypted());
    node.SetPasswordSpecifics(data);
    const syncable::Entry* node_entry = node.GetEntry();
    EXPECT_TRUE(node_entry->GetIsUnsynced());
  }
}

// Passwords have their own handling for encryption. Verify setting a new
// passphrase updates the data.
TEST_F(SyncManagerTest, UpdatePasswordNewPassphrase) {
  std::string client_tag = "title";
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  sync_pb::EntitySpecifics entity_specifics;
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    sync_pb::PasswordSpecificsData data;
    data.set_password_value("secret");
    cryptographer->Encrypt(
        data,
        entity_specifics.mutable_password()->mutable_encrypted());
  }
  MakeServerNode(sync_manager_.GetUserShare(), PASSWORDS, client_tag,
                 syncable::GenerateSyncableHash(PASSWORDS,
                                                client_tag),
                 entity_specifics);
  // New node shouldn't start off unsynced.
  EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));

  // Set a new passphrase. Should set is_unsynced.
  testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
  EXPECT_CALL(encryption_observer_,
              OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
  EXPECT_CALL(encryption_observer_, OnPassphraseAccepted());
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_,
      OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
  sync_manager_.GetEncryptionHandler()->SetEncryptionPassphrase(
      "new_passphrase",
      true);
  EXPECT_EQ(CUSTOM_PASSPHRASE,
            sync_manager_.GetEncryptionHandler()->GetPassphraseType());
  EXPECT_TRUE(ResetUnsyncedEntry(PASSWORDS, client_tag));
}

// Passwords have their own handling for encryption. Verify it does not result
// in unnecessary writes via ReencryptEverything.
TEST_F(SyncManagerTest, UpdatePasswordReencryptEverything) {
  std::string client_tag = "title";
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  sync_pb::EntitySpecifics entity_specifics;
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* cryptographer = trans.GetCryptographer();
    sync_pb::PasswordSpecificsData data;
    data.set_password_value("secret");
    cryptographer->Encrypt(
        data,
        entity_specifics.mutable_password()->mutable_encrypted());
  }
  MakeServerNode(sync_manager_.GetUserShare(), PASSWORDS, client_tag,
                 syncable::GenerateSyncableHash(PASSWORDS,
                                                client_tag),
                 entity_specifics);
  // New node shouldn't start off unsynced.
  EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));

  // Force a re-encrypt everything. Should not set is_unsynced.
  testing::Mock::VerifyAndClearExpectations(&encryption_observer_);
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, false));
  sync_manager_.GetEncryptionHandler()->Init();
  PumpLoop();
  EXPECT_FALSE(ResetUnsyncedEntry(PASSWORDS, client_tag));
}

// Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for bookmarks
// when we write the same data, but does set it when we write new data.
TEST_F(SyncManagerTest, SetBookmarkTitle) {
  std::string client_tag = "title";
  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_bookmark()->set_url("url");
  entity_specifics.mutable_bookmark()->set_title("title");
  MakeServerNode(sync_manager_.GetUserShare(), BOOKMARKS, client_tag,
                 syncable::GenerateSyncableHash(BOOKMARKS,
                                                client_tag),
                 entity_specifics);
  // New node shouldn't start off unsynced.
  EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));

  // Manually change to the same title. Should not set is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    node.SetTitle(client_tag);
  }
  EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));

  // Manually change to new title. Should set is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    node.SetTitle("title2");
  }
  EXPECT_TRUE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
}

// Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for encrypted
// bookmarks when we write the same data, but does set it when we write new
// data.
TEST_F(SyncManagerTest, SetBookmarkTitleWithEncryption) {
  std::string client_tag = "title";
  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_bookmark()->set_url("url");
  entity_specifics.mutable_bookmark()->set_title("title");
  MakeServerNode(sync_manager_.GetUserShare(), BOOKMARKS, client_tag,
                 syncable::GenerateSyncableHash(BOOKMARKS,
                                                client_tag),
                 entity_specifics);
  // New node shouldn't start off unsynced.
  EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));

  // Encrypt the datatatype, should set is_unsynced.
  EXPECT_CALL(encryption_observer_,
              OnEncryptedTypesChanged(
                  HasModelTypes(EncryptableUserTypes()), true));
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, FULL_ENCRYPTION));
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, true));
  sync_manager_.GetEncryptionHandler()->Init();
  PumpLoop();
  EXPECT_TRUE(ResetUnsyncedEntry(BOOKMARKS, client_tag));

  // Manually change to the same title. Should not set is_unsynced.
  // NON_UNIQUE_NAME should be kEncryptedString.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    node.SetTitle(client_tag);
    const syncable::Entry* node_entry = node.GetEntry();
    const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
    EXPECT_TRUE(specifics.has_encrypted());
    EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
  }
  EXPECT_FALSE(ResetUnsyncedEntry(BOOKMARKS, client_tag));

  // Manually change to new title. Should set is_unsynced. NON_UNIQUE_NAME
  // should still be kEncryptedString.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    node.SetTitle("title2");
    const syncable::Entry* node_entry = node.GetEntry();
    const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
    EXPECT_TRUE(specifics.has_encrypted());
    EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
  }
  EXPECT_TRUE(ResetUnsyncedEntry(BOOKMARKS, client_tag));
}

// Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for non-bookmarks
// when we write the same data, but does set it when we write new data.
TEST_F(SyncManagerTest, SetNonBookmarkTitle) {
  std::string client_tag = "title";
  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_preference()->set_name("name");
  entity_specifics.mutable_preference()->set_value("value");
  MakeServerNode(sync_manager_.GetUserShare(),
                 PREFERENCES,
                 client_tag,
                 syncable::GenerateSyncableHash(PREFERENCES,
                                                client_tag),
                 entity_specifics);
  // New node shouldn't start off unsynced.
  EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, client_tag));

  // Manually change to the same title. Should not set is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(PREFERENCES, client_tag));
    node.SetTitle(client_tag);
  }
  EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, client_tag));

  // Manually change to new title. Should set is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(PREFERENCES, client_tag));
    node.SetTitle("title2");
  }
  EXPECT_TRUE(ResetUnsyncedEntry(PREFERENCES, client_tag));
}

// Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for encrypted
// non-bookmarks when we write the same data or when we write new data
// data (should remained kEncryptedString).
TEST_F(SyncManagerTest, SetNonBookmarkTitleWithEncryption) {
  std::string client_tag = "title";
  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_preference()->set_name("name");
  entity_specifics.mutable_preference()->set_value("value");
  MakeServerNode(sync_manager_.GetUserShare(),
                 PREFERENCES,
                 client_tag,
                 syncable::GenerateSyncableHash(PREFERENCES,
                                                client_tag),
                 entity_specifics);
  // New node shouldn't start off unsynced.
  EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, client_tag));

  // Encrypt the datatatype, should set is_unsynced.
  EXPECT_CALL(encryption_observer_,
              OnEncryptedTypesChanged(
                  HasModelTypes(EncryptableUserTypes()), true));
  EXPECT_CALL(encryption_observer_, OnEncryptionComplete());
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, FULL_ENCRYPTION));
  EXPECT_CALL(encryption_observer_, OnCryptographerStateChanged(_));
  EXPECT_CALL(encryption_observer_, OnEncryptedTypesChanged(_, true));
  sync_manager_.GetEncryptionHandler()->Init();
  PumpLoop();
  EXPECT_TRUE(ResetUnsyncedEntry(PREFERENCES, client_tag));

  // Manually change to the same title. Should not set is_unsynced.
  // NON_UNIQUE_NAME should be kEncryptedString.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(PREFERENCES, client_tag));
    node.SetTitle(client_tag);
    const syncable::Entry* node_entry = node.GetEntry();
    const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
    EXPECT_TRUE(specifics.has_encrypted());
    EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
  }
  EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, client_tag));

  // Manually change to new title. Should not set is_unsynced because the
  // NON_UNIQUE_NAME should still be kEncryptedString.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(PREFERENCES, client_tag));
    node.SetTitle("title2");
    const syncable::Entry* node_entry = node.GetEntry();
    const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
    EXPECT_TRUE(specifics.has_encrypted());
    EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
    EXPECT_FALSE(node_entry->GetIsUnsynced());
  }
}

// Ensure that titles are truncated to 255 bytes, and attempting to reset
// them to their longer version does not set IS_UNSYNCED.
TEST_F(SyncManagerTest, SetLongTitle) {
  const int kNumChars = 512;
  const std::string kClientTag = "tag";
  std::string title(kNumChars, '0');
  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_preference()->set_name("name");
  entity_specifics.mutable_preference()->set_value("value");
  MakeServerNode(sync_manager_.GetUserShare(),
                 PREFERENCES,
                 "short_title",
                 syncable::GenerateSyncableHash(PREFERENCES,
                                                kClientTag),
                 entity_specifics);
  // New node shouldn't start off unsynced.
  EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, kClientTag));

  // Manually change to the long title. Should set is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(PREFERENCES, kClientTag));
    node.SetTitle(title);
    EXPECT_EQ(node.GetTitle(), title.substr(0, 255));
  }
  EXPECT_TRUE(ResetUnsyncedEntry(PREFERENCES, kClientTag));

  // Manually change to the same title. Should not set is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(PREFERENCES, kClientTag));
    node.SetTitle(title);
    EXPECT_EQ(node.GetTitle(), title.substr(0, 255));
  }
  EXPECT_FALSE(ResetUnsyncedEntry(PREFERENCES, kClientTag));

  // Manually change to new title. Should set is_unsynced.
  {
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(PREFERENCES, kClientTag));
    node.SetTitle("title2");
  }
  EXPECT_TRUE(ResetUnsyncedEntry(PREFERENCES, kClientTag));
}

// Create an encrypted entry when the cryptographer doesn't think the type is
// marked for encryption. Ensure reads/writes don't break and don't unencrypt
// the data.
TEST_F(SyncManagerTest, SetPreviouslyEncryptedSpecifics) {
  std::string client_tag = "tag";
  std::string url = "url";
  std::string url2 = "new_url";
  std::string title = "title";
  sync_pb::EntitySpecifics entity_specifics;
  EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION));
  {
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    Cryptographer* crypto = trans.GetCryptographer();
    sync_pb::EntitySpecifics bm_specifics;
    bm_specifics.mutable_bookmark()->set_title("title");
    bm_specifics.mutable_bookmark()->set_url("url");
    sync_pb::EncryptedData encrypted;
    crypto->Encrypt(bm_specifics, &encrypted);
    entity_specifics.mutable_encrypted()->CopyFrom(encrypted);
    AddDefaultFieldValue(BOOKMARKS, &entity_specifics);
  }
  MakeServerNode(sync_manager_.GetUserShare(), BOOKMARKS, client_tag,
                 syncable::GenerateSyncableHash(BOOKMARKS,
                                                client_tag),
                 entity_specifics);

  {
    // Verify the data.
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    EXPECT_EQ(title, node.GetTitle());
    EXPECT_EQ(url, node.GetBookmarkSpecifics().url());
  }

  {
    // Overwrite the url (which overwrites the specifics).
    WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    WriteNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));

    sync_pb::BookmarkSpecifics bookmark_specifics(node.GetBookmarkSpecifics());
    bookmark_specifics.set_url(url2);
    node.SetBookmarkSpecifics(bookmark_specifics);
  }

  {
    // Verify it's still encrypted and it has the most recent url.
    ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare());
    ReadNode node(&trans);
    EXPECT_EQ(BaseNode::INIT_OK,
              node.InitByClientTagLookup(BOOKMARKS, client_tag));
    EXPECT_EQ(title, node.GetTitle());
    EXPECT_EQ(url2, node.GetBookmarkSpecifics().url());
    const syncable::Entry* node_entry = node.GetEntry();
    EXPECT_EQ(kEncryptedString, node_entry->GetNonUniqueName());
    const sync_pb::EntitySpecifics& specifics = node_entry->GetSpecifics();
    EXPECT_TRUE(specifics.has_encrypted());
  }
}

// Verify transaction version of a model type is incremented when node of
// that type is updated.
TEST_F(SyncManagerTest, IncrementTransactionVersion) {
  ModelSafeRoutingInfo routing_info;
  GetModelSafeRoutingInfo(&routing_info);

  {
    ReadTransaction read_trans(FROM_HERE, sync_manager_.GetUserShare());
    for (ModelSafeRoutingInfo::iterator i = routing_info.begin();
         i != routing_info.end(); ++i) {
      // Transaction version is incremented when SyncManagerTest::SetUp()
      // creates a node of each type.
      EXPECT_EQ(1,
                sync_manager_.GetUserShare()->directory->
                    GetTransactionVersion(i->first));
    }
  }

  // Create bookmark node to increment transaction version of bookmark model.
  std::string client_tag = "title";
  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_bookmark()->set_url("url");
  entity_specifics.mutable_bookmark()->set_title("title");
  MakeServerNode(sync_manager_.GetUserShare(), BOOKMARKS, client_tag,
                 syncable::GenerateSyncableHash(BOOKMARKS,
                                                client_tag),
                 entity_specifics);

  {
    ReadTransaction read_trans(FROM_HERE, sync_manager_.GetUserShare());
    for (ModelSafeRoutingInfo::iterator i = routing_info.begin();
         i != routing_info.end(); ++i) {
      EXPECT_EQ(i->first == BOOKMARKS ? 2 : 1,
                sync_manager_.GetUserShare()->directory->
                    GetTransactionVersion(i->first));
    }
  }
}

class MockSyncScheduler : public FakeSyncScheduler {
 public:
  MockSyncScheduler() : FakeSyncScheduler() {}
  virtual ~MockSyncScheduler() {}

  MOCK_METHOD1(Start, void(SyncScheduler::Mode));
  MOCK_METHOD1(ScheduleConfiguration, void(const ConfigurationParams&));
};

class ComponentsFactory : public TestInternalComponentsFactory {
 public:
  ComponentsFactory(const Switches& switches,
                    SyncScheduler* scheduler_to_use,
                    sessions::SyncSessionContext** session_context,
                    InternalComponentsFactory::StorageOption* storage_used)
      : TestInternalComponentsFactory(
          switches, InternalComponentsFactory::STORAGE_IN_MEMORY, storage_used),
        scheduler_to_use_(scheduler_to_use),
        session_context_(session_context) {}
  ~ComponentsFactory() override {}

  scoped_ptr<SyncScheduler> BuildScheduler(
      const std::string& name,
      sessions::SyncSessionContext* context,
      CancelationSignal* stop_handle) override {
    *session_context_ = context;
    return scheduler_to_use_.Pass();
  }

 private:
  scoped_ptr<SyncScheduler> scheduler_to_use_;
  sessions::SyncSessionContext** session_context_;
};

class SyncManagerTestWithMockScheduler : public SyncManagerTest {
 public:
  SyncManagerTestWithMockScheduler() : scheduler_(NULL) {}
  InternalComponentsFactory* GetFactory() override {
    scheduler_ = new MockSyncScheduler();
    return new ComponentsFactory(GetSwitches(), scheduler_, &session_context_,
                                 &storage_used_);
  }

  MockSyncScheduler* scheduler() { return scheduler_; }
  sessions::SyncSessionContext* session_context() {
      return session_context_;
  }

 private:
  MockSyncScheduler* scheduler_;
  sessions::SyncSessionContext* session_context_;
};

// Test that the configuration params are properly created and sent to
// ScheduleConfigure. No callback should be invoked. Any disabled datatypes
// should be purged.
TEST_F(SyncManagerTestWithMockScheduler, BasicConfiguration) {
  ConfigureReason reason = CONFIGURE_REASON_RECONFIGURATION;
  ModelTypeSet types_to_download(BOOKMARKS, PREFERENCES);
  ModelSafeRoutingInfo new_routing_info;
  GetModelSafeRoutingInfo(&new_routing_info);
  ModelTypeSet enabled_types = GetRoutingInfoTypes(new_routing_info);
  ModelTypeSet disabled_types = Difference(ModelTypeSet::All(), enabled_types);

  ConfigurationParams params;
  EXPECT_CALL(*scheduler(), Start(SyncScheduler::CONFIGURATION_MODE));
  EXPECT_CALL(*scheduler(), ScheduleConfiguration(_)).
      WillOnce(SaveArg<0>(&params));

  // Set data for all types.
  ModelTypeSet protocol_types = ProtocolTypes();
  for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good();
       iter.Inc()) {
    SetProgressMarkerForType(iter.Get(), true);
  }

  CallbackCounter ready_task_counter, retry_task_counter;
  sync_manager_.ConfigureSyncer(
      reason,
      types_to_download,
      disabled_types,
      ModelTypeSet(),
      ModelTypeSet(),
      new_routing_info,
      base::Bind(&CallbackCounter::Callback,
                 base::Unretained(&ready_task_counter)),
      base::Bind(&CallbackCounter::Callback,
                 base::Unretained(&retry_task_counter)));
  EXPECT_EQ(0, ready_task_counter.times_called());
  EXPECT_EQ(0, retry_task_counter.times_called());
  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RECONFIGURATION,
            params.source);
  EXPECT_TRUE(types_to_download.Equals(params.types_to_download));
  EXPECT_EQ(new_routing_info, params.routing_info);

  // Verify all the disabled types were purged.
  EXPECT_TRUE(sync_manager_.InitialSyncEndedTypes().Equals(
      enabled_types));
  EXPECT_TRUE(sync_manager_.GetTypesWithEmptyProgressMarkerToken(
      ModelTypeSet::All()).Equals(disabled_types));
}

// Test that on a reconfiguration (configuration where the session context
// already has routing info), only those recently disabled types are purged.
TEST_F(SyncManagerTestWithMockScheduler, ReConfiguration) {
  ConfigureReason reason = CONFIGURE_REASON_RECONFIGURATION;
  ModelTypeSet types_to_download(BOOKMARKS, PREFERENCES);
  ModelTypeSet disabled_types = ModelTypeSet(THEMES, SESSIONS);
  ModelSafeRoutingInfo old_routing_info;
  ModelSafeRoutingInfo new_routing_info;
  GetModelSafeRoutingInfo(&old_routing_info);
  new_routing_info = old_routing_info;
  new_routing_info.erase(THEMES);
  new_routing_info.erase(SESSIONS);
  ModelTypeSet enabled_types = GetRoutingInfoTypes(new_routing_info);

  ConfigurationParams params;
  EXPECT_CALL(*scheduler(), Start(SyncScheduler::CONFIGURATION_MODE));
  EXPECT_CALL(*scheduler(), ScheduleConfiguration(_)).
      WillOnce(SaveArg<0>(&params));

  // Set data for all types except those recently disabled (so we can verify
  // only those recently disabled are purged) .
  ModelTypeSet protocol_types = ProtocolTypes();
  for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good();
       iter.Inc()) {
    if (!disabled_types.Has(iter.Get())) {
      SetProgressMarkerForType(iter.Get(), true);
    } else {
      SetProgressMarkerForType(iter.Get(), false);
    }
  }

  // Set the context to have the old routing info.
  session_context()->SetRoutingInfo(old_routing_info);

  CallbackCounter ready_task_counter, retry_task_counter;
  sync_manager_.ConfigureSyncer(
      reason,
      types_to_download,
      ModelTypeSet(),
      ModelTypeSet(),
      ModelTypeSet(),
      new_routing_info,
      base::Bind(&CallbackCounter::Callback,
                 base::Unretained(&ready_task_counter)),
      base::Bind(&CallbackCounter::Callback,
                 base::Unretained(&retry_task_counter)));
  EXPECT_EQ(0, ready_task_counter.times_called());
  EXPECT_EQ(0, retry_task_counter.times_called());
  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RECONFIGURATION,
            params.source);
  EXPECT_TRUE(types_to_download.Equals(params.types_to_download));
  EXPECT_EQ(new_routing_info, params.routing_info);

  // Verify only the recently disabled types were purged.
  EXPECT_TRUE(sync_manager_.GetTypesWithEmptyProgressMarkerToken(
      ProtocolTypes()).Equals(disabled_types));
}

// Test that PurgePartiallySyncedTypes purges only those types that have not
// fully completed their initial download and apply.
TEST_F(SyncManagerTest, PurgePartiallySyncedTypes) {
  ModelSafeRoutingInfo routing_info;
  GetModelSafeRoutingInfo(&routing_info);
  ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);

  UserShare* share = sync_manager_.GetUserShare();

  // The test harness automatically initializes all types in the routing info.
  // Check that autofill is not among them.
  ASSERT_FALSE(enabled_types.Has(AUTOFILL));

  // Further ensure that the test harness did not create its root node.
  {
    syncable::ReadTransaction trans(FROM_HERE, share->directory.get());
    syncable::Entry autofill_root_node(&trans,
                                       syncable::GET_TYPE_ROOT,
                                       AUTOFILL);
    ASSERT_FALSE(autofill_root_node.good());
  }

  // One more redundant check.
  ASSERT_FALSE(sync_manager_.InitialSyncEndedTypes().Has(AUTOFILL));

  // Give autofill a progress marker.
  sync_pb::DataTypeProgressMarker autofill_marker;
  autofill_marker.set_data_type_id(
      GetSpecificsFieldNumberFromModelType(AUTOFILL));
  autofill_marker.set_token("token");
  share->directory->SetDownloadProgress(AUTOFILL, autofill_marker);

  // Also add a pending autofill root node update from the server.
  TestEntryFactory factory_(share->directory.get());
  int autofill_meta = factory_.CreateUnappliedRootNode(AUTOFILL);

  // Preferences is an enabled type.  Check that the harness initialized it.
  ASSERT_TRUE(enabled_types.Has(PREFERENCES));
  ASSERT_TRUE(sync_manager_.InitialSyncEndedTypes().Has(PREFERENCES));

  // Give preferencse a progress marker.
  sync_pb::DataTypeProgressMarker prefs_marker;
  prefs_marker.set_data_type_id(
      GetSpecificsFieldNumberFromModelType(PREFERENCES));
  prefs_marker.set_token("token");
  share->directory->SetDownloadProgress(PREFERENCES, prefs_marker);

  // Add a fully synced preferences node under the root.
  std::string pref_client_tag = "prefABC";
  std::string pref_hashed_tag = "hashXYZ";
  sync_pb::EntitySpecifics pref_specifics;
  AddDefaultFieldValue(PREFERENCES, &pref_specifics);
  int pref_meta = MakeServerNode(
      share, PREFERENCES, pref_client_tag, pref_hashed_tag, pref_specifics);

  // And now, the purge.
  EXPECT_TRUE(sync_manager_.PurgePartiallySyncedTypes());

  // Ensure that autofill lost its progress marker, but preferences did not.
  ModelTypeSet empty_tokens =
      sync_manager_.GetTypesWithEmptyProgressMarkerToken(ModelTypeSet::All());
  EXPECT_TRUE(empty_tokens.Has(AUTOFILL));
  EXPECT_FALSE(empty_tokens.Has(PREFERENCES));

  // Ensure that autofill lots its node, but preferences did not.
  {
    syncable::ReadTransaction trans(FROM_HERE, share->directory.get());
    syncable::Entry autofill_node(&trans, GET_BY_HANDLE, autofill_meta);
    syncable::Entry pref_node(&trans, GET_BY_HANDLE, pref_meta);
    EXPECT_FALSE(autofill_node.good());
    EXPECT_TRUE(pref_node.good());
  }
}

// Test CleanupDisabledTypes properly purges all disabled types as specified
// by the previous and current enabled params.
TEST_F(SyncManagerTest, PurgeDisabledTypes) {
  ModelSafeRoutingInfo routing_info;
  GetModelSafeRoutingInfo(&routing_info);
  ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
  ModelTypeSet disabled_types = Difference(ModelTypeSet::All(), enabled_types);

  // The harness should have initialized the enabled_types for us.
  EXPECT_TRUE(enabled_types.Equals(sync_manager_.InitialSyncEndedTypes()));

  // Set progress markers for all types.
  ModelTypeSet protocol_types = ProtocolTypes();
  for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good();
       iter.Inc()) {
    SetProgressMarkerForType(iter.Get(), true);
  }

  // Verify all the enabled types remain after cleanup, and all the disabled
  // types were purged.
  sync_manager_.PurgeDisabledTypes(disabled_types,
                                   ModelTypeSet(),
                                   ModelTypeSet());
  EXPECT_TRUE(enabled_types.Equals(sync_manager_.InitialSyncEndedTypes()));
  EXPECT_TRUE(disabled_types.Equals(
      sync_manager_.GetTypesWithEmptyProgressMarkerToken(ModelTypeSet::All())));

  // Disable some more types.
  disabled_types.Put(BOOKMARKS);
  disabled_types.Put(PREFERENCES);
  ModelTypeSet new_enabled_types =
      Difference(ModelTypeSet::All(), disabled_types);

  // Verify only the non-disabled types remain after cleanup.
  sync_manager_.PurgeDisabledTypes(disabled_types,
                                   ModelTypeSet(),
                                   ModelTypeSet());
  EXPECT_TRUE(new_enabled_types.Equals(sync_manager_.InitialSyncEndedTypes()));
  EXPECT_TRUE(disabled_types.Equals(
      sync_manager_.GetTypesWithEmptyProgressMarkerToken(ModelTypeSet::All())));
}

// Test PurgeDisabledTypes properly unapplies types by deleting their local data
// and preserving their server data and progress marker.
TEST_F(SyncManagerTest, PurgeUnappliedTypes) {
  ModelSafeRoutingInfo routing_info;
  GetModelSafeRoutingInfo(&routing_info);
  ModelTypeSet unapplied_types = ModelTypeSet(BOOKMARKS, PREFERENCES);
  ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
  ModelTypeSet disabled_types = Difference(ModelTypeSet::All(), enabled_types);

  // The harness should have initialized the enabled_types for us.
  EXPECT_TRUE(enabled_types.Equals(sync_manager_.InitialSyncEndedTypes()));

  // Set progress markers for all types.
  ModelTypeSet protocol_types = ProtocolTypes();
  for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good();
       iter.Inc()) {
    SetProgressMarkerForType(iter.Get(), true);
  }

  // Add the following kinds of items:
  // 1. Fully synced preference.
  // 2. Locally created preference, server unknown, unsynced
  // 3. Locally deleted preference, server known, unsynced
  // 4. Server deleted preference, locally known.
  // 5. Server created preference, locally unknown, unapplied.
  // 6. A fully synced bookmark (no unique_client_tag).
  UserShare* share = sync_manager_.GetUserShare();
  sync_pb::EntitySpecifics pref_specifics;
  AddDefaultFieldValue(PREFERENCES, &pref_specifics);
  sync_pb::EntitySpecifics bm_specifics;
  AddDefaultFieldValue(BOOKMARKS, &bm_specifics);
  int pref1_meta = MakeServerNode(
      share, PREFERENCES, "pref1", "hash1", pref_specifics);
  int64 pref2_meta = MakeNode(share, PREFERENCES, "pref2");
  int pref3_meta = MakeServerNode(
      share, PREFERENCES, "pref3", "hash3", pref_specifics);
  int pref4_meta = MakeServerNode(
      share, PREFERENCES, "pref4", "hash4", pref_specifics);
  int pref5_meta = MakeServerNode(
      share, PREFERENCES, "pref5", "hash5", pref_specifics);
  int bookmark_meta = MakeServerNode(
      share, BOOKMARKS, "bookmark", "", bm_specifics);

  {
    syncable::WriteTransaction trans(FROM_HERE,
                                     syncable::SYNCER,
                                     share->directory.get());
    // Pref's 1 and 2 are already set up properly.
    // Locally delete pref 3.
    syncable::MutableEntry pref3(&trans, GET_BY_HANDLE, pref3_meta);
    pref3.PutIsDel(true);
    pref3.PutIsUnsynced(true);
    // Delete pref 4 at the server.
    syncable::MutableEntry pref4(&trans, GET_BY_HANDLE, pref4_meta);
    pref4.PutServerIsDel(true);
    pref4.PutIsUnappliedUpdate(true);
    pref4.PutServerVersion(2);
    // Pref 5 is an new unapplied update.
    syncable::MutableEntry pref5(&trans, GET_BY_HANDLE, pref5_meta);
    pref5.PutIsUnappliedUpdate(true);
    pref5.PutIsDel(true);
    pref5.PutBaseVersion(-1);
    // Bookmark is already set up properly
  }

  // Take a snapshot to clear all the dirty bits.
  share->directory.get()->SaveChanges();

  // Now request a purge for the unapplied types.
  disabled_types.PutAll(unapplied_types);
  sync_manager_.PurgeDisabledTypes(disabled_types,
                                   ModelTypeSet(),
                                   unapplied_types);

  // Verify the unapplied types still have progress markers and initial sync
  // ended after cleanup.
  EXPECT_TRUE(sync_manager_.InitialSyncEndedTypes().HasAll(unapplied_types));
  EXPECT_TRUE(
      sync_manager_.GetTypesWithEmptyProgressMarkerToken(unapplied_types).
          Empty());

  // Ensure the items were unapplied as necessary.
  {
    syncable::ReadTransaction trans(FROM_HERE, share->directory.get());
    syncable::Entry pref_node(&trans, GET_BY_HANDLE, pref1_meta);
    ASSERT_TRUE(pref_node.good());
    EXPECT_TRUE(pref_node.GetKernelCopy().is_dirty());
    EXPECT_FALSE(pref_node.GetIsUnsynced());
    EXPECT_TRUE(pref_node.GetIsUnappliedUpdate());
    EXPECT_TRUE(pref_node.GetIsDel());
    EXPECT_GT(pref_node.GetServerVersion(), 0);
    EXPECT_EQ(pref_node.GetBaseVersion(), -1);

    // Pref 2 should just be locally deleted.
    syncable::Entry pref2_node(&trans, GET_BY_HANDLE, pref2_meta);
    ASSERT_TRUE(pref2_node.good());
    EXPECT_TRUE(pref2_node.GetKernelCopy().is_dirty());
    EXPECT_FALSE(pref2_node.GetIsUnsynced());
    EXPECT_TRUE(pref2_node.GetIsDel());
    EXPECT_FALSE(pref2_node.GetIsUnappliedUpdate());
    EXPECT_TRUE(pref2_node.GetIsDel());
    EXPECT_EQ(pref2_node.GetServerVersion(), 0);
    EXPECT_EQ(pref2_node.GetBaseVersion(), -1);

    syncable::Entry pref3_node(&trans, GET_BY_HANDLE, pref3_meta);
    ASSERT_TRUE(pref3_node.good());
    EXPECT_TRUE(pref3_node.GetKernelCopy().is_dirty());
    EXPECT_FALSE(pref3_node.GetIsUnsynced());
    EXPECT_TRUE(pref3_node.GetIsUnappliedUpdate());
    EXPECT_TRUE(pref3_node.GetIsDel());
    EXPECT_GT(pref3_node.GetServerVersion(), 0);
    EXPECT_EQ(pref3_node.GetBaseVersion(), -1);

    syncable::Entry pref4_node(&trans, GET_BY_HANDLE, pref4_meta);
    ASSERT_TRUE(pref4_node.good());
    EXPECT_TRUE(pref4_node.GetKernelCopy().is_dirty());
    EXPECT_FALSE(pref4_node.GetIsUnsynced());
    EXPECT_TRUE(pref4_node.GetIsUnappliedUpdate());
    EXPECT_TRUE(pref4_node.GetIsDel());
    EXPECT_GT(pref4_node.GetServerVersion(), 0);
    EXPECT_EQ(pref4_node.GetBaseVersion(), -1);

    // Pref 5 should remain untouched.
    syncable::Entry pref5_node(&trans, GET_BY_HANDLE, pref5_meta);
    ASSERT_TRUE(pref5_node.good());
    EXPECT_FALSE(pref5_node.GetKernelCopy().is_dirty());
    EXPECT_FALSE(pref5_node.GetIsUnsynced());
    EXPECT_TRUE(pref5_node.GetIsUnappliedUpdate());
    EXPECT_TRUE(pref5_node.GetIsDel());
    EXPECT_GT(pref5_node.GetServerVersion(), 0);
    EXPECT_EQ(pref5_node.GetBaseVersion(), -1);

    syncable::Entry bookmark_node(&trans, GET_BY_HANDLE, bookmark_meta);
    ASSERT_TRUE(bookmark_node.good());
    EXPECT_TRUE(bookmark_node.GetKernelCopy().is_dirty());
    EXPECT_FALSE(bookmark_node.GetIsUnsynced());
    EXPECT_TRUE(bookmark_node.GetIsUnappliedUpdate());
    EXPECT_TRUE(bookmark_node.GetIsDel());
    EXPECT_GT(bookmark_node.GetServerVersion(), 0);
    EXPECT_EQ(bookmark_node.GetBaseVersion(), -1);
  }
}

// A test harness to exercise the code that processes and passes changes from
// the "SYNCER"-WriteTransaction destructor, through the SyncManager, to the
// ChangeProcessor.
class SyncManagerChangeProcessingTest : public SyncManagerTest {
 public:
  void OnChangesApplied(ModelType model_type,
                        int64 model_version,
                        const BaseTransaction* trans,
                        const ImmutableChangeRecordList& changes) override {
    last_changes_ = changes;
  }

  void OnChangesComplete(ModelType model_type) override {}

  const ImmutableChangeRecordList& GetRecentChangeList() {
    return last_changes_;
  }

  UserShare* share() {
    return sync_manager_.GetUserShare();
  }

  // Set some flags so our nodes reasonably approximate the real world scenario
  // and can get past CheckTreeInvariants.
  //
  // It's never going to be truly accurate, since we're squashing update
  // receipt, processing and application into a single transaction.
  void SetNodeProperties(syncable::MutableEntry *entry) {
    entry->PutId(id_factory_.NewServerId());
    entry->PutBaseVersion(10);
    entry->PutServerVersion(10);
  }

  // Looks for the given change in the list.  Returns the index at which it was
  // found.  Returns -1 on lookup failure.
  size_t FindChangeInList(int64 id, ChangeRecord::Action action) {
    SCOPED_TRACE(id);
    for (size_t i = 0; i < last_changes_.Get().size(); ++i) {
      if (last_changes_.Get()[i].id == id
          && last_changes_.Get()[i].action == action) {
        return i;
      }
    }
    ADD_FAILURE() << "Failed to find specified change";
    return static_cast<size_t>(-1);
  }

  // Returns the current size of the change list.
  //
  // Note that spurious changes do not necessarily indicate a problem.
  // Assertions on change list size can help detect problems, but it may be
  // necessary to reduce their strictness if the implementation changes.
  size_t GetChangeListSize() {
    return last_changes_.Get().size();
  }

  void ClearChangeList() { last_changes_ = ImmutableChangeRecordList(); }

 protected:
  ImmutableChangeRecordList last_changes_;
  TestIdFactory id_factory_;
};

// Test creation of a folder and a bookmark.
TEST_F(SyncManagerChangeProcessingTest, AddBookmarks) {
  int64 type_root = GetIdForDataType(BOOKMARKS);
  int64 folder_id = kInvalidId;
  int64 child_id = kInvalidId;

  // Create a folder and a bookmark under it.
  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());
    syncable::Entry root(&trans, syncable::GET_BY_HANDLE, type_root);
    ASSERT_TRUE(root.good());

    syncable::MutableEntry folder(&trans, syncable::CREATE,
                                  BOOKMARKS, root.GetId(), "folder");
    ASSERT_TRUE(folder.good());
    SetNodeProperties(&folder);
    folder.PutIsDir(true);
    folder_id = folder.GetMetahandle();

    syncable::MutableEntry child(&trans, syncable::CREATE,
                                 BOOKMARKS, folder.GetId(), "child");
    ASSERT_TRUE(child.good());
    SetNodeProperties(&child);
    child_id = child.GetMetahandle();
  }

  // The closing of the above scope will delete the transaction.  Its processed
  // changes should be waiting for us in a member of the test harness.
  EXPECT_EQ(2UL, GetChangeListSize());

  // We don't need to check these return values here.  The function will add a
  // non-fatal failure if these changes are not found.
  size_t folder_change_pos =
      FindChangeInList(folder_id, ChangeRecord::ACTION_ADD);
  size_t child_change_pos =
      FindChangeInList(child_id, ChangeRecord::ACTION_ADD);

  // Parents are delivered before children.
  EXPECT_LT(folder_change_pos, child_change_pos);
}

// Test moving a bookmark into an empty folder.
TEST_F(SyncManagerChangeProcessingTest, MoveBookmarkIntoEmptyFolder) {
  int64 type_root = GetIdForDataType(BOOKMARKS);
  int64 folder_b_id = kInvalidId;
  int64 child_id = kInvalidId;

  // Create two folders.  Place a child under folder A.
  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());
    syncable::Entry root(&trans, syncable::GET_BY_HANDLE, type_root);
    ASSERT_TRUE(root.good());

    syncable::MutableEntry folder_a(&trans, syncable::CREATE,
                                    BOOKMARKS, root.GetId(), "folderA");
    ASSERT_TRUE(folder_a.good());
    SetNodeProperties(&folder_a);
    folder_a.PutIsDir(true);

    syncable::MutableEntry folder_b(&trans, syncable::CREATE,
                                    BOOKMARKS, root.GetId(), "folderB");
    ASSERT_TRUE(folder_b.good());
    SetNodeProperties(&folder_b);
    folder_b.PutIsDir(true);
    folder_b_id = folder_b.GetMetahandle();

    syncable::MutableEntry child(&trans, syncable::CREATE,
                                 BOOKMARKS, folder_a.GetId(),
                                 "child");
    ASSERT_TRUE(child.good());
    SetNodeProperties(&child);
    child_id = child.GetMetahandle();
  }

  // Close that transaction.  The above was to setup the initial scenario.  The
  // real test starts now.

  // Move the child from folder A to folder B.
  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());

    syncable::Entry folder_b(&trans, syncable::GET_BY_HANDLE, folder_b_id);
    syncable::MutableEntry child(&trans, syncable::GET_BY_HANDLE, child_id);

    child.PutParentId(folder_b.GetId());
  }

  EXPECT_EQ(1UL, GetChangeListSize());

  // Verify that this was detected as a real change.  An early version of the
  // UniquePosition code had a bug where moves from one folder to another were
  // ignored unless the moved node's UniquePosition value was also changed in
  // some way.
  FindChangeInList(child_id, ChangeRecord::ACTION_UPDATE);
}

// Test moving a bookmark into a non-empty folder.
TEST_F(SyncManagerChangeProcessingTest, MoveIntoPopulatedFolder) {
  int64 type_root = GetIdForDataType(BOOKMARKS);
  int64 child_a_id = kInvalidId;
  int64 child_b_id = kInvalidId;

  // Create two folders.  Place one child each under folder A and folder B.
  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());
    syncable::Entry root(&trans, syncable::GET_BY_HANDLE, type_root);
    ASSERT_TRUE(root.good());

    syncable::MutableEntry folder_a(&trans, syncable::CREATE,
                                    BOOKMARKS, root.GetId(), "folderA");
    ASSERT_TRUE(folder_a.good());
    SetNodeProperties(&folder_a);
    folder_a.PutIsDir(true);

    syncable::MutableEntry folder_b(&trans, syncable::CREATE,
                                    BOOKMARKS, root.GetId(), "folderB");
    ASSERT_TRUE(folder_b.good());
    SetNodeProperties(&folder_b);
    folder_b.PutIsDir(true);

    syncable::MutableEntry child_a(&trans, syncable::CREATE,
                                   BOOKMARKS, folder_a.GetId(),
                                   "childA");
    ASSERT_TRUE(child_a.good());
    SetNodeProperties(&child_a);
    child_a_id = child_a.GetMetahandle();

    syncable::MutableEntry child_b(&trans, syncable::CREATE,
                                   BOOKMARKS, folder_b.GetId(),
                                   "childB");
    SetNodeProperties(&child_b);
    child_b_id = child_b.GetMetahandle();
  }

  // Close that transaction.  The above was to setup the initial scenario.  The
  // real test starts now.

  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());

    syncable::MutableEntry child_a(&trans, syncable::GET_BY_HANDLE, child_a_id);
    syncable::MutableEntry child_b(&trans, syncable::GET_BY_HANDLE, child_b_id);

    // Move child A from folder A to folder B and update its position.
    child_a.PutParentId(child_b.GetParentId());
    child_a.PutPredecessor(child_b.GetId());
  }

  EXPECT_EQ(1UL, GetChangeListSize());

  // Verify that only child a is in the change list.
  // (This function will add a failure if the lookup fails.)
  FindChangeInList(child_a_id, ChangeRecord::ACTION_UPDATE);
}

// Tests the ordering of deletion changes.
TEST_F(SyncManagerChangeProcessingTest, DeletionsAndChanges) {
  int64 type_root = GetIdForDataType(BOOKMARKS);
  int64 folder_a_id = kInvalidId;
  int64 folder_b_id = kInvalidId;
  int64 child_id = kInvalidId;

  // Create two folders.  Place a child under folder A.
  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());
    syncable::Entry root(&trans, syncable::GET_BY_HANDLE, type_root);
    ASSERT_TRUE(root.good());

    syncable::MutableEntry folder_a(&trans, syncable::CREATE,
                                    BOOKMARKS, root.GetId(), "folderA");
    ASSERT_TRUE(folder_a.good());
    SetNodeProperties(&folder_a);
    folder_a.PutIsDir(true);
    folder_a_id = folder_a.GetMetahandle();

    syncable::MutableEntry folder_b(&trans, syncable::CREATE,
                                    BOOKMARKS, root.GetId(), "folderB");
    ASSERT_TRUE(folder_b.good());
    SetNodeProperties(&folder_b);
    folder_b.PutIsDir(true);
    folder_b_id = folder_b.GetMetahandle();

    syncable::MutableEntry child(&trans, syncable::CREATE,
                                 BOOKMARKS, folder_a.GetId(),
                                 "child");
    ASSERT_TRUE(child.good());
    SetNodeProperties(&child);
    child_id = child.GetMetahandle();
  }

  // Close that transaction.  The above was to setup the initial scenario.  The
  // real test starts now.

  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());

    syncable::MutableEntry folder_a(
        &trans, syncable::GET_BY_HANDLE, folder_a_id);
    syncable::MutableEntry folder_b(
        &trans, syncable::GET_BY_HANDLE, folder_b_id);
    syncable::MutableEntry child(&trans, syncable::GET_BY_HANDLE, child_id);

    // Delete folder B and its child.
    child.PutIsDel(true);
    folder_b.PutIsDel(true);

    // Make an unrelated change to folder A.
    folder_a.PutNonUniqueName("NewNameA");
  }

  EXPECT_EQ(3UL, GetChangeListSize());

  size_t folder_a_pos =
      FindChangeInList(folder_a_id, ChangeRecord::ACTION_UPDATE);
  size_t folder_b_pos =
      FindChangeInList(folder_b_id, ChangeRecord::ACTION_DELETE);
  size_t child_pos = FindChangeInList(child_id, ChangeRecord::ACTION_DELETE);

  // Deletes should appear before updates.
  EXPECT_LT(child_pos, folder_a_pos);
  EXPECT_LT(folder_b_pos, folder_a_pos);
}

// See that attachment metadata changes are not filtered out by
// SyncManagerImpl::VisiblePropertiesDiffer.
TEST_F(SyncManagerChangeProcessingTest, AttachmentMetadataOnlyChanges) {
  // Create an article with no attachments.  See that a change is generated.
  int64 article_id = kInvalidId;
  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());
    int64 type_root = GetIdForDataType(ARTICLES);
    syncable::Entry root(&trans, syncable::GET_BY_HANDLE, type_root);
    ASSERT_TRUE(root.good());
    syncable::MutableEntry article(
        &trans, syncable::CREATE, ARTICLES, root.GetId(), "article");
    ASSERT_TRUE(article.good());
    SetNodeProperties(&article);
    article_id = article.GetMetahandle();
  }
  ASSERT_EQ(1UL, GetChangeListSize());
  FindChangeInList(article_id, ChangeRecord::ACTION_ADD);
  ClearChangeList();

  // Modify the article by adding one attachment.  Don't touch anything else.
  // See that a change is generated.
  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());
    syncable::MutableEntry article(&trans, syncable::GET_BY_HANDLE, article_id);
    sync_pb::AttachmentMetadata metadata;
    *metadata.add_record()->mutable_id() = CreateAttachmentIdProto();
    article.PutAttachmentMetadata(metadata);
  }
  ASSERT_EQ(1UL, GetChangeListSize());
  FindChangeInList(article_id, ChangeRecord::ACTION_UPDATE);
  ClearChangeList();

  // Modify the article by replacing its attachment with a different one.  See
  // that a change is generated.
  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());
    syncable::MutableEntry article(&trans, syncable::GET_BY_HANDLE, article_id);
    sync_pb::AttachmentMetadata metadata = article.GetAttachmentMetadata();
    *metadata.add_record()->mutable_id() = CreateAttachmentIdProto();
    article.PutAttachmentMetadata(metadata);
  }
  ASSERT_EQ(1UL, GetChangeListSize());
  FindChangeInList(article_id, ChangeRecord::ACTION_UPDATE);
  ClearChangeList();

  // Modify the article by replacing its attachment metadata with the same
  // attachment metadata.  No change should be generated.
  {
    syncable::WriteTransaction trans(
        FROM_HERE, syncable::SYNCER, share()->directory.get());
    syncable::MutableEntry article(&trans, syncable::GET_BY_HANDLE, article_id);
    article.PutAttachmentMetadata(article.GetAttachmentMetadata());
  }
  ASSERT_EQ(0UL, GetChangeListSize());
}

// During initialization SyncManagerImpl loads sqlite database. If it fails to
// do so it should fail initialization. This test verifies this behavior.
// Test reuses SyncManagerImpl initialization from SyncManagerTest but overrides
// InternalComponentsFactory to return DirectoryBackingStore that always fails
// to load.
class SyncManagerInitInvalidStorageTest : public SyncManagerTest {
 public:
  SyncManagerInitInvalidStorageTest() {
  }

  InternalComponentsFactory* GetFactory() override {
    return new TestInternalComponentsFactory(
        GetSwitches(), InternalComponentsFactory::STORAGE_INVALID,
        &storage_used_);
  }
};

// SyncManagerInitInvalidStorageTest::GetFactory will return
// DirectoryBackingStore that ensures that SyncManagerImpl::OpenDirectory fails.
// SyncManagerImpl initialization is done in SyncManagerTest::SetUp. This test's
// task is to ensure that SyncManagerImpl reported initialization failure in
// OnInitializationComplete callback.
TEST_F(SyncManagerInitInvalidStorageTest, FailToOpenDatabase) {
  EXPECT_FALSE(initialization_succeeded_);
}

}  // namespace syncer
