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