Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / url_request / url_request_file_job_unittest.cc
1 // Copyright 2014 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 "net/url_request/url_request_file_job.h"
6
7 #include "base/files/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "net/base/filename_util.h"
14 #include "net/base/net_util.h"
15 #include "net/url_request/url_request.h"
16 #include "net/url_request/url_request_test_util.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace net {
20
21 namespace {
22
23 // A URLRequestFileJob for testing OnSeekComplete / OnReadComplete callbacks.
24 class URLRequestFileJobWithCallbacks : public URLRequestFileJob {
25  public:
26   URLRequestFileJobWithCallbacks(
27       URLRequest* request,
28       NetworkDelegate* network_delegate,
29       const base::FilePath& file_path,
30       const scoped_refptr<base::TaskRunner>& file_task_runner)
31       : URLRequestFileJob(request,
32                           network_delegate,
33                           file_path,
34                           file_task_runner),
35         seek_position_(0) {
36   }
37
38   int64 seek_position() { return seek_position_; }
39   const std::vector<std::string>& data_chunks() { return data_chunks_; }
40
41  protected:
42   ~URLRequestFileJobWithCallbacks() override {}
43
44   void OnSeekComplete(int64 result) override {
45     ASSERT_EQ(seek_position_, 0);
46     seek_position_ = result;
47   }
48
49   void OnReadComplete(IOBuffer* buf, int result) override {
50     data_chunks_.push_back(std::string(buf->data(), result));
51   }
52
53   int64 seek_position_;
54   std::vector<std::string> data_chunks_;
55 };
56
57 // A URLRequestJobFactory that will return URLRequestFileJobWithCallbacks
58 // instances for file:// scheme URLs.
59 class CallbacksJobFactory : public URLRequestJobFactory {
60  public:
61   class JobObserver {
62    public:
63     virtual void OnJobCreated(URLRequestFileJobWithCallbacks* job) = 0;
64   };
65
66   CallbacksJobFactory(const base::FilePath& path, JobObserver* observer)
67       : path_(path), observer_(observer) {
68   }
69
70   ~CallbacksJobFactory() override {}
71
72   URLRequestJob* MaybeCreateJobWithProtocolHandler(
73       const std::string& scheme,
74       URLRequest* request,
75       NetworkDelegate* network_delegate) const override {
76     URLRequestFileJobWithCallbacks* job = new URLRequestFileJobWithCallbacks(
77         request,
78         network_delegate,
79         path_,
80         base::MessageLoop::current()->message_loop_proxy());
81     observer_->OnJobCreated(job);
82     return job;
83   }
84
85   net::URLRequestJob* MaybeInterceptRedirect(
86       net::URLRequest* request,
87       net::NetworkDelegate* network_delegate,
88       const GURL& location) const override {
89     return nullptr;
90   }
91
92   net::URLRequestJob* MaybeInterceptResponse(
93       net::URLRequest* request,
94       net::NetworkDelegate* network_delegate) const override {
95     return nullptr;
96   }
97
98   bool IsHandledProtocol(const std::string& scheme) const override {
99     return scheme == "file";
100   }
101
102   bool IsHandledURL(const GURL& url) const override {
103     return IsHandledProtocol(url.scheme());
104   }
105
106   bool IsSafeRedirectTarget(const GURL& location) const override {
107     return false;
108   }
109
110  private:
111   base::FilePath path_;
112   JobObserver* observer_;
113 };
114
115 // Helper function to create a file in |directory| filled with
116 // |content|. Returns true on succes and fills in |path| with the full path to
117 // the file.
118 bool CreateTempFileWithContent(const std::string& content,
119                                const base::ScopedTempDir& directory,
120                                base::FilePath* path) {
121   if (!directory.IsValid())
122     return false;
123
124   if (!base::CreateTemporaryFileInDir(directory.path(), path))
125     return false;
126
127   return base::WriteFile(*path, content.c_str(), content.length());
128 }
129
130 class JobObserverImpl : public CallbacksJobFactory::JobObserver {
131  public:
132   void OnJobCreated(URLRequestFileJobWithCallbacks* job) override {
133     jobs_.push_back(job);
134   }
135
136   typedef std::vector<scoped_refptr<URLRequestFileJobWithCallbacks> > JobList;
137
138   const JobList& jobs() { return jobs_; }
139
140  protected:
141   JobList jobs_;
142 };
143
144 // A simple holder for start/end used in http range requests.
145 struct Range {
146   int start;
147   int end;
148
149   Range() {
150     start = 0;
151     end = 0;
152   }
153
154   Range(int start, int end) {
155     this->start = start;
156     this->end = end;
157   }
158 };
159
160 // A superclass for tests of the OnSeekComplete / OnReadComplete functions of
161 // URLRequestFileJob.
162 class URLRequestFileJobEventsTest : public testing::Test {
163  public:
164   URLRequestFileJobEventsTest();
165
166  protected:
167   // This creates a file with |content| as the contents, and then creates and
168   // runs a URLRequestFileJobWithCallbacks job to get the contents out of it,
169   // and makes sure that the callbacks observed the correct bytes. If a Range
170   // is provided, this function will add the appropriate Range http header to
171   // the request and verify that only the bytes in that range (inclusive) were
172   // observed.
173   void RunRequest(const std::string& content, const Range* range);
174
175   JobObserverImpl observer_;
176   TestURLRequestContext context_;
177   TestDelegate delegate_;
178 };
179
180 URLRequestFileJobEventsTest::URLRequestFileJobEventsTest() {}
181
182 void URLRequestFileJobEventsTest::RunRequest(const std::string& content,
183                                              const Range* range) {
184   base::ScopedTempDir directory;
185   ASSERT_TRUE(directory.CreateUniqueTempDir());
186   base::FilePath path;
187   ASSERT_TRUE(CreateTempFileWithContent(content, directory, &path));
188   CallbacksJobFactory factory(path, &observer_);
189   context_.set_job_factory(&factory);
190
191   scoped_ptr<URLRequest> request(context_.CreateRequest(
192       FilePathToFileURL(path), DEFAULT_PRIORITY, &delegate_, NULL));
193   if (range) {
194     ASSERT_GE(range->start, 0);
195     ASSERT_GE(range->end, 0);
196     ASSERT_LE(range->start, range->end);
197     ASSERT_LT(static_cast<unsigned int>(range->end), content.length());
198     std::string range_value =
199         base::StringPrintf("bytes=%d-%d", range->start, range->end);
200     request->SetExtraRequestHeaderByName(
201         HttpRequestHeaders::kRange, range_value, true /*overwrite*/);
202   }
203   request->Start();
204
205   base::RunLoop loop;
206   loop.Run();
207
208   EXPECT_FALSE(delegate_.request_failed());
209   int expected_length =
210       range ? (range->end - range->start + 1) : content.length();
211   EXPECT_EQ(delegate_.bytes_received(), expected_length);
212
213   std::string expected_content;
214   if (range) {
215     expected_content.insert(0, content, range->start, expected_length);
216   } else {
217     expected_content = content;
218   }
219   EXPECT_TRUE(delegate_.data_received() == expected_content);
220
221   ASSERT_EQ(observer_.jobs().size(), 1u);
222   ASSERT_EQ(observer_.jobs().at(0)->seek_position(), range ? range->start : 0);
223
224   std::string observed_content;
225   const std::vector<std::string>& chunks =
226       observer_.jobs().at(0)->data_chunks();
227   for (std::vector<std::string>::const_iterator i = chunks.begin();
228        i != chunks.end();
229        ++i) {
230     observed_content.append(*i);
231   }
232   EXPECT_EQ(expected_content, observed_content);
233 }
234
235 // Helper function to make a character array filled with |size| bytes of
236 // test content.
237 std::string MakeContentOfSize(int size) {
238   EXPECT_GE(size, 0);
239   std::string result;
240   result.reserve(size);
241   for (int i = 0; i < size; i++) {
242     result.append(1, static_cast<char>(i % 256));
243   }
244   return result;
245 }
246
247 TEST_F(URLRequestFileJobEventsTest, TinyFile) {
248   RunRequest(std::string("hello world"), NULL);
249 }
250
251 TEST_F(URLRequestFileJobEventsTest, SmallFile) {
252   RunRequest(MakeContentOfSize(17 * 1024), NULL);
253 }
254
255 TEST_F(URLRequestFileJobEventsTest, BigFile) {
256   RunRequest(MakeContentOfSize(3 * 1024 * 1024), NULL);
257 }
258
259 TEST_F(URLRequestFileJobEventsTest, Range) {
260   // Use a 15KB content file and read a range chosen somewhat arbitrarily but
261   // not aligned on any likely page boundaries.
262   int size = 15 * 1024;
263   Range range(1701, (6 * 1024) + 3);
264   RunRequest(MakeContentOfSize(size), &range);
265 }
266
267 }  // namespace
268
269 }  // namespace net