Mock sdbus lib, add unit tests of Connection class.

Introduce mock of sdbus library through extracting its interface. Set up unit tests of Connection class through injection of sdbusMock to constructor. Clients of Connections class should use fabrics instead.
This commit is contained in:
ardazishvili
2019-03-17 18:02:47 +03:00
parent 8c5c774727
commit 2b83d7ca2d
12 changed files with 529 additions and 35 deletions
+2 -1
View File
@@ -36,7 +36,8 @@ set(UNITTESTS_SRCS
${UNITTESTS_SOURCE_DIR}/libsdbus-c++_unittests.cpp
${UNITTESTS_SOURCE_DIR}/Message_test.cpp
${UNITTESTS_SOURCE_DIR}/Types_test.cpp
${UNITTESTS_SOURCE_DIR}/TypeTraits_test.cpp)
${UNITTESTS_SOURCE_DIR}/TypeTraits_test.cpp
${UNITTESTS_SOURCE_DIR}/Connection_test.cpp)
set(INTEGRATIONTESTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/integrationtests)
set(INTEGRATIONTESTS_SRCS
@@ -25,6 +25,7 @@
// Own
#include "Connection.h"
#include "SdBus.h"
#include "TestingAdaptor.h"
#include "TestingProxy.h"
@@ -87,7 +88,8 @@ public:
std::unique_ptr<TestingProxy> m_proxy;
};
sdbus::internal::Connection AdaptorAndProxyFixture::m_connection{sdbus::internal::Connection::BusType::eSystem};
sdbus::internal::Connection AdaptorAndProxyFixture::m_connection{sdbus::internal::Connection::BusType::eSystem,
std::make_unique<SdBus>(SdBus())};
}
+148
View File
@@ -0,0 +1,148 @@
/**
* (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
*
* @file Connection_test.cpp
* @author Ardazishvili Roman (ardazishvili.roman@yandex.ru)
*
* Created on: Feb 4, 2019
* Project: sdbus-c++
* Description: High-level D-Bus IPC C++ library based on sd-bus
*
* This file is part of sdbus-c++.
*
* sdbus-c++ is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* sdbus-c++ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with sdbus-c++. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Connection.h"
#include "unittests/mocks/SdBusMock.h"
#include <gtest/gtest.h>
using ::testing::_;
using ::testing::DoAll;
using ::testing::SetArgPointee;
using ::testing::Return;
using ::testing::NiceMock;
using BusType = sdbus::internal::Connection::BusType;
class ConnectionCreationTest : public ::testing::Test
{
protected:
ConnectionCreationTest() = default;
std::unique_ptr<NiceMock<SdBusMock>> mock_ { std::make_unique<NiceMock<SdBusMock>>() };
sd_bus* STUB_ { reinterpret_cast<sd_bus*>(1) };
};
using ASystemBusConnection = ConnectionCreationTest;
using ASessionBusConnection = ConnectionCreationTest;
TEST_F(ASystemBusConnection, OpensAndFlushesBusWhenCreated)
{
EXPECT_CALL(*mock_, sd_bus_open_system(_)).WillOnce(DoAll(SetArgPointee<0>(STUB_), Return(1)));
EXPECT_CALL(*mock_, sd_bus_flush(_)).Times(1);
sdbus::internal::Connection(BusType::eSystem, std::move(mock_));
}
TEST_F(ASessionBusConnection, OpensAndFlushesBusWhenCreated)
{
EXPECT_CALL(*mock_, sd_bus_open_user(_)).WillOnce(DoAll(SetArgPointee<0>(STUB_), Return(1)));
EXPECT_CALL(*mock_, sd_bus_flush(_)).Times(1);
sdbus::internal::Connection(BusType::eSession, std::move(mock_));
}
TEST_F(ASystemBusConnection, ClosesAndUnrefsBusWhenDestructed)
{
ON_CALL(*mock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(1)));
EXPECT_CALL(*mock_, sd_bus_flush_close_unref(_)).Times(1);
sdbus::internal::Connection(BusType::eSession, std::move(mock_));
}
TEST_F(ASessionBusConnection, ClosesAndUnrefsBusWhenDestructed)
{
ON_CALL(*mock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(1)));
EXPECT_CALL(*mock_, sd_bus_flush_close_unref(_)).Times(1);
sdbus::internal::Connection(BusType::eSession, std::move(mock_));
}
TEST_F(ASystemBusConnection, ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)
{
ON_CALL(*mock_, sd_bus_open_system(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(-1)));
ASSERT_THROW(sdbus::internal::Connection(BusType::eSystem, std::move(mock_)), sdbus::Error);
}
TEST_F(ASessionBusConnection, ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)
{
ON_CALL(*mock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(-1)));
ASSERT_THROW(sdbus::internal::Connection(BusType::eSession, std::move(mock_)), sdbus::Error);
}
TEST_F(ASystemBusConnection, ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)
{
ON_CALL(*mock_, sd_bus_open_system(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(1)));
ON_CALL(*mock_, sd_bus_flush(_)).WillByDefault(Return(-1));
ASSERT_THROW(sdbus::internal::Connection(BusType::eSystem, std::move(mock_)), sdbus::Error);
}
TEST_F(ASessionBusConnection, ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)
{
ON_CALL(*mock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(1)));
ON_CALL(*mock_, sd_bus_flush(_)).WillByDefault(Return(-1));
ASSERT_THROW(sdbus::internal::Connection(BusType::eSession, std::move(mock_)), sdbus::Error);
}
class ConnectionRequestTest : public ::testing::TestWithParam<BusType>
{
protected:
ConnectionRequestTest() = default;
void SetUp() override
{
switch (GetParam())
{
case BusType::eSystem:
EXPECT_CALL(*mock_, sd_bus_open_system(_)).WillOnce(DoAll(SetArgPointee<0>(STUB_), Return(1)));
break;
case BusType::eSession:
EXPECT_CALL(*mock_, sd_bus_open_user(_)).WillOnce(DoAll(SetArgPointee<0>(STUB_), Return(1)));
break;
default:
break;
}
ON_CALL(*mock_, sd_bus_flush(_)).WillByDefault(Return(1));
ON_CALL(*mock_, sd_bus_flush_close_unref(_)).WillByDefault(Return(STUB_));
}
std::unique_ptr<NiceMock<SdBusMock>> mock_ { std::make_unique<NiceMock<SdBusMock>>() };
sd_bus* STUB_ { reinterpret_cast<sd_bus*>(1) };
};
using AConnectionNameRequest = ConnectionRequestTest;
TEST_P(AConnectionNameRequest, DoesNotThrowOnSuccess)
{
EXPECT_CALL(*mock_, sd_bus_request_name(_, _, _)).WillOnce(Return(1));
sdbus::internal::Connection(GetParam(), std::move(mock_)).requestName("");
}
TEST_P(AConnectionNameRequest, ThrowsOnFail)
{
EXPECT_CALL(*mock_, sd_bus_request_name(_, _, _)).WillOnce(Return(-1));
auto conn_ = sdbus::internal::Connection(GetParam(), std::move(mock_)) ;
ASSERT_THROW(conn_.requestName(""), sdbus::Error);
}
INSTANTIATE_TEST_SUITE_P(Request, AConnectionNameRequest, ::testing::Values(BusType::eSystem, BusType::eSession));
+55
View File
@@ -0,0 +1,55 @@
/**
* (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
*
* @file SdBusMock.h
* @author Ardazishvili Roman (ardazishvili.roman@yandex.ru)
*
* Created on: Mar 12, 2019
* Project: sdbus-c++
* Description: High-level D-Bus IPC C++ library based on sd-bus
*
* This file is part of sdbus-c++.
*
* sdbus-c++ is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* sdbus-c++ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with sdbus-c++. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SDBUS_CXX_SDBUS_MOCK_H
#define SDBUS_CXX_SDBUS_MOCK_H
#include "ISdBus.h"
#include <gmock/gmock.h>
class SdBusMock : public ISdBus
{
public:
MOCK_METHOD3(sd_bus_request_name, int(sd_bus *bus, const char *name, uint64_t flags));
MOCK_METHOD2(sd_bus_release_name, int(sd_bus *bus, const char *name));
MOCK_METHOD6(sd_bus_add_object_vtable, int(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata));
MOCK_METHOD1(sd_bus_slot_unref, sd_bus_slot*(sd_bus_slot *slot));
MOCK_METHOD6(sd_bus_message_new_method_call, int(sd_bus *bus, sd_bus_message **m, const char *destination, const char *path, const char *interface, const char *member));
MOCK_METHOD1(sd_bus_message_unref, sd_bus_message* (sd_bus_message *m));
MOCK_METHOD5(sd_bus_message_new_signal, int(sd_bus *bus, sd_bus_message **m, const char *path, const char *interface, const char *member));
MOCK_METHOD5(sd_bus_add_match, int(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata));
MOCK_METHOD1(sd_bus_open_user, int(sd_bus **ret));
MOCK_METHOD1(sd_bus_open_system, int(sd_bus **ret));
MOCK_METHOD1(sd_bus_flush, int(sd_bus *bus));
MOCK_METHOD2(sd_bus_process, int(sd_bus *bus, sd_bus_message **r));
MOCK_METHOD1(sd_bus_get_fd, int(sd_bus *bus));
MOCK_METHOD1(sd_bus_get_events, int(sd_bus *bus));
MOCK_METHOD2(sd_bus_get_timeout, int(sd_bus *bus, uint64_t *timeout_usec));
MOCK_METHOD1(sd_bus_flush_close_unref, sd_bus *(sd_bus *bus));
};
#endif //SDBUS_CXX_SDBUS_MOCK_H