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.
5 #include "sync/internal_api/public/attachments/attachment_service_impl.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/timer/mock_timer.h"
13 #include "sync/api/attachments/attachment_store_backend.h"
14 #include "sync/internal_api/public/attachments/attachment_util.h"
15 #include "sync/internal_api/public/attachments/fake_attachment_downloader.h"
16 #include "sync/internal_api/public/attachments/fake_attachment_uploader.h"
17 #include "testing/gmock/include/gmock/gmock-matchers.h"
18 #include "testing/gtest/include/gtest/gtest.h"
24 class MockAttachmentStoreBackend
25 : public AttachmentStoreBackend
,
26 public base::SupportsWeakPtr
<MockAttachmentStoreBackend
> {
28 MockAttachmentStoreBackend(
29 const scoped_refptr
<base::SequencedTaskRunner
>& callback_task_runner
)
30 : AttachmentStoreBackend(callback_task_runner
) {}
32 ~MockAttachmentStoreBackend() override
{}
34 void Init(const AttachmentStore::InitCallback
& callback
) override
{}
36 void Read(const AttachmentIdList
& ids
,
37 const AttachmentStore::ReadCallback
& callback
) override
{
38 read_ids
.push_back(ids
);
39 read_callbacks
.push_back(callback
);
42 void Write(AttachmentStore::Component component
,
43 const AttachmentList
& attachments
,
44 const AttachmentStore::WriteCallback
& callback
) override
{
45 write_attachments
.push_back(attachments
);
46 write_callbacks
.push_back(callback
);
49 void SetReference(AttachmentStore::Component component
,
50 const AttachmentIdList
& ids
) override
{
51 set_reference_ids
.push_back(ids
);
54 void DropReference(AttachmentStore::Component component
,
55 const AttachmentIdList
& ids
,
56 const AttachmentStore::DropCallback
& callback
) override
{
57 ASSERT_EQ(AttachmentStore::SYNC
, component
);
58 drop_ids
.push_back(ids
);
62 const AttachmentIdList
& ids
,
63 const AttachmentStore::ReadMetadataCallback
& callback
) override
{
68 AttachmentStore::Component component
,
69 const AttachmentStore::ReadMetadataCallback
& callback
) override
{
73 // Respond to Read request. Attachments found in local_attachments should be
74 // returned, everything else should be reported unavailable.
75 void RespondToRead(const AttachmentIdSet
& local_attachments
) {
76 scoped_refptr
<base::RefCountedString
> data
= new base::RefCountedString();
77 AttachmentStore::ReadCallback callback
= read_callbacks
.back();
78 AttachmentIdList ids
= read_ids
.back();
79 read_callbacks
.pop_back();
82 scoped_ptr
<AttachmentMap
> attachments(new AttachmentMap());
83 scoped_ptr
<AttachmentIdList
> unavailable_attachments(
84 new AttachmentIdList());
85 for (AttachmentIdList::const_iterator iter
= ids
.begin(); iter
!= ids
.end();
87 if (local_attachments
.find(*iter
) != local_attachments
.end()) {
88 Attachment attachment
= Attachment::CreateFromParts(*iter
, data
);
89 attachments
->insert(std::make_pair(*iter
, attachment
));
91 unavailable_attachments
->push_back(*iter
);
94 AttachmentStore::Result result
= unavailable_attachments
->empty()
95 ? AttachmentStore::SUCCESS
96 : AttachmentStore::UNSPECIFIED_ERROR
;
98 base::MessageLoop::current()->PostTask(
102 base::Passed(&attachments
),
103 base::Passed(&unavailable_attachments
)));
106 // Respond to Write request with |result|.
107 void RespondToWrite(const AttachmentStore::Result
& result
) {
108 AttachmentStore::WriteCallback callback
= write_callbacks
.back();
109 write_callbacks
.pop_back();
110 write_attachments
.pop_back();
111 base::MessageLoop::current()->PostTask(FROM_HERE
,
112 base::Bind(callback
, result
));
115 std::vector
<AttachmentIdList
> read_ids
;
116 std::vector
<AttachmentStore::ReadCallback
> read_callbacks
;
117 std::vector
<AttachmentList
> write_attachments
;
118 std::vector
<AttachmentStore::WriteCallback
> write_callbacks
;
119 std::vector
<AttachmentIdList
> set_reference_ids
;
120 std::vector
<AttachmentIdList
> drop_ids
;
123 DISALLOW_COPY_AND_ASSIGN(MockAttachmentStoreBackend
);
126 class MockAttachmentDownloader
127 : public AttachmentDownloader
,
128 public base::SupportsWeakPtr
<MockAttachmentDownloader
> {
130 MockAttachmentDownloader() {}
132 void DownloadAttachment(const AttachmentId
& id
,
133 const DownloadCallback
& callback
) override
{
134 ASSERT_TRUE(download_requests
.find(id
) == download_requests
.end());
135 download_requests
.insert(std::make_pair(id
, callback
));
138 // Multiple requests to download will be active at the same time.
139 // RespondToDownload should respond to only one of them.
140 void RespondToDownload(const AttachmentId
& id
, const DownloadResult
& result
) {
141 ASSERT_TRUE(download_requests
.find(id
) != download_requests
.end());
142 scoped_ptr
<Attachment
> attachment
;
143 if (result
== DOWNLOAD_SUCCESS
) {
144 scoped_refptr
<base::RefCountedString
> data
= new base::RefCountedString();
145 attachment
.reset(new Attachment(Attachment::CreateFromParts(id
, data
)));
147 base::MessageLoop::current()->PostTask(
149 base::Bind(download_requests
[id
], result
, base::Passed(&attachment
)));
151 download_requests
.erase(id
);
154 std::map
<AttachmentId
, DownloadCallback
> download_requests
;
156 DISALLOW_COPY_AND_ASSIGN(MockAttachmentDownloader
);
159 class MockAttachmentUploader
160 : public AttachmentUploader
,
161 public base::SupportsWeakPtr
<MockAttachmentUploader
> {
163 MockAttachmentUploader() {}
165 // AttachmentUploader implementation.
166 void UploadAttachment(const Attachment
& attachment
,
167 const UploadCallback
& callback
) override
{
168 const AttachmentId id
= attachment
.GetId();
169 ASSERT_TRUE(upload_requests
.find(id
) == upload_requests
.end());
170 upload_requests
.insert(std::make_pair(id
, callback
));
173 void RespondToUpload(const AttachmentId
& id
, const UploadResult
& result
) {
174 ASSERT_TRUE(upload_requests
.find(id
) != upload_requests
.end());
175 base::MessageLoop::current()->PostTask(
176 FROM_HERE
, base::Bind(upload_requests
[id
], result
, id
));
177 upload_requests
.erase(id
);
180 std::map
<AttachmentId
, UploadCallback
> upload_requests
;
182 DISALLOW_COPY_AND_ASSIGN(MockAttachmentUploader
);
187 class AttachmentServiceImplTest
: public testing::Test
,
188 public AttachmentService::Delegate
{
190 AttachmentServiceImplTest() {}
192 void SetUp() override
{
193 network_change_notifier_
.reset(net::NetworkChangeNotifier::CreateMock());
194 InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()),
195 make_scoped_ptr(new MockAttachmentDownloader()),
199 void TearDown() override
{
200 attachment_service_
.reset();
202 ASSERT_FALSE(attachment_store_backend_
);
203 ASSERT_FALSE(attachment_uploader_
);
204 ASSERT_FALSE(attachment_downloader_
);
207 // AttachmentService::Delegate implementation.
208 void OnAttachmentUploaded(const AttachmentId
& attachment_id
) override
{
209 on_attachment_uploaded_list_
.push_back(attachment_id
);
212 void InitializeAttachmentService(
213 scoped_ptr
<MockAttachmentUploader
> uploader
,
214 scoped_ptr
<MockAttachmentDownloader
> downloader
,
215 AttachmentService::Delegate
* delegate
) {
216 // Initialize mock attachment store
217 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
218 base::ThreadTaskRunnerHandle::Get();
219 scoped_ptr
<MockAttachmentStoreBackend
> attachment_store_backend(
220 new MockAttachmentStoreBackend(runner
));
221 attachment_store_backend_
= attachment_store_backend
->AsWeakPtr();
222 scoped_ptr
<AttachmentStore
> attachment_store
=
223 AttachmentStore::CreateMockStoreForTest(
224 attachment_store_backend
.Pass());
226 if (uploader
.get()) {
227 attachment_uploader_
= uploader
->AsWeakPtr();
229 if (downloader
.get()) {
230 attachment_downloader_
= downloader
->AsWeakPtr();
232 attachment_service_
.reset(new AttachmentServiceImpl(
233 attachment_store
->CreateAttachmentStoreForSync(), uploader
.Pass(),
234 downloader
.Pass(), delegate
, base::TimeDelta::FromMinutes(1),
235 base::TimeDelta::FromMinutes(8)));
237 scoped_ptr
<base::MockTimer
> timer_to_pass(
238 new base::MockTimer(false, false));
239 mock_timer_
= timer_to_pass
.get();
240 attachment_service_
->SetTimerForTest(timer_to_pass
.Pass());
243 AttachmentService
* attachment_service() { return attachment_service_
.get(); }
245 base::MockTimer
* mock_timer() { return mock_timer_
; }
247 AttachmentService::GetOrDownloadCallback
download_callback() {
248 return base::Bind(&AttachmentServiceImplTest::DownloadDone
,
249 base::Unretained(this));
252 void DownloadDone(const AttachmentService::GetOrDownloadResult
& result
,
253 scoped_ptr
<AttachmentMap
> attachments
) {
254 download_results_
.push_back(result
);
255 last_download_attachments_
= attachments
.Pass();
259 base::RunLoop run_loop
;
260 run_loop
.RunUntilIdle();
263 void RunLoopAndFireTimer() {
265 if (mock_timer()->IsRunning()) {
266 mock_timer()->Fire();
271 static AttachmentIdSet
AttachmentIdSetFromList(
272 const AttachmentIdList
& id_list
) {
273 AttachmentIdSet id_set
;
274 std::copy(id_list
.begin(), id_list
.end(),
275 std::inserter(id_set
, id_set
.end()));
279 const std::vector
<AttachmentService::GetOrDownloadResult
>&
280 download_results() const {
281 return download_results_
;
284 const AttachmentMap
& last_download_attachments() const {
285 return *last_download_attachments_
.get();
288 net::NetworkChangeNotifier
* network_change_notifier() {
289 return network_change_notifier_
.get();
292 MockAttachmentStoreBackend
* store() {
293 return attachment_store_backend_
.get();
296 MockAttachmentDownloader
* downloader() {
297 return attachment_downloader_
.get();
300 MockAttachmentUploader
* uploader() {
301 return attachment_uploader_
.get();
304 const std::vector
<AttachmentId
>& on_attachment_uploaded_list() const {
305 return on_attachment_uploaded_list_
;
309 base::MessageLoop message_loop_
;
310 scoped_ptr
<net::NetworkChangeNotifier
> network_change_notifier_
;
311 base::WeakPtr
<MockAttachmentStoreBackend
> attachment_store_backend_
;
312 base::WeakPtr
<MockAttachmentDownloader
> attachment_downloader_
;
313 base::WeakPtr
<MockAttachmentUploader
> attachment_uploader_
;
314 scoped_ptr
<AttachmentServiceImpl
> attachment_service_
;
315 base::MockTimer
* mock_timer_
; // not owned
317 std::vector
<AttachmentService::GetOrDownloadResult
> download_results_
;
318 scoped_ptr
<AttachmentMap
> last_download_attachments_
;
319 std::vector
<AttachmentId
> on_attachment_uploaded_list_
;
322 TEST_F(AttachmentServiceImplTest
, GetOrDownload_EmptyAttachmentList
) {
323 AttachmentIdList attachment_ids
;
324 attachment_service()->GetOrDownloadAttachments(attachment_ids
,
325 download_callback());
327 store()->RespondToRead(AttachmentIdSet());
330 EXPECT_EQ(1U, download_results().size());
331 EXPECT_EQ(0U, last_download_attachments().size());
334 TEST_F(AttachmentServiceImplTest
, GetOrDownload_Local
) {
335 AttachmentIdList attachment_ids
;
336 attachment_ids
.push_back(AttachmentId::Create(0, 0));
337 attachment_service()->GetOrDownloadAttachments(attachment_ids
,
338 download_callback());
339 AttachmentIdSet local_attachments
;
340 local_attachments
.insert(attachment_ids
[0]);
342 store()->RespondToRead(local_attachments
);
345 EXPECT_EQ(1U, download_results().size());
346 EXPECT_EQ(1U, last_download_attachments().size());
347 EXPECT_TRUE(last_download_attachments().find(attachment_ids
[0]) !=
348 last_download_attachments().end());
351 TEST_F(AttachmentServiceImplTest
, GetOrDownload_LocalRemoteUnavailable
) {
352 // Create attachment list with 4 ids.
353 AttachmentIdList attachment_ids
;
354 attachment_ids
.push_back(AttachmentId::Create(0, 0));
355 attachment_ids
.push_back(AttachmentId::Create(0, 0));
356 attachment_ids
.push_back(AttachmentId::Create(0, 0));
357 attachment_ids
.push_back(AttachmentId::Create(0, 0));
358 // Call attachment service.
359 attachment_service()->GetOrDownloadAttachments(attachment_ids
,
360 download_callback());
362 // Ensure AttachmentStore is called.
363 EXPECT_FALSE(store()->read_ids
.empty());
365 // Make AttachmentStore return only attachment 0.
366 AttachmentIdSet local_attachments
;
367 local_attachments
.insert(attachment_ids
[0]);
368 store()->RespondToRead(local_attachments
);
370 // Ensure Downloader called with right attachment ids
371 EXPECT_EQ(3U, downloader()->download_requests
.size());
373 // Make downloader return attachment 1.
374 downloader()->RespondToDownload(attachment_ids
[1],
375 AttachmentDownloader::DOWNLOAD_SUCCESS
);
377 // Ensure consumer callback is not called.
378 EXPECT_TRUE(download_results().empty());
379 // Make AttachmentStore acknowledge writing attachment 1.
380 store()->RespondToWrite(AttachmentStore::SUCCESS
);
382 // Ensure consumer callback is not called.
383 EXPECT_TRUE(download_results().empty());
385 // Make downloader return attachment 2.
386 downloader()->RespondToDownload(attachment_ids
[2],
387 AttachmentDownloader::DOWNLOAD_SUCCESS
);
389 // Ensure consumer callback is not called.
390 EXPECT_TRUE(download_results().empty());
391 // Make AttachmentStore fail writing attachment 2.
392 store()->RespondToWrite(AttachmentStore::UNSPECIFIED_ERROR
);
394 // Ensure consumer callback is not called.
395 EXPECT_TRUE(download_results().empty());
397 // Make downloader fail attachment 3.
398 downloader()->RespondToDownload(
399 attachment_ids
[3], AttachmentDownloader::DOWNLOAD_UNSPECIFIED_ERROR
);
402 // Ensure callback is called
403 EXPECT_FALSE(download_results().empty());
404 // There should be only two attachments returned, 0 and 1.
405 EXPECT_EQ(2U, last_download_attachments().size());
406 EXPECT_TRUE(last_download_attachments().find(attachment_ids
[0]) !=
407 last_download_attachments().end());
408 EXPECT_TRUE(last_download_attachments().find(attachment_ids
[1]) !=
409 last_download_attachments().end());
410 EXPECT_TRUE(last_download_attachments().find(attachment_ids
[2]) ==
411 last_download_attachments().end());
412 EXPECT_TRUE(last_download_attachments().find(attachment_ids
[3]) ==
413 last_download_attachments().end());
416 TEST_F(AttachmentServiceImplTest
, GetOrDownload_NoDownloader
) {
418 InitializeAttachmentService(
419 make_scoped_ptr
<MockAttachmentUploader
>(new MockAttachmentUploader()),
420 make_scoped_ptr
<MockAttachmentDownloader
>(NULL
),
423 AttachmentIdList attachment_ids
;
424 attachment_ids
.push_back(AttachmentId::Create(0, 0));
425 attachment_service()->GetOrDownloadAttachments(attachment_ids
,
426 download_callback());
428 EXPECT_FALSE(store()->read_ids
.empty());
430 AttachmentIdSet local_attachments
;
431 store()->RespondToRead(local_attachments
);
433 ASSERT_EQ(1U, download_results().size());
434 EXPECT_EQ(AttachmentService::GET_UNSPECIFIED_ERROR
, download_results()[0]);
435 EXPECT_TRUE(last_download_attachments().empty());
438 TEST_F(AttachmentServiceImplTest
, UploadAttachments_Success
) {
439 AttachmentIdList attachment_ids
;
440 const unsigned num_attachments
= 3;
441 for (unsigned i
= 0; i
< num_attachments
; ++i
) {
442 attachment_ids
.push_back(AttachmentId::Create(0, 0));
444 attachment_service()->UploadAttachments(attachment_ids
);
446 EXPECT_FALSE(store()->set_reference_ids
.empty());
447 for (unsigned i
= 0; i
< num_attachments
; ++i
) {
448 RunLoopAndFireTimer();
449 // See that the service has issued a read for at least one of the
451 ASSERT_GE(store()->read_ids
.size(), 1U);
452 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids
));
454 ASSERT_GE(uploader()->upload_requests
.size(), 1U);
455 uploader()->RespondToUpload(uploader()->upload_requests
.begin()->first
,
456 AttachmentUploader::UPLOAD_SUCCESS
);
459 ASSERT_EQ(0U, store()->read_ids
.size());
460 ASSERT_EQ(0U, uploader()->upload_requests
.size());
462 // See that all the attachments were uploaded.
463 ASSERT_EQ(attachment_ids
.size(), on_attachment_uploaded_list().size());
464 for (auto iter
= attachment_ids
.begin(); iter
!= attachment_ids
.end();
466 EXPECT_THAT(on_attachment_uploaded_list(), testing::Contains(*iter
));
468 EXPECT_EQ(num_attachments
, store()->drop_ids
.size());
471 TEST_F(AttachmentServiceImplTest
, UploadAttachments_Success_NoDelegate
) {
472 InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()),
473 make_scoped_ptr(new MockAttachmentDownloader()),
474 NULL
); // No delegate.
476 AttachmentIdList attachment_ids
;
477 attachment_ids
.push_back(AttachmentId::Create(0, 0));
478 attachment_service()->UploadAttachments(attachment_ids
);
479 RunLoopAndFireTimer();
480 ASSERT_EQ(1U, store()->read_ids
.size());
481 ASSERT_EQ(0U, uploader()->upload_requests
.size());
482 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids
));
484 ASSERT_EQ(0U, store()->read_ids
.size());
485 ASSERT_EQ(1U, uploader()->upload_requests
.size());
486 uploader()->RespondToUpload(*attachment_ids
.begin(),
487 AttachmentUploader::UPLOAD_SUCCESS
);
489 ASSERT_TRUE(on_attachment_uploaded_list().empty());
492 TEST_F(AttachmentServiceImplTest
, UploadAttachments_SomeMissingFromStore
) {
493 AttachmentIdList attachment_ids
;
494 attachment_ids
.push_back(AttachmentId::Create(0, 0));
495 attachment_ids
.push_back(AttachmentId::Create(0, 0));
496 attachment_service()->UploadAttachments(attachment_ids
);
497 RunLoopAndFireTimer();
498 ASSERT_GE(store()->read_ids
.size(), 1U);
500 ASSERT_EQ(0U, uploader()->upload_requests
.size());
501 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids
));
503 ASSERT_EQ(1U, uploader()->upload_requests
.size());
505 uploader()->RespondToUpload(uploader()->upload_requests
.begin()->first
,
506 AttachmentUploader::UPLOAD_SUCCESS
);
507 RunLoopAndFireTimer();
508 ASSERT_EQ(1U, on_attachment_uploaded_list().size());
509 ASSERT_GE(store()->read_ids
.size(), 1U);
511 store()->RespondToRead(AttachmentIdSet());
513 // No upload requests since the read failed.
514 ASSERT_EQ(0U, uploader()->upload_requests
.size());
515 EXPECT_EQ(attachment_ids
.size(), store()->drop_ids
.size());
518 TEST_F(AttachmentServiceImplTest
, UploadAttachments_AllMissingFromStore
) {
519 AttachmentIdList attachment_ids
;
520 const unsigned num_attachments
= 2;
521 for (unsigned i
= 0; i
< num_attachments
; ++i
) {
522 attachment_ids
.push_back(AttachmentId::Create(0, 0));
524 attachment_service()->UploadAttachments(attachment_ids
);
526 for (unsigned i
= 0; i
< num_attachments
; ++i
) {
527 RunLoopAndFireTimer();
528 ASSERT_GE(store()->read_ids
.size(), 1U);
530 store()->RespondToRead(AttachmentIdSet());
535 EXPECT_EQ(0U, uploader()->upload_requests
.size());
536 // See that the delegate was never called.
537 ASSERT_EQ(0U, on_attachment_uploaded_list().size());
538 EXPECT_EQ(num_attachments
, store()->drop_ids
.size());
541 TEST_F(AttachmentServiceImplTest
, UploadAttachments_NoUploader
) {
542 InitializeAttachmentService(make_scoped_ptr
<MockAttachmentUploader
>(NULL
),
543 make_scoped_ptr(new MockAttachmentDownloader()),
546 AttachmentIdList attachment_ids
;
547 attachment_ids
.push_back(AttachmentId::Create(0, 0));
548 attachment_service()->UploadAttachments(attachment_ids
);
550 EXPECT_EQ(0U, store()->read_ids
.size());
551 ASSERT_EQ(0U, on_attachment_uploaded_list().size());
552 EXPECT_EQ(0U, store()->drop_ids
.size());
555 // Upload three attachments. For one of them, server responds with error.
556 TEST_F(AttachmentServiceImplTest
, UploadAttachments_OneUploadFails
) {
557 AttachmentIdList attachment_ids
;
558 const unsigned num_attachments
= 3;
559 for (unsigned i
= 0; i
< num_attachments
; ++i
) {
560 attachment_ids
.push_back(AttachmentId::Create(0, 0));
562 attachment_service()->UploadAttachments(attachment_ids
);
564 for (unsigned i
= 0; i
< 3; ++i
) {
565 RunLoopAndFireTimer();
566 ASSERT_GE(store()->read_ids
.size(), 1U);
567 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids
));
569 ASSERT_EQ(1U, uploader()->upload_requests
.size());
570 AttachmentUploader::UploadResult result
=
571 AttachmentUploader::UPLOAD_SUCCESS
;
574 result
= AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR
;
576 result
= AttachmentUploader::UPLOAD_SUCCESS
;
578 uploader()->RespondToUpload(uploader()->upload_requests
.begin()->first
,
582 ASSERT_EQ(2U, on_attachment_uploaded_list().size());
583 EXPECT_EQ(num_attachments
, store()->drop_ids
.size());
586 // Attempt an upload, respond with transient error to trigger backoff, issue
587 // network disconnect/connect events and see that backoff is cleared.
588 TEST_F(AttachmentServiceImplTest
,
589 UploadAttachments_ResetBackoffAfterNetworkChange
) {
590 AttachmentIdList attachment_ids
;
591 attachment_ids
.push_back(AttachmentId::Create(0, 0));
592 attachment_service()->UploadAttachments(attachment_ids
);
594 RunLoopAndFireTimer();
595 ASSERT_EQ(1U, store()->read_ids
.size());
596 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids
));
598 ASSERT_EQ(1U, uploader()->upload_requests
.size());
600 uploader()->RespondToUpload(uploader()->upload_requests
.begin()->first
,
601 AttachmentUploader::UPLOAD_TRANSIENT_ERROR
);
604 // See that we are in backoff.
605 ASSERT_TRUE(mock_timer()->IsRunning());
606 ASSERT_GT(mock_timer()->GetCurrentDelay(), base::TimeDelta());
608 // Issue a network disconnect event.
609 network_change_notifier()->NotifyObserversOfNetworkChangeForTests(
610 net::NetworkChangeNotifier::CONNECTION_NONE
);
614 ASSERT_TRUE(mock_timer()->IsRunning());
615 ASSERT_GT(mock_timer()->GetCurrentDelay(), base::TimeDelta());
617 // Issue a network connect event.
618 net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
619 net::NetworkChangeNotifier::CONNECTION_WIFI
);
622 // No longer in backoff.
623 ASSERT_TRUE(mock_timer()->IsRunning());
624 ASSERT_EQ(base::TimeDelta(), mock_timer()->GetCurrentDelay());
627 } // namespace syncer