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"
8 #include "base/callback.h"
9 #include "base/file_util.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/path_service.h"
13 #include "base/platform_file.h"
14 #include "base/run_loop.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/test/test_timeouts.h"
17 #include "net/base/capturing_net_log.h"
18 #include "net/base/io_buffer.h"
19 #include "net/base/net_errors.h"
20 #include "net/base/test_completion_callback.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "testing/platform_test.h"
28 const char kTestData[] = "0123456789";
29 const int kTestDataSize = arraysize(kTestData) - 1;
31 // Creates an IOBufferWithSize that contains the kTestDataSize.
32 IOBufferWithSize* CreateTestDataBuffer() {
33 IOBufferWithSize* buf = new IOBufferWithSize(kTestDataSize);
34 memcpy(buf->data(), kTestData, kTestDataSize);
40 class FileStreamTest : public PlatformTest {
42 virtual void SetUp() {
43 PlatformTest::SetUp();
45 file_util::CreateTemporaryFile(&temp_file_path_);
46 file_util::WriteFile(temp_file_path_, kTestData, kTestDataSize);
48 virtual void TearDown() {
49 EXPECT_TRUE(base::DeleteFile(temp_file_path_, false));
51 // FileStreamContexts must be asynchronously closed on the file task runner
52 // before they can be deleted. Pump the RunLoop to avoid leaks.
53 base::RunLoop().RunUntilIdle();
54 PlatformTest::TearDown();
57 const base::FilePath temp_file_path() const { return temp_file_path_; }
60 base::FilePath temp_file_path_;
65 TEST_F(FileStreamTest, BasicOpenClose) {
66 base::PlatformFile file = base::kInvalidPlatformFileValue;
68 FileStream stream(NULL, base::MessageLoopProxy::current());
69 int rv = stream.OpenSync(temp_file_path(),
70 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
72 EXPECT_TRUE(stream.IsOpen());
73 file = stream.GetPlatformFileForTesting();
75 EXPECT_NE(base::kInvalidPlatformFileValue, file);
76 base::PlatformFileInfo info;
77 // The file should be closed.
78 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info));
81 TEST_F(FileStreamTest, BasicOpenExplicitClose) {
82 base::PlatformFile file = base::kInvalidPlatformFileValue;
83 FileStream stream(NULL);
84 int rv = stream.OpenSync(temp_file_path(),
85 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
87 EXPECT_TRUE(stream.IsOpen());
88 file = stream.GetPlatformFileForTesting();
89 EXPECT_NE(base::kInvalidPlatformFileValue, file);
90 EXPECT_EQ(OK, stream.CloseSync());
91 EXPECT_FALSE(stream.IsOpen());
92 base::PlatformFileInfo info;
93 // The file should be closed.
94 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info));
97 TEST_F(FileStreamTest, AsyncOpenExplicitClose) {
98 base::PlatformFile file = base::kInvalidPlatformFileValue;
99 TestCompletionCallback callback;
100 FileStream stream(NULL);
101 int flags = base::PLATFORM_FILE_OPEN |
102 base::PLATFORM_FILE_READ |
103 base::PLATFORM_FILE_ASYNC;
104 int rv = stream.Open(temp_file_path(), flags, callback.callback());
105 EXPECT_EQ(ERR_IO_PENDING, rv);
106 EXPECT_EQ(OK, callback.WaitForResult());
107 EXPECT_TRUE(stream.IsOpen());
108 file = stream.GetPlatformFileForTesting();
109 EXPECT_EQ(ERR_IO_PENDING, stream.Close(callback.callback()));
110 EXPECT_EQ(OK, callback.WaitForResult());
111 EXPECT_FALSE(stream.IsOpen());
112 base::PlatformFileInfo info;
113 // The file should be closed.
114 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info));
117 TEST_F(FileStreamTest, AsyncOpenExplicitCloseOrphaned) {
118 base::PlatformFile file = base::kInvalidPlatformFileValue;
119 TestCompletionCallback callback;
120 base::PlatformFileInfo info;
121 scoped_ptr<FileStream> stream(new FileStream(
122 NULL, base::MessageLoopProxy::current()));
123 int flags = base::PLATFORM_FILE_OPEN |
124 base::PLATFORM_FILE_READ |
125 base::PLATFORM_FILE_ASYNC;
126 int rv = stream->Open(temp_file_path(), flags, callback.callback());
127 EXPECT_EQ(ERR_IO_PENDING, rv);
128 EXPECT_EQ(OK, callback.WaitForResult());
129 EXPECT_TRUE(stream->IsOpen());
130 file = stream->GetPlatformFileForTesting();
131 EXPECT_EQ(ERR_IO_PENDING, stream->Close(callback.callback()));
133 // File isn't actually closed yet.
134 EXPECT_TRUE(base::GetPlatformFileInfo(file, &info));
135 base::RunLoop runloop;
136 runloop.RunUntilIdle();
137 // The file should now be closed, though the callback has not been called.
138 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info));
141 TEST_F(FileStreamTest, FileHandleNotLeftOpen) {
142 bool created = false;
143 ASSERT_EQ(kTestDataSize,
144 file_util::WriteFile(temp_file_path(), kTestData, kTestDataSize));
145 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ;
146 base::PlatformFile file = base::CreatePlatformFile(
147 temp_file_path(), flags, &created, NULL);
150 // Seek to the beginning of the file and read.
151 FileStream read_stream(file, flags, NULL,
152 base::MessageLoopProxy::current());
153 EXPECT_TRUE(read_stream.IsOpen());
156 EXPECT_NE(base::kInvalidPlatformFileValue, file);
157 base::PlatformFileInfo info;
158 // The file should be closed.
159 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info));
162 // Test the use of FileStream with a file handle provided at construction.
163 TEST_F(FileStreamTest, UseFileHandle) {
164 bool created = false;
166 // 1. Test reading with a file handle.
167 ASSERT_EQ(kTestDataSize,
168 file_util::WriteFile(temp_file_path(), kTestData, kTestDataSize));
169 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ;
170 base::PlatformFile file = base::CreatePlatformFile(
171 temp_file_path(), flags, &created, NULL);
173 // Seek to the beginning of the file and read.
174 scoped_ptr<FileStream> read_stream(
175 new FileStream(file, flags, NULL, base::MessageLoopProxy::current()));
176 ASSERT_EQ(0, read_stream->SeekSync(FROM_BEGIN, 0));
177 ASSERT_EQ(kTestDataSize, read_stream->Available());
178 // Read into buffer and compare.
179 char buffer[kTestDataSize];
180 ASSERT_EQ(kTestDataSize,
181 read_stream->ReadSync(buffer, kTestDataSize));
182 ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize));
185 // 2. Test writing with a file handle.
186 base::DeleteFile(temp_file_path(), false);
187 flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE;
188 file = base::CreatePlatformFile(temp_file_path(), flags, &created, NULL);
190 scoped_ptr<FileStream> write_stream(
191 new FileStream(file, flags, NULL, base::MessageLoopProxy::current()));
192 ASSERT_EQ(0, write_stream->SeekSync(FROM_BEGIN, 0));
193 ASSERT_EQ(kTestDataSize,
194 write_stream->WriteSync(kTestData, kTestDataSize));
195 write_stream.reset();
197 // Read into buffer and compare to make sure the handle worked fine.
198 ASSERT_EQ(kTestDataSize,
199 file_util::ReadFile(temp_file_path(), buffer, kTestDataSize));
200 ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize));
203 TEST_F(FileStreamTest, UseClosedStream) {
204 FileStream stream(NULL, base::MessageLoopProxy::current());
206 EXPECT_FALSE(stream.IsOpen());
209 int64 new_offset = stream.SeekSync(FROM_BEGIN, 5);
210 EXPECT_EQ(ERR_UNEXPECTED, new_offset);
213 int64 avail = stream.Available();
214 EXPECT_EQ(ERR_UNEXPECTED, avail);
218 int rv = stream.ReadSync(buf, arraysize(buf));
219 EXPECT_EQ(ERR_UNEXPECTED, rv);
222 TEST_F(FileStreamTest, BasicRead) {
224 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
227 FileStream stream(NULL, base::MessageLoopProxy::current());
228 int flags = base::PLATFORM_FILE_OPEN |
229 base::PLATFORM_FILE_READ;
230 int rv = stream.OpenSync(temp_file_path(), flags);
233 int64 total_bytes_avail = stream.Available();
234 EXPECT_EQ(file_size, total_bytes_avail);
236 int total_bytes_read = 0;
238 std::string data_read;
241 rv = stream.ReadSync(buf, arraysize(buf));
245 total_bytes_read += rv;
246 data_read.append(buf, rv);
248 EXPECT_EQ(file_size, total_bytes_read);
249 EXPECT_EQ(kTestData, data_read);
252 TEST_F(FileStreamTest, AsyncRead) {
254 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
257 FileStream stream(NULL, base::MessageLoopProxy::current());
258 int flags = base::PLATFORM_FILE_OPEN |
259 base::PLATFORM_FILE_READ |
260 base::PLATFORM_FILE_ASYNC;
261 TestCompletionCallback callback;
262 int rv = stream.Open(temp_file_path(), flags, callback.callback());
263 EXPECT_EQ(ERR_IO_PENDING, rv);
264 EXPECT_EQ(OK, callback.WaitForResult());
266 int64 total_bytes_avail = stream.Available();
267 EXPECT_EQ(file_size, total_bytes_avail);
269 int total_bytes_read = 0;
271 std::string data_read;
273 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
274 rv = stream.Read(buf.get(), buf->size(), callback.callback());
275 if (rv == ERR_IO_PENDING)
276 rv = callback.WaitForResult();
280 total_bytes_read += rv;
281 data_read.append(buf->data(), rv);
283 EXPECT_EQ(file_size, total_bytes_read);
284 EXPECT_EQ(kTestData, data_read);
287 TEST_F(FileStreamTest, AsyncRead_EarlyDelete) {
289 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
292 scoped_ptr<FileStream> stream(
293 new FileStream(NULL, base::MessageLoopProxy::current()));
294 int flags = base::PLATFORM_FILE_OPEN |
295 base::PLATFORM_FILE_READ |
296 base::PLATFORM_FILE_ASYNC;
297 TestCompletionCallback callback;
298 int rv = stream->Open(temp_file_path(), flags, callback.callback());
299 EXPECT_EQ(ERR_IO_PENDING, rv);
300 EXPECT_EQ(OK, callback.WaitForResult());
302 int64 total_bytes_avail = stream->Available();
303 EXPECT_EQ(file_size, total_bytes_avail);
305 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
306 rv = stream->Read(buf.get(), buf->size(), callback.callback());
307 stream.reset(); // Delete instead of closing it.
309 EXPECT_EQ(ERR_IO_PENDING, rv);
310 // The callback should not be called if the request is cancelled.
311 base::RunLoop().RunUntilIdle();
312 EXPECT_FALSE(callback.have_result());
314 EXPECT_EQ(std::string(kTestData, rv), std::string(buf->data(), rv));
318 TEST_F(FileStreamTest, BasicRead_FromOffset) {
320 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
323 FileStream stream(NULL, base::MessageLoopProxy::current());
324 int flags = base::PLATFORM_FILE_OPEN |
325 base::PLATFORM_FILE_READ;
326 int rv = stream.OpenSync(temp_file_path(), flags);
329 const int64 kOffset = 3;
330 int64 new_offset = stream.SeekSync(FROM_BEGIN, kOffset);
331 EXPECT_EQ(kOffset, new_offset);
333 int64 total_bytes_avail = stream.Available();
334 EXPECT_EQ(file_size - kOffset, total_bytes_avail);
336 int64 total_bytes_read = 0;
338 std::string data_read;
341 rv = stream.ReadSync(buf, arraysize(buf));
345 total_bytes_read += rv;
346 data_read.append(buf, rv);
348 EXPECT_EQ(file_size - kOffset, total_bytes_read);
349 EXPECT_TRUE(data_read == kTestData + kOffset);
350 EXPECT_EQ(kTestData + kOffset, data_read);
353 TEST_F(FileStreamTest, AsyncRead_FromOffset) {
355 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
358 FileStream stream(NULL, base::MessageLoopProxy::current());
359 int flags = base::PLATFORM_FILE_OPEN |
360 base::PLATFORM_FILE_READ |
361 base::PLATFORM_FILE_ASYNC;
362 TestCompletionCallback callback;
363 int rv = stream.Open(temp_file_path(), flags, callback.callback());
364 EXPECT_EQ(ERR_IO_PENDING, rv);
365 EXPECT_EQ(OK, callback.WaitForResult());
367 TestInt64CompletionCallback callback64;
368 const int64 kOffset = 3;
369 rv = stream.Seek(FROM_BEGIN, kOffset, callback64.callback());
370 ASSERT_EQ(ERR_IO_PENDING, rv);
371 int64 new_offset = callback64.WaitForResult();
372 EXPECT_EQ(kOffset, new_offset);
374 int64 total_bytes_avail = stream.Available();
375 EXPECT_EQ(file_size - kOffset, total_bytes_avail);
377 int total_bytes_read = 0;
379 std::string data_read;
381 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
382 rv = stream.Read(buf.get(), buf->size(), callback.callback());
383 if (rv == ERR_IO_PENDING)
384 rv = callback.WaitForResult();
388 total_bytes_read += rv;
389 data_read.append(buf->data(), rv);
391 EXPECT_EQ(file_size - kOffset, total_bytes_read);
392 EXPECT_EQ(kTestData + kOffset, data_read);
395 TEST_F(FileStreamTest, SeekAround) {
396 FileStream stream(NULL, base::MessageLoopProxy::current());
397 int flags = base::PLATFORM_FILE_OPEN |
398 base::PLATFORM_FILE_READ;
399 int rv = stream.OpenSync(temp_file_path(), flags);
402 const int64 kOffset = 3;
403 int64 new_offset = stream.SeekSync(FROM_BEGIN, kOffset);
404 EXPECT_EQ(kOffset, new_offset);
406 new_offset = stream.SeekSync(FROM_CURRENT, kOffset);
407 EXPECT_EQ(2 * kOffset, new_offset);
409 new_offset = stream.SeekSync(FROM_CURRENT, -kOffset);
410 EXPECT_EQ(kOffset, new_offset);
412 const int kTestDataLen = arraysize(kTestData) - 1;
414 new_offset = stream.SeekSync(FROM_END, -kTestDataLen);
415 EXPECT_EQ(0, new_offset);
418 TEST_F(FileStreamTest, AsyncSeekAround) {
419 FileStream stream(NULL, base::MessageLoopProxy::current());
420 int flags = base::PLATFORM_FILE_OPEN |
421 base::PLATFORM_FILE_ASYNC |
422 base::PLATFORM_FILE_READ;
423 TestCompletionCallback callback;
424 int rv = stream.Open(temp_file_path(), flags, callback.callback());
425 EXPECT_EQ(ERR_IO_PENDING, rv);
426 EXPECT_EQ(OK, callback.WaitForResult());
428 TestInt64CompletionCallback callback64;
430 const int64 kOffset = 3;
431 rv = stream.Seek(FROM_BEGIN, kOffset, callback64.callback());
432 ASSERT_EQ(ERR_IO_PENDING, rv);
433 int64 new_offset = callback64.WaitForResult();
434 EXPECT_EQ(kOffset, new_offset);
436 rv = stream.Seek(FROM_CURRENT, kOffset, callback64.callback());
437 ASSERT_EQ(ERR_IO_PENDING, rv);
438 new_offset = callback64.WaitForResult();
439 EXPECT_EQ(2 * kOffset, new_offset);
441 rv = stream.Seek(FROM_CURRENT, -kOffset, callback64.callback());
442 ASSERT_EQ(ERR_IO_PENDING, rv);
443 new_offset = callback64.WaitForResult();
444 EXPECT_EQ(kOffset, new_offset);
446 const int kTestDataLen = arraysize(kTestData) - 1;
448 rv = stream.Seek(FROM_END, -kTestDataLen, callback64.callback());
449 ASSERT_EQ(ERR_IO_PENDING, rv);
450 new_offset = callback64.WaitForResult();
451 EXPECT_EQ(0, new_offset);
454 TEST_F(FileStreamTest, BasicWrite) {
455 scoped_ptr<FileStream> stream(
456 new FileStream(NULL, base::MessageLoopProxy::current()));
457 int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
458 base::PLATFORM_FILE_WRITE;
459 int rv = stream->OpenSync(temp_file_path(), flags);
463 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
465 EXPECT_EQ(0, file_size);
467 rv = stream->WriteSync(kTestData, kTestDataSize);
468 EXPECT_EQ(kTestDataSize, rv);
471 ok = file_util::GetFileSize(temp_file_path(), &file_size);
473 EXPECT_EQ(kTestDataSize, file_size);
476 TEST_F(FileStreamTest, AsyncWrite) {
477 FileStream stream(NULL, base::MessageLoopProxy::current());
478 int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
479 base::PLATFORM_FILE_WRITE |
480 base::PLATFORM_FILE_ASYNC;
481 TestCompletionCallback callback;
482 int rv = stream.Open(temp_file_path(), flags, callback.callback());
483 EXPECT_EQ(ERR_IO_PENDING, rv);
484 EXPECT_EQ(OK, callback.WaitForResult());
487 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
489 EXPECT_EQ(0, file_size);
491 int total_bytes_written = 0;
493 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
494 scoped_refptr<DrainableIOBuffer> drainable =
495 new DrainableIOBuffer(buf.get(), buf->size());
496 while (total_bytes_written != kTestDataSize) {
498 drainable.get(), drainable->BytesRemaining(), callback.callback());
499 if (rv == ERR_IO_PENDING)
500 rv = callback.WaitForResult();
504 drainable->DidConsume(rv);
505 total_bytes_written += rv;
507 ok = file_util::GetFileSize(temp_file_path(), &file_size);
509 EXPECT_EQ(file_size, total_bytes_written);
512 TEST_F(FileStreamTest, AsyncWrite_EarlyDelete) {
513 scoped_ptr<FileStream> stream(
514 new FileStream(NULL, base::MessageLoopProxy::current()));
515 int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
516 base::PLATFORM_FILE_WRITE |
517 base::PLATFORM_FILE_ASYNC;
518 TestCompletionCallback callback;
519 int rv = stream->Open(temp_file_path(), flags, callback.callback());
520 EXPECT_EQ(ERR_IO_PENDING, rv);
521 EXPECT_EQ(OK, callback.WaitForResult());
524 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
526 EXPECT_EQ(0, file_size);
528 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
529 rv = stream->Write(buf.get(), buf->size(), callback.callback());
532 EXPECT_EQ(ERR_IO_PENDING, rv);
533 // The callback should not be called if the request is cancelled.
534 base::RunLoop().RunUntilIdle();
535 EXPECT_FALSE(callback.have_result());
537 ok = file_util::GetFileSize(temp_file_path(), &file_size);
539 EXPECT_EQ(file_size, rv);
543 TEST_F(FileStreamTest, BasicWrite_FromOffset) {
544 scoped_ptr<FileStream> stream(
545 new FileStream(NULL, base::MessageLoopProxy::current()));
546 int flags = base::PLATFORM_FILE_OPEN |
547 base::PLATFORM_FILE_WRITE;
548 int rv = stream->OpenSync(temp_file_path(), flags);
552 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
554 EXPECT_EQ(kTestDataSize, file_size);
556 const int64 kOffset = 0;
557 int64 new_offset = stream->SeekSync(FROM_END, kOffset);
558 EXPECT_EQ(kTestDataSize, new_offset);
560 rv = stream->WriteSync(kTestData, kTestDataSize);
561 EXPECT_EQ(kTestDataSize, rv);
564 ok = file_util::GetFileSize(temp_file_path(), &file_size);
566 EXPECT_EQ(kTestDataSize * 2, file_size);
569 TEST_F(FileStreamTest, AsyncWrite_FromOffset) {
571 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
574 FileStream stream(NULL, base::MessageLoopProxy::current());
575 int flags = base::PLATFORM_FILE_OPEN |
576 base::PLATFORM_FILE_WRITE |
577 base::PLATFORM_FILE_ASYNC;
578 TestCompletionCallback callback;
579 int rv = stream.Open(temp_file_path(), flags, callback.callback());
580 EXPECT_EQ(ERR_IO_PENDING, rv);
581 EXPECT_EQ(OK, callback.WaitForResult());
583 TestInt64CompletionCallback callback64;
584 const int64 kOffset = 0;
585 rv = stream.Seek(FROM_END, kOffset, callback64.callback());
586 ASSERT_EQ(ERR_IO_PENDING, rv);
587 int64 new_offset = callback64.WaitForResult();
588 EXPECT_EQ(kTestDataSize, new_offset);
590 int total_bytes_written = 0;
592 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
593 scoped_refptr<DrainableIOBuffer> drainable =
594 new DrainableIOBuffer(buf.get(), buf->size());
595 while (total_bytes_written != kTestDataSize) {
597 drainable.get(), drainable->BytesRemaining(), callback.callback());
598 if (rv == ERR_IO_PENDING)
599 rv = callback.WaitForResult();
603 drainable->DidConsume(rv);
604 total_bytes_written += rv;
606 ok = file_util::GetFileSize(temp_file_path(), &file_size);
608 EXPECT_EQ(file_size, kTestDataSize * 2);
611 TEST_F(FileStreamTest, BasicReadWrite) {
613 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
616 scoped_ptr<FileStream> stream(
617 new FileStream(NULL, base::MessageLoopProxy::current()));
618 int flags = base::PLATFORM_FILE_OPEN |
619 base::PLATFORM_FILE_READ |
620 base::PLATFORM_FILE_WRITE;
621 int rv = stream->OpenSync(temp_file_path(), flags);
624 int64 total_bytes_avail = stream->Available();
625 EXPECT_EQ(file_size, total_bytes_avail);
627 int total_bytes_read = 0;
629 std::string data_read;
632 rv = stream->ReadSync(buf, arraysize(buf));
636 total_bytes_read += rv;
637 data_read.append(buf, rv);
639 EXPECT_EQ(file_size, total_bytes_read);
640 EXPECT_TRUE(data_read == kTestData);
642 rv = stream->WriteSync(kTestData, kTestDataSize);
643 EXPECT_EQ(kTestDataSize, rv);
646 ok = file_util::GetFileSize(temp_file_path(), &file_size);
648 EXPECT_EQ(kTestDataSize * 2, file_size);
651 TEST_F(FileStreamTest, BasicWriteRead) {
653 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
656 scoped_ptr<FileStream> stream(
657 new FileStream(NULL, base::MessageLoopProxy::current()));
658 int flags = base::PLATFORM_FILE_OPEN |
659 base::PLATFORM_FILE_READ |
660 base::PLATFORM_FILE_WRITE;
661 int rv = stream->OpenSync(temp_file_path(), flags);
664 int64 total_bytes_avail = stream->Available();
665 EXPECT_EQ(file_size, total_bytes_avail);
667 int64 offset = stream->SeekSync(FROM_END, 0);
668 EXPECT_EQ(offset, file_size);
670 rv = stream->WriteSync(kTestData, kTestDataSize);
671 EXPECT_EQ(kTestDataSize, rv);
673 offset = stream->SeekSync(FROM_BEGIN, 0);
674 EXPECT_EQ(0, offset);
676 int64 total_bytes_read = 0;
678 std::string data_read;
681 rv = stream->ReadSync(buf, arraysize(buf));
685 total_bytes_read += rv;
686 data_read.append(buf, rv);
690 ok = file_util::GetFileSize(temp_file_path(), &file_size);
692 EXPECT_EQ(kTestDataSize * 2, file_size);
693 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
695 const std::string kExpectedFileData =
696 std::string(kTestData) + std::string(kTestData);
697 EXPECT_EQ(kExpectedFileData, data_read);
700 TEST_F(FileStreamTest, BasicAsyncReadWrite) {
702 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
705 scoped_ptr<FileStream> stream(
706 new FileStream(NULL, base::MessageLoopProxy::current()));
707 int flags = base::PLATFORM_FILE_OPEN |
708 base::PLATFORM_FILE_READ |
709 base::PLATFORM_FILE_WRITE |
710 base::PLATFORM_FILE_ASYNC;
711 TestCompletionCallback callback;
712 int rv = stream->Open(temp_file_path(), flags, callback.callback());
713 EXPECT_EQ(ERR_IO_PENDING, rv);
714 EXPECT_EQ(OK, callback.WaitForResult());
716 int64 total_bytes_avail = stream->Available();
717 EXPECT_EQ(file_size, total_bytes_avail);
719 int64 total_bytes_read = 0;
721 std::string data_read;
723 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
724 rv = stream->Read(buf.get(), buf->size(), callback.callback());
725 if (rv == ERR_IO_PENDING)
726 rv = callback.WaitForResult();
730 total_bytes_read += rv;
731 data_read.append(buf->data(), rv);
733 EXPECT_EQ(file_size, total_bytes_read);
734 EXPECT_TRUE(data_read == kTestData);
736 int total_bytes_written = 0;
738 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
739 scoped_refptr<DrainableIOBuffer> drainable =
740 new DrainableIOBuffer(buf.get(), buf->size());
741 while (total_bytes_written != kTestDataSize) {
743 drainable.get(), drainable->BytesRemaining(), callback.callback());
744 if (rv == ERR_IO_PENDING)
745 rv = callback.WaitForResult();
749 drainable->DidConsume(rv);
750 total_bytes_written += rv;
755 ok = file_util::GetFileSize(temp_file_path(), &file_size);
757 EXPECT_EQ(kTestDataSize * 2, file_size);
760 TEST_F(FileStreamTest, BasicAsyncWriteRead) {
762 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
765 scoped_ptr<FileStream> stream(
766 new FileStream(NULL, base::MessageLoopProxy::current()));
767 int flags = base::PLATFORM_FILE_OPEN |
768 base::PLATFORM_FILE_READ |
769 base::PLATFORM_FILE_WRITE |
770 base::PLATFORM_FILE_ASYNC;
771 TestCompletionCallback callback;
772 int rv = stream->Open(temp_file_path(), flags, callback.callback());
773 EXPECT_EQ(ERR_IO_PENDING, rv);
774 EXPECT_EQ(OK, callback.WaitForResult());
776 int64 total_bytes_avail = stream->Available();
777 EXPECT_EQ(file_size, total_bytes_avail);
779 TestInt64CompletionCallback callback64;
780 rv = stream->Seek(FROM_END, 0, callback64.callback());
781 ASSERT_EQ(ERR_IO_PENDING, rv);
782 int64 offset = callback64.WaitForResult();
783 EXPECT_EQ(offset, file_size);
785 int total_bytes_written = 0;
787 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
788 scoped_refptr<DrainableIOBuffer> drainable =
789 new DrainableIOBuffer(buf.get(), buf->size());
790 while (total_bytes_written != kTestDataSize) {
792 drainable.get(), drainable->BytesRemaining(), callback.callback());
793 if (rv == ERR_IO_PENDING)
794 rv = callback.WaitForResult();
798 drainable->DidConsume(rv);
799 total_bytes_written += rv;
802 EXPECT_EQ(kTestDataSize, total_bytes_written);
804 rv = stream->Seek(FROM_BEGIN, 0, callback64.callback());
805 ASSERT_EQ(ERR_IO_PENDING, rv);
806 offset = callback64.WaitForResult();
807 EXPECT_EQ(0, offset);
809 int total_bytes_read = 0;
811 std::string data_read;
813 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
814 rv = stream->Read(buf.get(), buf->size(), callback.callback());
815 if (rv == ERR_IO_PENDING)
816 rv = callback.WaitForResult();
820 total_bytes_read += rv;
821 data_read.append(buf->data(), rv);
825 ok = file_util::GetFileSize(temp_file_path(), &file_size);
827 EXPECT_EQ(kTestDataSize * 2, file_size);
829 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
830 const std::string kExpectedFileData =
831 std::string(kTestData) + std::string(kTestData);
832 EXPECT_EQ(kExpectedFileData, data_read);
835 class TestWriteReadCompletionCallback {
837 TestWriteReadCompletionCallback(FileStream* stream,
838 int* total_bytes_written,
839 int* total_bytes_read,
840 std::string* data_read)
843 waiting_for_result_(false),
845 total_bytes_written_(total_bytes_written),
846 total_bytes_read_(total_bytes_read),
847 data_read_(data_read),
848 callback_(base::Bind(&TestWriteReadCompletionCallback::OnComplete,
849 base::Unretained(this))),
850 test_data_(CreateTestDataBuffer()),
851 drainable_(new DrainableIOBuffer(test_data_.get(), kTestDataSize)) {}
853 int WaitForResult() {
854 DCHECK(!waiting_for_result_);
855 while (!have_result_) {
856 waiting_for_result_ = true;
857 base::RunLoop().Run();
858 waiting_for_result_ = false;
860 have_result_ = false; // auto-reset for next callback
864 const CompletionCallback& callback() const { return callback_; }
867 void OnComplete(int result) {
868 DCHECK_LT(0, result);
869 *total_bytes_written_ += result;
873 if (*total_bytes_written_ != kTestDataSize) {
874 // Recurse to finish writing all data.
875 int total_bytes_written = 0, total_bytes_read = 0;
876 std::string data_read;
877 TestWriteReadCompletionCallback callback(
878 stream_, &total_bytes_written, &total_bytes_read, &data_read);
880 drainable_.get(), drainable_->BytesRemaining(), callback.callback());
881 DCHECK_EQ(ERR_IO_PENDING, rv);
882 rv = callback.WaitForResult();
883 drainable_->DidConsume(total_bytes_written);
884 *total_bytes_written_ += total_bytes_written;
885 *total_bytes_read_ += total_bytes_read;
886 *data_read_ += data_read;
887 } else { // We're done writing all data. Start reading the data.
888 stream_->SeekSync(FROM_BEGIN, 0);
890 TestCompletionCallback callback;
892 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
893 rv = stream_->Read(buf.get(), buf->size(), callback.callback());
894 if (rv == ERR_IO_PENDING) {
895 base::MessageLoop::ScopedNestableTaskAllower allow(
896 base::MessageLoop::current());
897 rv = callback.WaitForResult();
902 *total_bytes_read_ += rv;
903 data_read_->append(buf->data(), rv);
907 result_ = *total_bytes_written_;
909 if (waiting_for_result_)
910 base::MessageLoop::current()->Quit();
915 bool waiting_for_result_;
917 int* total_bytes_written_;
918 int* total_bytes_read_;
919 std::string* data_read_;
920 const CompletionCallback callback_;
921 scoped_refptr<IOBufferWithSize> test_data_;
922 scoped_refptr<DrainableIOBuffer> drainable_;
924 DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback);
927 TEST_F(FileStreamTest, AsyncWriteRead) {
929 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
932 scoped_ptr<FileStream> stream(
933 new FileStream(NULL, base::MessageLoopProxy::current()));
934 int flags = base::PLATFORM_FILE_OPEN |
935 base::PLATFORM_FILE_READ |
936 base::PLATFORM_FILE_WRITE |
937 base::PLATFORM_FILE_ASYNC;
938 TestCompletionCallback open_callback;
939 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
940 EXPECT_EQ(ERR_IO_PENDING, rv);
941 EXPECT_EQ(OK, open_callback.WaitForResult());
943 int64 total_bytes_avail = stream->Available();
944 EXPECT_EQ(file_size, total_bytes_avail);
946 int64 offset = stream->SeekSync(FROM_END, 0);
947 EXPECT_EQ(offset, file_size);
949 int total_bytes_written = 0;
950 int total_bytes_read = 0;
951 std::string data_read;
952 TestWriteReadCompletionCallback callback(stream.get(), &total_bytes_written,
953 &total_bytes_read, &data_read);
955 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
956 rv = stream->Write(buf.get(), buf->size(), callback.callback());
957 if (rv == ERR_IO_PENDING)
958 rv = callback.WaitForResult();
960 EXPECT_EQ(kTestDataSize, total_bytes_written);
964 ok = file_util::GetFileSize(temp_file_path(), &file_size);
966 EXPECT_EQ(kTestDataSize * 2, file_size);
968 EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
969 const std::string kExpectedFileData =
970 std::string(kTestData) + std::string(kTestData);
971 EXPECT_EQ(kExpectedFileData, data_read);
974 class TestWriteCloseCompletionCallback {
976 TestWriteCloseCompletionCallback(FileStream* stream, int* total_bytes_written)
979 waiting_for_result_(false),
981 total_bytes_written_(total_bytes_written),
982 callback_(base::Bind(&TestWriteCloseCompletionCallback::OnComplete,
983 base::Unretained(this))),
984 test_data_(CreateTestDataBuffer()),
985 drainable_(new DrainableIOBuffer(test_data_.get(), kTestDataSize)) {}
987 int WaitForResult() {
988 DCHECK(!waiting_for_result_);
989 while (!have_result_) {
990 waiting_for_result_ = true;
991 base::RunLoop().Run();
992 waiting_for_result_ = false;
994 have_result_ = false; // auto-reset for next callback
998 const CompletionCallback& callback() const { return callback_; }
1001 void OnComplete(int result) {
1002 DCHECK_LT(0, result);
1003 *total_bytes_written_ += result;
1007 if (*total_bytes_written_ != kTestDataSize) {
1008 // Recurse to finish writing all data.
1009 int total_bytes_written = 0;
1010 TestWriteCloseCompletionCallback callback(stream_, &total_bytes_written);
1011 rv = stream_->Write(
1012 drainable_.get(), drainable_->BytesRemaining(), callback.callback());
1013 DCHECK_EQ(ERR_IO_PENDING, rv);
1014 rv = callback.WaitForResult();
1015 drainable_->DidConsume(total_bytes_written);
1016 *total_bytes_written_ += total_bytes_written;
1019 result_ = *total_bytes_written_;
1020 have_result_ = true;
1021 if (waiting_for_result_)
1022 base::MessageLoop::current()->Quit();
1027 bool waiting_for_result_;
1028 FileStream* stream_;
1029 int* total_bytes_written_;
1030 const CompletionCallback callback_;
1031 scoped_refptr<IOBufferWithSize> test_data_;
1032 scoped_refptr<DrainableIOBuffer> drainable_;
1034 DISALLOW_COPY_AND_ASSIGN(TestWriteCloseCompletionCallback);
1037 TEST_F(FileStreamTest, AsyncWriteClose) {
1039 bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
1042 scoped_ptr<FileStream> stream(
1043 new FileStream(NULL, base::MessageLoopProxy::current()));
1044 int flags = base::PLATFORM_FILE_OPEN |
1045 base::PLATFORM_FILE_READ |
1046 base::PLATFORM_FILE_WRITE |
1047 base::PLATFORM_FILE_ASYNC;
1048 TestCompletionCallback open_callback;
1049 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
1050 EXPECT_EQ(ERR_IO_PENDING, rv);
1051 EXPECT_EQ(OK, open_callback.WaitForResult());
1053 int64 total_bytes_avail = stream->Available();
1054 EXPECT_EQ(file_size, total_bytes_avail);
1056 int64 offset = stream->SeekSync(FROM_END, 0);
1057 EXPECT_EQ(offset, file_size);
1059 int total_bytes_written = 0;
1060 TestWriteCloseCompletionCallback callback(stream.get(), &total_bytes_written);
1062 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
1063 rv = stream->Write(buf.get(), buf->size(), callback.callback());
1064 if (rv == ERR_IO_PENDING)
1065 total_bytes_written = callback.WaitForResult();
1066 EXPECT_LT(0, total_bytes_written);
1067 EXPECT_EQ(kTestDataSize, total_bytes_written);
1071 ok = file_util::GetFileSize(temp_file_path(), &file_size);
1073 EXPECT_EQ(kTestDataSize * 2, file_size);
1076 // Tests truncating a file.
1077 TEST_F(FileStreamTest, Truncate) {
1078 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE;
1080 scoped_ptr<FileStream> write_stream(
1081 new FileStream(NULL, base::MessageLoopProxy::current()));
1082 ASSERT_EQ(OK, write_stream->OpenSync(temp_file_path(), flags));
1084 // Write some data to the file.
1085 const char test_data[] = "0123456789";
1086 write_stream->WriteSync(test_data, arraysize(test_data));
1088 // Truncate the file.
1089 ASSERT_EQ(4, write_stream->Truncate(4));
1092 write_stream->WriteSync(test_data, 4);
1094 // Close the stream.
1095 write_stream.reset();
1097 // Read in the contents and make sure we get back what we expected.
1098 std::string read_contents;
1099 EXPECT_TRUE(base::ReadFileToString(temp_file_path(), &read_contents));
1101 EXPECT_EQ("01230123", read_contents);
1104 TEST_F(FileStreamTest, AsyncOpenAndDelete) {
1105 scoped_ptr<FileStream> stream(
1106 new FileStream(NULL, base::MessageLoopProxy::current()));
1107 int flags = base::PLATFORM_FILE_OPEN |
1108 base::PLATFORM_FILE_WRITE |
1109 base::PLATFORM_FILE_ASYNC;
1110 TestCompletionCallback open_callback;
1111 int rv = stream->Open(temp_file_path(), flags, open_callback.callback());
1112 EXPECT_EQ(ERR_IO_PENDING, rv);
1114 // Delete the stream without waiting for the open operation to be
1115 // complete. Should be safe.
1117 // open_callback won't be called.
1118 base::RunLoop().RunUntilIdle();
1119 EXPECT_FALSE(open_callback.have_result());
1122 // Verify that async Write() errors are mapped correctly.
1123 TEST_F(FileStreamTest, AsyncWriteError) {
1124 // Try opening file as read-only and then writing to it using FileStream.
1125 base::PlatformFile file = base::CreatePlatformFile(
1127 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ |
1128 base::PLATFORM_FILE_ASYNC,
1131 ASSERT_NE(base::kInvalidPlatformFileValue, file);
1133 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE |
1134 base::PLATFORM_FILE_ASYNC;
1135 scoped_ptr<FileStream> stream(
1136 new FileStream(file, flags, NULL, base::MessageLoopProxy::current()));
1138 scoped_refptr<IOBuffer> buf = new IOBuffer(1);
1141 TestCompletionCallback callback;
1142 int rv = stream->Write(buf.get(), 1, callback.callback());
1143 if (rv == ERR_IO_PENDING)
1144 rv = callback.WaitForResult();
1147 base::ClosePlatformFile(file);
1150 // Verify that async Read() errors are mapped correctly.
1151 TEST_F(FileStreamTest, AsyncReadError) {
1152 // Try opening file for write and then reading from it using FileStream.
1153 base::PlatformFile file = base::CreatePlatformFile(
1155 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE |
1156 base::PLATFORM_FILE_ASYNC,
1159 ASSERT_NE(base::kInvalidPlatformFileValue, file);
1161 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ |
1162 base::PLATFORM_FILE_ASYNC;
1163 scoped_ptr<FileStream> stream(
1164 new FileStream(file, flags, NULL, base::MessageLoopProxy::current()));
1166 scoped_refptr<IOBuffer> buf = new IOBuffer(1);
1167 TestCompletionCallback callback;
1168 int rv = stream->Read(buf.get(), 1, callback.callback());
1169 if (rv == ERR_IO_PENDING)
1170 rv = callback.WaitForResult();
1173 base::ClosePlatformFile(file);