diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index b226eac..3d3431f 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -39,14 +39,23 @@ set(UNITTESTS_SRCS
set(INTEGRATIONTESTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/integrationtests)
set(INTEGRATIONTESTS_SRCS
- ${INTEGRATIONTESTS_SOURCE_DIR}/AdaptorAndProxy_test.cpp
- ${INTEGRATIONTESTS_SOURCE_DIR}/Connection_test.cpp
- ${INTEGRATIONTESTS_SOURCE_DIR}/sdbus-c++-integration-tests.cpp
- ${INTEGRATIONTESTS_SOURCE_DIR}/adaptor-glue.h
- ${INTEGRATIONTESTS_SOURCE_DIR}/defs.h
- ${INTEGRATIONTESTS_SOURCE_DIR}/proxy-glue.h
- ${INTEGRATIONTESTS_SOURCE_DIR}/TestingAdaptor.h
- ${INTEGRATIONTESTS_SOURCE_DIR}/TestingProxy.h)
+ ${INTEGRATIONTESTS_SOURCE_DIR}/DBusConnectionTests.cpp
+ ${INTEGRATIONTESTS_SOURCE_DIR}/DBusGeneralTests.cpp
+ ${INTEGRATIONTESTS_SOURCE_DIR}/DBusMethodsTests.cpp
+ ${INTEGRATIONTESTS_SOURCE_DIR}/DBusAsyncMethodsTests.cpp
+ ${INTEGRATIONTESTS_SOURCE_DIR}/DBusSignalsTests.cpp
+ ${INTEGRATIONTESTS_SOURCE_DIR}/DBusPropertiesTests.cpp
+ ${INTEGRATIONTESTS_SOURCE_DIR}/DBusStandardInterfacesTests.cpp
+ ${INTEGRATIONTESTS_SOURCE_DIR}/Defs.h
+ ${INTEGRATIONTESTS_SOURCE_DIR}/integrationtests-adaptor.h
+ ${INTEGRATIONTESTS_SOURCE_DIR}/integrationtests-proxy.h
+ ${INTEGRATIONTESTS_SOURCE_DIR}/TestFixture.h
+ ${INTEGRATIONTESTS_SOURCE_DIR}/TestFixture.cpp
+ ${INTEGRATIONTESTS_SOURCE_DIR}/TestAdaptor.h
+ ${INTEGRATIONTESTS_SOURCE_DIR}/TestAdaptor.cpp
+ ${INTEGRATIONTESTS_SOURCE_DIR}/TestProxy.h
+ ${INTEGRATIONTESTS_SOURCE_DIR}/TestProxy.cpp
+ ${INTEGRATIONTESTS_SOURCE_DIR}/sdbus-c++-integration-tests.cpp)
set(PERFTESTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/perftests)
set(STRESSTESTS_CLIENT_SRCS
diff --git a/tests/integrationtests/AdaptorAndProxy_test.cpp b/tests/integrationtests/AdaptorAndProxy_test.cpp
index 17df3b0..8ee2a44 100644
--- a/tests/integrationtests/AdaptorAndProxy_test.cpp
+++ b/tests/integrationtests/AdaptorAndProxy_test.cpp
@@ -24,25 +24,19 @@
* along with sdbus-c++. If not, see .
*/
-// Own
-#include "TestingAdaptor.h"
-#include "TestingProxy.h"
-
-// sdbus
+#include "TestFixture.h"
+#include "TestAdaptor.h"
+#include "TestProxy.h"
#include "sdbus-c++/sdbus-c++.h"
-// gmock
#include
#include
-
-// STL
#include
#include
#include
#include
#include
#include
-
#include
using ::testing::Eq;
@@ -52,71 +46,9 @@ using ::testing::AnyOf;
using ::testing::ElementsAre;
using ::testing::SizeIs;
using namespace std::chrono_literals;
+using namespace sdbus::test;
-namespace
-{
-
-class AdaptorAndProxyFixture : public ::testing::Test
-{
-public:
- static void SetUpTestCase()
- {
- s_connection->requestName(INTERFACE_NAME);
- s_connection->enterEventLoopAsync();
- }
-
- static void TearDownTestCase()
- {
- s_connection->leaveEventLoop();
- s_connection->releaseName(INTERFACE_NAME);
- }
-
- template
- static bool waitUntil(_Fnc&& fnc, std::chrono::milliseconds timeout = 5s)
- {
- std::chrono::milliseconds elapsed{};
- std::chrono::milliseconds step{5ms};
- do {
- std::this_thread::sleep_for(step);
- elapsed += step;
- if (elapsed > timeout)
- return false;
- } while (!fnc());
-
- return true;
- }
-
- static bool waitUntil(std::atomic& flag, std::chrono::milliseconds timeout = 5s)
- {
- return waitUntil([&flag]() -> bool { return flag; }, timeout);
- }
-
-private:
- void SetUp() override
- {
- m_adaptor = std::make_unique(*s_connection);
- m_proxy = std::make_unique(INTERFACE_NAME, OBJECT_PATH);
- std::this_thread::sleep_for(50ms); // Give time for the proxy to start listening to signals
- }
-
- void TearDown() override
- {
- m_proxy.reset();
- m_adaptor.reset();
- }
-
-public:
- static std::unique_ptr s_connection;
-
- std::unique_ptr m_adaptor;
- std::unique_ptr m_proxy;
-};
-
-std::unique_ptr AdaptorAndProxyFixture::s_connection = sdbus::createSystemBusConnection();
-
-}
-
-using SdbusTestObject = AdaptorAndProxyFixture;
+using SdbusTestObject = TestFixture;
/*-------------------------------------*/
/* -- TEST CASES -- */
@@ -127,8 +59,8 @@ TEST(AdaptorAndProxy, CanBeConstructedSuccesfully)
auto connection = sdbus::createConnection();
connection->requestName(INTERFACE_NAME);
- ASSERT_NO_THROW(TestingAdaptor adaptor(*connection));
- ASSERT_NO_THROW(TestingProxy proxy(INTERFACE_NAME, OBJECT_PATH));
+ ASSERT_NO_THROW(TestAdaptor adaptor(*connection));
+ ASSERT_NO_THROW(TestProxy proxy(INTERFACE_NAME, OBJECT_PATH));
connection->releaseName(INTERFACE_NAME);
}
@@ -279,7 +211,7 @@ TEST_F(SdbusTestObject, ThrowsTimeoutErrorWhenClientSideAsyncMethodTimesOut)
});
m_proxy->doOperationClientSideAsyncWith500msTimeout(1000); // The operation will take 1s, but the timeout is 500ms, so we should time out
- future.get(), Eq(100);
+ future.get();
FAIL() << "Expected sdbus::Error exception";
}
@@ -328,7 +260,7 @@ TEST_F(SdbusTestObject, RunsServerSideAsynchoronousMethodAsynchronously)
std::atomic startedCount{};
auto call = [&](uint32_t param)
{
- TestingProxy proxy{INTERFACE_NAME, OBJECT_PATH};
+ TestProxy proxy{INTERFACE_NAME, OBJECT_PATH};
++startedCount;
while (!invoke) ;
auto result = proxy.doOperationAsync(param);
@@ -351,7 +283,7 @@ TEST_F(SdbusTestObject, HandlesCorrectlyABulkOfParallelServerSideAsyncMethods)
std::atomic startedCount{};
auto call = [&]()
{
- TestingProxy proxy{INTERFACE_NAME, OBJECT_PATH};
+ TestProxy proxy{INTERFACE_NAME, OBJECT_PATH};
++startedCount;
while (!invoke) ;
@@ -465,17 +397,17 @@ TEST_F(SdbusTestObject, FailsCallingMethodOnNonexistentInterface)
TEST_F(SdbusTestObject, FailsCallingMethodOnNonexistentDestination)
{
- TestingProxy proxy("sdbuscpp.destination.that.does.not.exist", OBJECT_PATH);
+ TestProxy proxy("sdbuscpp.destination.that.does.not.exist", OBJECT_PATH);
ASSERT_THROW(proxy.getInt(), sdbus::Error);
}
TEST_F(SdbusTestObject, FailsCallingMethodOnNonexistentObject)
{
- TestingProxy proxy(INTERFACE_NAME, "/sdbuscpp/path/that/does/not/exist");
+ TestProxy proxy(INTERFACE_NAME, "/sdbuscpp/path/that/does/not/exist");
ASSERT_THROW(proxy.getInt(), sdbus::Error);
}
-TEST_F(SdbusTestObject, ReceivesTwoSignalsWhileMakingMethodCall)
+TEST_F(SdbusTestObject, CanReceiveSignalWhileMakingMethodCall)
{
m_proxy->emitTwoSimpleSignals();
@@ -508,8 +440,8 @@ TEST_F(SdbusTestObject, EmitsSimpleSignalSuccesfully)
TEST_F(SdbusTestObject, EmitsSimpleSignalToMultipleProxiesSuccesfully)
{
- auto proxy1 = std::make_unique(*s_connection, INTERFACE_NAME, OBJECT_PATH);
- auto proxy2 = std::make_unique(*s_connection, INTERFACE_NAME, OBJECT_PATH);
+ auto proxy1 = std::make_unique(*s_connection, INTERFACE_NAME, OBJECT_PATH);
+ auto proxy2 = std::make_unique(*s_connection, INTERFACE_NAME, OBJECT_PATH);
m_adaptor->emitSimpleSignal();
@@ -553,7 +485,7 @@ TEST_F(SdbusTestObject, ReadsReadOnlyPropertySuccesfully)
TEST_F(SdbusTestObject, FailsWritingToReadOnlyProperty)
{
- ASSERT_THROW(m_proxy->state("new_value"), sdbus::Error);
+ ASSERT_THROW(m_proxy->setStateProperty("new_value"), sdbus::Error);
}
TEST_F(SdbusTestObject, WritesAndReadsReadWritePropertySuccesfully)
diff --git a/tests/integrationtests/DBusAsyncMethodsTests.cpp b/tests/integrationtests/DBusAsyncMethodsTests.cpp
new file mode 100644
index 0000000..7c185f4
--- /dev/null
+++ b/tests/integrationtests/DBusAsyncMethodsTests.cpp
@@ -0,0 +1,219 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2020 Stanislav Angelovic
+ *
+ * @file DBusAsyncMethodsTests.cpp
+ *
+ * Created on: Jan 2, 2017
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "TestFixture.h"
+#include "TestAdaptor.h"
+#include "TestProxy.h"
+#include "sdbus-c++/sdbus-c++.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using ::testing::Eq;
+using ::testing::DoubleEq;
+using ::testing::Gt;
+using ::testing::AnyOf;
+using ::testing::ElementsAre;
+using ::testing::SizeIs;
+using namespace std::chrono_literals;
+using namespace sdbus::test;
+
+using SdbusTestObject = TestFixture;
+
+/*-------------------------------------*/
+/* -- TEST CASES -- */
+/*-------------------------------------*/
+
+TEST_F(SdbusTestObject, ThrowsTimeoutErrorWhenClientSideAsyncMethodTimesOut)
+{
+ try
+ {
+ std::promise promise;
+ auto future = promise.get_future();
+ m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t res, const sdbus::Error* err)
+ {
+ if (err == nullptr)
+ promise.set_value(res);
+ else
+ promise.set_exception(std::make_exception_ptr(*err));
+ });
+
+ m_proxy->doOperationClientSideAsyncWith500msTimeout(1000); // The operation will take 1s, but the timeout is 500ms, so we should time out
+ future.get();
+
+ FAIL() << "Expected sdbus::Error exception";
+ }
+ catch (const sdbus::Error& e)
+ {
+ ASSERT_THAT(e.getName(), AnyOf("org.freedesktop.DBus.Error.Timeout", "org.freedesktop.DBus.Error.NoReply"));
+ ASSERT_THAT(e.getMessage(), AnyOf("Connection timed out", "Method call timed out"));
+ }
+ catch(...)
+ {
+ FAIL() << "Expected sdbus::Error exception";
+ }
+}
+
+TEST_F(SdbusTestObject, RunsServerSideAsynchoronousMethodAsynchronously)
+{
+ // Yeah, this is kinda timing-dependent test, but times should be safe...
+ std::mutex mtx;
+ std::vector results;
+ std::atomic invoke{};
+ std::atomic startedCount{};
+ auto call = [&](uint32_t param)
+ {
+ TestProxy proxy{INTERFACE_NAME, OBJECT_PATH};
+ ++startedCount;
+ while (!invoke) ;
+ auto result = proxy.doOperationAsync(param);
+ std::lock_guard guard(mtx);
+ results.push_back(result);
+ };
+
+ std::thread invocations[]{std::thread{call, 1500}, std::thread{call, 1000}, std::thread{call, 500}};
+ while (startedCount != 3) ;
+ invoke = true;
+ std::for_each(std::begin(invocations), std::end(invocations), [](auto& t){ t.join(); });
+
+ ASSERT_THAT(results, ElementsAre(500, 1000, 1500));
+}
+
+TEST_F(SdbusTestObject, HandlesCorrectlyABulkOfParallelServerSideAsyncMethods)
+{
+ std::atomic resultCount{};
+ std::atomic invoke{};
+ std::atomic startedCount{};
+ auto call = [&]()
+ {
+ TestProxy proxy{INTERFACE_NAME, OBJECT_PATH};
+ ++startedCount;
+ while (!invoke) ;
+
+ size_t localResultCount{};
+ for (size_t i = 0; i < 500; ++i)
+ {
+ auto result = proxy.doOperationAsync(i % 2);
+ if (result == (i % 2)) // Correct return value?
+ localResultCount++;
+ }
+
+ resultCount += localResultCount;
+ };
+
+ std::thread invocations[]{std::thread{call}, std::thread{call}, std::thread{call}};
+ while (startedCount != 3) ;
+ invoke = true;
+ std::for_each(std::begin(invocations), std::end(invocations), [](auto& t){ t.join(); });
+
+ ASSERT_THAT(resultCount, Eq(1500));
+}
+
+TEST_F(SdbusTestObject, InvokesMethodAsynchronouslyOnClientSide)
+{
+ std::promise promise;
+ auto future = promise.get_future();
+ m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t res, const sdbus::Error* err)
+ {
+ if (err == nullptr)
+ promise.set_value(res);
+ else
+ promise.set_exception(std::make_exception_ptr(*err));
+ });
+
+ m_proxy->doOperationClientSideAsync(100);
+
+ ASSERT_THAT(future.get(), Eq(100));
+}
+
+TEST_F(SdbusTestObject, AnswersThatAsyncCallIsPendingIfItIsInProgress)
+{
+ m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t /*res*/, const sdbus::Error* /*err*/){});
+
+ auto call = m_proxy->doOperationClientSideAsync(100);
+
+ ASSERT_TRUE(call.isPending());
+}
+
+TEST_F(SdbusTestObject, CancelsPendingAsyncCallOnClientSide)
+{
+ std::promise 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);
+
+ call.cancel();
+
+ ASSERT_THAT(future.wait_for(300ms), Eq(std::future_status::timeout));
+}
+
+TEST_F(SdbusTestObject, AnswersThatAsyncCallIsNotPendingAfterItHasBeenCancelled)
+{
+ std::promise 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);
+
+ call.cancel();
+
+ ASSERT_FALSE(call.isPending());
+}
+
+TEST_F(SdbusTestObject, AnswersThatAsyncCallIsNotPendingAfterItHasBeenCompleted)
+{
+ std::promise 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(0);
+ (void) future.get(); // Wait for the call to finish
+
+ ASSERT_TRUE(waitUntil([&call](){ return !call.isPending(); }));
+}
+
+TEST_F(SdbusTestObject, InvokesErroneousMethodAsynchronouslyOnClientSide)
+{
+ std::promise promise;
+ auto future = promise.get_future();
+ m_proxy->installDoOperationClientSideAsyncReplyHandler([&](uint32_t res, const sdbus::Error* err)
+ {
+ if (err == nullptr)
+ promise.set_value(res);
+ else
+ promise.set_exception(std::make_exception_ptr(*err));
+ });
+
+ m_proxy->doErroneousOperationClientSideAsync();
+
+ ASSERT_THROW(future.get(), sdbus::Error);
+}
diff --git a/tests/integrationtests/Connection_test.cpp b/tests/integrationtests/DBusConnectionTests.cpp
similarity index 94%
rename from tests/integrationtests/Connection_test.cpp
rename to tests/integrationtests/DBusConnectionTests.cpp
index 231aa95..714f6ba 100644
--- a/tests/integrationtests/Connection_test.cpp
+++ b/tests/integrationtests/DBusConnectionTests.cpp
@@ -1,8 +1,8 @@
/**
* (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
- * (C) 2016 - 2019 Stanislav Angelovic
+ * (C) 2016 - 2020 Stanislav Angelovic
*
- * @file Connection_test.cpp
+ * @file DBusConnectionTests.cpp
*
* Created on: Jan 2, 2017
* Project: sdbus-c++
@@ -25,7 +25,7 @@
*/
// Own
-#include "defs.h"
+#include "Defs.h"
// sdbus
#include
@@ -39,7 +39,7 @@
#include
using ::testing::Eq;
-
+using namespace sdbus::test;
/*-------------------------------------*/
/* -- TEST CASES -- */
diff --git a/tests/integrationtests/DBusGeneralTests.cpp b/tests/integrationtests/DBusGeneralTests.cpp
new file mode 100644
index 0000000..a0eab34
--- /dev/null
+++ b/tests/integrationtests/DBusGeneralTests.cpp
@@ -0,0 +1,56 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2020 Stanislav Angelovic
+ *
+ * @file DBusGeneralTests.cpp
+ *
+ * Created on: Jan 2, 2017
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "TestAdaptor.h"
+#include "TestProxy.h"
+#include "sdbus-c++/sdbus-c++.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace sdbus::test;
+
+/*-------------------------------------*/
+/* -- TEST CASES -- */
+/*-------------------------------------*/
+
+TEST(AdaptorAndProxy, CanBeConstructedSuccesfully)
+{
+ auto connection = sdbus::createConnection();
+ connection->requestName(INTERFACE_NAME);
+
+ ASSERT_NO_THROW(TestAdaptor adaptor(*connection));
+ ASSERT_NO_THROW(TestProxy proxy(INTERFACE_NAME, OBJECT_PATH));
+
+ connection->releaseName(INTERFACE_NAME);
+}
diff --git a/tests/integrationtests/DBusMethodsTests.cpp b/tests/integrationtests/DBusMethodsTests.cpp
new file mode 100644
index 0000000..c1362db
--- /dev/null
+++ b/tests/integrationtests/DBusMethodsTests.cpp
@@ -0,0 +1,253 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2020 Stanislav Angelovic
+ *
+ * @file DBusMethodsTests.cpp
+ *
+ * Created on: Jan 2, 2017
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "TestFixture.h"
+#include "TestAdaptor.h"
+#include "TestProxy.h"
+#include "sdbus-c++/sdbus-c++.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using ::testing::Eq;
+using ::testing::DoubleEq;
+using ::testing::Gt;
+using ::testing::AnyOf;
+using ::testing::ElementsAre;
+using ::testing::SizeIs;
+using namespace std::chrono_literals;
+using namespace sdbus::test;
+
+using SdbusTestObject = TestFixture;
+
+/*-------------------------------------*/
+/* -- TEST CASES -- */
+/*-------------------------------------*/
+
+TEST_F(SdbusTestObject, CallsEmptyMethodSuccesfully)
+{
+ ASSERT_NO_THROW(m_proxy->noArgNoReturn());
+}
+
+TEST_F(SdbusTestObject, CallsMethodsWithBaseTypesSuccesfully)
+{
+ auto resInt = m_proxy->getInt();
+ ASSERT_THAT(resInt, Eq(INT32_VALUE));
+
+ auto multiplyRes = m_proxy->multiply(INT64_VALUE, DOUBLE_VALUE);
+ ASSERT_THAT(multiplyRes, Eq(INT64_VALUE * DOUBLE_VALUE));
+}
+
+TEST_F(SdbusTestObject, CallsMethodsWithTuplesSuccesfully)
+{
+ auto resTuple = 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)
+{
+ sdbus::Struct> a{};
+ auto vectorRes = m_proxy->getInts16FromStruct(a);
+ ASSERT_THAT(vectorRes, Eq(std::vector{0})); // because second item is by default initialized to 0
+
+
+ sdbus::Struct> b{
+ UINT8_VALUE, INT16_VALUE, DOUBLE_VALUE, STRING_VALUE, {INT16_VALUE, -INT16_VALUE}
+ };
+ vectorRes = m_proxy->getInts16FromStruct(b);
+ ASSERT_THAT(vectorRes, Eq(std::vector{INT16_VALUE, INT16_VALUE, -INT16_VALUE}));
+}
+
+TEST_F(SdbusTestObject, CallsMethodWithVariantSuccesfully)
+{
+ sdbus::Variant v{DOUBLE_VALUE};
+ auto variantRes = m_proxy->processVariant(v);
+ ASSERT_THAT(variantRes.get(), Eq(static_cast(DOUBLE_VALUE)));
+}
+
+TEST_F(SdbusTestObject, CallsMethodWithStructVariantsAndGetMapSuccesfully)
+{
+ std::vector x{-2, 0, 2};
+ sdbus::Struct y{false, true};
+ auto mapOfVariants = m_proxy->getMapOfVariants(x, y);
+ decltype(mapOfVariants) res{{-2, false}, {0, false}, {2, true}};
+
+ ASSERT_THAT(mapOfVariants[-2].get(), Eq(res[-2].get()));
+ ASSERT_THAT(mapOfVariants[0].get(), Eq(res[0].get()));
+ ASSERT_THAT(mapOfVariants[2].get(), Eq(res[2].get()));
+}
+
+TEST_F(SdbusTestObject, CallsMethodWithStructInStructSuccesfully)
+{
+ auto val = m_proxy->getStructInStruct();
+ ASSERT_THAT(val.get<0>(), Eq(STRING_VALUE));
+ ASSERT_THAT(std::get<0>(std::get<1>(val))[INT32_VALUE], Eq(INT32_VALUE));
+}
+
+TEST_F(SdbusTestObject, CallsMethodWithTwoStructsSuccesfully)
+{
+ auto val = m_proxy->sumStructItems({1, 2}, {3, 4});
+ ASSERT_THAT(val, Eq(1 + 2 + 3 + 4));
+}
+
+TEST_F(SdbusTestObject, CallsMethodWithTwoVectorsSuccesfully)
+{
+ auto val = m_proxy->sumVectorItems({1, 7}, {2, 3});
+ ASSERT_THAT(val, Eq(1 + 7 + 2 + 3));
+}
+
+TEST_F(SdbusTestObject, CallsMethodWithSignatureSuccesfully)
+{
+ auto resSignature = m_proxy->getSignature();
+ ASSERT_THAT(resSignature, Eq(SIGNATURE_VALUE));
+}
+
+TEST_F(SdbusTestObject, CallsMethodWithObjectPathSuccesfully)
+{
+ auto resObjectPath = m_proxy->getObjectPath();
+ ASSERT_THAT(resObjectPath, Eq(OBJECT_PATH_VALUE));
+}
+
+TEST_F(SdbusTestObject, CallsMethodWithUnixFdSuccesfully)
+{
+ auto resUnixFd = m_proxy->getUnixFd();
+ ASSERT_THAT(resUnixFd.get(), Gt(UNIX_FD_VALUE));
+}
+
+TEST_F(SdbusTestObject, CallsMethodWithComplexTypeSuccesfully)
+{
+ auto resComplex = m_proxy->getComplex();
+ ASSERT_THAT(resComplex.count(0), Eq(1));
+}
+
+TEST_F(SdbusTestObject, CallsMultiplyMethodWithNoReplyFlag)
+{
+ 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));
+}
+
+TEST_F(SdbusTestObject, CallsMethodWithCustomTimeoutSuccessfully)
+{
+ auto res = m_proxy->doOperationWith500msTimeout(20); // The operation will take 20ms, but the timeout is 500ms, so we are fine
+ ASSERT_THAT(res, Eq(20));
+}
+
+TEST_F(SdbusTestObject, ThrowsTimeoutErrorWhenMethodTimesOut)
+{
+ try
+ {
+ m_proxy->doOperationWith500msTimeout(1000); // The operation will take 1s, but the timeout is 500ms, so we should time out
+ FAIL() << "Expected sdbus::Error exception";
+ }
+ catch (const sdbus::Error& e)
+ {
+ ASSERT_THAT(e.getName(), AnyOf("org.freedesktop.DBus.Error.Timeout", "org.freedesktop.DBus.Error.NoReply"));
+ ASSERT_THAT(e.getMessage(), AnyOf("Connection timed out", "Method call timed out"));
+ }
+ catch(...)
+ {
+ FAIL() << "Expected sdbus::Error exception";
+ }
+}
+
+TEST_F(SdbusTestObject, CallsMethodThatThrowsError)
+{
+ try
+ {
+ m_proxy->throwError();
+ FAIL() << "Expected sdbus::Error exception";
+ }
+ catch (const sdbus::Error& e)
+ {
+ ASSERT_THAT(e.getName(), Eq("org.freedesktop.DBus.Error.AccessDenied"));
+ ASSERT_THAT(e.getMessage(), Eq("A test error occurred (Operation not permitted)"));
+ }
+ catch(...)
+ {
+ FAIL() << "Expected sdbus::Error exception";
+ }
+}
+
+TEST_F(SdbusTestObject, CallsErrorThrowingMethodWithDontExpectReplySet)
+{
+ ASSERT_NO_THROW(m_proxy->throwErrorWithNoReply());
+
+ ASSERT_TRUE(waitUntil(m_adaptor->m_wasThrowErrorCalled));
+}
+
+TEST_F(SdbusTestObject, FailsCallingNonexistentMethod)
+{
+ ASSERT_THROW(m_proxy->callNonexistentMethod(), sdbus::Error);
+}
+
+TEST_F(SdbusTestObject, FailsCallingMethodOnNonexistentInterface)
+{
+ ASSERT_THROW(m_proxy->callMethodOnNonexistentInterface(), sdbus::Error);
+}
+
+TEST_F(SdbusTestObject, FailsCallingMethodOnNonexistentDestination)
+{
+ TestProxy proxy("sdbuscpp.destination.that.does.not.exist", OBJECT_PATH);
+ ASSERT_THROW(proxy.getInt(), sdbus::Error);
+}
+
+TEST_F(SdbusTestObject, FailsCallingMethodOnNonexistentObject)
+{
+ TestProxy proxy(INTERFACE_NAME, "/sdbuscpp/path/that/does/not/exist");
+ ASSERT_THROW(proxy.getInt(), sdbus::Error);
+}
+
+TEST_F(SdbusTestObject, CanReceiveSignalWhileMakingMethodCall)
+{
+ m_proxy->emitTwoSimpleSignals();
+
+ ASSERT_TRUE(waitUntil(m_proxy->m_gotSimpleSignal));
+ ASSERT_TRUE(waitUntil(m_proxy->m_gotSignalWithMap));
+}
+
+#if LIBSYSTEMD_VERSION>=240
+TEST_F(SdbusTestObject, CanSetGeneralMethodTimeoutWithLibsystemdVersionGreaterThan239)
+{
+ s_connection->setMethodCallTimeout(5000000);
+ ASSERT_THAT(s_connection->getMethodCallTimeout(), Eq(5000000));
+}
+#else
+TEST_F(SdbusTestObject, CannotSetGeneralMethodTimeoutWithLibsystemdVersionLessThan240)
+{
+ ASSERT_THROW(s_connection->setMethodCallTimeout(5000000), sdbus::Error);
+ ASSERT_THROW(s_connection->getMethodCallTimeout(), sdbus::Error);
+}
+#endif
diff --git a/tests/integrationtests/DBusPropertiesTests.cpp b/tests/integrationtests/DBusPropertiesTests.cpp
new file mode 100644
index 0000000..5ab712c
--- /dev/null
+++ b/tests/integrationtests/DBusPropertiesTests.cpp
@@ -0,0 +1,74 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2020 Stanislav Angelovic
+ *
+ * @file DBusPropertiesTests.cpp
+ *
+ * Created on: Jan 2, 2017
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "TestFixture.h"
+#include "TestAdaptor.h"
+#include "TestProxy.h"
+#include "sdbus-c++/sdbus-c++.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using ::testing::Eq;
+using ::testing::DoubleEq;
+using ::testing::Gt;
+using ::testing::AnyOf;
+using ::testing::ElementsAre;
+using ::testing::SizeIs;
+using namespace std::chrono_literals;
+using namespace sdbus::test;
+
+using SdbusTestObject = TestFixture;
+
+/*-------------------------------------*/
+/* -- TEST CASES -- */
+/*-------------------------------------*/
+
+TEST_F(SdbusTestObject, ReadsReadOnlyPropertySuccesfully)
+{
+ ASSERT_THAT(m_proxy->state(), Eq(DEFAULT_STATE_VALUE));
+}
+
+TEST_F(SdbusTestObject, FailsWritingToReadOnlyProperty)
+{
+ ASSERT_THROW(m_proxy->setStateProperty("new_value"), sdbus::Error);
+}
+
+TEST_F(SdbusTestObject, WritesAndReadsReadWritePropertySuccesfully)
+{
+ uint32_t newActionValue = 5678;
+
+ m_proxy->action(newActionValue);
+
+ ASSERT_THAT(m_proxy->action(), Eq(newActionValue));
+}
diff --git a/tests/integrationtests/DBusSignalsTests.cpp b/tests/integrationtests/DBusSignalsTests.cpp
new file mode 100644
index 0000000..bbf6b35
--- /dev/null
+++ b/tests/integrationtests/DBusSignalsTests.cpp
@@ -0,0 +1,94 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2019 Stanislav Angelovic
+ *
+ * @file AdaptorAndProxy_test.cpp
+ *
+ * Created on: Jan 2, 2017
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "TestFixture.h"
+#include "TestAdaptor.h"
+#include "TestProxy.h"
+#include "sdbus-c++/sdbus-c++.h"
+
+#include
+#include
+#include
+
+using ::testing::Eq;
+using ::testing::DoubleEq;
+using ::testing::Gt;
+using ::testing::AnyOf;
+using ::testing::ElementsAre;
+using ::testing::SizeIs;
+using namespace std::chrono_literals;
+using namespace sdbus::test;
+
+using SdbusTestObject = TestFixture;
+
+/*-------------------------------------*/
+/* -- TEST CASES -- */
+/*-------------------------------------*/
+
+TEST_F(SdbusTestObject, EmitsSimpleSignalSuccesfully)
+{
+ m_adaptor->emitSimpleSignal();
+
+ ASSERT_TRUE(waitUntil(m_proxy->m_gotSimpleSignal));
+}
+
+TEST_F(SdbusTestObject, EmitsSimpleSignalToMultipleProxiesSuccesfully)
+{
+ auto proxy1 = std::make_unique(*s_connection, INTERFACE_NAME, OBJECT_PATH);
+ auto proxy2 = std::make_unique(*s_connection, INTERFACE_NAME, OBJECT_PATH);
+
+ m_adaptor->emitSimpleSignal();
+
+ ASSERT_TRUE(waitUntil(m_proxy->m_gotSimpleSignal));
+ ASSERT_TRUE(waitUntil(proxy1->m_gotSimpleSignal));
+ ASSERT_TRUE(waitUntil(proxy2->m_gotSimpleSignal));
+}
+
+TEST_F(SdbusTestObject, EmitsSignalWithMapSuccesfully)
+{
+ 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"));
+}
+
+TEST_F(SdbusTestObject, EmitsSignalWithVariantSuccesfully)
+{
+ double d = 3.14;
+ m_adaptor->emitSignalWithVariant(d);
+
+ ASSERT_TRUE(waitUntil(m_proxy->m_gotSignalWithVariant));
+ ASSERT_THAT(m_proxy->m_variantFromSignal, DoubleEq(d));
+}
+
+TEST_F(SdbusTestObject, EmitsSignalWithoutRegistrationSuccesfully)
+{
+ m_adaptor->emitSignalWithoutRegistration({"platform", {"av"}});
+
+ ASSERT_TRUE(waitUntil(m_proxy->m_gotSignalWithSignature));
+ ASSERT_THAT(m_proxy->m_signatureFromSignal["platform"], Eq("av"));
+}
diff --git a/tests/integrationtests/DBusStandardInterfacesTests.cpp b/tests/integrationtests/DBusStandardInterfacesTests.cpp
new file mode 100644
index 0000000..bef754e
--- /dev/null
+++ b/tests/integrationtests/DBusStandardInterfacesTests.cpp
@@ -0,0 +1,259 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2020 Stanislav Angelovic
+ *
+ * @file DBusStandardInterfacesTests.cpp
+ *
+ * Created on: Jan 2, 2017
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "TestFixture.h"
+#include "TestAdaptor.h"
+#include "TestProxy.h"
+#include "sdbus-c++/sdbus-c++.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using ::testing::Eq;
+using ::testing::DoubleEq;
+using ::testing::Gt;
+using ::testing::AnyOf;
+using ::testing::ElementsAre;
+using ::testing::SizeIs;
+using namespace std::chrono_literals;
+using namespace sdbus::test;
+
+using SdbusTestObject = TestFixture;
+
+/*-------------------------------------*/
+/* -- TEST CASES -- */
+/*-------------------------------------*/
+
+TEST_F(SdbusTestObject, PingsViaPeerInterface)
+{
+ ASSERT_NO_THROW(m_proxy->Ping());
+}
+
+TEST_F(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
+ // this, you can create /etc/machine-id yourself as symlink to /var/lib/dbus/machine-id,
+ // and then org.freedesktop.DBus.Peer.GetMachineId() will start to work.
+ 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());
+}
+
+// TODO: Adjust expected xml and uncomment this test
+//TEST_F(SdbusTestObject, AnswersXmlApiDescriptionViaIntrospectableInterface)
+//{
+// ASSERT_THAT(m_proxy->Introspect(), Eq(m_adaptor->getExpectedXmlApiDescription()));
+//}
+
+TEST_F(SdbusTestObject, GetsPropertyViaPropertiesInterface)
+{
+ ASSERT_THAT(m_proxy->Get(INTERFACE_NAME, "state").get(), Eq(DEFAULT_STATE_VALUE));
+}
+
+TEST_F(SdbusTestObject, SetsPropertyViaPropertiesInterface)
+{
+ uint32_t newActionValue = 2345;
+
+ m_proxy->Set(INTERFACE_NAME, "action", newActionValue);
+
+ ASSERT_THAT(m_proxy->action(), Eq(newActionValue));
+}
+
+TEST_F(SdbusTestObject, GetsAllPropertiesViaPropertiesInterface)
+{
+ const auto properties = m_proxy->GetAll(INTERFACE_NAME);
+
+ ASSERT_THAT(properties, SizeIs(3));
+ EXPECT_THAT(properties.at("state").get(), Eq(DEFAULT_STATE_VALUE));
+ EXPECT_THAT(properties.at("action").get(), Eq(DEFAULT_ACTION_VALUE));
+ EXPECT_THAT(properties.at("blocking").get(), Eq(DEFAULT_BLOCKING_VALUE));
+}
+
+TEST_F(SdbusTestObject, EmitsPropertyChangedSignalForSelectedProperties)
+{
+ std::atomic signalReceived{false};
+ m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const std::string& interfaceName
+ , const std::map& changedProperties
+ , const std::vector& /*invalidatedProperties*/ )
+ {
+ EXPECT_THAT(interfaceName, Eq(INTERFACE_NAME));
+ EXPECT_THAT(changedProperties, SizeIs(1));
+ EXPECT_THAT(changedProperties.at("blocking").get(), Eq(!DEFAULT_BLOCKING_VALUE));
+ signalReceived = true;
+ };
+
+ m_proxy->blocking(!DEFAULT_BLOCKING_VALUE);
+ m_proxy->action(DEFAULT_ACTION_VALUE*2);
+ m_adaptor->emitPropertiesChangedSignal(INTERFACE_NAME, {"blocking"});
+
+ ASSERT_TRUE(waitUntil(signalReceived));
+}
+
+TEST_F(SdbusTestObject, EmitsPropertyChangedSignalForAllProperties)
+{
+ std::atomic signalReceived{false};
+ m_proxy->m_onPropertiesChangedHandler = [&signalReceived]( const std::string& interfaceName
+ , const std::map& changedProperties
+ , const std::vector& invalidatedProperties )
+ {
+ EXPECT_THAT(interfaceName, Eq(INTERFACE_NAME));
+ EXPECT_THAT(changedProperties, SizeIs(1));
+ EXPECT_THAT(changedProperties.at("blocking").get(), Eq(DEFAULT_BLOCKING_VALUE));
+ ASSERT_THAT(invalidatedProperties, SizeIs(1));
+ EXPECT_THAT(invalidatedProperties[0], Eq("action"));
+ signalReceived = true;
+ };
+
+ m_adaptor->emitPropertiesChangedSignal(INTERFACE_NAME);
+
+ ASSERT_TRUE(waitUntil(signalReceived));
+}
+
+TEST_F(SdbusTestObject, GetsZeroManagedObjectsIfHasNoSubPathObjects)
+{
+ const auto objectsInterfacesAndProperties = m_proxy->GetManagedObjects();
+
+ ASSERT_THAT(objectsInterfacesAndProperties, SizeIs(0));
+}
+
+TEST_F(SdbusTestObject, GetsManagedObjectsSuccessfully)
+{
+ auto subObject1 = sdbus::createObject(*s_connection, "/sub/path1");
+ subObject1->registerProperty("aProperty1").onInterface("org.sdbuscpp.integrationtests.iface1").withGetter([]{return uint8_t{123};});
+ subObject1->finishRegistration();
+ auto subObject2 = sdbus::createObject(*s_connection, "/sub/path2");
+ subObject2->registerProperty("aProperty2").onInterface("org.sdbuscpp.integrationtests.iface2").withGetter([]{return "hi";});
+ subObject2->finishRegistration();
+
+ const auto objectsInterfacesAndProperties = m_proxy->GetManagedObjects();
+
+ ASSERT_THAT(objectsInterfacesAndProperties, SizeIs(2));
+ EXPECT_THAT(objectsInterfacesAndProperties.at("/sub/path1").at("org.sdbuscpp.integrationtests.iface1").at("aProperty1").get(), Eq(123));
+ EXPECT_THAT(objectsInterfacesAndProperties.at("/sub/path2").at("org.sdbuscpp.integrationtests.iface2").at("aProperty2").get(), Eq("hi"));
+}
+
+TEST_F(SdbusTestObject, EmitsInterfacesAddedSignalForSelectedObjectInterfaces)
+{
+ std::atomic signalReceived{false};
+ m_proxy->m_onInterfacesAddedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
+ , const std::map>& interfacesAndProperties )
+ {
+ EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
+ EXPECT_THAT(interfacesAndProperties, SizeIs(1));
+ EXPECT_THAT(interfacesAndProperties.count(INTERFACE_NAME), Eq(1));
+#if LIBSYSTEMD_VERSION<=244
+ // Up to sd-bus v244, all properties are added to the list, i.e. `state', `action', and `blocking' in this case.
+ EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(3));
+ EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state"));
+ EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("action"));
+ EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking"));
+#else
+ // Since v245 sd-bus does not add to the InterfacesAdded signal message the values of properties marked only
+ // for invalidation on change, which makes the behavior consistent with the PropertiesChangedSignal.
+ // So in this specific instance, `action' property is no more added to the list.
+ EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(2));
+ EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state"));
+ EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking"));
+#endif
+ signalReceived = true;
+ };
+
+ m_adaptor->emitInterfacesAddedSignal({INTERFACE_NAME});
+
+ ASSERT_TRUE(waitUntil(signalReceived));
+}
+
+TEST_F(SdbusTestObject, EmitsInterfacesAddedSignalForAllObjectInterfaces)
+{
+ std::atomic signalReceived{false};
+ m_proxy->m_onInterfacesAddedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
+ , const std::map>& interfacesAndProperties )
+ {
+ EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
+ EXPECT_THAT(interfacesAndProperties, SizeIs(5)); // INTERFACE_NAME + 4 standard interfaces
+#if LIBSYSTEMD_VERSION<=244
+ // Up to sd-bus v244, all properties are added to the list, i.e. `state', `action', and `blocking' in this case.
+ EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(3));
+ EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state"));
+ EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("action"));
+ EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking"));
+#else
+ // Since v245 sd-bus does not add to the InterfacesAdded signal message the values of properties marked only
+ // for invalidation on change, which makes the behavior consistent with the PropertiesChangedSignal.
+ // So in this specific instance, `action' property is no more added to the list.
+ EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(2));
+ EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("state"));
+ EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count("blocking"));
+#endif
+ signalReceived = true;
+ };
+
+ m_adaptor->emitInterfacesAddedSignal();
+
+ ASSERT_TRUE(waitUntil(signalReceived));
+}
+
+TEST_F(SdbusTestObject, EmitsInterfacesRemovedSignalForSelectedObjectInterfaces)
+{
+ std::atomic signalReceived{false};
+ m_proxy->m_onInterfacesRemovedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
+ , const std::vector& interfaces )
+ {
+ EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
+ ASSERT_THAT(interfaces, SizeIs(1));
+ EXPECT_THAT(interfaces[0], Eq(INTERFACE_NAME));
+ signalReceived = true;
+ };
+
+ m_adaptor->emitInterfacesRemovedSignal({INTERFACE_NAME});
+
+ ASSERT_TRUE(waitUntil(signalReceived));
+}
+
+TEST_F(SdbusTestObject, EmitsInterfacesRemovedSignalForAllObjectInterfaces)
+{
+ std::atomic signalReceived{false};
+ m_proxy->m_onInterfacesRemovedHandler = [&signalReceived]( const sdbus::ObjectPath& objectPath
+ , const std::vector& interfaces )
+ {
+ EXPECT_THAT(objectPath, Eq(OBJECT_PATH));
+ ASSERT_THAT(interfaces, SizeIs(5)); // INTERFACE_NAME + 4 standard interfaces
+ signalReceived = true;
+ };
+
+ m_adaptor->emitInterfacesRemovedSignal();
+
+ ASSERT_TRUE(waitUntil(signalReceived));
+}
diff --git a/tests/integrationtests/defs.h b/tests/integrationtests/Defs.h
similarity index 96%
rename from tests/integrationtests/defs.h
rename to tests/integrationtests/Defs.h
index 985d522..7dcc4d9 100644
--- a/tests/integrationtests/defs.h
+++ b/tests/integrationtests/Defs.h
@@ -2,7 +2,7 @@
* (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
* (C) 2016 - 2019 Stanislav Angelovic
*
- * @file defs.h
+ * @file Defs.h
*
* Created on: Jan 2, 2017
* Project: sdbus-c++
@@ -29,6 +29,8 @@
#include "sdbus-c++/Types.h"
+namespace sdbus { namespace test {
+
const std::string INTERFACE_NAME{"org.sdbuscpp.integrationtests"};
const std::string OBJECT_PATH{"/"};
@@ -49,4 +51,6 @@ const bool DEFAULT_BLOCKING_VALUE{true};
constexpr const double DOUBLE_VALUE{3.24L};
+}}
+
#endif /* SDBUS_CPP_INTEGRATIONTESTS_DEFS_H_ */
diff --git a/tests/integrationtests/TestAdaptor.cpp b/tests/integrationtests/TestAdaptor.cpp
new file mode 100644
index 0000000..b66c963
--- /dev/null
+++ b/tests/integrationtests/TestAdaptor.cpp
@@ -0,0 +1,416 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2019 Stanislav Angelovic
+ *
+ * @file TestAdaptor.cpp
+ *
+ * Created on: May 23, 2020
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "TestAdaptor.h"
+#include
+#include
+#include
+
+namespace sdbus { namespace test {
+
+TestAdaptor::TestAdaptor(sdbus::IConnection& connection) :
+ AdaptorInterfaces(connection, OBJECT_PATH)
+{
+ registerAdaptor();
+}
+
+TestAdaptor::~TestAdaptor()
+{
+ unregisterAdaptor();
+}
+
+void TestAdaptor::noArgNoReturn()
+{
+}
+
+int32_t TestAdaptor::getInt()
+{
+ return INT32_VALUE;
+}
+
+std::tuple TestAdaptor::getTuple()
+{
+ return std::make_tuple(UINT32_VALUE, STRING_VALUE);
+}
+
+double TestAdaptor::multiply(const int64_t& a, const double& b)
+{
+ return a * b;
+}
+
+void TestAdaptor::multiplyWithNoReply(const int64_t& a, const double& b)
+{
+ m_multiplyResult = a * b;
+ m_wasMultiplyCalled = true;
+}
+
+std::vector TestAdaptor::getInts16FromStruct(const sdbus::Struct>& x)
+{
+ std::vector res{x.get<1>()};
+ auto y = std::get>(x);
+ res.insert(res.end(), y.begin(), y.end());
+ return res;
+}
+
+sdbus::Variant TestAdaptor::processVariant(const sdbus::Variant& v)
+{
+ sdbus::Variant res = static_cast(v.get());
+ return res;
+}
+
+std::map TestAdaptor::getMapOfVariants(const std::vector& x, const sdbus::Struct& y)
+{
+ std::map res;
+ for (auto item : x)
+ {
+ res[item] = (item <= 0) ? std::get<0>(y) : std::get<1>(y);
+ }
+ return res;
+}
+
+sdbus::Struct>> TestAdaptor::getStructInStruct()
+{
+ return sdbus::make_struct(STRING_VALUE, sdbus::make_struct(std::map{{INT32_VALUE, INT32_VALUE}}));
+}
+
+int32_t TestAdaptor::sumStructItems(const sdbus::Struct& a, const sdbus::Struct& b)
+{
+ int32_t res{0};
+ res += std::get<0>(a) + std::get<1>(a);
+ res += std::get<0>(b) + std::get<1>(b);
+ return res;
+}
+
+uint32_t TestAdaptor::sumVectorItems(const std::vector& a, const std::vector& b)
+{
+ uint32_t res{0};
+ for (auto x : a)
+ {
+ res += x;
+ }
+ for (auto x : b)
+ {
+ res += x;
+ }
+ return res;
+}
+
+uint32_t TestAdaptor::doOperation(const uint32_t& param)
+{
+ std::this_thread::sleep_for(std::chrono::milliseconds(param));
+ return param;
+}
+
+void TestAdaptor::doOperationAsync(sdbus::Result&& result, uint32_t param)
+{
+ if (param == 0)
+ {
+ // Don't sleep and return the result from this thread
+ result.returnResults(param);
+ }
+ else
+ {
+ // Process asynchronously in another thread and return the result from there
+ std::thread([param, result = std::move(result)]()
+ {
+ std::this_thread::sleep_for(std::chrono::milliseconds(param));
+ result.returnResults(param);
+ }).detach();
+ }
+}
+
+sdbus::Signature TestAdaptor::getSignature()
+{
+ return SIGNATURE_VALUE;
+}
+sdbus::ObjectPath TestAdaptor::getObjectPath()
+{
+ return OBJECT_PATH_VALUE;
+}
+sdbus::UnixFd TestAdaptor::getUnixFd()
+{
+ return sdbus::UnixFd{UNIX_FD_VALUE};
+}
+
+std::map>>>, sdbus::Signature, std::string>> TestAdaptor::getComplex()
+{
+ return { // map
+ {
+ 0, // uint_64_t
+ { // struct
+ { // map
+ {
+ 23, // uint8_t
+ { // vector
+ { // struct
+ "/object/path", // object path
+ false,
+ Variant{3.14},
+ { // map
+ {0, "zero"}
+ }
+ }
+ }
+ }
+ },
+ "a{t(a{ya(obva{is})}gs)}", // signature
+ std::string{}
+ }
+ }
+ };
+}
+
+void TestAdaptor::throwError()
+{
+ m_wasThrowErrorCalled = true;
+ throw sdbus::createError(1, "A test error occurred");
+}
+
+void TestAdaptor::throwErrorWithNoReply()
+{
+ TestAdaptor::throwError();
+}
+
+void TestAdaptor::doPrivilegedStuff()
+{
+ // Intentionally left blank
+}
+
+void TestAdaptor::emitTwoSimpleSignals()
+{
+ emitSimpleSignal();
+ emitSignalWithMap({});
+}
+
+std::string TestAdaptor::state()
+{
+ return m_state;
+}
+
+uint32_t TestAdaptor::action()
+{
+ return m_action;
+}
+
+void TestAdaptor::action(const uint32_t& value)
+{
+ m_action = value;
+}
+
+bool TestAdaptor::blocking()
+{
+ return m_blocking;
+}
+
+void TestAdaptor::blocking(const bool& value)
+{
+ m_blocking = value;
+}
+
+void TestAdaptor::emitSignalWithoutRegistration(const sdbus::Struct>& s)
+{
+ getObject().emitSignal("signalWithoutRegistration").onInterface(sdbus::test::INTERFACE_NAME).withArguments(s);
+}
+
+std::string TestAdaptor::getExpectedXmlApiDescription() const
+{
+ return
+R"delimiter(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)delimiter"
+#if LIBSYSTEMD_VERSION>=242
+R"delimiter(
+)delimiter"
+#else
+R"delimiter(
+)delimiter"
+#endif
+R"delimiter(
+
+
+
+
+
+)delimiter"
+#if LIBSYSTEMD_VERSION>=242
+R"delimiter(
+
+
+)delimiter"
+#else
+R"delimiter(
+
+
+)delimiter"
+#endif
+R"delimiter(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)delimiter"
+#if LIBSYSTEMD_VERSION>=242
+R"delimiter(
+
+
+)delimiter"
+#else
+R"delimiter(
+
+
+)delimiter"
+#endif
+R"delimiter(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)delimiter";
+}
+
+}}
diff --git a/tests/integrationtests/TestAdaptor.h b/tests/integrationtests/TestAdaptor.h
new file mode 100644
index 0000000..89b738b
--- /dev/null
+++ b/tests/integrationtests/TestAdaptor.h
@@ -0,0 +1,93 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2019 Stanislav Angelovic
+ *
+ * @file TestAdaptor.h
+ *
+ * Created on: Jan 2, 2017
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#ifndef SDBUS_CPP_INTEGRATIONTESTS_TESTADAPTOR_H_
+#define SDBUS_CPP_INTEGRATIONTESTS_TESTADAPTOR_H_
+
+#include "integrationtests-adaptor.h"
+#include "Defs.h"
+#include
+#include
+#include
+
+namespace sdbus { namespace test {
+
+class TestAdaptor final : public sdbus::AdaptorInterfaces< org::sdbuscpp::integrationtests_adaptor
+ , sdbus::Properties_adaptor
+ , sdbus::ObjectManager_adaptor >
+{
+public:
+ TestAdaptor(sdbus::IConnection& connection);
+ ~TestAdaptor();
+
+protected:
+ void noArgNoReturn() override;
+ int32_t getInt() override;
+ std::tuple getTuple() override;
+ double multiply(const int64_t& a, const double& b) override;
+ void multiplyWithNoReply(const int64_t& a, const double& b) override;
+ std::vector getInts16FromStruct(const sdbus::Struct>& arg0) override;
+ sdbus::Variant processVariant(const sdbus::Variant& variant) override;
+ std::map getMapOfVariants(const std::vector& x, const sdbus::Struct& y) override;
+ sdbus::Struct>> getStructInStruct() override;
+ int32_t sumStructItems(const sdbus::Struct& arg0, const sdbus::Struct& arg1) override;
+ uint32_t sumVectorItems(const std::vector& arg0, const std::vector& arg1) override;
+ uint32_t doOperation(const uint32_t& arg0) override;
+ void doOperationAsync(sdbus::Result&& result, uint32_t arg0) override;
+ sdbus::Signature getSignature() override;
+ sdbus::ObjectPath getObjectPath() override;
+ sdbus::UnixFd getUnixFd() override;
+ std::map>>>, sdbus::Signature, std::string>> getComplex() override;
+ void throwError() override;
+ void throwErrorWithNoReply() override;
+ void doPrivilegedStuff() override;
+ void emitTwoSimpleSignals() override;
+
+ uint32_t action() override;
+ void action(const uint32_t& value) override;
+ bool blocking() override;
+ void blocking(const bool& value) override;
+ std::string state() override;
+
+public:
+ void emitSignalWithoutRegistration(const sdbus::Struct>& s);
+ std::string getExpectedXmlApiDescription() const;
+
+private:
+ const std::string m_state{DEFAULT_STATE_VALUE};
+ uint32_t m_action{DEFAULT_ACTION_VALUE};
+ bool m_blocking{DEFAULT_BLOCKING_VALUE};
+
+public: // for tests
+ // For dont-expect-reply method call verifications
+ mutable std::atomic m_wasMultiplyCalled{false};
+ mutable double m_multiplyResult{};
+ mutable std::atomic m_wasThrowErrorCalled{false};
+};
+
+}}
+
+#endif /* INTEGRATIONTESTS_TESTADAPTOR_H_ */
diff --git a/tests/integrationtests/TestFixture.cpp b/tests/integrationtests/TestFixture.cpp
new file mode 100644
index 0000000..e49b395
--- /dev/null
+++ b/tests/integrationtests/TestFixture.cpp
@@ -0,0 +1,33 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2019 Stanislav Angelovic
+ *
+ * @file TestAdaptor.cpp
+ *
+ * Created on: May 23, 2020
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "TestFixture.h"
+
+namespace sdbus { namespace test {
+
+std::unique_ptr TestFixture::s_connection = sdbus::createSystemBusConnection();
+
+}}
diff --git a/tests/integrationtests/TestFixture.h b/tests/integrationtests/TestFixture.h
new file mode 100644
index 0000000..88cc32f
--- /dev/null
+++ b/tests/integrationtests/TestFixture.h
@@ -0,0 +1,104 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2019 Stanislav Angelovic
+ *
+ * @file TestAdaptor.h
+ *
+ * Created on: Jan 2, 2017
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#ifndef SDBUS_CPP_INTEGRATIONTESTS_TESTFIXTURE_H_
+#define SDBUS_CPP_INTEGRATIONTESTS_TESTFIXTURE_H_
+
+#include "TestAdaptor.h"
+#include "TestProxy.h"
+#include "Defs.h"
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+namespace sdbus { namespace test {
+
+class TestFixture : public ::testing::Test
+{
+public:
+ static void SetUpTestCase()
+ {
+ s_connection->requestName(INTERFACE_NAME);
+ s_connection->enterEventLoopAsync();
+ }
+
+ static void TearDownTestCase()
+ {
+ s_connection->leaveEventLoop();
+ s_connection->releaseName(INTERFACE_NAME);
+ }
+
+ template
+ static bool waitUntil(_Fnc&& fnc, std::chrono::milliseconds timeout = std::chrono::seconds(5))
+ {
+ using namespace std::chrono_literals;
+
+ std::chrono::milliseconds elapsed{};
+ std::chrono::milliseconds step{5ms};
+ do {
+ std::this_thread::sleep_for(step);
+ elapsed += step;
+ if (elapsed > timeout)
+ return false;
+ } while (!fnc());
+
+ return true;
+ }
+
+ static bool waitUntil(std::atomic& flag, std::chrono::milliseconds timeout = std::chrono::seconds(5))
+ {
+ return waitUntil([&flag]() -> bool { return flag; }, timeout);
+ }
+
+private:
+ void SetUp() override
+ {
+ m_adaptor = std::make_unique(*s_connection);
+ m_proxy = std::make_unique(INTERFACE_NAME, OBJECT_PATH);
+ std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Give time for the proxy to start listening to signals
+ }
+
+ void TearDown() override
+ {
+ m_proxy.reset();
+ m_adaptor.reset();
+ }
+
+public:
+ static std::unique_ptr s_connection;
+
+ std::unique_ptr m_adaptor;
+ std::unique_ptr m_proxy;
+};
+
+}}
+
+#endif /* SDBUS_CPP_INTEGRATIONTESTS_TESTFIXTURE_H_ */
diff --git a/tests/integrationtests/TestProxy.cpp b/tests/integrationtests/TestProxy.cpp
new file mode 100644
index 0000000..91a9cd4
--- /dev/null
+++ b/tests/integrationtests/TestProxy.cpp
@@ -0,0 +1,170 @@
+/**
+ * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
+ * (C) 2016 - 2019 Stanislav Angelovic
+ *
+ * @file TestAdaptor.cpp
+ *
+ * Created on: May 23, 2020
+ * Project: sdbus-c++
+ * Description: High-level D-Bus IPC C++ library based on sd-bus
+ *
+ * This file is part of sdbus-c++.
+ *
+ * sdbus-c++ is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * sdbus-c++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with sdbus-c++. If not, see .
+ */
+
+#include "TestProxy.h"
+#include
+#include
+#include
+
+namespace sdbus { namespace test {
+
+TestProxy::TestProxy(std::string destination, std::string objectPath)
+ : ProxyInterfaces(std::move(destination), std::move(objectPath))
+{
+ getProxy().uponSignal("signalWithoutRegistration").onInterface(sdbus::test::INTERFACE_NAME).call([this](const sdbus::Struct>& s){ this->onSignalWithoutRegistration(s); });
+
+ registerProxy();
+}
+
+TestProxy::TestProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath)
+ : ProxyInterfaces(connection, std::move(destination), std::move(objectPath))
+{
+ getProxy().uponSignal("signalWithoutRegistration").onInterface(sdbus::test::INTERFACE_NAME).call([this](const sdbus::Struct>& s){ this->onSignalWithoutRegistration(s); });
+
+ registerProxy();
+}
+
+TestProxy::~TestProxy()
+{
+ unregisterProxy();
+}
+
+void TestProxy::onSimpleSignal()
+{
+ m_gotSimpleSignal = true;
+}
+
+void TestProxy::onSignalWithMap(const std::map& aMap)
+{
+ m_mapFromSignal = aMap;
+ m_gotSignalWithMap = true;
+}
+
+void TestProxy::onSignalWithVariant(const sdbus::Variant& aVariant)
+{
+ m_variantFromSignal = aVariant.get();
+ m_gotSignalWithVariant = true;
+}
+
+void TestProxy::onSignalWithoutRegistration(const sdbus::Struct>& s)
+{
+ m_signatureFromSignal[std::get<0>(s)] = static_cast(std::get<0>(std::get<1>(s)));
+ m_gotSignalWithSignature = true;
+}
+
+void TestProxy::onDoOperationReply(uint32_t returnValue, const sdbus::Error* error)
+{
+ if (m_DoOperationClientSideAsyncReplyHandler)
+ m_DoOperationClientSideAsyncReplyHandler(returnValue, error);
+}
+
+void TestProxy::onPropertiesChanged( const std::string& interfaceName
+ , const std::map& changedProperties
+ , const std::vector& invalidatedProperties )
+{
+ if (m_onPropertiesChangedHandler)
+ m_onPropertiesChangedHandler(interfaceName, changedProperties, invalidatedProperties);
+}
+
+void TestProxy::onInterfacesAdded(const sdbus::ObjectPath& objectPath, const std::map>& interfacesAndProperties)
+{
+ if (m_onInterfacesAddedHandler)
+ m_onInterfacesAddedHandler(objectPath, interfacesAndProperties);
+}
+
+void TestProxy::onInterfacesRemoved(const sdbus::ObjectPath& objectPath, const std::vector& interfaces)
+{
+ if (m_onInterfacesRemovedHandler)
+ m_onInterfacesRemovedHandler(objectPath, interfaces);
+}
+
+void TestProxy::installDoOperationClientSideAsyncReplyHandler(std::function handler)
+{
+ m_DoOperationClientSideAsyncReplyHandler = std::move(handler);
+}
+
+uint32_t TestProxy::doOperationWith500msTimeout(uint32_t param)
+{
+ using namespace std::chrono_literals;
+ uint32_t result;
+ getProxy().callMethod("doOperation").onInterface(sdbus::test::INTERFACE_NAME).withTimeout(500000us).withArguments(param).storeResultsTo(result);
+ return result;
+}
+
+sdbus::PendingAsyncCall TestProxy::doOperationClientSideAsync(uint32_t param)
+{
+ return getProxy().callMethodAsync("doOperation")
+ .onInterface(sdbus::test::INTERFACE_NAME)
+ .withArguments(param)
+ .uponReplyInvoke([this](const sdbus::Error* error, uint32_t returnValue)
+ {
+ this->onDoOperationReply(returnValue, error);
+ });
+}
+
+void TestProxy::doErroneousOperationClientSideAsync()
+{
+ getProxy().callMethodAsync("throwError")
+ .onInterface(sdbus::test::INTERFACE_NAME)
+ .uponReplyInvoke([this](const sdbus::Error* error)
+ {
+ this->onDoOperationReply(0, error);
+ });
+}
+
+void TestProxy::doOperationClientSideAsyncWith500msTimeout(uint32_t param)
+{
+ using namespace std::chrono_literals;
+ getProxy().callMethodAsync("doOperation")
+ .onInterface(sdbus::test::INTERFACE_NAME)
+ .withTimeout(500000us)
+ .withArguments(param)
+ .uponReplyInvoke([this](const sdbus::Error* error, uint32_t returnValue)
+ {
+ this->onDoOperationReply(returnValue, error);
+ });
+}
+
+int32_t TestProxy::callNonexistentMethod()
+{
+ int32_t result;
+ getProxy().callMethod("callNonexistentMethod").onInterface(sdbus::test::INTERFACE_NAME).storeResultsTo(result);
+ return result;
+}
+
+int32_t TestProxy::callMethodOnNonexistentInterface()
+{
+ int32_t result;
+ getProxy().callMethod("someMethod").onInterface("sdbuscpp.interface.that.does.not.exist").storeResultsTo(result);
+ return result;
+}
+
+void TestProxy::setStateProperty(const std::string& value)
+{
+ getProxy().setProperty("state").onInterface(sdbus::test::INTERFACE_NAME).toValue(value);
+}
+
+}}
diff --git a/tests/integrationtests/TestingProxy.h b/tests/integrationtests/TestProxy.h
similarity index 51%
rename from tests/integrationtests/TestingProxy.h
rename to tests/integrationtests/TestProxy.h
index c4ea3e0..d152474 100644
--- a/tests/integrationtests/TestingProxy.h
+++ b/tests/integrationtests/TestProxy.h
@@ -2,7 +2,7 @@
* (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
* (C) 2016 - 2019 Stanislav Angelovic
*
- * @file TestingProxy.h
+ * @file TestAdaptor.h
*
* Created on: Jan 2, 2017
* Project: sdbus-c++
@@ -24,93 +24,53 @@
* along with sdbus-c++. If not, see .
*/
-#ifndef SDBUS_CPP_INTEGRATIONTESTS_TESTINGPROXY_H_
-#define SDBUS_CPP_INTEGRATIONTESTS_TESTINGPROXY_H_
+#ifndef SDBUS_CPP_INTEGRATIONTESTS_TESTPROXY_H_
+#define SDBUS_CPP_INTEGRATIONTESTS_TESTPROXY_H_
-#include "proxy-glue.h"
+#include "integrationtests-proxy.h"
+#include "Defs.h"
+#include
+#include
#include
-class TestingProxy : public sdbus::ProxyInterfaces< ::testing_proxy
- , sdbus::Peer_proxy
- , sdbus::Introspectable_proxy
- , sdbus::Properties_proxy
- , sdbus::ObjectManager_proxy >
+namespace sdbus { namespace test {
+
+class TestProxy final : public sdbus::ProxyInterfaces< org::sdbuscpp::integrationtests_proxy
+ , sdbus::Peer_proxy
+ , sdbus::Introspectable_proxy
+ , sdbus::Properties_proxy
+ , sdbus::ObjectManager_proxy >
{
public:
- TestingProxy(std::string destination, std::string objectPath)
- : ProxyInterfaces(std::move(destination), std::move(objectPath))
- {
- registerProxy();
- }
-
- TestingProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath)
- : ProxyInterfaces(connection, std::move(destination), std::move(objectPath))
- {
- registerProxy();
- }
-
- ~TestingProxy()
- {
- unregisterProxy();
- }
-
- void installDoOperationClientSideAsyncReplyHandler(std::function handler)
- {
- m_DoOperationClientSideAsyncReplyHandler = handler;
- }
+ TestProxy(std::string destination, std::string objectPath);
+ TestProxy(sdbus::IConnection& connection, std::string destination, std::string objectPath);
+ ~TestProxy();
protected:
- void onSimpleSignal() override
- {
- m_gotSimpleSignal = true;
- }
+ void onSimpleSignal() override;
+ void onSignalWithMap(const std::map& aMap) override;
+ void onSignalWithVariant(const sdbus::Variant& aVariant) override;
- void onSignalWithMap(const std::map& m) override
- {
- m_mapFromSignal = m;
- m_gotSignalWithMap = true;
- }
-
- void onSignalWithVariant(const sdbus::Variant& v) override
- {
- m_variantFromSignal = v.get();
- m_gotSignalWithVariant = true;
- }
-
- void onSignalWithoutRegistration(const sdbus::Struct>& s) override
- {
- m_signatureFromSignal[std::get<0>(s)] = static_cast(std::get<0>(std::get<1>(s)));
- m_gotSignalWithSignature = true;
- }
-
- void onDoOperationReply(uint32_t returnValue, const sdbus::Error* error) override
- {
- if (m_DoOperationClientSideAsyncReplyHandler)
- m_DoOperationClientSideAsyncReplyHandler(returnValue, error);
- }
+ void onSignalWithoutRegistration(const sdbus::Struct>& s);
+ void onDoOperationReply(uint32_t returnValue, const sdbus::Error* error);
// Signals of standard D-Bus interfaces
-
void onPropertiesChanged( const std::string& interfaceName
, const std::map& changedProperties
- , const std::vector& invalidatedProperties ) override
- {
- if (m_onPropertiesChangedHandler)
- m_onPropertiesChangedHandler(interfaceName, changedProperties, invalidatedProperties);
- }
-
+ , const std::vector& invalidatedProperties ) override;
void onInterfacesAdded( const sdbus::ObjectPath& objectPath
- , const std::map>& interfacesAndProperties) override
- {
- if (m_onInterfacesAddedHandler)
- m_onInterfacesAddedHandler(objectPath, interfacesAndProperties);
- }
- void onInterfacesRemoved( const sdbus::ObjectPath& objectPath
- , const std::vector& interfaces) override
- {
- if (m_onInterfacesRemovedHandler)
- m_onInterfacesRemovedHandler(objectPath, interfaces);
- }
+ , const std::map>& interfacesAndProperties) override;
+ void onInterfacesRemoved( const sdbus::ObjectPath& objectPath, const std::vector& interfaces) override;
+
+public:
+ void installDoOperationClientSideAsyncReplyHandler(std::function handler);
+ uint32_t doOperationWith500msTimeout(uint32_t param);
+ sdbus::PendingAsyncCall doOperationClientSideAsync(uint32_t param);
+ void doErroneousOperationClientSideAsync();
+ void doOperationClientSideAsyncWith500msTimeout(uint32_t param);
+ int32_t callNonexistentMethod();
+ int32_t callMethodOnNonexistentInterface();
+ void setStateProperty(const std::string& value);
//private:
public: // for tests
@@ -129,4 +89,6 @@ public: // for tests
std::function&)> m_onInterfacesRemovedHandler;
};
-#endif /* SDBUS_CPP_INTEGRATIONTESTS_TESTINGPROXY_H_ */
+}}
+
+#endif /* SDBUS_CPP_INTEGRATIONTESTS_TESTPROXY_H_ */
diff --git a/tests/integrationtests/TestingAdaptor.h b/tests/integrationtests/TestingAdaptor.h
deleted file mode 100644
index 2793987..0000000
--- a/tests/integrationtests/TestingAdaptor.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/**
- * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
- * (C) 2016 - 2019 Stanislav Angelovic
- *
- * @file TestingAdaptor.h
- *
- * Created on: Jan 2, 2017
- * Project: sdbus-c++
- * Description: High-level D-Bus IPC C++ library based on sd-bus
- *
- * This file is part of sdbus-c++.
- *
- * sdbus-c++ is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * sdbus-c++ is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with sdbus-c++. If not, see .
- */
-
-#ifndef SDBUS_CPP_INTEGRATIONTESTS_TESTINGADAPTOR_H_
-#define SDBUS_CPP_INTEGRATIONTESTS_TESTINGADAPTOR_H_
-
-#include "adaptor-glue.h"
-#include
-#include
-#include
-
-class TestingAdaptor : public sdbus::AdaptorInterfaces< testing_adaptor
- , sdbus::Properties_adaptor
- , sdbus::ObjectManager_adaptor >
-{
-public:
- TestingAdaptor(sdbus::IConnection& connection) :
- AdaptorInterfaces(connection, OBJECT_PATH)
- {
- registerAdaptor();
- }
-
- ~TestingAdaptor()
- {
- unregisterAdaptor();
- }
-
-protected:
-
- void noArgNoReturn() const override
- {
- }
-
- int32_t getInt() const override
- {
- return INT32_VALUE;
- }
-
- std::tuple getTuple() const override
- {
- return std::make_tuple(UINT32_VALUE, STRING_VALUE);
- }
-
- double multiply(const int64_t& a, const double& b) const override
- {
- return a * b;
- }
-
- void multiplyWithNoReply(const int64_t& a, const double& b) const override
- {
- m_multiplyResult = a * b;
- m_wasMultiplyCalled = true;
- }
-
- std::vector getInts16FromStruct(const sdbus::Struct>& x) const override
- {
- std::vector res{x.get<1>()};
- auto y = std::get>(x);
- res.insert(res.end(), y.begin(), y.end());
- return res;
- }
-
- sdbus::Variant processVariant(sdbus::Variant& v) override
- {
- sdbus::Variant res = static_cast(v.get());
- return res;
- }
-
- std::map getMapOfVariants(const std::vector& x, const sdbus::Struct& y) const override
- {
- std::map res;
- for (auto item : x)
- {
- res[item] = (item <= 0) ? std::get<0>(y) : std::get<1>(y);
- }
- return res;
- }
-
- sdbus::Struct>> getStructInStruct() const override
- {
- return sdbus::make_struct(STRING_VALUE, sdbus::make_struct(std::map{{INT32_VALUE, INT32_VALUE}}));
- }
-
- int32_t sumStructItems(const sdbus::Struct& a, const sdbus::Struct& b) override
- {
- int32_t res{0};
- res += std::get<0>(a) + std::get<1>(a);
- res += std::get<0>(b) + std::get<1>(b);
- return res;
- }
-
- uint32_t sumVectorItems(const std::vector& a, const std::vector& b) override
- {
- uint32_t res{0};
- for (auto x : a)
- {
- res += x;
- }
- for (auto x : b)
- {
- res += x;
- }
- return res;
- }
-
- uint32_t doOperation(uint32_t param) override
- {
- std::this_thread::sleep_for(std::chrono::milliseconds(param));
- return param;
- }
-
- void doOperationAsync(uint32_t param, sdbus::Result result) override
- {
- if (param == 0)
- {
- // Don't sleep and return the result from this thread
- result.returnResults(param);
- }
- else
- {
- // Process asynchronously in another thread and return the result from there
- std::thread([param, result = std::move(result)]()
- {
- std::this_thread::sleep_for(std::chrono::milliseconds(param));
- result.returnResults(param);
- }).detach();
- }
- }
-
- sdbus::Signature getSignature() const override
- {
- return SIGNATURE_VALUE;
- }
- sdbus::ObjectPath getObjPath() const override
- {
- return OBJECT_PATH_VALUE;
- }
- sdbus::UnixFd getUnixFd() const override
- {
- return sdbus::UnixFd{UNIX_FD_VALUE};
- }
-
- ComplexType getComplex() const override
- {
- return { // map
- {
- 0, // uint_64_t
- { // struct
- { // map
- {
- 'a', // uint8_t
- { // vector
- { // struct
- "/object/path", // object path
- false,
- 3.14,
- { // map
- {0, "zero"}
- }
- }
- }
- }
- },
- "a{t(a{ya(obva{is})}gs)}", // signature
- ""
- }
- }
- };
- }
-
- void throwError() const override
- {
- m_wasThrowErrorCalled = true;
- throw sdbus::createError(1, "A test error occurred");
- }
-
-
- void emitTwoSimpleSignals() override
- {
- emitSimpleSignal();
- emitSignalWithMap({});
- }
-
- std::string state() override
- {
- return m_state;
- }
-
- uint32_t action() override
- {
- return m_action;
- }
-
- void action(const uint32_t& value) override
- {
- m_action = value;
- }
-
- bool blocking() override
- {
- return m_blocking;
- }
-
- void blocking(const bool& value) override
- {
- m_blocking = value;
- }
-
-private:
- const std::string m_state{DEFAULT_STATE_VALUE};
- uint32_t m_action{DEFAULT_ACTION_VALUE};
- bool m_blocking{DEFAULT_BLOCKING_VALUE};
-
-public: // for tests
- // For dont-expect-reply method call verifications
- mutable std::atomic m_wasMultiplyCalled{false};
- mutable double m_multiplyResult{};
- mutable std::atomic m_wasThrowErrorCalled{false};
-};
-
-
-
-#endif /* INTEGRATIONTESTS_TESTINGADAPTOR_H_ */
diff --git a/tests/integrationtests/adaptor-glue.h b/tests/integrationtests/adaptor-glue.h
deleted file mode 100644
index d160e41..0000000
--- a/tests/integrationtests/adaptor-glue.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/**
- * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
- * (C) 2016 - 2019 Stanislav Angelovic
- *
- * @file adaptor-glue.h
- *
- * Created on: Jan 2, 2017
- * Project: sdbus-c++
- * Description: High-level D-Bus IPC C++ library based on sd-bus
- *
- * This file is part of sdbus-c++.
- *
- * sdbus-c++ is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * sdbus-c++ is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with sdbus-c++. If not, see .
- */
-
-#ifndef SDBUS_CPP_INTEGRATIONTESTS_ADAPTOR_GLUE_H_
-#define SDBUS_CPP_INTEGRATIONTESTS_ADAPTOR_GLUE_H_
-
-#include "defs.h"
-
-// sdbus
-#include "sdbus-c++/sdbus-c++.h"
-
-using ComplexType = std::map<
- uint64_t,
- sdbus::Struct<
- std::map<
- uint8_t,
- std::vector<
- sdbus::Struct<
- sdbus::ObjectPath,
- bool,
- sdbus::Variant,
- std::map
- >
- >
- >,
- sdbus::Signature,
- std::string // char* leads to type and memory issues, std::string is best choice
- >
- >;
-
-class testing_adaptor
-{
-protected:
- testing_adaptor(sdbus::IObject& object) :
- object_(object)
- {
- object_.setInterfaceFlags(INTERFACE_NAME).markAsDeprecated().withPropertyUpdateBehavior(sdbus::Flags::EMITS_NO_SIGNAL);
-
- object_.registerMethod("noArgNoReturn").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->noArgNoReturn(); });
- object_.registerMethod("getInt").onInterface(INTERFACE_NAME).withOutputParamNames("anInt").implementedAs([this](){ return this->getInt(); });
- object_.registerMethod("getTuple").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getTuple(); });
-
- object_.registerMethod("multiply").onInterface(INTERFACE_NAME).withInputParamNames("a", "b").withOutputParamNames("result").implementedAs([this](const int64_t& a, const double& b){ return this->multiply(a, b); });
- object_.registerMethod("multiplyWithNoReply").onInterface(INTERFACE_NAME).implementedAs([this](const int64_t& a, const double& b){ this->multiplyWithNoReply(a, b); }).markAsDeprecated().withNoReply();
- object_.registerMethod("getInts16FromStruct").onInterface(INTERFACE_NAME).implementedAs([this](
- const sdbus::Struct