- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / fileapi / file_system_dir_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 "webkit/browser/fileapi/file_system_dir_url_request_job.h"
6
7 #include <string>
8
9 #include "base/files/file_path.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/format_macros.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/platform_file.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string_piece.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "content/public/test/test_file_system_context.h"
19 #include "net/base/net_errors.h"
20 #include "net/base/net_util.h"
21 #include "net/base/request_priority.h"
22 #include "net/http/http_request_headers.h"
23 #include "net/url_request/url_request.h"
24 #include "net/url_request/url_request_context.h"
25 #include "net/url_request/url_request_test_util.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "third_party/icu/source/i18n/unicode/regex.h"
28 #include "webkit/browser/fileapi/file_system_context.h"
29 #include "webkit/browser/fileapi/file_system_file_util.h"
30 #include "webkit/browser/fileapi/file_system_operation_context.h"
31 #include "webkit/browser/fileapi/file_system_url.h"
32 #include "webkit/browser/quota/mock_special_storage_policy.h"
33
34 namespace fileapi {
35 namespace {
36
37 // We always use the TEMPORARY FileSystem in this test.
38 static const char kFileSystemURLPrefix[] =
39     "filesystem:http://remote/temporary/";
40
41 }  // namespace
42
43 class FileSystemDirURLRequestJobTest : public testing::Test {
44  protected:
45   FileSystemDirURLRequestJobTest()
46     : weak_factory_(this) {
47   }
48
49   virtual void SetUp() OVERRIDE {
50     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
51
52     special_storage_policy_ = new quota::MockSpecialStoragePolicy;
53     file_system_context_ = CreateFileSystemContextForTesting(
54         NULL, temp_dir_.path());
55
56     file_system_context_->OpenFileSystem(
57         GURL("http://remote/"), kFileSystemTypeTemporary,
58         OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
59         base::Bind(&FileSystemDirURLRequestJobTest::OnOpenFileSystem,
60                    weak_factory_.GetWeakPtr()));
61     base::RunLoop().RunUntilIdle();
62
63     net::URLRequest::Deprecated::RegisterProtocolFactory(
64         "filesystem", &FileSystemDirURLRequestJobFactory);
65   }
66
67   virtual void TearDown() OVERRIDE {
68     // NOTE: order matters, request must die before delegate
69     request_.reset(NULL);
70     delegate_.reset(NULL);
71
72     net::URLRequest::Deprecated::RegisterProtocolFactory("filesystem", NULL);
73     ClearUnusedJob();
74   }
75
76   void OnOpenFileSystem(const GURL& root_url,
77                         const std::string& name,
78                         base::PlatformFileError result) {
79     ASSERT_EQ(base::PLATFORM_FILE_OK, result);
80   }
81
82   void TestRequestHelper(const GURL& url, bool run_to_completion,
83                          FileSystemContext* file_system_context) {
84     delegate_.reset(new net::TestDelegate());
85     delegate_->set_quit_on_redirect(true);
86     request_ = empty_context_.CreateRequest(
87         url, net::DEFAULT_PRIORITY, delegate_.get());
88     job_ = new FileSystemDirURLRequestJob(
89         request_.get(), NULL, file_system_context);
90
91     request_->Start();
92     ASSERT_TRUE(request_->is_pending());  // verify that we're starting async
93     if (run_to_completion)
94       base::MessageLoop::current()->Run();
95   }
96
97   void TestRequest(const GURL& url) {
98     TestRequestHelper(url, true, file_system_context_.get());
99   }
100
101   void TestRequestWithContext(const GURL& url,
102                               FileSystemContext* file_system_context) {
103     TestRequestHelper(url, true, file_system_context);
104   }
105
106   void TestRequestNoRun(const GURL& url) {
107     TestRequestHelper(url, false, file_system_context_.get());
108   }
109
110   FileSystemURL CreateURL(const base::FilePath& file_path) {
111     return file_system_context_->CreateCrackedFileSystemURL(
112         GURL("http://remote"),
113         fileapi::kFileSystemTypeTemporary,
114         file_path);
115   }
116
117   FileSystemOperationContext* NewOperationContext() {
118     FileSystemOperationContext* context(
119         new FileSystemOperationContext(file_system_context_.get()));
120     context->set_allowed_bytes_growth(1024);
121     return context;
122   }
123
124   void CreateDirectory(const base::StringPiece& dir_name) {
125     base::FilePath path = base::FilePath().AppendASCII(dir_name);
126     scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
127     ASSERT_EQ(base::PLATFORM_FILE_OK, file_util()->CreateDirectory(
128         context.get(),
129         CreateURL(path),
130         false /* exclusive */,
131         false /* recursive */));
132   }
133
134   void EnsureFileExists(const base::StringPiece file_name) {
135     base::FilePath path = base::FilePath().AppendASCII(file_name);
136     scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
137     ASSERT_EQ(base::PLATFORM_FILE_OK, file_util()->EnsureFileExists(
138         context.get(), CreateURL(path), NULL));
139   }
140
141   void TruncateFile(const base::StringPiece file_name, int64 length) {
142     base::FilePath path = base::FilePath().AppendASCII(file_name);
143     scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
144     ASSERT_EQ(base::PLATFORM_FILE_OK, file_util()->Truncate(
145         context.get(), CreateURL(path), length));
146   }
147
148   base::PlatformFileError GetFileInfo(const base::FilePath& path,
149                                       base::PlatformFileInfo* file_info,
150                                       base::FilePath* platform_file_path) {
151     scoped_ptr<FileSystemOperationContext> context(NewOperationContext());
152     return file_util()->GetFileInfo(context.get(),
153                                     CreateURL(path),
154                                     file_info, platform_file_path);
155   }
156
157   void VerifyListingEntry(const std::string& entry_line,
158                           const std::string& name,
159                           const std::string& url,
160                           bool is_directory,
161                           int64 size) {
162 #define STR "([^\"]*)"
163     icu::UnicodeString pattern("^<script>addRow\\(\"" STR "\",\"" STR
164                                "\",(0|1),\"" STR "\",\"" STR "\"\\);</script>");
165 #undef STR
166     icu::UnicodeString input(entry_line.c_str());
167
168     UErrorCode status = U_ZERO_ERROR;
169     icu::RegexMatcher match(pattern, input, 0, status);
170
171     EXPECT_TRUE(match.find());
172     EXPECT_EQ(5, match.groupCount());
173     EXPECT_EQ(icu::UnicodeString(name.c_str()), match.group(1, status));
174     EXPECT_EQ(icu::UnicodeString(url.c_str()), match.group(2, status));
175     EXPECT_EQ(icu::UnicodeString(is_directory ? "1" : "0"),
176               match.group(3, status));
177     icu::UnicodeString size_string(FormatBytesUnlocalized(size).c_str());
178     EXPECT_EQ(size_string, match.group(4, status));
179
180     base::Time date;
181     icu::UnicodeString date_ustr(match.group(5, status));
182     std::string date_str;
183     UTF16ToUTF8(date_ustr.getBuffer(), date_ustr.length(), &date_str);
184     EXPECT_TRUE(base::Time::FromString(date_str.c_str(), &date));
185     EXPECT_FALSE(date.is_null());
186   }
187
188   GURL CreateFileSystemURL(const std::string path) {
189     return GURL(kFileSystemURLPrefix + path);
190   }
191
192   static net::URLRequestJob* FileSystemDirURLRequestJobFactory(
193       net::URLRequest* request,
194       net::NetworkDelegate* network_delegate,
195       const std::string& scheme) {
196     DCHECK(job_);
197     net::URLRequestJob* temp = job_;
198     job_ = NULL;
199     return temp;
200   }
201
202   static void ClearUnusedJob() {
203     if (job_) {
204       scoped_refptr<net::URLRequestJob> deleter = job_;
205       job_ = NULL;
206     }
207   }
208
209   FileSystemFileUtil* file_util() {
210     return file_system_context_->sandbox_delegate()->sync_file_util();
211   }
212
213   // Put the message loop at the top, so that it's the last thing deleted.
214   // Delete all MessageLoopProxy objects before the MessageLoop, to help prevent
215   // leaks caused by tasks posted during shutdown.
216   base::MessageLoopForIO message_loop_;
217
218   base::ScopedTempDir temp_dir_;
219   net::URLRequestContext empty_context_;
220   scoped_ptr<net::TestDelegate> delegate_;
221   scoped_ptr<net::URLRequest> request_;
222   scoped_refptr<quota::MockSpecialStoragePolicy> special_storage_policy_;
223   scoped_refptr<FileSystemContext> file_system_context_;
224   base::WeakPtrFactory<FileSystemDirURLRequestJobTest> weak_factory_;
225
226   static net::URLRequestJob* job_;
227 };
228
229 // static
230 net::URLRequestJob* FileSystemDirURLRequestJobTest::job_ = NULL;
231
232 namespace {
233
234 TEST_F(FileSystemDirURLRequestJobTest, DirectoryListing) {
235   CreateDirectory("foo");
236   CreateDirectory("foo/bar");
237   CreateDirectory("foo/bar/baz");
238
239   EnsureFileExists("foo/bar/hoge");
240   TruncateFile("foo/bar/hoge", 10);
241
242   TestRequest(CreateFileSystemURL("foo/bar/"));
243
244   ASSERT_FALSE(request_->is_pending());
245   EXPECT_EQ(1, delegate_->response_started_count());
246   EXPECT_FALSE(delegate_->received_data_before_response());
247   EXPECT_GT(delegate_->bytes_received(), 0);
248
249   std::istringstream in(delegate_->data_received());
250   std::string line;
251   EXPECT_TRUE(std::getline(in, line));
252
253 #if defined(OS_WIN)
254   EXPECT_EQ("<script>start(\"foo\\\\bar\");</script>", line);
255 #elif defined(OS_POSIX)
256   EXPECT_EQ("<script>start(\"/foo/bar\");</script>", line);
257 #endif
258
259   EXPECT_TRUE(std::getline(in, line));
260   VerifyListingEntry(line, "hoge", "hoge", false, 10);
261
262   EXPECT_TRUE(std::getline(in, line));
263   VerifyListingEntry(line, "baz", "baz", true, 0);
264 }
265
266 TEST_F(FileSystemDirURLRequestJobTest, InvalidURL) {
267   TestRequest(GURL("filesystem:/foo/bar/baz"));
268   ASSERT_FALSE(request_->is_pending());
269   EXPECT_TRUE(delegate_->request_failed());
270   ASSERT_FALSE(request_->status().is_success());
271   EXPECT_EQ(net::ERR_INVALID_URL, request_->status().error());
272 }
273
274 TEST_F(FileSystemDirURLRequestJobTest, NoSuchRoot) {
275   TestRequest(GURL("filesystem:http://remote/persistent/somedir/"));
276   ASSERT_FALSE(request_->is_pending());
277   ASSERT_FALSE(request_->status().is_success());
278   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
279 }
280
281 TEST_F(FileSystemDirURLRequestJobTest, NoSuchDirectory) {
282   TestRequest(CreateFileSystemURL("somedir/"));
283   ASSERT_FALSE(request_->is_pending());
284   ASSERT_FALSE(request_->status().is_success());
285   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
286 }
287
288 TEST_F(FileSystemDirURLRequestJobTest, Cancel) {
289   CreateDirectory("foo");
290   TestRequestNoRun(CreateFileSystemURL("foo/"));
291   // Run StartAsync() and only StartAsync().
292   base::MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release());
293   base::RunLoop().RunUntilIdle();
294   // If we get here, success! we didn't crash!
295 }
296
297 TEST_F(FileSystemDirURLRequestJobTest, Incognito) {
298   CreateDirectory("foo");
299
300   scoped_refptr<FileSystemContext> file_system_context =
301       CreateIncognitoFileSystemContextForTesting(NULL, temp_dir_.path());
302
303   TestRequestWithContext(CreateFileSystemURL("/"),
304                          file_system_context.get());
305   ASSERT_FALSE(request_->is_pending());
306   ASSERT_TRUE(request_->status().is_success());
307
308   std::istringstream in(delegate_->data_received());
309   std::string line;
310   EXPECT_TRUE(std::getline(in, line));
311   EXPECT_FALSE(std::getline(in, line));
312
313   TestRequestWithContext(CreateFileSystemURL("foo"),
314                          file_system_context.get());
315   ASSERT_FALSE(request_->is_pending());
316   ASSERT_FALSE(request_->status().is_success());
317   EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
318 }
319
320 }  // namespace (anonymous)
321 }  // namespace fileapi