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