| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sync/engine/model_type_sync_worker_impl.h" | 5 #include "sync/engine/commit_queue_impl.h" |
| 6 | 6 |
| 7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
| 8 #include "sync/engine/commit_contribution.h" | 8 #include "sync/engine/commit_contribution.h" |
| 9 #include "sync/engine/model_type_sync_proxy.h" | 9 #include "sync/engine/model_type_processor.h" |
| 10 #include "sync/internal_api/public/base/model_type.h" | 10 #include "sync/internal_api/public/base/model_type.h" |
| 11 #include "sync/internal_api/public/non_blocking_sync_common.h" | 11 #include "sync/internal_api/public/non_blocking_sync_common.h" |
| 12 #include "sync/protocol/sync.pb.h" | 12 #include "sync/protocol/sync.pb.h" |
| 13 #include "sync/sessions/status_controller.h" | 13 #include "sync/sessions/status_controller.h" |
| 14 #include "sync/syncable/syncable_util.h" | 14 #include "sync/syncable/syncable_util.h" |
| 15 #include "sync/test/engine/mock_model_type_sync_proxy.h" | 15 #include "sync/test/engine/mock_model_type_processor.h" |
| 16 #include "sync/test/engine/mock_nudge_handler.h" | 16 #include "sync/test/engine/mock_nudge_handler.h" |
| 17 #include "sync/test/engine/single_type_mock_server.h" | 17 #include "sync/test/engine/single_type_mock_server.h" |
| 18 #include "sync/test/fake_encryptor.h" | 18 #include "sync/test/fake_encryptor.h" |
| 19 | 19 |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 21 | 21 |
| 22 static const syncer::ModelType kModelType = syncer::PREFERENCES; | 22 static const syncer::ModelType kModelType = syncer::PREFERENCES; |
| 23 | 23 |
| 24 // Special constant value taken from cryptographer.cc. | 24 // Special constant value taken from cryptographer.cc. |
| 25 const char kNigoriKeyName[] = "nigori-key"; | 25 const char kNigoriKeyName[] = "nigori-key"; |
| 26 | 26 |
| 27 namespace syncer_v2 { | 27 namespace syncer_v2 { |
| 28 | 28 |
| 29 using syncer::Cryptographer; | 29 using syncer::Cryptographer; |
| 30 using syncer::CommitContribution; | 30 using syncer::CommitContribution; |
| 31 using syncer::KeyParams; | 31 using syncer::KeyParams; |
| 32 using syncer::Nigori; | 32 using syncer::Nigori; |
| 33 using syncer::sessions::StatusController; | 33 using syncer::sessions::StatusController; |
| 34 | 34 |
| 35 // Tests the ModelTypeSyncWorkerImpl. | 35 // Tests the CommitQueueImpl. |
| 36 // | 36 // |
| 37 // This class passes messages between the model thread and sync server. | 37 // This class passes messages between the model thread and sync server. |
| 38 // As such, its code is subject to lots of different race conditions. This | 38 // As such, its code is subject to lots of different race conditions. This |
| 39 // test harness lets us exhaustively test all possible races. We try to | 39 // test harness lets us exhaustively test all possible races. We try to |
| 40 // focus on just a few interesting cases. | 40 // focus on just a few interesting cases. |
| 41 // | 41 // |
| 42 // Inputs: | 42 // Inputs: |
| 43 // - Initial data type state from the model thread. | 43 // - Initial data type state from the model thread. |
| 44 // - Commit requests from the model thread. | 44 // - Commit requests from the model thread. |
| 45 // - Update responses from the server. | 45 // - Update responses from the server. |
| 46 // - Commit responses from the server. | 46 // - Commit responses from the server. |
| 47 // - The cryptographer, if encryption is enabled. | 47 // - The cryptographer, if encryption is enabled. |
| 48 // | 48 // |
| 49 // Outputs: | 49 // Outputs: |
| 50 // - Commit requests to the server. | 50 // - Commit requests to the server. |
| 51 // - Commit responses to the model thread. | 51 // - Commit responses to the model thread. |
| 52 // - Update responses to the model thread. | 52 // - Update responses to the model thread. |
| 53 // - Nudges to the sync scheduler. | 53 // - Nudges to the sync scheduler. |
| 54 // | 54 // |
| 55 // We use the MockModelTypeSyncProxy to stub out all communication | 55 // We use the MockModelTypeProcessor to stub out all communication |
| 56 // with the model thread. That interface is synchronous, which makes it | 56 // with the model thread. That interface is synchronous, which makes it |
| 57 // much easier to test races. | 57 // much easier to test races. |
| 58 // | 58 // |
| 59 // The interface with the server is built around "pulling" data from this | 59 // The interface with the server is built around "pulling" data from this |
| 60 // class, so we don't have to mock out any of it. We wrap it with some | 60 // class, so we don't have to mock out any of it. We wrap it with some |
| 61 // convenience functions to we can emulate server behavior. | 61 // convenience functions to we can emulate server behavior. |
| 62 class ModelTypeSyncWorkerImplTest : public ::testing::Test { | 62 class CommitQueueImplTest : public ::testing::Test { |
| 63 public: | 63 public: |
| 64 ModelTypeSyncWorkerImplTest(); | 64 CommitQueueImplTest(); |
| 65 ~ModelTypeSyncWorkerImplTest() override; | 65 ~CommitQueueImplTest() override; |
| 66 | 66 |
| 67 // One of these Initialize functions should be called at the beginning of | 67 // One of these Initialize functions should be called at the beginning of |
| 68 // each test. | 68 // each test. |
| 69 | 69 |
| 70 // Initializes with no data type state. We will be unable to perform any | 70 // Initializes with no data type state. We will be unable to perform any |
| 71 // significant server action until we receive an update response that | 71 // significant server action until we receive an update response that |
| 72 // contains the type root node for this type. | 72 // contains the type root node for this type. |
| 73 void FirstInitialize(); | 73 void FirstInitialize(); |
| 74 | 74 |
| 75 // Initializes with some existing data type state. Allows us to start | 75 // Initializes with some existing data type state. Allows us to start |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 CommitResponseData GetCommitResponseOnModelThread( | 167 CommitResponseData GetCommitResponseOnModelThread( |
| 168 const std::string& tag) const; | 168 const std::string& tag) const; |
| 169 | 169 |
| 170 // Returns the number of commit nudges sent to the mock nudge handler. | 170 // Returns the number of commit nudges sent to the mock nudge handler. |
| 171 int GetNumCommitNudges() const; | 171 int GetNumCommitNudges() const; |
| 172 | 172 |
| 173 // Returns the number of initial sync nudges sent to the mock nudge handler. | 173 // Returns the number of initial sync nudges sent to the mock nudge handler. |
| 174 int GetNumInitialDownloadNudges() const; | 174 int GetNumInitialDownloadNudges() const; |
| 175 | 175 |
| 176 // Returns the name of the encryption key in the cryptographer last passed to | 176 // Returns the name of the encryption key in the cryptographer last passed to |
| 177 // the ModelTypeSyncWorker. Returns an empty string if no crypgorapher is | 177 // the CommitQueue. Returns an empty string if no crypgorapher is |
| 178 // in use. See also: UpdateLocalCryptographer(). | 178 // in use. See also: UpdateLocalCryptographer(). |
| 179 std::string GetLocalCryptographerKeyName() const; | 179 std::string GetLocalCryptographerKeyName() const; |
| 180 | 180 |
| 181 // Helpers for building various messages and structures. | 181 // Helpers for building various messages and structures. |
| 182 static std::string GenerateTagHash(const std::string& tag); | 182 static std::string GenerateTagHash(const std::string& tag); |
| 183 static sync_pb::EntitySpecifics GenerateSpecifics(const std::string& tag, | 183 static sync_pb::EntitySpecifics GenerateSpecifics(const std::string& tag, |
| 184 const std::string& value); | 184 const std::string& value); |
| 185 | 185 |
| 186 // Returns a set of KeyParams for the cryptographer. Each input 'n' value | 186 // Returns a set of KeyParams for the cryptographer. Each input 'n' value |
| 187 // results in a different set of parameters. | 187 // results in a different set of parameters. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 206 scoped_ptr<Cryptographer> cryptographer_; | 206 scoped_ptr<Cryptographer> cryptographer_; |
| 207 | 207 |
| 208 // The number of the most recent foreign encryption key known to our | 208 // The number of the most recent foreign encryption key known to our |
| 209 // cryptographer. Note that not all of these will be decryptable. | 209 // cryptographer. Note that not all of these will be decryptable. |
| 210 int foreign_encryption_key_index_; | 210 int foreign_encryption_key_index_; |
| 211 | 211 |
| 212 // The number of the encryption key used to encrypt incoming updates. A zero | 212 // The number of the encryption key used to encrypt incoming updates. A zero |
| 213 // value implies no encryption. | 213 // value implies no encryption. |
| 214 int update_encryption_filter_index_; | 214 int update_encryption_filter_index_; |
| 215 | 215 |
| 216 // The ModelTypeSyncWorkerImpl being tested. | 216 // The CommitQueueImpl being tested. |
| 217 scoped_ptr<ModelTypeSyncWorkerImpl> worker_; | 217 scoped_ptr<CommitQueueImpl> worker_; |
| 218 | 218 |
| 219 // Non-owned, possibly NULL pointer. This object belongs to the | 219 // Non-owned, possibly NULL pointer. This object belongs to the |
| 220 // ModelTypeSyncWorkerImpl under test. | 220 // CommitQueueImpl under test. |
| 221 MockModelTypeSyncProxy* mock_type_sync_proxy_; | 221 MockModelTypeProcessor* mock_type_sync_proxy_; |
| 222 | 222 |
| 223 // A mock that emulates enough of the sync server that it can be used | 223 // A mock that emulates enough of the sync server that it can be used |
| 224 // a single UpdateHandler and CommitContributor pair. In this test | 224 // a single UpdateHandler and CommitContributor pair. In this test |
| 225 // harness, the |worker_| is both of them. | 225 // harness, the |worker_| is both of them. |
| 226 syncer::SingleTypeMockServer mock_server_; | 226 syncer::SingleTypeMockServer mock_server_; |
| 227 | 227 |
| 228 // A mock to track the number of times the ModelTypeSyncWorker requests to | 228 // A mock to track the number of times the CommitQueue requests to |
| 229 // sync. | 229 // sync. |
| 230 syncer::MockNudgeHandler mock_nudge_handler_; | 230 syncer::MockNudgeHandler mock_nudge_handler_; |
| 231 }; | 231 }; |
| 232 | 232 |
| 233 ModelTypeSyncWorkerImplTest::ModelTypeSyncWorkerImplTest() | 233 CommitQueueImplTest::CommitQueueImplTest() |
| 234 : foreign_encryption_key_index_(0), | 234 : foreign_encryption_key_index_(0), |
| 235 update_encryption_filter_index_(0), | 235 update_encryption_filter_index_(0), |
| 236 mock_type_sync_proxy_(NULL), | 236 mock_type_sync_proxy_(NULL), |
| 237 mock_server_(kModelType) { | 237 mock_server_(kModelType) { |
| 238 } | 238 } |
| 239 | 239 |
| 240 ModelTypeSyncWorkerImplTest::~ModelTypeSyncWorkerImplTest() { | 240 CommitQueueImplTest::~CommitQueueImplTest() { |
| 241 } | 241 } |
| 242 | 242 |
| 243 void ModelTypeSyncWorkerImplTest::FirstInitialize() { | 243 void CommitQueueImplTest::FirstInitialize() { |
| 244 DataTypeState initial_state; | 244 DataTypeState initial_state; |
| 245 initial_state.progress_marker.set_data_type_id( | 245 initial_state.progress_marker.set_data_type_id( |
| 246 GetSpecificsFieldNumberFromModelType(kModelType)); | 246 GetSpecificsFieldNumberFromModelType(kModelType)); |
| 247 | 247 |
| 248 InitializeWithState(initial_state, UpdateResponseDataList()); | 248 InitializeWithState(initial_state, UpdateResponseDataList()); |
| 249 } | 249 } |
| 250 | 250 |
| 251 void ModelTypeSyncWorkerImplTest::NormalInitialize() { | 251 void CommitQueueImplTest::NormalInitialize() { |
| 252 InitializeWithPendingUpdates(UpdateResponseDataList()); | 252 InitializeWithPendingUpdates(UpdateResponseDataList()); |
| 253 } | 253 } |
| 254 | 254 |
| 255 void ModelTypeSyncWorkerImplTest::InitializeWithPendingUpdates( | 255 void CommitQueueImplTest::InitializeWithPendingUpdates( |
| 256 const UpdateResponseDataList& initial_pending_updates) { | 256 const UpdateResponseDataList& initial_pending_updates) { |
| 257 DataTypeState initial_state; | 257 DataTypeState initial_state; |
| 258 initial_state.progress_marker.set_data_type_id( | 258 initial_state.progress_marker.set_data_type_id( |
| 259 GetSpecificsFieldNumberFromModelType(kModelType)); | 259 GetSpecificsFieldNumberFromModelType(kModelType)); |
| 260 initial_state.progress_marker.set_token("some_saved_progress_token"); | 260 initial_state.progress_marker.set_token("some_saved_progress_token"); |
| 261 | 261 |
| 262 initial_state.initial_sync_done = true; | 262 initial_state.initial_sync_done = true; |
| 263 | 263 |
| 264 InitializeWithState(initial_state, initial_pending_updates); | 264 InitializeWithState(initial_state, initial_pending_updates); |
| 265 | 265 |
| 266 mock_nudge_handler_.ClearCounters(); | 266 mock_nudge_handler_.ClearCounters(); |
| 267 } | 267 } |
| 268 | 268 |
| 269 void ModelTypeSyncWorkerImplTest::InitializeWithState( | 269 void CommitQueueImplTest::InitializeWithState( |
| 270 const DataTypeState& state, | 270 const DataTypeState& state, |
| 271 const UpdateResponseDataList& initial_pending_updates) { | 271 const UpdateResponseDataList& initial_pending_updates) { |
| 272 DCHECK(!worker_); | 272 DCHECK(!worker_); |
| 273 | 273 |
| 274 // We don't get to own this object. The |worker_| keeps a scoped_ptr to it. | 274 // We don't get to own this object. The |worker_| keeps a scoped_ptr to it. |
| 275 mock_type_sync_proxy_ = new MockModelTypeSyncProxy(); | 275 mock_type_sync_proxy_ = new MockModelTypeProcessor(); |
| 276 scoped_ptr<ModelTypeSyncProxy> proxy(mock_type_sync_proxy_); | 276 scoped_ptr<ModelTypeProcessor> proxy(mock_type_sync_proxy_); |
| 277 | 277 |
| 278 scoped_ptr<Cryptographer> cryptographer_copy; | 278 scoped_ptr<Cryptographer> cryptographer_copy; |
| 279 if (cryptographer_) { | 279 if (cryptographer_) { |
| 280 cryptographer_copy.reset(new Cryptographer(*cryptographer_)); | 280 cryptographer_copy.reset(new Cryptographer(*cryptographer_)); |
| 281 } | 281 } |
| 282 | 282 |
| 283 worker_.reset(new ModelTypeSyncWorkerImpl(kModelType, | 283 worker_.reset(new CommitQueueImpl(kModelType, |
| 284 state, | 284 state, |
| 285 initial_pending_updates, | 285 initial_pending_updates, |
| 286 cryptographer_copy.Pass(), | 286 cryptographer_copy.Pass(), |
| 287 &mock_nudge_handler_, | 287 &mock_nudge_handler_, |
| 288 proxy.Pass())); | 288 proxy.Pass())); |
| 289 } | 289 } |
| 290 | 290 |
| 291 void ModelTypeSyncWorkerImplTest::NewForeignEncryptionKey() { | 291 void CommitQueueImplTest::NewForeignEncryptionKey() { |
| 292 if (!cryptographer_) { | 292 if (!cryptographer_) { |
| 293 cryptographer_.reset(new Cryptographer(&fake_encryptor_)); | 293 cryptographer_.reset(new Cryptographer(&fake_encryptor_)); |
| 294 } | 294 } |
| 295 | 295 |
| 296 foreign_encryption_key_index_++; | 296 foreign_encryption_key_index_++; |
| 297 | 297 |
| 298 sync_pb::NigoriKeyBag bag; | 298 sync_pb::NigoriKeyBag bag; |
| 299 | 299 |
| 300 for (int i = 0; i <= foreign_encryption_key_index_; ++i) { | 300 for (int i = 0; i <= foreign_encryption_key_index_; ++i) { |
| 301 Nigori nigori; | 301 Nigori nigori; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 327 // Update the cryptographer with new pending keys. | 327 // Update the cryptographer with new pending keys. |
| 328 cryptographer_->SetPendingKeys(encrypted); | 328 cryptographer_->SetPendingKeys(encrypted); |
| 329 | 329 |
| 330 // Update the worker with the latest cryptographer. | 330 // Update the worker with the latest cryptographer. |
| 331 if (worker_) { | 331 if (worker_) { |
| 332 worker_->UpdateCryptographer( | 332 worker_->UpdateCryptographer( |
| 333 make_scoped_ptr(new Cryptographer(*cryptographer_))); | 333 make_scoped_ptr(new Cryptographer(*cryptographer_))); |
| 334 } | 334 } |
| 335 } | 335 } |
| 336 | 336 |
| 337 void ModelTypeSyncWorkerImplTest::UpdateLocalCryptographer() { | 337 void CommitQueueImplTest::UpdateLocalCryptographer() { |
| 338 if (!cryptographer_) { | 338 if (!cryptographer_) { |
| 339 cryptographer_.reset(new Cryptographer(&fake_encryptor_)); | 339 cryptographer_.reset(new Cryptographer(&fake_encryptor_)); |
| 340 } | 340 } |
| 341 | 341 |
| 342 KeyParams params = GetNthKeyParams(foreign_encryption_key_index_); | 342 KeyParams params = GetNthKeyParams(foreign_encryption_key_index_); |
| 343 bool success = cryptographer_->DecryptPendingKeys(params); | 343 bool success = cryptographer_->DecryptPendingKeys(params); |
| 344 DCHECK(success); | 344 DCHECK(success); |
| 345 | 345 |
| 346 // Update the worker with the latest cryptographer. | 346 // Update the worker with the latest cryptographer. |
| 347 if (worker_) { | 347 if (worker_) { |
| 348 worker_->UpdateCryptographer( | 348 worker_->UpdateCryptographer( |
| 349 make_scoped_ptr(new Cryptographer(*cryptographer_))); | 349 make_scoped_ptr(new Cryptographer(*cryptographer_))); |
| 350 } | 350 } |
| 351 } | 351 } |
| 352 | 352 |
| 353 void ModelTypeSyncWorkerImplTest::SetUpdateEncryptionFilter(int n) { | 353 void CommitQueueImplTest::SetUpdateEncryptionFilter(int n) { |
| 354 update_encryption_filter_index_ = n; | 354 update_encryption_filter_index_ = n; |
| 355 } | 355 } |
| 356 | 356 |
| 357 void ModelTypeSyncWorkerImplTest::CommitRequest(const std::string& name, | 357 void CommitQueueImplTest::CommitRequest(const std::string& name, |
| 358 const std::string& value) { | 358 const std::string& value) { |
| 359 const std::string tag_hash = GenerateTagHash(name); | 359 const std::string tag_hash = GenerateTagHash(name); |
| 360 CommitRequestData data = mock_type_sync_proxy_->CommitRequest( | 360 CommitRequestData data = mock_type_sync_proxy_->CommitRequest( |
| 361 tag_hash, GenerateSpecifics(name, value)); | 361 tag_hash, GenerateSpecifics(name, value)); |
| 362 CommitRequestDataList list; | 362 CommitRequestDataList list; |
| 363 list.push_back(data); | 363 list.push_back(data); |
| 364 worker_->EnqueueForCommit(list); | 364 worker_->EnqueueForCommit(list); |
| 365 } | 365 } |
| 366 | 366 |
| 367 void ModelTypeSyncWorkerImplTest::DeleteRequest(const std::string& tag) { | 367 void CommitQueueImplTest::DeleteRequest(const std::string& tag) { |
| 368 const std::string tag_hash = GenerateTagHash(tag); | 368 const std::string tag_hash = GenerateTagHash(tag); |
| 369 CommitRequestData data = mock_type_sync_proxy_->DeleteRequest(tag_hash); | 369 CommitRequestData data = mock_type_sync_proxy_->DeleteRequest(tag_hash); |
| 370 CommitRequestDataList list; | 370 CommitRequestDataList list; |
| 371 list.push_back(data); | 371 list.push_back(data); |
| 372 worker_->EnqueueForCommit(list); | 372 worker_->EnqueueForCommit(list); |
| 373 } | 373 } |
| 374 | 374 |
| 375 void ModelTypeSyncWorkerImplTest::TriggerTypeRootUpdateFromServer() { | 375 void CommitQueueImplTest::TriggerTypeRootUpdateFromServer() { |
| 376 sync_pb::SyncEntity entity = mock_server_.TypeRootUpdate(); | 376 sync_pb::SyncEntity entity = mock_server_.TypeRootUpdate(); |
| 377 SyncEntityList entity_list; | 377 SyncEntityList entity_list; |
| 378 entity_list.push_back(&entity); | 378 entity_list.push_back(&entity); |
| 379 | 379 |
| 380 StatusController dummy_status; | 380 StatusController dummy_status; |
| 381 | 381 |
| 382 worker_->ProcessGetUpdatesResponse(mock_server_.GetProgress(), | 382 worker_->ProcessGetUpdatesResponse(mock_server_.GetProgress(), |
| 383 mock_server_.GetContext(), | 383 mock_server_.GetContext(), |
| 384 entity_list, | 384 entity_list, |
| 385 &dummy_status); | 385 &dummy_status); |
| 386 worker_->ApplyUpdates(&dummy_status); | 386 worker_->ApplyUpdates(&dummy_status); |
| 387 } | 387 } |
| 388 | 388 |
| 389 void ModelTypeSyncWorkerImplTest::TriggerUpdateFromServer( | 389 void CommitQueueImplTest::TriggerUpdateFromServer( |
| 390 int64 version_offset, | 390 int64 version_offset, |
| 391 const std::string& tag, | 391 const std::string& tag, |
| 392 const std::string& value) { | 392 const std::string& value) { |
| 393 sync_pb::SyncEntity entity = mock_server_.UpdateFromServer( | 393 sync_pb::SyncEntity entity = mock_server_.UpdateFromServer( |
| 394 version_offset, GenerateTagHash(tag), GenerateSpecifics(tag, value)); | 394 version_offset, GenerateTagHash(tag), GenerateSpecifics(tag, value)); |
| 395 | 395 |
| 396 if (update_encryption_filter_index_ != 0) { | 396 if (update_encryption_filter_index_ != 0) { |
| 397 EncryptUpdate(GetNthKeyParams(update_encryption_filter_index_), | 397 EncryptUpdate(GetNthKeyParams(update_encryption_filter_index_), |
| 398 entity.mutable_specifics()); | 398 entity.mutable_specifics()); |
| 399 } | 399 } |
| 400 | 400 |
| 401 SyncEntityList entity_list; | 401 SyncEntityList entity_list; |
| 402 entity_list.push_back(&entity); | 402 entity_list.push_back(&entity); |
| 403 | 403 |
| 404 StatusController dummy_status; | 404 StatusController dummy_status; |
| 405 | 405 |
| 406 worker_->ProcessGetUpdatesResponse(mock_server_.GetProgress(), | 406 worker_->ProcessGetUpdatesResponse(mock_server_.GetProgress(), |
| 407 mock_server_.GetContext(), | 407 mock_server_.GetContext(), |
| 408 entity_list, | 408 entity_list, |
| 409 &dummy_status); | 409 &dummy_status); |
| 410 worker_->ApplyUpdates(&dummy_status); | 410 worker_->ApplyUpdates(&dummy_status); |
| 411 } | 411 } |
| 412 | 412 |
| 413 void ModelTypeSyncWorkerImplTest::DeliverRawUpdates( | 413 void CommitQueueImplTest::DeliverRawUpdates( |
| 414 const SyncEntityList& list) { | 414 const SyncEntityList& list) { |
| 415 StatusController dummy_status; | 415 StatusController dummy_status; |
| 416 worker_->ProcessGetUpdatesResponse(mock_server_.GetProgress(), | 416 worker_->ProcessGetUpdatesResponse(mock_server_.GetProgress(), |
| 417 mock_server_.GetContext(), | 417 mock_server_.GetContext(), |
| 418 list, | 418 list, |
| 419 &dummy_status); | 419 &dummy_status); |
| 420 worker_->ApplyUpdates(&dummy_status); | 420 worker_->ApplyUpdates(&dummy_status); |
| 421 } | 421 } |
| 422 | 422 |
| 423 void ModelTypeSyncWorkerImplTest::TriggerTombstoneFromServer( | 423 void CommitQueueImplTest::TriggerTombstoneFromServer( |
| 424 int64 version_offset, | 424 int64 version_offset, |
| 425 const std::string& tag) { | 425 const std::string& tag) { |
| 426 sync_pb::SyncEntity entity = | 426 sync_pb::SyncEntity entity = |
| 427 mock_server_.TombstoneFromServer(version_offset, GenerateTagHash(tag)); | 427 mock_server_.TombstoneFromServer(version_offset, GenerateTagHash(tag)); |
| 428 | 428 |
| 429 if (update_encryption_filter_index_ != 0) { | 429 if (update_encryption_filter_index_ != 0) { |
| 430 EncryptUpdate(GetNthKeyParams(update_encryption_filter_index_), | 430 EncryptUpdate(GetNthKeyParams(update_encryption_filter_index_), |
| 431 entity.mutable_specifics()); | 431 entity.mutable_specifics()); |
| 432 } | 432 } |
| 433 | 433 |
| 434 SyncEntityList entity_list; | 434 SyncEntityList entity_list; |
| 435 entity_list.push_back(&entity); | 435 entity_list.push_back(&entity); |
| 436 | 436 |
| 437 StatusController dummy_status; | 437 StatusController dummy_status; |
| 438 | 438 |
| 439 worker_->ProcessGetUpdatesResponse(mock_server_.GetProgress(), | 439 worker_->ProcessGetUpdatesResponse(mock_server_.GetProgress(), |
| 440 mock_server_.GetContext(), | 440 mock_server_.GetContext(), |
| 441 entity_list, | 441 entity_list, |
| 442 &dummy_status); | 442 &dummy_status); |
| 443 worker_->ApplyUpdates(&dummy_status); | 443 worker_->ApplyUpdates(&dummy_status); |
| 444 } | 444 } |
| 445 | 445 |
| 446 void ModelTypeSyncWorkerImplTest::SetModelThreadIsSynchronous( | 446 void CommitQueueImplTest::SetModelThreadIsSynchronous( |
| 447 bool is_synchronous) { | 447 bool is_synchronous) { |
| 448 mock_type_sync_proxy_->SetSynchronousExecution(is_synchronous); | 448 mock_type_sync_proxy_->SetSynchronousExecution(is_synchronous); |
| 449 } | 449 } |
| 450 | 450 |
| 451 void ModelTypeSyncWorkerImplTest::PumpModelThread() { | 451 void CommitQueueImplTest::PumpModelThread() { |
| 452 mock_type_sync_proxy_->RunQueuedTasks(); | 452 mock_type_sync_proxy_->RunQueuedTasks(); |
| 453 } | 453 } |
| 454 | 454 |
| 455 bool ModelTypeSyncWorkerImplTest::WillCommit() { | 455 bool CommitQueueImplTest::WillCommit() { |
| 456 scoped_ptr<CommitContribution> contribution( | 456 scoped_ptr<CommitContribution> contribution( |
| 457 worker_->GetContribution(INT_MAX)); | 457 worker_->GetContribution(INT_MAX)); |
| 458 | 458 |
| 459 if (contribution) { | 459 if (contribution) { |
| 460 contribution->CleanUp(); // Gracefully abort the commit. | 460 contribution->CleanUp(); // Gracefully abort the commit. |
| 461 return true; | 461 return true; |
| 462 } else { | 462 } else { |
| 463 return false; | 463 return false; |
| 464 } | 464 } |
| 465 } | 465 } |
| 466 | 466 |
| 467 // Conveniently, this is all one big synchronous operation. The sync thread | 467 // Conveniently, this is all one big synchronous operation. The sync thread |
| 468 // remains blocked while the commit is in progress, so we don't need to worry | 468 // remains blocked while the commit is in progress, so we don't need to worry |
| 469 // about other tasks being run between the time when the commit request is | 469 // about other tasks being run between the time when the commit request is |
| 470 // issued and the time when the commit response is received. | 470 // issued and the time when the commit response is received. |
| 471 void ModelTypeSyncWorkerImplTest::DoSuccessfulCommit() { | 471 void CommitQueueImplTest::DoSuccessfulCommit() { |
| 472 DCHECK(WillCommit()); | 472 DCHECK(WillCommit()); |
| 473 scoped_ptr<CommitContribution> contribution( | 473 scoped_ptr<CommitContribution> contribution( |
| 474 worker_->GetContribution(INT_MAX)); | 474 worker_->GetContribution(INT_MAX)); |
| 475 | 475 |
| 476 sync_pb::ClientToServerMessage message; | 476 sync_pb::ClientToServerMessage message; |
| 477 contribution->AddToCommitMessage(&message); | 477 contribution->AddToCommitMessage(&message); |
| 478 | 478 |
| 479 sync_pb::ClientToServerResponse response = | 479 sync_pb::ClientToServerResponse response = |
| 480 mock_server_.DoSuccessfulCommit(message); | 480 mock_server_.DoSuccessfulCommit(message); |
| 481 | 481 |
| 482 StatusController dummy_status; | 482 StatusController dummy_status; |
| 483 contribution->ProcessCommitResponse(response, &dummy_status); | 483 contribution->ProcessCommitResponse(response, &dummy_status); |
| 484 contribution->CleanUp(); | 484 contribution->CleanUp(); |
| 485 } | 485 } |
| 486 | 486 |
| 487 size_t ModelTypeSyncWorkerImplTest::GetNumCommitMessagesOnServer() const { | 487 size_t CommitQueueImplTest::GetNumCommitMessagesOnServer() const { |
| 488 return mock_server_.GetNumCommitMessages(); | 488 return mock_server_.GetNumCommitMessages(); |
| 489 } | 489 } |
| 490 | 490 |
| 491 sync_pb::ClientToServerMessage | 491 sync_pb::ClientToServerMessage |
| 492 ModelTypeSyncWorkerImplTest::GetNthCommitMessageOnServer(size_t n) const { | 492 CommitQueueImplTest::GetNthCommitMessageOnServer(size_t n) const { |
| 493 DCHECK_LT(n, GetNumCommitMessagesOnServer()); | 493 DCHECK_LT(n, GetNumCommitMessagesOnServer()); |
| 494 return mock_server_.GetNthCommitMessage(n); | 494 return mock_server_.GetNthCommitMessage(n); |
| 495 } | 495 } |
| 496 | 496 |
| 497 bool ModelTypeSyncWorkerImplTest::HasCommitEntityOnServer( | 497 bool CommitQueueImplTest::HasCommitEntityOnServer( |
| 498 const std::string& tag) const { | 498 const std::string& tag) const { |
| 499 const std::string tag_hash = GenerateTagHash(tag); | 499 const std::string tag_hash = GenerateTagHash(tag); |
| 500 return mock_server_.HasCommitEntity(tag_hash); | 500 return mock_server_.HasCommitEntity(tag_hash); |
| 501 } | 501 } |
| 502 | 502 |
| 503 sync_pb::SyncEntity ModelTypeSyncWorkerImplTest::GetLatestCommitEntityOnServer( | 503 sync_pb::SyncEntity CommitQueueImplTest::GetLatestCommitEntityOnServer( |
| 504 const std::string& tag) const { | 504 const std::string& tag) const { |
| 505 DCHECK(HasCommitEntityOnServer(tag)); | 505 DCHECK(HasCommitEntityOnServer(tag)); |
| 506 const std::string tag_hash = GenerateTagHash(tag); | 506 const std::string tag_hash = GenerateTagHash(tag); |
| 507 return mock_server_.GetLastCommittedEntity(tag_hash); | 507 return mock_server_.GetLastCommittedEntity(tag_hash); |
| 508 } | 508 } |
| 509 | 509 |
| 510 size_t ModelTypeSyncWorkerImplTest::GetNumModelThreadUpdateResponses() const { | 510 size_t CommitQueueImplTest::GetNumModelThreadUpdateResponses() const { |
| 511 return mock_type_sync_proxy_->GetNumUpdateResponses(); | 511 return mock_type_sync_proxy_->GetNumUpdateResponses(); |
| 512 } | 512 } |
| 513 | 513 |
| 514 UpdateResponseDataList | 514 UpdateResponseDataList |
| 515 ModelTypeSyncWorkerImplTest::GetNthModelThreadUpdateResponse(size_t n) const { | 515 CommitQueueImplTest::GetNthModelThreadUpdateResponse(size_t n) const { |
| 516 DCHECK_LT(n, GetNumModelThreadUpdateResponses()); | 516 DCHECK_LT(n, GetNumModelThreadUpdateResponses()); |
| 517 return mock_type_sync_proxy_->GetNthUpdateResponse(n); | 517 return mock_type_sync_proxy_->GetNthUpdateResponse(n); |
| 518 } | 518 } |
| 519 | 519 |
| 520 UpdateResponseDataList | 520 UpdateResponseDataList |
| 521 ModelTypeSyncWorkerImplTest::GetNthModelThreadPendingUpdates(size_t n) const { | 521 CommitQueueImplTest::GetNthModelThreadPendingUpdates(size_t n) const { |
| 522 DCHECK_LT(n, GetNumModelThreadUpdateResponses()); | 522 DCHECK_LT(n, GetNumModelThreadUpdateResponses()); |
| 523 return mock_type_sync_proxy_->GetNthPendingUpdates(n); | 523 return mock_type_sync_proxy_->GetNthPendingUpdates(n); |
| 524 } | 524 } |
| 525 | 525 |
| 526 DataTypeState ModelTypeSyncWorkerImplTest::GetNthModelThreadUpdateState( | 526 DataTypeState CommitQueueImplTest::GetNthModelThreadUpdateState( |
| 527 size_t n) const { | 527 size_t n) const { |
| 528 DCHECK_LT(n, GetNumModelThreadUpdateResponses()); | 528 DCHECK_LT(n, GetNumModelThreadUpdateResponses()); |
| 529 return mock_type_sync_proxy_->GetNthTypeStateReceivedInUpdateResponse(n); | 529 return mock_type_sync_proxy_->GetNthTypeStateReceivedInUpdateResponse(n); |
| 530 } | 530 } |
| 531 | 531 |
| 532 bool ModelTypeSyncWorkerImplTest::HasUpdateResponseOnModelThread( | 532 bool CommitQueueImplTest::HasUpdateResponseOnModelThread( |
| 533 const std::string& tag) const { | 533 const std::string& tag) const { |
| 534 const std::string tag_hash = GenerateTagHash(tag); | 534 const std::string tag_hash = GenerateTagHash(tag); |
| 535 return mock_type_sync_proxy_->HasUpdateResponse(tag_hash); | 535 return mock_type_sync_proxy_->HasUpdateResponse(tag_hash); |
| 536 } | 536 } |
| 537 | 537 |
| 538 UpdateResponseData ModelTypeSyncWorkerImplTest::GetUpdateResponseOnModelThread( | 538 UpdateResponseData CommitQueueImplTest::GetUpdateResponseOnModelThread( |
| 539 const std::string& tag) const { | 539 const std::string& tag) const { |
| 540 const std::string tag_hash = GenerateTagHash(tag); | 540 const std::string tag_hash = GenerateTagHash(tag); |
| 541 return mock_type_sync_proxy_->GetUpdateResponse(tag_hash); | 541 return mock_type_sync_proxy_->GetUpdateResponse(tag_hash); |
| 542 } | 542 } |
| 543 | 543 |
| 544 size_t ModelTypeSyncWorkerImplTest::GetNumModelThreadCommitResponses() const { | 544 size_t CommitQueueImplTest::GetNumModelThreadCommitResponses() const { |
| 545 return mock_type_sync_proxy_->GetNumCommitResponses(); | 545 return mock_type_sync_proxy_->GetNumCommitResponses(); |
| 546 } | 546 } |
| 547 | 547 |
| 548 CommitResponseDataList | 548 CommitResponseDataList |
| 549 ModelTypeSyncWorkerImplTest::GetNthModelThreadCommitResponse(size_t n) const { | 549 CommitQueueImplTest::GetNthModelThreadCommitResponse(size_t n) const { |
| 550 DCHECK_LT(n, GetNumModelThreadCommitResponses()); | 550 DCHECK_LT(n, GetNumModelThreadCommitResponses()); |
| 551 return mock_type_sync_proxy_->GetNthCommitResponse(n); | 551 return mock_type_sync_proxy_->GetNthCommitResponse(n); |
| 552 } | 552 } |
| 553 | 553 |
| 554 DataTypeState ModelTypeSyncWorkerImplTest::GetNthModelThreadCommitState( | 554 DataTypeState CommitQueueImplTest::GetNthModelThreadCommitState( |
| 555 size_t n) const { | 555 size_t n) const { |
| 556 DCHECK_LT(n, GetNumModelThreadCommitResponses()); | 556 DCHECK_LT(n, GetNumModelThreadCommitResponses()); |
| 557 return mock_type_sync_proxy_->GetNthTypeStateReceivedInCommitResponse(n); | 557 return mock_type_sync_proxy_->GetNthTypeStateReceivedInCommitResponse(n); |
| 558 } | 558 } |
| 559 | 559 |
| 560 bool ModelTypeSyncWorkerImplTest::HasCommitResponseOnModelThread( | 560 bool CommitQueueImplTest::HasCommitResponseOnModelThread( |
| 561 const std::string& tag) const { | 561 const std::string& tag) const { |
| 562 const std::string tag_hash = GenerateTagHash(tag); | 562 const std::string tag_hash = GenerateTagHash(tag); |
| 563 return mock_type_sync_proxy_->HasCommitResponse(tag_hash); | 563 return mock_type_sync_proxy_->HasCommitResponse(tag_hash); |
| 564 } | 564 } |
| 565 | 565 |
| 566 CommitResponseData ModelTypeSyncWorkerImplTest::GetCommitResponseOnModelThread( | 566 CommitResponseData CommitQueueImplTest::GetCommitResponseOnModelThread( |
| 567 const std::string& tag) const { | 567 const std::string& tag) const { |
| 568 DCHECK(HasCommitResponseOnModelThread(tag)); | 568 DCHECK(HasCommitResponseOnModelThread(tag)); |
| 569 const std::string tag_hash = GenerateTagHash(tag); | 569 const std::string tag_hash = GenerateTagHash(tag); |
| 570 return mock_type_sync_proxy_->GetCommitResponse(tag_hash); | 570 return mock_type_sync_proxy_->GetCommitResponse(tag_hash); |
| 571 } | 571 } |
| 572 | 572 |
| 573 int ModelTypeSyncWorkerImplTest::GetNumCommitNudges() const { | 573 int CommitQueueImplTest::GetNumCommitNudges() const { |
| 574 return mock_nudge_handler_.GetNumCommitNudges(); | 574 return mock_nudge_handler_.GetNumCommitNudges(); |
| 575 } | 575 } |
| 576 | 576 |
| 577 int ModelTypeSyncWorkerImplTest::GetNumInitialDownloadNudges() const { | 577 int CommitQueueImplTest::GetNumInitialDownloadNudges() const { |
| 578 return mock_nudge_handler_.GetNumInitialDownloadNudges(); | 578 return mock_nudge_handler_.GetNumInitialDownloadNudges(); |
| 579 } | 579 } |
| 580 | 580 |
| 581 std::string ModelTypeSyncWorkerImplTest::GetLocalCryptographerKeyName() const { | 581 std::string CommitQueueImplTest::GetLocalCryptographerKeyName() const { |
| 582 if (!cryptographer_) { | 582 if (!cryptographer_) { |
| 583 return std::string(); | 583 return std::string(); |
| 584 } | 584 } |
| 585 | 585 |
| 586 return cryptographer_->GetDefaultNigoriKeyName(); | 586 return cryptographer_->GetDefaultNigoriKeyName(); |
| 587 } | 587 } |
| 588 | 588 |
| 589 // static. | 589 // static. |
| 590 std::string ModelTypeSyncWorkerImplTest::GenerateTagHash( | 590 std::string CommitQueueImplTest::GenerateTagHash( |
| 591 const std::string& tag) { | 591 const std::string& tag) { |
| 592 const std::string& client_tag_hash = | 592 const std::string& client_tag_hash = |
| 593 syncer::syncable::GenerateSyncableHash(kModelType, tag); | 593 syncer::syncable::GenerateSyncableHash(kModelType, tag); |
| 594 return client_tag_hash; | 594 return client_tag_hash; |
| 595 } | 595 } |
| 596 | 596 |
| 597 // static. | 597 // static. |
| 598 sync_pb::EntitySpecifics ModelTypeSyncWorkerImplTest::GenerateSpecifics( | 598 sync_pb::EntitySpecifics CommitQueueImplTest::GenerateSpecifics( |
| 599 const std::string& tag, | 599 const std::string& tag, |
| 600 const std::string& value) { | 600 const std::string& value) { |
| 601 sync_pb::EntitySpecifics specifics; | 601 sync_pb::EntitySpecifics specifics; |
| 602 specifics.mutable_preference()->set_name(tag); | 602 specifics.mutable_preference()->set_name(tag); |
| 603 specifics.mutable_preference()->set_value(value); | 603 specifics.mutable_preference()->set_value(value); |
| 604 return specifics; | 604 return specifics; |
| 605 } | 605 } |
| 606 | 606 |
| 607 // static. | 607 // static. |
| 608 std::string ModelTypeSyncWorkerImplTest::GetNigoriName(const Nigori& nigori) { | 608 std::string CommitQueueImplTest::GetNigoriName(const Nigori& nigori) { |
| 609 std::string name; | 609 std::string name; |
| 610 if (!nigori.Permute(Nigori::Password, kNigoriKeyName, &name)) { | 610 if (!nigori.Permute(Nigori::Password, kNigoriKeyName, &name)) { |
| 611 NOTREACHED(); | 611 NOTREACHED(); |
| 612 return std::string(); | 612 return std::string(); |
| 613 } | 613 } |
| 614 | 614 |
| 615 return name; | 615 return name; |
| 616 } | 616 } |
| 617 | 617 |
| 618 // static. | 618 // static. |
| 619 KeyParams ModelTypeSyncWorkerImplTest::GetNthKeyParams(int n) { | 619 KeyParams CommitQueueImplTest::GetNthKeyParams(int n) { |
| 620 KeyParams params; | 620 KeyParams params; |
| 621 params.hostname = std::string("localhost"); | 621 params.hostname = std::string("localhost"); |
| 622 params.username = std::string("userX"); | 622 params.username = std::string("userX"); |
| 623 params.password = base::StringPrintf("pw%02d", n); | 623 params.password = base::StringPrintf("pw%02d", n); |
| 624 return params; | 624 return params; |
| 625 } | 625 } |
| 626 | 626 |
| 627 // static. | 627 // static. |
| 628 void ModelTypeSyncWorkerImplTest::EncryptUpdate( | 628 void CommitQueueImplTest::EncryptUpdate( |
| 629 const KeyParams& params, | 629 const KeyParams& params, |
| 630 sync_pb::EntitySpecifics* specifics) { | 630 sync_pb::EntitySpecifics* specifics) { |
| 631 Nigori nigori; | 631 Nigori nigori; |
| 632 nigori.InitByDerivation(params.hostname, params.username, params.password); | 632 nigori.InitByDerivation(params.hostname, params.username, params.password); |
| 633 | 633 |
| 634 sync_pb::EntitySpecifics original_specifics = *specifics; | 634 sync_pb::EntitySpecifics original_specifics = *specifics; |
| 635 std::string plaintext; | 635 std::string plaintext; |
| 636 original_specifics.SerializeToString(&plaintext); | 636 original_specifics.SerializeToString(&plaintext); |
| 637 | 637 |
| 638 std::string encrypted; | 638 std::string encrypted; |
| 639 nigori.Encrypt(plaintext, &encrypted); | 639 nigori.Encrypt(plaintext, &encrypted); |
| 640 | 640 |
| 641 specifics->Clear(); | 641 specifics->Clear(); |
| 642 AddDefaultFieldValue(kModelType, specifics); | 642 AddDefaultFieldValue(kModelType, specifics); |
| 643 specifics->mutable_encrypted()->set_key_name(GetNigoriName(nigori)); | 643 specifics->mutable_encrypted()->set_key_name(GetNigoriName(nigori)); |
| 644 specifics->mutable_encrypted()->set_blob(encrypted); | 644 specifics->mutable_encrypted()->set_blob(encrypted); |
| 645 } | 645 } |
| 646 | 646 |
| 647 // Requests a commit and verifies the messages sent to the client and server as | 647 // Requests a commit and verifies the messages sent to the client and server as |
| 648 // a result. | 648 // a result. |
| 649 // | 649 // |
| 650 // This test performs sanity checks on most of the fields in these messages. | 650 // This test performs sanity checks on most of the fields in these messages. |
| 651 // For the most part this is checking that the test code behaves as expected | 651 // For the most part this is checking that the test code behaves as expected |
| 652 // and the |worker_| doesn't mess up its simple task of moving around these | 652 // and the |worker_| doesn't mess up its simple task of moving around these |
| 653 // values. It makes sense to have one or two tests that are this thorough, but | 653 // values. It makes sense to have one or two tests that are this thorough, but |
| 654 // we shouldn't be this verbose in all tests. | 654 // we shouldn't be this verbose in all tests. |
| 655 TEST_F(ModelTypeSyncWorkerImplTest, SimpleCommit) { | 655 TEST_F(CommitQueueImplTest, SimpleCommit) { |
| 656 NormalInitialize(); | 656 NormalInitialize(); |
| 657 | 657 |
| 658 EXPECT_FALSE(WillCommit()); | 658 EXPECT_FALSE(WillCommit()); |
| 659 EXPECT_EQ(0U, GetNumCommitMessagesOnServer()); | 659 EXPECT_EQ(0U, GetNumCommitMessagesOnServer()); |
| 660 EXPECT_EQ(0U, GetNumModelThreadCommitResponses()); | 660 EXPECT_EQ(0U, GetNumModelThreadCommitResponses()); |
| 661 | 661 |
| 662 CommitRequest("tag1", "value1"); | 662 CommitRequest("tag1", "value1"); |
| 663 | 663 |
| 664 EXPECT_EQ(1, GetNumCommitNudges()); | 664 EXPECT_EQ(1, GetNumCommitNudges()); |
| 665 | 665 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 691 GetCommitResponseOnModelThread("tag1"); | 691 GetCommitResponseOnModelThread("tag1"); |
| 692 | 692 |
| 693 // The ID changes in a commit response to initial commit. | 693 // The ID changes in a commit response to initial commit. |
| 694 EXPECT_FALSE(commit_response.id.empty()); | 694 EXPECT_FALSE(commit_response.id.empty()); |
| 695 EXPECT_NE(entity.id_string(), commit_response.id); | 695 EXPECT_NE(entity.id_string(), commit_response.id); |
| 696 | 696 |
| 697 EXPECT_EQ(client_tag_hash, commit_response.client_tag_hash); | 697 EXPECT_EQ(client_tag_hash, commit_response.client_tag_hash); |
| 698 EXPECT_LT(0, commit_response.response_version); | 698 EXPECT_LT(0, commit_response.response_version); |
| 699 } | 699 } |
| 700 | 700 |
| 701 TEST_F(ModelTypeSyncWorkerImplTest, SimpleDelete) { | 701 TEST_F(CommitQueueImplTest, SimpleDelete) { |
| 702 NormalInitialize(); | 702 NormalInitialize(); |
| 703 | 703 |
| 704 // We can't delete an entity that was never committed. | 704 // We can't delete an entity that was never committed. |
| 705 // Step 1 is to create and commit a new entity. | 705 // Step 1 is to create and commit a new entity. |
| 706 CommitRequest("tag1", "value1"); | 706 CommitRequest("tag1", "value1"); |
| 707 EXPECT_EQ(1, GetNumCommitNudges()); | 707 EXPECT_EQ(1, GetNumCommitNudges()); |
| 708 ASSERT_TRUE(WillCommit()); | 708 ASSERT_TRUE(WillCommit()); |
| 709 DoSuccessfulCommit(); | 709 DoSuccessfulCommit(); |
| 710 | 710 |
| 711 ASSERT_TRUE(HasCommitResponseOnModelThread("tag1")); | 711 ASSERT_TRUE(HasCommitResponseOnModelThread("tag1")); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 740 GetCommitResponseOnModelThread("tag1"); | 740 GetCommitResponseOnModelThread("tag1"); |
| 741 | 741 |
| 742 EXPECT_EQ(entity.id_string(), commit_response.id); | 742 EXPECT_EQ(entity.id_string(), commit_response.id); |
| 743 EXPECT_EQ(entity.client_defined_unique_tag(), | 743 EXPECT_EQ(entity.client_defined_unique_tag(), |
| 744 commit_response.client_tag_hash); | 744 commit_response.client_tag_hash); |
| 745 EXPECT_EQ(entity.version(), commit_response.response_version); | 745 EXPECT_EQ(entity.version(), commit_response.response_version); |
| 746 } | 746 } |
| 747 | 747 |
| 748 // The server doesn't like it when we try to delete an entity it's never heard | 748 // The server doesn't like it when we try to delete an entity it's never heard |
| 749 // of before. This test helps ensure we avoid that scenario. | 749 // of before. This test helps ensure we avoid that scenario. |
| 750 TEST_F(ModelTypeSyncWorkerImplTest, NoDeleteUncommitted) { | 750 TEST_F(CommitQueueImplTest, NoDeleteUncommitted) { |
| 751 NormalInitialize(); | 751 NormalInitialize(); |
| 752 | 752 |
| 753 // Request the commit of a new, never-before-seen item. | 753 // Request the commit of a new, never-before-seen item. |
| 754 CommitRequest("tag1", "value1"); | 754 CommitRequest("tag1", "value1"); |
| 755 EXPECT_TRUE(WillCommit()); | 755 EXPECT_TRUE(WillCommit()); |
| 756 EXPECT_EQ(1, GetNumCommitNudges()); | 756 EXPECT_EQ(1, GetNumCommitNudges()); |
| 757 | 757 |
| 758 // Request a deletion of that item before we've had a chance to commit it. | 758 // Request a deletion of that item before we've had a chance to commit it. |
| 759 DeleteRequest("tag1"); | 759 DeleteRequest("tag1"); |
| 760 EXPECT_FALSE(WillCommit()); | 760 EXPECT_FALSE(WillCommit()); |
| 761 EXPECT_EQ(2, GetNumCommitNudges()); | 761 EXPECT_EQ(2, GetNumCommitNudges()); |
| 762 } | 762 } |
| 763 | 763 |
| 764 // Verifies the sending of an "initial sync done" signal. | 764 // Verifies the sending of an "initial sync done" signal. |
| 765 TEST_F(ModelTypeSyncWorkerImplTest, SendInitialSyncDone) { | 765 TEST_F(CommitQueueImplTest, SendInitialSyncDone) { |
| 766 FirstInitialize(); // Initialize with no saved sync state. | 766 FirstInitialize(); // Initialize with no saved sync state. |
| 767 EXPECT_EQ(0U, GetNumModelThreadUpdateResponses()); | 767 EXPECT_EQ(0U, GetNumModelThreadUpdateResponses()); |
| 768 EXPECT_EQ(1, GetNumInitialDownloadNudges()); | 768 EXPECT_EQ(1, GetNumInitialDownloadNudges()); |
| 769 | 769 |
| 770 // Receive an update response that contains only the type root node. | 770 // Receive an update response that contains only the type root node. |
| 771 TriggerTypeRootUpdateFromServer(); | 771 TriggerTypeRootUpdateFromServer(); |
| 772 | 772 |
| 773 // Two updates: | 773 // Two updates: |
| 774 // - One triggered by process updates to forward the type root ID. | 774 // - One triggered by process updates to forward the type root ID. |
| 775 // - One triggered by apply updates, which the worker interprets to mean | 775 // - One triggered by apply updates, which the worker interprets to mean |
| 776 // "initial sync done". This triggers a model thread update, too. | 776 // "initial sync done". This triggers a model thread update, too. |
| 777 EXPECT_EQ(2U, GetNumModelThreadUpdateResponses()); | 777 EXPECT_EQ(2U, GetNumModelThreadUpdateResponses()); |
| 778 | 778 |
| 779 // The type root and initial sync done updates both contain no entities. | 779 // The type root and initial sync done updates both contain no entities. |
| 780 EXPECT_EQ(0U, GetNthModelThreadUpdateResponse(0).size()); | 780 EXPECT_EQ(0U, GetNthModelThreadUpdateResponse(0).size()); |
| 781 EXPECT_EQ(0U, GetNthModelThreadUpdateResponse(1).size()); | 781 EXPECT_EQ(0U, GetNthModelThreadUpdateResponse(1).size()); |
| 782 | 782 |
| 783 const DataTypeState& state = GetNthModelThreadUpdateState(1); | 783 const DataTypeState& state = GetNthModelThreadUpdateState(1); |
| 784 EXPECT_FALSE(state.progress_marker.token().empty()); | 784 EXPECT_FALSE(state.progress_marker.token().empty()); |
| 785 EXPECT_TRUE(state.initial_sync_done); | 785 EXPECT_TRUE(state.initial_sync_done); |
| 786 } | 786 } |
| 787 | 787 |
| 788 // Commit two new entities in two separate commit messages. | 788 // Commit two new entities in two separate commit messages. |
| 789 TEST_F(ModelTypeSyncWorkerImplTest, TwoNewItemsCommittedSeparately) { | 789 TEST_F(CommitQueueImplTest, TwoNewItemsCommittedSeparately) { |
| 790 NormalInitialize(); | 790 NormalInitialize(); |
| 791 | 791 |
| 792 // Commit the first of two entities. | 792 // Commit the first of two entities. |
| 793 CommitRequest("tag1", "value1"); | 793 CommitRequest("tag1", "value1"); |
| 794 EXPECT_EQ(1, GetNumCommitNudges()); | 794 EXPECT_EQ(1, GetNumCommitNudges()); |
| 795 ASSERT_TRUE(WillCommit()); | 795 ASSERT_TRUE(WillCommit()); |
| 796 DoSuccessfulCommit(); | 796 DoSuccessfulCommit(); |
| 797 ASSERT_EQ(1U, GetNumCommitMessagesOnServer()); | 797 ASSERT_EQ(1U, GetNumCommitMessagesOnServer()); |
| 798 EXPECT_EQ(1, GetNthCommitMessageOnServer(0).commit().entries_size()); | 798 EXPECT_EQ(1, GetNthCommitMessageOnServer(0).commit().entries_size()); |
| 799 ASSERT_TRUE(HasCommitEntityOnServer("tag1")); | 799 ASSERT_TRUE(HasCommitEntityOnServer("tag1")); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 819 // Check that the committed specifics values are sane. | 819 // Check that the committed specifics values are sane. |
| 820 EXPECT_EQ(tag1_entity.specifics().preference().value(), "value1"); | 820 EXPECT_EQ(tag1_entity.specifics().preference().value(), "value1"); |
| 821 EXPECT_EQ(tag2_entity.specifics().preference().value(), "value2"); | 821 EXPECT_EQ(tag2_entity.specifics().preference().value(), "value2"); |
| 822 | 822 |
| 823 // There should have been two separate commit responses sent to the model | 823 // There should have been two separate commit responses sent to the model |
| 824 // thread. They should be uninteresting, so we don't bother inspecting them. | 824 // thread. They should be uninteresting, so we don't bother inspecting them. |
| 825 EXPECT_EQ(2U, GetNumModelThreadCommitResponses()); | 825 EXPECT_EQ(2U, GetNumModelThreadCommitResponses()); |
| 826 } | 826 } |
| 827 | 827 |
| 828 // Test normal update receipt code path. | 828 // Test normal update receipt code path. |
| 829 TEST_F(ModelTypeSyncWorkerImplTest, ReceiveUpdates) { | 829 TEST_F(CommitQueueImplTest, ReceiveUpdates) { |
| 830 NormalInitialize(); | 830 NormalInitialize(); |
| 831 | 831 |
| 832 const std::string& tag_hash = GenerateTagHash("tag1"); | 832 const std::string& tag_hash = GenerateTagHash("tag1"); |
| 833 | 833 |
| 834 TriggerUpdateFromServer(10, "tag1", "value1"); | 834 TriggerUpdateFromServer(10, "tag1", "value1"); |
| 835 | 835 |
| 836 ASSERT_EQ(1U, GetNumModelThreadUpdateResponses()); | 836 ASSERT_EQ(1U, GetNumModelThreadUpdateResponses()); |
| 837 UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(0); | 837 UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(0); |
| 838 ASSERT_EQ(1U, updates_list.size()); | 838 ASSERT_EQ(1U, updates_list.size()); |
| 839 | 839 |
| 840 ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1")); | 840 ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1")); |
| 841 UpdateResponseData update = GetUpdateResponseOnModelThread("tag1"); | 841 UpdateResponseData update = GetUpdateResponseOnModelThread("tag1"); |
| 842 | 842 |
| 843 EXPECT_FALSE(update.id.empty()); | 843 EXPECT_FALSE(update.id.empty()); |
| 844 EXPECT_EQ(tag_hash, update.client_tag_hash); | 844 EXPECT_EQ(tag_hash, update.client_tag_hash); |
| 845 EXPECT_LT(0, update.response_version); | 845 EXPECT_LT(0, update.response_version); |
| 846 EXPECT_FALSE(update.ctime.is_null()); | 846 EXPECT_FALSE(update.ctime.is_null()); |
| 847 EXPECT_FALSE(update.mtime.is_null()); | 847 EXPECT_FALSE(update.mtime.is_null()); |
| 848 EXPECT_FALSE(update.non_unique_name.empty()); | 848 EXPECT_FALSE(update.non_unique_name.empty()); |
| 849 EXPECT_FALSE(update.deleted); | 849 EXPECT_FALSE(update.deleted); |
| 850 EXPECT_EQ("tag1", update.specifics.preference().name()); | 850 EXPECT_EQ("tag1", update.specifics.preference().name()); |
| 851 EXPECT_EQ("value1", update.specifics.preference().value()); | 851 EXPECT_EQ("value1", update.specifics.preference().value()); |
| 852 } | 852 } |
| 853 | 853 |
| 854 // Test commit of encrypted updates. | 854 // Test commit of encrypted updates. |
| 855 TEST_F(ModelTypeSyncWorkerImplTest, EncryptedCommit) { | 855 TEST_F(CommitQueueImplTest, EncryptedCommit) { |
| 856 NormalInitialize(); | 856 NormalInitialize(); |
| 857 | 857 |
| 858 ASSERT_EQ(0U, GetNumModelThreadUpdateResponses()); | 858 ASSERT_EQ(0U, GetNumModelThreadUpdateResponses()); |
| 859 | 859 |
| 860 NewForeignEncryptionKey(); | 860 NewForeignEncryptionKey(); |
| 861 UpdateLocalCryptographer(); | 861 UpdateLocalCryptographer(); |
| 862 | 862 |
| 863 ASSERT_EQ(1U, GetNumModelThreadUpdateResponses()); | 863 ASSERT_EQ(1U, GetNumModelThreadUpdateResponses()); |
| 864 EXPECT_EQ(GetLocalCryptographerKeyName(), | 864 EXPECT_EQ(GetLocalCryptographerKeyName(), |
| 865 GetNthModelThreadUpdateState(0).encryption_key_name); | 865 GetNthModelThreadUpdateState(0).encryption_key_name); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 878 // The title should be overwritten. | 878 // The title should be overwritten. |
| 879 EXPECT_EQ(tag1_entity.name(), "encrypted"); | 879 EXPECT_EQ(tag1_entity.name(), "encrypted"); |
| 880 | 880 |
| 881 // The type should be set, but there should be no non-encrypted contents. | 881 // The type should be set, but there should be no non-encrypted contents. |
| 882 EXPECT_TRUE(tag1_entity.specifics().has_preference()); | 882 EXPECT_TRUE(tag1_entity.specifics().has_preference()); |
| 883 EXPECT_FALSE(tag1_entity.specifics().preference().has_name()); | 883 EXPECT_FALSE(tag1_entity.specifics().preference().has_name()); |
| 884 EXPECT_FALSE(tag1_entity.specifics().preference().has_value()); | 884 EXPECT_FALSE(tag1_entity.specifics().preference().has_value()); |
| 885 } | 885 } |
| 886 | 886 |
| 887 // Test items are not committed when encryption is required but unavailable. | 887 // Test items are not committed when encryption is required but unavailable. |
| 888 TEST_F(ModelTypeSyncWorkerImplTest, EncryptionBlocksCommits) { | 888 TEST_F(CommitQueueImplTest, EncryptionBlocksCommits) { |
| 889 NormalInitialize(); | 889 NormalInitialize(); |
| 890 | 890 |
| 891 CommitRequest("tag1", "value1"); | 891 CommitRequest("tag1", "value1"); |
| 892 EXPECT_TRUE(WillCommit()); | 892 EXPECT_TRUE(WillCommit()); |
| 893 | 893 |
| 894 // We know encryption is in use on this account, but don't have the necessary | 894 // We know encryption is in use on this account, but don't have the necessary |
| 895 // encryption keys. The worker should refuse to commit. | 895 // encryption keys. The worker should refuse to commit. |
| 896 NewForeignEncryptionKey(); | 896 NewForeignEncryptionKey(); |
| 897 EXPECT_FALSE(WillCommit()); | 897 EXPECT_FALSE(WillCommit()); |
| 898 | 898 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 911 const sync_pb::SyncEntity& tag1_entity = | 911 const sync_pb::SyncEntity& tag1_entity = |
| 912 GetLatestCommitEntityOnServer("tag1"); | 912 GetLatestCommitEntityOnServer("tag1"); |
| 913 EXPECT_TRUE(tag1_entity.specifics().has_encrypted()); | 913 EXPECT_TRUE(tag1_entity.specifics().has_encrypted()); |
| 914 EXPECT_EQ(tag1_entity.name(), "encrypted"); | 914 EXPECT_EQ(tag1_entity.name(), "encrypted"); |
| 915 EXPECT_TRUE(tag1_entity.specifics().has_preference()); | 915 EXPECT_TRUE(tag1_entity.specifics().has_preference()); |
| 916 EXPECT_FALSE(tag1_entity.specifics().preference().has_name()); | 916 EXPECT_FALSE(tag1_entity.specifics().preference().has_name()); |
| 917 EXPECT_FALSE(tag1_entity.specifics().preference().has_value()); | 917 EXPECT_FALSE(tag1_entity.specifics().preference().has_value()); |
| 918 } | 918 } |
| 919 | 919 |
| 920 // Test the receipt of decryptable entities. | 920 // Test the receipt of decryptable entities. |
| 921 TEST_F(ModelTypeSyncWorkerImplTest, ReceiveDecryptableEntities) { | 921 TEST_F(CommitQueueImplTest, ReceiveDecryptableEntities) { |
| 922 NormalInitialize(); | 922 NormalInitialize(); |
| 923 | 923 |
| 924 // Create a new Nigori and allow the cryptographer to decrypt it. | 924 // Create a new Nigori and allow the cryptographer to decrypt it. |
| 925 NewForeignEncryptionKey(); | 925 NewForeignEncryptionKey(); |
| 926 UpdateLocalCryptographer(); | 926 UpdateLocalCryptographer(); |
| 927 | 927 |
| 928 // First, receive an unencrypted entry. | 928 // First, receive an unencrypted entry. |
| 929 TriggerUpdateFromServer(10, "tag1", "value1"); | 929 TriggerUpdateFromServer(10, "tag1", "value1"); |
| 930 | 930 |
| 931 // Test some basic properties regarding the update. | 931 // Test some basic properties regarding the update. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 942 TriggerUpdateFromServer(10, "tag2", "value2"); | 942 TriggerUpdateFromServer(10, "tag2", "value2"); |
| 943 | 943 |
| 944 // Test its basic features and the value of encryption_key_name. | 944 // Test its basic features and the value of encryption_key_name. |
| 945 ASSERT_TRUE(HasUpdateResponseOnModelThread("tag2")); | 945 ASSERT_TRUE(HasUpdateResponseOnModelThread("tag2")); |
| 946 UpdateResponseData update2 = GetUpdateResponseOnModelThread("tag2"); | 946 UpdateResponseData update2 = GetUpdateResponseOnModelThread("tag2"); |
| 947 EXPECT_EQ("tag2", update2.specifics.preference().name()); | 947 EXPECT_EQ("tag2", update2.specifics.preference().name()); |
| 948 EXPECT_EQ("value2", update2.specifics.preference().value()); | 948 EXPECT_EQ("value2", update2.specifics.preference().value()); |
| 949 EXPECT_FALSE(update2.encryption_key_name.empty()); | 949 EXPECT_FALSE(update2.encryption_key_name.empty()); |
| 950 } | 950 } |
| 951 | 951 |
| 952 // Test initializing a ModelTypeSyncWorker with a cryptographer at startup. | 952 // Test initializing a CommitQueue with a cryptographer at startup. |
| 953 TEST_F(ModelTypeSyncWorkerImplTest, InitializeWithCryptographer) { | 953 TEST_F(CommitQueueImplTest, InitializeWithCryptographer) { |
| 954 // Set up some encryption state. | 954 // Set up some encryption state. |
| 955 NewForeignEncryptionKey(); | 955 NewForeignEncryptionKey(); |
| 956 UpdateLocalCryptographer(); | 956 UpdateLocalCryptographer(); |
| 957 | 957 |
| 958 // Then initialize. | 958 // Then initialize. |
| 959 NormalInitialize(); | 959 NormalInitialize(); |
| 960 | 960 |
| 961 // The worker should tell the model thread about encryption as soon as | 961 // The worker should tell the model thread about encryption as soon as |
| 962 // possible, so that it will have the chance to re-encrypt local data if | 962 // possible, so that it will have the chance to re-encrypt local data if |
| 963 // necessary. | 963 // necessary. |
| 964 ASSERT_EQ(1U, GetNumModelThreadUpdateResponses()); | 964 ASSERT_EQ(1U, GetNumModelThreadUpdateResponses()); |
| 965 EXPECT_EQ(GetLocalCryptographerKeyName(), | 965 EXPECT_EQ(GetLocalCryptographerKeyName(), |
| 966 GetNthModelThreadUpdateState(0).encryption_key_name); | 966 GetNthModelThreadUpdateState(0).encryption_key_name); |
| 967 } | 967 } |
| 968 | 968 |
| 969 // Receive updates that are initially undecryptable, then ensure they get | 969 // Receive updates that are initially undecryptable, then ensure they get |
| 970 // delivered to the model thread when decryption becomes possible. | 970 // delivered to the model thread when decryption becomes possible. |
| 971 TEST_F(ModelTypeSyncWorkerImplTest, ReceiveUndecryptableEntries) { | 971 TEST_F(CommitQueueImplTest, ReceiveUndecryptableEntries) { |
| 972 NormalInitialize(); | 972 NormalInitialize(); |
| 973 | 973 |
| 974 // Receive a new foreign encryption key that we can't decrypt. | 974 // Receive a new foreign encryption key that we can't decrypt. |
| 975 NewForeignEncryptionKey(); | 975 NewForeignEncryptionKey(); |
| 976 | 976 |
| 977 // Receive an encrypted with that new key, which we can't access. | 977 // Receive an encrypted with that new key, which we can't access. |
| 978 SetUpdateEncryptionFilter(1); | 978 SetUpdateEncryptionFilter(1); |
| 979 TriggerUpdateFromServer(10, "tag1", "value1"); | 979 TriggerUpdateFromServer(10, "tag1", "value1"); |
| 980 | 980 |
| 981 // At this point, the cryptographer does not have access to the key, so the | 981 // At this point, the cryptographer does not have access to the key, so the |
| 982 // updates will be undecryptable. They'll be transfered to the model thread | 982 // updates will be undecryptable. They'll be transfered to the model thread |
| 983 // for safe-keeping as pending updates. | 983 // for safe-keeping as pending updates. |
| 984 ASSERT_EQ(1U, GetNumModelThreadUpdateResponses()); | 984 ASSERT_EQ(1U, GetNumModelThreadUpdateResponses()); |
| 985 UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(0); | 985 UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(0); |
| 986 EXPECT_EQ(0U, updates_list.size()); | 986 EXPECT_EQ(0U, updates_list.size()); |
| 987 UpdateResponseDataList pending_updates = GetNthModelThreadPendingUpdates(0); | 987 UpdateResponseDataList pending_updates = GetNthModelThreadPendingUpdates(0); |
| 988 EXPECT_EQ(1U, pending_updates.size()); | 988 EXPECT_EQ(1U, pending_updates.size()); |
| 989 | 989 |
| 990 // The update will be delivered as soon as decryption becomes possible. | 990 // The update will be delivered as soon as decryption becomes possible. |
| 991 UpdateLocalCryptographer(); | 991 UpdateLocalCryptographer(); |
| 992 ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1")); | 992 ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1")); |
| 993 UpdateResponseData update = GetUpdateResponseOnModelThread("tag1"); | 993 UpdateResponseData update = GetUpdateResponseOnModelThread("tag1"); |
| 994 EXPECT_EQ("tag1", update.specifics.preference().name()); | 994 EXPECT_EQ("tag1", update.specifics.preference().name()); |
| 995 EXPECT_EQ("value1", update.specifics.preference().value()); | 995 EXPECT_EQ("value1", update.specifics.preference().value()); |
| 996 EXPECT_FALSE(update.encryption_key_name.empty()); | 996 EXPECT_FALSE(update.encryption_key_name.empty()); |
| 997 } | 997 } |
| 998 | 998 |
| 999 // Ensure that even encrypted updates can cause conflicts. | 999 // Ensure that even encrypted updates can cause conflicts. |
| 1000 TEST_F(ModelTypeSyncWorkerImplTest, EncryptedUpdateOverridesPendingCommit) { | 1000 TEST_F(CommitQueueImplTest, EncryptedUpdateOverridesPendingCommit) { |
| 1001 NormalInitialize(); | 1001 NormalInitialize(); |
| 1002 | 1002 |
| 1003 // Prepeare to commit an item. | 1003 // Prepeare to commit an item. |
| 1004 CommitRequest("tag1", "value1"); | 1004 CommitRequest("tag1", "value1"); |
| 1005 EXPECT_TRUE(WillCommit()); | 1005 EXPECT_TRUE(WillCommit()); |
| 1006 | 1006 |
| 1007 // Receive an encrypted update for that item. | 1007 // Receive an encrypted update for that item. |
| 1008 SetUpdateEncryptionFilter(1); | 1008 SetUpdateEncryptionFilter(1); |
| 1009 TriggerUpdateFromServer(10, "tag1", "value1"); | 1009 TriggerUpdateFromServer(10, "tag1", "value1"); |
| 1010 | 1010 |
| 1011 // The pending commit state should be cleared. | 1011 // The pending commit state should be cleared. |
| 1012 EXPECT_FALSE(WillCommit()); | 1012 EXPECT_FALSE(WillCommit()); |
| 1013 | 1013 |
| 1014 // The encrypted update will be delivered to the model thread. | 1014 // The encrypted update will be delivered to the model thread. |
| 1015 ASSERT_EQ(1U, GetNumModelThreadUpdateResponses()); | 1015 ASSERT_EQ(1U, GetNumModelThreadUpdateResponses()); |
| 1016 UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(0); | 1016 UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(0); |
| 1017 EXPECT_EQ(0U, updates_list.size()); | 1017 EXPECT_EQ(0U, updates_list.size()); |
| 1018 UpdateResponseDataList pending_updates = GetNthModelThreadPendingUpdates(0); | 1018 UpdateResponseDataList pending_updates = GetNthModelThreadPendingUpdates(0); |
| 1019 EXPECT_EQ(1U, pending_updates.size()); | 1019 EXPECT_EQ(1U, pending_updates.size()); |
| 1020 } | 1020 } |
| 1021 | 1021 |
| 1022 // Test decryption of pending updates saved across a restart. | 1022 // Test decryption of pending updates saved across a restart. |
| 1023 TEST_F(ModelTypeSyncWorkerImplTest, RestorePendingEntries) { | 1023 TEST_F(CommitQueueImplTest, RestorePendingEntries) { |
| 1024 // Create a fake pending update. | 1024 // Create a fake pending update. |
| 1025 UpdateResponseData update; | 1025 UpdateResponseData update; |
| 1026 | 1026 |
| 1027 update.client_tag_hash = GenerateTagHash("tag1"); | 1027 update.client_tag_hash = GenerateTagHash("tag1"); |
| 1028 update.id = "SomeID"; | 1028 update.id = "SomeID"; |
| 1029 update.response_version = 100; | 1029 update.response_version = 100; |
| 1030 update.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(10); | 1030 update.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(10); |
| 1031 update.mtime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(11); | 1031 update.mtime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(11); |
| 1032 update.non_unique_name = "encrypted"; | 1032 update.non_unique_name = "encrypted"; |
| 1033 update.deleted = false; | 1033 update.deleted = false; |
| 1034 | 1034 |
| 1035 update.specifics = GenerateSpecifics("tag1", "value1"); | 1035 update.specifics = GenerateSpecifics("tag1", "value1"); |
| 1036 EncryptUpdate(GetNthKeyParams(1), &(update.specifics)); | 1036 EncryptUpdate(GetNthKeyParams(1), &(update.specifics)); |
| 1037 | 1037 |
| 1038 // Inject the update during ModelTypeSyncWorker initialization. | 1038 // Inject the update during CommitQueue initialization. |
| 1039 UpdateResponseDataList saved_pending_updates; | 1039 UpdateResponseDataList saved_pending_updates; |
| 1040 saved_pending_updates.push_back(update); | 1040 saved_pending_updates.push_back(update); |
| 1041 InitializeWithPendingUpdates(saved_pending_updates); | 1041 InitializeWithPendingUpdates(saved_pending_updates); |
| 1042 | 1042 |
| 1043 // Update will be undecryptable at first. | 1043 // Update will be undecryptable at first. |
| 1044 EXPECT_EQ(0U, GetNumModelThreadUpdateResponses()); | 1044 EXPECT_EQ(0U, GetNumModelThreadUpdateResponses()); |
| 1045 ASSERT_FALSE(HasUpdateResponseOnModelThread("tag1")); | 1045 ASSERT_FALSE(HasUpdateResponseOnModelThread("tag1")); |
| 1046 | 1046 |
| 1047 // Update the cryptographer so it can decrypt that update. | 1047 // Update the cryptographer so it can decrypt that update. |
| 1048 NewForeignEncryptionKey(); | 1048 NewForeignEncryptionKey(); |
| 1049 UpdateLocalCryptographer(); | 1049 UpdateLocalCryptographer(); |
| 1050 | 1050 |
| 1051 // Verify the item gets decrypted and sent back to the model thread. | 1051 // Verify the item gets decrypted and sent back to the model thread. |
| 1052 ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1")); | 1052 ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1")); |
| 1053 } | 1053 } |
| 1054 | 1054 |
| 1055 // Test decryption of pending updates saved across a restart. This test | 1055 // Test decryption of pending updates saved across a restart. This test |
| 1056 // differs from the previous one in that the restored updates can be decrypted | 1056 // differs from the previous one in that the restored updates can be decrypted |
| 1057 // immediately after the ModelTypeSyncWorker is constructed. | 1057 // immediately after the CommitQueue is constructed. |
| 1058 TEST_F(ModelTypeSyncWorkerImplTest, RestoreApplicableEntries) { | 1058 TEST_F(CommitQueueImplTest, RestoreApplicableEntries) { |
| 1059 // Update the cryptographer so it can decrypt that update. | 1059 // Update the cryptographer so it can decrypt that update. |
| 1060 NewForeignEncryptionKey(); | 1060 NewForeignEncryptionKey(); |
| 1061 UpdateLocalCryptographer(); | 1061 UpdateLocalCryptographer(); |
| 1062 | 1062 |
| 1063 // Create a fake pending update. | 1063 // Create a fake pending update. |
| 1064 UpdateResponseData update; | 1064 UpdateResponseData update; |
| 1065 update.client_tag_hash = GenerateTagHash("tag1"); | 1065 update.client_tag_hash = GenerateTagHash("tag1"); |
| 1066 update.id = "SomeID"; | 1066 update.id = "SomeID"; |
| 1067 update.response_version = 100; | 1067 update.response_version = 100; |
| 1068 update.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(10); | 1068 update.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(10); |
| 1069 update.mtime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(11); | 1069 update.mtime = base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(11); |
| 1070 update.non_unique_name = "encrypted"; | 1070 update.non_unique_name = "encrypted"; |
| 1071 update.deleted = false; | 1071 update.deleted = false; |
| 1072 | 1072 |
| 1073 update.specifics = GenerateSpecifics("tag1", "value1"); | 1073 update.specifics = GenerateSpecifics("tag1", "value1"); |
| 1074 EncryptUpdate(GetNthKeyParams(1), &(update.specifics)); | 1074 EncryptUpdate(GetNthKeyParams(1), &(update.specifics)); |
| 1075 | 1075 |
| 1076 // Inject the update during ModelTypeSyncWorker initialization. | 1076 // Inject the update during CommitQueue initialization. |
| 1077 UpdateResponseDataList saved_pending_updates; | 1077 UpdateResponseDataList saved_pending_updates; |
| 1078 saved_pending_updates.push_back(update); | 1078 saved_pending_updates.push_back(update); |
| 1079 InitializeWithPendingUpdates(saved_pending_updates); | 1079 InitializeWithPendingUpdates(saved_pending_updates); |
| 1080 | 1080 |
| 1081 // Verify the item gets decrypted and sent back to the model thread. | 1081 // Verify the item gets decrypted and sent back to the model thread. |
| 1082 ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1")); | 1082 ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1")); |
| 1083 } | 1083 } |
| 1084 | 1084 |
| 1085 // Test that undecryptable updates provide sufficient reason to not commit. | 1085 // Test that undecryptable updates provide sufficient reason to not commit. |
| 1086 // | 1086 // |
| 1087 // This should be rare in practice. Usually the cryptographer will be in an | 1087 // This should be rare in practice. Usually the cryptographer will be in an |
| 1088 // unusable state when we receive undecryptable updates, and that alone will be | 1088 // unusable state when we receive undecryptable updates, and that alone will be |
| 1089 // enough to prevent all commits. | 1089 // enough to prevent all commits. |
| 1090 TEST_F(ModelTypeSyncWorkerImplTest, CommitBlockedByPending) { | 1090 TEST_F(CommitQueueImplTest, CommitBlockedByPending) { |
| 1091 NormalInitialize(); | 1091 NormalInitialize(); |
| 1092 | 1092 |
| 1093 // Prepeare to commit an item. | 1093 // Prepeare to commit an item. |
| 1094 CommitRequest("tag1", "value1"); | 1094 CommitRequest("tag1", "value1"); |
| 1095 EXPECT_TRUE(WillCommit()); | 1095 EXPECT_TRUE(WillCommit()); |
| 1096 | 1096 |
| 1097 // Receive an encrypted update for that item. | 1097 // Receive an encrypted update for that item. |
| 1098 SetUpdateEncryptionFilter(1); | 1098 SetUpdateEncryptionFilter(1); |
| 1099 TriggerUpdateFromServer(10, "tag1", "value1"); | 1099 TriggerUpdateFromServer(10, "tag1", "value1"); |
| 1100 | 1100 |
| 1101 // The pending commit state should be cleared. | 1101 // The pending commit state should be cleared. |
| 1102 EXPECT_FALSE(WillCommit()); | 1102 EXPECT_FALSE(WillCommit()); |
| 1103 | 1103 |
| 1104 // The pending update will be delivered to the model thread. | 1104 // The pending update will be delivered to the model thread. |
| 1105 HasUpdateResponseOnModelThread("tag1"); | 1105 HasUpdateResponseOnModelThread("tag1"); |
| 1106 | 1106 |
| 1107 // Pretend the update arrived too late to prevent another commit request. | 1107 // Pretend the update arrived too late to prevent another commit request. |
| 1108 CommitRequest("tag1", "value2"); | 1108 CommitRequest("tag1", "value2"); |
| 1109 | 1109 |
| 1110 EXPECT_FALSE(WillCommit()); | 1110 EXPECT_FALSE(WillCommit()); |
| 1111 } | 1111 } |
| 1112 | 1112 |
| 1113 // Verify that corrupted encrypted updates don't cause crashes. | 1113 // Verify that corrupted encrypted updates don't cause crashes. |
| 1114 TEST_F(ModelTypeSyncWorkerImplTest, ReceiveCorruptEncryption) { | 1114 TEST_F(CommitQueueImplTest, ReceiveCorruptEncryption) { |
| 1115 // Initialize the worker with basic encryption state. | 1115 // Initialize the worker with basic encryption state. |
| 1116 NormalInitialize(); | 1116 NormalInitialize(); |
| 1117 NewForeignEncryptionKey(); | 1117 NewForeignEncryptionKey(); |
| 1118 UpdateLocalCryptographer(); | 1118 UpdateLocalCryptographer(); |
| 1119 | 1119 |
| 1120 // Manually create an update. | 1120 // Manually create an update. |
| 1121 sync_pb::SyncEntity entity; | 1121 sync_pb::SyncEntity entity; |
| 1122 entity.set_client_defined_unique_tag(GenerateTagHash("tag1")); | 1122 entity.set_client_defined_unique_tag(GenerateTagHash("tag1")); |
| 1123 entity.set_id_string("SomeID"); | 1123 entity.set_id_string("SomeID"); |
| 1124 entity.set_version(1); | 1124 entity.set_version(1); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1143 | 1143 |
| 1144 EXPECT_FALSE(HasUpdateResponseOnModelThread("tag1")); | 1144 EXPECT_FALSE(HasUpdateResponseOnModelThread("tag1")); |
| 1145 | 1145 |
| 1146 // Deliver a non-corrupt update to see if the everything still works. | 1146 // Deliver a non-corrupt update to see if the everything still works. |
| 1147 SetUpdateEncryptionFilter(1); | 1147 SetUpdateEncryptionFilter(1); |
| 1148 TriggerUpdateFromServer(10, "tag1", "value1"); | 1148 TriggerUpdateFromServer(10, "tag1", "value1"); |
| 1149 EXPECT_TRUE(HasUpdateResponseOnModelThread("tag1")); | 1149 EXPECT_TRUE(HasUpdateResponseOnModelThread("tag1")); |
| 1150 } | 1150 } |
| 1151 | 1151 |
| 1152 } // namespace syncer | 1152 } // namespace syncer |
| OLD | NEW |