// Copyright (c) 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.

#include "base/format_macros.h"
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/stringprintf.h"
#include "sync/engine/apply_control_data_updates.h"
#include "sync/engine/syncer.h"
#include "sync/engine/syncer_util.h"
#include "sync/internal_api/public/test/test_entry_factory.h"
#include "sync/protocol/nigori_specifics.pb.h"
#include "sync/syncable/mutable_entry.h"
#include "sync/syncable/nigori_util.h"
#include "sync/syncable/read_transaction.h"
#include "sync/syncable/syncable_util.h"
#include "sync/syncable/write_transaction.h"
#include "sync/test/engine/fake_model_worker.h"
#include "sync/test/engine/syncer_command_test.h"
#include "sync/test/engine/test_id_factory.h"
#include "sync/test/fake_sync_encryption_handler.h"
#include "sync/util/cryptographer.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace syncer {

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

class ApplyControlDataUpdatesTest : public SyncerCommandTest {
 public:
 protected:
  ApplyControlDataUpdatesTest() {}
  virtual ~ApplyControlDataUpdatesTest() {}

  virtual void SetUp() {
    workers()->clear();
    mutable_routing_info()->clear();
    workers()->push_back(make_scoped_refptr(new FakeModelWorker(GROUP_UI)));
    workers()->push_back(
        make_scoped_refptr(new FakeModelWorker(GROUP_PASSWORD)));
    (*mutable_routing_info())[BOOKMARKS] = GROUP_UI;
    (*mutable_routing_info())[PASSWORDS] = GROUP_PASSWORD;
    (*mutable_routing_info())[NIGORI] = GROUP_PASSIVE;
    SyncerCommandTest::SetUp();
    entry_factory_.reset(new TestEntryFactory(directory()));

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

  TestIdFactory id_factory_;
  scoped_ptr<TestEntryFactory> entry_factory_;
 private:
  DISALLOW_COPY_AND_ASSIGN(ApplyControlDataUpdatesTest);
};

// Verify that applying a nigori node sets initial sync ended properly,
// updates the set of encrypted types, and updates the cryptographer.
TEST_F(ApplyControlDataUpdatesTest, NigoriUpdate) {
  // Storing the cryptographer separately is bad, but for this test we
  // know it's safe.
  Cryptographer* cryptographer;
  ModelTypeSet encrypted_types;
  encrypted_types.PutAll(SyncEncryptionHandler::SensitiveTypes());

  // We start with initial_sync_ended == false.  This is wrong, since we would
  // have no nigori node if that were the case.  However, it makes it easier to
  // verify that ApplyControlDataUpdates sets initial_sync_ended correctly.
  EXPECT_FALSE(directory()->initial_sync_ended_types().Has(NIGORI));

  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(encrypted_types));
  }

  // Nigori node updates should update the Cryptographer.
  Cryptographer other_cryptographer(cryptographer->encryptor());
  KeyParams params = {"localhost", "dummy", "foobar"};
  other_cryptographer.AddKey(params);

  sync_pb::EntitySpecifics specifics;
  sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
  other_cryptographer.GetKeys(nigori->mutable_encryption_keybag());
  nigori->set_encrypt_everything(true);
  entry_factory_->CreateUnappliedNewItem(
      ModelTypeToRootTag(NIGORI), specifics, true);
  EXPECT_FALSE(cryptographer->has_pending_keys());

  ApplyControlDataUpdates(directory());

  EXPECT_FALSE(cryptographer->is_ready());
  EXPECT_TRUE(cryptographer->has_pending_keys());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(ModelTypeSet::All()));
    EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI));
  }
}

