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. 4 5 #include "net/base/file_stream.h" 6 7 #include "base/bind.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" 23 24 #if defined(OS_ANDROID) 25 #include "base/test/test_file_util.h" 26 #endif 27 28 namespace net { 29 30 namespace { 31 32 const char kTestData[] = "0123456789"; 33 const int kTestDataSize = arraysize(kTestData) - 1; 34 35 // Creates an IOBufferWithSize that contains the kTestDataSize. 36 IOBufferWithSize* CreateTestDataBuffer() { 37 IOBufferWithSize* buf = new IOBufferWithSize(kTestDataSize); 38 memcpy(buf->data(), kTestData, kTestDataSize); 39 return buf; 40 } 41 42 } // namespace 43 44 class FileStreamTest : public PlatformTest { 45 public: 46 virtual void SetUp() { 47 PlatformTest::SetUp(); 48 49 base::CreateTemporaryFile(&temp_file_path_); 50 file_util::WriteFile(temp_file_path_, kTestData, kTestDataSize); 51 } 52 virtual void TearDown() { 53 EXPECT_TRUE(base::DeleteFile(temp_file_path_, false)); 54 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 PlatformTest::TearDown(); 59 } 60 61 const base::FilePath temp_file_path() const { return temp_file_path_; } 62 63 private: 64 base::FilePath temp_file_path_; 65 }; 66 67 namespace { 68 69 TEST_F(FileStreamTest, BasicOpenClose) { 70 base::PlatformFile file = base::kInvalidPlatformFileValue; 71 { 72 FileStream stream(NULL, base::MessageLoopProxy::current()); 73 int rv = stream.OpenSync(temp_file_path(), 74 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); 75 EXPECT_EQ(OK, rv); 76 EXPECT_TRUE(stream.IsOpen()); 77 file = stream.GetPlatformFileForTesting(); 78 } 79 EXPECT_NE(base::kInvalidPlatformFileValue, file); 80 base::PlatformFileInfo info; 81 // The file should be closed. 82 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info)); 83 } 84 85 TEST_F(FileStreamTest, BasicOpenExplicitClose) { 86 base::PlatformFile file = base::kInvalidPlatformFileValue; 87 FileStream stream(NULL); 88 int rv = stream.OpenSync(temp_file_path(), 89 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); 90 EXPECT_EQ(OK, rv); 91 EXPECT_TRUE(stream.IsOpen()); 92 file = stream.GetPlatformFileForTesting(); 93 EXPECT_NE(base::kInvalidPlatformFileValue, file); 94 EXPECT_EQ(OK, stream.CloseSync()); 95 EXPECT_FALSE(stream.IsOpen()); 96 base::PlatformFileInfo info; 97 // The file should be closed. 98 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info)); 99 } 100 101 TEST_F(FileStreamTest, AsyncOpenExplicitClose) { 102 base::PlatformFile file = base::kInvalidPlatformFileValue; 103 TestCompletionCallback callback; 104 FileStream stream(NULL); 105 int flags = base::PLATFORM_FILE_OPEN | 106 base::PLATFORM_FILE_READ | 107 base::PLATFORM_FILE_ASYNC; 108 int rv = stream.Open(temp_file_path(), flags, callback.callback()); 109 EXPECT_EQ(ERR_IO_PENDING, rv); 110 EXPECT_EQ(OK, callback.WaitForResult()); 111 EXPECT_TRUE(stream.IsOpen()); 112 file = stream.GetPlatformFileForTesting(); 113 EXPECT_EQ(ERR_IO_PENDING, stream.Close(callback.callback())); 114 EXPECT_EQ(OK, callback.WaitForResult()); 115 EXPECT_FALSE(stream.IsOpen()); 116 base::PlatformFileInfo info; 117 // The file should be closed. 118 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info)); 119 } 120 121 TEST_F(FileStreamTest, AsyncOpenExplicitCloseOrphaned) { 122 base::PlatformFile file = base::kInvalidPlatformFileValue; 123 TestCompletionCallback callback; 124 base::PlatformFileInfo info; 125 scoped_ptr<FileStream> stream(new FileStream( 126 NULL, base::MessageLoopProxy::current())); 127 int flags = base::PLATFORM_FILE_OPEN | 128 base::PLATFORM_FILE_READ | 129 base::PLATFORM_FILE_ASYNC; 130 int rv = stream->Open(temp_file_path(), flags, callback.callback()); 131 EXPECT_EQ(ERR_IO_PENDING, rv); 132 EXPECT_EQ(OK, callback.WaitForResult()); 133 EXPECT_TRUE(stream->IsOpen()); 134 file = stream->GetPlatformFileForTesting(); 135 EXPECT_EQ(ERR_IO_PENDING, stream->Close(callback.callback())); 136 stream.reset(); 137 // File isn't actually closed yet. 138 EXPECT_TRUE(base::GetPlatformFileInfo(file, &info)); 139 base::RunLoop runloop; 140 runloop.RunUntilIdle(); 141 // The file should now be closed, though the callback has not been called. 142 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info)); 143 } 144 145 TEST_F(FileStreamTest, FileHandleNotLeftOpen) { 146 bool created = false; 147 ASSERT_EQ(kTestDataSize, 148 file_util::WriteFile(temp_file_path(), kTestData, kTestDataSize)); 149 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ; 150 base::PlatformFile file = base::CreatePlatformFile( 151 temp_file_path(), flags, &created, NULL); 152 153 { 154 // Seek to the beginning of the file and read. 155 FileStream read_stream(file, flags, NULL, 156 base::MessageLoopProxy::current()); 157 EXPECT_TRUE(read_stream.IsOpen()); 158 } 159 160 EXPECT_NE(base::kInvalidPlatformFileValue, file); 161 base::PlatformFileInfo info; 162 // The file should be closed. 163 EXPECT_FALSE(base::GetPlatformFileInfo(file, &info)); 164 } 165 166 // Test the use of FileStream with a file handle provided at construction. 167 TEST_F(FileStreamTest, UseFileHandle) { 168 bool created = false; 169 170 // 1. Test reading with a file handle. 171 ASSERT_EQ(kTestDataSize, 172 file_util::WriteFile(temp_file_path(), kTestData, kTestDataSize)); 173 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ; 174 base::PlatformFile file = base::CreatePlatformFile( 175 temp_file_path(), flags, &created, NULL); 176 177 // Seek to the beginning of the file and read. 178 scoped_ptr<FileStream> read_stream( 179 new FileStream(file, flags, NULL, base::MessageLoopProxy::current())); 180 ASSERT_EQ(0, read_stream->SeekSync(FROM_BEGIN, 0)); 181 ASSERT_EQ(kTestDataSize, read_stream->Available()); 182 // Read into buffer and compare. 183 char buffer[kTestDataSize]; 184 ASSERT_EQ(kTestDataSize, 185 read_stream->ReadSync(buffer, kTestDataSize)); 186 ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize)); 187 read_stream.reset(); 188 189 // 2. Test writing with a file handle. 190 base::DeleteFile(temp_file_path(), false); 191 flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE; 192 file = base::CreatePlatformFile(temp_file_path(), flags, &created, NULL); 193 194 scoped_ptr<FileStream> write_stream( 195 new FileStream(file, flags, NULL, base::MessageLoopProxy::current())); 196 ASSERT_EQ(0, write_stream->SeekSync(FROM_BEGIN, 0)); 197 ASSERT_EQ(kTestDataSize, 198 write_stream->WriteSync(kTestData, kTestDataSize)); 199 write_stream.reset(); 200 201 // Read into buffer and compare to make sure the handle worked fine. 202 ASSERT_EQ(kTestDataSize, 203 base::ReadFile(temp_file_path(), buffer, kTestDataSize)); 204 ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize)); 205 } 206 207 TEST_F(FileStreamTest, UseClosedStream) { 208 FileStream stream(NULL, base::MessageLoopProxy::current()); 209 210 EXPECT_FALSE(stream.IsOpen()); 211 212 // Try seeking... 213 int64 new_offset = stream.SeekSync(FROM_BEGIN, 5); 214 EXPECT_EQ(ERR_UNEXPECTED, new_offset); 215 216 // Try available... 217 int64 avail = stream.Available(); 218 EXPECT_EQ(ERR_UNEXPECTED, avail); 219 220 // Try reading... 221 char buf[10]; 222 int rv = stream.ReadSync(buf, arraysize(buf)); 223 EXPECT_EQ(ERR_UNEXPECTED, rv); 224 } 225 226 TEST_F(FileStreamTest, BasicRead) { 227 int64 file_size; 228 bool ok = base::GetFileSize(temp_file_path(), &file_size); 229 EXPECT_TRUE(ok); 230 231 FileStream stream(NULL, base::MessageLoopProxy::current()); 232 int flags = base::PLATFORM_FILE_OPEN | 233 base::PLATFORM_FILE_READ; 234 int rv = stream.OpenSync(temp_file_path(), flags); 235 EXPECT_EQ(OK, rv); 236 237 int64 total_bytes_avail = stream.Available(); 238 EXPECT_EQ(file_size, total_bytes_avail); 239 240 int total_bytes_read = 0; 241 242 std::string data_read; 243 for (;;) { 244 char buf[4]; 245 rv = stream.ReadSync(buf, arraysize(buf)); 246 EXPECT_LE(0, rv); 247 if (rv <= 0) 248 break; 249 total_bytes_read += rv; 250 data_read.append(buf, rv); 251 } 252 EXPECT_EQ(file_size, total_bytes_read); 253 EXPECT_EQ(kTestData, data_read); 254 } 255 256 TEST_F(FileStreamTest, AsyncRead) { 257 int64 file_size; 258 bool ok = base::GetFileSize(temp_file_path(), &file_size); 259 EXPECT_TRUE(ok); 260 261 FileStream stream(NULL, base::MessageLoopProxy::current()); 262 int flags = base::PLATFORM_FILE_OPEN | 263 base::PLATFORM_FILE_READ | 264 base::PLATFORM_FILE_ASYNC; 265 TestCompletionCallback callback; 266 int rv = stream.Open(temp_file_path(), flags, callback.callback()); 267 EXPECT_EQ(ERR_IO_PENDING, rv); 268 EXPECT_EQ(OK, callback.WaitForResult()); 269 270 int64 total_bytes_avail = stream.Available(); 271 EXPECT_EQ(file_size, total_bytes_avail); 272 273 int total_bytes_read = 0; 274 275 std::string data_read; 276 for (;;) { 277 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); 278 rv = stream.Read(buf.get(), buf->size(), callback.callback()); 279 if (rv == ERR_IO_PENDING) 280 rv = callback.WaitForResult(); 281 EXPECT_LE(0, rv); 282 if (rv <= 0) 283 break; 284 total_bytes_read += rv; 285 data_read.append(buf->data(), rv); 286 } 287 EXPECT_EQ(file_size, total_bytes_read); 288 EXPECT_EQ(kTestData, data_read); 289 } 290 291 TEST_F(FileStreamTest, AsyncRead_EarlyDelete) { 292 int64 file_size; 293 bool ok = base::GetFileSize(temp_file_path(), &file_size); 294 EXPECT_TRUE(ok); 295 296 scoped_ptr<FileStream> stream( 297 new FileStream(NULL, base::MessageLoopProxy::current())); 298 int flags = base::PLATFORM_FILE_OPEN | 299 base::PLATFORM_FILE_READ | 300 base::PLATFORM_FILE_ASYNC; 301 TestCompletionCallback callback; 302 int rv = stream->Open(temp_file_path(), flags, callback.callback()); 303 EXPECT_EQ(ERR_IO_PENDING, rv); 304 EXPECT_EQ(OK, callback.WaitForResult()); 305 306 int64 total_bytes_avail = stream->Available(); 307 EXPECT_EQ(file_size, total_bytes_avail); 308 309 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); 310 rv = stream->Read(buf.get(), buf->size(), callback.callback()); 311 stream.reset(); // Delete instead of closing it. 312 if (rv < 0) { 313 EXPECT_EQ(ERR_IO_PENDING, rv); 314 // The callback should not be called if the request is cancelled. 315 base::RunLoop().RunUntilIdle(); 316 EXPECT_FALSE(callback.have_result()); 317 } else { 318 EXPECT_EQ(std::string(kTestData, rv), std::string(buf->data(), rv)); 319 } 320 } 321 322 TEST_F(FileStreamTest, BasicRead_FromOffset) { 323 int64 file_size; 324 bool ok = base::GetFileSize(temp_file_path(), &file_size); 325 EXPECT_TRUE(ok); 326 327 FileStream stream(NULL, base::MessageLoopProxy::current()); 328 int flags = base::PLATFORM_FILE_OPEN | 329 base::PLATFORM_FILE_READ; 330 int rv = stream.OpenSync(temp_file_path(), flags); 331 EXPECT_EQ(OK, rv); 332 333 const int64 kOffset = 3; 334 int64 new_offset = stream.SeekSync(FROM_BEGIN, kOffset); 335 EXPECT_EQ(kOffset, new_offset); 336 337 int64 total_bytes_avail = stream.Available(); 338 EXPECT_EQ(file_size - kOffset, total_bytes_avail); 339 340 int64 total_bytes_read = 0; 341 342 std::string data_read; 343 for (;;) { 344 char buf[4]; 345 rv = stream.ReadSync(buf, arraysize(buf)); 346 EXPECT_LE(0, rv); 347 if (rv <= 0) 348 break; 349 total_bytes_read += rv; 350 data_read.append(buf, rv); 351 } 352 EXPECT_EQ(file_size - kOffset, total_bytes_read); 353 EXPECT_TRUE(data_read == kTestData + kOffset); 354 EXPECT_EQ(kTestData + kOffset, data_read); 355 } 356 357 TEST_F(FileStreamTest, AsyncRead_FromOffset) { 358 int64 file_size; 359 bool ok = base::GetFileSize(temp_file_path(), &file_size); 360 EXPECT_TRUE(ok); 361 362 FileStream stream(NULL, base::MessageLoopProxy::current()); 363 int flags = base::PLATFORM_FILE_OPEN | 364 base::PLATFORM_FILE_READ | 365 base::PLATFORM_FILE_ASYNC; 366 TestCompletionCallback callback; 367 int rv = stream.Open(temp_file_path(), flags, callback.callback()); 368 EXPECT_EQ(ERR_IO_PENDING, rv); 369 EXPECT_EQ(OK, callback.WaitForResult()); 370 371 TestInt64CompletionCallback callback64; 372 const int64 kOffset = 3; 373 rv = stream.Seek(FROM_BEGIN, kOffset, callback64.callback()); 374 ASSERT_EQ(ERR_IO_PENDING, rv); 375 int64 new_offset = callback64.WaitForResult(); 376 EXPECT_EQ(kOffset, new_offset); 377 378 int64 total_bytes_avail = stream.Available(); 379 EXPECT_EQ(file_size - kOffset, total_bytes_avail); 380 381 int total_bytes_read = 0; 382 383 std::string data_read; 384 for (;;) { 385 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); 386 rv = stream.Read(buf.get(), buf->size(), callback.callback()); 387 if (rv == ERR_IO_PENDING) 388 rv = callback.WaitForResult(); 389 EXPECT_LE(0, rv); 390 if (rv <= 0) 391 break; 392 total_bytes_read += rv; 393 data_read.append(buf->data(), rv); 394 } 395 EXPECT_EQ(file_size - kOffset, total_bytes_read); 396 EXPECT_EQ(kTestData + kOffset, data_read); 397 } 398 399 TEST_F(FileStreamTest, SeekAround) { 400 FileStream stream(NULL, base::MessageLoopProxy::current()); 401 int flags = base::PLATFORM_FILE_OPEN | 402 base::PLATFORM_FILE_READ; 403 int rv = stream.OpenSync(temp_file_path(), flags); 404 EXPECT_EQ(OK, rv); 405 406 const int64 kOffset = 3; 407 int64 new_offset = stream.SeekSync(FROM_BEGIN, kOffset); 408 EXPECT_EQ(kOffset, new_offset); 409 410 new_offset = stream.SeekSync(FROM_CURRENT, kOffset); 411 EXPECT_EQ(2 * kOffset, new_offset); 412 413 new_offset = stream.SeekSync(FROM_CURRENT, -kOffset); 414 EXPECT_EQ(kOffset, new_offset); 415 416 const int kTestDataLen = arraysize(kTestData) - 1; 417 418 new_offset = stream.SeekSync(FROM_END, -kTestDataLen); 419 EXPECT_EQ(0, new_offset); 420 } 421 422 TEST_F(FileStreamTest, AsyncSeekAround) { 423 FileStream stream(NULL, base::MessageLoopProxy::current()); 424 int flags = base::PLATFORM_FILE_OPEN | 425 base::PLATFORM_FILE_ASYNC | 426 base::PLATFORM_FILE_READ; 427 TestCompletionCallback callback; 428 int rv = stream.Open(temp_file_path(), flags, callback.callback()); 429 EXPECT_EQ(ERR_IO_PENDING, rv); 430 EXPECT_EQ(OK, callback.WaitForResult()); 431 432 TestInt64CompletionCallback callback64; 433 434 const int64 kOffset = 3; 435 rv = stream.Seek(FROM_BEGIN, kOffset, callback64.callback()); 436 ASSERT_EQ(ERR_IO_PENDING, rv); 437 int64 new_offset = callback64.WaitForResult(); 438 EXPECT_EQ(kOffset, new_offset); 439 440 rv = stream.Seek(FROM_CURRENT, kOffset, callback64.callback()); 441 ASSERT_EQ(ERR_IO_PENDING, rv); 442 new_offset = callback64.WaitForResult(); 443 EXPECT_EQ(2 * kOffset, new_offset); 444 445 rv = stream.Seek(FROM_CURRENT, -kOffset, callback64.callback()); 446 ASSERT_EQ(ERR_IO_PENDING, rv); 447 new_offset = callback64.WaitForResult(); 448 EXPECT_EQ(kOffset, new_offset); 449 450 const int kTestDataLen = arraysize(kTestData) - 1; 451 452 rv = stream.Seek(FROM_END, -kTestDataLen, callback64.callback()); 453 ASSERT_EQ(ERR_IO_PENDING, rv); 454 new_offset = callback64.WaitForResult(); 455 EXPECT_EQ(0, new_offset); 456 } 457 458 TEST_F(FileStreamTest, BasicWrite) { 459 scoped_ptr<FileStream> stream( 460 new FileStream(NULL, base::MessageLoopProxy::current())); 461 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | 462 base::PLATFORM_FILE_WRITE; 463 int rv = stream->OpenSync(temp_file_path(), flags); 464 EXPECT_EQ(OK, rv); 465 466 int64 file_size; 467 bool ok = base::GetFileSize(temp_file_path(), &file_size); 468 EXPECT_TRUE(ok); 469 EXPECT_EQ(0, file_size); 470 471 rv = stream->WriteSync(kTestData, kTestDataSize); 472 EXPECT_EQ(kTestDataSize, rv); 473 stream.reset(); 474 475 ok = base::GetFileSize(temp_file_path(), &file_size); 476 EXPECT_TRUE(ok); 477 EXPECT_EQ(kTestDataSize, file_size); 478 } 479 480 TEST_F(FileStreamTest, AsyncWrite) { 481 FileStream stream(NULL, base::MessageLoopProxy::current()); 482 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | 483 base::PLATFORM_FILE_WRITE | 484 base::PLATFORM_FILE_ASYNC; 485 TestCompletionCallback callback; 486 int rv = stream.Open(temp_file_path(), flags, callback.callback()); 487 EXPECT_EQ(ERR_IO_PENDING, rv); 488 EXPECT_EQ(OK, callback.WaitForResult()); 489 490 int64 file_size; 491 bool ok = base::GetFileSize(temp_file_path(), &file_size); 492 EXPECT_TRUE(ok); 493 EXPECT_EQ(0, file_size); 494 495 int total_bytes_written = 0; 496 497 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); 498 scoped_refptr<DrainableIOBuffer> drainable = 499 new DrainableIOBuffer(buf.get(), buf->size()); 500 while (total_bytes_written != kTestDataSize) { 501 rv = stream.Write( 502 drainable.get(), drainable->BytesRemaining(), callback.callback()); 503 if (rv == ERR_IO_PENDING) 504 rv = callback.WaitForResult(); 505 EXPECT_LT(0, rv); 506 if (rv <= 0) 507 break; 508 drainable->DidConsume(rv); 509 total_bytes_written += rv; 510 } 511 ok = base::GetFileSize(temp_file_path(), &file_size); 512 EXPECT_TRUE(ok); 513 EXPECT_EQ(file_size, total_bytes_written); 514 } 515 516 TEST_F(FileStreamTest, AsyncWrite_EarlyDelete) { 517 scoped_ptr<FileStream> stream( 518 new FileStream(NULL, base::MessageLoopProxy::current())); 519 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | 520 base::PLATFORM_FILE_WRITE | 521 base::PLATFORM_FILE_ASYNC; 522 TestCompletionCallback callback; 523 int rv = stream->Open(temp_file_path(), flags, callback.callback()); 524 EXPECT_EQ(ERR_IO_PENDING, rv); 525 EXPECT_EQ(OK, callback.WaitForResult()); 526 527 int64 file_size; 528 bool ok = base::GetFileSize(temp_file_path(), &file_size); 529 EXPECT_TRUE(ok); 530 EXPECT_EQ(0, file_size); 531 532 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); 533 rv = stream->Write(buf.get(), buf->size(), callback.callback()); 534 stream.reset(); 535 if (rv < 0) { 536 EXPECT_EQ(ERR_IO_PENDING, rv); 537 // The callback should not be called if the request is cancelled. 538 base::RunLoop().RunUntilIdle(); 539 EXPECT_FALSE(callback.have_result()); 540 } else { 541 ok = base::GetFileSize(temp_file_path(), &file_size); 542 EXPECT_TRUE(ok); 543 EXPECT_EQ(file_size, rv); 544 } 545 } 546 547 TEST_F(FileStreamTest, BasicWrite_FromOffset) { 548 scoped_ptr<FileStream> stream( 549 new FileStream(NULL, base::MessageLoopProxy::current())); 550 int flags = base::PLATFORM_FILE_OPEN | 551 base::PLATFORM_FILE_WRITE; 552 int rv = stream->OpenSync(temp_file_path(), flags); 553 EXPECT_EQ(OK, rv); 554 555 int64 file_size; 556 bool ok = base::GetFileSize(temp_file_path(), &file_size); 557 EXPECT_TRUE(ok); 558 EXPECT_EQ(kTestDataSize, file_size); 559 560 const int64 kOffset = 0; 561 int64 new_offset = stream->SeekSync(FROM_END, kOffset); 562 EXPECT_EQ(kTestDataSize, new_offset); 563 564 rv = stream->WriteSync(kTestData, kTestDataSize); 565 EXPECT_EQ(kTestDataSize, rv); 566 stream.reset(); 567 568 ok = base::GetFileSize(temp_file_path(), &file_size); 569 EXPECT_TRUE(ok); 570 EXPECT_EQ(kTestDataSize * 2, file_size); 571 } 572 573 TEST_F(FileStreamTest, AsyncWrite_FromOffset) { 574 int64 file_size; 575 bool ok = base::GetFileSize(temp_file_path(), &file_size); 576 EXPECT_TRUE(ok); 577 578 FileStream stream(NULL, base::MessageLoopProxy::current()); 579 int flags = base::PLATFORM_FILE_OPEN | 580 base::PLATFORM_FILE_WRITE | 581 base::PLATFORM_FILE_ASYNC; 582 TestCompletionCallback callback; 583 int rv = stream.Open(temp_file_path(), flags, callback.callback()); 584 EXPECT_EQ(ERR_IO_PENDING, rv); 585 EXPECT_EQ(OK, callback.WaitForResult()); 586 587 TestInt64CompletionCallback callback64; 588 const int64 kOffset = 0; 589 rv = stream.Seek(FROM_END, kOffset, callback64.callback()); 590 ASSERT_EQ(ERR_IO_PENDING, rv); 591 int64 new_offset = callback64.WaitForResult(); 592 EXPECT_EQ(kTestDataSize, new_offset); 593 594 int total_bytes_written = 0; 595 596 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); 597 scoped_refptr<DrainableIOBuffer> drainable = 598 new DrainableIOBuffer(buf.get(), buf->size()); 599 while (total_bytes_written != kTestDataSize) { 600 rv = stream.Write( 601 drainable.get(), drainable->BytesRemaining(), callback.callback()); 602 if (rv == ERR_IO_PENDING) 603 rv = callback.WaitForResult(); 604 EXPECT_LT(0, rv); 605 if (rv <= 0) 606 break; 607 drainable->DidConsume(rv); 608 total_bytes_written += rv; 609 } 610 ok = base::GetFileSize(temp_file_path(), &file_size); 611 EXPECT_TRUE(ok); 612 EXPECT_EQ(file_size, kTestDataSize * 2); 613 } 614 615 TEST_F(FileStreamTest, BasicReadWrite) { 616 int64 file_size; 617 bool ok = base::GetFileSize(temp_file_path(), &file_size); 618 EXPECT_TRUE(ok); 619 620 scoped_ptr<FileStream> stream( 621 new FileStream(NULL, base::MessageLoopProxy::current())); 622 int flags = base::PLATFORM_FILE_OPEN | 623 base::PLATFORM_FILE_READ | 624 base::PLATFORM_FILE_WRITE; 625 int rv = stream->OpenSync(temp_file_path(), flags); 626 EXPECT_EQ(OK, rv); 627 628 int64 total_bytes_avail = stream->Available(); 629 EXPECT_EQ(file_size, total_bytes_avail); 630 631 int total_bytes_read = 0; 632 633 std::string data_read; 634 for (;;) { 635 char buf[4]; 636 rv = stream->ReadSync(buf, arraysize(buf)); 637 EXPECT_LE(0, rv); 638 if (rv <= 0) 639 break; 640 total_bytes_read += rv; 641 data_read.append(buf, rv); 642 } 643 EXPECT_EQ(file_size, total_bytes_read); 644 EXPECT_TRUE(data_read == kTestData); 645 646 rv = stream->WriteSync(kTestData, kTestDataSize); 647 EXPECT_EQ(kTestDataSize, rv); 648 stream.reset(); 649 650 ok = base::GetFileSize(temp_file_path(), &file_size); 651 EXPECT_TRUE(ok); 652 EXPECT_EQ(kTestDataSize * 2, file_size); 653 } 654 655 TEST_F(FileStreamTest, BasicWriteRead) { 656 int64 file_size; 657 bool ok = base::GetFileSize(temp_file_path(), &file_size); 658 EXPECT_TRUE(ok); 659 660 scoped_ptr<FileStream> stream( 661 new FileStream(NULL, base::MessageLoopProxy::current())); 662 int flags = base::PLATFORM_FILE_OPEN | 663 base::PLATFORM_FILE_READ | 664 base::PLATFORM_FILE_WRITE; 665 int rv = stream->OpenSync(temp_file_path(), flags); 666 EXPECT_EQ(OK, rv); 667 668 int64 total_bytes_avail = stream->Available(); 669 EXPECT_EQ(file_size, total_bytes_avail); 670 671 int64 offset = stream->SeekSync(FROM_END, 0); 672 EXPECT_EQ(offset, file_size); 673 674 rv = stream->WriteSync(kTestData, kTestDataSize); 675 EXPECT_EQ(kTestDataSize, rv); 676 677 offset = stream->SeekSync(FROM_BEGIN, 0); 678 EXPECT_EQ(0, offset); 679 680 int64 total_bytes_read = 0; 681 682 std::string data_read; 683 for (;;) { 684 char buf[4]; 685 rv = stream->ReadSync(buf, arraysize(buf)); 686 EXPECT_LE(0, rv); 687 if (rv <= 0) 688 break; 689 total_bytes_read += rv; 690 data_read.append(buf, rv); 691 } 692 stream.reset(); 693 694 ok = base::GetFileSize(temp_file_path(), &file_size); 695 EXPECT_TRUE(ok); 696 EXPECT_EQ(kTestDataSize * 2, file_size); 697 EXPECT_EQ(kTestDataSize * 2, total_bytes_read); 698 699 const std::string kExpectedFileData = 700 std::string(kTestData) + std::string(kTestData); 701 EXPECT_EQ(kExpectedFileData, data_read); 702 } 703 704 TEST_F(FileStreamTest, BasicAsyncReadWrite) { 705 int64 file_size; 706 bool ok = base::GetFileSize(temp_file_path(), &file_size); 707 EXPECT_TRUE(ok); 708 709 scoped_ptr<FileStream> stream( 710 new FileStream(NULL, base::MessageLoopProxy::current())); 711 int flags = base::PLATFORM_FILE_OPEN | 712 base::PLATFORM_FILE_READ | 713 base::PLATFORM_FILE_WRITE | 714 base::PLATFORM_FILE_ASYNC; 715 TestCompletionCallback callback; 716 int rv = stream->Open(temp_file_path(), flags, callback.callback()); 717 EXPECT_EQ(ERR_IO_PENDING, rv); 718 EXPECT_EQ(OK, callback.WaitForResult()); 719 720 int64 total_bytes_avail = stream->Available(); 721 EXPECT_EQ(file_size, total_bytes_avail); 722 723 int64 total_bytes_read = 0; 724 725 std::string data_read; 726 for (;;) { 727 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); 728 rv = stream->Read(buf.get(), buf->size(), callback.callback()); 729 if (rv == ERR_IO_PENDING) 730 rv = callback.WaitForResult(); 731 EXPECT_LE(0, rv); 732 if (rv <= 0) 733 break; 734 total_bytes_read += rv; 735 data_read.append(buf->data(), rv); 736 } 737 EXPECT_EQ(file_size, total_bytes_read); 738 EXPECT_TRUE(data_read == kTestData); 739 740 int total_bytes_written = 0; 741 742 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); 743 scoped_refptr<DrainableIOBuffer> drainable = 744 new DrainableIOBuffer(buf.get(), buf->size()); 745 while (total_bytes_written != kTestDataSize) { 746 rv = stream->Write( 747 drainable.get(), drainable->BytesRemaining(), callback.callback()); 748 if (rv == ERR_IO_PENDING) 749 rv = callback.WaitForResult(); 750 EXPECT_LT(0, rv); 751 if (rv <= 0) 752 break; 753 drainable->DidConsume(rv); 754 total_bytes_written += rv; 755 } 756 757 stream.reset(); 758 759 ok = base::GetFileSize(temp_file_path(), &file_size); 760 EXPECT_TRUE(ok); 761 EXPECT_EQ(kTestDataSize * 2, file_size); 762 } 763 764 TEST_F(FileStreamTest, BasicAsyncWriteRead) { 765 int64 file_size; 766 bool ok = base::GetFileSize(temp_file_path(), &file_size); 767 EXPECT_TRUE(ok); 768 769 scoped_ptr<FileStream> stream( 770 new FileStream(NULL, base::MessageLoopProxy::current())); 771 int flags = base::PLATFORM_FILE_OPEN | 772 base::PLATFORM_FILE_READ | 773 base::PLATFORM_FILE_WRITE | 774 base::PLATFORM_FILE_ASYNC; 775 TestCompletionCallback callback; 776 int rv = stream->Open(temp_file_path(), flags, callback.callback()); 777 EXPECT_EQ(ERR_IO_PENDING, rv); 778 EXPECT_EQ(OK, callback.WaitForResult()); 779 780 int64 total_bytes_avail = stream->Available(); 781 EXPECT_EQ(file_size, total_bytes_avail); 782 783 TestInt64CompletionCallback callback64; 784 rv = stream->Seek(FROM_END, 0, callback64.callback()); 785 ASSERT_EQ(ERR_IO_PENDING, rv); 786 int64 offset = callback64.WaitForResult(); 787 EXPECT_EQ(offset, file_size); 788 789 int total_bytes_written = 0; 790 791 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); 792 scoped_refptr<DrainableIOBuffer> drainable = 793 new DrainableIOBuffer(buf.get(), buf->size()); 794 while (total_bytes_written != kTestDataSize) { 795 rv = stream->Write( 796 drainable.get(), drainable->BytesRemaining(), callback.callback()); 797 if (rv == ERR_IO_PENDING) 798 rv = callback.WaitForResult(); 799 EXPECT_LT(0, rv); 800 if (rv <= 0) 801 break; 802 drainable->DidConsume(rv); 803 total_bytes_written += rv; 804 } 805 806 EXPECT_EQ(kTestDataSize, total_bytes_written); 807 808 rv = stream->Seek(FROM_BEGIN, 0, callback64.callback()); 809 ASSERT_EQ(ERR_IO_PENDING, rv); 810 offset = callback64.WaitForResult(); 811 EXPECT_EQ(0, offset); 812 813 int total_bytes_read = 0; 814 815 std::string data_read; 816 for (;;) { 817 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); 818 rv = stream->Read(buf.get(), buf->size(), callback.callback()); 819 if (rv == ERR_IO_PENDING) 820 rv = callback.WaitForResult(); 821 EXPECT_LE(0, rv); 822 if (rv <= 0) 823 break; 824 total_bytes_read += rv; 825 data_read.append(buf->data(), rv); 826 } 827 stream.reset(); 828 829 ok = base::GetFileSize(temp_file_path(), &file_size); 830 EXPECT_TRUE(ok); 831 EXPECT_EQ(kTestDataSize * 2, file_size); 832 833 EXPECT_EQ(kTestDataSize * 2, total_bytes_read); 834 const std::string kExpectedFileData = 835 std::string(kTestData) + std::string(kTestData); 836 EXPECT_EQ(kExpectedFileData, data_read); 837 } 838 839 class TestWriteReadCompletionCallback { 840 public: 841 TestWriteReadCompletionCallback(FileStream* stream, 842 int* total_bytes_written, 843 int* total_bytes_read, 844 std::string* data_read) 845 : result_(0), 846 have_result_(false), 847 waiting_for_result_(false), 848 stream_(stream), 849 total_bytes_written_(total_bytes_written), 850 total_bytes_read_(total_bytes_read), 851 data_read_(data_read), 852 callback_(base::Bind(&TestWriteReadCompletionCallback::OnComplete, 853 base::Unretained(this))), 854 test_data_(CreateTestDataBuffer()), 855 drainable_(new DrainableIOBuffer(test_data_.get(), kTestDataSize)) {} 856 857 int WaitForResult() { 858 DCHECK(!waiting_for_result_); 859 while (!have_result_) { 860 waiting_for_result_ = true; 861 base::RunLoop().Run(); 862 waiting_for_result_ = false; 863 } 864 have_result_ = false; // auto-reset for next callback 865 return result_; 866 } 867 868 const CompletionCallback& callback() const { return callback_; } 869 870 private: 871 void OnComplete(int result) { 872 DCHECK_LT(0, result); 873 *total_bytes_written_ += result; 874 875 int rv; 876 877 if (*total_bytes_written_ != kTestDataSize) { 878 // Recurse to finish writing all data. 879 int total_bytes_written = 0, total_bytes_read = 0; 880 std::string data_read; 881 TestWriteReadCompletionCallback callback( 882 stream_, &total_bytes_written, &total_bytes_read, &data_read); 883 rv = stream_->Write( 884 drainable_.get(), drainable_->BytesRemaining(), callback.callback()); 885 DCHECK_EQ(ERR_IO_PENDING, rv); 886 rv = callback.WaitForResult(); 887 drainable_->DidConsume(total_bytes_written); 888 *total_bytes_written_ += total_bytes_written; 889 *total_bytes_read_ += total_bytes_read; 890 *data_read_ += data_read; 891 } else { // We're done writing all data. Start reading the data. 892 stream_->SeekSync(FROM_BEGIN, 0); 893 894 TestCompletionCallback callback; 895 for (;;) { 896 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); 897 rv = stream_->Read(buf.get(), buf->size(), callback.callback()); 898 if (rv == ERR_IO_PENDING) { 899 base::MessageLoop::ScopedNestableTaskAllower allow( 900 base::MessageLoop::current()); 901 rv = callback.WaitForResult(); 902 } 903 EXPECT_LE(0, rv); 904 if (rv <= 0) 905 break; 906 *total_bytes_read_ += rv; 907 data_read_->append(buf->data(), rv); 908 } 909 } 910 911 result_ = *total_bytes_written_; 912 have_result_ = true; 913 if (waiting_for_result_) 914 base::MessageLoop::current()->Quit(); 915 } 916 917 int result_; 918 bool have_result_; 919 bool waiting_for_result_; 920 FileStream* stream_; 921 int* total_bytes_written_; 922 int* total_bytes_read_; 923 std::string* data_read_; 924 const CompletionCallback callback_; 925 scoped_refptr<IOBufferWithSize> test_data_; 926 scoped_refptr<DrainableIOBuffer> drainable_; 927 928 DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback); 929 }; 930 931 TEST_F(FileStreamTest, AsyncWriteRead) { 932 int64 file_size; 933 bool ok = base::GetFileSize(temp_file_path(), &file_size); 934 EXPECT_TRUE(ok); 935 936 scoped_ptr<FileStream> stream( 937 new FileStream(NULL, base::MessageLoopProxy::current())); 938 int flags = base::PLATFORM_FILE_OPEN | 939 base::PLATFORM_FILE_READ | 940 base::PLATFORM_FILE_WRITE | 941 base::PLATFORM_FILE_ASYNC; 942 TestCompletionCallback open_callback; 943 int rv = stream->Open(temp_file_path(), flags, open_callback.callback()); 944 EXPECT_EQ(ERR_IO_PENDING, rv); 945 EXPECT_EQ(OK, open_callback.WaitForResult()); 946 947 int64 total_bytes_avail = stream->Available(); 948 EXPECT_EQ(file_size, total_bytes_avail); 949 950 int64 offset = stream->SeekSync(FROM_END, 0); 951 EXPECT_EQ(offset, file_size); 952 953 int total_bytes_written = 0; 954 int total_bytes_read = 0; 955 std::string data_read; 956 TestWriteReadCompletionCallback callback(stream.get(), &total_bytes_written, 957 &total_bytes_read, &data_read); 958 959 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); 960 rv = stream->Write(buf.get(), buf->size(), callback.callback()); 961 if (rv == ERR_IO_PENDING) 962 rv = callback.WaitForResult(); 963 EXPECT_LT(0, rv); 964 EXPECT_EQ(kTestDataSize, total_bytes_written); 965 966 stream.reset(); 967 968 ok = base::GetFileSize(temp_file_path(), &file_size); 969 EXPECT_TRUE(ok); 970 EXPECT_EQ(kTestDataSize * 2, file_size); 971 972 EXPECT_EQ(kTestDataSize * 2, total_bytes_read); 973 const std::string kExpectedFileData = 974 std::string(kTestData) + std::string(kTestData); 975 EXPECT_EQ(kExpectedFileData, data_read); 976 } 977 978 class TestWriteCloseCompletionCallback { 979 public: 980 TestWriteCloseCompletionCallback(FileStream* stream, int* total_bytes_written) 981 : result_(0), 982 have_result_(false), 983 waiting_for_result_(false), 984 stream_(stream), 985 total_bytes_written_(total_bytes_written), 986 callback_(base::Bind(&TestWriteCloseCompletionCallback::OnComplete, 987 base::Unretained(this))), 988 test_data_(CreateTestDataBuffer()), 989 drainable_(new DrainableIOBuffer(test_data_.get(), kTestDataSize)) {} 990 991 int WaitForResult() { 992 DCHECK(!waiting_for_result_); 993 while (!have_result_) { 994 waiting_for_result_ = true; 995 base::RunLoop().Run(); 996 waiting_for_result_ = false; 997 } 998 have_result_ = false; // auto-reset for next callback 999 return result_; 1000 } 1001 1002 const CompletionCallback& callback() const { return callback_; } 1003 1004 private: 1005 void OnComplete(int result) { 1006 DCHECK_LT(0, result); 1007 *total_bytes_written_ += result; 1008 1009 int rv; 1010 1011 if (*total_bytes_written_ != kTestDataSize) { 1012 // Recurse to finish writing all data. 1013 int total_bytes_written = 0; 1014 TestWriteCloseCompletionCallback callback(stream_, &total_bytes_written); 1015 rv = stream_->Write( 1016 drainable_.get(), drainable_->BytesRemaining(), callback.callback()); 1017 DCHECK_EQ(ERR_IO_PENDING, rv); 1018 rv = callback.WaitForResult(); 1019 drainable_->DidConsume(total_bytes_written); 1020 *total_bytes_written_ += total_bytes_written; 1021 } 1022 1023 result_ = *total_bytes_written_; 1024 have_result_ = true; 1025 if (waiting_for_result_) 1026 base::MessageLoop::current()->Quit(); 1027 } 1028 1029 int result_; 1030 bool have_result_; 1031 bool waiting_for_result_; 1032 FileStream* stream_; 1033 int* total_bytes_written_; 1034 const CompletionCallback callback_; 1035 scoped_refptr<IOBufferWithSize> test_data_; 1036 scoped_refptr<DrainableIOBuffer> drainable_; 1037 1038 DISALLOW_COPY_AND_ASSIGN(TestWriteCloseCompletionCallback); 1039 }; 1040 1041 TEST_F(FileStreamTest, AsyncWriteClose) { 1042 int64 file_size; 1043 bool ok = base::GetFileSize(temp_file_path(), &file_size); 1044 EXPECT_TRUE(ok); 1045 1046 scoped_ptr<FileStream> stream( 1047 new FileStream(NULL, base::MessageLoopProxy::current())); 1048 int flags = base::PLATFORM_FILE_OPEN | 1049 base::PLATFORM_FILE_READ | 1050 base::PLATFORM_FILE_WRITE | 1051 base::PLATFORM_FILE_ASYNC; 1052 TestCompletionCallback open_callback; 1053 int rv = stream->Open(temp_file_path(), flags, open_callback.callback()); 1054 EXPECT_EQ(ERR_IO_PENDING, rv); 1055 EXPECT_EQ(OK, open_callback.WaitForResult()); 1056 1057 int64 total_bytes_avail = stream->Available(); 1058 EXPECT_EQ(file_size, total_bytes_avail); 1059 1060 int64 offset = stream->SeekSync(FROM_END, 0); 1061 EXPECT_EQ(offset, file_size); 1062 1063 int total_bytes_written = 0; 1064 TestWriteCloseCompletionCallback callback(stream.get(), &total_bytes_written); 1065 1066 scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); 1067 rv = stream->Write(buf.get(), buf->size(), callback.callback()); 1068 if (rv == ERR_IO_PENDING) 1069 total_bytes_written = callback.WaitForResult(); 1070 EXPECT_LT(0, total_bytes_written); 1071 EXPECT_EQ(kTestDataSize, total_bytes_written); 1072 1073 stream.reset(); 1074 1075 ok = base::GetFileSize(temp_file_path(), &file_size); 1076 EXPECT_TRUE(ok); 1077 EXPECT_EQ(kTestDataSize * 2, file_size); 1078 } 1079 1080 // Tests truncating a file. 1081 TEST_F(FileStreamTest, Truncate) { 1082 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE; 1083 1084 scoped_ptr<FileStream> write_stream( 1085 new FileStream(NULL, base::MessageLoopProxy::current())); 1086 ASSERT_EQ(OK, write_stream->OpenSync(temp_file_path(), flags)); 1087 1088 // Write some data to the file. 1089 const char test_data[] = "0123456789"; 1090 write_stream->WriteSync(test_data, arraysize(test_data)); 1091 1092 // Truncate the file. 1093 ASSERT_EQ(4, write_stream->Truncate(4)); 1094 1095 // Write again. 1096 write_stream->WriteSync(test_data, 4); 1097 1098 // Close the stream. 1099 write_stream.reset(); 1100 1101 // Read in the contents and make sure we get back what we expected. 1102 std::string read_contents; 1103 EXPECT_TRUE(base::ReadFileToString(temp_file_path(), &read_contents)); 1104 1105 EXPECT_EQ("01230123", read_contents); 1106 } 1107 1108 TEST_F(FileStreamTest, AsyncOpenAndDelete) { 1109 scoped_ptr<FileStream> stream( 1110 new FileStream(NULL, base::MessageLoopProxy::current())); 1111 int flags = base::PLATFORM_FILE_OPEN | 1112 base::PLATFORM_FILE_WRITE | 1113 base::PLATFORM_FILE_ASYNC; 1114 TestCompletionCallback open_callback; 1115 int rv = stream->Open(temp_file_path(), flags, open_callback.callback()); 1116 EXPECT_EQ(ERR_IO_PENDING, rv); 1117 1118 // Delete the stream without waiting for the open operation to be 1119 // complete. Should be safe. 1120 stream.reset(); 1121 // open_callback won't be called. 1122 base::RunLoop().RunUntilIdle(); 1123 EXPECT_FALSE(open_callback.have_result()); 1124 } 1125 1126 // Verify that async Write() errors are mapped correctly. 1127 TEST_F(FileStreamTest, AsyncWriteError) { 1128 // Try opening file as read-only and then writing to it using FileStream. 1129 base::PlatformFile file = base::CreatePlatformFile( 1130 temp_file_path(), 1131 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ | 1132 base::PLATFORM_FILE_ASYNC, 1133 NULL, 1134 NULL); 1135 ASSERT_NE(base::kInvalidPlatformFileValue, file); 1136 1137 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE | 1138 base::PLATFORM_FILE_ASYNC; 1139 scoped_ptr<FileStream> stream( 1140 new FileStream(file, flags, NULL, base::MessageLoopProxy::current())); 1141 1142 scoped_refptr<IOBuffer> buf = new IOBuffer(1); 1143 buf->data()[0] = 0; 1144 1145 TestCompletionCallback callback; 1146 int rv = stream->Write(buf.get(), 1, callback.callback()); 1147 if (rv == ERR_IO_PENDING) 1148 rv = callback.WaitForResult(); 1149 EXPECT_LT(rv, 0); 1150 1151 base::ClosePlatformFile(file); 1152 } 1153 1154 // Verify that async Read() errors are mapped correctly. 1155 TEST_F(FileStreamTest, AsyncReadError) { 1156 // Try opening file for write and then reading from it using FileStream. 1157 base::PlatformFile file = base::CreatePlatformFile( 1158 temp_file_path(), 1159 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE | 1160 base::PLATFORM_FILE_ASYNC, 1161 NULL, 1162 NULL); 1163 ASSERT_NE(base::kInvalidPlatformFileValue, file); 1164 1165 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ | 1166 base::PLATFORM_FILE_ASYNC; 1167 scoped_ptr<FileStream> stream( 1168 new FileStream(file, flags, NULL, base::MessageLoopProxy::current())); 1169 1170 scoped_refptr<IOBuffer> buf = new IOBuffer(1); 1171 TestCompletionCallback callback; 1172 int rv = stream->Read(buf.get(), 1, callback.callback()); 1173 if (rv == ERR_IO_PENDING) 1174 rv = callback.WaitForResult(); 1175 EXPECT_LT(rv, 0); 1176 1177 base::ClosePlatformFile(file); 1178 } 1179 1180 #if defined(OS_ANDROID) 1181 TEST_F(FileStreamTest, ContentUriAsyncRead) { 1182 base::FilePath test_dir; 1183 PathService::Get(base::DIR_SOURCE_ROOT, &test_dir); 1184 test_dir = test_dir.AppendASCII("net"); 1185 test_dir = test_dir.AppendASCII("data"); 1186 test_dir = test_dir.AppendASCII("file_stream_unittest"); 1187 ASSERT_TRUE(base::PathExists(test_dir)); 1188 base::FilePath image_file = test_dir.Append(FILE_PATH_LITERAL("red.png")); 1189 1190 // Insert the image into MediaStore. MediaStore will do some conversions, and 1191 // return the content URI. 1192 base::FilePath path = file_util::InsertImageIntoMediaStore(image_file); 1193 EXPECT_TRUE(path.IsContentUri()); 1194 EXPECT_TRUE(base::PathExists(path)); 1195 int64 file_size; 1196 EXPECT_TRUE(base::GetFileSize(path, &file_size)); 1197 EXPECT_LT(0, file_size); 1198 1199 FileStream stream(NULL, base::MessageLoopProxy::current()); 1200 int flags = base::PLATFORM_FILE_OPEN | 1201 base::PLATFORM_FILE_READ | 1202 base::PLATFORM_FILE_ASYNC; 1203 TestCompletionCallback callback; 1204 int rv = stream.Open(path, flags, callback.callback()); 1205 EXPECT_EQ(ERR_IO_PENDING, rv); 1206 EXPECT_EQ(OK, callback.WaitForResult()); 1207 1208 int64 total_bytes_avail = stream.Available(); 1209 EXPECT_EQ(file_size, total_bytes_avail); 1210 1211 int total_bytes_read = 0; 1212 1213 std::string data_read; 1214 for (;;) { 1215 scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); 1216 rv = stream.Read(buf.get(), buf->size(), callback.callback()); 1217 if (rv == ERR_IO_PENDING) 1218 rv = callback.WaitForResult(); 1219 EXPECT_LE(0, rv); 1220 if (rv <= 0) 1221 break; 1222 total_bytes_read += rv; 1223 data_read.append(buf->data(), rv); 1224 } 1225 EXPECT_EQ(file_size, total_bytes_read); 1226 } 1227 #endif 1228 1229 } // namespace 1230 1231 } // namespace net 1232