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
, local_path
, kTestMimeType
,
438 UploadExistingFileOptions(),
439 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
440 base::Bind(&test_util::AppendProgressCallbackResult
,
441 &upload_progress_values
));
442 base::RunLoop().RunUntilIdle();
444 EXPECT_EQ(0, mock_service
.resume_upload_call_count());
445 EXPECT_EQ(1, mock_service
.multipart_upload_call_count());
446 EXPECT_EQ(0, mock_service
.received_bytes());
447 EXPECT_EQ(HTTP_SUCCESS
, error
);
448 EXPECT_TRUE(upload_location
.is_empty());
450 EXPECT_EQ(kTestDummyMd5
, entry
->md5_checksum());
451 ASSERT_EQ(1U, upload_progress_values
.size());
452 EXPECT_EQ(test_util::ProgressInfo(0, 0), upload_progress_values
[0]);
455 TEST_F(DriveUploaderTest
, UploadExisting512KB
) {
456 base::FilePath local_path
;
458 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
459 temp_dir_
.path(), 512 * 1024, &local_path
, &data
));
461 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
462 GURL upload_location
;
463 scoped_ptr
<FileResource
> entry
;
465 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
466 DriveUploader
uploader(&mock_service
,
467 base::MessageLoopProxy::current().get());
468 std::vector
<test_util::ProgressInfo
> upload_progress_values
;
469 uploader
.UploadExistingFile(
470 kTestInitiateUploadResourceId
, local_path
, kTestMimeType
,
471 UploadExistingFileOptions(),
472 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
473 base::Bind(&test_util::AppendProgressCallbackResult
,
474 &upload_progress_values
));
475 base::RunLoop().RunUntilIdle();
477 // 512KB upload should be uploaded as multipart body.
478 EXPECT_EQ(0, mock_service
.resume_upload_call_count());
479 EXPECT_EQ(1, mock_service
.multipart_upload_call_count());
480 EXPECT_EQ(512 * 1024, mock_service
.received_bytes());
481 EXPECT_EQ(HTTP_SUCCESS
, error
);
482 EXPECT_TRUE(upload_location
.is_empty());
484 EXPECT_EQ(kTestDummyMd5
, entry
->md5_checksum());
485 ASSERT_EQ(1U, upload_progress_values
.size());
486 EXPECT_EQ(test_util::ProgressInfo(512 * 1024, 512 * 1024),
487 upload_progress_values
[0]);
490 TEST_F(DriveUploaderTest
, UploadExisting2MB
) {
491 base::FilePath local_path
;
493 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
494 temp_dir_
.path(), 2 * 1024 * 1024, &local_path
, &data
));
496 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
497 GURL upload_location
;
498 scoped_ptr
<FileResource
> entry
;
500 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
501 DriveUploader
uploader(&mock_service
,
502 base::MessageLoopProxy::current().get());
503 std::vector
<test_util::ProgressInfo
> upload_progress_values
;
504 uploader
.UploadExistingFile(
505 kTestInitiateUploadResourceId
, local_path
, kTestMimeType
,
506 UploadExistingFileOptions(),
507 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
508 base::Bind(&test_util::AppendProgressCallbackResult
,
509 &upload_progress_values
));
510 base::RunLoop().RunUntilIdle();
512 // 2MB upload should not be split into multiple chunks.
513 EXPECT_EQ(1, mock_service
.resume_upload_call_count());
514 EXPECT_EQ(0, mock_service
.multipart_upload_call_count());
515 EXPECT_EQ(2 * 1024 * 1024, mock_service
.received_bytes());
516 EXPECT_EQ(HTTP_SUCCESS
, error
);
517 EXPECT_TRUE(upload_location
.is_empty());
519 EXPECT_EQ(kTestDummyMd5
, entry
->md5_checksum());
520 ASSERT_EQ(1U, upload_progress_values
.size());
521 EXPECT_EQ(test_util::ProgressInfo(2 * 1024 * 1024, 2 * 1024 * 1024),
522 upload_progress_values
[0]);
525 TEST_F(DriveUploaderTest
, InitiateUploadFail
) {
526 base::FilePath local_path
;
528 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
529 temp_dir_
.path(), 2 * 1024 * 1024, &local_path
, &data
));
531 DriveApiErrorCode error
= HTTP_SUCCESS
;
532 GURL upload_location
;
533 scoped_ptr
<FileResource
> entry
;
535 MockDriveServiceNoConnectionAtInitiate mock_service
;
536 DriveUploader
uploader(&mock_service
,
537 base::MessageLoopProxy::current().get());
538 uploader
.UploadExistingFile(
539 kTestInitiateUploadResourceId
, local_path
, kTestMimeType
,
540 UploadExistingFileOptions(),
541 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
542 google_apis::ProgressCallback());
543 base::RunLoop().RunUntilIdle();
545 EXPECT_EQ(DRIVE_NO_CONNECTION
, error
);
546 EXPECT_TRUE(upload_location
.is_empty());
550 TEST_F(DriveUploaderTest
, MultipartUploadFail
) {
551 base::FilePath local_path
;
553 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(temp_dir_
.path(), 512 * 1024,
554 &local_path
, &data
));
556 DriveApiErrorCode error
= HTTP_SUCCESS
;
557 GURL upload_location
;
558 scoped_ptr
<FileResource
> entry
;
560 MockDriveServiceNoConnectionAtInitiate mock_service
;
561 DriveUploader
uploader(&mock_service
,
562 base::MessageLoopProxy::current().get());
563 uploader
.UploadExistingFile(
564 kTestInitiateUploadResourceId
, local_path
, kTestMimeType
,
565 UploadExistingFileOptions(),
566 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
567 google_apis::ProgressCallback());
568 base::RunLoop().RunUntilIdle();
570 EXPECT_EQ(DRIVE_NO_CONNECTION
, error
);
571 EXPECT_TRUE(upload_location
.is_empty());
575 TEST_F(DriveUploaderTest
, InitiateUploadNoConflict
) {
576 base::FilePath local_path
;
578 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
579 temp_dir_
.path(), 512 * 1024, &local_path
, &data
));
581 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
582 GURL upload_location
;
583 scoped_ptr
<FileResource
> entry
;
585 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
586 DriveUploader
uploader(&mock_service
,
587 base::MessageLoopProxy::current().get());
588 UploadExistingFileOptions options
;
589 options
.etag
= kTestETag
;
590 uploader
.UploadExistingFile(kTestInitiateUploadResourceId
,
594 test_util::CreateCopyResultCallback(
595 &error
, &upload_location
, &entry
),
596 google_apis::ProgressCallback());
597 base::RunLoop().RunUntilIdle();
599 EXPECT_EQ(HTTP_SUCCESS
, error
);
600 EXPECT_TRUE(upload_location
.is_empty());
603 TEST_F(DriveUploaderTest
, MultipartUploadConflict
) {
604 base::FilePath local_path
;
606 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
607 temp_dir_
.path(), 512 * 1024, &local_path
, &data
));
608 const std::string
kDestinationETag("destination_etag");
610 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
611 GURL upload_location
;
612 scoped_ptr
<FileResource
> entry
;
614 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
615 DriveUploader
uploader(&mock_service
,
616 base::MessageLoopProxy::current().get());
617 UploadExistingFileOptions options
;
618 options
.etag
= kDestinationETag
;
619 uploader
.UploadExistingFile(kTestInitiateUploadResourceId
,
623 test_util::CreateCopyResultCallback(
624 &error
, &upload_location
, &entry
),
625 google_apis::ProgressCallback());
626 base::RunLoop().RunUntilIdle();
628 EXPECT_EQ(HTTP_CONFLICT
, error
);
629 EXPECT_TRUE(upload_location
.is_empty());
632 TEST_F(DriveUploaderTest
, InitiateUploadConflict
) {
633 base::FilePath local_path
;
635 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
636 temp_dir_
.path(), 2 * 1024 * 1024, &local_path
, &data
));
637 const std::string
kDestinationETag("destination_etag");
639 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
640 GURL upload_location
;
641 scoped_ptr
<FileResource
> entry
;
643 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
644 DriveUploader
uploader(&mock_service
,
645 base::MessageLoopProxy::current().get());
646 UploadExistingFileOptions options
;
647 options
.etag
= kDestinationETag
;
648 uploader
.UploadExistingFile(
649 kTestInitiateUploadResourceId
, local_path
, kTestMimeType
, options
,
650 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
651 google_apis::ProgressCallback());
652 base::RunLoop().RunUntilIdle();
654 EXPECT_EQ(HTTP_CONFLICT
, error
);
655 EXPECT_TRUE(upload_location
.is_empty());
658 TEST_F(DriveUploaderTest
, ResumeUploadFail
) {
659 base::FilePath local_path
;
661 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
662 temp_dir_
.path(), 2 * 1024 * 1024, &local_path
, &data
));
664 DriveApiErrorCode error
= HTTP_SUCCESS
;
665 GURL upload_location
;
666 scoped_ptr
<FileResource
> entry
;
668 MockDriveServiceNoConnectionAtResume mock_service
;
669 DriveUploader
uploader(&mock_service
,
670 base::MessageLoopProxy::current().get());
671 uploader
.UploadExistingFile(
672 kTestInitiateUploadResourceId
, local_path
, kTestMimeType
,
673 UploadExistingFileOptions(),
674 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
675 google_apis::ProgressCallback());
676 base::RunLoop().RunUntilIdle();
678 EXPECT_EQ(DRIVE_NO_CONNECTION
, error
);
679 EXPECT_EQ(GURL(kTestUploadExistingFileURL
), upload_location
);
682 TEST_F(DriveUploaderTest
, GetUploadStatusFail
) {
683 base::FilePath local_path
;
685 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
686 temp_dir_
.path(), 2 * 1024 * 1024, &local_path
, &data
));
688 DriveApiErrorCode error
= HTTP_SUCCESS
;
689 GURL upload_location
;
690 scoped_ptr
<FileResource
> entry
;
692 MockDriveServiceNoConnectionAtGetUploadStatus mock_service
;
693 DriveUploader
uploader(&mock_service
,
694 base::MessageLoopProxy::current().get());
695 uploader
.ResumeUploadFile(GURL(kTestUploadExistingFileURL
),
698 test_util::CreateCopyResultCallback(
699 &error
, &upload_location
, &entry
),
700 google_apis::ProgressCallback());
701 base::RunLoop().RunUntilIdle();
703 EXPECT_EQ(DRIVE_NO_CONNECTION
, error
);
704 EXPECT_TRUE(upload_location
.is_empty());
707 TEST_F(DriveUploaderTest
, NonExistingSourceFile
) {
708 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
709 GURL upload_location
;
710 scoped_ptr
<FileResource
> entry
;
712 DriveUploader
uploader(NULL
, // NULL, the service won't be used.
713 base::MessageLoopProxy::current().get());
714 uploader
.UploadExistingFile(
715 kTestInitiateUploadResourceId
,
716 temp_dir_
.path().AppendASCII("_this_path_should_not_exist_"),
717 kTestMimeType
, UploadExistingFileOptions(),
718 test_util::CreateCopyResultCallback(&error
, &upload_location
, &entry
),
719 google_apis::ProgressCallback());
720 base::RunLoop().RunUntilIdle();
722 // Should return failure without doing any attempt to connect to the server.
723 EXPECT_EQ(HTTP_NOT_FOUND
, error
);
724 EXPECT_TRUE(upload_location
.is_empty());
727 TEST_F(DriveUploaderTest
, ResumeUpload
) {
728 base::FilePath local_path
;
730 ASSERT_TRUE(test_util::CreateFileOfSpecifiedSize(
731 temp_dir_
.path(), 1024 * 1024, &local_path
, &data
));
733 DriveApiErrorCode error
= DRIVE_OTHER_ERROR
;
734 GURL upload_location
;
735 scoped_ptr
<FileResource
> entry
;
737 MockDriveServiceWithUploadExpectation
mock_service(local_path
, data
.size());
738 DriveUploader
uploader(&mock_service
,
739 base::MessageLoopProxy::current().get());
740 // Emulate the situation that the only first part is successfully uploaded,
741 // but not the latter half.
742 mock_service
.set_received_bytes(512 * 1024);
744 std::vector
<test_util::ProgressInfo
> upload_progress_values
;
745 uploader
.ResumeUploadFile(
746 GURL(kTestUploadExistingFileURL
),
749 test_util::CreateCopyResultCallback(
750 &error
, &upload_location
, &entry
),
751 base::Bind(&test_util::AppendProgressCallbackResult
,
752 &upload_progress_values
));
753 base::RunLoop().RunUntilIdle();
755 EXPECT_EQ(1, mock_service
.resume_upload_call_count());
756 EXPECT_EQ(1024 * 1024, mock_service
.received_bytes());
757 EXPECT_EQ(HTTP_SUCCESS
, error
);
758 EXPECT_TRUE(upload_location
.is_empty());
760 EXPECT_EQ(kTestDummyMd5
, entry
->md5_checksum());
761 ASSERT_EQ(1U, upload_progress_values
.size());
762 EXPECT_EQ(test_util::ProgressInfo(1024 * 1024, 1024 * 1024),
763 upload_progress_values
[0]);