Add notranslate meta tag on dir_header.html
[chromium-blink-merge.git] / net / base / file_stream_unittest.cc
blob8b47eccf4144185da0a990c7f60a85fa848b7080
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/message_loop/message_loop_proxy.h"
13 #include "base/path_service.h"
14 #include "base/run_loop.h"
15 #include "base/strings/string_util.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/test/test_timeouts.h"
18 #include "base/threading/sequenced_worker_pool.h"
19 #include "base/threading/thread_restrictions.h"
20 #include "net/base/capturing_net_log.h"
21 #include "net/base/io_buffer.h"
22 #include "net/base/net_errors.h"
23 #include "net/base/test_completion_callback.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::MessageLoopProxy::current());
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_TRUE(stream.GetFileForTesting().IsValid());
83 EXPECT_EQ(ERR_IO_PENDING, stream.Close(callback.callback()));
84 EXPECT_EQ(OK, callback.WaitForResult());
85 EXPECT_FALSE(stream.IsOpen());
86 EXPECT_FALSE(stream.GetFileForTesting().IsValid());
89 TEST_F(FileStreamTest, OpenExplicitCloseOrphaned) {
90 TestCompletionCallback callback;
91 scoped_ptr<FileStream> stream(new FileStream(
92 base::MessageLoopProxy::current()));
93 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
94 base::File::FLAG_ASYNC;
95 int rv = stream->Open(temp_file_path(), flags, callback.callback());
96 EXPECT_EQ(ERR_IO_PENDING, rv);
97 EXPECT_EQ(OK, callback.WaitForResult());
98 EXPECT_TRUE(stream->IsOpen());
99 EXPECT_TRUE(stream->GetFileForTesting().IsValid());
100 EXPECT_EQ(ERR_IO_PENDING, stream->Close(callback.callback()));
101 stream.reset();
102 // File isn't actually closed yet.
103 base::RunLoop runloop;
104 runloop.RunUntilIdle();
105 // The file should now be closed, though the callback has not been called.
108 // Test the use of FileStream with a file handle provided at construction.
109 TEST_F(FileStreamTest, UseFileHandle) {
110 int rv = 0;
111 TestCompletionCallback callback;
112 TestInt64CompletionCallback callback64;
113 // 1. Test reading with a file handle.
114 ASSERT_EQ(kTestDataSize,
115 base::WriteFile(temp_file_path(), kTestData, kTestDataSize));
116 int flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
117 base::File::FLAG_ASYNC;
118 base::File file(temp_file_path(), flags);
120 // Seek to the beginning of the file and read.
121 scoped_ptr<FileStream> read_stream(
122 new FileStream(file.Pass(), base::MessageLoopProxy::current()));
123 ASSERT_EQ(ERR_IO_PENDING,
124 read_stream->Seek(base::File::FROM_BEGIN, 0,
125 callback64.callback()));
126 ASSERT_EQ(0, callback64.WaitForResult());
127 // Read into buffer and compare.
128 scoped_refptr<IOBufferWithSize> read_buffer =
129 new IOBufferWithSize(kTestDataSize);
130 rv = read_stream->Read(read_buffer.get(), kTestDataSize, callback.callback());
131 ASSERT_EQ(kTestDataSize, callback.GetResult(rv));
132 ASSERT_EQ(0, memcmp(kTestData, read_buffer->data(), kTestDataSize));
133 read_stream.reset();
135 // 2. Test writing with a file handle.
136 base::DeleteFile(temp_file_path(), false);
137 flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE |
138 base::File::FLAG_ASYNC;
139 file.Initialize(temp_file_path(), flags);
141 scoped_ptr<FileStream> write_stream(
142 new FileStream(file.Pass(), base::MessageLoopProxy::current()));
143 ASSERT_EQ(ERR_IO_PENDING,
144 write_stream->Seek(base::File::FROM_BEGIN, 0,
145 callback64.callback()));
146 ASSERT_EQ(0, callback64.WaitForResult());
147 scoped_refptr<IOBufferWithSize> write_buffer = CreateTestDataBuffer();
148 rv = write_stream->Write(write_buffer.get(), kTestDataSize,
149 callback.callback());
150 ASSERT_EQ(kTestDataSize, callback.GetResult(rv));
151 write_stream.reset();
153 // Read into buffer and compare to make sure the handle worked fine.
154 ASSERT_EQ(kTestDataSize,
155 base::ReadFile(temp_file_path(), read_buffer->data(),
156 kTestDataSize));
157 ASSERT_EQ(0, memcmp(kTestData, read_buffer->data(), kTestDataSize));
160 TEST_F(FileStreamTest, UseClosedStream) {
161 int rv = 0;
162 TestCompletionCallback callback;
163 TestInt64CompletionCallback callback64;
165 FileStream stream(base::MessageLoopProxy::current());
167 EXPECT_FALSE(stream.IsOpen());
169 // Try seeking...
170 rv = stream.Seek(base::File::FROM_BEGIN, 5, callback64.callback());
171 EXPECT_EQ(ERR_UNEXPECTED, callback64.GetResult(rv));
173 // Try reading...
174 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(10);
175 rv = stream.Read(buf.get(), buf->size(), callback.callback());
176 EXPECT_EQ(ERR_UNEXPECTED, callback.GetResult(rv));
179 TEST_F(FileStreamTest, Read) {
180 int64 file_size;
181 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
183 FileStream stream(base::MessageLoopProxy::current());
184 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
185 base::File::FLAG_ASYNC;
186 TestCompletionCallback callback;
187 int rv = stream.Open(temp_file_path(), flags, callback.callback());
188 EXPECT_EQ(OK, callback.GetResult(rv));
190 int total_bytes_read = 0;
192 std::string data_read;
193 for (;;) {
194 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
195 rv = stream.Read(buf.get(), buf->size(), callback.callback());
196 rv = callback.GetResult(rv);
197 EXPECT_LE(0, rv);
198 if (rv <= 0)
199 break;
200 total_bytes_read += rv;
201 data_read.append(buf->data(), rv);
203 EXPECT_EQ(file_size, total_bytes_read);
204 EXPECT_EQ(kTestData, data_read);
207 TEST_F(FileStreamTest, Read_EarlyDelete) {
208 int64 file_size;
209 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
211 scoped_ptr<FileStream> stream(
212 new FileStream(base::MessageLoopProxy::current()));
213 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
214 base::File::FLAG_ASYNC;
215 TestCompletionCallback callback;
216 int rv = stream->Open(temp_file_path(), flags, callback.callback());
217 EXPECT_EQ(ERR_IO_PENDING, rv);
218 EXPECT_EQ(OK, callback.WaitForResult());
220 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
221 rv = stream->Read(buf.get(), buf->size(), callback.callback());
222 stream.reset(); // Delete instead of closing it.
223 if (rv < 0) {
224 EXPECT_EQ(ERR_IO_PENDING, rv);
225 // The callback should not be called if the request is cancelled.
226 base::RunLoop().RunUntilIdle();
227 EXPECT_FALSE(callback.have_result());
228 } else {
229 EXPECT_EQ(std::string(kTestData, rv), std::string(buf->data(), rv));
233 TEST_F(FileStreamTest, Read_FromOffset) {
234 int64 file_size;
235 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
237 FileStream stream(base::MessageLoopProxy::current());
238 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
239 base::File::FLAG_ASYNC;
240 TestCompletionCallback callback;
241 int rv = stream.Open(temp_file_path(), flags, callback.callback());
242 EXPECT_EQ(ERR_IO_PENDING, rv);
243 EXPECT_EQ(OK, callback.WaitForResult());
245 TestInt64CompletionCallback callback64;
246 const int64 kOffset = 3;
247 rv = stream.Seek(base::File::FROM_BEGIN, kOffset, callback64.callback());
248 ASSERT_EQ(ERR_IO_PENDING, rv);
249 int64 new_offset = callback64.WaitForResult();
250 EXPECT_EQ(kOffset, new_offset);
252 int total_bytes_read = 0;
254 std::string data_read;
255 for (;;) {
256 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
257 rv = stream.Read(buf.get(), buf->size(), callback.callback());
258 if (rv == ERR_IO_PENDING)
259 rv = callback.WaitForResult();
260 EXPECT_LE(0, rv);
261 if (rv <= 0)
262 break;
263 total_bytes_read += rv;
264 data_read.append(buf->data(), rv);
266 EXPECT_EQ(file_size - kOffset, total_bytes_read);
267 EXPECT_EQ(kTestData + kOffset, data_read);
270 TEST_F(FileStreamTest, SeekAround) {
271 FileStream stream(base::MessageLoopProxy::current());
272 int flags = base::File::FLAG_OPEN | base::File::FLAG_ASYNC |
273 base::File::FLAG_READ;
274 TestCompletionCallback callback;
275 int rv = stream.Open(temp_file_path(), flags, callback.callback());
276 EXPECT_EQ(ERR_IO_PENDING, rv);
277 EXPECT_EQ(OK, callback.WaitForResult());
279 TestInt64CompletionCallback callback64;
281 const int64 kOffset = 3;
282 rv = stream.Seek(base::File::FROM_BEGIN, kOffset, callback64.callback());
283 ASSERT_EQ(ERR_IO_PENDING, rv);
284 int64 new_offset = callback64.WaitForResult();
285 EXPECT_EQ(kOffset, new_offset);
287 rv = stream.Seek(base::File::FROM_CURRENT, kOffset, callback64.callback());
288 ASSERT_EQ(ERR_IO_PENDING, rv);
289 new_offset = callback64.WaitForResult();
290 EXPECT_EQ(2 * kOffset, new_offset);
292 rv = stream.Seek(base::File::FROM_CURRENT, -kOffset, callback64.callback());
293 ASSERT_EQ(ERR_IO_PENDING, rv);
294 new_offset = callback64.WaitForResult();
295 EXPECT_EQ(kOffset, new_offset);
297 const int kTestDataLen = arraysize(kTestData) - 1;
299 rv = stream.Seek(base::File::FROM_END, -kTestDataLen, callback64.callback());
300 ASSERT_EQ(ERR_IO_PENDING, rv);
301 new_offset = callback64.WaitForResult();
302 EXPECT_EQ(0, new_offset);
305 TEST_F(FileStreamTest, Write) {
306 FileStream stream(base::MessageLoopProxy::current());
307 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
308 base::File::FLAG_ASYNC;
309 TestCompletionCallback callback;
310 int rv = stream.Open(temp_file_path(), flags, callback.callback());
311 EXPECT_EQ(OK, callback.GetResult(rv));
313 int64 file_size;
314 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
315 EXPECT_EQ(0, file_size);
317 scoped_refptr<IOBuffer> buf = CreateTestDataBuffer();
318 rv = stream.Write(buf.get(), kTestDataSize, callback.callback());
319 rv = callback.GetResult(rv);
320 EXPECT_EQ(kTestDataSize, rv);
322 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
323 EXPECT_EQ(kTestDataSize, file_size);
325 std::string data_read;
326 EXPECT_TRUE(base::ReadFileToString(temp_file_path(), &data_read));
327 EXPECT_EQ(kTestData, data_read);
330 TEST_F(FileStreamTest, Write_EarlyDelete) {
331 scoped_ptr<FileStream> stream(
332 new FileStream(base::MessageLoopProxy::current()));
333 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
334 base::File::FLAG_ASYNC;
335 TestCompletionCallback callback;
336 int rv = stream->Open(temp_file_path(), flags, callback.callback());
337 EXPECT_EQ(ERR_IO_PENDING, rv);
338 EXPECT_EQ(OK, callback.WaitForResult());
340 int64 file_size;
341 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
342 EXPECT_EQ(0, file_size);
344 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
345 rv = stream->Write(buf.get(), buf->size(), callback.callback());
346 stream.reset();
347 if (rv < 0) {
348 EXPECT_EQ(ERR_IO_PENDING, rv);
349 // The callback should not be called if the request is cancelled.
350 base::RunLoop().RunUntilIdle();
351 EXPECT_FALSE(callback.have_result());
352 } else {
353 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
354 EXPECT_EQ(file_size, rv);
358 TEST_F(FileStreamTest, Write_FromOffset) {
359 int64 file_size;
360 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
362 FileStream stream(base::MessageLoopProxy::current());
363 int flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
364 base::File::FLAG_ASYNC;
365 TestCompletionCallback callback;
366 int rv = stream.Open(temp_file_path(), flags, callback.callback());
367 EXPECT_EQ(ERR_IO_PENDING, rv);
368 EXPECT_EQ(OK, callback.WaitForResult());
370 TestInt64CompletionCallback callback64;
371 const int64 kOffset = 0;
372 rv = stream.Seek(base::File::FROM_END, kOffset, callback64.callback());
373 ASSERT_EQ(ERR_IO_PENDING, rv);
374 int64 new_offset = callback64.WaitForResult();
375 EXPECT_EQ(kTestDataSize, new_offset);
377 int total_bytes_written = 0;
379 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
380 scoped_refptr<DrainableIOBuffer> drainable =
381 new DrainableIOBuffer(buf.get(), buf->size());
382 while (total_bytes_written != kTestDataSize) {
383 rv = stream.Write(drainable.get(), drainable->BytesRemaining(),
384 callback.callback());
385 if (rv == ERR_IO_PENDING)
386 rv = callback.WaitForResult();
387 EXPECT_LT(0, rv);
388 if (rv <= 0)
389 break;
390 drainable->DidConsume(rv);
391 total_bytes_written += rv;
393 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
394 EXPECT_EQ(file_size, kTestDataSize * 2);
397 TEST_F(FileStreamTest, BasicReadWrite) {
398 int64 file_size;
399 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
401 scoped_ptr<FileStream> stream(
402 new FileStream(base::MessageLoopProxy::current()));
403 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
404 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
405 TestCompletionCallback callback;
406 int rv = stream->Open(temp_file_path(), flags, callback.callback());
407 EXPECT_EQ(ERR_IO_PENDING, rv);
408 EXPECT_EQ(OK, callback.WaitForResult());
410 int64 total_bytes_read = 0;
412 std::string data_read;
413 for (;;) {
414 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
415 rv = stream->Read(buf.get(), buf->size(), callback.callback());
416 if (rv == ERR_IO_PENDING)
417 rv = callback.WaitForResult();
418 EXPECT_LE(0, rv);
419 if (rv <= 0)
420 break;
421 total_bytes_read += rv;
422 data_read.append(buf->data(), rv);
424 EXPECT_EQ(file_size, total_bytes_read);
425 EXPECT_TRUE(data_read == kTestData);
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 stream.reset();
446 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
447 EXPECT_EQ(kTestDataSize * 2, file_size);
450 TEST_F(FileStreamTest, BasicWriteRead) {
451 int64 file_size;
452 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
454 scoped_ptr<FileStream> stream(
455 new FileStream(base::MessageLoopProxy::current()));
456 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
457 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
458 TestCompletionCallback callback;
459 int rv = stream->Open(temp_file_path(), flags, callback.callback());
460 EXPECT_EQ(ERR_IO_PENDING, rv);
461 EXPECT_EQ(OK, callback.WaitForResult());
463 TestInt64CompletionCallback callback64;
464 rv = stream->Seek(base::File::FROM_END, 0, callback64.callback());
465 ASSERT_EQ(ERR_IO_PENDING, rv);
466 int64 offset = callback64.WaitForResult();
467 EXPECT_EQ(offset, file_size);
469 int total_bytes_written = 0;
471 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
472 scoped_refptr<DrainableIOBuffer> drainable =
473 new DrainableIOBuffer(buf.get(), buf->size());
474 while (total_bytes_written != kTestDataSize) {
475 rv = stream->Write(drainable.get(), drainable->BytesRemaining(),
476 callback.callback());
477 if (rv == ERR_IO_PENDING)
478 rv = callback.WaitForResult();
479 EXPECT_LT(0, rv);
480 if (rv <= 0)
481 break;
482 drainable->DidConsume(rv);
483 total_bytes_written += rv;
486 EXPECT_EQ(kTestDataSize, total_bytes_written);
488 rv = stream->Seek(base::File::FROM_BEGIN, 0, callback64.callback());
489 ASSERT_EQ(ERR_IO_PENDING, rv);
490 offset = callback64.WaitForResult();
491 EXPECT_EQ(0, offset);
493 int total_bytes_read = 0;
495 std::string data_read;
496 for (;;) {
497 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
498 rv = stream->Read(buf.get(), buf->size(), callback.callback());
499 if (rv == ERR_IO_PENDING)
500 rv = callback.WaitForResult();
501 EXPECT_LE(0, rv);
502 if (rv <= 0)
503 break;
504 total_bytes_read += rv;
505 data_read.append(buf->data(), rv);
507 stream.reset();
509 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
510 EXPECT_EQ(kTestDataSize * 2, file_size);
512 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
513 const std::string kExpectedFileData =
514 std::string(kTestData) + std::string(kTestData);
515 EXPECT_EQ(kExpectedFileData, data_read);
518 class TestWriteReadCompletionCallback {
519 public:
520 TestWriteReadCompletionCallback(FileStream* stream,
521 int* total_bytes_written,
522 int* total_bytes_read,
523 std::string* data_read)
524 : result_(0),
525 have_result_(false),
526 waiting_for_result_(false),
527 stream_(stream),
528 total_bytes_written_(total_bytes_written),
529 total_bytes_read_(total_bytes_read),
530 data_read_(data_read),
531 callback_(base::Bind(&TestWriteReadCompletionCallback::OnComplete,
532 base::Unretained(this))),
533 test_data_(CreateTestDataBuffer()),
534 drainable_(new DrainableIOBuffer(test_data_.get(), kTestDataSize)) {}
536 int WaitForResult() {
537 DCHECK(!waiting_for_result_);
538 while (!have_result_) {
539 waiting_for_result_ = true;
540 base::RunLoop().Run();
541 waiting_for_result_ = false;
543 have_result_ = false; // auto-reset for next callback
544 return result_;
547 const CompletionCallback& callback() const { return callback_; }
549 void ValidateWrittenData() {
550 TestCompletionCallback callback;
551 int rv = 0;
552 for (;;) {
553 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
554 rv = stream_->Read(buf.get(), buf->size(), callback.callback());
555 if (rv == ERR_IO_PENDING) {
556 base::MessageLoop::ScopedNestableTaskAllower allow(
557 base::MessageLoop::current());
558 rv = callback.WaitForResult();
560 EXPECT_LE(0, rv);
561 if (rv <= 0)
562 break;
563 *total_bytes_read_ += rv;
564 data_read_->append(buf->data(), rv);
568 private:
569 void OnComplete(int result) {
570 DCHECK_LT(0, result);
571 *total_bytes_written_ += result;
573 int rv;
575 if (*total_bytes_written_ != kTestDataSize) {
576 // Recurse to finish writing all data.
577 int total_bytes_written = 0, total_bytes_read = 0;
578 std::string data_read;
579 TestWriteReadCompletionCallback callback(
580 stream_, &total_bytes_written, &total_bytes_read, &data_read);
581 rv = stream_->Write(
582 drainable_.get(), drainable_->BytesRemaining(), callback.callback());
583 DCHECK_EQ(ERR_IO_PENDING, rv);
584 rv = callback.WaitForResult();
585 drainable_->DidConsume(total_bytes_written);
586 *total_bytes_written_ += total_bytes_written;
587 *total_bytes_read_ += total_bytes_read;
588 *data_read_ += data_read;
589 } else { // We're done writing all data. Start reading the data.
590 TestInt64CompletionCallback callback64;
591 EXPECT_EQ(ERR_IO_PENDING,
592 stream_->Seek(base::File::FROM_BEGIN, 0,
593 callback64.callback()));
595 base::MessageLoop::ScopedNestableTaskAllower allow(
596 base::MessageLoop::current());
597 EXPECT_LE(0, callback64.WaitForResult());
601 result_ = *total_bytes_written_;
602 have_result_ = true;
603 if (waiting_for_result_)
604 base::MessageLoop::current()->Quit();
607 int result_;
608 bool have_result_;
609 bool waiting_for_result_;
610 FileStream* stream_;
611 int* total_bytes_written_;
612 int* total_bytes_read_;
613 std::string* data_read_;
614 const CompletionCallback callback_;
615 scoped_refptr<IOBufferWithSize> test_data_;
616 scoped_refptr<DrainableIOBuffer> drainable_;
618 DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback);
621 TEST_F(FileStreamTest, WriteRead) {
622 int64 file_size;
623 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
625 scoped_ptr<FileStream> stream(
626 new FileStream(base::MessageLoopProxy::current()));
627 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
628 base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
629 TestCompletionCallback open_callback;
630 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
631 EXPECT_EQ(ERR_IO_PENDING, rv);
632 EXPECT_EQ(OK, open_callback.WaitForResult());
634 TestInt64CompletionCallback callback64;
635 EXPECT_EQ(ERR_IO_PENDING,
636 stream->Seek(base::File::FROM_END, 0, callback64.callback()));
637 EXPECT_EQ(file_size, callback64.WaitForResult());
639 int total_bytes_written = 0;
640 int total_bytes_read = 0;
641 std::string data_read;
642 TestWriteReadCompletionCallback callback(stream.get(), &total_bytes_written,
643 &total_bytes_read, &data_read);
645 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
646 rv = stream->Write(buf.get(), buf->size(), callback.callback());
647 if (rv == ERR_IO_PENDING)
648 rv = callback.WaitForResult();
649 EXPECT_LT(0, rv);
650 EXPECT_EQ(kTestDataSize, total_bytes_written);
652 callback.ValidateWrittenData();
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, WriteClose) {
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,
743 stream->Seek(base::File::FROM_END, 0, callback64.callback()));
744 EXPECT_EQ(file_size, callback64.WaitForResult());
746 int total_bytes_written = 0;
747 TestWriteCloseCompletionCallback callback(stream.get(), &total_bytes_written);
749 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
750 rv = stream->Write(buf.get(), buf->size(), callback.callback());
751 if (rv == ERR_IO_PENDING)
752 total_bytes_written = callback.WaitForResult();
753 EXPECT_LT(0, total_bytes_written);
754 EXPECT_EQ(kTestDataSize, total_bytes_written);
756 stream.reset();
758 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
759 EXPECT_EQ(kTestDataSize * 2, file_size);
762 TEST_F(FileStreamTest, OpenAndDelete) {
763 scoped_refptr<base::SequencedWorkerPool> pool(
764 new base::SequencedWorkerPool(1, "StreamTest"));
766 bool prev = base::ThreadRestrictions::SetIOAllowed(false);
767 scoped_ptr<FileStream> stream(new FileStream(pool.get()));
768 int flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
769 base::File::FLAG_ASYNC;
770 TestCompletionCallback open_callback;
771 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
772 EXPECT_EQ(ERR_IO_PENDING, rv);
774 // Delete the stream without waiting for the open operation to be
775 // complete. Should be safe.
776 stream.reset();
778 // Force an operation through the pool.
779 scoped_ptr<FileStream> stream2(new FileStream(pool.get()));
780 TestCompletionCallback open_callback2;
781 rv = stream2->Open(temp_file_path(), flags, open_callback2.callback());
782 EXPECT_EQ(OK, open_callback2.GetResult(rv));
783 stream2.reset();
785 pool->Shutdown();
787 // open_callback won't be called.
788 base::RunLoop().RunUntilIdle();
789 EXPECT_FALSE(open_callback.have_result());
790 base::ThreadRestrictions::SetIOAllowed(prev);
793 // Verify that Write() errors are mapped correctly.
794 TEST_F(FileStreamTest, WriteError) {
795 // Try opening file as read-only and then writing to it using FileStream.
796 uint32 flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
797 base::File::FLAG_ASYNC;
799 base::File file(temp_file_path(), flags);
800 ASSERT_TRUE(file.IsValid());
802 scoped_ptr<FileStream> stream(
803 new FileStream(file.Pass(), base::MessageLoopProxy::current()));
805 scoped_refptr<IOBuffer> buf = new IOBuffer(1);
806 buf->data()[0] = 0;
808 TestCompletionCallback callback;
809 int rv = stream->Write(buf.get(), 1, callback.callback());
810 if (rv == ERR_IO_PENDING)
811 rv = callback.WaitForResult();
812 EXPECT_LT(rv, 0);
814 stream.reset();
815 base::RunLoop().RunUntilIdle();
818 // Verify that Read() errors are mapped correctly.
819 TEST_F(FileStreamTest, ReadError) {
820 // Try opening file for write and then reading from it using FileStream.
821 uint32 flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
822 base::File::FLAG_ASYNC;
824 base::File file(temp_file_path(), flags);
825 ASSERT_TRUE(file.IsValid());
827 scoped_ptr<FileStream> stream(
828 new FileStream(file.Pass(), base::MessageLoopProxy::current()));
830 scoped_refptr<IOBuffer> buf = new IOBuffer(1);
831 TestCompletionCallback callback;
832 int rv = stream->Read(buf.get(), 1, callback.callback());
833 if (rv == ERR_IO_PENDING)
834 rv = callback.WaitForResult();
835 EXPECT_LT(rv, 0);
837 stream.reset();
838 base::RunLoop().RunUntilIdle();
841 #if defined(OS_ANDROID)
842 TEST_F(FileStreamTest, ContentUriRead) {
843 base::FilePath test_dir;
844 PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
845 test_dir = test_dir.AppendASCII("net");
846 test_dir = test_dir.AppendASCII("data");
847 test_dir = test_dir.AppendASCII("file_stream_unittest");
848 ASSERT_TRUE(base::PathExists(test_dir));
849 base::FilePath image_file = test_dir.Append(FILE_PATH_LITERAL("red.png"));
851 // Insert the image into MediaStore. MediaStore will do some conversions, and
852 // return the content URI.
853 base::FilePath path = base::InsertImageIntoMediaStore(image_file);
854 EXPECT_TRUE(path.IsContentUri());
855 EXPECT_TRUE(base::PathExists(path));
856 int64 file_size;
857 EXPECT_TRUE(base::GetFileSize(path, &file_size));
858 EXPECT_LT(0, file_size);
860 FileStream stream(base::MessageLoopProxy::current());
861 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
862 base::File::FLAG_ASYNC;
863 TestCompletionCallback callback;
864 int rv = stream.Open(path, flags, callback.callback());
865 EXPECT_EQ(ERR_IO_PENDING, rv);
866 EXPECT_EQ(OK, callback.WaitForResult());
868 int total_bytes_read = 0;
870 std::string data_read;
871 for (;;) {
872 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
873 rv = stream.Read(buf.get(), buf->size(), callback.callback());
874 if (rv == ERR_IO_PENDING)
875 rv = callback.WaitForResult();
876 EXPECT_LE(0, rv);
877 if (rv <= 0)
878 break;
879 total_bytes_read += rv;
880 data_read.append(buf->data(), rv);
882 EXPECT_EQ(file_size, total_bytes_read);
884 #endif
886 } // namespace
888 } // namespace net