1 // Copyright 2014 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 #include "sync/test/engine/mock_non_blocking_type_processor.h" 6 7 #include "base/bind.h" 8 9 namespace syncer { 10 11 MockNonBlockingTypeProcessor::MockNonBlockingTypeProcessor() 12 : is_synchronous_(true) { 13 } 14 15 MockNonBlockingTypeProcessor::~MockNonBlockingTypeProcessor() { 16 } 17 18 void MockNonBlockingTypeProcessor::ReceiveCommitResponse( 19 const DataTypeState& type_state, 20 const CommitResponseDataList& response_list) { 21 base::Closure task = 22 base::Bind(&MockNonBlockingTypeProcessor::ReceiveCommitResponseImpl, 23 base::Unretained(this), 24 type_state, 25 response_list); 26 pending_tasks_.push_back(task); 27 if (is_synchronous_) 28 RunQueuedTasks(); 29 } 30 31 void MockNonBlockingTypeProcessor::ReceiveUpdateResponse( 32 const DataTypeState& type_state, 33 const UpdateResponseDataList& response_list) { 34 base::Closure task = 35 base::Bind(&MockNonBlockingTypeProcessor::ReceiveUpdateResponseImpl, 36 base::Unretained(this), 37 type_state, 38 response_list); 39 pending_tasks_.push_back(task); 40 if (is_synchronous_) 41 RunQueuedTasks(); 42 } 43 44 void MockNonBlockingTypeProcessor::SetSynchronousExecution( 45 bool is_synchronous) { 46 is_synchronous_ = is_synchronous; 47 } 48 49 void MockNonBlockingTypeProcessor::RunQueuedTasks() { 50 for (std::vector<base::Closure>::iterator it = pending_tasks_.begin(); 51 it != pending_tasks_.end(); 52 ++it) { 53 it->Run(); 54 } 55 pending_tasks_.clear(); 56 } 57 58 CommitRequestData MockNonBlockingTypeProcessor::CommitRequest( 59 const std::string& tag_hash, 60 const sync_pb::EntitySpecifics& specifics) { 61 const int64 base_version = GetBaseVersion(tag_hash); 62 63 CommitRequestData data; 64 65 if (HasServerAssignedId(tag_hash)) { 66 data.id = GetServerAssignedId(tag_hash); 67 } 68 69 data.client_tag_hash = tag_hash; 70 data.sequence_number = GetNextSequenceNumber(tag_hash); 71 data.deleted = false; 72 data.specifics = specifics; 73 data.base_version = base_version; 74 75 // These fields are not really used for much, but we set them anyway 76 // to make this item look more realistic. 77 data.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1); 78 data.mtime = data.ctime + base::TimeDelta::FromSeconds(base_version); 79 data.non_unique_name = "Name: " + tag_hash; 80 81 return data; 82 } 83 84 CommitRequestData MockNonBlockingTypeProcessor::DeleteRequest( 85 const std::string& tag_hash) { 86 const int64 base_version = GetBaseVersion(tag_hash); 87 CommitRequestData data; 88 89 if (HasServerAssignedId(tag_hash)) { 90 data.id = GetServerAssignedId(tag_hash); 91 } 92 93 data.client_tag_hash = tag_hash; 94 data.sequence_number = GetNextSequenceNumber(tag_hash); 95 data.base_version = base_version; 96 data.mtime = data.ctime + base::TimeDelta::FromSeconds(base_version); 97 data.deleted = true; 98 99 // These fields have little or no effect on behavior. We set them anyway to 100 // make the test more realistic. 101 data.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1); 102 data.non_unique_name = "Name deleted"; 103 104 return data; 105 } 106 107 size_t MockNonBlockingTypeProcessor::GetNumUpdateResponses() const { 108 return received_update_responses_.size(); 109 } 110 111 UpdateResponseDataList MockNonBlockingTypeProcessor::GetNthUpdateResponse( 112 size_t n) const { 113 DCHECK_LT(n, GetNumUpdateResponses()); 114 return received_update_responses_[n]; 115 } 116 117 DataTypeState 118 MockNonBlockingTypeProcessor::GetNthTypeStateReceivedInUpdateResponse( 119 size_t n) const { 120 DCHECK_LT(n, GetNumUpdateResponses()); 121 return type_states_received_on_update_[n]; 122 } 123 124 size_t MockNonBlockingTypeProcessor::GetNumCommitResponses() const { 125 return received_commit_responses_.size(); 126 } 127 128 CommitResponseDataList MockNonBlockingTypeProcessor::GetNthCommitResponse( 129 size_t n) const { 130 DCHECK_LT(n, GetNumCommitResponses()); 131 return received_commit_responses_[n]; 132 } 133 134 DataTypeState 135 MockNonBlockingTypeProcessor::GetNthTypeStateReceivedInCommitResponse( 136 size_t n) const { 137 DCHECK_LT(n, GetNumCommitResponses()); 138 return type_states_received_on_commit_[n]; 139 } 140 141 bool MockNonBlockingTypeProcessor::HasUpdateResponse( 142 const std::string& tag_hash) const { 143 std::map<const std::string, UpdateResponseData>::const_iterator it = 144 update_response_items_.find(tag_hash); 145 return it != update_response_items_.end(); 146 } 147 148 UpdateResponseData MockNonBlockingTypeProcessor::GetUpdateResponse( 149 const std::string& tag_hash) const { 150 DCHECK(HasUpdateResponse(tag_hash)); 151 std::map<const std::string, UpdateResponseData>::const_iterator it = 152 update_response_items_.find(tag_hash); 153 return it->second; 154 } 155 156 bool MockNonBlockingTypeProcessor::HasCommitResponse( 157 const std::string& tag_hash) const { 158 std::map<const std::string, CommitResponseData>::const_iterator it = 159 commit_response_items_.find(tag_hash); 160 return it != commit_response_items_.end(); 161 } 162 163 CommitResponseData MockNonBlockingTypeProcessor::GetCommitResponse( 164 const std::string& tag_hash) const { 165 DCHECK(HasCommitResponse(tag_hash)); 166 std::map<const std::string, CommitResponseData>::const_iterator it = 167 commit_response_items_.find(tag_hash); 168 return it->second; 169 } 170 171 void MockNonBlockingTypeProcessor::ReceiveCommitResponseImpl( 172 const DataTypeState& type_state, 173 const CommitResponseDataList& response_list) { 174 received_commit_responses_.push_back(response_list); 175 type_states_received_on_commit_.push_back(type_state); 176 for (CommitResponseDataList::const_iterator it = response_list.begin(); 177 it != response_list.end(); 178 ++it) { 179 commit_response_items_.insert(std::make_pair(it->client_tag_hash, *it)); 180 181 // Server wins. Set the model's base version. 182 SetBaseVersion(it->client_tag_hash, it->response_version); 183 SetServerAssignedId(it->client_tag_hash, it->id); 184 } 185 } 186 187 void MockNonBlockingTypeProcessor::ReceiveUpdateResponseImpl( 188 const DataTypeState& type_state, 189 const UpdateResponseDataList& response_list) { 190 received_update_responses_.push_back(response_list); 191 type_states_received_on_update_.push_back(type_state); 192 for (UpdateResponseDataList::const_iterator it = response_list.begin(); 193 it != response_list.end(); 194 ++it) { 195 update_response_items_.insert(std::make_pair(it->client_tag_hash, *it)); 196 197 // Server wins. Set the model's base version. 198 SetBaseVersion(it->client_tag_hash, it->response_version); 199 SetServerAssignedId(it->client_tag_hash, it->id); 200 } 201 } 202 203 // Fetches the sequence number as of the most recent update request. 204 int64 MockNonBlockingTypeProcessor::GetCurrentSequenceNumber( 205 const std::string& tag_hash) const { 206 std::map<const std::string, int64>::const_iterator it = 207 sequence_numbers_.find(tag_hash); 208 if (it == sequence_numbers_.end()) { 209 return 0; 210 } else { 211 return it->second; 212 } 213 } 214 215 // The model thread should be sending us items with strictly increasing 216 // sequence numbers. Here's where we emulate that behavior. 217 int64 MockNonBlockingTypeProcessor::GetNextSequenceNumber( 218 const std::string& tag_hash) { 219 int64 sequence_number = GetCurrentSequenceNumber(tag_hash); 220 sequence_number++; 221 sequence_numbers_[tag_hash] = sequence_number; 222 return sequence_number; 223 } 224 225 int64 MockNonBlockingTypeProcessor::GetBaseVersion( 226 const std::string& tag_hash) const { 227 std::map<const std::string, int64>::const_iterator it = 228 base_versions_.find(tag_hash); 229 if (it == base_versions_.end()) { 230 return kUncommittedVersion; 231 } else { 232 return it->second; 233 } 234 } 235 236 void MockNonBlockingTypeProcessor::SetBaseVersion(const std::string& tag_hash, 237 int64 version) { 238 base_versions_[tag_hash] = version; 239 } 240 241 bool MockNonBlockingTypeProcessor::HasServerAssignedId( 242 const std::string& tag_hash) const { 243 return assigned_ids_.find(tag_hash) != assigned_ids_.end(); 244 } 245 246 const std::string& MockNonBlockingTypeProcessor::GetServerAssignedId( 247 const std::string& tag_hash) const { 248 DCHECK(HasServerAssignedId(tag_hash)); 249 return assigned_ids_.find(tag_hash)->second; 250 } 251 252 void MockNonBlockingTypeProcessor::SetServerAssignedId( 253 const std::string& tag_hash, 254 const std::string& id) { 255 assigned_ids_[tag_hash] = id; 256 } 257 258 } // namespace syncer 259