IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / fileapi / file_system_operation_impl_write_unittest.cc
bloba92288af0fded445b0674a1f8eeb8f5831b0c606
1 // Copyright 2013 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.
5 #include <vector>
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/run_loop.h"
12 #include "content/public/test/test_file_system_backend.h"
13 #include "content/public/test/test_file_system_context.h"
14 #include "net/url_request/url_request.h"
15 #include "net/url_request/url_request_context.h"
16 #include "net/url_request/url_request_job.h"
17 #include "net/url_request/url_request_job_factory_impl.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "url/gurl.h"
20 #include "webkit/browser/blob/blob_storage_context.h"
21 #include "webkit/browser/blob/blob_url_request_job.h"
22 #include "webkit/browser/blob/mock_blob_url_request_context.h"
23 #include "webkit/browser/fileapi/file_system_context.h"
24 #include "webkit/browser/fileapi/file_system_file_util.h"
25 #include "webkit/browser/fileapi/file_system_operation_context.h"
26 #include "webkit/browser/fileapi/file_system_operation_runner.h"
27 #include "webkit/browser/fileapi/local_file_util.h"
28 #include "webkit/browser/fileapi/mock_file_change_observer.h"
29 #include "webkit/browser/quota/mock_quota_manager.h"
30 #include "webkit/common/blob/blob_data.h"
31 #include "webkit/common/fileapi/file_system_util.h"
33 using webkit_blob::MockBlobURLRequestContext;
34 using webkit_blob::ScopedTextBlob;
36 namespace fileapi {
38 namespace {
40 const GURL kOrigin("http://example.com");
41 const FileSystemType kFileSystemType = kFileSystemTypeTest;
43 void AssertStatusEq(base::PlatformFileError expected,
44 base::PlatformFileError actual) {
45 ASSERT_EQ(expected, actual);
48 } // namespace
50 class FileSystemOperationImplWriteTest
51 : public testing::Test {
52 public:
53 FileSystemOperationImplWriteTest()
54 : status_(base::PLATFORM_FILE_OK),
55 cancel_status_(base::PLATFORM_FILE_ERROR_FAILED),
56 bytes_written_(0),
57 complete_(false),
58 weak_factory_(this) {
59 change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
62 virtual void SetUp() {
63 ASSERT_TRUE(dir_.CreateUniqueTempDir());
65 quota_manager_ =
66 new quota::MockQuotaManager(false /* is_incognito */,
67 dir_.path(),
68 base::MessageLoopProxy::current().get(),
69 base::MessageLoopProxy::current().get(),
70 NULL /* special storage policy */);
71 virtual_path_ = base::FilePath(FILE_PATH_LITERAL("temporary file"));
73 file_system_context_ = CreateFileSystemContextForTesting(
74 quota_manager_->proxy(), dir_.path());
75 url_request_context_.reset(
76 new MockBlobURLRequestContext(file_system_context_.get()));
78 file_system_context_->operation_runner()->CreateFile(
79 URLForPath(virtual_path_), true /* exclusive */,
80 base::Bind(&AssertStatusEq, base::PLATFORM_FILE_OK));
82 static_cast<TestFileSystemBackend*>(
83 file_system_context_->GetFileSystemBackend(kFileSystemType))
84 ->AddFileChangeObserver(change_observer());
87 virtual void TearDown() {
88 quota_manager_ = NULL;
89 file_system_context_ = NULL;
90 base::RunLoop().RunUntilIdle();
93 base::PlatformFileError status() const { return status_; }
94 base::PlatformFileError cancel_status() const { return cancel_status_; }
95 void add_bytes_written(int64 bytes, bool complete) {
96 bytes_written_ += bytes;
97 EXPECT_FALSE(complete_);
98 complete_ = complete;
100 int64 bytes_written() const { return bytes_written_; }
101 bool complete() const { return complete_; }
103 protected:
104 const ChangeObserverList& change_observers() const {
105 return change_observers_;
108 MockFileChangeObserver* change_observer() {
109 return &change_observer_;
112 FileSystemURL URLForPath(const base::FilePath& path) const {
113 return file_system_context_->CreateCrackedFileSystemURL(
114 kOrigin, kFileSystemType, path);
117 // Callback function for recording test results.
118 FileSystemOperation::WriteCallback RecordWriteCallback() {
119 return base::Bind(&FileSystemOperationImplWriteTest::DidWrite,
120 weak_factory_.GetWeakPtr());
123 FileSystemOperation::StatusCallback RecordCancelCallback() {
124 return base::Bind(&FileSystemOperationImplWriteTest::DidCancel,
125 weak_factory_.GetWeakPtr());
128 void DidWrite(base::PlatformFileError status, int64 bytes, bool complete) {
129 if (status == base::PLATFORM_FILE_OK) {
130 add_bytes_written(bytes, complete);
131 if (complete)
132 base::MessageLoop::current()->Quit();
133 } else {
134 EXPECT_FALSE(complete_);
135 EXPECT_EQ(status_, base::PLATFORM_FILE_OK);
136 complete_ = true;
137 status_ = status;
138 if (base::MessageLoop::current()->is_running())
139 base::MessageLoop::current()->Quit();
143 void DidCancel(base::PlatformFileError status) {
144 cancel_status_ = status;
147 const MockBlobURLRequestContext& url_request_context() const {
148 return *url_request_context_;
151 scoped_refptr<FileSystemContext> file_system_context_;
152 scoped_refptr<quota::MockQuotaManager> quota_manager_;
154 base::MessageLoopForIO loop_;
156 base::ScopedTempDir dir_;
157 base::FilePath virtual_path_;
159 // For post-operation status.
160 base::PlatformFileError status_;
161 base::PlatformFileError cancel_status_;
162 int64 bytes_written_;
163 bool complete_;
165 scoped_ptr<MockBlobURLRequestContext> url_request_context_;
167 MockFileChangeObserver change_observer_;
168 ChangeObserverList change_observers_;
170 base::WeakPtrFactory<FileSystemOperationImplWriteTest> weak_factory_;
172 DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplWriteTest);
175 TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) {
176 ScopedTextBlob blob(url_request_context(),
177 "blob-id:success",
178 "Hello, world!\n");
179 file_system_context_->operation_runner()->Write(
180 &url_request_context(), URLForPath(virtual_path_),
181 blob.GetBlobDataHandle(),
182 0, RecordWriteCallback());
183 base::MessageLoop::current()->Run();
185 EXPECT_EQ(14, bytes_written());
186 EXPECT_EQ(base::PLATFORM_FILE_OK, status());
187 EXPECT_TRUE(complete());
189 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
192 TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) {
193 ScopedTextBlob blob(url_request_context(), "blob_id:zero", "");
194 file_system_context_->operation_runner()->Write(
195 &url_request_context(), URLForPath(virtual_path_),
196 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
197 base::MessageLoop::current()->Run();
199 EXPECT_EQ(0, bytes_written());
200 EXPECT_EQ(base::PLATFORM_FILE_OK, status());
201 EXPECT_TRUE(complete());
203 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
207 TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) {
208 scoped_ptr<webkit_blob::BlobDataHandle> null_handle;
209 file_system_context_->operation_runner()->Write(
210 &url_request_context(), URLForPath(virtual_path_),
211 null_handle.Pass(), 0, RecordWriteCallback());
212 base::MessageLoop::current()->Run();
214 EXPECT_EQ(0, bytes_written());
215 EXPECT_EQ(base::PLATFORM_FILE_ERROR_FAILED, status());
216 EXPECT_TRUE(complete());
218 EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
221 TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidFile) {
222 ScopedTextBlob blob(url_request_context(), "blob_id:writeinvalidfile",
223 "It\'ll not be written.");
224 file_system_context_->operation_runner()->Write(
225 &url_request_context(),
226 URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))),
227 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
228 base::MessageLoop::current()->Run();
230 EXPECT_EQ(0, bytes_written());
231 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
232 EXPECT_TRUE(complete());
234 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
237 TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) {
238 base::FilePath virtual_dir_path(FILE_PATH_LITERAL("d"));
239 file_system_context_->operation_runner()->CreateDirectory(
240 URLForPath(virtual_dir_path),
241 true /* exclusive */, false /* recursive */,
242 base::Bind(&AssertStatusEq, base::PLATFORM_FILE_OK));
244 ScopedTextBlob blob(url_request_context(), "blob:writedir",
245 "It\'ll not be written, too.");
246 file_system_context_->operation_runner()->Write(
247 &url_request_context(), URLForPath(virtual_dir_path),
248 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
249 base::MessageLoop::current()->Run();
251 EXPECT_EQ(0, bytes_written());
252 // TODO(kinuko): This error code is platform- or fileutil- dependent
253 // right now. Make it return PLATFORM_FILE_ERROR_NOT_A_FILE in every case.
254 EXPECT_TRUE(status() == base::PLATFORM_FILE_ERROR_NOT_A_FILE ||
255 status() == base::PLATFORM_FILE_ERROR_ACCESS_DENIED ||
256 status() == base::PLATFORM_FILE_ERROR_FAILED);
257 EXPECT_TRUE(complete());
259 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
262 TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) {
263 ScopedTextBlob blob(url_request_context(), "blob:success",
264 "Hello, world!\n");
265 quota_manager_->SetQuota(
266 kOrigin, FileSystemTypeToQuotaStorageType(kFileSystemType), 10);
267 file_system_context_->operation_runner()->Write(
268 &url_request_context(), URLForPath(virtual_path_),
269 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
270 base::MessageLoop::current()->Run();
272 EXPECT_EQ(10, bytes_written());
273 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status());
274 EXPECT_TRUE(complete());
276 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
279 TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) {
280 ScopedTextBlob blob(url_request_context(), "blob:success",
281 "Hello, world!\n");
282 FileSystemOperationRunner::OperationID id =
283 file_system_context_->operation_runner()->Write(
284 &url_request_context(), URLForPath(virtual_path_),
285 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
286 file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
287 // We use RunAllPendings() instead of Run() here, because we won't dispatch
288 // callbacks after Cancel() is issued (so no chance to Quit) nor do we need
289 // to run another write cycle.
290 base::RunLoop().RunUntilIdle();
292 // Issued Cancel() before receiving any response from Write(),
293 // so nothing should have happen.
294 EXPECT_EQ(0, bytes_written());
295 EXPECT_EQ(base::PLATFORM_FILE_ERROR_ABORT, status());
296 EXPECT_EQ(base::PLATFORM_FILE_OK, cancel_status());
297 EXPECT_TRUE(complete());
299 EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
302 TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelFailingWrite) {
303 ScopedTextBlob blob(url_request_context(), "blob:writeinvalidfile",
304 "It\'ll not be written.");
305 FileSystemOperationRunner::OperationID id =
306 file_system_context_->operation_runner()->Write(
307 &url_request_context(),
308 URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))),
309 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
310 file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
311 // We use RunAllPendings() instead of Run() here, because we won't dispatch
312 // callbacks after Cancel() is issued (so no chance to Quit) nor do we need
313 // to run another write cycle.
314 base::RunLoop().RunUntilIdle();
316 // Issued Cancel() before receiving any response from Write(),
317 // so nothing should have happen.
318 EXPECT_EQ(0, bytes_written());
319 EXPECT_EQ(base::PLATFORM_FILE_ERROR_ABORT, status());
320 EXPECT_EQ(base::PLATFORM_FILE_OK, cancel_status());
321 EXPECT_TRUE(complete());
323 EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
326 // TODO(ericu,dmikurube,kinuko): Add more tests for cancel cases.
328 } // namespace fileapi