// Create some local unsynced and unencrypted data. Apply a nigori update that
// turns on encryption for the unsynced data. Ensure we properly encrypt the
// data as part of the nigori update. Apply another nigori update with no
// changes. Ensure we ignore already-encrypted unsynced data and that nothing
// breaks.
TEST_F(ApplyControlDataUpdatesTest, EncryptUnsyncedChanges) {
  // Storing the cryptographer separately is bad, but for this test we
  // know it's safe.
  Cryptographer* cryptographer;
  ModelTypeSet encrypted_types;
  encrypted_types.PutAll(SyncEncryptionHandler::SensitiveTypes());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(encrypted_types));

    // With default encrypted_types, this should be true.
    EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));

    Syncer::UnsyncedMetaHandles handles;
    GetUnsyncedEntries(&trans, &handles);
    EXPECT_TRUE(handles.empty());
  }

  // Create unsynced bookmarks without encryption.
  // First item is a folder
  Id folder_id = id_factory_.NewLocalId();
  entry_factory_->CreateUnsyncedItem(folder_id, id_factory_.root(), "folder",
                                     true, BOOKMARKS, NULL);
  // Next five items are children of the folder
  size_t i;
  size_t batch_s = 5;
  for (i = 0; i < batch_s; ++i) {
    entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
                                       base::StringPrintf("Item %"PRIuS"", i),
                                       false, BOOKMARKS, NULL);
  }
  // Next five items are children of the root.
  for (; i < 2*batch_s; ++i) {
    entry_factory_->CreateUnsyncedItem(
        id_factory_.NewLocalId(), id_factory_.root(),
        base::StringPrintf("Item %"PRIuS"", i), false,
        BOOKMARKS, NULL);
  }

  KeyParams params = {"localhost", "dummy", "foobar"};
  cryptographer->AddKey(params);
  sync_pb::EntitySpecifics specifics;
  sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
  cryptographer->GetKeys(nigori->mutable_encryption_keybag());
  nigori->set_encrypt_everything(true);
  encrypted_types.Put(BOOKMARKS);
  entry_factory_->CreateUnappliedNewItem(
      ModelTypeToRootTag(NIGORI), specifics, true);
  EXPECT_FALSE(cryptographer->has_pending_keys());
  EXPECT_TRUE(cryptographer->is_ready());

  {
    // Ensure we have unsynced nodes that aren't properly encrypted.
    syncable::ReadTransaction trans(FROM_HERE, directory());
    EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));

    Syncer::UnsyncedMetaHandles handles;
    GetUnsyncedEntries(&trans, &handles);
    EXPECT_EQ(2*batch_s+1, handles.size());
  }

  ApplyControlDataUpdates(directory());

  EXPECT_FALSE(cryptographer->has_pending_keys());
  EXPECT_TRUE(cryptographer->is_ready());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());

    // If ProcessUnsyncedChangesForEncryption worked, all our unsynced changes
    // should be encrypted now.
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(ModelTypeSet::All()));
    EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));

    Syncer::UnsyncedMetaHandles handles;
    GetUnsyncedEntries(&trans, &handles);
    EXPECT_EQ(2*batch_s+1, handles.size());
  }

  // Simulate another nigori update that doesn't change anything.
  {
    syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory());
    MutableEntry entry(&trans, syncable::GET_BY_SERVER_TAG,
                       ModelTypeToRootTag(NIGORI));
    ASSERT_TRUE(entry.good());
    entry.Put(syncable::SERVER_VERSION, entry_factory_->GetNextRevision());
    entry.Put(syncable::IS_UNAPPLIED_UPDATE, true);
  }

  ApplyControlDataUpdates(directory());

  EXPECT_FALSE(cryptographer->has_pending_keys());
  EXPECT_TRUE(cryptographer->is_ready());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());

    // All our changes should still be encrypted.
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(ModelTypeSet::All()));
    EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));

    Syncer::UnsyncedMetaHandles handles;
    GetUnsyncedEntries(&trans, &handles);
    EXPECT_EQ(2*batch_s+1, handles.size());
  }
}

