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().
ACTION(ReturnWouldBlock)38 ACTION(ReturnWouldBlock) {
39 errno = EWOULDBLOCK;
40 return -1;
41 }
42
43 // Helper function to read one byte from the stream.
ReadByte(Stream * 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.
WriteByte(Stream * stream,uint8_t byte)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.
TestCreateFile(Stream * stream)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:
SetUp()142 void SetUp() override {
143 CreateStream(S_IFREG, Stream::AccessMode::READ_WRITE);
144 }
145
fd_mock()146 MockFileDescriptor& fd_mock() {
147 return *static_cast<MockFileDescriptor*>(stream_->fd_interface_.get());
148 }
149
CreateStream(mode_t file_mode,Stream::AccessMode access_mode)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
ExpectStreamClosed(const ErrorPtr & error) const157 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
ExpectStreamOffsetTooLarge(const ErrorPtr & error) const163 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
IntToPtr(int addr)169 inline static char* IntToPtr(int addr) {
170 return reinterpret_cast<char*>(addr);
171 }
172
IntToConstPtr(int addr)173 inline static const char* IntToConstPtr(int addr) {
174 return reinterpret_cast<const char*>(addr);
175 }
176
CallWaitForData(Stream::AccessMode mode,ErrorPtr * error)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
TEST_F(FileStreamTest,IsOpen)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
TEST_F(FileStreamTest,CanRead)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
TEST_F(FileStreamTest,CanWrite)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
TEST_F(FileStreamTest,CanSeek)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
TEST_F(FileStreamTest,CanGetSize)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
TEST_F(FileStreamTest,GetSize)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
TEST_F(FileStreamTest,SetSizeBlocking)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
TEST_F(FileStreamTest,SetSizeBlocking_Fail)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
TEST_F(FileStreamTest,GetRemainingSize)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
TEST_F(FileStreamTest,Seek_Set)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
TEST_F(FileStreamTest,Seek_Cur)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
TEST_F(FileStreamTest,Seek_End)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
TEST_F(FileStreamTest,Seek_Fail)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
TEST_F(FileStreamTest,ReadAsync)371 TEST_F(FileStreamTest, ReadAsync) {
372 size_t read_size = 0;
373 bool failed = false;
374 auto success_callback = [&read_size](size_t size) { read_size = size; };
375 auto error_callback = [&failed](const Error* /* error */) { failed = true; };
376 FileStream::FileDescriptorInterface::DataCallback data_callback;
377
378 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 100))
379 .WillOnce(ReturnWouldBlock());
380 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::READ, _, _))
381 .WillOnce(DoAll(SaveArg<1>(&data_callback), Return(true)));
382 EXPECT_TRUE(stream_->ReadAsync(test_read_buffer_, 100,
383 base::Bind(success_callback),
384 base::Bind(error_callback),
385 nullptr));
386 EXPECT_EQ(0u, read_size);
387 EXPECT_FALSE(failed);
388
389 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 100)).WillOnce(Return(83));
390 data_callback.Run(Stream::AccessMode::READ);
391 EXPECT_EQ(83u, read_size);
392 EXPECT_FALSE(failed);
393 }
394
TEST_F(FileStreamTest,ReadNonBlocking)395 TEST_F(FileStreamTest, ReadNonBlocking) {
396 size_t size = 0;
397 bool eos = false;
398 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, _))
399 .WillRepeatedly(ReturnArg<1>());
400 EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 100, &size, &eos,
401 nullptr));
402 EXPECT_EQ(100u, size);
403 EXPECT_FALSE(eos);
404
405 EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 0, &size, &eos,
406 nullptr));
407 EXPECT_EQ(0u, size);
408 EXPECT_FALSE(eos);
409
410 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, _)).WillOnce(Return(0));
411 EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 100, &size, &eos,
412 nullptr));
413 EXPECT_EQ(0u, size);
414 EXPECT_TRUE(eos);
415
416 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, _))
417 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
418 EXPECT_TRUE(stream_->ReadNonBlocking(test_read_buffer_, 100, &size, &eos,
419 nullptr));
420 EXPECT_EQ(0u, size);
421 EXPECT_FALSE(eos);
422 }
423
TEST_F(FileStreamTest,ReadNonBlocking_Fail)424 TEST_F(FileStreamTest, ReadNonBlocking_Fail) {
425 size_t size = 0;
426 brillo::ErrorPtr error;
427 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, _))
428 .WillOnce(SetErrnoAndReturn(EACCES, -1));
429 EXPECT_FALSE(stream_->ReadNonBlocking(test_read_buffer_, 100, &size, nullptr,
430 &error));
431 EXPECT_EQ(errors::system::kDomain, error->GetDomain());
432 EXPECT_EQ("EACCES", error->GetCode());
433 }
434
TEST_F(FileStreamTest,ReadBlocking)435 TEST_F(FileStreamTest, ReadBlocking) {
436 size_t size = 0;
437 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 100)).WillOnce(Return(20));
438 EXPECT_TRUE(stream_->ReadBlocking(test_read_buffer_, 100, &size, nullptr));
439 EXPECT_EQ(20u, size);
440
441 {
442 InSequence seq;
443 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 80))
444 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
445 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::READ, _, _))
446 .WillOnce(Return(1));
447 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 80)).WillOnce(Return(45));
448 }
449 EXPECT_TRUE(stream_->ReadBlocking(test_read_buffer_, 80, &size, nullptr));
450 EXPECT_EQ(45u, size);
451
452 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 50)).WillOnce(Return(0));
453 EXPECT_TRUE(stream_->ReadBlocking(test_read_buffer_, 50, &size, nullptr));
454 EXPECT_EQ(0u, size);
455 }
456
TEST_F(FileStreamTest,ReadBlocking_Fail)457 TEST_F(FileStreamTest, ReadBlocking_Fail) {
458 {
459 InSequence seq;
460 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 80))
461 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
462 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::READ, _, _))
463 .WillOnce(SetErrnoAndReturn(EBADF, -1));
464 }
465 brillo::ErrorPtr error;
466 size_t size = 0;
467 EXPECT_FALSE(stream_->ReadBlocking(test_read_buffer_, 80, &size, &error));
468 EXPECT_EQ(errors::system::kDomain, error->GetDomain());
469 EXPECT_EQ("EBADF", error->GetCode());
470 }
471
TEST_F(FileStreamTest,ReadAllBlocking)472 TEST_F(FileStreamTest, ReadAllBlocking) {
473 {
474 InSequence seq;
475 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 100)).WillOnce(Return(20));
476 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 20, 80))
477 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
478 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::READ, _, _))
479 .WillOnce(Return(1));
480 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 20, 80))
481 .WillOnce(Return(45));
482 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 65, 35))
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_ + 65, 35))
487 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
488 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::READ, _, _))
489 .WillOnce(Return(1));
490 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 65, 35))
491 .WillOnce(Return(35));
492 }
493 EXPECT_TRUE(stream_->ReadAllBlocking(test_read_buffer_, 100, nullptr));
494 }
495
TEST_F(FileStreamTest,ReadAllBlocking_Fail)496 TEST_F(FileStreamTest, ReadAllBlocking_Fail) {
497 {
498 InSequence seq;
499 EXPECT_CALL(fd_mock(), Read(test_read_buffer_, 100)).WillOnce(Return(20));
500 EXPECT_CALL(fd_mock(), Read(test_read_buffer_ + 20, 80))
501 .WillOnce(Return(0));
502 }
503 brillo::ErrorPtr error;
504 EXPECT_FALSE(stream_->ReadAllBlocking(test_read_buffer_, 100, &error));
505 EXPECT_EQ(errors::stream::kDomain, error->GetDomain());
506 EXPECT_EQ(errors::stream::kPartialData, error->GetCode());
507 EXPECT_EQ("Reading past the end of stream", error->GetMessage());
508 }
509
TEST_F(FileStreamTest,WriteAsync)510 TEST_F(FileStreamTest, WriteAsync) {
511 size_t write_size = 0;
512 bool failed = false;
513 auto success_callback = [&write_size](size_t size) { write_size = size; };
514 auto error_callback = [&failed](const Error* /* error */) { failed = true; };
515 FileStream::FileDescriptorInterface::DataCallback data_callback;
516
517 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 100))
518 .WillOnce(ReturnWouldBlock());
519 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::WRITE, _, _))
520 .WillOnce(DoAll(SaveArg<1>(&data_callback), Return(true)));
521 EXPECT_TRUE(stream_->WriteAsync(test_write_buffer_, 100,
522 base::Bind(success_callback),
523 base::Bind(error_callback),
524 nullptr));
525 EXPECT_EQ(0u, write_size);
526 EXPECT_FALSE(failed);
527
528 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 100)).WillOnce(Return(87));
529 data_callback.Run(Stream::AccessMode::WRITE);
530 EXPECT_EQ(87u, write_size);
531 EXPECT_FALSE(failed);
532 }
533
TEST_F(FileStreamTest,WriteNonBlocking)534 TEST_F(FileStreamTest, WriteNonBlocking) {
535 size_t size = 0;
536 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, _))
537 .WillRepeatedly(ReturnArg<1>());
538 EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 100, &size,
539 nullptr));
540 EXPECT_EQ(100u, size);
541
542 EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 0, &size, nullptr));
543 EXPECT_EQ(0u, size);
544
545 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, _)).WillOnce(Return(0));
546 EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 100, &size,
547 nullptr));
548 EXPECT_EQ(0u, size);
549
550 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, _))
551 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
552 EXPECT_TRUE(stream_->WriteNonBlocking(test_write_buffer_, 100, &size,
553 nullptr));
554 EXPECT_EQ(0u, size);
555 }
556
TEST_F(FileStreamTest,WriteNonBlocking_Fail)557 TEST_F(FileStreamTest, WriteNonBlocking_Fail) {
558 size_t size = 0;
559 brillo::ErrorPtr error;
560 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, _))
561 .WillOnce(SetErrnoAndReturn(EACCES, -1));
562 EXPECT_FALSE(stream_->WriteNonBlocking(test_write_buffer_, 100, &size,
563 &error));
564 EXPECT_EQ(errors::system::kDomain, error->GetDomain());
565 EXPECT_EQ("EACCES", error->GetCode());
566 }
567
TEST_F(FileStreamTest,WriteBlocking)568 TEST_F(FileStreamTest, WriteBlocking) {
569 size_t size = 0;
570 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 100)).WillOnce(Return(20));
571 EXPECT_TRUE(stream_->WriteBlocking(test_write_buffer_, 100, &size, nullptr));
572 EXPECT_EQ(20u, size);
573
574 {
575 InSequence seq;
576 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 80))
577 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
578 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _))
579 .WillOnce(Return(1));
580 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 80)).WillOnce(Return(45));
581 }
582 EXPECT_TRUE(stream_->WriteBlocking(test_write_buffer_, 80, &size, nullptr));
583 EXPECT_EQ(45u, size);
584
585 {
586 InSequence seq;
587 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 50)).WillOnce(Return(0));
588 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _))
589 .WillOnce(Return(1));
590 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 50)).WillOnce(Return(1));
591 }
592 EXPECT_TRUE(stream_->WriteBlocking(test_write_buffer_, 50, &size, nullptr));
593 EXPECT_EQ(1u, size);
594 }
595
TEST_F(FileStreamTest,WriteBlocking_Fail)596 TEST_F(FileStreamTest, WriteBlocking_Fail) {
597 {
598 InSequence seq;
599 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 80))
600 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
601 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _))
602 .WillOnce(SetErrnoAndReturn(EBADF, -1));
603 }
604 brillo::ErrorPtr error;
605 size_t size = 0;
606 EXPECT_FALSE(stream_->WriteBlocking(test_write_buffer_, 80, &size, &error));
607 EXPECT_EQ(errors::system::kDomain, error->GetDomain());
608 EXPECT_EQ("EBADF", error->GetCode());
609 }
610
TEST_F(FileStreamTest,WriteAllBlocking)611 TEST_F(FileStreamTest, WriteAllBlocking) {
612 {
613 InSequence seq;
614 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 100)).WillOnce(Return(20));
615 EXPECT_CALL(fd_mock(), Write(test_write_buffer_ + 20, 80))
616 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
617 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _))
618 .WillOnce(Return(1));
619 EXPECT_CALL(fd_mock(), Write(test_write_buffer_ + 20, 80))
620 .WillOnce(Return(45));
621 EXPECT_CALL(fd_mock(), Write(test_write_buffer_ + 65, 35))
622 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
623 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _))
624 .WillOnce(Return(1));
625 EXPECT_CALL(fd_mock(), Write(test_write_buffer_ + 65, 35))
626 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
627 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _))
628 .WillOnce(Return(1));
629 EXPECT_CALL(fd_mock(), Write(test_write_buffer_ + 65, 35))
630 .WillOnce(Return(35));
631 }
632 EXPECT_TRUE(stream_->WriteAllBlocking(test_write_buffer_, 100, nullptr));
633 }
634
TEST_F(FileStreamTest,WriteAllBlocking_Fail)635 TEST_F(FileStreamTest, WriteAllBlocking_Fail) {
636 {
637 InSequence seq;
638 EXPECT_CALL(fd_mock(), Write(test_write_buffer_, 80))
639 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
640 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _))
641 .WillOnce(SetErrnoAndReturn(EBADF, -1));
642 }
643 brillo::ErrorPtr error;
644 EXPECT_FALSE(stream_->WriteAllBlocking(test_write_buffer_, 80, &error));
645 EXPECT_EQ(errors::system::kDomain, error->GetDomain());
646 EXPECT_EQ("EBADF", error->GetCode());
647 }
648
TEST_F(FileStreamTest,WaitForDataBlocking_Timeout)649 TEST_F(FileStreamTest, WaitForDataBlocking_Timeout) {
650 EXPECT_CALL(fd_mock(), WaitForDataBlocking(Stream::AccessMode::WRITE, _, _))
651 .WillOnce(Return(0));
652 brillo::ErrorPtr error;
653 EXPECT_FALSE(stream_->WaitForDataBlocking(Stream::AccessMode::WRITE, {},
654 nullptr, &error));
655 EXPECT_EQ(errors::stream::kDomain, error->GetDomain());
656 EXPECT_EQ(errors::stream::kTimeout, error->GetCode());
657 }
658
TEST_F(FileStreamTest,FlushBlocking)659 TEST_F(FileStreamTest, FlushBlocking) {
660 EXPECT_TRUE(stream_->FlushBlocking(nullptr));
661 }
662
TEST_F(FileStreamTest,CloseBlocking)663 TEST_F(FileStreamTest, CloseBlocking) {
664 EXPECT_CALL(fd_mock(), Close()).WillOnce(Return(0));
665 EXPECT_TRUE(stream_->CloseBlocking(nullptr));
666
667 EXPECT_CALL(fd_mock(), IsOpen()).WillOnce(Return(false));
668 EXPECT_TRUE(stream_->CloseBlocking(nullptr));
669 }
670
TEST_F(FileStreamTest,CloseBlocking_Fail)671 TEST_F(FileStreamTest, CloseBlocking_Fail) {
672 brillo::ErrorPtr error;
673 EXPECT_CALL(fd_mock(), Close()).WillOnce(SetErrnoAndReturn(EFBIG, -1));
674 EXPECT_FALSE(stream_->CloseBlocking(&error));
675 EXPECT_EQ(errors::system::kDomain, error->GetDomain());
676 EXPECT_EQ("EFBIG", error->GetCode());
677 }
678
TEST_F(FileStreamTest,WaitForData)679 TEST_F(FileStreamTest, WaitForData) {
680 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::READ, _, _))
681 .WillOnce(Return(true));
682 EXPECT_TRUE(CallWaitForData(Stream::AccessMode::READ, nullptr));
683
684 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::WRITE, _, _))
685 .WillOnce(Return(true));
686 EXPECT_TRUE(CallWaitForData(Stream::AccessMode::WRITE, nullptr));
687
688 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::READ_WRITE, _, _))
689 .WillOnce(Return(true));
690 EXPECT_TRUE(CallWaitForData(Stream::AccessMode::READ_WRITE, nullptr));
691
692 EXPECT_CALL(fd_mock(), WaitForData(Stream::AccessMode::READ_WRITE, _, _))
693 .WillOnce(Return(false));
694 EXPECT_FALSE(CallWaitForData(Stream::AccessMode::READ_WRITE, nullptr));
695 }
696
TEST_F(FileStreamTest,CreateTemporary)697 TEST_F(FileStreamTest, CreateTemporary) {
698 StreamPtr stream = FileStream::CreateTemporary(nullptr);
699 ASSERT_NE(nullptr, stream.get());
700 TestCreateFile(stream.get());
701 }
702
TEST_F(FileStreamTest,OpenRead)703 TEST_F(FileStreamTest, OpenRead) {
704 base::ScopedTempDir temp_dir;
705 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
706 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"});
707 std::vector<char> buffer(1024 * 1024);
708 base::RandBytes(buffer.data(), buffer.size());
709 int file_size = buffer.size(); // Stupid base::WriteFile taking "int" size.
710 ASSERT_EQ(file_size, base::WriteFile(path, buffer.data(), file_size));
711
712 StreamPtr stream = FileStream::Open(path,
713 Stream::AccessMode::READ,
714 FileStream::Disposition::OPEN_EXISTING,
715 nullptr);
716 ASSERT_NE(nullptr, stream.get());
717 ASSERT_TRUE(stream->IsOpen());
718 EXPECT_TRUE(stream->CanRead());
719 EXPECT_FALSE(stream->CanWrite());
720 EXPECT_TRUE(stream->CanSeek());
721 EXPECT_TRUE(stream->CanGetSize());
722 EXPECT_EQ(0u, stream->GetPosition());
723 EXPECT_EQ(buffer.size(), stream->GetSize());
724
725 std::vector<char> buffer2(buffer.size());
726 EXPECT_TRUE(stream->ReadAllBlocking(buffer2.data(), buffer2.size(), nullptr));
727 EXPECT_EQ(buffer2, buffer);
728 EXPECT_TRUE(stream->CloseBlocking(nullptr));
729 }
730
TEST_F(FileStreamTest,OpenWrite)731 TEST_F(FileStreamTest, OpenWrite) {
732 base::ScopedTempDir temp_dir;
733 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
734 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"});
735 std::vector<char> buffer(1024 * 1024);
736 base::RandBytes(buffer.data(), buffer.size());
737
738 StreamPtr stream = FileStream::Open(path,
739 Stream::AccessMode::WRITE,
740 FileStream::Disposition::CREATE_ALWAYS,
741 nullptr);
742 ASSERT_NE(nullptr, stream.get());
743 ASSERT_TRUE(stream->IsOpen());
744 EXPECT_FALSE(stream->CanRead());
745 EXPECT_TRUE(stream->CanWrite());
746 EXPECT_TRUE(stream->CanSeek());
747 EXPECT_TRUE(stream->CanGetSize());
748 EXPECT_EQ(0u, stream->GetPosition());
749 EXPECT_EQ(0u, stream->GetSize());
750
751 EXPECT_TRUE(stream->WriteAllBlocking(buffer.data(), buffer.size(), nullptr));
752 EXPECT_TRUE(stream->CloseBlocking(nullptr));
753
754 std::vector<char> buffer2(buffer.size());
755 int file_size = buffer2.size(); // Stupid base::ReadFile taking "int" size.
756 ASSERT_EQ(file_size, base::ReadFile(path, buffer2.data(), file_size));
757 EXPECT_EQ(buffer2, buffer);
758 }
759
TEST_F(FileStreamTest,Open_OpenExisting)760 TEST_F(FileStreamTest, Open_OpenExisting) {
761 base::ScopedTempDir temp_dir;
762 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
763 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"});
764 std::string data{"Lorem ipsum dolor sit amet ..."};
765 int data_size = data.size(); // I hate ints for data size...
766 ASSERT_EQ(data_size, base::WriteFile(path, data.data(), data_size));
767
768 StreamPtr stream = FileStream::Open(path,
769 Stream::AccessMode::READ_WRITE,
770 FileStream::Disposition::OPEN_EXISTING,
771 nullptr);
772 ASSERT_NE(nullptr, stream.get());
773 EXPECT_TRUE(stream->CanRead());
774 EXPECT_TRUE(stream->CanWrite());
775 EXPECT_TRUE(stream->CanSeek());
776 EXPECT_TRUE(stream->CanGetSize());
777 EXPECT_EQ(0u, stream->GetPosition());
778 EXPECT_EQ(data.size(), stream->GetSize());
779 EXPECT_TRUE(stream->CloseBlocking(nullptr));
780 }
781
TEST_F(FileStreamTest,Open_OpenExisting_Fail)782 TEST_F(FileStreamTest, Open_OpenExisting_Fail) {
783 base::ScopedTempDir temp_dir;
784 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
785 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"});
786
787 ErrorPtr error;
788 StreamPtr stream = FileStream::Open(path,
789 Stream::AccessMode::READ_WRITE,
790 FileStream::Disposition::OPEN_EXISTING,
791 &error);
792 ASSERT_EQ(nullptr, stream.get());
793 EXPECT_EQ(errors::system::kDomain, error->GetDomain());
794 EXPECT_EQ("ENOENT", error->GetCode());
795 }
796
TEST_F(FileStreamTest,Open_CreateAlways_New)797 TEST_F(FileStreamTest, Open_CreateAlways_New) {
798 base::ScopedTempDir temp_dir;
799 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
800 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"});
801
802 StreamPtr stream = FileStream::Open(path,
803 Stream::AccessMode::READ_WRITE,
804 FileStream::Disposition::CREATE_ALWAYS,
805 nullptr);
806 ASSERT_NE(nullptr, stream.get());
807 EXPECT_TRUE(stream->CanRead());
808 EXPECT_TRUE(stream->CanWrite());
809 EXPECT_TRUE(stream->CanSeek());
810 EXPECT_TRUE(stream->CanGetSize());
811 EXPECT_EQ(0u, stream->GetPosition());
812 EXPECT_EQ(0u, stream->GetSize());
813 EXPECT_TRUE(stream->CloseBlocking(nullptr));
814 }
815
TEST_F(FileStreamTest,Open_CreateAlways_Existing)816 TEST_F(FileStreamTest, Open_CreateAlways_Existing) {
817 base::ScopedTempDir temp_dir;
818 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
819 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"});
820 std::string data{"Lorem ipsum dolor sit amet ..."};
821 int data_size = data.size(); // I hate ints for data size...
822 ASSERT_EQ(data_size, base::WriteFile(path, data.data(), data_size));
823
824 StreamPtr stream = FileStream::Open(path,
825 Stream::AccessMode::READ_WRITE,
826 FileStream::Disposition::CREATE_ALWAYS,
827 nullptr);
828 ASSERT_NE(nullptr, stream.get());
829 EXPECT_TRUE(stream->CanRead());
830 EXPECT_TRUE(stream->CanWrite());
831 EXPECT_TRUE(stream->CanSeek());
832 EXPECT_TRUE(stream->CanGetSize());
833 EXPECT_EQ(0u, stream->GetPosition());
834 EXPECT_EQ(0u, stream->GetSize());
835 EXPECT_TRUE(stream->CloseBlocking(nullptr));
836 }
837
TEST_F(FileStreamTest,Open_CreateNewOnly_New)838 TEST_F(FileStreamTest, Open_CreateNewOnly_New) {
839 base::ScopedTempDir temp_dir;
840 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
841 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"});
842
843 StreamPtr stream = FileStream::Open(path,
844 Stream::AccessMode::READ_WRITE,
845 FileStream::Disposition::CREATE_NEW_ONLY,
846 nullptr);
847 ASSERT_NE(nullptr, stream.get());
848 EXPECT_TRUE(stream->CanRead());
849 EXPECT_TRUE(stream->CanWrite());
850 EXPECT_TRUE(stream->CanSeek());
851 EXPECT_TRUE(stream->CanGetSize());
852 EXPECT_EQ(0u, stream->GetPosition());
853 EXPECT_EQ(0u, stream->GetSize());
854 EXPECT_TRUE(stream->CloseBlocking(nullptr));
855 }
856
TEST_F(FileStreamTest,Open_CreateNewOnly_Existing)857 TEST_F(FileStreamTest, Open_CreateNewOnly_Existing) {
858 base::ScopedTempDir temp_dir;
859 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
860 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"});
861 std::string data{"Lorem ipsum dolor sit amet ..."};
862 int data_size = data.size(); // I hate ints for data size...
863 ASSERT_EQ(data_size, base::WriteFile(path, data.data(), data_size));
864
865 ErrorPtr error;
866 StreamPtr stream = FileStream::Open(path,
867 Stream::AccessMode::READ_WRITE,
868 FileStream::Disposition::CREATE_NEW_ONLY,
869 &error);
870 ASSERT_EQ(nullptr, stream.get());
871 EXPECT_EQ(errors::system::kDomain, error->GetDomain());
872 EXPECT_EQ("EEXIST", error->GetCode());
873 }
874
TEST_F(FileStreamTest,Open_TruncateExisting_New)875 TEST_F(FileStreamTest, Open_TruncateExisting_New) {
876 base::ScopedTempDir temp_dir;
877 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
878 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"});
879
880 ErrorPtr error;
881 StreamPtr stream = FileStream::Open(
882 path,
883 Stream::AccessMode::READ_WRITE,
884 FileStream::Disposition::TRUNCATE_EXISTING,
885 &error);
886 ASSERT_EQ(nullptr, stream.get());
887 EXPECT_EQ(errors::system::kDomain, error->GetDomain());
888 EXPECT_EQ("ENOENT", error->GetCode());
889 }
890
TEST_F(FileStreamTest,Open_TruncateExisting_Existing)891 TEST_F(FileStreamTest, Open_TruncateExisting_Existing) {
892 base::ScopedTempDir temp_dir;
893 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
894 base::FilePath path = temp_dir.path().Append(base::FilePath{"test.dat"});
895 std::string data{"Lorem ipsum dolor sit amet ..."};
896 int data_size = data.size(); // I hate ints for data size...
897 ASSERT_EQ(data_size, base::WriteFile(path, data.data(), data_size));
898
899 StreamPtr stream = FileStream::Open(
900 path,
901 Stream::AccessMode::READ_WRITE,
902 FileStream::Disposition::TRUNCATE_EXISTING,
903 nullptr);
904 ASSERT_NE(nullptr, stream.get());
905 EXPECT_TRUE(stream->CanRead());
906 EXPECT_TRUE(stream->CanWrite());
907 EXPECT_TRUE(stream->CanSeek());
908 EXPECT_TRUE(stream->CanGetSize());
909 EXPECT_EQ(0u, stream->GetPosition());
910 EXPECT_EQ(0u, stream->GetSize());
911 EXPECT_TRUE(stream->CloseBlocking(nullptr));
912 }
913
TEST_F(FileStreamTest,FromFileDescriptor_StdIn)914 TEST_F(FileStreamTest, FromFileDescriptor_StdIn) {
915 StreamPtr stream =
916 FileStream::FromFileDescriptor(STDIN_FILENO, false, nullptr);
917 ASSERT_NE(nullptr, stream.get());
918 EXPECT_TRUE(stream->IsOpen());
919 EXPECT_TRUE(stream->CanRead());
920 EXPECT_FALSE(stream->CanSeek());
921 EXPECT_FALSE(stream->CanGetSize());
922 }
923
TEST_F(FileStreamTest,FromFileDescriptor_StdOut)924 TEST_F(FileStreamTest, FromFileDescriptor_StdOut) {
925 StreamPtr stream =
926 FileStream::FromFileDescriptor(STDOUT_FILENO, false, nullptr);
927 ASSERT_NE(nullptr, stream.get());
928 EXPECT_TRUE(stream->IsOpen());
929 EXPECT_TRUE(stream->CanWrite());
930 EXPECT_FALSE(stream->CanSeek());
931 EXPECT_FALSE(stream->CanGetSize());
932 }
933
TEST_F(FileStreamTest,FromFileDescriptor_StdErr)934 TEST_F(FileStreamTest, FromFileDescriptor_StdErr) {
935 StreamPtr stream =
936 FileStream::FromFileDescriptor(STDERR_FILENO, false, nullptr);
937 ASSERT_NE(nullptr, stream.get());
938 EXPECT_TRUE(stream->IsOpen());
939 EXPECT_TRUE(stream->CanWrite());
940 EXPECT_FALSE(stream->CanSeek());
941 EXPECT_FALSE(stream->CanGetSize());
942 }
943
TEST_F(FileStreamTest,FromFileDescriptor_ReadNonBlocking)944 TEST_F(FileStreamTest, FromFileDescriptor_ReadNonBlocking) {
945 int fds[2] = {-1, -1};
946 ASSERT_EQ(0, pipe(fds));
947
948 StreamPtr stream = FileStream::FromFileDescriptor(fds[0], true, nullptr);
949 ASSERT_NE(nullptr, stream.get());
950 EXPECT_TRUE(stream->IsOpen());
951 EXPECT_TRUE(stream->CanRead());
952 EXPECT_FALSE(stream->CanWrite());
953 EXPECT_FALSE(stream->CanSeek());
954 EXPECT_FALSE(stream->CanGetSize());
955
956 char buf[10];
957 size_t read = 0;
958 bool eos = true;
959 EXPECT_TRUE(stream->ReadNonBlocking(buf, sizeof(buf), &read, &eos, nullptr));
960 EXPECT_EQ(0, read);
961 EXPECT_FALSE(eos);
962
963 std::string data{"foo_bar"};
964 EXPECT_TRUE(base::WriteFileDescriptor(fds[1], data.data(), data.size()));
965 EXPECT_TRUE(stream->ReadNonBlocking(buf, sizeof(buf), &read, &eos, nullptr));
966 EXPECT_EQ(data.size(), read);
967 EXPECT_FALSE(eos);
968 EXPECT_EQ(data, (std::string{buf, read}));
969
970 EXPECT_TRUE(stream->ReadNonBlocking(buf, sizeof(buf), &read, &eos, nullptr));
971 EXPECT_EQ(0, read);
972 EXPECT_FALSE(eos);
973
974 close(fds[1]);
975
976 EXPECT_TRUE(stream->ReadNonBlocking(buf, sizeof(buf), &read, &eos, nullptr));
977 EXPECT_EQ(0, read);
978 EXPECT_TRUE(eos);
979
980 EXPECT_TRUE(stream->CloseBlocking(nullptr));
981 }
982
TEST_F(FileStreamTest,FromFileDescriptor_WriteNonBlocking)983 TEST_F(FileStreamTest, FromFileDescriptor_WriteNonBlocking) {
984 int fds[2] = {-1, -1};
985 ASSERT_EQ(0, pipe(fds));
986
987 StreamPtr stream = FileStream::FromFileDescriptor(fds[1], true, nullptr);
988 ASSERT_NE(nullptr, stream.get());
989 EXPECT_TRUE(stream->IsOpen());
990 EXPECT_FALSE(stream->CanRead());
991 EXPECT_TRUE(stream->CanWrite());
992 EXPECT_FALSE(stream->CanSeek());
993 EXPECT_FALSE(stream->CanGetSize());
994
995 // Pipe buffer is generally 64K, so 128K should be more than enough.
996 std::vector<char> buffer(128 * 1024);
997 base::RandBytes(buffer.data(), buffer.size());
998 size_t written = 0;
999 size_t total_size = 0;
1000
1001 // Fill the output buffer of the pipe until we can no longer write any data
1002 // to it.
1003 do {
1004 ASSERT_TRUE(stream->WriteNonBlocking(buffer.data(), buffer.size(), &written,
1005 nullptr));
1006 total_size += written;
1007 } while (written == buffer.size());
1008
1009 EXPECT_TRUE(stream->WriteNonBlocking(buffer.data(), buffer.size(), &written,
1010 nullptr));
1011 EXPECT_EQ(0, written);
1012
1013 std::vector<char> out_buffer(total_size);
1014 EXPECT_TRUE(base::ReadFromFD(fds[0], out_buffer.data(), out_buffer.size()));
1015
1016 EXPECT_TRUE(stream->WriteNonBlocking(buffer.data(), buffer.size(), &written,
1017 nullptr));
1018 EXPECT_GT(written, 0);
1019 out_buffer.resize(written);
1020 EXPECT_TRUE(base::ReadFromFD(fds[0], out_buffer.data(), out_buffer.size()));
1021 EXPECT_TRUE(std::equal(out_buffer.begin(), out_buffer.end(), buffer.begin()));
1022
1023 close(fds[0]);
1024 EXPECT_TRUE(stream->CloseBlocking(nullptr));
1025 }
1026
TEST_F(FileStreamTest,FromFileDescriptor_ReadAsync)1027 TEST_F(FileStreamTest, FromFileDescriptor_ReadAsync) {
1028 int fds[2] = {-1, -1};
1029 bool succeeded = false;
1030 bool failed = false;
1031 char buffer[100];
1032 base::MessageLoopForIO base_loop;
1033 BaseMessageLoop brillo_loop{&base_loop};
1034 brillo_loop.SetAsCurrent();
1035
1036 auto success_callback = [&succeeded, &buffer](size_t size) {
1037 std::string data{buffer, buffer + size};
1038 ASSERT_EQ("abracadabra", data);
1039 succeeded = true;
1040 };
1041
1042 auto error_callback = [&failed](const Error* /* error */) {
1043 failed = true;
1044 };
1045
1046 auto write_data_callback = [](int write_fd) {
1047 std::string data{"abracadabra"};
1048 EXPECT_TRUE(base::WriteFileDescriptor(write_fd, data.data(), data.size()));
1049 };
1050
1051 ASSERT_EQ(0, pipe(fds));
1052
1053 StreamPtr stream = FileStream::FromFileDescriptor(fds[0], true, nullptr);
1054
1055 // Write to the pipe with a bit of delay.
1056 brillo_loop.PostDelayedTask(
1057 FROM_HERE,
1058 base::Bind(write_data_callback, fds[1]),
1059 base::TimeDelta::FromMilliseconds(10));
1060
1061 EXPECT_TRUE(stream->ReadAsync(buffer, 100, base::Bind(success_callback),
1062 base::Bind(error_callback), nullptr));
1063
1064 auto end_condition = [&failed, &succeeded] { return failed || succeeded; };
1065 MessageLoopRunUntil(&brillo_loop,
1066 base::TimeDelta::FromSeconds(1),
1067 base::Bind(end_condition));
1068
1069 EXPECT_TRUE(succeeded);
1070 EXPECT_FALSE(failed);
1071
1072 close(fds[1]);
1073 EXPECT_TRUE(stream->CloseBlocking(nullptr));
1074 }
1075
TEST_F(FileStreamTest,FromFileDescriptor_WriteAsync)1076 TEST_F(FileStreamTest, FromFileDescriptor_WriteAsync) {
1077 int fds[2] = {-1, -1};
1078 bool succeeded = false;
1079 bool failed = false;
1080 const std::string data{"abracadabra"};
1081 base::MessageLoopForIO base_loop;
1082 BaseMessageLoop brillo_loop{&base_loop};
1083 brillo_loop.SetAsCurrent();
1084
1085 ASSERT_EQ(0, pipe(fds));
1086
1087 auto success_callback = [&succeeded, &data](int read_fd, size_t /* size */) {
1088 char buffer[100];
1089 EXPECT_TRUE(base::ReadFromFD(read_fd, buffer, data.size()));
1090 EXPECT_EQ(data, (std::string{buffer, buffer + data.size()}));
1091 succeeded = true;
1092 };
1093
1094 auto error_callback = [&failed](const Error* /* error */) {
1095 failed = true;
1096 };
1097
1098 StreamPtr stream = FileStream::FromFileDescriptor(fds[1], true, nullptr);
1099
1100 EXPECT_TRUE(stream->WriteAsync(data.data(), data.size(),
1101 base::Bind(success_callback, fds[0]),
1102 base::Bind(error_callback), nullptr));
1103
1104 auto end_condition = [&failed, &succeeded] { return failed || succeeded; };
1105 MessageLoopRunUntil(&brillo_loop,
1106 base::TimeDelta::FromSeconds(1),
1107 base::Bind(end_condition));
1108
1109 EXPECT_TRUE(succeeded);
1110 EXPECT_FALSE(failed);
1111
1112 close(fds[0]);
1113 EXPECT_TRUE(stream->CloseBlocking(nullptr));
1114 }
1115
1116 } // namespace brillo
1117