1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SYNC_TEST_FAKE_SERVER_H_
#define COMPONENTS_SYNC_TEST_FAKE_SERVER_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>
#include "base/location.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "base/values.h"
#include "components/sync/base/collaboration_id.h"
#include "components/sync/base/data_type.h"
#include "components/sync/engine/loopback_server/loopback_server.h"
#include "components/sync/engine/loopback_server/loopback_server_entity.h"
#include "components/sync/engine/loopback_server/persistent_bookmark_entity.h"
#include "components/sync/engine/loopback_server/persistent_tombstone_entity.h"
#include "components/sync/engine/loopback_server/persistent_unique_client_entity.h"
#include "components/sync/protocol/client_commands.pb.h"
#include "components/sync/protocol/deletion_origin.pb.h"
#include "components/sync/protocol/sync.pb.h"
#include "net/http/http_status_code.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace switches {
inline constexpr char kDisableFakeServerFailureOutput[] =
"disable-fake-server-failure-output";
} // namespace switches
namespace sync_pb {
class EntitySpecifics;
class DataTypeProgressMarker;
class SyncEntity;
enum SyncEnums_ErrorType : int;
} // namespace sync_pb
namespace fake_server {
// This function only compares one part of the markers, the time-independent
// hashes of the data served in the update. Apart from this, the progress
// markers for fake wallet data also include information about fetch time. This
// is in-line with the server behavior and -- as it keeps changing -- allows
// integration tests to wait for a GetUpdates call to finish, even if they don't
// contain data updates.
bool AreFullUpdateTypeDataProgressMarkersEquivalent(
const sync_pb::DataTypeProgressMarker& marker1,
const sync_pb::DataTypeProgressMarker& marker2);
// A fake version of the Sync server used for testing. This class is not thread
// safe.
// `switches::kDisableFakeServerFailureOutput` can be passed to the command line
// to avoid debug logs upon test failure.
class FakeServer : public syncer::LoopbackServer::ObserverForTests {
public:
class Observer {
public:
virtual ~Observer() = default;
// Called whenever a commit command is received by FakeServer. Note that
// Commit command may fail and hence it's not guaranteed that OnCommit()
// will be called. However, before any OnCommit() call there will be a
// corresponding OnWillCommit() call.
virtual void OnWillCommit() {}
// Called after FakeServer has processed a successful commit. The types
// updated as part of the commit are passed in `committed_data_types`.
virtual void OnCommit(syncer::DataTypeSet committed_data_types) {}
// Called whenever a get updates request is received by FakeServer.
virtual void OnWillGetUpdates(
const sync_pb::ClientToServerMessage& message) {}
// Called after FakeServer has processed a successful get updates request.
virtual void OnSuccessfulGetUpdates() {}
};
// Persists the server state to `loopback_server_dir` (useful for PRE_ tests).
explicit FakeServer(const base::FilePath& loopback_server_dir);
// Convenience version of the above which uses a new temporary directory.
FakeServer();
~FakeServer() override;
// Handles a /command POST (with the given `request`) to the server.
// `response` must not be null.
net::HttpStatusCode HandleCommand(const std::string& request,
std::string* response);
// Helpers for fetching the last Commit or GetUpdates messages, respectively.
// Returns true if the specified message existed, and false if no message has
// been received.
bool GetLastCommitMessage(sync_pb::ClientToServerMessage* message);
bool GetLastGetUpdatesMessage(sync_pb::ClientToServerMessage* message);
// Creates a `base::Value::Dict` representation of all entities present in the
// server. The dictionary keys are the strings generated by
// DataTypeToDebugString and the values are Value::Lists containing
// StringValue versions of entity names.
base::Value::Dict GetEntitiesAsDictForTesting();
// Returns all entities stored by the server of the given `data_type`.
// This method returns SyncEntity protocol buffer objects (instead of
// LoopbackServerEntity) so that callers can inspect datatype-specific data
// (e.g., the URL of a session tab). Permanent entities are excluded.
std::vector<sync_pb::SyncEntity> GetSyncEntitiesByDataType(
syncer::DataType data_type);
// Returns all permanent entities stored by the server of the given
// `data_type`. This method returns SyncEntity protocol buffer objects
// (instead of LoopbackServerEntity) so that callers can inspect
// datatype-specific data (e.g., the URL of a session tab).
std::vector<sync_pb::SyncEntity> GetPermanentSyncEntitiesByDataType(
syncer::DataType data_type);
// Returns all keystore keys from the server.
const std::vector<std::vector<uint8_t>>& GetKeystoreKeys() const;
// Triggers the keystore key rotation events on the server side: generating
// new keystore key and touching the Nigori node.
void TriggerKeystoreKeyRotation();
// Adds `entity` to the server's collection of entities. This method makes no
// guarantees that the added entity will result in successful server
// operations.
void InjectEntity(std::unique_ptr<syncer::LoopbackServerEntity> entity);
// Sets the Wallet card and address data to be served in following GetUpdates
// requests (any further GetUpdates response will be empty, indicating no
// change, if the client already has received `wallet_entities`).
//
// The returned value represents the timestamp of the write, such that any
// progress marker greater or equal to this timestamp must have processed the
// changes. See GetProgressMarkerTimestamp() below.
base::Time SetWalletData(
const std::vector<sync_pb::SyncEntity>& wallet_entities);
// Sets the Autofill offer data to be served in following GetUpdates
// requests (any further GetUpdates response will be empty, indicating no
// change, if the client already has received `offer_entities`).
//
// The returned value represents the timestamp of the write, such that any
// progress marker greater or equal to this timestamp must have processed the
// changes. See GetProgressMarkerTimestamp() below.
base::Time SetOfferData(
const std::vector<sync_pb::SyncEntity>& offer_entities);
// Sets the Google Wallet valuable data to be served in following GetUpdates
// requests (any further GetUpdates response will be empty, indicating no
// change, if the client already has received `valuable_entities`).
//
// The returned value represents the timestamp of the write, such that any
// progress marker greater or equal to this timestamp must have processed the
// changes. See GetProgressMarkerTimestamp() below.
base::Time SetValuableData(
const std::vector<sync_pb::SyncEntity>& valuable_entities);
// Allows the caller to know the timestamp corresponding to
// `progress_marker` as annotated by the FakeServer during the GetUpdates
// request that returned the progress marker.
static base::Time GetProgressMarkerTimestamp(
const sync_pb::DataTypeProgressMarker& progress_marker);
// Modifies the entity on the server with the given `id`. The entity's
// EntitySpecifics are replaced with `updated_specifics` and its version is
// updated. If the given `id` does not exist or the DataType of
// `updated_specifics` does not match the entity, false is returned.
// Otherwise, true is returned to represent a successful modification.
//
// This method sometimes updates entity data beyond EntitySpecifics. For
// example, in the case of a bookmark, changing the BookmarkSpecifics title
// field will modify the top-level entity's name field.
bool ModifyEntitySpecifics(const std::string& id,
const sync_pb::EntitySpecifics& updated_specifics);
bool ModifyBookmarkEntity(const std::string& id,
const std::string& parent_id,
const sync_pb::EntitySpecifics& updated_specifics);
// Clears server data simulating a "dashboard stop and clear" and sets a new
// store birthday.
void ClearServerData();
// Deletes all `data_type` entities from the server without creating
// tombstones.
void DeleteAllEntitiesForDataType(syncer::DataType data_type);
// Causes future calls to HandleCommand() fail with the given response code.
void SetHttpError(net::HttpStatusCode http_status_code);
// Undoes previous calls to SetHttpError().
void ClearHttpError();
// Sets the provided `client_command` in all subsequent successful requests.
void SetClientCommand(const sync_pb::ClientCommand& client_command);
// Force the server to return `error_type` in the error_code field of
// ClientToServerResponse on all subsequent commit requests. If any of errors
// triggerings currently configured it must be called only with
// sync_pb::SyncEnums::SUCCESS.
void TriggerCommitError(const sync_pb::SyncEnums_ErrorType& error_type);
// Force the server to return `error_type` in the error_code field of
// ClientToServerResponse on all subsequent sync requests. If any of errors
// triggerings currently configured it must be called only with
// sync_pb::SyncEnums::SUCCESS.
void TriggerError(const sync_pb::SyncEnums_ErrorType& error_type);
// Force the server to return the given data as part of the error field of
// ClientToServerResponse on all subsequent sync requests. Must not be called
// if any of errors triggerings currently configured.
void TriggerActionableProtocolError(
const sync_pb::SyncEnums_ErrorType& error_type,
const std::string& description,
const std::string& url,
const sync_pb::SyncEnums::Action& action);
void ClearActionableProtocolError();
// Instructs the server to send triggered errors on every other request
// (starting with the first one after this call). This feature can be used to
// test the resiliency of the client when communicating with a problematic
// server or flaky network connection. This method should only be called
// after a call to TriggerError or TriggerActionableProtocolError. Returns
// true if triggered error alternating was successful.
bool EnableAlternatingTriggeredErrors();
// If called, all subsequent GetUpdatesResponses won't contain
// encryption_keys.
void DisallowSendingEncryptionKeys();
// Mimics throttling of datatypes.
void SetThrottledTypes(syncer::DataTypeSet types);
// Adds `observer` to FakeServer's observer list. This should be called
// before the Profile associated with `observer` is connected to the server.
void AddObserver(Observer* observer);
// Removes `observer` from the FakeServer's observer list. This method
// must be called if AddObserver was ever called with `observer`.
void RemoveObserver(Observer* observer);
// Enables strong consistency model (i.e. server detects conflicts).
void EnableStrongConsistencyWithConflictDetectionModel();
// Sets a maximum batch size for GetUpdates requests.
void SetMaxGetUpdatesBatchSize(int batch_size);
// Sets the bag of chips returned by the server.
void SetBagOfChips(const sync_pb::ChipBag& bag_of_chips);
void TriggerMigrationDoneError(syncer::DataTypeSet types);
// Add the user to the collaboration for the shared data types. No-op if the
// user is already in this collaboration.
void AddCollaboration(syncer::CollaborationId collaboration_id);
// Removes the user from the collaboration. Does not clean up related entities
// from the server.
void RemoveCollaboration(const syncer::CollaborationId& collaboration_id);
// Implement LoopbackServer::ObserverForTests:
void OnCommit(syncer::DataTypeSet committed_data_types) override;
void OnCommittedDeletionOrigin(
syncer::DataType type,
const sync_pb::DeletionOrigin& deletion_origin) override;
// Returns all DeletionOrigin protos committed to the server for `type`.
const std::vector<sync_pb::DeletionOrigin>& GetCommittedDeletionOrigins(
syncer::DataType type) const;
std::string GetStoreBirthday() const;
// Returns the current FakeServer as a WeakPtr.
base::WeakPtr<FakeServer> AsWeakPtr();
// Use this callback to generate response types for entities. They will still
// be "committed" and stored as normal, this only affects the response type
// the client sees. This allows tests to still inspect what the client has
// done, although not as useful of a mechanism for multi client tests. Care
// should be taken when failing responses, as the client will go into
// exponential backoff, which can cause tests to be slow or time out.
void OverrideResponseType(
syncer::LoopbackServer::ResponseTypeProvider response_type_override);
// Performs any pending disk write immediately. This is useful on platforms
// where shutdown isn't graceful, and this object may not be destructed
// properly (otherwise, the destructor takes care of this automatically).
void FlushToDisk();
private:
// Analogous to HandleCommand() but deals with parsed protos.
net::HttpStatusCode HandleParsedCommand(
const sync_pb::ClientToServerMessage& message,
sync_pb::ClientToServerResponse* response);
// Returns whether a triggered error should be sent for the request.
bool ShouldSendTriggeredError() const;
bool HasTriggeredError() const;
net::HttpStatusCode SendToLoopbackServer(
const sync_pb::ClientToServerMessage& message,
sync_pb::ClientToServerResponse* response);
// Logs a string that is meant to be shown in case the running test fails,
// as long as `switches::kDisableFakeServerFailureOutput` hasn't been passed
// to the command line.
void LogForTestFailure(const base::Location& location,
const std::string& title,
const std::string& body);
// Notifies observers about an ongoing commit.
void OnWillCommit();
// List used to implement LogForTestFailure().
std::vector<std::unique_ptr<testing::ScopedTrace>> gtest_scoped_traces_;
// If set, the server will return HTTP errors.
std::optional<net::HttpStatusCode> http_error_status_code_;
// All committed deletion origins (optional part of committed tombstone).
std::map<syncer::DataType, std::vector<sync_pb::DeletionOrigin>>
committed_deletion_origins_;
// Used as the error_code field of ClientToServerResponse on all commit
// requests.
sync_pb::SyncEnums_ErrorType commit_error_type_ = sync_pb::SyncEnums::SUCCESS;
// Used as the error_code field of ClientToServerResponse on all responses.
sync_pb::SyncEnums_ErrorType error_type_ = sync_pb::SyncEnums::SUCCESS;
// Used as the error field of ClientToServerResponse when its pointer is not
// null.
std::unique_ptr<sync_pb::ClientToServerResponse_Error>
triggered_actionable_error_;
// These values are used in tandem to return a triggered error (either
// `error_type_` or `triggered_actionable_error_`) on every other request.
// `alternate_triggered_errors_` is set if this feature is enabled and
// `request_counter_` is used to send triggered errors on odd-numbered
// requests. Note that `request_counter_` can be reset and is not necessarily
// indicative of the total number of requests handled during the object's
// lifetime.
bool alternate_triggered_errors_ = false;
int request_counter_ = 0;
// If set to true all `this` will clear `encryption_keys` in all
// GetUpdateResponse's.
bool disallow_sending_encryption_keys_ = false;
// Client command to be included in every response.
sync_pb::ClientCommand client_command_;
// FakeServer's observers.
base::ObserverList<Observer, true>::Unchecked observers_;
// The last received client to server messages.
sync_pb::ClientToServerMessage last_commit_message_;
sync_pb::ClientToServerMessage last_getupdates_message_;
// Used to verify that FakeServer is only used from one thread.
base::ThreadChecker thread_checker_;
std::unique_ptr<syncer::LoopbackServer> loopback_server_;
// The LoopbackServer does not know how to handle Wallet data properly, so
// the FakeServer handles those itself.
std::vector<sync_pb::SyncEntity> wallet_entities_;
// The LoopbackServer does not know how to handle offer data properly, so
// the FakeServer handles those itself.
std::vector<sync_pb::SyncEntity> offer_entities_;
// The LoopbackServer does not know how to handle valuable data properly, so
// the FakeServer handles those itself.
std::vector<sync_pb::SyncEntity> valuable_entities_;
// Collaborations the user is a member of, used for all shared types.
std::set<syncer::CollaborationId> collaborations_;
// Creates WeakPtr versions of the current FakeServer. This must be the last
// data member!
base::WeakPtrFactory<FakeServer> weak_ptr_factory_{this};
};
} // namespace fake_server
#endif // COMPONENTS_SYNC_TEST_FAKE_SERVER_H_
|