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