1// Copyright (c) 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 "base/file_util.h"
6#include "base/files/file_path.h"
7#include "base/files/scoped_temp_dir.h"
8#include "base/platform_file.h"
9#include "testing/gtest/include/gtest/gtest.h"
10#include "webkit/browser/fileapi/native_file_util.h"
11
12namespace fileapi {
13
14class NativeFileUtilTest : public testing::Test {
15 public:
16  NativeFileUtilTest() {}
17
18  virtual void SetUp() {
19    ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
20  }
21
22 protected:
23  base::FilePath Path() {
24    return data_dir_.path();
25  }
26
27  base::FilePath Path(const char* file_name) {
28    return data_dir_.path().AppendASCII(file_name);
29  }
30
31  bool FileExists(const base::FilePath& path) {
32    return base::PathExists(path) &&
33           !base::DirectoryExists(path);
34  }
35
36  int64 GetSize(const base::FilePath& path) {
37    base::PlatformFileInfo info;
38    file_util::GetFileInfo(path, &info);
39    return info.size;
40  }
41
42 private:
43  base::ScopedTempDir data_dir_;
44
45  DISALLOW_COPY_AND_ASSIGN(NativeFileUtilTest);
46};
47
48TEST_F(NativeFileUtilTest, CreateCloseAndDeleteFile) {
49  base::FilePath file_name = Path("test_file");
50  base::PlatformFile file_handle;
51  bool created = false;
52  int flags = base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC;
53  ASSERT_EQ(base::PLATFORM_FILE_OK,
54            NativeFileUtil::CreateOrOpen(file_name,
55                                         base::PLATFORM_FILE_CREATE | flags,
56                                         &file_handle, &created));
57  ASSERT_TRUE(created);
58
59  EXPECT_TRUE(base::PathExists(file_name));
60  EXPECT_TRUE(NativeFileUtil::PathExists(file_name));
61  EXPECT_EQ(0, GetSize(file_name));
62  EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
63
64  ASSERT_EQ(base::PLATFORM_FILE_OK, NativeFileUtil::Close(file_handle));
65
66  ASSERT_EQ(base::PLATFORM_FILE_OK,
67            NativeFileUtil::CreateOrOpen(file_name,
68                                         base::PLATFORM_FILE_OPEN | flags,
69                                         &file_handle, &created));
70  ASSERT_FALSE(created);
71  ASSERT_EQ(base::PLATFORM_FILE_OK, NativeFileUtil::Close(file_handle));
72
73  ASSERT_EQ(base::PLATFORM_FILE_OK,
74            NativeFileUtil::DeleteFile(file_name));
75  EXPECT_FALSE(base::PathExists(file_name));
76  EXPECT_FALSE(NativeFileUtil::PathExists(file_name));
77}
78
79TEST_F(NativeFileUtilTest, EnsureFileExists) {
80  base::FilePath file_name = Path("foobar");
81  bool created = false;
82  ASSERT_EQ(base::PLATFORM_FILE_OK,
83            NativeFileUtil::EnsureFileExists(file_name, &created));
84  ASSERT_TRUE(created);
85
86  EXPECT_TRUE(FileExists(file_name));
87  EXPECT_EQ(0, GetSize(file_name));
88
89  ASSERT_EQ(base::PLATFORM_FILE_OK,
90            NativeFileUtil::EnsureFileExists(file_name, &created));
91  EXPECT_FALSE(created);
92}
93
94TEST_F(NativeFileUtilTest, CreateAndDeleteDirectory) {
95  base::FilePath dir_name = Path("test_dir");
96  ASSERT_EQ(base::PLATFORM_FILE_OK,
97            NativeFileUtil::CreateDirectory(dir_name,
98                                            false /* exclusive */,
99                                            false /* recursive */));
100
101  EXPECT_TRUE(NativeFileUtil::DirectoryExists(dir_name));
102  EXPECT_TRUE(base::DirectoryExists(dir_name));
103
104  ASSERT_EQ(base::PLATFORM_FILE_ERROR_EXISTS,
105            NativeFileUtil::CreateDirectory(dir_name,
106                                            true /* exclusive */,
107                                            false /* recursive */));
108
109  ASSERT_EQ(base::PLATFORM_FILE_OK,
110            NativeFileUtil::DeleteDirectory(dir_name));
111  EXPECT_FALSE(base::DirectoryExists(dir_name));
112  EXPECT_FALSE(NativeFileUtil::DirectoryExists(dir_name));
113}
114
115TEST_F(NativeFileUtilTest, TouchFileAndGetFileInfo) {
116  base::FilePath file_name = Path("test_file");
117  base::PlatformFileInfo native_info;
118  ASSERT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
119            NativeFileUtil::GetFileInfo(file_name, &native_info));
120
121  bool created = false;
122  ASSERT_EQ(base::PLATFORM_FILE_OK,
123            NativeFileUtil::EnsureFileExists(file_name, &created));
124  ASSERT_TRUE(created);
125
126  base::PlatformFileInfo info;
127  ASSERT_TRUE(file_util::GetFileInfo(file_name, &info));
128  ASSERT_EQ(base::PLATFORM_FILE_OK,
129            NativeFileUtil::GetFileInfo(file_name, &native_info));
130  ASSERT_EQ(info.size, native_info.size);
131  ASSERT_EQ(info.is_directory, native_info.is_directory);
132  ASSERT_EQ(info.is_symbolic_link, native_info.is_symbolic_link);
133  ASSERT_EQ(info.last_modified, native_info.last_modified);
134  ASSERT_EQ(info.last_accessed, native_info.last_accessed);
135  ASSERT_EQ(info.creation_time, native_info.creation_time);
136
137  const base::Time new_accessed =
138      info.last_accessed + base::TimeDelta::FromHours(10);
139  const base::Time new_modified =
140      info.last_modified + base::TimeDelta::FromHours(5);
141
142  EXPECT_EQ(base::PLATFORM_FILE_OK,
143            NativeFileUtil::Touch(file_name,
144                                  new_accessed, new_modified));
145
146  ASSERT_TRUE(file_util::GetFileInfo(file_name, &info));
147  EXPECT_EQ(new_accessed, info.last_accessed);
148  EXPECT_EQ(new_modified, info.last_modified);
149}
150
151TEST_F(NativeFileUtilTest, CreateFileEnumerator) {
152  base::FilePath path_1 = Path("dir1");
153  base::FilePath path_2 = Path("file1");
154  base::FilePath path_11 = Path("dir1").AppendASCII("file11");
155  base::FilePath path_12 = Path("dir1").AppendASCII("dir12");
156  base::FilePath path_121 =
157      Path("dir1").AppendASCII("dir12").AppendASCII("file121");
158  ASSERT_EQ(base::PLATFORM_FILE_OK,
159            NativeFileUtil::CreateDirectory(path_1, false, false));
160  bool created = false;
161  ASSERT_EQ(base::PLATFORM_FILE_OK,
162            NativeFileUtil::EnsureFileExists(path_2, &created));
163  ASSERT_EQ(base::PLATFORM_FILE_OK,
164            NativeFileUtil::EnsureFileExists(path_11, &created));
165  ASSERT_EQ(base::PLATFORM_FILE_OK,
166            NativeFileUtil::CreateDirectory(path_12, false, false));
167  ASSERT_EQ(base::PLATFORM_FILE_OK,
168            NativeFileUtil::EnsureFileExists(path_121, &created));
169
170  {
171    scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator =
172        NativeFileUtil::CreateFileEnumerator(Path(), false);
173    std::set<base::FilePath> set;
174    set.insert(path_1);
175    set.insert(path_2);
176    for (base::FilePath path = enumerator->Next(); !path.empty();
177         path = enumerator->Next())
178      EXPECT_EQ(1U, set.erase(path));
179    EXPECT_TRUE(set.empty());
180  }
181
182  {
183    scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator =
184        NativeFileUtil::CreateFileEnumerator(Path(), true);
185        std::set<base::FilePath> set;
186    set.insert(path_1);
187    set.insert(path_2);
188    set.insert(path_11);
189    set.insert(path_12);
190    set.insert(path_121);
191    for (base::FilePath path = enumerator->Next(); !path.empty();
192         path = enumerator->Next())
193      EXPECT_EQ(1U, set.erase(path));
194    EXPECT_TRUE(set.empty());
195  }
196}
197
198TEST_F(NativeFileUtilTest, Truncate) {
199  base::FilePath file_name = Path("truncated");
200  bool created = false;
201  ASSERT_EQ(base::PLATFORM_FILE_OK,
202            NativeFileUtil::EnsureFileExists(file_name, &created));
203  ASSERT_TRUE(created);
204
205  ASSERT_EQ(base::PLATFORM_FILE_OK,
206            NativeFileUtil::Truncate(file_name, 1020));
207
208  EXPECT_TRUE(FileExists(file_name));
209  EXPECT_EQ(1020, GetSize(file_name));
210}
211
212TEST_F(NativeFileUtilTest, CopyFile) {
213  base::FilePath from_file = Path("fromfile");
214  base::FilePath to_file1 = Path("tofile1");
215  base::FilePath to_file2 = Path("tofile2");
216  bool created = false;
217  ASSERT_EQ(base::PLATFORM_FILE_OK,
218            NativeFileUtil::EnsureFileExists(from_file, &created));
219  ASSERT_TRUE(created);
220
221  ASSERT_EQ(base::PLATFORM_FILE_OK,
222            NativeFileUtil::Truncate(from_file, 1020));
223
224  EXPECT_TRUE(FileExists(from_file));
225  EXPECT_EQ(1020, GetSize(from_file));
226
227  ASSERT_EQ(base::PLATFORM_FILE_OK,
228            NativeFileUtil::CopyOrMoveFile(from_file, to_file1, true));
229
230  ASSERT_EQ(base::PLATFORM_FILE_OK,
231            NativeFileUtil::CopyOrMoveFile(from_file, to_file2, true));
232
233  EXPECT_TRUE(FileExists(from_file));
234  EXPECT_EQ(1020, GetSize(from_file));
235  EXPECT_TRUE(FileExists(to_file1));
236  EXPECT_EQ(1020, GetSize(to_file1));
237  EXPECT_TRUE(FileExists(to_file2));
238  EXPECT_EQ(1020, GetSize(to_file2));
239
240  base::FilePath dir = Path("dir");
241  ASSERT_EQ(base::PLATFORM_FILE_OK,
242            NativeFileUtil::CreateDirectory(dir, false, false));
243  ASSERT_TRUE(base::DirectoryExists(dir));
244  base::FilePath to_dir_file = dir.AppendASCII("file");
245  ASSERT_EQ(base::PLATFORM_FILE_OK,
246            NativeFileUtil::CopyOrMoveFile(from_file, to_dir_file, true));
247  EXPECT_TRUE(FileExists(to_dir_file));
248  EXPECT_EQ(1020, GetSize(to_dir_file));
249
250  // Following tests are error checking.
251  // Source doesn't exist.
252  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
253            NativeFileUtil::CopyOrMoveFile(Path("nonexists"), Path("file"),
254                                           true));
255
256  // Source is not a file.
257  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE,
258            NativeFileUtil::CopyOrMoveFile(dir, Path("file"), true));
259  // Destination is not a file.
260  EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION,
261            NativeFileUtil::CopyOrMoveFile(from_file, dir, true));
262  // Destination's parent doesn't exist.
263  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
264            NativeFileUtil::CopyOrMoveFile(from_file,
265                                           Path("nodir").AppendASCII("file"),
266                                           true));
267  // Destination's parent is a file.
268  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
269            NativeFileUtil::CopyOrMoveFile(from_file,
270                                           Path("tofile1").AppendASCII("file"),
271                                           true));
272}
273
274TEST_F(NativeFileUtilTest, MoveFile) {
275  base::FilePath from_file = Path("fromfile");
276  base::FilePath to_file = Path("tofile");
277  bool created = false;
278  ASSERT_EQ(base::PLATFORM_FILE_OK,
279            NativeFileUtil::EnsureFileExists(from_file, &created));
280  ASSERT_TRUE(created);
281
282  ASSERT_EQ(base::PLATFORM_FILE_OK, NativeFileUtil::Truncate(from_file, 1020));
283
284  EXPECT_TRUE(FileExists(from_file));
285  EXPECT_EQ(1020, GetSize(from_file));
286
287  ASSERT_EQ(base::PLATFORM_FILE_OK,
288            NativeFileUtil::CopyOrMoveFile(from_file, to_file, false));
289
290  EXPECT_FALSE(FileExists(from_file));
291  EXPECT_TRUE(FileExists(to_file));
292  EXPECT_EQ(1020, GetSize(to_file));
293
294  ASSERT_EQ(base::PLATFORM_FILE_OK,
295            NativeFileUtil::EnsureFileExists(from_file, &created));
296  ASSERT_TRUE(FileExists(from_file));
297  ASSERT_EQ(base::PLATFORM_FILE_OK, NativeFileUtil::Truncate(from_file, 1020));
298
299  base::FilePath dir = Path("dir");
300  ASSERT_EQ(base::PLATFORM_FILE_OK,
301            NativeFileUtil::CreateDirectory(dir, false, false));
302  ASSERT_TRUE(base::DirectoryExists(dir));
303  base::FilePath to_dir_file = dir.AppendASCII("file");
304  ASSERT_EQ(base::PLATFORM_FILE_OK,
305            NativeFileUtil::CopyOrMoveFile(from_file, to_dir_file, false));
306  EXPECT_FALSE(FileExists(from_file));
307  EXPECT_TRUE(FileExists(to_dir_file));
308  EXPECT_EQ(1020, GetSize(to_dir_file));
309
310  // Following is error checking.
311  // Source doesn't exist.
312  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
313            NativeFileUtil::CopyOrMoveFile(Path("nonexists"), Path("file"),
314                                           false));
315
316  // Source is not a file.
317  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_A_FILE,
318            NativeFileUtil::CopyOrMoveFile(dir, Path("file"), false));
319  ASSERT_EQ(base::PLATFORM_FILE_OK,
320            NativeFileUtil::EnsureFileExists(from_file, &created));
321  ASSERT_TRUE(FileExists(from_file));
322  // Destination is not a file.
323  EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION,
324            NativeFileUtil::CopyOrMoveFile(from_file, dir, false));
325
326  ASSERT_EQ(base::PLATFORM_FILE_OK,
327            NativeFileUtil::EnsureFileExists(from_file, &created));
328  ASSERT_TRUE(FileExists(from_file));
329  // Destination's parent doesn't exist.
330  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
331            NativeFileUtil::CopyOrMoveFile(from_file,
332                                           Path("nodir").AppendASCII("file"),
333                                           false));
334  // Destination's parent is a file.
335  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
336            NativeFileUtil::CopyOrMoveFile(from_file,
337                                           Path("tofile1").AppendASCII("file"),
338                                           false));
339}
340
341}  // namespace fileapi
342