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
13using testing::An;
14using testing::DoAll;
15using testing::InSequence;
16using testing::Return;
17using testing::SetArgPointee;
18using testing::StrictMock;
19using testing::_;
20
21namespace brillo {
22
23class InputStreamSetTest : public testing::Test {
24 public:
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
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
41  inline static void* IntToPtr(int addr) {
42    return reinterpret_cast<void*>(addr);
43  }
44};
45
46TEST_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
67TEST_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
82TEST_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
95TEST_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
101TEST_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
134TEST_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