OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <cstddef> | 9 #include <cstddef> |
10 #include <map> | 10 #include <map> |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 using browser_sync::JsEventHandler; | 66 using browser_sync::JsEventHandler; |
67 using browser_sync::JsReplyHandler; | 67 using browser_sync::JsReplyHandler; |
68 using browser_sync::MockJsEventHandler; | 68 using browser_sync::MockJsEventHandler; |
69 using browser_sync::MockJsReplyHandler; | 69 using browser_sync::MockJsReplyHandler; |
70 using browser_sync::ModelSafeRoutingInfo; | 70 using browser_sync::ModelSafeRoutingInfo; |
71 using browser_sync::ModelSafeWorker; | 71 using browser_sync::ModelSafeWorker; |
72 using browser_sync::ModelSafeWorkerRegistrar; | 72 using browser_sync::ModelSafeWorkerRegistrar; |
73 using browser_sync::sessions::SyncSessionSnapshot; | 73 using browser_sync::sessions::SyncSessionSnapshot; |
74 using browser_sync::WeakHandle; | 74 using browser_sync::WeakHandle; |
75 using content::BrowserThread; | 75 using content::BrowserThread; |
| 76 using syncable::IS_DEL; |
| 77 using syncable::IS_UNSYNCED; |
76 using syncable::kEncryptedString; | 78 using syncable::kEncryptedString; |
77 using syncable::ModelTypeSet; | 79 using syncable::ModelTypeSet; |
78 using syncable::ModelType; | 80 using syncable::ModelType; |
| 81 using syncable::NON_UNIQUE_NAME; |
| 82 using syncable::SPECIFICS; |
79 using test::ExpectDictStringValue; | 83 using test::ExpectDictStringValue; |
80 using testing::_; | 84 using testing::_; |
81 using testing::AnyNumber; | 85 using testing::AnyNumber; |
82 using testing::AtLeast; | 86 using testing::AtLeast; |
83 using testing::InSequence; | 87 using testing::InSequence; |
84 using testing::Invoke; | 88 using testing::Invoke; |
85 using testing::SaveArg; | 89 using testing::SaveArg; |
86 using testing::StrictMock; | 90 using testing::StrictMock; |
87 | 91 |
88 namespace sync_api { | 92 namespace sync_api { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 entry.Put(syncable::SERVER_IS_DIR, true); | 176 entry.Put(syncable::SERVER_IS_DIR, true); |
173 entry.Put(syncable::IS_DIR, true); | 177 entry.Put(syncable::IS_DIR, true); |
174 entry.Put(syncable::SERVER_SPECIFICS, specifics); | 178 entry.Put(syncable::SERVER_SPECIFICS, specifics); |
175 entry.Put(syncable::UNIQUE_SERVER_TAG, type_tag); | 179 entry.Put(syncable::UNIQUE_SERVER_TAG, type_tag); |
176 entry.Put(syncable::NON_UNIQUE_NAME, type_tag); | 180 entry.Put(syncable::NON_UNIQUE_NAME, type_tag); |
177 entry.Put(syncable::IS_DEL, false); | 181 entry.Put(syncable::IS_DEL, false); |
178 entry.Put(syncable::SPECIFICS, specifics); | 182 entry.Put(syncable::SPECIFICS, specifics); |
179 return entry.Get(syncable::META_HANDLE); | 183 return entry.Get(syncable::META_HANDLE); |
180 } | 184 } |
181 | 185 |
| 186 // Simulates creating a "synced" node as a child of the root datatype node. |
| 187 int64 MakeServerNode(UserShare* share, ModelType model_type, |
| 188 const std::string& client_tag, |
| 189 const std::string& hashed_tag, |
| 190 const sync_pb::EntitySpecifics& specifics) { |
| 191 syncable::ScopedDirLookup dir(share->dir_manager.get(), share->name); |
| 192 EXPECT_TRUE(dir.good()); |
| 193 syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, dir); |
| 194 syncable::Entry root_entry(&trans, syncable::GET_BY_SERVER_TAG, |
| 195 syncable::ModelTypeToRootTag(model_type)); |
| 196 EXPECT_TRUE(root_entry.good()); |
| 197 syncable::Id root_id = root_entry.Get(syncable::ID); |
| 198 syncable::Id node_id = syncable::Id::CreateFromServerId(client_tag); |
| 199 syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM, |
| 200 node_id); |
| 201 EXPECT_TRUE(entry.good()); |
| 202 entry.Put(syncable::BASE_VERSION, 1); |
| 203 entry.Put(syncable::SERVER_VERSION, 1); |
| 204 entry.Put(syncable::IS_UNAPPLIED_UPDATE, false); |
| 205 entry.Put(syncable::SERVER_PARENT_ID, root_id); |
| 206 entry.Put(syncable::PARENT_ID, root_id); |
| 207 entry.Put(syncable::SERVER_IS_DIR, false); |
| 208 entry.Put(syncable::IS_DIR, false); |
| 209 entry.Put(syncable::SERVER_SPECIFICS, specifics); |
| 210 entry.Put(syncable::NON_UNIQUE_NAME, client_tag); |
| 211 entry.Put(syncable::UNIQUE_CLIENT_TAG, hashed_tag); |
| 212 entry.Put(syncable::IS_DEL, false); |
| 213 entry.Put(syncable::SPECIFICS, specifics); |
| 214 return entry.Get(syncable::META_HANDLE); |
| 215 } |
| 216 |
182 } // namespace | 217 } // namespace |
183 | 218 |
184 class SyncApiTest : public testing::Test { | 219 class SyncApiTest : public testing::Test { |
185 public: | 220 public: |
186 virtual void SetUp() { | 221 virtual void SetUp() { |
187 test_user_share_.SetUp(); | 222 test_user_share_.SetUp(); |
188 } | 223 } |
189 | 224 |
190 virtual void TearDown() { | 225 virtual void TearDown() { |
191 test_user_share_.TearDown(); | 226 test_user_share_.TearDown(); |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 MOCK_METHOD1(RemoveObserver, void(sync_notifier::SyncNotifierObserver*)); | 679 MOCK_METHOD1(RemoveObserver, void(sync_notifier::SyncNotifierObserver*)); |
645 MOCK_METHOD1(SetUniqueId, void(const std::string&)); | 680 MOCK_METHOD1(SetUniqueId, void(const std::string&)); |
646 MOCK_METHOD1(SetState, void(const std::string&)); | 681 MOCK_METHOD1(SetState, void(const std::string&)); |
647 MOCK_METHOD2(UpdateCredentials, | 682 MOCK_METHOD2(UpdateCredentials, |
648 void(const std::string&, const std::string&)); | 683 void(const std::string&, const std::string&)); |
649 MOCK_METHOD1(UpdateEnabledTypes, | 684 MOCK_METHOD1(UpdateEnabledTypes, |
650 void(syncable::ModelTypeSet)); | 685 void(syncable::ModelTypeSet)); |
651 MOCK_METHOD1(SendNotification, void(syncable::ModelTypeSet)); | 686 MOCK_METHOD1(SendNotification, void(syncable::ModelTypeSet)); |
652 }; | 687 }; |
653 | 688 |
| 689 } // namespace |
| 690 |
654 class SyncManagerTest : public testing::Test, | 691 class SyncManagerTest : public testing::Test, |
655 public ModelSafeWorkerRegistrar, | 692 public ModelSafeWorkerRegistrar, |
656 public SyncManager::ChangeDelegate { | 693 public SyncManager::ChangeDelegate { |
657 protected: | 694 protected: |
| 695 enum NigoriStatus { |
| 696 DONT_WRITE_NIGORI, |
| 697 WRITE_TO_NIGORI |
| 698 }; |
| 699 |
| 700 enum EncryptionStatus { |
| 701 DEFAULT_ENCRYPTION, |
| 702 FULL_ENCRYPTION |
| 703 }; |
| 704 |
658 SyncManagerTest() | 705 SyncManagerTest() |
659 : ui_thread_(BrowserThread::UI, &ui_loop_), | 706 : ui_thread_(BrowserThread::UI, &ui_loop_), |
660 sync_notifier_mock_(NULL), | 707 sync_notifier_mock_(NULL), |
661 sync_manager_("Test sync manager"), | 708 sync_manager_("Test sync manager"), |
662 sync_notifier_observer_(NULL), | 709 sync_notifier_observer_(NULL), |
663 update_enabled_types_call_count_(0) {} | 710 update_enabled_types_call_count_(0) {} |
664 | 711 |
665 virtual ~SyncManagerTest() { | 712 virtual ~SyncManagerTest() { |
666 EXPECT_FALSE(sync_notifier_mock_); | 713 EXPECT_FALSE(sync_notifier_mock_); |
667 } | 714 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 } | 787 } |
741 | 788 |
742 virtual void OnChangesApplied( | 789 virtual void OnChangesApplied( |
743 syncable::ModelType model_type, | 790 syncable::ModelType model_type, |
744 const BaseTransaction* trans, | 791 const BaseTransaction* trans, |
745 const ImmutableChangeRecordList& changes) OVERRIDE {} | 792 const ImmutableChangeRecordList& changes) OVERRIDE {} |
746 | 793 |
747 virtual void OnChangesComplete(syncable::ModelType model_type) OVERRIDE {} | 794 virtual void OnChangesComplete(syncable::ModelType model_type) OVERRIDE {} |
748 | 795 |
749 // Helper methods. | 796 // Helper methods. |
750 bool SetUpEncryption(bool write_to_nigori) { | 797 bool SetUpEncryption(NigoriStatus nigori_status, |
| 798 EncryptionStatus encryption_status) { |
751 // Mock the Mac Keychain service. The real Keychain can block on user input. | 799 // Mock the Mac Keychain service. The real Keychain can block on user input. |
752 #if defined(OS_MACOSX) | 800 #if defined(OS_MACOSX) |
753 Encryptor::UseMockKeychain(true); | 801 Encryptor::UseMockKeychain(true); |
754 #endif | 802 #endif |
755 | 803 |
756 UserShare* share = sync_manager_.GetUserShare(); | 804 UserShare* share = sync_manager_.GetUserShare(); |
757 { | 805 { |
758 syncable::ScopedDirLookup dir(share->dir_manager.get(), share->name); | 806 syncable::ScopedDirLookup dir(share->dir_manager.get(), share->name); |
759 if (!dir.good()) | 807 if (!dir.good()) |
760 return false; | 808 return false; |
761 dir->set_initial_sync_ended_for_type(syncable::NIGORI, true); | 809 dir->set_initial_sync_ended_for_type(syncable::NIGORI, true); |
762 } | 810 } |
763 | 811 |
764 // We need to create the nigori node as if it were an applied server update. | 812 // We need to create the nigori node as if it were an applied server update. |
765 int64 nigori_id = GetIdForDataType(syncable::NIGORI); | 813 int64 nigori_id = GetIdForDataType(syncable::NIGORI); |
766 if (nigori_id == kInvalidId) | 814 if (nigori_id == kInvalidId) |
767 return false; | 815 return false; |
768 | 816 |
769 // Set the nigori cryptographer information. | 817 // Set the nigori cryptographer information. |
770 WriteTransaction trans(FROM_HERE, share); | 818 WriteTransaction trans(FROM_HERE, share); |
771 Cryptographer* cryptographer = trans.GetCryptographer(); | 819 Cryptographer* cryptographer = trans.GetCryptographer(); |
772 if (!cryptographer) | 820 if (!cryptographer) |
773 return false; | 821 return false; |
774 KeyParams params = {"localhost", "dummy", "foobar"}; | 822 KeyParams params = {"localhost", "dummy", "foobar"}; |
775 cryptographer->AddKey(params); | 823 cryptographer->AddKey(params); |
776 if (write_to_nigori) { | 824 if (encryption_status == FULL_ENCRYPTION) |
| 825 cryptographer->set_encrypt_everything(); |
| 826 if (nigori_status == WRITE_TO_NIGORI) { |
777 sync_pb::NigoriSpecifics nigori; | 827 sync_pb::NigoriSpecifics nigori; |
778 cryptographer->GetKeys(nigori.mutable_encrypted()); | 828 cryptographer->GetKeys(nigori.mutable_encrypted()); |
| 829 cryptographer->UpdateNigoriFromEncryptedTypes(&nigori); |
779 WriteNode node(&trans); | 830 WriteNode node(&trans); |
780 EXPECT_TRUE(node.InitByIdLookup(nigori_id)); | 831 EXPECT_TRUE(node.InitByIdLookup(nigori_id)); |
781 node.SetNigoriSpecifics(nigori); | 832 node.SetNigoriSpecifics(nigori); |
782 } | 833 } |
783 return cryptographer->is_ready(); | 834 return cryptographer->is_ready(); |
784 } | 835 } |
785 | 836 |
786 int64 GetIdForDataType(ModelType type) { | 837 int64 GetIdForDataType(ModelType type) { |
787 if (type_roots_.count(type) == 0) | 838 if (type_roots_.count(type) == 0) |
788 return 0; | 839 return 0; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 name, args, reply_handler); | 871 name, args, reply_handler); |
821 PumpLoop(); | 872 PumpLoop(); |
822 } | 873 } |
823 | 874 |
824 void SetJsEventHandler(const WeakHandle<JsEventHandler>& event_handler) { | 875 void SetJsEventHandler(const WeakHandle<JsEventHandler>& event_handler) { |
825 js_backend_.Call(FROM_HERE, &JsBackend::SetJsEventHandler, | 876 js_backend_.Call(FROM_HERE, &JsBackend::SetJsEventHandler, |
826 event_handler); | 877 event_handler); |
827 PumpLoop(); | 878 PumpLoop(); |
828 } | 879 } |
829 | 880 |
| 881 // Looks up an entry by client tag and resets IS_UNSYNCED value to false. |
| 882 // Returns true if entry was previously unsynced, false if IS_UNSYNCED was |
| 883 // already false. |
| 884 bool ResetUnsyncedEntry(syncable::ModelType type, |
| 885 const std::string& client_tag) { |
| 886 UserShare* share = sync_manager_.GetUserShare(); |
| 887 syncable::ScopedDirLookup dir(share->dir_manager.get(), share->name); |
| 888 EXPECT_TRUE(dir.good()); |
| 889 syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, dir); |
| 890 const std::string hash = BaseNode::GenerateSyncableHash(type, client_tag); |
| 891 syncable::MutableEntry entry(&trans, syncable::GET_BY_CLIENT_TAG, |
| 892 hash); |
| 893 EXPECT_TRUE(entry.good()); |
| 894 if (!entry.Get(IS_UNSYNCED)) |
| 895 return false; |
| 896 entry.Put(IS_UNSYNCED, false); |
| 897 return true; |
| 898 } |
| 899 |
830 private: | 900 private: |
831 // Needed by |ui_thread_|. | 901 // Needed by |ui_thread_|. |
832 MessageLoopForUI ui_loop_; | 902 MessageLoopForUI ui_loop_; |
833 // Needed by |sync_manager_|. | 903 // Needed by |sync_manager_|. |
834 content::TestBrowserThread ui_thread_; | 904 content::TestBrowserThread ui_thread_; |
835 // Needed by |sync_manager_|. | 905 // Needed by |sync_manager_|. |
836 ScopedTempDir temp_dir_; | 906 ScopedTempDir temp_dir_; |
837 // Sync Id's for the roots of the enabled datatypes. | 907 // Sync Id's for the roots of the enabled datatypes. |
838 std::map<ModelType, int64> type_roots_; | 908 std::map<ModelType, int64> type_roots_; |
839 StrictMock<SyncNotifierMock>* sync_notifier_mock_; | 909 StrictMock<SyncNotifierMock>* sync_notifier_mock_; |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1188 SetJsEventHandler(WeakHandle<JsEventHandler>()); | 1258 SetJsEventHandler(WeakHandle<JsEventHandler>()); |
1189 | 1259 |
1190 sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types); | 1260 sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types); |
1191 sync_manager_.TriggerOnIncomingNotificationForTest(model_types); | 1261 sync_manager_.TriggerOnIncomingNotificationForTest(model_types); |
1192 | 1262 |
1193 // Should trigger the replies. | 1263 // Should trigger the replies. |
1194 PumpLoop(); | 1264 PumpLoop(); |
1195 } | 1265 } |
1196 | 1266 |
1197 TEST_F(SyncManagerTest, RefreshEncryptionReady) { | 1267 TEST_F(SyncManagerTest, RefreshEncryptionReady) { |
1198 EXPECT_TRUE(SetUpEncryption(true)); | 1268 EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); |
1199 EXPECT_CALL(observer_, OnEncryptionComplete()); | 1269 EXPECT_CALL(observer_, OnEncryptionComplete()); |
1200 sync_manager_.RefreshEncryption(); | 1270 sync_manager_.RefreshEncryption(); |
1201 const syncable::ModelTypeSet encrypted_types = | 1271 const syncable::ModelTypeSet encrypted_types = |
1202 sync_manager_.GetEncryptedDataTypesForTest(); | 1272 sync_manager_.GetEncryptedDataTypesForTest(); |
1203 EXPECT_TRUE(encrypted_types.Has(syncable::PASSWORDS)); | 1273 EXPECT_TRUE(encrypted_types.Has(syncable::PASSWORDS)); |
1204 EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); | 1274 EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); |
1205 { | 1275 { |
1206 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); | 1276 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
1207 ReadNode node(&trans); | 1277 ReadNode node(&trans); |
1208 EXPECT_TRUE(node.InitByIdLookup(GetIdForDataType(syncable::NIGORI))); | 1278 EXPECT_TRUE(node.InitByIdLookup(GetIdForDataType(syncable::NIGORI))); |
(...skipping 10 matching lines...) Expand all Loading... |
1219 // Don't set up encryption (no nigori node created). | 1289 // Don't set up encryption (no nigori node created). |
1220 sync_manager_.RefreshEncryption(); // Should fail. | 1290 sync_manager_.RefreshEncryption(); // Should fail. |
1221 const syncable::ModelTypeSet encrypted_types = | 1291 const syncable::ModelTypeSet encrypted_types = |
1222 sync_manager_.GetEncryptedDataTypesForTest(); | 1292 sync_manager_.GetEncryptedDataTypesForTest(); |
1223 EXPECT_TRUE(encrypted_types.Has(syncable::PASSWORDS)); // Hardcoded. | 1293 EXPECT_TRUE(encrypted_types.Has(syncable::PASSWORDS)); // Hardcoded. |
1224 EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); | 1294 EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); |
1225 } | 1295 } |
1226 | 1296 |
1227 // Attempt to refresh encryption when nigori is empty. | 1297 // Attempt to refresh encryption when nigori is empty. |
1228 TEST_F(SyncManagerTest, RefreshEncryptionEmptyNigori) { | 1298 TEST_F(SyncManagerTest, RefreshEncryptionEmptyNigori) { |
1229 EXPECT_TRUE(SetUpEncryption(false)); | 1299 EXPECT_TRUE(SetUpEncryption(DONT_WRITE_NIGORI, DEFAULT_ENCRYPTION)); |
1230 EXPECT_CALL(observer_, OnEncryptionComplete()); | 1300 EXPECT_CALL(observer_, OnEncryptionComplete()); |
1231 sync_manager_.RefreshEncryption(); // Should write to nigori. | 1301 sync_manager_.RefreshEncryption(); // Should write to nigori. |
1232 const syncable::ModelTypeSet encrypted_types = | 1302 const syncable::ModelTypeSet encrypted_types = |
1233 sync_manager_.GetEncryptedDataTypesForTest(); | 1303 sync_manager_.GetEncryptedDataTypesForTest(); |
1234 EXPECT_TRUE(encrypted_types.Has(syncable::PASSWORDS)); // Hardcoded. | 1304 EXPECT_TRUE(encrypted_types.Has(syncable::PASSWORDS)); // Hardcoded. |
1235 EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); | 1305 EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); |
1236 { | 1306 { |
1237 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); | 1307 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
1238 ReadNode node(&trans); | 1308 ReadNode node(&trans); |
1239 EXPECT_TRUE(node.InitByIdLookup(GetIdForDataType(syncable::NIGORI))); | 1309 EXPECT_TRUE(node.InitByIdLookup(GetIdForDataType(syncable::NIGORI))); |
1240 sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics(); | 1310 sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics(); |
1241 EXPECT_TRUE(nigori.has_encrypted()); | 1311 EXPECT_TRUE(nigori.has_encrypted()); |
1242 Cryptographer* cryptographer = trans.GetCryptographer(); | 1312 Cryptographer* cryptographer = trans.GetCryptographer(); |
1243 EXPECT_TRUE(cryptographer->is_ready()); | 1313 EXPECT_TRUE(cryptographer->is_ready()); |
1244 EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encrypted())); | 1314 EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encrypted())); |
1245 } | 1315 } |
1246 } | 1316 } |
1247 | 1317 |
1248 TEST_F(SyncManagerTest, EncryptDataTypesWithNoData) { | 1318 TEST_F(SyncManagerTest, EncryptDataTypesWithNoData) { |
1249 EXPECT_TRUE(SetUpEncryption(true)); | 1319 EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); |
1250 EXPECT_CALL(observer_, | 1320 EXPECT_CALL(observer_, |
1251 OnEncryptedTypesChanged( | 1321 OnEncryptedTypesChanged( |
1252 HasModelTypes(syncable::ModelTypeSet::All()), true)); | 1322 HasModelTypes(syncable::ModelTypeSet::All()), true)); |
1253 EXPECT_CALL(observer_, OnEncryptionComplete()); | 1323 EXPECT_CALL(observer_, OnEncryptionComplete()); |
1254 sync_manager_.EnableEncryptEverything(); | 1324 sync_manager_.EnableEncryptEverything(); |
1255 EXPECT_TRUE(sync_manager_.EncryptEverythingEnabledForTest()); | 1325 EXPECT_TRUE(sync_manager_.EncryptEverythingEnabledForTest()); |
1256 } | 1326 } |
1257 | 1327 |
1258 TEST_F(SyncManagerTest, EncryptDataTypesWithData) { | 1328 TEST_F(SyncManagerTest, EncryptDataTypesWithData) { |
1259 size_t batch_size = 5; | 1329 size_t batch_size = 5; |
1260 EXPECT_TRUE(SetUpEncryption(true)); | 1330 EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); |
1261 | 1331 |
1262 // Create some unencrypted unsynced data. | 1332 // Create some unencrypted unsynced data. |
1263 int64 folder = MakeFolderWithParent(sync_manager_.GetUserShare(), | 1333 int64 folder = MakeFolderWithParent(sync_manager_.GetUserShare(), |
1264 syncable::BOOKMARKS, | 1334 syncable::BOOKMARKS, |
1265 GetIdForDataType(syncable::BOOKMARKS), | 1335 GetIdForDataType(syncable::BOOKMARKS), |
1266 NULL); | 1336 NULL); |
1267 // First batch_size nodes are children of folder. | 1337 // First batch_size nodes are children of folder. |
1268 size_t i; | 1338 size_t i; |
1269 for (i = 0; i < batch_size; ++i) { | 1339 for (i = 0; i < batch_size; ++i) { |
1270 MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::BOOKMARKS, | 1340 MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::BOOKMARKS, |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1360 // Calling EncryptDataTypes with an empty encrypted types should not trigger | 1430 // Calling EncryptDataTypes with an empty encrypted types should not trigger |
1361 // a reencryption and should just notify immediately. | 1431 // a reencryption and should just notify immediately. |
1362 // TODO(zea): add logic to ensure nothing was written. | 1432 // TODO(zea): add logic to ensure nothing was written. |
1363 testing::Mock::VerifyAndClearExpectations(&observer_); | 1433 testing::Mock::VerifyAndClearExpectations(&observer_); |
1364 EXPECT_CALL(observer_, OnPassphraseAccepted(_)).Times(0); | 1434 EXPECT_CALL(observer_, OnPassphraseAccepted(_)).Times(0); |
1365 EXPECT_CALL(observer_, OnEncryptionComplete()); | 1435 EXPECT_CALL(observer_, OnEncryptionComplete()); |
1366 sync_manager_.EnableEncryptEverything(); | 1436 sync_manager_.EnableEncryptEverything(); |
1367 } | 1437 } |
1368 | 1438 |
1369 TEST_F(SyncManagerTest, SetPassphraseWithPassword) { | 1439 TEST_F(SyncManagerTest, SetPassphraseWithPassword) { |
1370 EXPECT_TRUE(SetUpEncryption(true)); | 1440 EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); |
1371 { | 1441 { |
1372 WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); | 1442 WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
1373 ReadNode root_node(&trans); | 1443 ReadNode root_node(&trans); |
1374 root_node.InitByRootLookup(); | 1444 root_node.InitByRootLookup(); |
1375 | 1445 |
1376 WriteNode password_node(&trans); | 1446 WriteNode password_node(&trans); |
1377 EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS, | 1447 EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS, |
1378 root_node, "foo")); | 1448 root_node, "foo")); |
1379 sync_pb::PasswordSpecificsData data; | 1449 sync_pb::PasswordSpecificsData data; |
1380 data.set_password_value("secret"); | 1450 data.set_password_value("secret"); |
1381 password_node.SetPasswordSpecifics(data); | 1451 password_node.SetPasswordSpecifics(data); |
1382 } | 1452 } |
1383 EXPECT_CALL(observer_, OnPassphraseAccepted(_)); | 1453 EXPECT_CALL(observer_, OnPassphraseAccepted(_)); |
1384 EXPECT_CALL(observer_, OnEncryptionComplete()); | 1454 EXPECT_CALL(observer_, OnEncryptionComplete()); |
1385 sync_manager_.SetPassphrase("new_passphrase", true); | 1455 sync_manager_.SetPassphrase("new_passphrase", true); |
1386 EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); | 1456 EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); |
1387 { | 1457 { |
1388 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); | 1458 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
1389 ReadNode password_node(&trans); | 1459 ReadNode password_node(&trans); |
1390 EXPECT_TRUE(password_node.InitByClientTagLookup(syncable::PASSWORDS, | 1460 EXPECT_TRUE(password_node.InitByClientTagLookup(syncable::PASSWORDS, |
1391 "foo")); | 1461 "foo")); |
1392 const sync_pb::PasswordSpecificsData& data = | 1462 const sync_pb::PasswordSpecificsData& data = |
1393 password_node.GetPasswordSpecifics(); | 1463 password_node.GetPasswordSpecifics(); |
1394 EXPECT_EQ("secret", data.password_value()); | 1464 EXPECT_EQ("secret", data.password_value()); |
1395 } | 1465 } |
1396 } | 1466 } |
1397 | 1467 |
1398 TEST_F(SyncManagerTest, SetPassphraseWithEmptyPasswordNode) { | 1468 TEST_F(SyncManagerTest, SetPassphraseWithEmptyPasswordNode) { |
1399 EXPECT_TRUE(SetUpEncryption(true)); | 1469 EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); |
1400 int64 node_id = 0; | 1470 int64 node_id = 0; |
1401 std::string tag = "foo"; | 1471 std::string tag = "foo"; |
1402 { | 1472 { |
1403 WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); | 1473 WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
1404 ReadNode root_node(&trans); | 1474 ReadNode root_node(&trans); |
1405 root_node.InitByRootLookup(); | 1475 root_node.InitByRootLookup(); |
1406 | 1476 |
1407 WriteNode password_node(&trans); | 1477 WriteNode password_node(&trans); |
1408 EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS, | 1478 EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS, |
1409 root_node, tag)); | 1479 root_node, tag)); |
1410 node_id = password_node.GetId(); | 1480 node_id = password_node.GetId(); |
1411 } | 1481 } |
1412 EXPECT_CALL(observer_, OnPassphraseAccepted(_)); | 1482 EXPECT_CALL(observer_, OnPassphraseAccepted(_)); |
1413 EXPECT_CALL(observer_, OnEncryptionComplete()); | 1483 EXPECT_CALL(observer_, OnEncryptionComplete()); |
1414 sync_manager_.SetPassphrase("new_passphrase", true); | 1484 sync_manager_.SetPassphrase("new_passphrase", true); |
1415 EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); | 1485 EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); |
1416 { | 1486 { |
1417 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); | 1487 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
1418 ReadNode password_node(&trans); | 1488 ReadNode password_node(&trans); |
1419 EXPECT_FALSE(password_node.InitByClientTagLookup(syncable::PASSWORDS, | 1489 EXPECT_FALSE(password_node.InitByClientTagLookup(syncable::PASSWORDS, |
1420 tag)); | 1490 tag)); |
1421 } | 1491 } |
1422 { | 1492 { |
1423 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); | 1493 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
1424 ReadNode password_node(&trans); | 1494 ReadNode password_node(&trans); |
1425 EXPECT_FALSE(password_node.InitByIdLookup(node_id)); | 1495 EXPECT_FALSE(password_node.InitByIdLookup(node_id)); |
1426 } | 1496 } |
1427 } | 1497 } |
1428 | 1498 |
1429 } // namespace | |
1430 | |
1431 // Friended by WriteNode, so can't be in an anonymouse namespace. | 1499 // Friended by WriteNode, so can't be in an anonymouse namespace. |
1432 TEST_F(SyncManagerTest, EncryptBookmarksWithLegacyData) { | 1500 TEST_F(SyncManagerTest, EncryptBookmarksWithLegacyData) { |
1433 EXPECT_TRUE(SetUpEncryption(true)); | 1501 EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); |
1434 std::string title; | 1502 std::string title; |
1435 SyncAPINameToServerName("Google", &title); | 1503 SyncAPINameToServerName("Google", &title); |
1436 std::string url = "http://www.google.com"; | 1504 std::string url = "http://www.google.com"; |
1437 std::string raw_title2 = ".."; // An invalid cosmo title. | 1505 std::string raw_title2 = ".."; // An invalid cosmo title. |
1438 std::string title2; | 1506 std::string title2; |
1439 SyncAPINameToServerName(raw_title2, &title2); | 1507 SyncAPINameToServerName(raw_title2, &title2); |
1440 std::string url2 = "http://www.bla.com"; | 1508 std::string url2 = "http://www.bla.com"; |
1441 | 1509 |
1442 // Create a bookmark using the legacy format. | 1510 // Create a bookmark using the legacy format. |
1443 int64 node_id1 = MakeNode(sync_manager_.GetUserShare(), | 1511 int64 node_id1 = MakeNode(sync_manager_.GetUserShare(), |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1527 EXPECT_TRUE(node2.InitByIdLookup(node_id2)); | 1595 EXPECT_TRUE(node2.InitByIdLookup(node_id2)); |
1528 EXPECT_EQ(syncable::BOOKMARKS, node2.GetModelType()); | 1596 EXPECT_EQ(syncable::BOOKMARKS, node2.GetModelType()); |
1529 // We should de-canonicalize the title in GetTitle(), but the title in the | 1597 // We should de-canonicalize the title in GetTitle(), but the title in the |
1530 // specifics should be stored in the server legal form. | 1598 // specifics should be stored in the server legal form. |
1531 EXPECT_EQ(raw_title2, node2.GetTitle()); | 1599 EXPECT_EQ(raw_title2, node2.GetTitle()); |
1532 EXPECT_EQ(title2, node2.GetBookmarkSpecifics().title()); | 1600 EXPECT_EQ(title2, node2.GetBookmarkSpecifics().title()); |
1533 EXPECT_EQ(url2, node2.GetBookmarkSpecifics().url()); | 1601 EXPECT_EQ(url2, node2.GetBookmarkSpecifics().url()); |
1534 } | 1602 } |
1535 } | 1603 } |
1536 | 1604 |
| 1605 // Verifies WriteNode::UpdateEntryWithEncryption does not make unnecessary |
| 1606 // changes. |
| 1607 TEST_F(SyncManagerTest, UpdateEntryWithEncryption) { |
| 1608 std::string client_tag = "title"; |
| 1609 sync_pb::EntitySpecifics entity_specifics; |
| 1610 entity_specifics.MutableExtension(sync_pb::bookmark)->set_url("url"); |
| 1611 entity_specifics.MutableExtension(sync_pb::bookmark)->set_title("title"); |
| 1612 MakeServerNode(sync_manager_.GetUserShare(), syncable::BOOKMARKS, client_tag, |
| 1613 BaseNode::GenerateSyncableHash(syncable::BOOKMARKS, |
| 1614 client_tag), |
| 1615 entity_specifics); |
| 1616 // New node shouldn't start off unsynced. |
| 1617 EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); |
| 1618 // Manually change to the same data. Should not set is_unsynced. |
| 1619 { |
| 1620 WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
| 1621 WriteNode node(&trans); |
| 1622 EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); |
| 1623 node.SetEntitySpecifics(entity_specifics); |
| 1624 } |
| 1625 EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); |
| 1626 |
| 1627 // Encrypt the datatatype, should set is_unsynced. |
| 1628 EXPECT_CALL(observer_, |
| 1629 OnEncryptedTypesChanged( |
| 1630 HasModelTypes(syncable::ModelEnumSet::All()), true)); |
| 1631 EXPECT_CALL(observer_, OnEncryptionComplete()); |
| 1632 EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, FULL_ENCRYPTION)); |
| 1633 sync_manager_.RefreshEncryption(); |
| 1634 { |
| 1635 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
| 1636 ReadNode node(&trans); |
| 1637 EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); |
| 1638 const syncable::Entry* node_entry = node.GetEntry(); |
| 1639 const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); |
| 1640 EXPECT_TRUE(specifics.has_encrypted()); |
| 1641 EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); |
| 1642 Cryptographer* cryptographer = trans.GetCryptographer(); |
| 1643 EXPECT_TRUE(cryptographer->is_ready()); |
| 1644 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( |
| 1645 specifics.encrypted())); |
| 1646 } |
| 1647 EXPECT_TRUE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); |
| 1648 |
| 1649 // Set a new passphrase. Should set is_unsynced. |
| 1650 testing::Mock::VerifyAndClearExpectations(&observer_); |
| 1651 EXPECT_CALL(observer_, OnPassphraseAccepted(_)); |
| 1652 EXPECT_CALL(observer_, OnEncryptionComplete()); |
| 1653 sync_manager_.SetPassphrase("new_passphrase", true); |
| 1654 { |
| 1655 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
| 1656 ReadNode node(&trans); |
| 1657 EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); |
| 1658 const syncable::Entry* node_entry = node.GetEntry(); |
| 1659 const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); |
| 1660 EXPECT_TRUE(specifics.has_encrypted()); |
| 1661 EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); |
| 1662 Cryptographer* cryptographer = trans.GetCryptographer(); |
| 1663 EXPECT_TRUE(cryptographer->is_ready()); |
| 1664 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( |
| 1665 specifics.encrypted())); |
| 1666 } |
| 1667 EXPECT_TRUE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); |
| 1668 |
| 1669 // Force a re-encrypt everything. Should not set is_unsynced. |
| 1670 testing::Mock::VerifyAndClearExpectations(&observer_); |
| 1671 EXPECT_CALL(observer_, OnEncryptionComplete()); |
| 1672 sync_manager_.RefreshEncryption(); |
| 1673 { |
| 1674 ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
| 1675 ReadNode node(&trans); |
| 1676 EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); |
| 1677 const syncable::Entry* node_entry = node.GetEntry(); |
| 1678 const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); |
| 1679 EXPECT_TRUE(specifics.has_encrypted()); |
| 1680 EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); |
| 1681 Cryptographer* cryptographer = trans.GetCryptographer(); |
| 1682 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( |
| 1683 specifics.encrypted())); |
| 1684 } |
| 1685 EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); |
| 1686 |
| 1687 // Manually change to the same data. Should not set is_unsynced. |
| 1688 { |
| 1689 WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
| 1690 WriteNode node(&trans); |
| 1691 EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); |
| 1692 node.SetEntitySpecifics(entity_specifics); |
| 1693 const syncable::Entry* node_entry = node.GetEntry(); |
| 1694 const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); |
| 1695 EXPECT_TRUE(specifics.has_encrypted()); |
| 1696 EXPECT_FALSE(node_entry->Get(IS_UNSYNCED)); |
| 1697 EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); |
| 1698 Cryptographer* cryptographer = trans.GetCryptographer(); |
| 1699 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( |
| 1700 specifics.encrypted())); |
| 1701 } |
| 1702 EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); |
| 1703 |
| 1704 // Manually change to different data. Should set is_unsynced. |
| 1705 { |
| 1706 entity_specifics.MutableExtension(sync_pb::bookmark)->set_url("url2"); |
| 1707 entity_specifics.MutableExtension(sync_pb::bookmark)->set_title("title2"); |
| 1708 WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); |
| 1709 WriteNode node(&trans); |
| 1710 EXPECT_TRUE(node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); |
| 1711 node.SetEntitySpecifics(entity_specifics); |
| 1712 const syncable::Entry* node_entry = node.GetEntry(); |
| 1713 const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); |
| 1714 EXPECT_TRUE(specifics.has_encrypted()); |
| 1715 EXPECT_TRUE(node_entry->Get(IS_UNSYNCED)); |
| 1716 EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); |
| 1717 Cryptographer* cryptographer = trans.GetCryptographer(); |
| 1718 EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( |
| 1719 specifics.encrypted())); |
| 1720 } |
| 1721 } |
| 1722 |
1537 } // namespace browser_sync | 1723 } // namespace browser_sync |
OLD | NEW |