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