Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2008 The Chromium Authors. All rights reserved.  Use of this
      2 // source code is governed by a BSD-style license that can be found in the
      3 // LICENSE file.
      4 
      5 #include "base/file_util.h"
      6 #include "base/path_service.h"
      7 #include "base/platform_file.h"
      8 #include "net/base/file_stream.h"
      9 #include "net/base/net_errors.h"
     10 #include "net/base/test_completion_callback.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 #include "testing/platform_test.h"
     13 
     14 namespace {
     15 
     16 const char kTestData[] = "0123456789";
     17 const int kTestDataSize = arraysize(kTestData) - 1;
     18 
     19 class FileStreamTest : public PlatformTest {
     20  public:
     21   virtual void SetUp() {
     22     PlatformTest::SetUp();
     23 
     24     file_util::CreateTemporaryFile(&temp_file_path_);
     25     file_util::WriteFile(temp_file_path_, kTestData, kTestDataSize);
     26   }
     27   virtual void TearDown() {
     28     file_util::Delete(temp_file_path_, false);
     29 
     30     PlatformTest::TearDown();
     31   }
     32   const FilePath temp_file_path() const { return temp_file_path_; }
     33  private:
     34   FilePath temp_file_path_;
     35 };
     36 
     37 TEST_F(FileStreamTest, BasicOpenClose) {
     38   net::FileStream stream;
     39   int rv = stream.Open(temp_file_path(),
     40       base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
     41   EXPECT_EQ(net::OK, rv);
     42 }
     43 
     44 // Test the use of FileStream with a file handle provided at construction.
     45 TEST_F(FileStreamTest, UseFileHandle) {
     46   bool created = false;
     47 
     48   // 1. Test reading with a file handle.
     49   ASSERT_EQ(kTestDataSize,
     50       file_util::WriteFile(temp_file_path(), kTestData, kTestDataSize));
     51   int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ;
     52   base::PlatformFile file = base::CreatePlatformFile(
     53       temp_file_path().ToWStringHack(), flags, &created);
     54 
     55   // Seek to the beginning of the file and read.
     56   net::FileStream read_stream(file, flags);
     57   ASSERT_EQ(0, read_stream.Seek(net::FROM_BEGIN, 0));
     58   ASSERT_EQ(kTestDataSize, read_stream.Available());
     59   // Read into buffer and compare.
     60   char buffer[kTestDataSize];
     61   ASSERT_EQ(kTestDataSize, read_stream.Read(buffer, kTestDataSize, NULL));
     62   ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize));
     63   read_stream.Close();
     64 
     65   // 2. Test writing with a file handle.
     66   file_util::Delete(temp_file_path(), false);
     67   flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE;
     68   file = base::CreatePlatformFile(temp_file_path().ToWStringHack(),
     69                                   flags, &created);
     70 
     71   net::FileStream write_stream(file, flags);
     72   ASSERT_EQ(0, write_stream.Seek(net::FROM_BEGIN, 0));
     73   ASSERT_EQ(kTestDataSize, write_stream.Write(kTestData, kTestDataSize, NULL));
     74   write_stream.Close();
     75 
     76   // Read into buffer and compare to make sure the handle worked fine.
     77   ASSERT_EQ(kTestDataSize,
     78       file_util::ReadFile(temp_file_path(), buffer, kTestDataSize));
     79   ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize));
     80 }
     81 
     82 TEST_F(FileStreamTest, UseClosedStream) {
     83   net::FileStream stream;
     84 
     85   EXPECT_FALSE(stream.IsOpen());
     86 
     87   // Try seeking...
     88   int64 new_offset = stream.Seek(net::FROM_BEGIN, 5);
     89   EXPECT_EQ(net::ERR_UNEXPECTED, new_offset);
     90 
     91   // Try available...
     92   int64 avail = stream.Available();
     93   EXPECT_EQ(net::ERR_UNEXPECTED, avail);
     94 
     95   // Try reading...
     96   char buf[10];
     97   int rv = stream.Read(buf, arraysize(buf), NULL);
     98   EXPECT_EQ(net::ERR_UNEXPECTED, rv);
     99 }
    100 
    101 TEST_F(FileStreamTest, BasicRead) {
    102   int64 file_size;
    103   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    104   EXPECT_TRUE(ok);
    105 
    106   net::FileStream stream;
    107   int flags = base::PLATFORM_FILE_OPEN |
    108               base::PLATFORM_FILE_READ;
    109   int rv = stream.Open(temp_file_path(), flags);
    110   EXPECT_EQ(net::OK, rv);
    111 
    112   int64 total_bytes_avail = stream.Available();
    113   EXPECT_EQ(file_size, total_bytes_avail);
    114 
    115   int total_bytes_read = 0;
    116 
    117   std::string data_read;
    118   for (;;) {
    119     char buf[4];
    120     rv = stream.Read(buf, arraysize(buf), NULL);
    121     EXPECT_LE(0, rv);
    122     if (rv <= 0)
    123       break;
    124     total_bytes_read += rv;
    125     data_read.append(buf, rv);
    126   }
    127   EXPECT_EQ(file_size, total_bytes_read);
    128   EXPECT_EQ(kTestData, data_read);
    129 }
    130 
    131 TEST_F(FileStreamTest, AsyncRead) {
    132   int64 file_size;
    133   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    134   EXPECT_TRUE(ok);
    135 
    136   net::FileStream stream;
    137   int flags = base::PLATFORM_FILE_OPEN |
    138               base::PLATFORM_FILE_READ |
    139               base::PLATFORM_FILE_ASYNC;
    140   int rv = stream.Open(temp_file_path(), flags);
    141   EXPECT_EQ(net::OK, rv);
    142 
    143   int64 total_bytes_avail = stream.Available();
    144   EXPECT_EQ(file_size, total_bytes_avail);
    145 
    146   TestCompletionCallback callback;
    147 
    148   int total_bytes_read = 0;
    149 
    150   std::string data_read;
    151   for (;;) {
    152     char buf[4];
    153     rv = stream.Read(buf, arraysize(buf), &callback);
    154     if (rv == net::ERR_IO_PENDING)
    155       rv = callback.WaitForResult();
    156     EXPECT_LE(0, rv);
    157     if (rv <= 0)
    158       break;
    159     total_bytes_read += rv;
    160     data_read.append(buf, rv);
    161   }
    162   EXPECT_EQ(file_size, total_bytes_read);
    163   EXPECT_EQ(kTestData, data_read);
    164 }
    165 
    166 TEST_F(FileStreamTest, AsyncRead_EarlyClose) {
    167   int64 file_size;
    168   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    169   EXPECT_TRUE(ok);
    170 
    171   net::FileStream stream;
    172   int flags = base::PLATFORM_FILE_OPEN |
    173               base::PLATFORM_FILE_READ |
    174               base::PLATFORM_FILE_ASYNC;
    175   int rv = stream.Open(temp_file_path(), flags);
    176   EXPECT_EQ(net::OK, rv);
    177 
    178   int64 total_bytes_avail = stream.Available();
    179   EXPECT_EQ(file_size, total_bytes_avail);
    180 
    181   TestCompletionCallback callback;
    182 
    183   char buf[4];
    184   rv = stream.Read(buf, arraysize(buf), &callback);
    185   stream.Close();
    186   if (rv < 0) {
    187     EXPECT_EQ(net::ERR_IO_PENDING, rv);
    188     // The callback should not be called if the request is cancelled.
    189     MessageLoop::current()->RunAllPending();
    190     EXPECT_FALSE(callback.have_result());
    191   } else {
    192     EXPECT_EQ(std::string(kTestData, rv), std::string(buf, rv));
    193   }
    194 }
    195 
    196 TEST_F(FileStreamTest, BasicRead_FromOffset) {
    197   int64 file_size;
    198   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    199   EXPECT_TRUE(ok);
    200 
    201   net::FileStream stream;
    202   int flags = base::PLATFORM_FILE_OPEN |
    203               base::PLATFORM_FILE_READ;
    204   int rv = stream.Open(temp_file_path(), flags);
    205   EXPECT_EQ(net::OK, rv);
    206 
    207   const int64 kOffset = 3;
    208   int64 new_offset = stream.Seek(net::FROM_BEGIN, kOffset);
    209   EXPECT_EQ(kOffset, new_offset);
    210 
    211   int64 total_bytes_avail = stream.Available();
    212   EXPECT_EQ(file_size - kOffset, total_bytes_avail);
    213 
    214   int64 total_bytes_read = 0;
    215 
    216   std::string data_read;
    217   for (;;) {
    218     char buf[4];
    219     rv = stream.Read(buf, arraysize(buf), NULL);
    220     EXPECT_LE(0, rv);
    221     if (rv <= 0)
    222       break;
    223     total_bytes_read += rv;
    224     data_read.append(buf, rv);
    225   }
    226   EXPECT_EQ(file_size - kOffset, total_bytes_read);
    227   EXPECT_TRUE(data_read == kTestData + kOffset);
    228   EXPECT_EQ(kTestData + kOffset, data_read);
    229 }
    230 
    231 TEST_F(FileStreamTest, AsyncRead_FromOffset) {
    232   int64 file_size;
    233   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    234   EXPECT_TRUE(ok);
    235 
    236   net::FileStream stream;
    237   int flags = base::PLATFORM_FILE_OPEN |
    238               base::PLATFORM_FILE_READ |
    239               base::PLATFORM_FILE_ASYNC;
    240   int rv = stream.Open(temp_file_path(), flags);
    241   EXPECT_EQ(net::OK, rv);
    242 
    243   const int64 kOffset = 3;
    244   int64 new_offset = stream.Seek(net::FROM_BEGIN, kOffset);
    245   EXPECT_EQ(kOffset, new_offset);
    246 
    247   int64 total_bytes_avail = stream.Available();
    248   EXPECT_EQ(file_size - kOffset, total_bytes_avail);
    249 
    250   TestCompletionCallback callback;
    251 
    252   int total_bytes_read = 0;
    253 
    254   std::string data_read;
    255   for (;;) {
    256     char buf[4];
    257     rv = stream.Read(buf, arraysize(buf), &callback);
    258     if (rv == net::ERR_IO_PENDING)
    259       rv = callback.WaitForResult();
    260     EXPECT_LE(0, rv);
    261     if (rv <= 0)
    262       break;
    263     total_bytes_read += rv;
    264     data_read.append(buf, rv);
    265   }
    266   EXPECT_EQ(file_size - kOffset, total_bytes_read);
    267   EXPECT_EQ(kTestData + kOffset, data_read);
    268 }
    269 
    270 TEST_F(FileStreamTest, SeekAround) {
    271   net::FileStream stream;
    272   int flags = base::PLATFORM_FILE_OPEN |
    273               base::PLATFORM_FILE_READ;
    274   int rv = stream.Open(temp_file_path(), flags);
    275   EXPECT_EQ(net::OK, rv);
    276 
    277   const int64 kOffset = 3;
    278   int64 new_offset = stream.Seek(net::FROM_BEGIN, kOffset);
    279   EXPECT_EQ(kOffset, new_offset);
    280 
    281   new_offset = stream.Seek(net::FROM_CURRENT, kOffset);
    282   EXPECT_EQ(2 * kOffset, new_offset);
    283 
    284   new_offset = stream.Seek(net::FROM_CURRENT, -kOffset);
    285   EXPECT_EQ(kOffset, new_offset);
    286 
    287   const int kTestDataLen = arraysize(kTestData) - 1;
    288 
    289   new_offset = stream.Seek(net::FROM_END, -kTestDataLen);
    290   EXPECT_EQ(0, new_offset);
    291 }
    292 
    293 TEST_F(FileStreamTest, BasicWrite) {
    294   net::FileStream stream;
    295   int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
    296               base::PLATFORM_FILE_WRITE;
    297   int rv = stream.Open(temp_file_path(), flags);
    298   EXPECT_EQ(net::OK, rv);
    299 
    300   int64 file_size;
    301   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    302   EXPECT_TRUE(ok);
    303   EXPECT_EQ(0, file_size);
    304 
    305   rv = stream.Write(kTestData, kTestDataSize, NULL);
    306   EXPECT_EQ(kTestDataSize, rv);
    307   stream.Close();
    308 
    309   ok = file_util::GetFileSize(temp_file_path(), &file_size);
    310   EXPECT_TRUE(ok);
    311   EXPECT_EQ(kTestDataSize, file_size);
    312 }
    313 
    314 TEST_F(FileStreamTest, AsyncWrite) {
    315   net::FileStream stream;
    316   int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
    317               base::PLATFORM_FILE_WRITE |
    318               base::PLATFORM_FILE_ASYNC;
    319   int rv = stream.Open(temp_file_path(), flags);
    320   EXPECT_EQ(net::OK, rv);
    321 
    322   int64 file_size;
    323   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    324   EXPECT_TRUE(ok);
    325   EXPECT_EQ(0, file_size);
    326 
    327   TestCompletionCallback callback;
    328   int total_bytes_written = 0;
    329 
    330   while (total_bytes_written != kTestDataSize) {
    331     rv = stream.Write(kTestData + total_bytes_written,
    332                       kTestDataSize - total_bytes_written,
    333                       &callback);
    334     if (rv == net::ERR_IO_PENDING)
    335       rv = callback.WaitForResult();
    336     EXPECT_LT(0, rv);
    337     if (rv <= 0)
    338       break;
    339     total_bytes_written += rv;
    340   }
    341   ok = file_util::GetFileSize(temp_file_path(), &file_size);
    342   EXPECT_TRUE(ok);
    343   EXPECT_EQ(file_size, total_bytes_written);
    344 }
    345 
    346 TEST_F(FileStreamTest, AsyncWrite_EarlyClose) {
    347   net::FileStream stream;
    348   int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
    349               base::PLATFORM_FILE_WRITE |
    350               base::PLATFORM_FILE_ASYNC;
    351   int rv = stream.Open(temp_file_path(), flags);
    352   EXPECT_EQ(net::OK, rv);
    353 
    354   int64 file_size;
    355   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    356   EXPECT_TRUE(ok);
    357   EXPECT_EQ(0, file_size);
    358 
    359   TestCompletionCallback callback;
    360   int total_bytes_written = 0;
    361 
    362   rv = stream.Write(kTestData + total_bytes_written,
    363                     kTestDataSize - total_bytes_written,
    364                     &callback);
    365   stream.Close();
    366   if (rv < 0) {
    367     EXPECT_EQ(net::ERR_IO_PENDING, rv);
    368     // The callback should not be called if the request is cancelled.
    369     MessageLoop::current()->RunAllPending();
    370     EXPECT_FALSE(callback.have_result());
    371   } else {
    372     ok = file_util::GetFileSize(temp_file_path(), &file_size);
    373     EXPECT_TRUE(ok);
    374     EXPECT_EQ(file_size, rv);
    375   }
    376 }
    377 
    378 TEST_F(FileStreamTest, BasicWrite_FromOffset) {
    379   net::FileStream stream;
    380   int flags = base::PLATFORM_FILE_OPEN |
    381               base::PLATFORM_FILE_WRITE;
    382   int rv = stream.Open(temp_file_path(), flags);
    383   EXPECT_EQ(net::OK, rv);
    384 
    385   int64 file_size;
    386   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    387   EXPECT_TRUE(ok);
    388   EXPECT_EQ(kTestDataSize, file_size);
    389 
    390   const int64 kOffset = 0;
    391   int64 new_offset = stream.Seek(net::FROM_END, kOffset);
    392   EXPECT_EQ(kTestDataSize, new_offset);
    393 
    394   rv = stream.Write(kTestData, kTestDataSize, NULL);
    395   EXPECT_EQ(kTestDataSize, rv);
    396   stream.Close();
    397 
    398   ok = file_util::GetFileSize(temp_file_path(), &file_size);
    399   EXPECT_TRUE(ok);
    400   EXPECT_EQ(kTestDataSize * 2, file_size);
    401 }
    402 
    403 TEST_F(FileStreamTest, AsyncWrite_FromOffset) {
    404   int64 file_size;
    405   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    406   EXPECT_TRUE(ok);
    407 
    408   net::FileStream stream;
    409   int flags = base::PLATFORM_FILE_OPEN |
    410               base::PLATFORM_FILE_WRITE |
    411               base::PLATFORM_FILE_ASYNC;
    412   int rv = stream.Open(temp_file_path(), flags);
    413   EXPECT_EQ(net::OK, rv);
    414 
    415   const int64 kOffset = 0;
    416   int64 new_offset = stream.Seek(net::FROM_END, kOffset);
    417   EXPECT_EQ(kTestDataSize, new_offset);
    418 
    419   TestCompletionCallback callback;
    420   int total_bytes_written = 0;
    421 
    422   while (total_bytes_written != kTestDataSize) {
    423     rv = stream.Write(kTestData + total_bytes_written,
    424                       kTestDataSize - total_bytes_written,
    425                       &callback);
    426     if (rv == net::ERR_IO_PENDING)
    427       rv = callback.WaitForResult();
    428     EXPECT_LT(0, rv);
    429     if (rv <= 0)
    430       break;
    431     total_bytes_written += rv;
    432   }
    433   ok = file_util::GetFileSize(temp_file_path(), &file_size);
    434   EXPECT_TRUE(ok);
    435   EXPECT_EQ(file_size, kTestDataSize * 2);
    436 }
    437 
    438 TEST_F(FileStreamTest, BasicReadWrite) {
    439   int64 file_size;
    440   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    441   EXPECT_TRUE(ok);
    442 
    443   net::FileStream stream;
    444   int flags = base::PLATFORM_FILE_OPEN |
    445               base::PLATFORM_FILE_READ |
    446               base::PLATFORM_FILE_WRITE;
    447   int rv = stream.Open(temp_file_path(), flags);
    448   EXPECT_EQ(net::OK, rv);
    449 
    450   int64 total_bytes_avail = stream.Available();
    451   EXPECT_EQ(file_size, total_bytes_avail);
    452 
    453   int total_bytes_read = 0;
    454 
    455   std::string data_read;
    456   for (;;) {
    457     char buf[4];
    458     rv = stream.Read(buf, arraysize(buf), NULL);
    459     EXPECT_LE(0, rv);
    460     if (rv <= 0)
    461       break;
    462     total_bytes_read += rv;
    463     data_read.append(buf, rv);
    464   }
    465   EXPECT_EQ(file_size, total_bytes_read);
    466   EXPECT_TRUE(data_read == kTestData);
    467 
    468   rv = stream.Write(kTestData, kTestDataSize, NULL);
    469   EXPECT_EQ(kTestDataSize, rv);
    470   stream.Close();
    471 
    472   ok = file_util::GetFileSize(temp_file_path(), &file_size);
    473   EXPECT_TRUE(ok);
    474   EXPECT_EQ(kTestDataSize * 2, file_size);
    475 }
    476 
    477 TEST_F(FileStreamTest, BasicWriteRead) {
    478   int64 file_size;
    479   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    480   EXPECT_TRUE(ok);
    481 
    482   net::FileStream stream;
    483   int flags = base::PLATFORM_FILE_OPEN |
    484               base::PLATFORM_FILE_READ |
    485               base::PLATFORM_FILE_WRITE;
    486   int rv = stream.Open(temp_file_path(), flags);
    487   EXPECT_EQ(net::OK, rv);
    488 
    489   int64 total_bytes_avail = stream.Available();
    490   EXPECT_EQ(file_size, total_bytes_avail);
    491 
    492   int64 offset = stream.Seek(net::FROM_END, 0);
    493   EXPECT_EQ(offset, file_size);
    494 
    495   rv = stream.Write(kTestData, kTestDataSize, NULL);
    496   EXPECT_EQ(kTestDataSize, rv);
    497 
    498   offset = stream.Seek(net::FROM_BEGIN, 0);
    499   EXPECT_EQ(0, offset);
    500 
    501   int64 total_bytes_read = 0;
    502 
    503   std::string data_read;
    504   for (;;) {
    505     char buf[4];
    506     rv = stream.Read(buf, arraysize(buf), NULL);
    507     EXPECT_LE(0, rv);
    508     if (rv <= 0)
    509       break;
    510     total_bytes_read += rv;
    511     data_read.append(buf, rv);
    512   }
    513   stream.Close();
    514 
    515   ok = file_util::GetFileSize(temp_file_path(), &file_size);
    516   EXPECT_TRUE(ok);
    517   EXPECT_EQ(kTestDataSize * 2, file_size);
    518   EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
    519 
    520   const std::string kExpectedFileData =
    521       std::string(kTestData) + std::string(kTestData);
    522   EXPECT_EQ(kExpectedFileData, data_read);
    523 }
    524 
    525 TEST_F(FileStreamTest, BasicAsyncReadWrite) {
    526   int64 file_size;
    527   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    528   EXPECT_TRUE(ok);
    529 
    530   net::FileStream stream;
    531   int flags = base::PLATFORM_FILE_OPEN |
    532               base::PLATFORM_FILE_READ |
    533               base::PLATFORM_FILE_WRITE |
    534               base::PLATFORM_FILE_ASYNC;
    535   int rv = stream.Open(temp_file_path(), flags);
    536   EXPECT_EQ(net::OK, rv);
    537 
    538   int64 total_bytes_avail = stream.Available();
    539   EXPECT_EQ(file_size, total_bytes_avail);
    540 
    541   TestCompletionCallback callback;
    542   int64 total_bytes_read = 0;
    543 
    544   std::string data_read;
    545   for (;;) {
    546     char buf[4];
    547     rv = stream.Read(buf, arraysize(buf), &callback);
    548     if (rv == net::ERR_IO_PENDING)
    549       rv = callback.WaitForResult();
    550     EXPECT_LE(0, rv);
    551     if (rv <= 0)
    552       break;
    553     total_bytes_read += rv;
    554     data_read.append(buf, rv);
    555   }
    556   EXPECT_EQ(file_size, total_bytes_read);
    557   EXPECT_TRUE(data_read == kTestData);
    558 
    559   int total_bytes_written = 0;
    560 
    561   while (total_bytes_written != kTestDataSize) {
    562     rv = stream.Write(kTestData + total_bytes_written,
    563                       kTestDataSize - total_bytes_written,
    564                       &callback);
    565     if (rv == net::ERR_IO_PENDING)
    566       rv = callback.WaitForResult();
    567     EXPECT_LT(0, rv);
    568     if (rv <= 0)
    569       break;
    570     total_bytes_written += rv;
    571   }
    572 
    573   stream.Close();
    574 
    575   ok = file_util::GetFileSize(temp_file_path(), &file_size);
    576   EXPECT_TRUE(ok);
    577   EXPECT_EQ(kTestDataSize * 2, file_size);
    578 }
    579 
    580 TEST_F(FileStreamTest, BasicAsyncWriteRead) {
    581   int64 file_size;
    582   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    583   EXPECT_TRUE(ok);
    584 
    585   net::FileStream stream;
    586   int flags = base::PLATFORM_FILE_OPEN |
    587               base::PLATFORM_FILE_READ |
    588               base::PLATFORM_FILE_WRITE |
    589               base::PLATFORM_FILE_ASYNC;
    590   int rv = stream.Open(temp_file_path(), flags);
    591   EXPECT_EQ(net::OK, rv);
    592 
    593   int64 total_bytes_avail = stream.Available();
    594   EXPECT_EQ(file_size, total_bytes_avail);
    595 
    596   int64 offset = stream.Seek(net::FROM_END, 0);
    597   EXPECT_EQ(offset, file_size);
    598 
    599   TestCompletionCallback callback;
    600   int total_bytes_written = 0;
    601 
    602   while (total_bytes_written != kTestDataSize) {
    603     rv = stream.Write(kTestData + total_bytes_written,
    604                       kTestDataSize - total_bytes_written,
    605                       &callback);
    606     if (rv == net::ERR_IO_PENDING)
    607       rv = callback.WaitForResult();
    608     EXPECT_LT(0, rv);
    609     if (rv <= 0)
    610       break;
    611     total_bytes_written += rv;
    612   }
    613 
    614   EXPECT_EQ(kTestDataSize, total_bytes_written);
    615 
    616   offset = stream.Seek(net::FROM_BEGIN, 0);
    617   EXPECT_EQ(0, offset);
    618 
    619   int total_bytes_read = 0;
    620 
    621   std::string data_read;
    622   for (;;) {
    623     char buf[4];
    624     rv = stream.Read(buf, arraysize(buf), &callback);
    625     if (rv == net::ERR_IO_PENDING)
    626       rv = callback.WaitForResult();
    627     EXPECT_LE(0, rv);
    628     if (rv <= 0)
    629       break;
    630     total_bytes_read += rv;
    631     data_read.append(buf, rv);
    632   }
    633   stream.Close();
    634 
    635   ok = file_util::GetFileSize(temp_file_path(), &file_size);
    636   EXPECT_TRUE(ok);
    637   EXPECT_EQ(kTestDataSize * 2, file_size);
    638 
    639   EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
    640   const std::string kExpectedFileData =
    641       std::string(kTestData) + std::string(kTestData);
    642   EXPECT_EQ(kExpectedFileData, data_read);
    643 }
    644 
    645 class TestWriteReadCompletionCallback : public Callback1<int>::Type {
    646  public:
    647   explicit TestWriteReadCompletionCallback(
    648       net::FileStream* stream,
    649       int* total_bytes_written,
    650       int* total_bytes_read,
    651       std::string* data_read)
    652       : result_(0),
    653         have_result_(false),
    654         waiting_for_result_(false),
    655         stream_(stream),
    656         total_bytes_written_(total_bytes_written),
    657         total_bytes_read_(total_bytes_read),
    658         data_read_(data_read) {}
    659 
    660   int WaitForResult() {
    661     DCHECK(!waiting_for_result_);
    662     while (!have_result_) {
    663       waiting_for_result_ = true;
    664       MessageLoop::current()->Run();
    665       waiting_for_result_ = false;
    666     }
    667     have_result_ = false;  // auto-reset for next callback
    668     return result_;
    669   }
    670 
    671  private:
    672   virtual void RunWithParams(const Tuple1<int>& params) {
    673     DCHECK_LT(0, params.a);
    674     *total_bytes_written_ += params.a;
    675 
    676     int rv;
    677 
    678     if (*total_bytes_written_ != kTestDataSize) {
    679       // Recurse to finish writing all data.
    680       int total_bytes_written = 0, total_bytes_read = 0;
    681       std::string data_read;
    682       TestWriteReadCompletionCallback callback(
    683           stream_, &total_bytes_written, &total_bytes_read, &data_read);
    684       rv = stream_->Write(kTestData + *total_bytes_written_,
    685                           kTestDataSize - *total_bytes_written_,
    686                           &callback);
    687       DCHECK_EQ(net::ERR_IO_PENDING, rv);
    688       rv = callback.WaitForResult();
    689       *total_bytes_written_ += total_bytes_written;
    690       *total_bytes_read_ += total_bytes_read;
    691       *data_read_ += data_read;
    692     } else {  // We're done writing all data.  Start reading the data.
    693       stream_->Seek(net::FROM_BEGIN, 0);
    694 
    695       TestCompletionCallback callback;
    696       for (;;) {
    697         char buf[4];
    698         rv = stream_->Read(buf, arraysize(buf), &callback);
    699         if (rv == net::ERR_IO_PENDING) {
    700           bool old_state = MessageLoop::current()->NestableTasksAllowed();
    701           MessageLoop::current()->SetNestableTasksAllowed(true);
    702           rv = callback.WaitForResult();
    703           MessageLoop::current()->SetNestableTasksAllowed(old_state);
    704         }
    705         EXPECT_LE(0, rv);
    706         if (rv <= 0)
    707           break;
    708         *total_bytes_read_ += rv;
    709         data_read_->append(buf, rv);
    710       }
    711     }
    712 
    713     result_ = *total_bytes_written_;
    714     have_result_ = true;
    715     if (waiting_for_result_)
    716       MessageLoop::current()->Quit();
    717   }
    718 
    719   int result_;
    720   bool have_result_;
    721   bool waiting_for_result_;
    722   net::FileStream* stream_;
    723   int* total_bytes_written_;
    724   int* total_bytes_read_;
    725   std::string* data_read_;
    726 
    727   DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback);
    728 };
    729 
    730 TEST_F(FileStreamTest, AsyncWriteRead) {
    731   int64 file_size;
    732   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    733   EXPECT_TRUE(ok);
    734 
    735   net::FileStream stream;
    736   int flags = base::PLATFORM_FILE_OPEN |
    737               base::PLATFORM_FILE_READ |
    738               base::PLATFORM_FILE_WRITE |
    739               base::PLATFORM_FILE_ASYNC;
    740   int rv = stream.Open(temp_file_path(), flags);
    741   EXPECT_EQ(net::OK, rv);
    742 
    743   int64 total_bytes_avail = stream.Available();
    744   EXPECT_EQ(file_size, total_bytes_avail);
    745 
    746   int64 offset = stream.Seek(net::FROM_END, 0);
    747   EXPECT_EQ(offset, file_size);
    748 
    749   int total_bytes_written = 0;
    750   int total_bytes_read = 0;
    751   std::string data_read;
    752   TestWriteReadCompletionCallback callback(&stream, &total_bytes_written,
    753                                            &total_bytes_read, &data_read);
    754 
    755   rv = stream.Write(kTestData + total_bytes_written,
    756                     kTestDataSize - static_cast<int>(total_bytes_written),
    757                     &callback);
    758   if (rv == net::ERR_IO_PENDING)
    759     rv = callback.WaitForResult();
    760   EXPECT_LT(0, rv);
    761   EXPECT_EQ(kTestDataSize, total_bytes_written);
    762 
    763   stream.Close();
    764 
    765   ok = file_util::GetFileSize(temp_file_path(), &file_size);
    766   EXPECT_TRUE(ok);
    767   EXPECT_EQ(kTestDataSize * 2, file_size);
    768 
    769   EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
    770   const std::string kExpectedFileData =
    771       std::string(kTestData) + std::string(kTestData);
    772   EXPECT_EQ(kExpectedFileData, data_read);
    773 }
    774 
    775 class TestWriteCloseCompletionCallback : public Callback1<int>::Type {
    776  public:
    777   explicit TestWriteCloseCompletionCallback(net::FileStream* stream,
    778                                             int* total_bytes_written)
    779       : result_(0),
    780         have_result_(false),
    781         waiting_for_result_(false),
    782         stream_(stream),
    783         total_bytes_written_(total_bytes_written) {}
    784 
    785   int WaitForResult() {
    786     DCHECK(!waiting_for_result_);
    787     while (!have_result_) {
    788       waiting_for_result_ = true;
    789       MessageLoop::current()->Run();
    790       waiting_for_result_ = false;
    791     }
    792     have_result_ = false;  // auto-reset for next callback
    793     return result_;
    794   }
    795 
    796  private:
    797   virtual void RunWithParams(const Tuple1<int>& params) {
    798     DCHECK_LT(0, params.a);
    799     *total_bytes_written_ += params.a;
    800 
    801     int rv;
    802 
    803     if (*total_bytes_written_ != kTestDataSize) {
    804       // Recurse to finish writing all data.
    805       int total_bytes_written = 0;
    806       TestWriteCloseCompletionCallback callback(stream_, &total_bytes_written);
    807       rv = stream_->Write(kTestData + *total_bytes_written_,
    808                           kTestDataSize - *total_bytes_written_,
    809                           &callback);
    810       DCHECK_EQ(net::ERR_IO_PENDING, rv);
    811       rv = callback.WaitForResult();
    812       *total_bytes_written_ += total_bytes_written;
    813     } else {  // We're done writing all data.  Close the file.
    814       stream_->Close();
    815     }
    816 
    817     result_ = *total_bytes_written_;
    818     have_result_ = true;
    819     if (waiting_for_result_)
    820       MessageLoop::current()->Quit();
    821   }
    822 
    823   int result_;
    824   bool have_result_;
    825   bool waiting_for_result_;
    826   net::FileStream* stream_;
    827   int* total_bytes_written_;
    828 
    829   DISALLOW_COPY_AND_ASSIGN(TestWriteCloseCompletionCallback);
    830 };
    831 
    832 TEST_F(FileStreamTest, AsyncWriteClose) {
    833   int64 file_size;
    834   bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
    835   EXPECT_TRUE(ok);
    836 
    837   net::FileStream stream;
    838   int flags = base::PLATFORM_FILE_OPEN |
    839               base::PLATFORM_FILE_READ |
    840               base::PLATFORM_FILE_WRITE |
    841               base::PLATFORM_FILE_ASYNC;
    842   int rv = stream.Open(temp_file_path(), flags);
    843   EXPECT_EQ(net::OK, rv);
    844 
    845   int64 total_bytes_avail = stream.Available();
    846   EXPECT_EQ(file_size, total_bytes_avail);
    847 
    848   int64 offset = stream.Seek(net::FROM_END, 0);
    849   EXPECT_EQ(offset, file_size);
    850 
    851   int total_bytes_written = 0;
    852   TestWriteCloseCompletionCallback callback(&stream, &total_bytes_written);
    853 
    854   rv = stream.Write(kTestData, kTestDataSize, &callback);
    855   if (rv == net::ERR_IO_PENDING)
    856     total_bytes_written = callback.WaitForResult();
    857   EXPECT_LT(0, total_bytes_written);
    858   EXPECT_EQ(kTestDataSize, total_bytes_written);
    859 
    860   ok = file_util::GetFileSize(temp_file_path(), &file_size);
    861   EXPECT_TRUE(ok);
    862   EXPECT_EQ(kTestDataSize * 2, file_size);
    863 }
    864 
    865 // Tests truncating a file.
    866 TEST_F(FileStreamTest, Truncate) {
    867   int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE;
    868 
    869   net::FileStream write_stream;
    870   ASSERT_EQ(net::OK, write_stream.Open(temp_file_path(), flags));
    871 
    872   // Write some data to the file.
    873   const char test_data[] = "0123456789";
    874   write_stream.Write(test_data, arraysize(test_data), NULL);
    875 
    876   // Truncate the file.
    877   ASSERT_EQ(4, write_stream.Truncate(4));
    878 
    879   // Write again.
    880   write_stream.Write(test_data, 4, NULL);
    881 
    882   // Close the stream.
    883   write_stream.Close();
    884 
    885   // Read in the contents and make sure we get back what we expected.
    886   std::string read_contents;
    887   EXPECT_TRUE(file_util::ReadFileToString(temp_file_path(), &read_contents));
    888 
    889   EXPECT_EQ("01230123", read_contents);
    890 }
    891 
    892 }  // namespace
    893