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