Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: sync/test/fake_server/fake_server.cc

Issue 115243007: Basic implementation of the Sync C++ fake server (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix constant for clang Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 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/fake_server/fake_server.h"
6
7 #include <limits>
8 #include <string>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "sync/internal_api/public/base/model_type.h"
16 #include "sync/protocol/sync.pb.h"
17
18 using std::string;
19
20 // The parent tag for childen of the root node.
21 static const char kRootParentTag[] = "0";
22
23 namespace syncer {
24 namespace {
25
26 // A filter used during GetUpdates calls to determine what information to
27 // send back to the client. There is a 1:1 correspondence between any given
28 // GetUpdates call and an UpdateSieve instance.
29 class UpdateSieve {
30 public:
31 ~UpdateSieve() { }
32
33 // Factory method for creating an UpdateSieve.
34 static scoped_ptr<UpdateSieve> Create(
35 const sync_pb::GetUpdatesMessage& get_updates_message);
36
37 // Sets the progress markers in |get_updates_response| given the progress
38 // markers from the original GetUpdatesMessage and |new_version| (the latest
39 // version in the entries sent back).
40 void UpdateProgressMarkers(
41 int64 new_version,
42 sync_pb::GetUpdatesResponse* get_updates_response) const {
43 ModelTypeToVersionMap::const_iterator it;
44 for (it = request_from_version_.begin(); it != request_from_version_.end();
45 ++it) {
46 sync_pb::DataTypeProgressMarker* new_marker =
47 get_updates_response->add_new_progress_marker();
48 new_marker->set_data_type_id(
49 GetSpecificsFieldNumberFromModelType(it->first));
50
51 int64 version = std::max(new_version, it->second);
52 new_marker->set_token(base::Int64ToString(version));
53 }
54 }
55
56 // Determines whether the server should send |entity| to the client based
57 // on its type and version.
58 bool ClientWantsItem(const sync_pb::SyncEntity& entity) const {
59 ModelTypeToVersionMap::const_iterator it =
60 request_from_version_.find(GetModelType(entity));
61
62 return it == request_from_version_.end() ?
63 false : it->second < entity.version();
64 }
65
66 // Returns the mininum version seen across all types.
67 int64 GetMinVersion() const {
68 return min_version_;
69 }
70
71 // Returns the data type IDs of types being synced for the first time.
72 std::vector<ModelType> GetFirstTimeTypes() const {
73 std::vector<ModelType> types;
74
75 ModelTypeToVersionMap::const_iterator it;
76 for (it = request_from_version_.begin(); it != request_from_version_.end();
77 ++it) {
78 if (it->second == 0)
79 types.push_back(it->first);
80 }
81
82 return types;
83 }
84
85 private:
86 typedef std::map<ModelType, int64> ModelTypeToVersionMap;
87
88 // Creates an UpdateSieve.
89 UpdateSieve(const ModelTypeToVersionMap request_from_version,
90 const int64 min_version)
91 : request_from_version_(request_from_version),
92 min_version_(min_version) { }
93
94 // Maps data type IDs to the latest version seen for that type.
95 const ModelTypeToVersionMap request_from_version_;
96
97 // The minimum version seen among all data types.
98 const int min_version_;
99 };
100
101 scoped_ptr<UpdateSieve> UpdateSieve::Create(
102 const sync_pb::GetUpdatesMessage& get_updates_message) {
103 DCHECK_GT(get_updates_message.from_progress_marker_size(), 0);
104
105 UpdateSieve::ModelTypeToVersionMap request_from_version;
106 int64 min_version = std::numeric_limits<int64>::max();
107 for (int i = 0; i < get_updates_message.from_progress_marker_size(); i++) {
108 sync_pb::DataTypeProgressMarker marker =
109 get_updates_message.from_progress_marker(i);
110
111 int64 version;
112 if (!marker.has_token() || marker.token().empty()) {
113 // Initialize the version on the first request for this type.
114 version = 0;
115 } else {
116 DCHECK(base::StringToInt64(marker.token(), &version));
117 }
118
119 ModelType model_type = GetModelTypeFromSpecificsFieldNumber(
120 marker.data_type_id());
121 request_from_version[model_type] = version;
122
123 if (version < min_version)
124 min_version = version;
125 }
126
127 return scoped_ptr<UpdateSieve>(
128 new UpdateSieve(request_from_version, min_version));
129 }
130
131 } // namespace
132
133 FakeServer::FakeServer() : version_(0), birthday_("1234567890") {
134 keystore_keys_.push_back("1111111111111111");
135 }
136
137 FakeServer::~FakeServer() { }
138
139 void FakeServer::CreateDefaultPermanentItems(
140 const std::vector<ModelType>& first_time_types) {
141 for (std::vector<ModelType>::const_iterator it = first_time_types.begin();
142 it != first_time_types.end(); ++it) {
143 if (!ModelTypeSet::All().Has(*it)) {
144 NOTREACHED() << "An unexpected ModelType was encountered.";
145 }
146
147 ModelType model_type = *it;
148 CreateSyncEntity(model_type,
149 ModelTypeToRootTag(model_type),
150 ModelTypeToString(model_type),
151 kRootParentTag);
152
153 if (model_type == BOOKMARKS) {
154 CreateSyncEntity(BOOKMARKS,
155 "bookmark_bar",
156 "Bookmark Bar",
157 ModelTypeToRootTag(BOOKMARKS));
158 CreateSyncEntity(BOOKMARKS,
159 "other_bookmarks",
160 "Other Bookmarks",
161 ModelTypeToRootTag(BOOKMARKS));
162 }
163 }
164
165
166 // TODO(pvalenzuela): Create the mobile bookmarks folder when the fake server
167 // is used by mobile tests.
168 }
169
170 void FakeServer::CreateSyncEntity(ModelType model_type,
171 const std::string& id,
172 const std::string& name,
173 const std::string& parent_tag) {
174 DCHECK(!id.empty());
175 DCHECK(!name.empty());
176 DCHECK(!parent_tag.empty());
177
178 sync_pb::SyncEntity entity;
179 entity.set_id_string(id);
180 entity.set_non_unique_name(name);
181 entity.set_name(name);
182 entity.set_server_defined_unique_tag(id);
183 entity.set_folder(true);
184 entity.set_deleted(false);
185
186 entity.set_parent_id_string(parent_tag);
187
188 if (parent_tag != kRootParentTag && model_type == BOOKMARKS) {
189 // Use a dummy value here.
190 entity.set_position_in_parent(1337);
191 }
192
193 sync_pb::EntitySpecifics* specifics = entity.mutable_specifics();
194 AddDefaultFieldValue(model_type, specifics);
195
196 SaveEntity(entity);
197 }
198
199 void FakeServer::SaveEntity(sync_pb::SyncEntity entity) {
200 version_++;
201 entity.set_version(version_);
202 entity.set_sync_timestamp(version_);
203
204 sync_pb::SyncEntity original_entity = entities_[entity.id_string()];
205 entity.set_originator_cache_guid(original_entity.originator_cache_guid());
206 entity.set_originator_client_item_id(
207 original_entity.originator_client_item_id());
208
209 entities_[entity.id_string()] = entity;
210 }
211
212 int FakeServer::HandleCommand(string request,
213 int* response_code,
214 string* response) {
215 sync_pb::ClientToServerMessage message;
216 DCHECK(message.ParseFromString(request));
217
218 sync_pb::ClientToServerResponse response_proto;
219 switch (message.message_contents()) {
220 case sync_pb::ClientToServerMessage::GET_UPDATES:
221 response_proto = HandleGetUpdatesRequest(message);
222 break;
223 case sync_pb::ClientToServerMessage::COMMIT:
224 response_proto = HandleCommitRequest(message);
225 break;
226 default:
227 // Any nonzero int will indicate a failure here. This one happens to
228 // be net::ERR_NOT_IMPLEMENTED.
229 return -11;
230 }
231
232 *response_code = 200;
233 *response = response_proto.SerializeAsString();
234 return 0;
235 }
236
237 bool SyncEntityVersionComparator(const sync_pb::SyncEntity& first,
238 const sync_pb::SyncEntity& second) {
239 return first.version() < second.version();
240 }
241
242 sync_pb::ClientToServerResponse FakeServer::HandleGetUpdatesRequest(
243 const sync_pb::ClientToServerMessage& message) {
244 sync_pb::ClientToServerResponse response;
245 response.set_error_code(sync_pb::SyncEnums::SUCCESS);
246 response.set_store_birthday(birthday_);
247
248 sync_pb::GetUpdatesResponse* get_updates_response =
249 response.mutable_get_updates();
250 // TODO(pvalenzuela): Implement batching instead of sending all information
251 // at once.
252 get_updates_response->set_changes_remaining(0);
253
254 scoped_ptr<UpdateSieve> sieve = UpdateSieve::Create(message.get_updates());
255 CreateDefaultPermanentItems(sieve->GetFirstTimeTypes());
256
257 int64 min_version = sieve->GetMinVersion();
258
259 bool send_encryption_keys_based_on_nigori = false;
260 int64 max_response_version = 0;
261 for (EntityMap::iterator it = entities_.begin(); it != entities_.end();
262 ++it) {
263 sync_pb::SyncEntity entity = it->second;
264 if (entity.version() > min_version && sieve->ClientWantsItem(entity)) {
265 sync_pb::SyncEntity* response_entity =
266 get_updates_response->add_entries();
267 response_entity->CopyFrom(entity);
268 max_response_version = std::max(max_response_version,
269 response_entity->version());
270
271 if (response_entity->name() == ModelTypeToString(NIGORI)) {
272 send_encryption_keys_based_on_nigori =
273 response_entity->specifics().nigori().passphrase_type() ==
274 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE;
275 }
276 }
277 }
278
279 if (send_encryption_keys_based_on_nigori ||
280 message.get_updates().need_encryption_key()) {
281 for (std::vector<std::string>::iterator it = keystore_keys_.begin();
282 it != keystore_keys_.end(); ++it) {
283 get_updates_response->add_encryption_keys(*it);
284 }
285 }
286
287 sieve->UpdateProgressMarkers(max_response_version, get_updates_response);
288
289 return response;
290 }
291
292 sync_pb::SyncEntity FakeServer::CommitEntity(sync_pb::SyncEntity entity,
293 string guid) {
294 // TODO(pvalenzuela): Implement this. Right now this method cheats and
295 // doesn't actually commit.
296 return entity;
297 }
298
299 sync_pb::ClientToServerResponse FakeServer::HandleCommitRequest(
300 const sync_pb::ClientToServerMessage& message) {
301 sync_pb::ClientToServerResponse response;
302 response.set_error_code(sync_pb::SyncEnums::SUCCESS);
303 response.set_store_birthday(birthday_);
304
305 sync_pb::CommitMessage commit = message.commit();
306 string guid = commit.cache_guid();
307
308 sync_pb::CommitResponse* commit_response = response.mutable_commit();
309
310 ::google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>::const_iterator it;
311 for (it = commit.entries().begin(); it != commit.entries().end(); ++it) {
312 sync_pb::CommitResponse_EntryResponse* entry_response =
313 commit_response->add_entryresponse();
314
315 sync_pb::SyncEntity server_entity = CommitEntity(*it, guid);
316
317 entry_response->set_id_string(server_entity.id_string());
318 entry_response->set_response_type(sync_pb::CommitResponse::SUCCESS);
319 entry_response->set_version(it->version() + 1);
320 }
321
322 return response;
323 }
324
325 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/test/fake_server/fake_server.h ('k') | sync/test/fake_server/fake_server_http_post_provider.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698