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