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