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