| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/google_apis/drive_uploader.h" | 5 #include "chrome/browser/google_apis/drive_uploader.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstdlib> | 8 #include <cstdlib> |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 // Mock DriveService that verifies if the uploaded content matches the preset | 51 // Mock DriveService that verifies if the uploaded content matches the preset |
| 52 // expectation. | 52 // expectation. |
| 53 class MockDriveServiceWithUploadExpectation : public DummyDriveService { | 53 class MockDriveServiceWithUploadExpectation : public DummyDriveService { |
| 54 public: | 54 public: |
| 55 // Sets up an expected upload content. InitiateUpload and ResumeUpload will | 55 // Sets up an expected upload content. InitiateUpload and ResumeUpload will |
| 56 // verify that the specified data is correctly uploaded. | 56 // verify that the specified data is correctly uploaded. |
| 57 explicit MockDriveServiceWithUploadExpectation( | 57 explicit MockDriveServiceWithUploadExpectation( |
| 58 const std::string& expected_upload_content) | 58 const std::string& expected_upload_content) |
| 59 : expected_upload_content_(expected_upload_content), | 59 : expected_upload_content_(expected_upload_content), |
| 60 received_bytes_(0), | 60 received_bytes_(0), |
| 61 resume_upload_call_count_(0) {} | 61 resume_upload_call_count_(0), |
| 62 get_upload_status_call_count_(0), |
| 63 resume_upload_failure_point_(-1) {} |
| 62 | 64 |
| 63 int64 received_bytes() const { return received_bytes_; } | 65 int64 received_bytes() const { return received_bytes_; } |
| 64 | 66 |
| 65 int64 resume_upload_call_count() const { return resume_upload_call_count_; } | 67 int64 resume_upload_call_count() const { return resume_upload_call_count_; } |
| 66 | 68 |
| 69 int64 get_upload_status_call_count() const { |
| 70 return get_upload_status_call_count_; |
| 71 } |
| 72 |
| 73 void set_resume_upload_failure_point(int64 resume_upload_failure_point) { |
| 74 resume_upload_failure_point_ = resume_upload_failure_point; |
| 75 } |
| 76 |
| 67 private: | 77 private: |
| 68 // DriveServiceInterface overrides. | 78 // DriveServiceInterface overrides. |
| 69 // Handles a request for obtaining an upload location URL. | 79 // Handles a request for obtaining an upload location URL. |
| 70 virtual void InitiateUpload(const InitiateUploadParams& params, | 80 virtual void InitiateUpload(const InitiateUploadParams& params, |
| 71 const InitiateUploadCallback& callback) OVERRIDE { | 81 const InitiateUploadCallback& callback) OVERRIDE { |
| 72 const int64 expected_size = expected_upload_content_.size(); | 82 const int64 expected_size = expected_upload_content_.size(); |
| 73 | 83 |
| 74 // Verify that the expected parameters are passed. | 84 // Verify that the expected parameters are passed. |
| 75 if (params.upload_mode == UPLOAD_NEW_FILE) | 85 if (params.upload_mode == UPLOAD_NEW_FILE) |
| 76 EXPECT_EQ(kTestDocumentTitle, params.title); | 86 EXPECT_EQ(kTestDocumentTitle, params.title); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 | 125 |
| 116 // The upload URL returned by InitiateUpload() must be used. | 126 // The upload URL returned by InitiateUpload() must be used. |
| 117 EXPECT_EQ(GURL(kTestUploadURL), params.upload_location); | 127 EXPECT_EQ(GURL(kTestUploadURL), params.upload_location); |
| 118 | 128 |
| 119 // Other parameters should be the exact values passed to DriveUploader. | 129 // Other parameters should be the exact values passed to DriveUploader. |
| 120 EXPECT_EQ(expected_size, params.content_length); | 130 EXPECT_EQ(expected_size, params.content_length); |
| 121 EXPECT_EQ(kTestMimeType, params.content_type); | 131 EXPECT_EQ(kTestMimeType, params.content_type); |
| 122 | 132 |
| 123 // Update the internal status of the current upload session. | 133 // Update the internal status of the current upload session. |
| 124 resume_upload_call_count_++; | 134 resume_upload_call_count_++; |
| 135 if (resume_upload_call_count_ == resume_upload_failure_point_) { |
| 136 // Emulate the server error. |
| 137 // ResumeUpload is an asynchronous function, so don't callback directly. |
| 138 scoped_ptr<ResourceEntry> entry; |
| 139 MessageLoop::current()->PostTask( |
| 140 FROM_HERE, |
| 141 base::Bind(callback, |
| 142 UploadRangeResponse(HTTP_SERVICE_UNAVAILABLE, 0, 0), |
| 143 base::Passed(&entry))); |
| 144 return; |
| 145 } |
| 125 received_bytes_ = params.end_position; | 146 received_bytes_ = params.end_position; |
| 126 | 147 |
| 127 // Callback with response. | 148 // Callback with response. |
| 128 UploadRangeResponse response; | 149 UploadRangeResponse response; |
| 129 scoped_ptr<ResourceEntry> entry; | 150 scoped_ptr<ResourceEntry> entry; |
| 130 if (received_bytes_ == params.content_length) { | 151 if (received_bytes_ == params.content_length) { |
| 131 response = UploadRangeResponse( | 152 response = UploadRangeResponse( |
| 132 params.upload_mode == UPLOAD_NEW_FILE ? HTTP_CREATED : HTTP_SUCCESS, | 153 params.upload_mode == UPLOAD_NEW_FILE ? HTTP_CREATED : HTTP_SUCCESS, |
| 133 -1, -1); | 154 -1, -1); |
| 134 | 155 |
| 135 base::DictionaryValue dict; | 156 base::DictionaryValue dict; |
| 136 dict.Set("id.$t", new base::StringValue(kTestDummyId)); | 157 dict.Set("id.$t", new base::StringValue(kTestDummyId)); |
| 137 entry = ResourceEntry::CreateFrom(dict); | 158 entry = ResourceEntry::CreateFrom(dict); |
| 138 } else { | 159 } else { |
| 139 response = UploadRangeResponse(HTTP_RESUME_INCOMPLETE, 0, | 160 response = UploadRangeResponse(HTTP_RESUME_INCOMPLETE, 0, |
| 140 params.end_position); | 161 params.end_position); |
| 141 } | 162 } |
| 142 // ResumeUpload is an asynchronous function, so don't callback directly. | 163 // ResumeUpload is an asynchronous function, so don't callback directly. |
| 143 MessageLoop::current()->PostTask(FROM_HERE, | 164 MessageLoop::current()->PostTask(FROM_HERE, |
| 144 base::Bind(callback, response, base::Passed(&entry))); | 165 base::Bind(callback, response, base::Passed(&entry))); |
| 145 } | 166 } |
| 146 | 167 |
| 168 // Handles a request for uploading a chunk of bytes. |
| 169 virtual void GetUploadStatus( |
| 170 UploadMode upload_mode, |
| 171 const FilePath& drive_file_path, |
| 172 const GURL& upload_url, |
| 173 int64 content_length, |
| 174 const UploadRangeCallback& callback) OVERRIDE { |
| 175 EXPECT_EQ(GURL(kTestUploadURL), upload_url); |
| 176 const int64 expected_upload_content_size = expected_upload_content_.size(); |
| 177 EXPECT_EQ(expected_upload_content_size, content_length); |
| 178 |
| 179 // Update the internal status of the current upload session. |
| 180 get_upload_status_call_count_++; |
| 181 |
| 182 // Callback with response. |
| 183 UploadRangeResponse response; |
| 184 scoped_ptr<ResourceEntry> entry; |
| 185 if (received_bytes_ == content_length) { |
| 186 response = UploadRangeResponse( |
| 187 upload_mode == UPLOAD_NEW_FILE ? HTTP_CREATED : HTTP_SUCCESS, |
| 188 -1, -1); |
| 189 |
| 190 base::DictionaryValue dict; |
| 191 dict.Set("id.$t", new base::StringValue(kTestDummyId)); |
| 192 entry = ResourceEntry::CreateFrom(dict); |
| 193 } else { |
| 194 response = |
| 195 UploadRangeResponse(HTTP_RESUME_INCOMPLETE, 0, received_bytes_); |
| 196 } |
| 197 // GetUploadStatus is an asynchronous function, so don't callback directly. |
| 198 MessageLoop::current()->PostTask(FROM_HERE, |
| 199 base::Bind(callback, response, base::Passed(&entry))); |
| 200 } |
| 201 |
| 147 std::string expected_upload_content_; | 202 std::string expected_upload_content_; |
| 148 int64 received_bytes_; | 203 int64 received_bytes_; |
| 149 int64 resume_upload_call_count_; | 204 int64 resume_upload_call_count_; |
| 205 int64 get_upload_status_call_count_; |
| 206 |
| 207 // When the resume_upload_call_count is equal to this value, |
| 208 // this mock server will return 503 SERVICE_UNAVAILABLE to test the |
| 209 // failure case. To disable this function, set the value to -1 so that |
| 210 // the resume_upload_call_count_ won't be equal to this in real use cases. |
| 211 int64 resume_upload_failure_point_; |
| 150 }; | 212 }; |
| 151 | 213 |
| 152 // Mock DriveService that returns a failure at InitiateUpload(). | 214 // Mock DriveService that returns a failure at InitiateUpload(). |
| 153 class MockDriveServiceNoConnectionAtInitiate : public DummyDriveService { | 215 class MockDriveServiceNoConnectionAtInitiate : public DummyDriveService { |
| 154 // Returns error. | 216 // Returns error. |
| 155 virtual void InitiateUpload(const InitiateUploadParams& params, | 217 virtual void InitiateUpload(const InitiateUploadParams& params, |
| 156 const InitiateUploadCallback& callback) OVERRIDE { | 218 const InitiateUploadCallback& callback) OVERRIDE { |
| 157 MessageLoop::current()->PostTask(FROM_HERE, | 219 MessageLoop::current()->PostTask(FROM_HERE, |
| 158 base::Bind(callback, GDATA_NO_CONNECTION, GURL())); | 220 base::Bind(callback, GDATA_NO_CONNECTION, GURL())); |
| 159 } | 221 } |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 // The file should be split into 3 chunks (1234 = 512 + 512 + 210). | 399 // The file should be split into 3 chunks (1234 = 512 + 512 + 210). |
| 338 EXPECT_EQ(3, mock_service.resume_upload_call_count()); | 400 EXPECT_EQ(3, mock_service.resume_upload_call_count()); |
| 339 EXPECT_EQ(1234 * 1024, mock_service.received_bytes()); | 401 EXPECT_EQ(1234 * 1024, mock_service.received_bytes()); |
| 340 EXPECT_EQ(DRIVE_UPLOAD_OK, out.error); | 402 EXPECT_EQ(DRIVE_UPLOAD_OK, out.error); |
| 341 EXPECT_EQ(FilePath::FromUTF8Unsafe(kTestDrivePath), out.drive_path); | 403 EXPECT_EQ(FilePath::FromUTF8Unsafe(kTestDrivePath), out.drive_path); |
| 342 EXPECT_EQ(local_path, out.file_path); | 404 EXPECT_EQ(local_path, out.file_path); |
| 343 ASSERT_TRUE(out.resource_entry); | 405 ASSERT_TRUE(out.resource_entry); |
| 344 EXPECT_EQ(kTestDummyId, out.resource_entry->id()); | 406 EXPECT_EQ(kTestDummyId, out.resource_entry->id()); |
| 345 } | 407 } |
| 346 | 408 |
| 409 TEST_F(DriveUploaderTest, UploadNew1234KBWithRetry) { |
| 410 FilePath local_path; |
| 411 std::string data; |
| 412 ASSERT_TRUE(CreateFileOfSpecifiedSize(temp_dir_.path(), 1234 * 1024, |
| 413 &local_path, &data)); |
| 414 UploadCompletionCallbackResult out; |
| 415 |
| 416 MockDriveServiceWithUploadExpectation mock_service(data); |
| 417 // Emulate the server failure when ResumeUpload is invoked twice. |
| 418 mock_service.set_resume_upload_failure_point(2); |
| 419 DriveUploader uploader(&mock_service); |
| 420 uploader.UploadNewFile( |
| 421 GURL(kTestInitialUploadURL), |
| 422 FilePath::FromUTF8Unsafe(kTestDrivePath), |
| 423 local_path, |
| 424 kTestDocumentTitle, |
| 425 kTestMimeType, |
| 426 base::Bind(&CopyResultsFromUploadCompletionCallbackAndQuit, &out)); |
| 427 message_loop_.Run(); |
| 428 |
| 429 // The file should be split into 3 chunks (1234 = 512 + 512 + 210) + 1 retry. |
| 430 EXPECT_EQ(4, mock_service.resume_upload_call_count()); |
| 431 EXPECT_EQ(1, mock_service.get_upload_status_call_count()); |
| 432 EXPECT_EQ(1234 * 1024, mock_service.received_bytes()); |
| 433 EXPECT_EQ(DRIVE_UPLOAD_OK, out.error); |
| 434 EXPECT_EQ(FilePath::FromUTF8Unsafe(kTestDrivePath), out.drive_path); |
| 435 EXPECT_EQ(local_path, out.file_path); |
| 436 ASSERT_TRUE(out.resource_entry); |
| 437 EXPECT_EQ(kTestDummyId, out.resource_entry->id()); |
| 438 } |
| 439 |
| 347 TEST_F(DriveUploaderTest, InitiateUploadFail) { | 440 TEST_F(DriveUploaderTest, InitiateUploadFail) { |
| 348 FilePath local_path; | 441 FilePath local_path; |
| 349 std::string data; | 442 std::string data; |
| 350 ASSERT_TRUE(CreateFileOfSpecifiedSize(temp_dir_.path(), 512 * 1024, | 443 ASSERT_TRUE(CreateFileOfSpecifiedSize(temp_dir_.path(), 512 * 1024, |
| 351 &local_path, &data)); | 444 &local_path, &data)); |
| 352 | 445 |
| 353 UploadCompletionCallbackResult out; | 446 UploadCompletionCallbackResult out; |
| 354 | 447 |
| 355 MockDriveServiceNoConnectionAtInitiate mock_service; | 448 MockDriveServiceNoConnectionAtInitiate mock_service; |
| 356 DriveUploader uploader(&mock_service); | 449 DriveUploader uploader(&mock_service); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 kTestMimeType, | 534 kTestMimeType, |
| 442 "", // etag | 535 "", // etag |
| 443 base::Bind(&CopyResultsFromUploadCompletionCallbackAndQuit, &out)); | 536 base::Bind(&CopyResultsFromUploadCompletionCallbackAndQuit, &out)); |
| 444 message_loop_.Run(); | 537 message_loop_.Run(); |
| 445 | 538 |
| 446 // Should return failure without doing any attempt to connect to the server. | 539 // Should return failure without doing any attempt to connect to the server. |
| 447 EXPECT_EQ(DRIVE_UPLOAD_ERROR_NOT_FOUND, out.error); | 540 EXPECT_EQ(DRIVE_UPLOAD_ERROR_NOT_FOUND, out.error); |
| 448 } | 541 } |
| 449 | 542 |
| 450 } // namespace google_apis | 543 } // namespace google_apis |
| OLD | NEW |