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 "chrome/browser/drive/drive_uploader.h"
10 #include "base/bind.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/run_loop.h"
15 #include "base/values.h"
16 #include "chrome/browser/drive/dummy_drive_service.h"
17 #include "google_apis/drive/drive_api_parser.h"
18 #include "google_apis/drive/test_util.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using google_apis::CancelCallback
;
22 using google_apis::FileResource
;
23 using google_apis::DriveApiErrorCode
;
24 using google_apis::DRIVE_NO_CONNECTION
;
25 using google_apis::DRIVE_OTHER_ERROR
;
26 using google_apis::HTTP_CONFLICT
;
27 using google_apis::HTTP_CREATED
;
28 using google_apis::HTTP_NOT_FOUND
;
29 using google_apis::HTTP_PRECONDITION
;
30 using google_apis::HTTP_RESUME_INCOMPLETE
;
31 using google_apis::HTTP_SUCCESS
;
32 using google_apis::InitiateUploadCallback
;
33 using google_apis::ProgressCallback
;
34 using google_apis::UploadRangeResponse
;
35 using google_apis::drive::UploadRangeCallback
;
36 namespace test_util
= google_apis::test_util
;
42 const char kTestDummyMd5
[] = "dummy_md5";
43 const char kTestDocumentTitle
[] = "Hello world";
44 const char kTestInitiateUploadParentResourceId
[] = "parent_resource_id";
45 const char kTestInitiateUploadResourceId
[] = "resource_id";
46 const char kTestMimeType
[] = "text/plain";
47 const char kTestUploadNewFileURL
[] = "http://test/upload_location/new_file";
48 const char kTestUploadExistingFileURL
[] =
49 "http://test/upload_location/existing_file";
50 const int64 kUploadChunkSize
= 1024 * 1024 * 1024;
51 const char kTestETag
[] = "test_etag";
53 // Mock DriveService that verifies if the uploaded content matches the preset
55 class MockDriveServiceWithUploadExpectation
: public DummyDriveService
{
57 // Sets up an expected upload content. InitiateUpload and ResumeUpload will
58 // verify that the specified data is correctly uploaded.
59 MockDriveServiceWithUploadExpectation(
60 const base::FilePath
& expected_upload_file
,
61 int64 expected_content_length
)
62 : expected_upload_file_(expected_upload_file
),
63 expected_content_length_(expected_content_length
),
65 resume_upload_call_count_(0),
66 multipart_upload_call_count_(0) {}
68 int64
received_bytes() const { return received_bytes_
; }
69 void set_received_bytes(int64 received_bytes
) {
70 received_bytes_
= received_bytes
;
73 int64
resume_upload_call_count() const { return resume_upload_call_count_
; }
74 int64
multipart_upload_call_count() const {
75 return multipart_upload_call_count_
;
79 // DriveServiceInterface overrides.
80 // Handles a request for obtaining an upload location URL.
81 CancelCallback
InitiateUploadNewFile(
82 const std::string
& content_type
,
84 const std::string
& parent_resource_id
,
85 const std::string
& title
,
86 const UploadNewFileOptions
& options
,
87 const InitiateUploadCallback
& callback
) override
{
88 EXPECT_EQ(kTestDocumentTitle
, title
);
89 EXPECT_EQ(kTestMimeType
, content_type
);
90 EXPECT_EQ(expected_content_length_
, content_length
);
91 EXPECT_EQ(kTestInitiateUploadParentResourceId
, parent_resource_id
);
93 // Calls back the upload URL for subsequent ResumeUpload requests.
94 // InitiateUpload is an asynchronous function, so don't callback directly.
95 base::MessageLoop::current()->PostTask(FROM_HERE
,
96 base::Bind(callback
, HTTP_SUCCESS
, GURL(kTestUploadNewFileURL
)));
97 return CancelCallback();
100 CancelCallback
InitiateUploadExistingFile(
101 const std::string
& content_type
,
102 int64 content_length
,
103 const std::string
& resource_id
,
104 const UploadExistingFileOptions
& options
,
105 const InitiateUploadCallback
& callback
) override
{
106 EXPECT_EQ(kTestMimeType
, content_type
);
107 EXPECT_EQ(expected_content_length_
, content_length
);
108 EXPECT_EQ(kTestInitiateUploadResourceId
, resource_id
);
110 if (!options
.etag
.empty() && options
.etag
!= kTestETag
) {
111 base::MessageLoop::current()->PostTask(FROM_HERE
,
112 base::Bind(callback
, HTTP_PRECONDITION
, GURL()));
113 return CancelCallback();
116 // Calls back the upload URL for subsequent ResumeUpload requests.
117 // InitiateUpload is an asynchronous function, so don't callback directly.
118 base::MessageLoop::current()->PostTask(FROM_HERE
,
119 base::Bind(callback
, HTTP_SUCCESS
, GURL(kTestUploadExistingFileURL
)));
120 return CancelCallback();
123 // Handles a request for uploading a chunk of bytes.
124 CancelCallback
ResumeUpload(
125 const GURL
& upload_location
,
126 int64 start_position
,
128 int64 content_length
,
129 const std::string
& content_type
,
130 const base::FilePath
& local_file_path
,
131 const UploadRangeCallback
& callback
,
132 const ProgressCallback
& progress_callback
) override
{
133 // The upload range should start from the current first unreceived byte.
134 EXPECT_EQ(received_bytes_
, start_position
);
135 EXPECT_EQ(expected_upload_file_
, local_file_path
);
137 // The upload data must be split into 512KB chunks.
138 const int64 expected_chunk_end
=
139 std::min(received_bytes_
+ kUploadChunkSize
, expected_content_length_
);
140 EXPECT_EQ(expected_chunk_end
, end_position
);
142 // The upload URL returned by InitiateUpload() must be used.
143 EXPECT_TRUE(GURL(kTestUploadNewFileURL
) == upload_location
||
144 GURL(kTestUploadExistingFileURL
) == upload_location
);
146 // Other parameters should be the exact values passed to DriveUploader.
147 EXPECT_EQ(expected_content_length_
, content_length
);
148 EXPECT_EQ(kTestMimeType
, content_type
);
150 // Update the internal status of the current upload session.
151 resume_upload_call_count_
++;
152 received_bytes_
= end_position
;
155 if (!progress_callback
.is_null()) {
156 // For the testing purpose, it always notifies the progress at the end of
157 // each chunk uploading.
158 int64 chunk_size
= end_position
- start_position
;
159 base::MessageLoop::current()->PostTask(FROM_HERE
,
160 base::Bind(progress_callback
, chunk_size
, chunk_size
));
163 SendUploadRangeResponse(upload_location
, callback
);
164 return CancelCallback();
167 // Handles a request to fetch the current upload status.
168 CancelCallback
GetUploadStatus(const GURL
& upload_location
,
169 int64 content_length
,
170 const UploadRangeCallback
& callback
) override
{
171 EXPECT_EQ(expected_content_length_
, content_length
);
172 // The upload URL returned by InitiateUpload() must be used.
173 EXPECT_TRUE(GURL(kTestUploadNewFileURL
) == upload_location
||
174 GURL(kTestUploadExistingFileURL
) == upload_location
);
176 SendUploadRangeResponse(upload_location
, callback
);
177 return CancelCallback();
180 // Runs |callback| with the current upload status.
181 void SendUploadRangeResponse(const GURL
& upload_location
,
182 const UploadRangeCallback
& callback
) {
183 // Callback with response.
184 UploadRangeResponse response
;
185 scoped_ptr
<FileResource
> entry
;
186 if (received_bytes_
== expected_content_length_
) {
187 DriveApiErrorCode response_code
=
188 upload_location
== GURL(kTestUploadNewFileURL
) ?
189 HTTP_CREATED
: HTTP_SUCCESS
;
190 response
= UploadRangeResponse(response_code
, -1, -1);
192 entry
.reset(new FileResource
);
193 entry
->set_md5_checksum(kTestDummyMd5
);
195 response
= UploadRangeResponse(
196 HTTP_RESUME_INCOMPLETE
, 0, received_bytes_
);
198 // ResumeUpload is an asynchronous function, so don't callback directly.
199 base::MessageLoop::current()->PostTask(FROM_HERE
,
200 base::Bind(callback
, response
, base::Passed(&entry
)));
203 CancelCallback
MultipartUploadNewFile(
204 const std::string
& content_type
,
205 int64 content_length
,
206 const std::string
& parent_resource_id
,
207 const std::string
& title
,
208 const base::FilePath
& local_file_path
,
209 const UploadNewFileOptions
& options
,
210 const google_apis::FileResourceCallback
& callback
,
211 const google_apis::ProgressCallback
& progress_callback
) override
{
212 EXPECT_EQ(kTestMimeType
, content_type
);
213 EXPECT_EQ(expected_content_length_
, content_length
);
214 EXPECT_EQ(kTestInitiateUploadParentResourceId
, parent_resource_id
);
215 EXPECT_EQ(kTestDocumentTitle
, title
);
216 EXPECT_EQ(expected_upload_file_
, local_file_path
);
218 return SendMultipartUploadResult(HTTP_CREATED
, content_length
, callback
,
222 CancelCallback
MultipartUploadExistingFile(
223 const std::string
& content_type
,
224 int64 content_length
,
225 const std::string
& resource_id
,
226 const base::FilePath
& local_file_path
,
227 const UploadExistingFileOptions
& options
,
228 const google_apis::FileResourceCallback
& callback
,
229 const google_apis::ProgressCallback
& progress_callback
) override
{
230 EXPECT_EQ(kTestMimeType
, content_type
);
231 EXPECT_EQ(expected_content_length_
, content_length
);
232 EXPECT_EQ(kTestInitiateUploadResourceId
, resource_id
);
233 EXPECT_EQ(expected_upload_file_
, local_file_path
);
235 if (!options
.etag
.empty() && options
.etag
!= kTestETag
) {
236 base::MessageLoop::current()->PostTask(
238 base::Bind(callback
, HTTP_PRECONDITION
,
239 base::Passed(make_scoped_ptr
<FileResource
>(NULL
))));
240 return CancelCallback();
243 return SendMultipartUploadResult(HTTP_SUCCESS
, content_length
, callback
,
247 CancelCallback
SendMultipartUploadResult(
248 DriveApiErrorCode response_code
,
249 int64 content_length
,
250 const google_apis::FileResourceCallback
& callback
,
251 const google_apis::ProgressCallback
& progress_callback
) {
252 received_bytes_
= content_length
;
253 multipart_upload_call_count_
++;
256 if (!progress_callback
.is_null()) {
257 // For the testing purpose, it always notifies the progress at the end of
258 // whole file uploading.
259 base::MessageLoop::current()->PostTask(
261 base::Bind(progress_callback
, content_length
, content_length
));
264 // MultipartUploadXXXFile is an asynchronous function, so don't callback
266 scoped_ptr
<FileResource
> entry
;
267 entry
.reset(new FileResource
);
268 entry
->set_md5_checksum(kTestDummyMd5
);
269 base::MessageLoop::current()->PostTask(
270 FROM_HERE
, base::Bind(callback
, response_code
, base::Passed(&entry
)));
271 return CancelCallback();
274 const base::FilePath expected_upload_file_
;
275 const int64 expected_content_length_
;
276 int64 received_bytes_
;
277 int64 resume_upload_call_count_
;
278 int64 multipart_upload_call_count_
;
281 // Mock DriveService that returns a failure at InitiateUpload().
282 class MockDriveServiceNoConnectionAtInitiate
: public DummyDriveService
{
284 CancelCallback
InitiateUploadNewFile(
285 const std::string
& content_type
,
286 int64 content_length
,
287 const std::string
& parent_resource_id
,
288 const std::string
& title
,
289 const UploadNewFileOptions
& options
,
290 const InitiateUploadCallback
& callback
) override
{
291 base::MessageLoop::current()->PostTask(FROM_HERE
,
292 base::Bind(callback
, DRIVE_NO_CONNECTION
, GURL()));
293 return CancelCallback();
296 CancelCallback
InitiateUploadExistingFile(
297 const std::string
& content_type
,
298 int64 content_length
,
299 const std::string
& resource_id
,
300 const UploadExistingFileOptions
& options
,
301 const InitiateUploadCallback
& callback
) override
{
302 base::MessageLoop::current()->PostTask(FROM_HERE
,
303 base::Bind(callback
, DRIVE_NO_CONNECTION
, GURL()));
304 return CancelCallback();
307 // Should not be used.
308 CancelCallback
ResumeUpload(
309 const GURL
& upload_url
,
310 int64 start_position
,
312 int64 content_length
,
313 const std::string
& content_type
,
314 const base::FilePath
& local_file_path
,
315 const UploadRangeCallback
& callback
,
316 const ProgressCallback
& progress_callback
) override
{
318 return CancelCallback();
321 CancelCallback
MultipartUploadNewFile(
322 const std::string
& content_type
,
323 int64 content_length
,
324 const std::string
& parent_resource_id
,
325 const std::string
& title
,
326 const base::FilePath
& local_file_path
,
327 const UploadNewFileOptions
& options
,
328 const google_apis::FileResourceCallback
& callback
,
329 const google_apis::ProgressCallback
& progress_callback
) override
{
330 base::MessageLoop::current()->PostTask(
332 base::Bind(callback
, DRIVE_NO_CONNECTION
,
333 base::Passed(make_scoped_ptr
<FileResource
>(NULL
))));
334 return CancelCallback();
337 CancelCallback
MultipartUploadExistingFile(
338 const std::string
& content_type
,
339 int64 content_length
,
340 const std::string
& resource_id
,
341 const base::FilePath
& local_file_path
,
342 const UploadExistingFileOptions
& options
,
343 const google_apis::FileResourceCallback
& callback
,
344 const google_apis::ProgressCallback
& progress_callback
) override
{
345 base::MessageLoop::current()->PostTask(
347 base::Bind(callback
, DRIVE_NO_CONNECTION
,
348 base::Passed(make_scoped_ptr
<FileResource
>(NULL
))));
349 return CancelCallback();
353 // Mock DriveService that returns a failure at ResumeUpload().
354 class MockDriveServiceNoConnectionAtResume
: public DummyDriveService
{
355 // Succeeds and returns an upload location URL.
356 CancelCallback
InitiateUploadNewFile(
357 const std::string
& content_type
,
358 int64 content_length
,
359 const std::string
& parent_resource_id
,
360 const std::string
& title
,
361 const UploadNewFileOptions
& options
,
362 const InitiateUploadCallback
& callback
) override
{
363 base::MessageLoop::current()->PostTask(FROM_HERE
,
364 base::Bind(callback
, HTTP_SUCCESS
, GURL(kTestUploadNewFileURL
)));
365 return CancelCallback();
368 CancelCallback
InitiateUploadExistingFile(
369 const std::string
& content_type
,
370 int64 content_length
,
371 const std::string
& resource_id
,
372 const UploadExistingFileOptions
& options
,
373 const InitiateUploadCallback
& callback
) override
{
374 base::MessageLoop::current()->PostTask(FROM_HERE
,
375 base::Bind(callback
, HTTP_SUCCESS
, GURL(kTestUploadExistingFileURL
)));
376 return CancelCallback();
380 CancelCallback
ResumeUpload(
381 const GURL
& upload_url
,
382 int64 start_position
,
384 int64 content_length
,
385 const std::string
& content_type
,
386 const base::FilePath
& local_file_path
,
387 const UploadRangeCallback
& callback
,
388 const ProgressCallback
& progress_callback
) override
{
389 base::MessageLoop::current()->PostTask(FROM_HERE
,
391 UploadRangeResponse(DRIVE_NO_CONNECTION
, -1, -1),
392 base::Passed(scoped_ptr
<FileResource
>())));
393 return CancelCallback();
397 // Mock DriveService that returns a failure at GetUploadStatus().
398 class MockDriveServiceNoConnectionAtGetUploadStatus
: public DummyDriveService
{
400 CancelCallback
GetUploadStatus(const GURL
& upload_url
,
401 int64 content_length
,
402 const UploadRangeCallback
& callback
) override
{
403 base::MessageLoop::current()->PostTask(FROM_HERE
,
405 UploadRangeResponse(DRIVE_NO_CONNECTION
, -1, -1),
406 base::Passed(scoped_ptr
<FileResource
>())));
407 return CancelCallback();
411 class DriveUploaderTest
: public testing::Test
{
413 void SetUp() override
{ ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir()); }
416 base::MessageLoop message_loop_
;
417 base::ScopedTempDir temp_dir_
;
422 TEST_F(DriveUploaderTest
, UploadExisting0KB
) {
423 base::FilePath local_path
;
425 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
426 temp_dir_
.path(), 0, &local_path
, &data
));
428 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
429 GURL upload_location
;
430 scoped_ptr
<FileResource
> entry
;
432 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
433 DriveUploader
uploader(&mock_service
,
434 base::MessageLoopProxy::current().get());
435 std::vector
<test_util::ProgressInfo
> upload_progress_values
;
436 uploader
.UploadExistingFile(
437 kTestInitiateUploadResourceId
,
440 DriveUploader::UploadExistingFileOptions(),
441 test_util::CreateCopyResultCallback(
442 &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());
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
;
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::MessageLoopProxy::current().get());
471 std::vector
<test_util::ProgressInfo
> upload_progress_values
;
472 uploader
.UploadExistingFile(
473 kTestInitiateUploadResourceId
,
476 DriveUploader::UploadExistingFileOptions(),
477 test_util::CreateCopyResultCallback(
478 &error
, &upload_location
, &entry
),
479 base::Bind(&test_util::AppendProgressCallbackResult
,
480 &upload_progress_values
));
481 base::RunLoop().RunUntilIdle();
483 // 512KB upload should be uploaded as multipart body.
484 EXPECT_EQ(0, mock_service
.resume_upload_call_count());
485 EXPECT_EQ(1, mock_service
.multipart_upload_call_count());
486 EXPECT_EQ(512 * 1024, mock_service
.received_bytes());
487 EXPECT_EQ(HTTP_SUCCESS
, error
);
488 EXPECT_TRUE(upload_location
.is_empty());
490 EXPECT_EQ(kTestDummyMd5
, entry
->md5_checksum());
491 ASSERT_EQ(1U, upload_progress_values
.size());
492 EXPECT_EQ(test_util::ProgressInfo(512 * 1024, 512 * 1024),
493 upload_progress_values
[0]);
496 TEST_F(DriveUploaderTest
, UploadExisting2MB
) {
497 base::FilePath local_path
;
499 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
500 temp_dir_
.path(), 2 * 1024 * 1024, &local_path
, &data
));
502 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
503 GURL upload_location
;
504 scoped_ptr
<FileResource
> entry
;
506 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
507 DriveUploader
uploader(&mock_service
,
508 base::MessageLoopProxy::current().get());
509 std::vector
<test_util::ProgressInfo
> upload_progress_values
;
510 uploader
.UploadExistingFile(
511 kTestInitiateUploadResourceId
, local_path
, kTestMimeType
,
512 DriveUploader::UploadExistingFileOptions(),
513 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
514 base::Bind(&test_util::AppendProgressCallbackResult
,
515 &upload_progress_values
));
516 base::RunLoop().RunUntilIdle();
518 // 2MB upload should not be split into multiple chunks.
519 EXPECT_EQ(1, mock_service
.resume_upload_call_count());
520 EXPECT_EQ(0, mock_service
.multipart_upload_call_count());
521 EXPECT_EQ(2 * 1024 * 1024, mock_service
.received_bytes());
522 EXPECT_EQ(HTTP_SUCCESS
, error
);
523 EXPECT_TRUE(upload_location
.is_empty());
525 EXPECT_EQ(kTestDummyMd5
, entry
->md5_checksum());
526 ASSERT_EQ(1U, upload_progress_values
.size());
527 EXPECT_EQ(test_util::ProgressInfo(2 * 1024 * 1024, 2 * 1024 * 1024),
528 upload_progress_values
[0]);
531 TEST_F(DriveUploaderTest
, InitiateUploadFail
) {
532 base::FilePath local_path
;
534 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
535 temp_dir_
.path(), 2 * 1024 * 1024, &local_path
, &data
));
537 DriveApiErrorCode error
= HTTP_SUCCESS
;
538 GURL upload_location
;
539 scoped_ptr
<FileResource
> entry
;
541 MockDriveServiceNoConnectionAtInitiate mock_service
;
542 DriveUploader
uploader(&mock_service
,
543 base::MessageLoopProxy::current().get());
544 uploader
.UploadExistingFile(
545 kTestInitiateUploadResourceId
, local_path
, kTestMimeType
,
546 DriveUploader::UploadExistingFileOptions(),
547 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
548 google_apis::ProgressCallback());
549 base::RunLoop().RunUntilIdle();
551 EXPECT_EQ(DRIVE_NO_CONNECTION
, error
);
552 EXPECT_TRUE(upload_location
.is_empty());
556 TEST_F(DriveUploaderTest
, MultipartUploadFail
) {
557 base::FilePath local_path
;
559 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(temp_dir_
.path(), 512 * 1024,
560 &local_path
, &data
));
562 DriveApiErrorCode error
= HTTP_SUCCESS
;
563 GURL upload_location
;
564 scoped_ptr
<FileResource
> entry
;
566 MockDriveServiceNoConnectionAtInitiate mock_service
;
567 DriveUploader
uploader(&mock_service
,
568 base::MessageLoopProxy::current().get());
569 uploader
.UploadExistingFile(kTestInitiateUploadResourceId
,
572 DriveUploader::UploadExistingFileOptions(),
573 test_util::CreateCopyResultCallback(
574 &error
, &upload_location
, &entry
),
575 google_apis::ProgressCallback());
576 base::RunLoop().RunUntilIdle();
578 EXPECT_EQ(DRIVE_NO_CONNECTION
, error
);
579 EXPECT_TRUE(upload_location
.is_empty());
583 TEST_F(DriveUploaderTest
, InitiateUploadNoConflict
) {
584 base::FilePath local_path
;
586 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
587 temp_dir_
.path(), 512 * 1024, &local_path
, &data
));
589 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
590 GURL upload_location
;
591 scoped_ptr
<FileResource
> entry
;
593 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
594 DriveUploader
uploader(&mock_service
,
595 base::MessageLoopProxy::current().get());
596 DriveUploader::UploadExistingFileOptions options
;
597 options
.etag
= kTestETag
;
598 uploader
.UploadExistingFile(kTestInitiateUploadResourceId
,
602 test_util::CreateCopyResultCallback(
603 &error
, &upload_location
, &entry
),
604 google_apis::ProgressCallback());
605 base::RunLoop().RunUntilIdle();
607 EXPECT_EQ(HTTP_SUCCESS
, error
);
608 EXPECT_TRUE(upload_location
.is_empty());
611 TEST_F(DriveUploaderTest
, MultipartUploadConflict
) {
612 base::FilePath local_path
;
614 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
615 temp_dir_
.path(), 512 * 1024, &local_path
, &data
));
616 const std::string
kDestinationETag("destination_etag");
618 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
619 GURL upload_location
;
620 scoped_ptr
<FileResource
> entry
;
622 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
623 DriveUploader
uploader(&mock_service
,
624 base::MessageLoopProxy::current().get());
625 DriveUploader::UploadExistingFileOptions options
;
626 options
.etag
= kDestinationETag
;
627 uploader
.UploadExistingFile(kTestInitiateUploadResourceId
,
631 test_util::CreateCopyResultCallback(
632 &error
, &upload_location
, &entry
),
633 google_apis::ProgressCallback());
634 base::RunLoop().RunUntilIdle();
636 EXPECT_EQ(HTTP_CONFLICT
, error
);
637 EXPECT_TRUE(upload_location
.is_empty());
640 TEST_F(DriveUploaderTest
, InitiateUploadConflict
) {
641 base::FilePath local_path
;
643 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
644 temp_dir_
.path(), 2 * 1024 * 1024, &local_path
, &data
));
645 const std::string
kDestinationETag("destination_etag");
647 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
648 GURL upload_location
;
649 scoped_ptr
<FileResource
> entry
;
651 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
652 DriveUploader
uploader(&mock_service
,
653 base::MessageLoopProxy::current().get());
654 DriveUploader::UploadExistingFileOptions options
;
655 options
.etag
= kDestinationETag
;
656 uploader
.UploadExistingFile(
657 kTestInitiateUploadResourceId
, local_path
, kTestMimeType
, options
,
658 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
659 google_apis::ProgressCallback());
660 base::RunLoop().RunUntilIdle();
662 EXPECT_EQ(HTTP_CONFLICT
, error
);
663 EXPECT_TRUE(upload_location
.is_empty());
666 TEST_F(DriveUploaderTest
, ResumeUploadFail
) {
667 base::FilePath local_path
;
669 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
670 temp_dir_
.path(), 2 * 1024 * 1024, &local_path
, &data
));
672 DriveApiErrorCode error
= HTTP_SUCCESS
;
673 GURL upload_location
;
674 scoped_ptr
<FileResource
> entry
;
676 MockDriveServiceNoConnectionAtResume mock_service
;
677 DriveUploader
uploader(&mock_service
,
678 base::MessageLoopProxy::current().get());
679 uploader
.UploadExistingFile(kTestInitiateUploadResourceId
,
682 DriveUploader::UploadExistingFileOptions(),
683 test_util::CreateCopyResultCallback(
684 &error
, &upload_location
, &entry
),
685 google_apis::ProgressCallback());
686 base::RunLoop().RunUntilIdle();
688 EXPECT_EQ(DRIVE_NO_CONNECTION
, error
);
689 EXPECT_EQ(GURL(kTestUploadExistingFileURL
), upload_location
);
692 TEST_F(DriveUploaderTest
, GetUploadStatusFail
) {
693 base::FilePath local_path
;
695 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
696 temp_dir_
.path(), 2 * 1024 * 1024, &local_path
, &data
));
698 DriveApiErrorCode error
= HTTP_SUCCESS
;
699 GURL upload_location
;
700 scoped_ptr
<FileResource
> entry
;
702 MockDriveServiceNoConnectionAtGetUploadStatus mock_service
;
703 DriveUploader
uploader(&mock_service
,
704 base::MessageLoopProxy::current().get());
705 uploader
.ResumeUploadFile(GURL(kTestUploadExistingFileURL
),
708 test_util::CreateCopyResultCallback(
709 &error
, &upload_location
, &entry
),
710 google_apis::ProgressCallback());
711 base::RunLoop().RunUntilIdle();
713 EXPECT_EQ(DRIVE_NO_CONNECTION
, error
);
714 EXPECT_TRUE(upload_location
.is_empty());
717 TEST_F(DriveUploaderTest
, NonExistingSourceFile
) {
718 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
719 GURL upload_location
;
720 scoped_ptr
<FileResource
> entry
;
722 DriveUploader
uploader(NULL
, // NULL, the service won't be used.
723 base::MessageLoopProxy::current().get());
724 uploader
.UploadExistingFile(
725 kTestInitiateUploadResourceId
,
726 temp_dir_
.path().AppendASCII("_this_path_should_not_exist_"),
728 DriveUploader::UploadExistingFileOptions(),
729 test_util::CreateCopyResultCallback(
730 &error
, &upload_location
, &entry
),
731 google_apis::ProgressCallback());
732 base::RunLoop().RunUntilIdle();
734 // Should return failure without doing any attempt to connect to the server.
735 EXPECT_EQ(HTTP_NOT_FOUND
, error
);
736 EXPECT_TRUE(upload_location
.is_empty());
739 TEST_F(DriveUploaderTest
, ResumeUpload
) {
740 base::FilePath local_path
;
742 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
743 temp_dir_
.path(), 1024 * 1024, &local_path
, &data
));
745 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
746 GURL upload_location
;
747 scoped_ptr
<FileResource
> entry
;
749 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
750 DriveUploader
uploader(&mock_service
,
751 base::MessageLoopProxy::current().get());
752 // Emulate the situation that the only first part is successfully uploaded,
753 // but not the latter half.
754 mock_service
.set_received_bytes(512 * 1024);
756 std::vector
<test_util::ProgressInfo
> upload_progress_values
;
757 uploader
.ResumeUploadFile(
758 GURL(kTestUploadExistingFileURL
),
761 test_util::CreateCopyResultCallback(
762 &error
, &upload_location
, &entry
),
763 base::Bind(&test_util::AppendProgressCallbackResult
,
764 &upload_progress_values
));
765 base::RunLoop().RunUntilIdle();
767 EXPECT_EQ(1, mock_service
.resume_upload_call_count());
768 EXPECT_EQ(1024 * 1024, mock_service
.received_bytes());
769 EXPECT_EQ(HTTP_SUCCESS
, error
);
770 EXPECT_TRUE(upload_location
.is_empty());
772 EXPECT_EQ(kTestDummyMd5
, entry
->md5_checksum());
773 ASSERT_EQ(1U, upload_progress_values
.size());
774 EXPECT_EQ(test_util::ProgressInfo(1024 * 1024, 1024 * 1024),
775 upload_progress_values
[0]);