Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(438)

Side by Side Diff: chrome/browser/google_apis/gdata_wapi_operations_unittest.cc

Issue 12246002: Implement GetUploadStatusOperation on GData WAPI. (Closed) Base URL: http://git.chromium.org/chromium/src.git@b148632_create_base_operation
Patch Set: Rebase Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/google_apis/gdata_wapi_operations.cc ('k') | chrome/browser/google_apis/gdata_wapi_service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698