| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "sync/test/engine/mock_model_type_worker.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include "base/logging.h" | |
| 11 #include "sync/internal_api/public/base/model_type.h" | |
| 12 #include "sync/syncable/syncable_util.h" | |
| 13 #include "testing/gtest/include/gtest/gtest.h" | |
| 14 | |
| 15 namespace syncer_v2 { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 std::string GenerateTagHash(const std::string& tag) { | |
| 20 return syncer::syncable::GenerateSyncableHash(syncer::PREFERENCES, tag); | |
| 21 } | |
| 22 | |
| 23 sync_pb::EntitySpecifics GenerateSpecifics(const std::string& tag, | |
| 24 const std::string& value) { | |
| 25 sync_pb::EntitySpecifics specifics; | |
| 26 specifics.mutable_preference()->set_name(tag); | |
| 27 specifics.mutable_preference()->set_value(value); | |
| 28 return specifics; | |
| 29 } | |
| 30 | |
| 31 } // namespace | |
| 32 | |
| 33 MockModelTypeWorker::MockModelTypeWorker( | |
| 34 const sync_pb::DataTypeState& data_type_state, | |
| 35 ModelTypeProcessor* processor) | |
| 36 : data_type_state_(data_type_state), processor_(processor) {} | |
| 37 | |
| 38 MockModelTypeWorker::~MockModelTypeWorker() {} | |
| 39 | |
| 40 void MockModelTypeWorker::EnqueueForCommit(const CommitRequestDataList& list) { | |
| 41 pending_commits_.push_back(list); | |
| 42 } | |
| 43 | |
| 44 size_t MockModelTypeWorker::GetNumPendingCommits() const { | |
| 45 return pending_commits_.size(); | |
| 46 } | |
| 47 | |
| 48 CommitRequestDataList MockModelTypeWorker::GetNthPendingCommit(size_t n) const { | |
| 49 DCHECK_LT(n, GetNumPendingCommits()); | |
| 50 return pending_commits_[n]; | |
| 51 } | |
| 52 | |
| 53 bool MockModelTypeWorker::HasPendingCommitForTag(const std::string& tag) const { | |
| 54 const std::string tag_hash = GenerateTagHash(tag); | |
| 55 for (const CommitRequestDataList& commit : pending_commits_) { | |
| 56 for (const CommitRequestData& data : commit) { | |
| 57 if (data.entity->client_tag_hash == tag_hash) { | |
| 58 return true; | |
| 59 } | |
| 60 } | |
| 61 } | |
| 62 return false; | |
| 63 } | |
| 64 | |
| 65 CommitRequestData MockModelTypeWorker::GetLatestPendingCommitForTag( | |
| 66 const std::string& tag) const { | |
| 67 const std::string tag_hash = GenerateTagHash(tag); | |
| 68 // Iterate backward through the sets of commit requests to find the most | |
| 69 // recent one that applies to the specified tag_hash. | |
| 70 for (auto rev_it = pending_commits_.rbegin(); | |
| 71 rev_it != pending_commits_.rend(); ++rev_it) { | |
| 72 for (const CommitRequestData& data : *rev_it) { | |
| 73 if (data.entity->client_tag_hash == tag_hash) { | |
| 74 return data; | |
| 75 } | |
| 76 } | |
| 77 } | |
| 78 NOTREACHED() << "Could not find commit for tag hash " << tag_hash << "."; | |
| 79 return CommitRequestData(); | |
| 80 } | |
| 81 | |
| 82 void MockModelTypeWorker::ExpectNthPendingCommit(size_t n, | |
| 83 const std::string& tag, | |
| 84 const std::string& value) { | |
| 85 const CommitRequestDataList& list = GetNthPendingCommit(n); | |
| 86 ASSERT_EQ(1U, list.size()); | |
| 87 const EntityData& data = list[0].entity.value(); | |
| 88 EXPECT_EQ(GenerateTagHash(tag), data.client_tag_hash); | |
| 89 EXPECT_EQ(value, data.specifics.preference().value()); | |
| 90 } | |
| 91 | |
| 92 void MockModelTypeWorker::ExpectPendingCommits( | |
| 93 const std::vector<std::string>& tags) { | |
| 94 EXPECT_EQ(tags.size(), GetNumPendingCommits()); | |
| 95 for (size_t i = 0; i < tags.size(); i++) { | |
| 96 const CommitRequestDataList& commits = GetNthPendingCommit(i); | |
| 97 EXPECT_EQ(1U, commits.size()); | |
| 98 EXPECT_EQ(GenerateTagHash(tags[i]), commits[0].entity->client_tag_hash) | |
| 99 << "Hash for tag " << tags[i] << " doesn't match."; | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 void MockModelTypeWorker::UpdateFromServer(const std::string& tag, | |
| 104 const std::string& value) { | |
| 105 UpdateFromServer(tag, value, 1); | |
| 106 } | |
| 107 | |
| 108 void MockModelTypeWorker::UpdateFromServer(const std::string& tag, | |
| 109 const std::string& value, | |
| 110 int64_t version_offset) { | |
| 111 UpdateFromServer(tag, value, version_offset, | |
| 112 data_type_state_.encryption_key_name()); | |
| 113 } | |
| 114 | |
| 115 void MockModelTypeWorker::UpdateFromServer(const std::string& tag, | |
| 116 const std::string& value, | |
| 117 int64_t version_offset, | |
| 118 const std::string& ekn) { | |
| 119 UpdateResponseDataList update; | |
| 120 update.push_back(GenerateUpdateData(tag, value, version_offset, ekn)); | |
| 121 processor_->OnUpdateReceived(data_type_state_, update); | |
| 122 } | |
| 123 | |
| 124 UpdateResponseData MockModelTypeWorker::GenerateUpdateData( | |
| 125 const std::string& tag, | |
| 126 const std::string& value, | |
| 127 int64_t version_offset, | |
| 128 const std::string& ekn) { | |
| 129 const std::string tag_hash = GenerateTagHash(tag); | |
| 130 // Overwrite the existing server version if this is the new highest version. | |
| 131 int64_t old_version = GetServerVersion(tag_hash); | |
| 132 int64_t version = old_version + version_offset; | |
| 133 if (version > old_version) { | |
| 134 SetServerVersion(tag_hash, version); | |
| 135 } | |
| 136 | |
| 137 EntityData data; | |
| 138 data.id = GenerateId(tag_hash); | |
| 139 data.client_tag_hash = tag_hash; | |
| 140 data.specifics = GenerateSpecifics(tag, value); | |
| 141 // These elements should have no effect on behavior, but we set them anyway | |
| 142 // so we can test they are properly copied around the system if we want to. | |
| 143 data.creation_time = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1); | |
| 144 data.modification_time = | |
| 145 data.creation_time + base::TimeDelta::FromSeconds(version); | |
| 146 data.non_unique_name = data.specifics.preference().name(); | |
| 147 | |
| 148 UpdateResponseData response_data; | |
| 149 response_data.entity = data.PassToPtr(); | |
| 150 response_data.response_version = version; | |
| 151 response_data.encryption_key_name = ekn; | |
| 152 | |
| 153 return response_data; | |
| 154 } | |
| 155 | |
| 156 void MockModelTypeWorker::TombstoneFromServer(const std::string& tag) { | |
| 157 const std::string tag_hash = GenerateTagHash(tag); | |
| 158 int64_t old_version = GetServerVersion(tag_hash); | |
| 159 int64_t version = old_version + 1; | |
| 160 SetServerVersion(tag_hash, version); | |
| 161 | |
| 162 EntityData data; | |
| 163 data.id = GenerateId(tag_hash); | |
| 164 data.client_tag_hash = tag_hash; | |
| 165 // These elements should have no effect on behavior, but we set them anyway | |
| 166 // so we can test they are properly copied around the system if we want to. | |
| 167 data.creation_time = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1); | |
| 168 data.modification_time = | |
| 169 data.creation_time + base::TimeDelta::FromSeconds(version); | |
| 170 data.non_unique_name = "Name Non Unique"; | |
| 171 | |
| 172 UpdateResponseData response_data; | |
| 173 response_data.entity = data.PassToPtr(); | |
| 174 response_data.response_version = version; | |
| 175 response_data.encryption_key_name = data_type_state_.encryption_key_name(); | |
| 176 | |
| 177 UpdateResponseDataList list; | |
| 178 list.push_back(response_data); | |
| 179 processor_->OnUpdateReceived(data_type_state_, list); | |
| 180 } | |
| 181 | |
| 182 void MockModelTypeWorker::AckOnePendingCommit() { | |
| 183 CommitResponseDataList list; | |
| 184 for (const CommitRequestData& data : pending_commits_.front()) { | |
| 185 list.push_back(SuccessfulCommitResponse(data)); | |
| 186 } | |
| 187 pending_commits_.pop_front(); | |
| 188 processor_->OnCommitCompleted(data_type_state_, list); | |
| 189 } | |
| 190 | |
| 191 CommitResponseData MockModelTypeWorker::SuccessfulCommitResponse( | |
| 192 const CommitRequestData& request_data) { | |
| 193 const EntityData& entity = request_data.entity.value(); | |
| 194 const std::string& client_tag_hash = entity.client_tag_hash; | |
| 195 | |
| 196 CommitResponseData response_data; | |
| 197 | |
| 198 if (request_data.base_version == 0) { | |
| 199 // Server assigns new ID to newly committed items. | |
| 200 DCHECK(entity.id.empty()); | |
| 201 response_data.id = entity.id; | |
| 202 } else { | |
| 203 // Otherwise we reuse the ID from the request. | |
| 204 response_data.id = GenerateId(client_tag_hash); | |
| 205 } | |
| 206 | |
| 207 response_data.client_tag_hash = client_tag_hash; | |
| 208 response_data.sequence_number = request_data.sequence_number; | |
| 209 response_data.specifics_hash = request_data.specifics_hash; | |
| 210 | |
| 211 // Increment the server version on successful commit. | |
| 212 int64_t version = GetServerVersion(client_tag_hash); | |
| 213 version++; | |
| 214 SetServerVersion(client_tag_hash, version); | |
| 215 | |
| 216 response_data.response_version = version; | |
| 217 | |
| 218 return response_data; | |
| 219 } | |
| 220 | |
| 221 void MockModelTypeWorker::UpdateWithEncryptionKey(const std::string& ekn) { | |
| 222 UpdateWithEncryptionKey(ekn, UpdateResponseDataList()); | |
| 223 } | |
| 224 | |
| 225 void MockModelTypeWorker::UpdateWithEncryptionKey( | |
| 226 const std::string& ekn, | |
| 227 const UpdateResponseDataList& update) { | |
| 228 data_type_state_.set_encryption_key_name(ekn); | |
| 229 processor_->OnUpdateReceived(data_type_state_, update); | |
| 230 } | |
| 231 | |
| 232 std::string MockModelTypeWorker::GenerateId(const std::string& tag_hash) { | |
| 233 return "FakeId:" + tag_hash; | |
| 234 } | |
| 235 | |
| 236 int64_t MockModelTypeWorker::GetServerVersion(const std::string& tag_hash) { | |
| 237 std::map<const std::string, int64_t>::const_iterator it; | |
| 238 it = server_versions_.find(tag_hash); | |
| 239 if (it == server_versions_.end()) { | |
| 240 return 0; | |
| 241 } else { | |
| 242 return it->second; | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 void MockModelTypeWorker::SetServerVersion(const std::string& tag_hash, | |
| 247 int64_t version) { | |
| 248 server_versions_[tag_hash] = version; | |
| 249 } | |
| 250 | |
| 251 } // namespace syncer_v2 | |
| OLD | NEW |