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
, FileHandleNotLeftOpen
) {
83 ASSERT_EQ(kTestDataSize
,
84 file_util::WriteFile(temp_file_path(), kTestData
, kTestDataSize
));
85 int flags
= base::PLATFORM_FILE_OPEN_ALWAYS
| base::PLATFORM_FILE_READ
;
86 base::PlatformFile file
= base::CreatePlatformFile(
87 temp_file_path(), flags
, &created
, NULL
);
90 // Seek to the beginning of the file and read.
91 FileStream
read_stream(file
, flags
, NULL
,
92 base::MessageLoopProxy::current());
93 EXPECT_TRUE(read_stream
.IsOpen());
96 EXPECT_NE(base::kInvalidPlatformFileValue
, file
);
97 base::PlatformFileInfo info
;
98 // The file should be closed.
99 EXPECT_FALSE(base::GetPlatformFileInfo(file
, &info
));
102 // Test the use of FileStream with a file handle provided at construction.
103 TEST_F(FileStreamTest
, UseFileHandle
) {
104 bool created
= false;
106 // 1. Test reading with a file handle.
107 ASSERT_EQ(kTestDataSize
,
108 file_util::WriteFile(temp_file_path(), kTestData
, kTestDataSize
));
109 int flags
= base::PLATFORM_FILE_OPEN_ALWAYS
| base::PLATFORM_FILE_READ
;
110 base::PlatformFile file
= base::CreatePlatformFile(
111 temp_file_path(), flags
, &created
, NULL
);
113 // Seek to the beginning of the file and read.
114 scoped_ptr
<FileStream
> read_stream(
115 new FileStream(file
, flags
, NULL
, base::MessageLoopProxy::current()));
116 ASSERT_EQ(0, read_stream
->SeekSync(FROM_BEGIN
, 0));
117 ASSERT_EQ(kTestDataSize
, read_stream
->Available());
118 // Read into buffer and compare.
119 char buffer
[kTestDataSize
];
120 ASSERT_EQ(kTestDataSize
,
121 read_stream
->ReadSync(buffer
, kTestDataSize
));
122 ASSERT_EQ(0, memcmp(kTestData
, buffer
, kTestDataSize
));
125 // 2. Test writing with a file handle.
126 base::DeleteFile(temp_file_path(), false);
127 flags
= base::PLATFORM_FILE_OPEN_ALWAYS
| base::PLATFORM_FILE_WRITE
;
128 file
= base::CreatePlatformFile(temp_file_path(), flags
, &created
, NULL
);
130 scoped_ptr
<FileStream
> write_stream(
131 new FileStream(file
, flags
, NULL
, base::MessageLoopProxy::current()));
132 ASSERT_EQ(0, write_stream
->SeekSync(FROM_BEGIN
, 0));
133 ASSERT_EQ(kTestDataSize
,
134 write_stream
->WriteSync(kTestData
, kTestDataSize
));
135 write_stream
.reset();
137 // Read into buffer and compare to make sure the handle worked fine.
138 ASSERT_EQ(kTestDataSize
,
139 file_util::ReadFile(temp_file_path(), buffer
, kTestDataSize
));
140 ASSERT_EQ(0, memcmp(kTestData
, buffer
, kTestDataSize
));
143 TEST_F(FileStreamTest
, UseClosedStream
) {
144 FileStream
stream(NULL
, base::MessageLoopProxy::current());
146 EXPECT_FALSE(stream
.IsOpen());
149 int64 new_offset
= stream
.SeekSync(FROM_BEGIN
, 5);
150 EXPECT_EQ(ERR_UNEXPECTED
, new_offset
);
153 int64 avail
= stream
.Available();
154 EXPECT_EQ(ERR_UNEXPECTED
, avail
);
158 int rv
= stream
.ReadSync(buf
, arraysize(buf
));
159 EXPECT_EQ(ERR_UNEXPECTED
, rv
);
162 TEST_F(FileStreamTest
, BasicRead
) {
164 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
167 FileStream
stream(NULL
, base::MessageLoopProxy::current());
168 int flags
= base::PLATFORM_FILE_OPEN
|
169 base::PLATFORM_FILE_READ
;
170 int rv
= stream
.OpenSync(temp_file_path(), flags
);
173 int64 total_bytes_avail
= stream
.Available();
174 EXPECT_EQ(file_size
, total_bytes_avail
);
176 int total_bytes_read
= 0;
178 std::string data_read
;
181 rv
= stream
.ReadSync(buf
, arraysize(buf
));
185 total_bytes_read
+= rv
;
186 data_read
.append(buf
, rv
);
188 EXPECT_EQ(file_size
, total_bytes_read
);
189 EXPECT_EQ(kTestData
, data_read
);
192 TEST_F(FileStreamTest
, AsyncRead
) {
194 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
197 FileStream
stream(NULL
, base::MessageLoopProxy::current());
198 int flags
= base::PLATFORM_FILE_OPEN
|
199 base::PLATFORM_FILE_READ
|
200 base::PLATFORM_FILE_ASYNC
;
201 TestCompletionCallback callback
;
202 int rv
= stream
.Open(temp_file_path(), flags
, callback
.callback());
203 EXPECT_EQ(ERR_IO_PENDING
, rv
);
204 EXPECT_EQ(OK
, callback
.WaitForResult());
206 int64 total_bytes_avail
= stream
.Available();
207 EXPECT_EQ(file_size
, total_bytes_avail
);
209 int total_bytes_read
= 0;
211 std::string data_read
;
213 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
214 rv
= stream
.Read(buf
.get(), buf
->size(), callback
.callback());
215 if (rv
== ERR_IO_PENDING
)
216 rv
= callback
.WaitForResult();
220 total_bytes_read
+= rv
;
221 data_read
.append(buf
->data(), rv
);
223 EXPECT_EQ(file_size
, total_bytes_read
);
224 EXPECT_EQ(kTestData
, data_read
);
227 TEST_F(FileStreamTest
, AsyncRead_EarlyDelete
) {
229 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
232 scoped_ptr
<FileStream
> stream(
233 new FileStream(NULL
, base::MessageLoopProxy::current()));
234 int flags
= base::PLATFORM_FILE_OPEN
|
235 base::PLATFORM_FILE_READ
|
236 base::PLATFORM_FILE_ASYNC
;
237 TestCompletionCallback callback
;
238 int rv
= stream
->Open(temp_file_path(), flags
, callback
.callback());
239 EXPECT_EQ(ERR_IO_PENDING
, rv
);
240 EXPECT_EQ(OK
, callback
.WaitForResult());
242 int64 total_bytes_avail
= stream
->Available();
243 EXPECT_EQ(file_size
, total_bytes_avail
);
245 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
246 rv
= stream
->Read(buf
.get(), buf
->size(), callback
.callback());
247 stream
.reset(); // Delete instead of closing it.
249 EXPECT_EQ(ERR_IO_PENDING
, rv
);
250 // The callback should not be called if the request is cancelled.
251 base::RunLoop().RunUntilIdle();
252 EXPECT_FALSE(callback
.have_result());
254 EXPECT_EQ(std::string(kTestData
, rv
), std::string(buf
->data(), rv
));
258 TEST_F(FileStreamTest
, BasicRead_FromOffset
) {
260 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
263 FileStream
stream(NULL
, base::MessageLoopProxy::current());
264 int flags
= base::PLATFORM_FILE_OPEN
|
265 base::PLATFORM_FILE_READ
;
266 int rv
= stream
.OpenSync(temp_file_path(), flags
);
269 const int64 kOffset
= 3;
270 int64 new_offset
= stream
.SeekSync(FROM_BEGIN
, kOffset
);
271 EXPECT_EQ(kOffset
, new_offset
);
273 int64 total_bytes_avail
= stream
.Available();
274 EXPECT_EQ(file_size
- kOffset
, total_bytes_avail
);
276 int64 total_bytes_read
= 0;
278 std::string data_read
;
281 rv
= stream
.ReadSync(buf
, arraysize(buf
));
285 total_bytes_read
+= rv
;
286 data_read
.append(buf
, rv
);
288 EXPECT_EQ(file_size
- kOffset
, total_bytes_read
);
289 EXPECT_TRUE(data_read
== kTestData
+ kOffset
);
290 EXPECT_EQ(kTestData
+ kOffset
, data_read
);
293 TEST_F(FileStreamTest
, AsyncRead_FromOffset
) {
295 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
298 FileStream
stream(NULL
, base::MessageLoopProxy::current());
299 int flags
= base::PLATFORM_FILE_OPEN
|
300 base::PLATFORM_FILE_READ
|
301 base::PLATFORM_FILE_ASYNC
;
302 TestCompletionCallback callback
;
303 int rv
= stream
.Open(temp_file_path(), flags
, callback
.callback());
304 EXPECT_EQ(ERR_IO_PENDING
, rv
);
305 EXPECT_EQ(OK
, callback
.WaitForResult());
307 TestInt64CompletionCallback callback64
;
308 const int64 kOffset
= 3;
309 rv
= stream
.Seek(FROM_BEGIN
, kOffset
, callback64
.callback());
310 ASSERT_EQ(ERR_IO_PENDING
, rv
);
311 int64 new_offset
= callback64
.WaitForResult();
312 EXPECT_EQ(kOffset
, new_offset
);
314 int64 total_bytes_avail
= stream
.Available();
315 EXPECT_EQ(file_size
- kOffset
, total_bytes_avail
);
317 int total_bytes_read
= 0;
319 std::string data_read
;
321 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
322 rv
= stream
.Read(buf
.get(), buf
->size(), callback
.callback());
323 if (rv
== ERR_IO_PENDING
)
324 rv
= callback
.WaitForResult();
328 total_bytes_read
+= rv
;
329 data_read
.append(buf
->data(), rv
);
331 EXPECT_EQ(file_size
- kOffset
, total_bytes_read
);
332 EXPECT_EQ(kTestData
+ kOffset
, data_read
);
335 TEST_F(FileStreamTest
, SeekAround
) {
336 FileStream
stream(NULL
, base::MessageLoopProxy::current());
337 int flags
= base::PLATFORM_FILE_OPEN
|
338 base::PLATFORM_FILE_READ
;
339 int rv
= stream
.OpenSync(temp_file_path(), flags
);
342 const int64 kOffset
= 3;
343 int64 new_offset
= stream
.SeekSync(FROM_BEGIN
, kOffset
);
344 EXPECT_EQ(kOffset
, new_offset
);
346 new_offset
= stream
.SeekSync(FROM_CURRENT
, kOffset
);
347 EXPECT_EQ(2 * kOffset
, new_offset
);
349 new_offset
= stream
.SeekSync(FROM_CURRENT
, -kOffset
);
350 EXPECT_EQ(kOffset
, new_offset
);
352 const int kTestDataLen
= arraysize(kTestData
) - 1;
354 new_offset
= stream
.SeekSync(FROM_END
, -kTestDataLen
);
355 EXPECT_EQ(0, new_offset
);
358 TEST_F(FileStreamTest
, AsyncSeekAround
) {
359 FileStream
stream(NULL
, base::MessageLoopProxy::current());
360 int flags
= base::PLATFORM_FILE_OPEN
|
361 base::PLATFORM_FILE_ASYNC
|
362 base::PLATFORM_FILE_READ
;
363 TestCompletionCallback callback
;
364 int rv
= stream
.Open(temp_file_path(), flags
, callback
.callback());
365 EXPECT_EQ(ERR_IO_PENDING
, rv
);
366 EXPECT_EQ(OK
, callback
.WaitForResult());
368 TestInt64CompletionCallback callback64
;
370 const int64 kOffset
= 3;
371 rv
= stream
.Seek(FROM_BEGIN
, kOffset
, callback64
.callback());
372 ASSERT_EQ(ERR_IO_PENDING
, rv
);
373 int64 new_offset
= callback64
.WaitForResult();
374 EXPECT_EQ(kOffset
, new_offset
);
376 rv
= stream
.Seek(FROM_CURRENT
, kOffset
, callback64
.callback());
377 ASSERT_EQ(ERR_IO_PENDING
, rv
);
378 new_offset
= callback64
.WaitForResult();
379 EXPECT_EQ(2 * kOffset
, new_offset
);
381 rv
= stream
.Seek(FROM_CURRENT
, -kOffset
, callback64
.callback());
382 ASSERT_EQ(ERR_IO_PENDING
, rv
);
383 new_offset
= callback64
.WaitForResult();
384 EXPECT_EQ(kOffset
, new_offset
);
386 const int kTestDataLen
= arraysize(kTestData
) - 1;
388 rv
= stream
.Seek(FROM_END
, -kTestDataLen
, callback64
.callback());
389 ASSERT_EQ(ERR_IO_PENDING
, rv
);
390 new_offset
= callback64
.WaitForResult();
391 EXPECT_EQ(0, new_offset
);
394 TEST_F(FileStreamTest
, BasicWrite
) {
395 scoped_ptr
<FileStream
> stream(
396 new FileStream(NULL
, base::MessageLoopProxy::current()));
397 int flags
= base::PLATFORM_FILE_CREATE_ALWAYS
|
398 base::PLATFORM_FILE_WRITE
;
399 int rv
= stream
->OpenSync(temp_file_path(), flags
);
403 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
405 EXPECT_EQ(0, file_size
);
407 rv
= stream
->WriteSync(kTestData
, kTestDataSize
);
408 EXPECT_EQ(kTestDataSize
, rv
);
411 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
413 EXPECT_EQ(kTestDataSize
, file_size
);
416 TEST_F(FileStreamTest
, AsyncWrite
) {
417 FileStream
stream(NULL
, base::MessageLoopProxy::current());
418 int flags
= base::PLATFORM_FILE_CREATE_ALWAYS
|
419 base::PLATFORM_FILE_WRITE
|
420 base::PLATFORM_FILE_ASYNC
;
421 TestCompletionCallback callback
;
422 int rv
= stream
.Open(temp_file_path(), flags
, callback
.callback());
423 EXPECT_EQ(ERR_IO_PENDING
, rv
);
424 EXPECT_EQ(OK
, callback
.WaitForResult());
427 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
429 EXPECT_EQ(0, file_size
);
431 int total_bytes_written
= 0;
433 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
434 scoped_refptr
<DrainableIOBuffer
> drainable
=
435 new DrainableIOBuffer(buf
.get(), buf
->size());
436 while (total_bytes_written
!= kTestDataSize
) {
438 drainable
.get(), drainable
->BytesRemaining(), callback
.callback());
439 if (rv
== ERR_IO_PENDING
)
440 rv
= callback
.WaitForResult();
444 drainable
->DidConsume(rv
);
445 total_bytes_written
+= rv
;
447 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
449 EXPECT_EQ(file_size
, total_bytes_written
);
452 TEST_F(FileStreamTest
, AsyncWrite_EarlyDelete
) {
453 scoped_ptr
<FileStream
> stream(
454 new FileStream(NULL
, base::MessageLoopProxy::current()));
455 int flags
= base::PLATFORM_FILE_CREATE_ALWAYS
|
456 base::PLATFORM_FILE_WRITE
|
457 base::PLATFORM_FILE_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());
464 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
466 EXPECT_EQ(0, file_size
);
468 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
469 rv
= stream
->Write(buf
.get(), buf
->size(), callback
.callback());
472 EXPECT_EQ(ERR_IO_PENDING
, rv
);
473 // The callback should not be called if the request is cancelled.
474 base::RunLoop().RunUntilIdle();
475 EXPECT_FALSE(callback
.have_result());
477 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
479 EXPECT_EQ(file_size
, rv
);
483 TEST_F(FileStreamTest
, BasicWrite_FromOffset
) {
484 scoped_ptr
<FileStream
> stream(
485 new FileStream(NULL
, base::MessageLoopProxy::current()));
486 int flags
= base::PLATFORM_FILE_OPEN
|
487 base::PLATFORM_FILE_WRITE
;
488 int rv
= stream
->OpenSync(temp_file_path(), flags
);
492 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
494 EXPECT_EQ(kTestDataSize
, file_size
);
496 const int64 kOffset
= 0;
497 int64 new_offset
= stream
->SeekSync(FROM_END
, kOffset
);
498 EXPECT_EQ(kTestDataSize
, new_offset
);
500 rv
= stream
->WriteSync(kTestData
, kTestDataSize
);
501 EXPECT_EQ(kTestDataSize
, rv
);
504 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
506 EXPECT_EQ(kTestDataSize
* 2, file_size
);
509 TEST_F(FileStreamTest
, AsyncWrite_FromOffset
) {
511 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
514 FileStream
stream(NULL
, base::MessageLoopProxy::current());
515 int flags
= base::PLATFORM_FILE_OPEN
|
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());
523 TestInt64CompletionCallback callback64
;
524 const int64 kOffset
= 0;
525 rv
= stream
.Seek(FROM_END
, kOffset
, callback64
.callback());
526 ASSERT_EQ(ERR_IO_PENDING
, rv
);
527 int64 new_offset
= callback64
.WaitForResult();
528 EXPECT_EQ(kTestDataSize
, new_offset
);
530 int total_bytes_written
= 0;
532 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
533 scoped_refptr
<DrainableIOBuffer
> drainable
=
534 new DrainableIOBuffer(buf
.get(), buf
->size());
535 while (total_bytes_written
!= kTestDataSize
) {
537 drainable
.get(), drainable
->BytesRemaining(), callback
.callback());
538 if (rv
== ERR_IO_PENDING
)
539 rv
= callback
.WaitForResult();
543 drainable
->DidConsume(rv
);
544 total_bytes_written
+= rv
;
546 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
548 EXPECT_EQ(file_size
, kTestDataSize
* 2);
551 TEST_F(FileStreamTest
, BasicReadWrite
) {
553 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
556 scoped_ptr
<FileStream
> stream(
557 new FileStream(NULL
, base::MessageLoopProxy::current()));
558 int flags
= base::PLATFORM_FILE_OPEN
|
559 base::PLATFORM_FILE_READ
|
560 base::PLATFORM_FILE_WRITE
;
561 int rv
= stream
->OpenSync(temp_file_path(), flags
);
564 int64 total_bytes_avail
= stream
->Available();
565 EXPECT_EQ(file_size
, total_bytes_avail
);
567 int total_bytes_read
= 0;
569 std::string data_read
;
572 rv
= stream
->ReadSync(buf
, arraysize(buf
));
576 total_bytes_read
+= rv
;
577 data_read
.append(buf
, rv
);
579 EXPECT_EQ(file_size
, total_bytes_read
);
580 EXPECT_TRUE(data_read
== kTestData
);
582 rv
= stream
->WriteSync(kTestData
, kTestDataSize
);
583 EXPECT_EQ(kTestDataSize
, rv
);
586 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
588 EXPECT_EQ(kTestDataSize
* 2, file_size
);
591 TEST_F(FileStreamTest
, BasicWriteRead
) {
593 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
596 scoped_ptr
<FileStream
> stream(
597 new FileStream(NULL
, base::MessageLoopProxy::current()));
598 int flags
= base::PLATFORM_FILE_OPEN
|
599 base::PLATFORM_FILE_READ
|
600 base::PLATFORM_FILE_WRITE
;
601 int rv
= stream
->OpenSync(temp_file_path(), flags
);
604 int64 total_bytes_avail
= stream
->Available();
605 EXPECT_EQ(file_size
, total_bytes_avail
);
607 int64 offset
= stream
->SeekSync(FROM_END
, 0);
608 EXPECT_EQ(offset
, file_size
);
610 rv
= stream
->WriteSync(kTestData
, kTestDataSize
);
611 EXPECT_EQ(kTestDataSize
, rv
);
613 offset
= stream
->SeekSync(FROM_BEGIN
, 0);
614 EXPECT_EQ(0, offset
);
616 int64 total_bytes_read
= 0;
618 std::string data_read
;
621 rv
= stream
->ReadSync(buf
, arraysize(buf
));
625 total_bytes_read
+= rv
;
626 data_read
.append(buf
, rv
);
630 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
632 EXPECT_EQ(kTestDataSize
* 2, file_size
);
633 EXPECT_EQ(kTestDataSize
* 2, total_bytes_read
);
635 const std::string kExpectedFileData
=
636 std::string(kTestData
) + std::string(kTestData
);
637 EXPECT_EQ(kExpectedFileData
, data_read
);
640 TEST_F(FileStreamTest
, BasicAsyncReadWrite
) {
642 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
645 scoped_ptr
<FileStream
> stream(
646 new FileStream(NULL
, base::MessageLoopProxy::current()));
647 int flags
= base::PLATFORM_FILE_OPEN
|
648 base::PLATFORM_FILE_READ
|
649 base::PLATFORM_FILE_WRITE
|
650 base::PLATFORM_FILE_ASYNC
;
651 TestCompletionCallback callback
;
652 int rv
= stream
->Open(temp_file_path(), flags
, callback
.callback());
653 EXPECT_EQ(ERR_IO_PENDING
, rv
);
654 EXPECT_EQ(OK
, callback
.WaitForResult());
656 int64 total_bytes_avail
= stream
->Available();
657 EXPECT_EQ(file_size
, total_bytes_avail
);
659 int64 total_bytes_read
= 0;
661 std::string data_read
;
663 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
664 rv
= stream
->Read(buf
.get(), buf
->size(), callback
.callback());
665 if (rv
== ERR_IO_PENDING
)
666 rv
= callback
.WaitForResult();
670 total_bytes_read
+= rv
;
671 data_read
.append(buf
->data(), rv
);
673 EXPECT_EQ(file_size
, total_bytes_read
);
674 EXPECT_TRUE(data_read
== kTestData
);
676 int total_bytes_written
= 0;
678 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
679 scoped_refptr
<DrainableIOBuffer
> drainable
=
680 new DrainableIOBuffer(buf
.get(), buf
->size());
681 while (total_bytes_written
!= kTestDataSize
) {
683 drainable
.get(), drainable
->BytesRemaining(), callback
.callback());
684 if (rv
== ERR_IO_PENDING
)
685 rv
= callback
.WaitForResult();
689 drainable
->DidConsume(rv
);
690 total_bytes_written
+= rv
;
695 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
697 EXPECT_EQ(kTestDataSize
* 2, file_size
);
700 TEST_F(FileStreamTest
, BasicAsyncWriteRead
) {
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 TestInt64CompletionCallback callback64
;
720 rv
= stream
->Seek(FROM_END
, 0, callback64
.callback());
721 ASSERT_EQ(ERR_IO_PENDING
, rv
);
722 int64 offset
= callback64
.WaitForResult();
723 EXPECT_EQ(offset
, file_size
);
725 int total_bytes_written
= 0;
727 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
728 scoped_refptr
<DrainableIOBuffer
> drainable
=
729 new DrainableIOBuffer(buf
.get(), buf
->size());
730 while (total_bytes_written
!= kTestDataSize
) {
732 drainable
.get(), drainable
->BytesRemaining(), callback
.callback());
733 if (rv
== ERR_IO_PENDING
)
734 rv
= callback
.WaitForResult();
738 drainable
->DidConsume(rv
);
739 total_bytes_written
+= rv
;
742 EXPECT_EQ(kTestDataSize
, total_bytes_written
);
744 rv
= stream
->Seek(FROM_BEGIN
, 0, callback64
.callback());
745 ASSERT_EQ(ERR_IO_PENDING
, rv
);
746 offset
= callback64
.WaitForResult();
747 EXPECT_EQ(0, offset
);
749 int total_bytes_read
= 0;
751 std::string data_read
;
753 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
754 rv
= stream
->Read(buf
.get(), buf
->size(), callback
.callback());
755 if (rv
== ERR_IO_PENDING
)
756 rv
= callback
.WaitForResult();
760 total_bytes_read
+= rv
;
761 data_read
.append(buf
->data(), rv
);
765 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
767 EXPECT_EQ(kTestDataSize
* 2, file_size
);
769 EXPECT_EQ(kTestDataSize
* 2, total_bytes_read
);
770 const std::string kExpectedFileData
=
771 std::string(kTestData
) + std::string(kTestData
);
772 EXPECT_EQ(kExpectedFileData
, data_read
);
775 class TestWriteReadCompletionCallback
{
777 TestWriteReadCompletionCallback(FileStream
* stream
,
778 int* total_bytes_written
,
779 int* total_bytes_read
,
780 std::string
* data_read
)
783 waiting_for_result_(false),
785 total_bytes_written_(total_bytes_written
),
786 total_bytes_read_(total_bytes_read
),
787 data_read_(data_read
),
788 callback_(base::Bind(&TestWriteReadCompletionCallback::OnComplete
,
789 base::Unretained(this))),
790 test_data_(CreateTestDataBuffer()),
791 drainable_(new DrainableIOBuffer(test_data_
.get(), kTestDataSize
)) {}
793 int WaitForResult() {
794 DCHECK(!waiting_for_result_
);
795 while (!have_result_
) {
796 waiting_for_result_
= true;
797 base::RunLoop().Run();
798 waiting_for_result_
= false;
800 have_result_
= false; // auto-reset for next callback
804 const CompletionCallback
& callback() const { return callback_
; }
807 void OnComplete(int result
) {
808 DCHECK_LT(0, result
);
809 *total_bytes_written_
+= result
;
813 if (*total_bytes_written_
!= kTestDataSize
) {
814 // Recurse to finish writing all data.
815 int total_bytes_written
= 0, total_bytes_read
= 0;
816 std::string data_read
;
817 TestWriteReadCompletionCallback
callback(
818 stream_
, &total_bytes_written
, &total_bytes_read
, &data_read
);
820 drainable_
.get(), drainable_
->BytesRemaining(), callback
.callback());
821 DCHECK_EQ(ERR_IO_PENDING
, rv
);
822 rv
= callback
.WaitForResult();
823 drainable_
->DidConsume(total_bytes_written
);
824 *total_bytes_written_
+= total_bytes_written
;
825 *total_bytes_read_
+= total_bytes_read
;
826 *data_read_
+= data_read
;
827 } else { // We're done writing all data. Start reading the data.
828 stream_
->SeekSync(FROM_BEGIN
, 0);
830 TestCompletionCallback callback
;
832 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
833 rv
= stream_
->Read(buf
.get(), buf
->size(), callback
.callback());
834 if (rv
== ERR_IO_PENDING
) {
835 base::MessageLoop::ScopedNestableTaskAllower
allow(
836 base::MessageLoop::current());
837 rv
= callback
.WaitForResult();
842 *total_bytes_read_
+= rv
;
843 data_read_
->append(buf
->data(), rv
);
847 result_
= *total_bytes_written_
;
849 if (waiting_for_result_
)
850 base::MessageLoop::current()->Quit();
855 bool waiting_for_result_
;
857 int* total_bytes_written_
;
858 int* total_bytes_read_
;
859 std::string
* data_read_
;
860 const CompletionCallback callback_
;
861 scoped_refptr
<IOBufferWithSize
> test_data_
;
862 scoped_refptr
<DrainableIOBuffer
> drainable_
;
864 DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback
);
867 TEST_F(FileStreamTest
, AsyncWriteRead
) {
869 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
872 scoped_ptr
<FileStream
> stream(
873 new FileStream(NULL
, base::MessageLoopProxy::current()));
874 int flags
= base::PLATFORM_FILE_OPEN
|
875 base::PLATFORM_FILE_READ
|
876 base::PLATFORM_FILE_WRITE
|
877 base::PLATFORM_FILE_ASYNC
;
878 TestCompletionCallback open_callback
;
879 int rv
= stream
->Open(temp_file_path(), flags
, open_callback
.callback());
880 EXPECT_EQ(ERR_IO_PENDING
, rv
);
881 EXPECT_EQ(OK
, open_callback
.WaitForResult());
883 int64 total_bytes_avail
= stream
->Available();
884 EXPECT_EQ(file_size
, total_bytes_avail
);
886 int64 offset
= stream
->SeekSync(FROM_END
, 0);
887 EXPECT_EQ(offset
, file_size
);
889 int total_bytes_written
= 0;
890 int total_bytes_read
= 0;
891 std::string data_read
;
892 TestWriteReadCompletionCallback
callback(stream
.get(), &total_bytes_written
,
893 &total_bytes_read
, &data_read
);
895 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
896 rv
= stream
->Write(buf
.get(), buf
->size(), callback
.callback());
897 if (rv
== ERR_IO_PENDING
)
898 rv
= callback
.WaitForResult();
900 EXPECT_EQ(kTestDataSize
, total_bytes_written
);
904 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
906 EXPECT_EQ(kTestDataSize
* 2, file_size
);
908 EXPECT_EQ(kTestDataSize
* 2, total_bytes_read
);
909 const std::string kExpectedFileData
=
910 std::string(kTestData
) + std::string(kTestData
);
911 EXPECT_EQ(kExpectedFileData
, data_read
);
914 class TestWriteCloseCompletionCallback
{
916 TestWriteCloseCompletionCallback(FileStream
* stream
, int* total_bytes_written
)
919 waiting_for_result_(false),
921 total_bytes_written_(total_bytes_written
),
922 callback_(base::Bind(&TestWriteCloseCompletionCallback::OnComplete
,
923 base::Unretained(this))),
924 test_data_(CreateTestDataBuffer()),
925 drainable_(new DrainableIOBuffer(test_data_
.get(), kTestDataSize
)) {}
927 int WaitForResult() {
928 DCHECK(!waiting_for_result_
);
929 while (!have_result_
) {
930 waiting_for_result_
= true;
931 base::RunLoop().Run();
932 waiting_for_result_
= false;
934 have_result_
= false; // auto-reset for next callback
938 const CompletionCallback
& callback() const { return callback_
; }
941 void OnComplete(int result
) {
942 DCHECK_LT(0, result
);
943 *total_bytes_written_
+= result
;
947 if (*total_bytes_written_
!= kTestDataSize
) {
948 // Recurse to finish writing all data.
949 int total_bytes_written
= 0;
950 TestWriteCloseCompletionCallback
callback(stream_
, &total_bytes_written
);
952 drainable_
.get(), drainable_
->BytesRemaining(), callback
.callback());
953 DCHECK_EQ(ERR_IO_PENDING
, rv
);
954 rv
= callback
.WaitForResult();
955 drainable_
->DidConsume(total_bytes_written
);
956 *total_bytes_written_
+= total_bytes_written
;
959 result_
= *total_bytes_written_
;
961 if (waiting_for_result_
)
962 base::MessageLoop::current()->Quit();
967 bool waiting_for_result_
;
969 int* total_bytes_written_
;
970 const CompletionCallback callback_
;
971 scoped_refptr
<IOBufferWithSize
> test_data_
;
972 scoped_refptr
<DrainableIOBuffer
> drainable_
;
974 DISALLOW_COPY_AND_ASSIGN(TestWriteCloseCompletionCallback
);
977 TEST_F(FileStreamTest
, AsyncWriteClose
) {
979 bool ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
982 scoped_ptr
<FileStream
> stream(
983 new FileStream(NULL
, base::MessageLoopProxy::current()));
984 int flags
= base::PLATFORM_FILE_OPEN
|
985 base::PLATFORM_FILE_READ
|
986 base::PLATFORM_FILE_WRITE
|
987 base::PLATFORM_FILE_ASYNC
;
988 TestCompletionCallback open_callback
;
989 int rv
= stream
->Open(temp_file_path(), flags
, open_callback
.callback());
990 EXPECT_EQ(ERR_IO_PENDING
, rv
);
991 EXPECT_EQ(OK
, open_callback
.WaitForResult());
993 int64 total_bytes_avail
= stream
->Available();
994 EXPECT_EQ(file_size
, total_bytes_avail
);
996 int64 offset
= stream
->SeekSync(FROM_END
, 0);
997 EXPECT_EQ(offset
, file_size
);
999 int total_bytes_written
= 0;
1000 TestWriteCloseCompletionCallback
callback(stream
.get(), &total_bytes_written
);
1002 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
1003 rv
= stream
->Write(buf
.get(), buf
->size(), callback
.callback());
1004 if (rv
== ERR_IO_PENDING
)
1005 total_bytes_written
= callback
.WaitForResult();
1006 EXPECT_LT(0, total_bytes_written
);
1007 EXPECT_EQ(kTestDataSize
, total_bytes_written
);
1011 ok
= file_util::GetFileSize(temp_file_path(), &file_size
);
1013 EXPECT_EQ(kTestDataSize
* 2, file_size
);
1016 // Tests truncating a file.
1017 TEST_F(FileStreamTest
, Truncate
) {
1018 int flags
= base::PLATFORM_FILE_CREATE_ALWAYS
| base::PLATFORM_FILE_WRITE
;
1020 scoped_ptr
<FileStream
> write_stream(
1021 new FileStream(NULL
, base::MessageLoopProxy::current()));
1022 ASSERT_EQ(OK
, write_stream
->OpenSync(temp_file_path(), flags
));
1024 // Write some data to the file.
1025 const char test_data
[] = "0123456789";
1026 write_stream
->WriteSync(test_data
, arraysize(test_data
));
1028 // Truncate the file.
1029 ASSERT_EQ(4, write_stream
->Truncate(4));
1032 write_stream
->WriteSync(test_data
, 4);
1034 // Close the stream.
1035 write_stream
.reset();
1037 // Read in the contents and make sure we get back what we expected.
1038 std::string read_contents
;
1039 EXPECT_TRUE(base::ReadFileToString(temp_file_path(), &read_contents
));
1041 EXPECT_EQ("01230123", read_contents
);
1044 TEST_F(FileStreamTest
, AsyncOpenAndDelete
) {
1045 scoped_ptr
<FileStream
> stream(
1046 new FileStream(NULL
, base::MessageLoopProxy::current()));
1047 int flags
= base::PLATFORM_FILE_OPEN
|
1048 base::PLATFORM_FILE_WRITE
|
1049 base::PLATFORM_FILE_ASYNC
;
1050 TestCompletionCallback open_callback
;
1051 int rv
= stream
->Open(temp_file_path(), flags
, open_callback
.callback());
1052 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1054 // Delete the stream without waiting for the open operation to be
1055 // complete. Should be safe.
1057 // open_callback won't be called.
1058 base::RunLoop().RunUntilIdle();
1059 EXPECT_FALSE(open_callback
.have_result());
1062 // Verify that async Write() errors are mapped correctly.
1063 TEST_F(FileStreamTest
, AsyncWriteError
) {
1064 scoped_ptr
<FileStream
> stream(
1065 new FileStream(NULL
, base::MessageLoopProxy::current()));
1066 int flags
= base::PLATFORM_FILE_CREATE_ALWAYS
|
1067 base::PLATFORM_FILE_WRITE
|
1068 base::PLATFORM_FILE_ASYNC
;
1069 TestCompletionCallback callback
;
1070 int rv
= stream
->Open(temp_file_path(), flags
, callback
.callback());
1071 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1072 EXPECT_EQ(OK
, callback
.WaitForResult());
1074 // Try passing NULL buffer to Write() and check that it fails.
1075 scoped_refptr
<IOBuffer
> buf
= new WrappedIOBuffer(NULL
);
1076 rv
= stream
->Write(buf
.get(), 1, callback
.callback());
1077 if (rv
== ERR_IO_PENDING
)
1078 rv
= callback
.WaitForResult();
1082 // Verify that async Read() errors are mapped correctly.
1083 TEST_F(FileStreamTest
, AsyncReadError
) {
1084 scoped_ptr
<FileStream
> stream(
1085 new FileStream(NULL
, base::MessageLoopProxy::current()));
1086 int flags
= base::PLATFORM_FILE_OPEN
|
1087 base::PLATFORM_FILE_READ
|
1088 base::PLATFORM_FILE_ASYNC
;
1089 TestCompletionCallback callback
;
1090 int rv
= stream
->Open(temp_file_path(), flags
, callback
.callback());
1091 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1092 EXPECT_EQ(OK
, callback
.WaitForResult());
1094 // Try passing NULL buffer to Read() and check that it fails.
1095 scoped_refptr
<IOBuffer
> buf
= new WrappedIOBuffer(NULL
);
1096 rv
= stream
->Read(buf
.get(), 1, callback
.callback());
1097 if (rv
== ERR_IO_PENDING
)
1098 rv
= callback
.WaitForResult();