Home | History | Annotate | Download | only in engine
      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:
     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 
    165   void FailNextPostBufferToPathCall() { countdown_to_postbuffer_fail_ = 1; }
    166   void FailNthPostBufferToPathCall(int n) { countdown_to_postbuffer_fail_ = n; }
    167 
    168   void SetKeystoreKey(const std::string& key);
    169 
    170   void FailNonPeriodicGetUpdates() { fail_non_periodic_get_updates_ = true; }
    171 
    172   // Simple inspectors.
    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 
    181   const std::vector<syncable::Id>& committed_ids() const {
    182     return committed_ids_;
    183   }
    184   const std::vector<sync_pb::CommitMessage*>& commit_messages() const {
    185     return commit_messages_.get();
    186   }
    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 
    202   void set_conflict_all_commits(bool value) {
    203     conflict_all_commits_ = value;
    204   }
    205   void set_next_new_id(int value) {
    206     next_new_id_ = value;
    207   }
    208   void set_conflict_n_commits(int value) {
    209     conflict_n_commits_ = value;
    210   }
    211 
    212   void set_use_legacy_bookmarks_protocol(bool value) {
    213     use_legacy_bookmarks_protocol_ = value;
    214   }
    215 
    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.
    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.
    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.
    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.
    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.
    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