Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: chrome/test/live_sync/profile_sync_service_test_harness.cc

Issue 159728: Add browser/sync to the repository. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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 #ifdef CHROME_PERSONALIZATION
5
6 #include "base/message_loop.h"
7 #include "chrome/browser/browser.h"
8 #include "chrome/browser/tab_contents/tab_contents.h"
9 #include "chrome/common/pref_names.h"
10 #include "chrome/common/pref_service.h"
11 #include "chrome/browser/sync/auth_error_state.h"
12 #include "chrome/test/live_sync/profile_sync_service_test_harness.h"
13 #include "chrome/test/ui_test_utils.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 // The default value for min_updates_needed_ when we're not in a call to
17 // WaitForUpdatesRecievedAtLeast.
18 static const int kMinUpdatesNeededNone = -1;
19
20 static const ProfileSyncService::Status kInvalidStatus = {};
21
22 // Simple class to implement a timeout using PostDelayedTask. If it is not
23 // aborted before picked up by a message queue, then it asserts with the message
24 // provided. This class is not thread safe.
25 class StateChangeTimeoutEvent
26 : public base::RefCountedThreadSafe<StateChangeTimeoutEvent> {
27 public:
28 explicit StateChangeTimeoutEvent(ProfileSyncServiceTestHarness* caller,
29 const std::string& message);
30 ~StateChangeTimeoutEvent();
31
32 // The entry point to the class from PostDelayedTask.
33 void Callback();
34
35 // Cancels the actions of the callback. Returns true if success, false
36 // if the callback has already timed out.
37 bool Abort();
38
39 private:
40 bool aborted_;
41 bool did_timeout_;
42
43 // Due to synchronization of the IO loop, the caller will always be alive
44 // if the class is not aborted.
45 ProfileSyncServiceTestHarness* caller_;
46
47 // Informative message to assert in the case of a timeout.
48 std::string message_;
49
50 DISALLOW_COPY_AND_ASSIGN(StateChangeTimeoutEvent);
51 };
52
53 StateChangeTimeoutEvent::StateChangeTimeoutEvent(
54 ProfileSyncServiceTestHarness* caller,
55 const std::string& message)
56 : aborted_(false), did_timeout_(false), caller_(caller), message_(message) {
57 }
58
59 StateChangeTimeoutEvent::~StateChangeTimeoutEvent() {
60 }
61
62 void StateChangeTimeoutEvent::Callback() {
63 if (!aborted_) {
64 if (!caller_->RunStateChangeMachine()) {
65 // Report the message.
66 did_timeout_ = true;
67 EXPECT_FALSE(aborted_) << message_;
68 caller_->SignalStateComplete();
69 }
70 }
71 }
72
73 bool StateChangeTimeoutEvent::Abort() {
74 aborted_ = true;
75 caller_ = NULL;
76 return !did_timeout_;
77 }
78
79 class ConflictTimeoutEvent
80 : public base::RefCountedThreadSafe<ConflictTimeoutEvent> {
81 public:
82 explicit ConflictTimeoutEvent(ProfileSyncServiceTestHarness* caller)
83 : caller_(caller), did_run_(false) {
84 }
85 ~ConflictTimeoutEvent() { }
86
87 // The entry point to the class from PostDelayedTask.
88 void Callback();
89 bool did_run_;
90
91 private:
92
93 // Due to synchronization of the IO loop, the caller will always be alive
94 // if the class is not aborted.
95 ProfileSyncServiceTestHarness* caller_;
96
97 DISALLOW_COPY_AND_ASSIGN(ConflictTimeoutEvent);
98 };
99
100 void ConflictTimeoutEvent::Callback() {
101 caller_->SignalStateComplete();
102 did_run_ = true;
103 }
104
105
106 ProfileSyncServiceTestHarness::ProfileSyncServiceTestHarness(
107 Profile* p, const std::string& username, const std::string& password)
108 : wait_state_(WAITING_FOR_INITIAL_CALLBACK), profile_(p), service_(NULL),
109 last_status_(kInvalidStatus), min_updates_needed_(kMinUpdatesNeededNone),
110 username_(username), password_(password) {
111 // Ensure the profile has enough prefs registered for use by sync.
112 if (!p->GetPrefs()->IsPrefRegistered(prefs::kAcceptLanguages))
113 TabContents::RegisterUserPrefs(p->GetPrefs());
114 if (!p->GetPrefs()->IsPrefRegistered(prefs::kCookieBehavior))
115 Browser::RegisterUserPrefs(p->GetPrefs());
116 }
117
118 bool ProfileSyncServiceTestHarness::SetupSync() {
119 service_ = profile_->GetProfilePersonalization()->sync_service();
120 profile_->GetPrefs()->SetBoolean(prefs::kSyncHasSetupCompleted, true);
121 service_->EnableForUser();
122
123 // Needed to avoid showing the login dialog. Well aware this is egregious.
124 service_->expecting_first_run_auth_needed_event_ = false;
125 service_->AddObserver(this);
126 return WaitForServiceInit();
127 }
128
129 void ProfileSyncServiceTestHarness::SignalStateCompleteWithNextState(
130 WaitState next_state) {
131
132 wait_state_ = next_state;
133 SignalStateComplete();
134 }
135
136 void ProfileSyncServiceTestHarness::SignalStateComplete() {
137 MessageLoopForUI::current()->Quit();
138 }
139
140 bool ProfileSyncServiceTestHarness::RunStateChangeMachine() {
141 WaitState state = wait_state_;
142 ProfileSyncService::Status status(service_->QueryDetailedSyncStatus());
143 switch (wait_state_) {
144 case WAITING_FOR_INITIAL_CALLBACK:
145 SignalStateCompleteWithNextState(WAITING_FOR_READY_TO_PROCESS_CHANGES);
146 break;
147 case WAITING_FOR_READY_TO_PROCESS_CHANGES:
148 if (service_->ready_to_process_changes_) {
149 SignalStateCompleteWithNextState(WAITING_FOR_NOTHING);
150 }
151 break;
152 case WAITING_FOR_TIMESTAMP_UPDATE: {
153 const base::Time current_timestamp = service_->last_synced_time();
154 if (current_timestamp == last_timestamp_) {
155 break;
156 }
157 EXPECT_TRUE(last_timestamp_ < current_timestamp);
158 last_timestamp_ = current_timestamp;
159 SignalStateCompleteWithNextState(WAITING_FOR_NOTHING);
160 break;
161 }
162 case WAITING_FOR_UPDATES:
163 if (status.updates_received < min_updates_needed_) {
164 break;
165 }
166 SignalStateCompleteWithNextState(WAITING_FOR_NOTHING);
167 break;
168 case WAITING_FOR_NOTHING:
169 default:
170 // Invalid state during observer callback which may be triggered by other
171 // classes using the the UI message loop. Defer to their handling.
172 break;
173 }
174 last_status_ = status;
175 return state != wait_state_;
176 }
177
178 void ProfileSyncServiceTestHarness::OnStateChanged() {
179 RunStateChangeMachine();
180 }
181
182 bool ProfileSyncServiceTestHarness::AwaitSyncCycleCompletion(
183 const std::string& reason) {
184 wait_state_ = WAITING_FOR_TIMESTAMP_UPDATE;
185 return AwaitStatusChangeWithTimeout(60, reason);
186 }
187
188 bool ProfileSyncServiceTestHarness::AwaitMutualSyncCycleCompletion(
189 ProfileSyncServiceTestHarness* partner) {
190 return AwaitSyncCycleCompletion("Sync cycle completion on active client.") &&
191 partner->AwaitSyncCycleCompletion(
192 "Sync cycle completion on passive client.");
193 }
194
195 bool ProfileSyncServiceTestHarness::AwaitStatusChangeWithTimeout(
196 int timeout_seconds,
197 const std::string& reason) {
198 scoped_refptr<StateChangeTimeoutEvent> timeout_signal(
199 new StateChangeTimeoutEvent(this, reason));
200 MessageLoopForUI* loop = MessageLoopForUI::current();
201 loop->PostDelayedTask(
202 FROM_HERE,
203 NewRunnableMethod(timeout_signal.get(),
204 &StateChangeTimeoutEvent::Callback),
205 1000 * timeout_seconds);
206 ui_test_utils::RunMessageLoop();
207 return timeout_signal->Abort();
208 }
209
210 bool ProfileSyncServiceTestHarness::AwaitMutualSyncCycleCompletionWithConflict(
211 ProfileSyncServiceTestHarness* partner) {
212
213 if (!AwaitMutualSyncCycleCompletion(partner)) {
214 return false;
215 }
216 if (!partner->AwaitMutualSyncCycleCompletion(this)) {
217 return false;
218 }
219
220 scoped_refptr<ConflictTimeoutEvent> timeout_signal(
221 new ConflictTimeoutEvent(this));
222
223 // Now we want to wait an extra 20 seconds to ensure any rebounding updates
224 // due to a conflict are processed and observed by each client.
225 MessageLoopForUI* loop = MessageLoopForUI::current();
226 loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(timeout_signal.get(),
227 &ConflictTimeoutEvent::Callback), 1000 * 20);
228 // It is possible that timeout has not run yet and loop exited due to
229 // OnStateChanged event. So to avoid pre-mature termination of loop,
230 // we are re-running the loop until did_run_ becomes true.
231 while (!timeout_signal->did_run_) {
232 ui_test_utils::RunMessageLoop();
233 }
234 return true;
235 }
236
237 bool ProfileSyncServiceTestHarness::WaitForServiceInit() {
238 // Wait for the initial (auth needed) callback.
239 EXPECT_EQ(wait_state_, WAITING_FOR_INITIAL_CALLBACK);
240 if (!AwaitStatusChangeWithTimeout(30, "Waiting for authwatcher calback.")) {
241 return false;
242 }
243
244 // Wait for the OnBackendInitialized callback.
245 service_->backend()->Authenticate(username_, password_);
246 EXPECT_EQ(wait_state_, WAITING_FOR_READY_TO_PROCESS_CHANGES);
247 if (!AwaitStatusChangeWithTimeout(30, "Waiting on backend initialization.")) {
248 return false;
249 }
250 return service_->sync_initialized();
251 }
252
253 #endif // CHROME_PERSONALIZATION
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698