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/input_stream_set.h>
6
7 #include <memory>
8
9 #include <brillo/errors/error_codes.h>
10 #include <brillo/streams/mock_stream.h>
11 #include <brillo/streams/stream_errors.h>
12 #include <gmock/gmock.h>
13 #include <gtest/gtest.h>
14
15 using testing::DoAll;
16 using testing::InSequence;
17 using testing::Return;
18 using testing::SetArgPointee;
19 using testing::StrictMock;
20 using testing::_;
21
22 namespace brillo {
23
24 class InputStreamSetTest : public testing::Test {
25 public:
SetUp()26 void SetUp() override {
27 itf1_.reset(new StrictMock<MockStream>{});
28 itf2_.reset(new StrictMock<MockStream>{});
29 stream_.reset(new InputStreamSet({itf1_.get(), itf2_.get()}, {}, 100));
30 }
31
TearDown()32 void TearDown() override {
33 stream_.reset();
34 itf2_.reset();
35 itf1_.reset();
36 }
37
38 std::unique_ptr<StrictMock<MockStream>> itf1_;
39 std::unique_ptr<StrictMock<MockStream>> itf2_;
40 std::unique_ptr<InputStreamSet> stream_;
41
IntToPtr(int addr)42 inline static void* IntToPtr(int addr) {
43 return reinterpret_cast<void*>(addr);
44 }
45 };
46
TEST_F(InputStreamSetTest,InitialFalseAssumptions)47 TEST_F(InputStreamSetTest, InitialFalseAssumptions) {
48 // Methods that should just succeed/fail without calling underlying streams.
49 EXPECT_TRUE(stream_->CanRead());
50 EXPECT_FALSE(stream_->CanWrite());
51 EXPECT_FALSE(stream_->CanSeek());
52 EXPECT_EQ(100, stream_->GetSize());
53 EXPECT_FALSE(stream_->SetSizeBlocking(0, nullptr));
54 EXPECT_FALSE(stream_->GetPosition());
55 EXPECT_FALSE(stream_->Seek(0, Stream::Whence::FROM_BEGIN, nullptr, nullptr));
56 char buffer[100];
57 size_t size = 0;
58 EXPECT_FALSE(stream_->WriteAsync(buffer, sizeof(buffer), {}, {}, nullptr));
59 EXPECT_FALSE(stream_->WriteAllAsync(buffer, sizeof(buffer), {}, {}, nullptr));
60 EXPECT_FALSE(stream_->WriteNonBlocking(buffer, sizeof(buffer), &size,
61 nullptr));
62 EXPECT_FALSE(stream_->WriteBlocking(buffer, sizeof(buffer), &size, nullptr));
63 EXPECT_FALSE(stream_->WriteAllBlocking(buffer, sizeof(buffer), nullptr));
64 EXPECT_TRUE(stream_->FlushBlocking(nullptr));
65 EXPECT_TRUE(stream_->CloseBlocking(nullptr));
66 }
67
TEST_F(InputStreamSetTest,InitialTrueAssumptions)68 TEST_F(InputStreamSetTest, InitialTrueAssumptions) {
69 // Methods that redirect calls to underlying streams.
70 EXPECT_CALL(*itf1_, CanGetSize()).WillOnce(Return(true));
71 EXPECT_CALL(*itf2_, CanGetSize()).WillOnce(Return(true));
72 EXPECT_TRUE(stream_->CanGetSize());
73
74 // Reading from the first stream fails, so the second one shouldn't be used.
75 EXPECT_CALL(*itf1_, ReadNonBlocking(_, _, _, _, _))
76 .WillOnce(Return(false));
77 EXPECT_CALL(*itf2_, ReadNonBlocking(_, _, _, _, _)).Times(0);
78 char buffer[100];
79 size_t size = 0;
80 EXPECT_FALSE(stream_->ReadBlocking(buffer, sizeof(buffer), &size, nullptr));
81 }
82
TEST_F(InputStreamSetTest,CanGetSize)83 TEST_F(InputStreamSetTest, CanGetSize) {
84 EXPECT_CALL(*itf1_, CanGetSize()).WillOnce(Return(true));
85 EXPECT_CALL(*itf2_, CanGetSize()).WillOnce(Return(true));
86 EXPECT_TRUE(stream_->CanGetSize());
87
88 EXPECT_CALL(*itf1_, CanGetSize()).WillOnce(Return(false));
89 EXPECT_FALSE(stream_->CanGetSize());
90
91 EXPECT_CALL(*itf1_, CanGetSize()).WillOnce(Return(true));
92 EXPECT_CALL(*itf2_, CanGetSize()).WillOnce(Return(false));
93 EXPECT_FALSE(stream_->CanGetSize());
94 }
95
TEST_F(InputStreamSetTest,GetRemainingSize)96 TEST_F(InputStreamSetTest, GetRemainingSize) {
97 EXPECT_CALL(*itf1_, GetRemainingSize()).WillOnce(Return(10));
98 EXPECT_CALL(*itf2_, GetRemainingSize()).WillOnce(Return(32));
99 EXPECT_EQ(42, stream_->GetRemainingSize());
100 }
101
TEST_F(InputStreamSetTest,ReadNonBlocking)102 TEST_F(InputStreamSetTest, ReadNonBlocking) {
103 size_t read = 0;
104 bool eos = false;
105
106 InSequence s;
107 EXPECT_CALL(*itf1_, ReadNonBlocking(IntToPtr(1000), 100, _, _, _))
108 .WillOnce(DoAll(SetArgPointee<2>(10),
109 SetArgPointee<3>(false),
110 Return(true)));
111 EXPECT_TRUE(stream_->ReadNonBlocking(IntToPtr(1000), 100, &read, &eos,
112 nullptr));
113 EXPECT_EQ(10, read);
114 EXPECT_FALSE(eos);
115
116 EXPECT_CALL(*itf1_, ReadNonBlocking(IntToPtr(1000), 100, _, _, _))
117 .WillOnce(DoAll(SetArgPointee<2>(0), SetArgPointee<3>(true), Return(true)));
118 EXPECT_CALL(*itf2_, ReadNonBlocking(IntToPtr(1000), 100 , _, _, _))
119 .WillOnce(DoAll(SetArgPointee<2>(100),
120 SetArgPointee<3>(false),
121 Return(true)));
122 EXPECT_TRUE(stream_->ReadNonBlocking(IntToPtr(1000), 100, &read, &eos,
123 nullptr));
124 EXPECT_EQ(100, read);
125 EXPECT_FALSE(eos);
126
127 EXPECT_CALL(*itf2_, ReadNonBlocking(IntToPtr(1000), 100, _, _, _))
128 .WillOnce(DoAll(SetArgPointee<2>(0), SetArgPointee<3>(true), Return(true)));
129 EXPECT_TRUE(stream_->ReadNonBlocking(IntToPtr(1000), 100, &read, &eos,
130 nullptr));
131 EXPECT_EQ(0, read);
132 EXPECT_TRUE(eos);
133 }
134
TEST_F(InputStreamSetTest,ReadBlocking)135 TEST_F(InputStreamSetTest, ReadBlocking) {
136 size_t read = 0;
137
138 InSequence s;
139 EXPECT_CALL(*itf1_, ReadNonBlocking(IntToPtr(1000), 100, _, _, _))
140 .WillOnce(DoAll(SetArgPointee<2>(10),
141 SetArgPointee<3>(false),
142 Return(true)));
143 EXPECT_TRUE(stream_->ReadBlocking(IntToPtr(1000), 100, &read, nullptr));
144 EXPECT_EQ(10, read);
145
146 EXPECT_CALL(*itf1_, ReadNonBlocking(IntToPtr(1000), 100, _, _, _))
147 .WillOnce(DoAll(SetArgPointee<2>(0),
148 SetArgPointee<3>(true),
149 Return(true)));
150 EXPECT_CALL(*itf2_, ReadNonBlocking(IntToPtr(1000), 100, _, _, _))
151 .WillOnce(DoAll(SetArgPointee<2>(0),
152 SetArgPointee<3>(false),
153 Return(true)));
154 EXPECT_CALL(*itf2_, WaitForDataBlocking(Stream::AccessMode::READ, _, _, _))
155 .WillOnce(Return(true));
156 EXPECT_CALL(*itf2_, ReadNonBlocking(IntToPtr(1000), 100, _, _, _))
157 .WillOnce(DoAll(SetArgPointee<2>(100),
158 SetArgPointee<3>(false),
159 Return(true)));
160 EXPECT_TRUE(stream_->ReadBlocking(IntToPtr(1000), 100, &read, nullptr));
161 EXPECT_EQ(100, read);
162
163 EXPECT_CALL(*itf2_, ReadNonBlocking(IntToPtr(1000), 100, _, _, _))
164 .WillOnce(DoAll(SetArgPointee<2>(0),
165 SetArgPointee<3>(true),
166 Return(true)));
167 EXPECT_TRUE(stream_->ReadBlocking(IntToPtr(1000), 100, &read, nullptr));
168 EXPECT_EQ(0, read);
169 }
170
171 } // namespace brillo
172