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