| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // Unit tests for the SyncApi. Note that a lot of the underlying | 5 // Unit tests for the SyncApi. Note that a lot of the underlying |
| 6 // functionality is provided by the Syncable layer, which has its own | 6 // functionality is provided by the Syncable layer, which has its own |
| 7 // unit tests. We'll test SyncApi specific things in this harness. | 7 // unit tests. We'll test SyncApi specific things in this harness. |
| 8 | 8 |
| 9 #include <map> |
| 10 |
| 9 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 10 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 11 #include "base/scoped_ptr.h" | 13 #include "base/scoped_ptr.h" |
| 12 #include "base/scoped_temp_dir.h" | 14 #include "base/scoped_temp_dir.h" |
| 13 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
| 16 #include "base/string_util.h" |
| 14 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
| 15 #include "base/values.h" | 18 #include "base/values.h" |
| 16 #include "chrome/browser/browser_thread.h" | 19 #include "chrome/browser/browser_thread.h" |
| 20 #include "chrome/browser/sync/engine/model_safe_worker.h" |
| 17 #include "chrome/browser/sync/engine/syncapi.h" | 21 #include "chrome/browser/sync/engine/syncapi.h" |
| 18 #include "chrome/browser/sync/js_arg_list.h" | 22 #include "chrome/browser/sync/js_arg_list.h" |
| 19 #include "chrome/browser/sync/js_backend.h" | 23 #include "chrome/browser/sync/js_backend.h" |
| 20 #include "chrome/browser/sync/js_event_handler.h" | 24 #include "chrome/browser/sync/js_event_handler.h" |
| 21 #include "chrome/browser/sync/js_event_router.h" | 25 #include "chrome/browser/sync/js_event_router.h" |
| 22 #include "chrome/browser/sync/js_test_util.h" | 26 #include "chrome/browser/sync/js_test_util.h" |
| 23 #include "chrome/browser/sync/protocol/password_specifics.pb.h" | 27 #include "chrome/browser/sync/protocol/password_specifics.pb.h" |
| 24 #include "chrome/browser/sync/protocol/proto_value_conversions.h" | 28 #include "chrome/browser/sync/protocol/proto_value_conversions.h" |
| 29 #include "chrome/browser/sync/sessions/sync_session.h" |
| 25 #include "chrome/browser/sync/syncable/directory_manager.h" | 30 #include "chrome/browser/sync/syncable/directory_manager.h" |
| 31 #include "chrome/browser/sync/syncable/nigori_util.h" |
| 26 #include "chrome/browser/sync/syncable/syncable.h" | 32 #include "chrome/browser/sync/syncable/syncable.h" |
| 33 #include "chrome/browser/sync/syncable/syncable_id.h" |
| 34 #include "chrome/browser/sync/util/cryptographer.h" |
| 27 #include "chrome/test/sync/engine/test_directory_setter_upper.h" | 35 #include "chrome/test/sync/engine/test_directory_setter_upper.h" |
| 28 #include "chrome/test/values_test_util.h" | 36 #include "chrome/test/values_test_util.h" |
| 29 #include "jingle/notifier/base/notifier_options.h" | 37 #include "jingle/notifier/base/notifier_options.h" |
| 30 #include "testing/gmock/include/gmock/gmock.h" | 38 #include "testing/gmock/include/gmock/gmock.h" |
| 31 #include "testing/gtest/include/gtest/gtest.h" | 39 #include "testing/gtest/include/gtest/gtest.h" |
| 32 | 40 |
| 41 using browser_sync::Cryptographer; |
| 33 using browser_sync::HasArgsAsList; | 42 using browser_sync::HasArgsAsList; |
| 34 using browser_sync::KeyParams; | 43 using browser_sync::KeyParams; |
| 35 using browser_sync::JsArgList; | 44 using browser_sync::JsArgList; |
| 36 using browser_sync::MockJsEventHandler; | 45 using browser_sync::MockJsEventHandler; |
| 37 using browser_sync::MockJsEventRouter; | 46 using browser_sync::MockJsEventRouter; |
| 47 using browser_sync::ModelSafeRoutingInfo; |
| 48 using browser_sync::ModelSafeWorker; |
| 49 using browser_sync::ModelSafeWorkerRegistrar; |
| 50 using browser_sync::sessions::SyncSessionSnapshot; |
| 51 using syncable::ModelType; |
| 52 using syncable::ModelTypeSet; |
| 38 using test::ExpectDictionaryValue; | 53 using test::ExpectDictionaryValue; |
| 39 using test::ExpectStringValue; | 54 using test::ExpectStringValue; |
| 40 using testing::_; | 55 using testing::_; |
| 41 using testing::Invoke; | 56 using testing::Invoke; |
| 42 using testing::SaveArg; | 57 using testing::SaveArg; |
| 43 using testing::StrictMock; | 58 using testing::StrictMock; |
| 44 | 59 |
| 45 namespace sync_api { | 60 namespace sync_api { |
| 46 | 61 |
| 47 namespace { | 62 namespace { |
| 48 | 63 |
| 49 void ExpectInt64Value(int64 expected_value, | 64 void ExpectInt64Value(int64 expected_value, |
| 50 const DictionaryValue& value, const std::string& key) { | 65 const DictionaryValue& value, const std::string& key) { |
| 51 std::string int64_str; | 66 std::string int64_str; |
| 52 EXPECT_TRUE(value.GetString(key, &int64_str)); | 67 EXPECT_TRUE(value.GetString(key, &int64_str)); |
| 53 int64 val = 0; | 68 int64 val = 0; |
| 54 EXPECT_TRUE(base::StringToInt64(int64_str, &val)); | 69 EXPECT_TRUE(base::StringToInt64(int64_str, &val)); |
| 55 EXPECT_EQ(expected_value, val); | 70 EXPECT_EQ(expected_value, val); |
| 56 } | 71 } |
| 57 | 72 |
| 58 // Makes a non-folder child of the root node. Returns the id of the | 73 // Makes a non-folder child of the root node. Returns the id of the |
| 59 // newly-created node. | 74 // newly-created node. |
| 60 int64 MakeNode(UserShare* share, | 75 int64 MakeNode(UserShare* share, |
| 61 syncable::ModelType model_type, | 76 ModelType model_type, |
| 62 const std::string& client_tag) { | 77 const std::string& client_tag) { |
| 63 WriteTransaction trans(share); | 78 WriteTransaction trans(share); |
| 64 ReadNode root_node(&trans); | 79 ReadNode root_node(&trans); |
| 65 root_node.InitByRootLookup(); | 80 root_node.InitByRootLookup(); |
| 66 WriteNode node(&trans); | 81 WriteNode node(&trans); |
| 67 EXPECT_TRUE(node.InitUniqueByCreation(model_type, root_node, client_tag)); | 82 EXPECT_TRUE(node.InitUniqueByCreation(model_type, root_node, client_tag)); |
| 68 node.SetIsFolder(false); | 83 node.SetIsFolder(false); |
| 69 return node.GetId(); | 84 return node.GetId(); |
| 70 } | 85 } |
| 71 | 86 |
| 87 // Make a folder as a child of the root node. Returns the id of the |
| 88 // newly-created node. |
| 89 int64 MakeFolder(UserShare* share, |
| 90 syncable::ModelType model_type, |
| 91 const std::string& client_tag) { |
| 92 WriteTransaction trans(share); |
| 93 ReadNode root_node(&trans); |
| 94 root_node.InitByRootLookup(); |
| 95 WriteNode node(&trans); |
| 96 EXPECT_TRUE(node.InitUniqueByCreation(model_type, root_node, client_tag)); |
| 97 node.SetIsFolder(true); |
| 98 return node.GetId(); |
| 99 } |
| 100 |
| 101 // Makes a non-folder child of a non-root node. Returns the id of the |
| 102 // newly-created node. |
| 103 int64 MakeNodeWithParent(UserShare* share, |
| 104 ModelType model_type, |
| 105 const std::string& client_tag, |
| 106 int64 parent_id) { |
| 107 WriteTransaction trans(share); |
| 108 ReadNode parent_node(&trans); |
| 109 parent_node.InitByIdLookup(parent_id); |
| 110 WriteNode node(&trans); |
| 111 EXPECT_TRUE(node.InitUniqueByCreation(model_type, parent_node, client_tag)); |
| 112 node.SetIsFolder(false); |
| 113 return node.GetId(); |
| 114 } |
| 115 |
| 116 // Makes a folder child of a non-root node. Returns the id of the |
| 117 // newly-created node. |
| 118 int64 MakeFolderWithParent(UserShare* share, |
| 119 ModelType model_type, |
| 120 int64 parent_id, |
| 121 BaseNode* predecessor) { |
| 122 WriteTransaction trans(share); |
| 123 ReadNode parent_node(&trans); |
| 124 parent_node.InitByIdLookup(parent_id); |
| 125 WriteNode node(&trans); |
| 126 EXPECT_TRUE(node.InitByCreation(model_type, parent_node, predecessor)); |
| 127 node.SetIsFolder(true); |
| 128 return node.GetId(); |
| 129 } |
| 130 |
| 131 // Creates the "synced" root node for a particular datatype. We use the syncable |
| 132 // methods here so that the syncer treats these nodes as if they were already |
| 133 // received from the server. |
| 134 int64 MakeServerNodeForType(UserShare* share, |
| 135 ModelType model_type) { |
| 136 sync_pb::EntitySpecifics specifics; |
| 137 syncable::AddDefaultExtensionValue(model_type, &specifics); |
| 138 syncable::ScopedDirLookup dir(share->dir_manager.get(), share->name); |
| 139 EXPECT_TRUE(dir.good()); |
| 140 syncable::WriteTransaction trans(dir, syncable::UNITTEST, __FILE__, __LINE__); |
| 141 // Attempt to lookup by nigori tag. |
| 142 std::string type_tag = syncable::ModelTypeToRootTag(model_type); |
| 143 syncable::Id node_id = syncable::Id::CreateFromServerId(type_tag); |
| 144 syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM, |
| 145 node_id); |
| 146 EXPECT_TRUE(entry.good()); |
| 147 entry.Put(syncable::BASE_VERSION, 1); |
| 148 entry.Put(syncable::SERVER_VERSION, 1); |
| 149 entry.Put(syncable::IS_UNAPPLIED_UPDATE, false); |
| 150 entry.Put(syncable::SERVER_PARENT_ID, syncable::kNullId); |
| 151 entry.Put(syncable::SERVER_IS_DIR, false); |
| 152 entry.Put(syncable::SERVER_SPECIFICS, specifics); |
| 153 entry.Put(syncable::UNIQUE_SERVER_TAG, type_tag); |
| 154 entry.Put(syncable::NON_UNIQUE_NAME, type_tag); |
| 155 entry.Put(syncable::IS_DEL, false); |
| 156 entry.Put(syncable::SPECIFICS, specifics); |
| 157 return entry.Get(syncable::META_HANDLE); |
| 158 } |
| 159 |
| 72 } // namespace | 160 } // namespace |
| 73 | 161 |
| 74 class SyncApiTest : public testing::Test { | 162 class SyncApiTest : public testing::Test { |
| 75 public: | 163 public: |
| 76 virtual void SetUp() { | 164 virtual void SetUp() { |
| 77 setter_upper_.SetUp(); | 165 setter_upper_.SetUp(); |
| 78 share_.dir_manager.reset(setter_upper_.manager()); | 166 share_.dir_manager.reset(setter_upper_.manager()); |
| 79 share_.name = setter_upper_.name(); | 167 share_.name = setter_upper_.name(); |
| 80 } | 168 } |
| 81 | 169 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 WriteTransaction trans(&share_); | 279 WriteTransaction trans(&share_); |
| 192 WriteNode node(&trans); | 280 WriteNode node(&trans); |
| 193 EXPECT_FALSE(node.InitByClientTagLookup(syncable::BOOKMARKS, | 281 EXPECT_FALSE(node.InitByClientTagLookup(syncable::BOOKMARKS, |
| 194 "testtag")); | 282 "testtag")); |
| 195 } | 283 } |
| 196 } | 284 } |
| 197 | 285 |
| 198 // TODO(chron): Hook this all up to the server and write full integration tests | 286 // TODO(chron): Hook this all up to the server and write full integration tests |
| 199 // for update->undelete behavior. | 287 // for update->undelete behavior. |
| 200 TEST_F(SyncApiTest, TestDeleteBehavior) { | 288 TEST_F(SyncApiTest, TestDeleteBehavior) { |
| 201 | |
| 202 int64 node_id; | 289 int64 node_id; |
| 203 int64 folder_id; | 290 int64 folder_id; |
| 204 std::wstring test_title(L"test1"); | 291 std::wstring test_title(L"test1"); |
| 205 | 292 |
| 206 { | 293 { |
| 207 WriteTransaction trans(&share_); | 294 WriteTransaction trans(&share_); |
| 208 ReadNode root_node(&trans); | 295 ReadNode root_node(&trans); |
| 209 root_node.InitByRootLookup(); | 296 root_node.InitByRootLookup(); |
| 210 | 297 |
| 211 // we'll use this spare folder later | 298 // we'll use this spare folder later |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 ExpectInt64Value(node.GetId(), value, "id"); | 396 ExpectInt64Value(node.GetId(), value, "id"); |
| 310 ExpectInt64Value(node.GetModificationTime(), value, "modificationTime"); | 397 ExpectInt64Value(node.GetModificationTime(), value, "modificationTime"); |
| 311 ExpectInt64Value(node.GetParentId(), value, "parentId"); | 398 ExpectInt64Value(node.GetParentId(), value, "parentId"); |
| 312 { | 399 { |
| 313 bool is_folder = false; | 400 bool is_folder = false; |
| 314 EXPECT_TRUE(value.GetBoolean("isFolder", &is_folder)); | 401 EXPECT_TRUE(value.GetBoolean("isFolder", &is_folder)); |
| 315 EXPECT_EQ(node.GetIsFolder(), is_folder); | 402 EXPECT_EQ(node.GetIsFolder(), is_folder); |
| 316 } | 403 } |
| 317 ExpectStringValue(WideToUTF8(node.GetTitle()), value, "title"); | 404 ExpectStringValue(WideToUTF8(node.GetTitle()), value, "title"); |
| 318 { | 405 { |
| 319 syncable::ModelType expected_model_type = node.GetModelType(); | 406 ModelType expected_model_type = node.GetModelType(); |
| 320 std::string type_str; | 407 std::string type_str; |
| 321 EXPECT_TRUE(value.GetString("type", &type_str)); | 408 EXPECT_TRUE(value.GetString("type", &type_str)); |
| 322 if (expected_model_type >= syncable::FIRST_REAL_MODEL_TYPE) { | 409 if (expected_model_type >= syncable::FIRST_REAL_MODEL_TYPE) { |
| 323 syncable::ModelType model_type = | 410 ModelType model_type = |
| 324 syncable::ModelTypeFromString(type_str); | 411 syncable::ModelTypeFromString(type_str); |
| 325 EXPECT_EQ(expected_model_type, model_type); | 412 EXPECT_EQ(expected_model_type, model_type); |
| 326 } else if (expected_model_type == syncable::TOP_LEVEL_FOLDER) { | 413 } else if (expected_model_type == syncable::TOP_LEVEL_FOLDER) { |
| 327 EXPECT_EQ("Top-level folder", type_str); | 414 EXPECT_EQ("Top-level folder", type_str); |
| 328 } else if (expected_model_type == syncable::UNSPECIFIED) { | 415 } else if (expected_model_type == syncable::UNSPECIFIED) { |
| 329 EXPECT_EQ("Unspecified", type_str); | 416 EXPECT_EQ("Unspecified", type_str); |
| 330 } else { | 417 } else { |
| 331 ADD_FAILURE(); | 418 ADD_FAILURE(); |
| 332 } | 419 } |
| 333 } | 420 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 if (record.extra.get()) { | 500 if (record.extra.get()) { |
| 414 expected_extra_value.reset(record.extra->ToValue()); | 501 expected_extra_value.reset(record.extra->ToValue()); |
| 415 } | 502 } |
| 416 Value* extra_value = NULL; | 503 Value* extra_value = NULL; |
| 417 EXPECT_EQ(record.extra.get() != NULL, | 504 EXPECT_EQ(record.extra.get() != NULL, |
| 418 node_value->Get("extra", &extra_value)); | 505 node_value->Get("extra", &extra_value)); |
| 419 EXPECT_TRUE(Value::Equals(extra_value, expected_extra_value.get())); | 506 EXPECT_TRUE(Value::Equals(extra_value, expected_extra_value.get())); |
| 420 } | 507 } |
| 421 } | 508 } |
| 422 | 509 |
| 423 class MockExtraChangeRecordData : public SyncManager::ExtraChangeRecordData { | 510 class MockExtraChangeRecordData |
| 511 : public SyncManager::ExtraPasswordChangeRecordData { |
| 424 public: | 512 public: |
| 425 MOCK_CONST_METHOD0(ToValue, DictionaryValue*()); | 513 MOCK_CONST_METHOD0(ToValue, DictionaryValue*()); |
| 426 }; | 514 }; |
| 427 | 515 |
| 428 } // namespace | 516 } // namespace |
| 429 | 517 |
| 430 TEST_F(SyncApiTest, ChangeRecordToValue) { | 518 TEST_F(SyncApiTest, ChangeRecordToValue) { |
| 431 int64 child_id = MakeNode(&share_, syncable::BOOKMARKS, "testtag"); | 519 int64 child_id = MakeNode(&share_, syncable::BOOKMARKS, "testtag"); |
| 432 sync_pb::EntitySpecifics child_specifics; | 520 sync_pb::EntitySpecifics child_specifics; |
| 433 { | 521 { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 virtual ~TestHttpPostProviderFactory() {} | 588 virtual ~TestHttpPostProviderFactory() {} |
| 501 virtual HttpPostProviderInterface* Create() { | 589 virtual HttpPostProviderInterface* Create() { |
| 502 NOTREACHED(); | 590 NOTREACHED(); |
| 503 return NULL; | 591 return NULL; |
| 504 } | 592 } |
| 505 virtual void Destroy(HttpPostProviderInterface* http) { | 593 virtual void Destroy(HttpPostProviderInterface* http) { |
| 506 NOTREACHED(); | 594 NOTREACHED(); |
| 507 } | 595 } |
| 508 }; | 596 }; |
| 509 | 597 |
| 510 class SyncManagerTest : public testing::Test { | 598 class SyncManagerObserverMock : public SyncManager::Observer { |
| 599 public: |
| 600 MOCK_METHOD4(OnChangesApplied, |
| 601 void(ModelType, |
| 602 const BaseTransaction*, |
| 603 const SyncManager::ChangeRecord*, |
| 604 int)); // NOLINT |
| 605 MOCK_METHOD1(OnChangesComplete, void(ModelType)); // NOLINT |
| 606 MOCK_METHOD1(OnSyncCycleCompleted, |
| 607 void(const SyncSessionSnapshot*)); // NOLINT |
| 608 MOCK_METHOD0(OnInitializationComplete, void()); // NOLINT |
| 609 MOCK_METHOD1(OnAuthError, void(const GoogleServiceAuthError&)); // NOLINT |
| 610 MOCK_METHOD1(OnPassphraseRequired, void(bool)); // NOLINT |
| 611 MOCK_METHOD1(OnPassphraseAccepted, void(const std::string&)); // NOLINT |
| 612 MOCK_METHOD0(OnPaused, void()); // NOLINT |
| 613 MOCK_METHOD0(OnResumed, void()); // NOLINT |
| 614 MOCK_METHOD0(OnStopSyncingPermanently, void()); // NOLINT |
| 615 MOCK_METHOD1(OnUpdatedToken, void(const std::string&)); // NOLINT |
| 616 MOCK_METHOD0(OnClearServerDataFailed, void()); // NOLINT |
| 617 MOCK_METHOD0(OnClearServerDataSucceeded, void()); // NOLINT |
| 618 MOCK_METHOD1(OnEncryptionComplete, void(const ModelTypeSet&)); // NOLINT |
| 619 }; |
| 620 |
| 621 class SyncManagerTest : public testing::Test, |
| 622 public ModelSafeWorkerRegistrar { |
| 511 protected: | 623 protected: |
| 512 SyncManagerTest() : ui_thread_(BrowserThread::UI, &ui_loop_) {} | 624 SyncManagerTest() : ui_thread_(BrowserThread::UI, &ui_loop_) {} |
| 513 | 625 |
| 626 // Test implementation. |
| 514 void SetUp() { | 627 void SetUp() { |
| 515 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 628 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 516 sync_manager_.Init(temp_dir_.path(), "bogus", 0, false, | 629 sync_manager_.Init(temp_dir_.path(), "bogus", 0, false, |
| 517 new TestHttpPostProviderFactory(), NULL, "bogus", | 630 new TestHttpPostProviderFactory(), this, "bogus", |
| 518 SyncCredentials(), notifier::NotifierOptions(), | 631 SyncCredentials(), notifier::NotifierOptions(), |
| 519 "", true /* setup_for_test_mode */); | 632 "", true /* setup_for_test_mode */); |
| 633 sync_manager_.AddObserver(&observer_); |
| 634 ModelSafeRoutingInfo routes; |
| 635 GetModelSafeRoutingInfo(&routes); |
| 636 for (ModelSafeRoutingInfo::iterator i = routes.begin(); i != routes.end(); |
| 637 ++i) { |
| 638 EXPECT_CALL(observer_, OnChangesApplied(i->first, _, _, 1)) |
| 639 .RetiresOnSaturation(); |
| 640 EXPECT_CALL(observer_, OnChangesComplete(i->first)) |
| 641 .RetiresOnSaturation(); |
| 642 type_roots_[i->first] = MakeServerNodeForType( |
| 643 sync_manager_.GetUserShare(), i->first); |
| 644 } |
| 520 } | 645 } |
| 521 | 646 |
| 522 void TearDown() { | 647 void TearDown() { |
| 648 sync_manager_.RemoveObserver(&observer_); |
| 523 sync_manager_.Shutdown(); | 649 sync_manager_.Shutdown(); |
| 524 } | 650 } |
| 525 | 651 |
| 652 // ModelSafeWorkerRegistrar implementation. |
| 653 virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) { |
| 654 NOTIMPLEMENTED(); |
| 655 out->clear(); |
| 656 } |
| 657 virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) { |
| 658 (*out)[syncable::NIGORI] = browser_sync::GROUP_PASSIVE; |
| 659 (*out)[syncable::BOOKMARKS] = browser_sync::GROUP_PASSIVE; |
| 660 (*out)[syncable::THEMES] = browser_sync::GROUP_PASSIVE; |
| 661 (*out)[syncable::SESSIONS] = browser_sync::GROUP_PASSIVE; |
| 662 } |
| 663 |
| 664 // Helper methods. |
| 665 bool SetUpEncryption() { |
| 666 // We need to create the nigori node as if it were an applied server update. |
| 667 UserShare* share = sync_manager_.GetUserShare(); |
| 668 int64 nigori_id = GetIdForDataType(syncable::NIGORI); |
| 669 if (nigori_id == kInvalidId) |
| 670 return false; |
| 671 |
| 672 // Set the nigori cryptographer information. |
| 673 Cryptographer* cryptographer = share->dir_manager->cryptographer(); |
| 674 if (!cryptographer) |
| 675 return false; |
| 676 KeyParams params = {"localhost", "dummy", "foobar"}; |
| 677 cryptographer->AddKey(params); |
| 678 sync_pb::NigoriSpecifics nigori; |
| 679 cryptographer->GetKeys(nigori.mutable_encrypted()); |
| 680 WriteTransaction trans(share); |
| 681 WriteNode node(&trans); |
| 682 node.InitByIdLookup(nigori_id); |
| 683 node.SetNigoriSpecifics(nigori); |
| 684 return cryptographer->is_ready(); |
| 685 } |
| 686 |
| 687 int64 GetIdForDataType(ModelType type) { |
| 688 if (type_roots_.count(type) == 0) |
| 689 return 0; |
| 690 return type_roots_[type]; |
| 691 } |
| 692 |
| 526 private: | 693 private: |
| 527 // Needed by |ui_thread_|. | 694 // Needed by |ui_thread_|. |
| 528 MessageLoopForUI ui_loop_; | 695 MessageLoopForUI ui_loop_; |
| 529 // Needed by |sync_manager_|. | 696 // Needed by |sync_manager_|. |
| 530 BrowserThread ui_thread_; | 697 BrowserThread ui_thread_; |
| 531 // Needed by |sync_manager_|. | 698 // Needed by |sync_manager_|. |
| 532 ScopedTempDir temp_dir_; | 699 ScopedTempDir temp_dir_; |
| 700 // Sync Id's for the roots of the enabled datatypes. |
| 701 std::map<ModelType, int64> type_roots_; |
| 533 | 702 |
| 534 protected: | 703 protected: |
| 535 SyncManager sync_manager_; | 704 SyncManager sync_manager_; |
| 705 StrictMock<SyncManagerObserverMock> observer_; |
| 536 }; | 706 }; |
| 537 | 707 |
| 538 TEST_F(SyncManagerTest, ParentJsEventRouter) { | 708 TEST_F(SyncManagerTest, ParentJsEventRouter) { |
| 539 StrictMock<MockJsEventRouter> event_router; | 709 StrictMock<MockJsEventRouter> event_router; |
| 540 browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend(); | 710 browser_sync::JsBackend* js_backend = sync_manager_.GetJsBackend(); |
| 541 EXPECT_EQ(NULL, js_backend->GetParentJsEventRouter()); | 711 EXPECT_EQ(NULL, js_backend->GetParentJsEventRouter()); |
| 542 js_backend->SetParentJsEventRouter(&event_router); | 712 js_backend->SetParentJsEventRouter(&event_router); |
| 543 EXPECT_EQ(&event_router, js_backend->GetParentJsEventRouter()); | 713 EXPECT_EQ(&event_router, js_backend->GetParentJsEventRouter()); |
| 544 js_backend->RemoveParentJsEventRouter(); | 714 js_backend->RemoveParentJsEventRouter(); |
| 545 EXPECT_EQ(NULL, js_backend->GetParentJsEventRouter()); | 715 EXPECT_EQ(NULL, js_backend->GetParentJsEventRouter()); |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 sync_manager_.TriggerOnIncomingNotificationForTest(model_types); | 966 sync_manager_.TriggerOnIncomingNotificationForTest(model_types); |
| 797 | 967 |
| 798 js_backend->SetParentJsEventRouter(&event_router); | 968 js_backend->SetParentJsEventRouter(&event_router); |
| 799 sync_manager_.TriggerOnIncomingNotificationForTest(model_types); | 969 sync_manager_.TriggerOnIncomingNotificationForTest(model_types); |
| 800 js_backend->RemoveParentJsEventRouter(); | 970 js_backend->RemoveParentJsEventRouter(); |
| 801 | 971 |
| 802 sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types); | 972 sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types); |
| 803 sync_manager_.TriggerOnIncomingNotificationForTest(model_types); | 973 sync_manager_.TriggerOnIncomingNotificationForTest(model_types); |
| 804 } | 974 } |
| 805 | 975 |
| 976 TEST_F(SyncManagerTest, EncryptDataTypesWithNoData) { |
| 977 EXPECT_TRUE(SetUpEncryption()); |
| 978 ModelTypeSet encrypted_types; |
| 979 encrypted_types.insert(syncable::BOOKMARKS); |
| 980 EXPECT_CALL(observer_, OnEncryptionComplete(encrypted_types)); |
| 981 sync_manager_.EncryptDataTypes(encrypted_types); |
| 982 { |
| 983 ReadTransaction trans(sync_manager_.GetUserShare()); |
| 984 EXPECT_EQ(encrypted_types, |
| 985 GetEncryptedDataTypesFromSyncer(trans.GetWrappedTrans())); |
| 986 } |
| 987 } |
| 988 |
| 989 TEST_F(SyncManagerTest, EncryptDataTypesWithData) { |
| 990 size_t batch_size = 5; |
| 991 EXPECT_TRUE(SetUpEncryption()); |
| 992 |
| 993 // Create some unencrypted unsynced data. |
| 994 int64 folder = MakeFolderWithParent(sync_manager_.GetUserShare(), |
| 995 syncable::BOOKMARKS, |
| 996 GetIdForDataType(syncable::BOOKMARKS), |
| 997 NULL); |
| 998 // First batch_size nodes are children of folder. |
| 999 size_t i; |
| 1000 for (i = 0; i < batch_size; ++i) { |
| 1001 MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::BOOKMARKS, |
| 1002 StringPrintf("%zu", i), folder); |
| 1003 } |
| 1004 // Next batch_size nodes are a different type and on their own. |
| 1005 for (; i < 2*batch_size; ++i) { |
| 1006 MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::SESSIONS, |
| 1007 StringPrintf("%zu", i), |
| 1008 GetIdForDataType(syncable::SESSIONS)); |
| 1009 } |
| 1010 // Last batch_size nodes are a third type that will not need encryption. |
| 1011 for (; i < 3*batch_size; ++i) { |
| 1012 MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::THEMES, |
| 1013 StringPrintf("%zu", i), |
| 1014 GetIdForDataType(syncable::THEMES)); |
| 1015 } |
| 1016 |
| 1017 { |
| 1018 ReadTransaction trans(sync_manager_.GetUserShare()); |
| 1019 EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(), |
| 1020 syncable::BOOKMARKS, |
| 1021 false /* not encrypted */)); |
| 1022 EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(), |
| 1023 syncable::SESSIONS, |
| 1024 false /* not encrypted */)); |
| 1025 EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(), |
| 1026 syncable::THEMES, |
| 1027 false /* not encrypted */)); |
| 1028 } |
| 1029 |
| 1030 ModelTypeSet encrypted_types; |
| 1031 encrypted_types.insert(syncable::BOOKMARKS); |
| 1032 encrypted_types.insert(syncable::SESSIONS); |
| 1033 EXPECT_CALL(observer_, OnEncryptionComplete(encrypted_types)); |
| 1034 sync_manager_.EncryptDataTypes(encrypted_types); |
| 1035 |
| 1036 { |
| 1037 ReadTransaction trans(sync_manager_.GetUserShare()); |
| 1038 EXPECT_EQ(encrypted_types, |
| 1039 GetEncryptedDataTypesFromSyncer(trans.GetWrappedTrans())); |
| 1040 EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(), |
| 1041 syncable::BOOKMARKS, |
| 1042 true /* is encrypted */)); |
| 1043 EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(), |
| 1044 syncable::SESSIONS, |
| 1045 true /* is encrypted */)); |
| 1046 EXPECT_TRUE(syncable::VerifyDataTypeEncryption(trans.GetWrappedTrans(), |
| 1047 syncable::THEMES, |
| 1048 false /* not encrypted */)); |
| 1049 } |
| 1050 } |
| 1051 |
| 806 } // namespace | 1052 } // namespace |
| 807 | 1053 |
| 808 } // namespace browser_sync | 1054 } // namespace browser_sync |
| OLD | NEW |