Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / base / file_stream_unittest.cc
blobd1985a8ace5b3d9735156cafb94c4229ee214149
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 "net/base/file_stream.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/files/file.h"
10 #include "base/files/file_util.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/path_service.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_util.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "base/threading/sequenced_worker_pool.h"
19 #include "base/threading/thread_restrictions.h"
20 #include "net/base/io_buffer.h"
21 #include "net/base/net_errors.h"
22 #include "net/base/test_completion_callback.h"
23 #include "net/log/test_net_log.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "testing/platform_test.h"
27 #if defined(OS_ANDROID)
28 #include "base/test/test_file_util.h"
29 #endif
31 namespace net {
33 namespace {
35 const char kTestData[] = "0123456789";
36 const int kTestDataSize = arraysize(kTestData) - 1;
38 // Creates an IOBufferWithSize that contains the kTestDataSize.
39 IOBufferWithSize* CreateTestDataBuffer() {
40 IOBufferWithSize* buf = new IOBufferWithSize(kTestDataSize);
41 memcpy(buf->data(), kTestData, kTestDataSize);
42 return buf;
45 } // namespace
47 class FileStreamTest : public PlatformTest {
48 public:
49 void SetUp() override {
50 PlatformTest::SetUp();
52 base::CreateTemporaryFile(&temp_file_path_);
53 base::WriteFile(temp_file_path_, kTestData, kTestDataSize);
55 void TearDown() override {
56 // FileStreamContexts must be asynchronously closed on the file task runner
57 // before they can be deleted. Pump the RunLoop to avoid leaks.
58 base::RunLoop().RunUntilIdle();
59 EXPECT_TRUE(base::DeleteFile(temp_file_path_, false));
61 PlatformTest::TearDown();
64 const base::FilePath temp_file_path() const { return temp_file_path_; }
66 private:
67 base::FilePath temp_file_path_;
70 namespace {
72 TEST_F(FileStreamTest, OpenExplicitClose) {
73 TestCompletionCallback callback;
74 FileStream stream(base::ThreadTaskRunnerHandle::Get());
75 int flags = base::File::FLAG_OPEN |
76 base::File::FLAG_READ |
77 base::File::FLAG_ASYNC;
78 int rv = stream.Open(temp_file_path(), flags, callback.callback());
79 EXPECT_EQ(ERR_IO_PENDING, rv);
80 EXPECT_EQ(OK, callback.WaitForResult());
81 EXPECT_TRUE(stream.IsOpen());
82 EXPECT_EQ(ERR_IO_PENDING, stream.Close(callback.callback()));
83 EXPECT_EQ(OK, callback.WaitForResult());
84 EXPECT_FALSE(stream.IsOpen());
87 TEST_F(FileStreamTest, OpenExplicitCloseOrphaned) {
88 TestCompletionCallback callback;
89 scoped_ptr<FileStream> stream(
90 new FileStream(base::ThreadTaskRunnerHandle::Get()));
91 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
92 base::File::FLAG_ASYNC;
93 int rv = stream->Open(temp_file_path(), flags, callback.callback());
94 EXPECT_EQ(ERR_IO_PENDING, rv);
95 EXPECT_EQ(OK, callback.WaitForResult());
96 EXPECT_TRUE(stream->IsOpen());
97 EXPECT_EQ(ERR_IO_PENDING, stream->Close(callback.callback()));
98 stream.reset();
99 // File isn't actually closed yet.
100 base::RunLoop runloop;
101 runloop.RunUntilIdle();
102 // The file should now be closed, though the callback has not been called.
105 // Test the use of FileStream with a file handle provided at construction.
106 TEST_F(FileStreamTest, UseFileHandle) {
107 int rv = 0;
108 TestCompletionCallback callback;
109 TestInt64CompletionCallback callback64;
110 // 1. Test reading with a file handle.
111 ASSERT_EQ(kTestDataSize,
112 base::WriteFile(temp_file_path(), kTestData, kTestDataSize));
113 int flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
114 base::File::FLAG_ASYNC;
115 base::File file(temp_file_path(), flags);
117 // Seek to the beginning of the file and read.
118 scoped_ptr<FileStream> read_stream(
119 new FileStream(file.Pass(), base::ThreadTaskRunnerHandle::Get()));
120 ASSERT_EQ(ERR_IO_PENDING, read_stream->Seek(0, callback64.callback()));
121 ASSERT_EQ(0, callback64.WaitForResult());
122 // Read into buffer and compare.
123 scoped_refptr<IOBufferWithSize> read_buffer =
124 new IOBufferWithSize(kTestDataSize);
125 rv = read_stream->Read(read_buffer.get(), kTestDataSize, callback.callback());
126 ASSERT_EQ(kTestDataSize, callback.GetResult(rv));
127 ASSERT_EQ(0, memcmp(kTestData, read_buffer->data(), kTestDataSize));
128 read_stream.reset();
130 // 2. Test writing with a file handle.
131 base::DeleteFile(temp_file_path(), false);
132 flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE |
133 base::File::FLAG_ASYNC;
134 file.Initialize(temp_file_path(), flags);
136 scoped_ptr<FileStream> write_stream(
137 new FileStream(file.Pass(), base::ThreadTaskRunnerHandle::Get()));
138 ASSERT_EQ(ERR_IO_PENDING, write_stream->Seek(0, callback64.callback()));
139 ASSERT_EQ(0, callback64.WaitForResult());
140 scoped_refptr<IOBufferWithSize> write_buffer = CreateTestDataBuffer();
141 rv = write_stream->Write(write_buffer.get(), kTestDataSize,
142 callback.callback());
143 ASSERT_EQ(kTestDataSize, callback.GetResult(rv));
144 write_stream.reset();
146 // Read into buffer and compare to make sure the handle worked fine.
147 ASSERT_EQ(kTestDataSize,
148 base::ReadFile(temp_file_path(), read_buffer->data(),
149 kTestDataSize));
150 ASSERT_EQ(0, memcmp(kTestData, read_buffer->data(), kTestDataSize));
153 TEST_F(FileStreamTest, UseClosedStream) {
154 int rv = 0;
155 TestCompletionCallback callback;
156 TestInt64CompletionCallback callback64;
158 FileStream stream(base::ThreadTaskRunnerHandle::Get());
160 EXPECT_FALSE(stream.IsOpen());
162 // Try seeking...
163 rv = stream.Seek(5, callback64.callback());
164 EXPECT_EQ(ERR_UNEXPECTED, callback64.GetResult(rv));
166 // Try reading...
167 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(10);
168 rv = stream.Read(buf.get(), buf->size(), callback.callback());
169 EXPECT_EQ(ERR_UNEXPECTED, callback.GetResult(rv));
172 TEST_F(FileStreamTest, Read) {
173 int64_t file_size;
174 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
176 FileStream stream(base::ThreadTaskRunnerHandle::Get());
177 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
178 base::File::FLAG_ASYNC;
179 TestCompletionCallback callback;
180 int rv = stream.Open(temp_file_path(), flags, callback.callback());
181 EXPECT_EQ(OK, callback.GetResult(rv));
183 int total_bytes_read = 0;
185 std::string data_read;
186 for (;;) {
187 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
188 rv = stream.Read(buf.get(), buf->size(), callback.callback());
189 rv = callback.GetResult(rv);
190 EXPECT_LE(0, rv);
191 if (rv <= 0)
192 break;
193 total_bytes_read += rv;
194 data_read.append(buf->data(), rv);
196 EXPECT_EQ(file_size, total_bytes_read);
197 EXPECT_EQ(kTestData, data_read);
200 TEST_F(FileStreamTest, Read_EarlyDelete) {
201 int64_t file_size;
202 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
204 scoped_ptr<FileStream> stream(
205 new FileStream(base::ThreadTaskRunnerHandle::Get()));
206 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
207 base::File::FLAG_ASYNC;
208 TestCompletionCallback callback;
209 int rv = stream->Open(temp_file_path(), flags, callback.callback());
210 EXPECT_EQ(ERR_IO_PENDING, rv);
211 EXPECT_EQ(OK, callback.WaitForResult());
213 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
214 rv = stream->Read(buf.get(), buf->size(), callback.callback());
215 stream.reset(); // Delete instead of closing it.
216 if (rv < 0) {
217 EXPECT_EQ(ERR_IO_PENDING, rv);
218 // The callback should not be called if the request is cancelled.
219 base::RunLoop().RunUntilIdle();
220 EXPECT_FALSE(callback.have_result());
221 } else {
222 EXPECT_EQ(std::string(kTestData, rv), std::string(buf->data(), rv));
226 TEST_F(FileStreamTest, Read_FromOffset) {
227 int64_t file_size;
228 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
230 FileStream stream(base::ThreadTaskRunnerHandle::Get());
231 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
232 base::File::FLAG_ASYNC;
233 TestCompletionCallback callback;
234 int rv = stream.Open(temp_file_path(), flags, callback.callback());
235 EXPECT_EQ(ERR_IO_PENDING, rv);
236 EXPECT_EQ(OK, callback.WaitForResult());
238 TestInt64CompletionCallback callback64;
239 const int64_t kOffset = 3;
240 rv = stream.Seek(kOffset, callback64.callback());
241 ASSERT_EQ(ERR_IO_PENDING, rv);
242 int64_t new_offset = callback64.WaitForResult();
243 EXPECT_EQ(kOffset, new_offset);
245 int total_bytes_read = 0;
247 std::string data_read;
248 for (;;) {
249 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
250 rv = stream.Read(buf.get(), buf->size(), callback.callback());
251 if (rv == ERR_IO_PENDING)
252 rv = callback.WaitForResult();
253 EXPECT_LE(0, rv);
254 if (rv <= 0)
255 break;
256 total_bytes_read += rv;
257 data_read.append(buf->data(), rv);
259 EXPECT_EQ(file_size - kOffset, total_bytes_read);
260 EXPECT_EQ(kTestData + kOffset, data_read);
263 TEST_F(FileStreamTest, Write) {
264 FileStream stream(base::ThreadTaskRunnerHandle::Get());
265 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
266 base::File::FLAG_ASYNC;
267 TestCompletionCallback callback;
268 int rv = stream.Open(temp_file_path(), flags, callback.callback());
269 EXPECT_EQ(OK, callback.GetResult(rv));
271 int64_t file_size;
272 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
273 EXPECT_EQ(0, file_size);
275 scoped_refptr<IOBuffer> buf = CreateTestDataBuffer();
276 rv = stream.Write(buf.get(), kTestDataSize, callback.callback());
277 rv = callback.GetResult(rv);
278 EXPECT_EQ(kTestDataSize, rv);
280 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
281 EXPECT_EQ(kTestDataSize, file_size);
283 std::string data_read;
284 EXPECT_TRUE(base::ReadFileToString(temp_file_path(), &data_read));
285 EXPECT_EQ(kTestData, data_read);
288 TEST_F(FileStreamTest, Write_EarlyDelete) {
289 scoped_ptr<FileStream> stream(
290 new FileStream(base::ThreadTaskRunnerHandle::Get()));
291 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
292 base::File::FLAG_ASYNC;
293 TestCompletionCallback callback;
294 int rv = stream->Open(temp_file_path(), flags, callback.callback());
295 EXPECT_EQ(ERR_IO_PENDING, rv);
296 EXPECT_EQ(OK, callback.WaitForResult());
298 int64_t file_size;
299 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
300 EXPECT_EQ(0, file_size);
302 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
303 rv = stream->Write(buf.get(), buf->size(), callback.callback());
304 stream.reset();
305 if (rv < 0) {
306 EXPECT_EQ(ERR_IO_PENDING, rv);
307 // The callback should not be called if the request is cancelled.
308 base::RunLoop().RunUntilIdle();
309 EXPECT_FALSE(callback.have_result());
310 } else {
311 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
312 EXPECT_EQ(file_size, rv);
316 TEST_F(FileStreamTest, Write_FromOffset) {
317 int64_t file_size;
318 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
320 FileStream stream(base::ThreadTaskRunnerHandle::Get());
321 int flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
322 base::File::FLAG_ASYNC;
323 TestCompletionCallback callback;
324 int rv = stream.Open(temp_file_path(), flags, callback.callback());
325 EXPECT_EQ(ERR_IO_PENDING, rv);
326 EXPECT_EQ(OK, callback.WaitForResult());
328 TestInt64CompletionCallback callback64;
329 const int64_t kOffset = kTestDataSize;
330 rv = stream.Seek(kOffset, callback64.callback());
331 ASSERT_EQ(ERR_IO_PENDING, rv);
332 int64_t new_offset = callback64.WaitForResult();
333 EXPECT_EQ(kTestDataSize, new_offset);
335 int total_bytes_written = 0;
337 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
338 scoped_refptr<DrainableIOBuffer> drainable =
339 new DrainableIOBuffer(buf.get(), buf->size());
340 while (total_bytes_written != kTestDataSize) {
341 rv = stream.Write(drainable.get(), drainable->BytesRemaining(),
342 callback.callback());
343 if (rv == ERR_IO_PENDING)
344 rv = callback.WaitForResult();
345 EXPECT_LT(0, rv);
346 if (rv <= 0)
347 break;
348 drainable->DidConsume(rv);
349 total_bytes_written += rv;
351 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
352 EXPECT_EQ(file_size, kTestDataSize * 2);
355 TEST_F(FileStreamTest, BasicReadWrite) {
356 int64_t file_size;
357 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
359 scoped_ptr<FileStream> stream(
360 new FileStream(base::ThreadTaskRunnerHandle::Get()));
361 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
362 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
363 TestCompletionCallback callback;
364 int rv = stream->Open(temp_file_path(), flags, callback.callback());
365 EXPECT_EQ(ERR_IO_PENDING, rv);
366 EXPECT_EQ(OK, callback.WaitForResult());
368 int64_t total_bytes_read = 0;
370 std::string data_read;
371 for (;;) {
372 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
373 rv = stream->Read(buf.get(), buf->size(), callback.callback());
374 if (rv == ERR_IO_PENDING)
375 rv = callback.WaitForResult();
376 EXPECT_LE(0, rv);
377 if (rv <= 0)
378 break;
379 total_bytes_read += rv;
380 data_read.append(buf->data(), rv);
382 EXPECT_EQ(file_size, total_bytes_read);
383 EXPECT_TRUE(data_read == kTestData);
385 int total_bytes_written = 0;
387 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
388 scoped_refptr<DrainableIOBuffer> drainable =
389 new DrainableIOBuffer(buf.get(), buf->size());
390 while (total_bytes_written != kTestDataSize) {
391 rv = stream->Write(drainable.get(), drainable->BytesRemaining(),
392 callback.callback());
393 if (rv == ERR_IO_PENDING)
394 rv = callback.WaitForResult();
395 EXPECT_LT(0, rv);
396 if (rv <= 0)
397 break;
398 drainable->DidConsume(rv);
399 total_bytes_written += rv;
402 stream.reset();
404 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
405 EXPECT_EQ(kTestDataSize * 2, file_size);
408 TEST_F(FileStreamTest, BasicWriteRead) {
409 int64_t file_size;
410 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
412 scoped_ptr<FileStream> stream(
413 new FileStream(base::ThreadTaskRunnerHandle::Get()));
414 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
415 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
416 TestCompletionCallback callback;
417 int rv = stream->Open(temp_file_path(), flags, callback.callback());
418 EXPECT_EQ(ERR_IO_PENDING, rv);
419 EXPECT_EQ(OK, callback.WaitForResult());
421 TestInt64CompletionCallback callback64;
422 rv = stream->Seek(file_size, callback64.callback());
423 ASSERT_EQ(ERR_IO_PENDING, rv);
424 int64_t offset = callback64.WaitForResult();
425 EXPECT_EQ(offset, file_size);
427 int total_bytes_written = 0;
429 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
430 scoped_refptr<DrainableIOBuffer> drainable =
431 new DrainableIOBuffer(buf.get(), buf->size());
432 while (total_bytes_written != kTestDataSize) {
433 rv = stream->Write(drainable.get(), drainable->BytesRemaining(),
434 callback.callback());
435 if (rv == ERR_IO_PENDING)
436 rv = callback.WaitForResult();
437 EXPECT_LT(0, rv);
438 if (rv <= 0)
439 break;
440 drainable->DidConsume(rv);
441 total_bytes_written += rv;
444 EXPECT_EQ(kTestDataSize, total_bytes_written);
446 rv = stream->Seek(0, callback64.callback());
447 ASSERT_EQ(ERR_IO_PENDING, rv);
448 offset = callback64.WaitForResult();
449 EXPECT_EQ(0, offset);
451 int total_bytes_read = 0;
453 std::string data_read;
454 for (;;) {
455 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
456 rv = stream->Read(buf.get(), buf->size(), callback.callback());
457 if (rv == ERR_IO_PENDING)
458 rv = callback.WaitForResult();
459 EXPECT_LE(0, rv);
460 if (rv <= 0)
461 break;
462 total_bytes_read += rv;
463 data_read.append(buf->data(), rv);
465 stream.reset();
467 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
468 EXPECT_EQ(kTestDataSize * 2, file_size);
470 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
471 const std::string kExpectedFileData =
472 std::string(kTestData) + std::string(kTestData);
473 EXPECT_EQ(kExpectedFileData, data_read);
476 class TestWriteReadCompletionCallback {
477 public:
478 TestWriteReadCompletionCallback(FileStream* stream,
479 int* total_bytes_written,
480 int* total_bytes_read,
481 std::string* data_read)
482 : result_(0),
483 have_result_(false),
484 waiting_for_result_(false),
485 stream_(stream),
486 total_bytes_written_(total_bytes_written),
487 total_bytes_read_(total_bytes_read),
488 data_read_(data_read),
489 callback_(base::Bind(&TestWriteReadCompletionCallback::OnComplete,
490 base::Unretained(this))),
491 test_data_(CreateTestDataBuffer()),
492 drainable_(new DrainableIOBuffer(test_data_.get(), kTestDataSize)) {}
494 int WaitForResult() {
495 DCHECK(!waiting_for_result_);
496 while (!have_result_) {
497 waiting_for_result_ = true;
498 base::RunLoop().Run();
499 waiting_for_result_ = false;
501 have_result_ = false; // auto-reset for next callback
502 return result_;
505 const CompletionCallback& callback() const { return callback_; }
507 void ValidateWrittenData() {
508 TestCompletionCallback callback;
509 int rv = 0;
510 for (;;) {
511 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
512 rv = stream_->Read(buf.get(), buf->size(), callback.callback());
513 if (rv == ERR_IO_PENDING) {
514 base::MessageLoop::ScopedNestableTaskAllower allow(
515 base::MessageLoop::current());
516 rv = callback.WaitForResult();
518 EXPECT_LE(0, rv);
519 if (rv <= 0)
520 break;
521 *total_bytes_read_ += rv;
522 data_read_->append(buf->data(), rv);
526 private:
527 void OnComplete(int result) {
528 DCHECK_LT(0, result);
529 *total_bytes_written_ += result;
531 int rv;
533 if (*total_bytes_written_ != kTestDataSize) {
534 // Recurse to finish writing all data.
535 int total_bytes_written = 0, total_bytes_read = 0;
536 std::string data_read;
537 TestWriteReadCompletionCallback callback(
538 stream_, &total_bytes_written, &total_bytes_read, &data_read);
539 rv = stream_->Write(
540 drainable_.get(), drainable_->BytesRemaining(), callback.callback());
541 DCHECK_EQ(ERR_IO_PENDING, rv);
542 rv = callback.WaitForResult();
543 drainable_->DidConsume(total_bytes_written);
544 *total_bytes_written_ += total_bytes_written;
545 *total_bytes_read_ += total_bytes_read;
546 *data_read_ += data_read;
547 } else { // We're done writing all data. Start reading the data.
548 TestInt64CompletionCallback callback64;
549 EXPECT_EQ(ERR_IO_PENDING, stream_->Seek(0, callback64.callback()));
551 base::MessageLoop::ScopedNestableTaskAllower allow(
552 base::MessageLoop::current());
553 EXPECT_LE(0, callback64.WaitForResult());
557 result_ = *total_bytes_written_;
558 have_result_ = true;
559 if (waiting_for_result_)
560 base::MessageLoop::current()->Quit();
563 int result_;
564 bool have_result_;
565 bool waiting_for_result_;
566 FileStream* stream_;
567 int* total_bytes_written_;
568 int* total_bytes_read_;
569 std::string* data_read_;
570 const CompletionCallback callback_;
571 scoped_refptr<IOBufferWithSize> test_data_;
572 scoped_refptr<DrainableIOBuffer> drainable_;
574 DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback);
577 TEST_F(FileStreamTest, WriteRead) {
578 int64_t file_size;
579 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
581 scoped_ptr<FileStream> stream(
582 new FileStream(base::ThreadTaskRunnerHandle::Get()));
583 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
584 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
585 TestCompletionCallback open_callback;
586 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
587 EXPECT_EQ(ERR_IO_PENDING, rv);
588 EXPECT_EQ(OK, open_callback.WaitForResult());
590 TestInt64CompletionCallback callback64;
591 EXPECT_EQ(ERR_IO_PENDING, stream->Seek(file_size, callback64.callback()));
592 EXPECT_EQ(file_size, callback64.WaitForResult());
594 int total_bytes_written = 0;
595 int total_bytes_read = 0;
596 std::string data_read;
597 TestWriteReadCompletionCallback callback(stream.get(), &total_bytes_written,
598 &total_bytes_read, &data_read);
600 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
601 rv = stream->Write(buf.get(), buf->size(), callback.callback());
602 if (rv == ERR_IO_PENDING)
603 rv = callback.WaitForResult();
604 EXPECT_LT(0, rv);
605 EXPECT_EQ(kTestDataSize, total_bytes_written);
607 callback.ValidateWrittenData();
609 stream.reset();
611 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
612 EXPECT_EQ(kTestDataSize * 2, file_size);
614 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
615 const std::string kExpectedFileData =
616 std::string(kTestData) + std::string(kTestData);
617 EXPECT_EQ(kExpectedFileData, data_read);
620 class TestWriteCloseCompletionCallback {
621 public:
622 TestWriteCloseCompletionCallback(FileStream* stream, int* total_bytes_written)
623 : result_(0),
624 have_result_(false),
625 waiting_for_result_(false),
626 stream_(stream),
627 total_bytes_written_(total_bytes_written),
628 callback_(base::Bind(&TestWriteCloseCompletionCallback::OnComplete,
629 base::Unretained(this))),
630 test_data_(CreateTestDataBuffer()),
631 drainable_(new DrainableIOBuffer(test_data_.get(), kTestDataSize)) {}
633 int WaitForResult() {
634 DCHECK(!waiting_for_result_);
635 while (!have_result_) {
636 waiting_for_result_ = true;
637 base::RunLoop().Run();
638 waiting_for_result_ = false;
640 have_result_ = false; // auto-reset for next callback
641 return result_;
644 const CompletionCallback& callback() const { return callback_; }
646 private:
647 void OnComplete(int result) {
648 DCHECK_LT(0, result);
649 *total_bytes_written_ += result;
651 int rv;
653 if (*total_bytes_written_ != kTestDataSize) {
654 // Recurse to finish writing all data.
655 int total_bytes_written = 0;
656 TestWriteCloseCompletionCallback callback(stream_, &total_bytes_written);
657 rv = stream_->Write(
658 drainable_.get(), drainable_->BytesRemaining(), callback.callback());
659 DCHECK_EQ(ERR_IO_PENDING, rv);
660 rv = callback.WaitForResult();
661 drainable_->DidConsume(total_bytes_written);
662 *total_bytes_written_ += total_bytes_written;
665 result_ = *total_bytes_written_;
666 have_result_ = true;
667 if (waiting_for_result_)
668 base::MessageLoop::current()->Quit();
671 int result_;
672 bool have_result_;
673 bool waiting_for_result_;
674 FileStream* stream_;
675 int* total_bytes_written_;
676 const CompletionCallback callback_;
677 scoped_refptr<IOBufferWithSize> test_data_;
678 scoped_refptr<DrainableIOBuffer> drainable_;
680 DISALLOW_COPY_AND_ASSIGN(TestWriteCloseCompletionCallback);
683 TEST_F(FileStreamTest, WriteClose) {
684 int64_t file_size;
685 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
687 scoped_ptr<FileStream> stream(
688 new FileStream(base::ThreadTaskRunnerHandle::Get()));
689 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
690 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
691 TestCompletionCallback open_callback;
692 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
693 EXPECT_EQ(ERR_IO_PENDING, rv);
694 EXPECT_EQ(OK, open_callback.WaitForResult());
696 TestInt64CompletionCallback callback64;
697 EXPECT_EQ(ERR_IO_PENDING, stream->Seek(file_size, callback64.callback()));
698 EXPECT_EQ(file_size, callback64.WaitForResult());
700 int total_bytes_written = 0;
701 TestWriteCloseCompletionCallback callback(stream.get(), &total_bytes_written);
703 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
704 rv = stream->Write(buf.get(), buf->size(), callback.callback());
705 if (rv == ERR_IO_PENDING)
706 total_bytes_written = callback.WaitForResult();
707 EXPECT_LT(0, total_bytes_written);
708 EXPECT_EQ(kTestDataSize, total_bytes_written);
710 stream.reset();
712 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
713 EXPECT_EQ(kTestDataSize * 2, file_size);
716 TEST_F(FileStreamTest, OpenAndDelete) {
717 scoped_refptr<base::SequencedWorkerPool> pool(
718 new base::SequencedWorkerPool(1, "StreamTest"));
720 bool prev = base::ThreadRestrictions::SetIOAllowed(false);
721 scoped_ptr<FileStream> stream(new FileStream(pool.get()));
722 int flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
723 base::File::FLAG_ASYNC;
724 TestCompletionCallback open_callback;
725 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
726 EXPECT_EQ(ERR_IO_PENDING, rv);
728 // Delete the stream without waiting for the open operation to be
729 // complete. Should be safe.
730 stream.reset();
732 // Force an operation through the pool.
733 scoped_ptr<FileStream> stream2(new FileStream(pool.get()));
734 TestCompletionCallback open_callback2;
735 rv = stream2->Open(temp_file_path(), flags, open_callback2.callback());
736 EXPECT_EQ(OK, open_callback2.GetResult(rv));
737 stream2.reset();
739 pool->Shutdown();
741 // open_callback won't be called.
742 base::RunLoop().RunUntilIdle();
743 EXPECT_FALSE(open_callback.have_result());
744 base::ThreadRestrictions::SetIOAllowed(prev);
747 // Verify that Write() errors are mapped correctly.
748 TEST_F(FileStreamTest, WriteError) {
749 // Try opening file as read-only and then writing to it using FileStream.
750 uint32_t flags =
751 base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_ASYNC;
753 base::File file(temp_file_path(), flags);
754 ASSERT_TRUE(file.IsValid());
756 scoped_ptr<FileStream> stream(
757 new FileStream(file.Pass(), base::ThreadTaskRunnerHandle::Get()));
759 scoped_refptr<IOBuffer> buf = new IOBuffer(1);
760 buf->data()[0] = 0;
762 TestCompletionCallback callback;
763 int rv = stream->Write(buf.get(), 1, callback.callback());
764 if (rv == ERR_IO_PENDING)
765 rv = callback.WaitForResult();
766 EXPECT_LT(rv, 0);
768 stream.reset();
769 base::RunLoop().RunUntilIdle();
772 // Verify that Read() errors are mapped correctly.
773 TEST_F(FileStreamTest, ReadError) {
774 // Try opening file for write and then reading from it using FileStream.
775 uint32_t flags =
776 base::File::FLAG_OPEN | base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
778 base::File file(temp_file_path(), flags);
779 ASSERT_TRUE(file.IsValid());
781 scoped_ptr<FileStream> stream(
782 new FileStream(file.Pass(), base::ThreadTaskRunnerHandle::Get()));
784 scoped_refptr<IOBuffer> buf = new IOBuffer(1);
785 TestCompletionCallback callback;
786 int rv = stream->Read(buf.get(), 1, callback.callback());
787 if (rv == ERR_IO_PENDING)
788 rv = callback.WaitForResult();
789 EXPECT_LT(rv, 0);
791 stream.reset();
792 base::RunLoop().RunUntilIdle();
795 #if defined(OS_ANDROID)
796 TEST_F(FileStreamTest, ContentUriRead) {
797 base::FilePath test_dir;
798 PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
799 test_dir = test_dir.AppendASCII("net");
800 test_dir = test_dir.AppendASCII("data");
801 test_dir = test_dir.AppendASCII("file_stream_unittest");
802 ASSERT_TRUE(base::PathExists(test_dir));
803 base::FilePath image_file = test_dir.Append(FILE_PATH_LITERAL("red.png"));
805 // Insert the image into MediaStore. MediaStore will do some conversions, and
806 // return the content URI.
807 base::FilePath path = base::InsertImageIntoMediaStore(image_file);
808 EXPECT_TRUE(path.IsContentUri());
809 EXPECT_TRUE(base::PathExists(path));
810 int64_t file_size;
811 EXPECT_TRUE(base::GetFileSize(path, &file_size));
812 EXPECT_LT(0, file_size);
814 FileStream stream(base::ThreadTaskRunnerHandle::Get());
815 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
816 base::File::FLAG_ASYNC;
817 TestCompletionCallback callback;
818 int rv = stream.Open(path, flags, callback.callback());
819 EXPECT_EQ(ERR_IO_PENDING, rv);
820 EXPECT_EQ(OK, callback.WaitForResult());
822 int total_bytes_read = 0;
824 std::string data_read;
825 for (;;) {
826 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
827 rv = stream.Read(buf.get(), buf->size(), callback.callback());
828 if (rv == ERR_IO_PENDING)
829 rv = callback.WaitForResult();
830 EXPECT_LE(0, rv);
831 if (rv <= 0)
832 break;
833 total_bytes_read += rv;
834 data_read.append(buf->data(), rv);
836 EXPECT_EQ(file_size, total_bytes_read);
838 #endif
840 } // namespace
842 } // namespace net