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.h"
9 #include "base/files/file_path.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/platform_file.h"
13 #include "base/run_loop.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "content/public/test/async_file_test_helper.h"
17 #include "content/public/test/test_file_system_context.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "webkit/browser/fileapi/async_file_util_adapter.h"
20 #include "webkit/browser/fileapi/file_system_context.h"
21 #include "webkit/browser/fileapi/file_system_file_util.h"
22 #include "webkit/browser/fileapi/file_system_operation_context.h"
23 #include "webkit/browser/fileapi/local_file_util.h"
24 #include "webkit/browser/fileapi/native_file_util.h"
25 #include "webkit/common/fileapi/file_system_types.h"
27 using content::AsyncFileTestHelper
;
28 using fileapi::AsyncFileUtilAdapter
;
29 using fileapi::FileSystemContext
;
30 using fileapi::FileSystemOperationContext
;
31 using fileapi::FileSystemType
;
32 using fileapi::FileSystemURL
;
33 using fileapi::LocalFileUtil
;
39 const GURL
kOrigin("http://foo/");
40 const FileSystemType kFileSystemType
= fileapi::kFileSystemTypeTest
;
44 class LocalFileUtilTest
: public testing::Test
{
46 LocalFileUtilTest() {}
48 virtual void SetUp() {
49 ASSERT_TRUE(data_dir_
.CreateUniqueTempDir());
50 file_system_context_
= CreateFileSystemContextForTesting(
51 NULL
, data_dir_
.path());
54 virtual void TearDown() {
55 file_system_context_
= NULL
;
56 base::RunLoop().RunUntilIdle();
60 FileSystemOperationContext
* NewContext() {
61 FileSystemOperationContext
* context
=
62 new FileSystemOperationContext(file_system_context_
.get());
63 context
->set_update_observers(
64 *file_system_context_
->GetUpdateObservers(kFileSystemType
));
68 LocalFileUtil
* file_util() {
69 AsyncFileUtilAdapter
* adapter
= static_cast<AsyncFileUtilAdapter
*>(
70 file_system_context_
->GetAsyncFileUtil(kFileSystemType
));
71 return static_cast<LocalFileUtil
*>(adapter
->sync_file_util());
74 FileSystemURL
CreateURL(const std::string
& file_name
) {
75 return file_system_context_
->CreateCrackedFileSystemURL(
76 kOrigin
, kFileSystemType
, base::FilePath().FromUTF8Unsafe(file_name
));
79 base::FilePath
LocalPath(const char *file_name
) {
81 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
82 file_util()->GetLocalFilePath(context
.get(), CreateURL(file_name
), &path
);
86 bool FileExists(const char *file_name
) {
87 return base::PathExists(LocalPath(file_name
)) &&
88 !base::DirectoryExists(LocalPath(file_name
));
91 bool DirectoryExists(const char *file_name
) {
92 return base::DirectoryExists(LocalPath(file_name
));
95 int64
GetSize(const char *file_name
) {
96 base::File::Info info
;
97 base::GetFileInfo(LocalPath(file_name
), &info
);
101 base::File::Error
CreateFile(const char* file_name
,
102 base::PlatformFile
* file_handle
,
104 int file_flags
= base::PLATFORM_FILE_CREATE
|
105 base::PLATFORM_FILE_WRITE
| base::PLATFORM_FILE_ASYNC
;
107 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
108 return file_util()->CreateOrOpen(
110 CreateURL(file_name
),
111 file_flags
, file_handle
, created
);
114 base::File::Error
EnsureFileExists(const char* file_name
,
116 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
117 return file_util()->EnsureFileExists(
119 CreateURL(file_name
), created
);
122 FileSystemContext
* file_system_context() {
123 return file_system_context_
.get();
127 base::MessageLoop message_loop_
;
128 scoped_refptr
<FileSystemContext
> file_system_context_
;
129 base::ScopedTempDir data_dir_
;
131 DISALLOW_COPY_AND_ASSIGN(LocalFileUtilTest
);
134 TEST_F(LocalFileUtilTest
, CreateAndClose
) {
135 const char *file_name
= "test_file";
136 base::PlatformFile file_handle
;
138 ASSERT_EQ(base::File::FILE_OK
,
139 CreateFile(file_name
, &file_handle
, &created
));
140 ASSERT_TRUE(created
);
142 EXPECT_TRUE(FileExists(file_name
));
143 EXPECT_EQ(0, GetSize(file_name
));
145 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
146 EXPECT_EQ(base::File::FILE_OK
,
147 file_util()->Close(context
.get(), file_handle
));
150 // base::CreateSymbolicLink is only supported on POSIX.
151 #if defined(OS_POSIX)
152 TEST_F(LocalFileUtilTest
, CreateFailForSymlink
) {
153 // Create symlink target file.
154 const char *target_name
= "symlink_target";
155 base::PlatformFile target_handle
;
156 bool symlink_target_created
= false;
157 ASSERT_EQ(base::File::FILE_OK
,
158 CreateFile(target_name
, &target_handle
, &symlink_target_created
));
159 ASSERT_TRUE(symlink_target_created
);
160 base::FilePath target_path
= LocalPath(target_name
);
162 // Create symlink where target must be real file.
163 const char *symlink_name
= "symlink_file";
164 base::FilePath symlink_path
= LocalPath(symlink_name
);
165 ASSERT_TRUE(base::CreateSymbolicLink(target_path
, symlink_path
));
166 ASSERT_TRUE(FileExists(symlink_name
));
168 // Try to open the symlink file which should fail.
169 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
170 FileSystemURL url
= CreateURL(symlink_name
);
171 int file_flags
= base::PLATFORM_FILE_OPEN
| base::PLATFORM_FILE_READ
;
172 base::PlatformFile file_handle
;
173 bool created
= false;
174 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND
,
175 file_util()->CreateOrOpen(context
.get(), url
, file_flags
,
176 &file_handle
, &created
));
177 EXPECT_FALSE(created
);
181 TEST_F(LocalFileUtilTest
, EnsureFileExists
) {
182 const char *file_name
= "foobar";
184 ASSERT_EQ(base::File::FILE_OK
, EnsureFileExists(file_name
, &created
));
185 ASSERT_TRUE(created
);
187 EXPECT_TRUE(FileExists(file_name
));
188 EXPECT_EQ(0, GetSize(file_name
));
190 ASSERT_EQ(base::File::FILE_OK
, EnsureFileExists(file_name
, &created
));
191 EXPECT_FALSE(created
);
194 TEST_F(LocalFileUtilTest
, TouchFile
) {
195 const char *file_name
= "test_file";
196 base::PlatformFile file_handle
;
198 ASSERT_EQ(base::File::FILE_OK
,
199 CreateFile(file_name
, &file_handle
, &created
));
200 ASSERT_TRUE(created
);
202 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
204 base::File::Info info
;
205 ASSERT_TRUE(base::GetFileInfo(LocalPath(file_name
), &info
));
206 const base::Time new_accessed
=
207 info
.last_accessed
+ base::TimeDelta::FromHours(10);
208 const base::Time new_modified
=
209 info
.last_modified
+ base::TimeDelta::FromHours(5);
211 EXPECT_EQ(base::File::FILE_OK
,
212 file_util()->Touch(context
.get(), CreateURL(file_name
),
213 new_accessed
, new_modified
));
215 ASSERT_TRUE(base::GetFileInfo(LocalPath(file_name
), &info
));
216 EXPECT_EQ(new_accessed
, info
.last_accessed
);
217 EXPECT_EQ(new_modified
, info
.last_modified
);
219 EXPECT_EQ(base::File::FILE_OK
,
220 file_util()->Close(context
.get(), file_handle
));
223 TEST_F(LocalFileUtilTest
, TouchDirectory
) {
224 const char *dir_name
= "test_dir";
225 scoped_ptr
<FileSystemOperationContext
> context(NewContext());
226 ASSERT_EQ(base::File::FILE_OK
,
227 file_util()->CreateDirectory(context
.get(),
229 false /* exclusive */,
230 false /* recursive */));
232 base::File::Info info
;
233 ASSERT_TRUE(base::GetFileInfo(LocalPath(dir_name
), &info
));
234 const base::Time new_accessed
=
235 info
.last_accessed
+ base::TimeDelta::FromHours(10);
236 const base::Time new_modified
=
237 info
.last_modified
+ base::TimeDelta::FromHours(5);
239 EXPECT_EQ(base::File::FILE_OK
,
240 file_util()->Touch(context
.get(), CreateURL(dir_name
),
241 new_accessed
, new_modified
));
243 ASSERT_TRUE(base::GetFileInfo(LocalPath(dir_name
), &info
));
244 EXPECT_EQ(new_accessed
, info
.last_accessed
);
245 EXPECT_EQ(new_modified
, info
.last_modified
);
248 TEST_F(LocalFileUtilTest
, Truncate
) {
249 const char *file_name
= "truncated";
251 ASSERT_EQ(base::File::FILE_OK
, EnsureFileExists(file_name
, &created
));
252 ASSERT_TRUE(created
);
254 scoped_ptr
<FileSystemOperationContext
> context
;
256 context
.reset(NewContext());
257 ASSERT_EQ(base::File::FILE_OK
,
258 file_util()->Truncate(context
.get(), CreateURL(file_name
), 1020));
260 EXPECT_TRUE(FileExists(file_name
));
261 EXPECT_EQ(1020, GetSize(file_name
));
264 TEST_F(LocalFileUtilTest
, CopyFile
) {
265 const char *from_file
= "fromfile";
266 const char *to_file1
= "tofile1";
267 const char *to_file2
= "tofile2";
269 ASSERT_EQ(base::File::FILE_OK
, EnsureFileExists(from_file
, &created
));
270 ASSERT_TRUE(created
);
272 scoped_ptr
<FileSystemOperationContext
> context
;
273 context
.reset(NewContext());
274 ASSERT_EQ(base::File::FILE_OK
,
275 file_util()->Truncate(context
.get(), CreateURL(from_file
), 1020));
277 EXPECT_TRUE(FileExists(from_file
));
278 EXPECT_EQ(1020, GetSize(from_file
));
280 ASSERT_EQ(base::File::FILE_OK
,
281 AsyncFileTestHelper::Copy(file_system_context(),
282 CreateURL(from_file
),
283 CreateURL(to_file1
)));
285 context
.reset(NewContext());
286 ASSERT_EQ(base::File::FILE_OK
,
287 AsyncFileTestHelper::Copy(file_system_context(),
288 CreateURL(from_file
),
289 CreateURL(to_file2
)));
291 EXPECT_TRUE(FileExists(from_file
));
292 EXPECT_EQ(1020, GetSize(from_file
));
293 EXPECT_TRUE(FileExists(to_file1
));
294 EXPECT_EQ(1020, GetSize(to_file1
));
295 EXPECT_TRUE(FileExists(to_file2
));
296 EXPECT_EQ(1020, GetSize(to_file2
));
299 TEST_F(LocalFileUtilTest
, CopyDirectory
) {
300 const char *from_dir
= "fromdir";
301 const char *from_file
= "fromdir/fromfile";
302 const char *to_dir
= "todir";
303 const char *to_file
= "todir/fromfile";
305 scoped_ptr
<FileSystemOperationContext
> context
;
307 context
.reset(NewContext());
308 ASSERT_EQ(base::File::FILE_OK
,
309 file_util()->CreateDirectory(context
.get(), CreateURL(from_dir
),
311 ASSERT_EQ(base::File::FILE_OK
, EnsureFileExists(from_file
, &created
));
312 ASSERT_TRUE(created
);
314 context
.reset(NewContext());
315 ASSERT_EQ(base::File::FILE_OK
,
316 file_util()->Truncate(context
.get(), CreateURL(from_file
), 1020));
318 EXPECT_TRUE(DirectoryExists(from_dir
));
319 EXPECT_TRUE(FileExists(from_file
));
320 EXPECT_EQ(1020, GetSize(from_file
));
321 EXPECT_FALSE(DirectoryExists(to_dir
));
323 context
.reset(NewContext());
324 ASSERT_EQ(base::File::FILE_OK
,
325 AsyncFileTestHelper::Copy(file_system_context(),
326 CreateURL(from_dir
), CreateURL(to_dir
)));
328 EXPECT_TRUE(DirectoryExists(from_dir
));
329 EXPECT_TRUE(FileExists(from_file
));
330 EXPECT_EQ(1020, GetSize(from_file
));
331 EXPECT_TRUE(DirectoryExists(to_dir
));
332 EXPECT_TRUE(FileExists(to_file
));
333 EXPECT_EQ(1020, GetSize(to_file
));
336 TEST_F(LocalFileUtilTest
, MoveFile
) {
337 const char *from_file
= "fromfile";
338 const char *to_file
= "tofile";
340 ASSERT_EQ(base::File::FILE_OK
, EnsureFileExists(from_file
, &created
));
341 ASSERT_TRUE(created
);
342 scoped_ptr
<FileSystemOperationContext
> context
;
344 context
.reset(NewContext());
345 ASSERT_EQ(base::File::FILE_OK
,
346 file_util()->Truncate(context
.get(), CreateURL(from_file
), 1020));
348 EXPECT_TRUE(FileExists(from_file
));
349 EXPECT_EQ(1020, GetSize(from_file
));
351 context
.reset(NewContext());
352 ASSERT_EQ(base::File::FILE_OK
,
353 AsyncFileTestHelper::Move(file_system_context(),
354 CreateURL(from_file
),
355 CreateURL(to_file
)));
357 EXPECT_FALSE(FileExists(from_file
));
358 EXPECT_TRUE(FileExists(to_file
));
359 EXPECT_EQ(1020, GetSize(to_file
));
362 TEST_F(LocalFileUtilTest
, MoveDirectory
) {
363 const char *from_dir
= "fromdir";
364 const char *from_file
= "fromdir/fromfile";
365 const char *to_dir
= "todir";
366 const char *to_file
= "todir/fromfile";
368 scoped_ptr
<FileSystemOperationContext
> context
;
370 context
.reset(NewContext());
371 ASSERT_EQ(base::File::FILE_OK
,
372 file_util()->CreateDirectory(context
.get(), CreateURL(from_dir
),
374 ASSERT_EQ(base::File::FILE_OK
, EnsureFileExists(from_file
, &created
));
375 ASSERT_TRUE(created
);
377 context
.reset(NewContext());
378 ASSERT_EQ(base::File::FILE_OK
,
379 file_util()->Truncate(context
.get(), CreateURL(from_file
), 1020));
381 EXPECT_TRUE(DirectoryExists(from_dir
));
382 EXPECT_TRUE(FileExists(from_file
));
383 EXPECT_EQ(1020, GetSize(from_file
));
384 EXPECT_FALSE(DirectoryExists(to_dir
));
386 context
.reset(NewContext());
387 ASSERT_EQ(base::File::FILE_OK
,
388 AsyncFileTestHelper::Move(file_system_context(),
392 EXPECT_FALSE(DirectoryExists(from_dir
));
393 EXPECT_TRUE(DirectoryExists(to_dir
));
394 EXPECT_TRUE(FileExists(to_file
));
395 EXPECT_EQ(1020, GetSize(to_file
));
398 } // namespace content