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

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: Fix mock server's behavior, as well as empty Range header handling. 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_path.h" 9 #include "base/file_path.h"
10 #include "base/file_util.h" 10 #include "base/file_util.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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 const GURL absolute_url = test_server_.GetURL(request.relative_url); 221 const GURL absolute_url = test_server_.GetURL(request.relative_url);
219 if (absolute_url.path() == 222 if (absolute_url.path() ==
220 // This is an upload URL of the root directory. 223 // This is an upload URL of the root directory.
221 "/feeds/upload/create-session/default/private/full" || 224 "/feeds/upload/create-session/default/private/full" ||
222 absolute_url.path() == 225 absolute_url.path() ==
223 // This is an upload URL of an existing file. 226 // This is an upload URL of an existing file.
224 "/feeds/upload/create-session/default/private/full/file:foo") { 227 "/feeds/upload/create-session/default/private/full/file:foo") {
225 scoped_ptr<test_server::HttpResponse> http_response( 228 scoped_ptr<test_server::HttpResponse> http_response(
226 new test_server::HttpResponse); 229 new test_server::HttpResponse);
227 230
231 // Check an ETag.
228 std::map<std::string, std::string>::const_iterator found = 232 std::map<std::string, std::string>::const_iterator found =
229 request.headers.find("If-Match"); 233 request.headers.find("If-Match");
230 if (found != request.headers.end() && 234 if (found != request.headers.end() &&
231 found->second != "*" && 235 found->second != "*" &&
232 found->second != kTestETag) { 236 found->second != kTestETag) {
233 http_response->set_code(test_server::PRECONDITION); 237 http_response->set_code(test_server::PRECONDITION);
234 return http_response.Pass(); 238 return http_response.Pass();
235 } 239 }
236 240
241 // Check if the X-Upload-Content-Length is present. If yes, store the
242 // length of the file.
243 found = request.headers.find("X-Upload-Content-Length");
244 if (found == request.headers.end() ||
245 !base::StringToInt64(found->second, &content_length_)) {
246 return scoped_ptr<test_server::HttpResponse>();
247 }
248 received_bytes_ = 0;
249
237 http_response->set_code(test_server::SUCCESS); 250 http_response->set_code(test_server::SUCCESS);
238 GURL upload_url; 251 GURL upload_url;
239 // POST is used for a new file, and PUT is used for an existing file. 252 // POST is used for a new file, and PUT is used for an existing file.
240 if (request.method == test_server::METHOD_POST) { 253 if (request.method == test_server::METHOD_POST) {
241 upload_url = test_server_.GetURL("/upload_new_file"); 254 upload_url = test_server_.GetURL("/upload_new_file");
242 } else if (request.method == test_server::METHOD_PUT) { 255 } else if (request.method == test_server::METHOD_PUT) {
243 upload_url = test_server_.GetURL("/upload_existing_file"); 256 upload_url = test_server_.GetURL("/upload_existing_file");
244 } else { 257 } else {
245 return scoped_ptr<test_server::HttpResponse>(); 258 return scoped_ptr<test_server::HttpResponse>();
246 } 259 }
(...skipping 25 matching lines...) Expand all
272 if (absolute_url.path() == "/upload_new_file") 285 if (absolute_url.path() == "/upload_new_file")
273 response->set_code(test_server::CREATED); 286 response->set_code(test_server::CREATED);
274 287
275 // Check if the Content-Range header is present. This must be present if 288 // Check if the Content-Range header is present. This must be present if
276 // the request body is not empty. 289 // the request body is not empty.
277 if (!request.content.empty()) { 290 if (!request.content.empty()) {
278 std::map<std::string, std::string>::const_iterator iter = 291 std::map<std::string, std::string>::const_iterator iter =
279 request.headers.find("Content-Range"); 292 request.headers.find("Content-Range");
280 if (iter == request.headers.end()) 293 if (iter == request.headers.end())
281 return scoped_ptr<test_server::HttpResponse>(); 294 return scoped_ptr<test_server::HttpResponse>();
295 int64 length = 0;
282 int64 start_position = 0; 296 int64 start_position = 0;
283 int64 end_position = 0; 297 int64 end_position = 0;
284 int64 length = 0;
285 if (!ParseContentRangeHeader(iter->second, 298 if (!ParseContentRangeHeader(iter->second,
286 &start_position, 299 &start_position,
287 &end_position, 300 &end_position,
288 &length)) { 301 &length)) {
289 return scoped_ptr<test_server::HttpResponse>(); 302 return scoped_ptr<test_server::HttpResponse>();
290 } 303 }
304 EXPECT_EQ(start_position, received_bytes_);
305 EXPECT_EQ(length, content_length_);
306 // end_position is inclusive, but so +1 to change the range to byte size.
307 received_bytes_ = end_position + 1;
308 }
291 309
292 // Add Range header to the response, based on the values of 310 // Add Range header to the response, based on the values of
293 // Content-Range header in the request. 311 // Content-Range header in the request.
312 // The header is annotated only when at least one byte is received.
313 if (received_bytes_ > 0) {
294 response->AddCustomHeader( 314 response->AddCustomHeader(
295 "Range", 315 "Range",
296 "bytes=" + 316 "bytes=0-" + base::Int64ToString(received_bytes_ - 1));
kinaba 2013/02/08 10:19:43 Is 0- the expected response when we have non-empty
hidehiko 2013/02/08 11:53:10 The actual server returns 0-end if there is (one o
297 base::Int64ToString(start_position) + "-" + 317 }
298 base::Int64ToString(end_position));
299 318
300 // Change the code to RESUME_INCOMPLETE if upload is not complete. 319 // Change the code to RESUME_INCOMPLETE if upload is not complete.
301 if (end_position + 1 < length) 320 if (received_bytes_ < content_length_)
302 response->set_code(test_server::RESUME_INCOMPLETE); 321 response->set_code(test_server::RESUME_INCOMPLETE);
303 }
304 322
305 return response.Pass(); 323 return response.Pass();
306 } 324 }
307 325
308 MessageLoopForUI message_loop_; 326 MessageLoopForUI message_loop_;
309 content::TestBrowserThread ui_thread_; 327 content::TestBrowserThread ui_thread_;
310 content::TestBrowserThread file_thread_; 328 content::TestBrowserThread file_thread_;
311 content::TestBrowserThread io_thread_; 329 content::TestBrowserThread io_thread_;
312 test_server::HttpServer test_server_; 330 test_server::HttpServer test_server_;
313 scoped_ptr<TestingProfile> profile_; 331 scoped_ptr<TestingProfile> profile_;
314 OperationRegistry operation_registry_; 332 OperationRegistry operation_registry_;
315 scoped_ptr<GDataWapiUrlGenerator> url_generator_; 333 scoped_ptr<GDataWapiUrlGenerator> url_generator_;
316 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; 334 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
317 335
336 // These fields are used to keep the current upload state during a
337 // test case. These values are updated by the request from
338 // ResumeUploadOperation, and used to construct the response for
339 // both ResumeUploadOperation and GetUploadStatusOperation, to emulate
340 // the WAPI server.
341 int64 received_bytes_;
342 int64 content_length_;
343
318 // The incoming HTTP request is saved so tests can verify the request 344 // The incoming HTTP request is saved so tests can verify the request
319 // parameters like HTTP method (ex. some operations should use DELETE 345 // parameters like HTTP method (ex. some operations should use DELETE
320 // instead of GET). 346 // instead of GET).
321 test_server::HttpRequest http_request_; 347 test_server::HttpRequest http_request_;
322 }; 348 };
323 349
324 } // namespace 350 } // namespace
325 351
326 TEST_F(GDataWapiOperationsTest, GetResourceListOperation_DefaultFeed) { 352 TEST_F(GDataWapiOperationsTest, GetResourceListOperation_DefaultFeed) {
327 GDataErrorCode result_code = GDATA_OTHER_ERROR; 353 GDataErrorCode result_code = GDATA_OTHER_ERROR;
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 885
860 // Check the response. 886 // Check the response.
861 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file 887 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file
862 // The start and end positions should be set to -1, if an upload is complete. 888 // The start and end positions should be set to -1, if an upload is complete.
863 EXPECT_EQ(-1, response.start_position_received); 889 EXPECT_EQ(-1, response.start_position_received);
864 EXPECT_EQ(-1, response.end_position_received); 890 EXPECT_EQ(-1, response.end_position_received);
865 } 891 }
866 892
867 // This test exercises InitiateUploadOperation and ResumeUploadOperation for 893 // This test exercises InitiateUploadOperation and ResumeUploadOperation for
868 // a scenario of uploading a new *large* file, which requires multiple requests 894 // a scenario of uploading a new *large* file, which requires multiple requests
869 // of ResumeUploadOperation. 895 // of ResumeUploadOperation. GetUploadOperation is also tested in this test
896 // case.
870 TEST_F(GDataWapiOperationsTest, UploadNewLargeFile) { 897 TEST_F(GDataWapiOperationsTest, UploadNewLargeFile) {
871 const size_t kMaxNumBytes = 10; 898 const size_t kMaxNumBytes = 10;
872 // This is big enough to cause multiple requests of ResumeUploadOperation 899 // This is big enough to cause multiple requests of ResumeUploadOperation
873 // as we are going to send at most kMaxNumBytes at a time. 900 // as we are going to send at most kMaxNumBytes at a time.
874 const std::string kUploadContent(kMaxNumBytes + 1, 'a'); 901 const std::string kUploadContent(kMaxNumBytes + 1, 'a');
kinaba 2013/02/08 10:19:43 In order to catch the above commented case, could
hidehiko 2013/02/08 11:53:10 Done.
875 GDataErrorCode result_code = GDATA_OTHER_ERROR; 902 GDataErrorCode result_code = GDATA_OTHER_ERROR;
876 GURL upload_url; 903 GURL upload_url;
877 904
878 // 1) Get the upload URL for uploading a new file. 905 // 1) Get the upload URL for uploading a new file.
879 InitiateUploadParams initiate_params( 906 InitiateUploadParams initiate_params(
880 UPLOAD_NEW_FILE, 907 UPLOAD_NEW_FILE,
881 "New file", 908 "New file",
882 "text/plain", 909 "text/plain",
883 kUploadContent.size(), 910 kUploadContent.size(),
884 test_server_.GetURL("/feeds/upload/create-session/default/private/full"), 911 test_server_.GetURL("/feeds/upload/create-session/default/private/full"),
(...skipping 26 matching lines...) Expand all
911 http_request_.headers["X-Upload-Content-Length"]); 938 http_request_.headers["X-Upload-Content-Length"]);
912 939
913 EXPECT_TRUE(http_request_.has_content); 940 EXPECT_TRUE(http_request_.has_content);
914 EXPECT_EQ("<?xml version=\"1.0\"?>\n" 941 EXPECT_EQ("<?xml version=\"1.0\"?>\n"
915 "<entry xmlns=\"http://www.w3.org/2005/Atom\" " 942 "<entry xmlns=\"http://www.w3.org/2005/Atom\" "
916 "xmlns:docs=\"http://schemas.google.com/docs/2007\">\n" 943 "xmlns:docs=\"http://schemas.google.com/docs/2007\">\n"
917 " <title>New file</title>\n" 944 " <title>New file</title>\n"
918 "</entry>\n", 945 "</entry>\n",
919 http_request_.content); 946 http_request_.content);
920 947
921 // 2) Upload the content to the upload URL with multiple requests. 948 // 2) Before sending any data, check the current status.
hidehiko 2013/02/08 09:17:00 Hmm, the diff looks not good. What I did is insert
949 // This is an edge case test for GetUploadStatusOperation
950 // (UploadRangeOperationBase).
951 {
952 // Check the response by GetUploadStatusOperation.
953 GetUploadStatusOperation* get_upload_status_operation =
954 new GetUploadStatusOperation(
955 &operation_registry_,
956 request_context_getter_.get(),
957 base::Bind(&CopyResultFromUploadRangeCallbackAndQuit,
958 &response,
959 &new_entry),
960 UPLOAD_NEW_FILE,
961 FilePath::FromUTF8Unsafe("drive/newfile.txt"),
962 upload_url,
963 kUploadContent.size());
964 get_upload_status_operation->Start(
965 kTestGDataAuthToken, kTestUserAgent,
966 base::Bind(&test_util::DoNothingForReAuthenticateCallback));
967 MessageLoop::current()->Run();
968
969 // METHOD_PUT should be used to upload data.
970 EXPECT_EQ(test_server::METHOD_PUT, http_request_.method);
971 // Request should go to the upload URL.
972 EXPECT_EQ(upload_url.path(), http_request_.relative_url);
973 // Content-Range header should be added.
974 EXPECT_EQ("bytes */" + base::Int64ToString(kUploadContent.size()),
975 http_request_.headers["Content-Range"]);
976 EXPECT_TRUE(http_request_.has_content);
977 EXPECT_TRUE(http_request_.content.empty());
978
979 // Check the response.
980 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code);
981 EXPECT_EQ(0, response.start_position_received);
982 EXPECT_EQ(0, response.end_position_received);
983 }
984
985 // 3) Upload the content to the upload URL with multiple requests.
922 size_t num_bytes_consumed = 0; 986 size_t num_bytes_consumed = 0;
923 for (size_t start_position = 0; start_position < kUploadContent.size(); 987 for (size_t start_position = 0; start_position < kUploadContent.size();
924 start_position += kMaxNumBytes) { 988 start_position += kMaxNumBytes) {
925 SCOPED_TRACE(testing::Message("start_position: ") << start_position); 989 SCOPED_TRACE(testing::Message("start_position: ") << start_position);
926 990
927 // The payload is at most kMaxNumBytes. 991 // The payload is at most kMaxNumBytes.
928 const size_t remaining_size = kUploadContent.size() - start_position; 992 const size_t remaining_size = kUploadContent.size() - start_position;
929 const std::string payload = kUploadContent.substr( 993 const std::string payload = kUploadContent.substr(
930 start_position, std::min(kMaxNumBytes, remaining_size)); 994 start_position, std::min(kMaxNumBytes, remaining_size));
931 num_bytes_consumed += payload.size(); 995 num_bytes_consumed += payload.size();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 EXPECT_TRUE(http_request_.has_content); 1037 EXPECT_TRUE(http_request_.has_content);
974 EXPECT_EQ(payload, http_request_.content); 1038 EXPECT_EQ(payload, http_request_.content);
975 1039
976 // Check the response. 1040 // Check the response.
977 if (payload.size() == remaining_size) { 1041 if (payload.size() == remaining_size) {
978 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file. 1042 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file.
979 // The start and end positions should be set to -1, if an upload is 1043 // The start and end positions should be set to -1, if an upload is
980 // complete. 1044 // complete.
981 EXPECT_EQ(-1, response.start_position_received); 1045 EXPECT_EQ(-1, response.start_position_received);
982 EXPECT_EQ(-1, response.end_position_received); 1046 EXPECT_EQ(-1, response.end_position_received);
983 } else { 1047 // The upload process is completed, so exit from the loop.
984 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); 1048 break;
985 EXPECT_EQ(static_cast<int64>(start_position),
986 response.start_position_received);
987 EXPECT_EQ(static_cast<int64>(end_position),
988 response.end_position_received);
989 } 1049 }
1050
1051 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code);
1052 EXPECT_EQ(static_cast<int64>(start_position),
1053 response.start_position_received);
1054 EXPECT_EQ(static_cast<int64>(end_position),
1055 response.end_position_received);
1056
1057 // Check the response by GetUploadStatusOperation.
1058 GetUploadStatusOperation* get_upload_status_operation =
1059 new GetUploadStatusOperation(
1060 &operation_registry_,
1061 request_context_getter_.get(),
1062 base::Bind(&CopyResultFromUploadRangeCallbackAndQuit,
1063 &response,
1064 &new_entry),
1065 UPLOAD_NEW_FILE,
1066 FilePath::FromUTF8Unsafe("drive/newfile.txt"),
1067 upload_url,
1068 kUploadContent.size());
1069 get_upload_status_operation->Start(
1070 kTestGDataAuthToken, kTestUserAgent,
1071 base::Bind(&test_util::DoNothingForReAuthenticateCallback));
1072 MessageLoop::current()->Run();
1073
1074 // METHOD_PUT should be used to upload data.
1075 EXPECT_EQ(test_server::METHOD_PUT, http_request_.method);
1076 // Request should go to the upload URL.
1077 EXPECT_EQ(upload_url.path(), http_request_.relative_url);
1078 // Content-Range header should be added.
1079 EXPECT_EQ("bytes */" + base::Int64ToString(kUploadContent.size()),
1080 http_request_.headers["Content-Range"]);
1081 EXPECT_TRUE(http_request_.has_content);
1082 EXPECT_TRUE(http_request_.content.empty());
1083
1084 // Check the response.
1085 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code);
1086 EXPECT_EQ(static_cast<int64>(start_position),
1087 response.start_position_received);
1088 EXPECT_EQ(static_cast<int64>(end_position),
1089 response.end_position_received);
990 } 1090 }
991 1091
992 EXPECT_EQ(kUploadContent.size(), num_bytes_consumed); 1092 EXPECT_EQ(kUploadContent.size(), num_bytes_consumed);
993 } 1093 }
994 1094
995 // This test exercises InitiateUploadOperation and ResumeUploadOperation for 1095 // This test exercises InitiateUploadOperation and ResumeUploadOperation for
996 // a scenario of uploading a new *empty* file. 1096 // a scenario of uploading a new *empty* file.
997 // 1097 //
998 // The test is almost identical to UploadNewFile. The only difference is the 1098 // The test is almost identical to UploadNewFile. The only difference is the
999 // expectation for the Content-Range header. 1099 // expectation for the Content-Range header.
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
1334 EXPECT_EQ(base::Int64ToString(kUploadContent.size()), 1434 EXPECT_EQ(base::Int64ToString(kUploadContent.size()),
1335 http_request_.headers["X-Upload-Content-Length"]); 1435 http_request_.headers["X-Upload-Content-Length"]);
1336 // For updating an existing file, an empty body should be attached (PUT 1436 // For updating an existing file, an empty body should be attached (PUT
1337 // requires a body) 1437 // requires a body)
1338 EXPECT_TRUE(http_request_.has_content); 1438 EXPECT_TRUE(http_request_.has_content);
1339 EXPECT_EQ("", http_request_.content); 1439 EXPECT_EQ("", http_request_.content);
1340 EXPECT_EQ(kWrongETag, http_request_.headers["If-Match"]); 1440 EXPECT_EQ(kWrongETag, http_request_.headers["If-Match"]);
1341 } 1441 }
1342 1442
1343 } // namespace google_apis 1443 } // 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