1 // Copyright 2015 The Chromium OS 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 <brillo/streams/file_stream.h> 6 7 #include <limits> 8 #include <numeric> 9 #include <string> 10 #include <sys/stat.h> 11 #include <vector> 12 13 #include <base/files/file_util.h> 14 #include <base/files/scoped_temp_dir.h> 15 #include <base/message_loop/message_loop.h> 16 #include <base/rand_util.h> 17 #include <base/run_loop.h> 18 #include <brillo/bind_lambda.h> 19 #include <brillo/errors/error_codes.h> 20 #include <brillo/message_loops/base_message_loop.h> 21 #include <brillo/message_loops/message_loop_utils.h> 22 #include <brillo/streams/stream_errors.h> 23 #include <gmock/gmock.h> 24 #include <gtest/gtest.h> 25 26 using testing::InSequence; 27 using testing::Return; 28 using testing::ReturnArg; 29 using testing::SaveArg; 30 using testing::SetErrnoAndReturn; 31 using testing::_; 32 33 namespace brillo { 34 35 namespace { 36 37 // gmock action that would return a blocking situation from a read() or write(). 38 ACTION(ReturnWouldBlock) { 39 errno = EWOULDBLOCK; 40 return -1; 41 } 42 43 // Helper function to read one byte from the stream. 44 inline int ReadByte(Stream* stream) { 45 uint8_t byte = 0; 46 return stream->ReadAllBlocking(&byte, sizeof(byte), nullptr) ? byte : -1; 47 } 48 49 // Helper function to write one byte from the stream. 50 inline bool WriteByte(Stream* stream, uint8_t byte) { 51 return stream->WriteAllBlocking(&byte, sizeof(byte), nullptr); 52 } 53 54 // Helper function to test file stream workflow on newly created file. 55 void TestCreateFile(Stream* stream) { 56 ASSERT_TRUE(stream->IsOpen()); 57 58 // Set up a sample data buffer. 59 std::vector<uint8_t> in_buffer(256); 60 std::iota(in_buffer.begin(), in_buffer.end(), 0); 61 62 // Initial assumptions about empty file stream. 63 EXPECT_TRUE(stream->CanRead()); 64 EXPECT_TRUE(stream->CanWrite()); 65 EXPECT_TRUE(stream->CanSeek()); 66 EXPECT_TRUE(stream->CanGetSize()); 67 EXPECT_EQ(0, stream->GetPosition()); 68 EXPECT_EQ(0, stream->GetSize()); 69 70 // Write sample data. 71 EXPECT_TRUE(stream->WriteAllBlocking(in_buffer.data(), in_buffer.size(), 72 nullptr)); 73 EXPECT_EQ(in_buffer.size(), stream->GetPosition()); 74 EXPECT_EQ(in_buffer.size(), stream->GetSize()); 75 76 // Rewind the stream to the beginning. 77 uint64_t pos = 0; 78 EXPECT_TRUE(stream->Seek(0, Stream::Whence::FROM_BEGIN, &pos, nullptr)); 79 EXPECT_EQ(0, pos); 80 EXPECT_EQ(0, stream->GetPosition()); 81 EXPECT_EQ(in_buffer.size(), stream->GetSize()); 82 83 // Read the file contents back. 84 std::vector<uint8_t> out_buffer(256); 85 EXPECT_TRUE(stream->ReadAllBlocking(out_buffer.data(), out_buffer.size(), 86 nullptr)); 87 EXPECT_EQ(out_buffer.size(), stream->GetPosition()); 88 EXPECT_EQ(out_buffer.size(), stream->GetSize()); 89 90 // Make sure the data read matches those written. 91 EXPECT_EQ(in_buffer, out_buffer); 92 93 // Random read/write 94 EXPECT_TRUE(stream->Seek(10, Stream::Whence::FROM_BEGIN, &pos, nullptr)); 95 EXPECT_EQ(10, pos); 96 97 // Since our data buffer contained values from 0 to 255, the byte at position 98 // 10 will contain the value of 10. 99 EXPECT_EQ(10, ReadByte(stream)); 100 EXPECT_EQ(11, ReadByte(stream)); 101 EXPECT_EQ(12, ReadByte(stream)); 102 EXPECT_TRUE(stream->Seek(7, Stream::Whence::FROM_CURRENT, nullptr, nullptr)); 103 EXPECT_EQ(20, ReadByte(stream)); 104 105 EXPECT_EQ(21, stream->GetPosition()); 106 EXPECT_TRUE(stream->Seek(-2, Stream::Whence::FROM_CURRENT, &pos, nullptr)); 107 EXPECT_EQ(19, pos); 108 EXPECT_TRUE(WriteByte(stream, 100)); 109 EXPECT_EQ(20, ReadByte(stream)); 110 EXPECT_TRUE(stream->Seek(-2, Stream::Whence::FROM_CURRENT, nullptr, nullptr)); 111 EXPECT_EQ(100, ReadByte(stream)); 112 EXPECT_EQ(20, ReadByte(stream)); 113 EXPECT_TRUE(stream->Seek(-1, Stream::Whence::FROM_END, &pos, nullptr)); 114 EXPECT_EQ(255, pos); 115 EXPECT_EQ(255, ReadByte(stream)); 116 EXPECT_EQ(-1, ReadByte(stream)); 117 } 118 119 } // anonymous namespace 120 121 // A mock file descriptor wrapper to test low-level file API used by FileStream. 122 class MockFileDescriptor : public FileStream::FileDescriptorInterface { 123 public: 124 MOCK_CONST_METHOD0(IsOpen, bool()); 125 MOCK_METHOD2(Read, ssize_t(void*, size_t)); 126 MOCK_METHOD2(Write, ssize_t(const void*, size_t)); 127 MOCK_METHOD2(Seek, off64_t(off64_t, int)); 128 MOCK_CONST_METHOD0(GetFileMode, mode_t()); 129 MOCK_CONST_METHOD0(GetSize, uint64_t()); 130 MOCK_CONST_METHOD1(Truncate, int(off64_t)); 131 MOCK_METHOD0(Flush, int()); 132 MOCK_METHOD0(Close, int()); 133 MOCK_METHOD3(WaitForData, 134 bool(Stream::AccessMode, const DataCallback&, ErrorPtr*)); 135 MOCK_METHOD3(WaitForDataBlocking, 136 int(Stream::AccessMode, base::TimeDelta, Stream::AccessMode*)); 137 MOCK_METHOD0(CancelPendingAsyncOperations, void()); 138 }; 139 140 class FileStreamTest : public testing::Test { 141 public: 142 void SetUp() override { 143 CreateStream(S_IFREG, Stream::AccessMode::READ_WRITE); 144 } 145 146 MockFileDescriptor& fd_mock() { 147 return *static_cast<MockFileDescriptor*>(stream_->fd_interface_.get()); 148 } 149 150 void CreateStream(mode_t file_mode, Stream::AccessMode access_mode) { 151 std::unique_ptr<MockFileDescriptor> fd{new MockFileDescriptor{}}; 152 EXPECT_CALL(*fd, GetFileMode()).WillOnce(Return(file_mode)); 153 stream_.reset(new FileStream(std::move(fd), access_mode)); 154 EXPECT_CALL(fd_mock(), IsOpen()).WillRepeatedly(Return(true)); 155 } 156 157 void ExpectStreamClosed(const ErrorPtr& error) const { 158 EXPECT_EQ(errors::stream::kDomain, error->GetDomain()); 159 EXPECT_EQ(errors::stream::kStreamClosed, error->GetCode()); 160 EXPECT_EQ("Stream is closed", error->GetMessage()); 161 } 162 163 void ExpectStreamOffsetTooLarge(const ErrorPtr& error) const { 164 EXPECT_EQ(errors::stream::kDomain, error->GetDomain()); 165 EXPECT_EQ(errors::stream::kInvalidParameter, error->GetCode()); 166 EXPECT_EQ("The stream offset value is out of range", error->GetMessage()); 167 } 168 169 inline static char* IntToPtr(int addr) { 170 return reinterpret_cast<char*>(addr); 171 } 172 173 inline static const char* IntToConstPtr(int addr) { 174 return reinterpret_cast<const char*>(addr); 175 } 176 177 bool CallWaitForData(Stream::AccessMode mode, ErrorPtr* error) { 178 return stream_->WaitForData(mode, {}, error); 179 } 180 181 std::unique_ptr<FileStream> stream_; 182 183 const uint64_t kMaxSize = std::numeric_limits<int64_t>::max(); 184 const uint64_t kTooLargeSize = std::numeric_limits<uint64_t>::max(); 185 186 // Dummy buffer pointer values to make sure that input pointer values 187 // are delegated to the file interface without a change. 188 char* const test_read_buffer_ = IntToPtr(12345); 189 const char* const test_write_buffer_ = IntToConstPtr(67890); 190 }; 191 192 TEST_F(FileStreamTest, IsOpen) { 193 EXPECT_TRUE(stream_->IsOpen()); 194 EXPECT_CALL(fd_mock(), IsOpen()).WillOnce(Return(false)); 195 EXPECT_FALSE(stream_->IsOpen()); 196 } 197 198 TEST_F(FileStreamTest, CanRead) { 199 CreateStream(S_IFREG, Stream::AccessMode::READ_WRITE); 200 EXPECT_TRUE(stream_->CanRead()); 201 EXPECT_CALL(fd_mock(), IsOpen()).WillRepeatedly(Return(false)); 202 EXPECT_FALSE(stream_->CanRead()); 203 CreateStream(S_IFREG, Stream::AccessMode::READ); 204 EXPECT_TRUE(stream_->CanRead()); 205 CreateStream(S_IFREG, Stream::AccessMode::WRITE); 206 EXPECT_FALSE(stream_->CanRead()); 207 } 208 209 TEST_F(FileStreamTest, CanWrite) { 210 CreateStream(S_IFREG, Stream::AccessMode::READ_WRITE); 211 EXPECT_TRUE(stream_->CanWrite()); 212 EXPECT_CALL(fd_mock(), IsOpen()).WillRepeatedly(Return(false)); 213 EXPECT_FALSE(stream_->CanWrite()); 214 CreateStream(S_IFREG, Stream::AccessMode::READ); 215 EXPECT_FALSE(stream_->CanWrite()); 216 CreateStream(S_IFREG, Stream::AccessMode::WRITE); 217 EXPECT_TRUE(stream_->CanWrite()); 218 } 219 220 TEST_F(FileStreamTest, CanSeek) { 221 CreateStream(S_IFBLK, Stream::AccessMode::READ_WRITE); 222 EXPECT_TRUE(stream_->CanSeek()); 223 CreateStream(S_IFDIR, Stream::AccessMode::READ_WRITE); 224 EXPECT_TRUE(stream_->CanSeek()); 225 CreateStream(S_IFREG, Stream::AccessMode::READ_WRITE); 226 EXPECT_TRUE(stream_->CanSeek()); 227 CreateStream(S_IFLNK, Stream::AccessMode::READ_WRITE); 228 EXPECT_TRUE(stream_->CanSeek()); 229 CreateStream(S_IFCHR, Stream::AccessMode::READ_WRITE); 230 EXPECT_FALSE(stream_->CanSeek()); 231 CreateStream(S_IFSOCK, Stream::AccessMode::READ_WRITE); 232 EXPECT_FALSE(stream_->CanSeek()); 233 CreateStream(S_IFIFO, Stream::AccessMode::READ_WRITE); 234 EXPECT_FALSE(stream_->CanSeek()); 235 236 CreateStream(S_IFREG, Stream::AccessMode::READ); 237 EXPECT_TRUE(stream_->CanSeek()); 238 CreateStream(S_IFREG, Stream::AccessMode::WRITE); 239 EXPECT_TRUE(stream_->CanSeek()); 240 } 241 242 TEST_F(FileStreamTest, CanGetSize) { 243 CreateStream(S_IFBLK, Stream::AccessMode::READ_WRITE); 244 EXPECT_TRUE(stream_->CanGetSize()); 245 CreateStream(S_IFDIR, Stream::AccessMode::READ_WRITE); 246 EXPECT_TRUE(stream_->CanGetSize()); 247 CreateStream(S_IFREG, Stream::AccessMode::READ_WRITE); 248 EXPECT_TRUE(stream_->CanGetSize()); 249 CreateStream(S_IFLNK, Stream::AccessMode::READ_WRITE); 250 EXPECT_TRUE(stream_->CanGetSize()); 251 CreateStream(S_IFCHR, Stream::AccessMode::READ_WRITE); 252 EXPECT_FALSE(stream_->CanGetSize()); 253 CreateStream(S_IFSOCK, Stream::AccessMode::READ_WRITE); 254 EXPECT_FALSE(stream_->CanGetSize()); 255 CreateStream(S_IFIFO, Stream::AccessMode::READ_WRITE); 256 EXPECT_FALSE(stream_->CanGetSize()); 257 258 CreateStream(S_IFREG, Stream::AccessMode::READ); 259 EXPECT_TRUE(stream_->CanGetSize()); 260 CreateStream(S_IFREG, Stream::AccessMode::WRITE); 261 EXPECT_TRUE(stream_->CanGetSize()); 262 } 263 264 TEST_F(FileStreamTest, GetSize) { 265 EXPECT_CALL(fd_mock(), GetSize()).WillRepeatedly(Return(12345)); 266 EXPECT_EQ(12345u, stream_->GetSize()); 267 EXPECT_CALL(fd_mock(), IsOpen()).WillOnce(Return(false)); 268 EXPECT_EQ(0u, stream_->GetSize()); 269 } 270 271 TEST_F(FileStreamTest, SetSizeBlocking) { 272 EXPECT_CALL(fd_mock(), Truncate(0)).WillOnce(Return(0)); 273 EXPECT_TRUE(stream_->SetSizeBlocking(0, nullptr)); 274 275 EXPECT_CALL(fd_mock(), Truncate(123)).WillOnce(Return(0)); 276 EXPECT_TRUE(stream_->SetSizeBlocking(123, nullptr)); 277 278 EXPECT_CALL(fd_mock(), Truncate(kMaxSize)).WillOnce(Return(0)); 279 EXPECT_TRUE(stream_->SetSizeBlocking(kMaxSize, nullptr)); 280 } 281 282 TEST_F(FileStreamTest, SetSizeBlocking_Fail) { 283 brillo::ErrorPtr error; 284 285 EXPECT_CALL(fd_mock(), Truncate(1235)).WillOnce(SetErrnoAndReturn(EIO, -1)); 286 EXPECT_FALSE(stream_->SetSizeBlocking(1235, &error)); 287 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 288 EXPECT_EQ("EIO", error->GetCode()); 289 290 error.reset(); 291 EXPECT_FALSE(stream_->SetSizeBlocking(kTooLargeSize, &error)); 292 ExpectStreamOffsetTooLarge(error); 293 294 error.reset(); 295 EXPECT_CALL(fd_mock(), IsOpen()).WillOnce(Return(false)); 296 EXPECT_FALSE(stream_->SetSizeBlocking(1235, &error)); 297 ExpectStreamClosed(error); 298 } 299 300 TEST_F(FileStreamTest, GetRemainingSize) { 301 EXPECT_CALL(fd_mock(), Seek(0, SEEK_CUR)).WillOnce(Return(234)); 302 EXPECT_CALL(fd_mock(), GetSize()).WillOnce(Return(1234)); 303 EXPECT_EQ(1000u, stream_->GetRemainingSize()); 304 305 EXPECT_CALL(fd_mock(), Seek(0, SEEK_CUR)).WillOnce(Return(1234)); 306 EXPECT_CALL(fd_mock(), GetSize()).WillOnce(Return(1000)); 307 EXPECT_EQ(0u, stream_->GetRemainingSize()); 308 } 309 310 TEST_F(FileStreamTest, Seek_Set) { 311 uint64_t pos = 0; 312 313 EXPECT_CALL(fd_mock(), Seek(0, SEEK_SET)).WillOnce(Return(0)); 314 EXPECT_TRUE(stream_->Seek(0, Stream::Whence::FROM_BEGIN, &pos, nullptr)); 315 EXPECT_EQ(0u, pos); 316 317 EXPECT_CALL(fd_mock(), Seek(123456, SEEK_SET)).WillOnce(Return(123456)); 318 EXPECT_TRUE(stream_->Seek(123456, Stream::Whence::FROM_BEGIN, &pos, nullptr)); 319 EXPECT_EQ(123456u, pos); 320 321 EXPECT_CALL(fd_mock(), Seek(kMaxSize, SEEK_SET)) 322 .WillRepeatedly(Return(kMaxSize)); 323 EXPECT_TRUE(stream_->Seek(kMaxSize, Stream::Whence::FROM_BEGIN, &pos, 324 nullptr)); 325 EXPECT_EQ(kMaxSize, pos); 326 EXPECT_TRUE(stream_->Seek(kMaxSize, Stream::Whence::FROM_BEGIN, nullptr, 327 nullptr)); 328 } 329 330 TEST_F(FileStreamTest, Seek_Cur) { 331 uint64_t pos = 0; 332 333 EXPECT_CALL(fd_mock(), Seek(0, SEEK_CUR)).WillOnce(Return(100)); 334 EXPECT_TRUE(stream_->Seek(0, Stream::Whence::FROM_CURRENT, &pos, nullptr)); 335 EXPECT_EQ(100u, pos); 336 337 EXPECT_CALL(fd_mock(), Seek(234, SEEK_CUR)).WillOnce(Return(1234)); 338 EXPECT_TRUE(stream_->Seek(234, Stream::Whence::FROM_CURRENT, &pos, nullptr)); 339 EXPECT_EQ(1234u, pos); 340 341 EXPECT_CALL(fd_mock(), Seek(-100, SEEK_CUR)).WillOnce(Return(900)); 342 EXPECT_TRUE(stream_->Seek(-100, Stream::Whence::FROM_CURRENT, &pos, nullptr)); 343 EXPECT_EQ(900u, pos); 344 } 345 346 TEST_F(FileStreamTest, Seek_End) { 347 uint64_t pos = 0; 348 349 EXPECT_CALL(fd_mock(), Seek(0, SEEK_END)).WillOnce(Return(1000)); 350 EXPECT_TRUE(stream_->Seek(0, Stream::Whence::FROM_END, &pos, nullptr)); 351 EXPECT_EQ(1000u, pos); 352 353 EXPECT_CALL(fd_mock(), Seek(234, SEEK_END)).WillOnce(Return(10234)); 354 EXPECT_TRUE(stream_->Seek(234, Stream::Whence::FROM_END, &pos, nullptr)); 355 EXPECT_EQ(10234u, pos); 356 357 EXPECT_CALL(fd_mock(), Seek(-100, SEEK_END)).WillOnce(Return(9900)); 358 EXPECT_TRUE(stream_->Seek(-100, Stream::Whence::FROM_END, &pos, nullptr)); 359 EXPECT_EQ(9900u, pos); 360 } 361 362 TEST_F(FileStreamTest, Seek_Fail) { 363 brillo::ErrorPtr error; 364 EXPECT_CALL(fd_mock(), Seek(0, SEEK_SET)) 365 .WillOnce(SetErrnoAndReturn(EPIPE, -1)); 366 EXPECT_FALSE(stream_->Seek(0, Stream::Whence::FROM_BEGIN, nullptr, &error)); 367 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 368 EXPECT_EQ("EPIPE", error->GetCode()); 369 } 370 371 TEST_F(FileStreamTest, ReadAsync) { 372 size_t read_size = 0; 373 bool failed = false; 374 auto success_callback = [](size_t* read_size, size_t size) { 375 *read_size = size; 376 }; 377 auto error_callback = [](bool* failed, const Error* /* error */) { 378 *failed = true; 379 }; 380 FileStream::FileDescriptorInterface::DataCallback data_callback; 381 382 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 100)) 383 .WillOnce(ReturnWouldBlock()); 384 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::READ, _, _)) 385 .WillOnce(DoAll(SaveArg<1>(&data_callback), Return(true))); 386 EXPECT_TRUE(stream_->ReadAsync( 387 test_read_buffer_, 388 100, 389 base::Bind(success_callback, base::Unretained(&read_size)), 390 base::Bind(error_callback, base::Unretained(&failed)), 391 nullptr)); 392 EXPECT_EQ(0u, read_size); 393 EXPECT_FALSE(failed); 394 395 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 100)).WillOnce(Return(83)); 396 data_callback.Run(Stream::AccessMode::READ); 397 EXPECT_EQ(83u, read_size); 398 EXPECT_FALSE(failed); 399 } 400 401 TEST_F(FileStreamTest, ReadNonBlocking) { 402 size_t size = 0; 403 bool eos = false; 404 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, _)) 405 .WillRepeatedly(ReturnArg<1>()); 406 EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 100, &size, &eos, 407 nullptr)); 408 EXPECT_EQ(100u, size); 409 EXPECT_FALSE(eos); 410 411 EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 0, &size, &eos, 412 nullptr)); 413 EXPECT_EQ(0u, size); 414 EXPECT_FALSE(eos); 415 416 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, _)).WillOnce(Return(0)); 417 EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 100, &size, &eos, 418 nullptr)); 419 EXPECT_EQ(0u, size); 420 EXPECT_TRUE(eos); 421 422 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, _)) 423 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 424 EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 100, &size, &eos, 425 nullptr)); 426 EXPECT_EQ(0u, size); 427 EXPECT_FALSE(eos); 428 } 429 430 TEST_F(FileStreamTest, ReadNonBlocking_Fail) { 431 size_t size = 0; 432 brillo::ErrorPtr error; 433 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, _)) 434 .WillOnce(SetErrnoAndReturn(EACCES, -1)); 435 EXPECT_FALSE(stream_->ReadNonBlocking(test_read_buffer_, 100, &size, nullptr, 436 &error)); 437 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 438 EXPECT_EQ("EACCES", error->GetCode()); 439 } 440 441 TEST_F(FileStreamTest, ReadBlocking) { 442 size_t size = 0; 443 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 100)).WillOnce(Return(20)); 444 EXPECT_TRUE(stream_->ReadBlocking(test_read_buffer_, 100, &size, nullptr)); 445 EXPECT_EQ(20u, size); 446 447 { 448 InSequence seq; 449 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 80)) 450 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 451 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::READ, _, _)) 452 .WillOnce(Return(1)); 453 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 80)).WillOnce(Return(45)); 454 } 455 EXPECT_TRUE(stream_->ReadBlocking(test_read_buffer_, 80, &size, nullptr)); 456 EXPECT_EQ(45u, size); 457 458 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 50)).WillOnce(Return(0)); 459 EXPECT_TRUE(stream_->ReadBlocking(test_read_buffer_, 50, &size, nullptr)); 460 EXPECT_EQ(0u, size); 461 } 462 463 TEST_F(FileStreamTest, ReadBlocking_Fail) { 464 { 465 InSequence seq; 466 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 80)) 467 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 468 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::READ, _, _)) 469 .WillOnce(SetErrnoAndReturn(EBADF, -1)); 470 } 471 brillo::ErrorPtr error; 472 size_t size = 0; 473 EXPECT_FALSE(stream_->ReadBlocking(test_read_buffer_, 80, &size, &error)); 474 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 475 EXPECT_EQ("EBADF", error->GetCode()); 476 } 477 478 TEST_F(FileStreamTest, ReadAllBlocking) { 479 { 480 InSequence seq; 481 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 100)).WillOnce(Return(20)); 482 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 20, 80)) 483 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 484 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::READ, _, _)) 485 .WillOnce(Return(1)); 486 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 20, 80)) 487 .WillOnce(Return(45)); 488 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 65, 35)) 489 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 490 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::READ, _, _)) 491 .WillOnce(Return(1)); 492 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 65, 35)) 493 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 494 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::READ, _, _)) 495 .WillOnce(Return(1)); 496 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 65, 35)) 497 .WillOnce(Return(35)); 498 } 499 EXPECT_TRUE(stream_->ReadAllBlocking(test_read_buffer_, 100, nullptr)); 500 } 501 502 TEST_F(FileStreamTest, ReadAllBlocking_Fail) { 503 { 504 InSequence seq; 505 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 100)).WillOnce(Return(20)); 506 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 20, 80)) 507 .WillOnce(Return(0)); 508 } 509 brillo::ErrorPtr error; 510 EXPECT_FALSE(stream_->ReadAllBlocking(test_read_buffer_, 100, &error)); 511 EXPECT_EQ(errors::stream::kDomain, error->GetDomain()); 512 EXPECT_EQ(errors::stream::kPartialData, error->GetCode()); 513 EXPECT_EQ("Reading past the end of stream", error->GetMessage()); 514 } 515 516 TEST_F(FileStreamTest, WriteAsync) { 517 size_t write_size = 0; 518 bool failed = false; 519 auto success_callback = [](size_t* write_size, size_t size) { 520 *write_size = size; 521 }; 522 auto error_callback = [](bool* failed, const Error* /* error */) { 523 *failed = true; 524 }; 525 FileStream::FileDescriptorInterface::DataCallback data_callback; 526 527 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 100)) 528 .WillOnce(ReturnWouldBlock()); 529 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::WRITE, _, _)) 530 .WillOnce(DoAll(SaveArg<1>(&data_callback), Return(true))); 531 EXPECT_TRUE(stream_->WriteAsync( 532 test_write_buffer_, 533 100, 534 base::Bind(success_callback, base::Unretained(&write_size)), 535 base::Bind(error_callback, base::Unretained(&failed)), 536 nullptr)); 537 EXPECT_EQ(0u, write_size); 538 EXPECT_FALSE(failed); 539 540 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 100)).WillOnce(Return(87)); 541 data_callback.Run(Stream::AccessMode::WRITE); 542 EXPECT_EQ(87u, write_size); 543 EXPECT_FALSE(failed); 544 } 545 546 TEST_F(FileStreamTest, WriteNonBlocking) { 547 size_t size = 0; 548 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, _)) 549 .WillRepeatedly(ReturnArg<1>()); 550 EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 100, &size, 551 nullptr)); 552 EXPECT_EQ(100u, size); 553 554 EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 0, &size, nullptr)); 555 EXPECT_EQ(0u, size); 556 557 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, _)).WillOnce(Return(0)); 558 EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 100, &size, 559 nullptr)); 560 EXPECT_EQ(0u, size); 561 562 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, _)) 563 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 564 EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 100, &size, 565 nullptr)); 566 EXPECT_EQ(0u, size); 567 } 568 569 TEST_F(FileStreamTest, WriteNonBlocking_Fail) { 570 size_t size = 0; 571 brillo::ErrorPtr error; 572 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, _)) 573 .WillOnce(SetErrnoAndReturn(EACCES, -1)); 574 EXPECT_FALSE(stream_->WriteNonBlocking(test_write_buffer_, 100, &size, 575 &error)); 576 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 577 EXPECT_EQ("EACCES", error->GetCode()); 578 } 579 580 TEST_F(FileStreamTest, WriteBlocking) { 581 size_t size = 0; 582 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 100)).WillOnce(Return(20)); 583 EXPECT_TRUE(stream_->WriteBlocking(test_write_buffer_, 100, &size, nullptr)); 584 EXPECT_EQ(20u, size); 585 586 { 587 InSequence seq; 588 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 80)) 589 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 590 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _)) 591 .WillOnce(Return(1)); 592 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 80)).WillOnce(Return(45)); 593 } 594 EXPECT_TRUE(stream_->WriteBlocking(test_write_buffer_, 80, &size, nullptr)); 595 EXPECT_EQ(45u, size); 596 597 { 598 InSequence seq; 599 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 50)).WillOnce(Return(0)); 600 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _)) 601 .WillOnce(Return(1)); 602 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 50)).WillOnce(Return(1)); 603 } 604 EXPECT_TRUE(stream_->WriteBlocking(test_write_buffer_, 50, &size, nullptr)); 605 EXPECT_EQ(1u, size); 606 } 607 608 TEST_F(FileStreamTest, WriteBlocking_Fail) { 609 { 610 InSequence seq; 611 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 80)) 612 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 613 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _)) 614 .WillOnce(SetErrnoAndReturn(EBADF, -1)); 615 } 616 brillo::ErrorPtr error; 617 size_t size = 0; 618 EXPECT_FALSE(stream_->WriteBlocking(test_write_buffer_, 80, &size, &error)); 619 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 620 EXPECT_EQ("EBADF", error->GetCode()); 621 } 622 623 TEST_F(FileStreamTest, WriteAllBlocking) { 624 { 625 InSequence seq; 626 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 100)).WillOnce(Return(20)); 627 EXPECT_CALL(fd_mock(), Write(test_write_buffer_ + 20, 80)) 628 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 629 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _)) 630 .WillOnce(Return(1)); 631 EXPECT_CALL(fd_mock(), Write(test_write_buffer_ + 20, 80)) 632 .WillOnce(Return(45)); 633 EXPECT_CALL(fd_mock(), Write(test_write_buffer_ + 65, 35)) 634 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 635 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _)) 636 .WillOnce(Return(1)); 637 EXPECT_CALL(fd_mock(), Write(test_write_buffer_ + 65, 35)) 638 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 639 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _)) 640 .WillOnce(Return(1)); 641 EXPECT_CALL(fd_mock(), Write(test_write_buffer_ + 65, 35)) 642 .WillOnce(Return(35)); 643 } 644 EXPECT_TRUE(stream_->WriteAllBlocking(test_write_buffer_, 100, nullptr)); 645 } 646 647 TEST_F(FileStreamTest, WriteAllBlocking_Fail) { 648 { 649 InSequence seq; 650 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 80)) 651 .WillOnce(SetErrnoAndReturn(EAGAIN, -1)); 652 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _)) 653 .WillOnce(SetErrnoAndReturn(EBADF, -1)); 654 } 655 brillo::ErrorPtr error; 656 EXPECT_FALSE(stream_->WriteAllBlocking(test_write_buffer_, 80, &error)); 657 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 658 EXPECT_EQ("EBADF", error->GetCode()); 659 } 660 661 TEST_F(FileStreamTest, WaitForDataBlocking_Timeout) { 662 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _)) 663 .WillOnce(Return(0)); 664 brillo::ErrorPtr error; 665 EXPECT_FALSE(stream_->WaitForDataBlocking(Stream::AccessMode::WRITE, {}, 666 nullptr, &error)); 667 EXPECT_EQ(errors::stream::kDomain, error->GetDomain()); 668 EXPECT_EQ(errors::stream::kTimeout, error->GetCode()); 669 } 670 671 TEST_F(FileStreamTest, FlushBlocking) { 672 EXPECT_TRUE(stream_->FlushBlocking(nullptr)); 673 } 674 675 TEST_F(FileStreamTest, CloseBlocking) { 676 EXPECT_CALL(fd_mock(), Close()).WillOnce(Return(0)); 677 EXPECT_TRUE(stream_->CloseBlocking(nullptr)); 678 679 EXPECT_CALL(fd_mock(), IsOpen()).WillOnce(Return(false)); 680 EXPECT_TRUE(stream_->CloseBlocking(nullptr)); 681 } 682 683 TEST_F(FileStreamTest, CloseBlocking_Fail) { 684 brillo::ErrorPtr error; 685 EXPECT_CALL(fd_mock(), Close()).WillOnce(SetErrnoAndReturn(EFBIG, -1)); 686 EXPECT_FALSE(stream_->CloseBlocking(&error)); 687 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 688 EXPECT_EQ("EFBIG", error->GetCode()); 689 } 690 691 TEST_F(FileStreamTest, WaitForData) { 692 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::READ, _, _)) 693 .WillOnce(Return(true)); 694 EXPECT_TRUE(CallWaitForData(Stream::AccessMode::READ, nullptr)); 695 696 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::WRITE, _, _)) 697 .WillOnce(Return(true)); 698 EXPECT_TRUE(CallWaitForData(Stream::AccessMode::WRITE, nullptr)); 699 700 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::READ_WRITE, _, _)) 701 .WillOnce(Return(true)); 702 EXPECT_TRUE(CallWaitForData(Stream::AccessMode::READ_WRITE, nullptr)); 703 704 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::READ_WRITE, _, _)) 705 .WillOnce(Return(false)); 706 EXPECT_FALSE(CallWaitForData(Stream::AccessMode::READ_WRITE, nullptr)); 707 } 708 709 TEST_F(FileStreamTest, CreateTemporary) { 710 StreamPtr stream = FileStream::CreateTemporary(nullptr); 711 ASSERT_NE(nullptr, stream.get()); 712 TestCreateFile(stream.get()); 713 } 714 715 TEST_F(FileStreamTest, OpenRead) { 716 base::ScopedTempDir temp_dir; 717 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 718 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"}); 719 std::vector<char> buffer(1024 * 1024); 720 base::RandBytes(buffer.data(), buffer.size()); 721 int file_size = buffer.size(); // Stupid base::WriteFile taking "int" size. 722 ASSERT_EQ(file_size, base::WriteFile(path, buffer.data(), file_size)); 723 724 StreamPtr stream = FileStream::Open(path, 725 Stream::AccessMode::READ, 726 FileStream::Disposition::OPEN_EXISTING, 727 nullptr); 728 ASSERT_NE(nullptr, stream.get()); 729 ASSERT_TRUE(stream->IsOpen()); 730 EXPECT_TRUE(stream->CanRead()); 731 EXPECT_FALSE(stream->CanWrite()); 732 EXPECT_TRUE(stream->CanSeek()); 733 EXPECT_TRUE(stream->CanGetSize()); 734 EXPECT_EQ(0u, stream->GetPosition()); 735 EXPECT_EQ(buffer.size(), stream->GetSize()); 736 737 std::vector<char> buffer2(buffer.size()); 738 EXPECT_TRUE(stream->ReadAllBlocking(buffer2.data(), buffer2.size(), nullptr)); 739 EXPECT_EQ(buffer2, buffer); 740 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 741 } 742 743 TEST_F(FileStreamTest, OpenWrite) { 744 base::ScopedTempDir temp_dir; 745 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 746 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"}); 747 std::vector<char> buffer(1024 * 1024); 748 base::RandBytes(buffer.data(), buffer.size()); 749 750 StreamPtr stream = FileStream::Open(path, 751 Stream::AccessMode::WRITE, 752 FileStream::Disposition::CREATE_ALWAYS, 753 nullptr); 754 ASSERT_NE(nullptr, stream.get()); 755 ASSERT_TRUE(stream->IsOpen()); 756 EXPECT_FALSE(stream->CanRead()); 757 EXPECT_TRUE(stream->CanWrite()); 758 EXPECT_TRUE(stream->CanSeek()); 759 EXPECT_TRUE(stream->CanGetSize()); 760 EXPECT_EQ(0u, stream->GetPosition()); 761 EXPECT_EQ(0u, stream->GetSize()); 762 763 EXPECT_TRUE(stream->WriteAllBlocking(buffer.data(), buffer.size(), nullptr)); 764 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 765 766 std::vector<char> buffer2(buffer.size()); 767 int file_size = buffer2.size(); // Stupid base::ReadFile taking "int" size. 768 ASSERT_EQ(file_size, base::ReadFile(path, buffer2.data(), file_size)); 769 EXPECT_EQ(buffer2, buffer); 770 } 771 772 TEST_F(FileStreamTest, Open_OpenExisting) { 773 base::ScopedTempDir temp_dir; 774 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 775 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"}); 776 std::string data{"Lorem ipsum dolor sit amet ..."}; 777 int data_size = data.size(); // I hate ints for data size... 778 ASSERT_EQ(data_size, base::WriteFile(path, data.data(), data_size)); 779 780 StreamPtr stream = FileStream::Open(path, 781 Stream::AccessMode::READ_WRITE, 782 FileStream::Disposition::OPEN_EXISTING, 783 nullptr); 784 ASSERT_NE(nullptr, stream.get()); 785 EXPECT_TRUE(stream->CanRead()); 786 EXPECT_TRUE(stream->CanWrite()); 787 EXPECT_TRUE(stream->CanSeek()); 788 EXPECT_TRUE(stream->CanGetSize()); 789 EXPECT_EQ(0u, stream->GetPosition()); 790 EXPECT_EQ(data.size(), stream->GetSize()); 791 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 792 } 793 794 TEST_F(FileStreamTest, Open_OpenExisting_Fail) { 795 base::ScopedTempDir temp_dir; 796 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 797 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"}); 798 799 ErrorPtr error; 800 StreamPtr stream = FileStream::Open(path, 801 Stream::AccessMode::READ_WRITE, 802 FileStream::Disposition::OPEN_EXISTING, 803 &error); 804 ASSERT_EQ(nullptr, stream.get()); 805 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 806 EXPECT_EQ("ENOENT", error->GetCode()); 807 } 808 809 TEST_F(FileStreamTest, Open_CreateAlways_New) { 810 base::ScopedTempDir temp_dir; 811 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 812 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"}); 813 814 StreamPtr stream = FileStream::Open(path, 815 Stream::AccessMode::READ_WRITE, 816 FileStream::Disposition::CREATE_ALWAYS, 817 nullptr); 818 ASSERT_NE(nullptr, stream.get()); 819 EXPECT_TRUE(stream->CanRead()); 820 EXPECT_TRUE(stream->CanWrite()); 821 EXPECT_TRUE(stream->CanSeek()); 822 EXPECT_TRUE(stream->CanGetSize()); 823 EXPECT_EQ(0u, stream->GetPosition()); 824 EXPECT_EQ(0u, stream->GetSize()); 825 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 826 } 827 828 TEST_F(FileStreamTest, Open_CreateAlways_Existing) { 829 base::ScopedTempDir temp_dir; 830 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 831 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"}); 832 std::string data{"Lorem ipsum dolor sit amet ..."}; 833 int data_size = data.size(); // I hate ints for data size... 834 ASSERT_EQ(data_size, base::WriteFile(path, data.data(), data_size)); 835 836 StreamPtr stream = FileStream::Open(path, 837 Stream::AccessMode::READ_WRITE, 838 FileStream::Disposition::CREATE_ALWAYS, 839 nullptr); 840 ASSERT_NE(nullptr, stream.get()); 841 EXPECT_TRUE(stream->CanRead()); 842 EXPECT_TRUE(stream->CanWrite()); 843 EXPECT_TRUE(stream->CanSeek()); 844 EXPECT_TRUE(stream->CanGetSize()); 845 EXPECT_EQ(0u, stream->GetPosition()); 846 EXPECT_EQ(0u, stream->GetSize()); 847 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 848 } 849 850 TEST_F(FileStreamTest, Open_CreateNewOnly_New) { 851 base::ScopedTempDir temp_dir; 852 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 853 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"}); 854 855 StreamPtr stream = FileStream::Open(path, 856 Stream::AccessMode::READ_WRITE, 857 FileStream::Disposition::CREATE_NEW_ONLY, 858 nullptr); 859 ASSERT_NE(nullptr, stream.get()); 860 EXPECT_TRUE(stream->CanRead()); 861 EXPECT_TRUE(stream->CanWrite()); 862 EXPECT_TRUE(stream->CanSeek()); 863 EXPECT_TRUE(stream->CanGetSize()); 864 EXPECT_EQ(0u, stream->GetPosition()); 865 EXPECT_EQ(0u, stream->GetSize()); 866 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 867 } 868 869 TEST_F(FileStreamTest, Open_CreateNewOnly_Existing) { 870 base::ScopedTempDir temp_dir; 871 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 872 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"}); 873 std::string data{"Lorem ipsum dolor sit amet ..."}; 874 int data_size = data.size(); // I hate ints for data size... 875 ASSERT_EQ(data_size, base::WriteFile(path, data.data(), data_size)); 876 877 ErrorPtr error; 878 StreamPtr stream = FileStream::Open(path, 879 Stream::AccessMode::READ_WRITE, 880 FileStream::Disposition::CREATE_NEW_ONLY, 881 &error); 882 ASSERT_EQ(nullptr, stream.get()); 883 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 884 EXPECT_EQ("EEXIST", error->GetCode()); 885 } 886 887 TEST_F(FileStreamTest, Open_TruncateExisting_New) { 888 base::ScopedTempDir temp_dir; 889 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 890 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"}); 891 892 ErrorPtr error; 893 StreamPtr stream = FileStream::Open( 894 path, 895 Stream::AccessMode::READ_WRITE, 896 FileStream::Disposition::TRUNCATE_EXISTING, 897 &error); 898 ASSERT_EQ(nullptr, stream.get()); 899 EXPECT_EQ(errors::system::kDomain, error->GetDomain()); 900 EXPECT_EQ("ENOENT", error->GetCode()); 901 } 902 903 TEST_F(FileStreamTest, Open_TruncateExisting_Existing) { 904 base::ScopedTempDir temp_dir; 905 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 906 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"}); 907 std::string data{"Lorem ipsum dolor sit amet ..."}; 908 int data_size = data.size(); // I hate ints for data size... 909 ASSERT_EQ(data_size, base::WriteFile(path, data.data(), data_size)); 910 911 StreamPtr stream = FileStream::Open( 912 path, 913 Stream::AccessMode::READ_WRITE, 914 FileStream::Disposition::TRUNCATE_EXISTING, 915 nullptr); 916 ASSERT_NE(nullptr, stream.get()); 917 EXPECT_TRUE(stream->CanRead()); 918 EXPECT_TRUE(stream->CanWrite()); 919 EXPECT_TRUE(stream->CanSeek()); 920 EXPECT_TRUE(stream->CanGetSize()); 921 EXPECT_EQ(0u, stream->GetPosition()); 922 EXPECT_EQ(0u, stream->GetSize()); 923 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 924 } 925 926 TEST_F(FileStreamTest, FromFileDescriptor_StdIn) { 927 StreamPtr stream = 928 FileStream::FromFileDescriptor(STDIN_FILENO, false, nullptr); 929 ASSERT_NE(nullptr, stream.get()); 930 EXPECT_TRUE(stream->IsOpen()); 931 EXPECT_TRUE(stream->CanRead()); 932 EXPECT_FALSE(stream->CanSeek()); 933 EXPECT_FALSE(stream->CanGetSize()); 934 } 935 936 TEST_F(FileStreamTest, FromFileDescriptor_StdOut) { 937 StreamPtr stream = 938 FileStream::FromFileDescriptor(STDOUT_FILENO, false, nullptr); 939 ASSERT_NE(nullptr, stream.get()); 940 EXPECT_TRUE(stream->IsOpen()); 941 EXPECT_TRUE(stream->CanWrite()); 942 EXPECT_FALSE(stream->CanSeek()); 943 EXPECT_FALSE(stream->CanGetSize()); 944 } 945 946 TEST_F(FileStreamTest, FromFileDescriptor_StdErr) { 947 StreamPtr stream = 948 FileStream::FromFileDescriptor(STDERR_FILENO, false, nullptr); 949 ASSERT_NE(nullptr, stream.get()); 950 EXPECT_TRUE(stream->IsOpen()); 951 EXPECT_TRUE(stream->CanWrite()); 952 EXPECT_FALSE(stream->CanSeek()); 953 EXPECT_FALSE(stream->CanGetSize()); 954 } 955 956 TEST_F(FileStreamTest, FromFileDescriptor_ReadNonBlocking) { 957 int fds[2] = {-1, -1}; 958 ASSERT_EQ(0, pipe(fds)); 959 960 StreamPtr stream = FileStream::FromFileDescriptor(fds[0], true, nullptr); 961 ASSERT_NE(nullptr, stream.get()); 962 EXPECT_TRUE(stream->IsOpen()); 963 EXPECT_TRUE(stream->CanRead()); 964 EXPECT_FALSE(stream->CanWrite()); 965 EXPECT_FALSE(stream->CanSeek()); 966 EXPECT_FALSE(stream->CanGetSize()); 967 968 char buf[10]; 969 size_t read = 0; 970 bool eos = true; 971 EXPECT_TRUE(stream->ReadNonBlocking(buf, sizeof(buf), &read, &eos, nullptr)); 972 EXPECT_EQ(0, read); 973 EXPECT_FALSE(eos); 974 975 std::string data{"foo_bar"}; 976 EXPECT_TRUE(base::WriteFileDescriptor(fds[1], data.data(), data.size())); 977 EXPECT_TRUE(stream->ReadNonBlocking(buf, sizeof(buf), &read, &eos, nullptr)); 978 EXPECT_EQ(data.size(), read); 979 EXPECT_FALSE(eos); 980 EXPECT_EQ(data, (std::string{buf, read})); 981 982 EXPECT_TRUE(stream->ReadNonBlocking(buf, sizeof(buf), &read, &eos, nullptr)); 983 EXPECT_EQ(0, read); 984 EXPECT_FALSE(eos); 985 986 close(fds[1]); 987 988 EXPECT_TRUE(stream->ReadNonBlocking(buf, sizeof(buf), &read, &eos, nullptr)); 989 EXPECT_EQ(0, read); 990 EXPECT_TRUE(eos); 991 992 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 993 } 994 995 TEST_F(FileStreamTest, FromFileDescriptor_WriteNonBlocking) { 996 int fds[2] = {-1, -1}; 997 ASSERT_EQ(0, pipe(fds)); 998 999 StreamPtr stream = FileStream::FromFileDescriptor(fds[1], true, nullptr); 1000 ASSERT_NE(nullptr, stream.get()); 1001 EXPECT_TRUE(stream->IsOpen()); 1002 EXPECT_FALSE(stream->CanRead()); 1003 EXPECT_TRUE(stream->CanWrite()); 1004 EXPECT_FALSE(stream->CanSeek()); 1005 EXPECT_FALSE(stream->CanGetSize()); 1006 1007 // Pipe buffer is generally 64K, so 128K should be more than enough. 1008 std::vector<char> buffer(128 * 1024); 1009 base::RandBytes(buffer.data(), buffer.size()); 1010 size_t written = 0; 1011 size_t total_size = 0; 1012 1013 // Fill the output buffer of the pipe until we can no longer write any data 1014 // to it. 1015 do { 1016 ASSERT_TRUE(stream->WriteNonBlocking(buffer.data(), buffer.size(), &written, 1017 nullptr)); 1018 total_size += written; 1019 } while (written == buffer.size()); 1020 1021 EXPECT_TRUE(stream->WriteNonBlocking(buffer.data(), buffer.size(), &written, 1022 nullptr)); 1023 EXPECT_EQ(0, written); 1024 1025 std::vector<char> out_buffer(total_size); 1026 EXPECT_TRUE(base::ReadFromFD(fds[0], out_buffer.data(), out_buffer.size())); 1027 1028 EXPECT_TRUE(stream->WriteNonBlocking(buffer.data(), buffer.size(), &written, 1029 nullptr)); 1030 EXPECT_GT(written, 0); 1031 out_buffer.resize(written); 1032 EXPECT_TRUE(base::ReadFromFD(fds[0], out_buffer.data(), out_buffer.size())); 1033 EXPECT_TRUE(std::equal(out_buffer.begin(), out_buffer.end(), buffer.begin())); 1034 1035 close(fds[0]); 1036 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 1037 } 1038 1039 TEST_F(FileStreamTest, FromFileDescriptor_ReadAsync) { 1040 int fds[2] = {-1, -1}; 1041 bool succeeded = false; 1042 bool failed = false; 1043 char buffer[100]; 1044 base::MessageLoopForIO base_loop; 1045 BaseMessageLoop brillo_loop{&base_loop}; 1046 brillo_loop.SetAsCurrent(); 1047 1048 auto success_callback = [](bool* succeeded, char* buffer, size_t size) { 1049 std::string data{buffer, buffer + size}; 1050 ASSERT_EQ("abracadabra", data); 1051 *succeeded = true; 1052 }; 1053 1054 auto error_callback = [](bool* failed, const Error* /* error */) { 1055 *failed = true; 1056 }; 1057 1058 auto write_data_callback = [](int write_fd) { 1059 std::string data{"abracadabra"}; 1060 EXPECT_TRUE(base::WriteFileDescriptor(write_fd, data.data(), data.size())); 1061 }; 1062 1063 ASSERT_EQ(0, pipe(fds)); 1064 1065 StreamPtr stream = FileStream::FromFileDescriptor(fds[0], true, nullptr); 1066 1067 // Write to the pipe with a bit of delay. 1068 brillo_loop.PostDelayedTask( 1069 FROM_HERE, 1070 base::Bind(write_data_callback, fds[1]), 1071 base::TimeDelta::FromMilliseconds(10)); 1072 1073 EXPECT_TRUE( 1074 stream->ReadAsync(buffer, 1075 100, 1076 base::Bind(success_callback, 1077 base::Unretained(&succeeded), 1078 base::Unretained(buffer)), 1079 base::Bind(error_callback, base::Unretained(&failed)), 1080 nullptr)); 1081 1082 auto end_condition = [](bool* failed, bool* succeeded) { 1083 return *failed || *succeeded; 1084 }; 1085 MessageLoopRunUntil(&brillo_loop, 1086 base::TimeDelta::FromSeconds(1), 1087 base::Bind(end_condition, 1088 base::Unretained(&failed), 1089 base::Unretained(&succeeded))); 1090 1091 EXPECT_TRUE(succeeded); 1092 EXPECT_FALSE(failed); 1093 1094 close(fds[1]); 1095 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 1096 } 1097 1098 TEST_F(FileStreamTest, FromFileDescriptor_WriteAsync) { 1099 int fds[2] = {-1, -1}; 1100 bool succeeded = false; 1101 bool failed = false; 1102 const std::string data{"abracadabra"}; 1103 base::MessageLoopForIO base_loop; 1104 BaseMessageLoop brillo_loop{&base_loop}; 1105 brillo_loop.SetAsCurrent(); 1106 1107 ASSERT_EQ(0, pipe(fds)); 1108 1109 auto success_callback = [](bool* succeeded, 1110 const std::string& data, 1111 int read_fd, 1112 size_t /* size */) { 1113 char buffer[100]; 1114 EXPECT_TRUE(base::ReadFromFD(read_fd, buffer, data.size())); 1115 EXPECT_EQ(data, (std::string{buffer, buffer + data.size()})); 1116 *succeeded = true; 1117 }; 1118 1119 auto error_callback = [](bool* failed, const Error* /* error */) { 1120 *failed = true; 1121 }; 1122 1123 StreamPtr stream = FileStream::FromFileDescriptor(fds[1], true, nullptr); 1124 1125 EXPECT_TRUE(stream->WriteAsync( 1126 data.data(), 1127 data.size(), 1128 base::Bind(success_callback, base::Unretained(&succeeded), data, fds[0]), 1129 base::Bind(error_callback, base::Unretained(&failed)), 1130 nullptr)); 1131 1132 auto end_condition = [](bool* failed, bool* succeeded) { 1133 return *failed || *succeeded; 1134 }; 1135 MessageLoopRunUntil(&brillo_loop, 1136 base::TimeDelta::FromSeconds(1), 1137 base::Bind(end_condition, 1138 base::Unretained(&failed), 1139 base::Unretained(&succeeded))); 1140 1141 EXPECT_TRUE(succeeded); 1142 EXPECT_FALSE(failed); 1143 1144 close(fds[0]); 1145 EXPECT_TRUE(stream->CloseBlocking(nullptr)); 1146 } 1147 1148 } // namespace brillo 1149