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