Provide GUID in ONC for all networks in ManagedNetworkConfigurationHandler
[chromium-blink-merge.git] / sync / internal_api / attachments / attachment_service_impl_unittest.cc
blobe72bb8fe578f469740f4744f0839c4cec1b28a48
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/timer/mock_timer.h"
12 #include "sync/internal_api/public/attachments/attachment_util.h"
13 #include "sync/internal_api/public/attachments/fake_attachment_downloader.h"
14 #include "sync/internal_api/public/attachments/fake_attachment_uploader.h"
15 #include "testing/gmock/include/gmock/gmock-matchers.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 namespace syncer {
20 namespace {
22 class MockAttachmentStore : public AttachmentStore,
23 public base::SupportsWeakPtr<MockAttachmentStore> {
24 public:
25 MockAttachmentStore() {}
27 void Init(const InitCallback& callback) override {
30 void Read(const AttachmentIdList& ids,
31 const ReadCallback& callback) override {
32 read_ids.push_back(ids);
33 read_callbacks.push_back(callback);
36 void Write(const AttachmentList& attachments,
37 const WriteCallback& callback) override {
38 write_attachments.push_back(attachments);
39 write_callbacks.push_back(callback);
42 void Drop(const AttachmentIdList& ids,
43 const DropCallback& callback) override {
44 NOTREACHED();
47 void ReadMetadata(const AttachmentIdList& ids,
48 const ReadMetadataCallback& callback) override {
49 NOTREACHED();
52 void ReadAllMetadata(const ReadMetadataCallback& callback) override {
53 NOTREACHED();
56 // Respond to Read request. Attachments found in local_attachments should be
57 // returned, everything else should be reported unavailable.
58 void RespondToRead(const AttachmentIdSet& local_attachments) {
59 scoped_refptr<base::RefCountedString> data = new base::RefCountedString();
60 ReadCallback callback = read_callbacks.back();
61 AttachmentIdList ids = read_ids.back();
62 read_callbacks.pop_back();
63 read_ids.pop_back();
65 scoped_ptr<AttachmentMap> attachments(new AttachmentMap());
66 scoped_ptr<AttachmentIdList> unavailable_attachments(
67 new AttachmentIdList());
68 for (AttachmentIdList::const_iterator iter = ids.begin(); iter != ids.end();
69 ++iter) {
70 if (local_attachments.find(*iter) != local_attachments.end()) {
71 uint32_t crc32c = ComputeCrc32c(data);
72 Attachment attachment =
73 Attachment::CreateFromParts(*iter, data, crc32c);
74 attachments->insert(std::make_pair(*iter, attachment));
75 } else {
76 unavailable_attachments->push_back(*iter);
79 Result result =
80 unavailable_attachments->empty() ? SUCCESS : UNSPECIFIED_ERROR;
82 base::MessageLoop::current()->PostTask(
83 FROM_HERE,
84 base::Bind(callback,
85 result,
86 base::Passed(&attachments),
87 base::Passed(&unavailable_attachments)));
90 // Respond to Write request with |result|.
91 void RespondToWrite(const Result& result) {
92 WriteCallback callback = write_callbacks.back();
93 AttachmentList attachments = write_attachments.back();
94 write_callbacks.pop_back();
95 write_attachments.pop_back();
96 base::MessageLoop::current()->PostTask(FROM_HERE,
97 base::Bind(callback, result));
100 std::vector<AttachmentIdList> read_ids;
101 std::vector<ReadCallback> read_callbacks;
102 std::vector<AttachmentList> write_attachments;
103 std::vector<WriteCallback> write_callbacks;
105 private:
106 ~MockAttachmentStore() override {}
108 DISALLOW_COPY_AND_ASSIGN(MockAttachmentStore);
111 class MockAttachmentDownloader
112 : public AttachmentDownloader,
113 public base::SupportsWeakPtr<MockAttachmentDownloader> {
114 public:
115 MockAttachmentDownloader() {}
117 void DownloadAttachment(const AttachmentId& id,
118 const DownloadCallback& callback) override {
119 ASSERT_TRUE(download_requests.find(id) == download_requests.end());
120 download_requests.insert(std::make_pair(id, callback));
123 // Multiple requests to download will be active at the same time.
124 // RespondToDownload should respond to only one of them.
125 void RespondToDownload(const AttachmentId& id, const DownloadResult& result) {
126 ASSERT_TRUE(download_requests.find(id) != download_requests.end());
127 scoped_ptr<Attachment> attachment;
128 if (result == DOWNLOAD_SUCCESS) {
129 scoped_refptr<base::RefCountedString> data = new base::RefCountedString();
130 uint32_t crc32c = ComputeCrc32c(data);
131 attachment.reset(
132 new Attachment(Attachment::CreateFromParts(id, data, crc32c)));
134 base::MessageLoop::current()->PostTask(
135 FROM_HERE,
136 base::Bind(download_requests[id], result, base::Passed(&attachment)));
138 download_requests.erase(id);
141 std::map<AttachmentId, DownloadCallback> download_requests;
143 DISALLOW_COPY_AND_ASSIGN(MockAttachmentDownloader);
146 class MockAttachmentUploader
147 : public AttachmentUploader,
148 public base::SupportsWeakPtr<MockAttachmentUploader> {
149 public:
150 MockAttachmentUploader() {}
152 // AttachmentUploader implementation.
153 void UploadAttachment(const Attachment& attachment,
154 const UploadCallback& callback) override {
155 const AttachmentId id = attachment.GetId();
156 ASSERT_TRUE(upload_requests.find(id) == upload_requests.end());
157 upload_requests.insert(std::make_pair(id, callback));
160 void RespondToUpload(const AttachmentId& id, const UploadResult& result) {
161 ASSERT_TRUE(upload_requests.find(id) != upload_requests.end());
162 base::MessageLoop::current()->PostTask(
163 FROM_HERE, base::Bind(upload_requests[id], result, id));
164 upload_requests.erase(id);
167 std::map<AttachmentId, UploadCallback> upload_requests;
169 DISALLOW_COPY_AND_ASSIGN(MockAttachmentUploader);
172 } // namespace
174 class AttachmentServiceImplTest : public testing::Test,
175 public AttachmentService::Delegate {
176 protected:
177 AttachmentServiceImplTest() {}
179 void SetUp() override {
180 network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock());
181 InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()),
182 make_scoped_ptr(new MockAttachmentDownloader()),
183 this);
186 void TearDown() override {
187 attachment_service_.reset();
188 ASSERT_FALSE(attachment_store_);
189 ASSERT_FALSE(attachment_uploader_);
190 ASSERT_FALSE(attachment_downloader_);
193 // AttachmentService::Delegate implementation.
194 void OnAttachmentUploaded(const AttachmentId& attachment_id) override {
195 on_attachment_uploaded_list_.push_back(attachment_id);
198 void InitializeAttachmentService(
199 scoped_ptr<MockAttachmentUploader> uploader,
200 scoped_ptr<MockAttachmentDownloader> downloader,
201 AttachmentService::Delegate* delegate) {
202 scoped_refptr<MockAttachmentStore> attachment_store(
203 new MockAttachmentStore());
204 attachment_store_ = attachment_store->AsWeakPtr();
206 if (uploader.get()) {
207 attachment_uploader_ = uploader->AsWeakPtr();
209 if (downloader.get()) {
210 attachment_downloader_ = downloader->AsWeakPtr();
212 attachment_service_.reset(
213 new AttachmentServiceImpl(attachment_store,
214 uploader.Pass(),
215 downloader.Pass(),
216 delegate,
217 base::TimeDelta::FromMinutes(1),
218 base::TimeDelta::FromMinutes(8)));
220 scoped_ptr<base::MockTimer> timer_to_pass(
221 new base::MockTimer(false, false));
222 mock_timer_ = timer_to_pass.get();
223 attachment_service_->SetTimerForTest(timer_to_pass.Pass());
226 AttachmentService* attachment_service() { return attachment_service_.get(); }
228 base::MockTimer* mock_timer() { return mock_timer_; }
230 AttachmentService::GetOrDownloadCallback download_callback() {
231 return base::Bind(&AttachmentServiceImplTest::DownloadDone,
232 base::Unretained(this));
235 void DownloadDone(const AttachmentService::GetOrDownloadResult& result,
236 scoped_ptr<AttachmentMap> attachments) {
237 download_results_.push_back(result);
238 last_download_attachments_ = attachments.Pass();
241 void RunLoop() {
242 base::RunLoop run_loop;
243 run_loop.RunUntilIdle();
246 void RunLoopAndFireTimer() {
247 RunLoop();
248 if (mock_timer()->IsRunning()) {
249 mock_timer()->Fire();
251 RunLoop();
254 const std::vector<AttachmentService::GetOrDownloadResult>&
255 download_results() const {
256 return download_results_;
259 const AttachmentMap& last_download_attachments() const {
260 return *last_download_attachments_.get();
263 net::NetworkChangeNotifier* network_change_notifier() {
264 return network_change_notifier_.get();
267 MockAttachmentStore* store() { return attachment_store_.get(); }
269 MockAttachmentDownloader* downloader() {
270 return attachment_downloader_.get();
273 MockAttachmentUploader* uploader() {
274 return attachment_uploader_.get();
277 const std::vector<AttachmentId>& on_attachment_uploaded_list() const {
278 return on_attachment_uploaded_list_;
281 private:
282 base::MessageLoop message_loop_;
283 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
284 base::WeakPtr<MockAttachmentStore> attachment_store_;
285 base::WeakPtr<MockAttachmentDownloader> attachment_downloader_;
286 base::WeakPtr<MockAttachmentUploader> attachment_uploader_;
287 scoped_ptr<AttachmentServiceImpl> attachment_service_;
288 base::MockTimer* mock_timer_; // not owned
290 std::vector<AttachmentService::GetOrDownloadResult> download_results_;
291 scoped_ptr<AttachmentMap> last_download_attachments_;
292 std::vector<AttachmentId> on_attachment_uploaded_list_;
295 TEST_F(AttachmentServiceImplTest, GetStore) {
296 EXPECT_EQ(store(), attachment_service()->GetStore());
299 TEST_F(AttachmentServiceImplTest, GetOrDownload_EmptyAttachmentList) {
300 AttachmentIdList attachment_ids;
301 attachment_service()->GetOrDownloadAttachments(attachment_ids,
302 download_callback());
303 store()->RespondToRead(AttachmentIdSet());
305 RunLoop();
306 EXPECT_EQ(1U, download_results().size());
307 EXPECT_EQ(0U, last_download_attachments().size());
310 TEST_F(AttachmentServiceImplTest, GetOrDownload_Local) {
311 AttachmentIdList attachment_ids;
312 attachment_ids.push_back(AttachmentId::Create());
313 attachment_service()->GetOrDownloadAttachments(attachment_ids,
314 download_callback());
315 AttachmentIdSet local_attachments;
316 local_attachments.insert(attachment_ids[0]);
317 store()->RespondToRead(local_attachments);
319 RunLoop();
320 EXPECT_EQ(1U, download_results().size());
321 EXPECT_EQ(1U, last_download_attachments().size());
322 EXPECT_TRUE(last_download_attachments().find(attachment_ids[0]) !=
323 last_download_attachments().end());
326 TEST_F(AttachmentServiceImplTest, GetOrDownload_LocalRemoteUnavailable) {
327 // Create attachment list with 4 ids.
328 AttachmentIdList attachment_ids;
329 attachment_ids.push_back(AttachmentId::Create());
330 attachment_ids.push_back(AttachmentId::Create());
331 attachment_ids.push_back(AttachmentId::Create());
332 attachment_ids.push_back(AttachmentId::Create());
333 // Call attachment service.
334 attachment_service()->GetOrDownloadAttachments(attachment_ids,
335 download_callback());
336 // Ensure AttachmentStore is called.
337 EXPECT_FALSE(store()->read_ids.empty());
339 // Make AttachmentStore return only attachment 0.
340 AttachmentIdSet local_attachments;
341 local_attachments.insert(attachment_ids[0]);
342 store()->RespondToRead(local_attachments);
343 RunLoop();
344 // Ensure Downloader called with right attachment ids
345 EXPECT_EQ(3U, downloader()->download_requests.size());
347 // Make downloader return attachment 1.
348 downloader()->RespondToDownload(attachment_ids[1],
349 AttachmentDownloader::DOWNLOAD_SUCCESS);
350 RunLoop();
351 // Ensure consumer callback is not called.
352 EXPECT_TRUE(download_results().empty());
353 // Make AttachmentStore acknowledge writing attachment 1.
354 store()->RespondToWrite(AttachmentStore::SUCCESS);
355 RunLoop();
356 // Ensure consumer callback is not called.
357 EXPECT_TRUE(download_results().empty());
359 // Make downloader return attachment 2.
360 downloader()->RespondToDownload(attachment_ids[2],
361 AttachmentDownloader::DOWNLOAD_SUCCESS);
362 RunLoop();
363 // Ensure consumer callback is not called.
364 EXPECT_TRUE(download_results().empty());
365 // Make AttachmentStore fail writing attachment 2.
366 store()->RespondToWrite(AttachmentStore::UNSPECIFIED_ERROR);
367 RunLoop();
368 // Ensure consumer callback is not called.
369 EXPECT_TRUE(download_results().empty());
371 // Make downloader fail attachment 3.
372 downloader()->RespondToDownload(
373 attachment_ids[3], AttachmentDownloader::DOWNLOAD_UNSPECIFIED_ERROR);
374 RunLoop();
376 // Ensure callback is called
377 EXPECT_FALSE(download_results().empty());
378 // There should be only two attachments returned, 0 and 1.
379 EXPECT_EQ(2U, last_download_attachments().size());
380 EXPECT_TRUE(last_download_attachments().find(attachment_ids[0]) !=
381 last_download_attachments().end());
382 EXPECT_TRUE(last_download_attachments().find(attachment_ids[1]) !=
383 last_download_attachments().end());
384 EXPECT_TRUE(last_download_attachments().find(attachment_ids[2]) ==
385 last_download_attachments().end());
386 EXPECT_TRUE(last_download_attachments().find(attachment_ids[3]) ==
387 last_download_attachments().end());
390 TEST_F(AttachmentServiceImplTest, GetOrDownload_NoDownloader) {
391 // No downloader.
392 InitializeAttachmentService(
393 make_scoped_ptr<MockAttachmentUploader>(new MockAttachmentUploader()),
394 make_scoped_ptr<MockAttachmentDownloader>(NULL),
395 this);
397 AttachmentIdList attachment_ids;
398 attachment_ids.push_back(AttachmentId::Create());
399 attachment_service()->GetOrDownloadAttachments(attachment_ids,
400 download_callback());
401 EXPECT_FALSE(store()->read_ids.empty());
403 AttachmentIdSet local_attachments;
404 store()->RespondToRead(local_attachments);
405 RunLoop();
406 ASSERT_EQ(1U, download_results().size());
407 EXPECT_EQ(AttachmentService::GET_UNSPECIFIED_ERROR, download_results()[0]);
408 EXPECT_TRUE(last_download_attachments().empty());
411 TEST_F(AttachmentServiceImplTest, UploadAttachments_Success) {
412 AttachmentIdSet attachment_ids;
413 const unsigned num_attachments = 3;
414 for (unsigned i = 0; i < num_attachments; ++i) {
415 attachment_ids.insert(AttachmentId::Create());
417 attachment_service()->UploadAttachments(attachment_ids);
419 for (unsigned i = 0; i < num_attachments; ++i) {
420 RunLoopAndFireTimer();
421 // See that the service has issued a read for at least one of the
422 // attachments.
423 ASSERT_GE(store()->read_ids.size(), 1U);
424 store()->RespondToRead(attachment_ids);
425 RunLoop();
426 ASSERT_GE(uploader()->upload_requests.size(), 1U);
427 uploader()->RespondToUpload(uploader()->upload_requests.begin()->first,
428 AttachmentUploader::UPLOAD_SUCCESS);
430 RunLoop();
431 ASSERT_EQ(0U, store()->read_ids.size());
432 ASSERT_EQ(0U, uploader()->upload_requests.size());
434 // See that all the attachments were uploaded.
435 ASSERT_EQ(attachment_ids.size(), on_attachment_uploaded_list().size());
436 AttachmentIdSet::const_iterator iter = attachment_ids.begin();
437 const AttachmentIdSet::const_iterator end = attachment_ids.end();
438 for (iter = attachment_ids.begin(); iter != end; ++iter) {
439 EXPECT_THAT(on_attachment_uploaded_list(), testing::Contains(*iter));
443 TEST_F(AttachmentServiceImplTest, UploadAttachments_Success_NoDelegate) {
444 InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()),
445 make_scoped_ptr(new MockAttachmentDownloader()),
446 NULL); // No delegate.
448 AttachmentIdSet attachment_ids;
449 attachment_ids.insert(AttachmentId::Create());
450 attachment_service()->UploadAttachments(attachment_ids);
451 RunLoopAndFireTimer();
452 ASSERT_EQ(1U, store()->read_ids.size());
453 ASSERT_EQ(0U, uploader()->upload_requests.size());
454 store()->RespondToRead(attachment_ids);
455 RunLoop();
456 ASSERT_EQ(0U, store()->read_ids.size());
457 ASSERT_EQ(1U, uploader()->upload_requests.size());
458 uploader()->RespondToUpload(*attachment_ids.begin(),
459 AttachmentUploader::UPLOAD_SUCCESS);
460 RunLoop();
461 ASSERT_TRUE(on_attachment_uploaded_list().empty());
464 TEST_F(AttachmentServiceImplTest, UploadAttachments_SomeMissingFromStore) {
465 AttachmentIdSet attachment_ids;
466 attachment_ids.insert(AttachmentId::Create());
467 attachment_ids.insert(AttachmentId::Create());
468 attachment_service()->UploadAttachments(attachment_ids);
469 RunLoopAndFireTimer();
470 ASSERT_GE(store()->read_ids.size(), 1U);
472 ASSERT_EQ(0U, uploader()->upload_requests.size());
473 store()->RespondToRead(attachment_ids);
474 RunLoop();
475 ASSERT_EQ(1U, uploader()->upload_requests.size());
477 uploader()->RespondToUpload(uploader()->upload_requests.begin()->first,
478 AttachmentUploader::UPLOAD_SUCCESS);
479 RunLoopAndFireTimer();
480 ASSERT_EQ(1U, on_attachment_uploaded_list().size());
481 ASSERT_GE(store()->read_ids.size(), 1U);
482 // Not found!
483 store()->RespondToRead(AttachmentIdSet());
484 RunLoop();
485 // No upload requests since the read failed.
486 ASSERT_EQ(0U, uploader()->upload_requests.size());
489 TEST_F(AttachmentServiceImplTest, UploadAttachments_AllMissingFromStore) {
490 AttachmentIdSet attachment_ids;
491 const unsigned num_attachments = 2;
492 for (unsigned i = 0; i < num_attachments; ++i) {
493 attachment_ids.insert(AttachmentId::Create());
495 attachment_service()->UploadAttachments(attachment_ids);
497 for (unsigned i = 0; i < num_attachments; ++i) {
498 RunLoopAndFireTimer();
499 ASSERT_GE(store()->read_ids.size(), 1U);
500 // None found!
501 store()->RespondToRead(AttachmentIdSet());
503 RunLoop();
505 // Nothing uploaded.
506 EXPECT_EQ(0U, uploader()->upload_requests.size());
507 // See that the delegate was never called.
508 ASSERT_EQ(0U, on_attachment_uploaded_list().size());
511 TEST_F(AttachmentServiceImplTest, UploadAttachments_NoUploader) {
512 InitializeAttachmentService(make_scoped_ptr<MockAttachmentUploader>(NULL),
513 make_scoped_ptr(new MockAttachmentDownloader()),
514 this);
516 AttachmentIdSet attachment_ids;
517 attachment_ids.insert(AttachmentId::Create());
518 attachment_service()->UploadAttachments(attachment_ids);
519 RunLoop();
520 EXPECT_EQ(0U, store()->read_ids.size());
521 ASSERT_EQ(0U, on_attachment_uploaded_list().size());
524 // Upload three attachments. For one of them, server responds with error.
525 TEST_F(AttachmentServiceImplTest, UploadAttachments_OneUploadFails) {
526 AttachmentIdSet attachment_ids;
527 const unsigned num_attachments = 3;
528 for (unsigned i = 0; i < num_attachments; ++i) {
529 attachment_ids.insert(AttachmentId::Create());
531 attachment_service()->UploadAttachments(attachment_ids);
533 for (unsigned i = 0; i < 3; ++i) {
534 RunLoopAndFireTimer();
535 ASSERT_GE(store()->read_ids.size(), 1U);
536 store()->RespondToRead(attachment_ids);
537 RunLoop();
538 ASSERT_EQ(1U, uploader()->upload_requests.size());
539 AttachmentUploader::UploadResult result =
540 AttachmentUploader::UPLOAD_SUCCESS;
541 // Fail the 2nd one.
542 if (i == 2U) {
543 result = AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR;
544 } else {
545 result = AttachmentUploader::UPLOAD_SUCCESS;
547 uploader()->RespondToUpload(uploader()->upload_requests.begin()->first,
548 result);
549 RunLoop();
551 ASSERT_EQ(2U, on_attachment_uploaded_list().size());
554 // Attempt an upload, respond with transient error to trigger backoff, issue
555 // network disconnect/connect events and see that backoff is cleared.
556 TEST_F(AttachmentServiceImplTest,
557 UploadAttachments_ResetBackoffAfterNetworkChange) {
558 AttachmentIdSet attachment_ids;
559 attachment_ids.insert(AttachmentId::Create());
560 attachment_service()->UploadAttachments(attachment_ids);
562 RunLoopAndFireTimer();
563 ASSERT_EQ(1U, store()->read_ids.size());
564 store()->RespondToRead(attachment_ids);
565 RunLoop();
566 ASSERT_EQ(1U, uploader()->upload_requests.size());
568 uploader()->RespondToUpload(uploader()->upload_requests.begin()->first,
569 AttachmentUploader::UPLOAD_TRANSIENT_ERROR);
570 RunLoop();
572 // See that we are in backoff.
573 ASSERT_TRUE(mock_timer()->IsRunning());
574 ASSERT_GT(mock_timer()->GetCurrentDelay(), base::TimeDelta());
576 // Issue a network disconnect event.
577 network_change_notifier()->NotifyObserversOfNetworkChangeForTests(
578 net::NetworkChangeNotifier::CONNECTION_NONE);
579 RunLoop();
581 // Still in backoff.
582 ASSERT_TRUE(mock_timer()->IsRunning());
583 ASSERT_GT(mock_timer()->GetCurrentDelay(), base::TimeDelta());
585 // Issue a network connect event.
586 net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(
587 net::NetworkChangeNotifier::CONNECTION_WIFI);
588 RunLoop();
590 // No longer in backoff.
591 ASSERT_TRUE(mock_timer()->IsRunning());
592 ASSERT_EQ(base::TimeDelta(), mock_timer()->GetCurrentDelay());
595 } // namespace syncer