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
26namespace google_apis {
27
28namespace {
29
30const char kTestETag[] = "test_etag";
31const char kTestUserAgent[] = "test-user-agent";
32
33const 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
41const char kTestPermissionResponse[] =
42    "{\n"
43    "\"kind\": \"drive#permission\",\n"
44    "\"id\": \"resource_id\",\n"
45    "\"selfLink\": \"self_link\",\n"
46    "}\n";
47
48const char kTestUploadExistingFilePath[] = "/upload/existingfile/path";
49const char kTestUploadNewFilePath[] = "/upload/newfile/path";
50const char kTestDownloadPathPrefix[] = "/download/";
51
52// Used as a GetContentCallback.
53void 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
62class 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
386TEST_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
428TEST_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
485TEST_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
535TEST_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
569TEST_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
596TEST_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
623TEST_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
652TEST_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
679TEST_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
720TEST_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
754TEST_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
782TEST_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
809TEST_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
833TEST_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
863TEST_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
896TEST_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
922TEST_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
1015TEST_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
1103TEST_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
1282TEST_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
1336TEST_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
1423TEST_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
1510TEST_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
1556TEST_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
1652TEST_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
1711TEST_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
1747TEST_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
1782TEST_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@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@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@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