IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / fileapi / file_system_url_request_job_unittest.cc
blob7edd26aa6562076b6e61d4b45b76a1bed3f2d17c
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.
5 #include "webkit/browser/fileapi/file_system_url_request_job.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/file_util.h"
11 #include "base/files/file_path.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/format_macros.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/message_loop/message_loop_proxy.h"
17 #include "base/platform_file.h"
18 #include "base/rand_util.h"
19 #include "base/run_loop.h"
20 #include "base/strings/string_piece.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "content/public/test/test_file_system_context.h"
24 #include "net/base/load_flags.h"
25 #include "net/base/mime_util.h"
26 #include "net/base/net_errors.h"
27 #include "net/base/net_util.h"
28 #include "net/base/request_priority.h"
29 #include "net/http/http_byte_range.h"
30 #include "net/http/http_request_headers.h"
31 #include "net/url_request/url_request.h"
32 #include "net/url_request/url_request_context.h"
33 #include "net/url_request/url_request_test_util.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 #include "webkit/browser/fileapi/async_file_test_helper.h"
36 #include "webkit/browser/fileapi/external_mount_points.h"
37 #include "webkit/browser/fileapi/file_system_context.h"
38 #include "webkit/browser/fileapi/file_system_file_util.h"
40 namespace fileapi {
41 namespace {
43 // We always use the TEMPORARY FileSystem in this test.
44 const char kFileSystemURLPrefix[] = "filesystem:http://remote/temporary/";
45 const char kTestFileData[] = "0123456789";
47 void FillBuffer(char* buffer, size_t len) {
48 base::RandBytes(buffer, len);
51 } // namespace
53 class FileSystemURLRequestJobTest : public testing::Test {
54 protected:
55 FileSystemURLRequestJobTest() : weak_factory_(this) {
58 virtual void SetUp() OVERRIDE {
59 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
61 // We use the main thread so that we can get the root path synchronously.
62 // TODO(adamk): Run this on the FILE thread we've created as well.
63 file_system_context_ =
64 CreateFileSystemContextForTesting(NULL, temp_dir_.path());
66 file_system_context_->OpenFileSystem(
67 GURL("http://remote/"), kFileSystemTypeTemporary,
68 OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
69 base::Bind(&FileSystemURLRequestJobTest::OnOpenFileSystem,
70 weak_factory_.GetWeakPtr()));
71 base::RunLoop().RunUntilIdle();
73 net::URLRequest::Deprecated::RegisterProtocolFactory(
74 "filesystem", &FileSystemURLRequestJobFactory);
77 virtual void TearDown() OVERRIDE {
78 net::URLRequest::Deprecated::RegisterProtocolFactory("filesystem", NULL);
79 ClearUnusedJob();
80 if (pending_job_.get()) {
81 pending_job_->Kill();
82 pending_job_ = NULL;
84 // FileReader posts a task to close the file in destructor.
85 base::RunLoop().RunUntilIdle();
88 void OnOpenFileSystem(const GURL& root_url,
89 const std::string& name,
90 base::PlatformFileError result) {
91 ASSERT_EQ(base::PLATFORM_FILE_OK, result);
94 void TestRequestHelper(const GURL& url,
95 const net::HttpRequestHeaders* headers,
96 bool run_to_completion,
97 FileSystemContext* file_system_context) {
98 delegate_.reset(new net::TestDelegate());
99 // Make delegate_ exit the MessageLoop when the request is done.
100 delegate_->set_quit_on_complete(true);
101 delegate_->set_quit_on_redirect(true);
102 request_ = empty_context_.CreateRequest(
103 url, net::DEFAULT_PRIORITY, delegate_.get());
104 if (headers)
105 request_->SetExtraRequestHeaders(*headers);
106 ASSERT_TRUE(!job_);
107 job_ = new FileSystemURLRequestJob(
108 request_.get(), NULL, file_system_context);
109 pending_job_ = job_;
111 request_->Start();
112 ASSERT_TRUE(request_->is_pending()); // verify that we're starting async
113 if (run_to_completion)
114 base::MessageLoop::current()->Run();
117 void TestRequest(const GURL& url) {
118 TestRequestHelper(url, NULL, true, file_system_context_.get());
121 void TestRequestWithContext(const GURL& url,
122 FileSystemContext* file_system_context) {
123 TestRequestHelper(url, NULL, true, file_system_context);
126 void TestRequestWithHeaders(const GURL& url,
127 const net::HttpRequestHeaders* headers) {
128 TestRequestHelper(url, headers, true, file_system_context_.get());
131 void TestRequestNoRun(const GURL& url) {
132 TestRequestHelper(url, NULL, false, file_system_context_.get());
135 void CreateDirectory(const base::StringPiece& dir_name) {
136 FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
137 GURL("http://remote"),
138 kFileSystemTypeTemporary,
139 base::FilePath().AppendASCII(dir_name));
140 ASSERT_EQ(base::PLATFORM_FILE_OK, AsyncFileTestHelper::CreateDirectory(
141 file_system_context_, url));
144 void WriteFile(const base::StringPiece& file_name,
145 const char* buf, int buf_size) {
146 FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
147 GURL("http://remote"),
148 kFileSystemTypeTemporary,
149 base::FilePath().AppendASCII(file_name));
150 ASSERT_EQ(base::PLATFORM_FILE_OK,
151 AsyncFileTestHelper::CreateFileWithData(
152 file_system_context_, url, buf, buf_size));
155 GURL CreateFileSystemURL(const std::string& path) {
156 return GURL(kFileSystemURLPrefix + path);
159 static net::URLRequestJob* FileSystemURLRequestJobFactory(
160 net::URLRequest* request,
161 net::NetworkDelegate* network_delegate,
162 const std::string& scheme) {
163 DCHECK(job_);
164 net::URLRequestJob* temp = job_;
165 job_ = NULL;
166 return temp;
169 static void ClearUnusedJob() {
170 if (job_) {
171 scoped_refptr<net::URLRequestJob> deleter = job_;
172 job_ = NULL;
176 // Put the message loop at the top, so that it's the last thing deleted.
177 base::MessageLoopForIO message_loop_;
179 base::ScopedTempDir temp_dir_;
180 scoped_refptr<FileSystemContext> file_system_context_;
181 base::WeakPtrFactory<FileSystemURLRequestJobTest> weak_factory_;
183 net::URLRequestContext empty_context_;
185 // NOTE: order matters, request must die before delegate
186 scoped_ptr<net::TestDelegate> delegate_;
187 scoped_ptr<net::URLRequest> request_;
189 scoped_refptr<net::URLRequestJob> pending_job_;
190 static net::URLRequestJob* job_;
193 // static
194 net::URLRequestJob* FileSystemURLRequestJobTest::job_ = NULL;
196 namespace {
198 TEST_F(FileSystemURLRequestJobTest, FileTest) {
199 WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
200 TestRequest(CreateFileSystemURL("file1.dat"));
202 ASSERT_FALSE(request_->is_pending());
203 EXPECT_EQ(1, delegate_->response_started_count());
204 EXPECT_FALSE(delegate_->received_data_before_response());
205 EXPECT_EQ(kTestFileData, delegate_->data_received());
206 EXPECT_EQ(200, request_->GetResponseCode());
207 std::string cache_control;
208 request_->GetResponseHeaderByName("cache-control", &cache_control);
209 EXPECT_EQ("no-cache", cache_control);
212 TEST_F(FileSystemURLRequestJobTest, FileTestFullSpecifiedRange) {
213 const size_t buffer_size = 4000;
214 scoped_ptr<char[]> buffer(new char[buffer_size]);
215 FillBuffer(buffer.get(), buffer_size);
216 WriteFile("bigfile", buffer.get(), buffer_size);
218 const size_t first_byte_position = 500;
219 const size_t last_byte_position = buffer_size - first_byte_position;
220 std::string partial_buffer_string(buffer.get() + first_byte_position,
221 buffer.get() + last_byte_position + 1);
223 net::HttpRequestHeaders headers;
224 headers.SetHeader(
225 net::HttpRequestHeaders::kRange,
226 net::HttpByteRange::Bounded(
227 first_byte_position, last_byte_position).GetHeaderValue());
228 TestRequestWithHeaders(CreateFileSystemURL("bigfile"), &headers);
230 ASSERT_FALSE(request_->is_pending());
231 EXPECT_EQ(1, delegate_->response_started_count());
232 EXPECT_FALSE(delegate_->received_data_before_response());
233 EXPECT_TRUE(partial_buffer_string == delegate_->data_received());
236 TEST_F(FileSystemURLRequestJobTest, FileTestHalfSpecifiedRange) {
237 const size_t buffer_size = 4000;
238 scoped_ptr<char[]> buffer(new char[buffer_size]);
239 FillBuffer(buffer.get(), buffer_size);
240 WriteFile("bigfile", buffer.get(), buffer_size);
242 const size_t first_byte_position = 500;
243 std::string partial_buffer_string(buffer.get() + first_byte_position,
244 buffer.get() + buffer_size);
246 net::HttpRequestHeaders headers;
247 headers.SetHeader(
248 net::HttpRequestHeaders::kRange,
249 net::HttpByteRange::RightUnbounded(first_byte_position).GetHeaderValue());
250 TestRequestWithHeaders(CreateFileSystemURL("bigfile"), &headers);
251 ASSERT_FALSE(request_->is_pending());
252 EXPECT_EQ(1, delegate_->response_started_count());
253 EXPECT_FALSE(delegate_->received_data_before_response());
254 // Don't use EXPECT_EQ, it will print out a lot of garbage if check failed.
255 EXPECT_TRUE(partial_buffer_string == delegate_->data_received());
259 TEST_F(FileSystemURLRequestJobTest, FileTestMultipleRangesNotSupported) {
260 WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
261 net::HttpRequestHeaders headers;
262 headers.SetHeader(net::HttpRequestHeaders::kRange,
263 "bytes=0-5,10-200,200-300");
264 TestRequestWithHeaders(CreateFileSystemURL("file1.dat"), &headers);
265 EXPECT_TRUE(delegate_->request_failed());
266 EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
267 request_->status().error());
270 TEST_F(FileSystemURLRequestJobTest, RangeOutOfBounds) {
271 WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
272 net::HttpRequestHeaders headers;
273 headers.SetHeader(
274 net::HttpRequestHeaders::kRange,
275 net::HttpByteRange::Bounded(500, 1000).GetHeaderValue());
276 TestRequestWithHeaders(CreateFileSystemURL("file1.dat"), &headers);
278 ASSERT_FALSE(request_->is_pending());
279 EXPECT_TRUE(delegate_->request_failed());
280 EXPECT_EQ(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE,
281 request_->status().error());
284 TEST_F(FileSystemURLRequestJobTest, FileDirRedirect) {
285 CreateDirectory("dir");
286 TestRequest(CreateFileSystemURL("dir"));
288 EXPECT_EQ(1, delegate_->received_redirect_count());
289 EXPECT_TRUE(request_->status().is_success());
290 EXPECT_FALSE(delegate_->request_failed());
292 // We've deferred the redirect; now cancel the request to avoid following it.
293 request_->Cancel();
294 base::MessageLoop::current()->Run();
297 TEST_F(FileSystemURLRequestJobTest, InvalidURL) {
298 TestRequest(GURL("filesystem:/foo/bar/baz"));
299 ASSERT_FALSE(request_->is_pending());
300 EXPECT_TRUE(delegate_->request_failed());
301 EXPECT_EQ(net::ERR_INVALID_URL, request_->status().error());
304 TEST_F(FileSystemURLRequestJobTest, NoSuchRoot) {
305 TestRequest(GURL("filesystem:http://remote/persistent/somefile"));
306 ASSERT_FALSE(request_->is_pending());
307 EXPECT_TRUE(delegate_->request_failed());
308 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
311 TEST_F(FileSystemURLRequestJobTest, NoSuchFile) {
312 TestRequest(CreateFileSystemURL("somefile"));
313 ASSERT_FALSE(request_->is_pending());
314 EXPECT_TRUE(delegate_->request_failed());
315 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
318 TEST_F(FileSystemURLRequestJobTest, Cancel) {
319 WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
320 TestRequestNoRun(CreateFileSystemURL("file1.dat"));
322 // Run StartAsync() and only StartAsync().
323 base::MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release());
324 base::RunLoop().RunUntilIdle();
325 // If we get here, success! we didn't crash!
328 TEST_F(FileSystemURLRequestJobTest, GetMimeType) {
329 const char kFilename[] = "hoge.html";
331 std::string mime_type_direct;
332 base::FilePath::StringType extension =
333 base::FilePath().AppendASCII(kFilename).Extension();
334 if (!extension.empty())
335 extension = extension.substr(1);
336 EXPECT_TRUE(net::GetWellKnownMimeTypeFromExtension(
337 extension, &mime_type_direct));
339 TestRequest(CreateFileSystemURL(kFilename));
341 std::string mime_type_from_job;
342 request_->GetMimeType(&mime_type_from_job);
343 EXPECT_EQ(mime_type_direct, mime_type_from_job);
346 TEST_F(FileSystemURLRequestJobTest, Incognito) {
347 WriteFile("file", kTestFileData, arraysize(kTestFileData) - 1);
349 // Creates a new filesystem context for incognito mode.
350 scoped_refptr<FileSystemContext> file_system_context =
351 CreateIncognitoFileSystemContextForTesting(NULL, temp_dir_.path());
353 // The request should return NOT_FOUND error if it's in incognito mode.
354 TestRequestWithContext(CreateFileSystemURL("file"),
355 file_system_context.get());
356 ASSERT_FALSE(request_->is_pending());
357 EXPECT_TRUE(delegate_->request_failed());
358 EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
360 // Make sure it returns success with regular (non-incognito) context.
361 TestRequest(CreateFileSystemURL("file"));
362 ASSERT_FALSE(request_->is_pending());
363 EXPECT_EQ(kTestFileData, delegate_->data_received());
364 EXPECT_EQ(200, request_->GetResponseCode());
367 } // namespace
368 } // namespace fileapi