1// Copyright (c) 2011 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 "base/time.h"
6#include "chrome/browser/sync/engine/mock_model_safe_workers.h"
7#include "chrome/browser/sync/engine/syncer_thread.h"
8#include "chrome/browser/sync/sessions/sync_session_context.h"
9#include "chrome/browser/sync/sessions/test_util.h"
10#include "chrome/test/sync/engine/mock_connection_manager.h"
11#include "chrome/test/sync/engine/test_directory_setter_upper.h"
12#include "testing/gtest/include/gtest/gtest.h"
13#include "testing/gmock/include/gmock/gmock.h"
14
15using base::TimeDelta;
16using base::TimeTicks;
17
18namespace browser_sync {
19using sessions::SyncSessionContext;
20using browser_sync::Syncer;
21
22class SyncerThread2WhiteboxTest : public testing::Test {
23 public:
24  virtual void SetUp() {
25    syncdb_.SetUp();
26    Syncer* syncer = new Syncer();
27    registrar_.reset(MockModelSafeWorkerRegistrar::PassiveBookmarks());
28    context_ = new SyncSessionContext(connection_.get(), syncdb_.manager(),
29        registrar_.get(), std::vector<SyncEngineEventListener*>());
30    context_->set_notifications_enabled(true);
31    context_->set_account_name("Test");
32    syncer_thread_.reset(new SyncerThread(context_, syncer));
33  }
34
35  virtual void TearDown() {
36    syncdb_.TearDown();
37  }
38
39  void SetMode(SyncerThread::Mode mode) {
40    syncer_thread_->mode_ = mode;
41  }
42
43  void SetLastSyncedTime(base::TimeTicks ticks) {
44    syncer_thread_->last_sync_session_end_time_ = ticks;
45  }
46
47  void SetServerConnection(bool connected) {
48    syncer_thread_->server_connection_ok_ = connected;
49  }
50
51  void ResetWaitInterval() {
52    syncer_thread_->wait_interval_.reset();
53  }
54
55  void SetWaitIntervalToThrottled() {
56    syncer_thread_->wait_interval_.reset(new SyncerThread::WaitInterval(
57        SyncerThread::WaitInterval::THROTTLED, TimeDelta::FromSeconds(1)));
58  }
59
60  void SetWaitIntervalToExponentialBackoff() {
61    syncer_thread_->wait_interval_.reset(
62       new SyncerThread::WaitInterval(
63       SyncerThread::WaitInterval::EXPONENTIAL_BACKOFF,
64       TimeDelta::FromSeconds(1)));
65  }
66
67  SyncerThread::JobProcessDecision DecideOnJob(
68      const SyncerThread::SyncSessionJob& job) {
69    return syncer_thread_->DecideOnJob(job);
70  }
71
72  void InitializeSyncerOnNormalMode() {
73    SetMode(SyncerThread::NORMAL_MODE);
74    ResetWaitInterval();
75    SetServerConnection(true);
76    SetLastSyncedTime(base::TimeTicks::Now());
77  }
78
79  SyncerThread::JobProcessDecision CreateAndDecideJob(
80      SyncerThread::SyncSessionJob::SyncSessionJobPurpose purpose) {
81    struct SyncerThread::SyncSessionJob job;
82    job.purpose = purpose;
83    job.scheduled_start = TimeTicks::Now();
84    return DecideOnJob(job);
85  }
86
87 protected:
88  scoped_ptr<SyncerThread> syncer_thread_;
89
90 private:
91  scoped_ptr<MockConnectionManager> connection_;
92  SyncSessionContext* context_;
93  //MockDelayProvider* delay_;
94  scoped_ptr<MockModelSafeWorkerRegistrar> registrar_;
95  MockDirectorySetterUpper syncdb_;
96};
97
98TEST_F(SyncerThread2WhiteboxTest, SaveNudge) {
99  InitializeSyncerOnNormalMode();
100
101  // Now set the mode to configure.
102  SetMode(SyncerThread::CONFIGURATION_MODE);
103
104  SyncerThread::JobProcessDecision decision =
105      CreateAndDecideJob(SyncerThread::SyncSessionJob::NUDGE);
106
107  EXPECT_EQ(decision, SyncerThread::SAVE);
108}
109
110TEST_F(SyncerThread2WhiteboxTest, ContinueNudge) {
111  InitializeSyncerOnNormalMode();
112
113  SyncerThread::JobProcessDecision decision = CreateAndDecideJob(
114      SyncerThread::SyncSessionJob::NUDGE);
115
116  EXPECT_EQ(decision, SyncerThread::CONTINUE);
117}
118
119TEST_F(SyncerThread2WhiteboxTest, DropPoll) {
120  InitializeSyncerOnNormalMode();
121  SetMode(SyncerThread::CONFIGURATION_MODE);
122
123  SyncerThread::JobProcessDecision decision = CreateAndDecideJob(
124      SyncerThread::SyncSessionJob::POLL);
125
126  EXPECT_EQ(decision, SyncerThread::DROP);
127}
128
129TEST_F(SyncerThread2WhiteboxTest, ContinuePoll) {
130  InitializeSyncerOnNormalMode();
131
132  SyncerThread::JobProcessDecision decision = CreateAndDecideJob(
133      SyncerThread::SyncSessionJob::POLL);
134
135  EXPECT_EQ(decision, SyncerThread::CONTINUE);
136}
137
138TEST_F(SyncerThread2WhiteboxTest, ContinueConfiguration) {
139  InitializeSyncerOnNormalMode();
140  SetMode(SyncerThread::CONFIGURATION_MODE);
141
142  SyncerThread::JobProcessDecision decision = CreateAndDecideJob(
143      SyncerThread::SyncSessionJob::CONFIGURATION);
144
145  EXPECT_EQ(decision, SyncerThread::CONTINUE);
146}
147
148TEST_F(SyncerThread2WhiteboxTest, SaveConfigurationWhileThrottled) {
149  InitializeSyncerOnNormalMode();
150  SetMode(SyncerThread::CONFIGURATION_MODE);
151
152  SetWaitIntervalToThrottled();
153
154  SyncerThread::JobProcessDecision decision = CreateAndDecideJob(
155      SyncerThread::SyncSessionJob::CONFIGURATION);
156
157  EXPECT_EQ(decision, SyncerThread::SAVE);
158}
159
160TEST_F(SyncerThread2WhiteboxTest, SaveNudgeWhileThrottled) {
161  InitializeSyncerOnNormalMode();
162  SetMode(SyncerThread::CONFIGURATION_MODE);
163
164  SetWaitIntervalToThrottled();
165
166  SyncerThread::JobProcessDecision decision = CreateAndDecideJob(
167      SyncerThread::SyncSessionJob::NUDGE);
168
169  EXPECT_EQ(decision, SyncerThread::SAVE);
170
171}
172
173TEST_F(SyncerThread2WhiteboxTest, ContinueClearUserDataUnderAllCircumstances) {
174  InitializeSyncerOnNormalMode();
175
176  SetMode(SyncerThread::CONFIGURATION_MODE);
177  SetWaitIntervalToThrottled();
178  SyncerThread::JobProcessDecision decision = CreateAndDecideJob(
179      SyncerThread::SyncSessionJob::CLEAR_USER_DATA);
180  EXPECT_EQ(decision, SyncerThread::CONTINUE);
181
182  SetMode(SyncerThread::NORMAL_MODE);
183  SetWaitIntervalToExponentialBackoff();
184  decision = CreateAndDecideJob(
185      SyncerThread::SyncSessionJob::CLEAR_USER_DATA);
186  EXPECT_EQ(decision, SyncerThread::CONTINUE);
187}
188
189TEST_F(SyncerThread2WhiteboxTest, ContinueNudgeWhileExponentialBackOff) {
190  InitializeSyncerOnNormalMode();
191  SetMode(SyncerThread::NORMAL_MODE);
192  SetWaitIntervalToExponentialBackoff();
193
194  SyncerThread::JobProcessDecision decision = CreateAndDecideJob(
195      SyncerThread::SyncSessionJob::NUDGE);
196
197  EXPECT_EQ(decision, SyncerThread::CONTINUE);
198}
199
200TEST_F(SyncerThread2WhiteboxTest, DropNudgeWhileExponentialBackOff) {
201  InitializeSyncerOnNormalMode();
202  SetMode(SyncerThread::NORMAL_MODE);
203  SetWaitIntervalToExponentialBackoff();
204
205  syncer_thread_->wait_interval_->had_nudge = true;
206
207  SyncerThread::JobProcessDecision decision = CreateAndDecideJob(
208      SyncerThread::SyncSessionJob::NUDGE);
209
210  EXPECT_EQ(decision, SyncerThread::DROP);
211}
212
213TEST_F(SyncerThread2WhiteboxTest, ContinueCanaryJobConfig) {
214  InitializeSyncerOnNormalMode();
215  SetMode(SyncerThread::CONFIGURATION_MODE);
216  SetWaitIntervalToExponentialBackoff();
217
218  struct SyncerThread::SyncSessionJob job;
219  job.purpose = SyncerThread::SyncSessionJob::CONFIGURATION;
220  job.scheduled_start = TimeTicks::Now();
221  job.is_canary_job = true;
222  SyncerThread::JobProcessDecision decision = DecideOnJob(job);
223
224  EXPECT_EQ(decision, SyncerThread::CONTINUE);
225}
226
227}  // namespace browser_sync
228
229// SyncerThread won't outlive the test!
230DISABLE_RUNNABLE_METHOD_REFCOUNT(
231    browser_sync::SyncerThread2WhiteboxTest);
232