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