// Create some local unsynced and unencrypted changes. Receive a new nigori
// node enabling their encryption but also introducing pending keys. Ensure
// we apply the update properly without encrypting the unsynced changes or
// breaking.
TEST_F(ApplyControlDataUpdatesTest, CannotEncryptUnsyncedChanges) {
  // Storing the cryptographer separately is bad, but for this test we
  // know it's safe.
  Cryptographer* cryptographer;
  ModelTypeSet encrypted_types;
  encrypted_types.PutAll(SyncEncryptionHandler::SensitiveTypes());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(encrypted_types));

    // With default encrypted_types, this should be true.
    EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));

    Syncer::UnsyncedMetaHandles handles;
    GetUnsyncedEntries(&trans, &handles);
    EXPECT_TRUE(handles.empty());
  }

  // Create unsynced bookmarks without encryption.
  // First item is a folder
  Id folder_id = id_factory_.NewLocalId();
  entry_factory_->CreateUnsyncedItem(
      folder_id, id_factory_.root(), "folder", true,
      BOOKMARKS, NULL);
  // Next five items are children of the folder
  size_t i;
  size_t batch_s = 5;
  for (i = 0; i < batch_s; ++i) {
    entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id,
                                       base::StringPrintf("Item %"PRIuS"", i),
                                       false, BOOKMARKS, NULL);
  }
  // Next five items are children of the root.
  for (; i < 2*batch_s; ++i) {
    entry_factory_->CreateUnsyncedItem(
        id_factory_.NewLocalId(), id_factory_.root(),
        base::StringPrintf("Item %"PRIuS"", i), false,
        BOOKMARKS, NULL);
  }

  // We encrypt with new keys, triggering the local cryptographer to be unready
  // and unable to decrypt data (once updated).
  Cryptographer other_cryptographer(cryptographer->encryptor());
  KeyParams params = {"localhost", "dummy", "foobar"};
  other_cryptographer.AddKey(params);
  sync_pb::EntitySpecifics specifics;
  sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori();
  other_cryptographer.GetKeys(nigori->mutable_encryption_keybag());
  nigori->set_encrypt_everything(true);
  encrypted_types.Put(BOOKMARKS);
  entry_factory_->CreateUnappliedNewItem(
      ModelTypeToRootTag(NIGORI), specifics, true);
  EXPECT_FALSE(cryptographer->has_pending_keys());

  {
    // Ensure we have unsynced nodes that aren't properly encrypted.
    syncable::ReadTransaction trans(FROM_HERE, directory());
    EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
    Syncer::UnsyncedMetaHandles handles;
    GetUnsyncedEntries(&trans, &handles);
    EXPECT_EQ(2*batch_s+1, handles.size());
  }

  ApplyControlDataUpdates(directory());

  EXPECT_FALSE(cryptographer->is_ready());
  EXPECT_TRUE(cryptographer->has_pending_keys());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());

    // Since we have pending keys, we would have failed to encrypt, but the
    // cryptographer should be updated.
    EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types));
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(ModelTypeSet::All()));
    EXPECT_FALSE(cryptographer->is_ready());
    EXPECT_TRUE(cryptographer->has_pending_keys());

    Syncer::UnsyncedMetaHandles handles;
    GetUnsyncedEntries(&trans, &handles);
    EXPECT_EQ(2*batch_s+1, handles.size());
  }
}

// Verify we handle a nigori node conflict by merging encryption keys and
// types, but preserve the custom passphrase state of the server.
// Initial sync ended should be set.
TEST_F(ApplyControlDataUpdatesTest,
       NigoriConflictPendingKeysServerEncryptEverythingCustom) {
  Cryptographer* cryptographer;
  ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
  KeyParams other_params = {"localhost", "dummy", "foobar"};
  KeyParams local_params = {"localhost", "dummy", "local"};
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    EXPECT_TRUE(encrypted_types.Equals(
            directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
  }

  // Set up a temporary cryptographer to generate new keys with.
  Cryptographer other_cryptographer(cryptographer->encryptor());
  other_cryptographer.AddKey(other_params);

  // Create server specifics with pending keys, new encrypted types,
  // and a custom passphrase (unmigrated).
  sync_pb::EntitySpecifics server_specifics;
  sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
  other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
  server_nigori->set_encrypt_everything(true);
  server_nigori->set_keybag_is_frozen(true);
  int64 nigori_handle =
      entry_factory_->CreateUnappliedNewItem(kNigoriTag,
                                             server_specifics,
                                             true);

  // Initialize the local cryptographer with the local keys.
  cryptographer->AddKey(local_params);
  EXPECT_TRUE(cryptographer->is_ready());

  // Set up a local nigori with the local encryption keys and default encrypted
  // types.
  sync_pb::EntitySpecifics local_specifics;
  sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
  cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
  local_nigori->set_encrypt_everything(false);
  local_nigori->set_keybag_is_frozen(true);
  ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
          nigori_handle, local_specifics));
  // Apply the update locally so that UpdateFromEncryptedTypes knows what state
  // to use.
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    directory()->GetNigoriHandler()->ApplyNigoriUpdate(
        *local_nigori,
        &trans);
  }

  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
  ApplyControlDataUpdates(directory());
  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));

  EXPECT_FALSE(cryptographer->is_ready());
  EXPECT_TRUE(cryptographer->is_initialized());
  EXPECT_TRUE(cryptographer->has_pending_keys());
  EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey(
          entry_factory_->GetLocalSpecificsForItem(nigori_handle).
              nigori().encryption_keybag()));
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().keybag_is_frozen());
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().encrypt_everything());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(ModelTypeSet::All()));
    EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI));
  }
}

