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