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