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

Side by Side Diff: chrome/browser/sync/test/integration/quiesce_status_change_checker.cc

Issue 184993006: sync: Change progress marker checking in tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review fixes Created 6 years, 9 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
OLDNEW
(Empty)
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 "chrome/browser/sync/test/integration/quiesce_status_change_checker.h"
6
7 #include "base/format_macros.h"
8 #include "base/scoped_observer.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/stringprintf.h"
11 #include "chrome/browser/sync/profile_sync_service.h"
12 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
13 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
14
15 namespace {
16
17 // Returns true if this service is disabled.
18 bool IsSyncDisabled(ProfileSyncService* service) {
19 return !service->setup_in_progress() && !service->HasSyncSetupCompleted();
20 }
21
22 // Returns true if these services have matching progress markers.
23 bool ProgressMarkersMatch(const ProfileSyncService* service1,
24 const ProfileSyncService* service2) {
25 const syncer::ModelTypeSet common_types =
26 Intersection(service1->GetActiveDataTypes(),
27 service2->GetActiveDataTypes());
28
29 const syncer::sessions::SyncSessionSnapshot& snap1 =
30 service1->GetLastSessionSnapshot();
31 const syncer::sessions::SyncSessionSnapshot& snap2 =
32 service2->GetLastSessionSnapshot();
33
34 for (syncer::ModelTypeSet::Iterator type_it = common_types.First();
35 type_it.Good(); type_it.Inc()) {
36 // Look up the progress markers. Fail if either one is missing.
37 syncer::ProgressMarkerMap::const_iterator pm_it1 =
38 snap1.download_progress_markers().find(type_it.Get());
39 if (pm_it1 == snap1.download_progress_markers().end()) {
40 return false;
41 }
42
43 syncer::ProgressMarkerMap::const_iterator pm_it2 =
44 snap2.download_progress_markers().find(type_it.Get());
45 if (pm_it2 == snap2.download_progress_markers().end()) {
46 return false;
47 }
48
49 // Fail if any of them don't match.
50 if (pm_it1->second != pm_it2->second) {
51 return false;
52 }
53 }
54 return true;
55 }
56
57 } // namespace
58
59 // A helper class to keep an eye on a particular ProfileSyncService's
60 // "HasLatestProgressMarkers()" state.
61 //
62 // This is a work-around for the HasLatestProgressMarkers check's inherent
63 // flakiness. It's not safe to check that condition whenever we want. The
64 // safest time to check it is when the ProfileSyncService emits an
65 // OnStateChanged() event. This class waits for those events and updates its
66 // cached HasLatestProgressMarkers state every time that event occurs.
67 //
68 // See the comments in UpdatedProgressMarkerChecker for more details.
69 //
70 // The long-term plan is to deprecate this hack by replacing all its usees with
71 // more reliable status checkers.
72 class ProgressMarkerWatcher : public ProfileSyncServiceObserver {
73 public:
74 ProgressMarkerWatcher(
75 ProfileSyncService* service,
76 QuiesceStatusChangeChecker* quiesce_checker);
77 virtual ~ProgressMarkerWatcher();
78 virtual void OnStateChanged() OVERRIDE;
79
80 bool HasLatestProgressMarkers();
81 bool IsSyncDisabled();
82
83 private:
84 void UpdateHasLatestProgressMarkers();
85
86 ProfileSyncService* service_;
87 QuiesceStatusChangeChecker* quiesce_checker_;
88 ScopedObserver<ProfileSyncService, ProgressMarkerWatcher> scoped_observer_;
89 bool probably_has_latest_progress_markers_;
90 };
91
92 ProgressMarkerWatcher::ProgressMarkerWatcher(
93 ProfileSyncService* service,
94 QuiesceStatusChangeChecker* quiesce_checker)
95 : service_(service),
96 quiesce_checker_(quiesce_checker),
97 scoped_observer_(this),
98 probably_has_latest_progress_markers_(false) {
99 scoped_observer_.Add(service);
100 UpdateHasLatestProgressMarkers();
101 }
102
103 ProgressMarkerWatcher::~ProgressMarkerWatcher() { }
104
105 void ProgressMarkerWatcher::OnStateChanged() {
106 UpdateHasLatestProgressMarkers();
107 quiesce_checker_->OnServiceStateChanged(service_);
108 }
109
110 void ProgressMarkerWatcher::UpdateHasLatestProgressMarkers() {
111 if (IsSyncDisabled()) {
112 probably_has_latest_progress_markers_ = false;
113 return;
114 }
115
116 // This is the same progress marker check as used by the
117 // UpdatedProgressMarkerChecker. It has the samed drawbacks and potential for
118 // flakiness. See the comment in
119 // UpdatedProgressMarkerChecker::IsExitConditionSatisfied() for more
120 // information.
121 //
122 // The QuiesceStatusChangeChecker attempts to work around the limitations of
123 // this progress marker checking method. It tries to update the progress
124 // marker status only in the OnStateChanged() callback, where the snapshot is
125 // freshest.
126 //
127 // It also checks the progress marker status when it is first initialized, and
128 // that's where it's most likely that we could return a false positive. We
129 // need to check these service at startup, since not every service is
130 // guaranteed to generate OnStateChanged() events while we're waiting for
131 // quiescence.
132 const syncer::sessions::SyncSessionSnapshot& snap =
133 service_->GetLastSessionSnapshot();
134 probably_has_latest_progress_markers_ =
135 snap.model_neutral_state().num_successful_commits == 0 &&
136 !service_->HasUnsyncedItems();
137 }
138
139 bool ProgressMarkerWatcher::HasLatestProgressMarkers() {
140 return probably_has_latest_progress_markers_;
141 }
142
143 bool ProgressMarkerWatcher::IsSyncDisabled() {
144 return ::IsSyncDisabled(service_);
145 }
146
147 QuiesceStatusChangeChecker::QuiesceStatusChangeChecker(
148 std::vector<ProfileSyncService*> services)
149 : services_(services), harness_(NULL) {
150 DCHECK_LE(1U, services_.size());
151 for (size_t i = 0; i < services_.size(); ++i) {
152 observers_.push_back(new ProgressMarkerWatcher(services[i], this));
153 }
154 }
155
156 QuiesceStatusChangeChecker::~QuiesceStatusChangeChecker() {}
157
158 bool QuiesceStatusChangeChecker::IsExitConditionSatisfied() {
159 // Check that all progress markers are up to date.
160 for (ScopedVector<ProgressMarkerWatcher>::const_iterator it =
161 observers_.begin(); it != observers_.end(); ++it) {
162 if ((*it)->IsSyncDisabled()) {
163 continue; // Skip disabled services.
164 }
165
166 if (!(*it)->HasLatestProgressMarkers()) {
167 VLOG(1) << "Not quiesced: Progress markers are old.";
168 return false;
169 }
170 }
171
172 std::vector<ProfileSyncService*> enabled_services;
173 for (std::vector<ProfileSyncService*>::const_iterator it = services_.begin();
174 it != services_.end(); ++it) {
175 if (!IsSyncDisabled(*it)) {
176 enabled_services.push_back(*it);
177 }
178 }
179
180 // Return true if we have nothing to compare against.
181 if (enabled_services.size() <= 1) {
182 return true;
183 }
184
185 std::vector<ProfileSyncService*>::const_iterator it1 =
186 enabled_services.begin();
187 std::vector<ProfileSyncService*>::const_iterator it2 =
188 enabled_services.begin();
189 it2++;
190
191 while (it2 != enabled_services.end()) {
192 // Return false if there is a progress marker mismatch.
193 if (!ProgressMarkersMatch(*it1, *it2)) {
194 VLOG(1) << "Not quiesced: Progress marker mismatch.";
195 return false;
196 }
197 it1++;
198 it2++;
199 }
200
201 return true;
202 }
203
204 std::string QuiesceStatusChangeChecker::GetDebugMessage() const {
205 return base::StringPrintf("Waiting for quiescence of %" PRIuS " clients",
206 services_.size());
207 }
208
209
210 void QuiesceStatusChangeChecker::InitObserver(
211 ProfileSyncServiceHarness* harness) {
212 harness_ = harness;
213 }
214
215 void QuiesceStatusChangeChecker::UninitObserver(
216 ProfileSyncServiceHarness* harness) {
217 harness_ = NULL;
218 }
219
220 void QuiesceStatusChangeChecker::OnServiceStateChanged(
221 ProfileSyncService* service) {
222 harness_->OnStateChanged();
223 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698