Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / net / base / file_stream_unittest.cc
blob292b0d207cfff37320e34e72fc53e25725302437
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/file_util.h"
10 #include "base/files/file.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/path_service.h"
14 #include "base/run_loop.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/threading/sequenced_worker_pool.h"
18 #include "base/threading/thread_restrictions.h"
19 #include "net/base/capturing_net_log.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 "testing/gtest/include/gtest/gtest.h"
24 #include "testing/platform_test.h"
26 #if defined(OS_ANDROID)
27 #include "base/test/test_file_util.h"
28 #endif
30 namespace net {
32 namespace {
34 const char kTestData[] = "0123456789";
35 const int kTestDataSize = arraysize(kTestData) - 1;
37 // Creates an IOBufferWithSize that contains the kTestDataSize.
38 IOBufferWithSize* CreateTestDataBuffer() {
39 IOBufferWithSize* buf = new IOBufferWithSize(kTestDataSize);
40 memcpy(buf->data(), kTestData, kTestDataSize);
41 return buf;
44 } // namespace
46 class FileStreamTest : public PlatformTest {
47 public:
48 virtual void SetUp() {
49 PlatformTest::SetUp();
51 base::CreateTemporaryFile(&temp_file_path_);
52 base::WriteFile(temp_file_path_, kTestData, kTestDataSize);
54 virtual void TearDown() {
55 // FileStreamContexts must be asynchronously closed on the file task runner
56 // before they can be deleted. Pump the RunLoop to avoid leaks.
57 base::RunLoop().RunUntilIdle();
58 EXPECT_TRUE(base::DeleteFile(temp_file_path_, false));
60 PlatformTest::TearDown();
63 const base::FilePath temp_file_path() const { return temp_file_path_; }
65 private:
66 base::FilePath temp_file_path_;
69 namespace {
71 TEST_F(FileStreamTest, AsyncOpenExplicitClose) {
72 TestCompletionCallback callback;
73 FileStream stream(base::MessageLoopProxy::current());
74 int flags = base::File::FLAG_OPEN |
75 base::File::FLAG_READ |
76 base::File::FLAG_ASYNC;
77 int rv = stream.Open(temp_file_path(), flags, callback.callback());
78 EXPECT_EQ(ERR_IO_PENDING, rv);
79 EXPECT_EQ(OK, callback.WaitForResult());
80 EXPECT_TRUE(stream.IsOpen());
81 EXPECT_TRUE(stream.GetFileForTesting().IsValid());
82 EXPECT_EQ(ERR_IO_PENDING, stream.Close(callback.callback()));
83 EXPECT_EQ(OK, callback.WaitForResult());
84 EXPECT_FALSE(stream.IsOpen());
85 EXPECT_FALSE(stream.GetFileForTesting().IsValid());
88 TEST_F(FileStreamTest, AsyncOpenExplicitCloseOrphaned) {
89 TestCompletionCallback callback;
90 scoped_ptr<FileStream> stream(new FileStream(
91 base::MessageLoopProxy::current()));
92 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
93 base::File::FLAG_ASYNC;
94 int rv = stream->Open(temp_file_path(), flags, callback.callback());
95 EXPECT_EQ(ERR_IO_PENDING, rv);
96 EXPECT_EQ(OK, callback.WaitForResult());
97 EXPECT_TRUE(stream->IsOpen());
98 EXPECT_TRUE(stream->GetFileForTesting().IsValid());
99 EXPECT_EQ(ERR_IO_PENDING, stream->Close(callback.callback()));
100 stream.reset();
101 // File isn't actually closed yet.
102 base::RunLoop runloop;
103 runloop.RunUntilIdle();
104 // The file should now be closed, though the callback has not been called.
107 // Test the use of FileStream with a file handle provided at construction.
108 TEST_F(FileStreamTest, UseFileHandle) {
109 int rv = 0;
110 TestCompletionCallback callback;
111 TestInt64CompletionCallback callback64;
112 // 1. Test reading with a file handle.
113 ASSERT_EQ(kTestDataSize,
114 base::WriteFile(temp_file_path(), kTestData, kTestDataSize));
115 int flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
116 base::File::FLAG_ASYNC;
117 base::File file(temp_file_path(), flags);
119 // Seek to the beginning of the file and read.
120 scoped_ptr<FileStream> read_stream(
121 new FileStream(file.Pass(), base::MessageLoopProxy::current()));
122 ASSERT_EQ(ERR_IO_PENDING,
123 read_stream->Seek(FROM_BEGIN, 0, callback64.callback()));
124 ASSERT_EQ(0, callback64.WaitForResult());
125 // Read into buffer and compare.
126 scoped_refptr<IOBufferWithSize> read_buffer =
127 new IOBufferWithSize(kTestDataSize);
128 rv = read_stream->Read(read_buffer.get(), kTestDataSize, callback.callback());
129 ASSERT_EQ(kTestDataSize, callback.GetResult(rv));
130 ASSERT_EQ(0, memcmp(kTestData, read_buffer->data(), kTestDataSize));
131 read_stream.reset();
133 // 2. Test writing with a file handle.
134 base::DeleteFile(temp_file_path(), false);
135 flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE |
136 base::File::FLAG_ASYNC;
137 file.Initialize(temp_file_path(), flags);
139 scoped_ptr<FileStream> write_stream(
140 new FileStream(file.Pass(), base::MessageLoopProxy::current()));
141 ASSERT_EQ(ERR_IO_PENDING,
142 write_stream->Seek(FROM_BEGIN, 0, callback64.callback()));
143 ASSERT_EQ(0, callback64.WaitForResult());
144 scoped_refptr<IOBufferWithSize> write_buffer = CreateTestDataBuffer();
145 rv = write_stream->Write(write_buffer.get(), kTestDataSize,
146 callback.callback());
147 ASSERT_EQ(kTestDataSize, callback.GetResult(rv));
148 write_stream.reset();
150 // Read into buffer and compare to make sure the handle worked fine.
151 ASSERT_EQ(kTestDataSize,
152 base::ReadFile(temp_file_path(), read_buffer->data(),
153 kTestDataSize));
154 ASSERT_EQ(0, memcmp(kTestData, read_buffer->data(), kTestDataSize));
157 TEST_F(FileStreamTest, UseClosedStream) {
158 int rv = 0;
159 TestCompletionCallback callback;
160 TestInt64CompletionCallback callback64;
162 FileStream stream(base::MessageLoopProxy::current());
164 EXPECT_FALSE(stream.IsOpen());
166 // Try seeking...
167 rv = stream.Seek(FROM_BEGIN, 5, callback64.callback());
168 EXPECT_EQ(ERR_UNEXPECTED, callback64.GetResult(rv));
170 // Try reading...
171 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(10);
172 rv = stream.Read(buf, buf->size(), callback.callback());
173 EXPECT_EQ(ERR_UNEXPECTED, callback.GetResult(rv));
176 TEST_F(FileStreamTest, AsyncRead) {
177 int64 file_size;
178 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
180 FileStream stream(base::MessageLoopProxy::current());
181 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
182 base::File::FLAG_ASYNC;
183 TestCompletionCallback callback;
184 int rv = stream.Open(temp_file_path(), flags, callback.callback());
185 EXPECT_EQ(ERR_IO_PENDING, rv);
186 EXPECT_EQ(OK, callback.WaitForResult());
188 int total_bytes_read = 0;
190 std::string data_read;
191 for (;;) {
192 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
193 rv = stream.Read(buf.get(), buf->size(), callback.callback());
194 if (rv == ERR_IO_PENDING)
195 rv = callback.WaitForResult();
196 EXPECT_LE(0, rv);
197 if (rv <= 0)
198 break;
199 total_bytes_read += rv;
200 data_read.append(buf->data(), rv);
202 EXPECT_EQ(file_size, total_bytes_read);
203 EXPECT_EQ(kTestData, data_read);
206 TEST_F(FileStreamTest, AsyncRead_EarlyDelete) {
207 int64 file_size;
208 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
210 scoped_ptr<FileStream> stream(
211 new FileStream(base::MessageLoopProxy::current()));
212 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
213 base::File::FLAG_ASYNC;
214 TestCompletionCallback callback;
215 int rv = stream->Open(temp_file_path(), flags, callback.callback());
216 EXPECT_EQ(ERR_IO_PENDING, rv);
217 EXPECT_EQ(OK, callback.WaitForResult());
219 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
220 rv = stream->Read(buf.get(), buf->size(), callback.callback());
221 stream.reset(); // Delete instead of closing it.
222 if (rv < 0) {
223 EXPECT_EQ(ERR_IO_PENDING, rv);
224 // The callback should not be called if the request is cancelled.
225 base::RunLoop().RunUntilIdle();
226 EXPECT_FALSE(callback.have_result());
227 } else {
228 EXPECT_EQ(std::string(kTestData, rv), std::string(buf->data(), rv));
232 TEST_F(FileStreamTest, AsyncRead_FromOffset) {
233 int64 file_size;
234 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
236 FileStream stream(base::MessageLoopProxy::current());
237 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
238 base::File::FLAG_ASYNC;
239 TestCompletionCallback callback;
240 int rv = stream.Open(temp_file_path(), flags, callback.callback());
241 EXPECT_EQ(ERR_IO_PENDING, rv);
242 EXPECT_EQ(OK, callback.WaitForResult());
244 TestInt64CompletionCallback callback64;
245 const int64 kOffset = 3;
246 rv = stream.Seek(FROM_BEGIN, kOffset, callback64.callback());
247 ASSERT_EQ(ERR_IO_PENDING, rv);
248 int64 new_offset = callback64.WaitForResult();
249 EXPECT_EQ(kOffset, new_offset);
251 int total_bytes_read = 0;
253 std::string data_read;
254 for (;;) {
255 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
256 rv = stream.Read(buf.get(), buf->size(), callback.callback());
257 if (rv == ERR_IO_PENDING)
258 rv = callback.WaitForResult();
259 EXPECT_LE(0, rv);
260 if (rv <= 0)
261 break;
262 total_bytes_read += rv;
263 data_read.append(buf->data(), rv);
265 EXPECT_EQ(file_size - kOffset, total_bytes_read);
266 EXPECT_EQ(kTestData + kOffset, data_read);
269 TEST_F(FileStreamTest, AsyncSeekAround) {
270 FileStream stream(base::MessageLoopProxy::current());
271 int flags = base::File::FLAG_OPEN | base::File::FLAG_ASYNC |
272 base::File::FLAG_READ;
273 TestCompletionCallback callback;
274 int rv = stream.Open(temp_file_path(), flags, callback.callback());
275 EXPECT_EQ(ERR_IO_PENDING, rv);
276 EXPECT_EQ(OK, callback.WaitForResult());
278 TestInt64CompletionCallback callback64;
280 const int64 kOffset = 3;
281 rv = stream.Seek(FROM_BEGIN, kOffset, callback64.callback());
282 ASSERT_EQ(ERR_IO_PENDING, rv);
283 int64 new_offset = callback64.WaitForResult();
284 EXPECT_EQ(kOffset, new_offset);
286 rv = stream.Seek(FROM_CURRENT, kOffset, callback64.callback());
287 ASSERT_EQ(ERR_IO_PENDING, rv);
288 new_offset = callback64.WaitForResult();
289 EXPECT_EQ(2 * kOffset, new_offset);
291 rv = stream.Seek(FROM_CURRENT, -kOffset, callback64.callback());
292 ASSERT_EQ(ERR_IO_PENDING, rv);
293 new_offset = callback64.WaitForResult();
294 EXPECT_EQ(kOffset, new_offset);
296 const int kTestDataLen = arraysize(kTestData) - 1;
298 rv = stream.Seek(FROM_END, -kTestDataLen, callback64.callback());
299 ASSERT_EQ(ERR_IO_PENDING, rv);
300 new_offset = callback64.WaitForResult();
301 EXPECT_EQ(0, new_offset);
304 TEST_F(FileStreamTest, AsyncWrite) {
305 FileStream stream(base::MessageLoopProxy::current());
306 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
307 base::File::FLAG_ASYNC;
308 TestCompletionCallback callback;
309 int rv = stream.Open(temp_file_path(), flags, callback.callback());
310 EXPECT_EQ(ERR_IO_PENDING, rv);
311 EXPECT_EQ(OK, callback.WaitForResult());
313 int64 file_size;
314 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
315 EXPECT_EQ(0, file_size);
317 int total_bytes_written = 0;
319 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
320 scoped_refptr<DrainableIOBuffer> drainable =
321 new DrainableIOBuffer(buf.get(), buf->size());
322 while (total_bytes_written != kTestDataSize) {
323 rv = stream.Write(drainable.get(), drainable->BytesRemaining(),
324 callback.callback());
325 if (rv == ERR_IO_PENDING)
326 rv = callback.WaitForResult();
327 EXPECT_LT(0, rv);
328 if (rv <= 0)
329 break;
330 drainable->DidConsume(rv);
331 total_bytes_written += rv;
333 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
334 EXPECT_EQ(file_size, total_bytes_written);
337 TEST_F(FileStreamTest, AsyncWrite_EarlyDelete) {
338 scoped_ptr<FileStream> stream(
339 new FileStream(base::MessageLoopProxy::current()));
340 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
341 base::File::FLAG_ASYNC;
342 TestCompletionCallback callback;
343 int rv = stream->Open(temp_file_path(), flags, callback.callback());
344 EXPECT_EQ(ERR_IO_PENDING, rv);
345 EXPECT_EQ(OK, callback.WaitForResult());
347 int64 file_size;
348 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
349 EXPECT_EQ(0, file_size);
351 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
352 rv = stream->Write(buf.get(), buf->size(), callback.callback());
353 stream.reset();
354 if (rv < 0) {
355 EXPECT_EQ(ERR_IO_PENDING, rv);
356 // The callback should not be called if the request is cancelled.
357 base::RunLoop().RunUntilIdle();
358 EXPECT_FALSE(callback.have_result());
359 } else {
360 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
361 EXPECT_EQ(file_size, rv);
365 TEST_F(FileStreamTest, AsyncWrite_FromOffset) {
366 int64 file_size;
367 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
369 FileStream stream(base::MessageLoopProxy::current());
370 int flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
371 base::File::FLAG_ASYNC;
372 TestCompletionCallback callback;
373 int rv = stream.Open(temp_file_path(), flags, callback.callback());
374 EXPECT_EQ(ERR_IO_PENDING, rv);
375 EXPECT_EQ(OK, callback.WaitForResult());
377 TestInt64CompletionCallback callback64;
378 const int64 kOffset = 0;
379 rv = stream.Seek(FROM_END, kOffset, callback64.callback());
380 ASSERT_EQ(ERR_IO_PENDING, rv);
381 int64 new_offset = callback64.WaitForResult();
382 EXPECT_EQ(kTestDataSize, new_offset);
384 int total_bytes_written = 0;
386 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
387 scoped_refptr<DrainableIOBuffer> drainable =
388 new DrainableIOBuffer(buf.get(), buf->size());
389 while (total_bytes_written != kTestDataSize) {
390 rv = stream.Write(drainable.get(), drainable->BytesRemaining(),
391 callback.callback());
392 if (rv == ERR_IO_PENDING)
393 rv = callback.WaitForResult();
394 EXPECT_LT(0, rv);
395 if (rv <= 0)
396 break;
397 drainable->DidConsume(rv);
398 total_bytes_written += rv;
400 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
401 EXPECT_EQ(file_size, kTestDataSize * 2);
404 TEST_F(FileStreamTest, BasicAsyncReadWrite) {
405 int64 file_size;
406 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
408 scoped_ptr<FileStream> stream(
409 new FileStream(base::MessageLoopProxy::current()));
410 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
411 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
412 TestCompletionCallback callback;
413 int rv = stream->Open(temp_file_path(), flags, callback.callback());
414 EXPECT_EQ(ERR_IO_PENDING, rv);
415 EXPECT_EQ(OK, callback.WaitForResult());
417 int64 total_bytes_read = 0;
419 std::string data_read;
420 for (;;) {
421 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
422 rv = stream->Read(buf.get(), buf->size(), callback.callback());
423 if (rv == ERR_IO_PENDING)
424 rv = callback.WaitForResult();
425 EXPECT_LE(0, rv);
426 if (rv <= 0)
427 break;
428 total_bytes_read += rv;
429 data_read.append(buf->data(), rv);
431 EXPECT_EQ(file_size, total_bytes_read);
432 EXPECT_TRUE(data_read == kTestData);
434 int total_bytes_written = 0;
436 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
437 scoped_refptr<DrainableIOBuffer> drainable =
438 new DrainableIOBuffer(buf.get(), buf->size());
439 while (total_bytes_written != kTestDataSize) {
440 rv = stream->Write(drainable.get(), drainable->BytesRemaining(),
441 callback.callback());
442 if (rv == ERR_IO_PENDING)
443 rv = callback.WaitForResult();
444 EXPECT_LT(0, rv);
445 if (rv <= 0)
446 break;
447 drainable->DidConsume(rv);
448 total_bytes_written += rv;
451 stream.reset();
453 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
454 EXPECT_EQ(kTestDataSize * 2, file_size);
457 TEST_F(FileStreamTest, BasicAsyncWriteRead) {
458 int64 file_size;
459 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
461 scoped_ptr<FileStream> stream(
462 new FileStream(base::MessageLoopProxy::current()));
463 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
464 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
465 TestCompletionCallback callback;
466 int rv = stream->Open(temp_file_path(), flags, callback.callback());
467 EXPECT_EQ(ERR_IO_PENDING, rv);
468 EXPECT_EQ(OK, callback.WaitForResult());
470 TestInt64CompletionCallback callback64;
471 rv = stream->Seek(FROM_END, 0, callback64.callback());
472 ASSERT_EQ(ERR_IO_PENDING, rv);
473 int64 offset = callback64.WaitForResult();
474 EXPECT_EQ(offset, file_size);
476 int total_bytes_written = 0;
478 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
479 scoped_refptr<DrainableIOBuffer> drainable =
480 new DrainableIOBuffer(buf.get(), buf->size());
481 while (total_bytes_written != kTestDataSize) {
482 rv = stream->Write(drainable.get(), drainable->BytesRemaining(),
483 callback.callback());
484 if (rv == ERR_IO_PENDING)
485 rv = callback.WaitForResult();
486 EXPECT_LT(0, rv);
487 if (rv <= 0)
488 break;
489 drainable->DidConsume(rv);
490 total_bytes_written += rv;
493 EXPECT_EQ(kTestDataSize, total_bytes_written);
495 rv = stream->Seek(FROM_BEGIN, 0, callback64.callback());
496 ASSERT_EQ(ERR_IO_PENDING, rv);
497 offset = callback64.WaitForResult();
498 EXPECT_EQ(0, offset);
500 int total_bytes_read = 0;
502 std::string data_read;
503 for (;;) {
504 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
505 rv = stream->Read(buf.get(), buf->size(), callback.callback());
506 if (rv == ERR_IO_PENDING)
507 rv = callback.WaitForResult();
508 EXPECT_LE(0, rv);
509 if (rv <= 0)
510 break;
511 total_bytes_read += rv;
512 data_read.append(buf->data(), rv);
514 stream.reset();
516 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
517 EXPECT_EQ(kTestDataSize * 2, file_size);
519 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
520 const std::string kExpectedFileData =
521 std::string(kTestData) + std::string(kTestData);
522 EXPECT_EQ(kExpectedFileData, data_read);
525 class TestWriteReadCompletionCallback {
526 public:
527 TestWriteReadCompletionCallback(FileStream* stream,
528 int* total_bytes_written,
529 int* total_bytes_read,
530 std::string* data_read)
531 : result_(0),
532 have_result_(false),
533 waiting_for_result_(false),
534 stream_(stream),
535 total_bytes_written_(total_bytes_written),
536 total_bytes_read_(total_bytes_read),
537 data_read_(data_read),
538 callback_(base::Bind(&TestWriteReadCompletionCallback::OnComplete,
539 base::Unretained(this))),
540 test_data_(CreateTestDataBuffer()),
541 drainable_(new DrainableIOBuffer(test_data_.get(), kTestDataSize)) {}
543 int WaitForResult() {
544 DCHECK(!waiting_for_result_);
545 while (!have_result_) {
546 waiting_for_result_ = true;
547 base::RunLoop().Run();
548 waiting_for_result_ = false;
550 have_result_ = false; // auto-reset for next callback
551 return result_;
554 const CompletionCallback& callback() const { return callback_; }
556 private:
557 void OnComplete(int result) {
558 DCHECK_LT(0, result);
559 *total_bytes_written_ += result;
561 int rv;
563 if (*total_bytes_written_ != kTestDataSize) {
564 // Recurse to finish writing all data.
565 int total_bytes_written = 0, total_bytes_read = 0;
566 std::string data_read;
567 TestWriteReadCompletionCallback callback(
568 stream_, &total_bytes_written, &total_bytes_read, &data_read);
569 rv = stream_->Write(
570 drainable_.get(), drainable_->BytesRemaining(), callback.callback());
571 DCHECK_EQ(ERR_IO_PENDING, rv);
572 rv = callback.WaitForResult();
573 drainable_->DidConsume(total_bytes_written);
574 *total_bytes_written_ += total_bytes_written;
575 *total_bytes_read_ += total_bytes_read;
576 *data_read_ += data_read;
577 } else { // We're done writing all data. Start reading the data.
578 TestInt64CompletionCallback callback64;
579 EXPECT_EQ(ERR_IO_PENDING,
580 stream_->Seek(FROM_BEGIN, 0, callback64.callback()));
582 base::MessageLoop::ScopedNestableTaskAllower allow(
583 base::MessageLoop::current());
584 EXPECT_LE(0, callback64.WaitForResult());
587 TestCompletionCallback callback;
588 for (;;) {
589 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
590 rv = stream_->Read(buf.get(), buf->size(), callback.callback());
591 if (rv == ERR_IO_PENDING) {
592 base::MessageLoop::ScopedNestableTaskAllower allow(
593 base::MessageLoop::current());
594 rv = callback.WaitForResult();
596 EXPECT_LE(0, rv);
597 if (rv <= 0)
598 break;
599 *total_bytes_read_ += rv;
600 data_read_->append(buf->data(), rv);
604 result_ = *total_bytes_written_;
605 have_result_ = true;
606 if (waiting_for_result_)
607 base::MessageLoop::current()->Quit();
610 int result_;
611 bool have_result_;
612 bool waiting_for_result_;
613 FileStream* stream_;
614 int* total_bytes_written_;
615 int* total_bytes_read_;
616 std::string* data_read_;
617 const CompletionCallback callback_;
618 scoped_refptr<IOBufferWithSize> test_data_;
619 scoped_refptr<DrainableIOBuffer> drainable_;
621 DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback);
624 TEST_F(FileStreamTest, AsyncWriteRead) {
625 int64 file_size;
626 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
628 scoped_ptr<FileStream> stream(
629 new FileStream(base::MessageLoopProxy::current()));
630 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
631 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
632 TestCompletionCallback open_callback;
633 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
634 EXPECT_EQ(ERR_IO_PENDING, rv);
635 EXPECT_EQ(OK, open_callback.WaitForResult());
637 TestInt64CompletionCallback callback64;
638 EXPECT_EQ(ERR_IO_PENDING, stream->Seek(FROM_END, 0, callback64.callback()));
639 EXPECT_EQ(file_size, callback64.WaitForResult());
641 int total_bytes_written = 0;
642 int total_bytes_read = 0;
643 std::string data_read;
644 TestWriteReadCompletionCallback callback(stream.get(), &total_bytes_written,
645 &total_bytes_read, &data_read);
647 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
648 rv = stream->Write(buf.get(), buf->size(), callback.callback());
649 if (rv == ERR_IO_PENDING)
650 rv = callback.WaitForResult();
651 EXPECT_LT(0, rv);
652 EXPECT_EQ(kTestDataSize, total_bytes_written);
654 stream.reset();
656 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
657 EXPECT_EQ(kTestDataSize * 2, file_size);
659 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
660 const std::string kExpectedFileData =
661 std::string(kTestData) + std::string(kTestData);
662 EXPECT_EQ(kExpectedFileData, data_read);
665 class TestWriteCloseCompletionCallback {
666 public:
667 TestWriteCloseCompletionCallback(FileStream* stream, int* total_bytes_written)
668 : result_(0),
669 have_result_(false),
670 waiting_for_result_(false),
671 stream_(stream),
672 total_bytes_written_(total_bytes_written),
673 callback_(base::Bind(&TestWriteCloseCompletionCallback::OnComplete,
674 base::Unretained(this))),
675 test_data_(CreateTestDataBuffer()),
676 drainable_(new DrainableIOBuffer(test_data_.get(), kTestDataSize)) {}
678 int WaitForResult() {
679 DCHECK(!waiting_for_result_);
680 while (!have_result_) {
681 waiting_for_result_ = true;
682 base::RunLoop().Run();
683 waiting_for_result_ = false;
685 have_result_ = false; // auto-reset for next callback
686 return result_;
689 const CompletionCallback& callback() const { return callback_; }
691 private:
692 void OnComplete(int result) {
693 DCHECK_LT(0, result);
694 *total_bytes_written_ += result;
696 int rv;
698 if (*total_bytes_written_ != kTestDataSize) {
699 // Recurse to finish writing all data.
700 int total_bytes_written = 0;
701 TestWriteCloseCompletionCallback callback(stream_, &total_bytes_written);
702 rv = stream_->Write(
703 drainable_.get(), drainable_->BytesRemaining(), callback.callback());
704 DCHECK_EQ(ERR_IO_PENDING, rv);
705 rv = callback.WaitForResult();
706 drainable_->DidConsume(total_bytes_written);
707 *total_bytes_written_ += total_bytes_written;
710 result_ = *total_bytes_written_;
711 have_result_ = true;
712 if (waiting_for_result_)
713 base::MessageLoop::current()->Quit();
716 int result_;
717 bool have_result_;
718 bool waiting_for_result_;
719 FileStream* stream_;
720 int* total_bytes_written_;
721 const CompletionCallback callback_;
722 scoped_refptr<IOBufferWithSize> test_data_;
723 scoped_refptr<DrainableIOBuffer> drainable_;
725 DISALLOW_COPY_AND_ASSIGN(TestWriteCloseCompletionCallback);
728 TEST_F(FileStreamTest, AsyncWriteClose) {
729 int64 file_size;
730 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
732 scoped_ptr<FileStream> stream(
733 new FileStream(base::MessageLoopProxy::current()));
734 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
735 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
736 TestCompletionCallback open_callback;
737 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
738 EXPECT_EQ(ERR_IO_PENDING, rv);
739 EXPECT_EQ(OK, open_callback.WaitForResult());
741 TestInt64CompletionCallback callback64;
742 EXPECT_EQ(ERR_IO_PENDING, stream->Seek(FROM_END, 0, callback64.callback()));
743 EXPECT_EQ(file_size, callback64.WaitForResult());
745 int total_bytes_written = 0;
746 TestWriteCloseCompletionCallback callback(stream.get(), &total_bytes_written);
748 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
749 rv = stream->Write(buf.get(), buf->size(), callback.callback());
750 if (rv == ERR_IO_PENDING)
751 total_bytes_written = callback.WaitForResult();
752 EXPECT_LT(0, total_bytes_written);
753 EXPECT_EQ(kTestDataSize, total_bytes_written);
755 stream.reset();
757 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
758 EXPECT_EQ(kTestDataSize * 2, file_size);
761 TEST_F(FileStreamTest, AsyncOpenAndDelete) {
762 scoped_refptr<base::SequencedWorkerPool> pool(
763 new base::SequencedWorkerPool(1, "StreamTest"));
765 bool prev = base::ThreadRestrictions::SetIOAllowed(false);
766 scoped_ptr<FileStream> stream(new FileStream(pool.get()));
767 int flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
768 base::File::FLAG_ASYNC;
769 TestCompletionCallback open_callback;
770 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
771 EXPECT_EQ(ERR_IO_PENDING, rv);
773 // Delete the stream without waiting for the open operation to be
774 // complete. Should be safe.
775 stream.reset();
777 // Force an operation through the pool.
778 scoped_ptr<FileStream> stream2(new FileStream(pool.get()));
779 TestCompletionCallback open_callback2;
780 rv = stream2->Open(temp_file_path(), flags, open_callback2.callback());
781 EXPECT_EQ(OK, open_callback2.GetResult(rv));
782 stream2.reset();
784 pool->Shutdown();
786 // open_callback won't be called.
787 base::RunLoop().RunUntilIdle();
788 EXPECT_FALSE(open_callback.have_result());
789 base::ThreadRestrictions::SetIOAllowed(prev);
792 // Verify that async Write() errors are mapped correctly.
793 TEST_F(FileStreamTest, AsyncWriteError) {
794 // Try opening file as read-only and then writing to it using FileStream.
795 uint32 flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
796 base::File::FLAG_ASYNC;
798 base::File file(temp_file_path(), flags);
799 ASSERT_TRUE(file.IsValid());
801 scoped_ptr<FileStream> stream(
802 new FileStream(file.Pass(), base::MessageLoopProxy::current()));
804 scoped_refptr<IOBuffer> buf = new IOBuffer(1);
805 buf->data()[0] = 0;
807 TestCompletionCallback callback;
808 int rv = stream->Write(buf.get(), 1, callback.callback());
809 if (rv == ERR_IO_PENDING)
810 rv = callback.WaitForResult();
811 EXPECT_LT(rv, 0);
813 stream.reset();
814 base::RunLoop().RunUntilIdle();
817 // Verify that async Read() errors are mapped correctly.
818 TEST_F(FileStreamTest, AsyncReadError) {
819 // Try opening file for write and then reading from it using FileStream.
820 uint32 flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
821 base::File::FLAG_ASYNC;
823 base::File file(temp_file_path(), flags);
824 ASSERT_TRUE(file.IsValid());
826 scoped_ptr<FileStream> stream(
827 new FileStream(file.Pass(), base::MessageLoopProxy::current()));
829 scoped_refptr<IOBuffer> buf = new IOBuffer(1);
830 TestCompletionCallback callback;
831 int rv = stream->Read(buf.get(), 1, callback.callback());
832 if (rv == ERR_IO_PENDING)
833 rv = callback.WaitForResult();
834 EXPECT_LT(rv, 0);
836 stream.reset();
837 base::RunLoop().RunUntilIdle();
840 #if defined(OS_ANDROID)
841 TEST_F(FileStreamTest, ContentUriAsyncRead) {
842 base::FilePath test_dir;
843 PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
844 test_dir = test_dir.AppendASCII("net");
845 test_dir = test_dir.AppendASCII("data");
846 test_dir = test_dir.AppendASCII("file_stream_unittest");
847 ASSERT_TRUE(base::PathExists(test_dir));
848 base::FilePath image_file = test_dir.Append(FILE_PATH_LITERAL("red.png"));
850 // Insert the image into MediaStore. MediaStore will do some conversions, and
851 // return the content URI.
852 base::FilePath path = file_util::InsertImageIntoMediaStore(image_file);
853 EXPECT_TRUE(path.IsContentUri());
854 EXPECT_TRUE(base::PathExists(path));
855 int64 file_size;
856 EXPECT_TRUE(base::GetFileSize(path, &file_size));
857 EXPECT_LT(0, file_size);
859 FileStream stream(base::MessageLoopProxy::current());
860 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
861 base::File::FLAG_ASYNC;
862 TestCompletionCallback callback;
863 int rv = stream.Open(path, flags, callback.callback());
864 EXPECT_EQ(ERR_IO_PENDING, rv);
865 EXPECT_EQ(OK, callback.WaitForResult());
867 int total_bytes_read = 0;
869 std::string data_read;
870 for (;;) {
871 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
872 rv = stream.Read(buf.get(), buf->size(), callback.callback());
873 if (rv == ERR_IO_PENDING)
874 rv = callback.WaitForResult();
875 EXPECT_LE(0, rv);
876 if (rv <= 0)
877 break;
878 total_bytes_read += rv;
879 data_read.append(buf->data(), rv);
881 EXPECT_EQ(file_size, total_bytes_read);
883 #endif
885 } // namespace
887 } // namespace net