Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / sync / internal_api / attachments / attachment_service_impl_unittest.cc
blobd8bf6b20dd5616c2f27b8ac09d0462237f19dced
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 "sync/internal_api/public/attachments/fake_attachment_downloader.h"
12 #include "sync/internal_api/public/attachments/fake_attachment_uploader.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace syncer {
17 class MockAttachmentStore : public AttachmentStore,
18 public base::SupportsWeakPtr<MockAttachmentStore> {
19 public:
20 MockAttachmentStore() {}
22 virtual void Read(const AttachmentIdList& ids,
23 const ReadCallback& callback) OVERRIDE {
24 read_ids.push_back(ids);
25 read_callbacks.push_back(callback);
28 virtual void Write(const AttachmentList& attachments,
29 const WriteCallback& callback) OVERRIDE {
30 write_attachments.push_back(attachments);
31 write_callbacks.push_back(callback);
34 virtual void Drop(const AttachmentIdList& ids,
35 const DropCallback& callback) OVERRIDE {
36 NOTREACHED();
39 // Respond to Read request. Attachments found in local_attachments should be
40 // returned, everything else should be reported unavailable.
41 void RespondToRead(const AttachmentIdSet& local_attachments) {
42 scoped_refptr<base::RefCountedString> data = new base::RefCountedString();
43 ReadCallback callback = read_callbacks.back();
44 AttachmentIdList ids = read_ids.back();
45 read_callbacks.pop_back();
46 read_ids.pop_back();
48 scoped_ptr<AttachmentMap> attachments(new AttachmentMap());
49 scoped_ptr<AttachmentIdList> unavailable_attachments(
50 new AttachmentIdList());
51 for (AttachmentIdList::const_iterator iter = ids.begin(); iter != ids.end();
52 ++iter) {
53 if (local_attachments.find(*iter) != local_attachments.end()) {
54 Attachment attachment = Attachment::CreateWithId(*iter, data);
55 attachments->insert(std::make_pair(*iter, attachment));
56 } else {
57 unavailable_attachments->push_back(*iter);
60 Result result =
61 unavailable_attachments->empty() ? SUCCESS : UNSPECIFIED_ERROR;
63 base::MessageLoop::current()->PostTask(
64 FROM_HERE,
65 base::Bind(callback,
66 result,
67 base::Passed(&attachments),
68 base::Passed(&unavailable_attachments)));
71 // Respond to Write request with |result|.
72 void RespondToWrite(const Result& result) {
73 WriteCallback callback = write_callbacks.back();
74 AttachmentList attachments = write_attachments.back();
75 write_callbacks.pop_back();
76 write_attachments.pop_back();
77 base::MessageLoop::current()->PostTask(FROM_HERE,
78 base::Bind(callback, result));
81 std::vector<AttachmentIdList> read_ids;
82 std::vector<ReadCallback> read_callbacks;
83 std::vector<AttachmentList> write_attachments;
84 std::vector<WriteCallback> write_callbacks;
86 DISALLOW_COPY_AND_ASSIGN(MockAttachmentStore);
89 class MockAttachmentDownloader
90 : public AttachmentDownloader,
91 public base::SupportsWeakPtr<MockAttachmentDownloader> {
92 public:
93 MockAttachmentDownloader() {}
95 virtual void DownloadAttachment(const AttachmentId& id,
96 const DownloadCallback& callback) OVERRIDE {
97 ASSERT_TRUE(download_requests.find(id) == download_requests.end());
98 download_requests.insert(std::make_pair(id, callback));
101 // Multiple requests to download will be active at the same time.
102 // RespondToDownload should respond to only one of them.
103 void RespondToDownload(const AttachmentId& id, const DownloadResult& result) {
104 ASSERT_TRUE(download_requests.find(id) != download_requests.end());
105 scoped_ptr<Attachment> attachment;
106 if (result == DOWNLOAD_SUCCESS) {
107 scoped_refptr<base::RefCountedString> data = new base::RefCountedString();
108 attachment.reset(new Attachment(Attachment::CreateWithId(id, data)));
110 base::MessageLoop::current()->PostTask(
111 FROM_HERE,
112 base::Bind(download_requests[id], result, base::Passed(&attachment)));
114 download_requests.erase(id);
117 std::map<AttachmentId, DownloadCallback> download_requests;
119 DISALLOW_COPY_AND_ASSIGN(MockAttachmentDownloader);
122 class MockAttachmentUploader
123 : public AttachmentUploader,
124 public base::SupportsWeakPtr<MockAttachmentUploader> {
125 public:
126 MockAttachmentUploader() {}
128 // AttachmentUploader implementation.
129 virtual void UploadAttachment(const Attachment& attachment,
130 const UploadCallback& callback) OVERRIDE {
131 const AttachmentId id = attachment.GetId();
132 ASSERT_TRUE(upload_requests.find(id) == upload_requests.end());
133 upload_requests.insert(std::make_pair(id, callback));
136 void RespondToUpload(const AttachmentId& id, const UploadResult& result) {
137 ASSERT_TRUE(upload_requests.find(id) != upload_requests.end());
138 base::MessageLoop::current()->PostTask(
139 FROM_HERE, base::Bind(upload_requests[id], result, id));
140 upload_requests.erase(id);
143 std::map<AttachmentId, UploadCallback> upload_requests;
145 DISALLOW_COPY_AND_ASSIGN(MockAttachmentUploader);
148 class AttachmentServiceImplTest : public testing::Test,
149 public AttachmentService::Delegate {
150 protected:
151 AttachmentServiceImplTest() {}
153 virtual void SetUp() OVERRIDE {
154 InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()),
155 make_scoped_ptr(new MockAttachmentDownloader()),
156 this);
159 virtual void TearDown() OVERRIDE {
160 attachment_service_.reset();
161 ASSERT_FALSE(attachment_store_);
162 ASSERT_FALSE(attachment_uploader_);
163 ASSERT_FALSE(attachment_downloader_);
166 // AttachmentService::Delegate implementation.
167 virtual void OnAttachmentUploaded(
168 const AttachmentId& attachment_id) OVERRIDE {
169 on_attachment_uploaded_list_.push_back(attachment_id);
172 void InitializeAttachmentService(
173 scoped_ptr<MockAttachmentUploader> uploader,
174 scoped_ptr<MockAttachmentDownloader> downloader,
175 AttachmentService::Delegate* delegate) {
176 scoped_ptr<MockAttachmentStore> attachment_store(new MockAttachmentStore());
177 attachment_store_ = attachment_store->AsWeakPtr();
179 if (uploader.get()) {
180 attachment_uploader_ = uploader->AsWeakPtr();
182 if (downloader.get()) {
183 attachment_downloader_ = downloader->AsWeakPtr();
185 attachment_service_.reset(
186 new AttachmentServiceImpl(attachment_store.PassAs<AttachmentStore>(),
187 uploader.PassAs<AttachmentUploader>(),
188 downloader.PassAs<AttachmentDownloader>(),
189 delegate));
192 AttachmentService* attachment_service() { return attachment_service_.get(); }
194 AttachmentService::GetOrDownloadCallback download_callback() {
195 return base::Bind(&AttachmentServiceImplTest::DownloadDone,
196 base::Unretained(this));
199 AttachmentService::StoreCallback store_callback() {
200 return base::Bind(&AttachmentServiceImplTest::StoreDone,
201 base::Unretained(this));
204 void DownloadDone(const AttachmentService::GetOrDownloadResult& result,
205 scoped_ptr<AttachmentMap> attachments) {
206 download_results_.push_back(result);
207 last_download_attachments_ = attachments.Pass();
210 void StoreDone(const AttachmentService::StoreResult& result) {
211 store_results_.push_back(result);
214 void RunLoop() {
215 base::RunLoop run_loop;
216 run_loop.RunUntilIdle();
219 const std::vector<AttachmentService::GetOrDownloadResult>&
220 download_results() const {
221 return download_results_;
224 const AttachmentMap& last_download_attachments() const {
225 return *last_download_attachments_.get();
228 const std::vector<AttachmentService::StoreResult>& store_results() const {
229 return store_results_;
232 MockAttachmentStore* store() { return attachment_store_.get(); }
234 MockAttachmentDownloader* downloader() {
235 return attachment_downloader_.get();
238 MockAttachmentUploader* uploader() {
239 return attachment_uploader_.get();
242 const std::vector<AttachmentId>& on_attachment_uploaded_list() const {
243 return on_attachment_uploaded_list_;
246 private:
247 base::MessageLoop message_loop_;
248 base::WeakPtr<MockAttachmentStore> attachment_store_;
249 base::WeakPtr<MockAttachmentDownloader> attachment_downloader_;
250 base::WeakPtr<MockAttachmentUploader> attachment_uploader_;
251 scoped_ptr<AttachmentService> attachment_service_;
253 std::vector<AttachmentService::GetOrDownloadResult> download_results_;
254 scoped_ptr<AttachmentMap> last_download_attachments_;
255 std::vector<AttachmentId> on_attachment_uploaded_list_;
257 std::vector<AttachmentService::StoreResult> store_results_;
260 TEST_F(AttachmentServiceImplTest, GetOrDownload_EmptyAttachmentList) {
261 AttachmentIdList attachment_ids;
262 attachment_service()->GetOrDownloadAttachments(attachment_ids,
263 download_callback());
264 store()->RespondToRead(AttachmentIdSet());
266 RunLoop();
267 EXPECT_EQ(1U, download_results().size());
268 EXPECT_EQ(0U, last_download_attachments().size());
271 TEST_F(AttachmentServiceImplTest, GetOrDownload_Local) {
272 AttachmentIdList attachment_ids;
273 attachment_ids.push_back(AttachmentId::Create());
274 attachment_service()->GetOrDownloadAttachments(attachment_ids,
275 download_callback());
276 AttachmentIdSet local_attachments;
277 local_attachments.insert(attachment_ids[0]);
278 store()->RespondToRead(local_attachments);
280 RunLoop();
281 EXPECT_EQ(1U, download_results().size());
282 EXPECT_EQ(1U, last_download_attachments().size());
283 EXPECT_TRUE(last_download_attachments().find(attachment_ids[0]) !=
284 last_download_attachments().end());
287 TEST_F(AttachmentServiceImplTest, GetOrDownload_LocalRemoteUnavailable) {
288 // Create attachment list with 3 ids.
289 AttachmentIdList attachment_ids;
290 attachment_ids.push_back(AttachmentId::Create());
291 attachment_ids.push_back(AttachmentId::Create());
292 attachment_ids.push_back(AttachmentId::Create());
293 // Call attachment service.
294 attachment_service()->GetOrDownloadAttachments(attachment_ids,
295 download_callback());
296 // Ensure AttachmentStore is called.
297 EXPECT_FALSE(store()->read_ids.empty());
299 // make AttachmentStore return only attachment 0.
300 AttachmentIdSet local_attachments;
301 local_attachments.insert(attachment_ids[0]);
302 store()->RespondToRead(local_attachments);
303 RunLoop();
304 // Ensure Downloader called with right attachment ids
305 EXPECT_EQ(2U, downloader()->download_requests.size());
307 // Make downloader return attachment 1.
308 downloader()->RespondToDownload(attachment_ids[1],
309 AttachmentDownloader::DOWNLOAD_SUCCESS);
310 RunLoop();
311 // Ensure consumer callback is not called.
312 EXPECT_TRUE(download_results().empty());
314 // Make downloader fail attachment 2.
315 downloader()->RespondToDownload(
316 attachment_ids[2], AttachmentDownloader::DOWNLOAD_UNSPECIFIED_ERROR);
317 RunLoop();
318 // Ensure callback is called
319 EXPECT_FALSE(download_results().empty());
320 // There should be only two attachments returned, 0 and 1.
321 EXPECT_EQ(2U, last_download_attachments().size());
322 EXPECT_TRUE(last_download_attachments().find(attachment_ids[0]) !=
323 last_download_attachments().end());
324 EXPECT_TRUE(last_download_attachments().find(attachment_ids[1]) !=
325 last_download_attachments().end());
326 EXPECT_TRUE(last_download_attachments().find(attachment_ids[2]) ==
327 last_download_attachments().end());
330 TEST_F(AttachmentServiceImplTest, GetOrDownload_NoDownloader) {
331 // No downloader.
332 InitializeAttachmentService(
333 make_scoped_ptr<MockAttachmentUploader>(new MockAttachmentUploader()),
334 make_scoped_ptr<MockAttachmentDownloader>(NULL),
335 this);
337 AttachmentIdList attachment_ids;
338 attachment_ids.push_back(AttachmentId::Create());
339 attachment_service()->GetOrDownloadAttachments(attachment_ids,
340 download_callback());
341 EXPECT_FALSE(store()->read_ids.empty());
343 AttachmentIdSet local_attachments;
344 store()->RespondToRead(local_attachments);
345 RunLoop();
346 ASSERT_EQ(1U, download_results().size());
347 EXPECT_EQ(AttachmentService::GET_UNSPECIFIED_ERROR, download_results()[0]);
348 EXPECT_TRUE(last_download_attachments().empty());
351 TEST_F(AttachmentServiceImplTest, StoreAttachments_Success) {
352 scoped_refptr<base::RefCountedString> data = new base::RefCountedString();
353 Attachment attachment(Attachment::Create(data));
354 AttachmentList attachments;
355 attachments.push_back(attachment);
356 attachment_service()->StoreAttachments(attachments, store_callback());
357 EXPECT_EQ(1U, store()->write_attachments.size());
358 EXPECT_EQ(1U, uploader()->upload_requests.size());
360 store()->RespondToWrite(AttachmentStore::SUCCESS);
361 uploader()->RespondToUpload(attachment.GetId(),
362 AttachmentUploader::UPLOAD_SUCCESS);
363 RunLoop();
364 ASSERT_EQ(1U, store_results().size());
365 EXPECT_EQ(AttachmentService::STORE_SUCCESS, store_results()[0]);
366 ASSERT_EQ(1U, on_attachment_uploaded_list().size());
367 EXPECT_EQ(attachment.GetId(), on_attachment_uploaded_list()[0]);
370 TEST_F(AttachmentServiceImplTest,
371 StoreAttachments_StoreFailsWithUnspecifiedError) {
372 scoped_refptr<base::RefCountedString> data = new base::RefCountedString();
373 Attachment attachment(Attachment::Create(data));
374 AttachmentList attachments;
375 attachments.push_back(attachment);
376 attachment_service()->StoreAttachments(attachments, store_callback());
377 EXPECT_EQ(1U, store()->write_attachments.size());
378 EXPECT_EQ(1U, uploader()->upload_requests.size());
380 store()->RespondToWrite(AttachmentStore::UNSPECIFIED_ERROR);
381 uploader()->RespondToUpload(attachment.GetId(),
382 AttachmentUploader::UPLOAD_SUCCESS);
383 RunLoop();
384 ASSERT_EQ(1U, store_results().size());
385 EXPECT_EQ(AttachmentService::STORE_UNSPECIFIED_ERROR, store_results()[0]);
386 ASSERT_EQ(1U, on_attachment_uploaded_list().size());
387 EXPECT_EQ(attachment.GetId(), on_attachment_uploaded_list()[0]);
390 TEST_F(AttachmentServiceImplTest,
391 StoreAttachments_UploadFailsWithUnspecifiedError) {
392 scoped_refptr<base::RefCountedString> data = new base::RefCountedString();
393 Attachment attachment(Attachment::Create(data));
394 AttachmentList attachments;
395 attachments.push_back(attachment);
396 attachment_service()->StoreAttachments(attachments, store_callback());
397 EXPECT_EQ(1U, store()->write_attachments.size());
398 EXPECT_EQ(1U, uploader()->upload_requests.size());
400 store()->RespondToWrite(AttachmentStore::SUCCESS);
401 uploader()->RespondToUpload(attachment.GetId(),
402 AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR);
403 RunLoop();
404 ASSERT_EQ(1U, store_results().size());
405 // Even though the upload failed, the Store operation is successful.
406 EXPECT_EQ(AttachmentService::STORE_SUCCESS, store_results()[0]);
407 EXPECT_TRUE(on_attachment_uploaded_list().empty());
410 TEST_F(AttachmentServiceImplTest, StoreAttachments_NoDelegate) {
411 InitializeAttachmentService(make_scoped_ptr(new MockAttachmentUploader()),
412 make_scoped_ptr(new MockAttachmentDownloader()),
413 NULL); // No delegate.
415 scoped_refptr<base::RefCountedString> data = new base::RefCountedString();
416 Attachment attachment(Attachment::Create(data));
417 AttachmentList attachments;
418 attachments.push_back(attachment);
419 attachment_service()->StoreAttachments(attachments, store_callback());
420 EXPECT_EQ(1U, store()->write_attachments.size());
421 EXPECT_EQ(1U, uploader()->upload_requests.size());
423 store()->RespondToWrite(AttachmentStore::SUCCESS);
424 uploader()->RespondToUpload(attachment.GetId(),
425 AttachmentUploader::UPLOAD_SUCCESS);
426 RunLoop();
427 ASSERT_EQ(1U, store_results().size());
428 EXPECT_EQ(AttachmentService::STORE_SUCCESS, store_results()[0]);
429 EXPECT_TRUE(on_attachment_uploaded_list().empty());
432 TEST_F(AttachmentServiceImplTest, StoreAttachments_NoUploader) {
433 // No uploader.
434 InitializeAttachmentService(make_scoped_ptr<MockAttachmentUploader>(NULL),
435 make_scoped_ptr(new MockAttachmentDownloader()),
436 this);
438 scoped_refptr<base::RefCountedString> data = new base::RefCountedString();
439 Attachment attachment(Attachment::Create(data));
440 AttachmentList attachments;
441 attachments.push_back(attachment);
442 attachment_service()->StoreAttachments(attachments, store_callback());
443 EXPECT_EQ(1U, store()->write_attachments.size());
445 store()->RespondToWrite(AttachmentStore::SUCCESS);
446 RunLoop();
447 ASSERT_EQ(1U, store_results().size());
448 EXPECT_EQ(AttachmentService::STORE_SUCCESS, store_results()[0]);
449 EXPECT_TRUE(on_attachment_uploaded_list().empty());
452 } // namespace syncer