diff options
53 files changed, 2725 insertions, 1432 deletions
@@ -40,3 +40,9 @@ /DBusConnectionTest /DBusMainLoopIntegrationTest /DBusServicePublisherTest +/DBusDynamicLoadingMixedValidityTest +/DBusDynamicLoadingMultipleDefinitionTest +/DBusDynamicLoadingWithConfigTest +/DBusDynamicLoadingBasicTest +/DBusDynamicLoadingMultipleBindingsTest +/DBusDynamicLoadingNoValidityTest diff --git a/Makefile.am b/Makefile.am index 1c5d2f3..2bc7241 100644 --- a/Makefile.am +++ b/Makefile.am @@ -36,6 +36,7 @@ lib_LTLIBRARIES += libCommonAPI-DBus.la libCommonAPI_DBus_la_SOURCES = \ src/CommonAPI/DBus/DBusAddressTranslator.cpp \ + src/CommonAPI/DBus/DBusConfiguration.cpp \ src/CommonAPI/DBus/DBusConnection.cpp \ src/CommonAPI/DBus/DBusDaemonProxy.cpp \ src/CommonAPI/DBus/DBusError.cpp \ @@ -65,6 +66,7 @@ CommonAPI_DBus_includedir=$(includedir)/CommonAPI-${VERSION}/CommonAPI/DBus CommonAPI_DBus_include_HEADERS = \ src/CommonAPI/DBus/DBusAddressTranslator.h \ src/CommonAPI/DBus/DBusAttribute.h \ + src/CommonAPI/DBus/DBusConfiguration.h \ src/CommonAPI/DBus/DBusConnection.h \ src/CommonAPI/DBus/DBusConnectionBusType.h \ src/CommonAPI/DBus/DBusDaemonProxy.h \ @@ -100,14 +102,58 @@ pkgconfig_DATA = CommonAPI-DBus.pc # ------------------------------------------------------------------------------ if ENABLE_TESTS +lib_LTLIBRARIES += libCommonAPI-Fake.la + +libCommonAPI_Fake_la_SOURCES = \ + src/test/dbusDynamicLoadingTests/fakeTestBinding/FakeBinding.cpp + +libCommonAPI_Fake_la_LIBADD = \ + ${COMMONAPI_LIBS} +libCommonAPI_Fake_la_LDFLAGS = \ + ${AM_LDFLAGS} \ + -version-info 1:0:0 + +CommonAPI_Fake_includedir=$(includedir)/CommonAPI-${VERSION}/CommonAPI/Fake +CommonAPI_Fake_include_HEADERS = \ + src/test/dbusDynamicLoadingTests/fakeTestBinding/FakeBinding.h + TestInterfaceSources = \ src/test/commonapi/tests/DerivedTypeCollection.cpp \ + src/test/commonapi/tests/TestInterfaceStubDefault.cpp + +TestInterfaceDBusSources = \ + ${TestInterfaceSources} \ src/test/commonapi/tests/TestInterfaceDBusProxy.cpp \ src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp \ - src/test/commonapi/tests/TestInterfaceStubDefault.cpp \ - src/test/fakeLegacyService/fake/legacy/service/LegacyInterfaceDBusProxy.cpp + src/test/fake/legacy/service/LegacyInterfaceDBusProxy.cpp + +lib_LTLIBRARIES += libDBusGen-TestInterface.la +libDBusGen_TestInterface_la_SOURCES = \ + ${TestInterfaceDBusSources} +libDBusGen_TestInterface_la_LIBADD = \ + ${COMMONAPI_LIBS} +libDBusGen_TestInterface_la_LDFLAGS = \ + ${AM_LDFLAGS} + +lib_LTLIBRARIES += libSomeOtherNameForGeneratedDBus.la +libSomeOtherNameForGeneratedDBus_la_SOURCES = \ + ${TestInterfaceDBusSources} +libSomeOtherNameForGeneratedDBus_la_LIBADD = \ + ${COMMONAPI_LIBS} +libSomeOtherNameForGeneratedDBus_la_LDFLAGS = \ + ${AM_LDFLAGS} + + +DYNAMIC_LOADING_TEST_SET = \ + DBusDynamicLoadingBasicTest \ + DBusDynamicLoadingMixedValidityTest \ + DBusDynamicLoadingNoValidityTest \ + DBusDynamicLoadingMultipleDefinitionTest \ + DBusDynamicLoadingMultipleBindingsTest check_PROGRAMS = \ + DBusRuntimeTest \ + ${DYNAMIC_LOADING_TEST_SET} \ DBusMainLoopIntegrationTest \ DBusConnectionTest \ DBusServiceRegistryTest \ @@ -115,7 +161,6 @@ check_PROGRAMS = \ DBusAddressTranslatorTest \ DBusInputStreamTest \ DBusOutputStreamTest \ - DBusRuntimeTest \ DBusFactoryTest \ DBusVariantTest \ DBusTypeStreamTest \ @@ -127,25 +172,27 @@ check_PROGRAMS = \ TESTS = ${check_PROGRAMS} -LDADD_FOR_GTEST = libCommonAPI-DBus.la ${GTEST_LIBS} ${LDADD} +LDADD_FOR_GTEST_WITHOUT_LIBCOMMON_API_DBUS = ${GTEST_LIBS} ${LDADD} +LDADD_FOR_GTEST = libCommonAPI-DBus.la ${LDADD_FOR_GTEST_WITHOUT_LIBCOMMON_API_DBUS} + DBusMainLoopIntegrationTest_SOURCES = \ src/test/DBusMainLoopIntegrationTest.cpp \ - ${TestInterfaceSources} + ${TestInterfaceDBusSources} DBusMainLoopIntegrationTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} ${GLIB_CFLAGS} DBusMainLoopIntegrationTest_CXXFLAGS = ${GTEST_CXXFLAGS} ${GLIB_CFLAGS} DBusMainLoopIntegrationTest_LDADD = ${LDADD_FOR_GTEST} ${GLIB_LIBS} DBusServiceRegistryTest_SOURCES = \ src/test/DBusServiceRegistryTest.cpp \ - ${TestInterfaceSources} + ${TestInterfaceDBusSources} DBusServiceRegistryTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} DBusServiceRegistryTest_CXXFLAGS = ${GTEST_CXXFLAGS} DBusServiceRegistryTest_LDADD = ${LDADD_FOR_GTEST} DBusAddressTranslatorTest_SOURCES = \ src/test/DBusAddressTranslatorTest.cpp \ - ${TestInterfaceSources} + ${TestInterfaceDBusSources} DBusAddressTranslatorTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} DBusAddressTranslatorTest_CXXFLAGS = ${GTEST_CXXFLAGS} DBusAddressTranslatorTest_LDADD = ${LDADD_FOR_GTEST} @@ -167,7 +214,7 @@ DBusVariantOutputStreamTest_LDADD = ${LDADD_FOR_GTEST} DBusCommunicationTest_SOURCES = \ src/test/DBusCommunicationTest.cpp \ - ${TestInterfaceSources} + ${TestInterfaceDBusSources} DBusCommunicationTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} DBusCommunicationTest_CXXFLAGS = ${GTEST_CXXFLAGS} DBusCommunicationTest_LDADD = ${LDADD_FOR_GTEST} @@ -179,47 +226,42 @@ DBusDaemonProxyTest_LDADD = ${LDADD_FOR_GTEST} DBusInputStreamTest_SOURCES = \ src/test/DBusInputStreamTest.cpp \ - ${TestInterfaceSources} + ${TestInterfaceDBusSources} DBusInputStreamTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} DBusInputStreamTest_CXXFLAGS = ${GTEST_CXXFLAGS} DBusInputStreamTest_LDADD = ${LDADD_FOR_GTEST} DBusOutputStreamTest_SOURCES = \ src/test/DBusOutputStreamTest.cpp \ - ${TestInterfaceSources} + ${TestInterfaceDBusSources} DBusOutputStreamTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} DBusOutputStreamTest_CXXFLAGS = ${GTEST_CXXFLAGS} DBusOutputStreamTest_LDADD = ${LDADD_FOR_GTEST} DBusFactoryTest_SOURCES = \ src/test/DBusFactoryTest.cpp \ - ${TestInterfaceSources} + ${TestInterfaceDBusSources} DBusFactoryTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} DBusFactoryTest_CXXFLAGS = ${GTEST_CXXFLAGS} DBusFactoryTest_LDADD = ${LDADD_FOR_GTEST} -DBusRuntimeTest_SOURCES = src/test/DBusRuntimeTest.cpp -DBusRuntimeTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} -DBusRuntimeTest_CXXFLAGS = ${GTEST_CXXFLAGS} -DBusRuntimeTest_LDADD = ${LDADD_FOR_GTEST} - DBusMultipleConnectionTest_SOURCES = \ src/test/DBusMultipleConnectionTest.cpp \ - ${TestInterfaceSources} + ${TestInterfaceDBusSources} DBusMultipleConnectionTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} DBusMultipleConnectionTest_CXXFLAGS = ${GTEST_CXXFLAGS} DBusMultipleConnectionTest_LDADD = ${LDADD_FOR_GTEST} DBusProxyTest_SOURCES = \ src/test/DBusProxyTest.cpp \ - ${TestInterfaceSources} + ${TestInterfaceDBusSources} DBusProxyTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} DBusProxyTest_CXXFLAGS = ${GTEST_CXXFLAGS} DBusProxyTest_LDADD = ${LDADD_FOR_GTEST} DBusServicePublisherTest_SOURCES = \ src/test/DBusServicePublisherTest.cpp \ - ${TestInterfaceSources} + ${TestInterfaceDBusSources} DBusServicePublisherTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} DBusServicePublisherTest_CXXFLAGS = ${GTEST_CXXFLAGS} DBusServicePublisherTest_LDADD = ${LDADD_FOR_GTEST} @@ -229,6 +271,46 @@ DBusVariantTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} DBusVariantTest_CXXFLAGS = ${GTEST_CXXFLAGS} DBusVariantTest_LDADD = ${LDADD_FOR_GTEST} +DBusRuntimeTest_SOURCES = src/test/DBusRuntimeTest.cpp +DBusRuntimeTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusRuntimeTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusRuntimeTest_LDADD = ${LDADD_FOR_GTEST} + +DBusDynamicLoadingBasicTest_SOURCES = \ + ${TestInterfaceSources} \ + src/test/dbusDynamicLoadingTests/DBusDynamicLoadingBasicTest.cpp +DBusDynamicLoadingBasicTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusDynamicLoadingBasicTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusDynamicLoadingBasicTest_LDADD = ${LDADD_FOR_GTEST_WITHOUT_LIBCOMMON_API_DBUS} + +DBusDynamicLoadingMultipleDefinitionTest_SOURCES = \ + ${TestInterfaceSources} \ + src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMultipleDefinitionTest.cpp +DBusDynamicLoadingMultipleDefinitionTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusDynamicLoadingMultipleDefinitionTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusDynamicLoadingMultipleDefinitionTest_LDADD = ${LDADD_FOR_GTEST_WITHOUT_LIBCOMMON_API_DBUS} + +DBusDynamicLoadingMultipleBindingsTest_SOURCES = \ + ${TestInterfaceSources} \ + src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMultipleBindingsTest.cpp +DBusDynamicLoadingMultipleBindingsTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusDynamicLoadingMultipleBindingsTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusDynamicLoadingMultipleBindingsTest_LDADD = ${LDADD_FOR_GTEST_WITHOUT_LIBCOMMON_API_DBUS} + +DBusDynamicLoadingMixedValidityTest_SOURCES = \ + ${TestInterfaceSources} \ + src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMixedValidityTest.cpp +DBusDynamicLoadingMixedValidityTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusDynamicLoadingMixedValidityTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusDynamicLoadingMixedValidityTest_LDADD = ${LDADD_FOR_GTEST_WITHOUT_LIBCOMMON_API_DBUS} + +DBusDynamicLoadingNoValidityTest_SOURCES = \ + ${TestInterfaceSources} \ + src/test/dbusDynamicLoadingTests/DBusDynamicLoadingNoValidityTest.cpp +DBusDynamicLoadingNoValidityTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS} +DBusDynamicLoadingNoValidityTest_CXXFLAGS = ${GTEST_CXXFLAGS} +DBusDynamicLoadingNoValidityTest_LDADD = ${LDADD_FOR_GTEST_WITHOUT_LIBCOMMON_API_DBUS} + endif @@ -97,6 +97,13 @@ CommonAPI and CommonAPI-D-Bus can be built and the make command "check" can be e "make check" builds and executes all tests. As the tests are developed as regression tests, the test output is limited to "OK" and "ERROR" for each test performed. + +== Configuring the D-Bus middleware binding + +=== Well known name +The well known name that may be used to identify and dynamically load the D-Bus middleware binding is "DBus". + + === Defining D-Bus Service Parameters Normally, a CommonAPI address, format ---- @@ -117,7 +124,7 @@ per binary or globally for all binaries. If more than one config file is defined across several config files, the locally defined values override the global ones. If a CommonAPI address is defined more than once within a single file, the first definition found will be the only definition used. -Config files have to be named this way: +CommonAPI D-Bus Config files have to be named this way: ---- # Binary local: "<FqnOfBinary>_dbus.conf", e.g. "/usr/bin/myBinary_dbus.conf" if the binary is "/usr/bin/myBinary" # Binary global: "/etc/CommonApiDBus/<NameOfBinary>_dbus.conf", e.g. "/etc/CommonApiDBus/myBinary_dbus.conf" diff --git a/src/CommonAPI/DBus/DBusAddressTranslator.cpp b/src/CommonAPI/DBus/DBusAddressTranslator.cpp index 5bdb3ee..6b6afce 100644 --- a/src/CommonAPI/DBus/DBusAddressTranslator.cpp +++ b/src/CommonAPI/DBus/DBusAddressTranslator.cpp @@ -6,8 +6,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <CommonAPI/utils.h> + #include "DBusAddressTranslator.h" -#include "DBusUtils.h" + +#include "DBusConnection.h" +#include "DBusFactory.h" #include "DBusConnection.h" #include "DBusFactory.h" @@ -23,206 +27,41 @@ namespace CommonAPI { namespace DBus { -enum class TypeEnum { - DBUS_CONNECTION, DBUS_OBJECT, DBUS_INTERFACE, DBUS_PREDEFINED -}; - -enum class TypeEnumFactory -{ - DBUS_BUSTYPE -}; - -enum class FileParsingState -{ - UNDEFINED, - PARSING_ADDRESS, - PARSING_FACTORY -}; - - -static const std::unordered_map<std::string, TypeEnum> allowedValueTypes = { - {"dbus_connection", TypeEnum::DBUS_CONNECTION}, - {"dbus_object", TypeEnum::DBUS_OBJECT}, - {"dbus_interface", TypeEnum::DBUS_INTERFACE}, - {"dbus_predefined", TypeEnum::DBUS_PREDEFINED} -}; - -static const std::unordered_map<std::string, TypeEnumFactory> allowedValueTypesFactory = { - {"dbus_bustype", TypeEnumFactory::DBUS_BUSTYPE} -}; - - DBusAddressTranslator::DBusAddressTranslator() {} - void DBusAddressTranslator::init() { - std::string fqnOfConfigFile = getCurrentBinaryFileFQN(); - std::ifstream addressConfigFile; - - if (fqnOfConfigFile != "") { - fqnOfConfigFile += DBUS_CONFIG_SUFFIX; - - addressConfigFile.open(fqnOfConfigFile.c_str()); - - if (addressConfigFile.is_open()) { - readConfigFile(addressConfigFile); - addressConfigFile.close(); - } - - addressConfigFile.clear(); - std::vector<std::string> splittedConfigFQN = split(fqnOfConfigFile, '/'); - std::string globalConfigFQN = DBUS_GLOBAL_CONFIG_ROOT + splittedConfigFQN.at(splittedConfigFQN.size() - 1); - addressConfigFile.open(globalConfigFQN); - if (addressConfigFile.is_open()) { - readConfigFile(addressConfigFile); - addressConfigFile.close(); - } - addressConfigFile.clear(); - } - - addressConfigFile.open(DBUS_GLOBAL_CONFIG_FQN); - if(addressConfigFile.is_open()) { - readConfigFile(addressConfigFile); - addressConfigFile.close(); + commonApiAddressDetails_ = DBusConfiguration::getInstance().getCommonApiAddressDetails(); + for (auto& addressDetail: commonApiAddressDetails_) { + fillUndefinedValues(addressDetail.second, addressDetail.first); + DBusServiceAddress dbusServiceDefinition = std::get<0>(addressDetail.second); + dbusToCommonApiAddress_.insert( {dbusServiceDefinition, addressDetail.first}); } } -inline void readValue(std::string& readLine, - DBusAddressTranslator::FactoryConfigDBus& factoryConfig) { - std::stringstream readStream(readLine); - std::string paramName; - std::string paramValue; - - getline(readStream, paramName, '='); - - auto typeEntry = allowedValueTypesFactory.find(paramName); - if (typeEntry != allowedValueTypesFactory.end()) { - getline(readStream, paramValue); - switch (typeEntry->second) { - case TypeEnumFactory::DBUS_BUSTYPE: - if (paramValue == "system") - factoryConfig.busType = DBus::BusType::SYSTEM; - break; - } - } -} - -inline void readValue(std::string& readLine, CommonApiServiceDetails& serviceDetails) { - std::stringstream readStream(readLine); - - std::string paramName; - std::string paramValue; - - getline(readStream, paramName, '='); - - auto typeEntry = allowedValueTypes.find(paramName); - if (typeEntry != allowedValueTypes.end()) { - getline(readStream, paramValue); - switch (typeEntry->second) { - case TypeEnum::DBUS_CONNECTION: - std::get<0>(std::get<0>(serviceDetails)) = paramValue; - break; - case TypeEnum::DBUS_OBJECT: - std::get<1>(std::get<0>(serviceDetails)) = paramValue; - break; - case TypeEnum::DBUS_INTERFACE: - std::get<2>(std::get<0>(serviceDetails)) = paramValue; - break; - case TypeEnum::DBUS_PREDEFINED: - std::get<1>(serviceDetails) = paramValue == "true" ? true : false; - break; - } +DBusAddressTranslator& DBusAddressTranslator::getInstance() { + static DBusAddressTranslator* dbusAddressTranslator; + if(!dbusAddressTranslator) { + dbusAddressTranslator = new DBusAddressTranslator(); + dbusAddressTranslator->init(); } + return *dbusAddressTranslator; } -inline void reset(DBusServiceAddress& dbusServiceAddress) { - std::get<0>(dbusServiceAddress) = ""; - std::get<1>(dbusServiceAddress) = ""; - std::get<2>(dbusServiceAddress) = ""; -} - -inline void reset(CommonApiServiceDetails& serviceDetails) { - reset(std::get<0>(serviceDetails)); - std::get<1>(serviceDetails) = false; -} - - -void DBusAddressTranslator::readConfigFile(std::ifstream& addressConfigFile) { - std::string currentlyParsedCommonApiAddress; - DBusAddressTranslator::FactoryConfigDBus currentlyParsedFactoryConfig; - CommonApiServiceDetails serviceDetails; - reset(serviceDetails); - - bool newAddressFound = false; - bool newFactoryFound = false; - - FileParsingState parsingState = FileParsingState::UNDEFINED; - - while (addressConfigFile.good()) { - std::string readLine; - getline(addressConfigFile, readLine); - const size_t readLineLength = readLine.length(); - - if (readLine[0] == '[' && readLine[readLineLength - 1] == ']') { - // entered section - std::string sectionName = readLine.substr(1, readLineLength - 2); - std::vector<std::string> addressParts = split(sectionName, '$'); - - // check, if it is a factory configuration or address configuration section - if (addressParts.size() == 2 && addressParts[0] == "factory") { - if (newFactoryFound) - { - factoryConfigurations.insert( {currentlyParsedFactoryConfig.factoryName, - currentlyParsedFactoryConfig}); - } - // initialize with default values - DBusFactory::getDefaultFactoryConfig(currentlyParsedFactoryConfig); - - currentlyParsedFactoryConfig.factoryName = addressParts[1]; - newFactoryFound = factoryConfigurations.find(addressParts[1]) == factoryConfigurations.end(); - parsingState = FileParsingState::PARSING_FACTORY; - } - else - { - - if (newAddressFound) { - fillUndefinedValues(serviceDetails, currentlyParsedCommonApiAddress); - commonApiAddressDetails.insert( {currentlyParsedCommonApiAddress, serviceDetails}); - dbusToCommonApiAddress.insert( {std::get<0>(serviceDetails), currentlyParsedCommonApiAddress}); - } - reset(serviceDetails); - if(isValidCommonApiAddress(sectionName)) { - currentlyParsedCommonApiAddress = std::move(sectionName); - newAddressFound = commonApiAddressDetails.find(currentlyParsedCommonApiAddress) == commonApiAddressDetails.end(); - parsingState = FileParsingState::PARSING_ADDRESS; - } - } - } - else - { - if (parsingState == FileParsingState::PARSING_FACTORY) { - readValue(readLine, currentlyParsedFactoryConfig); - } - else - { - if (newAddressFound) { - readValue(readLine, serviceDetails); - } - } - } - } +void DBusAddressTranslator::searchForDBusAddress(const std::string& commonApiAddress, + std::string& interfaceName, + std::string& connectionName, + std::string& objectPath) { - if (newAddressFound || newFactoryFound) { - if (parsingState == FileParsingState::PARSING_ADDRESS) { - fillUndefinedValues(serviceDetails, currentlyParsedCommonApiAddress); - commonApiAddressDetails.insert( {currentlyParsedCommonApiAddress, serviceDetails}); - dbusToCommonApiAddress.insert( {std::get<0>(serviceDetails), currentlyParsedCommonApiAddress}); - } + const auto& foundAddressMapping = commonApiAddressDetails_.find(commonApiAddress); - if (parsingState == FileParsingState::PARSING_FACTORY) { - factoryConfigurations.insert( {currentlyParsedFactoryConfig.factoryName, currentlyParsedFactoryConfig}); - } + if(foundAddressMapping != commonApiAddressDetails_.end()) { + connectionName = std::get<0>(std::get<0>(foundAddressMapping->second)); + objectPath = std::get<1>(std::get<0>(foundAddressMapping->second)); + interfaceName = std::get<2>(std::get<0>(foundAddressMapping->second)); + } else { + findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath); + commonApiAddressDetails_.insert( {commonApiAddress, std::make_tuple(std::make_tuple(connectionName, objectPath, interfaceName), false) } ); } } @@ -240,33 +79,6 @@ void DBusAddressTranslator::fillUndefinedValues(CommonApiServiceDetails& service } -DBusAddressTranslator& DBusAddressTranslator::getInstance() { - static DBusAddressTranslator* dbusNameService_; - if(!dbusNameService_) { - dbusNameService_ = new DBusAddressTranslator(); - dbusNameService_->init(); - } - return *dbusNameService_; -} - - -void DBusAddressTranslator::searchForDBusAddress(const std::string& commonApiAddress, - std::string& interfaceName, - std::string& connectionName, - std::string& objectPath) { - - const auto& foundAddressMapping = commonApiAddressDetails.find(commonApiAddress); - - if(foundAddressMapping != commonApiAddressDetails.end()) { - connectionName = std::get<0>(std::get<0>(foundAddressMapping->second)); - objectPath = std::get<1>(std::get<0>(foundAddressMapping->second)); - interfaceName = std::get<2>(std::get<0>(foundAddressMapping->second)); - } else { - findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath); - commonApiAddressDetails.insert( {commonApiAddress, std::make_tuple(std::make_tuple(connectionName, objectPath, interfaceName), false) } ); - } -} - void DBusAddressTranslator::searchForCommonAddress(const std::string& interfaceName, const std::string& connectionName, const std::string& objectPath, @@ -274,20 +86,20 @@ void DBusAddressTranslator::searchForCommonAddress(const std::string& interfaceN DBusServiceAddress dbusAddress(connectionName, objectPath, interfaceName); - const auto& foundAddressMapping = dbusToCommonApiAddress.find(dbusAddress); - if (foundAddressMapping != dbusToCommonApiAddress.end()) { + const auto& foundAddressMapping = dbusToCommonApiAddress_.find(dbusAddress); + if (foundAddressMapping != dbusToCommonApiAddress_.end()) { commonApiAddress = foundAddressMapping->second; } else { findFallbackCommonAddress(commonApiAddress, interfaceName, connectionName, objectPath); - dbusToCommonApiAddress.insert( {std::move(dbusAddress), commonApiAddress} ); + dbusToCommonApiAddress_.insert( {std::move(dbusAddress), commonApiAddress} ); } } void DBusAddressTranslator::getPredefinedInstances(const std::string& connectionName, std::vector<DBusServiceAddress>& instances) { instances.clear(); - auto dbusAddress = commonApiAddressDetails.begin(); - while (dbusAddress != commonApiAddressDetails.end()) { + auto dbusAddress = commonApiAddressDetails_.begin(); + while (dbusAddress != commonApiAddressDetails_.end()) { CommonApiServiceDetails serviceDetails = dbusAddress->second; if (connectionName == std::get<0>(std::get<0>(serviceDetails)) && true == std::get<1>(serviceDetails)) { @@ -315,15 +127,5 @@ void DBusAddressTranslator::findFallbackCommonAddress(std::string& commonApiAddr commonApiAddress = "local:" + interfaceName + ":" + connectionName; } -DBusAddressTranslator::FactoryConfigDBus* DBusAddressTranslator::searchForFactoryConfiguration(const std::string& factoryName) { - - const auto foundConfig = factoryConfigurations.find(factoryName); - - if (foundConfig != factoryConfigurations.end()) - return (&(foundConfig->second)); - else - return (NULL); -} - }// namespace DBus } // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusAddressTranslator.h b/src/CommonAPI/DBus/DBusAddressTranslator.h index e9bf994..89cebf1 100644 --- a/src/CommonAPI/DBus/DBusAddressTranslator.h +++ b/src/CommonAPI/DBus/DBusAddressTranslator.h @@ -9,13 +9,14 @@ #error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." #endif -#ifndef DBUSNAMESERVICE_H_ -#define DBUSNAMESERVICE_H_ - -#include "DBusFunctionalHash.h" +#ifndef COMMONAPI_DBUS_DBUS_ADDRESS_TRANSLATOR_H_ +#define COMMONAPI_DBUS_DBUS_ADDRESS_TRANSLATOR_H_ #include <CommonAPI/types.h> + #include "DBusConnectionBusType.h" +#include "DBusFunctionalHash.h" +#include "DBusConfiguration.h" #include <algorithm> #include <unordered_map> @@ -25,25 +26,8 @@ namespace CommonAPI { namespace DBus { -static const char* DBUS_CONFIG_SUFFIX = "_dbus.conf"; -static const char* DBUS_GLOBAL_CONFIG_FQN = "/etc/CommonApiDBus/dbusAddresses.conf"; -static const char* DBUS_GLOBAL_CONFIG_ROOT = "/etc/CommonApiDBus/"; - - -//connectionName, objectPath, interfaceName -typedef std::tuple<std::string, std::string, std::string> DBusServiceAddress; - -//Details for a common api address key: DBusAddress, predefined service -typedef std::tuple<DBusServiceAddress, bool> CommonApiServiceDetails; - - class DBusAddressTranslator { public: - struct FactoryConfigDBus { - std::string factoryName; - BusType busType; - }; - ~DBusAddressTranslator(); static DBusAddressTranslator& getInstance(); @@ -58,10 +42,8 @@ public: const std::string& objectPath, std::string& commonApiAddress); - FactoryConfigDBus* searchForFactoryConfiguration(const std::string& factoryName); - void getPredefinedInstances(const std::string& connectionName, - std::vector<DBusServiceAddress>& instances); + std::vector<DBusServiceAddress>& instances); private: DBusAddressTranslator(); @@ -69,28 +51,25 @@ private: DBusAddressTranslator& operator=(const DBusAddressTranslator&) = delete; void init(); - void readConfigFile(std::ifstream& addressConfigFile); void findFallbackDBusAddress(const std::string& instanceId, - std::string& interfaceName, - std::string& connectionName, - std::string& objectPath) const; + std::string& interfaceName, + std::string& connectionName, + std::string& objectPath) const; void findFallbackCommonAddress(std::string& instanceId, - const std::string& interfaceName, - const std::string& connectionName, - const std::string& objectPath) const; - - void fillUndefinedValues(CommonApiServiceDetails& dbusServiceAddress, const std::string& commonApiAddress) const; + const std::string& interfaceName, + const std::string& connectionName, + const std::string& objectPath) const; - std::unordered_map<std::string, CommonApiServiceDetails> commonApiAddressDetails; - std::unordered_map<DBusServiceAddress, std::string> dbusToCommonApiAddress; - std::unordered_map<std::string, DBusAddressTranslator::FactoryConfigDBus> factoryConfigurations; + void fillUndefinedValues(CommonApiServiceDetails& serviceDetails, const std::string& commonApiAddress) const; - }; + std::unordered_map<std::string, CommonApiServiceDetails> commonApiAddressDetails_; + std::unordered_map<DBusServiceAddress, std::string> dbusToCommonApiAddress_; +}; }// namespace DBus }// namespace CommonAPI -#endif /* DBUSNAMESERVICE_H_ */ +#endif /* COMMONAPI_DBUS_DBUS_ADDRESS_TRANSLATOR_H_ */ diff --git a/src/CommonAPI/DBus/DBusConfiguration.cpp b/src/CommonAPI/DBus/DBusConfiguration.cpp new file mode 100644 index 0000000..743fdaa --- /dev/null +++ b/src/CommonAPI/DBus/DBusConfiguration.cpp @@ -0,0 +1,260 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <fstream> + +#include <CommonAPI/utils.h> + +#include "DBusConfiguration.h" + + +namespace CommonAPI { +namespace DBus { + + +enum class TypeEnum { + DBUS_CONNECTION, DBUS_OBJECT, DBUS_INTERFACE, DBUS_PREDEFINED +}; + +enum class TypeEnumFactory { + DBUS_BUSTYPE +}; + +enum class FileParsingState { + UNDEFINED, + PARSING_ADDRESS, + PARSING_FACTORY +}; + + +static const std::unordered_map<std::string, TypeEnum> allowedValueTypes = { + {"dbus_connection", TypeEnum::DBUS_CONNECTION}, + {"dbus_object", TypeEnum::DBUS_OBJECT}, + {"dbus_interface", TypeEnum::DBUS_INTERFACE}, + {"dbus_predefined", TypeEnum::DBUS_PREDEFINED} +}; + +static const std::unordered_map<std::string, TypeEnumFactory> allowedValueTypesFactory = { + {"dbus_bustype", TypeEnumFactory::DBUS_BUSTYPE} +}; + + +const DBusConfiguration& DBusConfiguration::getInstance() { + static DBusConfiguration* instance = NULL; + if (!instance) { + instance = new DBusConfiguration(); + instance->retrieveCommonApiDBusConfiguration(); + } + return *instance; +} + +void DBusConfiguration::retrieveCommonApiDBusConfiguration() { + std::string fqnOfConfigFile = getCurrentBinaryFileFQN(); + std::ifstream addressConfigFile; + + fqnOfConfigFile += DBUS_CONFIG_SUFFIX; + + addressConfigFile.open(fqnOfConfigFile.c_str()); + + if (addressConfigFile.is_open()) { + readConfigFile(addressConfigFile); + addressConfigFile.close(); + } + + addressConfigFile.clear(); + std::vector<std::string> splittedConfigFQN = split(fqnOfConfigFile, '/'); + std::string globalConfigFQN = DBUS_GLOBAL_CONFIG_ROOT + splittedConfigFQN.at(splittedConfigFQN.size() - 1); + addressConfigFile.open(globalConfigFQN); + if (addressConfigFile.is_open()) { + readConfigFile(addressConfigFile); + addressConfigFile.close(); + } + addressConfigFile.clear(); + + addressConfigFile.open(DBUS_GLOBAL_CONFIG_FQN); + if(addressConfigFile.is_open()) { + readConfigFile(addressConfigFile); + addressConfigFile.close(); + } +} + +const std::unordered_map<std::string, CommonApiServiceDetails>& DBusConfiguration::getCommonApiAddressDetails() const { + return std::move(commonApiAddressDetails_); +} + +const DBusFactoryConfig* DBusConfiguration::getFactoryConfiguration(const std::string& factoryName) const { + const auto foundConfig = factoryConfigurations_.find(factoryName); + + if (foundConfig != factoryConfigurations_.end()) { + return &foundConfig->second; + } + return NULL; +} + +inline void reset(DBusServiceAddress& dbusServiceAddress) { + std::get<0>(dbusServiceAddress) = ""; + std::get<1>(dbusServiceAddress) = ""; + std::get<2>(dbusServiceAddress) = ""; +} + +inline void reset(CommonApiServiceDetails& serviceDetails) { + reset(std::get<0>(serviceDetails)); + std::get<1>(serviceDetails) = false; +} + + +inline void reset(DBusFactoryConfig& dbusFactoryconfiguration) { + dbusFactoryconfiguration.factoryName_ = ""; + dbusFactoryconfiguration.busType_ = BusType::SESSION; +} + +void DBusConfiguration::readValue(std::string& readLine, DBusFactoryConfig& factoryConfig) { + std::stringstream readStream(readLine); + std::string paramName; + std::string paramValue; + + getline(readStream, paramName, '='); + + auto typeEntry = allowedValueTypesFactory.find(paramName); + if (typeEntry != allowedValueTypesFactory.end()) { + getline(readStream, paramValue); + switch (typeEntry->second) { + case TypeEnumFactory::DBUS_BUSTYPE: + if (paramValue == "system") { + factoryConfig.busType_ = DBus::BusType::SYSTEM; + } + break; + } + } +} + +void DBusConfiguration::readValue(std::string& readLine, CommonApiServiceDetails& serviceDetails) { + std::stringstream readStream(readLine); + + std::string paramName; + std::string paramValue; + + getline(readStream, paramName, '='); + + auto typeEntry = allowedValueTypes.find(paramName); + if (typeEntry != allowedValueTypes.end()) { + getline(readStream, paramValue); + switch (typeEntry->second) { + case TypeEnum::DBUS_CONNECTION: + std::get<0>(std::get<0>(serviceDetails)) = paramValue; + break; + case TypeEnum::DBUS_OBJECT: + std::get<1>(std::get<0>(serviceDetails)) = paramValue; + break; + case TypeEnum::DBUS_INTERFACE: + std::get<2>(std::get<0>(serviceDetails)) = paramValue; + break; + case TypeEnum::DBUS_PREDEFINED: + std::get<1>(serviceDetails) = paramValue == "true" ? true : false; + break; + } + } +} + + +const FileParsingState isValidSection(const std::string& sectionIdentifier, std::string& newSectionName) { + const size_t sectionIdentifierLength = sectionIdentifier.length(); + + if (sectionIdentifier[0] == '[' && sectionIdentifier[sectionIdentifier.length() - 1] == ']') { + std::string sectionName = sectionIdentifier.substr(1, sectionIdentifierLength - 2); + std::vector<std::string> addressParts = split(sectionName, '$'); + + if (addressParts.size() == 2 && addressParts[0] == "factory") { + newSectionName = addressParts[1]; + return FileParsingState::PARSING_FACTORY; + } else if (isValidCommonApiAddress(sectionName)) { + newSectionName = sectionName; + return FileParsingState::PARSING_ADDRESS; + } + } + return FileParsingState::UNDEFINED; +} + + +void DBusConfiguration::readConfigFile(std::ifstream& addressConfigFile) { + std::string currentlyParsedCommonApiAddress; + DBusFactoryConfig currentlyParsedFactoryConfig; + CommonApiServiceDetails serviceDetails; + reset(serviceDetails); + + bool newAddressFound = false; + bool newFactoryFound = false; + + FileParsingState currentParsingState = FileParsingState::UNDEFINED; + + while (addressConfigFile.good()) { + std::string readLine; + std::string sectionName; + getline(addressConfigFile, readLine); + + FileParsingState newState = isValidSection(readLine, sectionName); + + //Finish currently read sections if necessary + if (newState != FileParsingState::UNDEFINED) { + switch (currentParsingState) { + case FileParsingState::PARSING_ADDRESS: + if (newAddressFound) { + commonApiAddressDetails_.insert( {currentlyParsedCommonApiAddress, serviceDetails}); + } + newAddressFound = false; + break; + case FileParsingState::PARSING_FACTORY: + if (newFactoryFound) { + factoryConfigurations_.insert( {currentlyParsedFactoryConfig.factoryName_, currentlyParsedFactoryConfig} ); + } + newFactoryFound = false; + break; + } + } + + //See what comes next + switch (newState) { + case FileParsingState::PARSING_ADDRESS: + reset(serviceDetails); + currentlyParsedCommonApiAddress = sectionName; + newAddressFound = commonApiAddressDetails_.find(currentlyParsedCommonApiAddress) == commonApiAddressDetails_.end(); + currentParsingState = FileParsingState::PARSING_ADDRESS; + break; + + case FileParsingState::PARSING_FACTORY: + reset(currentlyParsedFactoryConfig); + currentlyParsedFactoryConfig.factoryName_ = sectionName; + newFactoryFound = factoryConfigurations_.find(sectionName) == factoryConfigurations_.end(); + currentParsingState = FileParsingState::PARSING_FACTORY; + break; + + //nothing new, so this lines should contain additional information for the current state + case FileParsingState::UNDEFINED: + switch (currentParsingState) { + case FileParsingState::PARSING_FACTORY: + readValue(readLine, currentlyParsedFactoryConfig); + break; + case FileParsingState::PARSING_ADDRESS: + readValue(readLine, serviceDetails); + break; + } + break; + } + } + + //End of file, finish last section + if (newAddressFound) { + commonApiAddressDetails_.insert( {currentlyParsedCommonApiAddress, serviceDetails}); + } + if (newFactoryFound) { + factoryConfigurations_.insert( {currentlyParsedFactoryConfig.factoryName_, currentlyParsedFactoryConfig}); + } +} + + +}// namespace DBus +} // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusConfiguration.h b/src/CommonAPI/DBus/DBusConfiguration.h new file mode 100644 index 0000000..6ded2b6 --- /dev/null +++ b/src/CommonAPI/DBus/DBusConfiguration.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#if !defined (COMMONAPI_INTERNAL_COMPILATION) +#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef COMMONAPI_DBUS_DBUS_CONFIGURATION_H_ +#define COMMONAPI_DBUS_DBUS_CONFIGURATION_H_ + + +#include <unordered_map> + +#include "DBusConnectionBusType.h" +#include "DBusFunctionalHash.h" + + +namespace CommonAPI { +namespace DBus { + +static const char DBUS_CONFIG_SUFFIX[] = "_dbus.conf"; +static const char DBUS_GLOBAL_CONFIG_FQN[] = "/etc/CommonApiDBus/dbusAddresses.conf"; +static const char DBUS_GLOBAL_CONFIG_ROOT[] = "/etc/CommonApiDBus/"; + +//connectionName, objectPath, interfaceName +typedef std::tuple<std::string, std::string, std::string> DBusServiceAddress; + +//Details for a common api address key: DBusAddress, predefined service +typedef std::tuple<DBusServiceAddress, bool> CommonApiServiceDetails; + + +struct DBusFactoryConfig { + DBusFactoryConfig(): factoryName_(""), busType_(BusType::SESSION) {} + + std::string factoryName_; + BusType busType_; +}; + + +class DBusConfiguration { + public: + static const DBusConfiguration& getInstance(); + + DBusConfiguration(const DBusConfiguration&) = delete; + DBusConfiguration& operator=(const DBusConfiguration&) = delete; + DBusConfiguration(DBusConfiguration&&) = delete; + DBusConfiguration& operator=(DBusConfiguration&&) = delete; + + const std::unordered_map<std::string, CommonApiServiceDetails>& getCommonApiAddressDetails() const; + + const DBusFactoryConfig* getFactoryConfiguration(const std::string& factoryName) const; + + private: + DBusConfiguration() = default; + + void readConfigFile(std::ifstream& addressConfigFile); + void retrieveCommonApiDBusConfiguration(); + + void readValue(std::string& readLine, DBusFactoryConfig& factoryConfig); + void readValue(std::string& readLine, CommonApiServiceDetails& serviceDetails); + + std::unordered_map<std::string, CommonApiServiceDetails> commonApiAddressDetails_; + std::unordered_map<std::string, DBusFactoryConfig> factoryConfigurations_; +}; + + +}// namespace DBus +}// namespace CommonAPI + +#endif /* COMMONAPI_DBUS_DBUS_CONFIGURATION_H_ */ diff --git a/src/CommonAPI/DBus/DBusConnection.cpp b/src/CommonAPI/DBus/DBusConnection.cpp index 950c72a..c41f8ab 100644 --- a/src/CommonAPI/DBus/DBusConnection.cpp +++ b/src/CommonAPI/DBus/DBusConnection.cpp @@ -33,10 +33,13 @@ void DBusConnectionStatusEvent::onListenerAdded(const CancellableListener& liste } -DBusObjectPathVTable DBusConnection::libdbusObjectPathVTable_ = { - NULL, // no need to handle unregister callbacks - &DBusConnection::onLibdbusObjectPathMessageThunk -}; +const DBusObjectPathVTable* DBusConnection::getDBusObjectPathVTable() { + static const DBusObjectPathVTable libdbusObjectPathVTable = { + NULL, // no need to handle unregister callbacks + &DBusConnection::onLibdbusObjectPathMessageThunk + }; + return &libdbusObjectPathVTable; +} //std::bind used to start the dispatch thread holds one reference, and the selfReference @@ -643,7 +646,7 @@ void DBusConnection::registerObjectPath(const std::string& objectPath) { DBusError dbusError; const dbus_bool_t libdbusSuccess = dbus_connection_try_register_object_path(libdbusConnection_, objectPath.c_str(), - &libdbusObjectPathVTable_, + getDBusObjectPathVTable(), this, &dbusError.libdbusError_); assert(libdbusSuccess); @@ -782,7 +785,7 @@ void DBusConnection::initLibdbusObjectPathHandlerAfterConnect() { libdbusSuccess = dbus_connection_try_register_object_path(libdbusConnection_, objectPath.c_str(), - &libdbusObjectPathVTable_, + getDBusObjectPathVTable(), this, &dbusError.libdbusError_); assert(libdbusSuccess); diff --git a/src/CommonAPI/DBus/DBusConnection.h b/src/CommonAPI/DBus/DBusConnection.h index 2200cd2..a64693c 100644 --- a/src/CommonAPI/DBus/DBusConnection.h +++ b/src/CommonAPI/DBus/DBusConnection.h @@ -51,7 +51,7 @@ class DBusConnection: public DBusProxyConnection, public std::enable_shared_from public: DBusConnection(BusType busType); - inline static std::shared_ptr<DBusConnection> getBus(const BusType& busType); + inline static std::shared_ptr<DBusConnection> getBus(const BusType& dbusBusType); inline static std::shared_ptr<DBusConnection> wrapLibDBus(::DBusConnection* libDbusConnection); inline static std::shared_ptr<DBusConnection> getSessionBus(); inline static std::shared_ptr<DBusConnection> getSystemBus(); @@ -164,6 +164,7 @@ class DBusConnection: public DBusProxyConnection, public std::enable_shared_from static void onWakeupMainContext(void* data); void enforceAsynchronousTimeouts() const; + static const DBusObjectPathVTable* getDBusObjectPathVTable(); ::DBusConnection* libdbusConnection_; mutable std::mutex libdbusConnectionGuard_; @@ -189,8 +190,6 @@ class DBusConnection: public DBusProxyConnection, public std::enable_shared_from typedef std::unordered_map<std::string, uint32_t> LibdbusRegisteredObjectPathHandlersTable; LibdbusRegisteredObjectPathHandlersTable libdbusRegisteredObjectPaths_; - static DBusObjectPathVTable libdbusObjectPathVTable_; - DBusObjectPathMessageHandler dbusObjectMessageHandler_; mutable std::unordered_map<std::string, uint16_t> connectionNameCount_; diff --git a/src/CommonAPI/DBus/DBusConnectionBusType.h b/src/CommonAPI/DBus/DBusConnectionBusType.h index b91a01a..bdb98d9 100644 --- a/src/CommonAPI/DBus/DBusConnectionBusType.h +++ b/src/CommonAPI/DBus/DBusConnectionBusType.h @@ -1,26 +1,26 @@ -/* - * DBusConnectionBusType.h - * - * Created on: May 27, 2013 - * Author: hmi - */ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef DBUSCONNECTIONBUSTYPE_H_ #define DBUSCONNECTIONBUSTYPE_H_ #include <dbus/dbus-shared.h> -namespace CommonAPI -{ -namespace DBus -{ +namespace CommonAPI { +namespace DBus { + enum BusType { SESSION = DBUS_BUS_SESSION, SYSTEM = DBUS_BUS_SYSTEM, STARTER = DBUS_BUS_STARTER, WRAPPED }; -} -} + +} // namespace DBus +} // namespace CommonAPI #endif /* DBUSCONNECTIONBUSTYPE_H_ */ diff --git a/src/CommonAPI/DBus/DBusDaemonProxy.cpp b/src/CommonAPI/DBus/DBusDaemonProxy.cpp index 1401125..1c804ee 100644 --- a/src/CommonAPI/DBus/DBusDaemonProxy.cpp +++ b/src/CommonAPI/DBus/DBusDaemonProxy.cpp @@ -30,15 +30,15 @@ std::future<CallStatus> StaticInterfaceVersionAttribute::getValueAsync(Attribute } -StaticInterfaceVersionAttribute DBusDaemonProxy::interfaceVersionAttribute_(1, 0); -const std::string DBusDaemonProxy::dbusBusName_ = "org.freedesktop.DBus"; -const std::string DBusDaemonProxy::dbusObjectPath_ = "/org/freedesktop/DBus"; -const std::string DBusDaemonProxy::dbusInterfaceName_ = getInterfaceId(); -const std::string DBusDaemonProxy::commonApiParticipantId_ = "org.freedesktop.DBus-/org/freedesktop/DBus"; +static const std::string dbusDaemonBusName_ = "org.freedesktop.DBus"; +static const std::string dbusDaemonObjectPath_ = "/org/freedesktop/DBus"; +static const std::string dbusDaemonInterfaceName_ = DBusDaemonProxy::getInterfaceId(); +static const std::string commonApiParticipantId_ = "org.freedesktop.DBus-/org/freedesktop/DBus"; DBusDaemonProxy::DBusDaemonProxy(const std::shared_ptr<DBusProxyConnection>& dbusConnection): DBusProxyBase(dbusConnection), + interfaceVersionAttribute_(1, 0), nameOwnerChangedEvent_(*this, "NameOwnerChanged", "sss") { } @@ -49,20 +49,20 @@ const std::string& DBusDaemonProxy::getDomain() const { return commonApiDomain_; } const std::string& DBusDaemonProxy::getServiceId() const { - return dbusInterfaceName_; + return dbusDaemonInterfaceName_; } const std::string& DBusDaemonProxy::getInstanceId() const { return commonApiParticipantId_; } const std::string& DBusDaemonProxy::getDBusBusName() const { - return dbusBusName_; + return dbusDaemonBusName_; } const std::string& DBusDaemonProxy::getDBusObjectPath() const { - return dbusObjectPath_; + return dbusDaemonObjectPath_; } const std::string& DBusDaemonProxy::getInterfaceName() const { - return dbusInterfaceName_; + return dbusDaemonInterfaceName_; } bool DBusDaemonProxy::isAvailable() const { diff --git a/src/CommonAPI/DBus/DBusDaemonProxy.h b/src/CommonAPI/DBus/DBusDaemonProxy.h index ca4d248..b785f29 100644 --- a/src/CommonAPI/DBus/DBusDaemonProxy.h +++ b/src/CommonAPI/DBus/DBusDaemonProxy.h @@ -77,16 +77,12 @@ class DBusDaemonProxy: public DBusProxyBase { private: DBusEvent<NameOwnerChangedEvent> nameOwnerChangedEvent_; - static StaticInterfaceVersionAttribute interfaceVersionAttribute_; - - static const std::string dbusBusName_; - static const std::string dbusObjectPath_; - static const std::string commonApiParticipantId_; - static const std::string dbusInterfaceName_; + StaticInterfaceVersionAttribute interfaceVersionAttribute_; }; const char* DBusDaemonProxy::getInterfaceId() { - return "org.freedesktop.DBus"; + static const char interfaceId[] = "org.freedesktop.DBus"; + return interfaceId; } } // namespace DBus diff --git a/src/CommonAPI/DBus/DBusFactory.cpp b/src/CommonAPI/DBus/DBusFactory.cpp index a117e20..572f8f7 100644 --- a/src/CommonAPI/DBus/DBusFactory.cpp +++ b/src/CommonAPI/DBus/DBusFactory.cpp @@ -8,7 +8,6 @@ #include "DBusProxy.h" #include "DBusConnection.h" #include "DBusFactory.h" -#include "DBusAddressTranslator.h" #include "DBusServiceRegistry.h" #include "DBusUtils.h" #include "DBusServicePublisher.h" @@ -44,30 +43,13 @@ void DBusFactory::registerAdapterFactoryMethod(std::string interfaceName, DBusAd DBusFactory::DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, - std::shared_ptr<MainLoopContext> mainLoopContext) : + std::shared_ptr<MainLoopContext> mainLoopContext, + const DBusFactoryConfig& DBusFactoryConfig) : CommonAPI::Factory(runtime, middlewareInfo), - mainLoopContext_(mainLoopContext) { + mainLoopContext_(mainLoopContext), + DBusFactoryConfig_(DBusFactoryConfig){ - // init factoryConfigDBus_ with default parameters - DBusFactory::getDefaultFactoryConfig(factoryConfigDBus_); - connect(); -} - -DBusFactory::DBusFactory(std::shared_ptr<Runtime> runtime, - const MiddlewareInfo* middlewareInfo, - const DBusAddressTranslator::FactoryConfigDBus& factoryConfigDBus, - std::shared_ptr<MainLoopContext> mainLoopContext) : - CommonAPI::Factory(runtime, middlewareInfo), - mainLoopContext_(mainLoopContext) { - factoryConfigDBus_ = factoryConfigDBus; - connect(); -} - -/** - * contains the common logic for building a connection used by default Factory and Factory with named configuration - */ -void DBusFactory::connect() { - dbusConnection_ = CommonAPI::DBus::DBusConnection::getBus(factoryConfigDBus_.busType); + dbusConnection_ = CommonAPI::DBus::DBusConnection::getBus(DBusFactoryConfig_.busType_); bool startDispatchThread = !mainLoopContext_; dbusConnection_->connect(startDispatchThread); if (mainLoopContext_) { @@ -209,9 +191,5 @@ bool DBusFactory::unregisterService(const std::string& participantId, const std: } -void DBusFactory::getDefaultFactoryConfig(DBusAddressTranslator::FactoryConfigDBus& returnConfiguration) { - returnConfiguration = { "", BusType::SESSION }; -} - } // namespace DBus } // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusFactory.h b/src/CommonAPI/DBus/DBusFactory.h index 0067c0a..f9132f1 100644 --- a/src/CommonAPI/DBus/DBusFactory.h +++ b/src/CommonAPI/DBus/DBusFactory.h @@ -40,8 +40,7 @@ typedef std::shared_ptr<DBusStubAdapter> (*DBusAdapterFactoryFunction) (const st class DBusFactory: public Factory { public: - DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, std::shared_ptr<MainLoopContext> mainLoopContext = std::shared_ptr<MainLoopContext>(NULL)); - DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, const DBusAddressTranslator::FactoryConfigDBus&, std::shared_ptr<MainLoopContext> mainLoopContext = std::shared_ptr<MainLoopContext>(NULL)); + DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, std::shared_ptr<MainLoopContext> mainLoopContext, const DBusFactoryConfig& dbusFactoryConfig = DBusFactoryConfig()); virtual ~DBusFactory(); @@ -59,8 +58,6 @@ class DBusFactory: public Factory { virtual bool unregisterService(const std::string& participantId, const std::string& serviceName, const std::string& domain = "local"); - static void getDefaultFactoryConfig(DBusAddressTranslator::FactoryConfigDBus&); - protected: virtual std::shared_ptr<Proxy> createProxy(const char* interfaceId, const std::string& participantId, const std::string& serviceName, const std::string& domain); virtual bool registerAdapter(std::shared_ptr<StubBase> stubBase, const char* interfaceId, const std::string& participantId, const std::string& serviceName, const std::string& domain); @@ -70,9 +67,7 @@ class DBusFactory: public Factory { std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_; std::shared_ptr<MainLoopContext> mainLoopContext_; - DBusAddressTranslator::FactoryConfigDBus factoryConfigDBus_; - - inline void connect(); + DBusFactoryConfig DBusFactoryConfig_; }; } // namespace DBus diff --git a/src/CommonAPI/DBus/DBusObjectManager.cpp b/src/CommonAPI/DBus/DBusObjectManager.cpp index 4104fcd..96c61d1 100644 --- a/src/CommonAPI/DBus/DBusObjectManager.cpp +++ b/src/CommonAPI/DBus/DBusObjectManager.cpp @@ -10,6 +10,8 @@ #include "DBusOutputStream.h" #include "DBusUtils.h" +#include <CommonAPI/utils.h> + #include <dbus/dbus-protocol.h> #include <cassert> @@ -126,7 +128,7 @@ bool DBusObjectManager::onObjectManagerInterfaceDBusMessage(const DBusMessage& d } objectPathLock_.unlock(); - const char* getManagedObjectsDBusSignature = "a{oa{sa{sv}}}"; + const char getManagedObjectsDBusSignature[] = "a{oa{sa{sv}}}"; DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(getManagedObjectsDBusSignature); DBusOutputStream outStream(dbusMessageReply); @@ -161,7 +163,7 @@ bool DBusObjectManager::onIntrospectableInterfaceDBusMessage(const DBusMessage& const std::string& dbusObjectPath = handlerPath.first; const std::string& dbusInterfaceName = handlerPath.second; DBusStubAdapter* dbusStubAdapter = registeredObjectsIterator.second; - std::vector<std::string> elems = CommonAPI::DBus::split(dbusObjectPath, '/'); + std::vector<std::string> elems = CommonAPI::split(dbusObjectPath, '/'); if (dbusMessage.hasObjectPath(dbusObjectPath)) { foundRegisteredObjects = true; diff --git a/src/CommonAPI/DBus/DBusOutputStream.cpp b/src/CommonAPI/DBus/DBusOutputStream.cpp index 701a628..687d88d 100644 --- a/src/CommonAPI/DBus/DBusOutputStream.cpp +++ b/src/CommonAPI/DBus/DBusOutputStream.cpp @@ -274,7 +274,7 @@ DBusOutputStream& DBusOutputStream::writeString(const char* cString, const uint3 //Additional 0-termination, so this is 8 byte of \0 -static const char* eightByteZeroString = "\0\0\0\0\0\0\0"; +static const char eightByteZeroString[] = "\0\0\0\0\0\0\0"; void DBusOutputStream::alignToBoundary(const size_t alignBoundary) { assert(alignBoundary > 0 && alignBoundary <= 8 && (alignBoundary % 2 == 0 || alignBoundary == 1)); diff --git a/src/CommonAPI/DBus/DBusProxyBase.cpp b/src/CommonAPI/DBus/DBusProxyBase.cpp index 633fab4..e80224e 100644 --- a/src/CommonAPI/DBus/DBusProxyBase.cpp +++ b/src/CommonAPI/DBus/DBusProxyBase.cpp @@ -10,10 +10,9 @@ namespace CommonAPI { namespace DBus { -const std::string DBusProxyBase::commonApiDomain_ = "local"; - DBusProxyBase::DBusProxyBase(const std::shared_ptr<DBusProxyConnection>& dbusConnection) : - dbusConnection_(dbusConnection) { + dbusConnection_(dbusConnection), + commonApiDomain_("local") { } DBusMessage DBusProxyBase::createMethodCall(const char* methodName, diff --git a/src/CommonAPI/DBus/DBusProxyBase.h b/src/CommonAPI/DBus/DBusProxyBase.h index d1310b7..c995a1c 100644 --- a/src/CommonAPI/DBus/DBusProxyBase.h +++ b/src/CommonAPI/DBus/DBusProxyBase.h @@ -56,7 +56,7 @@ class DBusProxyBase: public virtual CommonAPI::Proxy { inline void removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken); protected: - static const std::string commonApiDomain_; + const std::string commonApiDomain_; private: DBusProxyBase(const DBusProxyBase&) = delete; diff --git a/src/CommonAPI/DBus/DBusRuntime.cpp b/src/CommonAPI/DBus/DBusRuntime.cpp index 98f4feb..24f81f3 100644 --- a/src/CommonAPI/DBus/DBusRuntime.cpp +++ b/src/CommonAPI/DBus/DBusRuntime.cpp @@ -4,53 +4,63 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <CommonAPI/Configuration.h> +#include <CommonAPI/utils.h> + #include "DBusRuntime.h" #include "DBusAddressTranslator.h" + +const char middlewareIdentifier[] = "DBus"; + +const CommonAPI::MiddlewareInfo middlewareInfo(middlewareIdentifier, &CommonAPI::DBus::DBusRuntime::getInstance); + + namespace CommonAPI { namespace DBus { -const MiddlewareInfo DBusRuntime::middlewareInfo_("DBus", &DBusRuntime::getInstance); - __attribute__((constructor)) void registerDBusMiddleware(void) { - Runtime::registerRuntimeLoader("DBus", &DBusRuntime::getInstance); + Runtime::registerRuntimeLoader(middlewareIdentifier, &DBusRuntime::getInstance); } std::shared_ptr<Runtime> DBusRuntime::getInstance() { - static std::shared_ptr<Runtime> singleton_; - if(!singleton_) { - singleton_ = std::make_shared<DBusRuntime>(); + static std::shared_ptr<Runtime> dbusRuntimeSingleton_; + if (!dbusRuntimeSingleton_) { + dbusRuntimeSingleton_ = std::make_shared<DBusRuntime>(); + for (const auto& genericLibraryPath: Configuration::getInstance().getGenericLibraryPaths(middlewareIdentifier)) { + if (!loadGenericLibrary(middlewareIdentifier, genericLibraryPath, false)) { + return std::shared_ptr<Runtime>(NULL); + } + } + findAndLoadGenericLibraries(middlewareIdentifier, Configuration::getInstance().getLibrarySearchPaths()); } - return singleton_; + return dbusRuntimeSingleton_; } + std::shared_ptr<Factory> DBusRuntime::doCreateFactory(std::shared_ptr<MainLoopContext> mainLoopContext, - const std::string factoryName, + const std::string& factoryName, const bool nullOnInvalidName) { auto factory = std::shared_ptr<DBusFactory>(NULL); if (factoryName == "") { - factory = std::make_shared<DBusFactory>(this->shared_from_this(), &middlewareInfo_, mainLoopContext); + factory = std::make_shared<DBusFactory>(this->shared_from_this(), &middlewareInfo, mainLoopContext); } else { - DBusAddressTranslator::FactoryConfigDBus* factoryConfigDBus = - DBusAddressTranslator::getInstance().searchForFactoryConfiguration(factoryName); - DBusAddressTranslator::FactoryConfigDBus defaultFactoryConfigDBus; + const DBusFactoryConfig* dbusFactoryConfig = DBusConfiguration::getInstance().getFactoryConfiguration(factoryName); - if (factoryConfigDBus == NULL) { - // unknown / unconfigured Factory requested + if (dbusFactoryConfig == NULL) { if (nullOnInvalidName) { - return (NULL); + return std::shared_ptr<Factory>(NULL); } else { - DBusFactory::getDefaultFactoryConfig(defaultFactoryConfigDBus); // get default settings - factoryConfigDBus = &defaultFactoryConfigDBus; + dbusFactoryConfig = new DBusFactoryConfig(); } } factory = std::make_shared<DBusFactory>( this->shared_from_this(), - &middlewareInfo_, - *factoryConfigDBus, - mainLoopContext); + &middlewareInfo, + mainLoopContext, + *dbusFactoryConfig); } return factory; diff --git a/src/CommonAPI/DBus/DBusRuntime.h b/src/CommonAPI/DBus/DBusRuntime.h index 4b0fdf5..725863e 100644 --- a/src/CommonAPI/DBus/DBusRuntime.h +++ b/src/CommonAPI/DBus/DBusRuntime.h @@ -25,12 +25,10 @@ class DBusRuntime: public Runtime, public std::enable_shared_from_this<DBusRunti static std::shared_ptr<Runtime> getInstance(); std::shared_ptr<ServicePublisher> getServicePublisher(); - static const MiddlewareInfo middlewareInfo_; - protected: std::shared_ptr<Factory> doCreateFactory(std::shared_ptr<MainLoopContext> mainLoopContext, - const std::string factoryName, - const bool nullOnInvalidName = false); + const std::string& factoryName, + const bool nullOnInvalidName); private: static std::unordered_map<std::string, DBusRuntime> registeredRuntimes; @@ -40,10 +38,6 @@ class DBusRuntime: public Runtime, public std::enable_shared_from_this<DBusRunti } // namespace CommonAPI -extern "C" { - -CommonAPI::MiddlewareInfo middlewareInfo = CommonAPI::DBus::DBusRuntime::middlewareInfo_; - -} +extern "C" const CommonAPI::MiddlewareInfo middlewareInfo; #endif // COMMONAPI_DBUS_DBUS_RUNTIME_H_ diff --git a/src/CommonAPI/DBus/DBusStubAdapter.cpp b/src/CommonAPI/DBus/DBusStubAdapter.cpp index 90e04b4..c71c47f 100644 --- a/src/CommonAPI/DBus/DBusStubAdapter.cpp +++ b/src/CommonAPI/DBus/DBusStubAdapter.cpp @@ -7,6 +7,8 @@ #include "DBusStubAdapter.h" #include "DBusUtils.h" +#include <CommonAPI/utils.h> + #include <cassert> #include <functional> #include <sstream> diff --git a/src/CommonAPI/DBus/DBusStubAdapterHelper.h b/src/CommonAPI/DBus/DBusStubAdapterHelper.h index b936f57..120aee7 100644 --- a/src/CommonAPI/DBus/DBusStubAdapterHelper.h +++ b/src/CommonAPI/DBus/DBusStubAdapterHelper.h @@ -85,8 +85,8 @@ class DBusStubAdapterHelper: public DBusStubAdapter, public std::enable_shared_f assert(interfaceMemberSignature); DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature); - auto findIterator = this->stubDispatcherTable_.find(dbusInterfaceMemberPath); - const bool foundInterfaceMemberHandler = (findIterator != this->stubDispatcherTable_.end()); + auto findIterator = getStubDispatcherTable().find(dbusInterfaceMemberPath); + const bool foundInterfaceMemberHandler = (findIterator != getStubDispatcherTable().end()); bool dbusMessageHandled = false; //To prevent the destruction of the stub whilst still handling a message @@ -99,9 +99,10 @@ class DBusStubAdapterHelper: public DBusStubAdapter, public std::enable_shared_f return dbusMessageHandled; } + virtual const StubDispatcherTable& getStubDispatcherTable() = 0; + std::shared_ptr<_StubClass> stub_; RemoteEventHandlerType* remoteEventHandler_; - static const StubDispatcherTable stubDispatcherTable_; }; template< class > diff --git a/src/CommonAPI/DBus/DBusUtils.h b/src/CommonAPI/DBus/DBusUtils.h index 22879d1..3b74ef5 100644 --- a/src/CommonAPI/DBus/DBusUtils.h +++ b/src/CommonAPI/DBus/DBusUtils.h @@ -12,89 +12,11 @@ #ifndef DBUSUTILS_H_ #define DBUSUTILS_H_ -#include <algorithm> -#include <string> -#include <sstream> -#include <vector> -#include <unistd.h> #include <future> namespace CommonAPI { namespace DBus { -inline std::vector<std::string>& split(const std::string& s, char delim, std::vector<std::string>& elems) { - std::istringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) { - elems.push_back(item); - } - return elems; -} - -inline std::vector<std::string> split(const std::string& s, char delim) { - std::vector<std::string> elems; - return split(s, delim, elems); -} - -inline bool containsOnlyAlphanumericCharacters(const std::string& toCheck) { - auto firstNonAlphanumericCharacterIt = std::find_if(toCheck.begin(), - toCheck.end(), - [](char c) { - return !std::isalnum(c); - }); - - return firstNonAlphanumericCharacterIt == toCheck.end(); -} - -inline bool isValidDomainName(const std::string& domainName) { - return containsOnlyAlphanumericCharacters(domainName); -} - -inline bool isValidServiceName(const std::string& serviceName) { - bool isValid = serviceName[0] != '.' && serviceName[serviceName.size() - 1] != '.'; - - if (isValid) { - std::vector<std::string> splittedServiceName = split(serviceName, '.'); - - for (auto serviceNameElementIt = splittedServiceName.begin(); - serviceNameElementIt != splittedServiceName.end() && isValid; - ++serviceNameElementIt) { - isValid &= containsOnlyAlphanumericCharacters(*serviceNameElementIt); - } - } - - return isValid; -} - -inline bool isValidInstanceId(const std::string& instanceId) { - //Validation rules for ServiceName and InstanceID are equivalent - return isValidServiceName(instanceId); -} - -inline bool isValidCommonApiAddress(const std::string& commonApiAddress) { - std::vector<std::string> splittedAddress = split(commonApiAddress, ':'); - if (splittedAddress.size() != 3) { - return false; - } - return isValidDomainName(splittedAddress[0]) && isValidServiceName(splittedAddress[1]) && isValidInstanceId(splittedAddress[2]); -} - - -inline std::string getCurrentBinaryFileFQN() { - char fqnOfBinary[FILENAME_MAX]; - char pathToProcessImage[FILENAME_MAX]; - - sprintf(pathToProcessImage, "/proc/%d/exe", getpid()); - const ssize_t lengthOfFqn = readlink(pathToProcessImage, fqnOfBinary, sizeof(fqnOfBinary) - 1); - - if (lengthOfFqn != -1) { - fqnOfBinary[lengthOfFqn] = '\0'; - return std::string(std::move(fqnOfBinary)); - } else { - return std::string(""); - } -} - //In gcc 4.4.1, the enumeration "std::future_status" is defined, but the return values of some functions //are bool where the same functions in gcc 4.6. return a value from this enum. This template is a way //to ensure compatibility for this issue. @@ -111,7 +33,7 @@ inline bool checkReady<std::future_status>(std::future_status& returnedValue) { return returnedValue == std::future_status::ready; } -} -} +} //namespace DBus +} //namespace CommonAPI #endif /* DBUSUTILS_H_ */ diff --git a/src/test/DBusAddressTranslatorTest.cpp b/src/test/DBusAddressTranslatorTest.cpp index bafe79f..ef5d828 100644 --- a/src/test/DBusAddressTranslatorTest.cpp +++ b/src/test/DBusAddressTranslatorTest.cpp @@ -27,7 +27,7 @@ #include "commonapi/tests/TestInterfaceStubDefault.h" #include "commonapi/tests/TestInterfaceDBusStubAdapter.h" -#include "fakeLegacyService/fake/legacy/service/LegacyInterfaceProxy.h" +#include <fake/legacy/service/LegacyInterfaceProxy.h> static const std::vector<std::string> commonApiAddresses = { @@ -108,7 +108,7 @@ public: } virtual void SetUp() { - configFileName_ = CommonAPI::DBus::getCurrentBinaryFileFQN(); + configFileName_ = CommonAPI::getCurrentBinaryFileFQN(); configFileName_ += CommonAPI::DBus::DBUS_CONFIG_SUFFIX; std::ofstream configFile(configFileName_); ASSERT_TRUE(configFile.is_open()); diff --git a/src/test/DBusCommunicationTest.cpp b/src/test/DBusCommunicationTest.cpp index bc8af66..fe4cb8c 100644 --- a/src/test/DBusCommunicationTest.cpp +++ b/src/test/DBusCommunicationTest.cpp @@ -85,14 +85,19 @@ class DBusCommunicationTest: public ::testing::Test { std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher_; static const std::string serviceAddress_; + static const std::string serviceAddress2_; + static const std::string serviceAddress3_; + static const std::string serviceAddress4_; static const std::string nonstandardAddress_; }; const std::string DBusCommunicationTest::serviceAddress_ = "local:CommonAPI.DBus.tests.DBusProxyTestInterface:CommonAPI.DBus.tests.DBusProxyTestService"; +const std::string DBusCommunicationTest::serviceAddress2_ = "local:CommonAPI.DBus.tests.DBusProxyTestInterface:CommonAPI.DBus.tests.DBusProxyTestService2"; +const std::string DBusCommunicationTest::serviceAddress3_ = "local:CommonAPI.DBus.tests.DBusProxyTestInterface:CommonAPI.DBus.tests.DBusProxyTestService3"; +const std::string DBusCommunicationTest::serviceAddress4_ = "local:CommonAPI.DBus.tests.DBusProxyTestInterface:CommonAPI.DBus.tests.DBusProxyTestService4"; const std::string DBusCommunicationTest::nonstandardAddress_ = "local:non.standard.ServiceName:non.standard.participand.ID"; - TEST_F(DBusCommunicationTest, RemoteMethodCallSucceeds) { auto defaultTestProxy = proxyFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(serviceAddress_); ASSERT_TRUE((bool)defaultTestProxy); @@ -122,6 +127,57 @@ TEST_F(DBusCommunicationTest, RemoteMethodCallSucceeds) { } +TEST_F(DBusCommunicationTest, SameStubCanBeRegisteredSeveralTimes) { + auto defaultTestProxy = proxyFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(serviceAddress_); + auto defaultTestProxy2 = proxyFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(serviceAddress2_); + auto defaultTestProxy3 = proxyFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(serviceAddress3_); + ASSERT_TRUE((bool)defaultTestProxy); + ASSERT_TRUE((bool)defaultTestProxy2); + ASSERT_TRUE((bool)defaultTestProxy3); + + auto stub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>(); + + bool serviceRegistered = servicePublisher_->registerService(stub, serviceAddress_, stubFactory_); + bool serviceRegistered2 = servicePublisher_->registerService(stub, serviceAddress2_, stubFactory_); + bool serviceRegistered3 = servicePublisher_->registerService(stub, serviceAddress3_, stubFactory_); + for (unsigned int i = 0; (!serviceRegistered || !serviceRegistered2 || !serviceRegistered3) && i < 100; ++i) { + if (!serviceRegistered) { + serviceRegistered = servicePublisher_->registerService(stub, serviceAddress_, stubFactory_); + } + if (!serviceRegistered2) { + serviceRegistered2 = servicePublisher_->registerService(stub, serviceAddress2_, stubFactory_); + } + if (!serviceRegistered3) { + serviceRegistered3 = servicePublisher_->registerService(stub, serviceAddress3_, stubFactory_); + } + usleep(10000); + } + ASSERT_TRUE(serviceRegistered); + ASSERT_TRUE(serviceRegistered2); + ASSERT_TRUE(serviceRegistered3); + + for(unsigned int i = 0; (!defaultTestProxy->isAvailable() || !defaultTestProxy2->isAvailable() || !defaultTestProxy3->isAvailable()) && i < 100; ++i) { + usleep(10000); + } + ASSERT_TRUE(defaultTestProxy->isAvailable()); + ASSERT_TRUE(defaultTestProxy2->isAvailable()); + ASSERT_TRUE(defaultTestProxy3->isAvailable()); + + uint32_t v1 = 5; + std::string v2 = "Ciao ;)"; + CommonAPI::CallStatus stat, stat2, stat3; + defaultTestProxy->testVoidPredefinedTypeMethod(v1, v2, stat); + defaultTestProxy2->testVoidPredefinedTypeMethod(v1, v2, stat2); + defaultTestProxy3->testVoidPredefinedTypeMethod(v1, v2, stat3); + + EXPECT_EQ(stat, CommonAPI::CallStatus::SUCCESS); + EXPECT_EQ(stat2, CommonAPI::CallStatus::SUCCESS); + EXPECT_EQ(stat3, CommonAPI::CallStatus::SUCCESS); + + servicePublisher_->unregisterService(serviceAddress_); +} + + TEST_F(DBusCommunicationTest, RemoteMethodCallWithNonstandardAddressSucceeds) { auto defaultTestProxy = proxyFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(nonstandardAddress_); ASSERT_TRUE((bool)defaultTestProxy); @@ -150,6 +206,37 @@ TEST_F(DBusCommunicationTest, RemoteMethodCallWithNonstandardAddressSucceeds) { } +TEST_F(DBusCommunicationTest, RemoteMethodCallHeavyLoad) { + auto defaultTestProxy = proxyFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(serviceAddress4_); + ASSERT_TRUE((bool)defaultTestProxy); + + auto stub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>(); + + bool serviceRegistered = servicePublisher_->registerService(stub, serviceAddress4_, stubFactory_); + for (unsigned int i = 0; !serviceRegistered && i < 100; ++i) { + serviceRegistered = servicePublisher_->registerService(stub, serviceAddress4_, stubFactory_); + usleep(10000); + } + ASSERT_TRUE(serviceRegistered); + + for (unsigned int i = 0; !defaultTestProxy->isAvailable() && i < 100; ++i) { + usleep(10000); + } + ASSERT_TRUE(defaultTestProxy->isAvailable()); + + uint32_t v1 = 5; + std::string v2 = "Ciao ;)"; + CommonAPI::CallStatus stat; + + for (uint32_t i = 0; i < 1000; i++) { + defaultTestProxy->testVoidPredefinedTypeMethod(v1, v2, stat); + EXPECT_EQ(stat, CommonAPI::CallStatus::SUCCESS); + } + + servicePublisher_->unregisterService(serviceAddress4_); +} + + //XXX This test case requires CommonAPI::DBus::DBusConnection::suspendDispatching and ...::resumeDispatching to be public! //static const std::string commonApiAddress = "local:CommonAPI.DBus.tests.DBusProxyTestInterface:CommonAPI.DBus.tests.DBusProxyTestService"; diff --git a/src/test/DBusConnectionTest.cpp b/src/test/DBusConnectionTest.cpp index b791cf1..ad51f38 100644 --- a/src/test/DBusConnectionTest.cpp +++ b/src/test/DBusConnectionTest.cpp @@ -13,208 +13,204 @@ #include <cstring> -//XXX This test illustrates a libdbus error. -//bool replyArrived; -// -//class LibdbusTest: public ::testing::Test { -// protected: -// virtual void SetUp() { -// } -// -// virtual void TearDown() { -// } -//}; -// -// -//::DBusHandlerResult onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection, -// ::DBusMessage* libdbusMessage, -// void* userData) { -// return ::DBusHandlerResult::DBUS_HANDLER_RESULT_HANDLED; -//} -// -//DBusObjectPathVTable libdbusObjectPathVTable = { -// NULL, -// &onLibdbusObjectPathMessageThunk -//}; -// -//::DBusConnection* createConnection() { -// const ::DBusBusType libdbusType = ::DBusBusType::DBUS_BUS_SESSION; -// ::DBusConnection* libdbusConnection = dbus_bus_get_private(libdbusType, NULL); -// dbus_connection_ref(libdbusConnection); -// dbus_connection_set_exit_on_disconnect(libdbusConnection, false); -// -// return libdbusConnection; -//} -// -//static void onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void *userData) { -// replyArrived = true; -// ::DBusMessage* libdbusMessage = dbus_pending_call_steal_reply(libdbusPendingCall); -// ASSERT_TRUE(libdbusMessage); -// dbus_pending_call_unref(libdbusPendingCall); -//} -// -//TEST_F(LibdbusTest, NonreplyingLibdbusConnectionsAreHandled) { -// const char* problemServiceName = "problem.service"; -// replyArrived = false; -// bool running = true; -// -// dbus_threads_init_default(); -// -// ::DBusConnection* serviceConnection = createConnection(); -// ::DBusConnection* clientConnection = createConnection(); -// -// -// dbus_bus_request_name(serviceConnection, -// problemServiceName, -// DBUS_NAME_FLAG_DO_NOT_QUEUE, -// NULL); -// -// dbus_connection_try_register_object_path(serviceConnection, -// "/", -// &libdbusObjectPathVTable, -// NULL, -// NULL); -// -// std::thread([&, this] { -// while(running) { -// dbus_connection_read_write_dispatch(serviceConnection, 10); -// } -// }).detach(); -// -// usleep(100000); -// -// ::DBusMessage* message = dbus_message_new_method_call(problemServiceName, "/", NULL, "someMethod"); -// -// ::DBusPendingCall* libdbusPendingCall; -// -// dbus_connection_send_with_reply( -// clientConnection, -// message, -// &libdbusPendingCall, -// 3000); -// -// dbus_pending_call_set_notify( -// libdbusPendingCall, -// onLibdbusPendingCallNotifyThunk, -// NULL, -// NULL); -// -// //100*50 = 5000 (ms) ==> 3 seconds timeout pending call *should* have arrived by now. -// for (unsigned int i = 0; i < 100 && (!replyArrived); i++) { -// dbus_connection_read_write_dispatch(clientConnection, 50); -// } -// -// EXPECT_TRUE(replyArrived); -// -// running = false; -// -// usleep(100000); -// -// dbus_connection_close(serviceConnection); -// dbus_connection_unref(serviceConnection); -// dbus_connection_close(clientConnection); -// dbus_connection_unref(clientConnection); -//} +bool replyArrived; + +class LibdbusTest: public ::testing::Test { + protected: + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + + +::DBusHandlerResult onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection, + ::DBusMessage* libdbusMessage, + void* userData) { + return ::DBusHandlerResult::DBUS_HANDLER_RESULT_HANDLED; +} + +DBusObjectPathVTable libdbusObjectPathVTable = { + NULL, + &onLibdbusObjectPathMessageThunk +}; + +::DBusConnection* createConnection() { + const ::DBusBusType libdbusType = ::DBusBusType::DBUS_BUS_SESSION; + ::DBusConnection* libdbusConnection = dbus_bus_get_private(libdbusType, NULL); + dbus_connection_ref(libdbusConnection); + dbus_connection_set_exit_on_disconnect(libdbusConnection, false); + + return libdbusConnection; +} + +static void onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void *userData) { + replyArrived = true; + ::DBusMessage* libdbusMessage = dbus_pending_call_steal_reply(libdbusPendingCall); + ASSERT_TRUE(libdbusMessage); + dbus_pending_call_unref(libdbusPendingCall); +} + +TEST_F(LibdbusTest, DISABLED_NonreplyingLibdbusConnectionsAreHandled) { + const char problemServiceName[] = "problem.service"; + replyArrived = false; + bool running = true; + + dbus_threads_init_default(); + + ::DBusConnection* serviceConnection = createConnection(); + ::DBusConnection* clientConnection = createConnection(); + + + dbus_bus_request_name(serviceConnection, + problemServiceName, + DBUS_NAME_FLAG_DO_NOT_QUEUE, + NULL); + + dbus_connection_try_register_object_path(serviceConnection, + "/", + &libdbusObjectPathVTable, + NULL, + NULL); + + std::thread([&, this] { + while(running) { + dbus_connection_read_write_dispatch(serviceConnection, 10); + } + }).detach(); + + usleep(100000); + + ::DBusMessage* message = dbus_message_new_method_call(problemServiceName, "/", NULL, "someMethod"); + + ::DBusPendingCall* libdbusPendingCall; + + dbus_connection_send_with_reply( + clientConnection, + message, + &libdbusPendingCall, + 3000); + + dbus_pending_call_set_notify( + libdbusPendingCall, + onLibdbusPendingCallNotifyThunk, + NULL, + NULL); + + //100*50 = 5000 (ms) ==> 3 seconds timeout pending call *should* have arrived by now. + for (unsigned int i = 0; i < 100 && (!replyArrived); i++) { + dbus_connection_read_write_dispatch(clientConnection, 50); + } + + EXPECT_TRUE(replyArrived); + + running = false; + + usleep(100000); + + dbus_connection_close(serviceConnection); + dbus_connection_unref(serviceConnection); + dbus_connection_close(clientConnection); + dbus_connection_unref(clientConnection); +} class DBusConnectionTest: public ::testing::Test { - protected: - virtual void SetUp() { +protected: + virtual void SetUp() { dbusConnection_ = CommonAPI::DBus::DBusConnection::getSessionBus(); - } + } - virtual void TearDown() { - } + virtual void TearDown() { + } - std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_; + std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_; }; - TEST_F(DBusConnectionTest, IsInitiallyDisconnected) { - ASSERT_FALSE(dbusConnection_->isConnected()); + ASSERT_FALSE(dbusConnection_->isConnected()); } TEST_F(DBusConnectionTest, ConnectAndDisconnectWork) { - ASSERT_TRUE(dbusConnection_->connect()); - ASSERT_TRUE(dbusConnection_->isConnected()); + ASSERT_TRUE(dbusConnection_->connect()); + ASSERT_TRUE(dbusConnection_->isConnected()); - dbusConnection_->disconnect(); - ASSERT_FALSE(dbusConnection_->isConnected()); + dbusConnection_->disconnect(); + ASSERT_FALSE(dbusConnection_->isConnected()); } TEST_F(DBusConnectionTest, ConnectionStatusEventWorks) { uint32_t connectionStatusEventCount = 0; CommonAPI::AvailabilityStatus connectionStatus = CommonAPI::AvailabilityStatus::UNKNOWN; - auto connectionStatusSubscription = dbusConnection_->getConnectionStatusEvent().subscribe(std::bind( - [&connectionStatusEventCount, &connectionStatus](CommonAPI::AvailabilityStatus availabilityStatus) { - ++connectionStatusEventCount; - connectionStatus = availabilityStatus; - }, - std::placeholders::_1)); - - ASSERT_FALSE(dbusConnection_->isConnected()); - ASSERT_EQ(connectionStatusEventCount, 0); - - uint32_t expectedEventCount = 0; - while (expectedEventCount < 10) { - ASSERT_TRUE(dbusConnection_->connect()); - ASSERT_TRUE(dbusConnection_->isConnected()); - usleep(20000); - ASSERT_EQ(connectionStatusEventCount, ++expectedEventCount); - ASSERT_EQ(connectionStatus, CommonAPI::AvailabilityStatus::AVAILABLE); - - dbusConnection_->disconnect(); - ASSERT_FALSE(dbusConnection_->isConnected()); + auto connectionStatusSubscription = dbusConnection_->getConnectionStatusEvent().subscribe(std::bind( + [&connectionStatusEventCount, &connectionStatus](CommonAPI::AvailabilityStatus availabilityStatus) { + ++connectionStatusEventCount; + connectionStatus = availabilityStatus; + }, + std::placeholders::_1)); + + ASSERT_FALSE(dbusConnection_->isConnected()); + ASSERT_EQ(connectionStatusEventCount, 0); + + uint32_t expectedEventCount = 0; + while (expectedEventCount < 10) { + ASSERT_TRUE(dbusConnection_->connect()); + ASSERT_TRUE(dbusConnection_->isConnected()); + usleep(20000); + ASSERT_EQ(connectionStatusEventCount, ++expectedEventCount); + ASSERT_EQ(connectionStatus, CommonAPI::AvailabilityStatus::AVAILABLE); + + dbusConnection_->disconnect(); + ASSERT_FALSE(dbusConnection_->isConnected()); usleep(20000); - ASSERT_EQ(connectionStatusEventCount, ++expectedEventCount); - ASSERT_EQ(connectionStatus, CommonAPI::AvailabilityStatus::NOT_AVAILABLE); - } + ASSERT_EQ(connectionStatusEventCount, ++expectedEventCount); + ASSERT_EQ(connectionStatus, CommonAPI::AvailabilityStatus::NOT_AVAILABLE); + } - dbusConnection_->getConnectionStatusEvent().unsubscribe(connectionStatusSubscription); - ASSERT_EQ(connectionStatusEventCount, expectedEventCount); + dbusConnection_->getConnectionStatusEvent().unsubscribe(connectionStatusSubscription); + ASSERT_EQ(connectionStatusEventCount, expectedEventCount); - ASSERT_TRUE(dbusConnection_->connect()); - ASSERT_TRUE(dbusConnection_->isConnected()); - ASSERT_EQ(connectionStatusEventCount, expectedEventCount); + ASSERT_TRUE(dbusConnection_->connect()); + ASSERT_TRUE(dbusConnection_->isConnected()); + ASSERT_EQ(connectionStatusEventCount, expectedEventCount); - dbusConnection_->disconnect(); - ASSERT_FALSE(dbusConnection_->isConnected()); - ASSERT_EQ(connectionStatusEventCount, expectedEventCount); + dbusConnection_->disconnect(); + ASSERT_FALSE(dbusConnection_->isConnected()); + ASSERT_EQ(connectionStatusEventCount, expectedEventCount); } TEST_F(DBusConnectionTest, SendingAsyncDBusMessagesWorks) { - const char* busName = "commonapi.dbus.test.TestInterfaceHandler"; - const char* objectPath = "/common/api/dbus/test/TestObject"; - const char* interfaceName = "commonapi.dbus.test.TestInterface"; - const char* methodName = "TestMethod"; + const char busName[] = "commonapi.dbus.test.TestInterfaceHandler"; + const char objectPath[] = "/common/api/dbus/test/TestObject"; + const char interfaceName[] = "commonapi.dbus.test.TestInterface"; + const char methodName[] = "TestMethod"; - auto interfaceHandlerDBusConnection = CommonAPI::DBus::DBusConnection::getSessionBus(); + auto interfaceHandlerDBusConnection = CommonAPI::DBus::DBusConnection::getSessionBus(); - ASSERT_TRUE(interfaceHandlerDBusConnection->connect()); - ASSERT_TRUE(interfaceHandlerDBusConnection->requestServiceNameAndBlock(busName)); + ASSERT_TRUE(interfaceHandlerDBusConnection->connect()); + ASSERT_TRUE(interfaceHandlerDBusConnection->requestServiceNameAndBlock(busName)); uint32_t serviceHandlerDBusMessageCount = 0; uint32_t clientReplyHandlerDBusMessageCount = 0; - - - interfaceHandlerDBusConnection->setObjectPathMessageHandler( + interfaceHandlerDBusConnection->setObjectPathMessageHandler( [&serviceHandlerDBusMessageCount, &interfaceHandlerDBusConnection] (CommonAPI::DBus::DBusMessage dbusMessage) -> bool { ++serviceHandlerDBusMessageCount; CommonAPI::DBus::DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(""); interfaceHandlerDBusConnection->sendDBusMessage(dbusMessageReply); return true; } - ); + ); - interfaceHandlerDBusConnection->registerObjectPath(objectPath); + interfaceHandlerDBusConnection->registerObjectPath(objectPath); - ASSERT_TRUE(dbusConnection_->connect()); + ASSERT_TRUE(dbusConnection_->connect()); - CommonAPI::DBus::DBusMessage dbusReplyMessage; + CommonAPI::DBus::DBusMessage dbusReplyMessage; - for (uint32_t expectedDBusMessageCount = 1; expectedDBusMessageCount <= 10; expectedDBusMessageCount++) { + for (uint32_t expectedDBusMessageCount = 1; expectedDBusMessageCount <= 10; expectedDBusMessageCount++) { CommonAPI::DBus::DBusMessage dbusMessageCall = CommonAPI::DBus::DBusMessage::createMethodCall( busName, objectPath, @@ -222,7 +218,6 @@ TEST_F(DBusConnectionTest, SendingAsyncDBusMessagesWorks) { methodName, ""); - CommonAPI::DBus::DBusOutputStream dbusOutputStream(dbusMessageCall); interfaceHandlerDBusConnection->sendDBusMessageWithReplyAsync( @@ -232,167 +227,166 @@ TEST_F(DBusConnectionTest, SendingAsyncDBusMessagesWorks) { ASSERT_EQ(CommonAPI::CallStatus::SUCCESS, status); ++clientReplyHandlerDBusMessageCount; }) - ); + ); + + for (int i = 0; i < 10 && serviceHandlerDBusMessageCount < expectedDBusMessageCount; i++) { + interfaceHandlerDBusConnection->readWriteDispatch(100); + } + + ASSERT_EQ(serviceHandlerDBusMessageCount, expectedDBusMessageCount); + + for (int i = 0; i < 10 && clientReplyHandlerDBusMessageCount < expectedDBusMessageCount; i++) { + dbusConnection_->readWriteDispatch(100); + } - for (int i = 0; i < 10 && serviceHandlerDBusMessageCount < expectedDBusMessageCount; i++) { - interfaceHandlerDBusConnection->readWriteDispatch(100); - } + ASSERT_EQ(clientReplyHandlerDBusMessageCount, expectedDBusMessageCount); + } - ASSERT_EQ(serviceHandlerDBusMessageCount, expectedDBusMessageCount); + dbusConnection_->disconnect(); - for (int i = 0; i < 10 && clientReplyHandlerDBusMessageCount < expectedDBusMessageCount; i++) { - dbusConnection_->readWriteDispatch(100); - } + interfaceHandlerDBusConnection->unregisterObjectPath(objectPath); - ASSERT_EQ(clientReplyHandlerDBusMessageCount, expectedDBusMessageCount); - } + ASSERT_TRUE(interfaceHandlerDBusConnection->releaseServiceName(busName)); + interfaceHandlerDBusConnection->disconnect(); +} - dbusConnection_->disconnect(); +void dispatch(::DBusConnection* libdbusConnection) { + dbus_bool_t success = TRUE; + while (success) { + success = dbus_connection_read_write_dispatch(libdbusConnection, 1); + } +} - interfaceHandlerDBusConnection->unregisterObjectPath(objectPath); +std::promise<bool> promise; +std::future<bool> future = promise.get_future(); - ASSERT_TRUE(interfaceHandlerDBusConnection->releaseServiceName(busName)); - interfaceHandlerDBusConnection->disconnect(); +void notifyThunk(DBusPendingCall*, void* data) { + ::DBusConnection* libdbusConnection = reinterpret_cast<DBusConnection*>(data); + dbus_connection_close(libdbusConnection); + dbus_connection_unref(libdbusConnection); + promise.set_value(true); } +TEST_F(DBusConnectionTest, DISABLED_LibdbusConnectionsMayCommitSuicide) { + const ::DBusBusType libdbusType = ::DBusBusType::DBUS_BUS_SESSION; + ::DBusError libdbusError; + dbus_error_init(&libdbusError); + ::DBusConnection* libdbusConnection = dbus_bus_get_private(libdbusType, &libdbusError); + + assert(libdbusConnection); + dbus_connection_set_exit_on_disconnect(libdbusConnection, false); + + auto dispatchThread = std::thread(&dispatch, libdbusConnection); + + ::DBusMessage* libdbusMessageCall = dbus_message_new_method_call( + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "ListNames"); -//void dispatch(::DBusConnection* libdbusConnection) { -// dbus_bool_t success = TRUE; -// while(success) { -// success = dbus_connection_read_write_dispatch(libdbusConnection, 1); -// } -//} -// -//std::promise<bool> promise; -//std::future<bool> future = promise.get_future(); -// -//void notifyThunk(DBusPendingCall*, void* data) { -// ::DBusConnection* libdbusConnection = reinterpret_cast<DBusConnection*>(data); -// dbus_connection_close(libdbusConnection); -// dbus_connection_unref(libdbusConnection); -// promise.set_value(true); -//} -// -//TEST_F(DBusConnectionTest, LibdbusConnectionsMayCommitSuicide) { -// const ::DBusBusType libdbusType = ::DBusBusType::DBUS_BUS_SESSION; -// ::DBusError libdbusError; -// dbus_error_init(&libdbusError); -// ::DBusConnection* libdbusConnection = dbus_bus_get_private(libdbusType, &libdbusError); -// -// assert(libdbusConnection); -// dbus_connection_set_exit_on_disconnect(libdbusConnection, false); -// -// auto dispatchThread = std::thread(&dispatch, libdbusConnection); -// -// ::DBusMessage* libdbusMessageCall = dbus_message_new_method_call( -// "org.freedesktop.DBus", -// "/org/freedesktop/DBus", -// "org.freedesktop.DBus", -// "ListNames"); -// -// dbus_message_set_signature(libdbusMessageCall, ""); -// -// DBusPendingCall* libdbusPendingCall; -// dbus_bool_t libdbusSuccess; -// -// dbus_connection_send_with_reply( -// libdbusConnection, -// libdbusMessageCall, -// &libdbusPendingCall, -// 500); -// -// dbus_pending_call_set_notify( -// libdbusPendingCall, -// notifyThunk, -// libdbusConnection, -// NULL); -// -// ASSERT_EQ(true, future.get()); -// dispatchThread.join(); -//} -// -// -//std::promise<bool> promise2; -//std::future<bool> future2 = promise2.get_future(); -//std::promise<bool> promise3; -//std::future<bool> future3 = promise3.get_future(); -// -//void noPartnerCallback(DBusPendingCall*, void* data) { -// ::DBusConnection* libdbusConnection = reinterpret_cast<DBusConnection*>(data); -// dbus_connection_close(libdbusConnection); -// dbus_connection_unref(libdbusConnection); -// promise2.set_value(true); -//} -// -//void noPartnerCleanup(void* data) { -// std::cout << "Cleanup" << std::endl; -// promise3.set_value(true); -//} -// -//TEST_F(DBusConnectionTest, TimeoutForNonexistingServices) { -// const ::DBusBusType libdbusType = ::DBusBusType::DBUS_BUS_SESSION; -// ::DBusError libdbusError; -// dbus_error_init(&libdbusError); -// ::DBusConnection* libdbusConnection = dbus_bus_get_private(libdbusType, &libdbusError); -// -// assert(libdbusConnection); -// dbus_connection_set_exit_on_disconnect(libdbusConnection, false); -// -// auto dispatchThread = std::thread(&dispatch, libdbusConnection); -// -// ::DBusMessage* libdbusMessageCall = dbus_message_new_method_call( -// "some.connection.somewhere", -// "/some/non/existing/object", -// "some.interface.somewhere.but.same.place", -// "NoReasonableMethod"); -// -// dbus_message_set_signature(libdbusMessageCall, ""); -// -// bool hasHappened = false; -// -// DBusPendingCall* libdbusPendingCall; -// dbus_bool_t libdbusSuccess; -// -// dbus_connection_send_with_reply( -// libdbusConnection, -// libdbusMessageCall, -// &libdbusPendingCall, -// 5000); -// -// dbus_pending_call_set_notify( -// libdbusPendingCall, -// noPartnerCallback, -// libdbusConnection, -// noPartnerCleanup); -// -// ASSERT_EQ(true, future2.get()); -// dispatchThread.join(); -//} -// -//TEST_F(DBusConnectionTest, ConnectionsMayCommitAsynchronousSuicide) { -// CommonAPI::DBus::DBusConnection* dbusConnection_ = new CommonAPI::DBus::DBusConnection(CommonAPI::DBus::DBusConnection::BusType::SESSION); -// dbusConnection_->connect(); -// -// auto dbusMessageCall = CommonAPI::DBus::DBusMessage::createMethodCall( -// "org.freedesktop.DBus", -// "/org/freedesktop/DBus", -// "org.freedesktop.DBus", -// "ListNames", -// ""); -// -// bool hasHappened = false; -// -// auto future = dbusConnection_->sendDBusMessageWithReplyAsync(dbusMessageCall, CommonAPI::DBus::DBusProxyAsyncCallbackHandler<std::vector<std::string>>::create( -// [&] (const CommonAPI::CallStatus&, std::vector<std::string>) { -// hasHappened = true; -// delete dbusConnection_; -// } -// )); -// -// ASSERT_EQ(CommonAPI::CallStatus::SUCCESS, future.get()); -//} + dbus_message_set_signature(libdbusMessageCall, ""); + DBusPendingCall* libdbusPendingCall; + dbus_bool_t libdbusSuccess; + + dbus_connection_send_with_reply( + libdbusConnection, + libdbusMessageCall, + &libdbusPendingCall, + 500); + + dbus_pending_call_set_notify( + libdbusPendingCall, + notifyThunk, + libdbusConnection, + NULL); + + ASSERT_EQ(true, future.get()); + dispatchThread.join(); +} +std::promise<bool> promise2; +std::future<bool> future2 = promise2.get_future(); +std::promise<bool> promise3; +std::future<bool> future3 = promise3.get_future(); + +void noPartnerCallback(DBusPendingCall*, void* data) { + ::DBusConnection* libdbusConnection = reinterpret_cast<DBusConnection*>(data); + dbus_connection_close(libdbusConnection); + dbus_connection_unref(libdbusConnection); + promise2.set_value(true); +} + +void noPartnerCleanup(void* data) { + std::cout << "Cleanup" << std::endl; + promise3.set_value(true); +} + +TEST_F(DBusConnectionTest, DISABLED_TimeoutForNonexistingServices) { + const ::DBusBusType libdbusType = ::DBusBusType::DBUS_BUS_SESSION; + ::DBusError libdbusError; + dbus_error_init(&libdbusError); + ::DBusConnection* libdbusConnection = dbus_bus_get_private(libdbusType, &libdbusError); + + assert(libdbusConnection); + dbus_connection_set_exit_on_disconnect(libdbusConnection, false); + + auto dispatchThread = std::thread(&dispatch, libdbusConnection); + + ::DBusMessage* libdbusMessageCall = dbus_message_new_method_call( + "some.connection.somewhere", + "/some/non/existing/object", + "some.interface.somewhere.but.same.place", + "NoReasonableMethod"); + + dbus_message_set_signature(libdbusMessageCall, ""); + + bool hasHappened = false; + + DBusPendingCall* libdbusPendingCall; + dbus_bool_t libdbusSuccess; + + dbus_connection_send_with_reply( + libdbusConnection, + libdbusMessageCall, + &libdbusPendingCall, + 5000); + + dbus_pending_call_set_notify( + libdbusPendingCall, + noPartnerCallback, + libdbusConnection, + noPartnerCleanup); + + ASSERT_EQ(true, future2.get()); + dispatchThread.join(); +} + +TEST_F(DBusConnectionTest, DISABLED_ConnectionsMayCommitAsynchronousSuicide) { + CommonAPI::DBus::DBusConnection* dbusConnection_ = new CommonAPI::DBus::DBusConnection( + CommonAPI::DBus::BusType::SESSION); + dbusConnection_->connect(); + + auto dbusMessageCall = CommonAPI::DBus::DBusMessage::createMethodCall( + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "ListNames", + ""); + + bool hasHappened = false; + + auto future = dbusConnection_->sendDBusMessageWithReplyAsync( + dbusMessageCall, + CommonAPI::DBus::DBusProxyAsyncCallbackHandler<std::vector<std::string>>::create( + [&] (const CommonAPI::CallStatus&, std::vector<std::string>) { + hasHappened = true; + delete dbusConnection_; + } + )); + + ASSERT_EQ(CommonAPI::CallStatus::SUCCESS, future.get()); +} int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/src/test/DBusFactoryTest.cpp b/src/test/DBusFactoryTest.cpp index bd8b1e6..1131fb7 100644 --- a/src/test/DBusFactoryTest.cpp +++ b/src/test/DBusFactoryTest.cpp @@ -10,6 +10,7 @@ #include <cassert> #include <cstdint> #include <iostream> +#include <fstream> #include <functional> #include <memory> #include <stdint.h> @@ -52,7 +53,7 @@ class DBusProxyFactoryTest: public ::testing::Test { CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast<CommonAPI::DBus::DBusRuntime*>(&(*runtime_)); ASSERT_TRUE(dbusRuntime != NULL); - configFileName_ = CommonAPI::DBus::getCurrentBinaryFileFQN(); + configFileName_ = CommonAPI::getCurrentBinaryFileFQN(); configFileName_ += CommonAPI::DBus::DBUS_CONFIG_SUFFIX; std::ofstream configFile(configFileName_); ASSERT_TRUE(configFile.is_open()); diff --git a/src/test/DBusMainLoopIntegrationTest.cpp b/src/test/DBusMainLoopIntegrationTest.cpp index f945e64..f3b2720 100644 --- a/src/test/DBusMainLoopIntegrationTest.cpp +++ b/src/test/DBusMainLoopIntegrationTest.cpp @@ -140,8 +140,9 @@ TEST_F(DBusBasicMainLoopTest, PrioritiesAreHandledCorrectlyInDemoMainloop) { mainLoop->doSingleIteration(CommonAPI::TIMEOUT_INFINITE); - std::string reference("ECABD"); - ASSERT_EQ(reference, result); + std::string reference1("ECABD"); + std::string reference2("ECBAD"); + ASSERT_TRUE(reference1 == result || reference2 == result); } diff --git a/src/test/DBusOutputStreamTest.cpp b/src/test/DBusOutputStreamTest.cpp index 34627d8..72cc6e9 100644 --- a/src/test/DBusOutputStreamTest.cpp +++ b/src/test/DBusOutputStreamTest.cpp @@ -15,541 +15,545 @@ #include "commonapi/tests/DerivedTypeCollection.h" - class OutputStreamTest: public ::testing::Test { protected: - size_t numOfElements; - CommonAPI::DBus::DBusMessage message; - const char* busName; - const char* objectPath; - const char* interfaceName; - const char* methodName; - - void SetUp() { - numOfElements = 10; - busName = "no.bus.here"; - objectPath = "/no/object/here"; - interfaceName = "no.interface.here"; - methodName = "noMethodHere"; - } - - void TearDown() { - } + size_t numOfElements; + CommonAPI::DBus::DBusMessage message; + const char* busName; + const char* objectPath; + const char* interfaceName; + const char* methodName; + + void SetUp() { + numOfElements = 10; + busName = "no.bus.here"; + objectPath = "/no/object/here"; + interfaceName = "no.interface.here"; + methodName = "noMethodHere"; + } + + void TearDown() { + } }; TEST_F(OutputStreamTest, CanBeConstructed) { - CommonAPI::DBus::DBusOutputStream outStream(message); + CommonAPI::DBus::DBusOutputStream outStream(message); } TEST_F(OutputStreamTest, WritesBytes) { - const char* signature = "yyyyyyyyyy"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - outStream.reserveMemory(numOfElements); - uint8_t val1 = 0xff; - uint8_t val2 = 0x00; - for (unsigned int i = 0; i < numOfElements; i += 2) { - outStream << val1; - outStream << val2; - } - outStream.flush(); - - EXPECT_EQ(numOfElements, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - - uint8_t verifyVal1; - uint8_t verifyVal2; - for (unsigned int i = 0; i < numOfElements; i += 2) { - inStream >> verifyVal1; - EXPECT_EQ(val1, verifyVal1); + const char signature[] = "yyyyyyyyyy"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements); + uint8_t val1 = 0xff; + uint8_t val2 = 0x00; + for (unsigned int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); - inStream >> verifyVal2; - EXPECT_EQ(val2, verifyVal2); - } + EXPECT_EQ(numOfElements, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + uint8_t verifyVal1; + uint8_t verifyVal2; + for (unsigned int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } } TEST_F(OutputStreamTest, WritesBools) { - const char* signature = "bbbbbbbbbb"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - outStream.reserveMemory(numOfElements * 4); - bool val1 = TRUE; - bool val2 = FALSE; - for (unsigned int i = 0; i < numOfElements; i += 2) { - outStream << val1; - outStream << val2; - } - outStream.flush(); - - EXPECT_EQ(numOfElements*4, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - - bool verifyVal1; - bool verifyVal2; - for (unsigned int i = 0; i < numOfElements; i += 2) { - inStream >> verifyVal1; - EXPECT_EQ(val1, verifyVal1); + const char signature[] = "bbbbbbbbbb"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 4); + bool val1 = TRUE; + bool val2 = FALSE; + for (unsigned int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); - inStream >> verifyVal2; - EXPECT_EQ(val2, verifyVal2); - } + EXPECT_EQ(numOfElements*4, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + bool verifyVal1; + bool verifyVal2; + for (unsigned int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } } TEST_F(OutputStreamTest, WritesUInt16) { - const char* signature = "qqqqqqqqqq"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - outStream.reserveMemory(numOfElements * 2); - uint16_t val1 = 0x0000; - uint16_t val2 = 0xffff; - for (unsigned int i = 0; i < numOfElements; i += 2) { - outStream << val1; - outStream << val2; - } - outStream.flush(); - - EXPECT_EQ(numOfElements*2, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - - uint16_t verifyVal1; - uint16_t verifyVal2; - for (unsigned int i = 0; i < numOfElements; i += 2) { - inStream >> verifyVal1; - EXPECT_EQ(val1, verifyVal1); + const char signature[] = "qqqqqqqqqq"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 2); + uint16_t val1 = 0x0000; + uint16_t val2 = 0xffff; + for (unsigned int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); - inStream >> verifyVal2; - EXPECT_EQ(val2, verifyVal2); - } + EXPECT_EQ(numOfElements*2, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + uint16_t verifyVal1; + uint16_t verifyVal2; + for (unsigned int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } } TEST_F(OutputStreamTest, WritesInt16) { - const char* signature = "nnnnnnnnnn"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - outStream.reserveMemory(numOfElements * 2); - int16_t val1 = 0x7fff; - int16_t val2 = 0xffff; - for (unsigned int i = 0; i < numOfElements; i += 2) { - outStream << val1; - outStream << val2; - } - outStream.flush(); - - EXPECT_EQ(numOfElements*2, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - - int16_t verifyVal1; - int16_t verifyVal2; - for (unsigned int i = 0; i < numOfElements; i += 2) { - inStream >> verifyVal1; - EXPECT_EQ(val1, verifyVal1); + const char signature[] = "nnnnnnnnnn"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 2); + int16_t val1 = 0x7fff; + int16_t val2 = 0xffff; + for (unsigned int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); - inStream >> verifyVal2; - EXPECT_EQ(val2, verifyVal2); - } + EXPECT_EQ(numOfElements*2, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + int16_t verifyVal1; + int16_t verifyVal2; + for (unsigned int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } } TEST_F(OutputStreamTest, WritesUInt32) { - const char* signature = "uuuuuuuuuu"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - outStream.reserveMemory(numOfElements * 4); - uint32_t val1 = 0x00000000; - uint32_t val2 = 0xffffffff; - for (unsigned int i = 0; i < numOfElements; i += 2) { - outStream << val1; - outStream << val2; - } - outStream.flush(); - - EXPECT_EQ(numOfElements*4, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - - uint32_t verifyVal1; - uint32_t verifyVal2; - for (unsigned int i = 0; i < numOfElements; i += 2) { - inStream >> verifyVal1; - EXPECT_EQ(val1, verifyVal1); + const char signature[] = "uuuuuuuuuu"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 4); + uint32_t val1 = 0x00000000; + uint32_t val2 = 0xffffffff; + for (unsigned int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); - inStream >> verifyVal2; - EXPECT_EQ(val2, verifyVal2); - } + EXPECT_EQ(numOfElements*4, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + uint32_t verifyVal1; + uint32_t verifyVal2; + for (unsigned int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } } TEST_F(OutputStreamTest, WritesInt32) { - const char* signature = "iiiiiiiiii"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - outStream.reserveMemory(numOfElements * 4); - int32_t val1 = 0x7fffffff; - int32_t val2 = 0xffffffff; - for (unsigned int i = 0; i < numOfElements; i += 2) { - outStream << val1; - outStream << val2; - } - outStream.flush(); - - EXPECT_EQ(numOfElements*4, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - - int32_t verifyVal1; - int32_t verifyVal2; - for (unsigned int i = 0; i < numOfElements; i += 2) { - inStream >> verifyVal1; - EXPECT_EQ(val1, verifyVal1); + const char signature[] = "iiiiiiiiii"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 4); + int32_t val1 = 0x7fffffff; + int32_t val2 = 0xffffffff; + for (unsigned int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); - inStream >> verifyVal2; - EXPECT_EQ(val2, verifyVal2); - } + EXPECT_EQ(numOfElements*4, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + int32_t verifyVal1; + int32_t verifyVal2; + for (unsigned int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } } TEST_F(OutputStreamTest, WritesUInt64) { - const char* signature = "tttttttttt"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - outStream.reserveMemory(numOfElements * 8); - uint64_t val1 = 0x0000000000000000; - uint64_t val2 = 0xffffffffffffffff; - for (unsigned int i = 0; i < numOfElements; i += 2) { - outStream << val1; - outStream << val2; - } - outStream.flush(); - - EXPECT_EQ(numOfElements*8, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - - uint64_t verifyVal1; - uint64_t verifyVal2; - for (unsigned int i = 0; i < numOfElements; i += 2) { - inStream >> verifyVal1; - EXPECT_EQ(val1, verifyVal1); + const char signature[] = "tttttttttt"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 8); + uint64_t val1 = 0x0000000000000000; + uint64_t val2 = 0xffffffffffffffff; + for (unsigned int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); - inStream >> verifyVal2; - EXPECT_EQ(val2, verifyVal2); - } + EXPECT_EQ(numOfElements*8, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + uint64_t verifyVal1; + uint64_t verifyVal2; + for (unsigned int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } } TEST_F(OutputStreamTest, WritesInt64) { - const char* signature = "xxxxxxxxxx"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - outStream.reserveMemory(numOfElements * 8); - int64_t val1 = 0x7fffffffffffffff; - int64_t val2 = 0xffffffffffffffff; - for (unsigned int i = 0; i < numOfElements; i += 2) { - outStream << val1; - outStream << val2; - } - outStream.flush(); - - EXPECT_EQ(numOfElements*8, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - - int64_t verifyVal1; - int64_t verifyVal2; - for (unsigned int i = 0; i < numOfElements; i += 2) { - inStream >> verifyVal1; - EXPECT_EQ(val1, verifyVal1); + const char signature[] = "xxxxxxxxxx"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 8); + int64_t val1 = 0x7fffffffffffffff; + int64_t val2 = 0xffffffffffffffff; + for (unsigned int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); - inStream >> verifyVal2; - EXPECT_EQ(val2, verifyVal2); - } + EXPECT_EQ(numOfElements*8, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + int64_t verifyVal1; + int64_t verifyVal2; + for (unsigned int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } } TEST_F(OutputStreamTest, WritesDouble) { - const char* signature = "dddddddddd"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - outStream.reserveMemory(numOfElements * 8); - double val1 = 13.37; - double val2 = 3.414; - for (unsigned int i = 0; i < numOfElements; i += 2) { - outStream << val1; - outStream << val2; - } - outStream.flush(); - - EXPECT_EQ(numOfElements*8, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - - double verifyVal1; - double verifyVal2; - std::string verifySignature; - for (unsigned int i = 0; i < numOfElements; i += 2) { - inStream >> verifyVal1; - EXPECT_EQ(val1, verifyVal1); + const char signature[] = "dddddddddd"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + outStream.reserveMemory(numOfElements * 8); + double val1 = 13.37; + double val2 = 3.414; + for (unsigned int i = 0; i < numOfElements; i += 2) { + outStream << val1; + outStream << val2; + } + outStream.flush(); - inStream >> verifyVal2; - EXPECT_EQ(val2, verifyVal2); - } + EXPECT_EQ(numOfElements*8, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + double verifyVal1; + double verifyVal2; + std::string verifySignature; + for (unsigned int i = 0; i < numOfElements; i += 2) { + inStream >> verifyVal1; + EXPECT_EQ(val1, verifyVal1); + + inStream >> verifyVal2; + EXPECT_EQ(val2, verifyVal2); + } } TEST_F(OutputStreamTest, WritesStrings) { - const char* signature = "sss"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); + const char signature[] = "sss"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); - std::string val1 = "hai"; - std::string val2 = "ciao"; - std::string val3 = "salut"; + std::string val1 = "hai"; + std::string val2 = "ciao"; + std::string val3 = "salut"; - //sizes of the strings + terminating null-bytes (each 1 byte) + length-fields (each 4 bytes) - outStream.reserveMemory(val1.size() + val2.size() + val3.size() + 3 + 3 * 4); - outStream << val1 << val2 << val3; - outStream.flush(); + //sizes of the strings + terminating null-bytes (each 1 byte) + length-fields (each 4 bytes) + outStream.reserveMemory(val1.size() + val2.size() + val3.size() + 3 + 3 * 4); + outStream << val1 << val2 << val3; + outStream.flush(); - //Length fields + actual strings + terminating '\0's + 3(padding) - EXPECT_EQ(3*4 + 3 + 4 + 5 + 3 + 3, message.getBodyLength()); + //Length fields + actual strings + terminating '\0's + 3(padding) + EXPECT_EQ(3*4 + 3 + 4 + 5 + 3 + 3, message.getBodyLength()); - CommonAPI::DBus::DBusInputStream inStream(message); + CommonAPI::DBus::DBusInputStream inStream(message); - std::string verifyVal1; - std::string verifyVal2; - std::string verifyVal3; - std::string verifySignature; + std::string verifyVal1; + std::string verifyVal2; + std::string verifyVal3; + std::string verifySignature; - inStream >> verifyVal1; - inStream >> verifyVal2; - inStream >> verifyVal3; + inStream >> verifyVal1; + inStream >> verifyVal2; + inStream >> verifyVal3; - EXPECT_EQ(val1, verifyVal1); - EXPECT_EQ(val2, verifyVal2); - EXPECT_EQ(val3, verifyVal3); + EXPECT_EQ(val1, verifyVal1); + EXPECT_EQ(val2, verifyVal2); + EXPECT_EQ(val3, verifyVal3); } namespace bmw { namespace test { struct myStruct: CommonAPI::SerializableStruct { - ~myStruct(); + ~myStruct(); - uint32_t a; - int16_t b; - bool c; - std::string d; - double e; + uint32_t a; + int16_t b; + bool c; + std::string d; + double e; - virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream); - virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const; + virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream); + virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const; }; myStruct::~myStruct() { } void myStruct::readFromInputStream(CommonAPI::InputStream& inputMessageStream) { - inputMessageStream >> a >> b >> c >> d >> e; + inputMessageStream >> a >> b >> c >> d >> e; } void myStruct::writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const { - outputMessageStream << a << b << c << d << e; + outputMessageStream << a << b << c << d << e; } } //namespace test } //namespace bmw TEST_F(OutputStreamTest, WritesStructs) { - const char* signature = "(unbsd)"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); + const char signature[] = "(unbsd)"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); - bmw::test::myStruct testStruct; - testStruct.a = 15; - testStruct.b = -32; - testStruct.c = FALSE; - testStruct.d = "Hello all"; - testStruct.e = 3.414; + bmw::test::myStruct testStruct; + testStruct.a = 15; + testStruct.b = -32; + testStruct.c = FALSE; + testStruct.d = "Hello all"; + testStruct.e = 3.414; - // 40(byte length of struct) = 4(uint32_t) + 2(int16_t) + 2(padding) + 4(bool) + 4(strlength) - // + 9(string) + 1(terminating '\0' of string) + 6(padding) + 8 (double) - outStream.reserveMemory(40); - outStream << testStruct; - outStream.flush(); + // 40(byte length of struct) = 4(uint32_t) + 2(int16_t) + 2(padding) + 4(bool) + 4(strlength) + // + 9(string) + 1(terminating '\0' of string) + 6(padding) + 8 (double) + outStream.reserveMemory(40); + outStream << testStruct; + outStream.flush(); - EXPECT_EQ(40, message.getBodyLength()); + EXPECT_EQ(40, message.getBodyLength()); - CommonAPI::DBus::DBusInputStream inStream(message); - bmw::test::myStruct verifyStruct; - inStream >> verifyStruct; + CommonAPI::DBus::DBusInputStream inStream(message); + bmw::test::myStruct verifyStruct; + inStream >> verifyStruct; - EXPECT_EQ(testStruct.a, verifyStruct.a); - EXPECT_EQ(testStruct.b, verifyStruct.b); - EXPECT_EQ(testStruct.c, verifyStruct.c); - EXPECT_EQ(testStruct.d, verifyStruct.d); - EXPECT_EQ(testStruct.e, verifyStruct.e); + EXPECT_EQ(testStruct.a, verifyStruct.a); + EXPECT_EQ(testStruct.b, verifyStruct.b); + EXPECT_EQ(testStruct.c, verifyStruct.c); + EXPECT_EQ(testStruct.d, verifyStruct.d); + EXPECT_EQ(testStruct.e, verifyStruct.e); } TEST_F(OutputStreamTest, WritesArrays) { - const char* signature = "ai"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - std::vector<int32_t> testVector; - int32_t val1 = 0xffffffff; - int32_t val2 = 0x7fffffff; - for (unsigned int i = 0; i < numOfElements; i += 2) { - testVector.push_back(val1); - testVector.push_back(val2); - } - - outStream.reserveMemory(numOfElements * 4 + 4); - outStream << testVector; - outStream.flush(); - - EXPECT_EQ(numOfElements*4 + 4, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - std::vector<int32_t> verifyVector; - inStream >> verifyVector; - - int32_t res1; - int32_t res2; - for (unsigned int i = 0; i < numOfElements; i += 2) { - res1 = verifyVector[i]; - EXPECT_EQ(val1, res1); - res2 = verifyVector[i + 1]; - EXPECT_EQ(val2, res2); - } + const char signature[] = "ai"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + std::vector<int32_t> testVector; + int32_t val1 = 0xffffffff; + int32_t val2 = 0x7fffffff; + for (unsigned int i = 0; i < numOfElements; i += 2) { + testVector.push_back(val1); + testVector.push_back(val2); + } + + outStream.reserveMemory(numOfElements * 4 + 4); + outStream << testVector; + outStream.flush(); + + EXPECT_EQ(numOfElements*4 + 4, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + std::vector<int32_t> verifyVector; + inStream >> verifyVector; + + int32_t res1; + int32_t res2; + for (unsigned int i = 0; i < numOfElements; i += 2) { + res1 = verifyVector[i]; + EXPECT_EQ(val1, res1); + res2 = verifyVector[i + 1]; + EXPECT_EQ(val2, res2); + } } TEST_F(OutputStreamTest, WritesArraysOfStrings) { - const char* signature = "as"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - std::vector<std::string> testVector; - std::string val1 = "Hai"; - std::string val2 = "Ciao"; - for (unsigned int i = 0; i < numOfElements; i += 2) { - testVector.push_back(val1); - testVector.push_back(val2); - } - - // 101 = 4(lengthFieldOfArray) + - // 4*(4(lengthField1) + 4(string1 mit \0-byte) + 4(lengthField2) + 5(string2 mit \0-byte) + 3(paddingTo4)) + - // (4(lengthField1) + 4(string1 mit \0-byte) + 4(lengthField2) + 5(string2 mit \0-byte)) - size_t vectorLength = 101; - outStream.reserveMemory(vectorLength); - outStream << testVector; - outStream.flush(); - - EXPECT_EQ(vectorLength, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - std::vector<std::string> verifyVector; - inStream >> verifyVector; - - std::string res1; - std::string res2; - for (unsigned int i = 0; i < numOfElements; i += 2) { - res1 = verifyVector[i]; - EXPECT_EQ(val1, res1); - res2 = verifyVector[i + 1]; - EXPECT_EQ(val2, res2); - } + const char signature[] = "as"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + std::vector<std::string> testVector; + std::string val1 = "Hai"; + std::string val2 = "Ciao"; + for (unsigned int i = 0; i < numOfElements; i += 2) { + testVector.push_back(val1); + testVector.push_back(val2); + } + + // 101 = 4(lengthFieldOfArray) + + // 4*(4(lengthField1) + 4(string1 mit \0-byte) + 4(lengthField2) + 5(string2 mit \0-byte) + 3(paddingTo4)) + + // (4(lengthField1) + 4(string1 mit \0-byte) + 4(lengthField2) + 5(string2 mit \0-byte)) + size_t vectorLength = 101; + outStream.reserveMemory(vectorLength); + outStream << testVector; + outStream.flush(); + + EXPECT_EQ(vectorLength, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + std::vector<std::string> verifyVector; + inStream >> verifyVector; + + std::string res1; + std::string res2; + for (unsigned int i = 0; i < numOfElements; i += 2) { + res1 = verifyVector[i]; + EXPECT_EQ(val1, res1); + res2 = verifyVector[i + 1]; + EXPECT_EQ(val2, res2); + } } TEST_F(OutputStreamTest, WritesArraysInArrays) { - const char* signature = "aai"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - std::vector<std::vector<int32_t>> testVector; - int32_t val1 = 0xffffffff; - int32_t val2 = 0x7fffffff; - for (unsigned int i = 0; i < numOfElements; i++) { - std::vector<int32_t> inner; - for (unsigned int j = 0; j < numOfElements; j += 2) { - inner.push_back(val1); - inner.push_back(val2); + const char signature[] = "aai"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + std::vector<std::vector<int32_t>> testVector; + int32_t val1 = 0xffffffff; + int32_t val2 = 0x7fffffff; + for (unsigned int i = 0; i < numOfElements; i++) { + std::vector<int32_t> inner; + for (unsigned int j = 0; j < numOfElements; j += 2) { + inner.push_back(val1); + inner.push_back(val2); + } + testVector.push_back(inner); } - testVector.push_back(inner); - } - - outStream.reserveMemory(numOfElements * numOfElements * 4 + numOfElements * 4 + 4); - outStream << testVector; - outStream.flush(); - - EXPECT_EQ(numOfElements*numOfElements*4 + numOfElements*4 + 4, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - std::vector<std::vector<int32_t>> verifyVector; - inStream >> verifyVector; - - int32_t res1; - int32_t res2; - for (unsigned int i = 0; i < numOfElements; i++) { - std::vector<int32_t> innerVerify = verifyVector[i]; - for (unsigned int j = 0; j < numOfElements; j += 2) { - res1 = innerVerify[j]; - EXPECT_EQ(val1, res1); - res2 = innerVerify[j + 1]; - EXPECT_EQ(val2, res2); + + outStream.reserveMemory(numOfElements * numOfElements * 4 + numOfElements * 4 + 4); + outStream << testVector; + outStream.flush(); + + EXPECT_EQ(numOfElements*numOfElements*4 + numOfElements*4 + 4, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + std::vector<std::vector<int32_t>> verifyVector; + inStream >> verifyVector; + + int32_t res1; + int32_t res2; + for (unsigned int i = 0; i < numOfElements; i++) { + std::vector<int32_t> innerVerify = verifyVector[i]; + for (unsigned int j = 0; j < numOfElements; j += 2) { + res1 = innerVerify[j]; + EXPECT_EQ(val1, res1); + res2 = innerVerify[j + 1]; + EXPECT_EQ(val2, res2); + } } - } } typedef CommonAPI::Variant<int8_t, uint32_t, double, std::string> BasicTypeVariant; -TEST_F(OutputStreamTest, WritesBasicTypeVariants) { - numOfElements = 4; - const char* signature = "(yv)(yv)(yv)(yv)"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - int8_t fromInt8Value = 7; - uint32_t fromUInt32Value = 42; - double fromDoubleValue = 13.37; - std::string fromStringValue = "Hai :)"; - BasicTypeVariant int8Variant(fromInt8Value); - BasicTypeVariant uint32Variant(fromUInt32Value); - BasicTypeVariant doubleVariant(fromDoubleValue); - BasicTypeVariant stringVariant(fromStringValue); - - /* TODO: - testVector.push_back(inner); - - //4 * (1(byte) + 2(signature length + content)) + 1(int8_t) + 4(uint32_t) + 8(double) + - outStream.reserveMemory(numOfElements * numOfElements * 4 + numOfElements * 4 + 4); - outStream << testVector; - outStream.flush(); - - EXPECT_EQ(numOfElements*numOfElements*4 + numOfElements*4 + 4, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - std::vector<std::vector<int32_t>> verifyVector; - inStream >> verifyVector; - - int32_t res1; - int32_t res2; - for (int i = 0; i < numOfElements; i++) { - std::vector<int32_t> innerVerify = verifyVector[i]; - for (int j = 0; j < numOfElements; j += 2) { - res1 = innerVerify[j]; - EXPECT_EQ(val1, res1); - res2 = innerVerify[j + 1]; - EXPECT_EQ(val2, res2); - } - } - */ +TEST_F(OutputStreamTest, WritesArraysOfVariants) { + numOfElements = 4; + const char signature[] = "(yv)(yv)(yv)(yv)"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + int8_t fromInt8Value = 7; + uint32_t fromUInt32Value = 42; + double fromDoubleValue = 13.37; + std::string fromStringValue = "Hai :)"; + BasicTypeVariant referenceInt8Variant(fromInt8Value); + BasicTypeVariant referenceUint32Variant(fromUInt32Value); + BasicTypeVariant referenceDoubleVariant(fromDoubleValue); + BasicTypeVariant referenceStringVariant(fromStringValue); + + std::vector<BasicTypeVariant> testVector; + + testVector.push_back(referenceInt8Variant); + testVector.push_back(fromUInt32Value); + testVector.push_back(fromDoubleValue); + testVector.push_back(fromStringValue); + + // 4(length field) + 4(padding) + (1(variant type byte) + 3(signature length + content + terminating null) + 1(int8_t)) + // + 3(padding) + (1(variant type byte) + 3(signature length + content + terminating null) + 4(uint32_t)) + // + (1(variant type byte) + 3(signature length + content + terminating null) + 8(uint32_t)) + // + 4(padding) + (1(variant type byte) + 3(signature length + content + terminating null) + 4(string length field) + 7(string)) + // = 55 + outStream.reserveMemory(55); + outStream << testVector; + outStream.flush(); + + EXPECT_EQ(55, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + std::vector<BasicTypeVariant> verifyVector; + inStream >> verifyVector; + + BasicTypeVariant resultInt8Variant = verifyVector[0]; + BasicTypeVariant resultUint32Variant = verifyVector[1]; + BasicTypeVariant resultDoubleVariant = verifyVector[2]; + BasicTypeVariant resultStringVariant = verifyVector[3]; + + EXPECT_EQ(referenceInt8Variant, resultInt8Variant); + EXPECT_EQ(referenceUint32Variant, resultUint32Variant); + EXPECT_EQ(referenceDoubleVariant, resultDoubleVariant); + EXPECT_EQ(referenceStringVariant, resultStringVariant); } namespace com { @@ -557,115 +561,116 @@ namespace bmw { namespace test { struct TestStruct: CommonAPI::SerializableStruct { - TestStruct(); - TestStruct(int32_t v1, double v2, double v3, std::string v4); - ~TestStruct(); + TestStruct(); + TestStruct(int32_t v1, double v2, double v3, std::string v4); + ~TestStruct(); - int32_t val1; - double val2; - double val3; - std::string val4; + int32_t val1; + double val2; + double val3; + std::string val4; - virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream); - virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const; + virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream); + virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const; }; typedef std::vector<TestStruct> TestStructList; TestStruct::TestStruct() : - val1(0), val2(0), val3(0), val4("") { + val1(0), val2(0), val3(0), val4("") { } TestStruct::TestStruct(int32_t v1, double v2, double v3, std::string v4) : - val1(v1), val2(v2), val3(v3), val4(v4) { + val1(v1), val2(v2), val3(v3), val4(v4) { } TestStruct::~TestStruct() { } void TestStruct::readFromInputStream(CommonAPI::InputStream& inputMessageStream) { - inputMessageStream >> val1 >> val2 >> val3 >> val4; + inputMessageStream >> val1 >> val2 >> val3 >> val4; } void TestStruct::writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const { - outputMessageStream << val1 << val2 << val3 << val4; + outputMessageStream << val1 << val2 << val3 << val4; } } // namespace test } // namespace bmw } // namespace com - TEST_F(OutputStreamTest, WritesTestStructs) { - const char* signature = "(idds)"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); + const char signature[] = "(idds)"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); - com::bmw::test::TestStruct testStruct(1, 12.6, 1e40, "XXXXXXXXXXXXXXXXXXXX"); + com::bmw::test::TestStruct testStruct(1, 12.6, 1e40, "XXXXXXXXXXXXXXXXXXXX"); - //4(int32_t) + 4(padding) + 8(double) + 8(double) + 4(str_length) + 20(string) + 1(null-termination) - uint32_t expectedSize = 49; - outStream.reserveMemory(expectedSize); - outStream << testStruct; - outStream.flush(); + //4(int32_t) + 4(padding) + 8(double) + 8(double) + 4(str_length) + 20(string) + 1(null-termination) + uint32_t expectedSize = 49; + outStream.reserveMemory(expectedSize); + outStream << testStruct; + outStream.flush(); - EXPECT_EQ(expectedSize, message.getBodyLength()); + EXPECT_EQ(expectedSize, message.getBodyLength()); - CommonAPI::DBus::DBusInputStream inStream(message); - com::bmw::test::TestStruct verifyStruct; - inStream >> verifyStruct; + CommonAPI::DBus::DBusInputStream inStream(message); + com::bmw::test::TestStruct verifyStruct; + inStream >> verifyStruct; - EXPECT_EQ(testStruct.val1, verifyStruct.val1); - EXPECT_EQ(testStruct.val2, verifyStruct.val2); - EXPECT_EQ(testStruct.val3, verifyStruct.val3); - EXPECT_EQ(testStruct.val4, verifyStruct.val4); + EXPECT_EQ(testStruct.val1, verifyStruct.val1); + EXPECT_EQ(testStruct.val2, verifyStruct.val2); + EXPECT_EQ(testStruct.val3, verifyStruct.val3); + EXPECT_EQ(testStruct.val4, verifyStruct.val4); } TEST_F(OutputStreamTest, WritesTestStructLists) { - const char* signature = "a(idds)"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); + const char signature[] = "a(idds)"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); - com::bmw::test::TestStructList testList; - for (unsigned int i = 0; i < numOfElements; i++) { - testList.emplace_back(1, 12.6, 1e40, "XXXXXXXXXXXXXXXXXXXX"); - } + com::bmw::test::TestStructList testList; + for (unsigned int i = 0; i < numOfElements; i++) { + testList.emplace_back(1, 12.6, 1e40, "XXXXXXXXXXXXXXXXXXXX"); + } - //struct size: 49 = 4(int32_t) + 4(padding) + 8(double) + 8(double) + 4(str_length) + 20(string) + 1(null-termination) - //array size: 4(array_length) + 4(struct_padding) + (numElements-1)*(49(struct) + 7(struct_padding)) + 49(struct) - uint32_t expectedSize = 8 + (numOfElements - 1) * (49 + 7) + 49; - outStream.reserveMemory(expectedSize); - outStream << testList; - outStream.flush(); + //struct size: 49 = 4(int32_t) + 4(padding) + 8(double) + 8(double) + 4(str_length) + 20(string) + 1(null-termination) + //array size: 4(array_length) + 4(struct_padding) + (numElements-1)*(49(struct) + 7(struct_padding)) + 49(struct) + uint32_t expectedSize = 8 + (numOfElements - 1) * (49 + 7) + 49; + outStream.reserveMemory(expectedSize); + outStream << testList; + outStream.flush(); - EXPECT_EQ(expectedSize, message.getBodyLength()); + EXPECT_EQ(expectedSize, message.getBodyLength()); - CommonAPI::DBus::DBusInputStream inStream(message); - com::bmw::test::TestStructList verifyList; - inStream >> verifyList; + CommonAPI::DBus::DBusInputStream inStream(message); + com::bmw::test::TestStructList verifyList; + inStream >> verifyList; - EXPECT_EQ(numOfElements, verifyList.size()); + EXPECT_EQ(numOfElements, verifyList.size()); } - - namespace com { namespace bmw { namespace test { struct ArrayStruct: CommonAPI::SerializableStruct { - ArrayStruct(); - ArrayStruct(std::vector<int64_t> v1, std::vector<std::string> v2, std::vector<double> v3, std::vector<std::string> v4, std::vector<uint16_t> v5); - ~ArrayStruct(); - - std::vector<int64_t> val1; - std::vector<std::string> val2; - std::vector<double> val3; - std::vector<std::string> val4; - std::vector<uint16_t> val5; - - virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream); - virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const; + ArrayStruct(); + ArrayStruct(std::vector<int64_t> v1, + std::vector<std::string> v2, + std::vector<double> v3, + std::vector<std::string> v4, + std::vector<uint16_t> v5); + ~ArrayStruct(); + + std::vector<int64_t> val1; + std::vector<std::string> val2; + std::vector<double> val3; + std::vector<std::string> val4; + std::vector<uint16_t> val5; + + virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream); + virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const; }; typedef std::vector<TestStruct> TestStructList; @@ -673,120 +678,124 @@ typedef std::vector<TestStruct> TestStructList; ArrayStruct::ArrayStruct() { } -ArrayStruct::ArrayStruct(std::vector<int64_t> v1, std::vector<std::string> v2, std::vector<double> v3, std::vector<std::string> v4, std::vector<uint16_t> v5) : - val1(v1), val2(v2), val3(v3), val4(v4), val5(v5) { +ArrayStruct::ArrayStruct(std::vector<int64_t> v1, + std::vector<std::string> v2, + std::vector<double> v3, + std::vector<std::string> v4, + std::vector<uint16_t> v5) : + val1(v1), val2(v2), val3(v3), val4(v4), val5(v5) { } ArrayStruct::~ArrayStruct() { } void ArrayStruct::readFromInputStream(CommonAPI::InputStream& inputMessageStream) { - inputMessageStream >> val1 >> val2 >> val3 >> val4 >> val5; + inputMessageStream >> val1 >> val2 >> val3 >> val4 >> val5; } void ArrayStruct::writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const { - outputMessageStream << val1 << val2 << val3 << val4 << val5; + outputMessageStream << val1 << val2 << val3 << val4 << val5; } } // namespace test } // namespace bmw } // namespace com - TEST_F(OutputStreamTest, WritesStructsOfArraysWithSthBefore) { - const char* signature = "(axasadasaq)"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - com::bmw::test::ArrayStruct arrayStruct; - for (unsigned int i = 0; i < numOfElements; i++) { - arrayStruct.val1.push_back(i*50); - arrayStruct.val2.push_back("Hai"); - arrayStruct.val3.push_back(3.414); - arrayStruct.val4.push_back("Ciao"); - arrayStruct.val5.push_back(i*5); - } - uint16_t frontValue = 0; - - // 2(uint16) + 6(padding) --> 8 - // 4(LengthField) + 4(padding) + 10 * 8(int64) --> 88 --> 96 - // 4(LengthField) + 10 * (4(LengthField) + 4("Hai\0")) --> 84 --> 180 - // 4(LengthField) + 10 * 8(double) --> 84 --> 264 - // 4(LengthField) + 10 * (4(LengthField) + 5("Ciao\0") + 3(padding)) --> 124 --> 388 - // 4(LengthField) + 10 * 2(uint16) --> 24 --> 412 - size_t structLength = 412; - outStream.reserveMemory(structLength); - outStream << frontValue << arrayStruct; - outStream.flush(); - - EXPECT_EQ(structLength, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - com::bmw::test::ArrayStruct verifyStruct; - - uint16_t frontVerification; - inStream >> frontVerification >> verifyStruct; - - EXPECT_EQ(frontValue, frontVerification); - - int64_t res1; - std::string res2; - double res3; - std::string res4; - uint16_t res5; - - for (unsigned int i = 0; i < numOfElements; i++) { - res1 = verifyStruct.val1[i]; - res2 = verifyStruct.val2[i]; - res3 = verifyStruct.val3[i]; - res4 = verifyStruct.val4[i]; - res5 = verifyStruct.val5[i]; - - EXPECT_EQ(i*50, res1); - EXPECT_EQ(std::string("Hai"), res2); - EXPECT_EQ(3.414, res3); - EXPECT_EQ(std::string("Ciao"), res4); - EXPECT_EQ(i*5, res5); - } + const char signature[] = "(axasadasaq)"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + com::bmw::test::ArrayStruct arrayStruct; + for (unsigned int i = 0; i < numOfElements; i++) { + arrayStruct.val1.push_back(i * 50); + arrayStruct.val2.push_back("Hai"); + arrayStruct.val3.push_back(3.414); + arrayStruct.val4.push_back("Ciao"); + arrayStruct.val5.push_back(i * 5); + } + uint16_t frontValue = 0; + + // 2(uint16) + 6(padding) --> 8 + // 4(LengthField) + 4(padding) + 10 * 8(int64) --> 88 --> 96 + // 4(LengthField) + 10 * (4(LengthField) + 4("Hai\0")) --> 84 --> 180 + // 4(LengthField) + 10 * 8(double) --> 84 --> 264 + // 4(LengthField) + 10 * (4(LengthField) + 5("Ciao\0") + 3(padding)) --> 124 --> 388 + // 4(LengthField) + 10 * 2(uint16) --> 24 --> 412 + size_t structLength = 412; + outStream.reserveMemory(structLength); + outStream << frontValue << arrayStruct; + outStream.flush(); + + EXPECT_EQ(structLength, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + com::bmw::test::ArrayStruct verifyStruct; + + uint16_t frontVerification; + inStream >> frontVerification >> verifyStruct; + + EXPECT_EQ(frontValue, frontVerification); + + int64_t res1; + std::string res2; + double res3; + std::string res4; + uint16_t res5; + + for (unsigned int i = 0; i < numOfElements; i++) { + res1 = verifyStruct.val1[i]; + res2 = verifyStruct.val2[i]; + res3 = verifyStruct.val3[i]; + res4 = verifyStruct.val4[i]; + res5 = verifyStruct.val5[i]; + + EXPECT_EQ(i*50, res1); + EXPECT_EQ(std::string("Hai"), res2); + EXPECT_EQ(3.414, res3); + EXPECT_EQ(std::string("Ciao"), res4); + EXPECT_EQ(i*5, res5); + } } - - TEST_F(OutputStreamTest, WritesEnumKeyedMaps) { - commonapi::tests::DerivedTypeCollection::TestEnumMap testEnumMap; - - commonapi::tests::DerivedTypeCollection::TestEnum key1 = commonapi::tests::DerivedTypeCollection::TestEnum::E_NOT_USED; - commonapi::tests::DerivedTypeCollection::TestEnum key2 = commonapi::tests::DerivedTypeCollection::TestEnum::E_OK; - commonapi::tests::DerivedTypeCollection::TestEnum key3 = commonapi::tests::DerivedTypeCollection::TestEnum::E_OUT_OF_RANGE; - commonapi::tests::DerivedTypeCollection::TestEnum key4 = commonapi::tests::DerivedTypeCollection::TestEnum::E_UNKNOWN; - std::string val = "Hai"; - - testEnumMap.insert( {key1, val} ); - testEnumMap.insert( {key2, val} ); - testEnumMap.insert( {key3, val} ); - testEnumMap.insert( {key4, val} ); - - const char* signature = "a{is}"; - message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); - CommonAPI::DBus::DBusOutputStream outStream(message); - - //array length (4) + struct-padding (4) + - // 3 * (sizeof(int) + sizeof(string) + struct-padding) + (sizeof(int) + sizeof(string)) - size_t sizeOfBody = 4 + 4 + 3 * (4 + 8 + 4) + (4 + 8); - outStream.reserveMemory(sizeOfBody); - outStream << testEnumMap; - outStream.flush(); - - EXPECT_EQ(sizeOfBody, message.getBodyLength()); - - CommonAPI::DBus::DBusInputStream inStream(message); - - commonapi::tests::DerivedTypeCollection::TestEnumMap verificationMap; - inStream >> verificationMap; - - for(auto it = verificationMap.begin(); it != verificationMap.end(); ++it) { - ASSERT_EQ(it->second, testEnumMap[it->first]); - } + commonapi::tests::DerivedTypeCollection::TestEnumMap testEnumMap; + + commonapi::tests::DerivedTypeCollection::TestEnum key1 = + commonapi::tests::DerivedTypeCollection::TestEnum::E_NOT_USED; + commonapi::tests::DerivedTypeCollection::TestEnum key2 = commonapi::tests::DerivedTypeCollection::TestEnum::E_OK; + commonapi::tests::DerivedTypeCollection::TestEnum key3 = + commonapi::tests::DerivedTypeCollection::TestEnum::E_OUT_OF_RANGE; + commonapi::tests::DerivedTypeCollection::TestEnum key4 = + commonapi::tests::DerivedTypeCollection::TestEnum::E_UNKNOWN; + std::string val = "Hai"; + + testEnumMap.insert( {key1, val}); + testEnumMap.insert( {key2, val}); + testEnumMap.insert( {key3, val}); + testEnumMap.insert( {key4, val}); + + const char signature[] = "a{is}"; + message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature); + CommonAPI::DBus::DBusOutputStream outStream(message); + + //array length (4) + struct-padding (4) + + // 3 * (sizeof(int) + sizeof(string) + struct-padding) + (sizeof(int) + sizeof(string)) + size_t sizeOfBody = 4 + 4 + 3 * (4 + 8 + 4) + (4 + 8); + outStream.reserveMemory(sizeOfBody); + outStream << testEnumMap; + outStream.flush(); + + EXPECT_EQ(sizeOfBody, message.getBodyLength()); + + CommonAPI::DBus::DBusInputStream inStream(message); + + commonapi::tests::DerivedTypeCollection::TestEnumMap verificationMap; + inStream >> verificationMap; + + for (auto it = verificationMap.begin(); it != verificationMap.end(); ++it) { + ASSERT_EQ(it->second, testEnumMap[it->first]); + } } int main(int argc, char** argv) { diff --git a/src/test/DBusRuntimeTest.cpp b/src/test/DBusRuntimeTest.cpp index 082ed68..231fd23 100644 --- a/src/test/DBusRuntimeTest.cpp +++ b/src/test/DBusRuntimeTest.cpp @@ -10,20 +10,18 @@ #include <CommonAPI/DBus/DBusRuntime.h> #include <CommonAPI/DBus/DBusFactory.h> - - +#include <CommonAPI/DBus/DBusServicePublisher.h> class DBusRuntimeTest: public ::testing::Test { protected: - virtual void SetUp() { - } + virtual void SetUp() { + } - virtual void TearDown() { - } + virtual void TearDown() { + } }; - TEST_F(DBusRuntimeTest, LoadsDefaultStaticallyLinkedDBusLibrary) { std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load(); ASSERT_TRUE((bool)runtime); @@ -74,6 +72,19 @@ TEST_F(DBusRuntimeTest, DBusRuntimeLoadsDBusFactory) { } +TEST_F(DBusRuntimeTest, DBusRuntimeLoadsDBusServicePublisher) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast<CommonAPI::DBus::DBusRuntime*>(&(*runtime)); + ASSERT_TRUE(dbusRuntime != NULL); + + std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher = runtime->getServicePublisher(); + ASSERT_TRUE((bool)servicePublisher); + CommonAPI::DBus::DBusServicePublisher* dbusServicePublisher = dynamic_cast<CommonAPI::DBus::DBusServicePublisher*>(&(*servicePublisher)); + ASSERT_TRUE(dbusServicePublisher != NULL); +} + + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/src/test/DBusServiceRegistryTest.cpp b/src/test/DBusServiceRegistryTest.cpp index 9a7676e..d5d2700 100644 --- a/src/test/DBusServiceRegistryTest.cpp +++ b/src/test/DBusServiceRegistryTest.cpp @@ -8,6 +8,8 @@ #define _GLIBCXX_USE_NANOSLEEP #endif +#include <fstream> + #include <CommonAPI/CommonAPI.h> #ifndef COMMONAPI_INTERNAL_COMPILATION @@ -44,7 +46,7 @@ public: } virtual void SetUp() { - configFileName_ = CommonAPI::DBus::getCurrentBinaryFileFQN(); + configFileName_ = CommonAPI::getCurrentBinaryFileFQN(); configFileName_ += CommonAPI::DBus::DBUS_CONFIG_SUFFIX; std::ofstream configFile(configFileName_); @@ -218,10 +220,10 @@ TEST_F(DBusServiceRegistryTest, PredefinedInstances) { } -const char* serviceAddress_ = "local:test.service.name:test.instance.name"; -const char* serviceName_ = "test.service.name"; -const char* nonexistingServiceAddress_ = "local:nonexisting.service.name:nonexisting.instance.name"; -const char* nonexistingServiceName_ = "nonexisting.service.name"; +const char serviceAddress_[] = "local:test.service.name:test.instance.name"; +const char serviceName_[] = "test.service.name"; +const char nonexistingServiceAddress_[] = "local:nonexisting.service.name:nonexisting.instance.name"; +const char nonexistingServiceName_[] = "nonexisting.service.name"; class DBusServiceDiscoveryTestWithPredefinedRemote: public ::testing::Test { protected: diff --git a/src/test/commonapi/tests/DerivedTypeCollection.h b/src/test/commonapi/tests/DerivedTypeCollection.h index 038a145..23d8a43 100644 --- a/src/test/commonapi/tests/DerivedTypeCollection.h +++ b/src/test/commonapi/tests/DerivedTypeCollection.h @@ -11,7 +11,9 @@ #include <commonapi/tests/PredefinedTypeCollection.h> +#if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION +#endif #include <CommonAPI/InputStream.h> #include <CommonAPI/OutputStream.h> @@ -56,7 +58,7 @@ namespace DerivedTypeCollection { E_NOT_USED = 0x3 }; - // XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 + // Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 struct TestEnumComparator; enum class TestEnumExtended: int32_t { @@ -68,7 +70,7 @@ namespace DerivedTypeCollection { E_NEW = 0x4 }; - // XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 + // Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 struct TestEnumExtendedComparator; enum class TestEnumExtended2: int32_t { @@ -82,7 +84,7 @@ namespace DerivedTypeCollection { E_NEW2 = 0x5 }; - // XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 + // Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 struct TestEnumExtended2Comparator; struct TestStructExtended: TestStruct { @@ -109,7 +111,7 @@ namespace DerivedTypeCollection { E3 = 2 }; - // XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 + // Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1 struct TestEnumMissingValueComparator; typedef std::vector<uint64_t> TestArrayUInt64; @@ -221,7 +223,8 @@ inline bool operator!=(const TestStruct& lhs, const TestStruct& rhs) { static inline const char* getTypeCollectionName() { - return "commonapi.tests.DerivedTypeCollection"; + static const char* typeCollectionName = "commonapi.tests.DerivedTypeCollection"; + return typeCollectionName; } diff --git a/src/test/commonapi/tests/PredefinedTypeCollection.h b/src/test/commonapi/tests/PredefinedTypeCollection.h index 577b70c..f5c65fd 100644 --- a/src/test/commonapi/tests/PredefinedTypeCollection.h +++ b/src/test/commonapi/tests/PredefinedTypeCollection.h @@ -10,7 +10,9 @@ +#if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION +#endif #include <CommonAPI/ByteBuffer.h> #include <CommonAPI/types.h> @@ -53,7 +55,8 @@ namespace PredefinedTypeCollection { static inline const char* getTypeCollectionName() { - return "commonapi.tests.PredefinedTypeCollection"; + static const char* typeCollectionName = "commonapi.tests.PredefinedTypeCollection"; + return typeCollectionName; } diff --git a/src/test/commonapi/tests/TestInterface.h b/src/test/commonapi/tests/TestInterface.h index 0832743..c38b541 100644 --- a/src/test/commonapi/tests/TestInterface.h +++ b/src/test/commonapi/tests/TestInterface.h @@ -10,7 +10,9 @@ +#if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION +#endif #include <CommonAPI/types.h> @@ -28,7 +30,8 @@ class TestInterface { }; const char* TestInterface::getInterfaceId() { - return "commonapi.tests.TestInterface"; + static const char* interfaceId = "commonapi.tests.TestInterface"; + return interfaceId; } CommonAPI::Version TestInterface::getInterfaceVersion() { diff --git a/src/test/commonapi/tests/TestInterfaceDBusProxy.h b/src/test/commonapi/tests/TestInterfaceDBusProxy.h index d623bc0..592e181 100644 --- a/src/test/commonapi/tests/TestInterfaceDBusProxy.h +++ b/src/test/commonapi/tests/TestInterfaceDBusProxy.h @@ -10,7 +10,9 @@ #include <commonapi/tests/TestInterfaceProxyBase.h> +#if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION +#endif #include <CommonAPI/DBus/DBusFactory.h> #include <CommonAPI/DBus/DBusProxy.h> diff --git a/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp b/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp index 2b4cb0c..cdbb6ab 100644 --- a/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp +++ b/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp @@ -37,7 +37,7 @@ TestInterfaceDBusStubAdapter::TestInterfaceDBusStubAdapter( } const char* TestInterfaceDBusStubAdapter::getMethodsDBusIntrospectionXmlData() const { - return + static const char* introspectionData = "<method name=\"getTestPredefinedTypeAttributeAttribute\">\n" "<arg name=\"value\" type=\"u\" direction=\"out\" />" "</method>\n" @@ -95,6 +95,7 @@ const char* TestInterfaceDBusStubAdapter::getMethodsDBusIntrospectionXmlData() c "<arg name=\"testMapOutValue\" type=\"a{ua(sq)}\" direction=\"out\" />\n" "</method>\n" ; + return introspectionData; } @@ -205,21 +206,23 @@ void TestInterfaceDBusStubAdapter::fireTestPredefinedTypeBroadcastEvent(const ui ); } +const TestInterfaceDBusStubAdapter::StubDispatcherTable& TestInterfaceDBusStubAdapter::getStubDispatcherTable() { + static const TestInterfaceDBusStubAdapter::StubDispatcherTable stubDispatcherTable = { + { { "getTestPredefinedTypeAttributeAttribute", "" }, &commonapi::tests::getTestPredefinedTypeAttributeAttributeStubDispatcher } + , { { "setTestPredefinedTypeAttributeAttribute", "u" }, &commonapi::tests::setTestPredefinedTypeAttributeAttributeStubDispatcher }, + { { "getTestDerivedStructAttributeAttribute", "" }, &commonapi::tests::getTestDerivedStructAttributeAttributeStubDispatcher } + , { { "setTestDerivedStructAttributeAttribute", "(sqi)" }, &commonapi::tests::setTestDerivedStructAttributeAttributeStubDispatcher }, + { { "getTestDerivedArrayAttributeAttribute", "" }, &commonapi::tests::getTestDerivedArrayAttributeAttributeStubDispatcher } + , { { "setTestDerivedArrayAttributeAttribute", "at" }, &commonapi::tests::setTestDerivedArrayAttributeAttributeStubDispatcher } + , + { { "testEmptyMethod", "" }, &commonapi::tests::testEmptyMethodStubDispatcher }, + { { "testVoidPredefinedTypeMethod", "us" }, &commonapi::tests::testVoidPredefinedTypeMethodStubDispatcher }, + { { "testPredefinedTypeMethod", "us" }, &commonapi::tests::testPredefinedTypeMethodStubDispatcher }, + { { "testVoidDerivedTypeMethod", "ia{ua(sq)}" }, &commonapi::tests::testVoidDerivedTypeMethodStubDispatcher }, + { { "testDerivedTypeMethod", "ia{ua(sq)}" }, &commonapi::tests::testDerivedTypeMethodStubDispatcher } + }; + return stubDispatcherTable; +} + } // namespace tests } // namespace commonapi - -template<> -const commonapi::tests::TestInterfaceDBusStubAdapterHelper::StubDispatcherTable commonapi::tests::TestInterfaceDBusStubAdapterHelper::stubDispatcherTable_ = { - { { "getTestPredefinedTypeAttributeAttribute", "" }, &commonapi::tests::getTestPredefinedTypeAttributeAttributeStubDispatcher } - , { { "setTestPredefinedTypeAttributeAttribute", "u" }, &commonapi::tests::setTestPredefinedTypeAttributeAttributeStubDispatcher }, - { { "getTestDerivedStructAttributeAttribute", "" }, &commonapi::tests::getTestDerivedStructAttributeAttributeStubDispatcher } - , { { "setTestDerivedStructAttributeAttribute", "(sqi)" }, &commonapi::tests::setTestDerivedStructAttributeAttributeStubDispatcher }, - { { "getTestDerivedArrayAttributeAttribute", "" }, &commonapi::tests::getTestDerivedArrayAttributeAttributeStubDispatcher } - , { { "setTestDerivedArrayAttributeAttribute", "at" }, &commonapi::tests::setTestDerivedArrayAttributeAttributeStubDispatcher } - , - { { "testEmptyMethod", "" }, &commonapi::tests::testEmptyMethodStubDispatcher }, - { { "testVoidPredefinedTypeMethod", "us" }, &commonapi::tests::testVoidPredefinedTypeMethodStubDispatcher }, - { { "testPredefinedTypeMethod", "us" }, &commonapi::tests::testPredefinedTypeMethodStubDispatcher }, - { { "testVoidDerivedTypeMethod", "ia{ua(sq)}" }, &commonapi::tests::testVoidDerivedTypeMethodStubDispatcher }, - { { "testDerivedTypeMethod", "ia{ua(sq)}" }, &commonapi::tests::testDerivedTypeMethodStubDispatcher } -}; diff --git a/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h b/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h index 278fdaa..952e9b2 100644 --- a/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h +++ b/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h @@ -10,7 +10,9 @@ #include <commonapi/tests/TestInterfaceStub.h> +#if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION +#endif #include <CommonAPI/DBus/DBusStubAdapterHelper.h> #include <CommonAPI/DBus/DBusFactory.h> @@ -38,6 +40,8 @@ class TestInterfaceDBusStubAdapter: public TestInterfaceStubAdapter, public Test void fireTestPredefinedTypeBroadcastEvent(const uint32_t& uint32Value, const std::string& stringValue); + const StubDispatcherTable& getStubDispatcherTable(); + protected: virtual const char* getMethodsDBusIntrospectionXmlData() const; }; diff --git a/src/test/commonapi/tests/TestInterfaceProxy.h b/src/test/commonapi/tests/TestInterfaceProxy.h index 56f6a06..40da245 100644 --- a/src/test/commonapi/tests/TestInterfaceProxy.h +++ b/src/test/commonapi/tests/TestInterfaceProxy.h @@ -10,7 +10,9 @@ #include "TestInterfaceProxyBase.h" +#if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION +#endif #include <CommonAPI/AttributeExtension.h> #include <CommonAPI/Factory.h> diff --git a/src/test/commonapi/tests/TestInterfaceProxyBase.h b/src/test/commonapi/tests/TestInterfaceProxyBase.h index 04ab825..99d73c5 100644 --- a/src/test/commonapi/tests/TestInterfaceProxyBase.h +++ b/src/test/commonapi/tests/TestInterfaceProxyBase.h @@ -13,7 +13,9 @@ #include <commonapi/tests/DerivedTypeCollection.h> + #if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION + #endif #include <CommonAPI/InputStream.h> #include <CommonAPI/OutputStream.h> diff --git a/src/test/commonapi/tests/TestInterfaceStub.h b/src/test/commonapi/tests/TestInterfaceStub.h index be1a656..1ac580c 100644 --- a/src/test/commonapi/tests/TestInterfaceStub.h +++ b/src/test/commonapi/tests/TestInterfaceStub.h @@ -14,7 +14,9 @@ #include "TestInterface.h" +#if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION +#endif #include <CommonAPI/InputStream.h> #include <CommonAPI/OutputStream.h> diff --git a/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingBasicTest.cpp b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingBasicTest.cpp new file mode 100644 index 0000000..9c49a6e --- /dev/null +++ b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingBasicTest.cpp @@ -0,0 +1,180 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <gtest/gtest.h> + +#include <fstream> + +#include "DBusDynamicLoadingDefinitions.h" + + +class Environment: public ::testing::Environment { +public: + virtual ~Environment() { + } + + virtual void SetUp() { + environmentIdentifier_ = COMMONAPI_ENVIRONMENT_BINDING_PATH + "=" ; + environmentString_ = environmentIdentifier_ + currentWorkingDirectory; + char* environment = (char*) (environmentString_.c_str()); + putenv(environment); + + configFileName_ = CommonAPI::getCurrentBinaryFileFQN(); + configFileName_ += COMMONAPI_CONFIG_SUFFIX; + std::ofstream configFile(configFileName_); + ASSERT_TRUE(configFile.is_open()); + configFile << validForLocalDBusBinding; + configFile.close(); + } + + virtual void TearDown() { + std::remove(configFileName_.c_str()); + + char* environment = (char*) (environmentIdentifier_.c_str()); + putenv(environment); + } + + std::string configFileName_; + std::string environmentIdentifier_; + std::string environmentString_; +}; + + +class DBusDynamicLoadingBasicTest: public ::testing::Test { + protected: + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + +TEST_F(DBusDynamicLoadingBasicTest, LoadsUnconfiguredDefaultDynamicallyLinkedLibrary) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load(); + EXPECT_TRUE((bool)runtime); +} + +TEST_F(DBusDynamicLoadingBasicTest, LoadsSpecificDynamicallyLinkedDBusLibrary) { + std::shared_ptr<CommonAPI::Runtime> defaultRuntime = CommonAPI::Runtime::load(); + std::shared_ptr<CommonAPI::Runtime> dbusRuntime = CommonAPI::Runtime::load("DBus"); + EXPECT_TRUE((bool)defaultRuntime); + EXPECT_TRUE((bool)dbusRuntime); + //Even though Fake has "DBus" defined as an alias, the well known name of the DBus binding + //(which coincidentially is "DBus") has precedence. + ASSERT_EQ(dbusRuntime, defaultRuntime); +} + +TEST_F(DBusDynamicLoadingBasicTest, LoadsAliasedDynamicallyLinkedDBusLibrary) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("MyFirstAlias"); + EXPECT_TRUE((bool)runtime); + std::shared_ptr<CommonAPI::Runtime> runtime2 = CommonAPI::Runtime::load("MySecondAlias"); + EXPECT_TRUE((bool)runtime2); +} + +TEST_F(DBusDynamicLoadingBasicTest, ReturnsEmptyPointerOnRequestForUnknownMiddleware) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("NonExisting"); + EXPECT_FALSE((bool)runtime); +} + +TEST_F(DBusDynamicLoadingBasicTest, LoadsDBusLibraryAsSingleton) { + std::shared_ptr<CommonAPI::Runtime> runtime1 = CommonAPI::Runtime::load("DBus"); + std::shared_ptr<CommonAPI::Runtime> runtime2 = CommonAPI::Runtime::load("MyFirstAlias"); + std::shared_ptr<CommonAPI::Runtime> runtime3 = CommonAPI::Runtime::load("MySecondAlias"); + std::shared_ptr<CommonAPI::Runtime> runtime4 = CommonAPI::Runtime::load("DBus"); + EXPECT_TRUE((bool)runtime1); + EXPECT_TRUE((bool)runtime2); + EXPECT_TRUE((bool)runtime3); + EXPECT_TRUE((bool)runtime4); + + EXPECT_EQ(runtime1, runtime2); + EXPECT_EQ(runtime1, runtime3); + EXPECT_EQ(runtime2, runtime3); + EXPECT_EQ(runtime1, runtime4); + EXPECT_EQ(runtime2, runtime4); + EXPECT_EQ(runtime3, runtime4); +} + +TEST_F(DBusDynamicLoadingBasicTest, RuntimeLoadsFactory) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory(); + EXPECT_TRUE((bool)proxyFactory); +} + +TEST_F(DBusDynamicLoadingBasicTest, RuntimeLoadsServicePublisher) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher = runtime->getServicePublisher(); + EXPECT_TRUE((bool)servicePublisher); +} + +TEST_F(DBusDynamicLoadingBasicTest, FactoryCanCreateProxies) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory(); + EXPECT_TRUE((bool)proxyFactory); + + auto defaultTestProxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>(testServiceAddress); + ASSERT_TRUE((bool)defaultTestProxy); +} + +TEST_F(DBusDynamicLoadingBasicTest, ServicePublisherCanRegisterStubs) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> serviceFactory = runtime->createFactory(); + EXPECT_TRUE((bool)serviceFactory); + + std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher = runtime->getServicePublisher(); + EXPECT_TRUE((bool)servicePublisher); + + auto myStub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>(); + + servicePublisher->registerService(myStub, testServiceAddress, serviceFactory); + servicePublisher->unregisterService(testServiceAddress); +} + +TEST_F(DBusDynamicLoadingBasicTest, CreatedProxiesAndServicesCanCommunicate) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory(); + EXPECT_TRUE((bool)proxyFactory); + + auto defaultTestProxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>(testServiceAddress); + ASSERT_TRUE((bool)defaultTestProxy); + + std::shared_ptr<CommonAPI::Factory> serviceFactory = runtime->createFactory(); + EXPECT_TRUE((bool)serviceFactory); + + std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher = runtime->getServicePublisher(); + EXPECT_TRUE((bool)servicePublisher); + + auto myStub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>(); + + servicePublisher->registerService(myStub, testServiceAddress, serviceFactory); + + uint32_t i = 0; + for (uint32_t i = 0; i < 300 && !defaultTestProxy->isAvailable(); ++i) { + usleep(1000); + } + EXPECT_TRUE(defaultTestProxy->isAvailable()); + + CommonAPI::CallStatus status; + defaultTestProxy->testEmptyMethod(status); + ASSERT_EQ(CommonAPI::CallStatus::SUCCESS, status); + + servicePublisher->unregisterService(testServiceAddress); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new Environment()); + return RUN_ALL_TESTS(); +} diff --git a/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingDefinitions.h b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingDefinitions.h new file mode 100644 index 0000000..cecf22e --- /dev/null +++ b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingDefinitions.h @@ -0,0 +1,112 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef DBUS_DYNAMIC_LOADING_DEFINITIONS_H_ +#define DBUS_DYNAMIC_LOADING_DEFINITIONS_H_ + +#include <cstring> +#include <string> + +#include <CommonAPI/CommonAPI.h> + +#ifndef COMMONAPI_INTERNAL_COMPILATION +#define COMMONAPI_INTERNAL_COMPILATION +#endif + +#include <CommonAPI/utils.h> + +#include <commonapi/tests/TestInterfaceProxy.h> +#include <commonapi/tests/TestInterfaceStubDefault.h> + + +const char testServiceAddress[] = "local:commonapi.tests.TestInterface:commonapi.tests.TestInterface"; + +const std::string COMMONAPI_CONFIG_SUFFIX = ".conf"; +const std::string COMMONAPI_ENVIRONMENT_BINDING_PATH = "COMMONAPI_BINDING_PATH"; + +const std::string currentBinaryFileFQN = CommonAPI::getCurrentBinaryFileFQN(); +const std::string currentWorkingDirectory = currentBinaryFileFQN.substr(0, currentBinaryFileFQN.find_last_of("/") + 1); + +const std::string firstAlias = "MyFirstAlias"; +const std::string secondAlias = "MySecondAlias"; +const std::string firstAliasDefinition = "alias=" + firstAlias + "\n"; +const std::string secondAliasDefinition = "alias=" + secondAlias + "\n"; +const std::string combinedAliasDefinition = "alias=" + firstAlias + ":" + secondAlias + "\n"; +const std::string libraryDBusPathDefinition = "libpath=" + currentWorkingDirectory + "libCommonAPI-DBus.so\n"; +const std::string libraryFakePathDefinition = "libpath=" + currentWorkingDirectory + "libCommonAPI-Fake.so\n"; +const std::string generatedDBusPathDefinition = "genpath=" + currentWorkingDirectory + "libSomeOtherNameForGeneratedDBus.so\n"; +const std::string dbusBindingDefinitionStart = "{binding:DBus}\n"; +const std::string fakeBindingDefinitionStart = "{binding:Fake}\n"; + +const std::string validForLocalDBusBinding = + dbusBindingDefinitionStart + + combinedAliasDefinition + + libraryDBusPathDefinition + + "default" + + fakeBindingDefinitionStart + + "alias=DBus\n"; + +const std::string validForMultiplyDefinedDBusBinding = + dbusBindingDefinitionStart + + libraryDBusPathDefinition + + generatedDBusPathDefinition + + firstAliasDefinition + + "\n" + + dbusBindingDefinitionStart + + secondAliasDefinition + + "libpath=/useless/path"; + +const std::string __garbageString = + "" + "{not#a$valid/binding+PATH}\n" + "{}\n" + " 98t3hpgjvqpvnü0 t4b+ qßk4 kv+üg4krgv+ß4krgv+ßkr \n" + "{binding:blub}\n" + "{}đwqervqerverver\n" + "{too:much:binding}\n" + "{binding:too:much}\n" + "jfgv2nqp3 riqpnvi39r{}\n" + "{hbi8uolnjk:}.-,0::9p:o:{}: bjk}{ {8h.ubpu:bzu}\n" + "\n" + "\n" + "\n" + "{noBinding:/useless/path}\n" + "{:incomplete}\n"; + +const std::string mixedValidityValuesAndBindings = + "{binding: InvalidBinding}\n" + + firstAliasDefinition + + __garbageString + + libraryDBusPathDefinition + + "\n" + + "{binding:BrokenPathBinding}\n" + + "libpath=/some/path/to/nowhere\n" + + "\n" + + validForMultiplyDefinedDBusBinding + + "\n" + "{binding: }\n" + + __garbageString + + "alias=emptyBindingAlias\n" + "libpath=/another/path/to/nowhere\n" + + __garbageString; + +const std::string noValidityValuesAndBindings = + __garbageString + + "{binding: InvalidBinding}\n" + + firstAliasDefinition + + __garbageString + + libraryDBusPathDefinition + + "{binding: }\n" + + __garbageString + + "alias=emptyBindingAlias\n" + "libpath=/some/path/to/nowhere\n" + + "default\n" + + __garbageString + + dbusBindingDefinitionStart + + "genpath=" + currentWorkingDirectory + "libNonsense.so\n"; + + +#endif /* DBUS_DYNAMIC_LOADING_DEFINITIONS_H_ */ diff --git a/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMixedValidityTest.cpp b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMixedValidityTest.cpp new file mode 100644 index 0000000..5e34932 --- /dev/null +++ b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMixedValidityTest.cpp @@ -0,0 +1,194 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <gtest/gtest.h> + +#include <stdexcept> +#include <fstream> + +#include "DBusDynamicLoadingDefinitions.h" + +#ifndef COMMONAPI_INTERNAL_COMPILATION +#define COMMONAPI_INTERNAL_COMPILATION +#endif +#include <CommonAPI/DBus/DBusRuntime.h> + + +class Environment: public ::testing::Environment { +public: + virtual ~Environment() { + } + + virtual void SetUp() { + environmentIdentifier_ = COMMONAPI_ENVIRONMENT_BINDING_PATH + "=" ; + environmentString_ = environmentIdentifier_ + currentWorkingDirectory; + char* environment = (char*) (environmentString_.c_str()); + putenv(environment); + + configFileName_ = CommonAPI::getCurrentBinaryFileFQN(); + configFileName_ += COMMONAPI_CONFIG_SUFFIX; + std::ofstream configFile(configFileName_); + ASSERT_TRUE(configFile.is_open()); + configFile << mixedValidityValuesAndBindings; + configFile.close(); + } + + virtual void TearDown() { + std::remove(configFileName_.c_str()); + + char* environment = (char*) (environmentIdentifier_.c_str()); + putenv(environment); + } + + std::string configFileName_; + std::string environmentIdentifier_; + std::string environmentString_; +}; + + +class DBusDynamicLoadingPartiallyInvalidConfigTest: public ::testing::Test { + protected: + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, LoadsUnconfiguredDefaultDynamicallyLinkedLibrary) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load(); + EXPECT_TRUE((bool)runtime); +} + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, LoadsSpecificDynamicallyLinkedDBusLibrary) { + std::shared_ptr<CommonAPI::Runtime> defaultRuntime = CommonAPI::Runtime::load(); + std::shared_ptr<CommonAPI::Runtime> fakeRuntime = CommonAPI::Runtime::load("Fake"); + EXPECT_TRUE((bool)defaultRuntime); + EXPECT_TRUE((bool)fakeRuntime); + //The DBus binding is alphabetically before the Fake binding, so the DBusRuntime will be loaded as default + ASSERT_NE(fakeRuntime, defaultRuntime); +} + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, LoadsAliasedDynamicallyLinkedDBusLibrary) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("MyFirstAlias"); + //The first alias is claimed by another binding, which was defined earlier in the config + EXPECT_FALSE((bool)runtime); + std::shared_ptr<CommonAPI::Runtime> runtime2 = CommonAPI::Runtime::load("MySecondAlias"); + EXPECT_TRUE((bool)runtime2); +} + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, ReturnsEmptyPointerOnRequestForUnknownMiddleware) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("NonExisting"); + EXPECT_FALSE((bool)runtime); +} + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, LoadsDBusLibraryAsSingleton) { + std::shared_ptr<CommonAPI::Runtime> runtime1 = CommonAPI::Runtime::load("DBus"); + std::shared_ptr<CommonAPI::Runtime> runtime2 = CommonAPI::Runtime::load("MyFirstAlias"); + std::shared_ptr<CommonAPI::Runtime> runtime3 = CommonAPI::Runtime::load("MySecondAlias"); + std::shared_ptr<CommonAPI::Runtime> runtime4 = CommonAPI::Runtime::load("DBus"); + EXPECT_TRUE((bool)runtime1); + //The first alias is claimed by another binding, which was defined earlier in the config + EXPECT_FALSE((bool)runtime2); + EXPECT_TRUE((bool)runtime3); + EXPECT_TRUE((bool)runtime4); + + EXPECT_NE(runtime1, runtime2); + EXPECT_EQ(runtime1, runtime3); + EXPECT_NE(runtime2, runtime3); + EXPECT_EQ(runtime1, runtime4); + EXPECT_NE(runtime2, runtime4); + EXPECT_EQ(runtime3, runtime4); +} + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, RuntimeLoadsFactory) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory(); + EXPECT_TRUE((bool)proxyFactory); +} + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, RuntimeLoadsServicePublisher) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher = runtime->getServicePublisher(); + EXPECT_TRUE((bool)servicePublisher); +} + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, FactoryCanCreateProxies) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory(); + EXPECT_TRUE((bool)proxyFactory); + + auto defaultTestProxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>(testServiceAddress); + ASSERT_TRUE((bool)defaultTestProxy); +} + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, ServicePublisherCanRegisterStubs) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> serviceFactory = runtime->createFactory(); + EXPECT_TRUE((bool)serviceFactory); + + std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher = runtime->getServicePublisher(); + EXPECT_TRUE((bool)servicePublisher); + + auto myStub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>(); + + servicePublisher->registerService(myStub, testServiceAddress, serviceFactory); + servicePublisher->unregisterService(testServiceAddress); +} + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, CreatedProxiesAndServicesCanCommunicate) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory(); + EXPECT_TRUE((bool)proxyFactory); + + auto defaultTestProxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>(testServiceAddress); + ASSERT_TRUE((bool)defaultTestProxy); + + std::shared_ptr<CommonAPI::Factory> serviceFactory = runtime->createFactory(); + EXPECT_TRUE((bool)serviceFactory); + + std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher = runtime->getServicePublisher(); + EXPECT_TRUE((bool)servicePublisher); + + auto myStub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>(); + + servicePublisher->registerService(myStub, testServiceAddress, serviceFactory); + + uint32_t i = 0; + for (uint32_t i = 0; i < 300 && !defaultTestProxy->isAvailable(); ++i) { + usleep(1000); + } + EXPECT_TRUE(defaultTestProxy->isAvailable()); + + CommonAPI::CallStatus status; + defaultTestProxy->testEmptyMethod(status); + ASSERT_EQ(CommonAPI::CallStatus::SUCCESS, status); + + servicePublisher->unregisterService(testServiceAddress); +} + +TEST_F(DBusDynamicLoadingPartiallyInvalidConfigTest, ErrorOnLoadingRuntimeForBrokenPath) { + CommonAPI::Runtime::LoadState loadState; + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("BrokenPathBinding", loadState); + ASSERT_EQ(CommonAPI::Runtime::LoadState::CONFIGURATION_ERROR, loadState); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new Environment()); + return RUN_ALL_TESTS(); +} diff --git a/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMultipleBindingsTest.cpp b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMultipleBindingsTest.cpp new file mode 100644 index 0000000..426d8d6 --- /dev/null +++ b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMultipleBindingsTest.cpp @@ -0,0 +1,143 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <gtest/gtest.h> + +#include "DBusDynamicLoadingDefinitions.h" + + +class Environment: public ::testing::Environment { + public: + virtual ~Environment() { + } + + virtual void SetUp() { + environmentIdentifier_ = COMMONAPI_ENVIRONMENT_BINDING_PATH + "=" ; + environmentString_ = environmentIdentifier_ + currentWorkingDirectory; + char* environment = (char*) (environmentString_.c_str()); + putenv(environment); + } + + virtual void TearDown() { + char* environment = (char*) (environmentIdentifier_.c_str()); + putenv(environment); + } + + private: + std::string environmentIdentifier_; + std::string environmentString_; +}; + + +class DBusDynamicLoadingMultipleBindingsTest: public ::testing::Test { + protected: + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + + +TEST_F(DBusDynamicLoadingMultipleBindingsTest, LoadsUnconfiguredDefaultDynamicallyLinkedLibrary) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load(); + EXPECT_TRUE((bool)runtime); +} + +TEST_F(DBusDynamicLoadingMultipleBindingsTest, LoadsSpecificDynamicallyLinkedDBusLibrary) { + std::shared_ptr<CommonAPI::Runtime> defaultRuntime = CommonAPI::Runtime::load(); + std::shared_ptr<CommonAPI::Runtime> fakeRuntime = CommonAPI::Runtime::load("Fake"); + EXPECT_TRUE((bool)defaultRuntime); + EXPECT_TRUE((bool)fakeRuntime); + //The DBus binding is alphabetically before the Fake binding, so the DBusRuntime will be loaded as default + ASSERT_NE(fakeRuntime, defaultRuntime); +} + +TEST_F(DBusDynamicLoadingMultipleBindingsTest, LoadsSpecificDynamicallyLinkedFakeLibrary) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("Fake"); + EXPECT_TRUE((bool)runtime); +} + +TEST_F(DBusDynamicLoadingMultipleBindingsTest, LoadsBothDynamicallyLinkedLibrariesAtTheSameTime) { + std::shared_ptr<CommonAPI::Runtime> dbusRuntime = CommonAPI::Runtime::load("DBus"); + EXPECT_TRUE((bool)dbusRuntime); + std::shared_ptr<CommonAPI::Runtime> fakeRuntime = CommonAPI::Runtime::load("Fake"); + EXPECT_TRUE((bool)fakeRuntime); + + ASSERT_NE(dbusRuntime, fakeRuntime); +} + +TEST_F(DBusDynamicLoadingMultipleBindingsTest, LoadsBothLibrariesAsSingletons) { + std::shared_ptr<CommonAPI::Runtime> dbusRuntime1 = CommonAPI::Runtime::load("DBus"); + std::shared_ptr<CommonAPI::Runtime> dbusRuntime2 = CommonAPI::Runtime::load("DBus"); + std::shared_ptr<CommonAPI::Runtime> dbusRuntime3 = CommonAPI::Runtime::load("DBus"); + EXPECT_TRUE((bool)dbusRuntime1); + EXPECT_TRUE((bool)dbusRuntime2); + EXPECT_TRUE((bool)dbusRuntime3); + + EXPECT_EQ(dbusRuntime1, dbusRuntime2); + EXPECT_EQ(dbusRuntime1, dbusRuntime3); + EXPECT_EQ(dbusRuntime2, dbusRuntime3); + + std::shared_ptr<CommonAPI::Runtime> fakeRuntime1 = CommonAPI::Runtime::load("Fake"); + std::shared_ptr<CommonAPI::Runtime> fakeRuntime2 = CommonAPI::Runtime::load("Fake"); + std::shared_ptr<CommonAPI::Runtime> fakeRuntime3 = CommonAPI::Runtime::load("Fake"); + EXPECT_TRUE((bool)fakeRuntime1); + EXPECT_TRUE((bool)fakeRuntime2); + EXPECT_TRUE((bool)fakeRuntime3); + + EXPECT_EQ(fakeRuntime1, fakeRuntime2); + EXPECT_EQ(fakeRuntime1, fakeRuntime3); + EXPECT_EQ(fakeRuntime2, fakeRuntime3); + + EXPECT_NE(fakeRuntime1, dbusRuntime1); + EXPECT_NE(fakeRuntime1, dbusRuntime2); + EXPECT_NE(fakeRuntime1, dbusRuntime3); + + EXPECT_NE(fakeRuntime2, dbusRuntime1); + EXPECT_NE(fakeRuntime2, dbusRuntime2); + EXPECT_NE(fakeRuntime2, dbusRuntime3); + + EXPECT_NE(fakeRuntime3, dbusRuntime1); + EXPECT_NE(fakeRuntime3, dbusRuntime2); + EXPECT_NE(fakeRuntime3, dbusRuntime3); +} + +TEST_F(DBusDynamicLoadingMultipleBindingsTest, RuntimesLoadBothFactories) { + std::shared_ptr<CommonAPI::Runtime> dbusRuntime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)dbusRuntime); + std::shared_ptr<CommonAPI::Factory> dbusProxyFactory = dbusRuntime->createFactory(); + EXPECT_TRUE((bool)dbusProxyFactory); + + std::shared_ptr<CommonAPI::Runtime> fakeRuntime = CommonAPI::Runtime::load("Fake"); + ASSERT_TRUE((bool)fakeRuntime); + std::shared_ptr<CommonAPI::Factory> fakeProxyFactory = dbusRuntime->createFactory(); + EXPECT_TRUE((bool)fakeProxyFactory); + + ASSERT_NE(dbusRuntime, fakeRuntime); + EXPECT_NE(dbusProxyFactory, fakeProxyFactory); +} + +TEST_F(DBusDynamicLoadingMultipleBindingsTest, RuntimesLoadBothServicePublishers) { + std::shared_ptr<CommonAPI::Runtime> dbusRuntime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)dbusRuntime); + std::shared_ptr<CommonAPI::ServicePublisher> dbusServicePublisher = dbusRuntime->getServicePublisher(); + EXPECT_TRUE((bool)dbusServicePublisher); + + std::shared_ptr<CommonAPI::Runtime> fakeRuntime = CommonAPI::Runtime::load("Fake"); + ASSERT_TRUE((bool)fakeRuntime); + std::shared_ptr<CommonAPI::ServicePublisher> fakeServicePublisher = fakeRuntime->getServicePublisher(); + EXPECT_TRUE((bool)fakeServicePublisher); + + ASSERT_NE(dbusRuntime, fakeRuntime); + EXPECT_NE(dbusServicePublisher, fakeServicePublisher); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new Environment()); + return RUN_ALL_TESTS(); +} diff --git a/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMultipleDefinitionTest.cpp b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMultipleDefinitionTest.cpp new file mode 100644 index 0000000..e30a8c5 --- /dev/null +++ b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingMultipleDefinitionTest.cpp @@ -0,0 +1,180 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <gtest/gtest.h> + +#include <fstream> + +#include "DBusDynamicLoadingDefinitions.h" + + +class Environment: public ::testing::Environment { +public: + virtual ~Environment() { + } + + virtual void SetUp() { + environmentIdentifier_ = COMMONAPI_ENVIRONMENT_BINDING_PATH + "=" ; + environmentString_ = environmentIdentifier_ + currentWorkingDirectory; + char* environment = (char*) (environmentString_.c_str()); + putenv(environment); + + configFileName_ = CommonAPI::getCurrentBinaryFileFQN(); + configFileName_ += COMMONAPI_CONFIG_SUFFIX; + std::ofstream configFile(configFileName_); + ASSERT_TRUE(configFile.is_open()); + configFile << validForMultiplyDefinedDBusBinding; + configFile.close(); + } + + virtual void TearDown() { + std::remove(configFileName_.c_str()); + + char* environment = (char*) (environmentIdentifier_.c_str()); + putenv(environment); + } + + std::string configFileName_; + std::string environmentIdentifier_; + std::string environmentString_; +}; + + +class DBusDynamicLoadingMultipleDefinitionTest: public ::testing::Test { + protected: + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + + +TEST_F(DBusDynamicLoadingMultipleDefinitionTest, LoadsUnconfiguredDefaultDynamicallyLinkedLibrary) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load(); + EXPECT_TRUE((bool)runtime); +} + +TEST_F(DBusDynamicLoadingMultipleDefinitionTest, LoadsSpecificDynamicallyLinkedDBusLibrary) { + std::shared_ptr<CommonAPI::Runtime> defaultRuntime = CommonAPI::Runtime::load(); + std::shared_ptr<CommonAPI::Runtime> fakeRuntime = CommonAPI::Runtime::load("Fake"); + EXPECT_TRUE((bool)defaultRuntime); + EXPECT_TRUE((bool)fakeRuntime); + //The DBus binding is alphabetically before the Fake binding, so the DBusRuntime will be loaded as default + ASSERT_NE(fakeRuntime, defaultRuntime); +} + +TEST_F(DBusDynamicLoadingMultipleDefinitionTest, LoadsAliasedDynamicallyLinkedDBusLibrary) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("MyFirstAlias"); + EXPECT_TRUE((bool)runtime); + std::shared_ptr<CommonAPI::Runtime> runtime2 = CommonAPI::Runtime::load("MySecondAlias"); + EXPECT_TRUE((bool)runtime2); +} + +TEST_F(DBusDynamicLoadingMultipleDefinitionTest, ReturnsEmptyPointerOnRequestForUnknownMiddleware) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("NonExisting"); + EXPECT_FALSE((bool)runtime); +} + +TEST_F(DBusDynamicLoadingMultipleDefinitionTest, LoadsDBusLibraryAsSingleton) { + std::shared_ptr<CommonAPI::Runtime> runtime1 = CommonAPI::Runtime::load("DBus"); + std::shared_ptr<CommonAPI::Runtime> runtime2 = CommonAPI::Runtime::load("MyFirstAlias"); + std::shared_ptr<CommonAPI::Runtime> runtime3 = CommonAPI::Runtime::load("MySecondAlias"); + std::shared_ptr<CommonAPI::Runtime> runtime4 = CommonAPI::Runtime::load("DBus"); + EXPECT_TRUE((bool)runtime1); + EXPECT_TRUE((bool)runtime2); + EXPECT_TRUE((bool)runtime3); + EXPECT_TRUE((bool)runtime4); + + EXPECT_EQ(runtime1, runtime2); + EXPECT_EQ(runtime1, runtime3); + EXPECT_EQ(runtime2, runtime3); + EXPECT_EQ(runtime1, runtime4); + EXPECT_EQ(runtime2, runtime4); + EXPECT_EQ(runtime3, runtime4); +} + +TEST_F(DBusDynamicLoadingMultipleDefinitionTest, RuntimeLoadsFactory) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory(); + EXPECT_TRUE((bool)proxyFactory); +} + +TEST_F(DBusDynamicLoadingMultipleDefinitionTest, RuntimeLoadsServicePublisher) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher = runtime->getServicePublisher(); + EXPECT_TRUE((bool)servicePublisher); +} + +TEST_F(DBusDynamicLoadingMultipleDefinitionTest, FactoryCanCreateProxies) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory(); + EXPECT_TRUE((bool)proxyFactory); + + auto defaultTestProxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>(testServiceAddress); + ASSERT_TRUE((bool)defaultTestProxy); +} + +TEST_F(DBusDynamicLoadingMultipleDefinitionTest, ServicePublisherCanRegisterStubs) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> serviceFactory = runtime->createFactory(); + EXPECT_TRUE((bool)serviceFactory); + + std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher = runtime->getServicePublisher(); + EXPECT_TRUE((bool)servicePublisher); + + auto myStub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>(); + + servicePublisher->registerService(myStub, testServiceAddress, serviceFactory); + servicePublisher->unregisterService(testServiceAddress); +} + +TEST_F(DBusDynamicLoadingMultipleDefinitionTest, CreatedProxiesAndServicesCanCommunicate) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus"); + ASSERT_TRUE((bool)runtime); + + std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory(); + EXPECT_TRUE((bool)proxyFactory); + + auto defaultTestProxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>(testServiceAddress); + ASSERT_TRUE((bool)defaultTestProxy); + + std::shared_ptr<CommonAPI::Factory> serviceFactory = runtime->createFactory(); + EXPECT_TRUE((bool)serviceFactory); + + std::shared_ptr<CommonAPI::ServicePublisher> servicePublisher = runtime->getServicePublisher(); + EXPECT_TRUE((bool)servicePublisher); + + auto myStub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>(); + + servicePublisher->registerService(myStub, testServiceAddress, serviceFactory); + + uint32_t i = 0; + for (uint32_t i = 0; i < 300 && !defaultTestProxy->isAvailable(); ++i) { + usleep(1000); + } + EXPECT_TRUE(defaultTestProxy->isAvailable()); + + CommonAPI::CallStatus status; + defaultTestProxy->testEmptyMethod(status); + ASSERT_EQ(CommonAPI::CallStatus::SUCCESS, status); + + servicePublisher->unregisterService(testServiceAddress); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new Environment()); + return RUN_ALL_TESTS(); +} diff --git a/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingNoValidityTest.cpp b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingNoValidityTest.cpp new file mode 100644 index 0000000..5a40126 --- /dev/null +++ b/src/test/dbusDynamicLoadingTests/DBusDynamicLoadingNoValidityTest.cpp @@ -0,0 +1,81 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <gtest/gtest.h> + +#include <fstream> + +#include "DBusDynamicLoadingDefinitions.h" + + +class Environment: public ::testing::Environment { +public: + virtual ~Environment() { + } + + virtual void SetUp() { + environmentIdentifier_ = COMMONAPI_ENVIRONMENT_BINDING_PATH + "=" ; + environmentString_ = environmentIdentifier_ + currentWorkingDirectory; + char* environment = (char*) (environmentString_.c_str()); + putenv(environment); + + configFileName_ = CommonAPI::getCurrentBinaryFileFQN(); + configFileName_ += COMMONAPI_CONFIG_SUFFIX; + std::ofstream configFile(configFileName_); + ASSERT_TRUE(configFile.is_open()); + configFile << noValidityValuesAndBindings; + configFile.close(); + } + + virtual void TearDown() { + std::remove(configFileName_.c_str()); + + char* environment = (char*) (environmentIdentifier_.c_str()); + putenv(environment); + } + + std::string configFileName_; + std::string environmentIdentifier_; + std::string environmentString_; +}; + + +class DBusDynamicLoadingFullyInvalidConfigTest: public ::testing::Test { + protected: + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + + +TEST_F(DBusDynamicLoadingFullyInvalidConfigTest, ErrorOnLoadingWronglyConfiguredDefaultDynamicallyLinkedLibrary) { + CommonAPI::Runtime::LoadState loadState; + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load(loadState); + ASSERT_EQ(CommonAPI::Runtime::LoadState::CONFIGURATION_ERROR, loadState); +} + +TEST_F(DBusDynamicLoadingFullyInvalidConfigTest, ErrorOnLoadingWronglyConfiguredGeneratedCodePath) { + CommonAPI::Runtime::LoadState loadState; + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus", loadState); + ASSERT_EQ(CommonAPI::Runtime::LoadState::BINDING_ERROR, loadState); +} + +TEST_F(DBusDynamicLoadingFullyInvalidConfigTest, LoadsNoAliasedDynamicallyLinkedLibrary) { + std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("MyFirstAlias"); + //The first alias is claimed by another binding, which was defined earlier in the config + EXPECT_FALSE((bool)runtime); + std::shared_ptr<CommonAPI::Runtime> runtime2 = CommonAPI::Runtime::load("MySecondAlias"); + EXPECT_FALSE((bool)runtime2); +} + + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new Environment()); + return RUN_ALL_TESTS(); +} diff --git a/src/test/dbusDynamicLoadingTests/fakeTestBinding/FakeBinding.cpp b/src/test/dbusDynamicLoadingTests/fakeTestBinding/FakeBinding.cpp new file mode 100644 index 0000000..b5280a4 --- /dev/null +++ b/src/test/dbusDynamicLoadingTests/fakeTestBinding/FakeBinding.cpp @@ -0,0 +1,89 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "FakeBinding.h" + + +const CommonAPI::MiddlewareInfo middlewareInfo("Fake", &CommonAPI::Fake::FakeRuntime::getInstance); + + +namespace CommonAPI { +namespace Fake { + +const MiddlewareInfo FakeRuntime::middlewareInfo_ = middlewareInfo; + +__attribute__((constructor)) void registerFakeMiddleware(void) { + Runtime::registerRuntimeLoader("Fake", &FakeRuntime::getInstance); +} + +FakeFactory::FakeFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, std::shared_ptr<MainLoopContext> mainLoopContext): + CommonAPI::Factory(runtime, middlewareInfo) {} + +std::vector<std::string> FakeFactory::getAvailableServiceInstances(const std::string& serviceName, const std::string& serviceDomainName) { + return std::vector<std::string>(); +} + +bool FakeFactory::isServiceInstanceAlive(const std::string& serviceAddress) { + return false; +} + +bool FakeFactory::isServiceInstanceAlive(const std::string& serviceInstanceID, const std::string& serviceName, const std::string& serviceDomainName) { + return false; +} + +void FakeFactory::getAvailableServiceInstancesAsync(GetAvailableServiceInstancesCallback callback, const std::string& serviceName, const std::string& serviceDomainName) {} +void FakeFactory::isServiceInstanceAliveAsync(IsServiceInstanceAliveCallback callback, const std::string& serviceAddress) {} +void FakeFactory::isServiceInstanceAliveAsync(IsServiceInstanceAliveCallback callback, const std::string& serviceInstanceID, const std::string& serviceName, const std::string& serviceDomainName) {} + +std::shared_ptr<Proxy> FakeFactory::createProxy(const char* interfaceId, const std::string& participantId, const std::string& serviceName, const std::string& domain) { + return std::shared_ptr<Proxy>(NULL); +} + +bool FakeFactory::registerAdapter(std::shared_ptr<StubBase> stubBase, const char* interfaceId, const std::string& participantId, const std::string& serviceName, const std::string& domain) { + return false; +} + +bool FakeFactory::unregisterService(const std::string& participantId, const std::string& serviceName, const std::string& domain) { + return false; +} + +std::shared_ptr<FakeServicePublisher> FakeServicePublisher::getInstance() { + static std::shared_ptr<FakeServicePublisher> instance; + if(!instance) { + instance = std::make_shared<FakeServicePublisher>(); + } + return instance; +} + +bool FakeServicePublisher::registerService(const std::string& serviceAddress, std::shared_ptr<FakeStubAdapter> adapter) { + return false; +} + +bool FakeServicePublisher::unregisterService(const std::string& serviceAddress) { + return false; +} + +std::shared_ptr<Runtime> FakeRuntime::getInstance() { + static std::shared_ptr<Runtime> singleton_; + if(!singleton_) { + singleton_ = std::make_shared<FakeRuntime>(); + } + return singleton_; +} + +std::shared_ptr<Factory> FakeRuntime::doCreateFactory(std::shared_ptr<MainLoopContext> mainLoopContext, + const std::string& factoryName, + const bool nullOnInvalidName) { + auto factory = std::make_shared<FakeFactory>(this->shared_from_this(), &middlewareInfo_, mainLoopContext); + return factory; +} + +std::shared_ptr<ServicePublisher> FakeRuntime::getServicePublisher() { + return FakeServicePublisher::getInstance(); +} + +} // namespace Fake +} // namespace CommonAPI diff --git a/src/test/dbusDynamicLoadingTests/fakeTestBinding/FakeBinding.h b/src/test/dbusDynamicLoadingTests/fakeTestBinding/FakeBinding.h new file mode 100644 index 0000000..e1cc96a --- /dev/null +++ b/src/test/dbusDynamicLoadingTests/fakeTestBinding/FakeBinding.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef COMMONAPI_FAKE_FAKE_RUNTIME_H_ +#define COMMONAPI_FAKE_FAKE_RUNTIME_H_ + +#include <CommonAPI/CommonAPI.h> + + +namespace CommonAPI { +namespace Fake { + +class FakeFactory: public Factory { + public: + FakeFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, std::shared_ptr<MainLoopContext> mainLoopContext); + ~FakeFactory() {} + std::vector<std::string> getAvailableServiceInstances(const std::string& serviceName, const std::string& serviceDomainName = "local"); + bool isServiceInstanceAlive(const std::string& serviceAddress); + bool isServiceInstanceAlive(const std::string& serviceInstanceID, const std::string& serviceName, const std::string& serviceDomainName = "local"); + void getAvailableServiceInstancesAsync(GetAvailableServiceInstancesCallback callback, const std::string& serviceName, const std::string& serviceDomainName = "local"); + void isServiceInstanceAliveAsync(IsServiceInstanceAliveCallback callback, const std::string& serviceAddress); + void isServiceInstanceAliveAsync(IsServiceInstanceAliveCallback callback, const std::string& serviceInstanceID, const std::string& serviceName, const std::string& serviceDomainName = "local"); + bool unregisterService(const std::string& participantId, const std::string& serviceName, const std::string& domain); + + protected: + std::shared_ptr<Proxy> createProxy(const char* interfaceId, const std::string& participantId, const std::string& serviceName, const std::string& domain); + bool registerAdapter(std::shared_ptr<StubBase> stubBase, const char* interfaceId, const std::string& participantId, const std::string& serviceName, const std::string& domain); +}; + +class FakeStubAdapter; + +class FakeServicePublisher: public ServicePublisher { +public: + FakeServicePublisher() {} + + static std::shared_ptr<FakeServicePublisher> getInstance(); + + bool registerService(const std::string& serviceAddress, std::shared_ptr<FakeStubAdapter> adapter); + + bool unregisterService(const std::string& serviceAddress); +}; + +class FakeRuntime: public Runtime, public std::enable_shared_from_this<FakeRuntime> { + public: + static std::shared_ptr<Runtime> getInstance(); + + std::shared_ptr<Factory> doCreateFactory(std::shared_ptr<MainLoopContext> mainLoopContext, + const std::string& factoryName, + const bool nullOnInvalidName); + + std::shared_ptr<ServicePublisher> getServicePublisher(); + + static const MiddlewareInfo middlewareInfo_; +}; + +} // namespace Fake +} // namespace CommonAPI + + +extern "C" const CommonAPI::MiddlewareInfo middlewareInfo; + +#endif // COMMONAPI_FAKE_FAKE_RUNTIME_H_ diff --git a/src/test/fakeLegacyService/fake/legacy/service/LegacyInterface.h b/src/test/fake/legacy/service/LegacyInterface.h index c1920a6..6a604d5 100644 --- a/src/test/fakeLegacyService/fake/legacy/service/LegacyInterface.h +++ b/src/test/fake/legacy/service/LegacyInterface.h @@ -10,7 +10,9 @@ +#if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION +#endif #include <CommonAPI/types.h> @@ -29,7 +31,8 @@ class LegacyInterface { }; const char* LegacyInterface::getInterfaceId() { - return "fake.legacy.service.LegacyInterface"; + static const char* interfaceId = "fake.legacy.service.LegacyInterface"; + return interfaceId; } CommonAPI::Version LegacyInterface::getInterfaceVersion() { diff --git a/src/test/fakeLegacyService/fake/legacy/service/LegacyInterfaceDBusProxy.cpp b/src/test/fake/legacy/service/LegacyInterfaceDBusProxy.cpp index 7006015..7006015 100644 --- a/src/test/fakeLegacyService/fake/legacy/service/LegacyInterfaceDBusProxy.cpp +++ b/src/test/fake/legacy/service/LegacyInterfaceDBusProxy.cpp diff --git a/src/test/fakeLegacyService/fake/legacy/service/LegacyInterfaceDBusProxy.h b/src/test/fake/legacy/service/LegacyInterfaceDBusProxy.h index 361ed2b..05782d8 100644 --- a/src/test/fakeLegacyService/fake/legacy/service/LegacyInterfaceDBusProxy.h +++ b/src/test/fake/legacy/service/LegacyInterfaceDBusProxy.h @@ -8,9 +8,11 @@ #ifndef FAKE_LEGACY_SERVICE_Legacy_Interface_DBUS_PROXY_H_ #define FAKE_LEGACY_SERVICE_Legacy_Interface_DBUS_PROXY_H_ -#include "fakeLegacyService/fake/legacy/service/LegacyInterfaceProxyBase.h" +#include <fake/legacy/service/LegacyInterfaceProxyBase.h> +#if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION +#endif #include <CommonAPI/DBus/DBusFactory.h> #include <CommonAPI/DBus/DBusProxy.h> diff --git a/src/test/fakeLegacyService/fake/legacy/service/LegacyInterfaceProxy.h b/src/test/fake/legacy/service/LegacyInterfaceProxy.h index 0d71c69..51fff47 100644 --- a/src/test/fakeLegacyService/fake/legacy/service/LegacyInterfaceProxy.h +++ b/src/test/fake/legacy/service/LegacyInterfaceProxy.h @@ -10,7 +10,9 @@ #include "LegacyInterfaceProxyBase.h" +#if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION +#endif #undef COMMONAPI_INTERNAL_COMPILATION diff --git a/src/test/fakeLegacyService/fake/legacy/service/LegacyInterfaceProxyBase.h b/src/test/fake/legacy/service/LegacyInterfaceProxyBase.h index ee82c89..f6d8467 100644 --- a/src/test/fakeLegacyService/fake/legacy/service/LegacyInterfaceProxyBase.h +++ b/src/test/fake/legacy/service/LegacyInterfaceProxyBase.h @@ -12,7 +12,9 @@ + #if !defined (COMMONAPI_INTERNAL_COMPILATION) #define COMMONAPI_INTERNAL_COMPILATION + #endif #include <CommonAPI/Proxy.h> |