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