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 "components/sync_driver/fake_data_type_controller.h"
6
7#include "testing/gmock/include/gmock/gmock.h"
8#include "testing/gtest/include/gtest/gtest.h"
9
10using syncer::ModelType;
11
12namespace sync_driver {
13
14FakeDataTypeController::FakeDataTypeController(ModelType type)
15      : DataTypeController(base::MessageLoopProxy::current(), base::Closure()),
16        state_(NOT_RUNNING),
17        model_load_delayed_(false),
18        type_(type),
19        ready_for_start_(true) {}
20
21FakeDataTypeController::~FakeDataTypeController() {
22}
23
24// NOT_RUNNING ->MODEL_LOADED |MODEL_STARTING.
25void FakeDataTypeController::LoadModels(
26    const ModelLoadCallback& model_load_callback) {
27  model_load_callback_ = model_load_callback;
28  if (state_ != NOT_RUNNING) {
29    ADD_FAILURE();
30    return;
31  }
32
33  if (model_load_delayed_ == false) {
34    if (load_error_.IsSet())
35      state_ = DISABLED;
36    else
37      state_ = MODEL_LOADED;
38    model_load_callback.Run(type(), load_error_);
39  } else {
40    state_ = MODEL_STARTING;
41  }
42}
43
44void FakeDataTypeController::OnModelLoaded() {
45  NOTREACHED();
46}
47
48// MODEL_LOADED -> MODEL_STARTING.
49void FakeDataTypeController::StartAssociating(
50   const StartCallback& start_callback) {
51  last_start_callback_ = start_callback;
52  state_ = ASSOCIATING;
53}
54
55// MODEL_STARTING | ASSOCIATING -> RUNNING | DISABLED | NOT_RUNNING
56// (depending on |result|)
57void FakeDataTypeController::FinishStart(ConfigureResult result) {
58  // We should have a callback from Start().
59  if (last_start_callback_.is_null()) {
60    ADD_FAILURE();
61    return;
62  }
63
64  // Set |state_| first below since the callback may call state().
65  syncer::SyncMergeResult local_merge_result(type());
66  syncer::SyncMergeResult syncer_merge_result(type());
67  if (result <= OK_FIRST_RUN) {
68    state_ = RUNNING;
69  } else if (result == ASSOCIATION_FAILED) {
70    state_ = DISABLED;
71    local_merge_result.set_error(
72        syncer::SyncError(FROM_HERE,
73                          syncer::SyncError::DATATYPE_ERROR,
74                          "Association failed",
75                          type()));
76  } else if (result == UNRECOVERABLE_ERROR) {
77    state_ = NOT_RUNNING;
78    local_merge_result.set_error(
79        syncer::SyncError(FROM_HERE,
80                          syncer::SyncError::UNRECOVERABLE_ERROR,
81                          "Unrecoverable error",
82                          type()));
83  } else if (result == NEEDS_CRYPTO) {
84    state_ = NOT_RUNNING;
85    local_merge_result.set_error(
86        syncer::SyncError(FROM_HERE,
87                          syncer::SyncError::CRYPTO_ERROR,
88                          "Crypto error",
89                          type()));
90  } else {
91    NOTREACHED();
92  }
93  last_start_callback_.Run(result, local_merge_result, syncer_merge_result);
94}
95
96// * -> NOT_RUNNING
97void FakeDataTypeController::Stop() {
98  state_ = NOT_RUNNING;
99  if (!model_load_callback_.is_null()) {
100    // Real data type controllers run the callback and specify "ABORTED" as an
101    // error.  We should probably find a way to use the real code and mock out
102    // unnecessary pieces.
103    SimulateModelLoadFinishing();
104  }
105}
106
107ModelType FakeDataTypeController::type() const {
108  return type_;
109}
110
111std::string FakeDataTypeController::name() const {
112  return ModelTypeToString(type_);
113}
114
115syncer::ModelSafeGroup FakeDataTypeController::model_safe_group() const {
116  return syncer::GROUP_PASSIVE;
117}
118
119ChangeProcessor* FakeDataTypeController::GetChangeProcessor() const {
120  return NULL;
121}
122
123DataTypeController::State FakeDataTypeController::state() const {
124  return state_;
125}
126
127void FakeDataTypeController::OnSingleDataTypeUnrecoverableError(
128    const syncer::SyncError& error) {
129  if (!model_load_callback_.is_null())
130    model_load_callback_.Run(type(), error);
131}
132
133bool FakeDataTypeController::ReadyForStart() const {
134  return ready_for_start_;
135}
136
137void FakeDataTypeController::SetDelayModelLoad() {
138  model_load_delayed_ = true;
139}
140
141void FakeDataTypeController::SetModelLoadError(syncer::SyncError error) {
142  load_error_ = error;
143}
144
145void FakeDataTypeController::SimulateModelLoadFinishing() {
146  model_load_callback_.Run(type(), load_error_);
147}
148
149void FakeDataTypeController::SetReadyForStart(bool ready) {
150  ready_for_start_ = ready;
151}
152
153}  // namespace sync_driver
154