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(AttachmentStore::Component component
,
37 const AttachmentIdList
& ids
,
38 const AttachmentStore::ReadCallback
& callback
) override
{
39 read_ids
.push_back(ids
);
40 read_callbacks
.push_back(callback
);
43 void Write(AttachmentStore::Component component
,
44 const AttachmentList
& attachments
,
45 const AttachmentStore::WriteCallback
& callback
) override
{
46 write_attachments
.push_back(attachments
);
47 write_callbacks
.push_back(callback
);
50 void SetReference(AttachmentStore::Component component
,
51 const AttachmentIdList
& ids
) override
{
52 set_reference_ids
.push_back(std::make_pair(component
, ids
));
55 void DropReference(AttachmentStore::Component component
,
56 const AttachmentIdList
& ids
,
57 const AttachmentStore::DropCallback
& callback
) override
{
58 ASSERT_EQ(AttachmentStore::SYNC
, component
);
59 drop_ids
.push_back(ids
);
62 void ReadMetadataById(
63 AttachmentStore::Component component
,
64 const AttachmentIdList
& ids
,
65 const AttachmentStore::ReadMetadataCallback
& callback
) override
{
70 AttachmentStore::Component component
,
71 const AttachmentStore::ReadMetadataCallback
& callback
) override
{
75 // Respond to Read request. Attachments found in local_attachments should be
76 // returned, everything else should be reported unavailable.
77 void RespondToRead(const AttachmentIdSet
& local_attachments
) {
78 scoped_refptr
<base::RefCountedString
> data
= new base::RefCountedString();
79 AttachmentStore::ReadCallback callback
= read_callbacks
.back();
80 AttachmentIdList ids
= read_ids
.back();
81 read_callbacks
.pop_back();
84 scoped_ptr
<AttachmentMap
> attachments(new AttachmentMap());
85 scoped_ptr
<AttachmentIdList
> unavailable_attachments(
86 new AttachmentIdList());
87 for (AttachmentIdList::const_iterator iter
= ids
.begin(); iter
!= ids
.end();
89 if (local_attachments
.find(*iter
) != local_attachments
.end()) {
90 Attachment attachment
= Attachment::CreateFromParts(*iter
, data
);
91 attachments
->insert(std::make_pair(*iter
, attachment
));
93 unavailable_attachments
->push_back(*iter
);
96 AttachmentStore::Result result
= unavailable_attachments
->empty()
97 ? AttachmentStore::SUCCESS
98 : AttachmentStore::UNSPECIFIED_ERROR
;
100 base::MessageLoop::current()->PostTask(
104 base::Passed(&attachments
),
105 base::Passed(&unavailable_attachments
)));
108 // Respond to Write request with |result|.
109 void RespondToWrite(const AttachmentStore::Result
& result
) {
110 AttachmentStore::WriteCallback callback
= write_callbacks
.back();
111 write_callbacks
.pop_back();
112 write_attachments
.pop_back();
113 base::MessageLoop::current()->PostTask(FROM_HERE
,
114 base::Bind(callback
, result
));
117 std::vector
<AttachmentIdList
> read_ids
;
118 std::vector
<AttachmentStore::ReadCallback
> read_callbacks
;
119 std::vector
<AttachmentList
> write_attachments
;
120 std::vector
<AttachmentStore::WriteCallback
> write_callbacks
;
121 std::vector
<std::pair
<AttachmentStore::Component
, AttachmentIdList
>>
123 std::vector
<AttachmentIdList
> drop_ids
;
126 DISALLOW_COPY_AND_ASSIGN(MockAttachmentStoreBackend
);
129 class MockAttachmentDownloader
130 : public AttachmentDownloader
,
131 public base::SupportsWeakPtr
<MockAttachmentDownloader
> {
133 MockAttachmentDownloader() {}
135 void DownloadAttachment(const AttachmentId
& id
,
136 const DownloadCallback
& callback
) override
{
137 ASSERT_TRUE(download_requests
.find(id
) == download_requests
.end());
138 download_requests
.insert(std::make_pair(id
, callback
));
141 // Multiple requests to download will be active at the same time.
142 // RespondToDownload should respond to only one of them.
143 void RespondToDownload(const AttachmentId
& id
, const DownloadResult
& result
) {
144 ASSERT_TRUE(download_requests
.find(id
) != download_requests
.end());
145 scoped_ptr
<Attachment
> attachment
;
146 if (result
== DOWNLOAD_SUCCESS
) {
147 scoped_refptr
<base::RefCountedString
> data
= new base::RefCountedString();
148 attachment
.reset(new Attachment(Attachment::CreateFromParts(id
, data
)));
150 base::MessageLoop::current()->PostTask(
152 base::Bind(download_requests
[id
], result
, base::Passed(&attachment
)));
154 download_requests
.erase(id
);
157 std::map
<AttachmentId
, DownloadCallback
> download_requests
;
159 DISALLOW_COPY_AND_ASSIGN(MockAttachmentDownloader
);
162 class MockAttachmentUploader
163 : public AttachmentUploader
,
164 public base::SupportsWeakPtr
<MockAttachmentUploader
> {
166 MockAttachmentUploader() {}
168 // AttachmentUploader implementation.
169 void UploadAttachment(const Attachment
& attachment
,
170 const UploadCallback
& callback
) override
{
171 const AttachmentId id
= attachment
.GetId();
172 ASSERT_TRUE(upload_requests
.find(id
) == upload_requests
.end());
173 upload_requests
.insert(std::make_pair(id
, callback
));
176 void RespondToUpload(const AttachmentId
& id
, const UploadResult
& result
) {
177 ASSERT_TRUE(upload_requests
.find(id
) != upload_requests
.end());
178 base::MessageLoop::current()->PostTask(
179 FROM_HERE
, base::Bind(upload_requests
[id
], result
, id
));
180 upload_requests
.erase(id
);
183 std::map
<AttachmentId
, UploadCallback
> upload_requests
;
185 DISALLOW_COPY_AND_ASSIGN(MockAttachmentUploader
);
190 class AttachmentServiceImplTest
: public testing::Test
,
191 public AttachmentService::Delegate
{
193 AttachmentServiceImplTest() {}
195 void SetUp() override
{
196 network_change_notifier_
.reset(net::NetworkChangeNotifier::CreateMock());
197 InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()),
198 make_scoped_ptr(new MockAttachmentDownloader()),
202 void TearDown() override
{
203 attachment_service_
.reset();
205 ASSERT_FALSE(attachment_store_backend_
);
206 ASSERT_FALSE(attachment_uploader_
);
207 ASSERT_FALSE(attachment_downloader_
);
210 // AttachmentService::Delegate implementation.
211 void OnAttachmentUploaded(const AttachmentId
& attachment_id
) override
{
212 on_attachment_uploaded_list_
.push_back(attachment_id
);
215 void InitializeAttachmentService(
216 scoped_ptr
<MockAttachmentUploader
> uploader
,
217 scoped_ptr
<MockAttachmentDownloader
> downloader
,
218 AttachmentService::Delegate
* delegate
) {
219 // Initialize mock attachment store
220 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
221 base::ThreadTaskRunnerHandle::Get();
222 scoped_ptr
<MockAttachmentStoreBackend
> attachment_store_backend(
223 new MockAttachmentStoreBackend(runner
));
224 attachment_store_backend_
= attachment_store_backend
->AsWeakPtr();
225 scoped_ptr
<AttachmentStore
> attachment_store
=
226 AttachmentStore::CreateMockStoreForTest(
227 attachment_store_backend
.Pass());
229 if (uploader
.get()) {
230 attachment_uploader_
= uploader
->AsWeakPtr();
232 if (downloader
.get()) {
233 attachment_downloader_
= downloader
->AsWeakPtr();
235 attachment_service_
.reset(new AttachmentServiceImpl(
236 attachment_store
->CreateAttachmentStoreForSync(), uploader
.Pass(),
237 downloader
.Pass(), delegate
, base::TimeDelta::FromMinutes(1),
238 base::TimeDelta::FromMinutes(8)));
240 scoped_ptr
<base::MockTimer
> timer_to_pass(
241 new base::MockTimer(false, false));
242 mock_timer_
= timer_to_pass
.get();
243 attachment_service_
->SetTimerForTest(timer_to_pass
.Pass());
246 AttachmentService
* attachment_service() { return attachment_service_
.get(); }
248 base::MockTimer
* mock_timer() { return mock_timer_
; }
250 AttachmentService::GetOrDownloadCallback
download_callback() {
251 return base::Bind(&AttachmentServiceImplTest::DownloadDone
,
252 base::Unretained(this));
255 void DownloadDone(const AttachmentService::GetOrDownloadResult
& result
,
256 scoped_ptr
<AttachmentMap
> attachments
) {
257 download_results_
.push_back(result
);
258 last_download_attachments_
= attachments
.Pass();
262 base::RunLoop run_loop
;
263 run_loop
.RunUntilIdle();
266 void RunLoopAndFireTimer() {
268 if (mock_timer()->IsRunning()) {
269 mock_timer()->Fire();
274 static AttachmentIdSet
AttachmentIdSetFromList(
275 const AttachmentIdList
& id_list
) {
276 AttachmentIdSet id_set
;
277 std::copy(id_list
.begin(), id_list
.end(),
278 std::inserter(id_set
, id_set
.end()));
282 const std::vector
<AttachmentService::GetOrDownloadResult
>&
283 download_results() const {
284 return download_results_
;
287 const AttachmentMap
& last_download_attachments() const {
288 return *last_download_attachments_
.get();
291 net::NetworkChangeNotifier
* network_change_notifier() {
292 return network_change_notifier_
.get();
295 MockAttachmentStoreBackend
* store() {
296 return attachment_store_backend_
.get();
299 MockAttachmentDownloader
* downloader() {
300 return attachment_downloader_
.get();
303 MockAttachmentUploader
* uploader() {
304 return attachment_uploader_
.get();
307 const std::vector
<AttachmentId
>& on_attachment_uploaded_list() const {
308 return on_attachment_uploaded_list_
;
312 base::MessageLoop message_loop_
;
313 scoped_ptr
<net::NetworkChangeNotifier
> network_change_notifier_
;
314 base::WeakPtr
<MockAttachmentStoreBackend
> attachment_store_backend_
;
315 base::WeakPtr
<MockAttachmentDownloader
> attachment_downloader_
;
316 base::WeakPtr
<MockAttachmentUploader
> attachment_uploader_
;
317 scoped_ptr
<AttachmentServiceImpl
> attachment_service_
;
318 base::MockTimer
* mock_timer_
; // not owned
320 std::vector
<AttachmentService::GetOrDownloadResult
> download_results_
;
321 scoped_ptr
<AttachmentMap
> last_download_attachments_
;
322 std::vector
<AttachmentId
> on_attachment_uploaded_list_
;
325 TEST_F(AttachmentServiceImplTest
, GetOrDownload_EmptyAttachmentList
) {
326 AttachmentIdList attachment_ids
;
327 attachment_service()->GetOrDownloadAttachments(attachment_ids
,
328 download_callback());
330 store()->RespondToRead(AttachmentIdSet());
333 EXPECT_EQ(1U, download_results().size());
334 EXPECT_EQ(0U, last_download_attachments().size());
337 TEST_F(AttachmentServiceImplTest
, GetOrDownload_Local
) {
338 AttachmentIdList attachment_ids
;
339 attachment_ids
.push_back(AttachmentId::Create(0, 0));
340 attachment_service()->GetOrDownloadAttachments(attachment_ids
,
341 download_callback());
342 AttachmentIdSet local_attachments
;
343 local_attachments
.insert(attachment_ids
[0]);
345 EXPECT_EQ(1U, store()->set_reference_ids
.size());
346 EXPECT_EQ(AttachmentStore::MODEL_TYPE
, store()->set_reference_ids
[0].first
);
347 store()->RespondToRead(local_attachments
);
350 EXPECT_EQ(1U, download_results().size());
351 EXPECT_EQ(1U, last_download_attachments().size());
352 EXPECT_TRUE(last_download_attachments().find(attachment_ids
[0]) !=
353 last_download_attachments().end());
356 TEST_F(AttachmentServiceImplTest
, GetOrDownload_LocalRemoteUnavailable
) {
357 // Create attachment list with 4 ids.
358 AttachmentIdList attachment_ids
;
359 attachment_ids
.push_back(AttachmentId::Create(0, 0));
360 attachment_ids
.push_back(AttachmentId::Create(0, 0));
361 attachment_ids
.push_back(AttachmentId::Create(0, 0));
362 attachment_ids
.push_back(AttachmentId::Create(0, 0));
363 // Call attachment service.
364 attachment_service()->GetOrDownloadAttachments(attachment_ids
,
365 download_callback());
367 // Ensure AttachmentStore is called.
368 EXPECT_FALSE(store()->read_ids
.empty());
370 // Make AttachmentStore return only attachment 0.
371 AttachmentIdSet local_attachments
;
372 local_attachments
.insert(attachment_ids
[0]);
373 store()->RespondToRead(local_attachments
);
375 // Ensure Downloader called with right attachment ids
376 EXPECT_EQ(3U, downloader()->download_requests
.size());
378 // Make downloader return attachment 1.
379 downloader()->RespondToDownload(attachment_ids
[1],
380 AttachmentDownloader::DOWNLOAD_SUCCESS
);
382 // Ensure consumer callback is not called.
383 EXPECT_TRUE(download_results().empty());
384 // Make AttachmentStore acknowledge writing attachment 1.
385 store()->RespondToWrite(AttachmentStore::SUCCESS
);
387 // Ensure consumer callback is not called.
388 EXPECT_TRUE(download_results().empty());
390 // Make downloader return attachment 2.
391 downloader()->RespondToDownload(attachment_ids
[2],
392 AttachmentDownloader::DOWNLOAD_SUCCESS
);
394 // Ensure consumer callback is not called.
395 EXPECT_TRUE(download_results().empty());
396 // Make AttachmentStore fail writing attachment 2.
397 store()->RespondToWrite(AttachmentStore::UNSPECIFIED_ERROR
);
399 // Ensure consumer callback is not called.
400 EXPECT_TRUE(download_results().empty());
402 // Make downloader fail attachment 3.
403 downloader()->RespondToDownload(
404 attachment_ids
[3], AttachmentDownloader::DOWNLOAD_UNSPECIFIED_ERROR
);
407 // Ensure callback is called
408 EXPECT_FALSE(download_results().empty());
409 // There should be only two attachments returned, 0 and 1.
410 EXPECT_EQ(2U, last_download_attachments().size());
411 EXPECT_TRUE(last_download_attachments().find(attachment_ids
[0]) !=
412 last_download_attachments().end());
413 EXPECT_TRUE(last_download_attachments().find(attachment_ids
[1]) !=
414 last_download_attachments().end());
415 EXPECT_TRUE(last_download_attachments().find(attachment_ids
[2]) ==
416 last_download_attachments().end());
417 EXPECT_TRUE(last_download_attachments().find(attachment_ids
[3]) ==
418 last_download_attachments().end());
421 TEST_F(AttachmentServiceImplTest
, GetOrDownload_NoDownloader
) {
423 InitializeAttachmentService(
424 make_scoped_ptr
<MockAttachmentUploader
>(new MockAttachmentUploader()),
425 make_scoped_ptr
<MockAttachmentDownloader
>(NULL
),
428 AttachmentIdList attachment_ids
;
429 attachment_ids
.push_back(AttachmentId::Create(0, 0));
430 attachment_service()->GetOrDownloadAttachments(attachment_ids
,
431 download_callback());
433 EXPECT_FALSE(store()->read_ids
.empty());
435 AttachmentIdSet local_attachments
;
436 store()->RespondToRead(local_attachments
);
438 ASSERT_EQ(1U, download_results().size());
439 EXPECT_EQ(AttachmentService::GET_UNSPECIFIED_ERROR
, download_results()[0]);
440 EXPECT_TRUE(last_download_attachments().empty());
443 TEST_F(AttachmentServiceImplTest
, UploadAttachments_Success
) {
444 AttachmentIdList attachment_ids
;
445 const unsigned num_attachments
= 3;
446 for (unsigned i
= 0; i
< num_attachments
; ++i
) {
447 attachment_ids
.push_back(AttachmentId::Create(0, 0));
449 attachment_service()->UploadAttachments(attachment_ids
);
451 ASSERT_EQ(1U, store()->set_reference_ids
.size());
452 EXPECT_EQ(AttachmentStore::SYNC
, store()->set_reference_ids
[0].first
);
453 for (unsigned i
= 0; i
< num_attachments
; ++i
) {
454 RunLoopAndFireTimer();
455 // See that the service has issued a read for at least one of the
457 ASSERT_GE(store()->read_ids
.size(), 1U);
458 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids
));
460 ASSERT_GE(uploader()->upload_requests
.size(), 1U);
461 uploader()->RespondToUpload(uploader()->upload_requests
.begin()->first
,
462 AttachmentUploader::UPLOAD_SUCCESS
);
465 ASSERT_EQ(0U, store()->read_ids
.size());
466 ASSERT_EQ(0U, uploader()->upload_requests
.size());
468 // See that all the attachments were uploaded.
469 ASSERT_EQ(attachment_ids
.size(), on_attachment_uploaded_list().size());
470 for (auto iter
= attachment_ids
.begin(); iter
!= attachment_ids
.end();
472 EXPECT_THAT(on_attachment_uploaded_list(), testing::Contains(*iter
));
474 EXPECT_EQ(num_attachments
, store()->drop_ids
.size());
477 TEST_F(AttachmentServiceImplTest
, UploadAttachments_Success_NoDelegate
) {
478 InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()),
479 make_scoped_ptr(new MockAttachmentDownloader()),
480 NULL
); // No delegate.
482 AttachmentIdList attachment_ids
;
483 attachment_ids
.push_back(AttachmentId::Create(0, 0));
484 attachment_service()->UploadAttachments(attachment_ids
);
485 RunLoopAndFireTimer();
486 ASSERT_EQ(1U, store()->read_ids
.size());
487 ASSERT_EQ(0U, uploader()->upload_requests
.size());
488 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids
));
490 ASSERT_EQ(0U, store()->read_ids
.size());
491 ASSERT_EQ(1U, uploader()->upload_requests
.size());
492 uploader()->RespondToUpload(*attachment_ids
.begin(),
493 AttachmentUploader::UPLOAD_SUCCESS
);
495 ASSERT_TRUE(on_attachment_uploaded_list().empty());
498 TEST_F(AttachmentServiceImplTest
, UploadAttachments_SomeMissingFromStore
) {
499 AttachmentIdList attachment_ids
;
500 attachment_ids
.push_back(AttachmentId::Create(0, 0));
501 attachment_ids
.push_back(AttachmentId::Create(0, 0));
502 attachment_service()->UploadAttachments(attachment_ids
);
503 RunLoopAndFireTimer();
504 ASSERT_GE(store()->read_ids
.size(), 1U);
506 ASSERT_EQ(0U, uploader()->upload_requests
.size());
507 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids
));
509 ASSERT_EQ(1U, uploader()->upload_requests
.size());
511 uploader()->RespondToUpload(uploader()->upload_requests
.begin()->first
,
512 AttachmentUploader::UPLOAD_SUCCESS
);
513 RunLoopAndFireTimer();
514 ASSERT_EQ(1U, on_attachment_uploaded_list().size());
515 ASSERT_GE(store()->read_ids
.size(), 1U);
517 store()->RespondToRead(AttachmentIdSet());
519 // No upload requests since the read failed.
520 ASSERT_EQ(0U, uploader()->upload_requests
.size());
521 EXPECT_EQ(attachment_ids
.size(), store()->drop_ids
.size());
524 TEST_F(AttachmentServiceImplTest
, UploadAttachments_AllMissingFromStore
) {
525 AttachmentIdList attachment_ids
;
526 const unsigned num_attachments
= 2;
527 for (unsigned i
= 0; i
< num_attachments
; ++i
) {
528 attachment_ids
.push_back(AttachmentId::Create(0, 0));
530 attachment_service()->UploadAttachments(attachment_ids
);
532 for (unsigned i
= 0; i
< num_attachments
; ++i
) {
533 RunLoopAndFireTimer();
534 ASSERT_GE(store()->read_ids
.size(), 1U);
536 store()->RespondToRead(AttachmentIdSet());
541 EXPECT_EQ(0U, uploader()->upload_requests
.size());
542 // See that the delegate was never called.
543 ASSERT_EQ(0U, on_attachment_uploaded_list().size());
544 EXPECT_EQ(num_attachments
, store()->drop_ids
.size());
547 TEST_F(AttachmentServiceImplTest
, UploadAttachments_NoUploader
) {
548 InitializeAttachmentService(make_scoped_ptr
<MockAttachmentUploader
>(NULL
),
549 make_scoped_ptr(new MockAttachmentDownloader()),
552 AttachmentIdList attachment_ids
;
553 attachment_ids
.push_back(AttachmentId::Create(0, 0));
554 attachment_service()->UploadAttachments(attachment_ids
);
556 EXPECT_EQ(0U, store()->read_ids
.size());
557 ASSERT_EQ(0U, on_attachment_uploaded_list().size());
558 EXPECT_EQ(0U, store()->drop_ids
.size());
561 // Upload three attachments. For one of them, server responds with error.
562 TEST_F(AttachmentServiceImplTest
, UploadAttachments_OneUploadFails
) {
563 AttachmentIdList attachment_ids
;
564 const unsigned num_attachments
= 3;
565 for (unsigned i
= 0; i
< num_attachments
; ++i
) {
566 attachment_ids
.push_back(AttachmentId::Create(0, 0));
568 attachment_service()->UploadAttachments(attachment_ids
);
570 for (unsigned i
= 0; i
< 3; ++i
) {
571 RunLoopAndFireTimer();
572 ASSERT_GE(store()->read_ids
.size(), 1U);
573 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids
));
575 ASSERT_EQ(1U, uploader()->upload_requests
.size());
576 AttachmentUploader::UploadResult result
=
577 AttachmentUploader::UPLOAD_SUCCESS
;
580 result
= AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR
;
582 result
= AttachmentUploader::UPLOAD_SUCCESS
;
584 uploader()->RespondToUpload(uploader()->upload_requests
.begin()->first
,
588 ASSERT_EQ(2U, on_attachment_uploaded_list().size());
589 EXPECT_EQ(num_attachments
, store()->drop_ids
.size());
592 // Attempt an upload, respond with transient error to trigger backoff, issue
593 // network disconnect/connect events and see that backoff is cleared.
594 TEST_F(AttachmentServiceImplTest
,
595 UploadAttachments_ResetBackoffAfterNetworkChange
) {
596 AttachmentIdList attachment_ids
;
597 attachment_ids
.push_back(AttachmentId::Create(0, 0));
598 attachment_service()->UploadAttachments(attachment_ids
);
600 RunLoopAndFireTimer();
601 ASSERT_EQ(1U, store()->read_ids
.size());
602 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids
));
604 ASSERT_EQ(1U, uploader()->upload_requests
.size());
606 uploader()->RespondToUpload(uploader()->upload_requests
.begin()->first
,
607 AttachmentUploader::UPLOAD_TRANSIENT_ERROR
);
610 // See that we are in backoff.
611 ASSERT_TRUE(mock_timer()->IsRunning());
612 ASSERT_GT(mock_timer()->GetCurrentDelay(), base::TimeDelta());
614 // Issue a network disconnect event.
615 network_change_notifier()->NotifyObserversOfNetworkChangeForTests(
616 net::NetworkChangeNotifier::CONNECTION_NONE
);
620 ASSERT_TRUE(mock_timer()->IsRunning());
621 ASSERT_GT(mock_timer()->GetCurrentDelay(), base::TimeDelta());
623 // Issue a network connect event.
624 net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
625 net::NetworkChangeNotifier::CONNECTION_WIFI
);
628 // No longer in backoff.
629 ASSERT_TRUE(mock_timer()->IsRunning());
630 ASSERT_EQ(base::TimeDelta(), mock_timer()->GetCurrentDelay());
633 } // namespace syncer