Chromium Code Reviews| 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 "sync/engine/process_commit_response_command.h" | 5 #include "sync/engine/process_commit_response_command.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| 11 #include "sync/protocol/bookmark_specifics.pb.h" | 11 #include "sync/protocol/bookmark_specifics.pb.h" |
| 12 #include "sync/protocol/sync.pb.h" | 12 #include "sync/protocol/sync.pb.h" |
| 13 #include "sync/sessions/sync_session.h" | 13 #include "sync/sessions/sync_session.h" |
| 14 #include "sync/syncable/entry.h" | 14 #include "sync/syncable/entry.h" |
| 15 #include "sync/syncable/mutable_entry.h" | 15 #include "sync/syncable/mutable_entry.h" |
| 16 #include "sync/syncable/read_transaction.h" | 16 #include "sync/syncable/read_transaction.h" |
| 17 #include "sync/syncable/syncable_id.h" | 17 #include "sync/syncable/syncable_id.h" |
| 18 #include "sync/syncable/syncable_proto_util.h" | |
| 18 #include "sync/syncable/write_transaction.h" | 19 #include "sync/syncable/write_transaction.h" |
| 19 #include "sync/test/engine/fake_model_worker.h" | 20 #include "sync/test/engine/fake_model_worker.h" |
| 20 #include "sync/test/engine/syncer_command_test.h" | 21 #include "sync/test/engine/syncer_command_test.h" |
| 21 #include "sync/test/engine/test_id_factory.h" | 22 #include "sync/test/engine/test_id_factory.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 24 |
| 25 using sync_pb::CommitResponse; | |
|
akalin
2012/07/11 01:42:22
move into namespace?
rlarocque
2012/07/11 19:22:16
Wouldn't it make more sense to move the other one
akalin
2012/07/11 23:10:40
I could be wrong, but 'using' declarations are sco
rlarocque
2012/07/11 23:45:36
If that's the strongest argument in favor of it, t
| |
| 26 | |
| 24 namespace syncer { | 27 namespace syncer { |
| 25 | 28 |
| 26 using sessions::SyncSession; | 29 using sessions::SyncSession; |
| 27 using std::string; | 30 using std::string; |
| 31 using sync_pb::ClientToServerMessage; | |
| 28 using syncable::BASE_VERSION; | 32 using syncable::BASE_VERSION; |
| 29 using syncable::Entry; | 33 using syncable::Entry; |
| 30 using syncable::IS_DIR; | 34 using syncable::IS_DIR; |
| 31 using syncable::IS_UNSYNCED; | 35 using syncable::IS_UNSYNCED; |
| 32 using syncable::Id; | 36 using syncable::Id; |
| 33 using syncable::MutableEntry; | 37 using syncable::MutableEntry; |
| 34 using syncable::NON_UNIQUE_NAME; | 38 using syncable::NON_UNIQUE_NAME; |
| 35 using syncable::UNITTEST; | 39 using syncable::UNITTEST; |
| 36 using syncable::WriteTransaction; | 40 using syncable::WriteTransaction; |
| 37 | 41 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 // Create a new unsynced item in the database, and synthesize a commit | 115 // Create a new unsynced item in the database, and synthesize a commit |
| 112 // record and a commit response for it in the syncer session. If item_id | 116 // record and a commit response for it in the syncer session. If item_id |
| 113 // is a local ID, the item will be a create operation. Otherwise, it | 117 // is a local ID, the item will be a create operation. Otherwise, it |
| 114 // will be an edit. | 118 // will be an edit. |
| 115 void CreateUnprocessedCommitResult( | 119 void CreateUnprocessedCommitResult( |
| 116 const Id& item_id, | 120 const Id& item_id, |
| 117 const Id& parent_id, | 121 const Id& parent_id, |
| 118 const string& name, | 122 const string& name, |
| 119 syncer::ModelType model_type, | 123 syncer::ModelType model_type, |
| 120 sessions::OrderedCommitSet *commit_set, | 124 sessions::OrderedCommitSet *commit_set, |
| 121 syncer::ClientToServerMessage *commit, | 125 sync_pb::ClientToServerMessage *commit, |
| 122 syncer::ClientToServerResponse *response) { | 126 sync_pb::ClientToServerResponse *response) { |
| 123 bool is_folder = true; | 127 bool is_folder = true; |
| 124 int64 metahandle = 0; | 128 int64 metahandle = 0; |
| 125 CreateUnsyncedItem(item_id, parent_id, name, is_folder, model_type, | 129 CreateUnsyncedItem(item_id, parent_id, name, is_folder, model_type, |
| 126 &metahandle); | 130 &metahandle); |
| 127 | 131 |
| 128 // ProcessCommitResponseCommand consumes commit_ids from the session | 132 // ProcessCommitResponseCommand consumes commit_ids from the session |
| 129 // state, so we need to update that. O(n^2) because it's a test. | 133 // state, so we need to update that. O(n^2) because it's a test. |
| 130 commit_set->AddCommitItem(metahandle, item_id, model_type); | 134 commit_set->AddCommitItem(metahandle, item_id, model_type); |
| 131 | 135 |
| 132 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 136 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
| 133 MutableEntry entry(&trans, syncable::GET_BY_ID, item_id); | 137 MutableEntry entry(&trans, syncable::GET_BY_ID, item_id); |
| 134 ASSERT_TRUE(entry.good()); | 138 ASSERT_TRUE(entry.good()); |
| 135 entry.Put(syncable::SYNCING, true); | 139 entry.Put(syncable::SYNCING, true); |
| 136 | 140 |
| 137 // Add to the commit message. | 141 // Add to the commit message. |
| 138 commit->set_message_contents(ClientToServerMessage::COMMIT); | 142 commit->set_message_contents(ClientToServerMessage::COMMIT); |
| 139 SyncEntity* entity = static_cast<SyncEntity*>( | 143 sync_pb::SyncEntity* entity = static_cast<sync_pb::SyncEntity*>( |
|
akalin
2012/07/11 01:42:22
static cast?
rlarocque
2012/07/11 19:22:16
Done.
| |
| 140 commit->mutable_commit()->add_entries()); | 144 commit->mutable_commit()->add_entries()); |
| 141 entity->set_non_unique_name(name); | 145 entity->set_non_unique_name(name); |
| 142 entity->set_folder(is_folder); | 146 entity->set_folder(is_folder); |
| 143 entity->set_parent_id(parent_id); | 147 entity->set_parent_id_string(SyncableIdToProto(parent_id)); |
| 144 entity->set_version(entry.Get(syncable::BASE_VERSION)); | 148 entity->set_version(entry.Get(syncable::BASE_VERSION)); |
| 145 entity->mutable_specifics()->CopyFrom(entry.Get(syncable::SPECIFICS)); | 149 entity->mutable_specifics()->CopyFrom(entry.Get(syncable::SPECIFICS)); |
| 146 entity->set_id(item_id); | 150 entity->set_id_string(SyncableIdToProto(item_id)); |
| 147 | 151 |
| 148 // Add to the response message. | 152 // Add to the response message. |
| 149 response->set_error_code(sync_pb::SyncEnums::SUCCESS); | 153 response->set_error_code(sync_pb::SyncEnums::SUCCESS); |
| 150 sync_pb::CommitResponse_EntryResponse* entry_response = | 154 sync_pb::CommitResponse_EntryResponse* entry_response = |
| 151 response->mutable_commit()->add_entryresponse(); | 155 response->mutable_commit()->add_entryresponse(); |
| 152 entry_response->set_response_type(CommitResponse::SUCCESS); | 156 entry_response->set_response_type(CommitResponse::SUCCESS); |
| 153 entry_response->set_name("Garbage."); | 157 entry_response->set_name("Garbage."); |
| 154 entry_response->set_non_unique_name(entity->name()); | 158 entry_response->set_non_unique_name(entity->name()); |
| 155 if (item_id.ServerKnows()) | 159 if (item_id.ServerKnows()) |
| 156 entry_response->set_id_string(entity->id_string()); | 160 entry_response->set_id_string(entity->id_string()); |
| 157 else | 161 else |
| 158 entry_response->set_id_string(id_factory_.NewServerId().GetServerId()); | 162 entry_response->set_id_string(id_factory_.NewServerId().GetServerId()); |
| 159 entry_response->set_version(next_new_revision_++); | 163 entry_response->set_version(next_new_revision_++); |
| 160 entry_response->set_position_in_parent(next_server_position_++); | 164 entry_response->set_position_in_parent(next_server_position_++); |
| 161 | 165 |
| 162 // If the ID of our parent item committed earlier in the batch was | 166 // If the ID of our parent item committed earlier in the batch was |
| 163 // rewritten, rewrite it in the entry response. This matches | 167 // rewritten, rewrite it in the entry response. This matches |
| 164 // the server behavior. | 168 // the server behavior. |
| 165 entry_response->set_parent_id_string(entity->parent_id_string()); | 169 entry_response->set_parent_id_string(entity->parent_id_string()); |
| 166 for (int i = 0; i < commit->commit().entries_size(); ++i) { | 170 for (int i = 0; i < commit->commit().entries_size(); ++i) { |
| 167 if (commit->commit().entries(i).id_string() == | 171 if (commit->commit().entries(i).id_string() == |
| 168 entity->parent_id_string()) { | 172 entity->parent_id_string()) { |
| 169 entry_response->set_parent_id_string( | 173 entry_response->set_parent_id_string( |
| 170 response->commit().entryresponse(i).id_string()); | 174 response->commit().entryresponse(i).id_string()); |
| 171 } | 175 } |
| 172 } | 176 } |
| 173 } | 177 } |
| 174 | 178 |
| 175 void SetLastErrorCode(CommitResponse::ResponseType error_code, | 179 void SetLastErrorCode(sync_pb::CommitResponse::ResponseType error_code, |
| 176 sync_pb::ClientToServerResponse* response) { | 180 sync_pb::ClientToServerResponse* response) { |
| 177 sync_pb::CommitResponse_EntryResponse* entry_response = | 181 sync_pb::CommitResponse_EntryResponse* entry_response = |
| 178 response->mutable_commit()->mutable_entryresponse( | 182 response->mutable_commit()->mutable_entryresponse( |
| 179 response->mutable_commit()->entryresponse_size() - 1); | 183 response->mutable_commit()->entryresponse_size() - 1); |
| 180 entry_response->set_response_type(error_code); | 184 entry_response->set_response_type(error_code); |
| 181 } | 185 } |
| 182 | 186 |
| 183 TestIdFactory id_factory_; | 187 TestIdFactory id_factory_; |
| 184 private: | 188 private: |
| 185 int64 next_old_revision_; | 189 int64 next_old_revision_; |
| 186 int64 next_new_revision_; | 190 int64 next_new_revision_; |
| 187 int64 next_server_position_; | 191 int64 next_server_position_; |
| 188 DISALLOW_COPY_AND_ASSIGN(ProcessCommitResponseCommandTest); | 192 DISALLOW_COPY_AND_ASSIGN(ProcessCommitResponseCommandTest); |
| 189 }; | 193 }; |
| 190 | 194 |
| 191 TEST_F(ProcessCommitResponseCommandTest, MultipleCommitIdProjections) { | 195 TEST_F(ProcessCommitResponseCommandTest, MultipleCommitIdProjections) { |
| 192 sessions::OrderedCommitSet commit_set(session()->routing_info()); | 196 sessions::OrderedCommitSet commit_set(session()->routing_info()); |
| 193 syncer::ClientToServerMessage request; | 197 sync_pb::ClientToServerMessage request; |
| 194 syncer::ClientToServerResponse response; | 198 sync_pb::ClientToServerResponse response; |
| 195 | 199 |
| 196 Id bookmark_folder_id = id_factory_.NewLocalId(); | 200 Id bookmark_folder_id = id_factory_.NewLocalId(); |
| 197 Id bookmark_id1 = id_factory_.NewLocalId(); | 201 Id bookmark_id1 = id_factory_.NewLocalId(); |
| 198 Id bookmark_id2 = id_factory_.NewLocalId(); | 202 Id bookmark_id2 = id_factory_.NewLocalId(); |
| 199 Id pref_id1 = id_factory_.NewLocalId(), pref_id2 = id_factory_.NewLocalId(); | 203 Id pref_id1 = id_factory_.NewLocalId(), pref_id2 = id_factory_.NewLocalId(); |
| 200 Id autofill_id1 = id_factory_.NewLocalId(); | 204 Id autofill_id1 = id_factory_.NewLocalId(); |
| 201 Id autofill_id2 = id_factory_.NewLocalId(); | 205 Id autofill_id2 = id_factory_.NewLocalId(); |
| 202 CreateUnprocessedCommitResult(bookmark_folder_id, id_factory_.root(), | 206 CreateUnprocessedCommitResult(bookmark_folder_id, id_factory_.root(), |
| 203 "A bookmark folder", syncer::BOOKMARKS, | 207 "A bookmark folder", syncer::BOOKMARKS, |
| 204 &commit_set, &request, &response); | 208 &commit_set, &request, &response); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 // In particular, the folder has 50 children, which alternate between being | 271 // In particular, the folder has 50 children, which alternate between being |
| 268 // new items and preexisting items. This mixture of new and old is meant to | 272 // new items and preexisting items. This mixture of new and old is meant to |
| 269 // be a torture test of the code in ProcessCommitResponseCommand that changes | 273 // be a torture test of the code in ProcessCommitResponseCommand that changes |
| 270 // an item's ID from a local ID to a server-generated ID on the first commit. | 274 // an item's ID from a local ID to a server-generated ID on the first commit. |
| 271 // We commit only the first 25 children in the sibling order, leaving the | 275 // We commit only the first 25 children in the sibling order, leaving the |
| 272 // second 25 children as unsynced items. http://crbug.com/33081 describes | 276 // second 25 children as unsynced items. http://crbug.com/33081 describes |
| 273 // how this scenario used to fail, reversing the order for the second half | 277 // how this scenario used to fail, reversing the order for the second half |
| 274 // of the children. | 278 // of the children. |
| 275 TEST_F(ProcessCommitResponseCommandTest, NewFolderCommitKeepsChildOrder) { | 279 TEST_F(ProcessCommitResponseCommandTest, NewFolderCommitKeepsChildOrder) { |
| 276 sessions::OrderedCommitSet commit_set(session()->routing_info()); | 280 sessions::OrderedCommitSet commit_set(session()->routing_info()); |
| 277 syncer::ClientToServerMessage request; | 281 sync_pb::ClientToServerMessage request; |
| 278 syncer::ClientToServerResponse response; | 282 sync_pb::ClientToServerResponse response; |
| 279 | 283 |
| 280 // Create the parent folder, a new item whose ID will change on commit. | 284 // Create the parent folder, a new item whose ID will change on commit. |
| 281 Id folder_id = id_factory_.NewLocalId(); | 285 Id folder_id = id_factory_.NewLocalId(); |
| 282 CreateUnprocessedCommitResult(folder_id, id_factory_.root(), "A", | 286 CreateUnprocessedCommitResult(folder_id, id_factory_.root(), "A", |
| 283 syncer::BOOKMARKS, | 287 syncer::BOOKMARKS, |
| 284 &commit_set, &request, &response); | 288 &commit_set, &request, &response); |
| 285 | 289 |
| 286 // Verify that the item is reachable. | 290 // Verify that the item is reachable. |
| 287 { | 291 { |
| 288 syncable::ReadTransaction trans(FROM_HERE, directory()); | 292 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 }; | 399 }; |
| 396 INSTANTIATE_TEST_CASE_P(ProcessCommitResponse, | 400 INSTANTIATE_TEST_CASE_P(ProcessCommitResponse, |
| 397 MixedResult, | 401 MixedResult, |
| 398 testing::Range(0, 1 << TEST_PARAM_BIT_COUNT)); | 402 testing::Range(0, 1 << TEST_PARAM_BIT_COUNT)); |
| 399 | 403 |
| 400 // This test commits 2 items (one bookmark, one autofill) and validates what | 404 // This test commits 2 items (one bookmark, one autofill) and validates what |
| 401 // happens to the extensions activity records. Commits could fail or succeed, | 405 // happens to the extensions activity records. Commits could fail or succeed, |
| 402 // depending on the test parameter. | 406 // depending on the test parameter. |
| 403 TEST_P(MixedResult, ExtensionActivity) { | 407 TEST_P(MixedResult, ExtensionActivity) { |
| 404 sessions::OrderedCommitSet commit_set(session()->routing_info()); | 408 sessions::OrderedCommitSet commit_set(session()->routing_info()); |
| 405 syncer::ClientToServerMessage request; | 409 sync_pb::ClientToServerMessage request; |
| 406 syncer::ClientToServerResponse response; | 410 sync_pb::ClientToServerResponse response; |
| 407 | 411 |
| 408 EXPECT_NE(routing_info().find(syncer::BOOKMARKS)->second, | 412 EXPECT_NE(routing_info().find(syncer::BOOKMARKS)->second, |
| 409 routing_info().find(syncer::AUTOFILL)->second) | 413 routing_info().find(syncer::AUTOFILL)->second) |
| 410 << "To not be lame, this test requires more than one active group."; | 414 << "To not be lame, this test requires more than one active group."; |
| 411 | 415 |
| 412 // Bookmark item setup. | 416 // Bookmark item setup. |
| 413 CreateUnprocessedCommitResult(id_factory_.NewServerId(), | 417 CreateUnprocessedCommitResult(id_factory_.NewServerId(), |
| 414 id_factory_.root(), "Some bookmark", syncer::BOOKMARKS, | 418 id_factory_.root(), "Some bookmark", syncer::BOOKMARKS, |
| 415 &commit_set, &request, &response); | 419 &commit_set, &request, &response); |
| 416 if (ShouldFailBookmarkCommit()) | 420 if (ShouldFailBookmarkCommit()) |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 445 EXPECT_EQ("xyz", final_monitor_records["xyz"].extension_id); | 449 EXPECT_EQ("xyz", final_monitor_records["xyz"].extension_id); |
| 446 EXPECT_EQ(2049U, final_monitor_records["ABC"].bookmark_write_count); | 450 EXPECT_EQ(2049U, final_monitor_records["ABC"].bookmark_write_count); |
| 447 EXPECT_EQ(4U, final_monitor_records["xyz"].bookmark_write_count); | 451 EXPECT_EQ(4U, final_monitor_records["xyz"].bookmark_write_count); |
| 448 } else { | 452 } else { |
| 449 EXPECT_TRUE(final_monitor_records.empty()) | 453 EXPECT_TRUE(final_monitor_records.empty()) |
| 450 << "Should not restore records after successful bookmark commit."; | 454 << "Should not restore records after successful bookmark commit."; |
| 451 } | 455 } |
| 452 } | 456 } |
| 453 | 457 |
| 454 } // namespace syncer | 458 } // namespace syncer |
| OLD | NEW |