1 // Copyright 2014 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/files/file.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "storage/browser/fileapi/native_file_util.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 using storage::FileSystemFileUtil
;
15 using storage::FileSystemOperation
;
16 using storage::NativeFileUtil
;
20 class NativeFileUtilTest
: public testing::Test
{
22 NativeFileUtilTest() {}
24 void SetUp() override
{ ASSERT_TRUE(data_dir_
.CreateUniqueTempDir()); }
27 base::FilePath
Path() {
28 return data_dir_
.path();
31 base::FilePath
Path(const char* file_name
) {
32 return data_dir_
.path().AppendASCII(file_name
);
35 bool FileExists(const base::FilePath
& path
) {
36 return base::PathExists(path
) &&
37 !base::DirectoryExists(path
);
40 int64
GetSize(const base::FilePath
& path
) {
41 base::File::Info info
;
42 base::GetFileInfo(path
, &info
);
47 base::ScopedTempDir data_dir_
;
49 DISALLOW_COPY_AND_ASSIGN(NativeFileUtilTest
);
52 TEST_F(NativeFileUtilTest
, CreateCloseAndDeleteFile
) {
53 base::FilePath file_name
= Path("test_file");
54 int flags
= base::File::FLAG_WRITE
| base::File::FLAG_ASYNC
;
56 NativeFileUtil::CreateOrOpen(file_name
, base::File::FLAG_CREATE
| flags
);
57 ASSERT_TRUE(file
.IsValid());
58 ASSERT_TRUE(file
.created());
60 EXPECT_TRUE(base::PathExists(file_name
));
61 EXPECT_TRUE(NativeFileUtil::PathExists(file_name
));
62 EXPECT_EQ(0, GetSize(file_name
));
65 file
= NativeFileUtil::CreateOrOpen(file_name
, base::File::FLAG_OPEN
| flags
);
66 ASSERT_TRUE(file
.IsValid());
67 ASSERT_FALSE(file
.created());
70 ASSERT_EQ(base::File::FILE_OK
,
71 NativeFileUtil::DeleteFile(file_name
));
72 EXPECT_FALSE(base::PathExists(file_name
));
73 EXPECT_FALSE(NativeFileUtil::PathExists(file_name
));
76 TEST_F(NativeFileUtilTest
, EnsureFileExists
) {
77 base::FilePath file_name
= Path("foobar");
79 ASSERT_EQ(base::File::FILE_OK
,
80 NativeFileUtil::EnsureFileExists(file_name
, &created
));
83 EXPECT_TRUE(FileExists(file_name
));
84 EXPECT_EQ(0, GetSize(file_name
));
86 ASSERT_EQ(base::File::FILE_OK
,
87 NativeFileUtil::EnsureFileExists(file_name
, &created
));
88 EXPECT_FALSE(created
);
91 TEST_F(NativeFileUtilTest
, CreateAndDeleteDirectory
) {
92 base::FilePath dir_name
= Path("test_dir");
93 ASSERT_EQ(base::File::FILE_OK
,
94 NativeFileUtil::CreateDirectory(dir_name
,
95 false /* exclusive */,
96 false /* recursive */));
98 EXPECT_TRUE(NativeFileUtil::DirectoryExists(dir_name
));
99 EXPECT_TRUE(base::DirectoryExists(dir_name
));
101 ASSERT_EQ(base::File::FILE_ERROR_EXISTS
,
102 NativeFileUtil::CreateDirectory(dir_name
,
103 true /* exclusive */,
104 false /* recursive */));
106 ASSERT_EQ(base::File::FILE_OK
,
107 NativeFileUtil::DeleteDirectory(dir_name
));
108 EXPECT_FALSE(base::DirectoryExists(dir_name
));
109 EXPECT_FALSE(NativeFileUtil::DirectoryExists(dir_name
));
112 TEST_F(NativeFileUtilTest
, TouchFileAndGetFileInfo
) {
113 base::FilePath file_name
= Path("test_file");
114 base::File::Info native_info
;
115 ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND
,
116 NativeFileUtil::GetFileInfo(file_name
, &native_info
));
118 bool created
= false;
119 ASSERT_EQ(base::File::FILE_OK
,
120 NativeFileUtil::EnsureFileExists(file_name
, &created
));
121 ASSERT_TRUE(created
);
123 base::File::Info info
;
124 ASSERT_TRUE(base::GetFileInfo(file_name
, &info
));
125 ASSERT_EQ(base::File::FILE_OK
,
126 NativeFileUtil::GetFileInfo(file_name
, &native_info
));
127 ASSERT_EQ(info
.size
, native_info
.size
);
128 ASSERT_EQ(info
.is_directory
, native_info
.is_directory
);
129 ASSERT_EQ(info
.is_symbolic_link
, native_info
.is_symbolic_link
);
130 ASSERT_EQ(info
.last_modified
, native_info
.last_modified
);
131 ASSERT_EQ(info
.last_accessed
, native_info
.last_accessed
);
132 ASSERT_EQ(info
.creation_time
, native_info
.creation_time
);
134 const base::Time new_accessed
=
135 info
.last_accessed
+ base::TimeDelta::FromHours(10);
136 const base::Time new_modified
=
137 info
.last_modified
+ base::TimeDelta::FromHours(5);
139 EXPECT_EQ(base::File::FILE_OK
,
140 NativeFileUtil::Touch(file_name
,
141 new_accessed
, new_modified
));
143 ASSERT_TRUE(base::GetFileInfo(file_name
, &info
));
144 EXPECT_EQ(new_accessed
, info
.last_accessed
);
145 EXPECT_EQ(new_modified
, info
.last_modified
);
148 TEST_F(NativeFileUtilTest
, CreateFileEnumerator
) {
149 base::FilePath path_1
= Path("dir1");
150 base::FilePath path_2
= Path("file1");
151 base::FilePath path_11
= Path("dir1").AppendASCII("file11");
152 base::FilePath path_12
= Path("dir1").AppendASCII("dir12");
153 base::FilePath path_121
=
154 Path("dir1").AppendASCII("dir12").AppendASCII("file121");
155 ASSERT_EQ(base::File::FILE_OK
,
156 NativeFileUtil::CreateDirectory(path_1
, false, false));
157 bool created
= false;
158 ASSERT_EQ(base::File::FILE_OK
,
159 NativeFileUtil::EnsureFileExists(path_2
, &created
));
160 ASSERT_EQ(base::File::FILE_OK
,
161 NativeFileUtil::EnsureFileExists(path_11
, &created
));
162 ASSERT_EQ(base::File::FILE_OK
,
163 NativeFileUtil::CreateDirectory(path_12
, false, false));
164 ASSERT_EQ(base::File::FILE_OK
,
165 NativeFileUtil::EnsureFileExists(path_121
, &created
));
168 scoped_ptr
<FileSystemFileUtil::AbstractFileEnumerator
> enumerator
=
169 NativeFileUtil::CreateFileEnumerator(Path(), false);
170 std::set
<base::FilePath
> set
;
173 for (base::FilePath path
= enumerator
->Next(); !path
.empty();
174 path
= enumerator
->Next())
175 EXPECT_EQ(1U, set
.erase(path
));
176 EXPECT_TRUE(set
.empty());
180 scoped_ptr
<FileSystemFileUtil::AbstractFileEnumerator
> enumerator
=
181 NativeFileUtil::CreateFileEnumerator(Path(), true);
182 std::set
<base::FilePath
> set
;
187 set
.insert(path_121
);
188 for (base::FilePath path
= enumerator
->Next(); !path
.empty();
189 path
= enumerator
->Next())
190 EXPECT_EQ(1U, set
.erase(path
));
191 EXPECT_TRUE(set
.empty());
195 TEST_F(NativeFileUtilTest
, Truncate
) {
196 base::FilePath file_name
= Path("truncated");
197 bool created
= false;
198 ASSERT_EQ(base::File::FILE_OK
,
199 NativeFileUtil::EnsureFileExists(file_name
, &created
));
200 ASSERT_TRUE(created
);
202 ASSERT_EQ(base::File::FILE_OK
,
203 NativeFileUtil::Truncate(file_name
, 1020));
205 EXPECT_TRUE(FileExists(file_name
));
206 EXPECT_EQ(1020, GetSize(file_name
));
209 TEST_F(NativeFileUtilTest
, CopyFile
) {
210 base::FilePath from_file
= Path("fromfile");
211 base::FilePath to_file1
= Path("tofile1");
212 base::FilePath to_file2
= Path("tofile2");
213 const NativeFileUtil::CopyOrMoveMode nosync
= NativeFileUtil::COPY_NOSYNC
;
214 const NativeFileUtil::CopyOrMoveMode sync
= NativeFileUtil::COPY_SYNC
;
215 bool created
= false;
216 ASSERT_EQ(base::File::FILE_OK
,
217 NativeFileUtil::EnsureFileExists(from_file
, &created
));
218 ASSERT_TRUE(created
);
220 ASSERT_EQ(base::File::FILE_OK
,
221 NativeFileUtil::Truncate(from_file
, 1020));
223 EXPECT_TRUE(FileExists(from_file
));
224 EXPECT_EQ(1020, GetSize(from_file
));
226 ASSERT_EQ(base::File::FILE_OK
,
227 NativeFileUtil::CopyOrMoveFile(
228 from_file
, to_file1
, FileSystemOperation::OPTION_NONE
, nosync
));
230 ASSERT_EQ(base::File::FILE_OK
,
231 NativeFileUtil::CopyOrMoveFile(
232 from_file
, to_file2
, FileSystemOperation::OPTION_NONE
, sync
));
234 EXPECT_TRUE(FileExists(from_file
));
235 EXPECT_EQ(1020, GetSize(from_file
));
236 EXPECT_TRUE(FileExists(to_file1
));
237 EXPECT_EQ(1020, GetSize(to_file1
));
238 EXPECT_TRUE(FileExists(to_file2
));
239 EXPECT_EQ(1020, GetSize(to_file2
));
241 base::FilePath dir
= Path("dir");
242 ASSERT_EQ(base::File::FILE_OK
,
243 NativeFileUtil::CreateDirectory(dir
, false, false));
244 ASSERT_TRUE(base::DirectoryExists(dir
));
245 base::FilePath to_dir_file
= dir
.AppendASCII("file");
246 ASSERT_EQ(base::File::FILE_OK
,
247 NativeFileUtil::CopyOrMoveFile(
248 from_file
, to_dir_file
,
249 FileSystemOperation::OPTION_NONE
, nosync
));
250 EXPECT_TRUE(FileExists(to_dir_file
));
251 EXPECT_EQ(1020, GetSize(to_dir_file
));
253 // Following tests are error checking.
254 // Source doesn't exist.
255 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND
,
256 NativeFileUtil::CopyOrMoveFile(
257 Path("nonexists"), Path("file"),
258 FileSystemOperation::OPTION_NONE
, nosync
));
260 // Source is not a file.
261 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE
,
262 NativeFileUtil::CopyOrMoveFile(
263 dir
, Path("file"), FileSystemOperation::OPTION_NONE
, nosync
));
264 // Destination is not a file.
265 EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION
,
266 NativeFileUtil::CopyOrMoveFile(
267 from_file
, dir
, FileSystemOperation::OPTION_NONE
, nosync
));
268 // Destination's parent doesn't exist.
269 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND
,
270 NativeFileUtil::CopyOrMoveFile(
271 from_file
, Path("nodir").AppendASCII("file"),
272 FileSystemOperation::OPTION_NONE
, nosync
));
273 // Destination's parent is a file.
274 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND
,
275 NativeFileUtil::CopyOrMoveFile(
276 from_file
, Path("tofile1").AppendASCII("file"),
277 FileSystemOperation::OPTION_NONE
, nosync
));
280 TEST_F(NativeFileUtilTest
, MoveFile
) {
281 base::FilePath from_file
= Path("fromfile");
282 base::FilePath to_file
= Path("tofile");
283 const NativeFileUtil::CopyOrMoveMode move
= NativeFileUtil::MOVE
;
284 bool created
= false;
285 ASSERT_EQ(base::File::FILE_OK
,
286 NativeFileUtil::EnsureFileExists(from_file
, &created
));
287 ASSERT_TRUE(created
);
289 ASSERT_EQ(base::File::FILE_OK
, NativeFileUtil::Truncate(from_file
, 1020));
291 EXPECT_TRUE(FileExists(from_file
));
292 EXPECT_EQ(1020, GetSize(from_file
));
294 ASSERT_EQ(base::File::FILE_OK
,
295 NativeFileUtil::CopyOrMoveFile(
296 from_file
, to_file
, FileSystemOperation::OPTION_NONE
, move
));
298 EXPECT_FALSE(FileExists(from_file
));
299 EXPECT_TRUE(FileExists(to_file
));
300 EXPECT_EQ(1020, GetSize(to_file
));
302 ASSERT_EQ(base::File::FILE_OK
,
303 NativeFileUtil::EnsureFileExists(from_file
, &created
));
304 ASSERT_TRUE(FileExists(from_file
));
305 ASSERT_EQ(base::File::FILE_OK
, NativeFileUtil::Truncate(from_file
, 1020));
307 base::FilePath dir
= Path("dir");
308 ASSERT_EQ(base::File::FILE_OK
,
309 NativeFileUtil::CreateDirectory(dir
, false, false));
310 ASSERT_TRUE(base::DirectoryExists(dir
));
311 base::FilePath to_dir_file
= dir
.AppendASCII("file");
312 ASSERT_EQ(base::File::FILE_OK
,
313 NativeFileUtil::CopyOrMoveFile(
314 from_file
, to_dir_file
,
315 FileSystemOperation::OPTION_NONE
, move
));
316 EXPECT_FALSE(FileExists(from_file
));
317 EXPECT_TRUE(FileExists(to_dir_file
));
318 EXPECT_EQ(1020, GetSize(to_dir_file
));
320 // Following is error checking.
321 // Source doesn't exist.
322 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND
,
323 NativeFileUtil::CopyOrMoveFile(
324 Path("nonexists"), Path("file"),
325 FileSystemOperation::OPTION_NONE
, move
));
327 // Source is not a file.
328 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE
,
329 NativeFileUtil::CopyOrMoveFile(
330 dir
, Path("file"), FileSystemOperation::OPTION_NONE
, move
));
331 ASSERT_EQ(base::File::FILE_OK
,
332 NativeFileUtil::EnsureFileExists(from_file
, &created
));
333 ASSERT_TRUE(FileExists(from_file
));
334 // Destination is not a file.
335 EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION
,
336 NativeFileUtil::CopyOrMoveFile(
337 from_file
, dir
, FileSystemOperation::OPTION_NONE
, move
));
339 ASSERT_EQ(base::File::FILE_OK
,
340 NativeFileUtil::EnsureFileExists(from_file
, &created
));
341 ASSERT_TRUE(FileExists(from_file
));
342 // Destination's parent doesn't exist.
343 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND
,
344 NativeFileUtil::CopyOrMoveFile(
345 from_file
, Path("nodir").AppendASCII("file"),
346 FileSystemOperation::OPTION_NONE
, move
));
347 // Destination's parent is a file.
348 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND
,
349 NativeFileUtil::CopyOrMoveFile(
350 from_file
, Path("tofile1").AppendASCII("file"),
351 FileSystemOperation::OPTION_NONE
, move
));
354 TEST_F(NativeFileUtilTest
, PreserveLastModified
) {
355 base::FilePath from_file
= Path("fromfile");
356 base::FilePath to_file1
= Path("tofile1");
357 base::FilePath to_file2
= Path("tofile2");
358 base::FilePath to_file3
= Path("tofile3");
359 bool created
= false;
360 ASSERT_EQ(base::File::FILE_OK
,
361 NativeFileUtil::EnsureFileExists(from_file
, &created
));
362 ASSERT_TRUE(created
);
363 EXPECT_TRUE(FileExists(from_file
));
365 base::File::Info file_info1
;
366 ASSERT_EQ(base::File::FILE_OK
,
367 NativeFileUtil::GetFileInfo(from_file
, &file_info1
));
369 // Test for copy (nosync).
370 ASSERT_EQ(base::File::FILE_OK
,
371 NativeFileUtil::CopyOrMoveFile(
373 FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED
,
374 NativeFileUtil::COPY_NOSYNC
));
376 base::File::Info file_info2
;
377 ASSERT_TRUE(FileExists(to_file1
));
378 ASSERT_EQ(base::File::FILE_OK
,
379 NativeFileUtil::GetFileInfo(to_file1
, &file_info2
));
380 EXPECT_EQ(file_info1
.last_modified
, file_info2
.last_modified
);
382 // Test for copy (sync).
383 ASSERT_EQ(base::File::FILE_OK
,
384 NativeFileUtil::CopyOrMoveFile(
386 FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED
,
387 NativeFileUtil::COPY_SYNC
));
389 ASSERT_TRUE(FileExists(to_file2
));
390 ASSERT_EQ(base::File::FILE_OK
,
391 NativeFileUtil::GetFileInfo(to_file1
, &file_info2
));
392 EXPECT_EQ(file_info1
.last_modified
, file_info2
.last_modified
);
395 ASSERT_EQ(base::File::FILE_OK
,
396 NativeFileUtil::CopyOrMoveFile(
398 FileSystemOperation::OPTION_PRESERVE_LAST_MODIFIED
,
399 NativeFileUtil::MOVE
));
401 ASSERT_TRUE(FileExists(to_file3
));
402 ASSERT_EQ(base::File::FILE_OK
,
403 NativeFileUtil::GetFileInfo(to_file2
, &file_info2
));
404 EXPECT_EQ(file_info1
.last_modified
, file_info2
.last_modified
);
407 } // namespace content