forked from Kistler-Group/sdbus-cpp
feat: add integration for sd-event
This commit is contained in:
@ -34,6 +34,8 @@
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
struct sd_event;
|
||||
|
||||
namespace sdbus {
|
||||
|
||||
/********************************************//**
|
||||
@ -127,7 +129,7 @@ namespace sdbus {
|
||||
virtual void releaseName(const std::string& name) = 0;
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the unique name of a connection. E.g. ":1.xx"
|
||||
* @brief Retrieves the unique name of a connection. E.g. ":1.xx"
|
||||
*
|
||||
* @throws sdbus::Error in case of failure
|
||||
*/
|
||||
@ -305,6 +307,32 @@ namespace sdbus {
|
||||
*/
|
||||
virtual void addMatch(const std::string& match, message_handler callback, floating_slot_t) = 0;
|
||||
|
||||
/*!
|
||||
* @brief Attaches the bus connection to an sd-event event loop
|
||||
*
|
||||
* @param[in] event sd-event event loop object
|
||||
* @param[in] priority Specified priority
|
||||
*
|
||||
* @throws sdbus::Error in case of failure
|
||||
*
|
||||
* See `man sd_bus_attach_event'.
|
||||
*/
|
||||
virtual void attachSdEventLoop(sd_event *event, int priority = 0) = 0;
|
||||
|
||||
/*!
|
||||
* @brief Detaches the bus connection from an sd-event event loop
|
||||
*
|
||||
* @throws sdbus::Error in case of failure
|
||||
*/
|
||||
virtual void detachSdEventLoop() = 0;
|
||||
|
||||
/*!
|
||||
* @brief Gets current sd-event event loop for the bus connection
|
||||
*
|
||||
* @return Pointer to event loop object if attached, nullptr otherwise
|
||||
*/
|
||||
virtual sd_event *getSdEventLoop() = 0;
|
||||
|
||||
/*!
|
||||
* @copydoc IConnection::enterEventLoop()
|
||||
*
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <sdbus-c++/Error.h>
|
||||
#include "ScopeGuard.h"
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <sys/eventfd.h>
|
||||
@ -223,6 +224,102 @@ void Connection::addMatch(const std::string& match, message_handler callback, fl
|
||||
floatingMatchRules_.push_back(addMatch(match, std::move(callback)));
|
||||
}
|
||||
|
||||
void Connection::attachSdEventLoop(sd_event *event, int priority)
|
||||
{
|
||||
// Get default event if no event is provided by the caller
|
||||
if (event != nullptr)
|
||||
event = sd_event_ref(event);
|
||||
else
|
||||
(void)sd_event_default(&event);
|
||||
SDBUS_THROW_ERROR_IF(!event, "Invalid sd_event handle", EINVAL);
|
||||
Slot sdEvent{event, [](void* event){ sd_event_unref((sd_event*)event); }};
|
||||
// TODO: auto sdEvent = createSdEventSlot(...);
|
||||
|
||||
sd_event_source *timeEventSource{};
|
||||
auto r = sd_event_add_time(event, &timeEventSource, CLOCK_MONOTONIC, 0, 0, onSdTimerEvent, this);
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to add timer event", -r);
|
||||
Slot sdTimeEventSource{timeEventSource, [](void* source){ sd_event_source_disable_unref((sd_event_source*)source); }};
|
||||
|
||||
r = sd_event_source_set_priority(timeEventSource, priority); // TODO maybe use custom EventSourceSlot with custom type? Then we can use slot.get() here
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to set time event priority", -r);
|
||||
|
||||
r = sd_event_source_set_description(timeEventSource, "bus-time");
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to set time event description", -r);
|
||||
// TODO: auto sdTimeEventSource = createSdTimeEventSourceSlot(...);
|
||||
|
||||
sd_event_source *ioEventSource{};
|
||||
auto pollData = getEventLoopPollData();
|
||||
r = sd_event_add_io(event, &ioEventSource, pollData.fd, 0, onSdIoEvent, this);
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to add io event", -r);
|
||||
Slot sdIoEventSource{ioEventSource, [](void* source){ sd_event_source_disable_unref((sd_event_source*)source); }};
|
||||
|
||||
r = sd_event_source_set_prepare(ioEventSource, onSdEventPrepare);
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to set prepare callback for IO event", -r);
|
||||
|
||||
r = sd_event_source_set_priority(ioEventSource, priority);
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to set priority for IO event", -r);
|
||||
|
||||
r = sd_event_source_set_description(ioEventSource, "bus-input");
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to set priority for IO event", -r);
|
||||
// TODO: auto sdIoEventSource = createSdIoEventSourceSlot(...);
|
||||
|
||||
sdEvent_ = std::make_unique<SdEvent>(SdEvent{std::move(sdEvent), std::move(sdTimeEventSource), std::move(sdIoEventSource)});
|
||||
}
|
||||
|
||||
void Connection::detachSdEventLoop()
|
||||
{
|
||||
sdEvent_.reset();
|
||||
}
|
||||
|
||||
sd_event *Connection::getSdEventLoop()
|
||||
{
|
||||
return iface_->sd_bus_get_event(bus_.get());
|
||||
}
|
||||
|
||||
int Connection::onSdTimerEvent(sd_event_source */*s*/, uint64_t /*usec*/, void *userdata)
|
||||
{
|
||||
auto connection = static_cast<Connection*>(userdata);
|
||||
assert(connection != nullptr);
|
||||
|
||||
connection->processPendingRequest();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Connection::onSdIoEvent(sd_event_source */*s*/, int /*fd*/, uint32_t /*revents*/, void *userdata)
|
||||
{
|
||||
auto connection = static_cast<Connection*>(userdata);
|
||||
assert(connection != nullptr);
|
||||
|
||||
connection->processPendingRequest();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Connection::onSdEventPrepare(sd_event_source */*s*/, void *userdata)
|
||||
{
|
||||
auto connection = static_cast<Connection*>(userdata);
|
||||
assert(connection != nullptr);
|
||||
|
||||
auto sdbusPollData = connection->getEventLoopPollData();
|
||||
|
||||
// Set poll events to watch out for
|
||||
auto* sdIoEventSource = static_cast<sd_event_source*>(connection->sdEvent_->sdIoEventSource_.get());
|
||||
auto r = sd_event_source_set_io_events(sdIoEventSource, sdbusPollData.events);
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to set poll events for IO event source", -r);
|
||||
|
||||
// Set current timeout to the time event source (may be zero if there are messages in the sd-bus queues to be processed)
|
||||
auto* sdTimeEventSource = static_cast<sd_event_source*>(connection->sdEvent_->sdTimeEventSource_.get());
|
||||
r = sd_event_source_set_time(sdTimeEventSource, sdbusPollData.timeout_usec);
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to set timeout for time event source", -r);
|
||||
r = sd_event_source_set_enabled(sdTimeEventSource, SD_EVENT_ON);
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to enable time event source", -r);
|
||||
|
||||
// TODO: Continue with integration tests
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
Slot Connection::addObjectVTable( const std::string& objectPath
|
||||
, const std::string& interfaceName
|
||||
, const sd_bus_vtable* vtable
|
||||
|
@ -87,6 +87,10 @@ namespace sdbus::internal {
|
||||
[[nodiscard]] Slot addMatch(const std::string& match, message_handler callback) override;
|
||||
void addMatch(const std::string& match, message_handler callback, floating_slot_t) override;
|
||||
|
||||
void attachSdEventLoop(sd_event *event, int priority) override;
|
||||
void detachSdEventLoop() override;
|
||||
sd_event *getSdEventLoop() override;
|
||||
|
||||
const ISdBus& getSdBusInterface() const override;
|
||||
ISdBus& getSdBusInterface() override;
|
||||
|
||||
@ -141,10 +145,13 @@ namespace sdbus::internal {
|
||||
void clearEventLoopNotification(int fd) const;
|
||||
void notifyEventLoopNewTimeout() const override;
|
||||
|
||||
private:
|
||||
void joinWithEventLoop();
|
||||
static std::vector</*const */char*> to_strv(const std::vector<std::string>& strings);
|
||||
|
||||
static int onSdTimerEvent(sd_event_source *s, uint64_t usec, void *userdata);
|
||||
static int onSdIoEvent(sd_event_source *s, int fd, uint32_t revents, void *userdata);
|
||||
static int onSdEventPrepare(sd_event_source *s, void *userdata);
|
||||
|
||||
struct EventFd
|
||||
{
|
||||
EventFd();
|
||||
@ -169,6 +176,15 @@ namespace sdbus::internal {
|
||||
EventFd eventFd_;
|
||||
std::atomic<uint64_t> activeTimeout_{};
|
||||
std::vector<Slot> floatingMatchRules_;
|
||||
|
||||
// sd-event integration
|
||||
struct SdEvent
|
||||
{
|
||||
Slot sdEvent_;
|
||||
Slot sdTimeEventSource_;
|
||||
Slot sdIoEventSource_{};
|
||||
};
|
||||
std::unique_ptr<SdEvent> sdEvent_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -101,6 +101,8 @@ namespace sdbus::internal {
|
||||
virtual int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) = 0;
|
||||
virtual int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) = 0;
|
||||
virtual int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **label) = 0;
|
||||
|
||||
virtual sd_event *sd_bus_get_event(sd_bus *bus) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -401,4 +401,11 @@ int SdBus::sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **label)
|
||||
return ::sd_bus_creds_get_selinux_context(c, label);
|
||||
}
|
||||
|
||||
sd_event *SdBus::sd_bus_get_event(sd_bus *bus)
|
||||
{
|
||||
std::lock_guard lock(sdbusMutex_);
|
||||
|
||||
return ::sd_bus_get_event(bus);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -94,6 +94,8 @@ public:
|
||||
virtual int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) override;
|
||||
virtual int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **label) override;
|
||||
|
||||
virtual sd_event *sd_bus_get_event(sd_bus *bus) override;
|
||||
|
||||
private:
|
||||
std::recursive_mutex sdbusMutex_;
|
||||
};
|
||||
|
@ -109,7 +109,8 @@ target_link_libraries(sdbus-c++-unit-tests sdbus-c++-objlib GTest::gmock)
|
||||
|
||||
add_executable(sdbus-c++-integration-tests ${INTEGRATIONTESTS_SRCS})
|
||||
target_compile_definitions(sdbus-c++-integration-tests PRIVATE LIBSYSTEMD_VERSION=${LIBSYSTEMD_VERSION})
|
||||
target_link_libraries(sdbus-c++-integration-tests sdbus-c++ GTest::gmock)
|
||||
# Systemd::Libsystemd is included because integration tests use sd-event. Otherwise sdbus-c++ encapsulates and hides libsystemd.
|
||||
target_link_libraries(sdbus-c++-integration-tests sdbus-c++ Systemd::Libsystemd GTest::gmock)
|
||||
|
||||
# Manual performance and stress tests
|
||||
option(ENABLE_PERF_TESTS "Build and install manual performance tests (default OFF)" OFF)
|
||||
|
@ -49,20 +49,18 @@ using ::testing::SizeIs;
|
||||
using namespace std::chrono_literals;
|
||||
using namespace sdbus::test;
|
||||
|
||||
using SdbusTestObject = TestFixture;
|
||||
|
||||
/*-------------------------------------*/
|
||||
/* -- TEST CASES -- */
|
||||
/*-------------------------------------*/
|
||||
|
||||
TEST_F(SdbusTestObject, ThrowsTimeoutErrorWhenClientSideAsyncMethodTimesOut)
|
||||
TYPED_TEST(AsyncSdbusTestObject, ThrowsTimeoutErrorWhenClientSideAsyncMethodTimesOut)
|
||||
{
|
||||
std::chrono::time_point<std::chrono::steady_clock> start;
|
||||
try
|
||||
{
|
||||
std::promise<uint32_t> promise;
|
||||
auto future = promise.get_future();
|
||||
m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t res, const sdbus::Error* err)
|
||||
this->m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t res, const sdbus::Error* err)
|
||||
{
|
||||
if (err == nullptr)
|
||||
promise.set_value(res);
|
||||
@ -71,7 +69,7 @@ TEST_F(SdbusTestObject, ThrowsTimeoutErrorWhenClientSideAsyncMethodTimesOut)
|
||||
});
|
||||
|
||||
start = std::chrono::steady_clock::now();
|
||||
m_proxy->doOperationClientSideAsyncWithTimeout(1us, 1000); // The operation will take 1s, but the timeout is 500ms, so we should time out
|
||||
this->m_proxy->doOperationClientSideAsyncWithTimeout(1us, 1000); // The operation will take 1s, but the timeout is 1us, so we should time out
|
||||
future.get();
|
||||
|
||||
FAIL() << "Expected sdbus::Error exception";
|
||||
@ -89,7 +87,7 @@ TEST_F(SdbusTestObject, ThrowsTimeoutErrorWhenClientSideAsyncMethodTimesOut)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, RunsServerSideAsynchoronousMethodAsynchronously)
|
||||
TYPED_TEST(AsyncSdbusTestObject, RunsServerSideAsynchoronousMethodAsynchronously)
|
||||
{
|
||||
// Yeah, this is kinda timing-dependent test, but times should be safe...
|
||||
std::mutex mtx;
|
||||
@ -114,7 +112,7 @@ TEST_F(SdbusTestObject, RunsServerSideAsynchoronousMethodAsynchronously)
|
||||
ASSERT_THAT(results, ElementsAre(500, 1000, 1500));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, HandlesCorrectlyABulkOfParallelServerSideAsyncMethods)
|
||||
TYPED_TEST(AsyncSdbusTestObject, HandlesCorrectlyABulkOfParallelServerSideAsyncMethods)
|
||||
{
|
||||
std::atomic<size_t> resultCount{};
|
||||
std::atomic<bool> invoke{};
|
||||
@ -144,11 +142,11 @@ TEST_F(SdbusTestObject, HandlesCorrectlyABulkOfParallelServerSideAsyncMethods)
|
||||
ASSERT_THAT(resultCount, Eq(1500));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, InvokesMethodAsynchronouslyOnClientSide)
|
||||
TYPED_TEST(AsyncSdbusTestObject, InvokesMethodAsynchronouslyOnClientSide)
|
||||
{
|
||||
std::promise<uint32_t> promise;
|
||||
auto future = promise.get_future();
|
||||
m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t res, const sdbus::Error* err)
|
||||
this->m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t res, const sdbus::Error* err)
|
||||
{
|
||||
if (err == nullptr)
|
||||
promise.set_value(res);
|
||||
@ -156,77 +154,77 @@ TEST_F(SdbusTestObject, InvokesMethodAsynchronouslyOnClientSide)
|
||||
promise.set_exception(std::make_exception_ptr(*err));
|
||||
});
|
||||
|
||||
m_proxy->doOperationClientSideAsync(100);
|
||||
this->m_proxy->doOperationClientSideAsync(100);
|
||||
|
||||
ASSERT_THAT(future.get(), Eq(100));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, AnswersThatAsyncCallIsPendingIfItIsInProgress)
|
||||
TYPED_TEST(AsyncSdbusTestObject, AnswersThatAsyncCallIsPendingIfItIsInProgress)
|
||||
{
|
||||
m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t /*res*/, const sdbus::Error* /*err*/){});
|
||||
this->m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t /*res*/, const sdbus::Error* /*err*/){});
|
||||
|
||||
auto call = m_proxy->doOperationClientSideAsync(100);
|
||||
auto call = this->m_proxy->doOperationClientSideAsync(100);
|
||||
|
||||
ASSERT_TRUE(call.isPending());
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CancelsPendingAsyncCallOnClientSide)
|
||||
TYPED_TEST(AsyncSdbusTestObject, CancelsPendingAsyncCallOnClientSide)
|
||||
{
|
||||
std::promise<uint32_t> promise;
|
||||
auto future = promise.get_future();
|
||||
m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t /*res*/, const sdbus::Error* /*err*/){ promise.set_value(1); });
|
||||
auto call = m_proxy->doOperationClientSideAsync(100);
|
||||
this->m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t /*res*/, const sdbus::Error* /*err*/){ promise.set_value(1); });
|
||||
auto call = this->m_proxy->doOperationClientSideAsync(100);
|
||||
|
||||
call.cancel();
|
||||
|
||||
ASSERT_THAT(future.wait_for(300ms), Eq(std::future_status::timeout));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, AnswersThatAsyncCallIsNotPendingAfterItHasBeenCancelled)
|
||||
TYPED_TEST(AsyncSdbusTestObject, AnswersThatAsyncCallIsNotPendingAfterItHasBeenCancelled)
|
||||
{
|
||||
std::promise<uint32_t> promise;
|
||||
auto future = promise.get_future();
|
||||
m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t /*res*/, const sdbus::Error* /*err*/){ promise.set_value(1); });
|
||||
auto call = m_proxy->doOperationClientSideAsync(100);
|
||||
this->m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t /*res*/, const sdbus::Error* /*err*/){ promise.set_value(1); });
|
||||
auto call = this->m_proxy->doOperationClientSideAsync(100);
|
||||
|
||||
call.cancel();
|
||||
|
||||
ASSERT_FALSE(call.isPending());
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, AnswersThatAsyncCallIsNotPendingAfterItHasBeenCompleted)
|
||||
TYPED_TEST(AsyncSdbusTestObject, AnswersThatAsyncCallIsNotPendingAfterItHasBeenCompleted)
|
||||
{
|
||||
std::promise<uint32_t> promise;
|
||||
auto future = promise.get_future();
|
||||
m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t /*res*/, const sdbus::Error* /*err*/){ promise.set_value(1); });
|
||||
this->m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t /*res*/, const sdbus::Error* /*err*/){ promise.set_value(1); });
|
||||
|
||||
auto call = m_proxy->doOperationClientSideAsync(0);
|
||||
auto call = this->m_proxy->doOperationClientSideAsync(0);
|
||||
(void) future.get(); // Wait for the call to finish
|
||||
|
||||
ASSERT_TRUE(waitUntil([&call](){ return !call.isPending(); }));
|
||||
ASSERT_TRUE(this->waitUntil([&call](){ return !call.isPending(); }));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, AnswersThatDefaultConstructedAsyncCallIsNotPending)
|
||||
TYPED_TEST(AsyncSdbusTestObject, AnswersThatDefaultConstructedAsyncCallIsNotPending)
|
||||
{
|
||||
sdbus::PendingAsyncCall call;
|
||||
|
||||
ASSERT_FALSE(call.isPending());
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, SupportsAsyncCallCopyAssignment)
|
||||
TYPED_TEST(AsyncSdbusTestObject, SupportsAsyncCallCopyAssignment)
|
||||
{
|
||||
sdbus::PendingAsyncCall call;
|
||||
|
||||
call = m_proxy->doOperationClientSideAsync(100);
|
||||
call = this->m_proxy->doOperationClientSideAsync(100);
|
||||
|
||||
ASSERT_TRUE(call.isPending());
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, InvokesErroneousMethodAsynchronouslyOnClientSide)
|
||||
TYPED_TEST(AsyncSdbusTestObject, InvokesErroneousMethodAsynchronouslyOnClientSide)
|
||||
{
|
||||
std::promise<uint32_t> promise;
|
||||
auto future = promise.get_future();
|
||||
m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t res, const sdbus::Error* err)
|
||||
this->m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t res, const sdbus::Error* err)
|
||||
{
|
||||
if (err == nullptr)
|
||||
promise.set_value(res);
|
||||
@ -234,7 +232,7 @@ TEST_F(SdbusTestObject, InvokesErroneousMethodAsynchronouslyOnClientSide)
|
||||
promise.set_exception(std::make_exception_ptr(*err));
|
||||
});
|
||||
|
||||
m_proxy->doErroneousOperationClientSideAsync();
|
||||
this->m_proxy->doErroneousOperationClientSideAsync();
|
||||
|
||||
ASSERT_THROW(future.get(), sdbus::Error);
|
||||
}
|
||||
|
@ -45,8 +45,6 @@ using ::testing::Eq;
|
||||
using namespace std::chrono_literals;
|
||||
using namespace sdbus::test;
|
||||
|
||||
using AConnection = TestFixture;
|
||||
|
||||
/*-------------------------------------*/
|
||||
/* -- TEST CASES -- */
|
||||
/*-------------------------------------*/
|
||||
@ -72,38 +70,38 @@ TEST(AnAdaptor, SupportsMoveSemantics)
|
||||
static_assert(std::is_move_assignable_v<DummyTestAdaptor>);
|
||||
}
|
||||
|
||||
TEST_F(AConnection, WillCallCallbackHandlerForIncomingMessageMatchingMatchRule)
|
||||
TYPED_TEST(AConnection, WillCallCallbackHandlerForIncomingMessageMatchingMatchRule)
|
||||
{
|
||||
auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
|
||||
std::atomic<bool> matchingMessageReceived{false};
|
||||
auto slot = s_proxyConnection->addMatch(matchRule, [&](sdbus::Message& msg)
|
||||
auto slot = this->s_proxyConnection->addMatch(matchRule, [&](sdbus::Message& msg)
|
||||
{
|
||||
if(msg.getPath() == OBJECT_PATH)
|
||||
matchingMessageReceived = true;
|
||||
});
|
||||
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
ASSERT_TRUE(waitUntil(matchingMessageReceived));
|
||||
ASSERT_TRUE(this->waitUntil(matchingMessageReceived));
|
||||
}
|
||||
|
||||
TEST_F(AConnection, WillUnsubscribeMatchRuleWhenClientDestroysTheAssociatedSlot)
|
||||
TYPED_TEST(AConnection, WillUnsubscribeMatchRuleWhenClientDestroysTheAssociatedSlot)
|
||||
{
|
||||
auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
|
||||
std::atomic<bool> matchingMessageReceived{false};
|
||||
auto slot = s_proxyConnection->addMatch(matchRule, [&](sdbus::Message& msg)
|
||||
auto slot = this->s_proxyConnection->addMatch(matchRule, [&](sdbus::Message& msg)
|
||||
{
|
||||
if(msg.getPath() == OBJECT_PATH)
|
||||
matchingMessageReceived = true;
|
||||
});
|
||||
slot.reset();
|
||||
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
ASSERT_FALSE(waitUntil(matchingMessageReceived, 2s));
|
||||
ASSERT_FALSE(this->waitUntil(matchingMessageReceived, 2s));
|
||||
}
|
||||
|
||||
TEST_F(AConnection, CanAddFloatingMatchRule)
|
||||
TYPED_TEST(AConnection, CanAddFloatingMatchRule)
|
||||
{
|
||||
auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
|
||||
std::atomic<bool> matchingMessageReceived{false};
|
||||
@ -115,32 +113,32 @@ TEST_F(AConnection, CanAddFloatingMatchRule)
|
||||
matchingMessageReceived = true;
|
||||
};
|
||||
con->addMatch(matchRule, std::move(callback), sdbus::floating_slot);
|
||||
m_adaptor->emitSimpleSignal();
|
||||
[[maybe_unused]] auto gotMessage = waitUntil(matchingMessageReceived, 2s);
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
[[maybe_unused]] auto gotMessage = this->waitUntil(matchingMessageReceived, 2s);
|
||||
assert(gotMessage);
|
||||
matchingMessageReceived = false;
|
||||
|
||||
con.reset();
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
ASSERT_FALSE(waitUntil(matchingMessageReceived, 2s));
|
||||
ASSERT_FALSE(this->waitUntil(matchingMessageReceived, 2s));
|
||||
}
|
||||
|
||||
TEST_F(AConnection, WillNotPassToMatchCallbackMessagesThatDoNotMatchTheRule)
|
||||
TYPED_TEST(AConnection, WillNotPassToMatchCallbackMessagesThatDoNotMatchTheRule)
|
||||
{
|
||||
auto matchRule = "type='signal',interface='" + INTERFACE_NAME + "',member='simpleSignal'";
|
||||
std::atomic<size_t> numberOfMatchingMessages{};
|
||||
auto slot = s_proxyConnection->addMatch(matchRule, [&](sdbus::Message& msg)
|
||||
auto slot = this->s_proxyConnection->addMatch(matchRule, [&](sdbus::Message& msg)
|
||||
{
|
||||
if(msg.getMemberName() == "simpleSignal")
|
||||
numberOfMatchingMessages++;
|
||||
});
|
||||
auto adaptor2 = std::make_unique<TestAdaptor>(*s_adaptorConnection, OBJECT_PATH_2);
|
||||
auto adaptor2 = std::make_unique<TestAdaptor>(*this->s_adaptorConnection, OBJECT_PATH_2);
|
||||
|
||||
m_adaptor->emitSignalWithMap({});
|
||||
this->m_adaptor->emitSignalWithMap({});
|
||||
adaptor2->emitSimpleSignal();
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
ASSERT_TRUE(waitUntil([&](){ return numberOfMatchingMessages == 2; }));
|
||||
ASSERT_FALSE(waitUntil([&](){ return numberOfMatchingMessages > 2; }, 1s));
|
||||
ASSERT_TRUE(this->waitUntil([&](){ return numberOfMatchingMessages == 2; }));
|
||||
ASSERT_FALSE(this->waitUntil([&](){ return numberOfMatchingMessages > 2; }, 1s));
|
||||
}
|
||||
|
@ -50,59 +50,57 @@ using ::testing::NotNull;
|
||||
using namespace std::chrono_literals;
|
||||
using namespace sdbus::test;
|
||||
|
||||
using SdbusTestObject = TestFixture;
|
||||
|
||||
/*-------------------------------------*/
|
||||
/* -- TEST CASES -- */
|
||||
/*-------------------------------------*/
|
||||
|
||||
TEST_F(SdbusTestObject, CallsEmptyMethodSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsEmptyMethodSuccesfully)
|
||||
{
|
||||
ASSERT_NO_THROW(m_proxy->noArgNoReturn());
|
||||
ASSERT_NO_THROW(this->m_proxy->noArgNoReturn());
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodsWithBaseTypesSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodsWithBaseTypesSuccesfully)
|
||||
{
|
||||
auto resInt = m_proxy->getInt();
|
||||
auto resInt = this->m_proxy->getInt();
|
||||
ASSERT_THAT(resInt, Eq(INT32_VALUE));
|
||||
|
||||
auto multiplyRes = m_proxy->multiply(INT64_VALUE, DOUBLE_VALUE);
|
||||
auto multiplyRes = this->m_proxy->multiply(INT64_VALUE, DOUBLE_VALUE);
|
||||
ASSERT_THAT(multiplyRes, Eq(INT64_VALUE * DOUBLE_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodsWithTuplesSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodsWithTuplesSuccesfully)
|
||||
{
|
||||
auto resTuple = m_proxy->getTuple();
|
||||
auto resTuple = this->m_proxy->getTuple();
|
||||
ASSERT_THAT(std::get<0>(resTuple), Eq(UINT32_VALUE));
|
||||
ASSERT_THAT(std::get<1>(resTuple), Eq(STRING_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodsWithStructSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodsWithStructSuccesfully)
|
||||
{
|
||||
sdbus::Struct<uint8_t, int16_t, double, std::string, std::vector<int16_t>> a{};
|
||||
auto vectorRes = m_proxy->getInts16FromStruct(a);
|
||||
auto vectorRes = this->m_proxy->getInts16FromStruct(a);
|
||||
ASSERT_THAT(vectorRes, Eq(std::vector<int16_t>{0})); // because second item is by default initialized to 0
|
||||
|
||||
|
||||
sdbus::Struct<uint8_t, int16_t, double, std::string, std::vector<int16_t>> b{
|
||||
UINT8_VALUE, INT16_VALUE, DOUBLE_VALUE, STRING_VALUE, {INT16_VALUE, -INT16_VALUE}
|
||||
};
|
||||
vectorRes = m_proxy->getInts16FromStruct(b);
|
||||
vectorRes = this->m_proxy->getInts16FromStruct(b);
|
||||
ASSERT_THAT(vectorRes, Eq(std::vector<int16_t>{INT16_VALUE, INT16_VALUE, -INT16_VALUE}));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodWithVariantSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodWithVariantSuccesfully)
|
||||
{
|
||||
sdbus::Variant v{DOUBLE_VALUE};
|
||||
auto variantRes = m_proxy->processVariant(v);
|
||||
sdbus::Variant variantRes = this->m_proxy->processVariant(v);
|
||||
ASSERT_THAT(variantRes.get<int32_t>(), Eq(static_cast<int32_t>(DOUBLE_VALUE)));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodWithStructVariantsAndGetMapSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodWithStructVariantsAndGetMapSuccesfully)
|
||||
{
|
||||
std::vector<int32_t> x{-2, 0, 2};
|
||||
sdbus::Struct<sdbus::Variant, sdbus::Variant> y{false, true};
|
||||
auto mapOfVariants = m_proxy->getMapOfVariants(x, y);
|
||||
std::map<int32_t, sdbus::Variant> mapOfVariants = this->m_proxy->getMapOfVariants(x, y);
|
||||
decltype(mapOfVariants) res{{-2, false}, {0, false}, {2, true}};
|
||||
|
||||
ASSERT_THAT(mapOfVariants[-2].get<bool>(), Eq(res[-2].get<bool>()));
|
||||
@ -110,69 +108,69 @@ TEST_F(SdbusTestObject, CallsMethodWithStructVariantsAndGetMapSuccesfully)
|
||||
ASSERT_THAT(mapOfVariants[2].get<bool>(), Eq(res[2].get<bool>()));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodWithStructInStructSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodWithStructInStructSuccesfully)
|
||||
{
|
||||
auto val = m_proxy->getStructInStruct();
|
||||
ASSERT_THAT(val.get<0>(), Eq(STRING_VALUE));
|
||||
auto val = this->m_proxy->getStructInStruct();
|
||||
ASSERT_THAT(val.template get<0>(), Eq(STRING_VALUE));
|
||||
ASSERT_THAT(std::get<0>(std::get<1>(val))[INT32_VALUE], Eq(INT32_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodWithTwoStructsSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodWithTwoStructsSuccesfully)
|
||||
{
|
||||
auto val = m_proxy->sumStructItems({1, 2}, {3, 4});
|
||||
auto val = this->m_proxy->sumStructItems({1, 2}, {3, 4});
|
||||
ASSERT_THAT(val, Eq(1 + 2 + 3 + 4));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodWithTwoVectorsSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodWithTwoVectorsSuccesfully)
|
||||
{
|
||||
auto val = m_proxy->sumVectorItems({1, 7}, {2, 3});
|
||||
auto val = this->m_proxy->sumVectorItems({1, 7}, {2, 3});
|
||||
ASSERT_THAT(val, Eq(1 + 7 + 2 + 3));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodWithSignatureSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodWithSignatureSuccesfully)
|
||||
{
|
||||
auto resSignature = m_proxy->getSignature();
|
||||
auto resSignature = this->m_proxy->getSignature();
|
||||
ASSERT_THAT(resSignature, Eq(SIGNATURE_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodWithObjectPathSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodWithObjectPathSuccesfully)
|
||||
{
|
||||
auto resObjectPath = m_proxy->getObjPath();
|
||||
auto resObjectPath = this->m_proxy->getObjPath();
|
||||
ASSERT_THAT(resObjectPath, Eq(OBJECT_PATH_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodWithUnixFdSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodWithUnixFdSuccesfully)
|
||||
{
|
||||
auto resUnixFd = m_proxy->getUnixFd();
|
||||
auto resUnixFd = this->m_proxy->getUnixFd();
|
||||
ASSERT_THAT(resUnixFd.get(), Gt(UNIX_FD_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodWithComplexTypeSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodWithComplexTypeSuccesfully)
|
||||
{
|
||||
auto resComplex = m_proxy->getComplex();
|
||||
auto resComplex = this->m_proxy->getComplex();
|
||||
ASSERT_THAT(resComplex.count(0), Eq(1));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMultiplyMethodWithNoReplyFlag)
|
||||
TYPED_TEST(SdbusTestObject, CallsMultiplyMethodWithNoReplyFlag)
|
||||
{
|
||||
m_proxy->multiplyWithNoReply(INT64_VALUE, DOUBLE_VALUE);
|
||||
this->m_proxy->multiplyWithNoReply(INT64_VALUE, DOUBLE_VALUE);
|
||||
|
||||
ASSERT_TRUE(waitUntil(m_adaptor->m_wasMultiplyCalled));
|
||||
ASSERT_THAT(m_adaptor->m_multiplyResult, Eq(INT64_VALUE * DOUBLE_VALUE));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_adaptor->m_wasMultiplyCalled));
|
||||
ASSERT_THAT(this->m_adaptor->m_multiplyResult, Eq(INT64_VALUE * DOUBLE_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodWithCustomTimeoutSuccessfully)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodWithCustomTimeoutSuccessfully)
|
||||
{
|
||||
auto res = m_proxy->doOperationWithTimeout(500ms, 20); // The operation will take 20ms, but the timeout is 500ms, so we are fine
|
||||
auto res = this->m_proxy->doOperationWithTimeout(500ms, 20); // The operation will take 20ms, but the timeout is 500ms, so we are fine
|
||||
ASSERT_THAT(res, Eq(20));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, ThrowsTimeoutErrorWhenMethodTimesOut)
|
||||
TYPED_TEST(SdbusTestObject, ThrowsTimeoutErrorWhenMethodTimesOut)
|
||||
{
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
try
|
||||
{
|
||||
m_proxy->doOperationWithTimeout(1us, 1000); // The operation will take 1s, but the timeout is 1us, so we should time out
|
||||
this->m_proxy->doOperationWithTimeout(1us, 1000); // The operation will take 1s, but the timeout is 1us, so we should time out
|
||||
FAIL() << "Expected sdbus::Error exception";
|
||||
}
|
||||
catch (const sdbus::Error& e)
|
||||
@ -188,11 +186,11 @@ TEST_F(SdbusTestObject, ThrowsTimeoutErrorWhenMethodTimesOut)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsMethodThatThrowsError)
|
||||
TYPED_TEST(SdbusTestObject, CallsMethodThatThrowsError)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_proxy->throwError();
|
||||
this->m_proxy->throwError();
|
||||
FAIL() << "Expected sdbus::Error exception";
|
||||
}
|
||||
catch (const sdbus::Error& e)
|
||||
@ -206,74 +204,74 @@ TEST_F(SdbusTestObject, CallsMethodThatThrowsError)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CallsErrorThrowingMethodWithDontExpectReplySet)
|
||||
TYPED_TEST(SdbusTestObject, CallsErrorThrowingMethodWithDontExpectReplySet)
|
||||
{
|
||||
ASSERT_NO_THROW(m_proxy->throwErrorWithNoReply());
|
||||
ASSERT_NO_THROW(this->m_proxy->throwErrorWithNoReply());
|
||||
|
||||
ASSERT_TRUE(waitUntil(m_adaptor->m_wasThrowErrorCalled));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_adaptor->m_wasThrowErrorCalled));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, FailsCallingNonexistentMethod)
|
||||
TYPED_TEST(SdbusTestObject, FailsCallingNonexistentMethod)
|
||||
{
|
||||
ASSERT_THROW(m_proxy->callNonexistentMethod(), sdbus::Error);
|
||||
ASSERT_THROW(this->m_proxy->callNonexistentMethod(), sdbus::Error);
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, FailsCallingMethodOnNonexistentInterface)
|
||||
TYPED_TEST(SdbusTestObject, FailsCallingMethodOnNonexistentInterface)
|
||||
{
|
||||
ASSERT_THROW(m_proxy->callMethodOnNonexistentInterface(), sdbus::Error);
|
||||
ASSERT_THROW(this->m_proxy->callMethodOnNonexistentInterface(), sdbus::Error);
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, FailsCallingMethodOnNonexistentDestination)
|
||||
TYPED_TEST(SdbusTestObject, FailsCallingMethodOnNonexistentDestination)
|
||||
{
|
||||
TestProxy proxy("sdbuscpp.destination.that.does.not.exist", OBJECT_PATH);
|
||||
ASSERT_THROW(proxy.getInt(), sdbus::Error);
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, FailsCallingMethodOnNonexistentObject)
|
||||
TYPED_TEST(SdbusTestObject, FailsCallingMethodOnNonexistentObject)
|
||||
{
|
||||
TestProxy proxy(BUS_NAME, "/sdbuscpp/path/that/does/not/exist");
|
||||
ASSERT_THROW(proxy.getInt(), sdbus::Error);
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CanReceiveSignalWhileMakingMethodCall)
|
||||
TYPED_TEST(SdbusTestObject, CanReceiveSignalWhileMakingMethodCall)
|
||||
{
|
||||
m_proxy->emitTwoSimpleSignals();
|
||||
this->m_proxy->emitTwoSimpleSignals();
|
||||
|
||||
ASSERT_TRUE(waitUntil(m_proxy->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(waitUntil(m_proxy->m_gotSignalWithMap));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_proxy->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_proxy->m_gotSignalWithMap));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CanAccessAssociatedMethodCallMessageInMethodCallHandler)
|
||||
TYPED_TEST(SdbusTestObject, CanAccessAssociatedMethodCallMessageInMethodCallHandler)
|
||||
{
|
||||
m_proxy->doOperation(10); // This will save pointer to method call message on server side
|
||||
this->m_proxy->doOperation(10); // This will save pointer to method call message on server side
|
||||
|
||||
ASSERT_THAT(m_adaptor->m_methodCallMsg, NotNull());
|
||||
ASSERT_THAT(m_adaptor->m_methodCallMemberName, Eq("doOperation"));
|
||||
ASSERT_THAT(this->m_adaptor->m_methodCallMsg, NotNull());
|
||||
ASSERT_THAT(this->m_adaptor->m_methodCallMemberName, Eq("doOperation"));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CanAccessAssociatedMethodCallMessageInAsyncMethodCallHandler)
|
||||
TYPED_TEST(SdbusTestObject, CanAccessAssociatedMethodCallMessageInAsyncMethodCallHandler)
|
||||
{
|
||||
m_proxy->doOperationAsync(10); // This will save pointer to method call message on server side
|
||||
this->m_proxy->doOperationAsync(10); // This will save pointer to method call message on server side
|
||||
|
||||
ASSERT_THAT(m_adaptor->m_methodCallMsg, NotNull());
|
||||
ASSERT_THAT(m_adaptor->m_methodCallMemberName, Eq("doOperationAsync"));
|
||||
ASSERT_THAT(this->m_adaptor->m_methodCallMsg, NotNull());
|
||||
ASSERT_THAT(this->m_adaptor->m_methodCallMemberName, Eq("doOperationAsync"));
|
||||
}
|
||||
|
||||
#if LIBSYSTEMD_VERSION>=240
|
||||
TEST_F(SdbusTestObject, CanSetGeneralMethodTimeoutWithLibsystemdVersionGreaterThan239)
|
||||
TYPED_TEST(SdbusTestObject, CanSetGeneralMethodTimeoutWithLibsystemdVersionGreaterThan239)
|
||||
{
|
||||
s_adaptorConnection->setMethodCallTimeout(5000000);
|
||||
ASSERT_THAT(s_adaptorConnection->getMethodCallTimeout(), Eq(5000000));
|
||||
this->s_adaptorConnection->setMethodCallTimeout(5000000);
|
||||
ASSERT_THAT(this->s_adaptorConnection->getMethodCallTimeout(), Eq(5000000));
|
||||
}
|
||||
#else
|
||||
TEST_F(SdbusTestObject, CannotSetGeneralMethodTimeoutWithLibsystemdVersionLessThan240)
|
||||
TYPED_TEST(SdbusTestObject, CannotSetGeneralMethodTimeoutWithLibsystemdVersionLessThan240)
|
||||
{
|
||||
ASSERT_THROW(s_adaptorConnection->setMethodCallTimeout(5000000), sdbus::Error);
|
||||
ASSERT_THROW(s_adaptorConnection->getMethodCallTimeout(), sdbus::Error);
|
||||
ASSERT_THROW(this->s_adaptorConnection->setMethodCallTimeout(5000000), sdbus::Error);
|
||||
ASSERT_THROW(this->s_adaptorConnection->getMethodCallTimeout(), sdbus::Error);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(SdbusTestObject, CanCallMethodSynchronouslyWithoutAnEventLoopThread)
|
||||
TYPED_TEST(SdbusTestObject, CanCallMethodSynchronouslyWithoutAnEventLoopThread)
|
||||
{
|
||||
auto proxy = std::make_unique<TestProxy>(BUS_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread);
|
||||
|
||||
|
@ -51,35 +51,33 @@ using ::testing::IsEmpty;
|
||||
using namespace std::chrono_literals;
|
||||
using namespace sdbus::test;
|
||||
|
||||
using SdbusTestObject = TestFixture;
|
||||
|
||||
/*-------------------------------------*/
|
||||
/* -- TEST CASES -- */
|
||||
/*-------------------------------------*/
|
||||
|
||||
TEST_F(SdbusTestObject, ReadsReadOnlyPropertySuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, ReadsReadOnlyPropertySuccesfully)
|
||||
{
|
||||
ASSERT_THAT(m_proxy->state(), Eq(DEFAULT_STATE_VALUE));
|
||||
ASSERT_THAT(this->m_proxy->state(), Eq(DEFAULT_STATE_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, FailsWritingToReadOnlyProperty)
|
||||
TYPED_TEST(SdbusTestObject, FailsWritingToReadOnlyProperty)
|
||||
{
|
||||
ASSERT_THROW(m_proxy->setStateProperty("new_value"), sdbus::Error);
|
||||
ASSERT_THROW(this->m_proxy->setStateProperty("new_value"), sdbus::Error);
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, WritesAndReadsReadWritePropertySuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, WritesAndReadsReadWritePropertySuccesfully)
|
||||
{
|
||||
uint32_t newActionValue = 5678;
|
||||
|
||||
m_proxy->action(newActionValue);
|
||||
this->m_proxy->action(newActionValue);
|
||||
|
||||
ASSERT_THAT(m_proxy->action(), Eq(newActionValue));
|
||||
ASSERT_THAT(this->m_proxy->action(), Eq(newActionValue));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CanAccessAssociatedPropertySetMessageInPropertySetHandler)
|
||||
TYPED_TEST(SdbusTestObject, CanAccessAssociatedPropertySetMessageInPropertySetHandler)
|
||||
{
|
||||
m_proxy->blocking(true); // This will save pointer to property get message on server side
|
||||
this->m_proxy->blocking(true); // This will save pointer to property get message on server side
|
||||
|
||||
ASSERT_THAT(m_adaptor->m_propertySetMsg, NotNull());
|
||||
ASSERT_THAT(m_adaptor->m_propertySetSender, Not(IsEmpty()));
|
||||
ASSERT_THAT(this->m_adaptor->m_propertySetMsg, NotNull());
|
||||
ASSERT_THAT(this->m_adaptor->m_propertySetSender, Not(IsEmpty()));
|
||||
}
|
||||
|
@ -44,32 +44,30 @@ using ::testing::NotNull;
|
||||
using namespace std::chrono_literals;
|
||||
using namespace sdbus::test;
|
||||
|
||||
using SdbusTestObject = TestFixture;
|
||||
|
||||
/*-------------------------------------*/
|
||||
/* -- TEST CASES -- */
|
||||
/*-------------------------------------*/
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsSimpleSignalSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, EmitsSimpleSignalSuccesfully)
|
||||
{
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
ASSERT_TRUE(waitUntil(m_proxy->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_proxy->m_gotSimpleSignal));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsSimpleSignalToMultipleProxiesSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, EmitsSimpleSignalToMultipleProxiesSuccesfully)
|
||||
{
|
||||
auto proxy1 = std::make_unique<TestProxy>(*s_adaptorConnection, BUS_NAME, OBJECT_PATH);
|
||||
auto proxy2 = std::make_unique<TestProxy>(*s_adaptorConnection, BUS_NAME, OBJECT_PATH);
|
||||
auto proxy1 = std::make_unique<TestProxy>(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH);
|
||||
auto proxy2 = std::make_unique<TestProxy>(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH);
|
||||
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
ASSERT_TRUE(waitUntil(m_proxy->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(waitUntil(proxy1->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(waitUntil(proxy2->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_proxy->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(this->waitUntil(proxy1->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(this->waitUntil(proxy2->m_gotSimpleSignal));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, ProxyDoesNotReceiveSignalFromOtherBusName)
|
||||
TYPED_TEST(SdbusTestObject, ProxyDoesNotReceiveSignalFromOtherBusName)
|
||||
{
|
||||
auto otherBusName = BUS_NAME + "2";
|
||||
auto connection2 = sdbus::createConnection(otherBusName);
|
||||
@ -77,93 +75,93 @@ TEST_F(SdbusTestObject, ProxyDoesNotReceiveSignalFromOtherBusName)
|
||||
|
||||
adaptor2->emitSimpleSignal();
|
||||
|
||||
ASSERT_FALSE(waitUntil(m_proxy->m_gotSimpleSignal, 2s));
|
||||
ASSERT_FALSE(this->waitUntil(this->m_proxy->m_gotSimpleSignal, 2s));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsSignalWithMapSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, EmitsSignalWithMapSuccesfully)
|
||||
{
|
||||
m_adaptor->emitSignalWithMap({{0, "zero"}, {1, "one"}});
|
||||
this->m_adaptor->emitSignalWithMap({{0, "zero"}, {1, "one"}});
|
||||
|
||||
ASSERT_TRUE(waitUntil(m_proxy->m_gotSignalWithMap));
|
||||
ASSERT_THAT(m_proxy->m_mapFromSignal[0], Eq("zero"));
|
||||
ASSERT_THAT(m_proxy->m_mapFromSignal[1], Eq("one"));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_proxy->m_gotSignalWithMap));
|
||||
ASSERT_THAT(this->m_proxy->m_mapFromSignal[0], Eq("zero"));
|
||||
ASSERT_THAT(this->m_proxy->m_mapFromSignal[1], Eq("one"));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsSignalWithLargeMapSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, EmitsSignalWithLargeMapSuccesfully)
|
||||
{
|
||||
std::map<int32_t, std::string> largeMap;
|
||||
for (int32_t i = 0; i < 20'000; ++i)
|
||||
largeMap.emplace(i, "This is string nr. " + std::to_string(i+1));
|
||||
m_adaptor->emitSignalWithMap(largeMap);
|
||||
this->m_adaptor->emitSignalWithMap(largeMap);
|
||||
|
||||
ASSERT_TRUE(waitUntil(m_proxy->m_gotSignalWithMap));
|
||||
ASSERT_THAT(m_proxy->m_mapFromSignal[0], Eq("This is string nr. 1"));
|
||||
ASSERT_THAT(m_proxy->m_mapFromSignal[1], Eq("This is string nr. 2"));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_proxy->m_gotSignalWithMap));
|
||||
ASSERT_THAT(this->m_proxy->m_mapFromSignal[0], Eq("This is string nr. 1"));
|
||||
ASSERT_THAT(this->m_proxy->m_mapFromSignal[1], Eq("This is string nr. 2"));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsSignalWithVariantSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, EmitsSignalWithVariantSuccesfully)
|
||||
{
|
||||
double d = 3.14;
|
||||
m_adaptor->emitSignalWithVariant(d);
|
||||
this->m_adaptor->emitSignalWithVariant(d);
|
||||
|
||||
ASSERT_TRUE(waitUntil(m_proxy->m_gotSignalWithVariant));
|
||||
ASSERT_THAT(m_proxy->m_variantFromSignal, DoubleEq(d));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_proxy->m_gotSignalWithVariant));
|
||||
ASSERT_THAT(this->m_proxy->m_variantFromSignal, DoubleEq(d));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsSignalWithoutRegistrationSuccesfully)
|
||||
TYPED_TEST(SdbusTestObject, EmitsSignalWithoutRegistrationSuccesfully)
|
||||
{
|
||||
m_adaptor->emitSignalWithoutRegistration({"platform", {"av"}});
|
||||
this->m_adaptor->emitSignalWithoutRegistration({"platform", {"av"}});
|
||||
|
||||
ASSERT_TRUE(waitUntil(m_proxy->m_gotSignalWithSignature));
|
||||
ASSERT_THAT(m_proxy->m_signatureFromSignal["platform"], Eq("av"));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_proxy->m_gotSignalWithSignature));
|
||||
ASSERT_THAT(this->m_proxy->m_signatureFromSignal["platform"], Eq("av"));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, CanAccessAssociatedSignalMessageInSignalHandler)
|
||||
TYPED_TEST(SdbusTestObject, CanAccessAssociatedSignalMessageInSignalHandler)
|
||||
{
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
waitUntil(m_proxy->m_gotSimpleSignal);
|
||||
this->waitUntil(this->m_proxy->m_gotSimpleSignal);
|
||||
|
||||
ASSERT_THAT(m_proxy->m_signalMsg, NotNull());
|
||||
ASSERT_THAT(m_proxy->m_signalMemberName, Eq("simpleSignal"));
|
||||
ASSERT_THAT(this->m_proxy->m_signalMsg, NotNull());
|
||||
ASSERT_THAT(this->m_proxy->m_signalMemberName, Eq("simpleSignal"));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, UnregistersSignalHandler)
|
||||
TYPED_TEST(SdbusTestObject, UnregistersSignalHandler)
|
||||
{
|
||||
ASSERT_NO_THROW(m_proxy->unregisterSimpleSignalHandler());
|
||||
ASSERT_NO_THROW(this->m_proxy->unregisterSimpleSignalHandler());
|
||||
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
ASSERT_FALSE(waitUntil(m_proxy->m_gotSimpleSignal, 2s));
|
||||
ASSERT_FALSE(this->waitUntil(this->m_proxy->m_gotSimpleSignal, 2s));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, UnregistersSignalHandlerForSomeProxies)
|
||||
TYPED_TEST(SdbusTestObject, UnregistersSignalHandlerForSomeProxies)
|
||||
{
|
||||
auto proxy1 = std::make_unique<TestProxy>(*s_adaptorConnection, BUS_NAME, OBJECT_PATH);
|
||||
auto proxy2 = std::make_unique<TestProxy>(*s_adaptorConnection, BUS_NAME, OBJECT_PATH);
|
||||
auto proxy1 = std::make_unique<TestProxy>(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH);
|
||||
auto proxy2 = std::make_unique<TestProxy>(*this->s_adaptorConnection, BUS_NAME, OBJECT_PATH);
|
||||
|
||||
ASSERT_NO_THROW(m_proxy->unregisterSimpleSignalHandler());
|
||||
ASSERT_NO_THROW(this->m_proxy->unregisterSimpleSignalHandler());
|
||||
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
ASSERT_TRUE(waitUntil(proxy1->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(waitUntil(proxy2->m_gotSimpleSignal));
|
||||
ASSERT_FALSE(waitUntil(m_proxy->m_gotSimpleSignal, 2s));
|
||||
ASSERT_TRUE(this->waitUntil(proxy1->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(this->waitUntil(proxy2->m_gotSimpleSignal));
|
||||
ASSERT_FALSE(this->waitUntil(this->m_proxy->m_gotSimpleSignal, 2s));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, ReRegistersSignalHandler)
|
||||
TYPED_TEST(SdbusTestObject, ReRegistersSignalHandler)
|
||||
{
|
||||
// unregister simple-signal handler
|
||||
ASSERT_NO_THROW(m_proxy->unregisterSimpleSignalHandler());
|
||||
ASSERT_NO_THROW(this->m_proxy->unregisterSimpleSignalHandler());
|
||||
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
ASSERT_FALSE(waitUntil(m_proxy->m_gotSimpleSignal, 2s));
|
||||
ASSERT_FALSE(this->waitUntil(this->m_proxy->m_gotSimpleSignal, 2s));
|
||||
|
||||
// re-register simple-signal handler
|
||||
ASSERT_NO_THROW(m_proxy->reRegisterSimpleSignalHandler());
|
||||
ASSERT_NO_THROW(this->m_proxy->reRegisterSimpleSignalHandler());
|
||||
|
||||
m_adaptor->emitSimpleSignal();
|
||||
this->m_adaptor->emitSimpleSignal();
|
||||
|
||||
ASSERT_TRUE(waitUntil(m_proxy->m_gotSimpleSignal));
|
||||
ASSERT_TRUE(this->waitUntil(this->m_proxy->m_gotSimpleSignal));
|
||||
}
|
||||
|
@ -48,18 +48,16 @@ using ::testing::SizeIs;
|
||||
using namespace std::chrono_literals;
|
||||
using namespace sdbus::test;
|
||||
|
||||
using SdbusTestObject = TestFixture;
|
||||
|
||||
/*-------------------------------------*/
|
||||
/* -- TEST CASES -- */
|
||||
/*-------------------------------------*/
|
||||
|
||||
TEST_F(SdbusTestObject, PingsViaPeerInterface)
|
||||
TYPED_TEST(SdbusTestObject, PingsViaPeerInterface)
|
||||
{
|
||||
ASSERT_NO_THROW(m_proxy->Ping());
|
||||
ASSERT_NO_THROW(this->m_proxy->Ping());
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, AnswersMachineUuidViaPeerInterface)
|
||||
TYPED_TEST(SdbusTestObject, AnswersMachineUuidViaPeerInterface)
|
||||
{
|
||||
// If /etc/machine-id does not exist in your system (which is very likely because you have
|
||||
// a non-systemd Linux), org.freedesktop.DBus.Peer.GetMachineId() will not work. To solve
|
||||
@ -68,45 +66,45 @@ TEST_F(SdbusTestObject, AnswersMachineUuidViaPeerInterface)
|
||||
if (::access("/etc/machine-id", F_OK) == -1)
|
||||
GTEST_SKIP() << "/etc/machine-id file does not exist, GetMachineId() will not work";
|
||||
|
||||
ASSERT_NO_THROW(m_proxy->GetMachineId());
|
||||
ASSERT_NO_THROW(this->m_proxy->GetMachineId());
|
||||
}
|
||||
|
||||
// TODO: Adjust expected xml and uncomment this test
|
||||
//TEST_F(SdbusTestObject, AnswersXmlApiDescriptionViaIntrospectableInterface)
|
||||
//TYPED_TEST(SdbusTestObject, AnswersXmlApiDescriptionViaIntrospectableInterface)
|
||||
//{
|
||||
// ASSERT_THAT(m_proxy->Introspect(), Eq(m_adaptor->getExpectedXmlApiDescription()));
|
||||
// ASSERT_THAT(this->m_proxy->Introspect(), Eq(this->m_adaptor->getExpectedXmlApiDescription()));
|
||||
//}
|
||||
|
||||
TEST_F(SdbusTestObject, GetsPropertyViaPropertiesInterface)
|
||||
TYPED_TEST(SdbusTestObject, GetsPropertyViaPropertiesInterface)
|
||||
{
|
||||
ASSERT_THAT(m_proxy->Get(INTERFACE_NAME, "state").get<std::string>(), Eq(DEFAULT_STATE_VALUE));
|
||||
ASSERT_THAT(this->m_proxy->Get(INTERFACE_NAME, "state").template get<std::string>(), Eq(DEFAULT_STATE_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, SetsPropertyViaPropertiesInterface)
|
||||
TYPED_TEST(SdbusTestObject, SetsPropertyViaPropertiesInterface)
|
||||
{
|
||||
uint32_t newActionValue = 2345;
|
||||
|
||||
m_proxy->Set(INTERFACE_NAME, "action", newActionValue);
|
||||
this->m_proxy->Set(INTERFACE_NAME, "action", newActionValue);
|
||||
|
||||
ASSERT_THAT(m_proxy->action(), Eq(newActionValue));
|
||||
ASSERT_THAT(this->m_proxy->action(), Eq(newActionValue));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, GetsAllPropertiesViaPropertiesInterface)
|
||||
TYPED_TEST(SdbusTestObject, GetsAllPropertiesViaPropertiesInterface)
|
||||
{
|
||||
const auto properties = m_proxy->GetAll(INTERFACE_NAME);
|
||||
const auto properties = this->m_proxy->GetAll(INTERFACE_NAME);
|
||||
|
||||
ASSERT_THAT(properties, SizeIs(3));
|
||||
EXPECT_THAT(properties.at("state").get<std::string>(), Eq(DEFAULT_STATE_VALUE));
|
||||
EXPECT_THAT(properties.at("action").get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
|
||||
EXPECT_THAT(properties.at("blocking").get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
|
||||
EXPECT_THAT(properties.at("state").template get<std::string>(), Eq(DEFAULT_STATE_VALUE));
|
||||
EXPECT_THAT(properties.at("action").template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
|
||||
EXPECT_THAT(properties.at("blocking").template get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsPropertyChangedSignalForSelectedProperties)
|
||||
TYPED_TEST(SdbusTestObject, EmitsPropertyChangedSignalForSelectedProperties)
|
||||
{
|
||||
std::atomic<bool> signalReceived{false};
|
||||
m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const std::string& interfaceName
|
||||
, const std::map<std::string, sdbus::Variant>& changedProperties
|
||||
, const std::vector<std::string>& /*invalidatedProperties*/ )
|
||||
this->m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const std::string& interfaceName
|
||||
, const std::map<std::string, sdbus::Variant>& changedProperties
|
||||
, const std::vector<std::string>& /*invalidatedProperties*/ )
|
||||
{
|
||||
EXPECT_THAT(interfaceName, Eq(INTERFACE_NAME));
|
||||
EXPECT_THAT(changedProperties, SizeIs(1));
|
||||
@ -114,19 +112,19 @@ TEST_F(SdbusTestObject, EmitsPropertyChangedSignalForSelectedProperties)
|
||||
signalReceived = true;
|
||||
};
|
||||
|
||||
m_proxy->blocking(!DEFAULT_BLOCKING_VALUE);
|
||||
m_proxy->action(DEFAULT_ACTION_VALUE*2);
|
||||
m_adaptor->emitPropertiesChangedSignal(INTERFACE_NAME, {"blocking"});
|
||||
this->m_proxy->blocking(!DEFAULT_BLOCKING_VALUE);
|
||||
this->m_proxy->action(DEFAULT_ACTION_VALUE*2);
|
||||
this->m_adaptor->emitPropertiesChangedSignal(INTERFACE_NAME, {"blocking"});
|
||||
|
||||
ASSERT_TRUE(waitUntil(signalReceived));
|
||||
ASSERT_TRUE(this->waitUntil(signalReceived));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsPropertyChangedSignalForAllProperties)
|
||||
TYPED_TEST(SdbusTestObject, EmitsPropertyChangedSignalForAllProperties)
|
||||
{
|
||||
std::atomic<bool> signalReceived{false};
|
||||
m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const std::string& interfaceName
|
||||
, const std::map<std::string, sdbus::Variant>& changedProperties
|
||||
, const std::vector<std::string>& invalidatedProperties )
|
||||
this->m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const std::string& interfaceName
|
||||
, const std::map<std::string, sdbus::Variant>& changedProperties
|
||||
, const std::vector<std::string>& invalidatedProperties )
|
||||
{
|
||||
EXPECT_THAT(interfaceName, Eq(INTERFACE_NAME));
|
||||
EXPECT_THAT(changedProperties, SizeIs(1));
|
||||
@ -136,38 +134,38 @@ TEST_F(SdbusTestObject, EmitsPropertyChangedSignalForAllProperties)
|
||||
signalReceived = true;
|
||||
};
|
||||
|
||||
m_adaptor->emitPropertiesChangedSignal(INTERFACE_NAME);
|
||||
this->m_adaptor->emitPropertiesChangedSignal(INTERFACE_NAME);
|
||||
|
||||
ASSERT_TRUE(waitUntil(signalReceived));
|
||||
ASSERT_TRUE(this->waitUntil(signalReceived));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, GetsZeroManagedObjectsIfHasNoSubPathObjects)
|
||||
TYPED_TEST(SdbusTestObject, GetsZeroManagedObjectsIfHasNoSubPathObjects)
|
||||
{
|
||||
m_adaptor.reset();
|
||||
const auto objectsInterfacesAndProperties = m_objectManagerProxy->GetManagedObjects();
|
||||
this->m_adaptor.reset();
|
||||
const auto objectsInterfacesAndProperties = this->m_objectManagerProxy->GetManagedObjects();
|
||||
|
||||
ASSERT_THAT(objectsInterfacesAndProperties, SizeIs(0));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, GetsManagedObjectsSuccessfully)
|
||||
TYPED_TEST(SdbusTestObject, GetsManagedObjectsSuccessfully)
|
||||
{
|
||||
auto adaptor2 = std::make_unique<TestAdaptor>(*s_adaptorConnection, OBJECT_PATH_2);
|
||||
const auto objectsInterfacesAndProperties = m_objectManagerProxy->GetManagedObjects();
|
||||
auto adaptor2 = std::make_unique<TestAdaptor>(*this->s_adaptorConnection, OBJECT_PATH_2);
|
||||
const auto objectsInterfacesAndProperties = this->m_objectManagerProxy->GetManagedObjects();
|
||||
|
||||
ASSERT_THAT(objectsInterfacesAndProperties, SizeIs(2));
|
||||
EXPECT_THAT(objectsInterfacesAndProperties.at(OBJECT_PATH)
|
||||
.at(org::sdbuscpp::integrationtests_adaptor::INTERFACE_NAME)
|
||||
.at("action").get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
|
||||
.at("action").template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
|
||||
EXPECT_THAT(objectsInterfacesAndProperties.at(OBJECT_PATH_2)
|
||||
.at(org::sdbuscpp::integrationtests_adaptor::INTERFACE_NAME)
|
||||
.at("action").get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
|
||||
.at("action").template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsInterfacesAddedSignalForSelectedObjectInterfaces)
|
||||
TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForSelectedObjectInterfaces)
|
||||
{
|
||||
std::atomic<bool> signalReceived{false};
|
||||
m_objectManagerProxy->m_onInterfacesAddedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
|
||||
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties )
|
||||
this->m_objectManagerProxy->m_onInterfacesAddedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
|
||||
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties )
|
||||
{
|
||||
EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
|
||||
EXPECT_THAT(interfacesAndProperties, SizeIs(1));
|
||||
@ -189,16 +187,16 @@ TEST_F(SdbusTestObject, EmitsInterfacesAddedSignalForSelectedObjectInterfaces)
|
||||
signalReceived = true;
|
||||
};
|
||||
|
||||
m_adaptor->emitInterfacesAddedSignal({INTERFACE_NAME});
|
||||
this->m_adaptor->emitInterfacesAddedSignal({INTERFACE_NAME});
|
||||
|
||||
ASSERT_TRUE(waitUntil(signalReceived));
|
||||
ASSERT_TRUE(this->waitUntil(signalReceived));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsInterfacesAddedSignalForAllObjectInterfaces)
|
||||
TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForAllObjectInterfaces)
|
||||
{
|
||||
std::atomic<bool> signalReceived{false};
|
||||
m_objectManagerProxy->m_onInterfacesAddedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
|
||||
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties )
|
||||
this->m_objectManagerProxy->m_onInterfacesAddedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
|
||||
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties )
|
||||
{
|
||||
EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
|
||||
#if LIBSYSTEMD_VERSION<=250
|
||||
@ -225,16 +223,16 @@ TEST_F(SdbusTestObject, EmitsInterfacesAddedSignalForAllObjectInterfaces)
|
||||
signalReceived = true;
|
||||
};
|
||||
|
||||
m_adaptor->emitInterfacesAddedSignal();
|
||||
this->m_adaptor->emitInterfacesAddedSignal();
|
||||
|
||||
ASSERT_TRUE(waitUntil(signalReceived));
|
||||
ASSERT_TRUE(this->waitUntil(signalReceived));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsInterfacesRemovedSignalForSelectedObjectInterfaces)
|
||||
TYPED_TEST(SdbusTestObject, EmitsInterfacesRemovedSignalForSelectedObjectInterfaces)
|
||||
{
|
||||
std::atomic<bool> signalReceived{false};
|
||||
m_objectManagerProxy->m_onInterfacesRemovedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
|
||||
, const std::vector<std::string>& interfaces )
|
||||
this->m_objectManagerProxy->m_onInterfacesRemovedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
|
||||
, const std::vector<std::string>& interfaces )
|
||||
{
|
||||
EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
|
||||
ASSERT_THAT(interfaces, SizeIs(1));
|
||||
@ -242,16 +240,16 @@ TEST_F(SdbusTestObject, EmitsInterfacesRemovedSignalForSelectedObjectInterfaces)
|
||||
signalReceived = true;
|
||||
};
|
||||
|
||||
m_adaptor->emitInterfacesRemovedSignal({INTERFACE_NAME});
|
||||
this->m_adaptor->emitInterfacesRemovedSignal({INTERFACE_NAME});
|
||||
|
||||
ASSERT_TRUE(waitUntil(signalReceived));
|
||||
ASSERT_TRUE(this->waitUntil(signalReceived));
|
||||
}
|
||||
|
||||
TEST_F(SdbusTestObject, EmitsInterfacesRemovedSignalForAllObjectInterfaces)
|
||||
TYPED_TEST(SdbusTestObject, EmitsInterfacesRemovedSignalForAllObjectInterfaces)
|
||||
{
|
||||
std::atomic<bool> signalReceived{false};
|
||||
m_objectManagerProxy->m_onInterfacesRemovedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
|
||||
, const std::vector<std::string>& interfaces )
|
||||
this->m_objectManagerProxy->m_onInterfacesRemovedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
|
||||
, const std::vector<std::string>& interfaces )
|
||||
{
|
||||
EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
|
||||
#if LIBSYSTEMD_VERSION<=250
|
||||
@ -264,7 +262,7 @@ TEST_F(SdbusTestObject, EmitsInterfacesRemovedSignalForAllObjectInterfaces)
|
||||
signalReceived = true;
|
||||
};
|
||||
|
||||
m_adaptor->emitInterfacesRemovedSignal();
|
||||
this->m_adaptor->emitInterfacesRemovedSignal();
|
||||
|
||||
ASSERT_TRUE(waitUntil(signalReceived));
|
||||
ASSERT_TRUE(this->waitUntil(signalReceived));
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
|
||||
* (C) 2016 - 2022 Stanislav Angelovic <stanislav.angelovic@protonmail.com>
|
||||
*
|
||||
* @file TestAdaptor.cpp
|
||||
* @file TestFixture.cpp
|
||||
*
|
||||
* Created on: May 23, 2020
|
||||
* Project: sdbus-c++
|
||||
@ -27,8 +27,12 @@
|
||||
#include "TestFixture.h"
|
||||
|
||||
namespace sdbus { namespace test {
|
||||
|
||||
std::unique_ptr<sdbus::IConnection> TestFixture::s_adaptorConnection = sdbus::createSystemBusConnection();
|
||||
std::unique_ptr<sdbus::IConnection> TestFixture::s_proxyConnection = sdbus::createSystemBusConnection();
|
||||
|
||||
std::unique_ptr<sdbus::IConnection> BaseTestFixture::s_adaptorConnection = sdbus::createSystemBusConnection();
|
||||
std::unique_ptr<sdbus::IConnection> BaseTestFixture::s_proxyConnection = sdbus::createSystemBusConnection();
|
||||
|
||||
std::thread TestFixture<SdEventLoop>::s_eventLoopThread{};
|
||||
sd_event *TestFixture<SdEventLoop>::s_sdEvent{};
|
||||
int TestFixture<SdEventLoop>::s_eventExitFd{-1};
|
||||
|
||||
}}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
|
||||
* (C) 2016 - 2022 Stanislav Angelovic <stanislav.angelovic@protonmail.com>
|
||||
*
|
||||
* @file TestAdaptor.h
|
||||
* @file TestFixture.h
|
||||
*
|
||||
* Created on: Jan 2, 2017
|
||||
* Project: sdbus-c++
|
||||
@ -33,6 +33,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
@ -41,22 +43,17 @@
|
||||
|
||||
namespace sdbus { namespace test {
|
||||
|
||||
class TestFixture : public ::testing::Test
|
||||
class BaseTestFixture : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
s_proxyConnection->enterEventLoopAsync();
|
||||
s_adaptorConnection->requestName(BUS_NAME);
|
||||
s_adaptorConnection->enterEventLoopAsync();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Give time for the proxy connection to start listening to signals
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
s_adaptorConnection->releaseName(BUS_NAME);
|
||||
s_adaptorConnection->leaveEventLoop();
|
||||
s_proxyConnection->leaveEventLoop();
|
||||
}
|
||||
|
||||
template <typename _Fnc>
|
||||
@ -84,17 +81,17 @@ public:
|
||||
private:
|
||||
void SetUp() override
|
||||
{
|
||||
m_objectManagerProxy = std::make_unique<ObjectManagerTestProxy>(*s_proxyConnection, BUS_NAME, MANAGER_PATH);
|
||||
m_proxy = std::make_unique<TestProxy>(*s_proxyConnection, BUS_NAME, OBJECT_PATH);
|
||||
m_objectManagerProxy = std::make_unique<ObjectManagerTestProxy>(*s_proxyConnection, BUS_NAME, MANAGER_PATH);
|
||||
m_proxy = std::make_unique<TestProxy>(*s_proxyConnection, BUS_NAME, OBJECT_PATH);
|
||||
|
||||
m_objectManagerAdaptor = std::make_unique<ObjectManagerTestAdaptor>(*s_adaptorConnection, MANAGER_PATH);
|
||||
m_adaptor = std::make_unique<TestAdaptor>(*s_adaptorConnection, OBJECT_PATH);
|
||||
m_objectManagerAdaptor = std::make_unique<ObjectManagerTestAdaptor>(*s_adaptorConnection, MANAGER_PATH);
|
||||
m_adaptor = std::make_unique<TestAdaptor>(*s_adaptorConnection, OBJECT_PATH);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_proxy.reset();
|
||||
m_adaptor.reset();
|
||||
m_proxy.reset();
|
||||
m_adaptor.reset();
|
||||
}
|
||||
|
||||
public:
|
||||
@ -106,6 +103,93 @@ public:
|
||||
std::unique_ptr<TestProxy> m_proxy;
|
||||
};
|
||||
|
||||
struct SdBusCppLoop{};
|
||||
struct SdEventLoop{};
|
||||
|
||||
template <typename _EventLoop>
|
||||
class TestFixture : public BaseTestFixture{};
|
||||
|
||||
// Fixture working upon internal sdbus-c++ event loop
|
||||
template <>
|
||||
class TestFixture<SdBusCppLoop> : public BaseTestFixture
|
||||
{
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
BaseTestFixture::SetUpTestCase();
|
||||
s_proxyConnection->enterEventLoopAsync();
|
||||
s_adaptorConnection->enterEventLoopAsync();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Give time for the proxy connection to start listening to signals
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
BaseTestFixture::TearDownTestCase();
|
||||
s_adaptorConnection->leaveEventLoop();
|
||||
s_proxyConnection->leaveEventLoop();
|
||||
}
|
||||
};
|
||||
|
||||
// Fixture working upon attached external sd-event loop
|
||||
template <>
|
||||
class TestFixture<SdEventLoop> : public BaseTestFixture
|
||||
{
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
sd_event_new(&s_sdEvent);
|
||||
|
||||
s_proxyConnection->attachSdEventLoop(s_sdEvent);
|
||||
s_adaptorConnection->attachSdEventLoop(s_sdEvent);
|
||||
|
||||
s_eventExitFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
// No callback means that the event loop will exit when this event source triggers
|
||||
sd_event_add_io(s_sdEvent, nullptr, s_eventExitFd, EPOLLIN, nullptr, NULL);
|
||||
|
||||
s_eventLoopThread = std::thread([]()
|
||||
{
|
||||
sd_event_loop(s_sdEvent);
|
||||
});
|
||||
|
||||
BaseTestFixture::SetUpTestCase();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Give time for the proxy connection to start listening to signals
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
uint64_t value = 1;
|
||||
write(s_eventExitFd, &value, sizeof(value));
|
||||
|
||||
s_eventLoopThread.join();
|
||||
|
||||
sd_event_unref(s_sdEvent);
|
||||
close(s_eventExitFd);
|
||||
|
||||
BaseTestFixture::TearDownTestCase();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::thread s_eventLoopThread;
|
||||
static sd_event *s_sdEvent;
|
||||
static int s_eventExitFd;
|
||||
};
|
||||
|
||||
typedef ::testing::Types<SdBusCppLoop, SdEventLoop> EventLoopTags;
|
||||
|
||||
TYPED_TEST_SUITE(TestFixture, EventLoopTags);
|
||||
|
||||
template <typename _EventLoop>
|
||||
using SdbusTestObject = TestFixture<_EventLoop>;
|
||||
TYPED_TEST_SUITE(SdbusTestObject, EventLoopTags);
|
||||
|
||||
template <typename _EventLoop>
|
||||
using AsyncSdbusTestObject = TestFixture<_EventLoop>;
|
||||
TYPED_TEST_SUITE(AsyncSdbusTestObject, EventLoopTags);
|
||||
|
||||
template <typename _EventLoop>
|
||||
using AConnection = TestFixture<_EventLoop>;
|
||||
TYPED_TEST_SUITE(AConnection, EventLoopTags);
|
||||
|
||||
}}
|
||||
|
||||
#endif /* SDBUS_CPP_INTEGRATIONTESTS_TESTFIXTURE_H_ */
|
||||
|
@ -2,7 +2,7 @@
|
||||
* (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
|
||||
* (C) 2016 - 2022 Stanislav Angelovic <stanislav.angelovic@protonmail.com>
|
||||
*
|
||||
* @file TestAdaptor.cpp
|
||||
* @file TestProxy.cpp
|
||||
*
|
||||
* Created on: May 23, 2020
|
||||
* Project: sdbus-c++
|
||||
|
@ -2,7 +2,7 @@
|
||||
* (C) 2016 - 2021 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
|
||||
* (C) 2016 - 2022 Stanislav Angelovic <stanislav.angelovic@protonmail.com>
|
||||
*
|
||||
* @file TestAdaptor.h
|
||||
* @file TestProxy.h
|
||||
*
|
||||
* Created on: Jan 2, 2017
|
||||
* Project: sdbus-c++
|
||||
|
@ -92,6 +92,8 @@ public:
|
||||
MOCK_METHOD2(sd_bus_creds_get_egid, int(sd_bus_creds *, gid_t *));
|
||||
MOCK_METHOD2(sd_bus_creds_get_supplementary_gids, int(sd_bus_creds *, const gid_t **));
|
||||
MOCK_METHOD2(sd_bus_creds_get_selinux_context, int(sd_bus_creds *, const char **));
|
||||
|
||||
MOCK_METHOD1(sd_bus_get_event, sd_event *(sd_bus *bus));
|
||||
};
|
||||
|
||||
#endif //SDBUS_CXX_SDBUS_MOCK_H
|
||||
|
Reference in New Issue
Block a user