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. 4 5#include "base/files/file.h" 6#include "base/files/file_util.h" 7#include "base/files/scoped_temp_dir.h" 8#include "base/time/time.h" 9#include "testing/gtest/include/gtest/gtest.h" 10 11using base::File; 12using base::FilePath; 13 14TEST(FileTest, Create) { 15 base::ScopedTempDir temp_dir; 16 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 17 FilePath file_path = temp_dir.path().AppendASCII("create_file_1"); 18 19 { 20 // Don't create a File at all. 21 File file; 22 EXPECT_FALSE(file.IsValid()); 23 EXPECT_EQ(base::File::FILE_ERROR_FAILED, file.error_details()); 24 25 File file2(base::File::FILE_ERROR_TOO_MANY_OPENED); 26 EXPECT_FALSE(file2.IsValid()); 27 EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, file2.error_details()); 28 } 29 30 { 31 // Open a file that doesn't exist. 32 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); 33 EXPECT_FALSE(file.IsValid()); 34 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details()); 35 } 36 37 { 38 // Open or create a file. 39 File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ); 40 EXPECT_TRUE(file.IsValid()); 41 EXPECT_TRUE(file.created()); 42 EXPECT_EQ(base::File::FILE_OK, file.error_details()); 43 } 44 45 { 46 // Open an existing file. 47 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); 48 EXPECT_TRUE(file.IsValid()); 49 EXPECT_FALSE(file.created()); 50 EXPECT_EQ(base::File::FILE_OK, file.error_details()); 51 52 // This time verify closing the file. 53 file.Close(); 54 EXPECT_FALSE(file.IsValid()); 55 } 56 57 { 58 // Open an existing file through Initialize 59 File file; 60 file.Initialize(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); 61 EXPECT_TRUE(file.IsValid()); 62 EXPECT_FALSE(file.created()); 63 EXPECT_EQ(base::File::FILE_OK, file.error_details()); 64 65 // This time verify closing the file. 66 file.Close(); 67 EXPECT_FALSE(file.IsValid()); 68 } 69 70 { 71 // Create a file that exists. 72 File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ); 73 EXPECT_FALSE(file.IsValid()); 74 EXPECT_FALSE(file.created()); 75 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error_details()); 76 } 77 78 { 79 // Create or overwrite a file. 80 File file(file_path, 81 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); 82 EXPECT_TRUE(file.IsValid()); 83 EXPECT_TRUE(file.created()); 84 EXPECT_EQ(base::File::FILE_OK, file.error_details()); 85 } 86 87 { 88 // Create a delete-on-close file. 89 file_path = temp_dir.path().AppendASCII("create_file_2"); 90 File file(file_path, 91 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ | 92 base::File::FLAG_DELETE_ON_CLOSE); 93 EXPECT_TRUE(file.IsValid()); 94 EXPECT_TRUE(file.created()); 95 EXPECT_EQ(base::File::FILE_OK, file.error_details()); 96 } 97 98 EXPECT_FALSE(base::PathExists(file_path)); 99} 100 101TEST(FileTest, Async) { 102 base::ScopedTempDir temp_dir; 103 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 104 FilePath file_path = temp_dir.path().AppendASCII("create_file"); 105 106 { 107 File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_ASYNC); 108 EXPECT_TRUE(file.IsValid()); 109 EXPECT_TRUE(file.async()); 110 } 111 112 { 113 File file(file_path, base::File::FLAG_OPEN_ALWAYS); 114 EXPECT_TRUE(file.IsValid()); 115 EXPECT_FALSE(file.async()); 116 } 117} 118 119TEST(FileTest, DeleteOpenFile) { 120 base::ScopedTempDir temp_dir; 121 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 122 FilePath file_path = temp_dir.path().AppendASCII("create_file_1"); 123 124 // Create a file. 125 File file(file_path, 126 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ | 127 base::File::FLAG_SHARE_DELETE); 128 EXPECT_TRUE(file.IsValid()); 129 EXPECT_TRUE(file.created()); 130 EXPECT_EQ(base::File::FILE_OK, file.error_details()); 131 132 // Open an existing file and mark it as delete on close. 133 File same_file(file_path, 134 base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE | 135 base::File::FLAG_READ); 136 EXPECT_TRUE(file.IsValid()); 137 EXPECT_FALSE(same_file.created()); 138 EXPECT_EQ(base::File::FILE_OK, same_file.error_details()); 139 140 // Close both handles and check that the file is gone. 141 file.Close(); 142 same_file.Close(); 143 EXPECT_FALSE(base::PathExists(file_path)); 144} 145 146TEST(FileTest, ReadWrite) { 147 base::ScopedTempDir temp_dir; 148 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 149 FilePath file_path = temp_dir.path().AppendASCII("read_write_file"); 150 File file(file_path, 151 base::File::FLAG_CREATE | base::File::FLAG_READ | 152 base::File::FLAG_WRITE); 153 ASSERT_TRUE(file.IsValid()); 154 155 char data_to_write[] = "test"; 156 const int kTestDataSize = 4; 157 158 // Write 0 bytes to the file. 159 int bytes_written = file.Write(0, data_to_write, 0); 160 EXPECT_EQ(0, bytes_written); 161 162 // Write "test" to the file. 163 bytes_written = file.Write(0, data_to_write, kTestDataSize); 164 EXPECT_EQ(kTestDataSize, bytes_written); 165 166 // Read from EOF. 167 char data_read_1[32]; 168 int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize); 169 EXPECT_EQ(0, bytes_read); 170 171 // Read from somewhere in the middle of the file. 172 const int kPartialReadOffset = 1; 173 bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize); 174 EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read); 175 for (int i = 0; i < bytes_read; i++) 176 EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]); 177 178 // Read 0 bytes. 179 bytes_read = file.Read(0, data_read_1, 0); 180 EXPECT_EQ(0, bytes_read); 181 182 // Read the entire file. 183 bytes_read = file.Read(0, data_read_1, kTestDataSize); 184 EXPECT_EQ(kTestDataSize, bytes_read); 185 for (int i = 0; i < bytes_read; i++) 186 EXPECT_EQ(data_to_write[i], data_read_1[i]); 187 188 // Read again, but using the trivial native wrapper. 189 bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize); 190 EXPECT_LE(bytes_read, kTestDataSize); 191 for (int i = 0; i < bytes_read; i++) 192 EXPECT_EQ(data_to_write[i], data_read_1[i]); 193 194 // Write past the end of the file. 195 const int kOffsetBeyondEndOfFile = 10; 196 const int kPartialWriteLength = 2; 197 bytes_written = file.Write(kOffsetBeyondEndOfFile, 198 data_to_write, kPartialWriteLength); 199 EXPECT_EQ(kPartialWriteLength, bytes_written); 200 201 // Make sure the file was extended. 202 int64 file_size = 0; 203 EXPECT_TRUE(GetFileSize(file_path, &file_size)); 204 EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size); 205 206 // Make sure the file was zero-padded. 207 char data_read_2[32]; 208 bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size)); 209 EXPECT_EQ(file_size, bytes_read); 210 for (int i = 0; i < kTestDataSize; i++) 211 EXPECT_EQ(data_to_write[i], data_read_2[i]); 212 for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++) 213 EXPECT_EQ(0, data_read_2[i]); 214 for (int i = kOffsetBeyondEndOfFile; i < file_size; i++) 215 EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]); 216} 217 218TEST(FileTest, Append) { 219 base::ScopedTempDir temp_dir; 220 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 221 FilePath file_path = temp_dir.path().AppendASCII("append_file"); 222 File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND); 223 ASSERT_TRUE(file.IsValid()); 224 225 char data_to_write[] = "test"; 226 const int kTestDataSize = 4; 227 228 // Write 0 bytes to the file. 229 int bytes_written = file.Write(0, data_to_write, 0); 230 EXPECT_EQ(0, bytes_written); 231 232 // Write "test" to the file. 233 bytes_written = file.Write(0, data_to_write, kTestDataSize); 234 EXPECT_EQ(kTestDataSize, bytes_written); 235 236 file.Close(); 237 File file2(file_path, 238 base::File::FLAG_OPEN | base::File::FLAG_READ | 239 base::File::FLAG_APPEND); 240 ASSERT_TRUE(file2.IsValid()); 241 242 // Test passing the file around. 243 file = file2.Pass(); 244 EXPECT_FALSE(file2.IsValid()); 245 ASSERT_TRUE(file.IsValid()); 246 247 char append_data_to_write[] = "78"; 248 const int kAppendDataSize = 2; 249 250 // Append "78" to the file. 251 bytes_written = file.Write(0, append_data_to_write, kAppendDataSize); 252 EXPECT_EQ(kAppendDataSize, bytes_written); 253 254 // Read the entire file. 255 char data_read_1[32]; 256 int bytes_read = file.Read(0, data_read_1, 257 kTestDataSize + kAppendDataSize); 258 EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read); 259 for (int i = 0; i < kTestDataSize; i++) 260 EXPECT_EQ(data_to_write[i], data_read_1[i]); 261 for (int i = 0; i < kAppendDataSize; i++) 262 EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]); 263} 264 265 266TEST(FileTest, Length) { 267 base::ScopedTempDir temp_dir; 268 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 269 FilePath file_path = temp_dir.path().AppendASCII("truncate_file"); 270 File file(file_path, 271 base::File::FLAG_CREATE | base::File::FLAG_READ | 272 base::File::FLAG_WRITE); 273 ASSERT_TRUE(file.IsValid()); 274 EXPECT_EQ(0, file.GetLength()); 275 276 // Write "test" to the file. 277 char data_to_write[] = "test"; 278 int kTestDataSize = 4; 279 int bytes_written = file.Write(0, data_to_write, kTestDataSize); 280 EXPECT_EQ(kTestDataSize, bytes_written); 281 282 // Extend the file. 283 const int kExtendedFileLength = 10; 284 int64 file_size = 0; 285 EXPECT_TRUE(file.SetLength(kExtendedFileLength)); 286 EXPECT_EQ(kExtendedFileLength, file.GetLength()); 287 EXPECT_TRUE(GetFileSize(file_path, &file_size)); 288 EXPECT_EQ(kExtendedFileLength, file_size); 289 290 // Make sure the file was zero-padded. 291 char data_read[32]; 292 int bytes_read = file.Read(0, data_read, static_cast<int>(file_size)); 293 EXPECT_EQ(file_size, bytes_read); 294 for (int i = 0; i < kTestDataSize; i++) 295 EXPECT_EQ(data_to_write[i], data_read[i]); 296 for (int i = kTestDataSize; i < file_size; i++) 297 EXPECT_EQ(0, data_read[i]); 298 299 // Truncate the file. 300 const int kTruncatedFileLength = 2; 301 EXPECT_TRUE(file.SetLength(kTruncatedFileLength)); 302 EXPECT_EQ(kTruncatedFileLength, file.GetLength()); 303 EXPECT_TRUE(GetFileSize(file_path, &file_size)); 304 EXPECT_EQ(kTruncatedFileLength, file_size); 305 306 // Make sure the file was truncated. 307 bytes_read = file.Read(0, data_read, kTestDataSize); 308 EXPECT_EQ(file_size, bytes_read); 309 for (int i = 0; i < file_size; i++) 310 EXPECT_EQ(data_to_write[i], data_read[i]); 311} 312 313// Flakily fails: http://crbug.com/86494 314#if defined(OS_ANDROID) 315TEST(FileTest, TouchGetInfo) { 316#else 317TEST(FileTest, DISABLED_TouchGetInfo) { 318#endif 319 base::ScopedTempDir temp_dir; 320 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 321 File file(temp_dir.path().AppendASCII("touch_get_info_file"), 322 base::File::FLAG_CREATE | base::File::FLAG_WRITE | 323 base::File::FLAG_WRITE_ATTRIBUTES); 324 ASSERT_TRUE(file.IsValid()); 325 326 // Get info for a newly created file. 327 base::File::Info info; 328 EXPECT_TRUE(file.GetInfo(&info)); 329 330 // Add 2 seconds to account for possible rounding errors on 331 // filesystems that use a 1s or 2s timestamp granularity. 332 base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2); 333 EXPECT_EQ(0, info.size); 334 EXPECT_FALSE(info.is_directory); 335 EXPECT_FALSE(info.is_symbolic_link); 336 EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue()); 337 EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue()); 338 EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue()); 339 base::Time creation_time = info.creation_time; 340 341 // Write "test" to the file. 342 char data[] = "test"; 343 const int kTestDataSize = 4; 344 int bytes_written = file.Write(0, data, kTestDataSize); 345 EXPECT_EQ(kTestDataSize, bytes_written); 346 347 // Change the last_accessed and last_modified dates. 348 // It's best to add values that are multiples of 2 (in seconds) 349 // to the current last_accessed and last_modified times, because 350 // FATxx uses a 2s timestamp granularity. 351 base::Time new_last_accessed = 352 info.last_accessed + base::TimeDelta::FromSeconds(234); 353 base::Time new_last_modified = 354 info.last_modified + base::TimeDelta::FromMinutes(567); 355 356 EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified)); 357 358 // Make sure the file info was updated accordingly. 359 EXPECT_TRUE(file.GetInfo(&info)); 360 EXPECT_EQ(info.size, kTestDataSize); 361 EXPECT_FALSE(info.is_directory); 362 EXPECT_FALSE(info.is_symbolic_link); 363 364 // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s. 365#if defined(OS_POSIX) 366 EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec, 367 new_last_accessed.ToTimeVal().tv_sec); 368 EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec, 369 new_last_modified.ToTimeVal().tv_sec); 370#else 371 EXPECT_EQ(info.last_accessed.ToInternalValue(), 372 new_last_accessed.ToInternalValue()); 373 EXPECT_EQ(info.last_modified.ToInternalValue(), 374 new_last_modified.ToInternalValue()); 375#endif 376 377 EXPECT_EQ(info.creation_time.ToInternalValue(), 378 creation_time.ToInternalValue()); 379} 380 381TEST(FileTest, ReadAtCurrentPosition) { 382 base::ScopedTempDir temp_dir; 383 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 384 FilePath file_path = temp_dir.path().AppendASCII("read_at_current_position"); 385 File file(file_path, 386 base::File::FLAG_CREATE | base::File::FLAG_READ | 387 base::File::FLAG_WRITE); 388 EXPECT_TRUE(file.IsValid()); 389 390 const char kData[] = "test"; 391 const int kDataSize = sizeof(kData) - 1; 392 EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize)); 393 394 EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0)); 395 396 char buffer[kDataSize]; 397 int first_chunk_size = kDataSize / 2; 398 EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size)); 399 EXPECT_EQ(kDataSize - first_chunk_size, 400 file.ReadAtCurrentPos(buffer + first_chunk_size, 401 kDataSize - first_chunk_size)); 402 EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData)); 403} 404 405TEST(FileTest, WriteAtCurrentPosition) { 406 base::ScopedTempDir temp_dir; 407 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 408 FilePath file_path = temp_dir.path().AppendASCII("write_at_current_position"); 409 File file(file_path, 410 base::File::FLAG_CREATE | base::File::FLAG_READ | 411 base::File::FLAG_WRITE); 412 EXPECT_TRUE(file.IsValid()); 413 414 const char kData[] = "test"; 415 const int kDataSize = sizeof(kData) - 1; 416 417 int first_chunk_size = kDataSize / 2; 418 EXPECT_EQ(first_chunk_size, file.WriteAtCurrentPos(kData, first_chunk_size)); 419 EXPECT_EQ(kDataSize - first_chunk_size, 420 file.WriteAtCurrentPos(kData + first_chunk_size, 421 kDataSize - first_chunk_size)); 422 423 char buffer[kDataSize]; 424 EXPECT_EQ(kDataSize, file.Read(0, buffer, kDataSize)); 425 EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData)); 426} 427 428TEST(FileTest, Seek) { 429 base::ScopedTempDir temp_dir; 430 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 431 FilePath file_path = temp_dir.path().AppendASCII("seek_file"); 432 File file(file_path, 433 base::File::FLAG_CREATE | base::File::FLAG_READ | 434 base::File::FLAG_WRITE); 435 ASSERT_TRUE(file.IsValid()); 436 437 const int64 kOffset = 10; 438 EXPECT_EQ(kOffset, file.Seek(base::File::FROM_BEGIN, kOffset)); 439 EXPECT_EQ(2 * kOffset, file.Seek(base::File::FROM_CURRENT, kOffset)); 440 EXPECT_EQ(kOffset, file.Seek(base::File::FROM_CURRENT, -kOffset)); 441 EXPECT_TRUE(file.SetLength(kOffset * 2)); 442 EXPECT_EQ(kOffset, file.Seek(base::File::FROM_END, -kOffset)); 443} 444 445#if defined(OS_WIN) 446TEST(FileTest, GetInfoForDirectory) { 447 base::ScopedTempDir temp_dir; 448 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 449 FilePath empty_dir = temp_dir.path().Append(FILE_PATH_LITERAL("gpfi_test")); 450 ASSERT_TRUE(CreateDirectory(empty_dir)); 451 452 base::File dir( 453 ::CreateFile(empty_dir.value().c_str(), 454 FILE_ALL_ACCESS, 455 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 456 NULL, 457 OPEN_EXISTING, 458 FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory. 459 NULL)); 460 ASSERT_TRUE(dir.IsValid()); 461 462 base::File::Info info; 463 EXPECT_TRUE(dir.GetInfo(&info)); 464 EXPECT_TRUE(info.is_directory); 465 EXPECT_FALSE(info.is_symbolic_link); 466 EXPECT_EQ(0, info.size); 467} 468#endif // defined(OS_WIN) 469