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