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