summaryrefslogtreecommitdiffstats
path: root/sync/engine/model_type_sync_worker_impl_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sync/engine/model_type_sync_worker_impl_unittest.cc')
-rw-r--r--sync/engine/model_type_sync_worker_impl_unittest.cc493
1 files changed, 8 insertions, 485 deletions
diff --git a/sync/engine/model_type_sync_worker_impl_unittest.cc b/sync/engine/model_type_sync_worker_impl_unittest.cc
index df2ed66..0c1fa13 100644
--- a/sync/engine/model_type_sync_worker_impl_unittest.cc
+++ b/sync/engine/model_type_sync_worker_impl_unittest.cc
@@ -4,7 +4,6 @@
#include "sync/engine/model_type_sync_worker_impl.h"
-#include "base/strings/stringprintf.h"
#include "sync/engine/commit_contribution.h"
#include "sync/engine/model_type_sync_proxy.h"
#include "sync/internal_api/public/base/model_type.h"
@@ -14,18 +13,13 @@
#include "sync/syncable/syncable_util.h"
#include "sync/test/engine/mock_model_type_sync_proxy.h"
#include "sync/test/engine/mock_nudge_handler.h"
-#include "sync/test/engine/simple_cryptographer_provider.h"
#include "sync/test/engine/single_type_mock_server.h"
-#include "sync/test/fake_encryptor.h"
#include "testing/gtest/include/gtest/gtest.h"
static const std::string kTypeParentId = "PrefsRootNodeID";
static const syncer::ModelType kModelType = syncer::PREFERENCES;
-// Special constant value taken from cryptographer.cc.
-const char kNigoriKeyName[] = "nigori-key";
-
namespace syncer {
// Tests the ModelTypeSyncWorkerImpl.
@@ -71,23 +65,8 @@ class ModelTypeSyncWorkerImplTest : public ::testing::Test {
// committing items right away.
void NormalInitialize();
- // Initialize with some saved pending updates from the model thread.
- void InitializeWithPendingUpdates(
- const UpdateResponseDataList& initial_pending_updates);
-
- // Initialize with a custom initial DataTypeState and pending updates.
- void InitializeWithState(const DataTypeState& state,
- const UpdateResponseDataList& pending_updates);
-
- // Introduce a new key that the local cryptographer can't decrypt.
- void NewForeignEncryptionKey();
-
- // Update the local cryptographer with all relevant keys.
- void UpdateLocalCryptographer();
-
- // Use the Nth nigori instance to encrypt incoming updates.
- // The default value, zero, indicates no encryption.
- void SetUpdateEncryptionFilter(int n);
+ // Initialize with a custom initial DataTypeState.
+ void InitializeWithState(const DataTypeState& state);
// Modifications on the model thread that get sent to the worker under test.
void CommitRequest(const std::string& tag, const std::string& value);
@@ -100,13 +79,6 @@ class ModelTypeSyncWorkerImplTest : public ::testing::Test {
const std::string& value);
void TriggerTombstoneFromServer(int64 version_offset, const std::string& tag);
- // Delivers specified protos as updates.
- //
- // Does not update mock server state. Should be used as a last resort when
- // writing test cases that require entities that don't fit the normal sync
- // protocol. Try to use the other, higher level methods if possible.
- void DeliverRawUpdates(const SyncEntityList& update_list);
-
// By default, this harness behaves as if all tasks posted to the model
// thread are executed immediately. However, this is not necessarily true.
// The model's TaskRunner has a queue, and the tasks we post to it could
@@ -138,7 +110,6 @@ class ModelTypeSyncWorkerImplTest : public ::testing::Test {
// be updated until the response is actually processed by the model thread.
size_t GetNumModelThreadUpdateResponses() const;
UpdateResponseDataList GetNthModelThreadUpdateResponse(size_t n) const;
- UpdateResponseDataList GetNthModelThreadPendingUpdates(size_t n) const;
DataTypeState GetNthModelThreadUpdateState(size_t n) const;
// Reads the latest update response datas on the model thread.
@@ -173,39 +144,7 @@ class ModelTypeSyncWorkerImplTest : public ::testing::Test {
static sync_pb::EntitySpecifics GenerateSpecifics(const std::string& tag,
const std::string& value);
- // Returns a set of KeyParams for the cryptographer. Each input 'n' value
- // results in a different set of parameters.
- static KeyParams GetNthKeyParams(int n);
-
- // Returns the name for the given Nigori.
- //
- // Uses some 'white-box' knowledge to mimic the names that a real sync client
- // would generate. It's probably not necessary to do so, but it can't hurt.
- static std::string GetNigoriName(const Nigori& nigori);
-
- // Modifies the input/output parameter |specifics| by encrypting it with
- // a Nigori intialized with the specified KeyParams.
- static void EncryptUpdate(const KeyParams& params,
- sync_pb::EntitySpecifics* specifics);
-
private:
- // An encryptor for our cryptographer.
- FakeEncryptor fake_encryptor_;
-
- // The cryptographer itself.
- Cryptographer cryptographer_;
-
- // A CryptographerProvider for the ModelTypeSyncWorkerImpl.
- SimpleCryptographerProvider cryptographer_provider_;
-
- // The number of the most recent foreign encryption key known to our
- // cryptographer. Note that not all of these will be decryptable.
- int foreign_encryption_key_index_;
-
- // The number of the encryption key used to encrypt incoming updates. A zero
- // value implies no encryption.
- int update_encryption_filter_index_;
-
// The ModelTypeSyncWorkerImpl being tested.
scoped_ptr<ModelTypeSyncWorkerImpl> worker_;
@@ -224,12 +163,7 @@ class ModelTypeSyncWorkerImplTest : public ::testing::Test {
};
ModelTypeSyncWorkerImplTest::ModelTypeSyncWorkerImplTest()
- : cryptographer_(&fake_encryptor_),
- cryptographer_provider_(&cryptographer_),
- foreign_encryption_key_index_(0),
- update_encryption_filter_index_(0),
- mock_type_sync_proxy_(NULL),
- mock_server_(kModelType) {
+ : mock_type_sync_proxy_(NULL), mock_server_(kModelType) {
}
ModelTypeSyncWorkerImplTest::~ModelTypeSyncWorkerImplTest() {
@@ -241,15 +175,10 @@ void ModelTypeSyncWorkerImplTest::FirstInitialize() {
GetSpecificsFieldNumberFromModelType(kModelType));
initial_state.next_client_id = 0;
- InitializeWithState(initial_state, UpdateResponseDataList());
+ InitializeWithState(initial_state);
}
void ModelTypeSyncWorkerImplTest::NormalInitialize() {
- InitializeWithPendingUpdates(UpdateResponseDataList());
-}
-
-void ModelTypeSyncWorkerImplTest::InitializeWithPendingUpdates(
- const UpdateResponseDataList& initial_pending_updates) {
DataTypeState initial_state;
initial_state.progress_marker.set_data_type_id(
GetSpecificsFieldNumberFromModelType(kModelType));
@@ -259,79 +188,21 @@ void ModelTypeSyncWorkerImplTest::InitializeWithPendingUpdates(
initial_state.type_root_id = kTypeParentId;
initial_state.initial_sync_done = true;
- InitializeWithState(initial_state, initial_pending_updates);
+ InitializeWithState(initial_state);
mock_nudge_handler_.ClearCounters();
}
void ModelTypeSyncWorkerImplTest::InitializeWithState(
- const DataTypeState& state,
- const UpdateResponseDataList& initial_pending_updates) {
+ const DataTypeState& state) {
DCHECK(!worker_);
// We don't get to own this object. The |worker_| keeps a scoped_ptr to it.
mock_type_sync_proxy_ = new MockModelTypeSyncProxy();
scoped_ptr<ModelTypeSyncProxy> proxy(mock_type_sync_proxy_);
- worker_.reset(new ModelTypeSyncWorkerImpl(kModelType,
- state,
- initial_pending_updates,
- &cryptographer_provider_,
- &mock_nudge_handler_,
- proxy.Pass()));
-}
-
-void ModelTypeSyncWorkerImplTest::NewForeignEncryptionKey() {
- foreign_encryption_key_index_++;
-
- sync_pb::NigoriKeyBag bag;
-
- for (int i = 0; i <= foreign_encryption_key_index_; ++i) {
- Nigori nigori;
- KeyParams params = GetNthKeyParams(i);
- nigori.InitByDerivation(params.hostname, params.username, params.password);
-
- sync_pb::NigoriKey* key = bag.add_key();
-
- key->set_name(GetNigoriName(nigori));
- nigori.ExportKeys(key->mutable_user_key(),
- key->mutable_encryption_key(),
- key->mutable_mac_key());
- }
-
- // Re-create the last nigori from that loop.
- Nigori last_nigori;
- KeyParams params = GetNthKeyParams(foreign_encryption_key_index_);
- last_nigori.InitByDerivation(
- params.hostname, params.username, params.password);
-
- // Serialize and encrypt the bag with the last nigori.
- std::string serialized_bag;
- bag.SerializeToString(&serialized_bag);
-
- sync_pb::EncryptedData encrypted;
- encrypted.set_key_name(GetNigoriName(last_nigori));
- last_nigori.Encrypt(serialized_bag, encrypted.mutable_blob());
-
- // Update the cryptographer with new pending keys.
- cryptographer_.SetPendingKeys(encrypted);
-
- // Update the worker with the latest encryption key name.
- if (worker_)
- worker_->SetEncryptionKeyName(encrypted.key_name());
-}
-
-void ModelTypeSyncWorkerImplTest::UpdateLocalCryptographer() {
- KeyParams params = GetNthKeyParams(foreign_encryption_key_index_);
- bool success = cryptographer_.DecryptPendingKeys(params);
- DCHECK(success);
-
- if (worker_)
- worker_->OnCryptographerStateChanged();
-}
-
-void ModelTypeSyncWorkerImplTest::SetUpdateEncryptionFilter(int n) {
- update_encryption_filter_index_ = n;
+ worker_.reset(new ModelTypeSyncWorkerImpl(
+ kModelType, state, &mock_nudge_handler_, proxy.Pass()));
}
void ModelTypeSyncWorkerImplTest::CommitRequest(const std::string& name,
@@ -372,12 +243,6 @@ void ModelTypeSyncWorkerImplTest::TriggerUpdateFromServer(
const std::string& value) {
sync_pb::SyncEntity entity = mock_server_.UpdateFromServer(
version_offset, GenerateTagHash(tag), GenerateSpecifics(tag, value));
-
- if (update_encryption_filter_index_ != 0) {
- EncryptUpdate(GetNthKeyParams(update_encryption_filter_index_),
- entity.mutable_specifics());
- }
-
SyncEntityList entity_list;
entity_list.push_back(&entity);
@@ -390,27 +255,11 @@ void ModelTypeSyncWorkerImplTest::TriggerUpdateFromServer(
worker_->ApplyUpdates(&dummy_status);
}
-void ModelTypeSyncWorkerImplTest::DeliverRawUpdates(
- const SyncEntityList& list) {
- sessions::StatusController dummy_status;
- worker_->ProcessGetUpdatesResponse(mock_server_.GetProgress(),
- mock_server_.GetContext(),
- list,
- &dummy_status);
- worker_->ApplyUpdates(&dummy_status);
-}
-
void ModelTypeSyncWorkerImplTest::TriggerTombstoneFromServer(
int64 version_offset,
const std::string& tag) {
sync_pb::SyncEntity entity =
mock_server_.TombstoneFromServer(version_offset, GenerateTagHash(tag));
-
- if (update_encryption_filter_index_ != 0) {
- EncryptUpdate(GetNthKeyParams(update_encryption_filter_index_),
- entity.mutable_specifics());
- }
-
SyncEntityList entity_list;
entity_list.push_back(&entity);
@@ -497,12 +346,6 @@ ModelTypeSyncWorkerImplTest::GetNthModelThreadUpdateResponse(size_t n) const {
return mock_type_sync_proxy_->GetNthUpdateResponse(n);
}
-UpdateResponseDataList
-ModelTypeSyncWorkerImplTest::GetNthModelThreadPendingUpdates(size_t n) const {
- DCHECK_LT(n, GetNumModelThreadUpdateResponses());
- return mock_type_sync_proxy_->GetNthPendingUpdates(n);
-}
-
DataTypeState ModelTypeSyncWorkerImplTest::GetNthModelThreadUpdateState(
size_t n) const {
DCHECK_LT(n, GetNumModelThreadUpdateResponses());
@@ -558,7 +401,6 @@ int ModelTypeSyncWorkerImplTest::GetNumInitialDownloadNudges() const {
return mock_nudge_handler_.GetNumInitialDownloadNudges();
}
-// static.
std::string ModelTypeSyncWorkerImplTest::GenerateTagHash(
const std::string& tag) {
const std::string& client_tag_hash =
@@ -566,7 +408,6 @@ std::string ModelTypeSyncWorkerImplTest::GenerateTagHash(
return client_tag_hash;
}
-// static.
sync_pb::EntitySpecifics ModelTypeSyncWorkerImplTest::GenerateSpecifics(
const std::string& tag,
const std::string& value) {
@@ -576,46 +417,6 @@ sync_pb::EntitySpecifics ModelTypeSyncWorkerImplTest::GenerateSpecifics(
return specifics;
}
-// static.
-std::string ModelTypeSyncWorkerImplTest::GetNigoriName(const Nigori& nigori) {
- std::string name;
- if (!nigori.Permute(Nigori::Password, kNigoriKeyName, &name)) {
- NOTREACHED();
- return std::string();
- }
-
- return name;
-}
-
-// static.
-KeyParams ModelTypeSyncWorkerImplTest::GetNthKeyParams(int n) {
- KeyParams params;
- params.hostname = std::string("localhost");
- params.username = std::string("userX");
- params.password = base::StringPrintf("pw%02d", n);
- return params;
-}
-
-// static.
-void ModelTypeSyncWorkerImplTest::EncryptUpdate(
- const KeyParams& params,
- sync_pb::EntitySpecifics* specifics) {
- Nigori nigori;
- nigori.InitByDerivation(params.hostname, params.username, params.password);
-
- sync_pb::EntitySpecifics original_specifics = *specifics;
- std::string plaintext;
- original_specifics.SerializeToString(&plaintext);
-
- std::string encrypted;
- nigori.Encrypt(plaintext, &encrypted);
-
- specifics->Clear();
- AddDefaultFieldValue(kModelType, specifics);
- specifics->mutable_encrypted()->set_key_name(GetNigoriName(nigori));
- specifics->mutable_encrypted()->set_blob(encrypted);
-}
-
// Requests a commit and verifies the messages sent to the client and server as
// a result.
//
@@ -799,7 +600,6 @@ TEST_F(ModelTypeSyncWorkerImplTest, TwoNewItemsCommittedSeparately) {
EXPECT_EQ(2U, GetNumModelThreadCommitResponses());
}
-// Test normal update receipt code path.
TEST_F(ModelTypeSyncWorkerImplTest, ReceiveUpdates) {
NormalInitialize();
@@ -825,281 +625,4 @@ TEST_F(ModelTypeSyncWorkerImplTest, ReceiveUpdates) {
EXPECT_EQ("value1", update.specifics.preference().value());
}
-// Test commit of encrypted updates.
-TEST_F(ModelTypeSyncWorkerImplTest, EncryptedCommit) {
- NormalInitialize();
-
- NewForeignEncryptionKey();
- UpdateLocalCryptographer();
-
- // Normal commit request stuff.
- CommitRequest("tag1", "value1");
- DoSuccessfulCommit();
- ASSERT_EQ(1U, GetNumCommitMessagesOnServer());
- EXPECT_EQ(1, GetNthCommitMessageOnServer(0).commit().entries_size());
- ASSERT_TRUE(HasCommitEntityOnServer("tag1"));
- const sync_pb::SyncEntity& tag1_entity =
- GetLatestCommitEntityOnServer("tag1");
-
- EXPECT_TRUE(tag1_entity.specifics().has_encrypted());
-
- // The title should be overwritten.
- EXPECT_EQ(tag1_entity.name(), "encrypted");
-
- // The type should be set, but there should be no non-encrypted contents.
- EXPECT_TRUE(tag1_entity.specifics().has_preference());
- EXPECT_FALSE(tag1_entity.specifics().preference().has_name());
- EXPECT_FALSE(tag1_entity.specifics().preference().has_value());
-}
-
-// Test items are not committed when encryption is required but unavailable.
-TEST_F(ModelTypeSyncWorkerImplTest, EncryptionBlocksCommits) {
- NormalInitialize();
-
- CommitRequest("tag1", "value1");
- EXPECT_TRUE(WillCommit());
-
- // We know encryption is in use on this account, but don't have the necessary
- // encryption keys. The worker should refuse to commit.
- NewForeignEncryptionKey();
- EXPECT_FALSE(WillCommit());
-
- // Once the cryptographer is returned to a normal state, we should be able to
- // commit again.
- EXPECT_EQ(1, GetNumCommitNudges());
- UpdateLocalCryptographer();
- EXPECT_EQ(2, GetNumCommitNudges());
- EXPECT_TRUE(WillCommit());
-
- // Verify the committed entity was properly encrypted.
- DoSuccessfulCommit();
- ASSERT_EQ(1U, GetNumCommitMessagesOnServer());
- EXPECT_EQ(1, GetNthCommitMessageOnServer(0).commit().entries_size());
- ASSERT_TRUE(HasCommitEntityOnServer("tag1"));
- const sync_pb::SyncEntity& tag1_entity =
- GetLatestCommitEntityOnServer("tag1");
- EXPECT_TRUE(tag1_entity.specifics().has_encrypted());
- EXPECT_EQ(tag1_entity.name(), "encrypted");
- EXPECT_TRUE(tag1_entity.specifics().has_preference());
- EXPECT_FALSE(tag1_entity.specifics().preference().has_name());
- EXPECT_FALSE(tag1_entity.specifics().preference().has_value());
-}
-
-// Test the receipt of decryptable entities.
-TEST_F(ModelTypeSyncWorkerImplTest, ReceiveDecryptableEntities) {
- NormalInitialize();
-
- // Create a new Nigori and allow the cryptographer to decrypt it.
- NewForeignEncryptionKey();
- UpdateLocalCryptographer();
-
- // First, receive an unencrypted entry.
- TriggerUpdateFromServer(10, "tag1", "value1");
-
- // Test some basic properties regarding the update.
- ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1"));
- UpdateResponseData update1 = GetUpdateResponseOnModelThread("tag1");
- EXPECT_EQ("tag1", update1.specifics.preference().name());
- EXPECT_EQ("value1", update1.specifics.preference().value());
- EXPECT_TRUE(update1.encryption_key_name.empty());
-
- // Set received updates to be encrypted using the new nigori.
- SetUpdateEncryptionFilter(1);
-
- // This next update will be encrypted.
- TriggerUpdateFromServer(10, "tag2", "value2");
-
- // Test its basic features and the value of encryption_key_name.
- ASSERT_TRUE(HasUpdateResponseOnModelThread("tag2"));
- UpdateResponseData update2 = GetUpdateResponseOnModelThread("tag2");
- EXPECT_EQ("tag2", update2.specifics.preference().name());
- EXPECT_EQ("value2", update2.specifics.preference().value());
- EXPECT_FALSE(update2.encryption_key_name.empty());
-}
-
-// Receive updates that are initially undecryptable, then ensure they get
-// delivered to the model thread when decryption becomes possible.
-TEST_F(ModelTypeSyncWorkerImplTest, ReceiveUndecryptableEntries) {
- NormalInitialize();
-
- // Set a new encryption key. The model thread will be notified of the new
- // encryption key through a faked update response.
- NewForeignEncryptionKey();
- EXPECT_EQ(1U, GetNumModelThreadUpdateResponses());
-
- // Send an update using that new key.
- SetUpdateEncryptionFilter(1);
- TriggerUpdateFromServer(10, "tag1", "value1");
-
- // At this point, the cryptographer does not have access to the key, so the
- // updates will be undecryptable. They'll be transfered to the model thread
- // for safe-keeping as pending updates.
- ASSERT_EQ(2U, GetNumModelThreadUpdateResponses());
- UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(1);
- EXPECT_EQ(0U, updates_list.size());
- UpdateResponseDataList pending_updates = GetNthModelThreadPendingUpdates(1);
- EXPECT_EQ(1U, pending_updates.size());
-
- // The update will be delivered as soon as decryption becomes possible.
- UpdateLocalCryptographer();
- ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1"));
- UpdateResponseData update = GetUpdateResponseOnModelThread("tag1");
- EXPECT_EQ("tag1", update.specifics.preference().name());
- EXPECT_EQ("value1", update.specifics.preference().value());
- EXPECT_FALSE(update.encryption_key_name.empty());
-}
-
-// Ensure that even encrypted updates can cause conflicts.
-TEST_F(ModelTypeSyncWorkerImplTest, EncryptedUpdateOverridesPendingCommit) {
- NormalInitialize();
-
- // Prepeare to commit an item.
- CommitRequest("tag1", "value1");
- EXPECT_TRUE(WillCommit());
-
- // Receive an encrypted update for that item.
- SetUpdateEncryptionFilter(1);
- TriggerUpdateFromServer(10, "tag1", "value1");
-
- // The pending commit state should be cleared.
- EXPECT_FALSE(WillCommit());
-
- // The encrypted update will be delivered to the model thread.
- ASSERT_EQ(1U, GetNumModelThreadUpdateResponses());
- UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(0);
- EXPECT_EQ(0U, updates_list.size());
- UpdateResponseDataList pending_updates = GetNthModelThreadPendingUpdates(0);
- EXPECT_EQ(1U, pending_updates.size());
-}
-
-// Test decryption of pending updates saved across a restart.
-TEST_F(ModelTypeSyncWorkerImplTest, RestorePendingEntries) {
- // Create a fake pending update.
- UpdateResponseData update;
-
- update.client_tag_hash = GenerateTagHash("tag1");
- update.id = "SomeID";
- update.response_version = 100;
- update.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(10);
- update.mtime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(11);
- update.non_unique_name = "encrypted";
- update.deleted = false;
-
- update.specifics = GenerateSpecifics("tag1", "value1");
- EncryptUpdate(GetNthKeyParams(1), &(update.specifics));
-
- // Inject the update during ModelTypeSyncWorker initialization.
- UpdateResponseDataList saved_pending_updates;
- saved_pending_updates.push_back(update);
- InitializeWithPendingUpdates(saved_pending_updates);
-
- // Update will be undecryptable at first.
- EXPECT_EQ(0U, GetNumModelThreadUpdateResponses());
- ASSERT_FALSE(HasUpdateResponseOnModelThread("tag1"));
-
- // Update the cryptographer so it can decrypt that update.
- NewForeignEncryptionKey();
- UpdateLocalCryptographer();
-
- // Verify the item gets decrypted and sent back to the model thread.
- ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1"));
-}
-
-// Test decryption of pending updates saved across a restart. This test
-// differs from the previous one in that the restored updates can be decrypted
-// immediately after the ModelTypeSyncWorker is constructed.
-TEST_F(ModelTypeSyncWorkerImplTest, RestoreApplicableEntries) {
- // Update the cryptographer so it can decrypt that update.
- NewForeignEncryptionKey();
- UpdateLocalCryptographer();
-
- // Create a fake pending update.
- UpdateResponseData update;
- update.client_tag_hash = GenerateTagHash("tag1");
- update.id = "SomeID";
- update.response_version = 100;
- update.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(10);
- update.mtime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(11);
- update.non_unique_name = "encrypted";
- update.deleted = false;
-
- update.specifics = GenerateSpecifics("tag1", "value1");
- EncryptUpdate(GetNthKeyParams(1), &(update.specifics));
-
- // Inject the update during ModelTypeSyncWorker initialization.
- UpdateResponseDataList saved_pending_updates;
- saved_pending_updates.push_back(update);
- InitializeWithPendingUpdates(saved_pending_updates);
-
- // Verify the item gets decrypted and sent back to the model thread.
- ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1"));
-}
-
-// Test that undecryptable updates provide sufficient reason to not commit.
-//
-// This should be rare in practice. Usually the cryptographer will be in an
-// unusable state when we receive undecryptable updates, and that alone will be
-// enough to prevent all commits.
-TEST_F(ModelTypeSyncWorkerImplTest, CommitBlockedByPending) {
- NormalInitialize();
-
- // Prepeare to commit an item.
- CommitRequest("tag1", "value1");
- EXPECT_TRUE(WillCommit());
-
- // Receive an encrypted update for that item.
- SetUpdateEncryptionFilter(1);
- TriggerUpdateFromServer(10, "tag1", "value1");
-
- // The pending commit state should be cleared.
- EXPECT_FALSE(WillCommit());
-
- // The pending update will be delivered to the model thread.
- HasUpdateResponseOnModelThread("tag1");
-
- // Pretend the update arrived too late to prevent another commit request.
- CommitRequest("tag1", "value2");
-
- EXPECT_FALSE(WillCommit());
-}
-
-// Verify that corrupted encrypted updates don't cause crashes.
-TEST_F(ModelTypeSyncWorkerImplTest, ReceiveCorruptEncryption) {
- // Initialize the worker with basic encryption state.
- NormalInitialize();
- NewForeignEncryptionKey();
- UpdateLocalCryptographer();
-
- // Manually create an update.
- sync_pb::SyncEntity entity;
- entity.set_client_defined_unique_tag(GenerateTagHash("tag1"));
- entity.set_id_string("SomeID");
- entity.set_version(1);
- entity.set_ctime(1000);
- entity.set_mtime(1001);
- entity.set_name("encrypted");
- entity.set_deleted(false);
-
- // Encrypt it.
- entity.mutable_specifics()->CopyFrom(GenerateSpecifics("tag1", "value1"));
- EncryptUpdate(GetNthKeyParams(1), entity.mutable_specifics());
-
- // Replace a few bytes to corrupt it.
- entity.mutable_specifics()->mutable_encrypted()->mutable_blob()->replace(
- 0, 4, "xyz!");
-
- SyncEntityList entity_list;
- entity_list.push_back(&entity);
-
- // If a corrupt update could trigger a crash, this is where it would happen.
- DeliverRawUpdates(entity_list);
-
- EXPECT_FALSE(HasUpdateResponseOnModelThread("tag1"));
-
- // Deliver a non-corrupt update to see if the everything still works.
- SetUpdateEncryptionFilter(1);
- TriggerUpdateFromServer(10, "tag1", "value1");
- EXPECT_TRUE(HasUpdateResponseOnModelThread("tag1"));
-}
-
} // namespace syncer