// Verify we handle a nigori node conflict by merging encryption keys and
// types, but preserve the custom passphrase state of the server.
// Initial sync ended should be set.
TEST_F(ApplyControlDataUpdatesTest,
       NigoriConflictPendingKeysLocalEncryptEverythingCustom) {
  Cryptographer* cryptographer;
  ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
  KeyParams other_params = {"localhost", "dummy", "foobar"};
  KeyParams local_params = {"localhost", "dummy", "local"};
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    EXPECT_TRUE(encrypted_types.Equals(
            directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
  }

  // Set up a temporary cryptographer to generate new keys with.
  Cryptographer other_cryptographer(cryptographer->encryptor());
  other_cryptographer.AddKey(other_params);

  // Create server specifics with pending keys, new encrypted types,
  // and a custom passphrase (unmigrated).
  sync_pb::EntitySpecifics server_specifics;
  sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
  other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
  server_nigori->set_encrypt_everything(false);
  server_nigori->set_keybag_is_frozen(false);
  int64 nigori_handle =
      entry_factory_->CreateUnappliedNewItem(kNigoriTag,
                                             server_specifics,
                                             true);

  // Initialize the local cryptographer with the local keys.
  cryptographer->AddKey(local_params);
  EXPECT_TRUE(cryptographer->is_ready());

  // Set up a local nigori with the local encryption keys and default encrypted
  // types.
  sync_pb::EntitySpecifics local_specifics;
  sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
  cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
  local_nigori->set_encrypt_everything(true);
  local_nigori->set_keybag_is_frozen(true);
  ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
          nigori_handle, local_specifics));
  // Apply the update locally so that UpdateFromEncryptedTypes knows what state
  // to use.
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    directory()->GetNigoriHandler()->ApplyNigoriUpdate(
        *local_nigori,
        &trans);
  }

  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
  ApplyControlDataUpdates(directory());
  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));

  EXPECT_FALSE(cryptographer->is_ready());
  EXPECT_TRUE(cryptographer->is_initialized());
  EXPECT_TRUE(cryptographer->has_pending_keys());
  EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey(
          entry_factory_->GetLocalSpecificsForItem(nigori_handle).
              nigori().encryption_keybag()));
  EXPECT_FALSE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().keybag_is_frozen());
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().encrypt_everything());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(ModelTypeSet::All()));
    EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI));
  }
}

