Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(915)

Side by Side Diff: content/browser/fileapi/file_writer_delegate_unittest.cc

Issue 2368913003: Populate storage_unittests target. (Closed)
Patch Set: Removed unnecessary include from storage/browser/blob/blob_storage_context_unittest.cc. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include <stdint.h>
6 #include <limits>
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/location.h"
15 #include "base/macros.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/run_loop.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "content/public/test/async_file_test_helper.h"
21 #include "content/public/test/test_file_system_context.h"
22 #include "net/base/io_buffer.h"
23 #include "net/base/request_priority.h"
24 #include "net/url_request/url_request.h"
25 #include "net/url_request/url_request_context.h"
26 #include "net/url_request/url_request_job.h"
27 #include "net/url_request/url_request_job_factory.h"
28 #include "net/url_request/url_request_status.h"
29 #include "storage/browser/fileapi/file_system_context.h"
30 #include "storage/browser/fileapi/file_system_quota_util.h"
31 #include "storage/browser/fileapi/file_writer_delegate.h"
32 #include "storage/browser/fileapi/sandbox_file_stream_writer.h"
33 #include "storage/common/fileapi/file_system_mount_option.h"
34 #include "testing/platform_test.h"
35 #include "url/gurl.h"
36
37 using content::AsyncFileTestHelper;
38 using storage::FileSystemURL;
39 using storage::FileWriterDelegate;
40
41 namespace content {
42
43 namespace {
44
45 const GURL kOrigin("http://example.com");
46 const storage::FileSystemType kFileSystemType = storage::kFileSystemTypeTest;
47
48 const char kData[] = "The quick brown fox jumps over the lazy dog.\n";
49 const int kDataSize = arraysize(kData) - 1;
50
51 class Result {
52 public:
53 Result()
54 : status_(base::File::FILE_OK),
55 bytes_written_(0),
56 write_status_(FileWriterDelegate::SUCCESS_IO_PENDING) {}
57
58 base::File::Error status() const { return status_; }
59 int64_t bytes_written() const { return bytes_written_; }
60 FileWriterDelegate::WriteProgressStatus write_status() const {
61 return write_status_;
62 }
63
64 void DidWrite(base::File::Error status,
65 int64_t bytes,
66 FileWriterDelegate::WriteProgressStatus write_status) {
67 write_status_ = write_status;
68 if (status == base::File::FILE_OK) {
69 bytes_written_ += bytes;
70 if (write_status_ != FileWriterDelegate::SUCCESS_IO_PENDING)
71 base::MessageLoop::current()->QuitWhenIdle();
72 } else {
73 EXPECT_EQ(base::File::FILE_OK, status_);
74 status_ = status;
75 base::MessageLoop::current()->QuitWhenIdle();
76 }
77 }
78
79 private:
80 // For post-operation status.
81 base::File::Error status_;
82 int64_t bytes_written_;
83 FileWriterDelegate::WriteProgressStatus write_status_;
84 };
85
86 class BlobURLRequestJobFactory;
87
88 } // namespace (anonymous)
89
90 class FileWriterDelegateTest : public PlatformTest {
91 public:
92 FileWriterDelegateTest() {}
93
94 protected:
95 void SetUp() override;
96 void TearDown() override;
97
98 int64_t usage() {
99 return file_system_context_->GetQuotaUtil(kFileSystemType)
100 ->GetOriginUsageOnFileTaskRunner(
101 file_system_context_.get(), kOrigin, kFileSystemType);
102 }
103
104 int64_t GetFileSizeOnDisk(const char* test_file_path) {
105 // There might be in-flight flush/write.
106 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
107 base::Bind(&base::DoNothing));
108 base::RunLoop().RunUntilIdle();
109
110 FileSystemURL url = GetFileSystemURL(test_file_path);
111 base::File::Info file_info;
112 EXPECT_EQ(base::File::FILE_OK,
113 AsyncFileTestHelper::GetMetadata(
114 file_system_context_.get(), url, &file_info));
115 return file_info.size;
116 }
117
118 FileSystemURL GetFileSystemURL(const char* file_name) const {
119 return file_system_context_->CreateCrackedFileSystemURL(
120 kOrigin, kFileSystemType, base::FilePath().FromUTF8Unsafe(file_name));
121 }
122
123 FileWriterDelegate* CreateWriterDelegate(const char* test_file_path,
124 int64_t offset,
125 int64_t allowed_growth) {
126 storage::SandboxFileStreamWriter* writer =
127 new storage::SandboxFileStreamWriter(
128 file_system_context_.get(),
129 GetFileSystemURL(test_file_path),
130 offset,
131 *file_system_context_->GetUpdateObservers(kFileSystemType));
132 writer->set_default_quota(allowed_growth);
133 return new FileWriterDelegate(
134 std::unique_ptr<storage::FileStreamWriter>(writer),
135 storage::FlushPolicy::FLUSH_ON_COMPLETION);
136 }
137
138 FileWriterDelegate::DelegateWriteCallback GetWriteCallback(Result* result) {
139 return base::Bind(&Result::DidWrite, base::Unretained(result));
140 }
141
142 // Creates and sets up a FileWriterDelegate for writing the given |blob_url|,
143 // and creates a new FileWriterDelegate for the file.
144 void PrepareForWrite(const char* test_file_path,
145 const GURL& blob_url,
146 int64_t offset,
147 int64_t allowed_growth) {
148 file_writer_delegate_.reset(
149 CreateWriterDelegate(test_file_path, offset, allowed_growth));
150 request_ = empty_context_.CreateRequest(
151 blob_url, net::DEFAULT_PRIORITY, file_writer_delegate_.get());
152 }
153
154 // This should be alive until the very end of this instance.
155 base::MessageLoopForIO loop_;
156
157 scoped_refptr<storage::FileSystemContext> file_system_context_;
158
159 net::URLRequestContext empty_context_;
160 std::unique_ptr<FileWriterDelegate> file_writer_delegate_;
161 std::unique_ptr<net::URLRequest> request_;
162 std::unique_ptr<BlobURLRequestJobFactory> job_factory_;
163
164 base::ScopedTempDir dir_;
165
166 static const char* content_;
167 };
168
169 const char* FileWriterDelegateTest::content_ = NULL;
170
171 namespace {
172
173 static std::string g_content;
174
175 class FileWriterDelegateTestJob : public net::URLRequestJob {
176 public:
177 FileWriterDelegateTestJob(net::URLRequest* request,
178 net::NetworkDelegate* network_delegate,
179 const std::string& content)
180 : net::URLRequestJob(request, network_delegate),
181 content_(content),
182 remaining_bytes_(content.length()),
183 cursor_(0),
184 weak_factory_(this) {}
185
186 void Start() override {
187 base::ThreadTaskRunnerHandle::Get()->PostTask(
188 FROM_HERE, base::Bind(&FileWriterDelegateTestJob::NotifyHeadersComplete,
189 weak_factory_.GetWeakPtr()));
190 }
191
192 int ReadRawData(net::IOBuffer* buf, int buf_size) override {
193 if (remaining_bytes_ < buf_size)
194 buf_size = remaining_bytes_;
195
196 for (int i = 0; i < buf_size; ++i)
197 buf->data()[i] = content_[cursor_++];
198 remaining_bytes_ -= buf_size;
199
200 return buf_size;
201 }
202
203 int GetResponseCode() const override { return 200; }
204
205 protected:
206 ~FileWriterDelegateTestJob() override {}
207
208 private:
209 std::string content_;
210 int remaining_bytes_;
211 int cursor_;
212
213 base::WeakPtrFactory<FileWriterDelegateTestJob> weak_factory_;
214 };
215
216 class BlobURLRequestJobFactory : public net::URLRequestJobFactory {
217 public:
218 explicit BlobURLRequestJobFactory(const char** content_data)
219 : content_data_(content_data) {
220 }
221
222 net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
223 const std::string& scheme,
224 net::URLRequest* request,
225 net::NetworkDelegate* network_delegate) const override {
226 return new FileWriterDelegateTestJob(
227 request, network_delegate, *content_data_);
228 }
229
230 net::URLRequestJob* MaybeInterceptRedirect(
231 net::URLRequest* request,
232 net::NetworkDelegate* network_delegate,
233 const GURL& location) const override {
234 return nullptr;
235 }
236
237 net::URLRequestJob* MaybeInterceptResponse(
238 net::URLRequest* request,
239 net::NetworkDelegate* network_delegate) const override {
240 return nullptr;
241 }
242
243 bool IsHandledProtocol(const std::string& scheme) const override {
244 return scheme == "blob";
245 }
246
247 bool IsHandledURL(const GURL& url) const override {
248 return url.SchemeIs("blob");
249 }
250
251 bool IsSafeRedirectTarget(const GURL& location) const override {
252 return true;
253 }
254
255 private:
256 const char** content_data_;
257
258 DISALLOW_COPY_AND_ASSIGN(BlobURLRequestJobFactory);
259 };
260
261 } // namespace (anonymous)
262
263 void FileWriterDelegateTest::SetUp() {
264 ASSERT_TRUE(dir_.CreateUniqueTempDir());
265
266 file_system_context_ =
267 CreateFileSystemContextForTesting(NULL, dir_.GetPath());
268 ASSERT_EQ(base::File::FILE_OK,
269 AsyncFileTestHelper::CreateFile(file_system_context_.get(),
270 GetFileSystemURL("test")));
271 job_factory_.reset(new BlobURLRequestJobFactory(&content_));
272 empty_context_.set_job_factory(job_factory_.get());
273 }
274
275 void FileWriterDelegateTest::TearDown() {
276 file_system_context_ = NULL;
277 base::RunLoop().RunUntilIdle();
278 }
279
280 TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimit) {
281 const GURL kBlobURL("blob:nolimit");
282 content_ = kData;
283
284 PrepareForWrite("test", kBlobURL, 0, std::numeric_limits<int64_t>::max());
285
286 Result result;
287 ASSERT_EQ(0, usage());
288 file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result));
289 base::RunLoop().Run();
290
291 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
292 file_writer_delegate_.reset();
293
294 ASSERT_EQ(kDataSize, usage());
295 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
296 EXPECT_EQ(kDataSize, result.bytes_written());
297 EXPECT_EQ(base::File::FILE_OK, result.status());
298 }
299
300 TEST_F(FileWriterDelegateTest, WriteSuccessWithJustQuota) {
301 const GURL kBlobURL("blob:just");
302 content_ = kData;
303 const int64_t kAllowedGrowth = kDataSize;
304 PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
305
306 Result result;
307 ASSERT_EQ(0, usage());
308 file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result));
309 base::RunLoop().Run();
310 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
311 file_writer_delegate_.reset();
312
313 ASSERT_EQ(kAllowedGrowth, usage());
314 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
315
316 EXPECT_EQ(kAllowedGrowth, result.bytes_written());
317 EXPECT_EQ(base::File::FILE_OK, result.status());
318 }
319
320 TEST_F(FileWriterDelegateTest, DISABLED_WriteFailureByQuota) {
321 const GURL kBlobURL("blob:failure");
322 content_ = kData;
323 const int64_t kAllowedGrowth = kDataSize - 1;
324 PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
325
326 Result result;
327 ASSERT_EQ(0, usage());
328 file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result));
329 base::RunLoop().Run();
330 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
331 file_writer_delegate_.reset();
332
333 ASSERT_EQ(kAllowedGrowth, usage());
334 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
335
336 EXPECT_EQ(kAllowedGrowth, result.bytes_written());
337 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, result.status());
338 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
339 }
340
341 TEST_F(FileWriterDelegateTest, WriteZeroBytesSuccessfullyWithZeroQuota) {
342 const GURL kBlobURL("blob:zero");
343 content_ = "";
344 int64_t kAllowedGrowth = 0;
345 PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
346
347 Result result;
348 ASSERT_EQ(0, usage());
349 file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result));
350 base::RunLoop().Run();
351 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
352 file_writer_delegate_.reset();
353
354 ASSERT_EQ(kAllowedGrowth, usage());
355 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
356
357 EXPECT_EQ(kAllowedGrowth, result.bytes_written());
358 EXPECT_EQ(base::File::FILE_OK, result.status());
359 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
360 }
361
362 TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimitConcurrent) {
363 std::unique_ptr<FileWriterDelegate> file_writer_delegate2;
364 std::unique_ptr<net::URLRequest> request2;
365
366 ASSERT_EQ(base::File::FILE_OK,
367 AsyncFileTestHelper::CreateFile(file_system_context_.get(),
368 GetFileSystemURL("test2")));
369
370 const GURL kBlobURL("blob:nolimitconcurrent");
371 const GURL kBlobURL2("blob:nolimitconcurrent2");
372 content_ = kData;
373
374 PrepareForWrite("test", kBlobURL, 0, std::numeric_limits<int64_t>::max());
375
376 // Credate another FileWriterDelegate for concurrent write.
377 file_writer_delegate2.reset(
378 CreateWriterDelegate("test2", 0, std::numeric_limits<int64_t>::max()));
379 request2 = empty_context_.CreateRequest(
380 kBlobURL2, net::DEFAULT_PRIORITY, file_writer_delegate2.get());
381
382 Result result, result2;
383 ASSERT_EQ(0, usage());
384 file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result));
385 file_writer_delegate2->Start(std::move(request2), GetWriteCallback(&result2));
386 base::RunLoop().Run();
387 if (result.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING ||
388 result2.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING)
389 base::RunLoop().Run();
390
391 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
392 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result2.write_status());
393 file_writer_delegate_.reset();
394 file_writer_delegate2.reset();
395
396 ASSERT_EQ(kDataSize * 2, usage());
397 EXPECT_EQ(GetFileSizeOnDisk("test") + GetFileSizeOnDisk("test2"), usage());
398
399 EXPECT_EQ(kDataSize, result.bytes_written());
400 EXPECT_EQ(base::File::FILE_OK, result.status());
401 EXPECT_EQ(kDataSize, result2.bytes_written());
402 EXPECT_EQ(base::File::FILE_OK, result2.status());
403 }
404
405 TEST_F(FileWriterDelegateTest, WritesWithQuotaAndOffset) {
406 const GURL kBlobURL("blob:failure-with-updated-quota");
407 content_ = kData;
408
409 // Writing kDataSize (=45) bytes data while allowed_growth is 100.
410 int64_t offset = 0;
411 int64_t allowed_growth = 100;
412 ASSERT_LT(kDataSize, allowed_growth);
413 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
414
415 {
416 Result result;
417 ASSERT_EQ(0, usage());
418 file_writer_delegate_->Start(std::move(request_),
419 GetWriteCallback(&result));
420 base::RunLoop().Run();
421 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
422 file_writer_delegate_.reset();
423
424 ASSERT_EQ(kDataSize, usage());
425 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
426 EXPECT_EQ(kDataSize, result.bytes_written());
427 EXPECT_EQ(base::File::FILE_OK, result.status());
428 }
429
430 // Trying to overwrite kDataSize bytes data while allowed_growth is 20.
431 offset = 0;
432 allowed_growth = 20;
433 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
434
435 {
436 Result result;
437 file_writer_delegate_->Start(std::move(request_),
438 GetWriteCallback(&result));
439 base::RunLoop().Run();
440 EXPECT_EQ(kDataSize, usage());
441 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
442 EXPECT_EQ(kDataSize, result.bytes_written());
443 EXPECT_EQ(base::File::FILE_OK, result.status());
444 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
445 }
446
447 // Trying to write kDataSize bytes data from offset 25 while
448 // allowed_growth is 55.
449 offset = 25;
450 allowed_growth = 55;
451 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
452
453 {
454 Result result;
455 file_writer_delegate_->Start(std::move(request_),
456 GetWriteCallback(&result));
457 base::RunLoop().Run();
458 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
459 file_writer_delegate_.reset();
460
461 EXPECT_EQ(offset + kDataSize, usage());
462 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
463 EXPECT_EQ(kDataSize, result.bytes_written());
464 EXPECT_EQ(base::File::FILE_OK, result.status());
465 }
466
467 // Trying to overwrite 45 bytes data while allowed_growth is -20.
468 offset = 0;
469 allowed_growth = -20;
470 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
471 int64_t pre_write_usage = GetFileSizeOnDisk("test");
472
473 {
474 Result result;
475 file_writer_delegate_->Start(std::move(request_),
476 GetWriteCallback(&result));
477 base::RunLoop().Run();
478 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
479 file_writer_delegate_.reset();
480
481 EXPECT_EQ(pre_write_usage, usage());
482 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
483 EXPECT_EQ(kDataSize, result.bytes_written());
484 EXPECT_EQ(base::File::FILE_OK, result.status());
485 }
486
487 // Trying to overwrite 45 bytes data with offset pre_write_usage - 20,
488 // while allowed_growth is 10.
489 const int kOverlap = 20;
490 offset = pre_write_usage - kOverlap;
491 allowed_growth = 10;
492 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
493
494 {
495 Result result;
496 file_writer_delegate_->Start(std::move(request_),
497 GetWriteCallback(&result));
498 base::RunLoop().Run();
499 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
500 file_writer_delegate_.reset();
501
502 EXPECT_EQ(pre_write_usage + allowed_growth, usage());
503 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
504 EXPECT_EQ(kOverlap + allowed_growth, result.bytes_written());
505 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, result.status());
506 }
507 }
508
509 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698