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