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