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