[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / fileapi / file_system_operation_impl_write_unittest.cc
blobae3277fc2c86ffb41e2558467c625b33a028fea4
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/run_loop.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "content/browser/fileapi/mock_file_change_observer.h"
13 #include "content/browser/quota/mock_quota_manager.h"
14 #include "content/public/test/mock_blob_url_request_context.h"
15 #include "content/public/test/test_file_system_backend.h"
16 #include "content/public/test/test_file_system_context.h"
17 #include "net/url_request/url_request.h"
18 #include "net/url_request/url_request_context.h"
19 #include "net/url_request/url_request_job.h"
20 #include "net/url_request/url_request_job_factory_impl.h"
21 #include "storage/browser/blob/blob_storage_context.h"
22 #include "storage/browser/blob/blob_url_request_job.h"
23 #include "storage/browser/fileapi/file_system_context.h"
24 #include "storage/browser/fileapi/file_system_file_util.h"
25 #include "storage/browser/fileapi/file_system_operation_context.h"
26 #include "storage/browser/fileapi/file_system_operation_runner.h"
27 #include "storage/browser/fileapi/local_file_util.h"
28 #include "storage/common/fileapi/file_system_util.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "url/gurl.h"
32 using storage::FileSystemOperation;
33 using storage::FileSystemOperationRunner;
34 using storage::FileSystemURL;
35 using content::MockBlobURLRequestContext;
36 using content::ScopedTextBlob;
38 namespace content {
40 namespace {
42 const GURL kOrigin("http://example.com");
43 const storage::FileSystemType kFileSystemType = storage::kFileSystemTypeTest;
45 void AssertStatusEq(base::File::Error expected,
46 base::File::Error actual) {
47 ASSERT_EQ(expected, actual);
50 } // namespace
52 class FileSystemOperationImplWriteTest
53 : public testing::Test {
54 public:
55 FileSystemOperationImplWriteTest()
56 : status_(base::File::FILE_OK),
57 cancel_status_(base::File::FILE_ERROR_FAILED),
58 bytes_written_(0),
59 complete_(false),
60 weak_factory_(this) {
61 change_observers_ =
62 storage::MockFileChangeObserver::CreateList(&change_observer_);
65 void SetUp() override {
66 ASSERT_TRUE(dir_.CreateUniqueTempDir());
68 quota_manager_ =
69 new MockQuotaManager(false /* is_incognito */, dir_.path(),
70 base::ThreadTaskRunnerHandle::Get().get(),
71 base::ThreadTaskRunnerHandle::Get().get(),
72 NULL /* special storage policy */);
73 virtual_path_ = base::FilePath(FILE_PATH_LITERAL("temporary file"));
75 file_system_context_ = CreateFileSystemContextForTesting(
76 quota_manager_->proxy(), dir_.path());
77 url_request_context_.reset(
78 new MockBlobURLRequestContext(file_system_context_.get()));
80 file_system_context_->operation_runner()->CreateFile(
81 URLForPath(virtual_path_), true /* exclusive */,
82 base::Bind(&AssertStatusEq, base::File::FILE_OK));
84 static_cast<TestFileSystemBackend*>(
85 file_system_context_->GetFileSystemBackend(kFileSystemType))
86 ->AddFileChangeObserver(change_observer());
89 void TearDown() override {
90 quota_manager_ = NULL;
91 file_system_context_ = NULL;
92 base::RunLoop().RunUntilIdle();
95 base::File::Error status() const { return status_; }
96 base::File::Error cancel_status() const { return cancel_status_; }
97 void add_bytes_written(int64 bytes, bool complete) {
98 bytes_written_ += bytes;
99 EXPECT_FALSE(complete_);
100 complete_ = complete;
102 int64 bytes_written() const { return bytes_written_; }
103 bool complete() const { return complete_; }
105 protected:
106 const storage::ChangeObserverList& change_observers() const {
107 return change_observers_;
110 storage::MockFileChangeObserver* change_observer() {
111 return &change_observer_;
114 FileSystemURL URLForPath(const base::FilePath& path) const {
115 return file_system_context_->CreateCrackedFileSystemURL(
116 kOrigin, kFileSystemType, path);
119 // Callback function for recording test results.
120 FileSystemOperation::WriteCallback RecordWriteCallback() {
121 return base::Bind(&FileSystemOperationImplWriteTest::DidWrite,
122 weak_factory_.GetWeakPtr());
125 FileSystemOperation::StatusCallback RecordCancelCallback() {
126 return base::Bind(&FileSystemOperationImplWriteTest::DidCancel,
127 weak_factory_.GetWeakPtr());
130 void DidWrite(base::File::Error status, int64 bytes, bool complete) {
131 if (status == base::File::FILE_OK) {
132 add_bytes_written(bytes, complete);
133 if (complete)
134 base::MessageLoop::current()->Quit();
135 } else {
136 EXPECT_FALSE(complete_);
137 EXPECT_EQ(status_, base::File::FILE_OK);
138 complete_ = true;
139 status_ = status;
140 if (base::MessageLoop::current()->is_running())
141 base::MessageLoop::current()->Quit();
145 void DidCancel(base::File::Error status) {
146 cancel_status_ = status;
149 const MockBlobURLRequestContext& url_request_context() const {
150 return *url_request_context_;
153 scoped_refptr<storage::FileSystemContext> file_system_context_;
154 scoped_refptr<MockQuotaManager> quota_manager_;
156 base::MessageLoopForIO loop_;
158 base::ScopedTempDir dir_;
159 base::FilePath virtual_path_;
161 // For post-operation status.
162 base::File::Error status_;
163 base::File::Error cancel_status_;
164 int64 bytes_written_;
165 bool complete_;
167 scoped_ptr<MockBlobURLRequestContext> url_request_context_;
169 storage::MockFileChangeObserver change_observer_;
170 storage::ChangeObserverList change_observers_;
172 base::WeakPtrFactory<FileSystemOperationImplWriteTest> weak_factory_;
174 DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplWriteTest);
177 TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) {
178 ScopedTextBlob blob(url_request_context(),
179 "blob-id:success",
180 "Hello, world!\n");
181 file_system_context_->operation_runner()->Write(
182 &url_request_context(), URLForPath(virtual_path_),
183 blob.GetBlobDataHandle(),
184 0, RecordWriteCallback());
185 base::MessageLoop::current()->Run();
187 EXPECT_EQ(14, bytes_written());
188 EXPECT_EQ(base::File::FILE_OK, status());
189 EXPECT_TRUE(complete());
191 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
194 TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) {
195 ScopedTextBlob blob(url_request_context(), "blob_id:zero", "");
196 file_system_context_->operation_runner()->Write(
197 &url_request_context(), URLForPath(virtual_path_),
198 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
199 base::MessageLoop::current()->Run();
201 EXPECT_EQ(0, bytes_written());
202 EXPECT_EQ(base::File::FILE_OK, status());
203 EXPECT_TRUE(complete());
205 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
209 TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) {
210 scoped_ptr<storage::BlobDataHandle> null_handle;
211 file_system_context_->operation_runner()->Write(
212 &url_request_context(), URLForPath(virtual_path_),
213 null_handle.Pass(), 0, RecordWriteCallback());
214 base::MessageLoop::current()->Run();
216 EXPECT_EQ(0, bytes_written());
217 EXPECT_EQ(base::File::FILE_ERROR_FAILED, status());
218 EXPECT_TRUE(complete());
220 EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
223 TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidFile) {
224 ScopedTextBlob blob(url_request_context(), "blob_id:writeinvalidfile",
225 "It\'ll not be written.");
226 file_system_context_->operation_runner()->Write(
227 &url_request_context(),
228 URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))),
229 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
230 base::MessageLoop::current()->Run();
232 EXPECT_EQ(0, bytes_written());
233 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
234 EXPECT_TRUE(complete());
236 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
239 TEST_F(FileSystemOperationImplWriteTest, TestWriteDir) {
240 base::FilePath virtual_dir_path(FILE_PATH_LITERAL("d"));
241 file_system_context_->operation_runner()->CreateDirectory(
242 URLForPath(virtual_dir_path),
243 true /* exclusive */, false /* recursive */,
244 base::Bind(&AssertStatusEq, base::File::FILE_OK));
246 ScopedTextBlob blob(url_request_context(), "blob:writedir",
247 "It\'ll not be written, too.");
248 file_system_context_->operation_runner()->Write(
249 &url_request_context(), URLForPath(virtual_dir_path),
250 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
251 base::MessageLoop::current()->Run();
253 EXPECT_EQ(0, bytes_written());
254 // TODO(kinuko): This error code is platform- or fileutil- dependent
255 // right now. Make it return File::FILE_ERROR_NOT_A_FILE in every case.
256 EXPECT_TRUE(status() == base::File::FILE_ERROR_NOT_A_FILE ||
257 status() == base::File::FILE_ERROR_ACCESS_DENIED ||
258 status() == base::File::FILE_ERROR_FAILED);
259 EXPECT_TRUE(complete());
261 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
264 TEST_F(FileSystemOperationImplWriteTest, TestWriteFailureByQuota) {
265 ScopedTextBlob blob(url_request_context(), "blob:success",
266 "Hello, world!\n");
267 quota_manager_->SetQuota(
268 kOrigin, FileSystemTypeToQuotaStorageType(kFileSystemType), 10);
269 file_system_context_->operation_runner()->Write(
270 &url_request_context(), URLForPath(virtual_path_),
271 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
272 base::MessageLoop::current()->Run();
274 EXPECT_EQ(10, bytes_written());
275 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status());
276 EXPECT_TRUE(complete());
278 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
281 TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) {
282 ScopedTextBlob blob(url_request_context(), "blob:success",
283 "Hello, world!\n");
284 FileSystemOperationRunner::OperationID id =
285 file_system_context_->operation_runner()->Write(
286 &url_request_context(), URLForPath(virtual_path_),
287 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
288 file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
289 // We use RunAllPendings() instead of Run() here, because we won't dispatch
290 // callbacks after Cancel() is issued (so no chance to Quit) nor do we need
291 // to run another write cycle.
292 base::RunLoop().RunUntilIdle();
294 // Issued Cancel() before receiving any response from Write(),
295 // so nothing should have happen.
296 EXPECT_EQ(0, bytes_written());
297 EXPECT_EQ(base::File::FILE_ERROR_ABORT, status());
298 EXPECT_EQ(base::File::FILE_OK, cancel_status());
299 EXPECT_TRUE(complete());
301 EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
304 TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelFailingWrite) {
305 ScopedTextBlob blob(url_request_context(), "blob:writeinvalidfile",
306 "It\'ll not be written.");
307 FileSystemOperationRunner::OperationID id =
308 file_system_context_->operation_runner()->Write(
309 &url_request_context(),
310 URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))),
311 blob.GetBlobDataHandle(), 0, RecordWriteCallback());
312 file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
313 // We use RunAllPendings() instead of Run() here, because we won't dispatch
314 // callbacks after Cancel() is issued (so no chance to Quit) nor do we need
315 // to run another write cycle.
316 base::RunLoop().RunUntilIdle();
318 // Issued Cancel() before receiving any response from Write(),
319 // so nothing should have happen.
320 EXPECT_EQ(0, bytes_written());
321 EXPECT_EQ(base::File::FILE_ERROR_ABORT, status());
322 EXPECT_EQ(base::File::FILE_OK, cancel_status());
323 EXPECT_TRUE(complete());
325 EXPECT_EQ(0, change_observer()->get_and_reset_modify_file_count());
328 // TODO(ericu,dmikurube,kinuko): Add more tests for cancel cases.
330 } // namespace content