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