1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/local_file_stream_reader.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/files/file.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/run_loop.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_completion_callback.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::LocalFileStreamReader;
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace content {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTestData[] = "0123456789";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTestDataSize = arraysize(kTestData) - 1;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReadFromReader(LocalFileStreamReader* reader,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    std::string* data, size_t size,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int* result) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(reader != NULL);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(result != NULL);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = net::OK;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestCompletionCallback callback;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t total_bytes_read = 0;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (total_bytes_read < size) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBufferWithSize> buf(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new net::IOBufferWithSize(size - total_bytes_read));
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int rv = reader->Read(buf.get(), buf->size(), callback.callback());
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == net::ERR_IO_PENDING)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = callback.WaitForResult();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv < 0)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = rv;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv <= 0)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_bytes_read += rv;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->append(buf->data(), rv);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NeverCalled(int) { ADD_FAILURE(); }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmptyCallback() {}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuitLoop() {
57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->Quit();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LocalFileStreamReaderTest : public testing::Test {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LocalFileStreamReaderTest()
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : file_thread_("FileUtilProxyTestFileThread") {}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(file_thread_.Start());
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(dir_.CreateUniqueTempDir());
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::WriteFile(test_path(), kTestData, kTestDataSize);
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Info info;
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(base::GetFileInfo(test_path(), &info));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_file_modification_time_ = info.last_modified;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Give another chance for deleted streams to perform Close.
79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_thread_.Stop();
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LocalFileStreamReader* CreateFileReader(
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& path,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 initial_offset,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Time& expected_modification_time) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new LocalFileStreamReader(
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            file_task_runner(),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            path,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            initial_offset,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            expected_modification_time);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TouchTestFile() {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time new_modified_time =
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        test_file_modification_time() - base::TimeDelta::FromSeconds(1);
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(base::TouchFile(test_path(),
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                test_file_modification_time(),
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                new_modified_time));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessageLoopProxy* file_task_runner() const {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return file_thread_.message_loop_proxy().get();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath test_dir() const { return dir_.path(); }
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath test_path() const { return dir_.path().AppendASCII("test"); }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time test_file_modification_time() const {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return test_file_modification_time_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EnsureFileTaskFinished() {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_task_runner()->PostTaskAndReply(
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(&EmptyCallback), base::Bind(&QuitLoop));
117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::MessageLoop::current()->Run();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::MessageLoopForIO message_loop_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread file_thread_;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir dir_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time test_file_modification_time_;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileStreamReaderTest, NonExistent) {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath nonexistent_path = test_dir().AppendASCII("nonexistent");
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocalFileStreamReader> reader(
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateFileReader(nonexistent_path, 0, base::Time()));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = 0;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadFromReader(reader.get(), &data, 10, &result);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(net::ERR_FILE_NOT_FOUND, result);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0U, data.size());
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileStreamReaderTest, Empty) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath empty_path = test_dir().AppendASCII("empty");
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File file(empty_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(file.IsValid());
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file.Close();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocalFileStreamReader> reader(
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateFileReader(empty_path, 0, base::Time()));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = 0;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadFromReader(reader.get(), &data, 10, &result);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(net::OK, result);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0U, data.size());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestInt64CompletionCallback callback;
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int64 length_result = reader->GetLength(callback.callback());
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (length_result == net::ERR_IO_PENDING)
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    length_result = callback.WaitForResult();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, result);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileStreamReaderTest, GetLengthNormal) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocalFileStreamReader> reader(
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateFileReader(test_path(), 0, test_file_modification_time()));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestInt64CompletionCallback callback;
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int64 result = reader->GetLength(callback.callback());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == net::ERR_IO_PENDING)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = callback.WaitForResult();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kTestDataSize, result);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileStreamReaderTest, GetLengthAfterModified) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Touch file so that the file's modification time becomes different
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from what we expect.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TouchTestFile();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocalFileStreamReader> reader(
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateFileReader(test_path(), 0, test_file_modification_time()));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestInt64CompletionCallback callback;
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int64 result = reader->GetLength(callback.callback());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == net::ERR_IO_PENDING)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = callback.WaitForResult();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // With NULL expected modification time this should work.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reader.reset(CreateFileReader(test_path(), 0, base::Time()));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = reader->GetLength(callback.callback());
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == net::ERR_IO_PENDING)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = callback.WaitForResult();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kTestDataSize, result);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileStreamReaderTest, GetLengthWithOffset) {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocalFileStreamReader> reader(
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateFileReader(test_path(), 3, base::Time()));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestInt64CompletionCallback callback;
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int64 result = reader->GetLength(callback.callback());
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == net::ERR_IO_PENDING)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = callback.WaitForResult();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initial offset does not affect the result of GetLength.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kTestDataSize, result);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileStreamReaderTest, ReadNormal) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocalFileStreamReader> reader(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateFileReader(test_path(), 0, test_file_modification_time()));
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = 0;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadFromReader(reader.get(), &data, kTestDataSize, &result);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(net::OK, result);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kTestData, data);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileStreamReaderTest, ReadAfterModified) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Touch file so that the file's modification time becomes different
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from what we expect.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TouchTestFile();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocalFileStreamReader> reader(
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateFileReader(test_path(), 0, test_file_modification_time()));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = 0;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadFromReader(reader.get(), &data, kTestDataSize, &result);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0U, data.size());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // With NULL expected modification time this should work.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.clear();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reader.reset(CreateFileReader(test_path(), 0, base::Time()));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadFromReader(reader.get(), &data, kTestDataSize, &result);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(net::OK, result);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kTestData, data);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileStreamReaderTest, ReadWithOffset) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocalFileStreamReader> reader(
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateFileReader(test_path(), 3, base::Time()));
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = 0;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadFromReader(reader.get(), &data, kTestDataSize, &result);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(net::OK, result);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(&kTestData[3], data);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(LocalFileStreamReaderTest, DeleteWithUnfinishedRead) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<LocalFileStreamReader> reader(
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateFileReader(test_path(), 0, base::Time()));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestCompletionCallback callback;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::IOBufferWithSize> buf(
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new net::IOBufferWithSize(kTestDataSize));
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int rv = reader->Read(buf.get(), buf->size(), base::Bind(&NeverCalled));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(rv == net::ERR_IO_PENDING || rv >= 0);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete immediately.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should not crash; nor should NeverCalled be callback.
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reader.reset();
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureFileTaskFinished();
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace content
259