cc: Convert LTHCommon tests to LayerImpl
[chromium-blink-merge.git] / components / drive / drive_uploader_unittest.cc
blob29fbf26acb1a00568227c60a11a28f2c3db8ea1f
1 // Copyright (c) 2012 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 "components/drive/drive_uploader.h"
7 #include <algorithm>
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/run_loop.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "base/values.h"
18 #include "components/drive/service/dummy_drive_service.h"
19 #include "google_apis/drive/drive_api_parser.h"
20 #include "google_apis/drive/test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using google_apis::CancelCallback;
24 using google_apis::FileResource;
25 using google_apis::DriveApiErrorCode;
26 using google_apis::DRIVE_NO_CONNECTION;
27 using google_apis::DRIVE_OTHER_ERROR;
28 using google_apis::HTTP_CONFLICT;
29 using google_apis::HTTP_CREATED;
30 using google_apis::HTTP_NOT_FOUND;
31 using google_apis::HTTP_PRECONDITION;
32 using google_apis::HTTP_RESUME_INCOMPLETE;
33 using google_apis::HTTP_SUCCESS;
34 using google_apis::InitiateUploadCallback;
35 using google_apis::ProgressCallback;
36 using google_apis::UploadRangeResponse;
37 using google_apis::drive::UploadRangeCallback;
38 namespace test_util = google_apis::test_util;
40 namespace drive {
42 namespace {
44 const char kTestDummyMd5[] = "dummy_md5";
45 const char kTestDocumentTitle[] = "Hello world";
46 const char kTestInitiateUploadParentResourceId[] = "parent_resource_id";
47 const char kTestInitiateUploadResourceId[] = "resource_id";
48 const char kTestMimeType[] = "text/plain";
49 const char kTestUploadNewFileURL[] = "http://test/upload_location/new_file";
50 const char kTestUploadExistingFileURL[] =
51 "http://test/upload_location/existing_file";
52 const int64 kUploadChunkSize = 1024 * 1024 * 1024;
53 const char kTestETag[] = "test_etag";
55 CancelCallback SendMultipartUploadResult(
56 DriveApiErrorCode response_code,
57 int64 content_length,
58 const google_apis::FileResourceCallback& callback,
59 const google_apis::ProgressCallback& progress_callback) {
60 // Callback progress
61 if (!progress_callback.is_null()) {
62 // For the testing purpose, it always notifies the progress at the end of
63 // whole file uploading.
64 base::ThreadTaskRunnerHandle::Get()->PostTask(
65 FROM_HERE,
66 base::Bind(progress_callback, content_length, content_length));
69 // MultipartUploadXXXFile is an asynchronous function, so don't callback
70 // directly.
71 scoped_ptr<FileResource> entry;
72 entry.reset(new FileResource);
73 entry->set_md5_checksum(kTestDummyMd5);
74 base::ThreadTaskRunnerHandle::Get()->PostTask(
75 FROM_HERE, base::Bind(callback, response_code, base::Passed(&entry)));
76 return CancelCallback();
79 // Mock DriveService that verifies if the uploaded content matches the preset
80 // expectation.
81 class MockDriveServiceWithUploadExpectation : public DummyDriveService {
82 public:
83 // Sets up an expected upload content. InitiateUpload and ResumeUpload will
84 // verify that the specified data is correctly uploaded.
85 MockDriveServiceWithUploadExpectation(
86 const base::FilePath& expected_upload_file,
87 int64 expected_content_length)
88 : expected_upload_file_(expected_upload_file),
89 expected_content_length_(expected_content_length),
90 received_bytes_(0),
91 resume_upload_call_count_(0),
92 multipart_upload_call_count_(0) {}
94 int64 received_bytes() const { return received_bytes_; }
95 void set_received_bytes(int64 received_bytes) {
96 received_bytes_ = received_bytes;
99 int64 resume_upload_call_count() const { return resume_upload_call_count_; }
100 int64 multipart_upload_call_count() const {
101 return multipart_upload_call_count_;
104 private:
105 // DriveServiceInterface overrides.
106 // Handles a request for obtaining an upload location URL.
107 CancelCallback InitiateUploadNewFile(
108 const std::string& content_type,
109 int64 content_length,
110 const std::string& parent_resource_id,
111 const std::string& title,
112 const UploadNewFileOptions& options,
113 const InitiateUploadCallback& callback) override {
114 EXPECT_EQ(kTestDocumentTitle, title);
115 EXPECT_EQ(kTestMimeType, content_type);
116 EXPECT_EQ(expected_content_length_, content_length);
117 EXPECT_EQ(kTestInitiateUploadParentResourceId, parent_resource_id);
119 // Calls back the upload URL for subsequent ResumeUpload requests.
120 // InitiateUpload is an asynchronous function, so don't callback directly.
121 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
122 base::Bind(callback, HTTP_SUCCESS, GURL(kTestUploadNewFileURL)));
123 return CancelCallback();
126 CancelCallback InitiateUploadExistingFile(
127 const std::string& content_type,
128 int64 content_length,
129 const std::string& resource_id,
130 const UploadExistingFileOptions& options,
131 const InitiateUploadCallback& callback) override {
132 EXPECT_EQ(kTestMimeType, content_type);
133 EXPECT_EQ(expected_content_length_, content_length);
134 EXPECT_EQ(kTestInitiateUploadResourceId, resource_id);
136 if (!options.etag.empty() && options.etag != kTestETag) {
137 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
138 base::Bind(callback, HTTP_PRECONDITION, GURL()));
139 return CancelCallback();
142 // Calls back the upload URL for subsequent ResumeUpload requests.
143 // InitiateUpload is an asynchronous function, so don't callback directly.
144 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
145 base::Bind(callback, HTTP_SUCCESS, GURL(kTestUploadExistingFileURL)));
146 return CancelCallback();
149 // Handles a request for uploading a chunk of bytes.
150 CancelCallback ResumeUpload(
151 const GURL& upload_location,
152 int64 start_position,
153 int64 end_position,
154 int64 content_length,
155 const std::string& content_type,
156 const base::FilePath& local_file_path,
157 const UploadRangeCallback& callback,
158 const ProgressCallback& progress_callback) override {
159 // The upload range should start from the current first unreceived byte.
160 EXPECT_EQ(received_bytes_, start_position);
161 EXPECT_EQ(expected_upload_file_, local_file_path);
163 // The upload data must be split into 512KB chunks.
164 const int64 expected_chunk_end =
165 std::min(received_bytes_ + kUploadChunkSize, expected_content_length_);
166 EXPECT_EQ(expected_chunk_end, end_position);
168 // The upload URL returned by InitiateUpload() must be used.
169 EXPECT_TRUE(GURL(kTestUploadNewFileURL) == upload_location ||
170 GURL(kTestUploadExistingFileURL) == upload_location);
172 // Other parameters should be the exact values passed to DriveUploader.
173 EXPECT_EQ(expected_content_length_, content_length);
174 EXPECT_EQ(kTestMimeType, content_type);
176 // Update the internal status of the current upload session.
177 resume_upload_call_count_++;
178 received_bytes_ = end_position;
180 // Callback progress
181 if (!progress_callback.is_null()) {
182 // For the testing purpose, it always notifies the progress at the end of
183 // each chunk uploading.
184 int64 chunk_size = end_position - start_position;
185 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
186 base::Bind(progress_callback, chunk_size, chunk_size));
189 SendUploadRangeResponse(upload_location, callback);
190 return CancelCallback();
193 // Handles a request to fetch the current upload status.
194 CancelCallback GetUploadStatus(const GURL& upload_location,
195 int64 content_length,
196 const UploadRangeCallback& callback) override {
197 EXPECT_EQ(expected_content_length_, content_length);
198 // The upload URL returned by InitiateUpload() must be used.
199 EXPECT_TRUE(GURL(kTestUploadNewFileURL) == upload_location ||
200 GURL(kTestUploadExistingFileURL) == upload_location);
202 SendUploadRangeResponse(upload_location, callback);
203 return CancelCallback();
206 // Runs |callback| with the current upload status.
207 void SendUploadRangeResponse(const GURL& upload_location,
208 const UploadRangeCallback& callback) {
209 // Callback with response.
210 UploadRangeResponse response;
211 scoped_ptr<FileResource> entry;
212 if (received_bytes_ == expected_content_length_) {
213 DriveApiErrorCode response_code =
214 upload_location == GURL(kTestUploadNewFileURL) ?
215 HTTP_CREATED : HTTP_SUCCESS;
216 response = UploadRangeResponse(response_code, -1, -1);
218 entry.reset(new FileResource);
219 entry->set_md5_checksum(kTestDummyMd5);
220 } else {
221 response = UploadRangeResponse(
222 HTTP_RESUME_INCOMPLETE, 0, received_bytes_);
224 // ResumeUpload is an asynchronous function, so don't callback directly.
225 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
226 base::Bind(callback, response, base::Passed(&entry)));
229 CancelCallback MultipartUploadNewFile(
230 const std::string& content_type,
231 int64 content_length,
232 const std::string& parent_resource_id,
233 const std::string& title,
234 const base::FilePath& local_file_path,
235 const UploadNewFileOptions& options,
236 const google_apis::FileResourceCallback& callback,
237 const google_apis::ProgressCallback& progress_callback) override {
238 EXPECT_EQ(kTestMimeType, content_type);
239 EXPECT_EQ(expected_content_length_, content_length);
240 EXPECT_EQ(kTestInitiateUploadParentResourceId, parent_resource_id);
241 EXPECT_EQ(kTestDocumentTitle, title);
242 EXPECT_EQ(expected_upload_file_, local_file_path);
244 received_bytes_ = content_length;
245 multipart_upload_call_count_++;
246 return SendMultipartUploadResult(HTTP_CREATED, content_length, callback,
247 progress_callback);
250 CancelCallback MultipartUploadExistingFile(
251 const std::string& content_type,
252 int64 content_length,
253 const std::string& resource_id,
254 const base::FilePath& local_file_path,
255 const UploadExistingFileOptions& options,
256 const google_apis::FileResourceCallback& callback,
257 const google_apis::ProgressCallback& progress_callback) override {
258 EXPECT_EQ(kTestMimeType, content_type);
259 EXPECT_EQ(expected_content_length_, content_length);
260 EXPECT_EQ(kTestInitiateUploadResourceId, resource_id);
261 EXPECT_EQ(expected_upload_file_, local_file_path);
263 if (!options.etag.empty() && options.etag != kTestETag) {
264 base::ThreadTaskRunnerHandle::Get()->PostTask(
265 FROM_HERE,
266 base::Bind(callback, HTTP_PRECONDITION,
267 base::Passed(make_scoped_ptr<FileResource>(NULL))));
268 return CancelCallback();
271 received_bytes_ = content_length;
272 multipart_upload_call_count_++;
273 return SendMultipartUploadResult(HTTP_SUCCESS, content_length, callback,
274 progress_callback);
277 const base::FilePath expected_upload_file_;
278 const int64 expected_content_length_;
279 int64 received_bytes_;
280 int64 resume_upload_call_count_;
281 int64 multipart_upload_call_count_;
284 // Mock DriveService that returns a failure at InitiateUpload().
285 class MockDriveServiceNoConnectionAtInitiate : public DummyDriveService {
286 // Returns error.
287 CancelCallback InitiateUploadNewFile(
288 const std::string& content_type,
289 int64 content_length,
290 const std::string& parent_resource_id,
291 const std::string& title,
292 const UploadNewFileOptions& options,
293 const InitiateUploadCallback& callback) override {
294 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
295 base::Bind(callback, DRIVE_NO_CONNECTION, GURL()));
296 return CancelCallback();
299 CancelCallback InitiateUploadExistingFile(
300 const std::string& content_type,
301 int64 content_length,
302 const std::string& resource_id,
303 const UploadExistingFileOptions& options,
304 const InitiateUploadCallback& callback) override {
305 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
306 base::Bind(callback, DRIVE_NO_CONNECTION, GURL()));
307 return CancelCallback();
310 // Should not be used.
311 CancelCallback ResumeUpload(
312 const GURL& upload_url,
313 int64 start_position,
314 int64 end_position,
315 int64 content_length,
316 const std::string& content_type,
317 const base::FilePath& local_file_path,
318 const UploadRangeCallback& callback,
319 const ProgressCallback& progress_callback) override {
320 NOTREACHED();
321 return CancelCallback();
324 CancelCallback MultipartUploadNewFile(
325 const std::string& content_type,
326 int64 content_length,
327 const std::string& parent_resource_id,
328 const std::string& title,
329 const base::FilePath& local_file_path,
330 const UploadNewFileOptions& options,
331 const google_apis::FileResourceCallback& callback,
332 const google_apis::ProgressCallback& progress_callback) override {
333 base::ThreadTaskRunnerHandle::Get()->PostTask(
334 FROM_HERE,
335 base::Bind(callback, DRIVE_NO_CONNECTION,
336 base::Passed(make_scoped_ptr<FileResource>(NULL))));
337 return CancelCallback();
340 CancelCallback MultipartUploadExistingFile(
341 const std::string& content_type,
342 int64 content_length,
343 const std::string& resource_id,
344 const base::FilePath& local_file_path,
345 const UploadExistingFileOptions& options,
346 const google_apis::FileResourceCallback& callback,
347 const google_apis::ProgressCallback& progress_callback) override {
348 base::ThreadTaskRunnerHandle::Get()->PostTask(
349 FROM_HERE,
350 base::Bind(callback, DRIVE_NO_CONNECTION,
351 base::Passed(make_scoped_ptr<FileResource>(NULL))));
352 return CancelCallback();
356 // Mock DriveService that returns a failure at ResumeUpload().
357 class MockDriveServiceNoConnectionAtResume : public DummyDriveService {
358 // Succeeds and returns an upload location URL.
359 CancelCallback InitiateUploadNewFile(
360 const std::string& content_type,
361 int64 content_length,
362 const std::string& parent_resource_id,
363 const std::string& title,
364 const UploadNewFileOptions& options,
365 const InitiateUploadCallback& callback) override {
366 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
367 base::Bind(callback, HTTP_SUCCESS, GURL(kTestUploadNewFileURL)));
368 return CancelCallback();
371 CancelCallback InitiateUploadExistingFile(
372 const std::string& content_type,
373 int64 content_length,
374 const std::string& resource_id,
375 const UploadExistingFileOptions& options,
376 const InitiateUploadCallback& callback) override {
377 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
378 base::Bind(callback, HTTP_SUCCESS, GURL(kTestUploadExistingFileURL)));
379 return CancelCallback();
382 // Returns error.
383 CancelCallback ResumeUpload(
384 const GURL& upload_url,
385 int64 start_position,
386 int64 end_position,
387 int64 content_length,
388 const std::string& content_type,
389 const base::FilePath& local_file_path,
390 const UploadRangeCallback& callback,
391 const ProgressCallback& progress_callback) override {
392 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
393 base::Bind(callback,
394 UploadRangeResponse(DRIVE_NO_CONNECTION, -1, -1),
395 base::Passed(scoped_ptr<FileResource>())));
396 return CancelCallback();
400 // Mock DriveService that returns a failure at GetUploadStatus().
401 class MockDriveServiceNoConnectionAtGetUploadStatus : public DummyDriveService {
402 // Returns error.
403 CancelCallback GetUploadStatus(const GURL& upload_url,
404 int64 content_length,
405 const UploadRangeCallback& callback) override {
406 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
407 base::Bind(callback,
408 UploadRangeResponse(DRIVE_NO_CONNECTION, -1, -1),
409 base::Passed(scoped_ptr<FileResource>())));
410 return CancelCallback();
414 class DriveUploaderTest : public testing::Test {
415 public:
416 void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
418 protected:
419 base::MessageLoop message_loop_;
420 base::ScopedTempDir temp_dir_;
423 } // namespace
425 TEST_F(DriveUploaderTest, UploadExisting0KB) {
426 base::FilePath local_path;
427 std::string data;
428 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
429 temp_dir_.path(), 0, &local_path, &data));
431 DriveApiErrorCode error = DRIVE_OTHER_ERROR;
432 GURL upload_location;
433 scoped_ptr<FileResource> entry;
435 MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
436 DriveUploader uploader(&mock_service,
437 base::ThreadTaskRunnerHandle::Get().get());
438 std::vector<test_util::ProgressInfo> upload_progress_values;
439 uploader.UploadExistingFile(
440 kTestInitiateUploadResourceId, local_path, kTestMimeType,
441 UploadExistingFileOptions(),
442 test_util::CreateCopyResultCallback(&error, &upload_location, &entry),
443 base::Bind(&test_util::AppendProgressCallbackResult,
444 &upload_progress_values));
445 base::RunLoop().RunUntilIdle();
447 EXPECT_EQ(0, mock_service.resume_upload_call_count());
448 EXPECT_EQ(1, mock_service.multipart_upload_call_count());
449 EXPECT_EQ(0, mock_service.received_bytes());
450 EXPECT_EQ(HTTP_SUCCESS, error);
451 EXPECT_TRUE(upload_location.is_empty());
452 ASSERT_TRUE(entry);
453 EXPECT_EQ(kTestDummyMd5, entry->md5_checksum());
454 ASSERT_EQ(1U, upload_progress_values.size());
455 EXPECT_EQ(test_util::ProgressInfo(0, 0), upload_progress_values[0]);
458 TEST_F(DriveUploaderTest, UploadExisting512KB) {
459 base::FilePath local_path;
460 std::string data;
461 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
462 temp_dir_.path(), 512 * 1024, &local_path, &data));
464 DriveApiErrorCode error = DRIVE_OTHER_ERROR;
465 GURL upload_location;
466 scoped_ptr<FileResource> entry;
468 MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
469 DriveUploader uploader(&mock_service,
470 base::ThreadTaskRunnerHandle::Get().get());
471 std::vector<test_util::ProgressInfo> upload_progress_values;
472 uploader.UploadExistingFile(
473 kTestInitiateUploadResourceId, local_path, kTestMimeType,
474 UploadExistingFileOptions(),
475 test_util::CreateCopyResultCallback(&error, &upload_location, &entry),
476 base::Bind(&test_util::AppendProgressCallbackResult,
477 &upload_progress_values));
478 base::RunLoop().RunUntilIdle();
480 // 512KB upload should be uploaded as multipart body.
481 EXPECT_EQ(0, mock_service.resume_upload_call_count());
482 EXPECT_EQ(1, mock_service.multipart_upload_call_count());
483 EXPECT_EQ(512 * 1024, mock_service.received_bytes());
484 EXPECT_EQ(HTTP_SUCCESS, error);
485 EXPECT_TRUE(upload_location.is_empty());
486 ASSERT_TRUE(entry);
487 EXPECT_EQ(kTestDummyMd5, entry->md5_checksum());
488 ASSERT_EQ(1U, upload_progress_values.size());
489 EXPECT_EQ(test_util::ProgressInfo(512 * 1024, 512 * 1024),
490 upload_progress_values[0]);
493 TEST_F(DriveUploaderTest, UploadExisting2MB) {
494 base::FilePath local_path;
495 std::string data;
496 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
497 temp_dir_.path(), 2 * 1024 * 1024, &local_path, &data));
499 DriveApiErrorCode error = DRIVE_OTHER_ERROR;
500 GURL upload_location;
501 scoped_ptr<FileResource> entry;
503 MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
504 DriveUploader uploader(&mock_service,
505 base::ThreadTaskRunnerHandle::Get().get());
506 std::vector<test_util::ProgressInfo> upload_progress_values;
507 uploader.UploadExistingFile(
508 kTestInitiateUploadResourceId, local_path, kTestMimeType,
509 UploadExistingFileOptions(),
510 test_util::CreateCopyResultCallback(&error, &upload_location, &entry),
511 base::Bind(&test_util::AppendProgressCallbackResult,
512 &upload_progress_values));
513 base::RunLoop().RunUntilIdle();
515 // 2MB upload should not be split into multiple chunks.
516 EXPECT_EQ(1, mock_service.resume_upload_call_count());
517 EXPECT_EQ(0, mock_service.multipart_upload_call_count());
518 EXPECT_EQ(2 * 1024 * 1024, mock_service.received_bytes());
519 EXPECT_EQ(HTTP_SUCCESS, error);
520 EXPECT_TRUE(upload_location.is_empty());
521 ASSERT_TRUE(entry);
522 EXPECT_EQ(kTestDummyMd5, entry->md5_checksum());
523 ASSERT_EQ(1U, upload_progress_values.size());
524 EXPECT_EQ(test_util::ProgressInfo(2 * 1024 * 1024, 2 * 1024 * 1024),
525 upload_progress_values[0]);
528 TEST_F(DriveUploaderTest, InitiateUploadFail) {
529 base::FilePath local_path;
530 std::string data;
531 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
532 temp_dir_.path(), 2 * 1024 * 1024, &local_path, &data));
534 DriveApiErrorCode error = HTTP_SUCCESS;
535 GURL upload_location;
536 scoped_ptr<FileResource> entry;
538 MockDriveServiceNoConnectionAtInitiate mock_service;
539 DriveUploader uploader(&mock_service,
540 base::ThreadTaskRunnerHandle::Get().get());
541 uploader.UploadExistingFile(
542 kTestInitiateUploadResourceId, local_path, kTestMimeType,
543 UploadExistingFileOptions(),
544 test_util::CreateCopyResultCallback(&error, &upload_location, &entry),
545 google_apis::ProgressCallback());
546 base::RunLoop().RunUntilIdle();
548 EXPECT_EQ(DRIVE_NO_CONNECTION, error);
549 EXPECT_TRUE(upload_location.is_empty());
550 EXPECT_FALSE(entry);
553 TEST_F(DriveUploaderTest, MultipartUploadFail) {
554 base::FilePath local_path;
555 std::string data;
556 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(temp_dir_.path(), 512 * 1024,
557 &local_path, &data));
559 DriveApiErrorCode error = HTTP_SUCCESS;
560 GURL upload_location;
561 scoped_ptr<FileResource> entry;
563 MockDriveServiceNoConnectionAtInitiate mock_service;
564 DriveUploader uploader(&mock_service,
565 base::ThreadTaskRunnerHandle::Get().get());
566 uploader.UploadExistingFile(
567 kTestInitiateUploadResourceId, local_path, kTestMimeType,
568 UploadExistingFileOptions(),
569 test_util::CreateCopyResultCallback(&error, &upload_location, &entry),
570 google_apis::ProgressCallback());
571 base::RunLoop().RunUntilIdle();
573 EXPECT_EQ(DRIVE_NO_CONNECTION, error);
574 EXPECT_TRUE(upload_location.is_empty());
575 EXPECT_FALSE(entry);
578 TEST_F(DriveUploaderTest, InitiateUploadNoConflict) {
579 base::FilePath local_path;
580 std::string data;
581 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
582 temp_dir_.path(), 512 * 1024, &local_path, &data));
584 DriveApiErrorCode error = DRIVE_OTHER_ERROR;
585 GURL upload_location;
586 scoped_ptr<FileResource> entry;
588 MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
589 DriveUploader uploader(&mock_service,
590 base::ThreadTaskRunnerHandle::Get().get());
591 UploadExistingFileOptions options;
592 options.etag = kTestETag;
593 uploader.UploadExistingFile(kTestInitiateUploadResourceId,
594 local_path,
595 kTestMimeType,
596 options,
597 test_util::CreateCopyResultCallback(
598 &error, &upload_location, &entry),
599 google_apis::ProgressCallback());
600 base::RunLoop().RunUntilIdle();
602 EXPECT_EQ(HTTP_SUCCESS, error);
603 EXPECT_TRUE(upload_location.is_empty());
606 TEST_F(DriveUploaderTest, MultipartUploadConflict) {
607 base::FilePath local_path;
608 std::string data;
609 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
610 temp_dir_.path(), 512 * 1024, &local_path, &data));
611 const std::string kDestinationETag("destination_etag");
613 DriveApiErrorCode error = DRIVE_OTHER_ERROR;
614 GURL upload_location;
615 scoped_ptr<FileResource> entry;
617 MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
618 DriveUploader uploader(&mock_service,
619 base::ThreadTaskRunnerHandle::Get().get());
620 UploadExistingFileOptions options;
621 options.etag = kDestinationETag;
622 uploader.UploadExistingFile(kTestInitiateUploadResourceId,
623 local_path,
624 kTestMimeType,
625 options,
626 test_util::CreateCopyResultCallback(
627 &error, &upload_location, &entry),
628 google_apis::ProgressCallback());
629 base::RunLoop().RunUntilIdle();
631 EXPECT_EQ(HTTP_CONFLICT, error);
632 EXPECT_TRUE(upload_location.is_empty());
635 TEST_F(DriveUploaderTest, InitiateUploadConflict) {
636 base::FilePath local_path;
637 std::string data;
638 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
639 temp_dir_.path(), 2 * 1024 * 1024, &local_path, &data));
640 const std::string kDestinationETag("destination_etag");
642 DriveApiErrorCode error = DRIVE_OTHER_ERROR;
643 GURL upload_location;
644 scoped_ptr<FileResource> entry;
646 MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
647 DriveUploader uploader(&mock_service,
648 base::ThreadTaskRunnerHandle::Get().get());
649 UploadExistingFileOptions options;
650 options.etag = kDestinationETag;
651 uploader.UploadExistingFile(
652 kTestInitiateUploadResourceId, local_path, kTestMimeType, options,
653 test_util::CreateCopyResultCallback(&error, &upload_location, &entry),
654 google_apis::ProgressCallback());
655 base::RunLoop().RunUntilIdle();
657 EXPECT_EQ(HTTP_CONFLICT, error);
658 EXPECT_TRUE(upload_location.is_empty());
661 TEST_F(DriveUploaderTest, ResumeUploadFail) {
662 base::FilePath local_path;
663 std::string data;
664 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
665 temp_dir_.path(), 2 * 1024 * 1024, &local_path, &data));
667 DriveApiErrorCode error = HTTP_SUCCESS;
668 GURL upload_location;
669 scoped_ptr<FileResource> entry;
671 MockDriveServiceNoConnectionAtResume mock_service;
672 DriveUploader uploader(&mock_service,
673 base::ThreadTaskRunnerHandle::Get().get());
674 uploader.UploadExistingFile(
675 kTestInitiateUploadResourceId, local_path, kTestMimeType,
676 UploadExistingFileOptions(),
677 test_util::CreateCopyResultCallback(&error, &upload_location, &entry),
678 google_apis::ProgressCallback());
679 base::RunLoop().RunUntilIdle();
681 EXPECT_EQ(DRIVE_NO_CONNECTION, error);
682 EXPECT_EQ(GURL(kTestUploadExistingFileURL), upload_location);
685 TEST_F(DriveUploaderTest, GetUploadStatusFail) {
686 base::FilePath local_path;
687 std::string data;
688 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
689 temp_dir_.path(), 2 * 1024 * 1024, &local_path, &data));
691 DriveApiErrorCode error = HTTP_SUCCESS;
692 GURL upload_location;
693 scoped_ptr<FileResource> entry;
695 MockDriveServiceNoConnectionAtGetUploadStatus mock_service;
696 DriveUploader uploader(&mock_service,
697 base::ThreadTaskRunnerHandle::Get().get());
698 uploader.ResumeUploadFile(GURL(kTestUploadExistingFileURL),
699 local_path,
700 kTestMimeType,
701 test_util::CreateCopyResultCallback(
702 &error, &upload_location, &entry),
703 google_apis::ProgressCallback());
704 base::RunLoop().RunUntilIdle();
706 EXPECT_EQ(DRIVE_NO_CONNECTION, error);
707 EXPECT_TRUE(upload_location.is_empty());
710 TEST_F(DriveUploaderTest, NonExistingSourceFile) {
711 DriveApiErrorCode error = DRIVE_OTHER_ERROR;
712 GURL upload_location;
713 scoped_ptr<FileResource> entry;
715 DriveUploader uploader(NULL, // NULL, the service won't be used.
716 base::ThreadTaskRunnerHandle::Get().get());
717 uploader.UploadExistingFile(
718 kTestInitiateUploadResourceId,
719 temp_dir_.path().AppendASCII("_this_path_should_not_exist_"),
720 kTestMimeType, UploadExistingFileOptions(),
721 test_util::CreateCopyResultCallback(&error, &upload_location, &entry),
722 google_apis::ProgressCallback());
723 base::RunLoop().RunUntilIdle();
725 // Should return failure without doing any attempt to connect to the server.
726 EXPECT_EQ(HTTP_NOT_FOUND, error);
727 EXPECT_TRUE(upload_location.is_empty());
730 TEST_F(DriveUploaderTest, ResumeUpload) {
731 base::FilePath local_path;
732 std::string data;
733 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
734 temp_dir_.path(), 1024 * 1024, &local_path, &data));
736 DriveApiErrorCode error = DRIVE_OTHER_ERROR;
737 GURL upload_location;
738 scoped_ptr<FileResource> entry;
740 MockDriveServiceWithUploadExpectation mock_service(local_path, data.size());
741 DriveUploader uploader(&mock_service,
742 base::ThreadTaskRunnerHandle::Get().get());
743 // Emulate the situation that the only first part is successfully uploaded,
744 // but not the latter half.
745 mock_service.set_received_bytes(512 * 1024);
747 std::vector<test_util::ProgressInfo> upload_progress_values;
748 uploader.ResumeUploadFile(
749 GURL(kTestUploadExistingFileURL),
750 local_path,
751 kTestMimeType,
752 test_util::CreateCopyResultCallback(
753 &error, &upload_location, &entry),
754 base::Bind(&test_util::AppendProgressCallbackResult,
755 &upload_progress_values));
756 base::RunLoop().RunUntilIdle();
758 EXPECT_EQ(1, mock_service.resume_upload_call_count());
759 EXPECT_EQ(1024 * 1024, mock_service.received_bytes());
760 EXPECT_EQ(HTTP_SUCCESS, error);
761 EXPECT_TRUE(upload_location.is_empty());
762 ASSERT_TRUE(entry);
763 EXPECT_EQ(kTestDummyMd5, entry->md5_checksum());
764 ASSERT_EQ(1U, upload_progress_values.size());
765 EXPECT_EQ(test_util::ProgressInfo(1024 * 1024, 1024 * 1024),
766 upload_progress_values[0]);
769 class MockDriveServiceForBatchProcessing : public DummyDriveService {
770 public:
771 struct UploadFileInfo {
772 enum { NEW_FILE, EXISTING_FILE } type;
773 std::string content_type;
774 uint64 content_length;
775 std::string parent_resource_id;
776 std::string resource_id;
777 std::string title;
778 base::FilePath local_file_path;
779 google_apis::FileResourceCallback callback;
780 google_apis::ProgressCallback progress_callback;
783 class BatchRequestConfigurator : public BatchRequestConfiguratorInterface {
784 public:
785 explicit BatchRequestConfigurator(
786 MockDriveServiceForBatchProcessing* service)
787 : service(service) {}
789 CancelCallback MultipartUploadNewFile(
790 const std::string& content_type,
791 int64 content_length,
792 const std::string& parent_resource_id,
793 const std::string& title,
794 const base::FilePath& local_file_path,
795 const UploadNewFileOptions& options,
796 const google_apis::FileResourceCallback& callback,
797 const google_apis::ProgressCallback& progress_callback) override {
798 UploadFileInfo info;
799 info.type = UploadFileInfo::NEW_FILE;
800 info.content_type = content_type;
801 info.content_length = content_length;
802 info.parent_resource_id = parent_resource_id;
803 info.title = title;
804 info.local_file_path = local_file_path;
805 info.callback = callback;
806 info.progress_callback = progress_callback;
807 service->files.push_back(info);
808 return CancelCallback();
811 CancelCallback MultipartUploadExistingFile(
812 const std::string& content_type,
813 int64 content_length,
814 const std::string& resource_id,
815 const base::FilePath& local_file_path,
816 const UploadExistingFileOptions& options,
817 const google_apis::FileResourceCallback& callback,
818 const google_apis::ProgressCallback& progress_callback) override {
819 UploadFileInfo info;
820 info.type = UploadFileInfo::EXISTING_FILE;
821 info.content_type = content_type;
822 info.content_length = content_length;
823 info.resource_id = resource_id;
824 info.local_file_path = local_file_path;
825 info.callback = callback;
826 info.progress_callback = progress_callback;
827 service->files.push_back(info);
828 return CancelCallback();
831 void Commit() override {
832 ASSERT_FALSE(service->committed);
833 service->committed = true;
834 for (const auto& file : service->files) {
835 SendMultipartUploadResult(HTTP_SUCCESS, file.content_length,
836 file.callback, file.progress_callback);
840 private:
841 MockDriveServiceForBatchProcessing* service;
844 public:
845 scoped_ptr<BatchRequestConfiguratorInterface> StartBatchRequest() override {
846 committed = false;
847 return scoped_ptr<BatchRequestConfiguratorInterface>(
848 new BatchRequestConfigurator(this));
851 std::vector<UploadFileInfo> files;
852 bool committed;
855 TEST_F(DriveUploaderTest, BatchProcessing) {
856 // Preapre test file.
857 const size_t kTestFileSize = 1024 * 512;
858 base::FilePath local_path;
859 std::string data;
860 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
861 temp_dir_.path(), kTestFileSize, &local_path, &data));
863 // Prepare test target.
864 MockDriveServiceForBatchProcessing service;
865 DriveUploader uploader(&service, base::ThreadTaskRunnerHandle::Get().get());
867 struct {
868 DriveApiErrorCode error;
869 GURL resume_url;
870 scoped_ptr<FileResource> file;
871 UploadCompletionCallback callback() {
872 return test_util::CreateCopyResultCallback(&error, &resume_url, &file);
874 } results[2];
876 uploader.StartBatchProcessing();
877 uploader.UploadNewFile("parent_resource_id", local_path, "title",
878 kTestMimeType, UploadNewFileOptions(),
879 results[0].callback(),
880 google_apis::ProgressCallback());
881 uploader.UploadExistingFile(
882 "resource_id", local_path, kTestMimeType, UploadExistingFileOptions(),
883 results[1].callback(), google_apis::ProgressCallback());
884 uploader.StopBatchProcessing();
885 base::RunLoop().RunUntilIdle();
887 ASSERT_EQ(2u, service.files.size());
888 EXPECT_TRUE(service.committed);
890 EXPECT_EQ(MockDriveServiceForBatchProcessing::UploadFileInfo::NEW_FILE,
891 service.files[0].type);
892 EXPECT_EQ(kTestMimeType, service.files[0].content_type);
893 EXPECT_EQ(kTestFileSize, service.files[0].content_length);
894 EXPECT_EQ("parent_resource_id", service.files[0].parent_resource_id);
895 EXPECT_EQ("", service.files[0].resource_id);
896 EXPECT_EQ("title", service.files[0].title);
897 EXPECT_EQ(local_path.value(), service.files[0].local_file_path.value());
899 EXPECT_EQ(MockDriveServiceForBatchProcessing::UploadFileInfo::EXISTING_FILE,
900 service.files[1].type);
901 EXPECT_EQ(kTestMimeType, service.files[1].content_type);
902 EXPECT_EQ(kTestFileSize, service.files[1].content_length);
903 EXPECT_EQ("", service.files[1].parent_resource_id);
904 EXPECT_EQ("resource_id", service.files[1].resource_id);
905 EXPECT_EQ("", service.files[1].title);
906 EXPECT_EQ(local_path.value(), service.files[1].local_file_path.value());
908 EXPECT_EQ(HTTP_SUCCESS, results[0].error);
909 EXPECT_TRUE(results[0].resume_url.is_empty());
910 EXPECT_TRUE(results[0].file);
912 EXPECT_EQ(HTTP_SUCCESS, results[1].error);
913 EXPECT_TRUE(results[1].resume_url.is_empty());
914 EXPECT_TRUE(results[1].file);
917 TEST_F(DriveUploaderTest, BatchProcessingWithError) {
918 // Prepare test target.
919 MockDriveServiceForBatchProcessing service;
920 DriveUploader uploader(&service, base::ThreadTaskRunnerHandle::Get().get());
922 struct {
923 DriveApiErrorCode error;
924 GURL resume_url;
925 scoped_ptr<FileResource> file;
926 UploadCompletionCallback callback() {
927 return test_util::CreateCopyResultCallback(&error, &resume_url, &file);
929 } results[2];
931 uploader.StartBatchProcessing();
932 uploader.UploadNewFile("parent_resource_id",
933 base::FilePath(FILE_PATH_LITERAL("/path/non_exists")),
934 "title", kTestMimeType, UploadNewFileOptions(),
935 results[0].callback(),
936 google_apis::ProgressCallback());
937 uploader.UploadExistingFile(
938 "resource_id", base::FilePath(FILE_PATH_LITERAL("/path/non_exists")),
939 kTestMimeType, UploadExistingFileOptions(), results[1].callback(),
940 google_apis::ProgressCallback());
941 uploader.StopBatchProcessing();
942 base::RunLoop().RunUntilIdle();
944 EXPECT_EQ(0u, service.files.size());
945 EXPECT_TRUE(service.committed);
947 EXPECT_EQ(HTTP_NOT_FOUND, results[0].error);
948 EXPECT_TRUE(results[0].resume_url.is_empty());
949 EXPECT_FALSE(results[0].file);
951 EXPECT_EQ(HTTP_NOT_FOUND, results[1].error);
952 EXPECT_TRUE(results[1].resume_url.is_empty());
953 EXPECT_FALSE(results[1].file);
955 } // namespace drive