- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / drive_url_request_job_unittest.cc
1 // Copyright 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 "chrome/browser/chromeos/drive/drive_url_request_job.h"
6
7 #include "base/bind.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/sequenced_task_runner.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "base/threading/thread.h"
14 #include "chrome/browser/chromeos/drive/drive_file_stream_reader.h"
15 #include "chrome/browser/chromeos/drive/fake_file_system.h"
16 #include "chrome/browser/chromeos/drive/file_system_util.h"
17 #include "chrome/browser/chromeos/drive/test_util.h"
18 #include "chrome/browser/drive/fake_drive_service.h"
19 #include "chrome/browser/google_apis/test_util.h"
20 #include "chrome/common/url_constants.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "net/base/request_priority.h"
24 #include "net/base/test_completion_callback.h"
25 #include "net/http/http_byte_range.h"
26 #include "net/url_request/url_request_test_util.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "url/gurl.h"
29
30 namespace drive {
31 namespace {
32
33 // A simple URLRequestJobFactory implementation to create DriveURLRequestJob.
34 class TestURLRequestJobFactory : public net::URLRequestJobFactory {
35  public:
36   TestURLRequestJobFactory(
37       const DriveURLRequestJob::FileSystemGetter& file_system_getter,
38       base::SequencedTaskRunner* sequenced_task_runner)
39       : file_system_getter_(file_system_getter),
40         sequenced_task_runner_(sequenced_task_runner) {
41   }
42
43   virtual ~TestURLRequestJobFactory() {}
44
45   // net::URLRequestJobFactory override:
46   virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
47       const std::string& scheme,
48       net::URLRequest* request,
49       net::NetworkDelegate* network_delegate) const OVERRIDE {
50     return new DriveURLRequestJob(file_system_getter_,
51                                   sequenced_task_runner_.get(),
52                                   request,
53                                   network_delegate);
54   }
55
56   virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE {
57     return scheme == chrome::kDriveScheme;
58   }
59
60   virtual bool IsHandledURL(const GURL& url) const OVERRIDE {
61     return url.is_valid() && IsHandledProtocol(url.scheme());
62   }
63
64   virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
65     return true;
66   }
67
68  private:
69   const DriveURLRequestJob::FileSystemGetter file_system_getter_;
70   scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
71
72   DISALLOW_COPY_AND_ASSIGN(TestURLRequestJobFactory);
73 };
74
75 class TestDelegate : public net::TestDelegate {
76  public:
77   TestDelegate() {}
78
79   const GURL& redirect_url() const { return redirect_url_; }
80
81   // net::TestDelegate override.
82   virtual void OnReceivedRedirect(net::URLRequest* request,
83                                   const GURL& new_url,
84                                   bool* defer_redirect) OVERRIDE{
85     redirect_url_ = new_url;
86     net::TestDelegate::OnReceivedRedirect(request, new_url, defer_redirect);
87   }
88
89  private:
90   GURL redirect_url_;
91
92   DISALLOW_COPY_AND_ASSIGN(TestDelegate);
93 };
94
95 }  // namespace
96
97 class DriveURLRequestJobTest : public testing::Test {
98  protected:
99   DriveURLRequestJobTest()
100       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
101   }
102
103   virtual ~DriveURLRequestJobTest() {
104   }
105
106   virtual void SetUp() OVERRIDE {
107     // Initialize FakeDriveService.
108     fake_drive_service_.reset(new FakeDriveService);
109     ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
110         "gdata/root_feed.json"));
111     ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
112         "gdata/account_metadata.json"));
113
114     // Initialize FakeFileSystem.
115     fake_file_system_.reset(
116         new test_util::FakeFileSystem(fake_drive_service_.get()));
117
118     scoped_refptr<base::SequencedWorkerPool> blocking_pool =
119         content::BrowserThread::GetBlockingPool();
120     test_network_delegate_.reset(new net::TestNetworkDelegate);
121     test_url_request_job_factory_.reset(new TestURLRequestJobFactory(
122         base::Bind(&DriveURLRequestJobTest::GetFileSystem,
123                    base::Unretained(this)),
124         blocking_pool->GetSequencedTaskRunner(
125             blocking_pool->GetSequenceToken()).get()));
126     url_request_context_.reset(new net::URLRequestContext());
127     url_request_context_->set_job_factory(test_url_request_job_factory_.get());
128     url_request_context_->set_network_delegate(test_network_delegate_.get());
129     test_delegate_.reset(new TestDelegate);
130   }
131
132   FileSystemInterface* GetFileSystem() {
133     return fake_file_system_.get();
134   }
135
136   bool ReadDriveFileSync(
137       const base::FilePath& file_path, std::string* out_content) {
138     scoped_ptr<base::Thread> worker_thread(
139         new base::Thread("ReadDriveFileSync"));
140     if (!worker_thread->Start())
141       return false;
142
143     scoped_ptr<DriveFileStreamReader> reader(new DriveFileStreamReader(
144         base::Bind(&DriveURLRequestJobTest::GetFileSystem,
145                    base::Unretained(this)),
146         worker_thread->message_loop_proxy().get()));
147     int error = net::ERR_FAILED;
148     scoped_ptr<ResourceEntry> entry;
149     {
150       base::RunLoop run_loop;
151       reader->Initialize(
152           file_path,
153           net::HttpByteRange(),
154           google_apis::test_util::CreateQuitCallback(
155               &run_loop,
156               google_apis::test_util::CreateCopyResultCallback(
157                   &error, &entry)));
158       run_loop.Run();
159     }
160     if (error != net::OK || !entry)
161       return false;
162
163     // Read data from the reader.
164     std::string content;
165     if (test_util::ReadAllData(reader.get(), &content) != net::OK)
166       return false;
167
168     if (static_cast<size_t>(entry->file_info().size()) != content.size())
169       return false;
170
171     *out_content = content;
172     return true;
173   }
174
175   content::TestBrowserThreadBundle thread_bundle_;
176
177   scoped_ptr<FakeDriveService> fake_drive_service_;
178   scoped_ptr<test_util::FakeFileSystem> fake_file_system_;
179
180   scoped_ptr<net::TestNetworkDelegate> test_network_delegate_;
181   scoped_ptr<TestURLRequestJobFactory> test_url_request_job_factory_;
182   scoped_ptr<net::URLRequestContext> url_request_context_;
183   scoped_ptr<TestDelegate> test_delegate_;
184 };
185
186 TEST_F(DriveURLRequestJobTest, NonGetMethod) {
187   net::URLRequest request(GURL("drive:drive/root/File 1.txt"),
188                           net::DEFAULT_PRIORITY,
189                           test_delegate_.get(),
190                           url_request_context_.get());
191   request.set_method("POST");  // Set non "GET" method.
192   request.Start();
193
194   base::RunLoop().Run();
195
196   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
197   EXPECT_EQ(net::ERR_METHOD_NOT_SUPPORTED, request.status().error());
198 }
199
200 TEST_F(DriveURLRequestJobTest, RegularFile) {
201   const GURL kTestUrl("drive:drive/root/File 1.txt");
202   const base::FilePath kTestFilePath("drive/root/File 1.txt");
203
204   // For the first time, the file should be fetched from the server.
205   {
206     net::URLRequest request(kTestUrl,
207                             net::DEFAULT_PRIORITY,
208                             test_delegate_.get(),
209                             url_request_context_.get());
210     request.Start();
211
212     base::RunLoop().Run();
213
214     EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
215     // It looks weird, but the mime type for the "File 1.txt" is "audio/mpeg"
216     // on the server.
217     std::string mime_type;
218     request.GetMimeType(&mime_type);
219     EXPECT_EQ("audio/mpeg", mime_type);
220
221     // Reading file must be done after |request| runs, otherwise
222     // it'll create a local cache file, and we cannot test correctly.
223     std::string expected_data;
224     ASSERT_TRUE(ReadDriveFileSync(kTestFilePath, &expected_data));
225     EXPECT_EQ(expected_data, test_delegate_->data_received());
226   }
227
228   // For the second time, the locally cached file should be used.
229   // The caching emulation is done by FakeFileSystem.
230   {
231     test_delegate_.reset(new TestDelegate);
232     net::URLRequest request(GURL("drive:drive/root/File 1.txt"),
233                             net::DEFAULT_PRIORITY,
234                             test_delegate_.get(),
235                             url_request_context_.get());
236     request.Start();
237
238     base::RunLoop().Run();
239
240     EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
241     std::string mime_type;
242     request.GetMimeType(&mime_type);
243     EXPECT_EQ("audio/mpeg", mime_type);
244
245     std::string expected_data;
246     ASSERT_TRUE(ReadDriveFileSync(kTestFilePath, &expected_data));
247     EXPECT_EQ(expected_data, test_delegate_->data_received());
248   }
249 }
250
251 TEST_F(DriveURLRequestJobTest, HostedDocument) {
252   // Open a gdoc file.
253   test_delegate_->set_quit_on_redirect(true);
254   net::URLRequest request(
255       GURL("drive:drive/root/Document 1 excludeDir-test.gdoc"),
256       net::DEFAULT_PRIORITY,
257       test_delegate_.get(),
258       url_request_context_.get());
259   request.Start();
260
261   base::RunLoop().Run();
262
263   EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
264   // Make sure that a hosted document triggers redirection.
265   EXPECT_TRUE(request.is_redirecting());
266   EXPECT_EQ(GURL("https://3_document_alternate_link"),
267             test_delegate_->redirect_url());
268 }
269
270 TEST_F(DriveURLRequestJobTest, RootDirectory) {
271   net::URLRequest request(GURL("drive:drive/root"),
272                           net::DEFAULT_PRIORITY,
273                           test_delegate_.get(),
274                           url_request_context_.get());
275   request.Start();
276
277   base::RunLoop().Run();
278
279   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
280   EXPECT_EQ(net::ERR_FAILED, request.status().error());
281 }
282
283 TEST_F(DriveURLRequestJobTest, Directory) {
284   net::URLRequest request(GURL("drive:drive/root/Directory 1"),
285                           net::DEFAULT_PRIORITY,
286                           test_delegate_.get(),
287                           url_request_context_.get());
288   request.Start();
289
290   base::RunLoop().Run();
291
292   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
293   EXPECT_EQ(net::ERR_FAILED, request.status().error());
294 }
295
296 TEST_F(DriveURLRequestJobTest, NonExistingFile) {
297   net::URLRequest request(GURL("drive:drive/root/non-existing-file.txt"),
298                           net::DEFAULT_PRIORITY,
299                           test_delegate_.get(),
300                           url_request_context_.get());
301   request.Start();
302
303   base::RunLoop().Run();
304
305   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
306   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request.status().error());
307 }
308
309 TEST_F(DriveURLRequestJobTest, WrongFormat) {
310   net::URLRequest request(GURL("drive:"),
311                           net::DEFAULT_PRIORITY,
312                           test_delegate_.get(),
313                           url_request_context_.get());
314   request.Start();
315
316   base::RunLoop().Run();
317
318   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
319   EXPECT_EQ(net::ERR_INVALID_URL, request.status().error());
320 }
321
322 TEST_F(DriveURLRequestJobTest, Cancel) {
323   net::URLRequest request(GURL("drive:drive/root/File 1.txt"),
324                           net::DEFAULT_PRIORITY,
325                           test_delegate_.get(),
326                           url_request_context_.get());
327
328   // Start the request, and cancel it immediately after it.
329   request.Start();
330   request.Cancel();
331
332   base::RunLoop().Run();
333
334   EXPECT_EQ(net::URLRequestStatus::CANCELED, request.status().status());
335 }
336
337 TEST_F(DriveURLRequestJobTest, RangeHeader) {
338   const GURL kTestUrl("drive:drive/root/File 1.txt");
339   const base::FilePath kTestFilePath("drive/root/File 1.txt");
340
341   net::URLRequest request(kTestUrl,
342                           net::DEFAULT_PRIORITY,
343                           test_delegate_.get(),
344                           url_request_context_.get());
345
346   // Set range header.
347   request.SetExtraRequestHeaderByName(
348       "Range", "bytes=3-5", false /* overwrite */);
349   request.Start();
350
351   base::RunLoop().Run();
352
353   EXPECT_EQ(net::URLRequestStatus::SUCCESS, request.status().status());
354
355   // Reading file must be done after |request| runs, otherwise
356   // it'll create a local cache file, and we cannot test correctly.
357   std::string expected_data;
358   ASSERT_TRUE(ReadDriveFileSync(kTestFilePath, &expected_data));
359   EXPECT_EQ(expected_data.substr(3, 3), test_delegate_->data_received());
360 }
361
362 TEST_F(DriveURLRequestJobTest, WrongRangeHeader) {
363   const GURL kTestUrl("drive:drive/root/File 1.txt");
364
365   net::URLRequest request(kTestUrl,
366                           net::DEFAULT_PRIORITY,
367                           test_delegate_.get(),
368                           url_request_context_.get());
369
370   // Set range header.
371   request.SetExtraRequestHeaderByName(
372       "Range", "Wrong Range Header Value", false /* overwrite */);
373   request.Start();
374
375   base::RunLoop().Run();
376
377   EXPECT_EQ(net::URLRequestStatus::FAILED, request.status().status());
378   EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, request.status().error());
379 }
380
381 }  // namespace drive