We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / sync / internal_api / attachments / attachment_service_impl_unittest.cc
blobf619b75d13a4d44d5192bf5c2728752f36933fe1
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"
7 #include "base/bind.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"
20 namespace syncer {
22 namespace {
24 class MockAttachmentStoreBackend
25 : public AttachmentStoreBackend,
26 public base::SupportsWeakPtr<MockAttachmentStoreBackend> {
27 public:
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);
61 void ReadMetadata(
62 const AttachmentIdList& ids,
63 const AttachmentStore::ReadMetadataCallback& callback) override {
64 NOTREACHED();
67 void ReadAllMetadata(
68 AttachmentStore::Component component,
69 const AttachmentStore::ReadMetadataCallback& callback) override {
70 NOTREACHED();
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();
80 read_ids.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();
86 ++iter) {
87 if (local_attachments.find(*iter) != local_attachments.end()) {
88 Attachment attachment = Attachment::CreateFromParts(*iter, data);
89 attachments->insert(std::make_pair(*iter, attachment));
90 } else {
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(
99 FROM_HERE,
100 base::Bind(callback,
101 result,
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;
122 private:
123 DISALLOW_COPY_AND_ASSIGN(MockAttachmentStoreBackend);
126 class MockAttachmentDownloader
127 : public AttachmentDownloader,
128 public base::SupportsWeakPtr<MockAttachmentDownloader> {
129 public:
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(
148 FROM_HERE,
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> {
162 public:
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);
185 } // namespace
187 class AttachmentServiceImplTest : public testing::Test,
188 public AttachmentService::Delegate {
189 protected:
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()),
196 this);
199 void TearDown() override {
200 attachment_service_.reset();
201 RunLoop();
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();
258 void RunLoop() {
259 base::RunLoop run_loop;
260 run_loop.RunUntilIdle();
263 void RunLoopAndFireTimer() {
264 RunLoop();
265 if (mock_timer()->IsRunning()) {
266 mock_timer()->Fire();
267 RunLoop();
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()));
276 return id_set;
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_;
308 private:
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());
326 RunLoop();
327 store()->RespondToRead(AttachmentIdSet());
329 RunLoop();
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]);
341 RunLoop();
342 store()->RespondToRead(local_attachments);
344 RunLoop();
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());
361 RunLoop();
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);
369 RunLoop();
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);
376 RunLoop();
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);
381 RunLoop();
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);
388 RunLoop();
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);
393 RunLoop();
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);
400 RunLoop();
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) {
417 // No downloader.
418 InitializeAttachmentService(
419 make_scoped_ptr<MockAttachmentUploader>(new MockAttachmentUploader()),
420 make_scoped_ptr<MockAttachmentDownloader>(NULL),
421 this);
423 AttachmentIdList attachment_ids;
424 attachment_ids.push_back(AttachmentId::Create(0, 0));
425 attachment_service()->GetOrDownloadAttachments(attachment_ids,
426 download_callback());
427 RunLoop();
428 EXPECT_FALSE(store()->read_ids.empty());
430 AttachmentIdSet local_attachments;
431 store()->RespondToRead(local_attachments);
432 RunLoop();
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);
445 RunLoop();
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
450 // attachments.
451 ASSERT_GE(store()->read_ids.size(), 1U);
452 store()->RespondToRead(AttachmentIdSetFromList(attachment_ids));
453 RunLoop();
454 ASSERT_GE(uploader()->upload_requests.size(), 1U);
455 uploader()->RespondToUpload(uploader()->upload_requests.begin()->first,
456 AttachmentUploader::UPLOAD_SUCCESS);
458 RunLoop();
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();
465 ++iter) {
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));
483 RunLoop();
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);
488 RunLoop();
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));
502 RunLoop();
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);
510 // Not found!
511 store()->RespondToRead(AttachmentIdSet());
512 RunLoop();
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);
529 // None found!
530 store()->RespondToRead(AttachmentIdSet());
532 RunLoop();
534 // Nothing uploaded.
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()),
544 this);
546 AttachmentIdList attachment_ids;
547 attachment_ids.push_back(AttachmentId::Create(0, 0));
548 attachment_service()->UploadAttachments(attachment_ids);
549 RunLoop();
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));
568 RunLoop();
569 ASSERT_EQ(1U, uploader()->upload_requests.size());
570 AttachmentUploader::UploadResult result =
571 AttachmentUploader::UPLOAD_SUCCESS;
572 // Fail the 2nd one.
573 if (i == 2U) {
574 result = AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR;
575 } else {
576 result = AttachmentUploader::UPLOAD_SUCCESS;
578 uploader()->RespondToUpload(uploader()->upload_requests.begin()->first,
579 result);
580 RunLoop();
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));
597 RunLoop();
598 ASSERT_EQ(1U, uploader()->upload_requests.size());
600 uploader()->RespondToUpload(uploader()->upload_requests.begin()->first,
601 AttachmentUploader::UPLOAD_TRANSIENT_ERROR);
602 RunLoop();
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);
611 RunLoop();
613 // Still in backoff.
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);
620 RunLoop();
622 // No longer in backoff.
623 ASSERT_TRUE(mock_timer()->IsRunning());
624 ASSERT_EQ(base::TimeDelta(), mock_timer()->GetCurrentDelay());
627 } // namespace syncer