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