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/file_util.h" 6 #include "base/files/file.h" 7 #include "base/files/scoped_temp_dir.h" 8 #include "base/time/time.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 11 using base::File; 12 using base::FilePath; 13 14 TEST(File, 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 // Open a file that doesn't exist. 21 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); 22 EXPECT_FALSE(file.IsValid()); 23 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error()); 24 } 25 26 { 27 // Open or create a file. 28 File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ); 29 EXPECT_TRUE(file.IsValid()); 30 EXPECT_TRUE(file.created()); 31 EXPECT_EQ(base::File::FILE_OK, file.error()); 32 } 33 34 { 35 // Open an existing file. 36 File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); 37 EXPECT_TRUE(file.IsValid()); 38 EXPECT_FALSE(file.created()); 39 EXPECT_EQ(base::File::FILE_OK, file.error()); 40 41 // This time verify closing the file. 42 file.Close(); 43 EXPECT_FALSE(file.IsValid()); 44 } 45 46 { 47 // Create a file that exists. 48 File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ); 49 EXPECT_FALSE(file.IsValid()); 50 EXPECT_FALSE(file.created()); 51 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error()); 52 } 53 54 { 55 // Create or overwrite a file. 56 File file(file_path, 57 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ); 58 EXPECT_TRUE(file.IsValid()); 59 EXPECT_TRUE(file.created()); 60 EXPECT_EQ(base::File::FILE_OK, file.error()); 61 } 62 63 { 64 // Create a delete-on-close file. 65 file_path = temp_dir.path().AppendASCII("create_file_2"); 66 File file(file_path, 67 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ | 68 base::File::FLAG_DELETE_ON_CLOSE); 69 EXPECT_TRUE(file.IsValid()); 70 EXPECT_TRUE(file.created()); 71 EXPECT_EQ(base::File::FILE_OK, file.error()); 72 } 73 74 EXPECT_FALSE(base::PathExists(file_path)); 75 } 76 77 TEST(File, DeleteOpenFile) { 78 base::ScopedTempDir temp_dir; 79 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 80 FilePath file_path = temp_dir.path().AppendASCII("create_file_1"); 81 82 // Create a file. 83 File file(file_path, 84 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ | 85 base::File::FLAG_SHARE_DELETE); 86 EXPECT_TRUE(file.IsValid()); 87 EXPECT_TRUE(file.created()); 88 EXPECT_EQ(base::File::FILE_OK, file.error()); 89 90 // Open an existing file and mark it as delete on close. 91 File same_file(file_path, 92 base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE | 93 base::File::FLAG_READ); 94 EXPECT_TRUE(file.IsValid()); 95 EXPECT_FALSE(same_file.created()); 96 EXPECT_EQ(base::File::FILE_OK, same_file.error()); 97 98 // Close both handles and check that the file is gone. 99 file.Close(); 100 same_file.Close(); 101 EXPECT_FALSE(base::PathExists(file_path)); 102 } 103 104 TEST(File, ReadWrite) { 105 base::ScopedTempDir temp_dir; 106 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 107 FilePath file_path = temp_dir.path().AppendASCII("read_write_file"); 108 File file(file_path, 109 base::File::FLAG_CREATE | base::File::FLAG_READ | 110 base::File::FLAG_WRITE); 111 ASSERT_TRUE(file.IsValid()); 112 113 char data_to_write[] = "test"; 114 const int kTestDataSize = 4; 115 116 // Write 0 bytes to the file. 117 int bytes_written = file.Write(0, data_to_write, 0); 118 EXPECT_EQ(0, bytes_written); 119 120 // Write "test" to the file. 121 bytes_written = file.Write(0, data_to_write, kTestDataSize); 122 EXPECT_EQ(kTestDataSize, bytes_written); 123 124 // Read from EOF. 125 char data_read_1[32]; 126 int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize); 127 EXPECT_EQ(0, bytes_read); 128 129 // Read from somewhere in the middle of the file. 130 const int kPartialReadOffset = 1; 131 bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize); 132 EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read); 133 for (int i = 0; i < bytes_read; i++) 134 EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]); 135 136 // Read 0 bytes. 137 bytes_read = file.Read(0, data_read_1, 0); 138 EXPECT_EQ(0, bytes_read); 139 140 // Read the entire file. 141 bytes_read = file.Read(0, data_read_1, kTestDataSize); 142 EXPECT_EQ(kTestDataSize, bytes_read); 143 for (int i = 0; i < bytes_read; i++) 144 EXPECT_EQ(data_to_write[i], data_read_1[i]); 145 146 // Read again, but using the trivial native wrapper. 147 bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize); 148 EXPECT_LE(bytes_read, kTestDataSize); 149 for (int i = 0; i < bytes_read; i++) 150 EXPECT_EQ(data_to_write[i], data_read_1[i]); 151 152 // Write past the end of the file. 153 const int kOffsetBeyondEndOfFile = 10; 154 const int kPartialWriteLength = 2; 155 bytes_written = file.Write(kOffsetBeyondEndOfFile, 156 data_to_write, kPartialWriteLength); 157 EXPECT_EQ(kPartialWriteLength, bytes_written); 158 159 // Make sure the file was extended. 160 int64 file_size = 0; 161 EXPECT_TRUE(GetFileSize(file_path, &file_size)); 162 EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size); 163 164 // Make sure the file was zero-padded. 165 char data_read_2[32]; 166 bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size)); 167 EXPECT_EQ(file_size, bytes_read); 168 for (int i = 0; i < kTestDataSize; i++) 169 EXPECT_EQ(data_to_write[i], data_read_2[i]); 170 for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++) 171 EXPECT_EQ(0, data_read_2[i]); 172 for (int i = kOffsetBeyondEndOfFile; i < file_size; i++) 173 EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]); 174 } 175 176 TEST(File, Append) { 177 base::ScopedTempDir temp_dir; 178 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 179 FilePath file_path = temp_dir.path().AppendASCII("append_file"); 180 File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND); 181 ASSERT_TRUE(file.IsValid()); 182 183 char data_to_write[] = "test"; 184 const int kTestDataSize = 4; 185 186 // Write 0 bytes to the file. 187 int bytes_written = file.Write(0, data_to_write, 0); 188 EXPECT_EQ(0, bytes_written); 189 190 // Write "test" to the file. 191 bytes_written = file.Write(0, data_to_write, kTestDataSize); 192 EXPECT_EQ(kTestDataSize, bytes_written); 193 194 file.Close(); 195 File file2(file_path, 196 base::File::FLAG_OPEN | base::File::FLAG_READ | 197 base::File::FLAG_APPEND); 198 ASSERT_TRUE(file2.IsValid()); 199 200 // Test passing the file around. 201 file = file2.Pass(); 202 EXPECT_FALSE(file2.IsValid()); 203 ASSERT_TRUE(file.IsValid()); 204 205 char append_data_to_write[] = "78"; 206 const int kAppendDataSize = 2; 207 208 // Append "78" to the file. 209 bytes_written = file.Write(0, append_data_to_write, kAppendDataSize); 210 EXPECT_EQ(kAppendDataSize, bytes_written); 211 212 // Read the entire file. 213 char data_read_1[32]; 214 int bytes_read = file.Read(0, data_read_1, 215 kTestDataSize + kAppendDataSize); 216 EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read); 217 for (int i = 0; i < kTestDataSize; i++) 218 EXPECT_EQ(data_to_write[i], data_read_1[i]); 219 for (int i = 0; i < kAppendDataSize; i++) 220 EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]); 221 } 222 223 224 TEST(File, Truncate) { 225 base::ScopedTempDir temp_dir; 226 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 227 FilePath file_path = temp_dir.path().AppendASCII("truncate_file"); 228 File file(file_path, 229 base::File::FLAG_CREATE | base::File::FLAG_READ | 230 base::File::FLAG_WRITE); 231 ASSERT_TRUE(file.IsValid()); 232 233 // Write "test" to the file. 234 char data_to_write[] = "test"; 235 int kTestDataSize = 4; 236 int bytes_written = file.Write(0, data_to_write, kTestDataSize); 237 EXPECT_EQ(kTestDataSize, bytes_written); 238 239 // Extend the file. 240 const int kExtendedFileLength = 10; 241 int64 file_size = 0; 242 EXPECT_TRUE(file.Truncate(kExtendedFileLength)); 243 EXPECT_TRUE(GetFileSize(file_path, &file_size)); 244 EXPECT_EQ(kExtendedFileLength, file_size); 245 246 // Make sure the file was zero-padded. 247 char data_read[32]; 248 int bytes_read = file.Read(0, data_read, static_cast<int>(file_size)); 249 EXPECT_EQ(file_size, bytes_read); 250 for (int i = 0; i < kTestDataSize; i++) 251 EXPECT_EQ(data_to_write[i], data_read[i]); 252 for (int i = kTestDataSize; i < file_size; i++) 253 EXPECT_EQ(0, data_read[i]); 254 255 // Truncate the file. 256 const int kTruncatedFileLength = 2; 257 EXPECT_TRUE(file.Truncate(kTruncatedFileLength)); 258 EXPECT_TRUE(GetFileSize(file_path, &file_size)); 259 EXPECT_EQ(kTruncatedFileLength, file_size); 260 261 // Make sure the file was truncated. 262 bytes_read = file.Read(0, data_read, kTestDataSize); 263 EXPECT_EQ(file_size, bytes_read); 264 for (int i = 0; i < file_size; i++) 265 EXPECT_EQ(data_to_write[i], data_read[i]); 266 } 267 268 // Flakily fails: http://crbug.com/86494 269 #if defined(OS_ANDROID) 270 TEST(File, TouchGetInfo) { 271 #else 272 TEST(File, DISABLED_TouchGetInfo) { 273 #endif 274 base::ScopedTempDir temp_dir; 275 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 276 File file(temp_dir.path().AppendASCII("touch_get_info_file"), 277 base::File::FLAG_CREATE | base::File::FLAG_WRITE | 278 base::File::FLAG_WRITE_ATTRIBUTES); 279 ASSERT_TRUE(file.IsValid()); 280 281 // Get info for a newly created file. 282 base::File::Info info; 283 EXPECT_TRUE(file.GetInfo(&info)); 284 285 // Add 2 seconds to account for possible rounding errors on 286 // filesystems that use a 1s or 2s timestamp granularity. 287 base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2); 288 EXPECT_EQ(0, info.size); 289 EXPECT_FALSE(info.is_directory); 290 EXPECT_FALSE(info.is_symbolic_link); 291 EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue()); 292 EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue()); 293 EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue()); 294 base::Time creation_time = info.creation_time; 295 296 // Write "test" to the file. 297 char data[] = "test"; 298 const int kTestDataSize = 4; 299 int bytes_written = file.Write(0, data, kTestDataSize); 300 EXPECT_EQ(kTestDataSize, bytes_written); 301 302 // Change the last_accessed and last_modified dates. 303 // It's best to add values that are multiples of 2 (in seconds) 304 // to the current last_accessed and last_modified times, because 305 // FATxx uses a 2s timestamp granularity. 306 base::Time new_last_accessed = 307 info.last_accessed + base::TimeDelta::FromSeconds(234); 308 base::Time new_last_modified = 309 info.last_modified + base::TimeDelta::FromMinutes(567); 310 311 EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified)); 312 313 // Make sure the file info was updated accordingly. 314 EXPECT_TRUE(file.GetInfo(&info)); 315 EXPECT_EQ(info.size, kTestDataSize); 316 EXPECT_FALSE(info.is_directory); 317 EXPECT_FALSE(info.is_symbolic_link); 318 319 // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s. 320 #if defined(OS_POSIX) 321 EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec, 322 new_last_accessed.ToTimeVal().tv_sec); 323 EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec, 324 new_last_modified.ToTimeVal().tv_sec); 325 #else 326 EXPECT_EQ(info.last_accessed.ToInternalValue(), 327 new_last_accessed.ToInternalValue()); 328 EXPECT_EQ(info.last_modified.ToInternalValue(), 329 new_last_modified.ToInternalValue()); 330 #endif 331 332 EXPECT_EQ(info.creation_time.ToInternalValue(), 333 creation_time.ToInternalValue()); 334 } 335 336 TEST(File, ReadFileAtCurrentPosition) { 337 base::ScopedTempDir temp_dir; 338 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 339 FilePath file_path = 340 temp_dir.path().AppendASCII("read_file_at_current_position"); 341 File file(file_path, 342 base::File::FLAG_CREATE | base::File::FLAG_READ | 343 base::File::FLAG_WRITE); 344 EXPECT_TRUE(file.IsValid()); 345 346 const char kData[] = "test"; 347 const int kDataSize = arraysize(kData) - 1; 348 EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize)); 349 350 EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0)); 351 352 char buffer[kDataSize]; 353 int first_chunk_size = kDataSize / 2; 354 EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size)); 355 EXPECT_EQ(kDataSize - first_chunk_size, 356 file.ReadAtCurrentPos(buffer + first_chunk_size, 357 kDataSize - first_chunk_size)); 358 EXPECT_EQ(std::string(buffer, buffer + kDataSize), 359 std::string(kData)); 360 } 361