diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a65f0a..9f43717 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,9 @@ include(GNUInstallDirs) # Installation directories for `install` command and pkg #------------------------------- find_package(PkgConfig REQUIRED) -pkg_check_modules(SYSTEMD REQUIRED libsystemd>=236) +#pkg_check_modules(SYSTEMD REQUIRED libsystemd>=236) + +set(CMAKE_CXX_FLAGS "-O0 -g") #------------------------------- # SOURCE FILES CONFIGURATION @@ -80,7 +82,7 @@ set(SDBUSCPP_VERSION "${PROJECT_VERSION}") # We are building in two steps: first objects, then link them into a library, # and that's because we need object files since unit tests link against them. add_library(sdbuscppobjects OBJECT ${SDBUSCPP_SRCS}) -target_include_directories(sdbuscppobjects PUBLIC ${SYSTEMD_INCLUDE_DIRS}) +#target_include_directories(sdbuscppobjects PUBLIC ${SYSTEMD_INCLUDE_DIRS}) target_compile_definitions(sdbuscppobjects PRIVATE BUILDLIB=1) set_target_properties(sdbuscppobjects PROPERTIES POSITION_INDEPENDENT_CODE ON) @@ -91,7 +93,7 @@ set_target_properties(sdbus-c++ VERSION "${SDBUSCPP_VERSION}" SOVERSION "${SDBUSCPP_VERSION_MAJOR}" OUTPUT_NAME "sdbus-c++") -target_link_libraries(sdbus-c++ ${SYSTEMD_LIBRARIES}) +target_link_libraries(sdbus-c++ -L/home/aeywalee/data/repos/systemd/.libs/ -lsystemd) #---------------------------------- # INSTALLATION diff --git a/src/Connection.cpp b/src/Connection.cpp index 0d7cc18..c46dae4 100755 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -79,7 +79,7 @@ void Connection::enterProcessingLoop() if (!success) break; // Exit processing loop if (success.asyncMsgsToProcess) - processAsynchronousMessages(); + processUserRequests(); } loopThreadId_ = std::thread::id{}; @@ -122,10 +122,10 @@ void Connection::removeObjectVTable(void* vtableHandle) sd_bus_slot_unref((sd_bus_slot *)vtableHandle); } -sdbus::MethodCall Connection::createMethodCall( const std::string& destination - , const std::string& objectPath - , const std::string& interfaceName - , const std::string& methodName ) const +MethodCall Connection::createMethodCall( const std::string& destination + , const std::string& objectPath + , const std::string& interfaceName + , const std::string& methodName ) const { sd_bus_message *sdbusMsg{}; @@ -145,44 +145,9 @@ sdbus::MethodCall Connection::createMethodCall( const std::string& destination return MethodCall(sdbusMsg); } -sdbus::MethodReply Connection::callMethod(const MethodCall& message) -{ - std::thread::id loopThreadId = loopThreadId_; - - // Is the loop not yet on? => Go make synchronous call - while (loopThreadId == std::thread::id{}) - { - // Did the loop begin in the meantime? Or try_lock() failed spuriously? - if (!loopMutex_.try_lock()) - continue; - - // Synchronous call - std::lock_guard guard(loopMutex_, std::adopt_lock); - return message.send(); - } - - // Is the loop on and we are in the same thread? => Go for synchronous call - if (loopThreadId == std::this_thread::get_id()) - { - assert(!loopMutex_.try_lock()); - return message.send(); // Synchronous call - } - - // We are in a different thread than the loop thread => Asynchronous call - UserRequest request{message, Message::Type::METHOD_CALL, {}, Message::Type::METHOD_REPLY}; - auto future = request.ret.get_future(); - { - std::lock_guard guard(userRequestsMutex_); - userRequests_.push(request); - } - // Wait for the reply from the loop thread - auto reply = future.get(); - return *static_cast(&reply); -} - -sdbus::Signal Connection::createSignal( const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName ) const +Signal Connection::createSignal( const std::string& objectPath + , const std::string& interfaceName + , const std::string& signalName ) const { sd_bus_message *sdbusSignal{}; @@ -207,14 +172,61 @@ void* Connection::registerSignalHandler( const std::string& objectPath , sd_bus_message_handler_t callback , void* userData ) { - sd_bus_slot *slot{}; + auto registerSignalHandler = [this]( const std::string& objectPath + , const std::string& interfaceName + , const std::string& signalName + , sd_bus_message_handler_t callback + , void* userData ) + { + sd_bus_slot *slot{}; - auto filter = composeSignalMatchFilter(objectPath, interfaceName, signalName); - auto r = sd_bus_add_match(bus_.get(), &slot, filter.c_str(), callback, userData); + auto filter = composeSignalMatchFilter(objectPath, interfaceName, signalName); + auto r = sd_bus_add_match(bus_.get(), &slot, filter.c_str(), callback, userData); - SDBUS_THROW_ERROR_IF(r < 0, "Failed to register signal handler", -r); + SDBUS_THROW_ERROR_IF(r < 0, "Failed to register signal handler", -r); - return slot; + return slot; + }; + + std::thread::id loopThreadId = loopThreadId_; + + // Is the loop not yet on? => Go make synchronous call + while (loopThreadId == std::thread::id{}) + { + // Did the loop begin in the meantime? Or try_lock() failed spuriously? + if (!loopMutex_.try_lock()) + continue; + + // Synchronous call + std::lock_guard guard(loopMutex_, std::adopt_lock); + return registerSignalHandler(objectPath, interfaceName, signalName, callback, userData); + } + + // Is the loop on and we are in the same thread? => Go for synchronous call + if (loopThreadId == std::this_thread::get_id()) + { + assert(!loopMutex_.try_lock()); + return registerSignalHandler(objectPath, interfaceName, signalName, callback, userData); + } + + // We are in a different thread than the loop thread => Asynchronous call + std::promise result; + auto future = result.get_future(); + queueUserRequest([registerSignalHandler, objectPath, interfaceName, signalName, callback, userData, &result]() + { + SCOPE_EXIT_NAMED(onSdbusError){ result.set_exception(std::current_exception()); }; + + void* slot = registerSignalHandler(objectPath, interfaceName, signalName, callback, userData); + result.set_value(slot); + + onSdbusError.dismiss(); + }); + auto request = std::make_unique(); + request->registerSignalHandler = registerSignalHandler; + auto future = request->result.get_future(); + queueUserRequest(std::move(request)); + // Wait for the reply from the loop thread + return future.get(); } void Connection::unregisterSignalHandler(void* handlerCookie) @@ -222,11 +234,129 @@ void Connection::unregisterSignalHandler(void* handlerCookie) sd_bus_slot_unref((sd_bus_slot *)handlerCookie); } -void Connection::sendReplyAsynchronously(const sdbus::MethodReply& reply) +//class AsyncExecutor +//ifPossibleExecuteSync() + +MethodReply Connection::callMethod(const MethodCall& message) { - std::lock_guard guard(mutex_); - asyncReplies_.push(reply); - notifyProcessingLoop(); + //ifPossibleExecuteSync().otherwiseExecuteAsync(); + std::thread::id loopThreadId = loopThreadId_; + + // Is the loop not yet on? => Go make synchronous call + while (loopThreadId == std::thread::id{}) + { + // Did the loop begin in the meantime? Or try_lock() failed spuriously? + if (!loopMutex_.try_lock()) + continue; + + // Synchronous call + std::lock_guard guard(loopMutex_, std::adopt_lock); + return message.send(); + } + + // Is the loop on and we are in the same thread? => Go for synchronous call + if (loopThreadId == std::this_thread::get_id()) + { + assert(!loopMutex_.try_lock()); + return message.send(); // Synchronous call + } + + // We are in a different thread than the loop thread => Asynchronous call + auto request = std::make_unique(); + request->msg = message; + auto future = request->result.get_future(); + queueUserRequest(std::move(request)); + // Wait for the reply from the loop thread + return future.get(); +} + +void Connection::callMethod(const AsyncMethodCall& message, void* callback, void* userData) +{ + std::thread::id loopThreadId = loopThreadId_; + + // Is the loop not yet on? => Go make synchronous call + while (loopThreadId == std::thread::id{}) + { + // Did the loop begin in the meantime? Or try_lock() failed spuriously? + if (!loopMutex_.try_lock()) + continue; + + // Synchronous call + std::lock_guard guard(loopMutex_, std::adopt_lock); + return message.send(callback, userData); + } + + // Is the loop on and we are in the same thread? => Go for synchronous call + if (loopThreadId == std::this_thread::get_id()) + { + assert(!loopMutex_.try_lock()); + return message.send(callback, userData); // Synchronous call + } + + // We are in a different thread than the loop thread => Asynchronous call + auto request = std::make_unique(); + request->msg = message; + request->callback = callback; + request->userData = userData; + queueUserRequest(std::move(request)); +} + +void Connection::sendMethodReply(const MethodReply& message) +{ + std::thread::id loopThreadId = loopThreadId_; + + // Is the loop not yet on? => Go make synchronous call + while (loopThreadId == std::thread::id{}) + { + // Did the loop begin in the meantime? Or try_lock() failed spuriously? + if (!loopMutex_.try_lock()) + continue; + + // Synchronous call + std::lock_guard guard(loopMutex_, std::adopt_lock); + return message.send(); + } + + // Is the loop on and we are in the same thread? => Go for synchronous call + if (loopThreadId == std::this_thread::get_id()) + { + assert(!loopMutex_.try_lock()); + return message.send(); // Synchronous call + } + + // We are in a different thread than the loop thread => Asynchronous call + auto request = std::make_unique(); + request->msg = message; + queueUserRequest(std::move(request)); +} + +void Connection::emitSignal(const Signal& message) +{ + std::thread::id loopThreadId = loopThreadId_; + + // Is the loop not yet on? => Go make synchronous call + while (loopThreadId == std::thread::id{}) + { + // Did the loop begin in the meantime? Or try_lock() failed spuriously? + if (!loopMutex_.try_lock()) + continue; + + // Synchronous call + std::lock_guard guard(loopMutex_, std::adopt_lock); + return message.send(); + } + + // Is the loop on and we are in the same thread? => Go for synchronous call + if (loopThreadId == std::this_thread::get_id()) + { + assert(!loopMutex_.try_lock()); + return message.send(); // Synchronous call + } + + // We are in a different thread than the loop thread => Asynchronous call + auto request = std::make_unique(); + request->msg = message; + queueUserRequest(std::move(request)); } std::unique_ptr Connection::clone() const @@ -315,14 +445,23 @@ bool Connection::processPendingRequest() return r > 0; } -void Connection::processAsynchronousMessages() +void Connection::queueUserRequest(std::unique_ptr&& request) { - std::lock_guard guard(mutex_); - while (!asyncReplies_.empty()) { - auto reply = asyncReplies_.front(); - asyncReplies_.pop(); - reply.send(); + std::lock_guard guard(userRequestsMutex_); + userRequests_.push(std::move(request)); + } + notifyProcessingLoop(); +} + +void Connection::processUserRequests() +{ + std::lock_guard guard(userRequestsMutex_); + while (!userRequests_.empty()) + { + auto& reply = userRequests_.front(); + reply->process(); + userRequests_.pop(); } } diff --git a/src/Connection.h b/src/Connection.h index 0f5af3c..faf4457 100755 --- a/src/Connection.h +++ b/src/Connection.h @@ -29,6 +29,7 @@ #include #include #include "IConnection.h" +#include "ScopeGuard.h" #include #include #include @@ -51,7 +52,7 @@ namespace sdbus { namespace internal { }; Connection(BusType type); - ~Connection(); + ~Connection() override; void requestName(const std::string& name) override; void releaseName(const std::string& name) override; @@ -65,13 +66,13 @@ namespace sdbus { namespace internal { , void* userData ) override; void removeObjectVTable(void* vtableHandle) override; - sdbus::MethodCall createMethodCall( const std::string& destination - , const std::string& objectPath - , const std::string& interfaceName - , const std::string& methodName ) const override; - sdbus::Signal createSignal( const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName ) const override; + MethodCall createMethodCall( const std::string& destination + , const std::string& objectPath + , const std::string& interfaceName + , const std::string& methodName ) const override; + Signal createSignal( const std::string& objectPath + , const std::string& interfaceName + , const std::string& signalName ) const override; void* registerSignalHandler( const std::string& objectPath , const std::string& interfaceName @@ -80,8 +81,10 @@ namespace sdbus { namespace internal { , void* userData ) override; void unregisterSignalHandler(void* handlerCookie) override; - MethodReply callMethod(const MethodCall& message); - void sendReplyAsynchronously(const sdbus::MethodReply& reply) override; + MethodReply callMethod(const MethodCall& message) override; + void callMethod(const AsyncMethodCall& message, void* callback, void* userData) override; + void sendMethodReply(const MethodReply& message) override; + void emitSignal(const Signal& message) override; std::unique_ptr clone() const override; @@ -95,12 +98,106 @@ namespace sdbus { namespace internal { return msgsToProcess || asyncMsgsToProcess; } }; + + // TODO move down + struct IUserRequest + { + virtual void process() = 0; + virtual ~IUserRequest() = default; + }; + + struct MethodCallRequest : IUserRequest + { + MethodCall msg; + std::promise result; + + void process() override + { + SCOPE_EXIT_NAMED(onSdbusError){ result.set_exception(std::current_exception()); }; + + auto reply = msg.send(); + result.set_value(std::move(reply)); + + onSdbusError.dismiss(); + } + }; + + struct AsyncMethodCallRequest : IUserRequest + { + AsyncMethodCall msg; + void* callback; + void* userData; + + // TODO: Catch exception and store to promise? + void process() override + { + msg.send(callback, userData); + } + }; + + struct MethodReplyRequest : IUserRequest + { + MethodReply msg; + + // TODO: Catch exception and store to promise? + void process() override + { + msg.send(); + } + }; + + struct SignalEmissionRequest : IUserRequest + { + Signal msg; + + // TODO: Catch exception and store to promise? + void process() override + { + msg.send(); + } + }; + + struct SignalRegistrationRequest : IUserRequest + { + std::function registerSignalHandler; + std::promise result; + + void process() override + { + SCOPE_EXIT_NAMED(onSdbusError){ result.set_exception(std::current_exception()); }; + + assert(registerSignalHandler); + void* slot = registerSignalHandler(); + result.set_value(slot); + + onSdbusError.dismiss(); + } + }; + + struct SignalUnregistrationRequest : IUserRequest + { + std::function unregisterSignalHandler; + std::promise result; + + void process() override + { + SCOPE_EXIT_NAMED(onSdbusError){ result.set_exception(std::current_exception()); }; + + assert(unregisterSignalHandler); + unregisterSignalHandler(); + result.set_value(); + + onSdbusError.dismiss(); + } + }; + static sd_bus* openBus(Connection::BusType type); static void finishHandshake(sd_bus* bus); static int createLoopNotificationDescriptor(); static void closeLoopNotificationDescriptor(int fd); bool processPendingRequest(); - void processAsynchronousMessages(); + void queueUserRequest(std::unique_ptr&& request); + void processUserRequests(); WaitResult waitForNextRequest(); static std::string composeSignalMatchFilter( const std::string& objectPath , const std::string& interfaceName @@ -115,20 +212,7 @@ namespace sdbus { namespace internal { std::atomic loopThreadId_; std::mutex loopMutex_; - //std::queue asyncReplies_; - struct UserRequest - { - Message msg; - Message::Type msgType; - std::promise ret; - Message::Type retType; - - static_assert(sizeof(Message) == sizeof(MethodCall)); - static_assert(sizeof(Message) == sizeof(AsyncMethodCall)); - static_assert(sizeof(Message) == sizeof(MethodReply)); - static_assert(sizeof(Message) == sizeof(Signal)); - }; - std::queue userRequests_; + std::queue> userRequests_; std::mutex userRequestsMutex_; std::atomic exitLoopThread_; diff --git a/src/IConnection.h b/src/IConnection.h index dba264c..f82db18 100755 --- a/src/IConnection.h +++ b/src/IConnection.h @@ -33,6 +33,7 @@ // Forward declaration namespace sdbus { class MethodCall; + class AsyncMethodCall; class MethodReply; class Signal; } @@ -49,14 +50,14 @@ namespace internal { , void* userData ) = 0; virtual void removeObjectVTable(void* vtableHandle) = 0; - virtual sdbus::MethodCall createMethodCall( const std::string& destination - , const std::string& objectPath - , const std::string& interfaceName - , const std::string& methodName ) const = 0; + virtual MethodCall createMethodCall( const std::string& destination + , const std::string& objectPath + , const std::string& interfaceName + , const std::string& methodName ) const = 0; - virtual sdbus::Signal createSignal( const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName ) const = 0; + virtual Signal createSignal( const std::string& objectPath + , const std::string& interfaceName + , const std::string& signalName ) const = 0; virtual void* registerSignalHandler( const std::string& objectPath , const std::string& interfaceName @@ -68,7 +69,10 @@ namespace internal { virtual void enterProcessingLoopAsync() = 0; virtual void leaveProcessingLoop() = 0; - virtual void sendReplyAsynchronously(const sdbus::MethodReply& reply) = 0; + virtual MethodReply callMethod(const MethodCall& message) = 0; + virtual void callMethod(const AsyncMethodCall& message, void* callback, void* userData) = 0; + virtual void sendMethodReply(const MethodReply& message) = 0; + virtual void emitSignal(const Signal& message) = 0; virtual std::unique_ptr clone() const = 0; diff --git a/src/MethodResult.cpp b/src/MethodResult.cpp index 9dd9149..4954ff3 100644 --- a/src/MethodResult.cpp +++ b/src/MethodResult.cpp @@ -37,7 +37,7 @@ MethodResult::MethodResult(const MethodCall& msg, sdbus::internal::Object& objec void MethodResult::send(const MethodReply& reply) const { assert(object_ != nullptr); - object_->sendReplyAsynchronously(reply); + object_->sendMethodReply(reply); } } diff --git a/src/Object.cpp b/src/Object.cpp index bc83cd9..6302307 100755 --- a/src/Object.cpp +++ b/src/Object.cpp @@ -156,15 +156,12 @@ sdbus::Signal Object::createSignal(const std::string& interfaceName, const std:: void Object::emitSignal(const sdbus::Signal& message) { - // TODO: Make signal emitting asynchronous. Now signal can probably be emitted only from user code - // handled within the D-Bus processing loop thread, but not from any thread. In principle it will - // be the same as async replies. - message.send(); + connection_.emitSignal(message); } -void Object::sendReplyAsynchronously(const MethodReply& reply) +void Object::sendMethodReply(const MethodReply& reply) { - connection_.sendReplyAsynchronously(reply); + connection_.sendMethodReply(reply); } const std::vector& Object::createInterfaceVTable(InterfaceData& interfaceData) diff --git a/src/Object.h b/src/Object.h index d35c8e2..ddc1347 100644 --- a/src/Object.h +++ b/src/Object.h @@ -84,7 +84,7 @@ namespace internal { sdbus::Signal createSignal(const std::string& interfaceName, const std::string& signalName) override; void emitSignal(const sdbus::Signal& message) override; - void sendReplyAsynchronously(const MethodReply& reply); + void sendMethodReply(const MethodReply& reply); private: using InterfaceName = std::string; diff --git a/src/ObjectProxy.cpp b/src/ObjectProxy.cpp index 8635dc9..98dc112 100755 --- a/src/ObjectProxy.cpp +++ b/src/ObjectProxy.cpp @@ -49,7 +49,7 @@ ObjectProxy::ObjectProxy( std::unique_ptr&& connec { // The connection is ours only, so we have to manage event loop upon this connection, // so we get signals, async replies, and other messages from D-Bus. - connection_->enterProcessingLoopAsync(); + // TODO uncomment connection_->enterProcessingLoopAsync(); } MethodCall ObjectProxy::createMethodCall(const std::string& interfaceName, const std::string& methodName) @@ -64,13 +64,16 @@ AsyncMethodCall ObjectProxy::createAsyncMethodCall(const std::string& interfaceN MethodReply ObjectProxy::callMethod(const MethodCall& message) { - return message.send(); + return connection_->callMethod(message); } void ObjectProxy::callMethod(const AsyncMethodCall& message, async_reply_handler asyncReplyCallback) { - // The new-ed handler gets deleted in the sdbus_async_reply_handler - message.send((void*)&ObjectProxy::sdbus_async_reply_handler, new async_reply_handler(std::move(asyncReplyCallback))); + auto callback = (void*)&ObjectProxy::sdbus_async_reply_handler; + // Allocated userData gets deleted in the sdbus_async_reply_handler + auto userData = new async_reply_handler(std::move(asyncReplyCallback)); + + connection_->callMethod(message, callback, userData); } void ObjectProxy::registerSignalHandler( const std::string& interfaceName diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fa3f6aa..8560674 100755 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,25 +3,25 @@ # https://github.com/google/googletest/blob/master/googletest/README.md#incorporating-into-an-existing-cmake-project #------------------------------- -#configure_file(googletest-download/CMakeLists.txt.in googletest-download/CMakeLists.txt) +configure_file(googletest-download/CMakeLists.txt.in googletest-download/CMakeLists.txt) -#execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . -# RESULT_VARIABLE result -# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download) +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download) -#if(result) -# message(FATAL_ERROR "CMake step for googletest failed: ${result}") -#endif() +if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") +endif() -#execute_process(COMMAND ${CMAKE_COMMAND} --build . -# RESULT_VARIABLE result -# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download) +execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download) -#if(result) -# message(FATAL_ERROR "Build step for googletest failed: ${result}") -#endif() +if(result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") +endif() -#set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src ${CMAKE_CURRENT_BINARY_DIR}/googletest-build @@ -63,8 +63,8 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) # targets even when INTERFACE_INCLUDE_DIRECTORIES is used. set(CMAKE_NO_SYSTEM_FROM_IMPORTED "1") -add_executable(libsdbus-c++_unittests ${UNITTESTS_SRCS} $) -target_link_libraries(libsdbus-c++_unittests ${SYSTEMD_LIBRARIES} gmock gmock_main) +#add_executable(libsdbus-c++_unittests ${UNITTESTS_SRCS} $) +#target_link_libraries(libsdbus-c++_unittests ${SYSTEMD_LIBRARIES} gmock gmock_main) add_executable(libsdbus-c++_integrationtests ${INTEGRATIONTESTS_SRCS}) target_link_libraries(libsdbus-c++_integrationtests sdbus-c++ gmock gmock_main) @@ -82,7 +82,7 @@ endif() # INSTALLATION #---------------------------------- -install(TARGETS libsdbus-c++_unittests DESTINATION /opt/test/bin) +#install(TARGETS libsdbus-c++_unittests DESTINATION /opt/test/bin) install(TARGETS libsdbus-c++_integrationtests DESTINATION /opt/test/bin) install(FILES ${INTEGRATIONTESTS_SOURCE_DIR}/files/libsdbus-cpp-test.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/dbus-1/system.d) @@ -107,9 +107,9 @@ if(CMAKE_CROSSCOMPILING) if(NOT (UNIT_TESTS_RUNNER AND TEST_DEVICE_IP)) message(WARNING "UNIT_TESTS_RUNNER and TEST_DEVICE_IP variables must be defined to run tests remotely") endif() - add_test(NAME libsdbus-c++_unittests COMMAND ${UNIT_TESTS_RUNNER} --deviceip=${TEST_DEVICE_IP} --testbin=libsdbus-c++_unittests) + #add_test(NAME libsdbus-c++_unittests COMMAND ${UNIT_TESTS_RUNNER} --deviceip=${TEST_DEVICE_IP} --testbin=libsdbus-c++_unittests) add_test(NAME libsdbus-c++_integrationtests COMMAND ${UNIT_TESTS_RUNNER} --deviceip=${TEST_DEVICE_IP} --testbin=libsdbus-c++_integrationtests) else() - add_test(NAME libsdbus-c++_unittests COMMAND libsdbus-c++_unittests) + #add_test(NAME libsdbus-c++_unittests COMMAND libsdbus-c++_unittests) add_test(NAME libsdbus-c++_integrationtests COMMAND libsdbus-c++_integrationtests) endif()