1 // Copyright (c) 2012 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.h"
11 #include "base/message_loop_proxy.h"
12 #include "base/platform_file.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "base/utf_string_conversions.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "webkit/fileapi/async_file_test_helper.h"
17 #include "webkit/fileapi/file_system_context.h"
18 #include "webkit/fileapi/file_system_file_util.h"
19 #include "webkit/fileapi/file_system_operation_context.h"
20 #include "webkit/fileapi/file_system_types.h"
21 #include "webkit/fileapi/local_file_system_test_helper.h"
22 #include "webkit/fileapi/local_file_util.h"
23 #include "webkit/fileapi/native_file_util.h"
27 // TODO(dmikurube): Cover all public methods in LocalFileUtil.
28 class LocalFileUtilTest
: public testing::Test
{
31 : test_helper_(GURL("http://foo/"), kFileSystemTypeTest
) {}
33 virtual void SetUp() {
34 ASSERT_TRUE(data_dir_
.CreateUniqueTempDir());
35 test_helper_
.SetUp(data_dir_
.path());
38 virtual void TearDown() {
39 test_helper_
.TearDown();
43 FileSystemOperationContext
* NewContext() {
44 FileSystemOperationContext
* context
= test_helper_
.NewOperationContext();
48 LocalFileUtil
* FileUtil() {
49 return static_cast<LocalFileUtil
*>(test_helper_
.file_util());
52 FileSystemURL
Path(const std::string
& file_name
) {
53 return test_helper_
.CreateURLFromUTF8(file_name
);
56 base::FilePath
LocalPath(const char *file_name
) {
57 return test_helper_
.GetLocalPathFromASCII(file_name
);
60 bool FileExists(const char *file_name
) {
61 return file_util::PathExists(LocalPath(file_name
)) &&
62 !file_util::DirectoryExists(LocalPath(file_name
));
65 bool DirectoryExists(const char *file_name
) {
66 return file_util::DirectoryExists(LocalPath(file_name
));
69 int64
GetSize(const char *file_name
) {
70 base::PlatformFileInfo info
;
71 file_util::GetFileInfo(LocalPath(file_name
), &info
);
75 base::PlatformFileError
CreateFile(const char* file_name
,
76 base::PlatformFile
* file_handle
,
78 int file_flags
= base::PLATFORM_FILE_CREATE
|
79 base::PLATFORM_FILE_WRITE
| base::PLATFORM_FILE_ASYNC
;
81 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
82 return FileUtil()->CreateOrOpen(
85 file_flags
, file_handle
, created
);
88 base::PlatformFileError
EnsureFileExists(const char* file_name
,
90 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
91 return FileUtil()->EnsureFileExists(
93 Path(file_name
), created
);
96 const LocalFileSystemTestOriginHelper
& test_helper() const {
100 FileSystemContext
* file_system_context() {
101 return test_helper_
.file_system_context();
105 scoped_ptr
<LocalFileUtil
> local_file_util_
;
106 base::ScopedTempDir data_dir_
;
107 base::MessageLoop message_loop_
;
108 LocalFileSystemTestOriginHelper test_helper_
;
110 DISALLOW_COPY_AND_ASSIGN(LocalFileUtilTest
);
113 TEST_F(LocalFileUtilTest
, CreateAndClose
) {
114 const char *file_name
= "test_file";
115 base::PlatformFile file_handle
;
117 ASSERT_EQ(base::PLATFORM_FILE_OK
,
118 CreateFile(file_name
, &file_handle
, &created
));
119 ASSERT_TRUE(created
);
121 EXPECT_TRUE(FileExists(file_name
));
122 EXPECT_EQ(0, GetSize(file_name
));
124 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
125 EXPECT_EQ(base::PLATFORM_FILE_OK
,
126 FileUtil()->Close(context
.get(), file_handle
));
129 // file_util::CreateSymbolicLink is only supported on POSIX.
130 #if defined(OS_POSIX)
131 TEST_F(LocalFileUtilTest
, CreateFailForSymlink
) {
132 // Create symlink target file.
133 const char *target_name
= "symlink_target";
134 base::PlatformFile target_handle
;
135 bool symlink_target_created
= false;
136 ASSERT_EQ(base::PLATFORM_FILE_OK
,
137 CreateFile(target_name
, &target_handle
, &symlink_target_created
));
138 ASSERT_TRUE(symlink_target_created
);
139 base::FilePath target_path
= LocalPath(target_name
);
141 // Create symlink where target must be real file.
142 const char *symlink_name
= "symlink_file";
143 base::FilePath symlink_path
= LocalPath(symlink_name
);
144 ASSERT_TRUE(file_util::CreateSymbolicLink(target_path
, symlink_path
));
145 ASSERT_TRUE(FileExists(symlink_name
));
147 // Try to open the symlink file which should fail.
148 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
149 FileSystemURL url
= test_helper().CreateURLFromUTF8(symlink_name
);
150 int file_flags
= base::PLATFORM_FILE_OPEN
| base::PLATFORM_FILE_READ
;
151 base::PlatformFile file_handle
;
152 bool created
= false;
153 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND
, FileUtil()->CreateOrOpen(
154 context
.get(), url
, file_flags
, &file_handle
, &created
));
155 EXPECT_FALSE(created
);
159 TEST_F(LocalFileUtilTest
, EnsureFileExists
) {
160 const char *file_name
= "foobar";
162 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(file_name
, &created
));
163 ASSERT_TRUE(created
);
165 EXPECT_TRUE(FileExists(file_name
));
166 EXPECT_EQ(0, GetSize(file_name
));
168 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(file_name
, &created
));
169 EXPECT_FALSE(created
);
172 TEST_F(LocalFileUtilTest
, TouchFile
) {
173 const char *file_name
= "test_file";
174 base::PlatformFile file_handle
;
176 ASSERT_EQ(base::PLATFORM_FILE_OK
,
177 CreateFile(file_name
, &file_handle
, &created
));
178 ASSERT_TRUE(created
);
180 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
182 base::PlatformFileInfo info
;
183 ASSERT_TRUE(file_util::GetFileInfo(LocalPath(file_name
), &info
));
184 const base::Time new_accessed
=
185 info
.last_accessed
+ base::TimeDelta::FromHours(10);
186 const base::Time new_modified
=
187 info
.last_modified
+ base::TimeDelta::FromHours(5);
189 EXPECT_EQ(base::PLATFORM_FILE_OK
,
190 FileUtil()->Touch(context
.get(), Path(file_name
),
191 new_accessed
, new_modified
));
193 ASSERT_TRUE(file_util::GetFileInfo(LocalPath(file_name
), &info
));
194 EXPECT_EQ(new_accessed
, info
.last_accessed
);
195 EXPECT_EQ(new_modified
, info
.last_modified
);
197 EXPECT_EQ(base::PLATFORM_FILE_OK
,
198 FileUtil()->Close(context
.get(), file_handle
));
201 TEST_F(LocalFileUtilTest
, TouchDirectory
) {
202 const char *dir_name
= "test_dir";
203 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
204 ASSERT_EQ(base::PLATFORM_FILE_OK
,
205 FileUtil()->CreateDirectory(context
.get(),
207 false /* exclusive */,
208 false /* recursive */));
210 base::PlatformFileInfo info
;
211 ASSERT_TRUE(file_util::GetFileInfo(LocalPath(dir_name
), &info
));
212 const base::Time new_accessed
=
213 info
.last_accessed
+ base::TimeDelta::FromHours(10);
214 const base::Time new_modified
=
215 info
.last_modified
+ base::TimeDelta::FromHours(5);
217 EXPECT_EQ(base::PLATFORM_FILE_OK
,
218 FileUtil()->Touch(context
.get(), Path(dir_name
),
219 new_accessed
, new_modified
));
221 ASSERT_TRUE(file_util::GetFileInfo(LocalPath(dir_name
), &info
));
222 EXPECT_EQ(new_accessed
, info
.last_accessed
);
223 EXPECT_EQ(new_modified
, info
.last_modified
);
226 TEST_F(LocalFileUtilTest
, Truncate
) {
227 const char *file_name
= "truncated";
229 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(file_name
, &created
));
230 ASSERT_TRUE(created
);
232 scoped_ptr
<FileSystemOperationContext
> context
;
234 context
.reset(NewContext());
235 ASSERT_EQ(base::PLATFORM_FILE_OK
,
236 FileUtil()->Truncate(context
.get(), Path(file_name
), 1020));
238 EXPECT_TRUE(FileExists(file_name
));
239 EXPECT_EQ(1020, GetSize(file_name
));
242 TEST_F(LocalFileUtilTest
, CopyFile
) {
243 const char *from_file
= "fromfile";
244 const char *to_file1
= "tofile1";
245 const char *to_file2
= "tofile2";
247 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(from_file
, &created
));
248 ASSERT_TRUE(created
);
250 scoped_ptr
<FileSystemOperationContext
> context
;
251 context
.reset(NewContext());
252 ASSERT_EQ(base::PLATFORM_FILE_OK
,
253 FileUtil()->Truncate(context
.get(), Path(from_file
), 1020));
255 EXPECT_TRUE(FileExists(from_file
));
256 EXPECT_EQ(1020, GetSize(from_file
));
258 ASSERT_EQ(base::PLATFORM_FILE_OK
,
259 AsyncFileTestHelper::Copy(file_system_context(),
260 Path(from_file
), Path(to_file1
)));
262 context
.reset(NewContext());
263 ASSERT_EQ(base::PLATFORM_FILE_OK
,
264 AsyncFileTestHelper::Copy(file_system_context(),
265 Path(from_file
), Path(to_file2
)));
267 EXPECT_TRUE(FileExists(from_file
));
268 EXPECT_EQ(1020, GetSize(from_file
));
269 EXPECT_TRUE(FileExists(to_file1
));
270 EXPECT_EQ(1020, GetSize(to_file1
));
271 EXPECT_TRUE(FileExists(to_file2
));
272 EXPECT_EQ(1020, GetSize(to_file2
));
275 TEST_F(LocalFileUtilTest
, CopyDirectory
) {
276 const char *from_dir
= "fromdir";
277 const char *from_file
= "fromdir/fromfile";
278 const char *to_dir
= "todir";
279 const char *to_file
= "todir/fromfile";
281 scoped_ptr
<FileSystemOperationContext
> context
;
283 context
.reset(NewContext());
284 ASSERT_EQ(base::PLATFORM_FILE_OK
,
285 FileUtil()->CreateDirectory(context
.get(), Path(from_dir
), false, false));
286 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(from_file
, &created
));
287 ASSERT_TRUE(created
);
289 context
.reset(NewContext());
290 ASSERT_EQ(base::PLATFORM_FILE_OK
,
291 FileUtil()->Truncate(context
.get(), Path(from_file
), 1020));
293 EXPECT_TRUE(DirectoryExists(from_dir
));
294 EXPECT_TRUE(FileExists(from_file
));
295 EXPECT_EQ(1020, GetSize(from_file
));
296 EXPECT_FALSE(DirectoryExists(to_dir
));
298 context
.reset(NewContext());
299 ASSERT_EQ(base::PLATFORM_FILE_OK
,
300 AsyncFileTestHelper::Copy(file_system_context(),
301 Path(from_dir
), Path(to_dir
)));
303 EXPECT_TRUE(DirectoryExists(from_dir
));
304 EXPECT_TRUE(FileExists(from_file
));
305 EXPECT_EQ(1020, GetSize(from_file
));
306 EXPECT_TRUE(DirectoryExists(to_dir
));
307 EXPECT_TRUE(FileExists(to_file
));
308 EXPECT_EQ(1020, GetSize(to_file
));
311 TEST_F(LocalFileUtilTest
, MoveFile
) {
312 const char *from_file
= "fromfile";
313 const char *to_file
= "tofile";
315 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(from_file
, &created
));
316 ASSERT_TRUE(created
);
317 scoped_ptr
<FileSystemOperationContext
> context
;
319 context
.reset(NewContext());
320 ASSERT_EQ(base::PLATFORM_FILE_OK
,
321 FileUtil()->Truncate(context
.get(), Path(from_file
), 1020));
323 EXPECT_TRUE(FileExists(from_file
));
324 EXPECT_EQ(1020, GetSize(from_file
));
326 context
.reset(NewContext());
327 ASSERT_EQ(base::PLATFORM_FILE_OK
,
328 AsyncFileTestHelper::Move(file_system_context(),
329 Path(from_file
), Path(to_file
)));
331 EXPECT_FALSE(FileExists(from_file
));
332 EXPECT_TRUE(FileExists(to_file
));
333 EXPECT_EQ(1020, GetSize(to_file
));
336 TEST_F(LocalFileUtilTest
, MoveDirectory
) {
337 const char *from_dir
= "fromdir";
338 const char *from_file
= "fromdir/fromfile";
339 const char *to_dir
= "todir";
340 const char *to_file
= "todir/fromfile";
342 scoped_ptr
<FileSystemOperationContext
> context
;
344 context
.reset(NewContext());
345 ASSERT_EQ(base::PLATFORM_FILE_OK
,
346 FileUtil()->CreateDirectory(context
.get(), Path(from_dir
), false, false));
347 ASSERT_EQ(base::PLATFORM_FILE_OK
, EnsureFileExists(from_file
, &created
));
348 ASSERT_TRUE(created
);
350 context
.reset(NewContext());
351 ASSERT_EQ(base::PLATFORM_FILE_OK
,
352 FileUtil()->Truncate(context
.get(), Path(from_file
), 1020));
354 EXPECT_TRUE(DirectoryExists(from_dir
));
355 EXPECT_TRUE(FileExists(from_file
));
356 EXPECT_EQ(1020, GetSize(from_file
));
357 EXPECT_FALSE(DirectoryExists(to_dir
));
359 context
.reset(NewContext());
360 ASSERT_EQ(base::PLATFORM_FILE_OK
,
361 AsyncFileTestHelper::Move(file_system_context(),
362 Path(from_dir
), Path(to_dir
)));
364 EXPECT_FALSE(DirectoryExists(from_dir
));
365 EXPECT_TRUE(DirectoryExists(to_dir
));
366 EXPECT_TRUE(FileExists(to_file
));
367 EXPECT_EQ(1020, GetSize(to_file
));
370 } // namespace fileapi