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