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 <algorithm> | 5 #include <algorithm> |
6 #include <map> | 6 #include <map> |
7 | 7 |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 base::Unretained(this))); | 120 base::Unretained(this))); |
121 test_server_.RegisterRequestHandler( | 121 test_server_.RegisterRequestHandler( |
122 base::Bind(&GDataWapiOperationsTest::HandleCreateSessionRequest, | 122 base::Bind(&GDataWapiOperationsTest::HandleCreateSessionRequest, |
123 base::Unretained(this))); | 123 base::Unretained(this))); |
124 test_server_.RegisterRequestHandler( | 124 test_server_.RegisterRequestHandler( |
125 base::Bind(&GDataWapiOperationsTest::HandleUploadRequest, | 125 base::Bind(&GDataWapiOperationsTest::HandleUploadRequest, |
126 base::Unretained(this))); | 126 base::Unretained(this))); |
127 | 127 |
128 url_generator_.reset(new GDataWapiUrlGenerator( | 128 url_generator_.reset(new GDataWapiUrlGenerator( |
129 test_util::GetBaseUrlForTesting(test_server_.port()))); | 129 test_util::GetBaseUrlForTesting(test_server_.port()))); |
| 130 |
| 131 received_bytes_ = 0; |
| 132 content_length_ = 0; |
130 } | 133 } |
131 | 134 |
132 virtual void TearDown() OVERRIDE { | 135 virtual void TearDown() OVERRIDE { |
133 test_server_.ShutdownAndWaitUntilComplete(); | 136 test_server_.ShutdownAndWaitUntilComplete(); |
134 request_context_getter_ = NULL; | 137 request_context_getter_ = NULL; |
135 } | 138 } |
136 | 139 |
137 protected: | 140 protected: |
138 // Handles a request for fetching a resource feed. | 141 // Handles a request for fetching a resource feed. |
139 scoped_ptr<test_server::HttpResponse> HandleResourceFeedRequest( | 142 scoped_ptr<test_server::HttpResponse> HandleResourceFeedRequest( |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 http_request_ = request; | 219 http_request_ = request; |
217 | 220 |
218 const GURL absolute_url = test_server_.GetURL(request.relative_url); | 221 const GURL absolute_url = test_server_.GetURL(request.relative_url); |
219 if (StartsWithASCII(absolute_url.path(), | 222 if (StartsWithASCII(absolute_url.path(), |
220 "/feeds/upload/create-session/default/private/full", | 223 "/feeds/upload/create-session/default/private/full", |
221 true)) { // case sensitive | 224 true)) { // case sensitive |
222 // This is an initiating upload URL. | 225 // This is an initiating upload URL. |
223 scoped_ptr<test_server::HttpResponse> http_response( | 226 scoped_ptr<test_server::HttpResponse> http_response( |
224 new test_server::HttpResponse); | 227 new test_server::HttpResponse); |
225 | 228 |
| 229 // Check an ETag. |
226 std::map<std::string, std::string>::const_iterator found = | 230 std::map<std::string, std::string>::const_iterator found = |
227 request.headers.find("If-Match"); | 231 request.headers.find("If-Match"); |
228 if (found != request.headers.end() && | 232 if (found != request.headers.end() && |
229 found->second != "*" && | 233 found->second != "*" && |
230 found->second != kTestETag) { | 234 found->second != kTestETag) { |
231 http_response->set_code(test_server::PRECONDITION); | 235 http_response->set_code(test_server::PRECONDITION); |
232 return http_response.Pass(); | 236 return http_response.Pass(); |
233 } | 237 } |
234 | 238 |
| 239 // Check if the X-Upload-Content-Length is present. If yes, store the |
| 240 // length of the file. |
| 241 found = request.headers.find("X-Upload-Content-Length"); |
| 242 if (found == request.headers.end() || |
| 243 !base::StringToInt64(found->second, &content_length_)) { |
| 244 return scoped_ptr<test_server::HttpResponse>(); |
| 245 } |
| 246 received_bytes_ = 0; |
| 247 |
235 http_response->set_code(test_server::SUCCESS); | 248 http_response->set_code(test_server::SUCCESS); |
236 GURL upload_url; | 249 GURL upload_url; |
237 // POST is used for a new file, and PUT is used for an existing file. | 250 // POST is used for a new file, and PUT is used for an existing file. |
238 if (request.method == test_server::METHOD_POST) { | 251 if (request.method == test_server::METHOD_POST) { |
239 upload_url = test_server_.GetURL("/upload_new_file"); | 252 upload_url = test_server_.GetURL("/upload_new_file"); |
240 } else if (request.method == test_server::METHOD_PUT) { | 253 } else if (request.method == test_server::METHOD_PUT) { |
241 upload_url = test_server_.GetURL("/upload_existing_file"); | 254 upload_url = test_server_.GetURL("/upload_existing_file"); |
242 } else { | 255 } else { |
243 return scoped_ptr<test_server::HttpResponse>(); | 256 return scoped_ptr<test_server::HttpResponse>(); |
244 } | 257 } |
(...skipping 25 matching lines...) Expand all Loading... |
270 if (absolute_url.path() == "/upload_new_file") | 283 if (absolute_url.path() == "/upload_new_file") |
271 response->set_code(test_server::CREATED); | 284 response->set_code(test_server::CREATED); |
272 | 285 |
273 // Check if the Content-Range header is present. This must be present if | 286 // Check if the Content-Range header is present. This must be present if |
274 // the request body is not empty. | 287 // the request body is not empty. |
275 if (!request.content.empty()) { | 288 if (!request.content.empty()) { |
276 std::map<std::string, std::string>::const_iterator iter = | 289 std::map<std::string, std::string>::const_iterator iter = |
277 request.headers.find("Content-Range"); | 290 request.headers.find("Content-Range"); |
278 if (iter == request.headers.end()) | 291 if (iter == request.headers.end()) |
279 return scoped_ptr<test_server::HttpResponse>(); | 292 return scoped_ptr<test_server::HttpResponse>(); |
| 293 int64 length = 0; |
280 int64 start_position = 0; | 294 int64 start_position = 0; |
281 int64 end_position = 0; | 295 int64 end_position = 0; |
282 int64 length = 0; | |
283 if (!ParseContentRangeHeader(iter->second, | 296 if (!ParseContentRangeHeader(iter->second, |
284 &start_position, | 297 &start_position, |
285 &end_position, | 298 &end_position, |
286 &length)) { | 299 &length)) { |
287 return scoped_ptr<test_server::HttpResponse>(); | 300 return scoped_ptr<test_server::HttpResponse>(); |
288 } | 301 } |
| 302 EXPECT_EQ(start_position, received_bytes_); |
| 303 EXPECT_EQ(length, content_length_); |
| 304 // end_position is inclusive, but so +1 to change the range to byte size. |
| 305 received_bytes_ = end_position + 1; |
| 306 } |
289 | 307 |
290 // Add Range header to the response, based on the values of | 308 // Add Range header to the response, based on the values of |
291 // Content-Range header in the request. | 309 // Content-Range header in the request. |
| 310 // The header is annotated only when at least one byte is received. |
| 311 if (received_bytes_ > 0) { |
292 response->AddCustomHeader( | 312 response->AddCustomHeader( |
293 "Range", | 313 "Range", |
294 "bytes=" + | 314 "bytes=0-" + base::Int64ToString(received_bytes_ - 1)); |
295 base::Int64ToString(start_position) + "-" + | 315 } |
296 base::Int64ToString(end_position)); | |
297 | 316 |
298 // Change the code to RESUME_INCOMPLETE if upload is not complete. | 317 // Change the code to RESUME_INCOMPLETE if upload is not complete. |
299 if (end_position + 1 < length) | 318 if (received_bytes_ < content_length_) |
300 response->set_code(test_server::RESUME_INCOMPLETE); | 319 response->set_code(test_server::RESUME_INCOMPLETE); |
301 } | |
302 | 320 |
303 return response.Pass(); | 321 return response.Pass(); |
304 } | 322 } |
305 | 323 |
306 MessageLoopForUI message_loop_; | 324 MessageLoopForUI message_loop_; |
307 content::TestBrowserThread ui_thread_; | 325 content::TestBrowserThread ui_thread_; |
308 content::TestBrowserThread file_thread_; | 326 content::TestBrowserThread file_thread_; |
309 content::TestBrowserThread io_thread_; | 327 content::TestBrowserThread io_thread_; |
310 test_server::HttpServer test_server_; | 328 test_server::HttpServer test_server_; |
311 scoped_ptr<TestingProfile> profile_; | 329 scoped_ptr<TestingProfile> profile_; |
312 OperationRegistry operation_registry_; | 330 OperationRegistry operation_registry_; |
313 scoped_ptr<GDataWapiUrlGenerator> url_generator_; | 331 scoped_ptr<GDataWapiUrlGenerator> url_generator_; |
314 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; | 332 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; |
315 | 333 |
| 334 // These fields are used to keep the current upload state during a |
| 335 // test case. These values are updated by the request from |
| 336 // ResumeUploadOperation, and used to construct the response for |
| 337 // both ResumeUploadOperation and GetUploadStatusOperation, to emulate |
| 338 // the WAPI server. |
| 339 int64 received_bytes_; |
| 340 int64 content_length_; |
| 341 |
316 // The incoming HTTP request is saved so tests can verify the request | 342 // The incoming HTTP request is saved so tests can verify the request |
317 // parameters like HTTP method (ex. some operations should use DELETE | 343 // parameters like HTTP method (ex. some operations should use DELETE |
318 // instead of GET). | 344 // instead of GET). |
319 test_server::HttpRequest http_request_; | 345 test_server::HttpRequest http_request_; |
320 }; | 346 }; |
321 | 347 |
322 } // namespace | 348 } // namespace |
323 | 349 |
324 TEST_F(GDataWapiOperationsTest, GetResourceListOperation_DefaultFeed) { | 350 TEST_F(GDataWapiOperationsTest, GetResourceListOperation_DefaultFeed) { |
325 GDataErrorCode result_code = GDATA_OTHER_ERROR; | 351 GDataErrorCode result_code = GDATA_OTHER_ERROR; |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 | 881 |
856 // Check the response. | 882 // Check the response. |
857 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file | 883 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file |
858 // The start and end positions should be set to -1, if an upload is complete. | 884 // The start and end positions should be set to -1, if an upload is complete. |
859 EXPECT_EQ(-1, response.start_position_received); | 885 EXPECT_EQ(-1, response.start_position_received); |
860 EXPECT_EQ(-1, response.end_position_received); | 886 EXPECT_EQ(-1, response.end_position_received); |
861 } | 887 } |
862 | 888 |
863 // This test exercises InitiateUploadNewFileOperation and ResumeUploadOperation | 889 // This test exercises InitiateUploadNewFileOperation and ResumeUploadOperation |
864 // for a scenario of uploading a new *large* file, which requires multiple | 890 // for a scenario of uploading a new *large* file, which requires multiple |
865 // requests of ResumeUploadOperation. | 891 // requests of ResumeUploadOperation. GetUploadOperation is also tested in this |
| 892 // test case. |
866 TEST_F(GDataWapiOperationsTest, UploadNewLargeFile) { | 893 TEST_F(GDataWapiOperationsTest, UploadNewLargeFile) { |
867 const size_t kMaxNumBytes = 10; | 894 const size_t kMaxNumBytes = 10; |
868 // This is big enough to cause multiple requests of ResumeUploadOperation | 895 // This is big enough to cause multiple requests of ResumeUploadOperation |
869 // as we are going to send at most kMaxNumBytes at a time. | 896 // as we are going to send at most kMaxNumBytes at a time. |
870 const std::string kUploadContent(kMaxNumBytes + 1, 'a'); | 897 // So, sending "kMaxNumBytes * 2 + 1" bytes ensures three |
| 898 // ResumeUploadOperations, which are start, middle and last operations. |
| 899 const std::string kUploadContent(kMaxNumBytes * 2 + 1, 'a'); |
871 GDataErrorCode result_code = GDATA_OTHER_ERROR; | 900 GDataErrorCode result_code = GDATA_OTHER_ERROR; |
872 GURL upload_url; | 901 GURL upload_url; |
873 | 902 |
874 // 1) Get the upload URL for uploading a new file. | 903 // 1) Get the upload URL for uploading a new file. |
875 InitiateUploadNewFileOperation* initiate_operation = | 904 InitiateUploadNewFileOperation* initiate_operation = |
876 new InitiateUploadNewFileOperation( | 905 new InitiateUploadNewFileOperation( |
877 &operation_registry_, | 906 &operation_registry_, |
878 request_context_getter_.get(), | 907 request_context_getter_.get(), |
879 *url_generator_, | 908 *url_generator_, |
880 base::Bind(&CopyResultFromInitiateUploadCallbackAndQuit, | 909 base::Bind(&CopyResultFromInitiateUploadCallbackAndQuit, |
(...skipping 24 matching lines...) Expand all Loading... |
905 http_request_.headers["X-Upload-Content-Length"]); | 934 http_request_.headers["X-Upload-Content-Length"]); |
906 | 935 |
907 EXPECT_TRUE(http_request_.has_content); | 936 EXPECT_TRUE(http_request_.has_content); |
908 EXPECT_EQ("<?xml version=\"1.0\"?>\n" | 937 EXPECT_EQ("<?xml version=\"1.0\"?>\n" |
909 "<entry xmlns=\"http://www.w3.org/2005/Atom\" " | 938 "<entry xmlns=\"http://www.w3.org/2005/Atom\" " |
910 "xmlns:docs=\"http://schemas.google.com/docs/2007\">\n" | 939 "xmlns:docs=\"http://schemas.google.com/docs/2007\">\n" |
911 " <title>New file</title>\n" | 940 " <title>New file</title>\n" |
912 "</entry>\n", | 941 "</entry>\n", |
913 http_request_.content); | 942 http_request_.content); |
914 | 943 |
915 // 2) Upload the content to the upload URL with multiple requests. | 944 // 2) Before sending any data, check the current status. |
| 945 // This is an edge case test for GetUploadStatusOperation |
| 946 // (UploadRangeOperationBase). |
| 947 { |
| 948 UploadRangeResponse response; |
| 949 scoped_ptr<ResourceEntry> new_entry; |
| 950 |
| 951 // Check the response by GetUploadStatusOperation. |
| 952 GetUploadStatusOperation* get_upload_status_operation = |
| 953 new GetUploadStatusOperation( |
| 954 &operation_registry_, |
| 955 request_context_getter_.get(), |
| 956 base::Bind(&CopyResultFromUploadRangeCallbackAndQuit, |
| 957 &response, |
| 958 &new_entry), |
| 959 UPLOAD_NEW_FILE, |
| 960 base::FilePath::FromUTF8Unsafe("drive/newfile.txt"), |
| 961 upload_url, |
| 962 kUploadContent.size()); |
| 963 get_upload_status_operation->Start( |
| 964 kTestGDataAuthToken, kTestUserAgent, |
| 965 base::Bind(&test_util::DoNothingForReAuthenticateCallback)); |
| 966 MessageLoop::current()->Run(); |
| 967 |
| 968 // METHOD_PUT should be used to upload data. |
| 969 EXPECT_EQ(test_server::METHOD_PUT, http_request_.method); |
| 970 // Request should go to the upload URL. |
| 971 EXPECT_EQ(upload_url.path(), http_request_.relative_url); |
| 972 // Content-Range header should be added. |
| 973 EXPECT_EQ("bytes */" + base::Int64ToString(kUploadContent.size()), |
| 974 http_request_.headers["Content-Range"]); |
| 975 EXPECT_TRUE(http_request_.has_content); |
| 976 EXPECT_TRUE(http_request_.content.empty()); |
| 977 |
| 978 // Check the response. |
| 979 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); |
| 980 EXPECT_EQ(0, response.start_position_received); |
| 981 EXPECT_EQ(0, response.end_position_received); |
| 982 } |
| 983 |
| 984 // 3) Upload the content to the upload URL with multiple requests. |
916 size_t num_bytes_consumed = 0; | 985 size_t num_bytes_consumed = 0; |
917 for (size_t start_position = 0; start_position < kUploadContent.size(); | 986 for (size_t start_position = 0; start_position < kUploadContent.size(); |
918 start_position += kMaxNumBytes) { | 987 start_position += kMaxNumBytes) { |
919 SCOPED_TRACE(testing::Message("start_position: ") << start_position); | 988 SCOPED_TRACE(testing::Message("start_position: ") << start_position); |
920 | 989 |
921 // The payload is at most kMaxNumBytes. | 990 // The payload is at most kMaxNumBytes. |
922 const size_t remaining_size = kUploadContent.size() - start_position; | 991 const size_t remaining_size = kUploadContent.size() - start_position; |
923 const std::string payload = kUploadContent.substr( | 992 const std::string payload = kUploadContent.substr( |
924 start_position, std::min(kMaxNumBytes, remaining_size)); | 993 start_position, std::min(kMaxNumBytes, remaining_size)); |
925 num_bytes_consumed += payload.size(); | 994 num_bytes_consumed += payload.size(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
967 EXPECT_TRUE(http_request_.has_content); | 1036 EXPECT_TRUE(http_request_.has_content); |
968 EXPECT_EQ(payload, http_request_.content); | 1037 EXPECT_EQ(payload, http_request_.content); |
969 | 1038 |
970 // Check the response. | 1039 // Check the response. |
971 if (payload.size() == remaining_size) { | 1040 if (payload.size() == remaining_size) { |
972 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file. | 1041 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file. |
973 // The start and end positions should be set to -1, if an upload is | 1042 // The start and end positions should be set to -1, if an upload is |
974 // complete. | 1043 // complete. |
975 EXPECT_EQ(-1, response.start_position_received); | 1044 EXPECT_EQ(-1, response.start_position_received); |
976 EXPECT_EQ(-1, response.end_position_received); | 1045 EXPECT_EQ(-1, response.end_position_received); |
977 } else { | 1046 // The upload process is completed, so exit from the loop. |
978 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); | 1047 break; |
979 EXPECT_EQ(static_cast<int64>(start_position), | |
980 response.start_position_received); | |
981 EXPECT_EQ(static_cast<int64>(end_position), | |
982 response.end_position_received); | |
983 } | 1048 } |
| 1049 |
| 1050 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); |
| 1051 EXPECT_EQ(0, response.start_position_received); |
| 1052 EXPECT_EQ(static_cast<int64>(end_position), |
| 1053 response.end_position_received); |
| 1054 |
| 1055 // Check the response by GetUploadStatusOperation. |
| 1056 GetUploadStatusOperation* get_upload_status_operation = |
| 1057 new GetUploadStatusOperation( |
| 1058 &operation_registry_, |
| 1059 request_context_getter_.get(), |
| 1060 base::Bind(&CopyResultFromUploadRangeCallbackAndQuit, |
| 1061 &response, |
| 1062 &new_entry), |
| 1063 UPLOAD_NEW_FILE, |
| 1064 base::FilePath::FromUTF8Unsafe("drive/newfile.txt"), |
| 1065 upload_url, |
| 1066 kUploadContent.size()); |
| 1067 get_upload_status_operation->Start( |
| 1068 kTestGDataAuthToken, kTestUserAgent, |
| 1069 base::Bind(&test_util::DoNothingForReAuthenticateCallback)); |
| 1070 MessageLoop::current()->Run(); |
| 1071 |
| 1072 // METHOD_PUT should be used to upload data. |
| 1073 EXPECT_EQ(test_server::METHOD_PUT, http_request_.method); |
| 1074 // Request should go to the upload URL. |
| 1075 EXPECT_EQ(upload_url.path(), http_request_.relative_url); |
| 1076 // Content-Range header should be added. |
| 1077 EXPECT_EQ("bytes */" + base::Int64ToString(kUploadContent.size()), |
| 1078 http_request_.headers["Content-Range"]); |
| 1079 EXPECT_TRUE(http_request_.has_content); |
| 1080 EXPECT_TRUE(http_request_.content.empty()); |
| 1081 |
| 1082 // Check the response. |
| 1083 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); |
| 1084 EXPECT_EQ(0, response.start_position_received); |
| 1085 EXPECT_EQ(static_cast<int64>(end_position), |
| 1086 response.end_position_received); |
984 } | 1087 } |
985 | 1088 |
986 EXPECT_EQ(kUploadContent.size(), num_bytes_consumed); | 1089 EXPECT_EQ(kUploadContent.size(), num_bytes_consumed); |
987 } | 1090 } |
988 | 1091 |
989 // This test exercises InitiateUploadNewFileOperation and ResumeUploadOperation | 1092 // This test exercises InitiateUploadNewFileOperation and ResumeUploadOperation |
990 // for a scenario of uploading a new *empty* file. | 1093 // for a scenario of uploading a new *empty* file. |
991 // | 1094 // |
992 // The test is almost identical to UploadNewFile. The only difference is the | 1095 // The test is almost identical to UploadNewFile. The only difference is the |
993 // expectation for the Content-Range header. | 1096 // expectation for the Content-Range header. |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1314 EXPECT_EQ(base::Int64ToString(kUploadContent.size()), | 1417 EXPECT_EQ(base::Int64ToString(kUploadContent.size()), |
1315 http_request_.headers["X-Upload-Content-Length"]); | 1418 http_request_.headers["X-Upload-Content-Length"]); |
1316 // For updating an existing file, an empty body should be attached (PUT | 1419 // For updating an existing file, an empty body should be attached (PUT |
1317 // requires a body) | 1420 // requires a body) |
1318 EXPECT_TRUE(http_request_.has_content); | 1421 EXPECT_TRUE(http_request_.has_content); |
1319 EXPECT_EQ("", http_request_.content); | 1422 EXPECT_EQ("", http_request_.content); |
1320 EXPECT_EQ(kWrongETag, http_request_.headers["If-Match"]); | 1423 EXPECT_EQ(kWrongETag, http_request_.headers["If-Match"]); |
1321 } | 1424 } |
1322 | 1425 |
1323 } // namespace google_apis | 1426 } // namespace google_apis |
OLD | NEW |