From 7fbfcec455a2af6efe3910baa3089ecba48a9d6d Mon Sep 17 00:00:00 2001 From: Joel Winarske Date: Mon, 5 May 2025 04:31:44 -0700 Subject: [PATCH] feat: add async overloads of GetManagedObjects() (#480) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implements three variants of `GetManagedObjectsAsync()` API into the standard `ObjectManager` client interface. --------- Signed-off-by: Joel Winarske Co-authored-by: Stanislav Angelovič --- .github/workflows/ci.yml | 8 +++- include/sdbus-c++/StandardInterfaces.h | 47 +++++++++++++------ .../DBusStandardInterfacesTests.cpp | 37 +++++++++++++++ 3 files changed, 76 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a20a36..8463dfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,8 +43,14 @@ jobs: # - name: install-googletest # run: | # sudo apt-get install -y libgmock-dev + - name: configure-debug-gcc11 # For gcc 11, turn off the annoying deprecated-copy warning + if: matrix.build == 'shared-libsystemd' && matrix.compiler == 'g++' && matrix.os == 'ubuntu-22.04' + run: | + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_CXX_FLAGS="-O0 -g -W -Wextra -Wall -Wnon-virtual-dtor -Wno-deprecated-copy -Werror $SDBUSCPP_EXTRA_CXX_FLAGS" -DCMAKE_VERBOSE_MAKEFILE=ON -DSDBUSCPP_INSTALL=ON -DSDBUSCPP_BUILD_TESTS=ON -DSDBUSCPP_BUILD_PERF_TESTS=ON -DSDBUSCPP_BUILD_STRESS_TESTS=ON -DSDBUSCPP_BUILD_CODEGEN=ON -DSDBUSCPP_GOOGLETEST_VERSION=1.14.0 .. - name: configure-debug - if: matrix.build == 'shared-libsystemd' + if: matrix.build == 'shared-libsystemd' && (matrix.compiler != 'g++' || matrix.os != 'ubuntu-22.04') run: | mkdir build cd build diff --git a/include/sdbus-c++/StandardInterfaces.h b/include/sdbus-c++/StandardInterfaces.h index bf8dc2e..83007b0 100644 --- a/include/sdbus-c++/StandardInterfaces.h +++ b/include/sdbus-c++/StandardInterfaces.h @@ -168,6 +168,11 @@ namespace sdbus { return m_proxy.getPropertyAsync(propertyName).onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback), return_slot); } + std::future GetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, with_future_t) + { + return m_proxy.getPropertyAsync(propertyName).onInterface(interfaceName).getResultAsFuture(); + } + template PendingAsyncCall GetAsync(std::string_view interfaceName, std::string_view propertyName, _Function&& callback) { @@ -180,11 +185,6 @@ namespace sdbus { return m_proxy.getPropertyAsync(propertyName).onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback), return_slot); } - std::future GetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, with_future_t) - { - return m_proxy.getPropertyAsync(propertyName).onInterface(interfaceName).getResultAsFuture(); - } - std::future GetAsync(std::string_view interfaceName, std::string_view propertyName, with_future_t) { return m_proxy.getPropertyAsync(propertyName).onInterface(interfaceName).getResultAsFuture(); @@ -222,6 +222,11 @@ namespace sdbus { return m_proxy.setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).uponReplyInvoke(std::forward<_Function>(callback), return_slot); } + std::future SetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, const sdbus::Variant& value, with_future_t) + { + return m_proxy.setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).getResultAsFuture(); + } + template PendingAsyncCall SetAsync(std::string_view interfaceName, std::string_view propertyName, const sdbus::Variant& value, _Function&& callback) { @@ -234,11 +239,6 @@ namespace sdbus { return m_proxy.setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).uponReplyInvoke(std::forward<_Function>(callback), return_slot); } - std::future SetAsync(const InterfaceName& interfaceName, const PropertyName& propertyName, const sdbus::Variant& value, with_future_t) - { - return m_proxy.setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).getResultAsFuture(); - } - std::future SetAsync(std::string_view interfaceName, std::string_view propertyName, const sdbus::Variant& value, with_future_t) { return m_proxy.setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).getResultAsFuture(); @@ -266,6 +266,11 @@ namespace sdbus { return m_proxy.getAllPropertiesAsync().onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback), return_slot); } + std::future> GetAllAsync(const InterfaceName& interfaceName, with_future_t) + { + return m_proxy.getAllPropertiesAsync().onInterface(interfaceName).getResultAsFuture(); + } + template PendingAsyncCall GetAllAsync(std::string_view interfaceName, _Function&& callback) { @@ -278,11 +283,6 @@ namespace sdbus { return m_proxy.getAllPropertiesAsync().onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback), return_slot); } - std::future> GetAllAsync(const InterfaceName& interfaceName, with_future_t) - { - return m_proxy.getAllPropertiesAsync().onInterface(interfaceName).getResultAsFuture(); - } - std::future> GetAllAsync(std::string_view interfaceName, with_future_t) { return m_proxy.getAllPropertiesAsync().onInterface(interfaceName).getResultAsFuture(); @@ -344,6 +344,23 @@ namespace sdbus { return objectsInterfacesAndProperties; } + template + PendingAsyncCall GetManagedObjectsAsync(_Function&& callback) + { + return m_proxy.callMethodAsync("GetManagedObjects").onInterface(INTERFACE_NAME).uponReplyInvoke(std::forward<_Function>(callback)); + } + + template + [[nodiscard]] Slot GetManagedObjectsAsync(_Function&& callback, return_slot_t) + { + return m_proxy.callMethodAsync("GetManagedObjects").onInterface(INTERFACE_NAME).uponReplyInvoke(std::forward<_Function>(callback), return_slot); + } + + std::future>>> GetManagedObjectsAsync(with_future_t) + { + return m_proxy.callMethodAsync("GetManagedObjects").onInterface(INTERFACE_NAME).getResultAsFuture>>>(); + } + private: sdbus::IProxy& m_proxy; }; diff --git a/tests/integrationtests/DBusStandardInterfacesTests.cpp b/tests/integrationtests/DBusStandardInterfacesTests.cpp index 1e30961..058cfb8 100644 --- a/tests/integrationtests/DBusStandardInterfacesTests.cpp +++ b/tests/integrationtests/DBusStandardInterfacesTests.cpp @@ -264,6 +264,43 @@ TYPED_TEST(SdbusTestObject, GetsManagedObjectsSuccessfully) .at(ACTION_PROPERTY).template get(), Eq(DEFAULT_ACTION_VALUE)); } +TYPED_TEST(SdbusTestObject, GetsManagedObjectsAsynchronously) +{ + std::promise promise; + auto future = promise.get_future(); + auto adaptor2 = std::make_unique(*this->s_adaptorConnection, OBJECT_PATH_2); + + this->m_objectManagerProxy->GetManagedObjectsAsync([&](std::optional /*err*/, const std::map>>& objectsInterfacesAndProperties) + { + promise.set_value(objectsInterfacesAndProperties.size()); + }); + + ASSERT_THAT(future.get(), Eq(2)); +} + +TYPED_TEST(SdbusTestObject, GetsManagedObjectsAsynchronouslyViaSlotReturningOverload) +{ + std::promise promise; + auto future = promise.get_future(); + auto adaptor2 = std::make_unique(*this->s_adaptorConnection, OBJECT_PATH_2); + + auto slot = this->m_objectManagerProxy->GetManagedObjectsAsync([&](std::optional /*err*/, const std::map>>& objectsInterfacesAndProperties) + { + promise.set_value(objectsInterfacesAndProperties.size()); + }, sdbus::return_slot); + + ASSERT_THAT(future.get(), Eq(2)); +} + +TYPED_TEST(SdbusTestObject, GetsManagedObjectsAsynchronouslyViaFutureOverload) +{ + auto adaptor2 = std::make_unique(*this->s_adaptorConnection, OBJECT_PATH_2); + + auto future = this->m_objectManagerProxy->GetManagedObjectsAsync(sdbus::with_future); + + ASSERT_THAT(future.get().size(), Eq(2)); +} + TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForSelectedObjectInterfaces) { std::atomic signalReceived{false};