| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <string> | 5 #include <string> |
| 6 | 6 |
| 7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 using sessions::SyncSession; | 32 using sessions::SyncSession; |
| 33 using std::string; | 33 using std::string; |
| 34 using syncable::Id; | 34 using syncable::Id; |
| 35 using syncable::MutableEntry; | 35 using syncable::MutableEntry; |
| 36 using syncable::UNITTEST; | 36 using syncable::UNITTEST; |
| 37 using syncable::WriteTransaction; | 37 using syncable::WriteTransaction; |
| 38 | 38 |
| 39 namespace { | 39 namespace { |
| 40 sync_pb::EntitySpecifics DefaultBookmarkSpecifics() { | 40 sync_pb::EntitySpecifics DefaultBookmarkSpecifics() { |
| 41 sync_pb::EntitySpecifics result; | 41 sync_pb::EntitySpecifics result; |
| 42 AddDefaultFieldValue(syncable::BOOKMARKS, &result); | 42 AddDefaultFieldValue(syncer::BOOKMARKS, &result); |
| 43 return result; | 43 return result; |
| 44 } | 44 } |
| 45 } // namespace | 45 } // namespace |
| 46 | 46 |
| 47 // A test fixture for tests exercising ApplyUpdatesCommand. | 47 // A test fixture for tests exercising ApplyUpdatesCommand. |
| 48 class ApplyUpdatesCommandTest : public SyncerCommandTest { | 48 class ApplyUpdatesCommandTest : public SyncerCommandTest { |
| 49 public: | 49 public: |
| 50 protected: | 50 protected: |
| 51 ApplyUpdatesCommandTest() {} | 51 ApplyUpdatesCommandTest() {} |
| 52 virtual ~ApplyUpdatesCommandTest() {} | 52 virtual ~ApplyUpdatesCommandTest() {} |
| 53 | 53 |
| 54 virtual void SetUp() { | 54 virtual void SetUp() { |
| 55 workers()->clear(); | 55 workers()->clear(); |
| 56 mutable_routing_info()->clear(); | 56 mutable_routing_info()->clear(); |
| 57 workers()->push_back( | 57 workers()->push_back( |
| 58 make_scoped_refptr(new FakeModelWorker(GROUP_UI))); | 58 make_scoped_refptr(new FakeModelWorker(GROUP_UI))); |
| 59 workers()->push_back( | 59 workers()->push_back( |
| 60 make_scoped_refptr(new FakeModelWorker(GROUP_PASSWORD))); | 60 make_scoped_refptr(new FakeModelWorker(GROUP_PASSWORD))); |
| 61 (*mutable_routing_info())[syncable::BOOKMARKS] = GROUP_UI; | 61 (*mutable_routing_info())[syncer::BOOKMARKS] = GROUP_UI; |
| 62 (*mutable_routing_info())[syncable::PASSWORDS] = GROUP_PASSWORD; | 62 (*mutable_routing_info())[syncer::PASSWORDS] = GROUP_PASSWORD; |
| 63 (*mutable_routing_info())[syncable::NIGORI] = GROUP_PASSIVE; | 63 (*mutable_routing_info())[syncer::NIGORI] = GROUP_PASSIVE; |
| 64 SyncerCommandTest::SetUp(); | 64 SyncerCommandTest::SetUp(); |
| 65 entry_factory_.reset(new TestEntryFactory(directory())); | 65 entry_factory_.reset(new TestEntryFactory(directory())); |
| 66 ExpectNoGroupsToChange(apply_updates_command_); | 66 ExpectNoGroupsToChange(apply_updates_command_); |
| 67 } | 67 } |
| 68 | 68 |
| 69 ApplyUpdatesCommand apply_updates_command_; | 69 ApplyUpdatesCommand apply_updates_command_; |
| 70 FakeEncryptor encryptor_; | 70 FakeEncryptor encryptor_; |
| 71 TestIdFactory id_factory_; | 71 TestIdFactory id_factory_; |
| 72 scoped_ptr<TestEntryFactory> entry_factory_; | 72 scoped_ptr<TestEntryFactory> entry_factory_; |
| 73 private: | 73 private: |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 << "Simple update shouldn't result in conflicts, even if out-of-order"; | 131 << "Simple update shouldn't result in conflicts, even if out-of-order"; |
| 132 EXPECT_EQ(5, status->update_progress()->SuccessfullyAppliedUpdateCount()) | 132 EXPECT_EQ(5, status->update_progress()->SuccessfullyAppliedUpdateCount()) |
| 133 << "All updates should have been successfully applied"; | 133 << "All updates should have been successfully applied"; |
| 134 } | 134 } |
| 135 | 135 |
| 136 // Runs the ApplyUpdatesCommand on an item that has both local and remote | 136 // Runs the ApplyUpdatesCommand on an item that has both local and remote |
| 137 // modifications (IS_UNSYNCED and IS_UNAPPLIED_UPDATE). We expect the command | 137 // modifications (IS_UNSYNCED and IS_UNAPPLIED_UPDATE). We expect the command |
| 138 // to detect that this update can't be applied because it is in a CONFLICT | 138 // to detect that this update can't be applied because it is in a CONFLICT |
| 139 // state. | 139 // state. |
| 140 TEST_F(ApplyUpdatesCommandTest, SimpleConflict) { | 140 TEST_F(ApplyUpdatesCommandTest, SimpleConflict) { |
| 141 entry_factory_->CreateUnappliedAndUnsyncedItem( | 141 entry_factory_->CreateUnappliedAndUnsyncedItem("item", syncer::BOOKMARKS); |
| 142 "item", syncable::BOOKMARKS); | |
| 143 | 142 |
| 144 ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 143 ExpectGroupToChange(apply_updates_command_, GROUP_UI); |
| 145 apply_updates_command_.ExecuteImpl(session()); | 144 apply_updates_command_.ExecuteImpl(session()); |
| 146 | 145 |
| 147 sessions::StatusController* status = session()->mutable_status_controller(); | 146 sessions::StatusController* status = session()->mutable_status_controller(); |
| 148 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); | 147 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); |
| 149 ASSERT_TRUE(status->conflict_progress()); | 148 ASSERT_TRUE(status->conflict_progress()); |
| 150 EXPECT_EQ(1, status->conflict_progress()->SimpleConflictingItemsSize()) | 149 EXPECT_EQ(1, status->conflict_progress()->SimpleConflictingItemsSize()) |
| 151 << "Unsynced and unapplied item should be a simple conflict"; | 150 << "Unsynced and unapplied item should be a simple conflict"; |
| 152 } | 151 } |
| 153 | 152 |
| 154 // Runs the ApplyUpdatesCommand on an item that has both local and remote | 153 // Runs the ApplyUpdatesCommand on an item that has both local and remote |
| 155 // modifications *and* the remote modification cannot be applied without | 154 // modifications *and* the remote modification cannot be applied without |
| 156 // violating the tree constraints. We expect the command to detect that this | 155 // violating the tree constraints. We expect the command to detect that this |
| 157 // update can't be applied and that this situation can't be resolved with the | 156 // update can't be applied and that this situation can't be resolved with the |
| 158 // simple conflict processing logic; it is in a CONFLICT_HIERARCHY state. | 157 // simple conflict processing logic; it is in a CONFLICT_HIERARCHY state. |
| 159 TEST_F(ApplyUpdatesCommandTest, HierarchyAndSimpleConflict) { | 158 TEST_F(ApplyUpdatesCommandTest, HierarchyAndSimpleConflict) { |
| 160 // Create a simply-conflicting item. It will start with valid parent ids. | 159 // Create a simply-conflicting item. It will start with valid parent ids. |
| 161 int64 handle = entry_factory_->CreateUnappliedAndUnsyncedItem( | 160 int64 handle = entry_factory_->CreateUnappliedAndUnsyncedItem( |
| 162 "orphaned_by_server", syncable::BOOKMARKS); | 161 "orphaned_by_server", syncer::BOOKMARKS); |
| 163 { | 162 { |
| 164 // Manually set the SERVER_PARENT_ID to bad value. | 163 // Manually set the SERVER_PARENT_ID to bad value. |
| 165 // A bad parent indicates a hierarchy conflict. | 164 // A bad parent indicates a hierarchy conflict. |
| 166 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 165 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
| 167 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); | 166 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); |
| 168 ASSERT_TRUE(entry.good()); | 167 ASSERT_TRUE(entry.good()); |
| 169 | 168 |
| 170 entry.Put(syncable::SERVER_PARENT_ID, | 169 entry.Put(syncable::SERVER_PARENT_ID, |
| 171 id_factory_.MakeServer("bogus_parent")); | 170 id_factory_.MakeServer("bogus_parent")); |
| 172 } | 171 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 190 // Runs the ApplyUpdatesCommand on an item with remote modifications that would | 189 // Runs the ApplyUpdatesCommand on an item with remote modifications that would |
| 191 // create a directory loop if the update were applied. We expect the command to | 190 // create a directory loop if the update were applied. We expect the command to |
| 192 // detect that this update can't be applied because it is in a | 191 // detect that this update can't be applied because it is in a |
| 193 // CONFLICT_HIERARCHY state. | 192 // CONFLICT_HIERARCHY state. |
| 194 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDirectoryLoop) { | 193 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDirectoryLoop) { |
| 195 // Item 'X' locally has parent of 'root'. Server is updating it to have | 194 // Item 'X' locally has parent of 'root'. Server is updating it to have |
| 196 // parent of 'Y'. | 195 // parent of 'Y'. |
| 197 { | 196 { |
| 198 // Create it as a child of root node. | 197 // Create it as a child of root node. |
| 199 int64 handle = entry_factory_->CreateSyncedItem( | 198 int64 handle = entry_factory_->CreateSyncedItem( |
| 200 "X", syncable::BOOKMARKS, true); | 199 "X", syncer::BOOKMARKS, true); |
| 201 | 200 |
| 202 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 201 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
| 203 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); | 202 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); |
| 204 ASSERT_TRUE(entry.good()); | 203 ASSERT_TRUE(entry.good()); |
| 205 | 204 |
| 206 // Re-parent from root to "Y" | 205 // Re-parent from root to "Y" |
| 207 entry.Put(syncable::SERVER_VERSION, entry_factory_->GetNextRevision()); | 206 entry.Put(syncable::SERVER_VERSION, entry_factory_->GetNextRevision()); |
| 208 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); | 207 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); |
| 209 entry.Put(syncable::SERVER_PARENT_ID, id_factory_.MakeServer("Y")); | 208 entry.Put(syncable::SERVER_PARENT_ID, id_factory_.MakeServer("Y")); |
| 210 } | 209 } |
| 211 | 210 |
| 212 // Item 'Y' is child of 'X'. | 211 // Item 'Y' is child of 'X'. |
| 213 entry_factory_->CreateUnsyncedItem( | 212 entry_factory_->CreateUnsyncedItem( |
| 214 id_factory_.MakeServer("Y"), id_factory_.MakeServer("X"), "Y", true, | 213 id_factory_.MakeServer("Y"), id_factory_.MakeServer("X"), "Y", true, |
| 215 syncable::BOOKMARKS, NULL); | 214 syncer::BOOKMARKS, NULL); |
| 216 | 215 |
| 217 // If the server's update were applied, we would have X be a child of Y, and Y | 216 // If the server's update were applied, we would have X be a child of Y, and Y |
| 218 // as a child of X. That's a directory loop. The UpdateApplicator should | 217 // as a child of X. That's a directory loop. The UpdateApplicator should |
| 219 // prevent the update from being applied and note that this is a hierarchy | 218 // prevent the update from being applied and note that this is a hierarchy |
| 220 // conflict. | 219 // conflict. |
| 221 | 220 |
| 222 ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 221 ExpectGroupToChange(apply_updates_command_, GROUP_UI); |
| 223 apply_updates_command_.ExecuteImpl(session()); | 222 apply_updates_command_.ExecuteImpl(session()); |
| 224 | 223 |
| 225 sessions::StatusController* status = session()->mutable_status_controller(); | 224 sessions::StatusController* status = session()->mutable_status_controller(); |
| 226 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); | 225 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); |
| 227 | 226 |
| 228 EXPECT_EQ(1, status->update_progress()->AppliedUpdatesSize()); | 227 EXPECT_EQ(1, status->update_progress()->AppliedUpdatesSize()); |
| 229 | 228 |
| 230 // This should count as a hierarchy conflict. | 229 // This should count as a hierarchy conflict. |
| 231 ASSERT_TRUE(status->conflict_progress()); | 230 ASSERT_TRUE(status->conflict_progress()); |
| 232 EXPECT_EQ(1, status->conflict_progress()->HierarchyConflictingItemsSize()); | 231 EXPECT_EQ(1, status->conflict_progress()->HierarchyConflictingItemsSize()); |
| 233 EXPECT_EQ(0, status->conflict_progress()->SimpleConflictingItemsSize()); | 232 EXPECT_EQ(0, status->conflict_progress()->SimpleConflictingItemsSize()); |
| 234 } | 233 } |
| 235 | 234 |
| 236 // Runs the ApplyUpdatesCommand on a directory where the server sent us an | 235 // Runs the ApplyUpdatesCommand on a directory where the server sent us an |
| 237 // update to add a child to a locally deleted (and unsynced) parent. We expect | 236 // update to add a child to a locally deleted (and unsynced) parent. We expect |
| 238 // the command to not apply the update and to indicate the update is in a | 237 // the command to not apply the update and to indicate the update is in a |
| 239 // CONFLICT_HIERARCHY state. | 238 // CONFLICT_HIERARCHY state. |
| 240 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDeletedParent) { | 239 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDeletedParent) { |
| 241 // Create a locally deleted parent item. | 240 // Create a locally deleted parent item. |
| 242 int64 parent_handle; | 241 int64 parent_handle; |
| 243 entry_factory_->CreateUnsyncedItem( | 242 entry_factory_->CreateUnsyncedItem( |
| 244 Id::CreateFromServerId("parent"), id_factory_.root(), | 243 Id::CreateFromServerId("parent"), id_factory_.root(), |
| 245 "parent", true, syncable::BOOKMARKS, &parent_handle); | 244 "parent", true, syncer::BOOKMARKS, &parent_handle); |
| 246 { | 245 { |
| 247 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 246 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
| 248 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, parent_handle); | 247 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, parent_handle); |
| 249 entry.Put(syncable::IS_DEL, true); | 248 entry.Put(syncable::IS_DEL, true); |
| 250 } | 249 } |
| 251 | 250 |
| 252 // Create an incoming child from the server. | 251 // Create an incoming child from the server. |
| 253 entry_factory_->CreateUnappliedNewItemWithParent( | 252 entry_factory_->CreateUnappliedNewItemWithParent( |
| 254 "child", DefaultBookmarkSpecifics(), "parent"); | 253 "child", DefaultBookmarkSpecifics(), "parent"); |
| 255 | 254 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 271 | 270 |
| 272 // Runs the ApplyUpdatesCommand on a directory where the server is trying to | 271 // Runs the ApplyUpdatesCommand on a directory where the server is trying to |
| 273 // delete a folder that has a recently added (and unsynced) child. We expect | 272 // delete a folder that has a recently added (and unsynced) child. We expect |
| 274 // the command to not apply the update because it is in a CONFLICT_HIERARCHY | 273 // the command to not apply the update because it is in a CONFLICT_HIERARCHY |
| 275 // state. | 274 // state. |
| 276 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDeleteNonEmptyDirectory) { | 275 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDeleteNonEmptyDirectory) { |
| 277 // Create a server-deleted directory. | 276 // Create a server-deleted directory. |
| 278 { | 277 { |
| 279 // Create it as a child of root node. | 278 // Create it as a child of root node. |
| 280 int64 handle = entry_factory_->CreateSyncedItem( | 279 int64 handle = entry_factory_->CreateSyncedItem( |
| 281 "parent", syncable::BOOKMARKS, true); | 280 "parent", syncer::BOOKMARKS, true); |
| 282 | 281 |
| 283 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 282 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
| 284 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); | 283 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); |
| 285 ASSERT_TRUE(entry.good()); | 284 ASSERT_TRUE(entry.good()); |
| 286 | 285 |
| 287 // Delete it on the server. | 286 // Delete it on the server. |
| 288 entry.Put(syncable::SERVER_VERSION, entry_factory_->GetNextRevision()); | 287 entry.Put(syncable::SERVER_VERSION, entry_factory_->GetNextRevision()); |
| 289 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); | 288 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); |
| 290 entry.Put(syncable::SERVER_PARENT_ID, id_factory_.root()); | 289 entry.Put(syncable::SERVER_PARENT_ID, id_factory_.root()); |
| 291 entry.Put(syncable::SERVER_IS_DEL, true); | 290 entry.Put(syncable::SERVER_IS_DEL, true); |
| 292 } | 291 } |
| 293 | 292 |
| 294 // Create a local child of the server-deleted directory. | 293 // Create a local child of the server-deleted directory. |
| 295 entry_factory_->CreateUnsyncedItem( | 294 entry_factory_->CreateUnsyncedItem( |
| 296 id_factory_.MakeServer("child"), id_factory_.MakeServer("parent"), | 295 id_factory_.MakeServer("child"), id_factory_.MakeServer("parent"), |
| 297 "child", false, syncable::BOOKMARKS, NULL); | 296 "child", false, syncer::BOOKMARKS, NULL); |
| 298 | 297 |
| 299 // The server's request to delete the directory must be ignored, otherwise our | 298 // The server's request to delete the directory must be ignored, otherwise our |
| 300 // unsynced new child would be orphaned. This is a hierarchy conflict. | 299 // unsynced new child would be orphaned. This is a hierarchy conflict. |
| 301 | 300 |
| 302 ExpectGroupToChange(apply_updates_command_, GROUP_UI); | 301 ExpectGroupToChange(apply_updates_command_, GROUP_UI); |
| 303 apply_updates_command_.ExecuteImpl(session()); | 302 apply_updates_command_.ExecuteImpl(session()); |
| 304 | 303 |
| 305 sessions::StatusController* status = session()->mutable_status_controller(); | 304 sessions::StatusController* status = session()->mutable_status_controller(); |
| 306 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); | 305 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_UI); |
| 307 | 306 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 EXPECT_EQ(0, status->conflict_progress()->SimpleConflictingItemsSize()) | 402 EXPECT_EQ(0, status->conflict_progress()->SimpleConflictingItemsSize()) |
| 404 << "No update should be in conflict because they're all decryptable"; | 403 << "No update should be in conflict because they're all decryptable"; |
| 405 EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) | 404 EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) |
| 406 << "The updates that can be decrypted should be applied"; | 405 << "The updates that can be decrypted should be applied"; |
| 407 } | 406 } |
| 408 | 407 |
| 409 TEST_F(ApplyUpdatesCommandTest, UndecryptableData) { | 408 TEST_F(ApplyUpdatesCommandTest, UndecryptableData) { |
| 410 // Undecryptable updates should not be applied. | 409 // Undecryptable updates should not be applied. |
| 411 sync_pb::EntitySpecifics encrypted_bookmark; | 410 sync_pb::EntitySpecifics encrypted_bookmark; |
| 412 encrypted_bookmark.mutable_encrypted(); | 411 encrypted_bookmark.mutable_encrypted(); |
| 413 AddDefaultFieldValue(syncable::BOOKMARKS, &encrypted_bookmark); | 412 AddDefaultFieldValue(syncer::BOOKMARKS, &encrypted_bookmark); |
| 414 string root_server_id = syncable::GetNullId().GetServerId(); | 413 string root_server_id = syncable::GetNullId().GetServerId(); |
| 415 entry_factory_->CreateUnappliedNewItemWithParent( | 414 entry_factory_->CreateUnappliedNewItemWithParent( |
| 416 "folder", encrypted_bookmark, root_server_id); | 415 "folder", encrypted_bookmark, root_server_id); |
| 417 entry_factory_->CreateUnappliedNewItem("item2", encrypted_bookmark, false); | 416 entry_factory_->CreateUnappliedNewItem("item2", encrypted_bookmark, false); |
| 418 sync_pb::EntitySpecifics encrypted_password; | 417 sync_pb::EntitySpecifics encrypted_password; |
| 419 encrypted_password.mutable_password(); | 418 encrypted_password.mutable_password(); |
| 420 entry_factory_->CreateUnappliedNewItem("item3", encrypted_password, false); | 419 entry_factory_->CreateUnappliedNewItem("item3", encrypted_password, false); |
| 421 | 420 |
| 422 ExpectGroupsToChange(apply_updates_command_, GROUP_UI, GROUP_PASSWORD); | 421 ExpectGroupsToChange(apply_updates_command_, GROUP_UI, GROUP_PASSWORD); |
| 423 apply_updates_command_.ExecuteImpl(session()); | 422 apply_updates_command_.ExecuteImpl(session()); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 << "conflict"; | 511 << "conflict"; |
| 513 EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) | 512 EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) |
| 514 << "The undecryptable password update shouldn't be applied"; | 513 << "The undecryptable password update shouldn't be applied"; |
| 515 } | 514 } |
| 516 } | 515 } |
| 517 | 516 |
| 518 TEST_F(ApplyUpdatesCommandTest, NigoriUpdate) { | 517 TEST_F(ApplyUpdatesCommandTest, NigoriUpdate) { |
| 519 // Storing the cryptographer separately is bad, but for this test we | 518 // Storing the cryptographer separately is bad, but for this test we |
| 520 // know it's safe. | 519 // know it's safe. |
| 521 Cryptographer* cryptographer; | 520 Cryptographer* cryptographer; |
| 522 syncable::ModelTypeSet encrypted_types; | 521 syncer::ModelTypeSet encrypted_types; |
| 523 encrypted_types.Put(syncable::PASSWORDS); | 522 encrypted_types.Put(syncer::PASSWORDS); |
| 524 encrypted_types.Put(syncable::NIGORI); | 523 encrypted_types.Put(syncer::NIGORI); |
| 525 { | 524 { |
| 526 syncable::ReadTransaction trans(FROM_HERE, directory()); | 525 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 527 cryptographer = directory()->GetCryptographer(&trans); | 526 cryptographer = directory()->GetCryptographer(&trans); |
| 528 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types)); | 527 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types)); |
| 529 } | 528 } |
| 530 | 529 |
| 531 // Nigori node updates should update the Cryptographer. | 530 // Nigori node updates should update the Cryptographer. |
| 532 Cryptographer other_cryptographer(&encryptor_); | 531 Cryptographer other_cryptographer(&encryptor_); |
| 533 KeyParams params = {"localhost", "dummy", "foobar"}; | 532 KeyParams params = {"localhost", "dummy", "foobar"}; |
| 534 other_cryptographer.AddKey(params); | 533 other_cryptographer.AddKey(params); |
| 535 | 534 |
| 536 sync_pb::EntitySpecifics specifics; | 535 sync_pb::EntitySpecifics specifics; |
| 537 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori(); | 536 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori(); |
| 538 other_cryptographer.GetKeys(nigori->mutable_encrypted()); | 537 other_cryptographer.GetKeys(nigori->mutable_encrypted()); |
| 539 nigori->set_encrypt_bookmarks(true); | 538 nigori->set_encrypt_bookmarks(true); |
| 540 encrypted_types.Put(syncable::BOOKMARKS); | 539 encrypted_types.Put(syncer::BOOKMARKS); |
| 541 entry_factory_->CreateUnappliedNewItem( | 540 entry_factory_->CreateUnappliedNewItem( |
| 542 syncable::ModelTypeToRootTag(syncable::NIGORI), specifics, true); | 541 syncer::ModelTypeToRootTag(syncer::NIGORI), specifics, true); |
| 543 EXPECT_FALSE(cryptographer->has_pending_keys()); | 542 EXPECT_FALSE(cryptographer->has_pending_keys()); |
| 544 | 543 |
| 545 ExpectGroupToChange(apply_updates_command_, GROUP_PASSIVE); | 544 ExpectGroupToChange(apply_updates_command_, GROUP_PASSIVE); |
| 546 apply_updates_command_.ExecuteImpl(session()); | 545 apply_updates_command_.ExecuteImpl(session()); |
| 547 | 546 |
| 548 sessions::StatusController* status = session()->mutable_status_controller(); | 547 sessions::StatusController* status = session()->mutable_status_controller(); |
| 549 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE); | 548 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE); |
| 550 ASSERT_TRUE(status->update_progress()); | 549 ASSERT_TRUE(status->update_progress()); |
| 551 EXPECT_EQ(1, status->update_progress()->AppliedUpdatesSize()) | 550 EXPECT_EQ(1, status->update_progress()->AppliedUpdatesSize()) |
| 552 << "All updates should have been attempted"; | 551 << "All updates should have been attempted"; |
| 553 ASSERT_TRUE(status->conflict_progress()); | 552 ASSERT_TRUE(status->conflict_progress()); |
| 554 EXPECT_EQ(0, status->conflict_progress()->SimpleConflictingItemsSize()) | 553 EXPECT_EQ(0, status->conflict_progress()->SimpleConflictingItemsSize()) |
| 555 << "The nigori update shouldn't be in conflict"; | 554 << "The nigori update shouldn't be in conflict"; |
| 556 EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) | 555 EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) |
| 557 << "The nigori update should be applied"; | 556 << "The nigori update should be applied"; |
| 558 | 557 |
| 559 EXPECT_FALSE(cryptographer->is_ready()); | 558 EXPECT_FALSE(cryptographer->is_ready()); |
| 560 EXPECT_TRUE(cryptographer->has_pending_keys()); | 559 EXPECT_TRUE(cryptographer->has_pending_keys()); |
| 561 EXPECT_TRUE( | 560 EXPECT_TRUE( |
| 562 cryptographer->GetEncryptedTypes() | 561 cryptographer->GetEncryptedTypes().Equals(syncer::ModelTypeSet::All())); |
| 563 .Equals(syncable::ModelTypeSet::All())); | |
| 564 } | 562 } |
| 565 | 563 |
| 566 TEST_F(ApplyUpdatesCommandTest, NigoriUpdateForDisabledTypes) { | 564 TEST_F(ApplyUpdatesCommandTest, NigoriUpdateForDisabledTypes) { |
| 567 // Storing the cryptographer separately is bad, but for this test we | 565 // Storing the cryptographer separately is bad, but for this test we |
| 568 // know it's safe. | 566 // know it's safe. |
| 569 Cryptographer* cryptographer; | 567 Cryptographer* cryptographer; |
| 570 syncable::ModelTypeSet encrypted_types; | 568 syncer::ModelTypeSet encrypted_types; |
| 571 encrypted_types.Put(syncable::PASSWORDS); | 569 encrypted_types.Put(syncer::PASSWORDS); |
| 572 encrypted_types.Put(syncable::NIGORI); | 570 encrypted_types.Put(syncer::NIGORI); |
| 573 { | 571 { |
| 574 syncable::ReadTransaction trans(FROM_HERE, directory()); | 572 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 575 cryptographer = directory()->GetCryptographer(&trans); | 573 cryptographer = directory()->GetCryptographer(&trans); |
| 576 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types)); | 574 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types)); |
| 577 } | 575 } |
| 578 | 576 |
| 579 // Nigori node updates should update the Cryptographer. | 577 // Nigori node updates should update the Cryptographer. |
| 580 Cryptographer other_cryptographer(&encryptor_); | 578 Cryptographer other_cryptographer(&encryptor_); |
| 581 KeyParams params = {"localhost", "dummy", "foobar"}; | 579 KeyParams params = {"localhost", "dummy", "foobar"}; |
| 582 other_cryptographer.AddKey(params); | 580 other_cryptographer.AddKey(params); |
| 583 | 581 |
| 584 sync_pb::EntitySpecifics specifics; | 582 sync_pb::EntitySpecifics specifics; |
| 585 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori(); | 583 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori(); |
| 586 other_cryptographer.GetKeys(nigori->mutable_encrypted()); | 584 other_cryptographer.GetKeys(nigori->mutable_encrypted()); |
| 587 nigori->set_encrypt_sessions(true); | 585 nigori->set_encrypt_sessions(true); |
| 588 nigori->set_encrypt_themes(true); | 586 nigori->set_encrypt_themes(true); |
| 589 encrypted_types.Put(syncable::SESSIONS); | 587 encrypted_types.Put(syncer::SESSIONS); |
| 590 encrypted_types.Put(syncable::THEMES); | 588 encrypted_types.Put(syncer::THEMES); |
| 591 entry_factory_->CreateUnappliedNewItem( | 589 entry_factory_->CreateUnappliedNewItem( |
| 592 syncable::ModelTypeToRootTag(syncable::NIGORI), specifics, true); | 590 syncer::ModelTypeToRootTag(syncer::NIGORI), specifics, true); |
| 593 EXPECT_FALSE(cryptographer->has_pending_keys()); | 591 EXPECT_FALSE(cryptographer->has_pending_keys()); |
| 594 | 592 |
| 595 ExpectGroupToChange(apply_updates_command_, GROUP_PASSIVE); | 593 ExpectGroupToChange(apply_updates_command_, GROUP_PASSIVE); |
| 596 apply_updates_command_.ExecuteImpl(session()); | 594 apply_updates_command_.ExecuteImpl(session()); |
| 597 | 595 |
| 598 sessions::StatusController* status = session()->mutable_status_controller(); | 596 sessions::StatusController* status = session()->mutable_status_controller(); |
| 599 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE); | 597 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE); |
| 600 ASSERT_TRUE(status->update_progress()); | 598 ASSERT_TRUE(status->update_progress()); |
| 601 EXPECT_EQ(1, status->update_progress()->AppliedUpdatesSize()) | 599 EXPECT_EQ(1, status->update_progress()->AppliedUpdatesSize()) |
| 602 << "All updates should have been attempted"; | 600 << "All updates should have been attempted"; |
| 603 ASSERT_TRUE(status->conflict_progress()); | 601 ASSERT_TRUE(status->conflict_progress()); |
| 604 EXPECT_EQ(0, status->conflict_progress()->SimpleConflictingItemsSize()) | 602 EXPECT_EQ(0, status->conflict_progress()->SimpleConflictingItemsSize()) |
| 605 << "The nigori update shouldn't be in conflict"; | 603 << "The nigori update shouldn't be in conflict"; |
| 606 EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) | 604 EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) |
| 607 << "The nigori update should be applied"; | 605 << "The nigori update should be applied"; |
| 608 | 606 |
| 609 EXPECT_FALSE(cryptographer->is_ready()); | 607 EXPECT_FALSE(cryptographer->is_ready()); |
| 610 EXPECT_TRUE(cryptographer->has_pending_keys()); | 608 EXPECT_TRUE(cryptographer->has_pending_keys()); |
| 611 EXPECT_TRUE( | 609 EXPECT_TRUE( |
| 612 cryptographer->GetEncryptedTypes() | 610 cryptographer->GetEncryptedTypes().Equals(syncer::ModelTypeSet::All())); |
| 613 .Equals(syncable::ModelTypeSet::All())); | |
| 614 } | 611 } |
| 615 | 612 |
| 616 // Create some local unsynced and unencrypted data. Apply a nigori update that | 613 // Create some local unsynced and unencrypted data. Apply a nigori update that |
| 617 // turns on encryption for the unsynced data. Ensure we properly encrypt the | 614 // turns on encryption for the unsynced data. Ensure we properly encrypt the |
| 618 // data as part of the nigori update. Apply another nigori update with no | 615 // data as part of the nigori update. Apply another nigori update with no |
| 619 // changes. Ensure we ignore already-encrypted unsynced data and that nothing | 616 // changes. Ensure we ignore already-encrypted unsynced data and that nothing |
| 620 // breaks. | 617 // breaks. |
| 621 TEST_F(ApplyUpdatesCommandTest, EncryptUnsyncedChanges) { | 618 TEST_F(ApplyUpdatesCommandTest, EncryptUnsyncedChanges) { |
| 622 // Storing the cryptographer separately is bad, but for this test we | 619 // Storing the cryptographer separately is bad, but for this test we |
| 623 // know it's safe. | 620 // know it's safe. |
| 624 Cryptographer* cryptographer; | 621 Cryptographer* cryptographer; |
| 625 syncable::ModelTypeSet encrypted_types; | 622 syncer::ModelTypeSet encrypted_types; |
| 626 encrypted_types.Put(syncable::PASSWORDS); | 623 encrypted_types.Put(syncer::PASSWORDS); |
| 627 encrypted_types.Put(syncable::NIGORI); | 624 encrypted_types.Put(syncer::NIGORI); |
| 628 { | 625 { |
| 629 syncable::ReadTransaction trans(FROM_HERE, directory()); | 626 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 630 cryptographer = directory()->GetCryptographer(&trans); | 627 cryptographer = directory()->GetCryptographer(&trans); |
| 631 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types)); | 628 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types)); |
| 632 | 629 |
| 633 // With default encrypted_types, this should be true. | 630 // With default encrypted_types, this should be true. |
| 634 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); | 631 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); |
| 635 | 632 |
| 636 Syncer::UnsyncedMetaHandles handles; | 633 Syncer::UnsyncedMetaHandles handles; |
| 637 GetUnsyncedEntries(&trans, &handles); | 634 GetUnsyncedEntries(&trans, &handles); |
| 638 EXPECT_TRUE(handles.empty()); | 635 EXPECT_TRUE(handles.empty()); |
| 639 } | 636 } |
| 640 | 637 |
| 641 // Create unsynced bookmarks without encryption. | 638 // Create unsynced bookmarks without encryption. |
| 642 // First item is a folder | 639 // First item is a folder |
| 643 Id folder_id = id_factory_.NewLocalId(); | 640 Id folder_id = id_factory_.NewLocalId(); |
| 644 entry_factory_->CreateUnsyncedItem(folder_id, id_factory_.root(), "folder", | 641 entry_factory_->CreateUnsyncedItem(folder_id, id_factory_.root(), "folder", |
| 645 true, syncable::BOOKMARKS, NULL); | 642 true, syncer::BOOKMARKS, NULL); |
| 646 // Next five items are children of the folder | 643 // Next five items are children of the folder |
| 647 size_t i; | 644 size_t i; |
| 648 size_t batch_s = 5; | 645 size_t batch_s = 5; |
| 649 for (i = 0; i < batch_s; ++i) { | 646 for (i = 0; i < batch_s; ++i) { |
| 650 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id, | 647 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id, |
| 651 base::StringPrintf("Item %"PRIuS"", i), | 648 base::StringPrintf("Item %"PRIuS"", i), |
| 652 false, syncable::BOOKMARKS, NULL); | 649 false, syncer::BOOKMARKS, NULL); |
| 653 } | 650 } |
| 654 // Next five items are children of the root. | 651 // Next five items are children of the root. |
| 655 for (; i < 2*batch_s; ++i) { | 652 for (; i < 2*batch_s; ++i) { |
| 656 entry_factory_->CreateUnsyncedItem( | 653 entry_factory_->CreateUnsyncedItem( |
| 657 id_factory_.NewLocalId(), id_factory_.root(), | 654 id_factory_.NewLocalId(), id_factory_.root(), |
| 658 base::StringPrintf("Item %"PRIuS"", i), false, | 655 base::StringPrintf("Item %"PRIuS"", i), false, |
| 659 syncable::BOOKMARKS, NULL); | 656 syncer::BOOKMARKS, NULL); |
| 660 } | 657 } |
| 661 | 658 |
| 662 KeyParams params = {"localhost", "dummy", "foobar"}; | 659 KeyParams params = {"localhost", "dummy", "foobar"}; |
| 663 cryptographer->AddKey(params); | 660 cryptographer->AddKey(params); |
| 664 sync_pb::EntitySpecifics specifics; | 661 sync_pb::EntitySpecifics specifics; |
| 665 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori(); | 662 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori(); |
| 666 cryptographer->GetKeys(nigori->mutable_encrypted()); | 663 cryptographer->GetKeys(nigori->mutable_encrypted()); |
| 667 nigori->set_encrypt_bookmarks(true); | 664 nigori->set_encrypt_bookmarks(true); |
| 668 encrypted_types.Put(syncable::BOOKMARKS); | 665 encrypted_types.Put(syncer::BOOKMARKS); |
| 669 entry_factory_->CreateUnappliedNewItem( | 666 entry_factory_->CreateUnappliedNewItem( |
| 670 syncable::ModelTypeToRootTag(syncable::NIGORI), specifics, true); | 667 syncer::ModelTypeToRootTag(syncer::NIGORI), specifics, true); |
| 671 EXPECT_FALSE(cryptographer->has_pending_keys()); | 668 EXPECT_FALSE(cryptographer->has_pending_keys()); |
| 672 EXPECT_TRUE(cryptographer->is_ready()); | 669 EXPECT_TRUE(cryptographer->is_ready()); |
| 673 | 670 |
| 674 { | 671 { |
| 675 // Ensure we have unsynced nodes that aren't properly encrypted. | 672 // Ensure we have unsynced nodes that aren't properly encrypted. |
| 676 syncable::ReadTransaction trans(FROM_HERE, directory()); | 673 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 677 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); | 674 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); |
| 678 | 675 |
| 679 Syncer::UnsyncedMetaHandles handles; | 676 Syncer::UnsyncedMetaHandles handles; |
| 680 GetUnsyncedEntries(&trans, &handles); | 677 GetUnsyncedEntries(&trans, &handles); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 698 EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) | 695 EXPECT_EQ(1, status->update_progress()->SuccessfullyAppliedUpdateCount()) |
| 699 << "The nigori update should be applied"; | 696 << "The nigori update should be applied"; |
| 700 } | 697 } |
| 701 EXPECT_FALSE(cryptographer->has_pending_keys()); | 698 EXPECT_FALSE(cryptographer->has_pending_keys()); |
| 702 EXPECT_TRUE(cryptographer->is_ready()); | 699 EXPECT_TRUE(cryptographer->is_ready()); |
| 703 { | 700 { |
| 704 syncable::ReadTransaction trans(FROM_HERE, directory()); | 701 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 705 | 702 |
| 706 // If ProcessUnsyncedChangesForEncryption worked, all our unsynced changes | 703 // If ProcessUnsyncedChangesForEncryption worked, all our unsynced changes |
| 707 // should be encrypted now. | 704 // should be encrypted now. |
| 708 EXPECT_TRUE(syncable::ModelTypeSet::All().Equals( | 705 EXPECT_TRUE(syncer::ModelTypeSet::All().Equals( |
| 709 cryptographer->GetEncryptedTypes())); | 706 cryptographer->GetEncryptedTypes())); |
| 710 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); | 707 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); |
| 711 | 708 |
| 712 Syncer::UnsyncedMetaHandles handles; | 709 Syncer::UnsyncedMetaHandles handles; |
| 713 GetUnsyncedEntries(&trans, &handles); | 710 GetUnsyncedEntries(&trans, &handles); |
| 714 EXPECT_EQ(2*batch_s+1, handles.size()); | 711 EXPECT_EQ(2*batch_s+1, handles.size()); |
| 715 } | 712 } |
| 716 | 713 |
| 717 // Simulate another nigori update that doesn't change anything. | 714 // Simulate another nigori update that doesn't change anything. |
| 718 { | 715 { |
| 719 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 716 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
| 720 MutableEntry entry(&trans, syncable::GET_BY_SERVER_TAG, | 717 MutableEntry entry(&trans, syncable::GET_BY_SERVER_TAG, |
| 721 syncable::ModelTypeToRootTag(syncable::NIGORI)); | 718 syncer::ModelTypeToRootTag(syncer::NIGORI)); |
| 722 ASSERT_TRUE(entry.good()); | 719 ASSERT_TRUE(entry.good()); |
| 723 entry.Put(syncable::SERVER_VERSION, entry_factory_->GetNextRevision()); | 720 entry.Put(syncable::SERVER_VERSION, entry_factory_->GetNextRevision()); |
| 724 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); | 721 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); |
| 725 } | 722 } |
| 726 ExpectGroupToChange(apply_updates_command_, GROUP_PASSIVE); | 723 ExpectGroupToChange(apply_updates_command_, GROUP_PASSIVE); |
| 727 apply_updates_command_.ExecuteImpl(session()); | 724 apply_updates_command_.ExecuteImpl(session()); |
| 728 { | 725 { |
| 729 sessions::StatusController* status = session()->mutable_status_controller(); | 726 sessions::StatusController* status = session()->mutable_status_controller(); |
| 730 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE); | 727 sessions::ScopedModelSafeGroupRestriction r(status, GROUP_PASSIVE); |
| 731 ASSERT_TRUE(status->update_progress()); | 728 ASSERT_TRUE(status->update_progress()); |
| 732 EXPECT_EQ(2, status->update_progress()->AppliedUpdatesSize()) | 729 EXPECT_EQ(2, status->update_progress()->AppliedUpdatesSize()) |
| 733 << "All updates should have been attempted"; | 730 << "All updates should have been attempted"; |
| 734 ASSERT_TRUE(status->conflict_progress()); | 731 ASSERT_TRUE(status->conflict_progress()); |
| 735 EXPECT_EQ(0, status->conflict_progress()->SimpleConflictingItemsSize()) | 732 EXPECT_EQ(0, status->conflict_progress()->SimpleConflictingItemsSize()) |
| 736 << "No updates should be in conflict"; | 733 << "No updates should be in conflict"; |
| 737 EXPECT_EQ(0, status->conflict_progress()->EncryptionConflictingItemsSize()) | 734 EXPECT_EQ(0, status->conflict_progress()->EncryptionConflictingItemsSize()) |
| 738 << "No updates should be in conflict"; | 735 << "No updates should be in conflict"; |
| 739 EXPECT_EQ(2, status->update_progress()->SuccessfullyAppliedUpdateCount()) | 736 EXPECT_EQ(2, status->update_progress()->SuccessfullyAppliedUpdateCount()) |
| 740 << "The nigori update should be applied"; | 737 << "The nigori update should be applied"; |
| 741 } | 738 } |
| 742 EXPECT_FALSE(cryptographer->has_pending_keys()); | 739 EXPECT_FALSE(cryptographer->has_pending_keys()); |
| 743 EXPECT_TRUE(cryptographer->is_ready()); | 740 EXPECT_TRUE(cryptographer->is_ready()); |
| 744 { | 741 { |
| 745 syncable::ReadTransaction trans(FROM_HERE, directory()); | 742 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 746 | 743 |
| 747 // All our changes should still be encrypted. | 744 // All our changes should still be encrypted. |
| 748 EXPECT_TRUE(syncable::ModelTypeSet::All().Equals( | 745 EXPECT_TRUE(syncer::ModelTypeSet::All().Equals( |
| 749 cryptographer->GetEncryptedTypes())); | 746 cryptographer->GetEncryptedTypes())); |
| 750 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); | 747 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); |
| 751 | 748 |
| 752 Syncer::UnsyncedMetaHandles handles; | 749 Syncer::UnsyncedMetaHandles handles; |
| 753 GetUnsyncedEntries(&trans, &handles); | 750 GetUnsyncedEntries(&trans, &handles); |
| 754 EXPECT_EQ(2*batch_s+1, handles.size()); | 751 EXPECT_EQ(2*batch_s+1, handles.size()); |
| 755 } | 752 } |
| 756 } | 753 } |
| 757 | 754 |
| 758 TEST_F(ApplyUpdatesCommandTest, CannotEncryptUnsyncedChanges) { | 755 TEST_F(ApplyUpdatesCommandTest, CannotEncryptUnsyncedChanges) { |
| 759 // Storing the cryptographer separately is bad, but for this test we | 756 // Storing the cryptographer separately is bad, but for this test we |
| 760 // know it's safe. | 757 // know it's safe. |
| 761 Cryptographer* cryptographer; | 758 Cryptographer* cryptographer; |
| 762 syncable::ModelTypeSet encrypted_types; | 759 syncer::ModelTypeSet encrypted_types; |
| 763 encrypted_types.Put(syncable::PASSWORDS); | 760 encrypted_types.Put(syncer::PASSWORDS); |
| 764 encrypted_types.Put(syncable::NIGORI); | 761 encrypted_types.Put(syncer::NIGORI); |
| 765 { | 762 { |
| 766 syncable::ReadTransaction trans(FROM_HERE, directory()); | 763 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 767 cryptographer = directory()->GetCryptographer(&trans); | 764 cryptographer = directory()->GetCryptographer(&trans); |
| 768 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types)); | 765 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals(encrypted_types)); |
| 769 | 766 |
| 770 // With default encrypted_types, this should be true. | 767 // With default encrypted_types, this should be true. |
| 771 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); | 768 EXPECT_TRUE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); |
| 772 | 769 |
| 773 Syncer::UnsyncedMetaHandles handles; | 770 Syncer::UnsyncedMetaHandles handles; |
| 774 GetUnsyncedEntries(&trans, &handles); | 771 GetUnsyncedEntries(&trans, &handles); |
| 775 EXPECT_TRUE(handles.empty()); | 772 EXPECT_TRUE(handles.empty()); |
| 776 } | 773 } |
| 777 | 774 |
| 778 // Create unsynced bookmarks without encryption. | 775 // Create unsynced bookmarks without encryption. |
| 779 // First item is a folder | 776 // First item is a folder |
| 780 Id folder_id = id_factory_.NewLocalId(); | 777 Id folder_id = id_factory_.NewLocalId(); |
| 781 entry_factory_->CreateUnsyncedItem( | 778 entry_factory_->CreateUnsyncedItem( |
| 782 folder_id, id_factory_.root(), "folder", true, | 779 folder_id, id_factory_.root(), "folder", true, |
| 783 syncable::BOOKMARKS, NULL); | 780 syncer::BOOKMARKS, NULL); |
| 784 // Next five items are children of the folder | 781 // Next five items are children of the folder |
| 785 size_t i; | 782 size_t i; |
| 786 size_t batch_s = 5; | 783 size_t batch_s = 5; |
| 787 for (i = 0; i < batch_s; ++i) { | 784 for (i = 0; i < batch_s; ++i) { |
| 788 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id, | 785 entry_factory_->CreateUnsyncedItem(id_factory_.NewLocalId(), folder_id, |
| 789 base::StringPrintf("Item %"PRIuS"", i), | 786 base::StringPrintf("Item %"PRIuS"", i), |
| 790 false, syncable::BOOKMARKS, NULL); | 787 false, syncer::BOOKMARKS, NULL); |
| 791 } | 788 } |
| 792 // Next five items are children of the root. | 789 // Next five items are children of the root. |
| 793 for (; i < 2*batch_s; ++i) { | 790 for (; i < 2*batch_s; ++i) { |
| 794 entry_factory_->CreateUnsyncedItem( | 791 entry_factory_->CreateUnsyncedItem( |
| 795 id_factory_.NewLocalId(), id_factory_.root(), | 792 id_factory_.NewLocalId(), id_factory_.root(), |
| 796 base::StringPrintf("Item %"PRIuS"", i), false, | 793 base::StringPrintf("Item %"PRIuS"", i), false, |
| 797 syncable::BOOKMARKS, NULL); | 794 syncer::BOOKMARKS, NULL); |
| 798 } | 795 } |
| 799 | 796 |
| 800 // We encrypt with new keys, triggering the local cryptographer to be unready | 797 // We encrypt with new keys, triggering the local cryptographer to be unready |
| 801 // and unable to decrypt data (once updated). | 798 // and unable to decrypt data (once updated). |
| 802 Cryptographer other_cryptographer(&encryptor_); | 799 Cryptographer other_cryptographer(&encryptor_); |
| 803 KeyParams params = {"localhost", "dummy", "foobar"}; | 800 KeyParams params = {"localhost", "dummy", "foobar"}; |
| 804 other_cryptographer.AddKey(params); | 801 other_cryptographer.AddKey(params); |
| 805 sync_pb::EntitySpecifics specifics; | 802 sync_pb::EntitySpecifics specifics; |
| 806 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori(); | 803 sync_pb::NigoriSpecifics* nigori = specifics.mutable_nigori(); |
| 807 other_cryptographer.GetKeys(nigori->mutable_encrypted()); | 804 other_cryptographer.GetKeys(nigori->mutable_encrypted()); |
| 808 nigori->set_encrypt_bookmarks(true); | 805 nigori->set_encrypt_bookmarks(true); |
| 809 encrypted_types.Put(syncable::BOOKMARKS); | 806 encrypted_types.Put(syncer::BOOKMARKS); |
| 810 entry_factory_->CreateUnappliedNewItem( | 807 entry_factory_->CreateUnappliedNewItem( |
| 811 syncable::ModelTypeToRootTag(syncable::NIGORI), specifics, true); | 808 syncer::ModelTypeToRootTag(syncer::NIGORI), specifics, true); |
| 812 EXPECT_FALSE(cryptographer->has_pending_keys()); | 809 EXPECT_FALSE(cryptographer->has_pending_keys()); |
| 813 | 810 |
| 814 { | 811 { |
| 815 // Ensure we have unsynced nodes that aren't properly encrypted. | 812 // Ensure we have unsynced nodes that aren't properly encrypted. |
| 816 syncable::ReadTransaction trans(FROM_HERE, directory()); | 813 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 817 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); | 814 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); |
| 818 Syncer::UnsyncedMetaHandles handles; | 815 Syncer::UnsyncedMetaHandles handles; |
| 819 GetUnsyncedEntries(&trans, &handles); | 816 GetUnsyncedEntries(&trans, &handles); |
| 820 EXPECT_EQ(2*batch_s+1, handles.size()); | 817 EXPECT_EQ(2*batch_s+1, handles.size()); |
| 821 } | 818 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 839 << "The nigori update should be applied"; | 836 << "The nigori update should be applied"; |
| 840 EXPECT_FALSE(cryptographer->is_ready()); | 837 EXPECT_FALSE(cryptographer->is_ready()); |
| 841 EXPECT_TRUE(cryptographer->has_pending_keys()); | 838 EXPECT_TRUE(cryptographer->has_pending_keys()); |
| 842 { | 839 { |
| 843 syncable::ReadTransaction trans(FROM_HERE, directory()); | 840 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 844 | 841 |
| 845 // Since we have pending keys, we would have failed to encrypt, but the | 842 // Since we have pending keys, we would have failed to encrypt, but the |
| 846 // cryptographer should be updated. | 843 // cryptographer should be updated. |
| 847 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); | 844 EXPECT_FALSE(VerifyUnsyncedChangesAreEncrypted(&trans, encrypted_types)); |
| 848 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals( | 845 EXPECT_TRUE(cryptographer->GetEncryptedTypes().Equals( |
| 849 syncable::ModelTypeSet().All())); | 846 syncer::ModelTypeSet().All())); |
| 850 EXPECT_FALSE(cryptographer->is_ready()); | 847 EXPECT_FALSE(cryptographer->is_ready()); |
| 851 EXPECT_TRUE(cryptographer->has_pending_keys()); | 848 EXPECT_TRUE(cryptographer->has_pending_keys()); |
| 852 | 849 |
| 853 Syncer::UnsyncedMetaHandles handles; | 850 Syncer::UnsyncedMetaHandles handles; |
| 854 GetUnsyncedEntries(&trans, &handles); | 851 GetUnsyncedEntries(&trans, &handles); |
| 855 EXPECT_EQ(2*batch_s+1, handles.size()); | 852 EXPECT_EQ(2*batch_s+1, handles.size()); |
| 856 } | 853 } |
| 857 } | 854 } |
| 858 | 855 |
| 859 } // namespace syncer | 856 } // namespace syncer |
| OLD | NEW |