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