• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 //
5 // Mock ServerConnectionManager class for use in client unit tests.
6 
7 #ifndef SYNC_TEST_ENGINE_MOCK_CONNECTION_MANAGER_H_
8 #define SYNC_TEST_ENGINE_MOCK_CONNECTION_MANAGER_H_
9 
10 #include <bitset>
11 #include <list>
12 #include <string>
13 #include <vector>
14 
15 #include "base/callback.h"
16 #include "base/compiler_specific.h"
17 #include "base/memory/scoped_vector.h"
18 #include "base/synchronization/lock.h"
19 #include "sync/engine/net/server_connection_manager.h"
20 #include "sync/internal_api/public/base/model_type.h"
21 #include "sync/internal_api/public/base/unique_position.h"
22 #include "sync/protocol/sync.pb.h"
23 
24 namespace syncer {
25 
26 class MockConnectionManager : public ServerConnectionManager {
27  public:
28   class MidCommitObserver {
29    public:
30     virtual void Observe() = 0;
31 
32    protected:
~MidCommitObserver()33     virtual ~MidCommitObserver() {}
34   };
35 
36   MockConnectionManager(syncable::Directory*,
37                         CancelationSignal* signal);
38   virtual ~MockConnectionManager();
39 
40   // Overridden ServerConnectionManager functions.
41   virtual bool PostBufferToPath(
42       PostBufferParams*,
43       const std::string& path,
44       const std::string& auth_token,
45       ScopedServerStatusWatcher* watcher) OVERRIDE;
46 
47   // Control of commit response.
48   // NOTE: Commit callback is invoked only once then reset.
49   void SetMidCommitCallback(const base::Closure& callback);
50   void SetMidCommitObserver(MidCommitObserver* observer);
51 
52   // Set this if you want commit to perform commit time rename. Will request
53   // that the client renames all commited entries, prepending this string.
54   void SetCommitTimeRename(std::string prepend);
55 
56   // Generic versions of AddUpdate functions. Tests using these function should
57   // compile for both the int64 and string id based versions of the server.
58   // The SyncEntity returned is only valid until the Sync is completed
59   // (e.g. with SyncShare.) It allows to add further entity properties before
60   // sync, using SetLastXXX() methods and/or GetMutableLastUpdate().
61   sync_pb::SyncEntity* AddUpdateDirectory(
62       syncable::Id id,
63       syncable::Id parent_id,
64       std::string name,
65       int64 version,
66       int64 sync_ts,
67       std::string originator_cache_guid,
68       std::string originator_client_item_id);
69   sync_pb::SyncEntity* AddUpdateBookmark(syncable::Id id,
70                                          syncable::Id parent_id,
71                                          std::string name,
72                                          int64 version,
73                                          int64 sync_ts,
74                                          std::string originator_cache_guid,
75                                          std::string originator_client_item_id);
76   // Versions of the AddUpdate functions that accept integer IDs.
77   sync_pb::SyncEntity* AddUpdateDirectory(
78       int id,
79       int parent_id,
80       std::string name,
81       int64 version,
82       int64 sync_ts,
83       std::string originator_cache_guid,
84       std::string originator_client_item_id);
85   sync_pb::SyncEntity* AddUpdateBookmark(int id,
86                                          int parent_id,
87                                          std::string name,
88                                          int64 version,
89                                          int64 sync_ts,
90                                          std::string originator_cache_guid,
91                                          std::string originator_client_item_id);
92   // New protocol versions of the AddUpdate functions.
93   sync_pb::SyncEntity* AddUpdateDirectory(
94       std::string id,
95       std::string parent_id,
96       std::string name,
97       int64 version,
98       int64 sync_ts,
99       std::string originator_cache_guid,
100       std::string originator_client_item_id);
101   sync_pb::SyncEntity* AddUpdateBookmark(std::string id,
102                                          std::string parent_id,
103                                          std::string name,
104                                          int64 version,
105                                          int64 sync_ts,
106                                          std::string originator_cache_guid,
107                                          std::string originator_client_item_id);
108   // Versions of the AddUpdate function that accept specifics.
109   sync_pb::SyncEntity* AddUpdateSpecifics(
110       int id,
111       int parent_id,
112       std::string name,
113       int64 version,
114       int64 sync_ts,
115       bool is_dir,
116       int64 position,
117       const sync_pb::EntitySpecifics& specifics);
118   sync_pb::SyncEntity* AddUpdateSpecifics(
119       int id,
120       int parent_id,
121       std::string name,
122       int64 version,
123       int64 sync_ts,
124       bool is_dir,
125       int64 position,
126       const sync_pb::EntitySpecifics& specifics,
127       std::string originator_cache_guid,
128       std::string originator_client_item_id);
129   sync_pb::SyncEntity* SetNigori(
130       int id,
131       int64 version,
132       int64 sync_ts,
133       const sync_pb::EntitySpecifics& specifics);
134   // Unique client tag variant for adding items.
135   sync_pb::SyncEntity* AddUpdatePref(std::string id,
136                                      std::string parent_id,
137                                      std::string client_tag,
138                                      int64 version,
139                                      int64 sync_ts);
140 
141   // Find the last commit sent by the client, and replay it for the next get
142   // updates command.  This can be used to simulate the GetUpdates that happens
143   // immediately after a successful commit.
144   sync_pb::SyncEntity* AddUpdateFromLastCommit();
145 
146   // Add a deleted item.  Deletion records typically contain no
147   // additional information beyond the deletion, and no specifics.
148   // The server may send the originator fields.
149   void AddUpdateTombstone(const syncable::Id& id);
150 
151   void SetLastUpdateDeleted();
152   void SetLastUpdateServerTag(const std::string& tag);
153   void SetLastUpdateClientTag(const std::string& tag);
154   void SetLastUpdateOriginatorFields(const std::string& client_id,
155                                      const std::string& entry_id);
156   void SetLastUpdatePosition(int64 position_in_parent);
157   void SetNewTimestamp(int ts);
158   void SetChangesRemaining(int64 count);
159 
160   // Add a new batch of updates after the current one.  Allows multiple
161   // GetUpdates responses to be buffered up, since the syncer may
162   // issue multiple requests during a sync cycle.
163   void NextUpdateBatch();
164 
FailNextPostBufferToPathCall()165   void FailNextPostBufferToPathCall() { countdown_to_postbuffer_fail_ = 1; }
FailNthPostBufferToPathCall(int n)166   void FailNthPostBufferToPathCall(int n) { countdown_to_postbuffer_fail_ = n; }
167 
168   void SetKeystoreKey(const std::string& key);
169 
FailNonPeriodicGetUpdates()170   void FailNonPeriodicGetUpdates() { fail_non_periodic_get_updates_ = true; }
171 
172   // Simple inspectors.
client_stuck()173   bool client_stuck() const { return client_stuck_; }
174 
175   // warning: These take ownership of their input.
176   void SetGUClientCommand(sync_pb::ClientCommand* command);
177   void SetCommitClientCommand(sync_pb::ClientCommand* command);
178 
179   void SetTransientErrorId(syncable::Id);
180 
committed_ids()181   const std::vector<syncable::Id>& committed_ids() const {
182     return committed_ids_;
183   }
commit_messages()184   const std::vector<sync_pb::CommitMessage*>& commit_messages() const {
185     return commit_messages_.get();
186   }
commit_responses()187   const std::vector<sync_pb::CommitResponse*>& commit_responses() const {
188     return commit_responses_.get();
189   }
190   // Retrieve the last sent commit message.
191   const sync_pb::CommitMessage& last_sent_commit() const;
192 
193   // Retrieve the last returned commit response.
194   const sync_pb::CommitResponse& last_commit_response() const;
195 
196   // Retrieve the last request submitted to the server (regardless of type).
197   const sync_pb::ClientToServerMessage& last_request() const;
198 
199   // Retrieve the cumulative collection of all requests sent by clients.
200   const std::vector<sync_pb::ClientToServerMessage>& requests() const;
201 
set_conflict_all_commits(bool value)202   void set_conflict_all_commits(bool value) {
203     conflict_all_commits_ = value;
204   }
set_next_new_id(int value)205   void set_next_new_id(int value) {
206     next_new_id_ = value;
207   }
set_conflict_n_commits(int value)208   void set_conflict_n_commits(int value) {
209     conflict_n_commits_ = value;
210   }
211 
set_use_legacy_bookmarks_protocol(bool value)212   void set_use_legacy_bookmarks_protocol(bool value) {
213     use_legacy_bookmarks_protocol_ = value;
214   }
215 
set_store_birthday(std::string new_birthday)216   void set_store_birthday(std::string new_birthday) {
217     // Multiple threads can set store_birthday_ in our tests, need to lock it to
218     // ensure atomic read/writes and avoid race conditions.
219     base::AutoLock lock(store_birthday_lock_);
220     store_birthday_ = new_birthday;
221   }
222 
223   // Retrieve the number of GetUpdates requests that the mock server has
224   // seen since the last time this function was called.  Can be used to
225   // verify that a GetUpdates actually did or did not happen after running
226   // the syncer.
GetAndClearNumGetUpdatesRequests()227   int GetAndClearNumGetUpdatesRequests() {
228     int result = num_get_updates_requests_;
229     num_get_updates_requests_ = 0;
230     return result;
231   }
232 
233   // Expect that GetUpdates will request exactly the types indicated in
234   // the bitset.
ExpectGetUpdatesRequestTypes(ModelTypeSet expected_filter)235   void ExpectGetUpdatesRequestTypes(ModelTypeSet expected_filter) {
236     expected_filter_ = expected_filter;
237   }
238 
239   void SetServerReachable();
240 
241   void SetServerNotReachable();
242 
243   // Updates our internal state as if we had attempted a connection.  Does not
244   // send notifications as a real connection attempt would.  This is useful in
245   // cases where we're mocking out most of the code that performs network
246   // requests.
247   void UpdateConnectionStatus();
248 
249   void SetServerStatus(HttpResponse::ServerConnectionCode server_status);
250 
251   // Return by copy to be thread-safe.
store_birthday()252   const std::string store_birthday() {
253     base::AutoLock lock(store_birthday_lock_);
254     return store_birthday_;
255   }
256 
257   // Explicitly indicate that we will not be fetching some updates.
ClearUpdatesQueue()258   void ClearUpdatesQueue() {
259     update_queue_.clear();
260   }
261 
262   // Locate the most recent update message for purpose of alteration.
263   sync_pb::SyncEntity* GetMutableLastUpdate();
264 
265  private:
266   sync_pb::SyncEntity* AddUpdateFull(syncable::Id id, syncable::Id parentid,
267                                      std::string name, int64 version,
268                                      int64 sync_ts,
269                                      bool is_dir);
270   sync_pb::SyncEntity* AddUpdateFull(std::string id,
271                                      std::string parentid, std::string name,
272                                      int64 version, int64 sync_ts,
273                                      bool is_dir);
274   sync_pb::SyncEntity* AddUpdateMeta(std::string id, std::string parentid,
275                                     std::string name, int64 version,
276                                     int64 sync_ts);
277 
278   // Functions to handle the various types of server request.
279   void ProcessGetUpdates(sync_pb::ClientToServerMessage* csm,
280                          sync_pb::ClientToServerResponse* response);
281   void ProcessCommit(sync_pb::ClientToServerMessage* csm,
282                      sync_pb::ClientToServerResponse* response_buffer);
283   void ProcessClearData(sync_pb::ClientToServerMessage* csm,
284                         sync_pb::ClientToServerResponse* response);
285   void AddDefaultBookmarkData(sync_pb::SyncEntity* entity, bool is_folder);
286 
287   // Determine if one entry in a commit should be rejected with a conflict.
288   bool ShouldConflictThisCommit();
289 
290   // Determine if the given item's commit request should be refused with
291   // a TRANSIENT_ERROR response.
292   bool ShouldTransientErrorThisId(syncable::Id id);
293 
294   // Generate a numeric position_in_parent value.  We use a global counter
295   // that only decreases; this simulates new objects always being added to the
296   // front of the ordering.
GeneratePositionInParent()297   int64 GeneratePositionInParent() {
298     return next_position_in_parent_--;
299   }
300 
301   // Get a mutable update response which will eventually be returned to the
302   // client.
303   sync_pb::GetUpdatesResponse* GetUpdateResponse();
304   void ApplyToken();
305 
306   // Determine whether an progress marker array (like that sent in
307   // GetUpdates.from_progress_marker) indicates that a particular ModelType
308   // should be included.
309   bool IsModelTypePresentInSpecifics(
310       const google::protobuf::RepeatedPtrField<
311           sync_pb::DataTypeProgressMarker>& filter,
312       ModelType value);
313 
314   sync_pb::DataTypeProgressMarker const* GetProgressMarkerForType(
315       const google::protobuf::RepeatedPtrField<
316           sync_pb::DataTypeProgressMarker>& filter,
317       ModelType value);
318 
319   // When false, we pretend to have network connectivity issues.
320   bool server_reachable_;
321 
322   // All IDs that have been committed.
323   std::vector<syncable::Id> committed_ids_;
324 
325   // List of IDs which should return a transient error.
326   std::vector<syncable::Id> transient_error_ids_;
327 
328   // Control of when/if we return conflicts.
329   bool conflict_all_commits_;
330   int conflict_n_commits_;
331 
332   // Commit messages we've sent, and responses we've returned.
333   ScopedVector<sync_pb::CommitMessage> commit_messages_;
334   ScopedVector<sync_pb::CommitResponse> commit_responses_;
335 
336   // The next id the mock will return to a commit.
337   int next_new_id_;
338 
339   // The store birthday we send to the client.
340   std::string store_birthday_;
341   base::Lock store_birthday_lock_;
342   bool store_birthday_sent_;
343   bool client_stuck_;
344   std::string commit_time_rename_prepended_string_;
345 
346   // On each PostBufferToPath() call, we decrement this counter.  The call fails
347   // iff we hit zero at that call.
348   int countdown_to_postbuffer_fail_;
349 
350   // Our directory.  Used only to ensure that we are not holding the transaction
351   // lock when performing network I/O.  Can be NULL if the test author is
352   // confident this can't happen.
353   syncable::Directory* directory_;
354 
355   // The updates we'll return to the next request.
356   std::list<sync_pb::GetUpdatesResponse> update_queue_;
357   base::Closure mid_commit_callback_;
358   MidCommitObserver* mid_commit_observer_;
359 
360   // The keystore key we return for a GetUpdates with need_encryption_key set.
361   std::string keystore_key_;
362 
363   // The AUTHENTICATE response we'll return for auth requests.
364   sync_pb::AuthenticateResponse auth_response_;
365   // What we use to determine if we should return SUCCESS or BAD_AUTH_TOKEN.
366   std::string valid_auth_token_;
367 
368   // Whether we are faking a server mandating clients to throttle requests.
369   // Protected by |response_code_override_lock_|.
370   bool throttling_;
371 
372   // Whether we are failing all requests by returning
373   // ClientToServerResponse::AUTH_INVALID.
374   // Protected by |response_code_override_lock_|.
375   bool fail_with_auth_invalid_;
376 
377   base::Lock response_code_override_lock_;
378 
379   // True if we are only accepting GetUpdatesCallerInfo::PERIODIC requests.
380   bool fail_non_periodic_get_updates_;
381 
382   scoped_ptr<sync_pb::ClientCommand> gu_client_command_;
383   scoped_ptr<sync_pb::ClientCommand> commit_client_command_;
384 
385   // The next value to use for the position_in_parent property.
386   int64 next_position_in_parent_;
387 
388   // The default is to use the newer sync_pb::BookmarkSpecifics-style protocol.
389   // If this option is set to true, then the MockConnectionManager will
390   // use the older sync_pb::SyncEntity_BookmarkData-style protocol.
391   bool use_legacy_bookmarks_protocol_;
392 
393   ModelTypeSet expected_filter_;
394 
395   int num_get_updates_requests_;
396 
397   std::string next_token_;
398 
399   std::vector<sync_pb::ClientToServerMessage> requests_;
400 
401   DISALLOW_COPY_AND_ASSIGN(MockConnectionManager);
402 };
403 
404 }  // namespace syncer
405 
406 #endif  // SYNC_TEST_ENGINE_MOCK_CONNECTION_MANAGER_H_
407