Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / webkit / fileapi / file_writer_delegate_unittest.cc
blob887ec56564b65bed579636a01b208382be5e1ed8
1 // Copyright (c) 2012 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/files/scoped_temp_dir.h"
11 #include "base/message_loop.h"
12 #include "googleurl/src/gurl.h"
13 #include "net/base/io_buffer.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_status.h"
18 #include "testing/platform_test.h"
19 #include "webkit/fileapi/file_system_context.h"
20 #include "webkit/fileapi/file_system_file_util.h"
21 #include "webkit/fileapi/file_system_operation_context.h"
22 #include "webkit/fileapi/file_writer_delegate.h"
23 #include "webkit/fileapi/local_file_system_operation.h"
24 #include "webkit/fileapi/local_file_system_test_helper.h"
25 #include "webkit/fileapi/sandbox_file_stream_writer.h"
26 #include "webkit/quota/quota_manager.h"
28 namespace fileapi {
30 namespace {
32 class Result {
33 public:
34 Result()
35 : status_(base::PLATFORM_FILE_OK),
36 bytes_written_(0),
37 write_status_(FileWriterDelegate::SUCCESS_IO_PENDING) {}
39 base::PlatformFileError status() const { return status_; }
40 int64 bytes_written() const { return bytes_written_; }
41 FileWriterDelegate::WriteProgressStatus write_status() const {
42 return write_status_;
45 void DidWrite(base::PlatformFileError status, int64 bytes,
46 FileWriterDelegate::WriteProgressStatus write_status) {
47 write_status_ = write_status;
48 if (status == base::PLATFORM_FILE_OK) {
49 bytes_written_ += bytes;
50 if (write_status_ != FileWriterDelegate::SUCCESS_IO_PENDING)
51 MessageLoop::current()->Quit();
52 } else {
53 EXPECT_EQ(base::PLATFORM_FILE_OK, status_);
54 status_ = status;
55 MessageLoop::current()->Quit();
59 private:
60 // For post-operation status.
61 base::PlatformFileError status_;
62 int64 bytes_written_;
63 FileWriterDelegate::WriteProgressStatus write_status_;
66 const char kData[] = "The quick brown fox jumps over the lazy dog.\n";
67 const int kDataSize = ARRAYSIZE_UNSAFE(kData) - 1;
69 } // namespace (anonymous)
71 class FileWriterDelegateTest : public PlatformTest {
72 public:
73 FileWriterDelegateTest()
74 : loop_(MessageLoop::TYPE_IO),
75 test_helper_(GURL("http://example.com"), kFileSystemTypeTest) {}
77 protected:
78 virtual void SetUp() OVERRIDE;
79 virtual void TearDown() OVERRIDE;
81 FileSystemFileUtil* file_util() {
82 return test_helper_.file_util();
85 int64 ComputeCurrentOriginUsage() {
86 return test_helper_.ComputeCurrentOriginUsage();
89 FileSystemURL GetFileSystemURL(const char* file_name) const {
90 return test_helper_.CreateURLFromUTF8(file_name);
93 FileWriterDelegate* CreateWriterDelegate(
94 const char* test_file_path,
95 int64 offset,
96 int64 allowed_growth,
97 Result* result) {
98 SandboxFileStreamWriter* writer = new SandboxFileStreamWriter(
99 test_helper_.file_system_context(),
100 GetFileSystemURL(test_file_path),
101 offset,
102 *test_helper_.file_system_context()->GetUpdateObservers(
103 test_helper_.type()));
104 writer->set_default_quota(allowed_growth);
105 return new FileWriterDelegate(
106 base::Bind(&Result::DidWrite, base::Unretained(result)),
107 scoped_ptr<FileStreamWriter>(writer));
110 // Creates and sets up a FileWriterDelegate for writing the given |blob_url|,
111 // and creates a new FileWriterDelegate for the file.
112 void PrepareForWrite(const GURL& blob_url,
113 int64 offset,
114 int64 allowed_growth) {
115 result_.reset(new Result());
116 file_writer_delegate_.reset(
117 CreateWriterDelegate("test", offset, allowed_growth, result_.get()));
118 request_.reset(empty_context_.CreateRequest(
119 blob_url, file_writer_delegate_.get()));
122 static net::URLRequest::ProtocolFactory Factory;
124 // This should be alive until the very end of this instance.
125 MessageLoop loop_;
127 net::URLRequestContext empty_context_;
128 scoped_ptr<FileWriterDelegate> file_writer_delegate_;
129 scoped_ptr<net::URLRequest> request_;
130 scoped_ptr<Result> result_;
131 LocalFileSystemTestOriginHelper test_helper_;
133 base::ScopedTempDir dir_;
135 static const char* content_;
138 const char* FileWriterDelegateTest::content_ = NULL;
140 namespace {
142 static std::string g_content;
144 class FileWriterDelegateTestJob : public net::URLRequestJob {
145 public:
146 FileWriterDelegateTestJob(net::URLRequest* request,
147 net::NetworkDelegate* network_delegate,
148 const std::string& content)
149 : net::URLRequestJob(request, network_delegate),
150 content_(content),
151 remaining_bytes_(content.length()),
152 cursor_(0) {
155 virtual void Start() OVERRIDE {
156 MessageLoop::current()->PostTask(
157 FROM_HERE,
158 base::Bind(&FileWriterDelegateTestJob::NotifyHeadersComplete, this));
161 virtual bool ReadRawData(net::IOBuffer* buf,
162 int buf_size,
163 int *bytes_read) OVERRIDE {
164 if (remaining_bytes_ < buf_size)
165 buf_size = static_cast<int>(remaining_bytes_);
167 for (int i = 0; i < buf_size; ++i)
168 buf->data()[i] = content_[cursor_++];
169 remaining_bytes_ -= buf_size;
171 SetStatus(net::URLRequestStatus());
172 *bytes_read = buf_size;
173 return true;
176 virtual int GetResponseCode() const OVERRIDE {
177 return 200;
180 protected:
181 virtual ~FileWriterDelegateTestJob() {}
183 private:
184 std::string content_;
185 int remaining_bytes_;
186 int cursor_;
189 } // namespace (anonymous)
191 // static
192 net::URLRequestJob* FileWriterDelegateTest::Factory(
193 net::URLRequest* request,
194 net::NetworkDelegate* network_delegate,
195 const std::string& scheme) {
196 return new FileWriterDelegateTestJob(
197 request, network_delegate, FileWriterDelegateTest::content_);
200 void FileWriterDelegateTest::SetUp() {
201 ASSERT_TRUE(dir_.CreateUniqueTempDir());
202 base::FilePath base_dir = dir_.path().AppendASCII("filesystem");
203 test_helper_.SetUp(base_dir);
205 scoped_ptr<FileSystemOperationContext> context(
206 test_helper_.NewOperationContext());
207 context->set_allowed_bytes_growth(kint64max);
208 bool created = false;
209 base::PlatformFileError error = file_util()->EnsureFileExists(
210 context.get(),
211 GetFileSystemURL("test"),
212 &created);
213 ASSERT_EQ(base::PLATFORM_FILE_OK, error);
214 ASSERT_TRUE(created);
215 net::URLRequest::Deprecated::RegisterProtocolFactory("blob", &Factory);
218 void FileWriterDelegateTest::TearDown() {
219 net::URLRequest::Deprecated::RegisterProtocolFactory("blob", NULL);
220 test_helper_.TearDown();
223 // FileWriterDelegateTest.WriteSuccessWithoutQuotaLimit is flaky on windows
224 // http://crbug.com/130401
225 #if defined(OS_WIN)
226 #define MAYBE_WriteSuccessWithoutQuotaLimit \
227 DISABLED_WriteSuccessWithoutQuotaLimit
228 #else
229 #define MAYBE_WriteSuccessWithoutQuotaLimit \
230 WriteSuccessWithoutQuotaLimit
231 #endif
232 TEST_F(FileWriterDelegateTest, MAYBE_WriteSuccessWithoutQuotaLimit) {
233 const GURL kBlobURL("blob:nolimit");
234 content_ = kData;
236 PrepareForWrite(kBlobURL, 0, quota::QuotaManager::kNoLimit);
238 ASSERT_EQ(0, test_helper_.GetCachedOriginUsage());
239 file_writer_delegate_->Start(request_.Pass());
240 MessageLoop::current()->Run();
242 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result_->write_status());
243 file_writer_delegate_.reset();
245 ASSERT_EQ(kDataSize, test_helper_.GetCachedOriginUsage());
246 EXPECT_EQ(ComputeCurrentOriginUsage(), test_helper_.GetCachedOriginUsage());
247 EXPECT_EQ(kDataSize, result_->bytes_written());
248 EXPECT_EQ(base::PLATFORM_FILE_OK, result_->status());
251 // FileWriterDelegateTest.WriteSuccessWithJustQuota is flaky on windows
252 // http://crbug.com/130401
253 #if defined(OS_WIN)
254 #define MAYBE_WriteSuccessWithJustQuota DISABLED_WriteSuccessWithJustQuota
255 #else
256 #define MAYBE_WriteSuccessWithJustQuota WriteSuccessWithJustQuota
257 #endif
259 TEST_F(FileWriterDelegateTest, MAYBE_WriteSuccessWithJustQuota) {
260 const GURL kBlobURL("blob:just");
261 content_ = kData;
262 const int64 kAllowedGrowth = kDataSize;
263 PrepareForWrite(kBlobURL, 0, kAllowedGrowth);
265 ASSERT_EQ(0, test_helper_.GetCachedOriginUsage());
266 file_writer_delegate_->Start(request_.Pass());
267 MessageLoop::current()->Run();
268 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result_->write_status());
269 file_writer_delegate_.reset();
271 ASSERT_EQ(kAllowedGrowth, test_helper_.GetCachedOriginUsage());
272 EXPECT_EQ(ComputeCurrentOriginUsage(), test_helper_.GetCachedOriginUsage());
274 EXPECT_EQ(kAllowedGrowth, result_->bytes_written());
275 EXPECT_EQ(base::PLATFORM_FILE_OK, result_->status());
278 TEST_F(FileWriterDelegateTest, DISABLED_WriteFailureByQuota) {
279 const GURL kBlobURL("blob:failure");
280 content_ = kData;
281 const int64 kAllowedGrowth = kDataSize - 1;
282 PrepareForWrite(kBlobURL, 0, kAllowedGrowth);
284 ASSERT_EQ(0, test_helper_.GetCachedOriginUsage());
285 file_writer_delegate_->Start(request_.Pass());
286 MessageLoop::current()->Run();
287 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result_->write_status());
288 file_writer_delegate_.reset();
290 ASSERT_EQ(kAllowedGrowth, test_helper_.GetCachedOriginUsage());
291 EXPECT_EQ(ComputeCurrentOriginUsage(), test_helper_.GetCachedOriginUsage());
293 EXPECT_EQ(kAllowedGrowth, result_->bytes_written());
294 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, result_->status());
295 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result_->write_status());
298 TEST_F(FileWriterDelegateTest, WriteZeroBytesSuccessfullyWithZeroQuota) {
299 const GURL kBlobURL("blob:zero");
300 content_ = "";
301 int64 kAllowedGrowth = 0;
302 PrepareForWrite(kBlobURL, 0, kAllowedGrowth);
304 ASSERT_EQ(0, test_helper_.GetCachedOriginUsage());
305 file_writer_delegate_->Start(request_.Pass());
306 MessageLoop::current()->Run();
307 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result_->write_status());
308 file_writer_delegate_.reset();
310 ASSERT_EQ(kAllowedGrowth, test_helper_.GetCachedOriginUsage());
311 EXPECT_EQ(ComputeCurrentOriginUsage(), test_helper_.GetCachedOriginUsage());
313 EXPECT_EQ(kAllowedGrowth, result_->bytes_written());
314 EXPECT_EQ(base::PLATFORM_FILE_OK, result_->status());
315 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result_->write_status());
318 #if defined(OS_WIN)
319 // See http://crbug.com/129264
320 #define MAYBE_WriteSuccessWithoutQuotaLimitConcurrent \
321 DISABLED_WriteSuccessWithoutQuotaLimitConcurrent
322 #else
323 #define MAYBE_WriteSuccessWithoutQuotaLimitConcurrent \
324 WriteSuccessWithoutQuotaLimitConcurrent
325 #endif
327 TEST_F(FileWriterDelegateTest, MAYBE_WriteSuccessWithoutQuotaLimitConcurrent) {
328 scoped_ptr<FileWriterDelegate> file_writer_delegate2;
329 scoped_ptr<net::URLRequest> request2;
330 scoped_ptr<Result> result2;
332 scoped_ptr<FileSystemOperationContext> context(
333 test_helper_.NewOperationContext());
334 bool created = false;
335 file_util()->EnsureFileExists(context.get(),
336 GetFileSystemURL("test2"),
337 &created);
338 ASSERT_TRUE(created);
340 const GURL kBlobURL("blob:nolimitconcurrent");
341 const GURL kBlobURL2("blob:nolimitconcurrent2");
342 content_ = kData;
344 PrepareForWrite(kBlobURL, 0, quota::QuotaManager::kNoLimit);
346 // Credate another FileWriterDelegate for concurrent write.
347 result2.reset(new Result());
348 file_writer_delegate2.reset(CreateWriterDelegate(
349 "test2", 0, quota::QuotaManager::kNoLimit, result2.get()));
350 request2.reset(empty_context_.CreateRequest(
351 kBlobURL2, file_writer_delegate2.get()));
353 ASSERT_EQ(0, test_helper_.GetCachedOriginUsage());
354 file_writer_delegate_->Start(request_.Pass());
355 file_writer_delegate2->Start(request2.Pass());
356 MessageLoop::current()->Run();
357 if (result_->write_status() == FileWriterDelegate::SUCCESS_IO_PENDING ||
358 result2->write_status() == FileWriterDelegate::SUCCESS_IO_PENDING)
359 MessageLoop::current()->Run();
361 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result_->write_status());
362 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result2->write_status());
363 file_writer_delegate_.reset();
364 file_writer_delegate2.reset();
366 ASSERT_EQ(kDataSize * 2, test_helper_.GetCachedOriginUsage());
367 EXPECT_EQ(ComputeCurrentOriginUsage(), test_helper_.GetCachedOriginUsage());
369 EXPECT_EQ(kDataSize, result_->bytes_written());
370 EXPECT_EQ(base::PLATFORM_FILE_OK, result_->status());
371 EXPECT_EQ(kDataSize, result2->bytes_written());
372 EXPECT_EQ(base::PLATFORM_FILE_OK, result2->status());
375 #if defined(OS_WIN)
376 // See http://crbug.com/129264
377 #define MAYBE_WritesWithQuotaAndOffset \
378 DISABLED_WritesWithQuotaAndOffset
379 #else
380 #define MAYBE_WritesWithQuotaAndOffset \
381 WritesWithQuotaAndOffset
382 #endif
384 TEST_F(FileWriterDelegateTest, MAYBE_WritesWithQuotaAndOffset) {
385 const GURL kBlobURL("blob:failure-with-updated-quota");
386 content_ = kData;
388 // Writing kDataSize (=45) bytes data while allowed_growth is 100.
389 int64 offset = 0;
390 int64 allowed_growth = 100;
391 ASSERT_LT(kDataSize, allowed_growth);
392 PrepareForWrite(kBlobURL, offset, allowed_growth);
394 ASSERT_EQ(0, test_helper_.GetCachedOriginUsage());
395 file_writer_delegate_->Start(request_.Pass());
396 MessageLoop::current()->Run();
397 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result_->write_status());
398 file_writer_delegate_.reset();
400 ASSERT_EQ(kDataSize, test_helper_.GetCachedOriginUsage());
401 EXPECT_EQ(ComputeCurrentOriginUsage(), test_helper_.GetCachedOriginUsage());
402 EXPECT_EQ(kDataSize, result_->bytes_written());
403 EXPECT_EQ(base::PLATFORM_FILE_OK, result_->status());
405 // Trying to overwrite kDataSize bytes data while allowed_growth is 20.
406 offset = 0;
407 allowed_growth = 20;
408 PrepareForWrite(kBlobURL, offset, allowed_growth);
410 file_writer_delegate_->Start(request_.Pass());
411 MessageLoop::current()->Run();
412 EXPECT_EQ(kDataSize, test_helper_.GetCachedOriginUsage());
413 EXPECT_EQ(ComputeCurrentOriginUsage(), test_helper_.GetCachedOriginUsage());
414 EXPECT_EQ(kDataSize, result_->bytes_written());
415 EXPECT_EQ(base::PLATFORM_FILE_OK, result_->status());
416 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result_->write_status());
418 // Trying to write kDataSize bytes data from offset 25 while
419 // allowed_growth is 55.
420 offset = 25;
421 allowed_growth = 55;
422 PrepareForWrite(kBlobURL, offset, allowed_growth);
424 file_writer_delegate_->Start(request_.Pass());
425 MessageLoop::current()->Run();
426 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result_->write_status());
427 file_writer_delegate_.reset();
429 EXPECT_EQ(offset + kDataSize, test_helper_.GetCachedOriginUsage());
430 EXPECT_EQ(ComputeCurrentOriginUsage(), test_helper_.GetCachedOriginUsage());
431 EXPECT_EQ(kDataSize, result_->bytes_written());
432 EXPECT_EQ(base::PLATFORM_FILE_OK, result_->status());
434 // Trying to overwrite 45 bytes data while allowed_growth is -20.
435 offset = 0;
436 allowed_growth = -20;
437 PrepareForWrite(kBlobURL, offset, allowed_growth);
439 int64 pre_write_usage = ComputeCurrentOriginUsage();
440 file_writer_delegate_->Start(request_.Pass());
441 MessageLoop::current()->Run();
442 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result_->write_status());
443 file_writer_delegate_.reset();
445 EXPECT_EQ(pre_write_usage, test_helper_.GetCachedOriginUsage());
446 EXPECT_EQ(ComputeCurrentOriginUsage(), test_helper_.GetCachedOriginUsage());
447 EXPECT_EQ(kDataSize, result_->bytes_written());
448 EXPECT_EQ(base::PLATFORM_FILE_OK, result_->status());
450 // Trying to overwrite 45 bytes data with offset pre_write_usage - 20,
451 // while allowed_growth is 10.
452 const int kOverlap = 20;
453 offset = pre_write_usage - kOverlap;
454 allowed_growth = 10;
455 PrepareForWrite(kBlobURL, offset, allowed_growth);
457 file_writer_delegate_->Start(request_.Pass());
458 MessageLoop::current()->Run();
459 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result_->write_status());
460 file_writer_delegate_.reset();
462 EXPECT_EQ(pre_write_usage + allowed_growth,
463 test_helper_.GetCachedOriginUsage());
464 EXPECT_EQ(ComputeCurrentOriginUsage(), test_helper_.GetCachedOriginUsage());
465 EXPECT_EQ(kOverlap + allowed_growth, result_->bytes_written());
466 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, result_->status());
469 } // namespace fileapi