Home | History | Annotate | Download | only in google_apis
      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