blob: e6d27015993623eb7f04a8e07f94662e38d33a9e [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sync/test/engine/mock_model_type_processor.h"
#include <stddef.h>
#include <stdint.h>
#include "base/base64.h"
#include "base/bind.h"
#include "base/sha1.h"
#include "sync/engine/commit_queue.h"
namespace syncer_v2 {
MockModelTypeProcessor::MockModelTypeProcessor() : is_synchronous_(true) {}
MockModelTypeProcessor::~MockModelTypeProcessor() {}
void MockModelTypeProcessor::ConnectSync(
std::unique_ptr<CommitQueue> commit_queue) {
NOTREACHED();
}
void MockModelTypeProcessor::DisconnectSync() {
if (!disconnect_callback_.is_null()) {
disconnect_callback_.Run();
}
}
void MockModelTypeProcessor::OnCommitCompleted(
const sync_pb::DataTypeState& type_state,
const CommitResponseDataList& response_list) {
base::Closure task =
base::Bind(&MockModelTypeProcessor::OnCommitCompletedImpl,
base::Unretained(this),
type_state,
response_list);
pending_tasks_.push_back(task);
if (is_synchronous_)
RunQueuedTasks();
}
void MockModelTypeProcessor::OnUpdateReceived(
const sync_pb::DataTypeState& type_state,
const UpdateResponseDataList& response_list) {
base::Closure task = base::Bind(&MockModelTypeProcessor::OnUpdateReceivedImpl,
base::Unretained(this),
type_state,
response_list);
pending_tasks_.push_back(task);
if (is_synchronous_)
RunQueuedTasks();
}
void MockModelTypeProcessor::SetSynchronousExecution(bool is_synchronous) {
is_synchronous_ = is_synchronous;
}
void MockModelTypeProcessor::RunQueuedTasks() {
for (std::vector<base::Closure>::iterator it = pending_tasks_.begin();
it != pending_tasks_.end();
++it) {
it->Run();
}
pending_tasks_.clear();
}
CommitRequestData MockModelTypeProcessor::CommitRequest(
const std::string& tag_hash,
const sync_pb::EntitySpecifics& specifics) {
const int64_t base_version = GetBaseVersion(tag_hash);
EntityData data;
if (HasServerAssignedId(tag_hash)) {
data.id = GetServerAssignedId(tag_hash);
}
data.client_tag_hash = tag_hash;
data.specifics = specifics;
// These fields are not really used for much, but we set them anyway
// to make this item look more realistic.
data.creation_time = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1);
data.modification_time =
data.creation_time + base::TimeDelta::FromSeconds(base_version);
data.non_unique_name = "Name: " + tag_hash;
CommitRequestData request_data;
request_data.entity = data.PassToPtr();
request_data.sequence_number = GetNextSequenceNumber(tag_hash);
request_data.base_version = base_version;
base::Base64Encode(base::SHA1HashString(specifics.SerializeAsString()),
&request_data.specifics_hash);
return request_data;
}
CommitRequestData MockModelTypeProcessor::DeleteRequest(
const std::string& tag_hash) {
const int64_t base_version = GetBaseVersion(tag_hash);
EntityData data;
if (HasServerAssignedId(tag_hash)) {
data.id = GetServerAssignedId(tag_hash);
}
data.client_tag_hash = tag_hash;
// These fields have little or no effect on behavior. We set them anyway to
// make the test more realistic.
data.creation_time = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1);
data.non_unique_name = "Name deleted";
data.modification_time =
data.creation_time + base::TimeDelta::FromSeconds(base_version);
CommitRequestData request_data;
request_data.entity = data.PassToPtr();
request_data.sequence_number = GetNextSequenceNumber(tag_hash);
request_data.base_version = base_version;
return request_data;
}
size_t MockModelTypeProcessor::GetNumUpdateResponses() const {
return received_update_responses_.size();
}
UpdateResponseDataList MockModelTypeProcessor::GetNthUpdateResponse(
size_t n) const {
DCHECK_LT(n, GetNumUpdateResponses());
return received_update_responses_[n];
}
sync_pb::DataTypeState
MockModelTypeProcessor::GetNthTypeStateReceivedInUpdateResponse(
size_t n) const {
DCHECK_LT(n, GetNumUpdateResponses());
return type_states_received_on_update_[n];
}
size_t MockModelTypeProcessor::GetNumCommitResponses() const {
return received_commit_responses_.size();
}
CommitResponseDataList MockModelTypeProcessor::GetNthCommitResponse(
size_t n) const {
DCHECK_LT(n, GetNumCommitResponses());
return received_commit_responses_[n];
}
sync_pb::DataTypeState
MockModelTypeProcessor::GetNthTypeStateReceivedInCommitResponse(
size_t n) const {
DCHECK_LT(n, GetNumCommitResponses());
return type_states_received_on_commit_[n];
}
bool MockModelTypeProcessor::HasUpdateResponse(
const std::string& tag_hash) const {
std::map<const std::string, UpdateResponseData>::const_iterator it =
update_response_items_.find(tag_hash);
return it != update_response_items_.end();
}
UpdateResponseData MockModelTypeProcessor::GetUpdateResponse(
const std::string& tag_hash) const {
DCHECK(HasUpdateResponse(tag_hash));
std::map<const std::string, UpdateResponseData>::const_iterator it =
update_response_items_.find(tag_hash);
return it->second;
}
bool MockModelTypeProcessor::HasCommitResponse(
const std::string& tag_hash) const {
std::map<const std::string, CommitResponseData>::const_iterator it =
commit_response_items_.find(tag_hash);
return it != commit_response_items_.end();
}
CommitResponseData MockModelTypeProcessor::GetCommitResponse(
const std::string& tag_hash) const {
DCHECK(HasCommitResponse(tag_hash));
std::map<const std::string, CommitResponseData>::const_iterator it =
commit_response_items_.find(tag_hash);
return it->second;
}
void MockModelTypeProcessor::SetDisconnectCallback(
const DisconnectCallback& callback) {
disconnect_callback_ = callback;
}
void MockModelTypeProcessor::OnCommitCompletedImpl(
const sync_pb::DataTypeState& type_state,
const CommitResponseDataList& response_list) {
received_commit_responses_.push_back(response_list);
type_states_received_on_commit_.push_back(type_state);
for (CommitResponseDataList::const_iterator it = response_list.begin();
it != response_list.end(); ++it) {
commit_response_items_.insert(std::make_pair(it->client_tag_hash, *it));
// Server wins. Set the model's base version.
SetBaseVersion(it->client_tag_hash, it->response_version);
SetServerAssignedId(it->client_tag_hash, it->id);
}
}
void MockModelTypeProcessor::OnUpdateReceivedImpl(
const sync_pb::DataTypeState& type_state,
const UpdateResponseDataList& response_list) {
received_update_responses_.push_back(response_list);
type_states_received_on_update_.push_back(type_state);
for (UpdateResponseDataList::const_iterator it = response_list.begin();
it != response_list.end(); ++it) {
const std::string client_tag_hash = it->entity->client_tag_hash;
update_response_items_.insert(std::make_pair(client_tag_hash, *it));
// Server wins. Set the model's base version.
SetBaseVersion(client_tag_hash, it->response_version);
SetServerAssignedId(client_tag_hash, it->entity->id);
}
}
// Fetches the sequence number as of the most recent update request.
int64_t MockModelTypeProcessor::GetCurrentSequenceNumber(
const std::string& tag_hash) const {
std::map<const std::string, int64_t>::const_iterator it =
sequence_numbers_.find(tag_hash);
if (it == sequence_numbers_.end()) {
return 0;
} else {
return it->second;
}
}
// The model thread should be sending us items with strictly increasing
// sequence numbers. Here's where we emulate that behavior.
int64_t MockModelTypeProcessor::GetNextSequenceNumber(
const std::string& tag_hash) {
int64_t sequence_number = GetCurrentSequenceNumber(tag_hash);
sequence_number++;
sequence_numbers_[tag_hash] = sequence_number;
return sequence_number;
}
int64_t MockModelTypeProcessor::GetBaseVersion(
const std::string& tag_hash) const {
std::map<const std::string, int64_t>::const_iterator it =
base_versions_.find(tag_hash);
if (it == base_versions_.end()) {
return kUncommittedVersion;
} else {
return it->second;
}
}
void MockModelTypeProcessor::SetBaseVersion(const std::string& tag_hash,
int64_t version) {
base_versions_[tag_hash] = version;
}
bool MockModelTypeProcessor::HasServerAssignedId(
const std::string& tag_hash) const {
return assigned_ids_.find(tag_hash) != assigned_ids_.end();
}
const std::string& MockModelTypeProcessor::GetServerAssignedId(
const std::string& tag_hash) const {
DCHECK(HasServerAssignedId(tag_hash));
return assigned_ids_.find(tag_hash)->second;
}
void MockModelTypeProcessor::SetServerAssignedId(const std::string& tag_hash,
const std::string& id) {
assigned_ids_[tag_hash] = id;
}
} // namespace syncer_v2