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 |