1 /**
2  * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
3  * (C) 2016 - 2019 Stanislav Angelovic <angelovic.s@gmail.com>
4  *
5  * @file Connection_test.cpp
6  * @author Ardazishvili Roman (ardazishvili.roman@yandex.ru)
7  *
8  * Created on: Feb 4, 2019
9  * Project: sdbus-c++
10  * Description: High-level D-Bus IPC C++ library based on sd-bus
11  *
12  * This file is part of sdbus-c++.
13  *
14  * sdbus-c++ is free software; you can redistribute it and/or modify it
15  * under the terms of the GNU Lesser General Public License as published by
16  * the Free Software Foundation, either version 2.1 of the License, or
17  * (at your option) any later version.
18  *
19  * sdbus-c++ is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with sdbus-c++. If not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 #include "Connection.h"
29 #include "unittests/mocks/SdBusMock.h"
30 
31 #include <gtest/gtest.h>
32 
33 using ::testing::_;
34 using ::testing::DoAll;
35 using ::testing::SetArgPointee;
36 using ::testing::Return;
37 using ::testing::NiceMock;
38 using sdbus::internal::Connection;
39 constexpr sdbus::internal::Connection::default_bus_t default_bus;
40 constexpr sdbus::internal::Connection::system_bus_t system_bus;
41 constexpr sdbus::internal::Connection::session_bus_t session_bus;
42 constexpr sdbus::internal::Connection::remote_system_bus_t remote_system_bus;
43 
44 class ConnectionCreationTest : public ::testing::Test
45 {
46 protected:
47     ConnectionCreationTest() = default;
48 
49     std::unique_ptr<NiceMock<SdBusMock>> sdBusIntfMock_ = std::make_unique<NiceMock<SdBusMock>>();
50     sd_bus* fakeBusPtr_ = reinterpret_cast<sd_bus*>(1);
51 };
52 
53 using ADefaultBusConnection = ConnectionCreationTest;
54 using ASystemBusConnection = ConnectionCreationTest;
55 using ASessionBusConnection = ConnectionCreationTest;
56 
TEST_F(ADefaultBusConnection,OpensAndFlushesBusWhenCreated)57 TEST_F(ADefaultBusConnection, OpensAndFlushesBusWhenCreated)
58 {
59     EXPECT_CALL(*sdBusIntfMock_, sd_bus_open(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
60     EXPECT_CALL(*sdBusIntfMock_, sd_bus_flush(_)).Times(1);
61     Connection(std::move(sdBusIntfMock_), default_bus);
62 }
63 
TEST_F(ASystemBusConnection,OpensAndFlushesBusWhenCreated)64 TEST_F(ASystemBusConnection, OpensAndFlushesBusWhenCreated)
65 {
66     EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_system(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
67     EXPECT_CALL(*sdBusIntfMock_, sd_bus_flush(_)).Times(1);
68     Connection(std::move(sdBusIntfMock_), system_bus);
69 }
70 
TEST_F(ASessionBusConnection,OpensAndFlushesBusWhenCreated)71 TEST_F(ASessionBusConnection, OpensAndFlushesBusWhenCreated)
72 {
73     EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
74     EXPECT_CALL(*sdBusIntfMock_, sd_bus_flush(_)).Times(1);
75     Connection(std::move(sdBusIntfMock_), session_bus);
76 }
77 
TEST_F(ADefaultBusConnection,ClosesAndUnrefsBusWhenDestructed)78 TEST_F(ADefaultBusConnection, ClosesAndUnrefsBusWhenDestructed)
79 {
80     ON_CALL(*sdBusIntfMock_, sd_bus_open(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
81     EXPECT_CALL(*sdBusIntfMock_, sd_bus_flush_close_unref(_)).Times(1);
82     Connection(std::move(sdBusIntfMock_), default_bus);
83 }
84 
TEST_F(ASystemBusConnection,ClosesAndUnrefsBusWhenDestructed)85 TEST_F(ASystemBusConnection, ClosesAndUnrefsBusWhenDestructed)
86 {
87     ON_CALL(*sdBusIntfMock_, sd_bus_open_system(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
88     EXPECT_CALL(*sdBusIntfMock_, sd_bus_flush_close_unref(_)).Times(1);
89     Connection(std::move(sdBusIntfMock_), system_bus);
90 }
91 
TEST_F(ASessionBusConnection,ClosesAndUnrefsBusWhenDestructed)92 TEST_F(ASessionBusConnection, ClosesAndUnrefsBusWhenDestructed)
93 {
94     ON_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
95     EXPECT_CALL(*sdBusIntfMock_, sd_bus_flush_close_unref(_)).Times(1);
96     Connection(std::move(sdBusIntfMock_), session_bus);
97 }
98 
TEST_F(ADefaultBusConnection,ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)99 TEST_F(ADefaultBusConnection, ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)
100 {
101     ON_CALL(*sdBusIntfMock_, sd_bus_open(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(-1)));
102     ASSERT_THROW(Connection(std::move(sdBusIntfMock_), default_bus), sdbus::Error);
103 }
104 
TEST_F(ASystemBusConnection,ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)105 TEST_F(ASystemBusConnection, ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)
106 {
107     ON_CALL(*sdBusIntfMock_, sd_bus_open_system(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(-1)));
108     ASSERT_THROW(Connection(std::move(sdBusIntfMock_), system_bus), sdbus::Error);
109 }
110 
TEST_F(ASessionBusConnection,ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)111 TEST_F(ASessionBusConnection, ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)
112 {
113     ON_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(-1)));
114     ASSERT_THROW(Connection(std::move(sdBusIntfMock_), session_bus), sdbus::Error);
115 }
116 
TEST_F(ADefaultBusConnection,ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)117 TEST_F(ADefaultBusConnection, ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)
118 {
119     ON_CALL(*sdBusIntfMock_, sd_bus_open(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
120     ON_CALL(*sdBusIntfMock_, sd_bus_flush(_)).WillByDefault(Return(-1));
121     ASSERT_THROW(Connection(std::move(sdBusIntfMock_), default_bus), sdbus::Error);
122 }
123 
TEST_F(ASystemBusConnection,ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)124 TEST_F(ASystemBusConnection, ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)
125 {
126     ON_CALL(*sdBusIntfMock_, sd_bus_open_system(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
127     ON_CALL(*sdBusIntfMock_, sd_bus_flush(_)).WillByDefault(Return(-1));
128     ASSERT_THROW(Connection(std::move(sdBusIntfMock_), system_bus), sdbus::Error);
129 }
130 
TEST_F(ASessionBusConnection,ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)131 TEST_F(ASessionBusConnection, ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)
132 {
133     ON_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
134     ON_CALL(*sdBusIntfMock_, sd_bus_flush(_)).WillByDefault(Return(-1));
135     ASSERT_THROW(Connection(std::move(sdBusIntfMock_), session_bus), sdbus::Error);
136 }
137 
138 namespace
139 {
140 template <typename _BusTypeTag>
141 class AConnectionNameRequest : public ::testing::Test
142 {
143 protected:
144     void setUpBusOpenExpectation();
145     std::unique_ptr<Connection> makeConnection();
146 
SetUp()147     void SetUp() override
148     {
149         setUpBusOpenExpectation();
150         ON_CALL(*sdBusIntfMock_, sd_bus_flush(_)).WillByDefault(Return(1));
151         ON_CALL(*sdBusIntfMock_, sd_bus_flush_close_unref(_)).WillByDefault(Return(fakeBusPtr_));
152         con_ = makeConnection();
153     }
154 
155     NiceMock<SdBusMock>* sdBusIntfMock_ = new NiceMock<SdBusMock>(); // con_ below will assume ownership
156     sd_bus* fakeBusPtr_ = reinterpret_cast<sd_bus*>(1);
157     std::unique_ptr<Connection> con_;
158 };
159 
setUpBusOpenExpectation()160 template<> void AConnectionNameRequest<Connection::default_bus_t>::setUpBusOpenExpectation()
161 {
162     EXPECT_CALL(*sdBusIntfMock_, sd_bus_open(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
163 }
setUpBusOpenExpectation()164 template<> void AConnectionNameRequest<Connection::system_bus_t>::setUpBusOpenExpectation()
165 {
166     EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_system(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
167 }
setUpBusOpenExpectation()168 template<> void AConnectionNameRequest<Connection::session_bus_t>::setUpBusOpenExpectation()
169 {
170     EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
171 }
setUpBusOpenExpectation()172 template<> void AConnectionNameRequest<Connection::remote_system_bus_t>::setUpBusOpenExpectation()
173 {
174     EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_system_remote(_, _)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
175 }
176 template <typename _BusTypeTag>
makeConnection()177 std::unique_ptr<Connection> AConnectionNameRequest<_BusTypeTag>::makeConnection()
178 {
179     return std::make_unique<Connection>(std::unique_ptr<NiceMock<SdBusMock>>(sdBusIntfMock_), _BusTypeTag{});
180 }
makeConnection()181 template<> std::unique_ptr<Connection> AConnectionNameRequest<Connection::remote_system_bus_t>::makeConnection()
182 {
183     return std::make_unique<Connection>(std::unique_ptr<NiceMock<SdBusMock>>(sdBusIntfMock_), remote_system_bus, "some host");
184 }
185 
186 typedef ::testing::Types< Connection::default_bus_t
187                         , Connection::system_bus_t
188                         , Connection::session_bus_t
189                         , Connection::remote_system_bus_t
190                         > BusTypeTags;
191 
192 TYPED_TEST_SUITE(AConnectionNameRequest, BusTypeTags);
193 }
194 
TYPED_TEST(AConnectionNameRequest,DoesNotThrowOnSuccess)195 TYPED_TEST(AConnectionNameRequest, DoesNotThrowOnSuccess)
196 {
197     EXPECT_CALL(*this->sdBusIntfMock_, sd_bus_request_name(_, _, _)).WillOnce(Return(1));
198     this->con_->requestName("org.sdbuscpp.somename");
199 }
200 
TYPED_TEST(AConnectionNameRequest,ThrowsOnFail)201 TYPED_TEST(AConnectionNameRequest, ThrowsOnFail)
202 {
203     EXPECT_CALL(*this->sdBusIntfMock_, sd_bus_request_name(_, _, _)).WillOnce(Return(-1));
204 
205     ASSERT_THROW(this->con_->requestName("org.sdbuscpp.somename"), sdbus::Error);
206 }
207