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/files/file.h"
10 #include "base/files/file_util.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/path_service.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_util.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "base/threading/sequenced_worker_pool.h"
19 #include "base/threading/thread_restrictions.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 "net/log/test_net_log.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "testing/platform_test.h"
27 #if defined(OS_ANDROID)
28 #include "base/test/test_file_util.h"
35 const char kTestData
[] = "0123456789";
36 const int kTestDataSize
= arraysize(kTestData
) - 1;
38 // Creates an IOBufferWithSize that contains the kTestDataSize.
39 IOBufferWithSize
* CreateTestDataBuffer() {
40 IOBufferWithSize
* buf
= new IOBufferWithSize(kTestDataSize
);
41 memcpy(buf
->data(), kTestData
, kTestDataSize
);
47 class FileStreamTest
: public PlatformTest
{
49 void SetUp() override
{
50 PlatformTest::SetUp();
52 base::CreateTemporaryFile(&temp_file_path_
);
53 base::WriteFile(temp_file_path_
, kTestData
, kTestDataSize
);
55 void TearDown() override
{
56 // FileStreamContexts must be asynchronously closed on the file task runner
57 // before they can be deleted. Pump the RunLoop to avoid leaks.
58 base::RunLoop().RunUntilIdle();
59 EXPECT_TRUE(base::DeleteFile(temp_file_path_
, false));
61 PlatformTest::TearDown();
64 const base::FilePath
temp_file_path() const { return temp_file_path_
; }
67 base::FilePath temp_file_path_
;
72 TEST_F(FileStreamTest
, OpenExplicitClose
) {
73 TestCompletionCallback callback
;
74 FileStream
stream(base::ThreadTaskRunnerHandle::Get());
75 int flags
= base::File::FLAG_OPEN
|
76 base::File::FLAG_READ
|
77 base::File::FLAG_ASYNC
;
78 int rv
= stream
.Open(temp_file_path(), flags
, callback
.callback());
79 EXPECT_EQ(ERR_IO_PENDING
, rv
);
80 EXPECT_EQ(OK
, callback
.WaitForResult());
81 EXPECT_TRUE(stream
.IsOpen());
82 EXPECT_EQ(ERR_IO_PENDING
, stream
.Close(callback
.callback()));
83 EXPECT_EQ(OK
, callback
.WaitForResult());
84 EXPECT_FALSE(stream
.IsOpen());
87 TEST_F(FileStreamTest
, OpenExplicitCloseOrphaned
) {
88 TestCompletionCallback callback
;
89 scoped_ptr
<FileStream
> stream(
90 new FileStream(base::ThreadTaskRunnerHandle::Get()));
91 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
92 base::File::FLAG_ASYNC
;
93 int rv
= stream
->Open(temp_file_path(), flags
, callback
.callback());
94 EXPECT_EQ(ERR_IO_PENDING
, rv
);
95 EXPECT_EQ(OK
, callback
.WaitForResult());
96 EXPECT_TRUE(stream
->IsOpen());
97 EXPECT_EQ(ERR_IO_PENDING
, stream
->Close(callback
.callback()));
99 // File isn't actually closed yet.
100 base::RunLoop runloop
;
101 runloop
.RunUntilIdle();
102 // The file should now be closed, though the callback has not been called.
105 // Test the use of FileStream with a file handle provided at construction.
106 TEST_F(FileStreamTest
, UseFileHandle
) {
108 TestCompletionCallback callback
;
109 TestInt64CompletionCallback callback64
;
110 // 1. Test reading with a file handle.
111 ASSERT_EQ(kTestDataSize
,
112 base::WriteFile(temp_file_path(), kTestData
, kTestDataSize
));
113 int flags
= base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_READ
|
114 base::File::FLAG_ASYNC
;
115 base::File
file(temp_file_path(), flags
);
117 // Seek to the beginning of the file and read.
118 scoped_ptr
<FileStream
> read_stream(
119 new FileStream(file
.Pass(), base::ThreadTaskRunnerHandle::Get()));
120 ASSERT_EQ(ERR_IO_PENDING
, read_stream
->Seek(0, callback64
.callback()));
121 ASSERT_EQ(0, callback64
.WaitForResult());
122 // Read into buffer and compare.
123 scoped_refptr
<IOBufferWithSize
> read_buffer
=
124 new IOBufferWithSize(kTestDataSize
);
125 rv
= read_stream
->Read(read_buffer
.get(), kTestDataSize
, callback
.callback());
126 ASSERT_EQ(kTestDataSize
, callback
.GetResult(rv
));
127 ASSERT_EQ(0, memcmp(kTestData
, read_buffer
->data(), kTestDataSize
));
130 // 2. Test writing with a file handle.
131 base::DeleteFile(temp_file_path(), false);
132 flags
= base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_WRITE
|
133 base::File::FLAG_ASYNC
;
134 file
.Initialize(temp_file_path(), flags
);
136 scoped_ptr
<FileStream
> write_stream(
137 new FileStream(file
.Pass(), base::ThreadTaskRunnerHandle::Get()));
138 ASSERT_EQ(ERR_IO_PENDING
, write_stream
->Seek(0, callback64
.callback()));
139 ASSERT_EQ(0, callback64
.WaitForResult());
140 scoped_refptr
<IOBufferWithSize
> write_buffer
= CreateTestDataBuffer();
141 rv
= write_stream
->Write(write_buffer
.get(), kTestDataSize
,
142 callback
.callback());
143 ASSERT_EQ(kTestDataSize
, callback
.GetResult(rv
));
144 write_stream
.reset();
146 // Read into buffer and compare to make sure the handle worked fine.
147 ASSERT_EQ(kTestDataSize
,
148 base::ReadFile(temp_file_path(), read_buffer
->data(),
150 ASSERT_EQ(0, memcmp(kTestData
, read_buffer
->data(), kTestDataSize
));
153 TEST_F(FileStreamTest
, UseClosedStream
) {
155 TestCompletionCallback callback
;
156 TestInt64CompletionCallback callback64
;
158 FileStream
stream(base::ThreadTaskRunnerHandle::Get());
160 EXPECT_FALSE(stream
.IsOpen());
163 rv
= stream
.Seek(5, callback64
.callback());
164 EXPECT_EQ(ERR_UNEXPECTED
, callback64
.GetResult(rv
));
167 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(10);
168 rv
= stream
.Read(buf
.get(), buf
->size(), callback
.callback());
169 EXPECT_EQ(ERR_UNEXPECTED
, callback
.GetResult(rv
));
172 TEST_F(FileStreamTest
, Read
) {
174 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
176 FileStream
stream(base::ThreadTaskRunnerHandle::Get());
177 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
178 base::File::FLAG_ASYNC
;
179 TestCompletionCallback callback
;
180 int rv
= stream
.Open(temp_file_path(), flags
, callback
.callback());
181 EXPECT_EQ(OK
, callback
.GetResult(rv
));
183 int total_bytes_read
= 0;
185 std::string data_read
;
187 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
188 rv
= stream
.Read(buf
.get(), buf
->size(), callback
.callback());
189 rv
= callback
.GetResult(rv
);
193 total_bytes_read
+= rv
;
194 data_read
.append(buf
->data(), rv
);
196 EXPECT_EQ(file_size
, total_bytes_read
);
197 EXPECT_EQ(kTestData
, data_read
);
200 TEST_F(FileStreamTest
, Read_EarlyDelete
) {
202 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
204 scoped_ptr
<FileStream
> stream(
205 new FileStream(base::ThreadTaskRunnerHandle::Get()));
206 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
207 base::File::FLAG_ASYNC
;
208 TestCompletionCallback callback
;
209 int rv
= stream
->Open(temp_file_path(), flags
, callback
.callback());
210 EXPECT_EQ(ERR_IO_PENDING
, rv
);
211 EXPECT_EQ(OK
, callback
.WaitForResult());
213 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
214 rv
= stream
->Read(buf
.get(), buf
->size(), callback
.callback());
215 stream
.reset(); // Delete instead of closing it.
217 EXPECT_EQ(ERR_IO_PENDING
, rv
);
218 // The callback should not be called if the request is cancelled.
219 base::RunLoop().RunUntilIdle();
220 EXPECT_FALSE(callback
.have_result());
222 EXPECT_EQ(std::string(kTestData
, rv
), std::string(buf
->data(), rv
));
226 TEST_F(FileStreamTest
, Read_FromOffset
) {
228 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
230 FileStream
stream(base::ThreadTaskRunnerHandle::Get());
231 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
232 base::File::FLAG_ASYNC
;
233 TestCompletionCallback callback
;
234 int rv
= stream
.Open(temp_file_path(), flags
, callback
.callback());
235 EXPECT_EQ(ERR_IO_PENDING
, rv
);
236 EXPECT_EQ(OK
, callback
.WaitForResult());
238 TestInt64CompletionCallback callback64
;
239 const int64_t kOffset
= 3;
240 rv
= stream
.Seek(kOffset
, callback64
.callback());
241 ASSERT_EQ(ERR_IO_PENDING
, rv
);
242 int64_t new_offset
= callback64
.WaitForResult();
243 EXPECT_EQ(kOffset
, new_offset
);
245 int total_bytes_read
= 0;
247 std::string data_read
;
249 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
250 rv
= stream
.Read(buf
.get(), buf
->size(), callback
.callback());
251 if (rv
== ERR_IO_PENDING
)
252 rv
= callback
.WaitForResult();
256 total_bytes_read
+= rv
;
257 data_read
.append(buf
->data(), rv
);
259 EXPECT_EQ(file_size
- kOffset
, total_bytes_read
);
260 EXPECT_EQ(kTestData
+ kOffset
, data_read
);
263 TEST_F(FileStreamTest
, Write
) {
264 FileStream
stream(base::ThreadTaskRunnerHandle::Get());
265 int flags
= base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_WRITE
|
266 base::File::FLAG_ASYNC
;
267 TestCompletionCallback callback
;
268 int rv
= stream
.Open(temp_file_path(), flags
, callback
.callback());
269 EXPECT_EQ(OK
, callback
.GetResult(rv
));
272 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
273 EXPECT_EQ(0, file_size
);
275 scoped_refptr
<IOBuffer
> buf
= CreateTestDataBuffer();
276 rv
= stream
.Write(buf
.get(), kTestDataSize
, callback
.callback());
277 rv
= callback
.GetResult(rv
);
278 EXPECT_EQ(kTestDataSize
, rv
);
280 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
281 EXPECT_EQ(kTestDataSize
, file_size
);
283 std::string data_read
;
284 EXPECT_TRUE(base::ReadFileToString(temp_file_path(), &data_read
));
285 EXPECT_EQ(kTestData
, data_read
);
288 TEST_F(FileStreamTest
, Write_EarlyDelete
) {
289 scoped_ptr
<FileStream
> stream(
290 new FileStream(base::ThreadTaskRunnerHandle::Get()));
291 int flags
= base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_WRITE
|
292 base::File::FLAG_ASYNC
;
293 TestCompletionCallback callback
;
294 int rv
= stream
->Open(temp_file_path(), flags
, callback
.callback());
295 EXPECT_EQ(ERR_IO_PENDING
, rv
);
296 EXPECT_EQ(OK
, callback
.WaitForResult());
299 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
300 EXPECT_EQ(0, file_size
);
302 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
303 rv
= stream
->Write(buf
.get(), buf
->size(), callback
.callback());
306 EXPECT_EQ(ERR_IO_PENDING
, rv
);
307 // The callback should not be called if the request is cancelled.
308 base::RunLoop().RunUntilIdle();
309 EXPECT_FALSE(callback
.have_result());
311 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
312 EXPECT_EQ(file_size
, rv
);
316 TEST_F(FileStreamTest
, Write_FromOffset
) {
318 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
320 FileStream
stream(base::ThreadTaskRunnerHandle::Get());
321 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_WRITE
|
322 base::File::FLAG_ASYNC
;
323 TestCompletionCallback callback
;
324 int rv
= stream
.Open(temp_file_path(), flags
, callback
.callback());
325 EXPECT_EQ(ERR_IO_PENDING
, rv
);
326 EXPECT_EQ(OK
, callback
.WaitForResult());
328 TestInt64CompletionCallback callback64
;
329 const int64_t kOffset
= kTestDataSize
;
330 rv
= stream
.Seek(kOffset
, callback64
.callback());
331 ASSERT_EQ(ERR_IO_PENDING
, rv
);
332 int64_t new_offset
= callback64
.WaitForResult();
333 EXPECT_EQ(kTestDataSize
, new_offset
);
335 int total_bytes_written
= 0;
337 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
338 scoped_refptr
<DrainableIOBuffer
> drainable
=
339 new DrainableIOBuffer(buf
.get(), buf
->size());
340 while (total_bytes_written
!= kTestDataSize
) {
341 rv
= stream
.Write(drainable
.get(), drainable
->BytesRemaining(),
342 callback
.callback());
343 if (rv
== ERR_IO_PENDING
)
344 rv
= callback
.WaitForResult();
348 drainable
->DidConsume(rv
);
349 total_bytes_written
+= rv
;
351 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
352 EXPECT_EQ(file_size
, kTestDataSize
* 2);
355 TEST_F(FileStreamTest
, BasicReadWrite
) {
357 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
359 scoped_ptr
<FileStream
> stream(
360 new FileStream(base::ThreadTaskRunnerHandle::Get()));
361 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
362 base::File::FLAG_WRITE
| base::File::FLAG_ASYNC
;
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 int64_t total_bytes_read
= 0;
370 std::string data_read
;
372 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
373 rv
= stream
->Read(buf
.get(), buf
->size(), callback
.callback());
374 if (rv
== ERR_IO_PENDING
)
375 rv
= callback
.WaitForResult();
379 total_bytes_read
+= rv
;
380 data_read
.append(buf
->data(), rv
);
382 EXPECT_EQ(file_size
, total_bytes_read
);
383 EXPECT_TRUE(data_read
== kTestData
);
385 int total_bytes_written
= 0;
387 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
388 scoped_refptr
<DrainableIOBuffer
> drainable
=
389 new DrainableIOBuffer(buf
.get(), buf
->size());
390 while (total_bytes_written
!= kTestDataSize
) {
391 rv
= stream
->Write(drainable
.get(), drainable
->BytesRemaining(),
392 callback
.callback());
393 if (rv
== ERR_IO_PENDING
)
394 rv
= callback
.WaitForResult();
398 drainable
->DidConsume(rv
);
399 total_bytes_written
+= rv
;
404 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
405 EXPECT_EQ(kTestDataSize
* 2, file_size
);
408 TEST_F(FileStreamTest
, BasicWriteRead
) {
410 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
412 scoped_ptr
<FileStream
> stream(
413 new FileStream(base::ThreadTaskRunnerHandle::Get()));
414 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
415 base::File::FLAG_WRITE
| base::File::FLAG_ASYNC
;
416 TestCompletionCallback callback
;
417 int rv
= stream
->Open(temp_file_path(), flags
, callback
.callback());
418 EXPECT_EQ(ERR_IO_PENDING
, rv
);
419 EXPECT_EQ(OK
, callback
.WaitForResult());
421 TestInt64CompletionCallback callback64
;
422 rv
= stream
->Seek(file_size
, callback64
.callback());
423 ASSERT_EQ(ERR_IO_PENDING
, rv
);
424 int64_t offset
= callback64
.WaitForResult();
425 EXPECT_EQ(offset
, file_size
);
427 int total_bytes_written
= 0;
429 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
430 scoped_refptr
<DrainableIOBuffer
> drainable
=
431 new DrainableIOBuffer(buf
.get(), buf
->size());
432 while (total_bytes_written
!= kTestDataSize
) {
433 rv
= stream
->Write(drainable
.get(), drainable
->BytesRemaining(),
434 callback
.callback());
435 if (rv
== ERR_IO_PENDING
)
436 rv
= callback
.WaitForResult();
440 drainable
->DidConsume(rv
);
441 total_bytes_written
+= rv
;
444 EXPECT_EQ(kTestDataSize
, total_bytes_written
);
446 rv
= stream
->Seek(0, callback64
.callback());
447 ASSERT_EQ(ERR_IO_PENDING
, rv
);
448 offset
= callback64
.WaitForResult();
449 EXPECT_EQ(0, offset
);
451 int total_bytes_read
= 0;
453 std::string data_read
;
455 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
456 rv
= stream
->Read(buf
.get(), buf
->size(), callback
.callback());
457 if (rv
== ERR_IO_PENDING
)
458 rv
= callback
.WaitForResult();
462 total_bytes_read
+= rv
;
463 data_read
.append(buf
->data(), rv
);
467 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
468 EXPECT_EQ(kTestDataSize
* 2, file_size
);
470 EXPECT_EQ(kTestDataSize
* 2, total_bytes_read
);
471 const std::string kExpectedFileData
=
472 std::string(kTestData
) + std::string(kTestData
);
473 EXPECT_EQ(kExpectedFileData
, data_read
);
476 class TestWriteReadCompletionCallback
{
478 TestWriteReadCompletionCallback(FileStream
* stream
,
479 int* total_bytes_written
,
480 int* total_bytes_read
,
481 std::string
* data_read
)
484 waiting_for_result_(false),
486 total_bytes_written_(total_bytes_written
),
487 total_bytes_read_(total_bytes_read
),
488 data_read_(data_read
),
489 callback_(base::Bind(&TestWriteReadCompletionCallback::OnComplete
,
490 base::Unretained(this))),
491 test_data_(CreateTestDataBuffer()),
492 drainable_(new DrainableIOBuffer(test_data_
.get(), kTestDataSize
)) {}
494 int WaitForResult() {
495 DCHECK(!waiting_for_result_
);
496 while (!have_result_
) {
497 waiting_for_result_
= true;
498 base::RunLoop().Run();
499 waiting_for_result_
= false;
501 have_result_
= false; // auto-reset for next callback
505 const CompletionCallback
& callback() const { return callback_
; }
507 void ValidateWrittenData() {
508 TestCompletionCallback callback
;
511 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
512 rv
= stream_
->Read(buf
.get(), buf
->size(), callback
.callback());
513 if (rv
== ERR_IO_PENDING
) {
514 base::MessageLoop::ScopedNestableTaskAllower
allow(
515 base::MessageLoop::current());
516 rv
= callback
.WaitForResult();
521 *total_bytes_read_
+= rv
;
522 data_read_
->append(buf
->data(), rv
);
527 void OnComplete(int result
) {
528 DCHECK_LT(0, result
);
529 *total_bytes_written_
+= result
;
533 if (*total_bytes_written_
!= kTestDataSize
) {
534 // Recurse to finish writing all data.
535 int total_bytes_written
= 0, total_bytes_read
= 0;
536 std::string data_read
;
537 TestWriteReadCompletionCallback
callback(
538 stream_
, &total_bytes_written
, &total_bytes_read
, &data_read
);
540 drainable_
.get(), drainable_
->BytesRemaining(), callback
.callback());
541 DCHECK_EQ(ERR_IO_PENDING
, rv
);
542 rv
= callback
.WaitForResult();
543 drainable_
->DidConsume(total_bytes_written
);
544 *total_bytes_written_
+= total_bytes_written
;
545 *total_bytes_read_
+= total_bytes_read
;
546 *data_read_
+= data_read
;
547 } else { // We're done writing all data. Start reading the data.
548 TestInt64CompletionCallback callback64
;
549 EXPECT_EQ(ERR_IO_PENDING
, stream_
->Seek(0, callback64
.callback()));
551 base::MessageLoop::ScopedNestableTaskAllower
allow(
552 base::MessageLoop::current());
553 EXPECT_LE(0, callback64
.WaitForResult());
557 result_
= *total_bytes_written_
;
559 if (waiting_for_result_
)
560 base::MessageLoop::current()->Quit();
565 bool waiting_for_result_
;
567 int* total_bytes_written_
;
568 int* total_bytes_read_
;
569 std::string
* data_read_
;
570 const CompletionCallback callback_
;
571 scoped_refptr
<IOBufferWithSize
> test_data_
;
572 scoped_refptr
<DrainableIOBuffer
> drainable_
;
574 DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback
);
577 TEST_F(FileStreamTest
, WriteRead
) {
579 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
581 scoped_ptr
<FileStream
> stream(
582 new FileStream(base::ThreadTaskRunnerHandle::Get()));
583 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
584 base::File::FLAG_WRITE
| base::File::FLAG_ASYNC
;
585 TestCompletionCallback open_callback
;
586 int rv
= stream
->Open(temp_file_path(), flags
, open_callback
.callback());
587 EXPECT_EQ(ERR_IO_PENDING
, rv
);
588 EXPECT_EQ(OK
, open_callback
.WaitForResult());
590 TestInt64CompletionCallback callback64
;
591 EXPECT_EQ(ERR_IO_PENDING
, stream
->Seek(file_size
, callback64
.callback()));
592 EXPECT_EQ(file_size
, callback64
.WaitForResult());
594 int total_bytes_written
= 0;
595 int total_bytes_read
= 0;
596 std::string data_read
;
597 TestWriteReadCompletionCallback
callback(stream
.get(), &total_bytes_written
,
598 &total_bytes_read
, &data_read
);
600 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
601 rv
= stream
->Write(buf
.get(), buf
->size(), callback
.callback());
602 if (rv
== ERR_IO_PENDING
)
603 rv
= callback
.WaitForResult();
605 EXPECT_EQ(kTestDataSize
, total_bytes_written
);
607 callback
.ValidateWrittenData();
611 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
612 EXPECT_EQ(kTestDataSize
* 2, file_size
);
614 EXPECT_EQ(kTestDataSize
* 2, total_bytes_read
);
615 const std::string kExpectedFileData
=
616 std::string(kTestData
) + std::string(kTestData
);
617 EXPECT_EQ(kExpectedFileData
, data_read
);
620 class TestWriteCloseCompletionCallback
{
622 TestWriteCloseCompletionCallback(FileStream
* stream
, int* total_bytes_written
)
625 waiting_for_result_(false),
627 total_bytes_written_(total_bytes_written
),
628 callback_(base::Bind(&TestWriteCloseCompletionCallback::OnComplete
,
629 base::Unretained(this))),
630 test_data_(CreateTestDataBuffer()),
631 drainable_(new DrainableIOBuffer(test_data_
.get(), kTestDataSize
)) {}
633 int WaitForResult() {
634 DCHECK(!waiting_for_result_
);
635 while (!have_result_
) {
636 waiting_for_result_
= true;
637 base::RunLoop().Run();
638 waiting_for_result_
= false;
640 have_result_
= false; // auto-reset for next callback
644 const CompletionCallback
& callback() const { return callback_
; }
647 void OnComplete(int result
) {
648 DCHECK_LT(0, result
);
649 *total_bytes_written_
+= result
;
653 if (*total_bytes_written_
!= kTestDataSize
) {
654 // Recurse to finish writing all data.
655 int total_bytes_written
= 0;
656 TestWriteCloseCompletionCallback
callback(stream_
, &total_bytes_written
);
658 drainable_
.get(), drainable_
->BytesRemaining(), callback
.callback());
659 DCHECK_EQ(ERR_IO_PENDING
, rv
);
660 rv
= callback
.WaitForResult();
661 drainable_
->DidConsume(total_bytes_written
);
662 *total_bytes_written_
+= total_bytes_written
;
665 result_
= *total_bytes_written_
;
667 if (waiting_for_result_
)
668 base::MessageLoop::current()->Quit();
673 bool waiting_for_result_
;
675 int* total_bytes_written_
;
676 const CompletionCallback callback_
;
677 scoped_refptr
<IOBufferWithSize
> test_data_
;
678 scoped_refptr
<DrainableIOBuffer
> drainable_
;
680 DISALLOW_COPY_AND_ASSIGN(TestWriteCloseCompletionCallback
);
683 TEST_F(FileStreamTest
, WriteClose
) {
685 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
687 scoped_ptr
<FileStream
> stream(
688 new FileStream(base::ThreadTaskRunnerHandle::Get()));
689 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
690 base::File::FLAG_WRITE
| base::File::FLAG_ASYNC
;
691 TestCompletionCallback open_callback
;
692 int rv
= stream
->Open(temp_file_path(), flags
, open_callback
.callback());
693 EXPECT_EQ(ERR_IO_PENDING
, rv
);
694 EXPECT_EQ(OK
, open_callback
.WaitForResult());
696 TestInt64CompletionCallback callback64
;
697 EXPECT_EQ(ERR_IO_PENDING
, stream
->Seek(file_size
, callback64
.callback()));
698 EXPECT_EQ(file_size
, callback64
.WaitForResult());
700 int total_bytes_written
= 0;
701 TestWriteCloseCompletionCallback
callback(stream
.get(), &total_bytes_written
);
703 scoped_refptr
<IOBufferWithSize
> buf
= CreateTestDataBuffer();
704 rv
= stream
->Write(buf
.get(), buf
->size(), callback
.callback());
705 if (rv
== ERR_IO_PENDING
)
706 total_bytes_written
= callback
.WaitForResult();
707 EXPECT_LT(0, total_bytes_written
);
708 EXPECT_EQ(kTestDataSize
, total_bytes_written
);
712 EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size
));
713 EXPECT_EQ(kTestDataSize
* 2, file_size
);
716 TEST_F(FileStreamTest
, OpenAndDelete
) {
717 scoped_refptr
<base::SequencedWorkerPool
> pool(
718 new base::SequencedWorkerPool(1, "StreamTest"));
720 bool prev
= base::ThreadRestrictions::SetIOAllowed(false);
721 scoped_ptr
<FileStream
> stream(new FileStream(pool
.get()));
722 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_WRITE
|
723 base::File::FLAG_ASYNC
;
724 TestCompletionCallback open_callback
;
725 int rv
= stream
->Open(temp_file_path(), flags
, open_callback
.callback());
726 EXPECT_EQ(ERR_IO_PENDING
, rv
);
728 // Delete the stream without waiting for the open operation to be
729 // complete. Should be safe.
732 // Force an operation through the pool.
733 scoped_ptr
<FileStream
> stream2(new FileStream(pool
.get()));
734 TestCompletionCallback open_callback2
;
735 rv
= stream2
->Open(temp_file_path(), flags
, open_callback2
.callback());
736 EXPECT_EQ(OK
, open_callback2
.GetResult(rv
));
741 // open_callback won't be called.
742 base::RunLoop().RunUntilIdle();
743 EXPECT_FALSE(open_callback
.have_result());
744 base::ThreadRestrictions::SetIOAllowed(prev
);
747 // Verify that Write() errors are mapped correctly.
748 TEST_F(FileStreamTest
, WriteError
) {
749 // Try opening file as read-only and then writing to it using FileStream.
751 base::File::FLAG_OPEN
| base::File::FLAG_READ
| base::File::FLAG_ASYNC
;
753 base::File
file(temp_file_path(), flags
);
754 ASSERT_TRUE(file
.IsValid());
756 scoped_ptr
<FileStream
> stream(
757 new FileStream(file
.Pass(), base::ThreadTaskRunnerHandle::Get()));
759 scoped_refptr
<IOBuffer
> buf
= new IOBuffer(1);
762 TestCompletionCallback callback
;
763 int rv
= stream
->Write(buf
.get(), 1, callback
.callback());
764 if (rv
== ERR_IO_PENDING
)
765 rv
= callback
.WaitForResult();
769 base::RunLoop().RunUntilIdle();
772 // Verify that Read() errors are mapped correctly.
773 TEST_F(FileStreamTest
, ReadError
) {
774 // Try opening file for write and then reading from it using FileStream.
776 base::File::FLAG_OPEN
| base::File::FLAG_WRITE
| base::File::FLAG_ASYNC
;
778 base::File
file(temp_file_path(), flags
);
779 ASSERT_TRUE(file
.IsValid());
781 scoped_ptr
<FileStream
> stream(
782 new FileStream(file
.Pass(), base::ThreadTaskRunnerHandle::Get()));
784 scoped_refptr
<IOBuffer
> buf
= new IOBuffer(1);
785 TestCompletionCallback callback
;
786 int rv
= stream
->Read(buf
.get(), 1, callback
.callback());
787 if (rv
== ERR_IO_PENDING
)
788 rv
= callback
.WaitForResult();
792 base::RunLoop().RunUntilIdle();
795 #if defined(OS_ANDROID)
796 TEST_F(FileStreamTest
, ContentUriRead
) {
797 base::FilePath test_dir
;
798 PathService::Get(base::DIR_SOURCE_ROOT
, &test_dir
);
799 test_dir
= test_dir
.AppendASCII("net");
800 test_dir
= test_dir
.AppendASCII("data");
801 test_dir
= test_dir
.AppendASCII("file_stream_unittest");
802 ASSERT_TRUE(base::PathExists(test_dir
));
803 base::FilePath image_file
= test_dir
.Append(FILE_PATH_LITERAL("red.png"));
805 // Insert the image into MediaStore. MediaStore will do some conversions, and
806 // return the content URI.
807 base::FilePath path
= base::InsertImageIntoMediaStore(image_file
);
808 EXPECT_TRUE(path
.IsContentUri());
809 EXPECT_TRUE(base::PathExists(path
));
811 EXPECT_TRUE(base::GetFileSize(path
, &file_size
));
812 EXPECT_LT(0, file_size
);
814 FileStream
stream(base::ThreadTaskRunnerHandle::Get());
815 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
816 base::File::FLAG_ASYNC
;
817 TestCompletionCallback callback
;
818 int rv
= stream
.Open(path
, flags
, callback
.callback());
819 EXPECT_EQ(ERR_IO_PENDING
, rv
);
820 EXPECT_EQ(OK
, callback
.WaitForResult());
822 int total_bytes_read
= 0;
824 std::string data_read
;
826 scoped_refptr
<IOBufferWithSize
> buf
= new IOBufferWithSize(4);
827 rv
= stream
.Read(buf
.get(), buf
->size(), callback
.callback());
828 if (rv
== ERR_IO_PENDING
)
829 rv
= callback
.WaitForResult();
833 total_bytes_read
+= rv
;
834 data_read
.append(buf
->data(), rv
);
836 EXPECT_EQ(file_size
, total_bytes_read
);