forked from Kistler-Group/sdbus-cpp
Use tag dispatching to construct various types of Connection, refactor Connection unit tests
This commit is contained in:
@ -35,54 +35,33 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
std::vector</*const */char*> to_strv(const std::vector<std::string>& strings)
|
|
||||||
{
|
|
||||||
std::vector</*const */char*> strv;
|
|
||||||
for (auto& str : strings)
|
|
||||||
strv.push_back(const_cast<char*>(str.c_str()));
|
|
||||||
strv.push_back(nullptr);
|
|
||||||
return strv;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace sdbus { namespace internal {
|
namespace sdbus { namespace internal {
|
||||||
|
|
||||||
Connection::Connection(Connection::BusType type, std::unique_ptr<ISdBus>&& interface)
|
Connection::Connection(std::unique_ptr<ISdBus>&& interface, const BusFactory& busFactory)
|
||||||
: iface_(std::move(interface))
|
: iface_(std::move(interface))
|
||||||
, busType_(type)
|
, bus_(openBus(busFactory))
|
||||||
{
|
{
|
||||||
assert(iface_ != nullptr);
|
assert(iface_ != nullptr);
|
||||||
|
|
||||||
auto bus = openBus(busType_);
|
|
||||||
bus_.reset(bus);
|
|
||||||
|
|
||||||
finishHandshake(bus);
|
|
||||||
|
|
||||||
loopExitFd_ = createProcessingLoopExitDescriptor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::Connection(const std::string& host, std::unique_ptr<ISdBus> &&interface)
|
Connection::Connection(std::unique_ptr<ISdBus>&& interface, system_bus_t)
|
||||||
: iface_(std::move(interface))
|
: Connection(std::move(interface), [this](sd_bus** bus){ return iface_->sd_bus_open_system(bus); })
|
||||||
, busType_(BusType::eRemoteSystem)
|
|
||||||
, host_(host)
|
|
||||||
{
|
{
|
||||||
assert(iface_ != nullptr);
|
}
|
||||||
|
|
||||||
auto bus = openBus(busType_);
|
Connection::Connection(std::unique_ptr<ISdBus>&& interface, session_bus_t)
|
||||||
bus_.reset(bus);
|
: Connection(std::move(interface), [this](sd_bus** bus){ return iface_->sd_bus_open_user(bus); })
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
finishHandshake(bus);
|
Connection::Connection(std::unique_ptr<ISdBus>&& interface, remote_system_bus_t, const std::string& host)
|
||||||
|
: Connection(std::move(interface), [this, &host](sd_bus** bus){ return iface_->sd_bus_open_system_remote(bus, host.c_str()); })
|
||||||
loopExitFd_ = createProcessingLoopExitDescriptor();
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::~Connection()
|
Connection::~Connection()
|
||||||
{
|
{
|
||||||
leaveProcessingLoop();
|
leaveProcessingLoop();
|
||||||
closeProcessingLoopExitDescriptor(loopExitFd_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::requestName(const std::string& name)
|
void Connection::requestName(const std::string& name)
|
||||||
@ -301,23 +280,15 @@ SlotPtr Connection::registerSignalHandler( const std::string& objectPath
|
|||||||
return {slot, [this](void *slot){ iface_->sd_bus_slot_unref((sd_bus_slot*)slot); }};
|
return {slot, [this](void *slot){ iface_->sd_bus_slot_unref((sd_bus_slot*)slot); }};
|
||||||
}
|
}
|
||||||
|
|
||||||
sd_bus* Connection::openBus(Connection::BusType type)
|
Connection::BusPtr Connection::openBus(const BusFactory& busFactory)
|
||||||
{
|
{
|
||||||
sd_bus* bus{};
|
sd_bus* bus{};
|
||||||
int r = 0;
|
int r = busFactory(&bus);
|
||||||
if (type == BusType::eSystem)
|
|
||||||
r = iface_->sd_bus_open_system(&bus);
|
|
||||||
else if (type == BusType::eSession)
|
|
||||||
r = iface_->sd_bus_open_user(&bus);
|
|
||||||
else if (type == BusType::eRemoteSystem)
|
|
||||||
r = iface_->sd_bus_open_system_remote(&bus, host_.c_str());
|
|
||||||
else
|
|
||||||
assert(false);
|
|
||||||
|
|
||||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to open bus", -r);
|
SDBUS_THROW_ERROR_IF(r < 0, "Failed to open bus", -r);
|
||||||
assert(bus != nullptr);
|
|
||||||
|
|
||||||
return bus;
|
BusPtr busPtr{bus, [this](sd_bus* bus){ return iface_->sd_bus_flush_close_unref(bus); }};
|
||||||
|
finishHandshake(busPtr.get());
|
||||||
|
return busPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::finishHandshake(sd_bus* bus)
|
void Connection::finishHandshake(sd_bus* bus)
|
||||||
@ -333,33 +304,19 @@ void Connection::finishHandshake(sd_bus* bus)
|
|||||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to flush bus on opening", -r);
|
SDBUS_THROW_ERROR_IF(r < 0, "Failed to flush bus on opening", -r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::createProcessingLoopExitDescriptor()
|
|
||||||
{
|
|
||||||
auto r = eventfd(0, EFD_SEMAPHORE | EFD_CLOEXEC | EFD_NONBLOCK);
|
|
||||||
|
|
||||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to create event object", -errno);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::closeProcessingLoopExitDescriptor(int fd)
|
|
||||||
{
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::notifyProcessingLoopToExit()
|
void Connection::notifyProcessingLoopToExit()
|
||||||
{
|
{
|
||||||
assert(loopExitFd_ >= 0);
|
assert(loopExitFd_.fd >= 0);
|
||||||
|
|
||||||
uint64_t value = 1;
|
uint64_t value = 1;
|
||||||
auto r = write(loopExitFd_, &value, sizeof(value));
|
auto r = write(loopExitFd_.fd, &value, sizeof(value));
|
||||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to notify processing loop", -errno);
|
SDBUS_THROW_ERROR_IF(r < 0, "Failed to notify processing loop", -errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::clearExitNotification()
|
void Connection::clearExitNotification()
|
||||||
{
|
{
|
||||||
uint64_t value{};
|
uint64_t value{};
|
||||||
auto r = read(loopExitFd_, &value, sizeof(value));
|
auto r = read(loopExitFd_.fd, &value, sizeof(value));
|
||||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to read from the event descriptor", -errno);
|
SDBUS_THROW_ERROR_IF(r < 0, "Failed to read from the event descriptor", -errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,10 +342,10 @@ bool Connection::waitForNextRequest()
|
|||||||
auto bus = bus_.get();
|
auto bus = bus_.get();
|
||||||
|
|
||||||
assert(bus != nullptr);
|
assert(bus != nullptr);
|
||||||
assert(loopExitFd_ != 0);
|
assert(loopExitFd_.fd != 0);
|
||||||
|
|
||||||
auto sdbusPollData = getProcessLoopPollData();
|
auto sdbusPollData = getProcessLoopPollData();
|
||||||
struct pollfd fds[] = {{sdbusPollData.fd, sdbusPollData.events, 0}, {loopExitFd_, POLLIN, 0}};
|
struct pollfd fds[] = {{sdbusPollData.fd, sdbusPollData.events, 0}, {loopExitFd_.fd, POLLIN, 0}};
|
||||||
auto fdsCount = sizeof(fds)/sizeof(fds[0]);
|
auto fdsCount = sizeof(fds)/sizeof(fds[0]);
|
||||||
|
|
||||||
auto timeout = sdbusPollData.timeout_usec == (uint64_t) -1 ? (uint64_t)-1 : (sdbusPollData.timeout_usec+999)/1000;
|
auto timeout = sdbusPollData.timeout_usec == (uint64_t) -1 ? (uint64_t)-1 : (sdbusPollData.timeout_usec+999)/1000;
|
||||||
@ -422,6 +379,27 @@ std::string Connection::composeSignalMatchFilter( const std::string& objectPath
|
|||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector</*const */char*> Connection::to_strv(const std::vector<std::string>& strings)
|
||||||
|
{
|
||||||
|
std::vector</*const */char*> strv;
|
||||||
|
for (auto& str : strings)
|
||||||
|
strv.push_back(const_cast<char*>(str.c_str()));
|
||||||
|
strv.push_back(nullptr);
|
||||||
|
return strv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection::LoopExitEventFd::LoopExitEventFd()
|
||||||
|
{
|
||||||
|
fd = eventfd(0, EFD_SEMAPHORE | EFD_CLOEXEC | EFD_NONBLOCK);
|
||||||
|
SDBUS_THROW_ERROR_IF(fd < 0, "Failed to create event object", -errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection::LoopExitEventFd::~LoopExitEventFd()
|
||||||
|
{
|
||||||
|
assert(fd >= 0);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
namespace sdbus {
|
namespace sdbus {
|
||||||
@ -440,8 +418,8 @@ std::unique_ptr<sdbus::IConnection> createSystemBusConnection()
|
|||||||
{
|
{
|
||||||
auto interface = std::make_unique<sdbus::internal::SdBus>();
|
auto interface = std::make_unique<sdbus::internal::SdBus>();
|
||||||
assert(interface != nullptr);
|
assert(interface != nullptr);
|
||||||
return std::make_unique<sdbus::internal::Connection>( sdbus::internal::Connection::BusType::eSystem
|
constexpr sdbus::internal::Connection::system_bus_t system_bus;
|
||||||
, std::move(interface));
|
return std::make_unique<sdbus::internal::Connection>(std::move(interface), system_bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<sdbus::IConnection> createSystemBusConnection(const std::string& name)
|
std::unique_ptr<sdbus::IConnection> createSystemBusConnection(const std::string& name)
|
||||||
@ -455,8 +433,8 @@ std::unique_ptr<sdbus::IConnection> createSessionBusConnection()
|
|||||||
{
|
{
|
||||||
auto interface = std::make_unique<sdbus::internal::SdBus>();
|
auto interface = std::make_unique<sdbus::internal::SdBus>();
|
||||||
assert(interface != nullptr);
|
assert(interface != nullptr);
|
||||||
return std::make_unique<sdbus::internal::Connection>( sdbus::internal::Connection::BusType::eSession
|
constexpr sdbus::internal::Connection::session_bus_t session_bus;
|
||||||
, std::move(interface));
|
return std::make_unique<sdbus::internal::Connection>(std::move(interface), session_bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<sdbus::IConnection> createSessionBusConnection(const std::string& name)
|
std::unique_ptr<sdbus::IConnection> createSessionBusConnection(const std::string& name)
|
||||||
@ -470,8 +448,8 @@ std::unique_ptr<sdbus::IConnection> createRemoteSystemBusConnection(const std::s
|
|||||||
{
|
{
|
||||||
auto interface = std::make_unique<sdbus::internal::SdBus>();
|
auto interface = std::make_unique<sdbus::internal::SdBus>();
|
||||||
assert(interface != nullptr);
|
assert(interface != nullptr);
|
||||||
return std::make_unique<sdbus::internal::Connection>( host
|
constexpr sdbus::internal::Connection::remote_system_bus_t remote_system_bus;
|
||||||
, std::move(interface));
|
return std::make_unique<sdbus::internal::Connection>(std::move(interface), remote_system_bus, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#include <systemd/sd-bus.h>
|
#include <systemd/sd-bus.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace sdbus { namespace internal {
|
namespace sdbus { namespace internal {
|
||||||
|
|
||||||
@ -43,15 +45,14 @@ namespace sdbus { namespace internal {
|
|||||||
, public sdbus::internal::IConnection // Internal, private interface
|
, public sdbus::internal::IConnection // Internal, private interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class BusType
|
// Bus type tags
|
||||||
{
|
struct system_bus_t{};
|
||||||
eSystem,
|
struct session_bus_t{};
|
||||||
eSession,
|
struct remote_system_bus_t{};
|
||||||
eRemoteSystem,
|
|
||||||
};
|
|
||||||
|
|
||||||
Connection(BusType type, std::unique_ptr<ISdBus>&& interface);
|
Connection(std::unique_ptr<ISdBus>&& interface, system_bus_t);
|
||||||
Connection(const std::string& host, std::unique_ptr<ISdBus>&& interface);
|
Connection(std::unique_ptr<ISdBus>&& interface, session_bus_t);
|
||||||
|
Connection(std::unique_ptr<ISdBus>&& interface, remote_system_bus_t, const std::string& host);
|
||||||
~Connection() override;
|
~Connection() override;
|
||||||
|
|
||||||
void requestName(const std::string& name) override;
|
void requestName(const std::string& name) override;
|
||||||
@ -102,10 +103,12 @@ namespace sdbus { namespace internal {
|
|||||||
, void* userData ) override;
|
, void* userData ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sd_bus* openBus(Connection::BusType type);
|
using BusFactory = std::function<int(sd_bus**)>;
|
||||||
|
using BusPtr = std::unique_ptr<sd_bus, std::function<sd_bus*(sd_bus*)>>;
|
||||||
|
Connection(std::unique_ptr<ISdBus>&& interface, const BusFactory& busFactory);
|
||||||
|
|
||||||
|
BusPtr openBus(const std::function<int(sd_bus**)>& busFactory);
|
||||||
void finishHandshake(sd_bus* bus);
|
void finishHandshake(sd_bus* bus);
|
||||||
static int createProcessingLoopExitDescriptor();
|
|
||||||
static void closeProcessingLoopExitDescriptor(int fd);
|
|
||||||
bool waitForNextRequest();
|
bool waitForNextRequest();
|
||||||
static std::string composeSignalMatchFilter( const std::string& objectPath
|
static std::string composeSignalMatchFilter( const std::string& objectPath
|
||||||
, const std::string& interfaceName
|
, const std::string& interfaceName
|
||||||
@ -113,18 +116,20 @@ namespace sdbus { namespace internal {
|
|||||||
void notifyProcessingLoopToExit();
|
void notifyProcessingLoopToExit();
|
||||||
void clearExitNotification();
|
void clearExitNotification();
|
||||||
void joinWithProcessingLoop();
|
void joinWithProcessingLoop();
|
||||||
|
static std::vector</*const */char*> to_strv(const std::vector<std::string>& strings);
|
||||||
|
|
||||||
|
struct LoopExitEventFd
|
||||||
|
{
|
||||||
|
LoopExitEventFd();
|
||||||
|
~LoopExitEventFd();
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<ISdBus> iface_;
|
std::unique_ptr<ISdBus> iface_;
|
||||||
std::unique_ptr<sd_bus, std::function<sd_bus*(sd_bus*)>> bus_ {nullptr, [this](sd_bus* bus)
|
BusPtr bus_;
|
||||||
{
|
|
||||||
return iface_->sd_bus_flush_close_unref(bus);
|
|
||||||
}};
|
|
||||||
BusType busType_;
|
|
||||||
|
|
||||||
std::thread asyncLoopThread_;
|
std::thread asyncLoopThread_;
|
||||||
int loopExitFd_{-1};
|
LoopExitEventFd loopExitFd_;
|
||||||
std::string host_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
@ -35,17 +35,18 @@ using ::testing::DoAll;
|
|||||||
using ::testing::SetArgPointee;
|
using ::testing::SetArgPointee;
|
||||||
using ::testing::Return;
|
using ::testing::Return;
|
||||||
using ::testing::NiceMock;
|
using ::testing::NiceMock;
|
||||||
|
using sdbus::internal::Connection;
|
||||||
using BusType = sdbus::internal::Connection::BusType;
|
constexpr sdbus::internal::Connection::system_bus_t system_bus;
|
||||||
|
constexpr sdbus::internal::Connection::session_bus_t session_bus;
|
||||||
|
constexpr sdbus::internal::Connection::remote_system_bus_t remote_system_bus;
|
||||||
|
|
||||||
class ConnectionCreationTest : public ::testing::Test
|
class ConnectionCreationTest : public ::testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
ConnectionCreationTest() = default;
|
ConnectionCreationTest() = default;
|
||||||
|
|
||||||
std::unique_ptr<NiceMock<SdBusMock>> mock_ { std::make_unique<NiceMock<SdBusMock>>() };
|
std::unique_ptr<NiceMock<SdBusMock>> sdBusIntfMock_ = std::make_unique<NiceMock<SdBusMock>>();
|
||||||
sd_bus* STUB_ { reinterpret_cast<sd_bus*>(1) };
|
sd_bus* fakeBusPtr_ = reinterpret_cast<sd_bus*>(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
using ASystemBusConnection = ConnectionCreationTest;
|
using ASystemBusConnection = ConnectionCreationTest;
|
||||||
@ -53,99 +54,119 @@ using ASessionBusConnection = ConnectionCreationTest;
|
|||||||
|
|
||||||
TEST_F(ASystemBusConnection, OpensAndFlushesBusWhenCreated)
|
TEST_F(ASystemBusConnection, OpensAndFlushesBusWhenCreated)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(*mock_, sd_bus_open_system(_)).WillOnce(DoAll(SetArgPointee<0>(STUB_), Return(1)));
|
EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_system(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||||
EXPECT_CALL(*mock_, sd_bus_flush(_)).Times(1);
|
EXPECT_CALL(*sdBusIntfMock_, sd_bus_flush(_)).Times(1);
|
||||||
sdbus::internal::Connection(BusType::eSystem, std::move(mock_));
|
Connection(std::move(sdBusIntfMock_), system_bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ASessionBusConnection, OpensAndFlushesBusWhenCreated)
|
TEST_F(ASessionBusConnection, OpensAndFlushesBusWhenCreated)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(*mock_, sd_bus_open_user(_)).WillOnce(DoAll(SetArgPointee<0>(STUB_), Return(1)));
|
EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||||
EXPECT_CALL(*mock_, sd_bus_flush(_)).Times(1);
|
EXPECT_CALL(*sdBusIntfMock_, sd_bus_flush(_)).Times(1);
|
||||||
sdbus::internal::Connection(BusType::eSession, std::move(mock_));
|
Connection(std::move(sdBusIntfMock_), session_bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ASystemBusConnection, ClosesAndUnrefsBusWhenDestructed)
|
TEST_F(ASystemBusConnection, ClosesAndUnrefsBusWhenDestructed)
|
||||||
{
|
{
|
||||||
ON_CALL(*mock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(1)));
|
ON_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||||
EXPECT_CALL(*mock_, sd_bus_flush_close_unref(_)).Times(1);
|
EXPECT_CALL(*sdBusIntfMock_, sd_bus_flush_close_unref(_)).Times(1);
|
||||||
sdbus::internal::Connection(BusType::eSession, std::move(mock_));
|
Connection(std::move(sdBusIntfMock_), session_bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ASessionBusConnection, ClosesAndUnrefsBusWhenDestructed)
|
TEST_F(ASessionBusConnection, ClosesAndUnrefsBusWhenDestructed)
|
||||||
{
|
{
|
||||||
ON_CALL(*mock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(1)));
|
ON_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||||
EXPECT_CALL(*mock_, sd_bus_flush_close_unref(_)).Times(1);
|
EXPECT_CALL(*sdBusIntfMock_, sd_bus_flush_close_unref(_)).Times(1);
|
||||||
sdbus::internal::Connection(BusType::eSession, std::move(mock_));
|
Connection(std::move(sdBusIntfMock_), session_bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ASystemBusConnection, ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)
|
TEST_F(ASystemBusConnection, ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)
|
||||||
{
|
{
|
||||||
ON_CALL(*mock_, sd_bus_open_system(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(-1)));
|
ON_CALL(*sdBusIntfMock_, sd_bus_open_system(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(-1)));
|
||||||
ASSERT_THROW(sdbus::internal::Connection(BusType::eSystem, std::move(mock_)), sdbus::Error);
|
ASSERT_THROW(Connection(std::move(sdBusIntfMock_), system_bus), sdbus::Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ASessionBusConnection, ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)
|
TEST_F(ASessionBusConnection, ThrowsErrorWhenOpeningTheBusFailsDuringConstruction)
|
||||||
{
|
{
|
||||||
ON_CALL(*mock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(-1)));
|
ON_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(-1)));
|
||||||
ASSERT_THROW(sdbus::internal::Connection(BusType::eSession, std::move(mock_)), sdbus::Error);
|
ASSERT_THROW(Connection(std::move(sdBusIntfMock_), session_bus), sdbus::Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ASystemBusConnection, ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)
|
TEST_F(ASystemBusConnection, ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)
|
||||||
{
|
{
|
||||||
ON_CALL(*mock_, sd_bus_open_system(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(1)));
|
ON_CALL(*sdBusIntfMock_, sd_bus_open_system(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||||
ON_CALL(*mock_, sd_bus_flush(_)).WillByDefault(Return(-1));
|
ON_CALL(*sdBusIntfMock_, sd_bus_flush(_)).WillByDefault(Return(-1));
|
||||||
ASSERT_THROW(sdbus::internal::Connection(BusType::eSystem, std::move(mock_)), sdbus::Error);
|
ASSERT_THROW(Connection(std::move(sdBusIntfMock_), system_bus), sdbus::Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ASessionBusConnection, ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)
|
TEST_F(ASessionBusConnection, ThrowsErrorWhenFlushingTheBusFailsDuringConstruction)
|
||||||
{
|
{
|
||||||
ON_CALL(*mock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(STUB_), Return(1)));
|
ON_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillByDefault(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||||
ON_CALL(*mock_, sd_bus_flush(_)).WillByDefault(Return(-1));
|
ON_CALL(*sdBusIntfMock_, sd_bus_flush(_)).WillByDefault(Return(-1));
|
||||||
ASSERT_THROW(sdbus::internal::Connection(BusType::eSession, std::move(mock_)), sdbus::Error);
|
ASSERT_THROW(Connection(std::move(sdBusIntfMock_), session_bus), sdbus::Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConnectionRequestTest : public ::testing::TestWithParam<BusType>
|
namespace
|
||||||
|
{
|
||||||
|
template <typename _BusTypeTag>
|
||||||
|
class AConnectionNameRequest : public ::testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
ConnectionRequestTest() = default;
|
void setUpBusOpenExpectation();
|
||||||
|
std::unique_ptr<Connection> makeConnection();
|
||||||
|
|
||||||
void SetUp() override
|
void SetUp() override
|
||||||
{
|
{
|
||||||
switch (GetParam())
|
setUpBusOpenExpectation();
|
||||||
{
|
ON_CALL(*sdBusIntfMock_, sd_bus_flush(_)).WillByDefault(Return(1));
|
||||||
case BusType::eSystem:
|
ON_CALL(*sdBusIntfMock_, sd_bus_flush_close_unref(_)).WillByDefault(Return(fakeBusPtr_));
|
||||||
EXPECT_CALL(*mock_, sd_bus_open_system(_)).WillOnce(DoAll(SetArgPointee<0>(STUB_), Return(1)));
|
con_ = makeConnection();
|
||||||
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>>() };
|
NiceMock<SdBusMock>* sdBusIntfMock_ = new NiceMock<SdBusMock>(); // con_ below will assume ownership
|
||||||
sd_bus* STUB_ { reinterpret_cast<sd_bus*>(1) };
|
sd_bus* fakeBusPtr_ = reinterpret_cast<sd_bus*>(1);
|
||||||
|
std::unique_ptr<Connection> con_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using AConnectionNameRequest = ConnectionRequestTest;
|
template<> void AConnectionNameRequest<Connection::system_bus_t>::setUpBusOpenExpectation()
|
||||||
|
|
||||||
TEST_P(AConnectionNameRequest, DoesNotThrowOnSuccess)
|
|
||||||
{
|
{
|
||||||
EXPECT_CALL(*mock_, sd_bus_request_name(_, _, _)).WillOnce(Return(1));
|
EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_system(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||||
sdbus::internal::Connection(GetParam(), std::move(mock_)).requestName("");
|
}
|
||||||
|
template<> void AConnectionNameRequest<Connection::session_bus_t>::setUpBusOpenExpectation()
|
||||||
|
{
|
||||||
|
EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_user(_)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||||
|
}
|
||||||
|
template<> void AConnectionNameRequest<Connection::remote_system_bus_t>::setUpBusOpenExpectation()
|
||||||
|
{
|
||||||
|
EXPECT_CALL(*sdBusIntfMock_, sd_bus_open_system_remote(_, _)).WillOnce(DoAll(SetArgPointee<0>(fakeBusPtr_), Return(1)));
|
||||||
|
}
|
||||||
|
template <typename _BusTypeTag>
|
||||||
|
std::unique_ptr<Connection> AConnectionNameRequest<_BusTypeTag>::makeConnection()
|
||||||
|
{
|
||||||
|
return std::make_unique<Connection>(std::unique_ptr<NiceMock<SdBusMock>>(sdBusIntfMock_), _BusTypeTag{});
|
||||||
|
}
|
||||||
|
template<> std::unique_ptr<Connection> AConnectionNameRequest<Connection::remote_system_bus_t>::makeConnection()
|
||||||
|
{
|
||||||
|
return std::make_unique<Connection>(std::unique_ptr<NiceMock<SdBusMock>>(sdBusIntfMock_), remote_system_bus, "some host");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(AConnectionNameRequest, ThrowsOnFail)
|
typedef ::testing::Types< Connection::system_bus_t
|
||||||
{
|
, Connection::session_bus_t
|
||||||
EXPECT_CALL(*mock_, sd_bus_request_name(_, _, _)).WillOnce(Return(-1));
|
, Connection::remote_system_bus_t
|
||||||
|
> BusTypeTags;
|
||||||
|
|
||||||
sdbus::internal::Connection conn_(GetParam(), std::move(mock_));
|
TYPED_TEST_SUITE(AConnectionNameRequest, BusTypeTags);
|
||||||
ASSERT_THROW(conn_.requestName(""), sdbus::Error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// INSTANTIATE_TEST_SUITE_P is defined in googletest master, but not in googletest v1.8.1 that we are using now
|
TYPED_TEST(AConnectionNameRequest, DoesNotThrowOnSuccess)
|
||||||
INSTANTIATE_TEST_CASE_P(Request, AConnectionNameRequest, ::testing::Values(BusType::eSystem, BusType::eSession));
|
{
|
||||||
//INSTANTIATE_TEST_SUITE_P(Request, AConnectionNameRequest, ::testing::Values(BusType::eSystem, BusType::eSession))
|
EXPECT_CALL(*this->sdBusIntfMock_, sd_bus_request_name(_, _, _)).WillOnce(Return(1));
|
||||||
|
this->con_->requestName("org.sdbuscpp.somename");
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(AConnectionNameRequest, ThrowsOnFail)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(*this->sdBusIntfMock_, sd_bus_request_name(_, _, _)).WillOnce(Return(-1));
|
||||||
|
|
||||||
|
ASSERT_THROW(this->con_->requestName("org.sdbuscpp.somename"), sdbus::Error);
|
||||||
|
}
|
||||||
|
@ -121,7 +121,7 @@ namespace
|
|||||||
, ComplexType
|
, ComplexType
|
||||||
> DBusSupportedTypes;
|
> DBusSupportedTypes;
|
||||||
|
|
||||||
TYPED_TEST_CASE(Type2DBusTypeSignatureConversion, DBusSupportedTypes);
|
TYPED_TEST_SUITE(Type2DBusTypeSignatureConversion, DBusSupportedTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------*/
|
/*-------------------------------------*/
|
||||||
|
@ -58,6 +58,7 @@ public:
|
|||||||
|
|
||||||
MOCK_METHOD1(sd_bus_open_user, int(sd_bus **ret));
|
MOCK_METHOD1(sd_bus_open_user, int(sd_bus **ret));
|
||||||
MOCK_METHOD1(sd_bus_open_system, int(sd_bus **ret));
|
MOCK_METHOD1(sd_bus_open_system, int(sd_bus **ret));
|
||||||
|
MOCK_METHOD2(sd_bus_open_system_remote, int(sd_bus **ret, const char *host));
|
||||||
MOCK_METHOD3(sd_bus_request_name, int(sd_bus *bus, const char *name, uint64_t flags));
|
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_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_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));
|
||||||
|
Reference in New Issue
Block a user