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

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

Issue 2813353003: Move some File API backend unit tests next to the files that they cover. (Closed)
Patch Set: Created 3 years, 8 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 "net/base/io_buffer.h"
21 #include "net/base/request_priority.h"
22 #include "net/url_request/url_request.h"
23 #include "net/url_request/url_request_context.h"
24 #include "net/url_request/url_request_job.h"
25 #include "net/url_request/url_request_job_factory.h"
26 #include "net/url_request/url_request_status.h"
27 #include "storage/browser/fileapi/file_system_context.h"
28 #include "storage/browser/fileapi/file_system_quota_util.h"
29 #include "storage/browser/fileapi/file_writer_delegate.h"
30 #include "storage/browser/fileapi/sandbox_file_stream_writer.h"
31 #include "storage/browser/test/async_file_test_helper.h"
32 #include "storage/browser/test/test_file_system_context.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 IsSafeRedirectTarget(const GURL& location) const override {
248 return true;
249 }
250
251 private:
252 const char** content_data_;
253
254 DISALLOW_COPY_AND_ASSIGN(BlobURLRequestJobFactory);
255 };
256
257 } // namespace (anonymous)
258
259 void FileWriterDelegateTest::SetUp() {
260 ASSERT_TRUE(dir_.CreateUniqueTempDir());
261
262 file_system_context_ =
263 CreateFileSystemContextForTesting(NULL, dir_.GetPath());
264 ASSERT_EQ(base::File::FILE_OK,
265 AsyncFileTestHelper::CreateFile(file_system_context_.get(),
266 GetFileSystemURL("test")));
267 job_factory_.reset(new BlobURLRequestJobFactory(&content_));
268 empty_context_.set_job_factory(job_factory_.get());
269 }
270
271 void FileWriterDelegateTest::TearDown() {
272 file_system_context_ = NULL;
273 base::RunLoop().RunUntilIdle();
274 }
275
276 TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimit) {
277 const GURL kBlobURL("blob:nolimit");
278 content_ = kData;
279
280 PrepareForWrite("test", kBlobURL, 0, std::numeric_limits<int64_t>::max());
281
282 Result result;
283 ASSERT_EQ(0, usage());
284 file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result));
285 base::RunLoop().Run();
286
287 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
288 file_writer_delegate_.reset();
289
290 ASSERT_EQ(kDataSize, usage());
291 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
292 EXPECT_EQ(kDataSize, result.bytes_written());
293 EXPECT_EQ(base::File::FILE_OK, result.status());
294 }
295
296 TEST_F(FileWriterDelegateTest, WriteSuccessWithJustQuota) {
297 const GURL kBlobURL("blob:just");
298 content_ = kData;
299 const int64_t kAllowedGrowth = kDataSize;
300 PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
301
302 Result result;
303 ASSERT_EQ(0, usage());
304 file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result));
305 base::RunLoop().Run();
306 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
307 file_writer_delegate_.reset();
308
309 ASSERT_EQ(kAllowedGrowth, usage());
310 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
311
312 EXPECT_EQ(kAllowedGrowth, result.bytes_written());
313 EXPECT_EQ(base::File::FILE_OK, result.status());
314 }
315
316 TEST_F(FileWriterDelegateTest, DISABLED_WriteFailureByQuota) {
317 const GURL kBlobURL("blob:failure");
318 content_ = kData;
319 const int64_t kAllowedGrowth = kDataSize - 1;
320 PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
321
322 Result result;
323 ASSERT_EQ(0, usage());
324 file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result));
325 base::RunLoop().Run();
326 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
327 file_writer_delegate_.reset();
328
329 ASSERT_EQ(kAllowedGrowth, usage());
330 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
331
332 EXPECT_EQ(kAllowedGrowth, result.bytes_written());
333 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, result.status());
334 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
335 }
336
337 TEST_F(FileWriterDelegateTest, WriteZeroBytesSuccessfullyWithZeroQuota) {
338 const GURL kBlobURL("blob:zero");
339 content_ = "";
340 int64_t kAllowedGrowth = 0;
341 PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth);
342
343 Result result;
344 ASSERT_EQ(0, usage());
345 file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result));
346 base::RunLoop().Run();
347 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
348 file_writer_delegate_.reset();
349
350 ASSERT_EQ(kAllowedGrowth, usage());
351 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
352
353 EXPECT_EQ(kAllowedGrowth, result.bytes_written());
354 EXPECT_EQ(base::File::FILE_OK, result.status());
355 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
356 }
357
358 TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimitConcurrent) {
359 std::unique_ptr<FileWriterDelegate> file_writer_delegate2;
360 std::unique_ptr<net::URLRequest> request2;
361
362 ASSERT_EQ(base::File::FILE_OK,
363 AsyncFileTestHelper::CreateFile(file_system_context_.get(),
364 GetFileSystemURL("test2")));
365
366 const GURL kBlobURL("blob:nolimitconcurrent");
367 const GURL kBlobURL2("blob:nolimitconcurrent2");
368 content_ = kData;
369
370 PrepareForWrite("test", kBlobURL, 0, std::numeric_limits<int64_t>::max());
371
372 // Credate another FileWriterDelegate for concurrent write.
373 file_writer_delegate2.reset(
374 CreateWriterDelegate("test2", 0, std::numeric_limits<int64_t>::max()));
375 request2 = empty_context_.CreateRequest(
376 kBlobURL2, net::DEFAULT_PRIORITY, file_writer_delegate2.get());
377
378 Result result, result2;
379 ASSERT_EQ(0, usage());
380 file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result));
381 file_writer_delegate2->Start(std::move(request2), GetWriteCallback(&result2));
382 base::RunLoop().Run();
383 if (result.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING ||
384 result2.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING)
385 base::RunLoop().Run();
386
387 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
388 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result2.write_status());
389 file_writer_delegate_.reset();
390 file_writer_delegate2.reset();
391
392 ASSERT_EQ(kDataSize * 2, usage());
393 EXPECT_EQ(GetFileSizeOnDisk("test") + GetFileSizeOnDisk("test2"), usage());
394
395 EXPECT_EQ(kDataSize, result.bytes_written());
396 EXPECT_EQ(base::File::FILE_OK, result.status());
397 EXPECT_EQ(kDataSize, result2.bytes_written());
398 EXPECT_EQ(base::File::FILE_OK, result2.status());
399 }
400
401 TEST_F(FileWriterDelegateTest, WritesWithQuotaAndOffset) {
402 const GURL kBlobURL("blob:failure-with-updated-quota");
403 content_ = kData;
404
405 // Writing kDataSize (=45) bytes data while allowed_growth is 100.
406 int64_t offset = 0;
407 int64_t allowed_growth = 100;
408 ASSERT_LT(kDataSize, allowed_growth);
409 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
410
411 {
412 Result result;
413 ASSERT_EQ(0, usage());
414 file_writer_delegate_->Start(std::move(request_),
415 GetWriteCallback(&result));
416 base::RunLoop().Run();
417 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
418 file_writer_delegate_.reset();
419
420 ASSERT_EQ(kDataSize, usage());
421 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
422 EXPECT_EQ(kDataSize, result.bytes_written());
423 EXPECT_EQ(base::File::FILE_OK, result.status());
424 }
425
426 // Trying to overwrite kDataSize bytes data while allowed_growth is 20.
427 offset = 0;
428 allowed_growth = 20;
429 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
430
431 {
432 Result result;
433 file_writer_delegate_->Start(std::move(request_),
434 GetWriteCallback(&result));
435 base::RunLoop().Run();
436 EXPECT_EQ(kDataSize, usage());
437 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
438 EXPECT_EQ(kDataSize, result.bytes_written());
439 EXPECT_EQ(base::File::FILE_OK, result.status());
440 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
441 }
442
443 // Trying to write kDataSize bytes data from offset 25 while
444 // allowed_growth is 55.
445 offset = 25;
446 allowed_growth = 55;
447 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
448
449 {
450 Result result;
451 file_writer_delegate_->Start(std::move(request_),
452 GetWriteCallback(&result));
453 base::RunLoop().Run();
454 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
455 file_writer_delegate_.reset();
456
457 EXPECT_EQ(offset + kDataSize, usage());
458 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
459 EXPECT_EQ(kDataSize, result.bytes_written());
460 EXPECT_EQ(base::File::FILE_OK, result.status());
461 }
462
463 // Trying to overwrite 45 bytes data while allowed_growth is -20.
464 offset = 0;
465 allowed_growth = -20;
466 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
467 int64_t pre_write_usage = GetFileSizeOnDisk("test");
468
469 {
470 Result result;
471 file_writer_delegate_->Start(std::move(request_),
472 GetWriteCallback(&result));
473 base::RunLoop().Run();
474 ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status());
475 file_writer_delegate_.reset();
476
477 EXPECT_EQ(pre_write_usage, usage());
478 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
479 EXPECT_EQ(kDataSize, result.bytes_written());
480 EXPECT_EQ(base::File::FILE_OK, result.status());
481 }
482
483 // Trying to overwrite 45 bytes data with offset pre_write_usage - 20,
484 // while allowed_growth is 10.
485 const int kOverlap = 20;
486 offset = pre_write_usage - kOverlap;
487 allowed_growth = 10;
488 PrepareForWrite("test", kBlobURL, offset, allowed_growth);
489
490 {
491 Result result;
492 file_writer_delegate_->Start(std::move(request_),
493 GetWriteCallback(&result));
494 base::RunLoop().Run();
495 ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status());
496 file_writer_delegate_.reset();
497
498 EXPECT_EQ(pre_write_usage + allowed_growth, usage());
499 EXPECT_EQ(GetFileSizeOnDisk("test"), usage());
500 EXPECT_EQ(kOverlap + allowed_growth, result.bytes_written());
501 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, result.status());
502 }
503 }
504
505 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/fileapi/file_system_url_request_job_unittest.cc ('k') | content/browser/fileapi/local_file_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698