1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/bind.h" 6 #include "base/file_util.h" 7 #include "base/files/file_path.h" 8 #include "base/files/scoped_temp_dir.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/run_loop.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/values.h" 13 #include "google_apis/drive/drive_api_parser.h" 14 #include "google_apis/drive/drive_api_requests.h" 15 #include "google_apis/drive/drive_api_url_generator.h" 16 #include "google_apis/drive/dummy_auth_service.h" 17 #include "google_apis/drive/request_sender.h" 18 #include "google_apis/drive/test_util.h" 19 #include "net/test/embedded_test_server/embedded_test_server.h" 20 #include "net/test/embedded_test_server/http_request.h" 21 #include "net/test/embedded_test_server/http_response.h" 22 #include "net/url_request/url_request_test_util.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 25 namespace google_apis { 26 27 namespace { 28 29 const char kTestETag[] = "test_etag"; 30 const char kTestUserAgent[] = "test-user-agent"; 31 32 const char kTestChildrenResponse[] = 33 "{\n" 34 "\"kind\": \"drive#childReference\",\n" 35 "\"id\": \"resource_id\",\n" 36 "\"selfLink\": \"self_link\",\n" 37 "\"childLink\": \"child_link\",\n" 38 "}\n"; 39 40 const char kTestUploadExistingFilePath[] = "/upload/existingfile/path"; 41 const char kTestUploadNewFilePath[] = "/upload/newfile/path"; 42 const char kTestDownloadPathPrefix[] = "/download/"; 43 44 // Used as a GetContentCallback. 45 void AppendContent(std::string* out, 46 GDataErrorCode error, 47 scoped_ptr<std::string> content) { 48 EXPECT_EQ(HTTP_SUCCESS, error); 49 out->append(*content); 50 } 51 52 } // namespace 53 54 class DriveApiRequestsTest : public testing::Test { 55 public: 56 DriveApiRequestsTest() { 57 } 58 59 virtual void SetUp() OVERRIDE { 60 request_context_getter_ = new net::TestURLRequestContextGetter( 61 message_loop_.message_loop_proxy()); 62 63 request_sender_.reset(new RequestSender(new DummyAuthService, 64 request_context_getter_.get(), 65 message_loop_.message_loop_proxy(), 66 kTestUserAgent)); 67 68 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 69 70 ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady()); 71 test_server_.RegisterRequestHandler( 72 base::Bind(&DriveApiRequestsTest::HandleChildrenDeleteRequest, 73 base::Unretained(this))); 74 test_server_.RegisterRequestHandler( 75 base::Bind(&DriveApiRequestsTest::HandleDataFileRequest, 76 base::Unretained(this))); 77 test_server_.RegisterRequestHandler( 78 base::Bind(&DriveApiRequestsTest::HandleDeleteRequest, 79 base::Unretained(this))); 80 test_server_.RegisterRequestHandler( 81 base::Bind(&DriveApiRequestsTest::HandlePreconditionFailedRequest, 82 base::Unretained(this))); 83 test_server_.RegisterRequestHandler( 84 base::Bind(&DriveApiRequestsTest::HandleResumeUploadRequest, 85 base::Unretained(this))); 86 test_server_.RegisterRequestHandler( 87 base::Bind(&DriveApiRequestsTest::HandleInitiateUploadRequest, 88 base::Unretained(this))); 89 test_server_.RegisterRequestHandler( 90 base::Bind(&DriveApiRequestsTest::HandleContentResponse, 91 base::Unretained(this))); 92 test_server_.RegisterRequestHandler( 93 base::Bind(&DriveApiRequestsTest::HandleDownloadRequest, 94 base::Unretained(this))); 95 96 GURL test_base_url = test_util::GetBaseUrlForTesting(test_server_.port()); 97 url_generator_.reset(new DriveApiUrlGenerator( 98 test_base_url, test_base_url.Resolve(kTestDownloadPathPrefix))); 99 100 // Reset the server's expected behavior just in case. 101 ResetExpectedResponse(); 102 received_bytes_ = 0; 103 content_length_ = 0; 104 } 105 106 base::MessageLoopForIO message_loop_; // Test server needs IO thread. 107 net::test_server::EmbeddedTestServer test_server_; 108 scoped_ptr<RequestSender> request_sender_; 109 scoped_ptr<DriveApiUrlGenerator> url_generator_; 110 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; 111 base::ScopedTempDir temp_dir_; 112 113 // This is a path to the file which contains expected response from 114 // the server. See also HandleDataFileRequest below. 115 base::FilePath expected_data_file_path_; 116 117 // This is a path string in the expected response header from the server 118 // for initiating file uploading. 119 std::string expected_upload_path_; 120 121 // This is a path to the file which contains expected response for 122 // PRECONDITION_FAILED response. 123 base::FilePath expected_precondition_failed_file_path_; 124 125 // These are content and its type in the expected response from the server. 126 // See also HandleContentResponse below. 127 std::string expected_content_type_; 128 std::string expected_content_; 129 130 // The incoming HTTP request is saved so tests can verify the request 131 // parameters like HTTP method (ex. some requests should use DELETE 132 // instead of GET). 133 net::test_server::HttpRequest http_request_; 134 135 private: 136 void ResetExpectedResponse() { 137 expected_data_file_path_.clear(); 138 expected_upload_path_.clear(); 139 expected_content_type_.clear(); 140 expected_content_.clear(); 141 } 142 143 // For "Children: delete" request, the server will return "204 No Content" 144 // response meaning "success". 145 scoped_ptr<net::test_server::HttpResponse> HandleChildrenDeleteRequest( 146 const net::test_server::HttpRequest& request) { 147 if (request.method != net::test_server::METHOD_DELETE || 148 request.relative_url.find("/children/") == string::npos) { 149 // The request is not the "Children: delete" request. Delegate the 150 // processing to the next handler. 151 return scoped_ptr<net::test_server::HttpResponse>(); 152 } 153 154 http_request_ = request; 155 156 // Return the response with just "204 No Content" status code. 157 scoped_ptr<net::test_server::BasicHttpResponse> http_response( 158 new net::test_server::BasicHttpResponse); 159 http_response->set_code(net::HTTP_NO_CONTENT); 160 return http_response.PassAs<net::test_server::HttpResponse>(); 161 } 162 163 // Reads the data file of |expected_data_file_path_| and returns its content 164 // for the request. 165 // To use this method, it is necessary to set |expected_data_file_path_| 166 // to the appropriate file path before sending the request to the server. 167 scoped_ptr<net::test_server::HttpResponse> HandleDataFileRequest( 168 const net::test_server::HttpRequest& request) { 169 if (expected_data_file_path_.empty()) { 170 // The file is not specified. Delegate the processing to the next 171 // handler. 172 return scoped_ptr<net::test_server::HttpResponse>(); 173 } 174 175 http_request_ = request; 176 177 // Return the response from the data file. 178 return test_util::CreateHttpResponseFromFile( 179 expected_data_file_path_).PassAs<net::test_server::HttpResponse>(); 180 } 181 182 // Deletes the resource and returns no content with HTTP_NO_CONTENT status 183 // code. 184 scoped_ptr<net::test_server::HttpResponse> HandleDeleteRequest( 185 const net::test_server::HttpRequest& request) { 186 if (request.method != net::test_server::METHOD_DELETE || 187 request.relative_url.find("/files/") == string::npos) { 188 // The file is not file deletion request. Delegate the processing to the 189 // next handler. 190 return scoped_ptr<net::test_server::HttpResponse>(); 191 } 192 193 http_request_ = request; 194 195 scoped_ptr<net::test_server::BasicHttpResponse> response( 196 new net::test_server::BasicHttpResponse); 197 response->set_code(net::HTTP_NO_CONTENT); 198 199 return response.PassAs<net::test_server::HttpResponse>(); 200 } 201 202 // Returns PRECONDITION_FAILED response for ETag mismatching with error JSON 203 // content specified by |expected_precondition_failed_file_path_|. 204 // To use this method, it is necessary to set the variable to the appropriate 205 // file path before sending the request to the server. 206 scoped_ptr<net::test_server::HttpResponse> HandlePreconditionFailedRequest( 207 const net::test_server::HttpRequest& request) { 208 if (expected_precondition_failed_file_path_.empty()) { 209 // The file is not specified. Delegate the process to the next handler. 210 return scoped_ptr<net::test_server::HttpResponse>(); 211 } 212 213 http_request_ = request; 214 215 scoped_ptr<net::test_server::BasicHttpResponse> response( 216 new net::test_server::BasicHttpResponse); 217 response->set_code(net::HTTP_PRECONDITION_FAILED); 218 219 std::string content; 220 if (base::ReadFileToString(expected_precondition_failed_file_path_, 221 &content)) { 222 response->set_content(content); 223 response->set_content_type("application/json"); 224 } 225 226 return response.PassAs<net::test_server::HttpResponse>(); 227 } 228 229 // Returns the response based on set expected upload url. 230 // The response contains the url in its "Location: " header. Also, it doesn't 231 // have any content. 232 // To use this method, it is necessary to set |expected_upload_path_| 233 // to the string representation of the url to be returned. 234 scoped_ptr<net::test_server::HttpResponse> HandleInitiateUploadRequest( 235 const net::test_server::HttpRequest& request) { 236 if (request.relative_url == expected_upload_path_ || 237 expected_upload_path_.empty()) { 238 // The request is for resume uploading or the expected upload url is not 239 // set. Delegate the processing to the next handler. 240 return scoped_ptr<net::test_server::HttpResponse>(); 241 } 242 243 http_request_ = request; 244 245 scoped_ptr<net::test_server::BasicHttpResponse> response( 246 new net::test_server::BasicHttpResponse); 247 248 // Check if the X-Upload-Content-Length is present. If yes, store the 249 // length of the file. 250 std::map<std::string, std::string>::const_iterator found = 251 request.headers.find("X-Upload-Content-Length"); 252 if (found == request.headers.end() || 253 !base::StringToInt64(found->second, &content_length_)) { 254 return scoped_ptr<net::test_server::HttpResponse>(); 255 } 256 received_bytes_ = 0; 257 258 response->set_code(net::HTTP_OK); 259 response->AddCustomHeader( 260 "Location", 261 test_server_.base_url().Resolve(expected_upload_path_).spec()); 262 return response.PassAs<net::test_server::HttpResponse>(); 263 } 264 265 scoped_ptr<net::test_server::HttpResponse> HandleResumeUploadRequest( 266 const net::test_server::HttpRequest& request) { 267 if (request.relative_url != expected_upload_path_) { 268 // The request path is different from the expected path for uploading. 269 // Delegate the processing to the next handler. 270 return scoped_ptr<net::test_server::HttpResponse>(); 271 } 272 273 http_request_ = request; 274 275 if (!request.content.empty()) { 276 std::map<std::string, std::string>::const_iterator iter = 277 request.headers.find("Content-Range"); 278 if (iter == request.headers.end()) { 279 // The range must be set. 280 return scoped_ptr<net::test_server::HttpResponse>(); 281 } 282 283 int64 length = 0; 284 int64 start_position = 0; 285 int64 end_position = 0; 286 if (!test_util::ParseContentRangeHeader( 287 iter->second, &start_position, &end_position, &length)) { 288 // Invalid "Content-Range" value. 289 return scoped_ptr<net::test_server::HttpResponse>(); 290 } 291 292 EXPECT_EQ(start_position, received_bytes_); 293 EXPECT_EQ(length, content_length_); 294 295 // end_position is inclusive, but so +1 to change the range to byte size. 296 received_bytes_ = end_position + 1; 297 } 298 299 if (received_bytes_ < content_length_) { 300 scoped_ptr<net::test_server::BasicHttpResponse> response( 301 new net::test_server::BasicHttpResponse); 302 // Set RESUME INCOMPLETE (308) status code. 303 response->set_code(static_cast<net::HttpStatusCode>(308)); 304 305 // Add Range header to the response, based on the values of 306 // Content-Range header in the request. 307 // The header is annotated only when at least one byte is received. 308 if (received_bytes_ > 0) { 309 response->AddCustomHeader( 310 "Range", "bytes=0-" + base::Int64ToString(received_bytes_ - 1)); 311 } 312 313 return response.PassAs<net::test_server::HttpResponse>(); 314 } 315 316 // All bytes are received. Return the "success" response with the file's 317 // (dummy) metadata. 318 scoped_ptr<net::test_server::BasicHttpResponse> response = 319 test_util::CreateHttpResponseFromFile( 320 test_util::GetTestFilePath("drive/file_entry.json")); 321 322 // The response code is CREATED if it is new file uploading. 323 if (http_request_.relative_url == kTestUploadNewFilePath) { 324 response->set_code(net::HTTP_CREATED); 325 } 326 327 return response.PassAs<net::test_server::HttpResponse>(); 328 } 329 330 // Returns the response based on set expected content and its type. 331 // To use this method, both |expected_content_type_| and |expected_content_| 332 // must be set in advance. 333 scoped_ptr<net::test_server::HttpResponse> HandleContentResponse( 334 const net::test_server::HttpRequest& request) { 335 if (expected_content_type_.empty() || expected_content_.empty()) { 336 // Expected content is not set. Delegate the processing to the next 337 // handler. 338 return scoped_ptr<net::test_server::HttpResponse>(); 339 } 340 341 http_request_ = request; 342 343 scoped_ptr<net::test_server::BasicHttpResponse> response( 344 new net::test_server::BasicHttpResponse); 345 response->set_code(net::HTTP_OK); 346 response->set_content_type(expected_content_type_); 347 response->set_content(expected_content_); 348 return response.PassAs<net::test_server::HttpResponse>(); 349 } 350 351 // Handles a request for downloading a file. 352 scoped_ptr<net::test_server::HttpResponse> HandleDownloadRequest( 353 const net::test_server::HttpRequest& request) { 354 http_request_ = request; 355 356 const GURL absolute_url = test_server_.GetURL(request.relative_url); 357 std::string id; 358 if (!test_util::RemovePrefix(absolute_url.path(), 359 kTestDownloadPathPrefix, 360 &id)) { 361 return scoped_ptr<net::test_server::HttpResponse>(); 362 } 363 364 // For testing, returns a text with |id| repeated 3 times. 365 scoped_ptr<net::test_server::BasicHttpResponse> response( 366 new net::test_server::BasicHttpResponse); 367 response->set_code(net::HTTP_OK); 368 response->set_content(id + id + id); 369 response->set_content_type("text/plain"); 370 return response.PassAs<net::test_server::HttpResponse>(); 371 } 372 373 // These are for the current upload file status. 374 int64 received_bytes_; 375 int64 content_length_; 376 }; 377 378 TEST_F(DriveApiRequestsTest, DriveApiDataRequest_Fields) { 379 // Make sure that "fields" query param is supported by using its subclass, 380 // AboutGetRequest. 381 382 // Set an expected data file containing valid result. 383 expected_data_file_path_ = test_util::GetTestFilePath( 384 "drive/about.json"); 385 386 GDataErrorCode error = GDATA_OTHER_ERROR; 387 scoped_ptr<AboutResource> about_resource; 388 389 { 390 base::RunLoop run_loop; 391 drive::AboutGetRequest* request = new drive::AboutGetRequest( 392 request_sender_.get(), 393 *url_generator_, 394 test_util::CreateQuitCallback( 395 &run_loop, 396 test_util::CreateCopyResultCallback(&error, &about_resource))); 397 request->set_fields( 398 "kind,quotaBytesTotal,quotaBytesUsed,largestChangeId,rootFolderId"); 399 request_sender_->StartRequestWithRetry(request); 400 run_loop.Run(); 401 } 402 403 EXPECT_EQ(HTTP_SUCCESS, error); 404 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); 405 EXPECT_EQ("/drive/v2/about?" 406 "fields=kind%2CquotaBytesTotal%2CquotaBytesUsed%2C" 407 "largestChangeId%2CrootFolderId", 408 http_request_.relative_url); 409 410 scoped_ptr<AboutResource> expected( 411 AboutResource::CreateFrom( 412 *test_util::LoadJSONFile("drive/about.json"))); 413 ASSERT_TRUE(about_resource.get()); 414 EXPECT_EQ(expected->largest_change_id(), about_resource->largest_change_id()); 415 EXPECT_EQ(expected->quota_bytes_total(), about_resource->quota_bytes_total()); 416 EXPECT_EQ(expected->quota_bytes_used(), about_resource->quota_bytes_used()); 417 EXPECT_EQ(expected->root_folder_id(), about_resource->root_folder_id()); 418 } 419 420 TEST_F(DriveApiRequestsTest, FilesInsertRequest) { 421 // Set an expected data file containing the directory's entry data. 422 expected_data_file_path_ = 423 test_util::GetTestFilePath("drive/directory_entry.json"); 424 425 GDataErrorCode error = GDATA_OTHER_ERROR; 426 scoped_ptr<FileResource> file_resource; 427 428 // Create "new directory" in the root directory. 429 { 430 base::RunLoop run_loop; 431 drive::FilesInsertRequest* request = new drive::FilesInsertRequest( 432 request_sender_.get(), 433 *url_generator_, 434 test_util::CreateQuitCallback( 435 &run_loop, 436 test_util::CreateCopyResultCallback(&error, &file_resource))); 437 request->set_mime_type("application/vnd.google-apps.folder"); 438 request->add_parent("root"); 439 request->set_title("new directory"); 440 request_sender_->StartRequestWithRetry(request); 441 run_loop.Run(); 442 } 443 444 EXPECT_EQ(HTTP_SUCCESS, error); 445 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); 446 EXPECT_EQ("/drive/v2/files", http_request_.relative_url); 447 EXPECT_EQ("application/json", http_request_.headers["Content-Type"]); 448 449 EXPECT_TRUE(http_request_.has_content); 450 451 scoped_ptr<FileResource> expected( 452 FileResource::CreateFrom( 453 *test_util::LoadJSONFile("drive/directory_entry.json"))); 454 455 // Sanity check. 456 ASSERT_TRUE(file_resource.get()); 457 458 EXPECT_EQ(expected->file_id(), file_resource->file_id()); 459 EXPECT_EQ(expected->title(), file_resource->title()); 460 EXPECT_EQ(expected->mime_type(), file_resource->mime_type()); 461 EXPECT_EQ(expected->parents().size(), file_resource->parents().size()); 462 } 463 464 TEST_F(DriveApiRequestsTest, FilesPatchRequest) { 465 const base::Time::Exploded kModifiedDate = {2012, 7, 0, 19, 15, 59, 13, 123}; 466 const base::Time::Exploded kLastViewedByMeDate = 467 {2013, 7, 0, 19, 15, 59, 13, 123}; 468 469 // Set an expected data file containing valid result. 470 expected_data_file_path_ = 471 test_util::GetTestFilePath("drive/file_entry.json"); 472 473 GDataErrorCode error = GDATA_OTHER_ERROR; 474 scoped_ptr<FileResource> file_resource; 475 476 { 477 base::RunLoop run_loop; 478 drive::FilesPatchRequest* request = new drive::FilesPatchRequest( 479 request_sender_.get(), 480 *url_generator_, 481 test_util::CreateQuitCallback( 482 &run_loop, 483 test_util::CreateCopyResultCallback(&error, &file_resource))); 484 request->set_file_id("resource_id"); 485 request->set_set_modified_date(true); 486 request->set_update_viewed_date(false); 487 488 request->set_title("new title"); 489 request->set_modified_date(base::Time::FromUTCExploded(kModifiedDate)); 490 request->set_last_viewed_by_me_date( 491 base::Time::FromUTCExploded(kLastViewedByMeDate)); 492 request->add_parent("parent_resource_id"); 493 494 request_sender_->StartRequestWithRetry(request); 495 run_loop.Run(); 496 } 497 498 EXPECT_EQ(HTTP_SUCCESS, error); 499 EXPECT_EQ(net::test_server::METHOD_PATCH, http_request_.method); 500 EXPECT_EQ("/drive/v2/files/resource_id" 501 "?setModifiedDate=true&updateViewedDate=false", 502 http_request_.relative_url); 503 504 EXPECT_EQ("application/json", http_request_.headers["Content-Type"]); 505 EXPECT_TRUE(http_request_.has_content); 506 EXPECT_EQ("{\"lastViewedByMeDate\":\"2013-07-19T15:59:13.123Z\"," 507 "\"modifiedDate\":\"2012-07-19T15:59:13.123Z\"," 508 "\"parents\":[{\"id\":\"parent_resource_id\"}]," 509 "\"title\":\"new title\"}", 510 http_request_.content); 511 EXPECT_TRUE(file_resource); 512 } 513 514 TEST_F(DriveApiRequestsTest, AboutGetRequest_ValidJson) { 515 // Set an expected data file containing valid result. 516 expected_data_file_path_ = test_util::GetTestFilePath( 517 "drive/about.json"); 518 519 GDataErrorCode error = GDATA_OTHER_ERROR; 520 scoped_ptr<AboutResource> about_resource; 521 522 { 523 base::RunLoop run_loop; 524 drive::AboutGetRequest* request = new drive::AboutGetRequest( 525 request_sender_.get(), 526 *url_generator_, 527 test_util::CreateQuitCallback( 528 &run_loop, 529 test_util::CreateCopyResultCallback(&error, &about_resource))); 530 request_sender_->StartRequestWithRetry(request); 531 run_loop.Run(); 532 } 533 534 EXPECT_EQ(HTTP_SUCCESS, error); 535 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); 536 EXPECT_EQ("/drive/v2/about", http_request_.relative_url); 537 538 scoped_ptr<AboutResource> expected( 539 AboutResource::CreateFrom( 540 *test_util::LoadJSONFile("drive/about.json"))); 541 ASSERT_TRUE(about_resource.get()); 542 EXPECT_EQ(expected->largest_change_id(), about_resource->largest_change_id()); 543 EXPECT_EQ(expected->quota_bytes_total(), about_resource->quota_bytes_total()); 544 EXPECT_EQ(expected->quota_bytes_used(), about_resource->quota_bytes_used()); 545 EXPECT_EQ(expected->root_folder_id(), about_resource->root_folder_id()); 546 } 547 548 TEST_F(DriveApiRequestsTest, AboutGetRequest_InvalidJson) { 549 // Set an expected data file containing invalid result. 550 expected_data_file_path_ = test_util::GetTestFilePath( 551 "gdata/testfile.txt"); 552 553 GDataErrorCode error = GDATA_OTHER_ERROR; 554 scoped_ptr<AboutResource> about_resource; 555 556 { 557 base::RunLoop run_loop; 558 drive::AboutGetRequest* request = new drive::AboutGetRequest( 559 request_sender_.get(), 560 *url_generator_, 561 test_util::CreateQuitCallback( 562 &run_loop, 563 test_util::CreateCopyResultCallback(&error, &about_resource))); 564 request_sender_->StartRequestWithRetry(request); 565 run_loop.Run(); 566 } 567 568 // "parse error" should be returned, and the about resource should be NULL. 569 EXPECT_EQ(GDATA_PARSE_ERROR, error); 570 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); 571 EXPECT_EQ("/drive/v2/about", http_request_.relative_url); 572 EXPECT_FALSE(about_resource); 573 } 574 575 TEST_F(DriveApiRequestsTest, AppsListRequest) { 576 // Set an expected data file containing valid result. 577 expected_data_file_path_ = test_util::GetTestFilePath( 578 "drive/applist.json"); 579 580 GDataErrorCode error = GDATA_OTHER_ERROR; 581 scoped_ptr<AppList> app_list; 582 583 { 584 base::RunLoop run_loop; 585 drive::AppsListRequest* request = new drive::AppsListRequest( 586 request_sender_.get(), 587 *url_generator_, 588 test_util::CreateQuitCallback( 589 &run_loop, 590 test_util::CreateCopyResultCallback(&error, &app_list))); 591 request_sender_->StartRequestWithRetry(request); 592 run_loop.Run(); 593 } 594 595 EXPECT_EQ(HTTP_SUCCESS, error); 596 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); 597 EXPECT_EQ("/drive/v2/apps", http_request_.relative_url); 598 EXPECT_TRUE(app_list); 599 } 600 601 TEST_F(DriveApiRequestsTest, ChangesListRequest) { 602 // Set an expected data file containing valid result. 603 expected_data_file_path_ = test_util::GetTestFilePath( 604 "drive/changelist.json"); 605 606 GDataErrorCode error = GDATA_OTHER_ERROR; 607 scoped_ptr<ChangeList> result; 608 609 { 610 base::RunLoop run_loop; 611 drive::ChangesListRequest* request = new drive::ChangesListRequest( 612 request_sender_.get(), *url_generator_, 613 test_util::CreateQuitCallback( 614 &run_loop, 615 test_util::CreateCopyResultCallback(&error, &result))); 616 request->set_include_deleted(true); 617 request->set_start_change_id(100); 618 request->set_max_results(500); 619 request_sender_->StartRequestWithRetry(request); 620 run_loop.Run(); 621 } 622 623 EXPECT_EQ(HTTP_SUCCESS, error); 624 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); 625 EXPECT_EQ("/drive/v2/changes?maxResults=500&startChangeId=100", 626 http_request_.relative_url); 627 EXPECT_TRUE(result); 628 } 629 630 TEST_F(DriveApiRequestsTest, ChangesListNextPageRequest) { 631 // Set an expected data file containing valid result. 632 expected_data_file_path_ = test_util::GetTestFilePath( 633 "drive/changelist.json"); 634 635 GDataErrorCode error = GDATA_OTHER_ERROR; 636 scoped_ptr<ChangeList> result; 637 638 { 639 base::RunLoop run_loop; 640 drive::ChangesListNextPageRequest* request = 641 new drive::ChangesListNextPageRequest( 642 request_sender_.get(), 643 test_util::CreateQuitCallback( 644 &run_loop, 645 test_util::CreateCopyResultCallback(&error, &result))); 646 request->set_next_link(test_server_.GetURL("/continue/get/change/list")); 647 request_sender_->StartRequestWithRetry(request); 648 run_loop.Run(); 649 } 650 651 EXPECT_EQ(HTTP_SUCCESS, error); 652 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); 653 EXPECT_EQ("/continue/get/change/list", http_request_.relative_url); 654 EXPECT_TRUE(result); 655 } 656 657 TEST_F(DriveApiRequestsTest, FilesCopyRequest) { 658 const base::Time::Exploded kModifiedDate = {2012, 7, 0, 19, 15, 59, 13, 123}; 659 660 // Set an expected data file containing the dummy file entry data. 661 // It'd be returned if we copy a file. 662 expected_data_file_path_ = 663 test_util::GetTestFilePath("drive/file_entry.json"); 664 665 GDataErrorCode error = GDATA_OTHER_ERROR; 666 scoped_ptr<FileResource> file_resource; 667 668 // Copy the file to a new file named "new title". 669 { 670 base::RunLoop run_loop; 671 drive::FilesCopyRequest* request = new drive::FilesCopyRequest( 672 request_sender_.get(), 673 *url_generator_, 674 test_util::CreateQuitCallback( 675 &run_loop, 676 test_util::CreateCopyResultCallback(&error, &file_resource))); 677 request->set_file_id("resource_id"); 678 request->set_modified_date(base::Time::FromUTCExploded(kModifiedDate)); 679 request->add_parent("parent_resource_id"); 680 request->set_title("new title"); 681 request_sender_->StartRequestWithRetry(request); 682 run_loop.Run(); 683 } 684 685 EXPECT_EQ(HTTP_SUCCESS, error); 686 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); 687 EXPECT_EQ("/drive/v2/files/resource_id/copy", http_request_.relative_url); 688 EXPECT_EQ("application/json", http_request_.headers["Content-Type"]); 689 690 EXPECT_TRUE(http_request_.has_content); 691 EXPECT_EQ( 692 "{\"modifiedDate\":\"2012-07-19T15:59:13.123Z\"," 693 "\"parents\":[{\"id\":\"parent_resource_id\"}],\"title\":\"new title\"}", 694 http_request_.content); 695 EXPECT_TRUE(file_resource); 696 } 697 698 TEST_F(DriveApiRequestsTest, FilesCopyRequest_EmptyParentResourceId) { 699 // Set an expected data file containing the dummy file entry data. 700 // It'd be returned if we copy a file. 701 expected_data_file_path_ = 702 test_util::GetTestFilePath("drive/file_entry.json"); 703 704 GDataErrorCode error = GDATA_OTHER_ERROR; 705 scoped_ptr<FileResource> file_resource; 706 707 // Copy the file to a new file named "new title". 708 { 709 base::RunLoop run_loop; 710 drive::FilesCopyRequest* request = new drive::FilesCopyRequest( 711 request_sender_.get(), 712 *url_generator_, 713 test_util::CreateQuitCallback( 714 &run_loop, 715 test_util::CreateCopyResultCallback(&error, &file_resource))); 716 request->set_file_id("resource_id"); 717 request->set_title("new title"); 718 request_sender_->StartRequestWithRetry(request); 719 run_loop.Run(); 720 } 721 722 EXPECT_EQ(HTTP_SUCCESS, error); 723 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); 724 EXPECT_EQ("/drive/v2/files/resource_id/copy", http_request_.relative_url); 725 EXPECT_EQ("application/json", http_request_.headers["Content-Type"]); 726 727 EXPECT_TRUE(http_request_.has_content); 728 EXPECT_EQ("{\"title\":\"new title\"}", http_request_.content); 729 EXPECT_TRUE(file_resource); 730 } 731 732 TEST_F(DriveApiRequestsTest, FilesListRequest) { 733 // Set an expected data file containing valid result. 734 expected_data_file_path_ = test_util::GetTestFilePath( 735 "drive/filelist.json"); 736 737 GDataErrorCode error = GDATA_OTHER_ERROR; 738 scoped_ptr<FileList> result; 739 740 { 741 base::RunLoop run_loop; 742 drive::FilesListRequest* request = new drive::FilesListRequest( 743 request_sender_.get(), *url_generator_, 744 test_util::CreateQuitCallback( 745 &run_loop, 746 test_util::CreateCopyResultCallback(&error, &result))); 747 request->set_max_results(50); 748 request->set_q("\"abcde\" in parents"); 749 request_sender_->StartRequestWithRetry(request); 750 run_loop.Run(); 751 } 752 753 EXPECT_EQ(HTTP_SUCCESS, error); 754 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); 755 EXPECT_EQ("/drive/v2/files?maxResults=50&q=%22abcde%22+in+parents", 756 http_request_.relative_url); 757 EXPECT_TRUE(result); 758 } 759 760 TEST_F(DriveApiRequestsTest, FilesListNextPageRequest) { 761 // Set an expected data file containing valid result. 762 expected_data_file_path_ = test_util::GetTestFilePath( 763 "drive/filelist.json"); 764 765 GDataErrorCode error = GDATA_OTHER_ERROR; 766 scoped_ptr<FileList> result; 767 768 { 769 base::RunLoop run_loop; 770 drive::FilesListNextPageRequest* request = 771 new drive::FilesListNextPageRequest( 772 request_sender_.get(), 773 test_util::CreateQuitCallback( 774 &run_loop, 775 test_util::CreateCopyResultCallback(&error, &result))); 776 request->set_next_link(test_server_.GetURL("/continue/get/file/list")); 777 request_sender_->StartRequestWithRetry(request); 778 run_loop.Run(); 779 } 780 781 EXPECT_EQ(HTTP_SUCCESS, error); 782 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); 783 EXPECT_EQ("/continue/get/file/list", http_request_.relative_url); 784 EXPECT_TRUE(result); 785 } 786 787 TEST_F(DriveApiRequestsTest, FilesDeleteRequest) { 788 GDataErrorCode error = GDATA_OTHER_ERROR; 789 790 // Delete a resource with the given resource id. 791 { 792 base::RunLoop run_loop; 793 drive::FilesDeleteRequest* request = new drive::FilesDeleteRequest( 794 request_sender_.get(), 795 *url_generator_, 796 test_util::CreateQuitCallback( 797 &run_loop, test_util::CreateCopyResultCallback(&error))); 798 request->set_file_id("resource_id"); 799 request->set_etag(kTestETag); 800 request_sender_->StartRequestWithRetry(request); 801 run_loop.Run(); 802 } 803 804 EXPECT_EQ(HTTP_NO_CONTENT, error); 805 EXPECT_EQ(net::test_server::METHOD_DELETE, http_request_.method); 806 EXPECT_EQ(kTestETag, http_request_.headers["If-Match"]); 807 EXPECT_EQ("/drive/v2/files/resource_id", http_request_.relative_url); 808 EXPECT_FALSE(http_request_.has_content); 809 } 810 811 TEST_F(DriveApiRequestsTest, FilesTrashRequest) { 812 // Set data for the expected result. Directory entry should be returned 813 // if the trashing entry is a directory, so using it here should be fine. 814 expected_data_file_path_ = 815 test_util::GetTestFilePath("drive/directory_entry.json"); 816 817 GDataErrorCode error = GDATA_OTHER_ERROR; 818 scoped_ptr<FileResource> file_resource; 819 820 // Trash a resource with the given resource id. 821 { 822 base::RunLoop run_loop; 823 drive::FilesTrashRequest* request = new drive::FilesTrashRequest( 824 request_sender_.get(), 825 *url_generator_, 826 test_util::CreateQuitCallback( 827 &run_loop, 828 test_util::CreateCopyResultCallback(&error, &file_resource))); 829 request->set_file_id("resource_id"); 830 request_sender_->StartRequestWithRetry(request); 831 run_loop.Run(); 832 } 833 834 EXPECT_EQ(HTTP_SUCCESS, error); 835 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); 836 EXPECT_EQ("/drive/v2/files/resource_id/trash", http_request_.relative_url); 837 EXPECT_TRUE(http_request_.has_content); 838 EXPECT_TRUE(http_request_.content.empty()); 839 } 840 841 TEST_F(DriveApiRequestsTest, ChildrenInsertRequest) { 842 // Set an expected data file containing the children entry. 843 expected_content_type_ = "application/json"; 844 expected_content_ = kTestChildrenResponse; 845 846 GDataErrorCode error = GDATA_OTHER_ERROR; 847 848 // Add a resource with "resource_id" to a directory with 849 // "parent_resource_id". 850 { 851 base::RunLoop run_loop; 852 drive::ChildrenInsertRequest* request = new drive::ChildrenInsertRequest( 853 request_sender_.get(), 854 *url_generator_, 855 test_util::CreateQuitCallback( 856 &run_loop, 857 test_util::CreateCopyResultCallback(&error))); 858 request->set_folder_id("parent_resource_id"); 859 request->set_id("resource_id"); 860 request_sender_->StartRequestWithRetry(request); 861 run_loop.Run(); 862 } 863 864 EXPECT_EQ(HTTP_SUCCESS, error); 865 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); 866 EXPECT_EQ("/drive/v2/files/parent_resource_id/children", 867 http_request_.relative_url); 868 EXPECT_EQ("application/json", http_request_.headers["Content-Type"]); 869 870 EXPECT_TRUE(http_request_.has_content); 871 EXPECT_EQ("{\"id\":\"resource_id\"}", http_request_.content); 872 } 873 874 TEST_F(DriveApiRequestsTest, ChildrenDeleteRequest) { 875 GDataErrorCode error = GDATA_OTHER_ERROR; 876 877 // Remove a resource with "resource_id" from a directory with 878 // "parent_resource_id". 879 { 880 base::RunLoop run_loop; 881 drive::ChildrenDeleteRequest* request = new drive::ChildrenDeleteRequest( 882 request_sender_.get(), 883 *url_generator_, 884 test_util::CreateQuitCallback( 885 &run_loop, 886 test_util::CreateCopyResultCallback(&error))); 887 request->set_child_id("resource_id"); 888 request->set_folder_id("parent_resource_id"); 889 request_sender_->StartRequestWithRetry(request); 890 run_loop.Run(); 891 } 892 893 EXPECT_EQ(HTTP_NO_CONTENT, error); 894 EXPECT_EQ(net::test_server::METHOD_DELETE, http_request_.method); 895 EXPECT_EQ("/drive/v2/files/parent_resource_id/children/resource_id", 896 http_request_.relative_url); 897 EXPECT_FALSE(http_request_.has_content); 898 } 899 900 TEST_F(DriveApiRequestsTest, UploadNewFileRequest) { 901 // Set an expected url for uploading. 902 expected_upload_path_ = kTestUploadNewFilePath; 903 904 const char kTestContentType[] = "text/plain"; 905 const std::string kTestContent(100, 'a'); 906 const base::FilePath kTestFilePath = 907 temp_dir_.path().AppendASCII("upload_file.txt"); 908 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kTestContent)); 909 910 GDataErrorCode error = GDATA_OTHER_ERROR; 911 GURL upload_url; 912 913 // Initiate uploading a new file to the directory with 914 // "parent_resource_id". 915 { 916 base::RunLoop run_loop; 917 drive::InitiateUploadNewFileRequest* request = 918 new drive::InitiateUploadNewFileRequest( 919 request_sender_.get(), 920 *url_generator_, 921 kTestContentType, 922 kTestContent.size(), 923 "parent_resource_id", // The resource id of the parent directory. 924 "new file title", // The title of the file being uploaded. 925 test_util::CreateQuitCallback( 926 &run_loop, 927 test_util::CreateCopyResultCallback(&error, &upload_url))); 928 request_sender_->StartRequestWithRetry(request); 929 run_loop.Run(); 930 } 931 932 EXPECT_EQ(HTTP_SUCCESS, error); 933 EXPECT_EQ(kTestUploadNewFilePath, upload_url.path()); 934 EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]); 935 EXPECT_EQ(base::Int64ToString(kTestContent.size()), 936 http_request_.headers["X-Upload-Content-Length"]); 937 938 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); 939 EXPECT_EQ("/upload/drive/v2/files?uploadType=resumable", 940 http_request_.relative_url); 941 EXPECT_EQ("application/json", http_request_.headers["Content-Type"]); 942 EXPECT_TRUE(http_request_.has_content); 943 EXPECT_EQ("{\"parents\":[{" 944 "\"id\":\"parent_resource_id\"," 945 "\"kind\":\"drive#fileLink\"" 946 "}]," 947 "\"title\":\"new file title\"}", 948 http_request_.content); 949 950 // Upload the content to the upload URL. 951 UploadRangeResponse response; 952 scoped_ptr<FileResource> new_entry; 953 954 { 955 base::RunLoop run_loop; 956 drive::ResumeUploadRequest* resume_request = 957 new drive::ResumeUploadRequest( 958 request_sender_.get(), 959 upload_url, 960 0, // start_position 961 kTestContent.size(), // end_position (exclusive) 962 kTestContent.size(), // content_length, 963 kTestContentType, 964 kTestFilePath, 965 test_util::CreateQuitCallback( 966 &run_loop, 967 test_util::CreateCopyResultCallback(&response, &new_entry)), 968 ProgressCallback()); 969 request_sender_->StartRequestWithRetry(resume_request); 970 run_loop.Run(); 971 } 972 973 // METHOD_PUT should be used to upload data. 974 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 975 // Request should go to the upload URL. 976 EXPECT_EQ(upload_url.path(), http_request_.relative_url); 977 // Content-Range header should be added. 978 EXPECT_EQ("bytes 0-" + 979 base::Int64ToString(kTestContent.size() - 1) + "/" + 980 base::Int64ToString(kTestContent.size()), 981 http_request_.headers["Content-Range"]); 982 // The upload content should be set in the HTTP request. 983 EXPECT_TRUE(http_request_.has_content); 984 EXPECT_EQ(kTestContent, http_request_.content); 985 986 // Check the response. 987 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file 988 // The start and end positions should be set to -1, if an upload is complete. 989 EXPECT_EQ(-1, response.start_position_received); 990 EXPECT_EQ(-1, response.end_position_received); 991 } 992 993 TEST_F(DriveApiRequestsTest, UploadNewEmptyFileRequest) { 994 // Set an expected url for uploading. 995 expected_upload_path_ = kTestUploadNewFilePath; 996 997 const char kTestContentType[] = "text/plain"; 998 const char kTestContent[] = ""; 999 const base::FilePath kTestFilePath = 1000 temp_dir_.path().AppendASCII("empty_file.txt"); 1001 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kTestContent)); 1002 1003 GDataErrorCode error = GDATA_OTHER_ERROR; 1004 GURL upload_url; 1005 1006 // Initiate uploading a new file to the directory with "parent_resource_id". 1007 { 1008 base::RunLoop run_loop; 1009 drive::InitiateUploadNewFileRequest* request = 1010 new drive::InitiateUploadNewFileRequest( 1011 request_sender_.get(), 1012 *url_generator_, 1013 kTestContentType, 1014 0, 1015 "parent_resource_id", // The resource id of the parent directory. 1016 "new file title", // The title of the file being uploaded. 1017 test_util::CreateQuitCallback( 1018 &run_loop, 1019 test_util::CreateCopyResultCallback(&error, &upload_url))); 1020 request_sender_->StartRequestWithRetry(request); 1021 run_loop.Run(); 1022 } 1023 1024 EXPECT_EQ(HTTP_SUCCESS, error); 1025 EXPECT_EQ(kTestUploadNewFilePath, upload_url.path()); 1026 EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]); 1027 EXPECT_EQ("0", http_request_.headers["X-Upload-Content-Length"]); 1028 1029 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); 1030 EXPECT_EQ("/upload/drive/v2/files?uploadType=resumable", 1031 http_request_.relative_url); 1032 EXPECT_EQ("application/json", http_request_.headers["Content-Type"]); 1033 EXPECT_TRUE(http_request_.has_content); 1034 EXPECT_EQ("{\"parents\":[{" 1035 "\"id\":\"parent_resource_id\"," 1036 "\"kind\":\"drive#fileLink\"" 1037 "}]," 1038 "\"title\":\"new file title\"}", 1039 http_request_.content); 1040 1041 // Upload the content to the upload URL. 1042 UploadRangeResponse response; 1043 scoped_ptr<FileResource> new_entry; 1044 1045 { 1046 base::RunLoop run_loop; 1047 drive::ResumeUploadRequest* resume_request = 1048 new drive::ResumeUploadRequest( 1049 request_sender_.get(), 1050 upload_url, 1051 0, // start_position 1052 0, // end_position (exclusive) 1053 0, // content_length, 1054 kTestContentType, 1055 kTestFilePath, 1056 test_util::CreateQuitCallback( 1057 &run_loop, 1058 test_util::CreateCopyResultCallback(&response, &new_entry)), 1059 ProgressCallback()); 1060 request_sender_->StartRequestWithRetry(resume_request); 1061 run_loop.Run(); 1062 } 1063 1064 // METHOD_PUT should be used to upload data. 1065 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1066 // Request should go to the upload URL. 1067 EXPECT_EQ(upload_url.path(), http_request_.relative_url); 1068 // Content-Range header should NOT be added. 1069 EXPECT_EQ(0U, http_request_.headers.count("Content-Range")); 1070 // The upload content should be set in the HTTP request. 1071 EXPECT_TRUE(http_request_.has_content); 1072 EXPECT_EQ(kTestContent, http_request_.content); 1073 1074 // Check the response. 1075 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file 1076 // The start and end positions should be set to -1, if an upload is complete. 1077 EXPECT_EQ(-1, response.start_position_received); 1078 EXPECT_EQ(-1, response.end_position_received); 1079 } 1080 1081 TEST_F(DriveApiRequestsTest, UploadNewLargeFileRequest) { 1082 // Set an expected url for uploading. 1083 expected_upload_path_ = kTestUploadNewFilePath; 1084 1085 const char kTestContentType[] = "text/plain"; 1086 const size_t kNumChunkBytes = 10; // Num bytes in a chunk. 1087 const std::string kTestContent(100, 'a'); 1088 const base::FilePath kTestFilePath = 1089 temp_dir_.path().AppendASCII("upload_file.txt"); 1090 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kTestContent)); 1091 1092 GDataErrorCode error = GDATA_OTHER_ERROR; 1093 GURL upload_url; 1094 1095 // Initiate uploading a new file to the directory with "parent_resource_id". 1096 { 1097 base::RunLoop run_loop; 1098 drive::InitiateUploadNewFileRequest* request = 1099 new drive::InitiateUploadNewFileRequest( 1100 request_sender_.get(), 1101 *url_generator_, 1102 kTestContentType, 1103 kTestContent.size(), 1104 "parent_resource_id", // The resource id of the parent directory. 1105 "new file title", // The title of the file being uploaded. 1106 test_util::CreateQuitCallback( 1107 &run_loop, 1108 test_util::CreateCopyResultCallback(&error, &upload_url))); 1109 request_sender_->StartRequestWithRetry(request); 1110 run_loop.Run(); 1111 } 1112 1113 EXPECT_EQ(HTTP_SUCCESS, error); 1114 EXPECT_EQ(kTestUploadNewFilePath, upload_url.path()); 1115 EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]); 1116 EXPECT_EQ(base::Int64ToString(kTestContent.size()), 1117 http_request_.headers["X-Upload-Content-Length"]); 1118 1119 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); 1120 EXPECT_EQ("/upload/drive/v2/files?uploadType=resumable", 1121 http_request_.relative_url); 1122 EXPECT_EQ("application/json", http_request_.headers["Content-Type"]); 1123 EXPECT_TRUE(http_request_.has_content); 1124 EXPECT_EQ("{\"parents\":[{" 1125 "\"id\":\"parent_resource_id\"," 1126 "\"kind\":\"drive#fileLink\"" 1127 "}]," 1128 "\"title\":\"new file title\"}", 1129 http_request_.content); 1130 1131 // Before sending any data, check the current status. 1132 // This is an edge case test for GetUploadStatusRequest. 1133 { 1134 UploadRangeResponse response; 1135 scoped_ptr<FileResource> new_entry; 1136 1137 // Check the response by GetUploadStatusRequest. 1138 { 1139 base::RunLoop run_loop; 1140 drive::GetUploadStatusRequest* get_upload_status_request = 1141 new drive::GetUploadStatusRequest( 1142 request_sender_.get(), 1143 upload_url, 1144 kTestContent.size(), 1145 test_util::CreateQuitCallback( 1146 &run_loop, 1147 test_util::CreateCopyResultCallback(&response, &new_entry))); 1148 request_sender_->StartRequestWithRetry(get_upload_status_request); 1149 run_loop.Run(); 1150 } 1151 1152 // METHOD_PUT should be used to upload data. 1153 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1154 // Request should go to the upload URL. 1155 EXPECT_EQ(upload_url.path(), http_request_.relative_url); 1156 // Content-Range header should be added. 1157 EXPECT_EQ("bytes */" + base::Int64ToString(kTestContent.size()), 1158 http_request_.headers["Content-Range"]); 1159 EXPECT_TRUE(http_request_.has_content); 1160 EXPECT_TRUE(http_request_.content.empty()); 1161 1162 // Check the response. 1163 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); 1164 EXPECT_EQ(0, response.start_position_received); 1165 EXPECT_EQ(0, response.end_position_received); 1166 } 1167 1168 // Upload the content to the upload URL. 1169 for (size_t start_position = 0; start_position < kTestContent.size(); 1170 start_position += kNumChunkBytes) { 1171 const std::string payload = kTestContent.substr( 1172 start_position, 1173 std::min(kNumChunkBytes, kTestContent.size() - start_position)); 1174 const size_t end_position = start_position + payload.size(); 1175 1176 UploadRangeResponse response; 1177 scoped_ptr<FileResource> new_entry; 1178 1179 { 1180 base::RunLoop run_loop; 1181 drive::ResumeUploadRequest* resume_request = 1182 new drive::ResumeUploadRequest( 1183 request_sender_.get(), 1184 upload_url, 1185 start_position, 1186 end_position, 1187 kTestContent.size(), // content_length, 1188 kTestContentType, 1189 kTestFilePath, 1190 test_util::CreateQuitCallback( 1191 &run_loop, 1192 test_util::CreateCopyResultCallback(&response, &new_entry)), 1193 ProgressCallback()); 1194 request_sender_->StartRequestWithRetry(resume_request); 1195 run_loop.Run(); 1196 } 1197 1198 // METHOD_PUT should be used to upload data. 1199 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1200 // Request should go to the upload URL. 1201 EXPECT_EQ(upload_url.path(), http_request_.relative_url); 1202 // Content-Range header should be added. 1203 EXPECT_EQ("bytes " + 1204 base::Int64ToString(start_position) + "-" + 1205 base::Int64ToString(end_position - 1) + "/" + 1206 base::Int64ToString(kTestContent.size()), 1207 http_request_.headers["Content-Range"]); 1208 // The upload content should be set in the HTTP request. 1209 EXPECT_TRUE(http_request_.has_content); 1210 EXPECT_EQ(payload, http_request_.content); 1211 1212 if (end_position == kTestContent.size()) { 1213 // Check the response. 1214 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file 1215 // The start and end positions should be set to -1, if an upload is 1216 // complete. 1217 EXPECT_EQ(-1, response.start_position_received); 1218 EXPECT_EQ(-1, response.end_position_received); 1219 break; 1220 } 1221 1222 // Check the response. 1223 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); 1224 EXPECT_EQ(0, response.start_position_received); 1225 EXPECT_EQ(static_cast<int64>(end_position), response.end_position_received); 1226 1227 // Check the response by GetUploadStatusRequest. 1228 { 1229 base::RunLoop run_loop; 1230 drive::GetUploadStatusRequest* get_upload_status_request = 1231 new drive::GetUploadStatusRequest( 1232 request_sender_.get(), 1233 upload_url, 1234 kTestContent.size(), 1235 test_util::CreateQuitCallback( 1236 &run_loop, 1237 test_util::CreateCopyResultCallback(&response, &new_entry))); 1238 request_sender_->StartRequestWithRetry(get_upload_status_request); 1239 run_loop.Run(); 1240 } 1241 1242 // METHOD_PUT should be used to upload data. 1243 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1244 // Request should go to the upload URL. 1245 EXPECT_EQ(upload_url.path(), http_request_.relative_url); 1246 // Content-Range header should be added. 1247 EXPECT_EQ("bytes */" + base::Int64ToString(kTestContent.size()), 1248 http_request_.headers["Content-Range"]); 1249 EXPECT_TRUE(http_request_.has_content); 1250 EXPECT_TRUE(http_request_.content.empty()); 1251 1252 // Check the response. 1253 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); 1254 EXPECT_EQ(0, response.start_position_received); 1255 EXPECT_EQ(static_cast<int64>(end_position), 1256 response.end_position_received); 1257 } 1258 } 1259 1260 TEST_F(DriveApiRequestsTest, UploadExistingFileRequest) { 1261 // Set an expected url for uploading. 1262 expected_upload_path_ = kTestUploadExistingFilePath; 1263 1264 const char kTestContentType[] = "text/plain"; 1265 const std::string kTestContent(100, 'a'); 1266 const base::FilePath kTestFilePath = 1267 temp_dir_.path().AppendASCII("upload_file.txt"); 1268 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kTestContent)); 1269 1270 GDataErrorCode error = GDATA_OTHER_ERROR; 1271 GURL upload_url; 1272 1273 // Initiate uploading a new file to the directory with "parent_resource_id". 1274 { 1275 base::RunLoop run_loop; 1276 drive::InitiateUploadExistingFileRequest* request = 1277 new drive::InitiateUploadExistingFileRequest( 1278 request_sender_.get(), 1279 *url_generator_, 1280 kTestContentType, 1281 kTestContent.size(), 1282 "resource_id", // The resource id of the file to be overwritten. 1283 std::string(), // No etag. 1284 test_util::CreateQuitCallback( 1285 &run_loop, 1286 test_util::CreateCopyResultCallback(&error, &upload_url))); 1287 request_sender_->StartRequestWithRetry(request); 1288 run_loop.Run(); 1289 } 1290 1291 EXPECT_EQ(HTTP_SUCCESS, error); 1292 EXPECT_EQ(kTestUploadExistingFilePath, upload_url.path()); 1293 EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]); 1294 EXPECT_EQ(base::Int64ToString(kTestContent.size()), 1295 http_request_.headers["X-Upload-Content-Length"]); 1296 EXPECT_EQ("*", http_request_.headers["If-Match"]); 1297 1298 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1299 EXPECT_EQ("/upload/drive/v2/files/resource_id?uploadType=resumable", 1300 http_request_.relative_url); 1301 EXPECT_TRUE(http_request_.has_content); 1302 EXPECT_TRUE(http_request_.content.empty()); 1303 1304 // Upload the content to the upload URL. 1305 UploadRangeResponse response; 1306 scoped_ptr<FileResource> new_entry; 1307 1308 { 1309 base::RunLoop run_loop; 1310 drive::ResumeUploadRequest* resume_request = 1311 new drive::ResumeUploadRequest( 1312 request_sender_.get(), 1313 upload_url, 1314 0, // start_position 1315 kTestContent.size(), // end_position (exclusive) 1316 kTestContent.size(), // content_length, 1317 kTestContentType, 1318 kTestFilePath, 1319 test_util::CreateQuitCallback( 1320 &run_loop, 1321 test_util::CreateCopyResultCallback(&response, &new_entry)), 1322 ProgressCallback()); 1323 request_sender_->StartRequestWithRetry(resume_request); 1324 run_loop.Run(); 1325 } 1326 1327 // METHOD_PUT should be used to upload data. 1328 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1329 // Request should go to the upload URL. 1330 EXPECT_EQ(upload_url.path(), http_request_.relative_url); 1331 // Content-Range header should be added. 1332 EXPECT_EQ("bytes 0-" + 1333 base::Int64ToString(kTestContent.size() - 1) + "/" + 1334 base::Int64ToString(kTestContent.size()), 1335 http_request_.headers["Content-Range"]); 1336 // The upload content should be set in the HTTP request. 1337 EXPECT_TRUE(http_request_.has_content); 1338 EXPECT_EQ(kTestContent, http_request_.content); 1339 1340 // Check the response. 1341 EXPECT_EQ(HTTP_SUCCESS, response.code); // Because it's an existing file 1342 // The start and end positions should be set to -1, if an upload is complete. 1343 EXPECT_EQ(-1, response.start_position_received); 1344 EXPECT_EQ(-1, response.end_position_received); 1345 } 1346 1347 TEST_F(DriveApiRequestsTest, UploadExistingFileRequestWithETag) { 1348 // Set an expected url for uploading. 1349 expected_upload_path_ = kTestUploadExistingFilePath; 1350 1351 const char kTestContentType[] = "text/plain"; 1352 const std::string kTestContent(100, 'a'); 1353 const base::FilePath kTestFilePath = 1354 temp_dir_.path().AppendASCII("upload_file.txt"); 1355 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kTestContent)); 1356 1357 GDataErrorCode error = GDATA_OTHER_ERROR; 1358 GURL upload_url; 1359 1360 // Initiate uploading a new file to the directory with "parent_resource_id". 1361 { 1362 base::RunLoop run_loop; 1363 drive::InitiateUploadExistingFileRequest* request = 1364 new drive::InitiateUploadExistingFileRequest( 1365 request_sender_.get(), 1366 *url_generator_, 1367 kTestContentType, 1368 kTestContent.size(), 1369 "resource_id", // The resource id of the file to be overwritten. 1370 kTestETag, 1371 test_util::CreateQuitCallback( 1372 &run_loop, 1373 test_util::CreateCopyResultCallback(&error, &upload_url))); 1374 request_sender_->StartRequestWithRetry(request); 1375 run_loop.Run(); 1376 } 1377 1378 EXPECT_EQ(HTTP_SUCCESS, error); 1379 EXPECT_EQ(kTestUploadExistingFilePath, upload_url.path()); 1380 EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]); 1381 EXPECT_EQ(base::Int64ToString(kTestContent.size()), 1382 http_request_.headers["X-Upload-Content-Length"]); 1383 EXPECT_EQ(kTestETag, http_request_.headers["If-Match"]); 1384 1385 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1386 EXPECT_EQ("/upload/drive/v2/files/resource_id?uploadType=resumable", 1387 http_request_.relative_url); 1388 EXPECT_TRUE(http_request_.has_content); 1389 EXPECT_TRUE(http_request_.content.empty()); 1390 1391 // Upload the content to the upload URL. 1392 UploadRangeResponse response; 1393 scoped_ptr<FileResource> new_entry; 1394 1395 { 1396 base::RunLoop run_loop; 1397 drive::ResumeUploadRequest* resume_request = 1398 new drive::ResumeUploadRequest( 1399 request_sender_.get(), 1400 upload_url, 1401 0, // start_position 1402 kTestContent.size(), // end_position (exclusive) 1403 kTestContent.size(), // content_length, 1404 kTestContentType, 1405 kTestFilePath, 1406 test_util::CreateQuitCallback( 1407 &run_loop, 1408 test_util::CreateCopyResultCallback(&response, &new_entry)), 1409 ProgressCallback()); 1410 request_sender_->StartRequestWithRetry(resume_request); 1411 run_loop.Run(); 1412 } 1413 1414 // METHOD_PUT should be used to upload data. 1415 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1416 // Request should go to the upload URL. 1417 EXPECT_EQ(upload_url.path(), http_request_.relative_url); 1418 // Content-Range header should be added. 1419 EXPECT_EQ("bytes 0-" + 1420 base::Int64ToString(kTestContent.size() - 1) + "/" + 1421 base::Int64ToString(kTestContent.size()), 1422 http_request_.headers["Content-Range"]); 1423 // The upload content should be set in the HTTP request. 1424 EXPECT_TRUE(http_request_.has_content); 1425 EXPECT_EQ(kTestContent, http_request_.content); 1426 1427 // Check the response. 1428 EXPECT_EQ(HTTP_SUCCESS, response.code); // Because it's an existing file 1429 // The start and end positions should be set to -1, if an upload is complete. 1430 EXPECT_EQ(-1, response.start_position_received); 1431 EXPECT_EQ(-1, response.end_position_received); 1432 } 1433 1434 TEST_F(DriveApiRequestsTest, UploadExistingFileRequestWithETagConflicting) { 1435 // Set an expected url for uploading. 1436 expected_upload_path_ = kTestUploadExistingFilePath; 1437 1438 // If it turned out that the etag is conflicting, PRECONDITION_FAILED should 1439 // be returned. 1440 expected_precondition_failed_file_path_ = 1441 test_util::GetTestFilePath("drive/error.json"); 1442 1443 const char kTestContentType[] = "text/plain"; 1444 const std::string kTestContent(100, 'a'); 1445 1446 GDataErrorCode error = GDATA_OTHER_ERROR; 1447 GURL upload_url; 1448 1449 // Initiate uploading a new file to the directory with "parent_resource_id". 1450 { 1451 base::RunLoop run_loop; 1452 drive::InitiateUploadExistingFileRequest* request = 1453 new drive::InitiateUploadExistingFileRequest( 1454 request_sender_.get(), 1455 *url_generator_, 1456 kTestContentType, 1457 kTestContent.size(), 1458 "resource_id", // The resource id of the file to be overwritten. 1459 "Conflicting-etag", 1460 test_util::CreateQuitCallback( 1461 &run_loop, 1462 test_util::CreateCopyResultCallback(&error, &upload_url))); 1463 request_sender_->StartRequestWithRetry(request); 1464 run_loop.Run(); 1465 } 1466 1467 EXPECT_EQ(HTTP_PRECONDITION, error); 1468 EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]); 1469 EXPECT_EQ(base::Int64ToString(kTestContent.size()), 1470 http_request_.headers["X-Upload-Content-Length"]); 1471 EXPECT_EQ("Conflicting-etag", http_request_.headers["If-Match"]); 1472 1473 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1474 EXPECT_EQ("/upload/drive/v2/files/resource_id?uploadType=resumable", 1475 http_request_.relative_url); 1476 EXPECT_TRUE(http_request_.has_content); 1477 EXPECT_TRUE(http_request_.content.empty()); 1478 } 1479 1480 TEST_F(DriveApiRequestsTest, 1481 UploadExistingFileRequestWithETagConflictOnResumeUpload) { 1482 // Set an expected url for uploading. 1483 expected_upload_path_ = kTestUploadExistingFilePath; 1484 1485 const char kTestContentType[] = "text/plain"; 1486 const std::string kTestContent(100, 'a'); 1487 const base::FilePath kTestFilePath = 1488 temp_dir_.path().AppendASCII("upload_file.txt"); 1489 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kTestContent)); 1490 1491 GDataErrorCode error = GDATA_OTHER_ERROR; 1492 GURL upload_url; 1493 1494 // Initiate uploading a new file to the directory with "parent_resource_id". 1495 { 1496 base::RunLoop run_loop; 1497 drive::InitiateUploadExistingFileRequest* request = 1498 new drive::InitiateUploadExistingFileRequest( 1499 request_sender_.get(), 1500 *url_generator_, 1501 kTestContentType, 1502 kTestContent.size(), 1503 "resource_id", // The resource id of the file to be overwritten. 1504 kTestETag, 1505 test_util::CreateQuitCallback( 1506 &run_loop, 1507 test_util::CreateCopyResultCallback(&error, &upload_url))); 1508 request_sender_->StartRequestWithRetry(request); 1509 run_loop.Run(); 1510 } 1511 1512 EXPECT_EQ(HTTP_SUCCESS, error); 1513 EXPECT_EQ(kTestUploadExistingFilePath, upload_url.path()); 1514 EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]); 1515 EXPECT_EQ(base::Int64ToString(kTestContent.size()), 1516 http_request_.headers["X-Upload-Content-Length"]); 1517 EXPECT_EQ(kTestETag, http_request_.headers["If-Match"]); 1518 1519 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1520 EXPECT_EQ("/upload/drive/v2/files/resource_id?uploadType=resumable", 1521 http_request_.relative_url); 1522 EXPECT_TRUE(http_request_.has_content); 1523 EXPECT_TRUE(http_request_.content.empty()); 1524 1525 // Set PRECONDITION_FAILED to the server. This is the emulation of the 1526 // confliction during uploading. 1527 expected_precondition_failed_file_path_ = 1528 test_util::GetTestFilePath("drive/error.json"); 1529 1530 // Upload the content to the upload URL. 1531 UploadRangeResponse response; 1532 scoped_ptr<FileResource> new_entry; 1533 1534 { 1535 base::RunLoop run_loop; 1536 drive::ResumeUploadRequest* resume_request = 1537 new drive::ResumeUploadRequest( 1538 request_sender_.get(), 1539 upload_url, 1540 0, // start_position 1541 kTestContent.size(), // end_position (exclusive) 1542 kTestContent.size(), // content_length, 1543 kTestContentType, 1544 kTestFilePath, 1545 test_util::CreateQuitCallback( 1546 &run_loop, 1547 test_util::CreateCopyResultCallback(&response, &new_entry)), 1548 ProgressCallback()); 1549 request_sender_->StartRequestWithRetry(resume_request); 1550 run_loop.Run(); 1551 } 1552 1553 // METHOD_PUT should be used to upload data. 1554 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); 1555 // Request should go to the upload URL. 1556 EXPECT_EQ(upload_url.path(), http_request_.relative_url); 1557 // Content-Range header should be added. 1558 EXPECT_EQ("bytes 0-" + 1559 base::Int64ToString(kTestContent.size() - 1) + "/" + 1560 base::Int64ToString(kTestContent.size()), 1561 http_request_.headers["Content-Range"]); 1562 // The upload content should be set in the HTTP request. 1563 EXPECT_TRUE(http_request_.has_content); 1564 EXPECT_EQ(kTestContent, http_request_.content); 1565 1566 // Check the response. 1567 EXPECT_EQ(HTTP_PRECONDITION, response.code); 1568 // The start and end positions should be set to -1 for error. 1569 EXPECT_EQ(-1, response.start_position_received); 1570 EXPECT_EQ(-1, response.end_position_received); 1571 1572 // New entry should be NULL. 1573 EXPECT_FALSE(new_entry.get()); 1574 } 1575 1576 TEST_F(DriveApiRequestsTest, DownloadFileRequest) { 1577 const base::FilePath kDownloadedFilePath = 1578 temp_dir_.path().AppendASCII("cache_file"); 1579 const std::string kTestId("dummyId"); 1580 1581 GDataErrorCode result_code = GDATA_OTHER_ERROR; 1582 base::FilePath temp_file; 1583 { 1584 base::RunLoop run_loop; 1585 drive::DownloadFileRequest* request = new drive::DownloadFileRequest( 1586 request_sender_.get(), 1587 *url_generator_, 1588 kTestId, 1589 kDownloadedFilePath, 1590 test_util::CreateQuitCallback( 1591 &run_loop, 1592 test_util::CreateCopyResultCallback(&result_code, &temp_file)), 1593 GetContentCallback(), 1594 ProgressCallback()); 1595 request_sender_->StartRequestWithRetry(request); 1596 run_loop.Run(); 1597 } 1598 1599 std::string contents; 1600 base::ReadFileToString(temp_file, &contents); 1601 base::DeleteFile(temp_file, false); 1602 1603 EXPECT_EQ(HTTP_SUCCESS, result_code); 1604 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); 1605 EXPECT_EQ(kTestDownloadPathPrefix + kTestId, http_request_.relative_url); 1606 EXPECT_EQ(kDownloadedFilePath, temp_file); 1607 1608 const std::string expected_contents = kTestId + kTestId + kTestId; 1609 EXPECT_EQ(expected_contents, contents); 1610 } 1611 1612 TEST_F(DriveApiRequestsTest, DownloadFileRequest_GetContentCallback) { 1613 const base::FilePath kDownloadedFilePath = 1614 temp_dir_.path().AppendASCII("cache_file"); 1615 const std::string kTestId("dummyId"); 1616 1617 GDataErrorCode result_code = GDATA_OTHER_ERROR; 1618 base::FilePath temp_file; 1619 std::string contents; 1620 { 1621 base::RunLoop run_loop; 1622 drive::DownloadFileRequest* request = new drive::DownloadFileRequest( 1623 request_sender_.get(), 1624 *url_generator_, 1625 kTestId, 1626 kDownloadedFilePath, 1627 test_util::CreateQuitCallback( 1628 &run_loop, 1629 test_util::CreateCopyResultCallback(&result_code, &temp_file)), 1630 base::Bind(&AppendContent, &contents), 1631 ProgressCallback()); 1632 request_sender_->StartRequestWithRetry(request); 1633 run_loop.Run(); 1634 } 1635 1636 base::DeleteFile(temp_file, false); 1637 1638 EXPECT_EQ(HTTP_SUCCESS, result_code); 1639 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); 1640 EXPECT_EQ(kTestDownloadPathPrefix + kTestId, http_request_.relative_url); 1641 EXPECT_EQ(kDownloadedFilePath, temp_file); 1642 1643 const std::string expected_contents = kTestId + kTestId + kTestId; 1644 EXPECT_EQ(expected_contents, contents); 1645 } 1646 1647 } // namespace google_apis 1648