1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright 2013 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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/run_loop.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/fileapi/mock_file_change_observer.h"
13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/browser/quota/mock_quota_manager.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/test/mock_blob_url_request_context.h"
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/test/test_file_system_backend.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/test/test_file_system_context.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_job.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_job_factory_impl.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_storage_context.h"
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_url_request_job.h"
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h"
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_file_util.h"
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_operation_context.h"
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_operation_runner.h"
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/local_file_util.h"
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/blob/blob_data.h"
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_util.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemOperation;
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemOperationRunner;
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileSystemURL;
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::MockBlobURLRequestContext;
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::ScopedTextBlob;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const GURL kOrigin("http://example.com");
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const storage::FileSystemType kFileSystemType = storage::kFileSystemTypeTest;
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AssertStatusEq(base::File::Error expected,
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    base::File::Error actual) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(expected, actual);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class FileSystemOperationImplWriteTest
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : public testing::Test {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FileSystemOperationImplWriteTest()
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : status_(base::File::FILE_OK),
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        cancel_status_(base::File::FILE_ERROR_FAILED),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bytes_written_(0),
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        complete_(false),
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        weak_factory_(this) {
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    change_observers_ =
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        storage::MockFileChangeObserver::CreateList(&change_observer_);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(dir_.CreateUniqueTempDir());
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    quota_manager_ =
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        new MockQuotaManager(false /* is_incognito */,
717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    dir_.path(),
727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    base::MessageLoopProxy::current().get(),
737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    base::MessageLoopProxy::current().get(),
747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    NULL /* special storage policy */);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual_path_ = base::FilePath(FILE_PATH_LITERAL("temporary file"));
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    file_system_context_ = CreateFileSystemContextForTesting(
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        quota_manager_->proxy(), dir_.path());
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    url_request_context_.reset(
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new MockBlobURLRequestContext(file_system_context_.get()));
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    file_system_context_->operation_runner()->CreateFile(
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        URLForPath(virtual_path_), true /* exclusive */,
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(&AssertStatusEq, base::File::FILE_OK));
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    static_cast<TestFileSystemBackend*>(
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        file_system_context_->GetFileSystemBackend(kFileSystemType))
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ->AddFileChangeObserver(change_observer());
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void TearDown() {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    quota_manager_ = NULL;
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    file_system_context_ = NULL;
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error status() const { return status_; }
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error cancel_status() const { return cancel_status_; }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void add_bytes_written(int64 bytes, bool complete) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes_written_ += bytes;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(complete_);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    complete_ = complete;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 bytes_written() const { return bytes_written_; }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool complete() const { return complete_; }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const storage::ChangeObserverList& change_observers() const {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return change_observers_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::MockFileChangeObserver* change_observer() {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &change_observer_;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FileSystemURL URLForPath(const base::FilePath& path) const {
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return file_system_context_->CreateCrackedFileSystemURL(
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        kOrigin, kFileSystemType, path);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback function for recording test results.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileSystemOperation::WriteCallback RecordWriteCallback() {
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return base::Bind(&FileSystemOperationImplWriteTest::DidWrite,
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      weak_factory_.GetWeakPtr());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileSystemOperation::StatusCallback RecordCancelCallback() {
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return base::Bind(&FileSystemOperationImplWriteTest::DidCancel,
129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      weak_factory_.GetWeakPtr());
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void DidWrite(base::File::Error status, int64 bytes, bool complete) {
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (status == base::File::FILE_OK) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      add_bytes_written(bytes, complete);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (complete)
136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        base::MessageLoop::current()->Quit();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(complete_);
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(status_, base::File::FILE_OK);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      complete_ = true;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      status_ = status;
142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (base::MessageLoop::current()->is_running())
143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        base::MessageLoop::current()->Quit();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void DidCancel(base::File::Error status) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cancel_status_ = status;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const MockBlobURLRequestContext& url_request_context() const {
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return *url_request_context_;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<storage::FileSystemContext> file_system_context_;
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<MockQuotaManager> quota_manager_;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::MessageLoopForIO loop_;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir dir_;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath virtual_path_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For post-operation status.
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error status_;
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::File::Error cancel_status_;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 bytes_written_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool complete_;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<MockBlobURLRequestContext> url_request_context_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::MockFileChangeObserver change_observer_;
17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::ChangeObserverList change_observers_;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::WeakPtrFactory<FileSystemOperationImplWriteTest> weak_factory_;
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplWriteTest);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) {
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ScopedTextBlob blob(url_request_context(),
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                      "blob-id:success",
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                      "Hello, world!\n");
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_context_->operation_runner()->Write(
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &url_request_context(), URLForPath(virtual_path_),
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      blob.GetBlobDataHandle(),
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      0, RecordWriteCallback());
187b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->Run();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(14, bytes_written());
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, status());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(complete());
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) {
19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ScopedTextBlob blob(url_request_context(), "blob_id:zero", "");
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_context_->operation_runner()->Write(
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      &url_request_context(), URLForPath(virtual_path_),
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      blob.GetBlobDataHandle(), 0, RecordWriteCallback());
201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->Run();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, bytes_written());
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, status());
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(complete());
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) {
21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_ptr<storage::BlobDataHandle> null_handle;
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_context_->operation_runner()->Write(
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      &url_request_context(), URLForPath(virtual_path_),
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      null_handle.Pass(), 0, RecordWriteCallback());
216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->Run();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, bytes_written());
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_ERROR_FAILED, status());
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(complete());
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidFile) {
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ScopedTextBlob blob(url_request_context(), "blob_id:writeinvalidfile",
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      "It\'ll not be written.");
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_context_->operation_runner()->Write(
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      &url_request_context(),
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))),
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      blob.GetBlobDataHandle(), 0, RecordWriteCallback());
232b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->Run();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, bytes_written());
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(complete());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath virtual_dir_path(FILE_PATH_LITERAL("d"));
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_context_->operation_runner()->CreateDirectory(
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URLForPath(virtual_dir_path),
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true /* exclusive */, false /* recursive */,
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&AssertStatusEq, base::File::FILE_OK));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ScopedTextBlob blob(url_request_context(), "blob:writedir",
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "It\'ll not be written, too.");
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_context_->operation_runner()->Write(
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &url_request_context(), URLForPath(virtual_dir_path),
25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      blob.GetBlobDataHandle(),  0, RecordWriteCallback());
253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->Run();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, bytes_written());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(kinuko): This error code is platform- or fileutil- dependent
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // right now.  Make it return File::FILE_ERROR_NOT_A_FILE in every case.
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(status() == base::File::FILE_ERROR_NOT_A_FILE ||
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              status() == base::File::FILE_ERROR_ACCESS_DENIED ||
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              status() == base::File::FILE_ERROR_FAILED);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(complete());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
266a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) {
26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ScopedTextBlob blob(url_request_context(), "blob:success",
26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                      "Hello, world!\n");
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  quota_manager_->SetQuota(
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      kOrigin, FileSystemTypeToQuotaStorageType(kFileSystemType), 10);
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_context_->operation_runner()->Write(
27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &url_request_context(), URLForPath(virtual_path_),
27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      blob.GetBlobDataHandle(), 0, RecordWriteCallback());
274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::MessageLoop::current()->Run();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(10, bytes_written());
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status());
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(complete());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) {
28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ScopedTextBlob blob(url_request_context(), "blob:success",
28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                      "Hello, world!\n");
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FileSystemOperationRunner::OperationID id =
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      file_system_context_->operation_runner()->Write(
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          &url_request_context(), URLForPath(virtual_path_),
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          blob.GetBlobDataHandle(), 0, RecordWriteCallback());
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We use RunAllPendings() instead of Run() here, because we won't dispatch
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callbacks after Cancel() is issued (so no chance to Quit) nor do we need
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to run another write cycle.
294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Issued Cancel() before receiving any response from Write(),
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so nothing should have happen.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, bytes_written());
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_ERROR_ABORT, status());
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, cancel_status());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(complete());
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelFailingWrite) {
30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ScopedTextBlob blob(url_request_context(), "blob:writeinvalidfile",
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      "It\'ll not be written.");
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FileSystemOperationRunner::OperationID id =
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      file_system_context_->operation_runner()->Write(
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          &url_request_context(),
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))),
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          blob.GetBlobDataHandle(), 0, RecordWriteCallback());
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We use RunAllPendings() instead of Run() here, because we won't dispatch
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callbacks after Cancel() is issued (so no chance to Quit) nor do we need
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to run another write cycle.
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Issued Cancel() before receiving any response from Write(),
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so nothing should have happen.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, bytes_written());
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_ERROR_ABORT, status());
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::File::FILE_OK, cancel_status());
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(complete());
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(ericu,dmikurube,kinuko): Add more tests for cancel cases.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace content
333