// If the conflicting nigori has a subset of the local keys, the conflict
// resolution should preserve the full local keys. Initial sync ended should be
// set.
TEST_F(ApplyControlDataUpdatesTest,
       NigoriConflictOldKeys) {
  Cryptographer* cryptographer;
  ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
  KeyParams old_params = {"localhost", "dummy", "old"};
  KeyParams new_params = {"localhost", "dummy", "new"};
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    EXPECT_TRUE(encrypted_types.Equals(
            directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
  }

  // Set up the cryptographer with old keys
  cryptographer->AddKey(old_params);

  // Create server specifics with old keys and new encrypted types.
  sync_pb::EntitySpecifics server_specifics;
  sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
  cryptographer->GetKeys(server_nigori->mutable_encryption_keybag());
  server_nigori->set_encrypt_everything(true);
  int64 nigori_handle =
      entry_factory_->CreateUnappliedNewItem(kNigoriTag,
                                             server_specifics,
                                             true);

  // Add the new keys to the cryptogrpaher
  cryptographer->AddKey(new_params);
  EXPECT_TRUE(cryptographer->is_ready());

  // Set up a local nigori with the superset of keys.
  sync_pb::EntitySpecifics local_specifics;
  sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
  cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
  local_nigori->set_encrypt_everything(false);
  ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
          nigori_handle, local_specifics));
  // Apply the update locally so that UpdateFromEncryptedTypes knows what state
  // to use.
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    directory()->GetNigoriHandler()->ApplyNigoriUpdate(
        *local_nigori,
        &trans);
  }

  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
  ApplyControlDataUpdates(directory());
  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));

  EXPECT_TRUE(cryptographer->is_ready());
  EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
          entry_factory_->GetLocalSpecificsForItem(nigori_handle).
              nigori().encryption_keybag()));
  EXPECT_FALSE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().keybag_is_frozen());
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().encrypt_everything());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(ModelTypeSet::All()));
    EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI));
  }
}

// If both nigoris are migrated, but we also set a custom passphrase locally,
// the local nigori should be preserved.
TEST_F(ApplyControlDataUpdatesTest,
       NigoriConflictBothMigratedLocalCustom) {
  Cryptographer* cryptographer;
  ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
  KeyParams old_params = {"localhost", "dummy", "old"};
  KeyParams new_params = {"localhost", "dummy", "new"};
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    EXPECT_TRUE(encrypted_types.Equals(
            directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
  }

  // Set up the cryptographer with new keys
  Cryptographer other_cryptographer(cryptographer->encryptor());
  other_cryptographer.AddKey(old_params);

  // Create server specifics with a migrated keystore passphrase type.
  sync_pb::EntitySpecifics server_specifics;
  sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
  other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
  server_nigori->set_encrypt_everything(false);
  server_nigori->set_keybag_is_frozen(true);
  server_nigori->set_passphrase_type(
      sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
  server_nigori->mutable_keystore_decryptor_token();
  int64 nigori_handle =
      entry_factory_->CreateUnappliedNewItem(kNigoriTag,
                                             server_specifics,
                                             true);

  // Add the new keys to the cryptographer.
  cryptographer->AddKey(old_params);
  cryptographer->AddKey(new_params);
  EXPECT_TRUE(cryptographer->is_ready());

  // Set up a local nigori with a migrated custom passphrase type
  sync_pb::EntitySpecifics local_specifics;
  sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
  cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
  local_nigori->set_encrypt_everything(true);
  local_nigori->set_keybag_is_frozen(true);
  local_nigori->set_passphrase_type(
      sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
  ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
          nigori_handle, local_specifics));
  // Apply the update locally so that UpdateFromEncryptedTypes knows what state
  // to use.
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    directory()->GetNigoriHandler()->ApplyNigoriUpdate(
        *local_nigori,
        &trans);
  }

  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
  ApplyControlDataUpdates(directory());
  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));

  EXPECT_TRUE(cryptographer->is_ready());
  EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
          entry_factory_->GetLocalSpecificsForItem(nigori_handle).
              nigori().encryption_keybag()));
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().keybag_is_frozen());
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().encrypt_everything());
  EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE,
            entry_factory_->GetLocalSpecificsForItem(nigori_handle).
                nigori().passphrase_type());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(ModelTypeSet::All()));
    EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI));
  }
}

