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