OLD | NEW |
| (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 "components/invalidation/registration_manager.h" | |
6 | |
7 #include <algorithm> | |
8 #include <cmath> | |
9 #include <cstddef> | |
10 #include <deque> | |
11 #include <vector> | |
12 | |
13 #include "base/basictypes.h" | |
14 #include "base/message_loop/message_loop.h" | |
15 #include "base/stl_util.h" | |
16 #include "components/invalidation/invalidation_util.h" | |
17 #include "google/cacheinvalidation/include/invalidation-client.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 | |
20 namespace syncer { | |
21 namespace { | |
22 | |
23 // Fake registration manager that lets you override jitter. | |
24 class FakeRegistrationManager : public RegistrationManager { | |
25 public: | |
26 explicit FakeRegistrationManager( | |
27 invalidation::InvalidationClient* invalidation_client) | |
28 : RegistrationManager(invalidation_client), | |
29 jitter_(0.0) {} | |
30 | |
31 ~FakeRegistrationManager() override {} | |
32 | |
33 void SetJitter(double jitter) { | |
34 jitter_ = jitter; | |
35 } | |
36 | |
37 protected: | |
38 double GetJitter() override { return jitter_; } | |
39 | |
40 private: | |
41 double jitter_; | |
42 | |
43 DISALLOW_COPY_AND_ASSIGN(FakeRegistrationManager); | |
44 }; | |
45 | |
46 // Fake invalidation client that just stores the currently-registered | |
47 // object IDs. | |
48 class FakeInvalidationClient : public invalidation::InvalidationClient { | |
49 public: | |
50 FakeInvalidationClient() {} | |
51 | |
52 ~FakeInvalidationClient() override {} | |
53 | |
54 void LoseRegistration(const invalidation::ObjectId& oid) { | |
55 EXPECT_TRUE(ContainsKey(registered_ids_, oid)); | |
56 registered_ids_.erase(oid); | |
57 } | |
58 | |
59 void LoseAllRegistrations() { | |
60 registered_ids_.clear(); | |
61 } | |
62 | |
63 // invalidation::InvalidationClient implementation. | |
64 | |
65 void Start() override {} | |
66 void Stop() override {} | |
67 void Acknowledge(const invalidation::AckHandle& handle) override {} | |
68 | |
69 void Register(const invalidation::ObjectId& oid) override { | |
70 EXPECT_FALSE(ContainsKey(registered_ids_, oid)); | |
71 registered_ids_.insert(oid); | |
72 } | |
73 | |
74 void Register(const std::vector<invalidation::ObjectId>& oids) override { | |
75 // Unused for now. | |
76 } | |
77 | |
78 void Unregister(const invalidation::ObjectId& oid) override { | |
79 EXPECT_TRUE(ContainsKey(registered_ids_, oid)); | |
80 registered_ids_.erase(oid); | |
81 } | |
82 | |
83 void Unregister(const std::vector<invalidation::ObjectId>& oids) override { | |
84 // Unused for now. | |
85 } | |
86 | |
87 const ObjectIdSet& GetRegisteredIdsForTest() const { | |
88 return registered_ids_; | |
89 } | |
90 | |
91 private: | |
92 ObjectIdSet registered_ids_; | |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(FakeInvalidationClient); | |
95 }; | |
96 | |
97 size_t kObjectIdsCount = 5; | |
98 | |
99 invalidation::ObjectId GetIdForIndex(size_t index) { | |
100 char name[2] = "a"; | |
101 name[0] += static_cast<char>(index); | |
102 return invalidation::ObjectId(1 + index, name); | |
103 } | |
104 | |
105 ObjectIdSet GetSequenceOfIdsStartingAt(size_t start, size_t count) { | |
106 ObjectIdSet ids; | |
107 for (size_t i = start; i < start + count; ++i) | |
108 ids.insert(GetIdForIndex(i)); | |
109 return ids; | |
110 } | |
111 | |
112 ObjectIdSet GetSequenceOfIds(size_t count) { | |
113 return GetSequenceOfIdsStartingAt(0, count); | |
114 } | |
115 | |
116 void ExpectPendingRegistrations( | |
117 const ObjectIdSet& expected_pending_ids, | |
118 double expected_delay_seconds, | |
119 const RegistrationManager::PendingRegistrationMap& pending_registrations) { | |
120 ObjectIdSet pending_ids; | |
121 for (RegistrationManager::PendingRegistrationMap::const_iterator it = | |
122 pending_registrations.begin(); it != pending_registrations.end(); | |
123 ++it) { | |
124 SCOPED_TRACE(ObjectIdToString(it->first)); | |
125 pending_ids.insert(it->first); | |
126 base::TimeDelta offset = | |
127 it->second.last_registration_request - | |
128 it->second.registration_attempt; | |
129 base::TimeDelta expected_delay = | |
130 base::TimeDelta::FromSeconds( | |
131 static_cast<int64>(expected_delay_seconds)) + offset; | |
132 // TODO(akalin): Add base::PrintTo() for base::Time and | |
133 // base::TimeDeltas. | |
134 EXPECT_EQ(expected_delay, it->second.delay) | |
135 << expected_delay.InMicroseconds() | |
136 << ", " << it->second.delay.InMicroseconds(); | |
137 if (it->second.delay <= base::TimeDelta()) { | |
138 EXPECT_EQ(base::TimeDelta(), it->second.actual_delay); | |
139 } else { | |
140 EXPECT_EQ(it->second.actual_delay, it->second.delay); | |
141 } | |
142 } | |
143 EXPECT_EQ(expected_pending_ids, pending_ids); | |
144 } | |
145 | |
146 class RegistrationManagerTest : public testing::Test { | |
147 protected: | |
148 RegistrationManagerTest() | |
149 : fake_registration_manager_(&fake_invalidation_client_) {} | |
150 | |
151 ~RegistrationManagerTest() override {} | |
152 | |
153 void LoseRegistrations(const ObjectIdSet& oids) { | |
154 for (ObjectIdSet::const_iterator it = oids.begin(); it != oids.end(); | |
155 ++it) { | |
156 fake_invalidation_client_.LoseRegistration(*it); | |
157 fake_registration_manager_.MarkRegistrationLost(*it); | |
158 } | |
159 } | |
160 | |
161 void DisableIds(const ObjectIdSet& oids) { | |
162 for (ObjectIdSet::const_iterator it = oids.begin(); it != oids.end(); | |
163 ++it) { | |
164 fake_invalidation_client_.LoseRegistration(*it); | |
165 fake_registration_manager_.DisableId(*it); | |
166 } | |
167 } | |
168 | |
169 // Used by MarkRegistrationLostBackoff* tests. | |
170 void RunBackoffTest(double jitter) { | |
171 fake_registration_manager_.SetJitter(jitter); | |
172 ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount); | |
173 fake_registration_manager_.UpdateRegisteredIds(ids); | |
174 | |
175 // Lose some ids. | |
176 ObjectIdSet lost_ids = GetSequenceOfIds(2); | |
177 LoseRegistrations(lost_ids); | |
178 ExpectPendingRegistrations( | |
179 lost_ids, 0.0, | |
180 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
181 | |
182 // Trigger another failure to start delaying. | |
183 fake_registration_manager_.FirePendingRegistrationsForTest(); | |
184 LoseRegistrations(lost_ids); | |
185 | |
186 double scaled_jitter = | |
187 jitter * RegistrationManager::kRegistrationDelayMaxJitter; | |
188 | |
189 double expected_delay = | |
190 RegistrationManager::kInitialRegistrationDelaySeconds * | |
191 (1.0 + scaled_jitter); | |
192 expected_delay = std::floor(expected_delay); | |
193 ExpectPendingRegistrations( | |
194 lost_ids, expected_delay, | |
195 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
196 | |
197 // Trigger another failure. | |
198 fake_registration_manager_.FirePendingRegistrationsForTest(); | |
199 LoseRegistrations(lost_ids); | |
200 expected_delay *= | |
201 RegistrationManager::kRegistrationDelayExponent + scaled_jitter; | |
202 expected_delay = std::floor(expected_delay); | |
203 ExpectPendingRegistrations( | |
204 lost_ids, expected_delay, | |
205 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
206 | |
207 // Trigger enough failures to hit the ceiling. | |
208 while (expected_delay < RegistrationManager::kMaxRegistrationDelaySeconds) { | |
209 fake_registration_manager_.FirePendingRegistrationsForTest(); | |
210 LoseRegistrations(lost_ids); | |
211 expected_delay *= | |
212 RegistrationManager::kRegistrationDelayExponent + scaled_jitter; | |
213 expected_delay = std::floor(expected_delay); | |
214 } | |
215 ExpectPendingRegistrations( | |
216 lost_ids, | |
217 RegistrationManager::kMaxRegistrationDelaySeconds, | |
218 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
219 } | |
220 | |
221 FakeInvalidationClient fake_invalidation_client_; | |
222 FakeRegistrationManager fake_registration_manager_; | |
223 | |
224 private: | |
225 // Needed by timers in RegistrationManager. | |
226 base::MessageLoop message_loop_; | |
227 | |
228 DISALLOW_COPY_AND_ASSIGN(RegistrationManagerTest); | |
229 }; | |
230 | |
231 // Basic test of UpdateRegisteredIds to make sure we properly register | |
232 // new IDs and unregister any IDs no longer in the set. | |
233 TEST_F(RegistrationManagerTest, UpdateRegisteredIds) { | |
234 ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount - 1); | |
235 | |
236 EXPECT_TRUE(fake_registration_manager_.GetRegisteredIdsForTest().empty()); | |
237 EXPECT_TRUE(fake_invalidation_client_.GetRegisteredIdsForTest().empty()); | |
238 | |
239 ObjectIdSet expected_unregistered_ids; | |
240 | |
241 ObjectIdSet unregistered_ids = | |
242 fake_registration_manager_.UpdateRegisteredIds(ids); | |
243 EXPECT_EQ(expected_unregistered_ids, unregistered_ids); | |
244 EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest()); | |
245 EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest()); | |
246 | |
247 ids.insert(GetIdForIndex(kObjectIdsCount - 1)); | |
248 ids.erase(GetIdForIndex(kObjectIdsCount - 2)); | |
249 unregistered_ids = fake_registration_manager_.UpdateRegisteredIds(ids); | |
250 expected_unregistered_ids.insert(GetIdForIndex(kObjectIdsCount - 2)); | |
251 EXPECT_EQ(expected_unregistered_ids, unregistered_ids); | |
252 EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest()); | |
253 EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest()); | |
254 } | |
255 | |
256 int GetRoundedBackoff(double retry_interval, double jitter) { | |
257 const double kInitialRetryInterval = 3.0; | |
258 const double kMinRetryInterval = 2.0; | |
259 const double kMaxRetryInterval = 20.0; | |
260 const double kBackoffExponent = 2.0; | |
261 const double kMaxJitter = 0.5; | |
262 | |
263 return static_cast<int>( | |
264 RegistrationManager::CalculateBackoff(retry_interval, | |
265 kInitialRetryInterval, | |
266 kMinRetryInterval, | |
267 kMaxRetryInterval, | |
268 kBackoffExponent, | |
269 jitter, | |
270 kMaxJitter)); | |
271 } | |
272 | |
273 TEST_F(RegistrationManagerTest, CalculateBackoff) { | |
274 // Test initial. | |
275 EXPECT_EQ(2, GetRoundedBackoff(0.0, -1.0)); | |
276 EXPECT_EQ(3, GetRoundedBackoff(0.0, 0.0)); | |
277 EXPECT_EQ(4, GetRoundedBackoff(0.0, +1.0)); | |
278 | |
279 // Test non-initial. | |
280 EXPECT_EQ(4, GetRoundedBackoff(3.0, -1.0)); | |
281 EXPECT_EQ(6, GetRoundedBackoff(3.0, 0.0)); | |
282 EXPECT_EQ(7, GetRoundedBackoff(3.0, +1.0)); | |
283 | |
284 EXPECT_EQ(7, GetRoundedBackoff(5.0, -1.0)); | |
285 EXPECT_EQ(10, GetRoundedBackoff(5.0, 0.0)); | |
286 EXPECT_EQ(12, GetRoundedBackoff(5.0, +1.0)); | |
287 | |
288 // Test ceiling. | |
289 EXPECT_EQ(19, GetRoundedBackoff(13.0, -1.0)); | |
290 EXPECT_EQ(20, GetRoundedBackoff(13.0, 0.0)); | |
291 EXPECT_EQ(20, GetRoundedBackoff(13.0, +1.0)); | |
292 } | |
293 | |
294 // Losing a registration should queue automatic re-registration. | |
295 TEST_F(RegistrationManagerTest, MarkRegistrationLost) { | |
296 ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount); | |
297 | |
298 fake_registration_manager_.UpdateRegisteredIds(ids); | |
299 EXPECT_TRUE( | |
300 fake_registration_manager_.GetPendingRegistrationsForTest().empty()); | |
301 | |
302 // Lose some ids. | |
303 ObjectIdSet lost_ids = GetSequenceOfIds(3); | |
304 ObjectIdSet non_lost_ids = GetSequenceOfIdsStartingAt(3, kObjectIdsCount - 3); | |
305 LoseRegistrations(lost_ids); | |
306 ExpectPendingRegistrations( | |
307 lost_ids, 0.0, | |
308 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
309 EXPECT_EQ(non_lost_ids, fake_registration_manager_.GetRegisteredIdsForTest()); | |
310 EXPECT_EQ(non_lost_ids, fake_invalidation_client_.GetRegisteredIdsForTest()); | |
311 | |
312 // Pretend we waited long enough to re-register. | |
313 fake_registration_manager_.FirePendingRegistrationsForTest(); | |
314 EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest()); | |
315 EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest()); | |
316 } | |
317 | |
318 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffLow) { | |
319 RunBackoffTest(-1.0); | |
320 } | |
321 | |
322 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffMid) { | |
323 RunBackoffTest(0.0); | |
324 } | |
325 | |
326 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffHigh) { | |
327 RunBackoffTest(+1.0); | |
328 } | |
329 | |
330 // Exponential backoff on lost registrations should be reset to zero if | |
331 // UpdateRegisteredIds is called. | |
332 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffReset) { | |
333 ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount); | |
334 | |
335 fake_registration_manager_.UpdateRegisteredIds(ids); | |
336 | |
337 // Lose some ids. | |
338 ObjectIdSet lost_ids = GetSequenceOfIds(2); | |
339 LoseRegistrations(lost_ids); | |
340 ExpectPendingRegistrations( | |
341 lost_ids, 0.0, | |
342 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
343 | |
344 // Trigger another failure to start delaying. | |
345 fake_registration_manager_.FirePendingRegistrationsForTest(); | |
346 LoseRegistrations(lost_ids); | |
347 double expected_delay = | |
348 RegistrationManager::kInitialRegistrationDelaySeconds; | |
349 ExpectPendingRegistrations( | |
350 lost_ids, expected_delay, | |
351 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
352 | |
353 // Set ids again. | |
354 fake_registration_manager_.UpdateRegisteredIds(ids); | |
355 ExpectPendingRegistrations( | |
356 ObjectIdSet(), | |
357 0.0, | |
358 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
359 } | |
360 | |
361 TEST_F(RegistrationManagerTest, MarkAllRegistrationsLost) { | |
362 ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount); | |
363 | |
364 fake_registration_manager_.UpdateRegisteredIds(ids); | |
365 | |
366 fake_invalidation_client_.LoseAllRegistrations(); | |
367 fake_registration_manager_.MarkAllRegistrationsLost(); | |
368 | |
369 EXPECT_TRUE(fake_registration_manager_.GetRegisteredIdsForTest().empty()); | |
370 EXPECT_TRUE(fake_invalidation_client_.GetRegisteredIdsForTest().empty()); | |
371 | |
372 ExpectPendingRegistrations( | |
373 ids, 0.0, | |
374 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
375 | |
376 // Trigger another failure to start delaying. | |
377 fake_registration_manager_.FirePendingRegistrationsForTest(); | |
378 fake_invalidation_client_.LoseAllRegistrations(); | |
379 fake_registration_manager_.MarkAllRegistrationsLost(); | |
380 double expected_delay = | |
381 RegistrationManager::kInitialRegistrationDelaySeconds; | |
382 ExpectPendingRegistrations( | |
383 ids, expected_delay, | |
384 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
385 | |
386 // Pretend we waited long enough to re-register. | |
387 fake_registration_manager_.FirePendingRegistrationsForTest(); | |
388 EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest()); | |
389 EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest()); | |
390 } | |
391 | |
392 // IDs that are disabled should not be re-registered by UpdateRegisteredIds or | |
393 // automatic re-registration if that registration is lost. | |
394 TEST_F(RegistrationManagerTest, DisableId) { | |
395 ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount); | |
396 | |
397 fake_registration_manager_.UpdateRegisteredIds(ids); | |
398 EXPECT_TRUE( | |
399 fake_registration_manager_.GetPendingRegistrationsForTest().empty()); | |
400 | |
401 // Disable some ids. | |
402 ObjectIdSet disabled_ids = GetSequenceOfIds(3); | |
403 ObjectIdSet enabled_ids = GetSequenceOfIdsStartingAt(3, kObjectIdsCount - 3); | |
404 DisableIds(disabled_ids); | |
405 ExpectPendingRegistrations( | |
406 ObjectIdSet(), | |
407 0.0, | |
408 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
409 EXPECT_EQ(enabled_ids, fake_registration_manager_.GetRegisteredIdsForTest()); | |
410 EXPECT_EQ(enabled_ids, fake_invalidation_client_.GetRegisteredIdsForTest()); | |
411 | |
412 fake_registration_manager_.UpdateRegisteredIds(ids); | |
413 EXPECT_EQ(enabled_ids, fake_registration_manager_.GetRegisteredIdsForTest()); | |
414 | |
415 fake_registration_manager_.MarkRegistrationLost( | |
416 *disabled_ids.begin()); | |
417 ExpectPendingRegistrations( | |
418 ObjectIdSet(), | |
419 0.0, | |
420 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
421 | |
422 fake_registration_manager_.MarkAllRegistrationsLost(); | |
423 ExpectPendingRegistrations( | |
424 enabled_ids, 0.0, | |
425 fake_registration_manager_.GetPendingRegistrationsForTest()); | |
426 } | |
427 | |
428 } // namespace | |
429 } // namespace syncer | |
OLD | NEW |