// If both nigoris are migrated, but a custom passphrase with a new key was
// set remotely, the remote nigori should be preserved.
TEST_F(ApplyControlDataUpdatesTest,
       NigoriConflictBothMigratedServerCustom) {
  Cryptographer* cryptographer;
  ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
  KeyParams old_params = {"localhost", "dummy", "old"};
  KeyParams new_params = {"localhost", "dummy", "new"};
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    EXPECT_TRUE(encrypted_types.Equals(
            directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
  }

  // Set up the cryptographer with both new keys and old keys.
  Cryptographer other_cryptographer(cryptographer->encryptor());
  other_cryptographer.AddKey(old_params);
  other_cryptographer.AddKey(new_params);

  // Create server specifics with a migrated custom passphrase type.
  sync_pb::EntitySpecifics server_specifics;
  sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
  other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
  server_nigori->set_encrypt_everything(true);
  server_nigori->set_keybag_is_frozen(true);
  server_nigori->set_passphrase_type(
      sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
  int64 nigori_handle =
      entry_factory_->CreateUnappliedNewItem(kNigoriTag,
                                             server_specifics,
                                             true);

  // Add the old keys to the cryptographer.
  cryptographer->AddKey(old_params);
  EXPECT_TRUE(cryptographer->is_ready());

  // Set up a local nigori with a migrated keystore passphrase type
  sync_pb::EntitySpecifics local_specifics;
  sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
  cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
  local_nigori->set_encrypt_everything(false);
  local_nigori->set_keybag_is_frozen(true);
  local_nigori->set_passphrase_type(
      sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
  server_nigori->mutable_keystore_decryptor_token();
  ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
          nigori_handle, local_specifics));
  // Apply the update locally so that UpdateFromEncryptedTypes knows what state
  // to use.
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    directory()->GetNigoriHandler()->ApplyNigoriUpdate(
        *local_nigori,
        &trans);
  }

  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
  ApplyControlDataUpdates(directory());
  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));

  EXPECT_TRUE(cryptographer->is_initialized());
  EXPECT_TRUE(cryptographer->has_pending_keys());
  EXPECT_TRUE(other_cryptographer.CanDecryptUsingDefaultKey(
          entry_factory_->GetLocalSpecificsForItem(nigori_handle).
              nigori().encryption_keybag()));
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().keybag_is_frozen());
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().encrypt_everything());
  EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE,
            entry_factory_->GetLocalSpecificsForItem(nigori_handle).
                nigori().passphrase_type());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(ModelTypeSet::All()));
    EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI));
  }
}

// If the local nigori is migrated but the server is not, preserve the local
// nigori.
TEST_F(ApplyControlDataUpdatesTest,
       NigoriConflictLocalMigrated) {
  Cryptographer* cryptographer;
  ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
  KeyParams old_params = {"localhost", "dummy", "old"};
  KeyParams new_params = {"localhost", "dummy", "new"};
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    EXPECT_TRUE(encrypted_types.Equals(
            directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
  }

  // Set up the cryptographer with both new keys and old keys.
  Cryptographer other_cryptographer(cryptographer->encryptor());
  other_cryptographer.AddKey(old_params);

  // Create server specifics with an unmigrated implicit passphrase type.
  sync_pb::EntitySpecifics server_specifics;
  sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
  other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
  server_nigori->set_encrypt_everything(true);
  server_nigori->set_keybag_is_frozen(false);
  int64 nigori_handle =
      entry_factory_->CreateUnappliedNewItem(kNigoriTag,
                                             server_specifics,
                                             true);

  // Add the old keys to the cryptographer.
  cryptographer->AddKey(old_params);
  cryptographer->AddKey(new_params);
  EXPECT_TRUE(cryptographer->is_ready());

  // Set up a local nigori with a migrated custom passphrase type
  sync_pb::EntitySpecifics local_specifics;
  sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
  cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
  local_nigori->set_encrypt_everything(true);
  local_nigori->set_keybag_is_frozen(true);
  local_nigori->set_passphrase_type(
      sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
  ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
          nigori_handle, local_specifics));
  // Apply the update locally so that UpdateFromEncryptedTypes knows what state
  // to use.
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    directory()->GetNigoriHandler()->ApplyNigoriUpdate(
        *local_nigori,
        &trans);
  }

  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
  ApplyControlDataUpdates(directory());
  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));

  EXPECT_TRUE(cryptographer->is_ready());
  EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey(
          entry_factory_->GetLocalSpecificsForItem(nigori_handle).
              nigori().encryption_keybag()));
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().keybag_is_frozen());
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().encrypt_everything());
  EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE,
            entry_factory_->GetLocalSpecificsForItem(nigori_handle).
                nigori().passphrase_type());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    EXPECT_TRUE(directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)
        .Equals(ModelTypeSet::All()));
    EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI));
  }
}

