1 // Copyright (c) 2011 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 "base/callback.h" 6 #include "base/file_util.h" 7 #include "base/message_loop.h" 8 #include "base/path_service.h" 9 #include "base/platform_file.h" 10 #include "net/base/file_stream.h" 11 #include "net/base/net_errors.h" 12 #include "net/base/test_completion_callback.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/platform_test.h" 15 16 namespace net { 17 namespace { 18 19 const char kTestData[] = "0123456789"; 20 const int kTestDataSize = arraysize(kTestData) - 1; 21 22 class FileStreamTest : public PlatformTest { 23 public: 24 virtual void SetUp() { 25 PlatformTest::SetUp(); 26 27 file_util::CreateTemporaryFile(&temp_file_path_); 28 file_util::WriteFile(temp_file_path_, kTestData, kTestDataSize); 29 } 30 virtual void TearDown() { 31 file_util::Delete(temp_file_path_, false); 32 33 PlatformTest::TearDown(); 34 } 35 const FilePath temp_file_path() const { return temp_file_path_; } 36 private: 37 FilePath temp_file_path_; 38 }; 39 40 TEST_F(FileStreamTest, BasicOpenClose) { 41 FileStream stream; 42 int rv = stream.Open(temp_file_path(), 43 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ); 44 EXPECT_EQ(OK, rv); 45 } 46 47 // Test the use of FileStream with a file handle provided at construction. 48 TEST_F(FileStreamTest, UseFileHandle) { 49 bool created = false; 50 51 // 1. Test reading with a file handle. 52 ASSERT_EQ(kTestDataSize, 53 file_util::WriteFile(temp_file_path(), kTestData, kTestDataSize)); 54 int flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ; 55 base::PlatformFile file = base::CreatePlatformFile( 56 temp_file_path(), flags, &created, NULL); 57 58 // Seek to the beginning of the file and read. 59 FileStream read_stream(file, flags); 60 ASSERT_EQ(0, read_stream.Seek(FROM_BEGIN, 0)); 61 ASSERT_EQ(kTestDataSize, read_stream.Available()); 62 // Read into buffer and compare. 63 char buffer[kTestDataSize]; 64 ASSERT_EQ(kTestDataSize, read_stream.Read(buffer, kTestDataSize, NULL)); 65 ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize)); 66 read_stream.Close(); 67 68 // 2. Test writing with a file handle. 69 file_util::Delete(temp_file_path(), false); 70 flags = base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE; 71 file = base::CreatePlatformFile(temp_file_path(), flags, &created, NULL); 72 73 FileStream write_stream(file, flags); 74 ASSERT_EQ(0, write_stream.Seek(FROM_BEGIN, 0)); 75 ASSERT_EQ(kTestDataSize, write_stream.Write(kTestData, kTestDataSize, NULL)); 76 write_stream.Close(); 77 78 // Read into buffer and compare to make sure the handle worked fine. 79 ASSERT_EQ(kTestDataSize, 80 file_util::ReadFile(temp_file_path(), buffer, kTestDataSize)); 81 ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize)); 82 } 83 84 TEST_F(FileStreamTest, UseClosedStream) { 85 FileStream stream; 86 87 EXPECT_FALSE(stream.IsOpen()); 88 89 // Try seeking... 90 int64 new_offset = stream.Seek(FROM_BEGIN, 5); 91 EXPECT_EQ(ERR_UNEXPECTED, new_offset); 92 93 // Try available... 94 int64 avail = stream.Available(); 95 EXPECT_EQ(ERR_UNEXPECTED, avail); 96 97 // Try reading... 98 char buf[10]; 99 int rv = stream.Read(buf, arraysize(buf), NULL); 100 EXPECT_EQ(ERR_UNEXPECTED, rv); 101 } 102 103 TEST_F(FileStreamTest, BasicRead) { 104 int64 file_size; 105 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 106 EXPECT_TRUE(ok); 107 108 FileStream stream; 109 int flags = base::PLATFORM_FILE_OPEN | 110 base::PLATFORM_FILE_READ; 111 int rv = stream.Open(temp_file_path(), flags); 112 EXPECT_EQ(OK, rv); 113 114 int64 total_bytes_avail = stream.Available(); 115 EXPECT_EQ(file_size, total_bytes_avail); 116 117 int total_bytes_read = 0; 118 119 std::string data_read; 120 for (;;) { 121 char buf[4]; 122 rv = stream.Read(buf, arraysize(buf), NULL); 123 EXPECT_LE(0, rv); 124 if (rv <= 0) 125 break; 126 total_bytes_read += rv; 127 data_read.append(buf, rv); 128 } 129 EXPECT_EQ(file_size, total_bytes_read); 130 EXPECT_EQ(kTestData, data_read); 131 } 132 133 TEST_F(FileStreamTest, AsyncRead) { 134 int64 file_size; 135 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 136 EXPECT_TRUE(ok); 137 138 FileStream stream; 139 int flags = base::PLATFORM_FILE_OPEN | 140 base::PLATFORM_FILE_READ | 141 base::PLATFORM_FILE_ASYNC; 142 int rv = stream.Open(temp_file_path(), flags); 143 EXPECT_EQ(OK, rv); 144 145 int64 total_bytes_avail = stream.Available(); 146 EXPECT_EQ(file_size, total_bytes_avail); 147 148 TestCompletionCallback callback; 149 150 int total_bytes_read = 0; 151 152 std::string data_read; 153 for (;;) { 154 char buf[4]; 155 rv = stream.Read(buf, arraysize(buf), &callback); 156 if (rv == ERR_IO_PENDING) 157 rv = callback.WaitForResult(); 158 EXPECT_LE(0, rv); 159 if (rv <= 0) 160 break; 161 total_bytes_read += rv; 162 data_read.append(buf, rv); 163 } 164 EXPECT_EQ(file_size, total_bytes_read); 165 EXPECT_EQ(kTestData, data_read); 166 } 167 168 TEST_F(FileStreamTest, AsyncRead_EarlyClose) { 169 int64 file_size; 170 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 171 EXPECT_TRUE(ok); 172 173 FileStream stream; 174 int flags = base::PLATFORM_FILE_OPEN | 175 base::PLATFORM_FILE_READ | 176 base::PLATFORM_FILE_ASYNC; 177 int rv = stream.Open(temp_file_path(), flags); 178 EXPECT_EQ(OK, rv); 179 180 int64 total_bytes_avail = stream.Available(); 181 EXPECT_EQ(file_size, total_bytes_avail); 182 183 TestCompletionCallback callback; 184 185 char buf[4]; 186 rv = stream.Read(buf, arraysize(buf), &callback); 187 stream.Close(); 188 if (rv < 0) { 189 EXPECT_EQ(ERR_IO_PENDING, rv); 190 // The callback should not be called if the request is cancelled. 191 MessageLoop::current()->RunAllPending(); 192 EXPECT_FALSE(callback.have_result()); 193 } else { 194 EXPECT_EQ(std::string(kTestData, rv), std::string(buf, rv)); 195 } 196 } 197 198 TEST_F(FileStreamTest, BasicRead_FromOffset) { 199 int64 file_size; 200 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 201 EXPECT_TRUE(ok); 202 203 FileStream stream; 204 int flags = base::PLATFORM_FILE_OPEN | 205 base::PLATFORM_FILE_READ; 206 int rv = stream.Open(temp_file_path(), flags); 207 EXPECT_EQ(OK, rv); 208 209 const int64 kOffset = 3; 210 int64 new_offset = stream.Seek(FROM_BEGIN, kOffset); 211 EXPECT_EQ(kOffset, new_offset); 212 213 int64 total_bytes_avail = stream.Available(); 214 EXPECT_EQ(file_size - kOffset, total_bytes_avail); 215 216 int64 total_bytes_read = 0; 217 218 std::string data_read; 219 for (;;) { 220 char buf[4]; 221 rv = stream.Read(buf, arraysize(buf), NULL); 222 EXPECT_LE(0, rv); 223 if (rv <= 0) 224 break; 225 total_bytes_read += rv; 226 data_read.append(buf, rv); 227 } 228 EXPECT_EQ(file_size - kOffset, total_bytes_read); 229 EXPECT_TRUE(data_read == kTestData + kOffset); 230 EXPECT_EQ(kTestData + kOffset, data_read); 231 } 232 233 TEST_F(FileStreamTest, AsyncRead_FromOffset) { 234 int64 file_size; 235 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 236 EXPECT_TRUE(ok); 237 238 FileStream stream; 239 int flags = base::PLATFORM_FILE_OPEN | 240 base::PLATFORM_FILE_READ | 241 base::PLATFORM_FILE_ASYNC; 242 int rv = stream.Open(temp_file_path(), flags); 243 EXPECT_EQ(OK, rv); 244 245 const int64 kOffset = 3; 246 int64 new_offset = stream.Seek(FROM_BEGIN, kOffset); 247 EXPECT_EQ(kOffset, new_offset); 248 249 int64 total_bytes_avail = stream.Available(); 250 EXPECT_EQ(file_size - kOffset, total_bytes_avail); 251 252 TestCompletionCallback callback; 253 254 int total_bytes_read = 0; 255 256 std::string data_read; 257 for (;;) { 258 char buf[4]; 259 rv = stream.Read(buf, arraysize(buf), &callback); 260 if (rv == ERR_IO_PENDING) 261 rv = callback.WaitForResult(); 262 EXPECT_LE(0, rv); 263 if (rv <= 0) 264 break; 265 total_bytes_read += rv; 266 data_read.append(buf, rv); 267 } 268 EXPECT_EQ(file_size - kOffset, total_bytes_read); 269 EXPECT_EQ(kTestData + kOffset, data_read); 270 } 271 272 TEST_F(FileStreamTest, SeekAround) { 273 FileStream stream; 274 int flags = base::PLATFORM_FILE_OPEN | 275 base::PLATFORM_FILE_READ; 276 int rv = stream.Open(temp_file_path(), flags); 277 EXPECT_EQ(OK, rv); 278 279 const int64 kOffset = 3; 280 int64 new_offset = stream.Seek(FROM_BEGIN, kOffset); 281 EXPECT_EQ(kOffset, new_offset); 282 283 new_offset = stream.Seek(FROM_CURRENT, kOffset); 284 EXPECT_EQ(2 * kOffset, new_offset); 285 286 new_offset = stream.Seek(FROM_CURRENT, -kOffset); 287 EXPECT_EQ(kOffset, new_offset); 288 289 const int kTestDataLen = arraysize(kTestData) - 1; 290 291 new_offset = stream.Seek(FROM_END, -kTestDataLen); 292 EXPECT_EQ(0, new_offset); 293 } 294 295 TEST_F(FileStreamTest, BasicWrite) { 296 FileStream stream; 297 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | 298 base::PLATFORM_FILE_WRITE; 299 int rv = stream.Open(temp_file_path(), flags); 300 EXPECT_EQ(OK, rv); 301 302 int64 file_size; 303 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 304 EXPECT_TRUE(ok); 305 EXPECT_EQ(0, file_size); 306 307 rv = stream.Write(kTestData, kTestDataSize, NULL); 308 EXPECT_EQ(kTestDataSize, rv); 309 stream.Close(); 310 311 ok = file_util::GetFileSize(temp_file_path(), &file_size); 312 EXPECT_TRUE(ok); 313 EXPECT_EQ(kTestDataSize, file_size); 314 } 315 316 TEST_F(FileStreamTest, AsyncWrite) { 317 FileStream stream; 318 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | 319 base::PLATFORM_FILE_WRITE | 320 base::PLATFORM_FILE_ASYNC; 321 int rv = stream.Open(temp_file_path(), flags); 322 EXPECT_EQ(OK, rv); 323 324 int64 file_size; 325 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 326 EXPECT_TRUE(ok); 327 EXPECT_EQ(0, file_size); 328 329 TestCompletionCallback callback; 330 int total_bytes_written = 0; 331 332 while (total_bytes_written != kTestDataSize) { 333 rv = stream.Write(kTestData + total_bytes_written, 334 kTestDataSize - total_bytes_written, 335 &callback); 336 if (rv == ERR_IO_PENDING) 337 rv = callback.WaitForResult(); 338 EXPECT_LT(0, rv); 339 if (rv <= 0) 340 break; 341 total_bytes_written += rv; 342 } 343 ok = file_util::GetFileSize(temp_file_path(), &file_size); 344 EXPECT_TRUE(ok); 345 EXPECT_EQ(file_size, total_bytes_written); 346 } 347 348 TEST_F(FileStreamTest, AsyncWrite_EarlyClose) { 349 FileStream stream; 350 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | 351 base::PLATFORM_FILE_WRITE | 352 base::PLATFORM_FILE_ASYNC; 353 int rv = stream.Open(temp_file_path(), flags); 354 EXPECT_EQ(OK, rv); 355 356 int64 file_size; 357 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 358 EXPECT_TRUE(ok); 359 EXPECT_EQ(0, file_size); 360 361 TestCompletionCallback callback; 362 int total_bytes_written = 0; 363 364 rv = stream.Write(kTestData + total_bytes_written, 365 kTestDataSize - total_bytes_written, 366 &callback); 367 stream.Close(); 368 if (rv < 0) { 369 EXPECT_EQ(ERR_IO_PENDING, rv); 370 // The callback should not be called if the request is cancelled. 371 MessageLoop::current()->RunAllPending(); 372 EXPECT_FALSE(callback.have_result()); 373 } else { 374 ok = file_util::GetFileSize(temp_file_path(), &file_size); 375 EXPECT_TRUE(ok); 376 EXPECT_EQ(file_size, rv); 377 } 378 } 379 380 TEST_F(FileStreamTest, BasicWrite_FromOffset) { 381 FileStream stream; 382 int flags = base::PLATFORM_FILE_OPEN | 383 base::PLATFORM_FILE_WRITE; 384 int rv = stream.Open(temp_file_path(), flags); 385 EXPECT_EQ(OK, rv); 386 387 int64 file_size; 388 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 389 EXPECT_TRUE(ok); 390 EXPECT_EQ(kTestDataSize, file_size); 391 392 const int64 kOffset = 0; 393 int64 new_offset = stream.Seek(FROM_END, kOffset); 394 EXPECT_EQ(kTestDataSize, new_offset); 395 396 rv = stream.Write(kTestData, kTestDataSize, NULL); 397 EXPECT_EQ(kTestDataSize, rv); 398 stream.Close(); 399 400 ok = file_util::GetFileSize(temp_file_path(), &file_size); 401 EXPECT_TRUE(ok); 402 EXPECT_EQ(kTestDataSize * 2, file_size); 403 } 404 405 TEST_F(FileStreamTest, AsyncWrite_FromOffset) { 406 int64 file_size; 407 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 408 EXPECT_TRUE(ok); 409 410 FileStream stream; 411 int flags = base::PLATFORM_FILE_OPEN | 412 base::PLATFORM_FILE_WRITE | 413 base::PLATFORM_FILE_ASYNC; 414 int rv = stream.Open(temp_file_path(), flags); 415 EXPECT_EQ(OK, rv); 416 417 const int64 kOffset = 0; 418 int64 new_offset = stream.Seek(FROM_END, kOffset); 419 EXPECT_EQ(kTestDataSize, new_offset); 420 421 TestCompletionCallback callback; 422 int total_bytes_written = 0; 423 424 while (total_bytes_written != kTestDataSize) { 425 rv = stream.Write(kTestData + total_bytes_written, 426 kTestDataSize - total_bytes_written, 427 &callback); 428 if (rv == ERR_IO_PENDING) 429 rv = callback.WaitForResult(); 430 EXPECT_LT(0, rv); 431 if (rv <= 0) 432 break; 433 total_bytes_written += rv; 434 } 435 ok = file_util::GetFileSize(temp_file_path(), &file_size); 436 EXPECT_TRUE(ok); 437 EXPECT_EQ(file_size, kTestDataSize * 2); 438 } 439 440 TEST_F(FileStreamTest, BasicReadWrite) { 441 int64 file_size; 442 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 443 EXPECT_TRUE(ok); 444 445 FileStream stream; 446 int flags = base::PLATFORM_FILE_OPEN | 447 base::PLATFORM_FILE_READ | 448 base::PLATFORM_FILE_WRITE; 449 int rv = stream.Open(temp_file_path(), flags); 450 EXPECT_EQ(OK, rv); 451 452 int64 total_bytes_avail = stream.Available(); 453 EXPECT_EQ(file_size, total_bytes_avail); 454 455 int total_bytes_read = 0; 456 457 std::string data_read; 458 for (;;) { 459 char buf[4]; 460 rv = stream.Read(buf, arraysize(buf), NULL); 461 EXPECT_LE(0, rv); 462 if (rv <= 0) 463 break; 464 total_bytes_read += rv; 465 data_read.append(buf, rv); 466 } 467 EXPECT_EQ(file_size, total_bytes_read); 468 EXPECT_TRUE(data_read == kTestData); 469 470 rv = stream.Write(kTestData, kTestDataSize, NULL); 471 EXPECT_EQ(kTestDataSize, rv); 472 stream.Close(); 473 474 ok = file_util::GetFileSize(temp_file_path(), &file_size); 475 EXPECT_TRUE(ok); 476 EXPECT_EQ(kTestDataSize * 2, file_size); 477 } 478 479 TEST_F(FileStreamTest, BasicWriteRead) { 480 int64 file_size; 481 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 482 EXPECT_TRUE(ok); 483 484 FileStream stream; 485 int flags = base::PLATFORM_FILE_OPEN | 486 base::PLATFORM_FILE_READ | 487 base::PLATFORM_FILE_WRITE; 488 int rv = stream.Open(temp_file_path(), flags); 489 EXPECT_EQ(OK, rv); 490 491 int64 total_bytes_avail = stream.Available(); 492 EXPECT_EQ(file_size, total_bytes_avail); 493 494 int64 offset = stream.Seek(FROM_END, 0); 495 EXPECT_EQ(offset, file_size); 496 497 rv = stream.Write(kTestData, kTestDataSize, NULL); 498 EXPECT_EQ(kTestDataSize, rv); 499 500 offset = stream.Seek(FROM_BEGIN, 0); 501 EXPECT_EQ(0, offset); 502 503 int64 total_bytes_read = 0; 504 505 std::string data_read; 506 for (;;) { 507 char buf[4]; 508 rv = stream.Read(buf, arraysize(buf), NULL); 509 EXPECT_LE(0, rv); 510 if (rv <= 0) 511 break; 512 total_bytes_read += rv; 513 data_read.append(buf, rv); 514 } 515 stream.Close(); 516 517 ok = file_util::GetFileSize(temp_file_path(), &file_size); 518 EXPECT_TRUE(ok); 519 EXPECT_EQ(kTestDataSize * 2, file_size); 520 EXPECT_EQ(kTestDataSize * 2, total_bytes_read); 521 522 const std::string kExpectedFileData = 523 std::string(kTestData) + std::string(kTestData); 524 EXPECT_EQ(kExpectedFileData, data_read); 525 } 526 527 TEST_F(FileStreamTest, BasicAsyncReadWrite) { 528 int64 file_size; 529 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 530 EXPECT_TRUE(ok); 531 532 FileStream stream; 533 int flags = base::PLATFORM_FILE_OPEN | 534 base::PLATFORM_FILE_READ | 535 base::PLATFORM_FILE_WRITE | 536 base::PLATFORM_FILE_ASYNC; 537 int rv = stream.Open(temp_file_path(), flags); 538 EXPECT_EQ(OK, rv); 539 540 int64 total_bytes_avail = stream.Available(); 541 EXPECT_EQ(file_size, total_bytes_avail); 542 543 TestCompletionCallback callback; 544 int64 total_bytes_read = 0; 545 546 std::string data_read; 547 for (;;) { 548 char buf[4]; 549 rv = stream.Read(buf, arraysize(buf), &callback); 550 if (rv == ERR_IO_PENDING) 551 rv = callback.WaitForResult(); 552 EXPECT_LE(0, rv); 553 if (rv <= 0) 554 break; 555 total_bytes_read += rv; 556 data_read.append(buf, rv); 557 } 558 EXPECT_EQ(file_size, total_bytes_read); 559 EXPECT_TRUE(data_read == kTestData); 560 561 int total_bytes_written = 0; 562 563 while (total_bytes_written != kTestDataSize) { 564 rv = stream.Write(kTestData + total_bytes_written, 565 kTestDataSize - total_bytes_written, 566 &callback); 567 if (rv == ERR_IO_PENDING) 568 rv = callback.WaitForResult(); 569 EXPECT_LT(0, rv); 570 if (rv <= 0) 571 break; 572 total_bytes_written += rv; 573 } 574 575 stream.Close(); 576 577 ok = file_util::GetFileSize(temp_file_path(), &file_size); 578 EXPECT_TRUE(ok); 579 EXPECT_EQ(kTestDataSize * 2, file_size); 580 } 581 582 TEST_F(FileStreamTest, BasicAsyncWriteRead) { 583 int64 file_size; 584 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 585 EXPECT_TRUE(ok); 586 587 FileStream stream; 588 int flags = base::PLATFORM_FILE_OPEN | 589 base::PLATFORM_FILE_READ | 590 base::PLATFORM_FILE_WRITE | 591 base::PLATFORM_FILE_ASYNC; 592 int rv = stream.Open(temp_file_path(), flags); 593 EXPECT_EQ(OK, rv); 594 595 int64 total_bytes_avail = stream.Available(); 596 EXPECT_EQ(file_size, total_bytes_avail); 597 598 int64 offset = stream.Seek(FROM_END, 0); 599 EXPECT_EQ(offset, file_size); 600 601 TestCompletionCallback callback; 602 int total_bytes_written = 0; 603 604 while (total_bytes_written != kTestDataSize) { 605 rv = stream.Write(kTestData + total_bytes_written, 606 kTestDataSize - total_bytes_written, 607 &callback); 608 if (rv == ERR_IO_PENDING) 609 rv = callback.WaitForResult(); 610 EXPECT_LT(0, rv); 611 if (rv <= 0) 612 break; 613 total_bytes_written += rv; 614 } 615 616 EXPECT_EQ(kTestDataSize, total_bytes_written); 617 618 offset = stream.Seek(FROM_BEGIN, 0); 619 EXPECT_EQ(0, offset); 620 621 int total_bytes_read = 0; 622 623 std::string data_read; 624 for (;;) { 625 char buf[4]; 626 rv = stream.Read(buf, arraysize(buf), &callback); 627 if (rv == ERR_IO_PENDING) 628 rv = callback.WaitForResult(); 629 EXPECT_LE(0, rv); 630 if (rv <= 0) 631 break; 632 total_bytes_read += rv; 633 data_read.append(buf, rv); 634 } 635 stream.Close(); 636 637 ok = file_util::GetFileSize(temp_file_path(), &file_size); 638 EXPECT_TRUE(ok); 639 EXPECT_EQ(kTestDataSize * 2, file_size); 640 641 EXPECT_EQ(kTestDataSize * 2, total_bytes_read); 642 const std::string kExpectedFileData = 643 std::string(kTestData) + std::string(kTestData); 644 EXPECT_EQ(kExpectedFileData, data_read); 645 } 646 647 class TestWriteReadCompletionCallback : public Callback1<int>::Type { 648 public: 649 explicit TestWriteReadCompletionCallback( 650 FileStream* stream, 651 int* total_bytes_written, 652 int* total_bytes_read, 653 std::string* data_read) 654 : result_(0), 655 have_result_(false), 656 waiting_for_result_(false), 657 stream_(stream), 658 total_bytes_written_(total_bytes_written), 659 total_bytes_read_(total_bytes_read), 660 data_read_(data_read) {} 661 662 int WaitForResult() { 663 DCHECK(!waiting_for_result_); 664 while (!have_result_) { 665 waiting_for_result_ = true; 666 MessageLoop::current()->Run(); 667 waiting_for_result_ = false; 668 } 669 have_result_ = false; // auto-reset for next callback 670 return result_; 671 } 672 673 private: 674 virtual void RunWithParams(const Tuple1<int>& params) { 675 DCHECK_LT(0, params.a); 676 *total_bytes_written_ += params.a; 677 678 int rv; 679 680 if (*total_bytes_written_ != kTestDataSize) { 681 // Recurse to finish writing all data. 682 int total_bytes_written = 0, total_bytes_read = 0; 683 std::string data_read; 684 TestWriteReadCompletionCallback callback( 685 stream_, &total_bytes_written, &total_bytes_read, &data_read); 686 rv = stream_->Write(kTestData + *total_bytes_written_, 687 kTestDataSize - *total_bytes_written_, 688 &callback); 689 DCHECK_EQ(ERR_IO_PENDING, rv); 690 rv = callback.WaitForResult(); 691 *total_bytes_written_ += total_bytes_written; 692 *total_bytes_read_ += total_bytes_read; 693 *data_read_ += data_read; 694 } else { // We're done writing all data. Start reading the data. 695 stream_->Seek(FROM_BEGIN, 0); 696 697 TestCompletionCallback callback; 698 for (;;) { 699 char buf[4]; 700 rv = stream_->Read(buf, arraysize(buf), &callback); 701 if (rv == ERR_IO_PENDING) { 702 bool old_state = MessageLoop::current()->NestableTasksAllowed(); 703 MessageLoop::current()->SetNestableTasksAllowed(true); 704 rv = callback.WaitForResult(); 705 MessageLoop::current()->SetNestableTasksAllowed(old_state); 706 } 707 EXPECT_LE(0, rv); 708 if (rv <= 0) 709 break; 710 *total_bytes_read_ += rv; 711 data_read_->append(buf, rv); 712 } 713 } 714 715 result_ = *total_bytes_written_; 716 have_result_ = true; 717 if (waiting_for_result_) 718 MessageLoop::current()->Quit(); 719 } 720 721 int result_; 722 bool have_result_; 723 bool waiting_for_result_; 724 FileStream* stream_; 725 int* total_bytes_written_; 726 int* total_bytes_read_; 727 std::string* data_read_; 728 729 DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback); 730 }; 731 732 TEST_F(FileStreamTest, AsyncWriteRead) { 733 int64 file_size; 734 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 735 EXPECT_TRUE(ok); 736 737 FileStream stream; 738 int flags = base::PLATFORM_FILE_OPEN | 739 base::PLATFORM_FILE_READ | 740 base::PLATFORM_FILE_WRITE | 741 base::PLATFORM_FILE_ASYNC; 742 int rv = stream.Open(temp_file_path(), flags); 743 EXPECT_EQ(OK, rv); 744 745 int64 total_bytes_avail = stream.Available(); 746 EXPECT_EQ(file_size, total_bytes_avail); 747 748 int64 offset = stream.Seek(FROM_END, 0); 749 EXPECT_EQ(offset, file_size); 750 751 int total_bytes_written = 0; 752 int total_bytes_read = 0; 753 std::string data_read; 754 TestWriteReadCompletionCallback callback(&stream, &total_bytes_written, 755 &total_bytes_read, &data_read); 756 757 rv = stream.Write(kTestData + total_bytes_written, 758 kTestDataSize - static_cast<int>(total_bytes_written), 759 &callback); 760 if (rv == ERR_IO_PENDING) 761 rv = callback.WaitForResult(); 762 EXPECT_LT(0, rv); 763 EXPECT_EQ(kTestDataSize, total_bytes_written); 764 765 stream.Close(); 766 767 ok = file_util::GetFileSize(temp_file_path(), &file_size); 768 EXPECT_TRUE(ok); 769 EXPECT_EQ(kTestDataSize * 2, file_size); 770 771 EXPECT_EQ(kTestDataSize * 2, total_bytes_read); 772 const std::string kExpectedFileData = 773 std::string(kTestData) + std::string(kTestData); 774 EXPECT_EQ(kExpectedFileData, data_read); 775 } 776 777 class TestWriteCloseCompletionCallback : public Callback1<int>::Type { 778 public: 779 explicit TestWriteCloseCompletionCallback(FileStream* stream, 780 int* total_bytes_written) 781 : result_(0), 782 have_result_(false), 783 waiting_for_result_(false), 784 stream_(stream), 785 total_bytes_written_(total_bytes_written) {} 786 787 int WaitForResult() { 788 DCHECK(!waiting_for_result_); 789 while (!have_result_) { 790 waiting_for_result_ = true; 791 MessageLoop::current()->Run(); 792 waiting_for_result_ = false; 793 } 794 have_result_ = false; // auto-reset for next callback 795 return result_; 796 } 797 798 private: 799 virtual void RunWithParams(const Tuple1<int>& params) { 800 DCHECK_LT(0, params.a); 801 *total_bytes_written_ += params.a; 802 803 int rv; 804 805 if (*total_bytes_written_ != kTestDataSize) { 806 // Recurse to finish writing all data. 807 int total_bytes_written = 0; 808 TestWriteCloseCompletionCallback callback(stream_, &total_bytes_written); 809 rv = stream_->Write(kTestData + *total_bytes_written_, 810 kTestDataSize - *total_bytes_written_, 811 &callback); 812 DCHECK_EQ(ERR_IO_PENDING, rv); 813 rv = callback.WaitForResult(); 814 *total_bytes_written_ += total_bytes_written; 815 } else { // We're done writing all data. Close the file. 816 stream_->Close(); 817 } 818 819 result_ = *total_bytes_written_; 820 have_result_ = true; 821 if (waiting_for_result_) 822 MessageLoop::current()->Quit(); 823 } 824 825 int result_; 826 bool have_result_; 827 bool waiting_for_result_; 828 FileStream* stream_; 829 int* total_bytes_written_; 830 831 DISALLOW_COPY_AND_ASSIGN(TestWriteCloseCompletionCallback); 832 }; 833 834 TEST_F(FileStreamTest, AsyncWriteClose) { 835 int64 file_size; 836 bool ok = file_util::GetFileSize(temp_file_path(), &file_size); 837 EXPECT_TRUE(ok); 838 839 FileStream stream; 840 int flags = base::PLATFORM_FILE_OPEN | 841 base::PLATFORM_FILE_READ | 842 base::PLATFORM_FILE_WRITE | 843 base::PLATFORM_FILE_ASYNC; 844 int rv = stream.Open(temp_file_path(), flags); 845 EXPECT_EQ(OK, rv); 846 847 int64 total_bytes_avail = stream.Available(); 848 EXPECT_EQ(file_size, total_bytes_avail); 849 850 int64 offset = stream.Seek(FROM_END, 0); 851 EXPECT_EQ(offset, file_size); 852 853 int total_bytes_written = 0; 854 TestWriteCloseCompletionCallback callback(&stream, &total_bytes_written); 855 856 rv = stream.Write(kTestData, kTestDataSize, &callback); 857 if (rv == ERR_IO_PENDING) 858 total_bytes_written = callback.WaitForResult(); 859 EXPECT_LT(0, total_bytes_written); 860 EXPECT_EQ(kTestDataSize, total_bytes_written); 861 862 ok = file_util::GetFileSize(temp_file_path(), &file_size); 863 EXPECT_TRUE(ok); 864 EXPECT_EQ(kTestDataSize * 2, file_size); 865 } 866 867 // Tests truncating a file. 868 TEST_F(FileStreamTest, Truncate) { 869 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE; 870 871 FileStream write_stream; 872 ASSERT_EQ(OK, write_stream.Open(temp_file_path(), flags)); 873 874 // Write some data to the file. 875 const char test_data[] = "0123456789"; 876 write_stream.Write(test_data, arraysize(test_data), NULL); 877 878 // Truncate the file. 879 ASSERT_EQ(4, write_stream.Truncate(4)); 880 881 // Write again. 882 write_stream.Write(test_data, 4, NULL); 883 884 // Close the stream. 885 write_stream.Close(); 886 887 // Read in the contents and make sure we get back what we expected. 888 std::string read_contents; 889 EXPECT_TRUE(file_util::ReadFileToString(temp_file_path(), &read_contents)); 890 891 EXPECT_EQ("01230123", read_contents); 892 } 893 894 } // namespace 895 } // namespace net 896