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