IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / fileapi / file_writer_delegate_unittest.cc
blob39ed9d7933bbbc3b33553ecc7a617dbf0478d79f
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 <string>
6 #include <vector>
8 #include "base/basictypes.h"
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "content/public/test/test_file_system_context.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/request_priority.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_status.h"
21 #include "testing/platform_test.h"
22 #include "url/gurl.h"
23 #include "webkit/browser/fileapi/async_file_test_helper.h"
24 #include "webkit/browser/fileapi/file_system_context.h"
25 #include "webkit/browser/fileapi/file_system_quota_util.h"
26 #include "webkit/browser/fileapi/file_writer_delegate.h"
27 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h"
29 namespace fileapi {
31 namespace {
33 const GURL kOrigin("http://example.com");
34 const FileSystemType kFileSystemType = kFileSystemTypeTest;
36 const char kData[] = "The quick brown fox jumps over the lazy dog.\n";
37 const int kDataSize = ARRAYSIZE_UNSAFE(kData) - 1;
39 class Result {
40 public:
41 Result()
42 : status_(base::PLATFORM_FILE_OK),
43 bytes_written_(0),
44 write_status_(FileWriterDelegate::SUCCESS_IO_PENDING) {}
46 base::PlatformFileError status() const { return status_; }
47 int64 bytes_written() const { return bytes_written_; }
48 FileWriterDelegate::WriteProgressStatus write_status() const {
49 return write_status_;
52 void DidWrite(base::PlatformFileError status, int64 bytes,
53 FileWriterDelegate::WriteProgressStatus write_status) {
54 write_status_ = write_status;
55 if (status == base::PLATFORM_FILE_OK) {
56 bytes_written_ += bytes;
57 if (write_status_ != FileWriterDelegate::SUCCESS_IO_PENDING)
58 base::MessageLoop::current()->Quit();
59 } else {
60 EXPECT_EQ(base::PLATFORM_FILE_OK, status_);
61 status_ = status;
62 base::MessageLoop::current()->Quit();
66 private:
67 // For post-operation status.
68 base::PlatformFileError status_;
69 int64 bytes_written_;
70 FileWriterDelegate::WriteProgressStatus write_status_;
73 } // namespace (anonymous)
75 class FileWriterDelegateTest : public PlatformTest {
76 public:
77 FileWriterDelegateTest() {}
79 protected:
80 virtual void SetUp() OVERRIDE;
81 virtual void TearDown() OVERRIDE;
83 int64 usage() {
84 return file_system_context_->GetQuotaUtil(kFileSystemType)
85 ->GetOriginUsageOnFileTaskRunner(
86 file_system_context_.get(), kOrigin, kFileSystemType);
89 int64 GetFileSizeOnDisk(const char* test_file_path) {
90 // There might be in-flight flush/write.
91 base::MessageLoop::current()->PostTask(
92 FROM_HERE, base::Bind(&base::DoNothing));
93 base::RunLoop().RunUntilIdle();
95 FileSystemURL url = GetFileSystemURL(test_file_path);
96 base::PlatformFileInfo file_info;
97 EXPECT_EQ(base::PLATFORM_FILE_OK,
98 AsyncFileTestHelper::GetMetadata(
99 file_system_context_, url, &file_info));
100 return file_info.size;
103 FileSystemURL GetFileSystemURL(const char* file_name) const {
104 return file_system_context_->CreateCrackedFileSystemURL(
105 kOrigin, kFileSystemType, base::FilePath().FromUTF8Unsafe(file_name));
108 FileWriterDelegate* CreateWriterDelegate(
109 const char* test_file_path,
110 int64 offset,
111 int64 allowed_growth) {
112 SandboxFileStreamWriter* writer = new SandboxFileStreamWriter(
113 file_system_context_.get(),
114 GetFileSystemURL(test_file_path),
115 offset,
116 *file_system_context_->GetUpdateObservers(kFileSystemType));
117 writer->set_default_quota(allowed_growth);
118 return new FileWriterDelegate(scoped_ptr<FileStreamWriter>(writer));
121 FileWriterDelegate::DelegateWriteCallback GetWriteCallback(Result* result) {
122 return base::Bind(&Result::DidWrite, base::Unretained(result));
125 // Creates and sets up a FileWriterDelegate for writing the given |blob_url|,
126 // and creates a new FileWriterDelegate for the file.
127 void PrepareForWrite(const char* test_file_path,
128 const GURL& blob_url,
129 int64 offset,
130 int64 allowed_growth) {
131 file_writer_delegate_.reset(
132 CreateWriterDelegate(test_file_path, offset, allowed_growth));
133 request_ = empty_context_.CreateRequest(
134 blob_url, net::DEFAULT_PRIORITY, file_writer_delegate_.get());
137 static net::URLRequest::ProtocolFactory Factory;
139 // This should be alive until the very end of this instance.
140 base::MessageLoopForIO loop_;
142 scoped_refptr<FileSystemContext> file_system_context_;
144 net::URLRequestContext empty_context_;
145 scoped_ptr<FileWriterDelegate> file_writer_delegate_;
146 scoped_ptr<net::URLRequest> request_;
148 base::ScopedTempDir dir_;
150 static const char* content_;
153 const char* FileWriterDelegateTest::content_ = NULL;
155 namespace {
157 static std::string g_content;
159 class FileWriterDelegateTestJob : public net::URLRequestJob {
160 public:
161 FileWriterDelegateTestJob(net::URLRequest* request,
162 net::NetworkDelegate* network_delegate,
163 const std::string& content)
164 : net::URLRequestJob(request, network_delegate),
165 content_(content),
166 remaining_bytes_(content.length()),
167 cursor_(0) {
170 virtual void Start() OVERRIDE {
171 base::MessageLoop::current()->PostTask(
172 FROM_HERE,
173 base::Bind(&FileWriterDelegateTestJob::NotifyHeadersComplete, this));
176 virtual bool ReadRawData(net::IOBuffer* buf,
177 int buf_size,
178 int *bytes_read) OVERRIDE {
179 if (remaining_bytes_ < buf_size)
180 buf_size = static_cast<int>(remaining_bytes_);
182 for (int i = 0; i < buf_size; ++i)
183 buf->data()[i] = content_[cursor_++];
184 remaining_bytes_ -= buf_size;
186 SetStatus(net::URLRequestStatus());
187 *bytes_read = buf_size;
188 return true;
191 virtual int GetResponseCode() const OVERRIDE {
192 return 200;
195 protected:
196 virtual ~FileWriterDelegateTestJob() {}
198 private:
199 std::string content_;
200 int remaining_bytes_;
201 int cursor_;
204 } // namespace (anonymous)
206 // static
207 net::URLRequestJob* FileWriterDelegateTest::Factory(
208 net::URLRequest* request,
209 net::NetworkDelegate* network_delegate,
210 const std::string& scheme) {
211 return new FileWriterDelegateTestJob(
212 request, network_delegate, FileWriterDelegateTest::content_);
215 void FileWriterDelegateTest::SetUp() {
216 ASSERT_TRUE(dir_.CreateUniqueTempDir());
218 file_system_context_ = CreateFileSystemContextForTesting(
219 NULL, dir_.path());
220 ASSERT_EQ(base::PLATFORM_FILE_OK,
221 AsyncFileTestHelper::CreateFile(
222 file_system_context_, GetFileSystemURL("test")));
223 net::URLRequest::Deprecated::RegisterProtocolFactory("blob", &Factory);
226 void FileWriterDelegateTest::TearDown() {
227 net::URLRequest::Deprecated::RegisterProtocolFactory("blob", NULL);
228 file_system_context_ = NULL;
229 base::RunLoop().RunUntilIdle();
232 TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimit) {
233 const GURL kBlobURL("blob:nolimit");
234 content_ = kData;
236 PrepareForWrite("test", kBlobURL, 0, kint64max);
238 Result result;
239 ASSERT_EQ(0, usage());
240 file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
241 base::MessageLoop::current()->Run();
243 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
244 file_writer_delegate_.reset();
246 ASSERT_EQ(kDataSize, usage());
247 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
248 EXPECT_EQ(kDataSize, result.bytes_written());
249 EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
252 TEST_F(FileWriterDelegateTest, WriteSuccessWithJustQuota) {
253 const GURL kBlobURL("blob:just");
254 content_ = kData;
255 const int64 kAllowedGrowth = kDataSize;
256 PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
258 Result result;
259 ASSERT_EQ(0, usage());
260 file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
261 base::MessageLoop::current()->Run();
262 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
263 file_writer_delegate_.reset();
265 ASSERT_EQ(kAllowedGrowth, usage());
266 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
268 EXPECT_EQ(kAllowedGrowth, result.bytes_written());
269 EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
272 TEST_F(FileWriterDelegateTest, DISABLED_WriteFailureByQuota) {
273 const GURL kBlobURL("blob:failure");
274 content_ = kData;
275 const int64 kAllowedGrowth = kDataSize - 1;
276 PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
278 Result result;
279 ASSERT_EQ(0, usage());
280 file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
281 base::MessageLoop::current()->Run();
282 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
283 file_writer_delegate_.reset();
285 ASSERT_EQ(kAllowedGrowth, usage());
286 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
288 EXPECT_EQ(kAllowedGrowth, result.bytes_written());
289 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, result.status());
290 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
293 TEST_F(FileWriterDelegateTest, WriteZeroBytesSuccessfullyWithZeroQuota) {
294 const GURL kBlobURL("blob:zero");
295 content_ = "";
296 int64 kAllowedGrowth = 0;
297 PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
299 Result result;
300 ASSERT_EQ(0, usage());
301 file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
302 base::MessageLoop::current()->Run();
303 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
304 file_writer_delegate_.reset();
306 ASSERT_EQ(kAllowedGrowth, usage());
307 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
309 EXPECT_EQ(kAllowedGrowth, result.bytes_written());
310 EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
311 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
314 TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimitConcurrent) {
315 scoped_ptr<FileWriterDelegate> file_writer_delegate2;
316 scoped_ptr<net::URLRequest> request2;
318 ASSERT_EQ(base::PLATFORM_FILE_OK,
319 AsyncFileTestHelper::CreateFile(
320 file_system_context_, GetFileSystemURL("test2")));
322 const GURL kBlobURL("blob:nolimitconcurrent");
323 const GURL kBlobURL2("blob:nolimitconcurrent2");
324 content_ = kData;
326 PrepareForWrite("test", kBlobURL, 0, kint64max);
328 // Credate another FileWriterDelegate for concurrent write.
329 file_writer_delegate2.reset(CreateWriterDelegate("test2", 0, kint64max));
330 request2 = empty_context_.CreateRequest(
331 kBlobURL2, net::DEFAULT_PRIORITY, file_writer_delegate2.get());
333 Result result, result2;
334 ASSERT_EQ(0, usage());
335 file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
336 file_writer_delegate2->Start(request2.Pass(), GetWriteCallback(&result2));
337 base::MessageLoop::current()->Run();
338 if (result.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING ||
339 result2.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING)
340 base::MessageLoop::current()->Run();
342 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
343 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result2.write_status());
344 file_writer_delegate_.reset();
345 file_writer_delegate2.reset();
347 ASSERT_EQ(kDataSize * 2, usage());
348 EXPECT_EQ(GetFileSizeOnDisk("test") + GetFileSizeOnDisk("test2"), usage());
350 EXPECT_EQ(kDataSize, result.bytes_written());
351 EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
352 EXPECT_EQ(kDataSize, result2.bytes_written());
353 EXPECT_EQ(base::PLATFORM_FILE_OK, result2.status());
356 TEST_F(FileWriterDelegateTest, WritesWithQuotaAndOffset) {
357 const GURL kBlobURL("blob:failure-with-updated-quota");
358 content_ = kData;
360 // Writing kDataSize (=45) bytes data while allowed_growth is 100.
361 int64 offset = 0;
362 int64 allowed_growth = 100;
363 ASSERT_LT(kDataSize, allowed_growth);
364 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
367 Result result;
368 ASSERT_EQ(0, usage());
369 file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
370 base::MessageLoop::current()->Run();
371 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
372 file_writer_delegate_.reset();
374 ASSERT_EQ(kDataSize, usage());
375 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
376 EXPECT_EQ(kDataSize, result.bytes_written());
377 EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
380 // Trying to overwrite kDataSize bytes data while allowed_growth is 20.
381 offset = 0;
382 allowed_growth = 20;
383 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
386 Result result;
387 file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
388 base::MessageLoop::current()->Run();
389 EXPECT_EQ(kDataSize, usage());
390 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
391 EXPECT_EQ(kDataSize, result.bytes_written());
392 EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
393 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
396 // Trying to write kDataSize bytes data from offset 25 while
397 // allowed_growth is 55.
398 offset = 25;
399 allowed_growth = 55;
400 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
403 Result result;
404 file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
405 base::MessageLoop::current()->Run();
406 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
407 file_writer_delegate_.reset();
409 EXPECT_EQ(offset + kDataSize, usage());
410 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
411 EXPECT_EQ(kDataSize, result.bytes_written());
412 EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
415 // Trying to overwrite 45 bytes data while allowed_growth is -20.
416 offset = 0;
417 allowed_growth = -20;
418 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
419 int64 pre_write_usage = GetFileSizeOnDisk("test");
422 Result result;
423 file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
424 base::MessageLoop::current()->Run();
425 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
426 file_writer_delegate_.reset();
428 EXPECT_EQ(pre_write_usage, usage());
429 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
430 EXPECT_EQ(kDataSize, result.bytes_written());
431 EXPECT_EQ(base::PLATFORM_FILE_OK, result.status());
434 // Trying to overwrite 45 bytes data with offset pre_write_usage - 20,
435 // while allowed_growth is 10.
436 const int kOverlap = 20;
437 offset = pre_write_usage - kOverlap;
438 allowed_growth = 10;
439 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
442 Result result;
443 file_writer_delegate_->Start(request_.Pass(), GetWriteCallback(&result));
444 base::MessageLoop::current()->Run();
445 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
446 file_writer_delegate_.reset();
448 EXPECT_EQ(pre_write_usage + allowed_growth, usage());
449 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
450 EXPECT_EQ(kOverlap + allowed_growth, result.bytes_written());
451 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, result.status());
455 } // namespace fileapi