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 |