OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 <algorithm> | |
6 #include <map> | |
7 | |
8 #include "base/bind.h" | |
9 #include "base/file_util.h" | |
10 #include "base/files/file_path.h" | |
11 #include "base/files/scoped_temp_dir.h" | |
12 #include "base/json/json_reader.h" | |
13 #include "base/json/json_writer.h" | |
14 #include "base/message_loop/message_loop.h" | |
15 #include "base/run_loop.h" | |
16 #include "base/strings/string_number_conversions.h" | |
17 #include "base/strings/stringprintf.h" | |
18 #include "base/values.h" | |
19 #include "chrome/browser/google_apis/dummy_auth_service.h" | |
20 #include "chrome/browser/google_apis/gdata_wapi_parser.h" | |
21 #include "chrome/browser/google_apis/gdata_wapi_requests.h" | |
22 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h" | |
23 #include "chrome/browser/google_apis/request_sender.h" | |
24 #include "chrome/browser/google_apis/test_util.h" | |
25 #include "net/base/escape.h" | |
26 #include "net/test/embedded_test_server/embedded_test_server.h" | |
27 #include "net/test/embedded_test_server/http_request.h" | |
28 #include "net/test/embedded_test_server/http_response.h" | |
29 #include "net/url_request/url_request_test_util.h" | |
30 #include "testing/gtest/include/gtest/gtest.h" | |
31 | |
32 namespace google_apis { | |
33 | |
34 namespace { | |
35 | |
36 const char kTestUserAgent[] = "test-user-agent"; | |
37 const char kTestETag[] = "test_etag"; | |
38 const char kTestDownloadPathPrefix[] = "/download/"; | |
39 | |
40 class GDataWapiRequestsTest : public testing::Test { | |
41 public: | |
42 GDataWapiRequestsTest() { | |
43 } | |
44 | |
45 virtual void SetUp() OVERRIDE { | |
46 request_context_getter_ = new net::TestURLRequestContextGetter( | |
47 message_loop_.message_loop_proxy()); | |
48 | |
49 request_sender_.reset(new RequestSender(new DummyAuthService, | |
50 request_context_getter_.get(), | |
51 message_loop_.message_loop_proxy(), | |
52 kTestUserAgent)); | |
53 | |
54 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
55 | |
56 ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady()); | |
57 test_server_.RegisterRequestHandler( | |
58 base::Bind(&test_util::HandleDownloadFileRequest, | |
59 test_server_.base_url(), | |
60 base::Unretained(&http_request_))); | |
61 test_server_.RegisterRequestHandler( | |
62 base::Bind(&GDataWapiRequestsTest::HandleResourceFeedRequest, | |
63 base::Unretained(this))); | |
64 test_server_.RegisterRequestHandler( | |
65 base::Bind(&GDataWapiRequestsTest::HandleMetadataRequest, | |
66 base::Unretained(this))); | |
67 test_server_.RegisterRequestHandler( | |
68 base::Bind(&GDataWapiRequestsTest::HandleCreateSessionRequest, | |
69 base::Unretained(this))); | |
70 test_server_.RegisterRequestHandler( | |
71 base::Bind(&GDataWapiRequestsTest::HandleUploadRequest, | |
72 base::Unretained(this))); | |
73 test_server_.RegisterRequestHandler( | |
74 base::Bind(&GDataWapiRequestsTest::HandleDownloadRequest, | |
75 base::Unretained(this))); | |
76 | |
77 GURL test_base_url = test_util::GetBaseUrlForTesting(test_server_.port()); | |
78 url_generator_.reset(new GDataWapiUrlGenerator( | |
79 test_base_url, test_base_url.Resolve(kTestDownloadPathPrefix))); | |
80 | |
81 received_bytes_ = 0; | |
82 content_length_ = 0; | |
83 } | |
84 | |
85 protected: | |
86 // Handles a request for fetching a resource feed. | |
87 scoped_ptr<net::test_server::HttpResponse> HandleResourceFeedRequest( | |
88 const net::test_server::HttpRequest& request) { | |
89 http_request_ = request; | |
90 | |
91 const GURL absolute_url = test_server_.GetURL(request.relative_url); | |
92 std::string remaining_path; | |
93 if (absolute_url.path() == "/feeds/default/private/full" && | |
94 request.method == net::test_server::METHOD_POST) { | |
95 // This is a request for copying a document. | |
96 // TODO(satorux): we should generate valid JSON data for the newly | |
97 // copied document but for now, just return "file_entry.json" | |
98 scoped_ptr<net::test_server::BasicHttpResponse> result( | |
99 test_util::CreateHttpResponseFromFile( | |
100 test_util::GetTestFilePath("gdata/file_entry.json"))); | |
101 return result.PassAs<net::test_server::HttpResponse>(); | |
102 } | |
103 | |
104 if (!test_util::RemovePrefix(absolute_url.path(), | |
105 "/feeds/default/private/full", | |
106 &remaining_path)) { | |
107 return scoped_ptr<net::test_server::HttpResponse>(); | |
108 } | |
109 | |
110 if (remaining_path.empty()) { | |
111 // Process the default feed. | |
112 scoped_ptr<net::test_server::BasicHttpResponse> result( | |
113 test_util::CreateHttpResponseFromFile( | |
114 test_util::GetTestFilePath("gdata/root_feed.json"))); | |
115 return result.PassAs<net::test_server::HttpResponse>(); | |
116 } else { | |
117 // Process a feed for a single resource ID. | |
118 const std::string resource_id = net::UnescapeURLComponent( | |
119 remaining_path.substr(1), net::UnescapeRule::URL_SPECIAL_CHARS); | |
120 if (resource_id == "file:2_file_resource_id") { | |
121 scoped_ptr<net::test_server::BasicHttpResponse> result( | |
122 test_util::CreateHttpResponseFromFile( | |
123 test_util::GetTestFilePath("gdata/file_entry.json"))); | |
124 return result.PassAs<net::test_server::HttpResponse>(); | |
125 } else if (resource_id == "folder:root/contents" && | |
126 request.method == net::test_server::METHOD_POST) { | |
127 // This is a request for creating a directory in the root directory. | |
128 // TODO(satorux): we should generate valid JSON data for the newly | |
129 // created directory but for now, just return "directory_entry.json" | |
130 scoped_ptr<net::test_server::BasicHttpResponse> result( | |
131 test_util::CreateHttpResponseFromFile( | |
132 test_util::GetTestFilePath( | |
133 "gdata/directory_entry.json"))); | |
134 return result.PassAs<net::test_server::HttpResponse>(); | |
135 } else if (resource_id == | |
136 "folder:root/contents/file:2_file_resource_id" && | |
137 request.method == net::test_server::METHOD_DELETE) { | |
138 // This is a request for deleting a file from the root directory. | |
139 // TODO(satorux): Investigate what's returned from the server, and | |
140 // copy it. For now, just return a random file, as the contents don't | |
141 // matter. | |
142 scoped_ptr<net::test_server::BasicHttpResponse> result( | |
143 test_util::CreateHttpResponseFromFile( | |
144 test_util::GetTestFilePath("gdata/testfile.txt"))); | |
145 return result.PassAs<net::test_server::HttpResponse>(); | |
146 } else if (resource_id == "invalid_resource_id") { | |
147 // Check if this is an authorization request for an app. | |
148 // This emulates to return invalid formatted result from the server. | |
149 if (request.method == net::test_server::METHOD_PUT && | |
150 request.content.find("<docs:authorizedApp>") != std::string::npos) { | |
151 scoped_ptr<net::test_server::BasicHttpResponse> result( | |
152 test_util::CreateHttpResponseFromFile( | |
153 test_util::GetTestFilePath("gdata/testfile.txt"))); | |
154 return result.PassAs<net::test_server::HttpResponse>(); | |
155 } | |
156 } | |
157 } | |
158 | |
159 return scoped_ptr<net::test_server::HttpResponse>(); | |
160 } | |
161 | |
162 // Handles a request for fetching a metadata feed. | |
163 scoped_ptr<net::test_server::HttpResponse> HandleMetadataRequest( | |
164 const net::test_server::HttpRequest& request) { | |
165 http_request_ = request; | |
166 | |
167 const GURL absolute_url = test_server_.GetURL(request.relative_url); | |
168 if (absolute_url.path() != "/feeds/metadata/default") | |
169 return scoped_ptr<net::test_server::HttpResponse>(); | |
170 | |
171 scoped_ptr<net::test_server::BasicHttpResponse> result( | |
172 test_util::CreateHttpResponseFromFile( | |
173 test_util::GetTestFilePath( | |
174 "gdata/account_metadata.json"))); | |
175 if (absolute_url.query().find("include-installed-apps=true") == | |
176 string::npos) { | |
177 // Exclude the list of installed apps. | |
178 scoped_ptr<base::Value> parsed_content( | |
179 base::JSONReader::Read(result->content(), base::JSON_PARSE_RFC)); | |
180 CHECK(parsed_content); | |
181 | |
182 // Remove the install apps node. | |
183 base::DictionaryValue* dictionary_value; | |
184 CHECK(parsed_content->GetAsDictionary(&dictionary_value)); | |
185 dictionary_value->Remove("entry.docs$installedApp", NULL); | |
186 | |
187 // Write back it as the content of the result. | |
188 std::string content; | |
189 base::JSONWriter::Write(parsed_content.get(), &content); | |
190 result->set_content(content); | |
191 } | |
192 | |
193 return result.PassAs<net::test_server::HttpResponse>(); | |
194 } | |
195 | |
196 // Handles a request for creating a session for uploading. | |
197 scoped_ptr<net::test_server::HttpResponse> HandleCreateSessionRequest( | |
198 const net::test_server::HttpRequest& request) { | |
199 http_request_ = request; | |
200 | |
201 const GURL absolute_url = test_server_.GetURL(request.relative_url); | |
202 if (StartsWithASCII(absolute_url.path(), | |
203 "/feeds/upload/create-session/default/private/full", | |
204 true)) { // case sensitive | |
205 // This is an initiating upload URL. | |
206 scoped_ptr<net::test_server::BasicHttpResponse> http_response( | |
207 new net::test_server::BasicHttpResponse); | |
208 | |
209 // Check an ETag. | |
210 std::map<std::string, std::string>::const_iterator found = | |
211 request.headers.find("If-Match"); | |
212 if (found != request.headers.end() && | |
213 found->second != "*" && | |
214 found->second != kTestETag) { | |
215 http_response->set_code(net::HTTP_PRECONDITION_FAILED); | |
216 return http_response.PassAs<net::test_server::HttpResponse>(); | |
217 } | |
218 | |
219 // Check if the X-Upload-Content-Length is present. If yes, store the | |
220 // length of the file. | |
221 found = request.headers.find("X-Upload-Content-Length"); | |
222 if (found == request.headers.end() || | |
223 !base::StringToInt64(found->second, &content_length_)) { | |
224 return scoped_ptr<net::test_server::HttpResponse>(); | |
225 } | |
226 received_bytes_ = 0; | |
227 | |
228 http_response->set_code(net::HTTP_OK); | |
229 GURL upload_url; | |
230 // POST is used for a new file, and PUT is used for an existing file. | |
231 if (request.method == net::test_server::METHOD_POST) { | |
232 upload_url = test_server_.GetURL("/upload_new_file"); | |
233 } else if (request.method == net::test_server::METHOD_PUT) { | |
234 upload_url = test_server_.GetURL("/upload_existing_file"); | |
235 } else { | |
236 return scoped_ptr<net::test_server::HttpResponse>(); | |
237 } | |
238 http_response->AddCustomHeader("Location", upload_url.spec()); | |
239 return http_response.PassAs<net::test_server::HttpResponse>(); | |
240 } | |
241 | |
242 return scoped_ptr<net::test_server::HttpResponse>(); | |
243 } | |
244 | |
245 // Handles a request for uploading content. | |
246 scoped_ptr<net::test_server::HttpResponse> HandleUploadRequest( | |
247 const net::test_server::HttpRequest& request) { | |
248 http_request_ = request; | |
249 | |
250 const GURL absolute_url = test_server_.GetURL(request.relative_url); | |
251 if (absolute_url.path() != "/upload_new_file" && | |
252 absolute_url.path() != "/upload_existing_file") { | |
253 return scoped_ptr<net::test_server::HttpResponse>(); | |
254 } | |
255 | |
256 // TODO(satorux): We should create a correct JSON data for the uploaded | |
257 // file, but for now, just return file_entry.json. | |
258 scoped_ptr<net::test_server::BasicHttpResponse> response = | |
259 test_util::CreateHttpResponseFromFile( | |
260 test_util::GetTestFilePath("gdata/file_entry.json")); | |
261 // response.code() is set to SUCCESS. Change it to CREATED if it's a new | |
262 // file. | |
263 if (absolute_url.path() == "/upload_new_file") | |
264 response->set_code(net::HTTP_CREATED); | |
265 | |
266 // Check if the Content-Range header is present. This must be present if | |
267 // the request body is not empty. | |
268 if (!request.content.empty()) { | |
269 std::map<std::string, std::string>::const_iterator iter = | |
270 request.headers.find("Content-Range"); | |
271 if (iter == request.headers.end()) | |
272 return scoped_ptr<net::test_server::HttpResponse>(); | |
273 int64 length = 0; | |
274 int64 start_position = 0; | |
275 int64 end_position = 0; | |
276 if (!test_util::ParseContentRangeHeader(iter->second, | |
277 &start_position, | |
278 &end_position, | |
279 &length)) { | |
280 return scoped_ptr<net::test_server::HttpResponse>(); | |
281 } | |
282 EXPECT_EQ(start_position, received_bytes_); | |
283 EXPECT_EQ(length, content_length_); | |
284 // end_position is inclusive, but so +1 to change the range to byte size. | |
285 received_bytes_ = end_position + 1; | |
286 } | |
287 | |
288 // Add Range header to the response, based on the values of | |
289 // Content-Range header in the request. | |
290 // The header is annotated only when at least one byte is received. | |
291 if (received_bytes_ > 0) { | |
292 response->AddCustomHeader( | |
293 "Range", | |
294 "bytes=0-" + base::Int64ToString(received_bytes_ - 1)); | |
295 } | |
296 | |
297 // Change the code to RESUME_INCOMPLETE if upload is not complete. | |
298 if (received_bytes_ < content_length_) | |
299 response->set_code(static_cast<net::HttpStatusCode>(308)); | |
300 | |
301 return response.PassAs<net::test_server::HttpResponse>(); | |
302 } | |
303 | |
304 // Handles a request for downloading a file. | |
305 scoped_ptr<net::test_server::HttpResponse> HandleDownloadRequest( | |
306 const net::test_server::HttpRequest& request) { | |
307 http_request_ = request; | |
308 | |
309 const GURL absolute_url = test_server_.GetURL(request.relative_url); | |
310 std::string id; | |
311 if (!test_util::RemovePrefix(absolute_url.path(), | |
312 kTestDownloadPathPrefix, | |
313 &id)) { | |
314 return scoped_ptr<net::test_server::HttpResponse>(); | |
315 } | |
316 | |
317 // For testing, returns a text with |id| repeated 3 times. | |
318 scoped_ptr<net::test_server::BasicHttpResponse> response( | |
319 new net::test_server::BasicHttpResponse); | |
320 response->set_code(net::HTTP_OK); | |
321 response->set_content(id + id + id); | |
322 response->set_content_type("text/plain"); | |
323 return response.PassAs<net::test_server::HttpResponse>(); | |
324 } | |
325 | |
326 base::MessageLoopForIO message_loop_; // Test server needs IO thread. | |
327 net::test_server::EmbeddedTestServer test_server_; | |
328 scoped_ptr<RequestSender> request_sender_; | |
329 scoped_ptr<GDataWapiUrlGenerator> url_generator_; | |
330 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; | |
331 base::ScopedTempDir temp_dir_; | |
332 | |
333 // These fields are used to keep the current upload state during a | |
334 // test case. These values are updated by the request from | |
335 // ResumeUploadRequest, and used to construct the response for | |
336 // both ResumeUploadRequest and GetUploadStatusRequest, to emulate | |
337 // the WAPI server. | |
338 int64 received_bytes_; | |
339 int64 content_length_; | |
340 | |
341 // The incoming HTTP request is saved so tests can verify the request | |
342 // parameters like HTTP method (ex. some requests should use DELETE | |
343 // instead of GET). | |
344 net::test_server::HttpRequest http_request_; | |
345 }; | |
346 | |
347 } // namespace | |
348 | |
349 TEST_F(GDataWapiRequestsTest, GetResourceListRequest_DefaultFeed) { | |
350 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
351 scoped_ptr<ResourceList> result_data; | |
352 | |
353 { | |
354 base::RunLoop run_loop; | |
355 GetResourceListRequest* request = new GetResourceListRequest( | |
356 request_sender_.get(), | |
357 *url_generator_, | |
358 GURL(), // Pass an empty URL to use the default feed | |
359 0, // start changestamp | |
360 std::string(), // search string | |
361 std::string(), // directory resource ID | |
362 test_util::CreateQuitCallback( | |
363 &run_loop, | |
364 test_util::CreateCopyResultCallback(&result_code, &result_data))); | |
365 request_sender_->StartRequestWithRetry(request); | |
366 run_loop.Run(); | |
367 } | |
368 | |
369 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
370 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); | |
371 EXPECT_EQ("/feeds/default/private/full?v=3&alt=json&showroot=true&" | |
372 "showfolders=true&include-shared=true&max-results=500", | |
373 http_request_.relative_url); | |
374 | |
375 // Sanity check of the result. | |
376 scoped_ptr<ResourceList> expected( | |
377 ResourceList::ExtractAndParse( | |
378 *test_util::LoadJSONFile("gdata/root_feed.json"))); | |
379 ASSERT_TRUE(result_data); | |
380 EXPECT_EQ(expected->title(), result_data->title()); | |
381 } | |
382 | |
383 TEST_F(GDataWapiRequestsTest, GetResourceListRequest_ValidFeed) { | |
384 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
385 scoped_ptr<ResourceList> result_data; | |
386 | |
387 { | |
388 base::RunLoop run_loop; | |
389 GetResourceListRequest* request = new GetResourceListRequest( | |
390 request_sender_.get(), | |
391 *url_generator_, | |
392 test_server_.GetURL("/files/gdata/root_feed.json"), | |
393 0, // start changestamp | |
394 std::string(), // search string | |
395 std::string(), // directory resource ID | |
396 test_util::CreateQuitCallback( | |
397 &run_loop, | |
398 test_util::CreateCopyResultCallback(&result_code, &result_data))); | |
399 request_sender_->StartRequestWithRetry(request); | |
400 run_loop.Run(); | |
401 } | |
402 | |
403 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
404 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); | |
405 EXPECT_EQ("/files/gdata/root_feed.json?v=3&alt=json&showroot=true&" | |
406 "showfolders=true&include-shared=true&max-results=500", | |
407 http_request_.relative_url); | |
408 | |
409 scoped_ptr<ResourceList> expected( | |
410 ResourceList::ExtractAndParse( | |
411 *test_util::LoadJSONFile("gdata/root_feed.json"))); | |
412 ASSERT_TRUE(result_data); | |
413 EXPECT_EQ(expected->title(), result_data->title()); | |
414 } | |
415 | |
416 TEST_F(GDataWapiRequestsTest, GetResourceListRequest_InvalidFeed) { | |
417 // testfile.txt exists but the response is not JSON, so it should | |
418 // emit a parse error instead. | |
419 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
420 scoped_ptr<ResourceList> result_data; | |
421 | |
422 { | |
423 base::RunLoop run_loop; | |
424 GetResourceListRequest* request = new GetResourceListRequest( | |
425 request_sender_.get(), | |
426 *url_generator_, | |
427 test_server_.GetURL("/files/gdata/testfile.txt"), | |
428 0, // start changestamp | |
429 std::string(), // search string | |
430 std::string(), // directory resource ID | |
431 test_util::CreateQuitCallback( | |
432 &run_loop, | |
433 test_util::CreateCopyResultCallback(&result_code, &result_data))); | |
434 request_sender_->StartRequestWithRetry(request); | |
435 run_loop.Run(); | |
436 } | |
437 | |
438 EXPECT_EQ(GDATA_PARSE_ERROR, result_code); | |
439 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); | |
440 EXPECT_EQ("/files/gdata/testfile.txt?v=3&alt=json&showroot=true&" | |
441 "showfolders=true&include-shared=true&max-results=500", | |
442 http_request_.relative_url); | |
443 EXPECT_FALSE(result_data); | |
444 } | |
445 | |
446 TEST_F(GDataWapiRequestsTest, SearchByTitleRequest) { | |
447 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
448 scoped_ptr<ResourceList> result_data; | |
449 | |
450 { | |
451 base::RunLoop run_loop; | |
452 SearchByTitleRequest* request = new SearchByTitleRequest( | |
453 request_sender_.get(), | |
454 *url_generator_, | |
455 "search-title", | |
456 std::string(), // directory resource id | |
457 test_util::CreateQuitCallback( | |
458 &run_loop, | |
459 test_util::CreateCopyResultCallback(&result_code, &result_data))); | |
460 request_sender_->StartRequestWithRetry(request); | |
461 run_loop.Run(); | |
462 } | |
463 | |
464 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
465 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); | |
466 EXPECT_EQ("/feeds/default/private/full?v=3&alt=json&showroot=true&" | |
467 "showfolders=true&include-shared=true&max-results=500" | |
468 "&title=search-title&title-exact=true", | |
469 http_request_.relative_url); | |
470 EXPECT_TRUE(result_data); | |
471 } | |
472 | |
473 TEST_F(GDataWapiRequestsTest, GetResourceEntryRequest_ValidResourceId) { | |
474 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
475 scoped_ptr<base::Value> result_data; | |
476 | |
477 { | |
478 base::RunLoop run_loop; | |
479 GetResourceEntryRequest* request = new GetResourceEntryRequest( | |
480 request_sender_.get(), | |
481 *url_generator_, | |
482 "file:2_file_resource_id", // resource ID | |
483 GURL(), // embed origin | |
484 test_util::CreateQuitCallback( | |
485 &run_loop, | |
486 test_util::CreateCopyResultCallback(&result_code, &result_data))); | |
487 request_sender_->StartRequestWithRetry(request); | |
488 run_loop.Run(); | |
489 } | |
490 | |
491 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
492 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); | |
493 EXPECT_EQ("/feeds/default/private/full/file%3A2_file_resource_id" | |
494 "?v=3&alt=json&showroot=true", | |
495 http_request_.relative_url); | |
496 scoped_ptr<base::Value> expected_json = | |
497 test_util::LoadJSONFile("gdata/file_entry.json"); | |
498 ASSERT_TRUE(expected_json); | |
499 EXPECT_TRUE(result_data); | |
500 EXPECT_TRUE(base::Value::Equals(expected_json.get(), result_data.get())); | |
501 } | |
502 | |
503 TEST_F(GDataWapiRequestsTest, GetResourceEntryRequest_InvalidResourceId) { | |
504 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
505 scoped_ptr<base::Value> result_data; | |
506 | |
507 { | |
508 base::RunLoop run_loop; | |
509 GetResourceEntryRequest* request = new GetResourceEntryRequest( | |
510 request_sender_.get(), | |
511 *url_generator_, | |
512 "<invalid>", // resource ID | |
513 GURL(), // embed origin | |
514 test_util::CreateQuitCallback( | |
515 &run_loop, | |
516 test_util::CreateCopyResultCallback(&result_code, &result_data))); | |
517 request_sender_->StartRequestWithRetry(request); | |
518 run_loop.Run(); | |
519 } | |
520 | |
521 EXPECT_EQ(HTTP_NOT_FOUND, result_code); | |
522 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); | |
523 EXPECT_EQ("/feeds/default/private/full/%3Cinvalid%3E?v=3&alt=json" | |
524 "&showroot=true", | |
525 http_request_.relative_url); | |
526 ASSERT_FALSE(result_data); | |
527 } | |
528 | |
529 TEST_F(GDataWapiRequestsTest, GetAccountMetadataRequest) { | |
530 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
531 scoped_ptr<AccountMetadata> result_data; | |
532 | |
533 { | |
534 base::RunLoop run_loop; | |
535 GetAccountMetadataRequest* request = new GetAccountMetadataRequest( | |
536 request_sender_.get(), | |
537 *url_generator_, | |
538 test_util::CreateQuitCallback( | |
539 &run_loop, | |
540 test_util::CreateCopyResultCallback(&result_code, &result_data)), | |
541 true); // Include installed apps. | |
542 request_sender_->StartRequestWithRetry(request); | |
543 run_loop.Run(); | |
544 } | |
545 | |
546 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
547 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); | |
548 EXPECT_EQ("/feeds/metadata/default?v=3&alt=json&showroot=true" | |
549 "&include-installed-apps=true", | |
550 http_request_.relative_url); | |
551 | |
552 scoped_ptr<AccountMetadata> expected( | |
553 AccountMetadata::CreateFrom( | |
554 *test_util::LoadJSONFile("gdata/account_metadata.json"))); | |
555 | |
556 ASSERT_TRUE(result_data.get()); | |
557 EXPECT_EQ(expected->largest_changestamp(), | |
558 result_data->largest_changestamp()); | |
559 EXPECT_EQ(expected->quota_bytes_total(), | |
560 result_data->quota_bytes_total()); | |
561 EXPECT_EQ(expected->quota_bytes_used(), | |
562 result_data->quota_bytes_used()); | |
563 | |
564 // Sanity check for installed apps. | |
565 EXPECT_EQ(expected->installed_apps().size(), | |
566 result_data->installed_apps().size()); | |
567 } | |
568 | |
569 TEST_F(GDataWapiRequestsTest, | |
570 GetAccountMetadataRequestWithoutInstalledApps) { | |
571 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
572 scoped_ptr<AccountMetadata> result_data; | |
573 | |
574 { | |
575 base::RunLoop run_loop; | |
576 GetAccountMetadataRequest* request = new GetAccountMetadataRequest( | |
577 request_sender_.get(), | |
578 *url_generator_, | |
579 test_util::CreateQuitCallback( | |
580 &run_loop, | |
581 test_util::CreateCopyResultCallback(&result_code, &result_data)), | |
582 false); // Exclude installed apps. | |
583 request_sender_->StartRequestWithRetry(request); | |
584 run_loop.Run(); | |
585 } | |
586 | |
587 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
588 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); | |
589 EXPECT_EQ("/feeds/metadata/default?v=3&alt=json&showroot=true", | |
590 http_request_.relative_url); | |
591 | |
592 scoped_ptr<AccountMetadata> expected( | |
593 AccountMetadata::CreateFrom( | |
594 *test_util::LoadJSONFile("gdata/account_metadata.json"))); | |
595 | |
596 ASSERT_TRUE(result_data.get()); | |
597 EXPECT_EQ(expected->largest_changestamp(), | |
598 result_data->largest_changestamp()); | |
599 EXPECT_EQ(expected->quota_bytes_total(), | |
600 result_data->quota_bytes_total()); | |
601 EXPECT_EQ(expected->quota_bytes_used(), | |
602 result_data->quota_bytes_used()); | |
603 | |
604 // Installed apps shouldn't be included. | |
605 EXPECT_EQ(0U, result_data->installed_apps().size()); | |
606 } | |
607 | |
608 TEST_F(GDataWapiRequestsTest, DeleteResourceRequest) { | |
609 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
610 | |
611 { | |
612 base::RunLoop run_loop; | |
613 DeleteResourceRequest* request = new DeleteResourceRequest( | |
614 request_sender_.get(), | |
615 *url_generator_, | |
616 test_util::CreateQuitCallback( | |
617 &run_loop, | |
618 test_util::CreateCopyResultCallback(&result_code)), | |
619 "file:2_file_resource_id", | |
620 std::string()); | |
621 | |
622 request_sender_->StartRequestWithRetry(request); | |
623 run_loop.Run(); | |
624 } | |
625 | |
626 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
627 EXPECT_EQ(net::test_server::METHOD_DELETE, http_request_.method); | |
628 EXPECT_EQ( | |
629 "/feeds/default/private/full/file%3A2_file_resource_id?v=3&alt=json" | |
630 "&showroot=true", | |
631 http_request_.relative_url); | |
632 EXPECT_EQ("*", http_request_.headers["If-Match"]); | |
633 } | |
634 | |
635 TEST_F(GDataWapiRequestsTest, DeleteResourceRequestWithETag) { | |
636 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
637 | |
638 { | |
639 base::RunLoop run_loop; | |
640 DeleteResourceRequest* request = new DeleteResourceRequest( | |
641 request_sender_.get(), | |
642 *url_generator_, | |
643 test_util::CreateQuitCallback( | |
644 &run_loop, | |
645 test_util::CreateCopyResultCallback(&result_code)), | |
646 "file:2_file_resource_id", | |
647 "etag"); | |
648 | |
649 request_sender_->StartRequestWithRetry(request); | |
650 run_loop.Run(); | |
651 } | |
652 | |
653 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
654 EXPECT_EQ(net::test_server::METHOD_DELETE, http_request_.method); | |
655 EXPECT_EQ( | |
656 "/feeds/default/private/full/file%3A2_file_resource_id?v=3&alt=json" | |
657 "&showroot=true", | |
658 http_request_.relative_url); | |
659 EXPECT_EQ("etag", http_request_.headers["If-Match"]); | |
660 } | |
661 | |
662 TEST_F(GDataWapiRequestsTest, CreateDirectoryRequest) { | |
663 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
664 scoped_ptr<base::Value> result_data; | |
665 | |
666 // Create "new directory" in the root directory. | |
667 { | |
668 base::RunLoop run_loop; | |
669 CreateDirectoryRequest* request = new CreateDirectoryRequest( | |
670 request_sender_.get(), | |
671 *url_generator_, | |
672 test_util::CreateQuitCallback( | |
673 &run_loop, | |
674 test_util::CreateCopyResultCallback(&result_code, &result_data)), | |
675 "folder:root", | |
676 "new directory"); | |
677 | |
678 request_sender_->StartRequestWithRetry(request); | |
679 run_loop.Run(); | |
680 } | |
681 | |
682 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
683 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); | |
684 EXPECT_EQ("/feeds/default/private/full/folder%3Aroot/contents?v=3&alt=json" | |
685 "&showroot=true", | |
686 http_request_.relative_url); | |
687 EXPECT_EQ("application/atom+xml", http_request_.headers["Content-Type"]); | |
688 | |
689 EXPECT_TRUE(http_request_.has_content); | |
690 EXPECT_EQ("<?xml version=\"1.0\"?>\n" | |
691 "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n" | |
692 " <category scheme=\"http://schemas.google.com/g/2005#kind\" " | |
693 "term=\"http://schemas.google.com/docs/2007#folder\"/>\n" | |
694 " <title>new directory</title>\n" | |
695 "</entry>\n", | |
696 http_request_.content); | |
697 } | |
698 | |
699 TEST_F(GDataWapiRequestsTest, CopyHostedDocumentRequest) { | |
700 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
701 scoped_ptr<base::Value> result_data; | |
702 | |
703 // Copy a document with a new name "New Document". | |
704 { | |
705 base::RunLoop run_loop; | |
706 CopyHostedDocumentRequest* request = new CopyHostedDocumentRequest( | |
707 request_sender_.get(), | |
708 *url_generator_, | |
709 test_util::CreateQuitCallback( | |
710 &run_loop, | |
711 test_util::CreateCopyResultCallback(&result_code, &result_data)), | |
712 "document:5_document_resource_id", // source resource ID | |
713 "New Document"); | |
714 | |
715 request_sender_->StartRequestWithRetry(request); | |
716 run_loop.Run(); | |
717 } | |
718 | |
719 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
720 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); | |
721 EXPECT_EQ("/feeds/default/private/full?v=3&alt=json&showroot=true", | |
722 http_request_.relative_url); | |
723 EXPECT_EQ("application/atom+xml", http_request_.headers["Content-Type"]); | |
724 | |
725 EXPECT_TRUE(http_request_.has_content); | |
726 EXPECT_EQ("<?xml version=\"1.0\"?>\n" | |
727 "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n" | |
728 " <id>document:5_document_resource_id</id>\n" | |
729 " <title>New Document</title>\n" | |
730 "</entry>\n", | |
731 http_request_.content); | |
732 } | |
733 | |
734 TEST_F(GDataWapiRequestsTest, RenameResourceRequest) { | |
735 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
736 | |
737 // Rename a file with a new name "New File". | |
738 { | |
739 base::RunLoop run_loop; | |
740 RenameResourceRequest* request = new RenameResourceRequest( | |
741 request_sender_.get(), | |
742 *url_generator_, | |
743 test_util::CreateQuitCallback( | |
744 &run_loop, | |
745 test_util::CreateCopyResultCallback(&result_code)), | |
746 "file:2_file_resource_id", | |
747 "New File"); | |
748 | |
749 request_sender_->StartRequestWithRetry(request); | |
750 run_loop.Run(); | |
751 } | |
752 | |
753 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
754 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
755 EXPECT_EQ( | |
756 "/feeds/default/private/full/file%3A2_file_resource_id?v=3&alt=json" | |
757 "&showroot=true", | |
758 http_request_.relative_url); | |
759 EXPECT_EQ("application/atom+xml", http_request_.headers["Content-Type"]); | |
760 EXPECT_EQ("*", http_request_.headers["If-Match"]); | |
761 | |
762 EXPECT_TRUE(http_request_.has_content); | |
763 EXPECT_EQ("<?xml version=\"1.0\"?>\n" | |
764 "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n" | |
765 " <title>New File</title>\n" | |
766 "</entry>\n", | |
767 http_request_.content); | |
768 } | |
769 | |
770 TEST_F(GDataWapiRequestsTest, AuthorizeAppRequest_ValidFeed) { | |
771 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
772 GURL result_data; | |
773 | |
774 // Authorize an app with APP_ID to access to a document. | |
775 { | |
776 base::RunLoop run_loop; | |
777 AuthorizeAppRequest* request = new AuthorizeAppRequest( | |
778 request_sender_.get(), | |
779 *url_generator_, | |
780 test_util::CreateQuitCallback( | |
781 &run_loop, | |
782 test_util::CreateCopyResultCallback(&result_code, &result_data)), | |
783 "file:2_file_resource_id", | |
784 "the_app_id"); | |
785 | |
786 request_sender_->StartRequestWithRetry(request); | |
787 run_loop.Run(); | |
788 } | |
789 | |
790 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
791 EXPECT_EQ(GURL("https://entry1_open_with_link/"), result_data); | |
792 | |
793 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
794 EXPECT_EQ("/feeds/default/private/full/file%3A2_file_resource_id" | |
795 "?v=3&alt=json&showroot=true", | |
796 http_request_.relative_url); | |
797 EXPECT_EQ("application/atom+xml", http_request_.headers["Content-Type"]); | |
798 EXPECT_EQ("*", http_request_.headers["If-Match"]); | |
799 | |
800 EXPECT_TRUE(http_request_.has_content); | |
801 EXPECT_EQ("<?xml version=\"1.0\"?>\n" | |
802 "<entry xmlns=\"http://www.w3.org/2005/Atom\" " | |
803 "xmlns:docs=\"http://schemas.google.com/docs/2007\">\n" | |
804 " <docs:authorizedApp>the_app_id</docs:authorizedApp>\n" | |
805 "</entry>\n", | |
806 http_request_.content); | |
807 } | |
808 | |
809 TEST_F(GDataWapiRequestsTest, AuthorizeAppRequest_NotFound) { | |
810 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
811 GURL result_data; | |
812 | |
813 // Authorize an app with APP_ID to access to a document. | |
814 { | |
815 base::RunLoop run_loop; | |
816 AuthorizeAppRequest* request = new AuthorizeAppRequest( | |
817 request_sender_.get(), | |
818 *url_generator_, | |
819 test_util::CreateQuitCallback( | |
820 &run_loop, | |
821 test_util::CreateCopyResultCallback(&result_code, &result_data)), | |
822 "file:2_file_resource_id", | |
823 "unauthorized_app_id"); | |
824 | |
825 request_sender_->StartRequestWithRetry(request); | |
826 run_loop.Run(); | |
827 } | |
828 | |
829 EXPECT_EQ(GDATA_OTHER_ERROR, result_code); | |
830 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
831 EXPECT_EQ("/feeds/default/private/full/file%3A2_file_resource_id" | |
832 "?v=3&alt=json&showroot=true", | |
833 http_request_.relative_url); | |
834 EXPECT_EQ("application/atom+xml", http_request_.headers["Content-Type"]); | |
835 EXPECT_EQ("*", http_request_.headers["If-Match"]); | |
836 | |
837 EXPECT_TRUE(http_request_.has_content); | |
838 EXPECT_EQ("<?xml version=\"1.0\"?>\n" | |
839 "<entry xmlns=\"http://www.w3.org/2005/Atom\" " | |
840 "xmlns:docs=\"http://schemas.google.com/docs/2007\">\n" | |
841 " <docs:authorizedApp>unauthorized_app_id</docs:authorizedApp>\n" | |
842 "</entry>\n", | |
843 http_request_.content); | |
844 } | |
845 | |
846 TEST_F(GDataWapiRequestsTest, AuthorizeAppRequest_InvalidFeed) { | |
847 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
848 GURL result_data; | |
849 | |
850 // Authorize an app with APP_ID to access to a document but an invalid feed. | |
851 { | |
852 base::RunLoop run_loop; | |
853 AuthorizeAppRequest* request = new AuthorizeAppRequest( | |
854 request_sender_.get(), | |
855 *url_generator_, | |
856 test_util::CreateQuitCallback( | |
857 &run_loop, | |
858 test_util::CreateCopyResultCallback(&result_code, &result_data)), | |
859 "invalid_resource_id", | |
860 "APP_ID"); | |
861 | |
862 request_sender_->StartRequestWithRetry(request); | |
863 run_loop.Run(); | |
864 } | |
865 | |
866 EXPECT_EQ(GDATA_PARSE_ERROR, result_code); | |
867 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
868 EXPECT_EQ("/feeds/default/private/full/invalid_resource_id" | |
869 "?v=3&alt=json&showroot=true", | |
870 http_request_.relative_url); | |
871 EXPECT_EQ("application/atom+xml", http_request_.headers["Content-Type"]); | |
872 EXPECT_EQ("*", http_request_.headers["If-Match"]); | |
873 | |
874 EXPECT_TRUE(http_request_.has_content); | |
875 EXPECT_EQ("<?xml version=\"1.0\"?>\n" | |
876 "<entry xmlns=\"http://www.w3.org/2005/Atom\" " | |
877 "xmlns:docs=\"http://schemas.google.com/docs/2007\">\n" | |
878 " <docs:authorizedApp>APP_ID</docs:authorizedApp>\n" | |
879 "</entry>\n", | |
880 http_request_.content); | |
881 } | |
882 | |
883 TEST_F(GDataWapiRequestsTest, AddResourceToDirectoryRequest) { | |
884 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
885 | |
886 // Add a file to the root directory. | |
887 { | |
888 base::RunLoop run_loop; | |
889 AddResourceToDirectoryRequest* request = | |
890 new AddResourceToDirectoryRequest( | |
891 request_sender_.get(), | |
892 *url_generator_, | |
893 test_util::CreateQuitCallback( | |
894 &run_loop, | |
895 test_util::CreateCopyResultCallback(&result_code)), | |
896 "folder:root", | |
897 "file:2_file_resource_id"); | |
898 | |
899 request_sender_->StartRequestWithRetry(request); | |
900 run_loop.Run(); | |
901 } | |
902 | |
903 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
904 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); | |
905 EXPECT_EQ("/feeds/default/private/full/folder%3Aroot/contents?v=3&alt=json" | |
906 "&showroot=true", | |
907 http_request_.relative_url); | |
908 EXPECT_EQ("application/atom+xml", http_request_.headers["Content-Type"]); | |
909 | |
910 EXPECT_TRUE(http_request_.has_content); | |
911 EXPECT_EQ(base::StringPrintf("<?xml version=\"1.0\"?>\n" | |
912 "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n" | |
913 " <id>%sfeeds/default/private/full/" | |
914 "file%%3A2_file_resource_id</id>\n" | |
915 "</entry>\n", | |
916 test_server_.base_url().spec().c_str()), | |
917 http_request_.content); | |
918 } | |
919 | |
920 TEST_F(GDataWapiRequestsTest, RemoveResourceFromDirectoryRequest) { | |
921 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
922 | |
923 // Remove a file from the root directory. | |
924 { | |
925 base::RunLoop run_loop; | |
926 RemoveResourceFromDirectoryRequest* request = | |
927 new RemoveResourceFromDirectoryRequest( | |
928 request_sender_.get(), | |
929 *url_generator_, | |
930 test_util::CreateQuitCallback( | |
931 &run_loop, | |
932 test_util::CreateCopyResultCallback(&result_code)), | |
933 "folder:root", | |
934 "file:2_file_resource_id"); | |
935 | |
936 request_sender_->StartRequestWithRetry(request); | |
937 run_loop.Run(); | |
938 } | |
939 | |
940 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
941 // DELETE method should be used, without the body content. | |
942 EXPECT_EQ(net::test_server::METHOD_DELETE, http_request_.method); | |
943 EXPECT_EQ("/feeds/default/private/full/folder%3Aroot/contents/" | |
944 "file%3A2_file_resource_id?v=3&alt=json&showroot=true", | |
945 http_request_.relative_url); | |
946 EXPECT_EQ("*", http_request_.headers["If-Match"]); | |
947 EXPECT_FALSE(http_request_.has_content); | |
948 } | |
949 | |
950 // This test exercises InitiateUploadNewFileRequest and | |
951 // ResumeUploadRequest for a scenario of uploading a new file. | |
952 TEST_F(GDataWapiRequestsTest, UploadNewFile) { | |
953 const std::string kUploadContent = "hello"; | |
954 const base::FilePath kTestFilePath = | |
955 temp_dir_.path().AppendASCII("upload_file.txt"); | |
956 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kUploadContent)); | |
957 | |
958 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
959 GURL upload_url; | |
960 | |
961 // 1) Get the upload URL for uploading a new file. | |
962 { | |
963 base::RunLoop run_loop; | |
964 InitiateUploadNewFileRequest* initiate_request = | |
965 new InitiateUploadNewFileRequest( | |
966 request_sender_.get(), | |
967 *url_generator_, | |
968 test_util::CreateQuitCallback( | |
969 &run_loop, | |
970 test_util::CreateCopyResultCallback(&result_code, &upload_url)), | |
971 "text/plain", | |
972 kUploadContent.size(), | |
973 "folder:id", | |
974 "New file"); | |
975 request_sender_->StartRequestWithRetry(initiate_request); | |
976 run_loop.Run(); | |
977 } | |
978 | |
979 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
980 EXPECT_EQ(test_server_.GetURL("/upload_new_file"), upload_url); | |
981 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); | |
982 // convert=false should be passed as files should be uploaded as-is. | |
983 EXPECT_EQ( | |
984 "/feeds/upload/create-session/default/private/full/folder%3Aid/contents" | |
985 "?convert=false&v=3&alt=json&showroot=true", | |
986 http_request_.relative_url); | |
987 EXPECT_EQ("text/plain", http_request_.headers["X-Upload-Content-Type"]); | |
988 EXPECT_EQ("application/atom+xml", http_request_.headers["Content-Type"]); | |
989 EXPECT_EQ(base::Int64ToString(kUploadContent.size()), | |
990 http_request_.headers["X-Upload-Content-Length"]); | |
991 | |
992 EXPECT_TRUE(http_request_.has_content); | |
993 EXPECT_EQ("<?xml version=\"1.0\"?>\n" | |
994 "<entry xmlns=\"http://www.w3.org/2005/Atom\" " | |
995 "xmlns:docs=\"http://schemas.google.com/docs/2007\">\n" | |
996 " <title>New file</title>\n" | |
997 "</entry>\n", | |
998 http_request_.content); | |
999 | |
1000 // 2) Upload the content to the upload URL. | |
1001 UploadRangeResponse response; | |
1002 scoped_ptr<ResourceEntry> new_entry; | |
1003 | |
1004 { | |
1005 base::RunLoop run_loop; | |
1006 ResumeUploadRequest* resume_request = new ResumeUploadRequest( | |
1007 request_sender_.get(), | |
1008 test_util::CreateQuitCallback( | |
1009 &run_loop, | |
1010 test_util::CreateCopyResultCallback(&response, &new_entry)), | |
1011 ProgressCallback(), | |
1012 upload_url, | |
1013 0, // start_position | |
1014 kUploadContent.size(), // end_position (exclusive) | |
1015 kUploadContent.size(), // content_length, | |
1016 "text/plain", // content_type | |
1017 kTestFilePath); | |
1018 | |
1019 request_sender_->StartRequestWithRetry(resume_request); | |
1020 run_loop.Run(); | |
1021 } | |
1022 | |
1023 // METHOD_PUT should be used to upload data. | |
1024 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
1025 // Request should go to the upload URL. | |
1026 EXPECT_EQ(upload_url.path(), http_request_.relative_url); | |
1027 // Content-Range header should be added. | |
1028 EXPECT_EQ("bytes 0-" + | |
1029 base::Int64ToString(kUploadContent.size() -1) + "/" + | |
1030 base::Int64ToString(kUploadContent.size()), | |
1031 http_request_.headers["Content-Range"]); | |
1032 // The upload content should be set in the HTTP request. | |
1033 EXPECT_TRUE(http_request_.has_content); | |
1034 EXPECT_EQ(kUploadContent, http_request_.content); | |
1035 | |
1036 // Check the response. | |
1037 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file | |
1038 // The start and end positions should be set to -1, if an upload is complete. | |
1039 EXPECT_EQ(-1, response.start_position_received); | |
1040 EXPECT_EQ(-1, response.end_position_received); | |
1041 } | |
1042 | |
1043 // This test exercises InitiateUploadNewFileRequest and ResumeUploadRequest | |
1044 // for a scenario of uploading a new *large* file, which requires multiple | |
1045 // requests of ResumeUploadRequest. GetUploadRequest is also tested in this | |
1046 // test case. | |
1047 TEST_F(GDataWapiRequestsTest, UploadNewLargeFile) { | |
1048 const size_t kMaxNumBytes = 10; | |
1049 // This is big enough to cause multiple requests of ResumeUploadRequest | |
1050 // as we are going to send at most kMaxNumBytes at a time. | |
1051 // So, sending "kMaxNumBytes * 2 + 1" bytes ensures three | |
1052 // ResumeUploadRequests, which are start, middle and last requests. | |
1053 const std::string kUploadContent(kMaxNumBytes * 2 + 1, 'a'); | |
1054 const base::FilePath kTestFilePath = | |
1055 temp_dir_.path().AppendASCII("upload_file.txt"); | |
1056 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kUploadContent)); | |
1057 | |
1058 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
1059 GURL upload_url; | |
1060 | |
1061 // 1) Get the upload URL for uploading a new file. | |
1062 { | |
1063 base::RunLoop run_loop; | |
1064 InitiateUploadNewFileRequest* initiate_request = | |
1065 new InitiateUploadNewFileRequest( | |
1066 request_sender_.get(), | |
1067 *url_generator_, | |
1068 test_util::CreateQuitCallback( | |
1069 &run_loop, | |
1070 test_util::CreateCopyResultCallback(&result_code, &upload_url)), | |
1071 "text/plain", | |
1072 kUploadContent.size(), | |
1073 "folder:id", | |
1074 "New file"); | |
1075 request_sender_->StartRequestWithRetry(initiate_request); | |
1076 run_loop.Run(); | |
1077 } | |
1078 | |
1079 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
1080 EXPECT_EQ(test_server_.GetURL("/upload_new_file"), upload_url); | |
1081 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); | |
1082 // convert=false should be passed as files should be uploaded as-is. | |
1083 EXPECT_EQ( | |
1084 "/feeds/upload/create-session/default/private/full/folder%3Aid/contents" | |
1085 "?convert=false&v=3&alt=json&showroot=true", | |
1086 http_request_.relative_url); | |
1087 EXPECT_EQ("text/plain", http_request_.headers["X-Upload-Content-Type"]); | |
1088 EXPECT_EQ("application/atom+xml", http_request_.headers["Content-Type"]); | |
1089 EXPECT_EQ(base::Int64ToString(kUploadContent.size()), | |
1090 http_request_.headers["X-Upload-Content-Length"]); | |
1091 | |
1092 EXPECT_TRUE(http_request_.has_content); | |
1093 EXPECT_EQ("<?xml version=\"1.0\"?>\n" | |
1094 "<entry xmlns=\"http://www.w3.org/2005/Atom\" " | |
1095 "xmlns:docs=\"http://schemas.google.com/docs/2007\">\n" | |
1096 " <title>New file</title>\n" | |
1097 "</entry>\n", | |
1098 http_request_.content); | |
1099 | |
1100 // 2) Before sending any data, check the current status. | |
1101 // This is an edge case test for GetUploadStatusRequest | |
1102 // (UploadRangeRequestBase). | |
1103 { | |
1104 UploadRangeResponse response; | |
1105 scoped_ptr<ResourceEntry> new_entry; | |
1106 | |
1107 // Check the response by GetUploadStatusRequest. | |
1108 { | |
1109 base::RunLoop run_loop; | |
1110 GetUploadStatusRequest* get_upload_status_request = | |
1111 new GetUploadStatusRequest( | |
1112 request_sender_.get(), | |
1113 test_util::CreateQuitCallback( | |
1114 &run_loop, | |
1115 test_util::CreateCopyResultCallback(&response, &new_entry)), | |
1116 upload_url, | |
1117 kUploadContent.size()); | |
1118 request_sender_->StartRequestWithRetry(get_upload_status_request); | |
1119 run_loop.Run(); | |
1120 } | |
1121 | |
1122 // METHOD_PUT should be used to upload data. | |
1123 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
1124 // Request should go to the upload URL. | |
1125 EXPECT_EQ(upload_url.path(), http_request_.relative_url); | |
1126 // Content-Range header should be added. | |
1127 EXPECT_EQ("bytes */" + base::Int64ToString(kUploadContent.size()), | |
1128 http_request_.headers["Content-Range"]); | |
1129 EXPECT_TRUE(http_request_.has_content); | |
1130 EXPECT_TRUE(http_request_.content.empty()); | |
1131 | |
1132 // Check the response. | |
1133 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); | |
1134 EXPECT_EQ(0, response.start_position_received); | |
1135 EXPECT_EQ(0, response.end_position_received); | |
1136 } | |
1137 | |
1138 // 3) Upload the content to the upload URL with multiple requests. | |
1139 size_t num_bytes_consumed = 0; | |
1140 for (size_t start_position = 0; start_position < kUploadContent.size(); | |
1141 start_position += kMaxNumBytes) { | |
1142 SCOPED_TRACE(testing::Message("start_position: ") << start_position); | |
1143 | |
1144 // The payload is at most kMaxNumBytes. | |
1145 const size_t remaining_size = kUploadContent.size() - start_position; | |
1146 const std::string payload = kUploadContent.substr( | |
1147 start_position, std::min(kMaxNumBytes, remaining_size)); | |
1148 num_bytes_consumed += payload.size(); | |
1149 // The end position is exclusive. | |
1150 const size_t end_position = start_position + payload.size(); | |
1151 | |
1152 UploadRangeResponse response; | |
1153 scoped_ptr<ResourceEntry> new_entry; | |
1154 | |
1155 { | |
1156 base::RunLoop run_loop; | |
1157 ResumeUploadRequest* resume_request = new ResumeUploadRequest( | |
1158 request_sender_.get(), | |
1159 test_util::CreateQuitCallback( | |
1160 &run_loop, | |
1161 test_util::CreateCopyResultCallback(&response, &new_entry)), | |
1162 ProgressCallback(), | |
1163 upload_url, | |
1164 start_position, | |
1165 end_position, | |
1166 kUploadContent.size(), // content_length, | |
1167 "text/plain", // content_type | |
1168 kTestFilePath); | |
1169 request_sender_->StartRequestWithRetry(resume_request); | |
1170 run_loop.Run(); | |
1171 } | |
1172 | |
1173 // METHOD_PUT should be used to upload data. | |
1174 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
1175 // Request should go to the upload URL. | |
1176 EXPECT_EQ(upload_url.path(), http_request_.relative_url); | |
1177 // Content-Range header should be added. | |
1178 EXPECT_EQ("bytes " + | |
1179 base::Int64ToString(start_position) + "-" + | |
1180 base::Int64ToString(end_position - 1) + "/" + | |
1181 base::Int64ToString(kUploadContent.size()), | |
1182 http_request_.headers["Content-Range"]); | |
1183 // The upload content should be set in the HTTP request. | |
1184 EXPECT_TRUE(http_request_.has_content); | |
1185 EXPECT_EQ(payload, http_request_.content); | |
1186 | |
1187 // Check the response. | |
1188 if (payload.size() == remaining_size) { | |
1189 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file. | |
1190 // The start and end positions should be set to -1, if an upload is | |
1191 // complete. | |
1192 EXPECT_EQ(-1, response.start_position_received); | |
1193 EXPECT_EQ(-1, response.end_position_received); | |
1194 // The upload process is completed, so exit from the loop. | |
1195 break; | |
1196 } | |
1197 | |
1198 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); | |
1199 EXPECT_EQ(0, response.start_position_received); | |
1200 EXPECT_EQ(static_cast<int64>(end_position), | |
1201 response.end_position_received); | |
1202 | |
1203 // Check the response by GetUploadStatusRequest. | |
1204 { | |
1205 base::RunLoop run_loop; | |
1206 GetUploadStatusRequest* get_upload_status_request = | |
1207 new GetUploadStatusRequest( | |
1208 request_sender_.get(), | |
1209 test_util::CreateQuitCallback( | |
1210 &run_loop, | |
1211 test_util::CreateCopyResultCallback(&response, &new_entry)), | |
1212 upload_url, | |
1213 kUploadContent.size()); | |
1214 request_sender_->StartRequestWithRetry(get_upload_status_request); | |
1215 run_loop.Run(); | |
1216 } | |
1217 | |
1218 // METHOD_PUT should be used to upload data. | |
1219 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
1220 // Request should go to the upload URL. | |
1221 EXPECT_EQ(upload_url.path(), http_request_.relative_url); | |
1222 // Content-Range header should be added. | |
1223 EXPECT_EQ("bytes */" + base::Int64ToString(kUploadContent.size()), | |
1224 http_request_.headers["Content-Range"]); | |
1225 EXPECT_TRUE(http_request_.has_content); | |
1226 EXPECT_TRUE(http_request_.content.empty()); | |
1227 | |
1228 // Check the response. | |
1229 EXPECT_EQ(HTTP_RESUME_INCOMPLETE, response.code); | |
1230 EXPECT_EQ(0, response.start_position_received); | |
1231 EXPECT_EQ(static_cast<int64>(end_position), | |
1232 response.end_position_received); | |
1233 } | |
1234 | |
1235 EXPECT_EQ(kUploadContent.size(), num_bytes_consumed); | |
1236 } | |
1237 | |
1238 // This test exercises InitiateUploadNewFileRequest and ResumeUploadRequest | |
1239 // for a scenario of uploading a new *empty* file. | |
1240 // | |
1241 // The test is almost identical to UploadNewFile. The only difference is the | |
1242 // expectation for the Content-Range header. | |
1243 TEST_F(GDataWapiRequestsTest, UploadNewEmptyFile) { | |
1244 const std::string kUploadContent; | |
1245 const base::FilePath kTestFilePath = | |
1246 temp_dir_.path().AppendASCII("empty_file.txt"); | |
1247 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kUploadContent)); | |
1248 | |
1249 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
1250 GURL upload_url; | |
1251 | |
1252 // 1) Get the upload URL for uploading a new file. | |
1253 { | |
1254 base::RunLoop run_loop; | |
1255 InitiateUploadNewFileRequest* initiate_request = | |
1256 new InitiateUploadNewFileRequest( | |
1257 request_sender_.get(), | |
1258 *url_generator_, | |
1259 test_util::CreateQuitCallback( | |
1260 &run_loop, | |
1261 test_util::CreateCopyResultCallback(&result_code, &upload_url)), | |
1262 "text/plain", | |
1263 kUploadContent.size(), | |
1264 "folder:id", | |
1265 "New file"); | |
1266 request_sender_->StartRequestWithRetry(initiate_request); | |
1267 run_loop.Run(); | |
1268 } | |
1269 | |
1270 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
1271 EXPECT_EQ(test_server_.GetURL("/upload_new_file"), upload_url); | |
1272 EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method); | |
1273 // convert=false should be passed as files should be uploaded as-is. | |
1274 EXPECT_EQ( | |
1275 "/feeds/upload/create-session/default/private/full/folder%3Aid/contents" | |
1276 "?convert=false&v=3&alt=json&showroot=true", | |
1277 http_request_.relative_url); | |
1278 EXPECT_EQ("text/plain", http_request_.headers["X-Upload-Content-Type"]); | |
1279 EXPECT_EQ("application/atom+xml", http_request_.headers["Content-Type"]); | |
1280 EXPECT_EQ(base::Int64ToString(kUploadContent.size()), | |
1281 http_request_.headers["X-Upload-Content-Length"]); | |
1282 | |
1283 EXPECT_TRUE(http_request_.has_content); | |
1284 EXPECT_EQ("<?xml version=\"1.0\"?>\n" | |
1285 "<entry xmlns=\"http://www.w3.org/2005/Atom\" " | |
1286 "xmlns:docs=\"http://schemas.google.com/docs/2007\">\n" | |
1287 " <title>New file</title>\n" | |
1288 "</entry>\n", | |
1289 http_request_.content); | |
1290 | |
1291 // 2) Upload the content to the upload URL. | |
1292 UploadRangeResponse response; | |
1293 scoped_ptr<ResourceEntry> new_entry; | |
1294 | |
1295 { | |
1296 base::RunLoop run_loop; | |
1297 ResumeUploadRequest* resume_request = new ResumeUploadRequest( | |
1298 request_sender_.get(), | |
1299 test_util::CreateQuitCallback( | |
1300 &run_loop, | |
1301 test_util::CreateCopyResultCallback(&response, &new_entry)), | |
1302 ProgressCallback(), | |
1303 upload_url, | |
1304 0, // start_position | |
1305 kUploadContent.size(), // end_position (exclusive) | |
1306 kUploadContent.size(), // content_length, | |
1307 "text/plain", // content_type | |
1308 kTestFilePath); | |
1309 request_sender_->StartRequestWithRetry(resume_request); | |
1310 run_loop.Run(); | |
1311 } | |
1312 | |
1313 // METHOD_PUT should be used to upload data. | |
1314 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
1315 // Request should go to the upload URL. | |
1316 EXPECT_EQ(upload_url.path(), http_request_.relative_url); | |
1317 // Content-Range header should not exit if the content is empty. | |
1318 // We should not generate the header with an invalid value "bytes 0--1/0". | |
1319 EXPECT_EQ(0U, http_request_.headers.count("Content-Range")); | |
1320 // The upload content should be set in the HTTP request. | |
1321 EXPECT_TRUE(http_request_.has_content); | |
1322 EXPECT_EQ(kUploadContent, http_request_.content); | |
1323 | |
1324 // Check the response. | |
1325 EXPECT_EQ(HTTP_CREATED, response.code); // Because it's a new file. | |
1326 // The start and end positions should be set to -1, if an upload is complete. | |
1327 EXPECT_EQ(-1, response.start_position_received); | |
1328 EXPECT_EQ(-1, response.end_position_received); | |
1329 } | |
1330 | |
1331 // This test exercises InitiateUploadExistingFileRequest and | |
1332 // ResumeUploadRequest for a scenario of updating an existing file. | |
1333 TEST_F(GDataWapiRequestsTest, UploadExistingFile) { | |
1334 const std::string kUploadContent = "hello"; | |
1335 const base::FilePath kTestFilePath = | |
1336 temp_dir_.path().AppendASCII("upload_file.txt"); | |
1337 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kUploadContent)); | |
1338 | |
1339 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
1340 GURL upload_url; | |
1341 | |
1342 // 1) Get the upload URL for uploading an existing file. | |
1343 { | |
1344 base::RunLoop run_loop; | |
1345 InitiateUploadExistingFileRequest* initiate_request = | |
1346 new InitiateUploadExistingFileRequest( | |
1347 request_sender_.get(), | |
1348 *url_generator_, | |
1349 test_util::CreateQuitCallback( | |
1350 &run_loop, | |
1351 test_util::CreateCopyResultCallback(&result_code, &upload_url)), | |
1352 "text/plain", | |
1353 kUploadContent.size(), | |
1354 "file:foo", | |
1355 std::string() /* etag */); | |
1356 request_sender_->StartRequestWithRetry(initiate_request); | |
1357 run_loop.Run(); | |
1358 } | |
1359 | |
1360 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
1361 EXPECT_EQ(test_server_.GetURL("/upload_existing_file"), upload_url); | |
1362 // For updating an existing file, METHOD_PUT should be used. | |
1363 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
1364 // convert=false should be passed as files should be uploaded as-is. | |
1365 EXPECT_EQ("/feeds/upload/create-session/default/private/full/file%3Afoo" | |
1366 "?convert=false&v=3&alt=json&showroot=true", | |
1367 http_request_.relative_url); | |
1368 // Even though the body is empty, the content type should be set to | |
1369 // "text/plain". | |
1370 EXPECT_EQ("text/plain", http_request_.headers["Content-Type"]); | |
1371 EXPECT_EQ("text/plain", http_request_.headers["X-Upload-Content-Type"]); | |
1372 EXPECT_EQ(base::Int64ToString(kUploadContent.size()), | |
1373 http_request_.headers["X-Upload-Content-Length"]); | |
1374 // For updating an existing file, an empty body should be attached (PUT | |
1375 // requires a body) | |
1376 EXPECT_TRUE(http_request_.has_content); | |
1377 EXPECT_EQ("", http_request_.content); | |
1378 EXPECT_EQ("*", http_request_.headers["If-Match"]); | |
1379 | |
1380 // 2) Upload the content to the upload URL. | |
1381 UploadRangeResponse response; | |
1382 scoped_ptr<ResourceEntry> new_entry; | |
1383 | |
1384 { | |
1385 base::RunLoop run_loop; | |
1386 ResumeUploadRequest* resume_request = new ResumeUploadRequest( | |
1387 request_sender_.get(), | |
1388 test_util::CreateQuitCallback( | |
1389 &run_loop, | |
1390 test_util::CreateCopyResultCallback(&response, &new_entry)), | |
1391 ProgressCallback(), | |
1392 upload_url, | |
1393 0, // start_position | |
1394 kUploadContent.size(), // end_position (exclusive) | |
1395 kUploadContent.size(), // content_length, | |
1396 "text/plain", // content_type | |
1397 kTestFilePath); | |
1398 | |
1399 request_sender_->StartRequestWithRetry(resume_request); | |
1400 run_loop.Run(); | |
1401 } | |
1402 | |
1403 // METHOD_PUT should be used to upload data. | |
1404 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
1405 // Request should go to the upload URL. | |
1406 EXPECT_EQ(upload_url.path(), http_request_.relative_url); | |
1407 // Content-Range header should be added. | |
1408 EXPECT_EQ("bytes 0-" + | |
1409 base::Int64ToString(kUploadContent.size() -1) + "/" + | |
1410 base::Int64ToString(kUploadContent.size()), | |
1411 http_request_.headers["Content-Range"]); | |
1412 // The upload content should be set in the HTTP request. | |
1413 EXPECT_TRUE(http_request_.has_content); | |
1414 EXPECT_EQ(kUploadContent, http_request_.content); | |
1415 | |
1416 // Check the response. | |
1417 EXPECT_EQ(HTTP_SUCCESS, response.code); // Because it's an existing file. | |
1418 // The start and end positions should be set to -1, if an upload is complete. | |
1419 EXPECT_EQ(-1, response.start_position_received); | |
1420 EXPECT_EQ(-1, response.end_position_received); | |
1421 } | |
1422 | |
1423 // This test exercises InitiateUploadExistingFileRequest and | |
1424 // ResumeUploadRequest for a scenario of updating an existing file. | |
1425 TEST_F(GDataWapiRequestsTest, UploadExistingFileWithETag) { | |
1426 const std::string kUploadContent = "hello"; | |
1427 const base::FilePath kTestFilePath = | |
1428 temp_dir_.path().AppendASCII("upload_file.txt"); | |
1429 ASSERT_TRUE(test_util::WriteStringToFile(kTestFilePath, kUploadContent)); | |
1430 | |
1431 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
1432 GURL upload_url; | |
1433 | |
1434 // 1) Get the upload URL for uploading an existing file. | |
1435 { | |
1436 base::RunLoop run_loop; | |
1437 InitiateUploadExistingFileRequest* initiate_request = | |
1438 new InitiateUploadExistingFileRequest( | |
1439 request_sender_.get(), | |
1440 *url_generator_, | |
1441 test_util::CreateQuitCallback( | |
1442 &run_loop, | |
1443 test_util::CreateCopyResultCallback(&result_code, &upload_url)), | |
1444 "text/plain", | |
1445 kUploadContent.size(), | |
1446 "file:foo", | |
1447 kTestETag); | |
1448 request_sender_->StartRequestWithRetry(initiate_request); | |
1449 run_loop.Run(); | |
1450 } | |
1451 | |
1452 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
1453 EXPECT_EQ(test_server_.GetURL("/upload_existing_file"), upload_url); | |
1454 // For updating an existing file, METHOD_PUT should be used. | |
1455 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
1456 // convert=false should be passed as files should be uploaded as-is. | |
1457 EXPECT_EQ("/feeds/upload/create-session/default/private/full/file%3Afoo" | |
1458 "?convert=false&v=3&alt=json&showroot=true", | |
1459 http_request_.relative_url); | |
1460 // Even though the body is empty, the content type should be set to | |
1461 // "text/plain". | |
1462 EXPECT_EQ("text/plain", http_request_.headers["Content-Type"]); | |
1463 EXPECT_EQ("text/plain", http_request_.headers["X-Upload-Content-Type"]); | |
1464 EXPECT_EQ(base::Int64ToString(kUploadContent.size()), | |
1465 http_request_.headers["X-Upload-Content-Length"]); | |
1466 // For updating an existing file, an empty body should be attached (PUT | |
1467 // requires a body) | |
1468 EXPECT_TRUE(http_request_.has_content); | |
1469 EXPECT_EQ("", http_request_.content); | |
1470 EXPECT_EQ(kTestETag, http_request_.headers["If-Match"]); | |
1471 | |
1472 // 2) Upload the content to the upload URL. | |
1473 UploadRangeResponse response; | |
1474 scoped_ptr<ResourceEntry> new_entry; | |
1475 | |
1476 { | |
1477 base::RunLoop run_loop; | |
1478 ResumeUploadRequest* resume_request = new ResumeUploadRequest( | |
1479 request_sender_.get(), | |
1480 test_util::CreateQuitCallback( | |
1481 &run_loop, | |
1482 test_util::CreateCopyResultCallback(&response, &new_entry)), | |
1483 ProgressCallback(), | |
1484 upload_url, | |
1485 0, // start_position | |
1486 kUploadContent.size(), // end_position (exclusive) | |
1487 kUploadContent.size(), // content_length, | |
1488 "text/plain", // content_type | |
1489 kTestFilePath); | |
1490 request_sender_->StartRequestWithRetry(resume_request); | |
1491 run_loop.Run(); | |
1492 } | |
1493 | |
1494 // METHOD_PUT should be used to upload data. | |
1495 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
1496 // Request should go to the upload URL. | |
1497 EXPECT_EQ(upload_url.path(), http_request_.relative_url); | |
1498 // Content-Range header should be added. | |
1499 EXPECT_EQ("bytes 0-" + | |
1500 base::Int64ToString(kUploadContent.size() -1) + "/" + | |
1501 base::Int64ToString(kUploadContent.size()), | |
1502 http_request_.headers["Content-Range"]); | |
1503 // The upload content should be set in the HTTP request. | |
1504 EXPECT_TRUE(http_request_.has_content); | |
1505 EXPECT_EQ(kUploadContent, http_request_.content); | |
1506 | |
1507 // Check the response. | |
1508 EXPECT_EQ(HTTP_SUCCESS, response.code); // Because it's an existing file. | |
1509 // The start and end positions should be set to -1, if an upload is complete. | |
1510 EXPECT_EQ(-1, response.start_position_received); | |
1511 EXPECT_EQ(-1, response.end_position_received); | |
1512 } | |
1513 | |
1514 // This test exercises InitiateUploadExistingFileRequest for a scenario of | |
1515 // confliction on updating an existing file. | |
1516 TEST_F(GDataWapiRequestsTest, UploadExistingFileWithETagConflict) { | |
1517 const std::string kUploadContent = "hello"; | |
1518 const std::string kWrongETag = "wrong_etag"; | |
1519 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
1520 GURL upload_url; | |
1521 | |
1522 { | |
1523 base::RunLoop run_loop; | |
1524 InitiateUploadExistingFileRequest* initiate_request = | |
1525 new InitiateUploadExistingFileRequest( | |
1526 request_sender_.get(), | |
1527 *url_generator_, | |
1528 test_util::CreateQuitCallback( | |
1529 &run_loop, | |
1530 test_util::CreateCopyResultCallback(&result_code, &upload_url)), | |
1531 "text/plain", | |
1532 kUploadContent.size(), | |
1533 "file:foo", | |
1534 kWrongETag); | |
1535 request_sender_->StartRequestWithRetry(initiate_request); | |
1536 run_loop.Run(); | |
1537 } | |
1538 | |
1539 EXPECT_EQ(HTTP_PRECONDITION, result_code); | |
1540 // For updating an existing file, METHOD_PUT should be used. | |
1541 EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method); | |
1542 // convert=false should be passed as files should be uploaded as-is. | |
1543 EXPECT_EQ("/feeds/upload/create-session/default/private/full/file%3Afoo" | |
1544 "?convert=false&v=3&alt=json&showroot=true", | |
1545 http_request_.relative_url); | |
1546 // Even though the body is empty, the content type should be set to | |
1547 // "text/plain". | |
1548 EXPECT_EQ("text/plain", http_request_.headers["Content-Type"]); | |
1549 EXPECT_EQ("text/plain", http_request_.headers["X-Upload-Content-Type"]); | |
1550 EXPECT_EQ(base::Int64ToString(kUploadContent.size()), | |
1551 http_request_.headers["X-Upload-Content-Length"]); | |
1552 // For updating an existing file, an empty body should be attached (PUT | |
1553 // requires a body) | |
1554 EXPECT_TRUE(http_request_.has_content); | |
1555 EXPECT_EQ("", http_request_.content); | |
1556 EXPECT_EQ(kWrongETag, http_request_.headers["If-Match"]); | |
1557 } | |
1558 | |
1559 TEST_F(GDataWapiRequestsTest, DownloadFileRequest) { | |
1560 const base::FilePath kDownloadedFilePath = | |
1561 temp_dir_.path().AppendASCII("cache_file"); | |
1562 const std::string kTestIdWithTypeLabel("file:dummyId"); | |
1563 const std::string kTestId("dummyId"); | |
1564 | |
1565 GDataErrorCode result_code = GDATA_OTHER_ERROR; | |
1566 base::FilePath temp_file; | |
1567 { | |
1568 base::RunLoop run_loop; | |
1569 DownloadFileRequest* request = new DownloadFileRequest( | |
1570 request_sender_.get(), | |
1571 *url_generator_, | |
1572 test_util::CreateQuitCallback( | |
1573 &run_loop, | |
1574 test_util::CreateCopyResultCallback(&result_code, &temp_file)), | |
1575 GetContentCallback(), | |
1576 ProgressCallback(), | |
1577 kTestIdWithTypeLabel, | |
1578 kDownloadedFilePath); | |
1579 request_sender_->StartRequestWithRetry(request); | |
1580 run_loop.Run(); | |
1581 } | |
1582 | |
1583 std::string contents; | |
1584 base::ReadFileToString(temp_file, &contents); | |
1585 base::DeleteFile(temp_file, false); | |
1586 | |
1587 EXPECT_EQ(HTTP_SUCCESS, result_code); | |
1588 EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); | |
1589 EXPECT_EQ(kTestDownloadPathPrefix + kTestId, http_request_.relative_url); | |
1590 EXPECT_EQ(kDownloadedFilePath, temp_file); | |
1591 | |
1592 const std::string expected_contents = kTestId + kTestId + kTestId; | |
1593 EXPECT_EQ(expected_contents, contents); | |
1594 } | |
1595 | |
1596 } // namespace google_apis | |
OLD | NEW |