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.
7 #include "base/file_util.h"
8 #include "base/files/file_path.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/platform_file.h"
12 #include "base/run_loop.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "content/public/test/test_file_system_context.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "webkit/browser/fileapi/async_file_test_helper.h"
18 #include "webkit/browser/fileapi/async_file_util_adapter.h"
19 #include "webkit/browser/fileapi/file_system_context.h"
20 #include "webkit/browser/fileapi/file_system_file_util.h"
21 #include "webkit/browser/fileapi/file_system_operation_context.h"
22 #include "webkit/browser/fileapi/local_file_util.h"
23 #include "webkit/browser/fileapi/native_file_util.h"
24 #include "webkit/common/fileapi/file_system_types.h"
30 const GURL
kOrigin("http://foo/");
31 const FileSystemType kFileSystemType
= kFileSystemTypeTest
;
35 class LocalFileUtilTest
: public testing::Test
{
37 LocalFileUtilTest() {}
39 virtual void SetUp() {
40 ASSERT_TRUE(data_dir_
.CreateUniqueTempDir());
41 file_system_context_
= CreateFileSystemContextForTesting(
42 NULL
, data_dir_
.path());
45 virtual void TearDown() {
46 file_system_context_
= NULL
;
47 base::RunLoop().RunUntilIdle();
51 FileSystemOperationContext
* NewContext() {
52 FileSystemOperationContext
* context
=
53 new FileSystemOperationContext(file_system_context_
.get());
54 context
->set_update_observers(
55 *file_system_context_
->GetUpdateObservers(kFileSystemType
));
59 LocalFileUtil
* file_util() {
60 AsyncFileUtilAdapter
* adapter
= static_cast<AsyncFileUtilAdapter
*>(
61 file_system_context_
->GetAsyncFileUtil(kFileSystemType
));
62 return static_cast<LocalFileUtil
*>(adapter
->sync_file_util());
65 FileSystemURL
CreateURL(const std::string
& file_name
) {
66 return file_system_context_
->CreateCrackedFileSystemURL(
67 kOrigin
, kFileSystemType
, base::FilePath().FromUTF8Unsafe(file_name
));
70 base::FilePath
LocalPath(const char *file_name
) {
72 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
73 file_util()->GetLocalFilePath(context
.get(), CreateURL(file_name
), &path
);
77 bool FileExists(const char *file_name
) {
78 return base::PathExists(LocalPath(file_name
)) &&
79 !base::DirectoryExists(LocalPath(file_name
));
82 bool DirectoryExists(const char *file_name
) {
83 return base::DirectoryExists(LocalPath(file_name
));
86 int64
GetSize(const char *file_name
) {
87 base::File::Info info
;
88 base::GetFileInfo(LocalPath(file_name
), &info
);
92 base::PlatformFileError
CreateFile(const char* file_name
,
93 base::PlatformFile
* file_handle
,
95 int file_flags
= base::PLATFORM_FILE_CREATE
|
96 base::PLATFORM_FILE_WRITE
| base::PLATFORM_FILE_ASYNC
;
98 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
99 return file_util()->CreateOrOpen(
101 CreateURL(file_name
),
102 file_flags
, file_handle
, created
);
105 base::PlatformFileError
EnsureFileExists(const char* file_name
,
107 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
108 return file_util()->EnsureFileExists(
110 CreateURL(file_name
), created
);
113 FileSystemContext
* file_system_context() {
114 return file_system_context_
.get();
118 base::MessageLoop message_loop_
;
119 scoped_refptr
<FileSystemContext
> file_system_context_
;
120 base::ScopedTempDir data_dir_
;
122 DISALLOW_COPY_AND_ASSIGN(LocalFileUtilTest
);
125 TEST_F(LocalFileUtilTest
, CreateAndClose
) {
126 const char *file_name
= "test_file";
127 base::PlatformFile file_handle
;
129 ASSERT_EQ(base::PLATFORM_FILE_OK
,
130 CreateFile(file_name
, &file_handle
, &created
));
131 ASSERT_TRUE(created
);
133 EXPECT_TRUE(FileExists(file_name
));
134 EXPECT_EQ(0, GetSize(file_name
));
136 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
137 EXPECT_EQ(base::PLATFORM_FILE_OK
,
138 file_util()->Close(context
.get(), file_handle
));
141 // base::CreateSymbolicLink is only supported on POSIX.
142 #if defined(OS_POSIX)
143 TEST_F(LocalFileUtilTest
, CreateFailForSymlink
) {
144 // Create symlink target file.
145 const char *target_name
= "symlink_target";
146 base::PlatformFile target_handle
;
147 bool symlink_target_created
= false;
148 ASSERT_EQ(base::PLATFORM_FILE_OK
,
149 CreateFile(target_name
, &target_handle
, &symlink_target_created
));
150 ASSERT_TRUE(symlink_target_created
);
151 base::FilePath target_path
= LocalPath(target_name
);
153 // Create symlink where target must be real file.
154 const char *symlink_name
= "symlink_file";
155 base::FilePath symlink_path
= LocalPath(symlink_name
);
156 ASSERT_TRUE(base::CreateSymbolicLink(target_path
, symlink_path
));
157 ASSERT_TRUE(FileExists(symlink_name
));
159 // Try to open the symlink file which should fail.
160 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
161 FileSystemURL url
= CreateURL(symlink_name
);
162 int file_flags
= base::PLATFORM_FILE_OPEN
| base::PLATFORM_FILE_READ
;
163 base::PlatformFile file_handle
;
164 bool created
= false;
165 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND
, file_util()->CreateOrOpen(
166 context
.get(), url
, file_flags
, &file_handle
, &created
));
167 EXPECT_FALSE(created
);
171 TEST_F(LocalFileUtilTest
, EnsureFileExists
) {
172 const char *file_name
= "foobar";
174 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(file_name
, &created
));
175 ASSERT_TRUE(created
);
177 EXPECT_TRUE(FileExists(file_name
));
178 EXPECT_EQ(0, GetSize(file_name
));
180 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(file_name
, &created
));
181 EXPECT_FALSE(created
);
184 TEST_F(LocalFileUtilTest
, TouchFile
) {
185 const char *file_name
= "test_file";
186 base::PlatformFile file_handle
;
188 ASSERT_EQ(base::PLATFORM_FILE_OK
,
189 CreateFile(file_name
, &file_handle
, &created
));
190 ASSERT_TRUE(created
);
192 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
194 base::File::Info info
;
195 ASSERT_TRUE(base::GetFileInfo(LocalPath(file_name
), &info
));
196 const base::Time new_accessed
=
197 info
.last_accessed
+ base::TimeDelta::FromHours(10);
198 const base::Time new_modified
=
199 info
.last_modified
+ base::TimeDelta::FromHours(5);
201 EXPECT_EQ(base::PLATFORM_FILE_OK
,
202 file_util()->Touch(context
.get(), CreateURL(file_name
),
203 new_accessed
, new_modified
));
205 ASSERT_TRUE(base::GetFileInfo(LocalPath(file_name
), &info
));
206 EXPECT_EQ(new_accessed
, info
.last_accessed
);
207 EXPECT_EQ(new_modified
, info
.last_modified
);
209 EXPECT_EQ(base::PLATFORM_FILE_OK
,
210 file_util()->Close(context
.get(), file_handle
));
213 TEST_F(LocalFileUtilTest
, TouchDirectory
) {
214 const char *dir_name
= "test_dir";
215 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
216 ASSERT_EQ(base::PLATFORM_FILE_OK
,
217 file_util()->CreateDirectory(context
.get(),
219 false /* exclusive */,
220 false /* recursive */));
222 base::File::Info info
;
223 ASSERT_TRUE(base::GetFileInfo(LocalPath(dir_name
), &info
));
224 const base::Time new_accessed
=
225 info
.last_accessed
+ base::TimeDelta::FromHours(10);
226 const base::Time new_modified
=
227 info
.last_modified
+ base::TimeDelta::FromHours(5);
229 EXPECT_EQ(base::PLATFORM_FILE_OK
,
230 file_util()->Touch(context
.get(), CreateURL(dir_name
),
231 new_accessed
, new_modified
));
233 ASSERT_TRUE(base::GetFileInfo(LocalPath(dir_name
), &info
));
234 EXPECT_EQ(new_accessed
, info
.last_accessed
);
235 EXPECT_EQ(new_modified
, info
.last_modified
);
238 TEST_F(LocalFileUtilTest
, Truncate
) {
239 const char *file_name
= "truncated";
241 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(file_name
, &created
));
242 ASSERT_TRUE(created
);
244 scoped_ptr
<FileSystemOperationContext
> context
;
246 context
.reset(NewContext());
247 ASSERT_EQ(base::PLATFORM_FILE_OK
,
248 file_util()->Truncate(context
.get(), CreateURL(file_name
), 1020));
250 EXPECT_TRUE(FileExists(file_name
));
251 EXPECT_EQ(1020, GetSize(file_name
));
254 TEST_F(LocalFileUtilTest
, CopyFile
) {
255 const char *from_file
= "fromfile";
256 const char *to_file1
= "tofile1";
257 const char *to_file2
= "tofile2";
259 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(from_file
, &created
));
260 ASSERT_TRUE(created
);
262 scoped_ptr
<FileSystemOperationContext
> context
;
263 context
.reset(NewContext());
264 ASSERT_EQ(base::PLATFORM_FILE_OK
,
265 file_util()->Truncate(context
.get(), CreateURL(from_file
), 1020));
267 EXPECT_TRUE(FileExists(from_file
));
268 EXPECT_EQ(1020, GetSize(from_file
));
270 ASSERT_EQ(base::PLATFORM_FILE_OK
,
271 AsyncFileTestHelper::Copy(file_system_context(),
272 CreateURL(from_file
),
273 CreateURL(to_file1
)));
275 context
.reset(NewContext());
276 ASSERT_EQ(base::PLATFORM_FILE_OK
,
277 AsyncFileTestHelper::Copy(file_system_context(),
278 CreateURL(from_file
),
279 CreateURL(to_file2
)));
281 EXPECT_TRUE(FileExists(from_file
));
282 EXPECT_EQ(1020, GetSize(from_file
));
283 EXPECT_TRUE(FileExists(to_file1
));
284 EXPECT_EQ(1020, GetSize(to_file1
));
285 EXPECT_TRUE(FileExists(to_file2
));
286 EXPECT_EQ(1020, GetSize(to_file2
));
289 TEST_F(LocalFileUtilTest
, CopyDirectory
) {
290 const char *from_dir
= "fromdir";
291 const char *from_file
= "fromdir/fromfile";
292 const char *to_dir
= "todir";
293 const char *to_file
= "todir/fromfile";
295 scoped_ptr
<FileSystemOperationContext
> context
;
297 context
.reset(NewContext());
298 ASSERT_EQ(base::PLATFORM_FILE_OK
,
299 file_util()->CreateDirectory(context
.get(), CreateURL(from_dir
),
301 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(from_file
, &created
));
302 ASSERT_TRUE(created
);
304 context
.reset(NewContext());
305 ASSERT_EQ(base::PLATFORM_FILE_OK
,
306 file_util()->Truncate(context
.get(), CreateURL(from_file
), 1020));
308 EXPECT_TRUE(DirectoryExists(from_dir
));
309 EXPECT_TRUE(FileExists(from_file
));
310 EXPECT_EQ(1020, GetSize(from_file
));
311 EXPECT_FALSE(DirectoryExists(to_dir
));
313 context
.reset(NewContext());
314 ASSERT_EQ(base::PLATFORM_FILE_OK
,
315 AsyncFileTestHelper::Copy(file_system_context(),
316 CreateURL(from_dir
), CreateURL(to_dir
)));
318 EXPECT_TRUE(DirectoryExists(from_dir
));
319 EXPECT_TRUE(FileExists(from_file
));
320 EXPECT_EQ(1020, GetSize(from_file
));
321 EXPECT_TRUE(DirectoryExists(to_dir
));
322 EXPECT_TRUE(FileExists(to_file
));
323 EXPECT_EQ(1020, GetSize(to_file
));
326 TEST_F(LocalFileUtilTest
, MoveFile
) {
327 const char *from_file
= "fromfile";
328 const char *to_file
= "tofile";
330 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(from_file
, &created
));
331 ASSERT_TRUE(created
);
332 scoped_ptr
<FileSystemOperationContext
> context
;
334 context
.reset(NewContext());
335 ASSERT_EQ(base::PLATFORM_FILE_OK
,
336 file_util()->Truncate(context
.get(), CreateURL(from_file
), 1020));
338 EXPECT_TRUE(FileExists(from_file
));
339 EXPECT_EQ(1020, GetSize(from_file
));
341 context
.reset(NewContext());
342 ASSERT_EQ(base::PLATFORM_FILE_OK
,
343 AsyncFileTestHelper::Move(file_system_context(),
344 CreateURL(from_file
),
345 CreateURL(to_file
)));
347 EXPECT_FALSE(FileExists(from_file
));
348 EXPECT_TRUE(FileExists(to_file
));
349 EXPECT_EQ(1020, GetSize(to_file
));
352 TEST_F(LocalFileUtilTest
, MoveDirectory
) {
353 const char *from_dir
= "fromdir";
354 const char *from_file
= "fromdir/fromfile";
355 const char *to_dir
= "todir";
356 const char *to_file
= "todir/fromfile";
358 scoped_ptr
<FileSystemOperationContext
> context
;
360 context
.reset(NewContext());
361 ASSERT_EQ(base::PLATFORM_FILE_OK
,
362 file_util()->CreateDirectory(context
.get(), CreateURL(from_dir
),
364 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(from_file
, &created
));
365 ASSERT_TRUE(created
);
367 context
.reset(NewContext());
368 ASSERT_EQ(base::PLATFORM_FILE_OK
,
369 file_util()->Truncate(context
.get(), CreateURL(from_file
), 1020));
371 EXPECT_TRUE(DirectoryExists(from_dir
));
372 EXPECT_TRUE(FileExists(from_file
));
373 EXPECT_EQ(1020, GetSize(from_file
));
374 EXPECT_FALSE(DirectoryExists(to_dir
));
376 context
.reset(NewContext());
377 ASSERT_EQ(base::PLATFORM_FILE_OK
,
378 AsyncFileTestHelper::Move(file_system_context(),
382 EXPECT_FALSE(DirectoryExists(from_dir
));
383 EXPECT_TRUE(DirectoryExists(to_dir
));
384 EXPECT_TRUE(FileExists(to_file
));
385 EXPECT_EQ(1020, GetSize(to_file
));
388 } // namespace fileapi