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