// If the server nigori is migrated but the local is not, preserve the server
// nigori.
TEST_F(ApplyControlDataUpdatesTest,
       NigoriConflictServerMigrated) {
  Cryptographer* cryptographer;
  ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
  KeyParams old_params = {"localhost", "dummy", "old"};
  KeyParams new_params = {"localhost", "dummy", "new"};
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    EXPECT_TRUE(encrypted_types.Equals(
            directory()->GetNigoriHandler()->GetEncryptedTypes(&trans)));
  }

  // Set up the cryptographer with both new keys and old keys.
  Cryptographer other_cryptographer(cryptographer->encryptor());
  other_cryptographer.AddKey(old_params);

  // Create server specifics with an migrated keystore passphrase type.
  sync_pb::EntitySpecifics server_specifics;
  sync_pb::NigoriSpecifics* server_nigori = server_specifics.mutable_nigori();
  other_cryptographer.GetKeys(server_nigori->mutable_encryption_keybag());
  server_nigori->set_encrypt_everything(false);
  server_nigori->set_keybag_is_frozen(true);
  server_nigori->set_passphrase_type(
      sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
  server_nigori->mutable_keystore_decryptor_token();
  int64 nigori_handle =
      entry_factory_->CreateUnappliedNewItem(kNigoriTag,
                                             server_specifics,
                                             true);

  // Add the old keys to the cryptographer.
  cryptographer->AddKey(old_params);
  cryptographer->AddKey(new_params);
  EXPECT_TRUE(cryptographer->is_ready());

  // Set up a local nigori with a migrated custom passphrase type
  sync_pb::EntitySpecifics local_specifics;
  sync_pb::NigoriSpecifics* local_nigori = local_specifics.mutable_nigori();
  cryptographer->GetKeys(local_nigori->mutable_encryption_keybag());
  local_nigori->set_encrypt_everything(false);
  local_nigori->set_keybag_is_frozen(false);
  ASSERT_TRUE(entry_factory_->SetLocalSpecificsForItem(
          nigori_handle, local_specifics));
  // Apply the update locally so that UpdateFromEncryptedTypes knows what state
  // to use.
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    cryptographer = directory()->GetCryptographer(&trans);
    directory()->GetNigoriHandler()->ApplyNigoriUpdate(
        *local_nigori,
        &trans);
  }

  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_TRUE(entry_factory_->GetIsUnappliedForItem(nigori_handle));
  ApplyControlDataUpdates(directory());
  EXPECT_TRUE(entry_factory_->GetIsUnsyncedForItem(nigori_handle));
  EXPECT_FALSE(entry_factory_->GetIsUnappliedForItem(nigori_handle));

  EXPECT_TRUE(cryptographer->is_ready());
  // Note: we didn't overwrite the encryption keybag with the local keys. The
  // sync encryption handler will do that when it detects that the new
  // keybag is out of date (and update the keystore bootstrap if necessary).
  EXPECT_FALSE(cryptographer->CanDecryptUsingDefaultKey(
          entry_factory_->GetLocalSpecificsForItem(nigori_handle).
              nigori().encryption_keybag()));
  EXPECT_TRUE(cryptographer->CanDecrypt(
          entry_factory_->GetLocalSpecificsForItem(nigori_handle).
              nigori().encryption_keybag()));
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().keybag_is_frozen());
  EXPECT_TRUE(entry_factory_->GetLocalSpecificsForItem(nigori_handle).
      nigori().has_keystore_decryptor_token());
  EXPECT_EQ(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE,
            entry_factory_->GetLocalSpecificsForItem(nigori_handle).
                nigori().passphrase_type());
  {
    syncable::ReadTransaction trans(FROM_HERE, directory());
    EXPECT_TRUE(directory()->initial_sync_ended_types().Has(NIGORI));
  }
}

}  // namespace syncer
