summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schanda <schanda@itestra.de>2013-05-27 11:47:36 +0200
committerJohannes Schanda <schanda@itestra.de>2013-05-27 11:47:36 +0200
commitd5c7906b728d6a03c468d9c4211417f97702494a (patch)
treec5a52ce78f80d009ea89ddee8c5bfdcce57ee532
parentd505e2e38717f3a22be24cc66b5b6559d4efe69f (diff)
parentf330e0d83eb92b07709a305f515a152d714ded0f (diff)
downloadgenivi-common-api-dbus-runtime-d5c7906b728d6a03c468d9c4211417f97702494a.tar.gz
Merge branch 'master' into genivi_releasegenivi_release_42.0.6
Conflicts: TODO
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am197
-rw-r--r--README54
-rw-r--r--configure.ac32
-rw-r--r--src/CommonAPI/DBus/DBusAttribute.h4
-rw-r--r--src/CommonAPI/DBus/DBusConnection.cpp327
-rw-r--r--src/CommonAPI/DBus/DBusConnection.h196
-rw-r--r--src/CommonAPI/DBus/DBusDaemonProxy.cpp40
-rw-r--r--src/CommonAPI/DBus/DBusDaemonProxy.h16
-rw-r--r--src/CommonAPI/DBus/DBusFactory.cpp41
-rw-r--r--src/CommonAPI/DBus/DBusFactory.h6
-rw-r--r--src/CommonAPI/DBus/DBusInputStream.h5
-rw-r--r--src/CommonAPI/DBus/DBusMainLoopContext.cpp143
-rw-r--r--src/CommonAPI/DBus/DBusMainLoopContext.h94
-rw-r--r--src/CommonAPI/DBus/DBusMessage.cpp18
-rw-r--r--src/CommonAPI/DBus/DBusMessage.h8
-rw-r--r--src/CommonAPI/DBus/DBusObjectManager.cpp182
-rw-r--r--src/CommonAPI/DBus/DBusObjectManager.h30
-rw-r--r--src/CommonAPI/DBus/DBusOutputStream.cpp9
-rw-r--r--src/CommonAPI/DBus/DBusOutputStream.h5
-rw-r--r--src/CommonAPI/DBus/DBusProxy.cpp43
-rw-r--r--src/CommonAPI/DBus/DBusProxy.h16
-rw-r--r--src/CommonAPI/DBus/DBusProxyBase.cpp46
-rw-r--r--src/CommonAPI/DBus/DBusProxyBase.h64
-rw-r--r--src/CommonAPI/DBus/DBusProxyConnection.h49
-rw-r--r--src/CommonAPI/DBus/DBusRuntime.cpp4
-rw-r--r--src/CommonAPI/DBus/DBusRuntime.h2
-rw-r--r--src/CommonAPI/DBus/DBusServiceRegistry.cpp33
-rw-r--r--src/CommonAPI/DBus/DBusStubAdapter.cpp45
-rw-r--r--src/CommonAPI/DBus/DBusStubAdapter.h9
-rw-r--r--src/CommonAPI/DBus/DBusStubAdapterHelper.h1
-rw-r--r--src/test/DBusAddressTranslatorTest.cpp29
-rw-r--r--src/test/DBusCommunicationTest.cpp119
-rw-r--r--src/test/DBusConnectionTest.cpp372
-rw-r--r--src/test/DBusDaemonProxyTest.cpp21
-rw-r--r--src/test/DBusFactoryTest.cpp1
-rw-r--r--src/test/DBusMainLoopIntegrationTest.cpp613
-rw-r--r--src/test/DBusMultipleConnectionTest.cpp26
-rw-r--r--src/test/DBusProxyTest.cpp68
-rw-r--r--src/test/DBusServiceRegistryTest.cpp19
-rw-r--r--src/test/DBusStubAdapterTest.cpp1
-rw-r--r--src/test/DBusTestUtils.h41
-rw-r--r--src/test/DemoMainLoop.h334
-rw-r--r--src/test/commonapi/tests/DerivedTypeCollection.cpp10
-rw-r--r--src/test/commonapi/tests/DerivedTypeCollection.h50
-rw-r--r--src/test/commonapi/tests/PredefinedTypeCollection.h61
-rw-r--r--src/test/commonapi/tests/TestInterfaceDBusProxy.cpp19
-rw-r--r--src/test/commonapi/tests/TestInterfaceDBusProxy.h12
-rw-r--r--src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp27
-rw-r--r--src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h2
-rw-r--r--src/test/commonapi/tests/TestInterfaceProxy.h132
-rw-r--r--src/test/commonapi/tests/TestInterfaceProxyBase.h7
-rw-r--r--src/test/commonapi/tests/TestInterfaceStub.h50
-rw-r--r--src/test/commonapi/tests/TestInterfaceStubDefault.cpp59
-rw-r--r--src/test/commonapi/tests/TestInterfaceStubDefault.h15
-rw-r--r--src/test/fakeLegacyService/sendToFakeLegacyService.py24
-rw-r--r--src/test/test-derived-types.fidl32
-rw-r--r--src/test/test-interface-proxy.fidl3
58 files changed, 2970 insertions, 897 deletions
diff --git a/.gitignore b/.gitignore
index 29281ae..36c6418 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,4 @@
/DBusAddressTranslatorTest
/.pydevproject
/DBusServiceRegistryTest
+/DBusConnectionTest
diff --git a/Makefile.am b/Makefile.am
index 0a42ea5..f5e43e1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,55 +4,65 @@ EXTRA_DIST = LICENSE LICENSE_dbus_patch LICENSE_MurmurHash
MOSTLYCLEANFILES =
AM_CPPFLAGS = \
- -I$(top_srcdir)/src \
- -I$(top_srcdir)/src/test \
- ${COMMONAPI_CFLAGS} \
- ${DBUS_CFLAGS}
-
+ -include $(top_builddir)/build-aux/config.h \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/test \
+ ${COMMONAPI_CFLAGS} \
+ ${DBUS_CFLAGS}
-LDADD = \
- ${COMMONAPI_LIBS} \
- ${DBUS_LIBS}
+AM_LDFLAGS = \
+ ${COMMONAPI_LIBS} \
+ ${DBUS_LIBS}
+
+noinst_LTLIBRARIES =
lib_LTLIBRARIES =
-lib_LIBRARIES =
+
+# Library interface (not package version!)
+LIBCOMMONAPI_DBUS_CURRENT=2
+LIBCOMMONAPI_DBUS_REVISION=0
+LIBCOMMONAPI_DBUS_AGE=0
# ------------------------------------------------------------------------------
-lib_LTLIBRARIES += libmurmurhash-internal.la
+noinst_LTLIBRARIES += libmurmurhash-internal.la
libmurmurhash_internal_la_SOURCES = \
- src/murmurhash/MurmurHash3.h \
- src/murmurhash/MurmurHash3.cpp
+ src/murmurhash/MurmurHash3.h \
+ src/murmurhash/MurmurHash3.cpp
# ------------------------------------------------------------------------------
lib_LTLIBRARIES += libCommonAPI-DBus.la
libCommonAPI_DBus_la_SOURCES = \
- src/CommonAPI/DBus/DBusAddressTranslator.cpp \
- src/CommonAPI/DBus/DBusConnection.cpp \
- src/CommonAPI/DBus/DBusDaemonProxy.cpp \
- src/CommonAPI/DBus/DBusError.cpp \
- src/CommonAPI/DBus/DBusFunctionalHash.cpp \
- src/CommonAPI/DBus/DBusInputStream.cpp \
- src/CommonAPI/DBus/DBusMessage.cpp \
- src/CommonAPI/DBus/DBusObjectManager.cpp \
- src/CommonAPI/DBus/DBusOutputStream.cpp \
- src/CommonAPI/DBus/DBusProxyBase.cpp \
- src/CommonAPI/DBus/DBusProxy.cpp \
- src/CommonAPI/DBus/DBusFactory.cpp \
- src/CommonAPI/DBus/DBusRuntime.cpp \
- src/CommonAPI/DBus/DBusServiceRegistry.cpp \
- src/CommonAPI/DBus/DBusServiceStatusEvent.cpp \
- src/CommonAPI/DBus/DBusStubAdapter.cpp
+ src/CommonAPI/DBus/DBusAddressTranslator.cpp \
+ src/CommonAPI/DBus/DBusConnection.cpp \
+ src/CommonAPI/DBus/DBusDaemonProxy.cpp \
+ src/CommonAPI/DBus/DBusError.cpp \
+ src/CommonAPI/DBus/DBusFunctionalHash.cpp \
+ src/CommonAPI/DBus/DBusInputStream.cpp \
+ src/CommonAPI/DBus/DBusMainLoopContext.cpp \
+ src/CommonAPI/DBus/DBusMessage.cpp \
+ src/CommonAPI/DBus/DBusObjectManager.cpp \
+ src/CommonAPI/DBus/DBusOutputStream.cpp \
+ src/CommonAPI/DBus/DBusProxyBase.cpp \
+ src/CommonAPI/DBus/DBusProxy.cpp \
+ src/CommonAPI/DBus/DBusFactory.cpp \
+ src/CommonAPI/DBus/DBusRuntime.cpp \
+ src/CommonAPI/DBus/DBusServiceRegistry.cpp \
+ src/CommonAPI/DBus/DBusServiceStatusEvent.cpp \
+ src/CommonAPI/DBus/DBusStubAdapter.cpp
libCommonAPI_DBus_la_LIBADD = \
- libmurmurhash-internal.la \
- ${COMMONAPI_LIBS}
+ libmurmurhash-internal.la \
+ ${COMMONAPI_LIBS}
+libCommonAPI_DBus_la_LDFLAGS = \
+ ${AM_LDFLAGS} \
+ -version-info ${LIBCOMMONAPI_DBUS_CURRENT}:${LIBCOMMONAPI_DBUS_REVISION}:${LIBCOMMONAPI_DBUS_AGE}
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/DBusAddressTranslator.h \
+ src/CommonAPI/DBus/DBusAttribute.h \
src/CommonAPI/DBus/DBusConnection.h \
src/CommonAPI/DBus/DBusDaemonProxy.h \
src/CommonAPI/DBus/DBusError.h \
@@ -60,6 +70,7 @@ CommonAPI_DBus_include_HEADERS = \
src/CommonAPI/DBus/DBusFunctionalHash.h \
src/CommonAPI/DBus/DBusHelper.h \
src/CommonAPI/DBus/DBusInputStream.h \
+ src/CommonAPI/DBus/DBusMainLoopContext.h \
src/CommonAPI/DBus/DBusMessage.h \
src/CommonAPI/DBus/DBusMultiEvent.h \
src/CommonAPI/DBus/DBusObjectManager.h \
@@ -68,15 +79,15 @@ CommonAPI_DBus_include_HEADERS = \
src/CommonAPI/DBus/DBusProxy.h \
src/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.h \
src/CommonAPI/DBus/DBusProxyConnection.h \
- src/CommonAPI/DBus/DBusFactory.h \
- src/CommonAPI/DBus/DBusProxyHelper.h \
- src/CommonAPI/DBus/DBusRuntime.h \
- src/CommonAPI/DBus/DBusSerializableArguments.h \
- src/CommonAPI/DBus/DBusServiceRegistry.h \
- src/CommonAPI/DBus/DBusServiceStatusEvent.h \
- src/CommonAPI/DBus/DBusStubAdapter.h \
- src/CommonAPI/DBus/DBusStubAdapterHelper.h \
- src/CommonAPI/DBus/DBusUtils.h
+ src/CommonAPI/DBus/DBusFactory.h \
+ src/CommonAPI/DBus/DBusProxyHelper.h \
+ src/CommonAPI/DBus/DBusRuntime.h \
+ src/CommonAPI/DBus/DBusSerializableArguments.h \
+ src/CommonAPI/DBus/DBusServiceRegistry.h \
+ src/CommonAPI/DBus/DBusServiceStatusEvent.h \
+ src/CommonAPI/DBus/DBusStubAdapter.h \
+ src/CommonAPI/DBus/DBusStubAdapterHelper.h \
+ src/CommonAPI/DBus/DBusUtils.h
pkgconfigdir = ${libdir}/pkgconfig
pkgconfig_DATA = CommonAPI-DBus.pc
@@ -85,46 +96,60 @@ pkgconfig_DATA = CommonAPI-DBus.pc
if ENABLE_TESTS
TestInterfaceSources = \
- src/test/commonapi/tests/DerivedTypeCollection.cpp \
- 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/commonapi/tests/DerivedTypeCollection.cpp \
+ 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
check_PROGRAMS = \
- DBusServiceRegistryTest \
- DBusProxyTest \
- DBusAddressTranslatorTest \
- DBusInputStreamTest \
- DBusOutputStreamTest \
- DBusRuntimeTest \
- DBusFactoryTest \
- DBusVariantTest \
- DBusTypeStreamTest \
- DBusVariantOutputStreamTest \
- DBusDaemonProxyTest \
- DBusCommunicationTest \
- DBusMultipleConnectionTest \
- DBusBenchmarkingTest
-
-
-TESTS = ${check_PROGRAMS}
+ DBusMainLoopIntegrationTest \
+ DBusConnectionTest \
+ DBusServiceRegistryTest \
+ DBusProxyTest \
+ DBusAddressTranslatorTest \
+ DBusInputStreamTest \
+ DBusOutputStreamTest \
+ DBusRuntimeTest \
+ DBusFactoryTest \
+ DBusVariantTest \
+ DBusTypeStreamTest \
+ DBusVariantOutputStreamTest \
+ DBusDaemonProxyTest \
+ DBusCommunicationTest \
+ DBusMultipleConnectionTest \
+ DBusBenchmarkingTest
+
+
+TESTS = ${check_PROGRAMS}
LDADD_FOR_GTEST = libCommonAPI-DBus.la ${GTEST_LIBS} ${LDADD}
+DBusMainLoopIntegrationTest_SOURCES = \
+ src/test/DBusMainLoopIntegrationTest.cpp \
+ ${TestInterfaceSources}
+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}
+ src/test/DBusServiceRegistryTest.cpp \
+ ${TestInterfaceSources}
DBusServiceRegistryTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
DBusServiceRegistryTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusServiceRegistryTest_LDADD = ${LDADD_FOR_GTEST}
DBusAddressTranslatorTest_SOURCES = \
- src/test/DBusAddressTranslatorTest.cpp \
- ${TestInterfaceSources}
+ src/test/DBusAddressTranslatorTest.cpp \
+ ${TestInterfaceSources}
DBusAddressTranslatorTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
DBusAddressTranslatorTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusAddressTranslatorTest_LDADD = ${LDADD_FOR_GTEST}
+DBusConnectionTest_SOURCES = src/test/DBusConnectionTest.cpp
+DBusConnectionTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusConnectionTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusConnectionTest_LDADD = ${LDADD_FOR_GTEST}
+
DBusTypeStreamTest_SOURCES = src/test/DBusTypeStreamTest.cpp
DBusTypeStreamTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
DBusTypeStreamTest_CXXFLAGS = ${GTEST_CXXFLAGS}
@@ -141,8 +166,8 @@ DBusBenchmarkingTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusBenchmarkingTest_LDADD = ${LDADD_FOR_GTEST}
DBusCommunicationTest_SOURCES = \
- src/test/DBusCommunicationTest.cpp \
- ${TestInterfaceSources}
+ src/test/DBusCommunicationTest.cpp \
+ ${TestInterfaceSources}
DBusCommunicationTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
DBusCommunicationTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusCommunicationTest_LDADD = ${LDADD_FOR_GTEST}
@@ -153,22 +178,22 @@ DBusDaemonProxyTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusDaemonProxyTest_LDADD = ${LDADD_FOR_GTEST}
DBusInputStreamTest_SOURCES = \
- src/test/DBusInputStreamTest.cpp \
- ${TestInterfaceSources}
+ src/test/DBusInputStreamTest.cpp \
+ ${TestInterfaceSources}
DBusInputStreamTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
DBusInputStreamTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusInputStreamTest_LDADD = ${LDADD_FOR_GTEST}
DBusOutputStreamTest_SOURCES = \
- src/test/DBusOutputStreamTest.cpp \
- ${TestInterfaceSources}
+ src/test/DBusOutputStreamTest.cpp \
+ ${TestInterfaceSources}
DBusOutputStreamTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
DBusOutputStreamTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusOutputStreamTest_LDADD = ${LDADD_FOR_GTEST}
DBusFactoryTest_SOURCES = \
- src/test/DBusFactoryTest.cpp \
- ${TestInterfaceSources}
+ src/test/DBusFactoryTest.cpp \
+ ${TestInterfaceSources}
DBusFactoryTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
DBusFactoryTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusFactoryTest_LDADD = ${LDADD_FOR_GTEST}
@@ -178,20 +203,16 @@ DBusRuntimeTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
DBusRuntimeTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusRuntimeTest_LDADD = ${LDADD_FOR_GTEST}
-#DBusStubAdapterTest_SOURCES = src/test/DBusStubAdapterTest.cpp
-#DBusStubAdapterTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
-#DBusStubAdapterTest_CXXFLAGS = ${GTEST_CXXFLAGS}
-#DBusStubAdapterTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
-
-DBusMultipleConnectionTest_SOURCES = src/test/DBusMultipleConnectionTest.cpp \
- ${TestInterfaceSources}
+DBusMultipleConnectionTest_SOURCES = \
+ src/test/DBusMultipleConnectionTest.cpp \
+ ${TestInterfaceSources}
DBusMultipleConnectionTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
DBusMultipleConnectionTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusMultipleConnectionTest_LDADD = ${LDADD_FOR_GTEST}
DBusProxyTest_SOURCES = \
- src/test/DBusProxyTest.cpp \
- ${TestInterfaceSources}
+ src/test/DBusProxyTest.cpp \
+ ${TestInterfaceSources}
DBusProxyTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
DBusProxyTest_CXXFLAGS = ${GTEST_CXXFLAGS}
DBusProxyTest_LDADD = ${LDADD_FOR_GTEST}
@@ -212,9 +233,9 @@ MOSTLYCLEANFILES += ${DX_CLEANFILES}
# ------------------------------------------------------------------------------
MAINTAINERCLEANFILES = \
- Makefile.in \
- aclocal.m4 \
- configure
+ Makefile.in \
+ aclocal.m4 \
+ configure
clean-local:
-rm -rf src-gen
@@ -223,4 +244,4 @@ maintainer-clean-local:
-rm -rf build-aux
-rm -f config.h.in*
-rm -f m4/libtool*.m4
- -rm -f m4/lt*.m4 \ No newline at end of file
+ -rm -f m4/lt*.m4
diff --git a/README b/README
index 5b2741d..d98843a 100644
--- a/README
+++ b/README
@@ -49,12 +49,6 @@ CommonAPI-D-Bus-Tools - The eclipse based tools for CommonAPI D-Bus. This is the
To build this package the CommonAPI library and a version of libdbus patched with the marshaling patch must be available through PkgConfig.
-
-== Build Instructions
-
-
-To build this package CommonAPI and a version of libdbus patched with the marshaling patch must be available.
-
Instructions for making a patched version of libdbus available in /usr/local:
----
# wget http://dbus.freedesktop.org/releases/dbus/dbus-1.4.16.tar.gz
@@ -89,6 +83,54 @@ Use autotools to build this package withthe above requirements available through
----
If the environment variable GTEST_CONFIG is set to the path of the gtest-config script in a Gtest tree test will also be built.
+=== Defining D-Bus Service Parameters
+Normally, a CommonAPI address, format
+----
+<Domain>:<ServiceID>:<InstanceID>
+----
+
+is mapped to a D-Bus address the following way:
+----
+# D-Bus Interface Name = ServiceID
+# D-Bus Connection Name = InstanceID
+# D-Bus Object Path = InstanceID with a preceding '/' and all '.' replaced with '/'
+----
+For Domain, only the value "local" is allowed in this context, and it has no influence on the associated D-Bus service address values.
+
+In case a proxy or a service should not use the default mapping, it is possible to define config files that use the CommonAPI Address
+as a key in order to map any combination of D-Bus address values to it. The config files can be defined locally per binary, globally
+per binary or globally for all binaries. If more than one config file is defined and a CommonAPI address is defined more than once
+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:
+----
+# 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"
+# Global: "/etc/CommonApiDBus/dbusAddresses.conf"
+----
+
+Each config file may have an arbitrary number of entries of the following format, with each entry being separated from the others by a newline:
+----
+[<CommonAPI Address>]
+dbus_connection=<valid D-Bus Connection Name>
+dbus_object=<valid D-Bus Object Path>
+dbus_interface=<valid D-Bus Interface Name>
+dbus_predefined=<true/false>
+----
+All "dbus_*"-values are optional. For each such omitted value the default value as described above will be used. For "dbus_predefined",
+the default value is "false".
+
+"dbus_predefined" should be used if the associated service of a proxy is a legacy service that does not provide the
+"org.freedesktop.DBus.ObjectManager" interface.
+----
+# If "dbus_predefined" is set to "false" (which is default), a proxy will try to verify the existence of the specific interface
+ at the specific connection name and object path, using the "org.freedesktop.DBus.ObjectManager" interface, before it is marked as available.
+# If "dbus_predefined" is set to "true", a proxy is marked as available as soon as the connection name of the associated
+ service is visible. No further checks will be executed.
+----
+
+
== Working on the code & contribution
.First get the code from the git:
diff --git a/configure.ac b/configure.ac
index 90ae370..3ab0d8f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,17 +1,19 @@
-AC_PREREQ(2.61)
+AC_PREREQ([2.61])
AC_INIT([GENIVI Common API DBus C++ Library],
[2.0],
[],
[CommonAPI-DBus])
+AC_USE_SYSTEM_EXTENSIONS
+
AC_CONFIG_MACRO_DIR([m4])
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([build-aux/config.h])
AC_CONFIG_FILES([
- Makefile
- CommonAPI-DBus.pc
- CommonAPI-DBus-uninstalled.pc])
+ Makefile
+ CommonAPI-DBus.pc
+ CommonAPI-DBus-uninstalled.pc])
AC_CANONICAL_SYSTEM
@@ -31,6 +33,13 @@ LT_INIT
PKG_PROG_PKG_CONFIG
PKG_CHECK_MODULES(COMMONAPI, [CommonAPI >= 0.7])
PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.4.6])
+PKG_CHECK_MODULES(GLIB, [glib-2.0],
+ [],
+ [
+ echo "WARNING: No glib found, tests will not be compiled!"
+ TESTS_CAN_BE_EXECUTED=false
+ ]
+)
GTEST_MIN_VERSION="1.6.0"
GTEST_URL="http://code.google.com/p/googletest"
@@ -58,8 +67,7 @@ AS_IF([test -f "${GTEST_CONFIG}"],
[]
)
-AM_CONDITIONAL(ENABLE_TESTS, [test -f "${GTEST_CONFIG}"])
-
+AM_CONDITIONAL(ENABLE_TESTS, [test -f "${GTEST_CONFIG}" && ${TESTS_CAN_BE_EXECUTED}])
# Doxygen support
DX_HTML_FEATURE(ON)
@@ -71,17 +79,17 @@ DX_XML_FEATURE(OFF)
DX_PDF_FEATURE(OFF)
DX_PS_FEATURE(OFF)
DX_INIT_DOXYGEN(${PACKAGE_NAME}, doxygen.cfg, doc)
-
+
AC_MSG_RESULT([
$PACKAGE_NAME v$VERSION
enable docs: ${ENABLE_DOCS}
- COMMONAPI_CFLAGS: ${COMMONAPI_CFLAGS}
- COMMONAPI_LIBS: ${COMMONAPI_LIBS}
+ COMMONAPI_CFLAGS: ${COMMONAPI_CFLAGS}
+ COMMONAPI_LIBS: ${COMMONAPI_LIBS}
- DBUS_CFLAGS: ${DBUS_CFLAGS}
- DBUS_LIBS: ${DBUS_LIBS}
+ DBUS_CFLAGS: ${DBUS_CFLAGS}
+ DBUS_LIBS: ${DBUS_LIBS}
GTEST_CONFIG: ${GTEST_CONFIG}
GTEST_CPPFLAGS: ${GTEST_CPPFLAGS}
@@ -95,4 +103,4 @@ AC_MSG_RESULT([
LDFLAGS: ${LDFLAGS}
])
-AC_OUTPUT \ No newline at end of file
+AC_OUTPUT
diff --git a/src/CommonAPI/DBus/DBusAttribute.h b/src/CommonAPI/DBus/DBusAttribute.h
index 04d1e72..4844b87 100644
--- a/src/CommonAPI/DBus/DBusAttribute.h
+++ b/src/CommonAPI/DBus/DBusAttribute.h
@@ -31,11 +31,9 @@ class DBusReadonlyAttribute: public _AttributeType {
assert(getMethodName);
}
- CallStatus getValue(ValueType& value) const {
- CallStatus callStatus;
+ void getValue(CallStatus& callStatus, ValueType& value) const {
DBusProxyHelper<DBusSerializableArguments<>,
DBusSerializableArguments<ValueType> >::callMethodWithReply(dbusProxy_, getMethodName_, "", callStatus, value);
- return callStatus;
}
std::future<CallStatus> getValueAsync(AttributeAsyncCallback attributeAsyncCallback) {
diff --git a/src/CommonAPI/DBus/DBusConnection.cpp b/src/CommonAPI/DBus/DBusConnection.cpp
index 4b4c406..df77e95 100644
--- a/src/CommonAPI/DBus/DBusConnection.cpp
+++ b/src/CommonAPI/DBus/DBusConnection.cpp
@@ -29,17 +29,43 @@ DBusObjectPathVTable DBusConnection::libdbusObjectPathVTable_ = {
&DBusConnection::onLibdbusObjectPathMessageThunk
};
-void DBusConnection::dispatch() {
- while (!stopDispatching_ && readWriteDispatch(10)) {
+void DBusConnection::dispatch(std::shared_ptr<DBusConnection> selfReference) {
+ while (!stopDispatching_ && readWriteDispatch(10) && !selfReference.unique()) {
+ if(pauseDispatching_) {
+ dispatchSuspendLock_.lock();
+ dispatchSuspendLock_.unlock();
+ }
}
}
+bool DBusConnection::readWriteDispatch(int timeoutMilliseconds) {
+ if(isConnected()) {
+ const dbus_bool_t libdbusSuccess = dbus_connection_read_write_dispatch(libdbusConnection_,
+ timeoutMilliseconds);
+ return libdbusSuccess;
+ }
+ return false;
+}
+
+void DBusConnection::suspendDispatching() const {
+ dispatchSuspendLock_.lock();
+ pauseDispatching_ = true;
+}
+
+void DBusConnection::resumeDispatching() const {
+ pauseDispatching_ = false;
+ dispatchSuspendLock_.unlock();
+}
+
DBusConnection::DBusConnection(BusType busType) :
busType_(busType),
libdbusConnection_(NULL),
dbusConnectionStatusEvent_(this),
- isLibdbusSignalFilterAdded_(false),
- stopDispatching_(false) {
+ stopDispatching_(false),
+ pauseDispatching_(false),
+ dispatchThread_(NULL),
+ dbusObjectMessageHandler_(),
+ watchContext_(NULL) {
dbus_threads_init_default();
}
@@ -47,27 +73,176 @@ DBusConnection::DBusConnection(::DBusConnection* libDbusConnection) :
busType_(WRAPPED),
libdbusConnection_(libDbusConnection),
dbusConnectionStatusEvent_(this),
- isLibdbusSignalFilterAdded_(false),
- stopDispatching_(false) {
+ stopDispatching_(false),
+ pauseDispatching_(false),
+ dispatchThread_(NULL),
+ dbusObjectMessageHandler_(),
+ watchContext_(NULL) {
dbus_threads_init_default();
}
+void DBusConnection::setObjectPathMessageHandler(DBusObjectPathMessageHandler handler) {
+ dbusObjectMessageHandler_ = handler;
+}
+
+bool DBusConnection::isObjectPathMessageHandlerSet() {
+ return dbusObjectMessageHandler_.operator bool();
+}
+
DBusConnection::~DBusConnection() {
- if (isConnected()) {
- disconnect();
+ if(auto lockedContext = mainLoopContext_.lock()) {
+ dbus_connection_set_watch_functions(libdbusConnection_, NULL, NULL, NULL, NULL, NULL);
+ dbus_connection_set_timeout_functions(libdbusConnection_, NULL, NULL, NULL, NULL, NULL);
+
+ lockedContext->deregisterDispatchSource(dispatchSource_);
+ delete watchContext_;
+ delete dispatchSource_;
+ }
+
+ disconnect();
+}
+
+
+bool DBusConnection::attachMainLoopContext(std::weak_ptr<MainLoopContext> mainLoopContext) {
+ mainLoopContext_ = mainLoopContext;
+
+ if (auto lockedContext = mainLoopContext_.lock()) {
+ dispatchSource_ = new DBusDispatchSource(this);
+ watchContext_ = new WatchContext(mainLoopContext_, dispatchSource_);
+ lockedContext->registerDispatchSource(dispatchSource_);
+
+ dbus_connection_set_wakeup_main_function(
+ libdbusConnection_,
+ &DBusConnection::onWakeupMainContext,
+ &mainLoopContext_,
+ NULL);
+
+ bool success = dbus_connection_set_watch_functions(
+ libdbusConnection_,
+ &DBusConnection::onAddWatch,
+ &DBusConnection::onRemoveWatch,
+ &DBusConnection::onToggleWatch,
+ watchContext_,
+ NULL);
+
+ if (!success) {
+ return false;
+ }
+
+ success = dbus_connection_set_timeout_functions(
+ libdbusConnection_,
+ &DBusConnection::onAddTimeout,
+ &DBusConnection::onRemoveTimeout,
+ &DBusConnection::onToggleTimeout,
+ &mainLoopContext_,
+ NULL);
+
+ if (!success) {
+ dbus_connection_set_watch_functions(libdbusConnection_, NULL, NULL, NULL, NULL, NULL);
+ return false;
+ }
+
+ return true;
}
+ return false;
}
-bool DBusConnection::connect() {
+void DBusConnection::onWakeupMainContext(void* data) {
+ std::weak_ptr<MainLoopContext>* mainloop = static_cast<std::weak_ptr<MainLoopContext>*>(data);
+ assert(mainloop);
+
+ if(auto lockedContext = mainloop->lock()) {
+ lockedContext->wakeup();
+ }
+}
+
+
+dbus_bool_t DBusConnection::onAddWatch(::DBusWatch* libdbusWatch, void* data) {
+ WatchContext* watchContext = static_cast<WatchContext*>(data);
+ assert(watchContext);
+
+ DBusWatch* dbusWatch = new DBusWatch(libdbusWatch, watchContext->mainLoopContext_);
+ dbusWatch->addDependentDispatchSource(watchContext->dispatchSource_);
+ dbus_watch_set_data(libdbusWatch, dbusWatch, NULL);
+
+ if (dbusWatch->isReadyToBeWatched()) {
+ dbusWatch->startWatching();
+ }
+
+ return TRUE;
+}
+
+void DBusConnection::onRemoveWatch(::DBusWatch* libdbusWatch, void* data) {
+ assert(static_cast<WatchContext*>(data));
+
+ DBusWatch* dbusWatch = static_cast<DBusWatch*>(dbus_watch_get_data(libdbusWatch));
+ if(dbusWatch->isReadyToBeWatched()) {
+ dbusWatch->stopWatching();
+ }
+ dbus_watch_set_data(libdbusWatch, NULL, NULL);
+ delete dbusWatch;
+}
+
+void DBusConnection::onToggleWatch(::DBusWatch* libdbusWatch, void* data) {
+ assert(static_cast<WatchContext*>(data));
+
+ DBusWatch* dbusWatch = static_cast<DBusWatch*>(dbus_watch_get_data(libdbusWatch));
+
+ if (dbusWatch->isReadyToBeWatched()) {
+ dbusWatch->startWatching();
+ } else {
+ dbusWatch->stopWatching();
+ }
+}
+
+
+dbus_bool_t DBusConnection::onAddTimeout(::DBusTimeout* libdbusTimeout, void* data) {
+ std::weak_ptr<MainLoopContext>* mainloop = static_cast<std::weak_ptr<MainLoopContext>*>(data);
+ assert(mainloop);
+
+ DBusTimeout* dbusTimeout = new DBusTimeout(libdbusTimeout, *mainloop);
+ dbus_timeout_set_data(libdbusTimeout, dbusTimeout, NULL);
+
+ if (dbusTimeout->isReadyToBeMonitored()) {
+ dbusTimeout->startMonitoring();
+ }
+
+ return TRUE;
+}
+
+void DBusConnection::onRemoveTimeout(::DBusTimeout* libdbusTimeout, void* data) {
+ assert(static_cast<std::weak_ptr<MainLoopContext>*>(data));
+
+ DBusTimeout* dbusTimeout = static_cast<DBusTimeout*>(dbus_timeout_get_data(libdbusTimeout));
+ dbusTimeout->stopMonitoring();
+ dbus_timeout_set_data(libdbusTimeout, NULL, NULL);
+ delete dbusTimeout;
+}
+
+void DBusConnection::onToggleTimeout(::DBusTimeout* dbustimeout, void* data) {
+ assert(static_cast<std::weak_ptr<MainLoopContext>*>(data));
+
+ DBusTimeout* timeout = static_cast<DBusTimeout*>(dbus_timeout_get_data(dbustimeout));
+
+ if (timeout->isReadyToBeMonitored()) {
+ timeout->startMonitoring();
+ } else {
+ timeout->stopMonitoring();
+ }
+}
+
+
+bool DBusConnection::connect(bool startDispatchThread) {
DBusError dbusError;
- return connect(dbusError);
+ return connect(dbusError, startDispatchThread);
}
-bool DBusConnection::connect(DBusError& dbusError) {
+bool DBusConnection::connect(DBusError& dbusError, bool startDispatchThread) {
assert(!dbusError);
- if (isConnected())
+ if (isConnected()) {
return true;
+ }
const ::DBusBusType libdbusType = static_cast<DBusBusType>(busType_);
@@ -83,8 +258,10 @@ bool DBusConnection::connect(DBusError& dbusError) {
initLibdbusSignalFilterAfterConnect();
- stopDispatching_ = false;
- dispatchThread_ = std::thread(std::bind(&DBusConnection::dispatch, this));
+ if(startDispatchThread) {
+ dispatchThread_ = new std::thread(&DBusConnection::dispatch, this, this->shared_from_this());
+ }
+ stopDispatching_ = !startDispatchThread;
dbusConnectionStatusEvent_.notifyListeners(AvailabilityStatus::AVAILABLE);
@@ -94,6 +271,8 @@ bool DBusConnection::connect(DBusError& dbusError) {
void DBusConnection::disconnect() {
std::lock_guard<std::mutex> dbusConnectionLock(libdbusConnectionGuard_);
if (isConnected()) {
+ dbusConnectionStatusEvent_.notifyListeners(AvailabilityStatus::NOT_AVAILABLE);
+
if (!dbusSignalMatchRulesMap_.empty()) {
dbus_connection_remove_filter(libdbusConnection_, &onLibdbusSignalFilterThunk, this);
}
@@ -102,18 +281,20 @@ void DBusConnection::disconnect() {
dbus_connection_close(libdbusConnection_);
- //It is possible for the disconnect to be called from within a callback, i.e. from within the dispatch
- //thread. Self-join is prevented this way.
- if (dispatchThread_.joinable() && std::this_thread::get_id() != dispatchThread_.get_id()) {
- dispatchThread_.join();
- } else {
- dispatchThread_.detach();
+ if(dispatchThread_) {
+ //It is possible for the disconnect to be called from within a callback, i.e. from within the dispatch
+ //thread. Self-join is prevented this way.
+ if (dispatchThread_->joinable() && std::this_thread::get_id() != dispatchThread_->get_id()) {
+ dispatchThread_->join();
+ } else {
+ dispatchThread_->detach();
+ }
+ delete dispatchThread_;
+ dispatchThread_ = NULL;
}
dbus_connection_unref(libdbusConnection_);
libdbusConnection_ = NULL;
-
- dbusConnectionStatusEvent_.notifyListeners(AvailabilityStatus::NOT_AVAILABLE);
}
}
@@ -128,9 +309,13 @@ DBusProxyConnection::ConnectionStatusEvent& DBusConnection::getConnectionStatusE
const std::shared_ptr<DBusServiceRegistry> DBusConnection::getDBusServiceRegistry() {
std::shared_ptr<DBusServiceRegistry> serviceRegistry = dbusServiceRegistry_.lock();
if (!serviceRegistry || dbusServiceRegistry_.expired()) {
- serviceRegistry = std::make_shared<DBusServiceRegistry>(this->shared_from_this());
- serviceRegistry->init();
- dbusServiceRegistry_ = serviceRegistry;
+ serviceRegistryGuard_.lock();
+ if (!serviceRegistry || dbusServiceRegistry_.expired()) {
+ serviceRegistry = std::make_shared<DBusServiceRegistry>(shared_from_this());
+ serviceRegistry->init();
+ dbusServiceRegistry_ = serviceRegistry;
+ }
+ serviceRegistryGuard_.unlock();
}
return serviceRegistry;
@@ -138,7 +323,11 @@ const std::shared_ptr<DBusServiceRegistry> DBusConnection::getDBusServiceRegistr
const std::shared_ptr<DBusObjectManager> DBusConnection::getDBusObjectManager() {
if (!dbusObjectManager_) {
- dbusObjectManager_ = std::make_shared<DBusObjectManager>(this->shared_from_this());
+ objectManagerGuard_.lock();
+ if (!dbusObjectManager_) {
+ dbusObjectManager_ = std::make_shared<DBusObjectManager>(shared_from_this());
+ }
+ objectManagerGuard_.unlock();
}
return dbusObjectManager_;
@@ -146,10 +335,16 @@ const std::shared_ptr<DBusObjectManager> DBusConnection::getDBusObjectManager()
bool DBusConnection::requestServiceNameAndBlock(const std::string& serviceName) const {
DBusError dbusError;
+
+ suspendDispatching();
+
const int libdbusStatus = dbus_bus_request_name(libdbusConnection_,
serviceName.c_str(),
DBUS_NAME_FLAG_DO_NOT_QUEUE,
&dbusError.libdbusError_);
+
+ resumeDispatching();
+
const bool isServiceNameAcquired = (libdbusStatus == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
return isServiceNameAcquired;
@@ -157,9 +352,11 @@ bool DBusConnection::requestServiceNameAndBlock(const std::string& serviceName)
bool DBusConnection::releaseServiceName(const std::string& serviceName) const {
DBusError dbusError;
+ suspendDispatching();
const int libdbusStatus = dbus_bus_release_name(libdbusConnection_,
serviceName.c_str(),
&dbusError.libdbusError_);
+ resumeDispatching();
const bool isServiceNameReleased = (libdbusStatus == DBUS_RELEASE_NAME_REPLY_RELEASED);
return isServiceNameReleased;
@@ -242,31 +439,39 @@ std::future<CallStatus> DBusConnection::sendDBusMessageWithReplyAsync(
DBusMessage DBusConnection::sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage,
DBusError& dbusError,
int timeoutMilliseconds) const {
+ auto selfReference = this->shared_from_this();
+
assert(dbusMessage);
assert(!dbusError);
assert(isConnected());
+ suspendDispatching();
+
::DBusMessage* libdbusMessageReply = dbus_connection_send_with_reply_and_block(libdbusConnection_,
dbusMessage.libdbusMessage_,
timeoutMilliseconds,
&dbusError.libdbusError_);
- if (dbusError)
+
+ resumeDispatching();
+
+ if (dbusError) {
return DBusMessage();
+ }
const bool increaseLibdbusMessageReferenceCount = false;
return DBusMessage(libdbusMessageReply, increaseLibdbusMessageReferenceCount);
}
-bool DBusConnection::readWriteDispatch(int timeoutMilliseconds) {
- if(isConnected()) {
- const dbus_bool_t libdbusSuccess = dbus_connection_read_write_dispatch(libdbusConnection_,
- timeoutMilliseconds);
- return libdbusSuccess;
- }
- return false;
+bool DBusConnection::singleDispatch() {
+ return (dbus_connection_dispatch(libdbusConnection_) == DBUS_DISPATCH_DATA_REMAINS);
+}
+
+bool DBusConnection::isDispatchReady() {
+ return (dbus_connection_get_dispatch_status(libdbusConnection_) == DBUS_DISPATCH_DATA_REMAINS);
}
+
DBusProxyConnection::DBusSignalHandlerToken DBusConnection::addSignalMemberHandler(const std::string& objectPath,
const std::string& interfaceName,
const std::string& interfaceMemberName,
@@ -291,25 +496,23 @@ DBusProxyConnection::DBusSignalHandlerToken DBusConnection::addSignalMemberHandl
void DBusConnection::removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken) {
std::lock_guard<std::mutex> dbusSignalLock(signalGuard_);
auto equalRangeIteratorPair = dbusSignalHandlerTable_.equal_range(dbusSignalHandlerToken);
+ if (equalRangeIteratorPair.first != equalRangeIteratorPair.second) {
+ // advance to the next element
+ equalRangeIteratorPair.first++;
- // the range can't be empty!
- assert(equalRangeIteratorPair.first != equalRangeIteratorPair.second);
-
- // advance to the next element
- equalRangeIteratorPair.first++;
+ // check if the first element was the only element
+ const bool isLastSignalMemberHandler = equalRangeIteratorPair.first == equalRangeIteratorPair.second;
- // check if the first element was the only element
- const bool isLastSignalMemberHandler = equalRangeIteratorPair.first == equalRangeIteratorPair.second;
+ if (isLastSignalMemberHandler) {
+ const std::string& objectPath = std::get<0>(dbusSignalHandlerToken);
+ const std::string& interfaceName = std::get<1>(dbusSignalHandlerToken);
+ const std::string& interfaceMemberName = std::get<2>(dbusSignalHandlerToken);
- if (isLastSignalMemberHandler) {
- const std::string& objectPath = std::get<0>(dbusSignalHandlerToken);
- const std::string& interfaceName = std::get<1>(dbusSignalHandlerToken);
- const std::string& interfaceMemberName = std::get<2>(dbusSignalHandlerToken);
+ removeLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName);
+ }
- removeLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName);
+ dbusSignalHandlerTable_.erase(dbusSignalHandlerToken);
}
-
- dbusSignalHandlerTable_.erase(dbusSignalHandlerToken);
}
void DBusConnection::registerObjectPath(const std::string& objectPath) {
@@ -397,6 +600,7 @@ void DBusConnection::addLibdbusSignalMatchRule(const std::string& objectPath,
// if not connected the filter and the rules will be added as soon as the connection is established
if (isConnected()) {
+ suspendDispatching();
// add the libdbus message signal filter
if (isFirstMatchRule) {
const dbus_bool_t libdbusSuccess = dbus_connection_add_filter(libdbusConnection_,
@@ -410,6 +614,8 @@ void DBusConnection::addLibdbusSignalMatchRule(const std::string& objectPath,
DBusError dbusError;
dbus_bus_add_match(libdbusConnection_, matchRuleString.c_str(), &dbusError.libdbusError_);
assert(!dbusError);
+
+ resumeDispatching();
}
}
@@ -430,8 +636,12 @@ void DBusConnection::removeLibdbusSignalMatchRule(const std::string& objectPath,
}
const std::string& matchRuleString = matchRuleIterator->second.second;
+
+ suspendDispatching();
+
DBusError dbusError;
dbus_bus_remove_match(libdbusConnection_, matchRuleString.c_str(), &dbusError.libdbusError_);
+
assert(!dbusError);
dbusSignalMatchRulesMap_.erase(matchRuleIterator);
@@ -440,14 +650,17 @@ void DBusConnection::removeLibdbusSignalMatchRule(const std::string& objectPath,
if (isLastMatchRule) {
dbus_connection_remove_filter(libdbusConnection_, &onLibdbusSignalFilterThunk, this);
}
+
+ resumeDispatching();
}
void DBusConnection::initLibdbusObjectPathHandlerAfterConnect() {
assert(isConnected());
// nothing to do if there aren't any registered object path handlers
- if (libdbusRegisteredObjectPaths_.empty())
+ if (libdbusRegisteredObjectPaths_.empty()) {
return;
+ }
DBusError dbusError;
dbus_bool_t libdbusSuccess;
@@ -476,6 +689,8 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() {
if (dbusSignalMatchRulesMap_.empty())
return;
+ suspendDispatching();
+
// first we add the libdbus message signal filter
const dbus_bool_t libdbusSuccess = dbus_connection_add_filter(libdbusConnection_,
&onLibdbusSignalFilterThunk,
@@ -492,9 +707,10 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() {
dbus_bus_add_match(libdbusConnection_, matchRuleString.c_str(), &dbusError.libdbusError_);
assert(!dbusError);
}
+ resumeDispatching();
}
-::DBusHandlerResult DBusConnection::onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage) const {
+::DBusHandlerResult DBusConnection::onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage) {
assert(libdbusMessage);
// handle only method call messages
@@ -502,7 +718,7 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() {
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
- bool isDBusMessageHandled = dbusObjectManager_->handleMessage(DBusMessage(libdbusMessage));
+ bool isDBusMessageHandled = dbusObjectMessageHandler_(DBusMessage(libdbusMessage));
return isDBusMessageHandled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
@@ -511,8 +727,9 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() {
auto selfReference = this->shared_from_this();
// handle only signal messages
- if (dbus_message_get_type(libdbusMessage) != DBUS_MESSAGE_TYPE_SIGNAL)
+ if (dbus_message_get_type(libdbusMessage) != DBUS_MESSAGE_TYPE_SIGNAL) {
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
const char* objectPath = dbus_message_get_path(libdbusMessage);
const char* interfaceName = dbus_message_get_interface(libdbusMessage);
@@ -536,9 +753,7 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() {
const SubscriptionStatus dbusSignalHandlerSubscriptionStatus = dbusSignalHandler->onSignalDBusMessage(dbusMessage);
if (dbusSignalHandlerSubscriptionStatus == SubscriptionStatus::CANCEL) {
- auto dbusSignalHandlerSubscription = equalRangeIteratorPair.first;
- equalRangeIteratorPair.first++;
- dbusSignalHandlerTable_.erase(dbusSignalHandlerSubscription);
+ equalRangeIteratorPair.first = dbusSignalHandlerTable_.erase(equalRangeIteratorPair.first);
} else {
equalRangeIteratorPair.first++;
}
@@ -571,7 +786,7 @@ void DBusConnection::initLibdbusSignalFilterAfterConnect() {
assert(libdbusMessage);
assert(userData);
- const DBusConnection* dbusConnection = reinterpret_cast<DBusConnection*>(userData);
+ DBusConnection* dbusConnection = reinterpret_cast<DBusConnection*>(userData);
assert(dbusConnection->libdbusConnection_ == libdbusConnection);
diff --git a/src/CommonAPI/DBus/DBusConnection.h b/src/CommonAPI/DBus/DBusConnection.h
index 8e95296..81c8cfa 100644
--- a/src/CommonAPI/DBus/DBusConnection.h
+++ b/src/CommonAPI/DBus/DBusConnection.h
@@ -11,10 +11,10 @@
#include "DBusDaemonProxy.h"
#include "DBusServiceRegistry.h"
#include "DBusObjectManager.h"
+#include "DBusMainLoopContext.h"
#include <dbus/dbus.h>
-
namespace CommonAPI {
namespace DBus {
@@ -32,134 +32,169 @@ class DBusConnectionStatusEvent: public DBusProxyConnection::ConnectionStatusEve
DBusConnection* dbusConnection_;
};
+struct WatchContext {
+ WatchContext(std::weak_ptr<MainLoopContext> mainLoopContext, DispatchSource* dispatchSource) :
+ mainLoopContext_(mainLoopContext), dispatchSource_(dispatchSource) {
+ }
+
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+ DispatchSource* dispatchSource_;
+};
class DBusConnection: public DBusProxyConnection, public std::enable_shared_from_this<DBusConnection> {
public:
- enum BusType {
- SESSION = DBUS_BUS_SESSION,
- SYSTEM = DBUS_BUS_SYSTEM,
- STARTER = DBUS_BUS_STARTER,
- WRAPPED
- };
+ enum BusType {
+ SESSION = DBUS_BUS_SESSION,
+ SYSTEM = DBUS_BUS_SYSTEM,
+ STARTER = DBUS_BUS_STARTER,
+ WRAPPED
+ };
- DBusConnection(BusType busType);
+ DBusConnection(BusType busType);
- inline static std::shared_ptr<DBusConnection> getBus(const BusType& busType);
- inline static std::shared_ptr<DBusConnection> wrapLibDBus(::DBusConnection* libDbusConnection);
- inline static std::shared_ptr<DBusConnection> getSessionBus();
- inline static std::shared_ptr<DBusConnection> getSystemBus();
- inline static std::shared_ptr<DBusConnection> getStarterBus();
+ inline static std::shared_ptr<DBusConnection> getBus(const BusType& busType);
+ inline static std::shared_ptr<DBusConnection> wrapLibDBus(::DBusConnection* libDbusConnection);
+ inline static std::shared_ptr<DBusConnection> getSessionBus();
+ inline static std::shared_ptr<DBusConnection> getSystemBus();
+ inline static std::shared_ptr<DBusConnection> getStarterBus();
- DBusConnection(const DBusConnection&) = delete;
- DBusConnection(::DBusConnection* libDbusConnection);
+ DBusConnection(const DBusConnection&) = delete;
+ DBusConnection(::DBusConnection* libDbusConnection);
- DBusConnection& operator=(const DBusConnection&) = delete;
- virtual ~DBusConnection();
+ DBusConnection& operator=(const DBusConnection&) = delete;
+ virtual ~DBusConnection();
- BusType getBusType() const;
+ BusType getBusType() const;
- bool connect();
- bool connect(DBusError& dbusError);
- void disconnect();
+ bool connect(bool startDispatchThread = true);
+ bool connect(DBusError& dbusError, bool startDispatchThread = true);
+ void disconnect();
- virtual bool isConnected() const;
+ virtual bool isConnected() const;
- virtual ConnectionStatusEvent& getConnectionStatusEvent();
+ virtual ConnectionStatusEvent& getConnectionStatusEvent();
- virtual bool requestServiceNameAndBlock(const std::string& serviceName) const;
- virtual bool releaseServiceName(const std::string& serviceName) const;
+ virtual bool requestServiceNameAndBlock(const std::string& serviceName) const;
+ virtual bool releaseServiceName(const std::string& serviceName) const;
- bool sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial = NULL) const;
+ bool sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial = NULL) const;
- static const int kDefaultSendTimeoutMs = 100 * 1000;
+ static const int kDefaultSendTimeoutMs = 5000;
- std::future<CallStatus> sendDBusMessageWithReplyAsync(
- const DBusMessage& dbusMessage,
- std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,
- int timeoutMilliseconds = kDefaultSendTimeoutMs) const;
+ std::future<CallStatus> sendDBusMessageWithReplyAsync(
+ const DBusMessage& dbusMessage,
+ std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,
+ int timeoutMilliseconds = kDefaultSendTimeoutMs) const;
- DBusMessage sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage,
- DBusError& dbusError,
- int timeoutMilliseconds = kDefaultSendTimeoutMs) const;
+ DBusMessage sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage,
+ DBusError& dbusError,
+ int timeoutMilliseconds = kDefaultSendTimeoutMs) const;
- DBusSignalHandlerToken addSignalMemberHandler(const std::string& objectPath,
- const std::string& interfaceName,
- const std::string& interfaceMemberName,
- const std::string& interfaceMemberSignature,
- DBusSignalHandler* dbusSignalHandler);
+ DBusSignalHandlerToken addSignalMemberHandler(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler);
- void registerObjectPath(const std::string& objectPath);
- void unregisterObjectPath(const std::string& objectPath);
+ void registerObjectPath(const std::string& objectPath);
+ void unregisterObjectPath(const std::string& objectPath);
- void removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken);
+ void removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken);
- bool readWriteDispatch(int timeoutMilliseconds = -1);
+ bool readWriteDispatch(int timeoutMilliseconds = -1);
virtual const std::shared_ptr<DBusServiceRegistry> getDBusServiceRegistry();
virtual const std::shared_ptr<DBusObjectManager> getDBusObjectManager();
+ void setObjectPathMessageHandler(DBusObjectPathMessageHandler);
+ bool isObjectPathMessageHandlerSet();
+
+ virtual bool attachMainLoopContext(std::weak_ptr<MainLoopContext>);
+
+ bool isDispatchReady();
+ bool singleDispatch();
+
private:
- void dispatch();
+ void dispatch(std::shared_ptr<DBusConnection> selfReference);
+ void suspendDispatching() const;
+ void resumeDispatching() const;
- std::thread dispatchThread_;
+ std::thread* dispatchThread_;
bool stopDispatching_;
- void addLibdbusSignalMatchRule(const std::string& objectPath,
- const std::string& interfaceName,
- const std::string& interfaceMemberName);
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+ DispatchSource* dispatchSource_;
+ WatchContext* watchContext_;
- void removeLibdbusSignalMatchRule(const std::string& objectPath,
- const std::string& interfaceName,
- const std::string& interfaceMemberName);
+ mutable bool pauseDispatching_;
+ mutable std::mutex dispatchSuspendLock_;
- void initLibdbusObjectPathHandlerAfterConnect();
+ void addLibdbusSignalMatchRule(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName);
- void initLibdbusSignalFilterAfterConnect();
+ void removeLibdbusSignalMatchRule(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName);
- ::DBusHandlerResult onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage) const;
+ void initLibdbusSignalFilterAfterConnect();
+ ::DBusHandlerResult onLibdbusSignalFilter(::DBusMessage* libdbusMessage);
- ::DBusHandlerResult onLibdbusSignalFilter(::DBusMessage* libdbusMessage);
+ void initLibdbusObjectPathHandlerAfterConnect();
+ ::DBusHandlerResult onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage);
- static void onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void* userData);
- static void onLibdbusDataCleanup(void* userData);
+ static void onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void* userData);
+ static void onLibdbusDataCleanup(void* userData);
- static ::DBusHandlerResult onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection,
- ::DBusMessage* libdbusMessage,
- void* userData);
+ static ::DBusHandlerResult onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection,
+ ::DBusMessage* libdbusMessage,
+ void* userData);
- static ::DBusHandlerResult onLibdbusSignalFilterThunk(::DBusConnection* libdbusConnection,
- ::DBusMessage* libdbusMessage,
- void* userData);
+ static ::DBusHandlerResult onLibdbusSignalFilterThunk(::DBusConnection* libdbusConnection,
+ ::DBusMessage* libdbusMessage,
+ void* userData);
- BusType busType_;
+ static dbus_bool_t onAddWatch(::DBusWatch* libdbusWatch, void* data);
+ static void onRemoveWatch(::DBusWatch* libdbusWatch, void* data);
+ static void onToggleWatch(::DBusWatch* libdbusWatch, void* data);
- ::DBusConnection* libdbusConnection_;
- std::mutex libdbusConnectionGuard_;
- std::mutex signalGuard_;
+ static dbus_bool_t onAddTimeout(::DBusTimeout* dbus_timeout, void* data);
+ static void onRemoveTimeout(::DBusTimeout* dbus_timeout, void* data);
+ static void onToggleTimeout(::DBusTimeout* dbus_timeout, void* data);
- std::weak_ptr<DBusServiceRegistry> dbusServiceRegistry_;
- std::shared_ptr<DBusObjectManager> dbusObjectManager_;
+ static void onWakeupMainContext(void* data);
+
+ ::DBusConnection* libdbusConnection_;
+ std::mutex libdbusConnectionGuard_;
+ std::mutex signalGuard_;
+ std::mutex objectManagerGuard_;
+ std::mutex serviceRegistryGuard_;
+
+ BusType busType_;
- DBusConnectionStatusEvent dbusConnectionStatusEvent_;
+ std::weak_ptr<DBusServiceRegistry> dbusServiceRegistry_;
+ std::shared_ptr<DBusObjectManager> dbusObjectManager_;
- typedef std::tuple<std::string, std::string, std::string> DBusSignalMatchRuleTuple;
- typedef std::pair<uint32_t, std::string> DBusSignalMatchRuleMapping;
- typedef std::unordered_map<DBusSignalMatchRuleTuple, DBusSignalMatchRuleMapping> DBusSignalMatchRulesMap;
- DBusSignalMatchRulesMap dbusSignalMatchRulesMap_;
+ DBusConnectionStatusEvent dbusConnectionStatusEvent_;
- bool isLibdbusSignalFilterAdded_;
+ typedef std::tuple<std::string, std::string, std::string> DBusSignalMatchRuleTuple;
+ typedef std::pair<uint32_t, std::string> DBusSignalMatchRuleMapping;
+ typedef std::unordered_map<DBusSignalMatchRuleTuple, DBusSignalMatchRuleMapping> DBusSignalMatchRulesMap;
+ DBusSignalMatchRulesMap dbusSignalMatchRulesMap_;
DBusSignalHandlerTable dbusSignalHandlerTable_;
- // referenceCount, objectPath
+ // objectPath, referenceCount
typedef std::unordered_map<std::string, uint32_t> LibdbusRegisteredObjectPathHandlersTable;
LibdbusRegisteredObjectPathHandlersTable libdbusRegisteredObjectPaths_;
static DBusObjectPathVTable libdbusObjectPathVTable_;
+
+ DBusObjectPathMessageHandler dbusObjectMessageHandler_;
};
std::shared_ptr<DBusConnection> DBusConnection::getBus(const BusType& busType) {
- return std::make_shared<DBusConnection>(busType);
+ return std::make_shared<DBusConnection>(busType);
}
std::shared_ptr<DBusConnection> DBusConnection::wrapLibDBus(::DBusConnection* libDbusConnection) {
@@ -167,18 +202,17 @@ std::shared_ptr<DBusConnection> DBusConnection::wrapLibDBus(::DBusConnection* li
}
std::shared_ptr<DBusConnection> DBusConnection::getSessionBus() {
- return getBus(BusType::SESSION);
+ return getBus(BusType::SESSION);
}
std::shared_ptr<DBusConnection> DBusConnection::getSystemBus() {
- return getBus(BusType::SYSTEM);
+ return getBus(BusType::SYSTEM);
}
std::shared_ptr<DBusConnection> DBusConnection::getStarterBus() {
- return getBus(BusType::STARTER);
+ return getBus(BusType::STARTER);
}
-
} // namespace DBus
} // namespace CommonAPI
diff --git a/src/CommonAPI/DBus/DBusDaemonProxy.cpp b/src/CommonAPI/DBus/DBusDaemonProxy.cpp
index f18d2ac..fe81995 100644
--- a/src/CommonAPI/DBus/DBusDaemonProxy.cpp
+++ b/src/CommonAPI/DBus/DBusDaemonProxy.cpp
@@ -15,10 +15,9 @@ StaticInterfaceVersionAttribute::StaticInterfaceVersionAttribute(const uint32_t&
version_(majorValue, minorValue) {
}
-CallStatus StaticInterfaceVersionAttribute::getValue(Version& version) const {
+void StaticInterfaceVersionAttribute::getValue(CallStatus& callStatus, Version& version) const {
version = version_;
-
- return CallStatus::SUCCESS;
+ callStatus = CallStatus::SUCCESS;
}
std::future<CallStatus> StaticInterfaceVersionAttribute::getValueAsync(AttributeAsyncCallback attributeAsyncCallback) {
@@ -32,12 +31,40 @@ 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";
+
DBusDaemonProxy::DBusDaemonProxy(const std::shared_ptr<DBusProxyConnection>& dbusConnection):
- DBusProxyBase(getInterfaceId(), "org.freedesktop.DBus", "/org/freedesktop/DBus", dbusConnection),
+ DBusProxyBase(dbusConnection),
nameOwnerChangedEvent_(*this, "NameOwnerChanged", "sss") {
}
+std::string DBusDaemonProxy::getAddress() const {
+ return getDomain() + ":" + getServiceId() + ":" + getInstanceId();
+}
+const std::string& DBusDaemonProxy::getDomain() const {
+ return commonApiDomain_;
+}
+const std::string& DBusDaemonProxy::getServiceId() const {
+ return dbusInterfaceName_;
+}
+const std::string& DBusDaemonProxy::getInstanceId() const {
+ return commonApiParticipantId_;
+}
+
+const std::string& DBusDaemonProxy::getDBusBusName() const {
+ return dbusBusName_;
+}
+const std::string& DBusDaemonProxy::getDBusObjectPath() const {
+ return dbusObjectPath_;
+}
+const std::string& DBusDaemonProxy::getInterfaceName() const {
+ return dbusInterfaceName_;
+}
+
bool DBusDaemonProxy::isAvailable() const {
return getDBusConnection()->isConnected();
}
@@ -138,12 +165,9 @@ std::future<CallStatus> DBusDaemonProxy::getManagedObjectsAsync(const std::strin
"GetManagedObjects",
"");
- const int timeoutMilliseconds = 100;
-
return getDBusConnection()->sendDBusMessageWithReplyAsync(
dbusMethodCallMessage,
- DBusProxyAsyncCallbackHandler<DBusObjectToInterfaceDict>::create(callback),
- timeoutMilliseconds);
+ DBusProxyAsyncCallbackHandler<DBusObjectToInterfaceDict>::create(callback));
}
diff --git a/src/CommonAPI/DBus/DBusDaemonProxy.h b/src/CommonAPI/DBus/DBusDaemonProxy.h
index aeb2feb..0053c1b 100644
--- a/src/CommonAPI/DBus/DBusDaemonProxy.h
+++ b/src/CommonAPI/DBus/DBusDaemonProxy.h
@@ -22,7 +22,7 @@ class StaticInterfaceVersionAttribute: public InterfaceVersionAttribute {
public:
StaticInterfaceVersionAttribute(const uint32_t& majorValue, const uint32_t& minorValue);
- CallStatus getValue(Version& version) const;
+ void getValue(CallStatus& callStatus, Version& version) const;
std::future<CallStatus> getValueAsync(AttributeAsyncCallback attributeAsyncCallback);
private:
@@ -61,9 +61,23 @@ class DBusDaemonProxy: public DBusProxyBase {
std::future<CallStatus> getManagedObjectsAsync(const std::string& forDBusServiceName, GetManagedObjectsAsyncCallback) const;
+ virtual std::string getAddress() const;
+ virtual const std::string& getDomain() const;
+ virtual const std::string& getServiceId() const;
+ virtual const std::string& getInstanceId() const;
+
+ virtual const std::string& getDBusBusName() const;
+ virtual const std::string& getDBusObjectPath() const;
+ virtual const std::string& getInterfaceName() const;
+
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_;
};
const char* DBusDaemonProxy::getInterfaceId() {
diff --git a/src/CommonAPI/DBus/DBusFactory.cpp b/src/CommonAPI/DBus/DBusFactory.cpp
index de74ef1..c75a393 100644
--- a/src/CommonAPI/DBus/DBusFactory.cpp
+++ b/src/CommonAPI/DBus/DBusFactory.cpp
@@ -4,6 +4,7 @@
* 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 "DBusProxy.h"
#include "DBusConnection.h"
#include "DBusFactory.h"
@@ -20,6 +21,7 @@
namespace CommonAPI {
namespace DBus {
+
std::unordered_map<std::string, DBusProxyFactoryFunction>* registeredProxyFactoryFunctions_;
std::unordered_map<std::string, DBusAdapterFactoryFunction>* registeredAdapterFactoryFunctions_;
@@ -39,12 +41,16 @@ void DBusFactory::registerAdapterFactoryMethod(std::string interfaceName, DBusAd
}
-
-DBusFactory::DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo) :
+DBusFactory::DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, std::shared_ptr<MainLoopContext> mainLoopContext) :
CommonAPI::Factory(runtime, middlewareInfo),
dbusConnection_(CommonAPI::DBus::DBusConnection::getSessionBus()),
- acquiredConnectionName_("") {
- dbusConnection_->connect();
+ acquiredConnectionName_(""),
+ mainLoopContext_(mainLoopContext) {
+ bool startDispatchThread = !mainLoopContext_;
+ dbusConnection_->connect(startDispatchThread);
+ if(mainLoopContext_) {
+ dbusConnection_->attachMainLoopContext(mainLoopContext);
+ }
}
@@ -120,27 +126,28 @@ bool DBusFactory::registerAdapter(std::shared_ptr<StubBase> stubBase,
DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
if(acquiredConnectionName_ == "") {
- dbusConnection_->requestServiceNameAndBlock(connectionName);
+ bool isServiceNameAcquired = dbusConnection_->requestServiceNameAndBlock(connectionName);
+ if(!isServiceNameAcquired) {
+ return false;
+ }
acquiredConnectionName_ = connectionName;
} else if (acquiredConnectionName_ != connectionName) {
- return NULL;
+ return false;
}
if(!registeredAdapterFactoryFunctions_) {
registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction> {};
}
- for (auto it = registeredAdapterFactoryFunctions_->begin(); it != registeredAdapterFactoryFunctions_->end(); ++it) {
- if(it->first == interfaceId) {
- std::shared_ptr<DBusStubAdapter> dbusStubAdapter = (it->second)(commonApiAddress, interfaceName, connectionName, objectPath, dbusConnection_, stubBase);
- if(!dbusStubAdapter) {
- return false;
- }
- std::string address = domain + ":" + serviceName + ":" + participantId;
- if(registeredServices_.insert( {std::move(address), dbusStubAdapter} ).second) {
- dbusStubAdapter->init();
- return true;
- }
+ auto foundFunction = registeredAdapterFactoryFunctions_->find(interfaceId);
+ if(foundFunction != registeredAdapterFactoryFunctions_->end()) {
+ std::shared_ptr<DBusStubAdapter> dbusStubAdapter = (foundFunction->second)(commonApiAddress, interfaceName, connectionName, objectPath, dbusConnection_, stubBase);
+ if(!dbusStubAdapter) {
+ return false;
+ }
+ if(registeredServices_.insert( {std::move(commonApiAddress), dbusStubAdapter} ).second) {
+ dbusStubAdapter->init();
+ return true;
}
}
diff --git a/src/CommonAPI/DBus/DBusFactory.h b/src/CommonAPI/DBus/DBusFactory.h
index a3edfdc..2b1a813 100644
--- a/src/CommonAPI/DBus/DBusFactory.h
+++ b/src/CommonAPI/DBus/DBusFactory.h
@@ -18,11 +18,14 @@
namespace CommonAPI {
namespace DBus {
+class DBusMainLoopContext;
+
typedef std::shared_ptr<DBusProxy> (*DBusProxyFactoryFunction) (const std::string& commonApiAddress,
const std::string& interfaceName,
const std::string& busName,
const std::string& objectPath,
const std::shared_ptr<DBusProxyConnection>& dbusProxyConnection);
+
typedef std::shared_ptr<DBusStubAdapter> (*DBusAdapterFactoryFunction) (const std::string& commonApiAddress,
const std::string& interfaceName,
const std::string& busName,
@@ -32,7 +35,7 @@ typedef std::shared_ptr<DBusStubAdapter> (*DBusAdapterFactoryFunction) (const st
class DBusFactory: public Factory {
public:
- DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo);
+ DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, std::shared_ptr<MainLoopContext> mainLoopContext = std::shared_ptr<MainLoopContext>(NULL));
virtual ~DBusFactory();
static void registerProxyFactoryMethod(std::string interfaceName, DBusProxyFactoryFunction proxyFactoryFunction);
@@ -53,6 +56,7 @@ class DBusFactory: public Factory {
std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_;
std::string acquiredConnectionName_;
std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> registeredServices_;
+ std::shared_ptr<MainLoopContext> mainLoopContext_;
};
} // namespace DBus
diff --git a/src/CommonAPI/DBus/DBusInputStream.h b/src/CommonAPI/DBus/DBusInputStream.h
index 3409d4c..6a8b32b 100644
--- a/src/CommonAPI/DBus/DBusInputStream.h
+++ b/src/CommonAPI/DBus/DBusInputStream.h
@@ -193,11 +193,6 @@ class DBusInputStream: public InputStream {
return *this;
}
- /**
- * Returns the position of the reading pointer, relative to the beginning of the data stream.
- */
- position_t getCurrentPosition() const;
-
private:
inline void beginReadGenericVector() {
uint32_t vectorByteSize;
diff --git a/src/CommonAPI/DBus/DBusMainLoopContext.cpp b/src/CommonAPI/DBus/DBusMainLoopContext.cpp
new file mode 100644
index 0000000..9b9c57c
--- /dev/null
+++ b/src/CommonAPI/DBus/DBusMainLoopContext.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 "DBusMainLoopContext.h"
+#include "DBusConnection.h"
+
+#include <poll.h>
+#include <chrono>
+
+
+namespace CommonAPI {
+namespace DBus {
+
+
+DBusDispatchSource::DBusDispatchSource(DBusConnection* dbusConnection):
+ dbusConnection_(dbusConnection) {
+}
+
+DBusDispatchSource::~DBusDispatchSource() {
+}
+
+bool DBusDispatchSource::prepare(int64_t& timeout) {
+ return dbusConnection_->isDispatchReady();
+}
+
+bool DBusDispatchSource::check() {
+ return dbusConnection_->isDispatchReady();
+}
+
+bool DBusDispatchSource::dispatch() {
+ return dbusConnection_->singleDispatch();
+}
+
+
+DBusWatch::DBusWatch(::DBusWatch* libdbusWatch, std::weak_ptr<MainLoopContext>& mainLoopContext):
+ libdbusWatch_(libdbusWatch),
+ mainLoopContext_(mainLoopContext),
+ channelFlags_(0) {
+ assert(libdbusWatch_);
+}
+
+bool DBusWatch::isReadyToBeWatched() {
+ return dbus_watch_get_enabled(libdbusWatch_);
+}
+
+void DBusWatch::startWatching() {
+ channelFlags_ = dbus_watch_get_flags(libdbusWatch_);
+ short int pollFlags = POLLERR | POLLHUP;
+ if(channelFlags_ & DBUS_WATCH_READABLE) {
+ pollFlags |= POLLIN;
+ }
+ if(channelFlags_ & DBUS_WATCH_WRITABLE) {
+ pollFlags |= POLLOUT;
+ }
+
+ pollFileDescriptor_.fd = dbus_watch_get_unix_fd(libdbusWatch_);
+ pollFileDescriptor_.events = pollFlags;
+ pollFileDescriptor_.revents = 0;
+
+ auto lockedContext = mainLoopContext_.lock();
+ assert(lockedContext);
+ lockedContext->registerWatch(this);
+}
+
+void DBusWatch::stopWatching() {
+ auto lockedContext = mainLoopContext_.lock();
+ assert(lockedContext);
+ lockedContext->deregisterWatch(this);
+}
+
+const pollfd& DBusWatch::getAssociatedFileDescriptor() {
+ return pollFileDescriptor_;
+}
+
+//XXX Default hierfür die revent-flags?
+void DBusWatch::dispatch(unsigned int eventFlags) {
+ dbus_watch_handle(libdbusWatch_, eventFlags);
+}
+
+const std::vector<DispatchSource*>& DBusWatch::getDependentDispatchSources() {
+ return dependentDispatchSources_;
+}
+
+void DBusWatch::addDependentDispatchSource(DispatchSource* dispatchSource) {
+ dependentDispatchSources_.push_back(dispatchSource);
+}
+
+
+DBusTimeout::DBusTimeout(::DBusTimeout* libdbusTimeout, std::weak_ptr<MainLoopContext>& mainLoopContext) :
+ libdbusTimeout_(libdbusTimeout),
+ mainLoopContext_(mainLoopContext),
+ dueTimeInMs_(TIMEOUT_INFINITE) {
+}
+
+bool DBusTimeout::isReadyToBeMonitored() {
+ return dbus_timeout_get_enabled(libdbusTimeout_);
+}
+
+void DBusTimeout::startMonitoring() {
+ auto lockedContext = mainLoopContext_.lock();
+ assert(lockedContext);
+ recalculateDueTime();
+ lockedContext->registerTimeoutSource(this);
+}
+
+void DBusTimeout::stopMonitoring() {
+ dueTimeInMs_ = TIMEOUT_INFINITE;
+ auto lockedContext = mainLoopContext_.lock();
+ assert(lockedContext);
+ lockedContext->deregisterTimeoutSource(this);
+}
+
+bool DBusTimeout::dispatch() {
+ recalculateDueTime();
+ dbus_timeout_handle(libdbusTimeout_);
+ return true;
+}
+
+int64_t DBusTimeout::getTimeoutInterval() const {
+ return dbus_timeout_get_interval(libdbusTimeout_);
+}
+
+int64_t DBusTimeout::getReadyTime() const {
+ return dueTimeInMs_;
+}
+
+void DBusTimeout::recalculateDueTime() {
+ if(dbus_timeout_get_enabled(libdbusTimeout_)) {
+ unsigned int intervalInMs = dbus_timeout_get_interval(libdbusTimeout_);
+ dueTimeInMs_ = getCurrentTimeInMs() + intervalInMs;
+ } else {
+ dueTimeInMs_ = TIMEOUT_INFINITE;
+ }
+}
+
+
+} // namespace DBus
+} // namespace CommonAPI
diff --git a/src/CommonAPI/DBus/DBusMainLoopContext.h b/src/CommonAPI/DBus/DBusMainLoopContext.h
new file mode 100644
index 0000000..8558527
--- /dev/null
+++ b/src/CommonAPI/DBus/DBusMainLoopContext.h
@@ -0,0 +1,94 @@
+/* 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_MAINLOOPCONTEXT_H_
+#define DBUS_MAINLOOPCONTEXT_H_
+
+#include <list>
+#include <memory>
+#include <poll.h>
+
+#include <dbus/dbus.h>
+
+#include <CommonAPI/MainLoopContext.h>
+
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusConnection;
+
+
+
+class DBusDispatchSource: public DispatchSource {
+ public:
+ DBusDispatchSource(DBusConnection* dbusConnection);
+ ~DBusDispatchSource();
+
+ bool prepare(int64_t& timeout);
+ bool check();
+ bool dispatch();
+
+ private:
+ DBusConnection* dbusConnection_;
+};
+
+class DBusWatch: public Watch {
+ public:
+ DBusWatch(::DBusWatch* libdbusWatch, std::weak_ptr<MainLoopContext>& mainLoopContext);
+
+ bool isReadyToBeWatched();
+ void startWatching();
+ void stopWatching();
+
+ void dispatch(unsigned int eventFlags);
+
+ const pollfd& getAssociatedFileDescriptor();
+
+ const std::vector<DispatchSource*>& getDependentDispatchSources();
+ void addDependentDispatchSource(DispatchSource* dispatchSource);
+
+ private:
+ bool isReady();
+
+ ::DBusWatch* libdbusWatch_;
+ pollfd pollFileDescriptor_;
+ std::vector<DispatchSource*> dependentDispatchSources_;
+
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+
+ //XXX Necessary? Are they not covered by the fd-events?
+ unsigned int channelFlags_;
+};
+
+
+class DBusTimeout: public Timeout {
+ public:
+ DBusTimeout(::DBusTimeout* libdbusTimeout, std::weak_ptr<MainLoopContext>& mainLoopContext);
+
+ bool isReadyToBeMonitored();
+ void startMonitoring();
+ void stopMonitoring();
+
+ bool dispatch();
+
+ int64_t getTimeoutInterval() const;
+ int64_t getReadyTime() const;
+
+ private:
+ void recalculateDueTime();
+
+ int64_t dueTimeInMs_;
+ ::DBusTimeout* libdbusTimeout_;
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+};
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif
diff --git a/src/CommonAPI/DBus/DBusMessage.cpp b/src/CommonAPI/DBus/DBusMessage.cpp
index 5990894..fc99b90 100644
--- a/src/CommonAPI/DBus/DBusMessage.cpp
+++ b/src/CommonAPI/DBus/DBusMessage.cpp
@@ -199,6 +199,24 @@ const char* DBusMessage::getErrorName() const {
return dbus_message_get_error_name(libdbusMessage_);
}
+bool DBusMessage::hasObjectPath(const char* objectPath) const {
+ const char* dbusMessageObjectPath = getObjectPath();
+
+ assert(objectPath);
+ assert(dbusMessageObjectPath);
+
+ return !strcmp(dbusMessageObjectPath, objectPath);
+}
+
+bool DBusMessage::hasInterfaceName(const char* interfaceName) const {
+ const char* dbusMessageInterfaceName = getInterfaceName();
+
+ assert(interfaceName);
+ assert(dbusMessageInterfaceName);
+
+ return !strcmp(dbusMessageInterfaceName, interfaceName);
+}
+
bool DBusMessage::hasMemberName(const char* memberName) const {
const char* dbusMessageMemberName = getMemberName();
diff --git a/src/CommonAPI/DBus/DBusMessage.h b/src/CommonAPI/DBus/DBusMessage.h
index 98cd9b7..558654e 100644
--- a/src/CommonAPI/DBus/DBusMessage.h
+++ b/src/CommonAPI/DBus/DBusMessage.h
@@ -69,6 +69,10 @@ class DBusMessage {
const char* getSignatureString() const;
const char* getErrorName() const;
+ inline bool hasObjectPath(const std::string& objectPath) const;
+
+ bool hasObjectPath(const char* objectPath) const;
+ bool hasInterfaceName(const char* interfaceName) const;
bool hasMemberName(const char* memberName) const;
bool hasSignature(const char* signature) const;
@@ -98,6 +102,10 @@ class DBusMessage {
friend class DBusConnection;
};
+bool DBusMessage::hasObjectPath(const std::string& objectPath) const {
+ return hasObjectPath(objectPath.c_str());
+}
+
bool DBusMessage::isInvalidType() const {
return (getType() == Type::Invalid);
}
diff --git a/src/CommonAPI/DBus/DBusObjectManager.cpp b/src/CommonAPI/DBus/DBusObjectManager.cpp
index 57c0727..09ff9ba 100644
--- a/src/CommonAPI/DBus/DBusObjectManager.cpp
+++ b/src/CommonAPI/DBus/DBusObjectManager.cpp
@@ -5,50 +5,74 @@
* 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 "DBusObjectManager.h"
+#include "DBusDaemonProxy.h"
+#include "DBusStubAdapter.h"
#include "DBusOutputStream.h"
+#include "DBusUtils.h"
+
+#include <dbus/dbus-protocol.h>
#include <cassert>
+#include <sstream>
+
+#include <unordered_set>
namespace CommonAPI {
namespace DBus {
-DBusObjectManager::DBusObjectManager(const std::shared_ptr<DBusConnection>& dbusConnection):
+DBusObjectManager::DBusObjectManager(const std::shared_ptr<DBusProxyConnection>& dbusConnection):
dbusConnection_(dbusConnection) {
- registerInterfaceHandler("/",
- "org.freedesktop.DBus.ObjectManager",
- std::bind(&DBusObjectManager::onGetDBusObjectManagerData, this, std::placeholders::_1));
+ if (!dbusConnection->isObjectPathMessageHandlerSet()) {
+ dbusConnection->setObjectPathMessageHandler(
+ std::bind(&DBusObjectManager::handleMessage, this, std::placeholders::_1));
+ }
+ dbusConnection->registerObjectPath("/");
+}
+
+DBusObjectManager::~DBusObjectManager() {
+ std::shared_ptr<DBusProxyConnection> dbusConnection = dbusConnection_.lock();
+ if (dbusConnection) {
+ dbusConnection->unregisterObjectPath("/");
+ dbusConnection->setObjectPathMessageHandler(DBusProxyConnection::DBusObjectPathMessageHandler());
+ }
}
-DBusInterfaceHandlerToken DBusObjectManager::registerInterfaceHandler(const std::string& objectPath,
- const std::string& interfaceName,
- const DBusMessageInterfaceHandler& dbusMessageInterfaceHandler) {
+DBusInterfaceHandlerToken DBusObjectManager::registerDBusStubAdapter(const std::string& objectPath,
+ const std::string& interfaceName,
+ DBusStubAdapter* dbusStubAdapter) {
DBusInterfaceHandlerPath handlerPath(objectPath, interfaceName);
+
+ objectPathLock_.lock();
bool noSuchHandlerRegistered = dbusRegisteredObjectsTable_.find(handlerPath) == dbusRegisteredObjectsTable_.end();
assert(noSuchHandlerRegistered);
- dbusRegisteredObjectsTable_.insert({handlerPath, dbusMessageInterfaceHandler});
- std::shared_ptr<DBusConnection> lockedConnection = dbusConnection_.lock();
- if(lockedConnection) {
- lockedConnection->registerObjectPath(objectPath);
+ dbusRegisteredObjectsTable_.insert({handlerPath, dbusStubAdapter});
+ objectPathLock_.unlock();
+
+ std::shared_ptr<DBusProxyConnection> dbusConnection = dbusConnection_.lock();
+ if (dbusConnection) {
+ dbusConnection->registerObjectPath(objectPath);
}
return handlerPath;
}
-void DBusObjectManager::unregisterInterfaceHandler(const DBusInterfaceHandlerToken& dbusInterfaceHandlerToken) {
+void DBusObjectManager::unregisterDBusStubAdapter(const DBusInterfaceHandlerToken& dbusInterfaceHandlerToken) {
+ objectPathLock_.lock();
const std::string& objectPath = dbusInterfaceHandlerToken.first;
- std::shared_ptr<DBusConnection> lockedConnection = dbusConnection_.lock();
- if(lockedConnection) {
+ std::shared_ptr<DBusProxyConnection> lockedConnection = dbusConnection_.lock();
+ if (lockedConnection) {
lockedConnection->unregisterObjectPath(objectPath);
}
dbusRegisteredObjectsTable_.erase(dbusInterfaceHandlerToken);
+ objectPathLock_.unlock();
}
-bool DBusObjectManager::handleMessage(const DBusMessage& dbusMessage) const {
+bool DBusObjectManager::handleMessage(const DBusMessage& dbusMessage) {
const char* objectPath = dbusMessage.getObjectPath();
const char* interfaceName = dbusMessage.getInterfaceName();
@@ -56,57 +80,147 @@ bool DBusObjectManager::handleMessage(const DBusMessage& dbusMessage) const {
assert(interfaceName);
DBusInterfaceHandlerPath handlerPath(objectPath, interfaceName);
+
+ objectPathLock_.lock();
auto handlerIterator = dbusRegisteredObjectsTable_.find(handlerPath);
const bool foundDBusInterfaceHandler = handlerIterator != dbusRegisteredObjectsTable_.end();
bool dbusMessageHandled = false;
if (foundDBusInterfaceHandler) {
- const DBusMessageInterfaceHandler& interfaceHandlerDBusMessageHandler = handlerIterator->second;
- dbusMessageHandled = interfaceHandlerDBusMessageHandler(dbusMessage);
+ DBusStubAdapter* dbusStubAdapter = handlerIterator->second;
+ dbusMessageHandled = dbusStubAdapter->onInterfaceDBusMessage(dbusMessage);
+ } else if (dbusMessage.hasInterfaceName("org.freedesktop.DBus.Introspectable")) {
+ dbusMessageHandled = onIntrospectableInterfaceDBusMessage(dbusMessage);
+ } else if (dbusMessage.hasInterfaceName("org.freedesktop.DBus.ObjectManager")) {
+ dbusMessageHandled = onObjectManagerInterfaceDBusMessage(dbusMessage);
}
+ objectPathLock_.unlock();
return dbusMessageHandled;
}
-bool DBusObjectManager::onGetDBusObjectManagerData(const DBusMessage& callMessage) {
- DBusDaemonProxy::DBusObjectToInterfaceDict dictToSend;
+bool DBusObjectManager::onObjectManagerInterfaceDBusMessage(const DBusMessage& dbusMessage) {
+ std::shared_ptr<DBusProxyConnection> dbusConnection = dbusConnection_.lock();
- const char* interfaceName = callMessage.getInterfaceName();
- const char* signature = callMessage.getSignatureString();
+ if (!dbusConnection || !dbusMessage.isMethodCallType() || !dbusMessage.hasMemberName("GetManagedObjects")) {
+ return false;
+ }
- assert(!strcmp(interfaceName, "org.freedesktop.DBus.ObjectManager"));
- assert(!strcmp(signature, ""));
- assert(callMessage.getType() == DBusMessage::Type::MethodCall);
+ DBusDaemonProxy::DBusObjectToInterfaceDict ObjectPathsInterfacesAndPropertiesDict;
+ objectPathLock_.lock();
auto registeredObjectsIterator = dbusRegisteredObjectsTable_.begin();
while(registeredObjectsIterator != dbusRegisteredObjectsTable_.end()) {
DBusInterfaceHandlerPath handlerPath = registeredObjectsIterator->first;
- auto foundDictEntry = dictToSend.find(handlerPath.first);
+ auto foundDictEntry = ObjectPathsInterfacesAndPropertiesDict.find(handlerPath.first);
- if(foundDictEntry == dictToSend.end()) {
- dictToSend.insert( { handlerPath.first, { { handlerPath.second, {} } } } );
+ if (foundDictEntry == ObjectPathsInterfacesAndPropertiesDict.end()) {
+ ObjectPathsInterfacesAndPropertiesDict.insert( { handlerPath.first, { { handlerPath.second, {} } } } );
} else {
foundDictEntry->second.insert( {handlerPath.second, {} } );
}
++registeredObjectsIterator;
}
+ objectPathLock_.unlock();
const char* getManagedObjectsDBusSignature = "a{oa{sa{sv}}}";
- DBusMessage replyMessage = callMessage.createMethodReturn(getManagedObjectsDBusSignature);
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(getManagedObjectsDBusSignature);
+ DBusOutputStream outStream(dbusMessageReply);
- DBusOutputStream outStream(replyMessage);
- outStream << dictToSend;
+ outStream << ObjectPathsInterfacesAndPropertiesDict;
outStream.flush();
- std::shared_ptr<DBusConnection> lockedConnection = dbusConnection_.lock();
- if(lockedConnection) {
- return lockedConnection->sendDBusMessage(replyMessage);
+ return dbusConnection->sendDBusMessage(dbusMessageReply);
+}
+
+bool DBusObjectManager::onIntrospectableInterfaceDBusMessage(const DBusMessage& dbusMessage) {
+ std::shared_ptr<DBusProxyConnection> dbusConnection = dbusConnection_.lock();
+
+ if (!dbusConnection || !dbusMessage.isMethodCallType() || !dbusMessage.hasMemberName("Introspect")) {
+ return false;
+ }
+
+ bool foundRegisteredObjects = false;
+ std::stringstream xmlData(std::ios_base::out);
+
+ xmlData << "<!DOCTYPE node PUBLIC \"" DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "\"\n\""
+ DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER"\">\n"
+ "<node name=\"" << dbusMessage.getObjectPath() << "\">\n"
+ "<interface name=\"org.freedesktop.DBus.Introspectable\">\n"
+ "<method name=\"Introspect\">\n"
+ "<arg type=\"s\" name=\"xml_data\" direction=\"out\"/>\n"
+ "</method>\n"
+ "</interface>\n";
+
+ std::unordered_set<std::string> nodeSet;
+ for (auto& registeredObjectsIterator : dbusRegisteredObjectsTable_) {
+ const DBusInterfaceHandlerPath& handlerPath = registeredObjectsIterator.first;
+ const std::string& dbusObjectPath = handlerPath.first;
+ const std::string& dbusInterfaceName = handlerPath.second;
+ DBusStubAdapter* dbusStubAdapter = registeredObjectsIterator.second;
+
+ if (dbusMessage.hasObjectPath(dbusObjectPath)) {
+ foundRegisteredObjects = true;
+
+ xmlData << "<interface name=\"" << dbusInterfaceName << "\">\n"
+ << dbusStubAdapter->getMethodsDBusIntrospectionXmlData() << "\n"
+ "</interface>\n";
+ } else {
+ std::vector<std::string> elems = CommonAPI::DBus::split(dbusObjectPath, '/');
+ if (dbusMessage.hasObjectPath("/") && elems.size() > 1) {
+ if (nodeSet.find(elems[1]) == nodeSet.end()) {
+ if (nodeSet.size() == 0) {
+ xmlData.str("");
+ xmlData << "<!DOCTYPE node PUBLIC \"" DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "\"\n\""
+ DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER"\">\n"
+ "<node>\n";
+ }
+ xmlData << " <node name=\"" << elems[1] << "\"/>\n";
+ nodeSet.insert(elems[1]);
+ foundRegisteredObjects = true;
+ }
+ } else {
+ for (int i = 1; i < elems.size() - 1; i++) {
+ std::string build;
+ for (int j = 1; j <= i; j++) {
+ build = build + "/" + elems[j];
+ if (dbusMessage.hasObjectPath(dbusObjectPath)) {
+ if (nodeSet.find(elems[j + 1]) == nodeSet.end()) {
+ if (nodeSet.size() == 0) {
+ xmlData.str("");
+ xmlData << "<!DOCTYPE node PUBLIC \"" DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "\"\n\""
+ DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER"\">\n"
+ "<node>\n";
+ }
+ xmlData << " <node name=\"" << elems[j + 1] << "\"/>\n";
+ nodeSet.insert(elems[j + 1]);
+ foundRegisteredObjects = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (foundRegisteredObjects) {
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("s");
+ DBusOutputStream dbusOutputStream(dbusMessageReply);
+
+ xmlData << "</node>"
+ "";
+
+ dbusOutputStream << xmlData.str();
+ dbusOutputStream.flush();
+
+ return dbusConnection->sendDBusMessage(dbusMessageReply);
}
+
return false;
}
-
} // namespace DBus
} // namespace CommonAPI
diff --git a/src/CommonAPI/DBus/DBusObjectManager.h b/src/CommonAPI/DBus/DBusObjectManager.h
index bfd2a71..cb60948 100644
--- a/src/CommonAPI/DBus/DBusObjectManager.h
+++ b/src/CommonAPI/DBus/DBusObjectManager.h
@@ -7,48 +7,46 @@
#ifndef COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_
#define COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_
+#include "DBusProxyConnection.h"
#include "DBusMessage.h"
-#include "DBusConnection.h"
namespace CommonAPI {
namespace DBus {
// objectPath, interfaceName
-typedef std::function<bool(const DBusMessage&)> DBusMessageInterfaceHandler;
typedef std::pair<std::string, std::string> DBusInterfaceHandlerPath;
typedef DBusInterfaceHandlerPath DBusInterfaceHandlerToken;
-class DBusConnection;
+class DBusStubAdapter;
class DBusObjectManager {
public:
- DBusObjectManager(const std::shared_ptr<DBusConnection>&);
+ DBusObjectManager(const std::shared_ptr<DBusProxyConnection>&);
+ ~DBusObjectManager();
void init();
- const DBusInterfaceHandlerToken registerInterfaceHandlerForDBusObject(const std::string& objectPath,
- const std::string& interfaceName,
- const DBusMessageInterfaceHandler& dbusMessageInterfaceHandler);
+ DBusInterfaceHandlerToken registerDBusStubAdapter(const std::string& objectPath,
+ const std::string& interfaceName,
+ DBusStubAdapter* dbusStubAdapter);
- DBusInterfaceHandlerToken registerInterfaceHandler(const std::string& objectPath,
- const std::string& interfaceName,
- const DBusMessageInterfaceHandler& dbusMessageInterfaceHandler);
+ void unregisterDBusStubAdapter(const DBusInterfaceHandlerToken& dbusInterfaceHandlerToken);
- void unregisterInterfaceHandler(const DBusInterfaceHandlerToken& dbusInterfaceHandlerToken);
-
- bool handleMessage(const DBusMessage&) const;
+ bool handleMessage(const DBusMessage&);
private:
void addLibdbusObjectPathHandler(const std::string& objectPath);
void removeLibdbusObjectPathHandler(const std::string& objectPath);
- bool onGetDBusObjectManagerData(const DBusMessage& callMessage);
+ bool onObjectManagerInterfaceDBusMessage(const DBusMessage& callMessage);
+ bool onIntrospectableInterfaceDBusMessage(const DBusMessage& callMessage);
- typedef std::unordered_map<DBusInterfaceHandlerPath, DBusMessageInterfaceHandler> DBusRegisteredObjectsTable;
+ typedef std::unordered_map<DBusInterfaceHandlerPath, DBusStubAdapter*> DBusRegisteredObjectsTable;
DBusRegisteredObjectsTable dbusRegisteredObjectsTable_;
- std::weak_ptr<DBusConnection> dbusConnection_;
+ std::weak_ptr<DBusProxyConnection> dbusConnection_;
+ std::recursive_mutex objectPathLock_;
};
} // namespace DBus
diff --git a/src/CommonAPI/DBus/DBusOutputStream.cpp b/src/CommonAPI/DBus/DBusOutputStream.cpp
index f600ced..0466b0e 100644
--- a/src/CommonAPI/DBus/DBusOutputStream.cpp
+++ b/src/CommonAPI/DBus/DBusOutputStream.cpp
@@ -229,7 +229,8 @@ void DBusOutputStream::flush() {
memcpy(destinationDataPtr, payload_.c_str(), toWrite);
}
-void DBusOutputStream::setError() {}
+void DBusOutputStream::setError() {
+}
/**
* Reserves the given number of bytes for writing, thereby negating the need to dynamically allocate memory while writing.
@@ -242,12 +243,6 @@ void DBusOutputStream::reserveMemory(size_t numOfBytes) {
payload_.reserve(numOfBytes);
}
-/**
- * @return current data position where later writing is possible
- */
-size_t getCurrentPosition();
-
-
DBusOutputStream& DBusOutputStream::writeString(const char* cString, const uint32_t& length) {
assert(cString != NULL);
assert(cString[length] == '\0');
diff --git a/src/CommonAPI/DBus/DBusOutputStream.h b/src/CommonAPI/DBus/DBusOutputStream.h
index 3a6a83b..c55f109 100644
--- a/src/CommonAPI/DBus/DBusOutputStream.h
+++ b/src/CommonAPI/DBus/DBusOutputStream.h
@@ -264,11 +264,6 @@ class DBusOutputStream: public OutputStream {
*/
void reserveMemory(size_t numOfBytes);
- /**
- * @return current data position where later writing is possible
- */
- size_t getCurrentPosition();
-
template<typename _BasicType>
DBusOutputStream& writeBasicTypeValue(const _BasicType& basicValue) {
if (sizeof(_BasicType) > 1)
diff --git a/src/CommonAPI/DBus/DBusProxy.cpp b/src/CommonAPI/DBus/DBusProxy.cpp
index 314c63f..9946859 100644
--- a/src/CommonAPI/DBus/DBusProxy.cpp
+++ b/src/CommonAPI/DBus/DBusProxy.cpp
@@ -33,12 +33,12 @@ DBusProxy::DBusProxy(const std::string& commonApiAddress,
const std::string& dbusBusName,
const std::string& dbusObjectPath,
const std::shared_ptr<DBusProxyConnection>& dbusConnection):
- DBusProxyBase(split(commonApiAddress, ':')[1],
- split(commonApiAddress, ':')[2],
- dbusInterfaceName,
- dbusBusName,
- dbusObjectPath,
- dbusConnection),
+ DBusProxyBase(dbusConnection),
+ commonApiServiceId_(split(commonApiAddress, ':')[1]),
+ commonApiParticipantId_(split(commonApiAddress, ':')[2]),
+ dbusBusName_(dbusBusName),
+ dbusObjectPath_(dbusObjectPath),
+ dbusInterfaceName_(dbusInterfaceName),
dbusProxyStatusEvent_(this),
availabilityStatus_(AvailabilityStatus::UNKNOWN),
interfaceVersionAttribute_(*this, "getInterfaceVersion"),
@@ -64,7 +64,7 @@ bool DBusProxy::isAvailable() const {
bool DBusProxy::isAvailableBlocking() const {
if (availabilityStatus_ == AvailabilityStatus::UNKNOWN) {
- std::chrono::milliseconds singleWaitDuration(100);
+ std::chrono::milliseconds singleWaitDuration(2);
// Wait for the service registry
while (availabilityStatus_ == AvailabilityStatus::UNKNOWN) {
@@ -85,9 +85,36 @@ InterfaceVersionAttribute& DBusProxy::getInterfaceVersionAttribute() {
void DBusProxy::onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus) {
availabilityStatus_ = availabilityStatus;
-
dbusProxyStatusEvent_.notifyListeners(availabilityStatus);
}
+const std::string& DBusProxy::getDBusBusName() const {
+ return dbusBusName_;
+}
+
+const std::string& DBusProxy::getDBusObjectPath() const {
+ return dbusObjectPath_;
+}
+
+const std::string& DBusProxy::getInterfaceName() const {
+ return dbusInterfaceName_;
+}
+
+const std::string& DBusProxy::getDomain() const {
+ return commonApiDomain_;
+}
+
+const std::string& DBusProxy::getServiceId() const {
+ return commonApiServiceId_;
+}
+
+const std::string& DBusProxy::getInstanceId() const {
+ return commonApiParticipantId_;
+}
+
+std::string DBusProxy::getAddress() const {
+ return commonApiDomain_ + ":" + commonApiServiceId_ + ":" + commonApiParticipantId_;
+}
+
} // namespace DBus
} // namespace CommonAPI
diff --git a/src/CommonAPI/DBus/DBusProxy.h b/src/CommonAPI/DBus/DBusProxy.h
index 6021a01..e838f6b 100644
--- a/src/CommonAPI/DBus/DBusProxy.h
+++ b/src/CommonAPI/DBus/DBusProxy.h
@@ -48,6 +48,15 @@ class DBusProxy: public DBusProxyBase {
virtual bool isAvailableBlocking() const;
+ virtual std::string getAddress() const;
+ virtual const std::string& getDomain() const;
+ virtual const std::string& getServiceId() const;
+ virtual const std::string& getInstanceId() const;
+
+ virtual const std::string& getDBusBusName() const;
+ virtual const std::string& getDBusObjectPath() const;
+ virtual const std::string& getInterfaceName() const;
+
private:
DBusProxy(const DBusProxy&) = delete;
@@ -61,6 +70,13 @@ class DBusProxy: public DBusProxyBase {
DBusReadonlyAttribute<InterfaceVersionAttribute> interfaceVersionAttribute_;
std::shared_ptr<DBusServiceRegistry> dbusServiceRegistry_;
+
+ const std::string commonApiServiceId_;
+ const std::string commonApiParticipantId_;
+
+ const std::string dbusBusName_;
+ const std::string dbusObjectPath_;
+ const std::string dbusInterfaceName_;
};
diff --git a/src/CommonAPI/DBus/DBusProxyBase.cpp b/src/CommonAPI/DBus/DBusProxyBase.cpp
index 8cb2400..633fab4 100644
--- a/src/CommonAPI/DBus/DBusProxyBase.cpp
+++ b/src/CommonAPI/DBus/DBusProxyBase.cpp
@@ -12,54 +12,16 @@ namespace DBus {
const std::string DBusProxyBase::commonApiDomain_ = "local";
-DBusProxyBase::DBusProxyBase(const std::string& commonApiServiceId,
- const std::string& commonApiParticipantId,
- const std::string& dbusInterfaceName,
- const std::string& dbusBusName,
- const std::string& dbusObjectPath,
- const std::shared_ptr<DBusProxyConnection>& dbusConnection) :
- commonApiServiceId_(commonApiServiceId),
- commonApiParticipantId_(commonApiParticipantId),
- dbusBusName_(dbusBusName),
- dbusObjectPath_(dbusObjectPath),
- dbusInterfaceName_(dbusInterfaceName),
+DBusProxyBase::DBusProxyBase(const std::shared_ptr<DBusProxyConnection>& dbusConnection) :
dbusConnection_(dbusConnection) {
}
-DBusProxyBase::DBusProxyBase(const std::string& dbusInterfaceName,
- const std::string& dbusBusName,
- const std::string& dbusObjectPath,
- const std::shared_ptr<DBusProxyConnection>& dbusConnection) :
- commonApiServiceId_(dbusInterfaceName),
- commonApiParticipantId_(dbusBusName + "-" + dbusObjectPath),
- dbusBusName_(dbusBusName),
- dbusObjectPath_(dbusObjectPath),
- dbusInterfaceName_(dbusInterfaceName),
- dbusConnection_(dbusConnection) {
-}
-
-std::string DBusProxyBase::getAddress() const {
- return commonApiDomain_ + ":" + commonApiServiceId_ + ":" + commonApiParticipantId_;
-}
-
-const std::string& DBusProxyBase::getDomain() const {
- return commonApiDomain_;
-}
-
-const std::string& DBusProxyBase::getServiceId() const {
- return commonApiServiceId_;
-}
-
-const std::string& DBusProxyBase::getInstanceId() const {
- return commonApiParticipantId_;
-}
-
DBusMessage DBusProxyBase::createMethodCall(const char* methodName,
const char* methodSignature) const {
return DBusMessage::createMethodCall(
- dbusBusName_.c_str(),
- dbusObjectPath_.c_str(),
- dbusInterfaceName_.c_str(),
+ getDBusBusName().c_str(),
+ getDBusObjectPath().c_str(),
+ getInterfaceName().c_str(),
methodName,
methodSignature);
}
diff --git a/src/CommonAPI/DBus/DBusProxyBase.h b/src/CommonAPI/DBus/DBusProxyBase.h
index 10b5bae..686c878 100644
--- a/src/CommonAPI/DBus/DBusProxyBase.h
+++ b/src/CommonAPI/DBus/DBusProxyBase.h
@@ -21,26 +21,16 @@ namespace DBus {
class DBusProxyBase: public virtual CommonAPI::Proxy {
public:
- DBusProxyBase(const std::string& commonApiServiceId,
- const std::string& commonApiParticipantId,
- const std::string& dbusInterfaceName,
- const std::string& dbusBusName,
- const std::string& dbusObjectPath,
- const std::shared_ptr<DBusProxyConnection>& dbusProxyConnection);
-
- DBusProxyBase(const std::string& dbusInterfaceName,
- const std::string& dbusBusName,
- const std::string& dbusObjectPath,
- const std::shared_ptr<DBusProxyConnection>& dbusProxyConnection);
-
- virtual std::string getAddress() const;
- virtual const std::string& getDomain() const;
- virtual const std::string& getServiceId() const;
- virtual const std::string& getInstanceId() const;
-
- inline const std::string& getDBusBusName() const;
- inline const std::string& getDBusObjectPath() const;
- inline const std::string& getInterfaceName() const;
+ DBusProxyBase(const std::shared_ptr<DBusProxyConnection>& dbusProxyConnection);
+
+ virtual std::string getAddress() const = 0;
+ virtual const std::string& getDomain() const = 0;
+ virtual const std::string& getServiceId() const = 0;
+ virtual const std::string& getInstanceId() const = 0;
+
+ virtual const std::string& getDBusBusName() const = 0;
+ virtual const std::string& getDBusObjectPath() const = 0;
+ virtual const std::string& getInterfaceName() const = 0;
inline const std::shared_ptr<DBusProxyConnection>& getDBusConnection() const;
DBusMessage createMethodCall(const char* methodName,
@@ -53,33 +43,15 @@ class DBusProxyBase: public virtual CommonAPI::Proxy {
inline void removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken);
+ protected:
+ static const std::string commonApiDomain_;
+
private:
DBusProxyBase(const DBusProxyBase&) = delete;
- const std::string commonApiServiceId_;
- const std::string commonApiParticipantId_;
-
- const std::string dbusBusName_;
- const std::string dbusObjectPath_;
- const std::string dbusInterfaceName_;
-
std::shared_ptr<DBusProxyConnection> dbusConnection_;
-
- static const std::string commonApiDomain_;
};
-const std::string& DBusProxyBase::getDBusBusName() const {
- return dbusBusName_;
-}
-
-const std::string& DBusProxyBase::getDBusObjectPath() const {
- return dbusObjectPath_;
-}
-
-const std::string& DBusProxyBase::getInterfaceName() const {
- return dbusInterfaceName_;
-}
-
const std::shared_ptr<DBusProxyConnection>& DBusProxyBase::getDBusConnection() const {
return dbusConnection_;
}
@@ -89,11 +61,11 @@ DBusProxyConnection::DBusSignalHandlerToken DBusProxyBase::addSignalMemberHandle
const std::string& signalSignature,
DBusProxyConnection::DBusSignalHandler* dbusSignalHandler) {
return dbusConnection_->addSignalMemberHandler(
- dbusObjectPath_,
- getInterfaceName(),
- signalName,
- signalSignature,
- dbusSignalHandler);
+ getDBusObjectPath(),
+ getInterfaceName(),
+ signalName,
+ signalSignature,
+ dbusSignalHandler);
}
void DBusProxyBase::removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken) {
diff --git a/src/CommonAPI/DBus/DBusProxyConnection.h b/src/CommonAPI/DBus/DBusProxyConnection.h
index e5dc24a..19140f2 100644
--- a/src/CommonAPI/DBus/DBusProxyConnection.h
+++ b/src/CommonAPI/DBus/DBusProxyConnection.h
@@ -59,37 +59,46 @@ class DBusProxyConnection {
typedef Event<AvailabilityStatus> ConnectionStatusEvent;
- virtual ~DBusProxyConnection() { }
+ virtual ~DBusProxyConnection() {
+ }
- virtual bool isConnected() const = 0;
+ virtual bool isConnected() const = 0;
- virtual ConnectionStatusEvent& getConnectionStatusEvent() = 0;
+ virtual ConnectionStatusEvent& getConnectionStatusEvent() = 0;
- virtual bool sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial = NULL) const = 0;
+ virtual bool sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial = NULL) const = 0;
- static const int kDefaultSendTimeoutMs = 100 * 1000;
+ static const int kDefaultSendTimeoutMs = 100 * 1000;
- virtual std::future<CallStatus> sendDBusMessageWithReplyAsync(
- const DBusMessage& dbusMessage,
- std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,
- int timeoutMilliseconds = kDefaultSendTimeoutMs) const = 0;
+ virtual std::future<CallStatus> sendDBusMessageWithReplyAsync(
+ const DBusMessage& dbusMessage,
+ std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,
+ int timeoutMilliseconds = kDefaultSendTimeoutMs) const = 0;
- virtual DBusMessage sendDBusMessageWithReplyAndBlock(
- const DBusMessage& dbusMessage,
- DBusError& dbusError,
- int timeoutMilliseconds = kDefaultSendTimeoutMs) const = 0;
+ virtual DBusMessage sendDBusMessageWithReplyAndBlock(
+ const DBusMessage& dbusMessage,
+ DBusError& dbusError,
+ int timeoutMilliseconds = kDefaultSendTimeoutMs) const = 0;
- virtual DBusSignalHandlerToken addSignalMemberHandler(
- const std::string& objectPath,
- const std::string& interfaceName,
- const std::string& interfaceMemberName,
- const std::string& interfaceMemberSignature,
- DBusSignalHandler* dbusSignalHandler) = 0;
+ virtual DBusSignalHandlerToken addSignalMemberHandler(
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler) = 0;
- virtual void removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken) = 0;
+ virtual void removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken) = 0;
virtual const std::shared_ptr<DBusServiceRegistry> getDBusServiceRegistry() = 0;
virtual const std::shared_ptr<DBusObjectManager> getDBusObjectManager() = 0;
+
+ virtual void registerObjectPath(const std::string& objectPath) = 0;
+ virtual void unregisterObjectPath(const std::string& objectPath) = 0;
+
+ typedef std::function<bool(const DBusMessage&)> DBusObjectPathMessageHandler;
+
+ virtual void setObjectPathMessageHandler(DBusObjectPathMessageHandler) = 0;
+ virtual bool isObjectPathMessageHandlerSet() = 0;
};
diff --git a/src/CommonAPI/DBus/DBusRuntime.cpp b/src/CommonAPI/DBus/DBusRuntime.cpp
index da1b272..a6d92db 100644
--- a/src/CommonAPI/DBus/DBusRuntime.cpp
+++ b/src/CommonAPI/DBus/DBusRuntime.cpp
@@ -23,8 +23,8 @@ std::shared_ptr<Runtime> DBusRuntime::getInstance() {
return singleton_;
}
-std::shared_ptr<Factory> DBusRuntime::createFactory() {
- auto factory = std::make_shared<DBusFactory>(this->shared_from_this(), &middlewareInfo_);
+std::shared_ptr<Factory> DBusRuntime::createFactory(std::shared_ptr<MainLoopContext> mainLoopContext) {
+ auto factory = std::make_shared<DBusFactory>(this->shared_from_this(), &middlewareInfo_, mainLoopContext);
return factory;
}
diff --git a/src/CommonAPI/DBus/DBusRuntime.h b/src/CommonAPI/DBus/DBusRuntime.h
index b91f304..3784f91 100644
--- a/src/CommonAPI/DBus/DBusRuntime.h
+++ b/src/CommonAPI/DBus/DBusRuntime.h
@@ -18,7 +18,7 @@ class DBusRuntime: public Runtime, public std::enable_shared_from_this<DBusRunti
public:
static std::shared_ptr<Runtime> getInstance();
- std::shared_ptr<Factory> createFactory();
+ std::shared_ptr<Factory> createFactory(std::shared_ptr<MainLoopContext> = std::shared_ptr<MainLoopContext>(NULL));
static const MiddlewareInfo middlewareInfo_;
};
diff --git a/src/CommonAPI/DBus/DBusServiceRegistry.cpp b/src/CommonAPI/DBus/DBusServiceRegistry.cpp
index a0ad227..9924cb6 100644
--- a/src/CommonAPI/DBus/DBusServiceRegistry.cpp
+++ b/src/CommonAPI/DBus/DBusServiceRegistry.cpp
@@ -20,7 +20,6 @@ DBusServiceRegistry::DBusServiceRegistry(std::shared_ptr<DBusProxyConnection> db
DBusServiceRegistry::~DBusServiceRegistry() {
if(initialized_) {
- std::lock_guard<std::mutex> dbusServicesLock(dbusServicesMutex_);
dbusDaemonProxy_->getNameOwnerChangedEvent().unsubscribe(dbusDaemonProxyNameOwnerChangedEventSubscription_);
dbusDaemonProxy_->getProxyStatusEvent().unsubscribe(dbusDaemonProxyStatusEventSubscription_);
}
@@ -42,26 +41,25 @@ void DBusServiceRegistry::init() {
}
bool DBusServiceRegistry::waitDBusServicesAvailable(std::unique_lock<std::mutex>& lock, std::chrono::milliseconds& timeout) {
- bool dbusServicesStatusIsKnown = (dbusNameListStatus_ != AvailabilityStatus::UNKNOWN);
+ bool dbusServicesStatusIsKnown = (dbusNameListStatus_ == AvailabilityStatus::AVAILABLE);
- while (!dbusServicesStatusIsKnown && timeout.count() > 0) {
+ if(!dbusServicesStatusIsKnown) {
typedef std::chrono::high_resolution_clock clock;
clock::time_point startTimePoint = clock::now();
- dbusServicesStatusIsKnown = dbusServiceChanged_.wait_for(
- lock,
- timeout,
- [&]{ return dbusNameListStatus_ != AvailabilityStatus::UNKNOWN; });
+ while (!dbusServicesStatusIsKnown && timeout.count() > 0) {
+ dbusServicesStatusIsKnown = dbusServiceChanged_.wait_for(
+ lock,
+ timeout / 10,
+ [&]{ return dbusNameListStatus_ == AvailabilityStatus::AVAILABLE; });
- std::chrono::milliseconds elapsedWaitTime =
- std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - startTimePoint);
+ std::chrono::milliseconds elapsedWaitTime =
+ std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - startTimePoint);
- if (elapsedWaitTime > timeout) {
- timeout = std::chrono::milliseconds::zero();
- break;
+ if (elapsedWaitTime > timeout) {
+ break;
+ }
}
-
- timeout -= elapsedWaitTime;
}
return (dbusNameListStatus_ == AvailabilityStatus::AVAILABLE);
@@ -72,7 +70,7 @@ bool DBusServiceRegistry::isServiceInstanceAlive(const std::string& dbusInterfac
return false;
}
- std::chrono::milliseconds timeout(2000);
+ std::chrono::milliseconds timeout(1000);
std::unique_lock<std::mutex> dbusServicesLock(dbusServicesMutex_);
if (!waitDBusServicesAvailable(dbusServicesLock, timeout)) {
@@ -128,7 +126,7 @@ std::vector<std::string> DBusServiceRegistry::getAvailableServiceInstances(const
return availableServiceInstances;
}
- std::chrono::milliseconds timeout(2000);
+ std::chrono::milliseconds timeout(1000);
std::unique_lock<std::mutex> dbusServicesLock(dbusServicesMutex_);
if (!waitDBusServicesAvailable(dbusServicesLock, timeout)) {
@@ -234,10 +232,11 @@ DBusServiceRegistry::Subscription DBusServiceRegistry::subscribeAvailabilityList
DBusServiceList::iterator dbusServiceIterator = dbusServices_.find(dbusServiceName);
- // add service for the first time
+ // Service not known, so just add it to the list of unkown or definitely not available services
if (dbusServiceIterator == dbusServices_.end()) {
DBusServiceState dbusConnectionNameState = DBusServiceState::UNKNOWN;
+ // Service is definitely not available if the complete list of available services is known and it is not in there
if (dbusNameListStatus_ == AvailabilityStatus::AVAILABLE) {
dbusConnectionNameState = DBusServiceState::RESOLVED;
}
diff --git a/src/CommonAPI/DBus/DBusStubAdapter.cpp b/src/CommonAPI/DBus/DBusStubAdapter.cpp
index e230062..050ed40 100644
--- a/src/CommonAPI/DBus/DBusStubAdapter.cpp
+++ b/src/CommonAPI/DBus/DBusStubAdapter.cpp
@@ -7,8 +7,6 @@
#include "DBusStubAdapter.h"
#include "DBusUtils.h"
-#include <dbus/dbus-protocol.h>
-
#include <cassert>
#include <functional>
#include <sstream>
@@ -47,23 +45,17 @@ DBusStubAdapter::~DBusStubAdapter() {
void DBusStubAdapter::deinit() {
assert(dbusConnection_);
- if(isInitialized_) {
- dbusConnection_->getDBusObjectManager()->unregisterInterfaceHandler(dbusIntrospectionInterfaceHandlerToken_);
- dbusConnection_->getDBusObjectManager()->unregisterInterfaceHandler(dbusInterfaceHandlerToken_);
+ if (isInitialized_) {
+ dbusConnection_->getDBusObjectManager()->unregisterDBusStubAdapter(dbusInterfaceHandlerToken_);
isInitialized_ = false;
}
}
void DBusStubAdapter::init() {
- dbusIntrospectionInterfaceHandlerToken_ = dbusConnection_->getDBusObjectManager()->registerInterfaceHandler(
- dbusObjectPath_,
- "org.freedesktop.DBus.Introspectable",
- std::bind(&DBusStubAdapter::onIntrospectionInterfaceDBusMessage, this, std::placeholders::_1));
-
- dbusInterfaceHandlerToken_ = dbusConnection_->getDBusObjectManager()->registerInterfaceHandler(
+ dbusInterfaceHandlerToken_ = dbusConnection_->getDBusObjectManager()->registerDBusStubAdapter(
dbusObjectPath_,
dbusInterfaceName_,
- std::bind(&DBusStubAdapter::onInterfaceDBusMessage, this, std::placeholders::_1));
+ this);
isInitialized_ = true;
}
@@ -84,34 +76,5 @@ const std::string& DBusStubAdapter::getInstanceId() const {
return commonApiParticipantId_;
}
-bool DBusStubAdapter::onIntrospectionInterfaceDBusMessage(const DBusMessage& dbusMessage) {
- bool dbusMessageHandled = false;
-
- if (dbusMessage.isMethodCallType() && dbusMessage.hasMemberName("Introspect")) {
- std::stringstream xmlData(std::ios_base::out);
- xmlData << "<!DOCTYPE node PUBLIC \"" DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "\"\n\""
- DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER"\">\n"
- "<node name=\"" << dbusObjectPath_ << "\">\n"
- "<interface name=\"org.freedesktop.DBus.Introspectable\">\n"
- "<method name=\"Introspect\">\n"
- "<arg type=\"s\" name=\"xml_data\" direction=\"out\"/>\n"
- "</method>\n"
- "</interface>\n"
- "<interface name=\"" << dbusInterfaceName_ << "\">\n"
- << getMethodsDBusIntrospectionXmlData() << "\n"
- "</interface>\n"
- "</node>";
-
- DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("s");
- DBusOutputStream dbusOutputStream(dbusMessageReply);
- dbusOutputStream << xmlData.str();
- dbusOutputStream.flush();
-
- dbusMessageHandled = dbusConnection_->sendDBusMessage(dbusMessageReply);
- }
-
- return dbusMessageHandled;
-}
-
} // namespace dbus
} // namespace CommonAPI
diff --git a/src/CommonAPI/DBus/DBusStubAdapter.h b/src/CommonAPI/DBus/DBusStubAdapter.h
index fafea2e..0382e61 100644
--- a/src/CommonAPI/DBus/DBusStubAdapter.h
+++ b/src/CommonAPI/DBus/DBusStubAdapter.h
@@ -7,10 +7,11 @@
#ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_
#define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_
-#include "DBusConnection.h"
+#include "DBusProxyConnection.h"
+#include "DBusObjectManager.h"
+#include "DBusMessage.h"
#include <CommonAPI/Stub.h>
-#include <CommonAPI/DBus/DBusMessage.h>
#include <string>
#include <memory>
@@ -41,13 +42,10 @@ class DBusStubAdapter: virtual public CommonAPI::StubAdapter {
inline const std::shared_ptr<DBusProxyConnection>& getDBusConnection() const;
- protected:
virtual const char* getMethodsDBusIntrospectionXmlData() const = 0;
virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) = 0;
private:
- bool onIntrospectionInterfaceDBusMessage(const DBusMessage& dbusMessage);
-
const std::string commonApiDomain_;
const std::string commonApiServiceId_;
const std::string commonApiParticipantId_;
@@ -59,7 +57,6 @@ class DBusStubAdapter: virtual public CommonAPI::StubAdapter {
bool isInitialized_;
- DBusInterfaceHandlerToken dbusIntrospectionInterfaceHandlerToken_;
DBusInterfaceHandlerToken dbusInterfaceHandlerToken_;
static const std::string domain_;
diff --git a/src/CommonAPI/DBus/DBusStubAdapterHelper.h b/src/CommonAPI/DBus/DBusStubAdapterHelper.h
index 4417c74..ee627a3 100644
--- a/src/CommonAPI/DBus/DBusStubAdapterHelper.h
+++ b/src/CommonAPI/DBus/DBusStubAdapterHelper.h
@@ -11,6 +11,7 @@
#include "DBusInputStream.h"
#include "DBusOutputStream.h"
#include "DBusHelper.h"
+#include "DBusSerializableArguments.h"
#include <memory>
#include <initializer_list>
diff --git a/src/test/DBusAddressTranslatorTest.cpp b/src/test/DBusAddressTranslatorTest.cpp
index c9dcca7..3382934 100644
--- a/src/test/DBusAddressTranslatorTest.cpp
+++ b/src/test/DBusAddressTranslatorTest.cpp
@@ -120,6 +120,7 @@ protected:
}
virtual void TearDown() {
+ usleep(30000);
}
};
@@ -158,28 +159,32 @@ TEST_F(AddressTranslatorTest, ParsesCommonAPIAddresses) {
TEST_F(AddressTranslatorTest, ServicesUsingPredefinedAddressesCanCommunicate) {
- std::shared_ptr<CommonAPI::Runtime> runtime;
- std::shared_ptr<CommonAPI::Factory> proxyFactory;
- std::shared_ptr<CommonAPI::Factory> stubFactory;
-
- runtime = CommonAPI::Runtime::load();
+ std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load();
ASSERT_TRUE((bool)runtime);
CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast<CommonAPI::DBus::DBusRuntime*>(&(*runtime));
ASSERT_TRUE(dbusRuntime != NULL);
- proxyFactory = runtime->createFactory();
+ std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory();
ASSERT_TRUE((bool)proxyFactory);
- stubFactory = runtime->createFactory();
+ std::shared_ptr<CommonAPI::Factory> stubFactory = runtime->createFactory();
ASSERT_TRUE((bool)stubFactory);
auto defaultTestProxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>(commonApiAddresses[0]);
ASSERT_TRUE((bool)defaultTestProxy);
auto stub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
- bool success = stubFactory->registerService(stub, commonApiAddresses[0]);
- ASSERT_TRUE(success);
- sleep(1);
+ bool serviceNameAcquired = stubFactory->registerService(stub, commonApiAddresses[0]);
+ for(unsigned int i = 0; !serviceNameAcquired && i < 100; i++) {
+ serviceNameAcquired = stubFactory->registerService(stub, commonApiAddresses[0]);
+ usleep(10000);
+ }
+ ASSERT_TRUE(serviceNameAcquired);
+
+ for(unsigned int i = 0; !defaultTestProxy->isAvailable() && i < 100; ++i) {
+ usleep(10000);
+ }
+ ASSERT_TRUE(defaultTestProxy->isAvailable());
uint32_t v1 = 5;
std::string v2 = "Hai :)";
@@ -223,7 +228,7 @@ void fakeLegacyServiceThread() {
TEST_F(AddressTranslatorTest, FakeLegacyServiceCanBeAddressed) {
std::thread fakeServiceThread = std::thread(fakeLegacyServiceThread);
- sleep(1);
+ usleep(500000);
std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load();
ASSERT_TRUE((bool)runtime);
@@ -259,7 +264,7 @@ TEST_F(AddressTranslatorTest, FakeLegacyServiceCanBeAddressed) {
//end the fake legacy service via dbus
int resultCode = system("python ./src/test/fakeLegacyService/sendToFakeLegacyService.py finish");
- EXPECT_EQ(0, resultCode);
+ ASSERT_EQ(0, resultCode);
fakeServiceThread.join();
}
diff --git a/src/test/DBusCommunicationTest.cpp b/src/test/DBusCommunicationTest.cpp
index 5eeb765..a2b62e0 100644
--- a/src/test/DBusCommunicationTest.cpp
+++ b/src/test/DBusCommunicationTest.cpp
@@ -73,6 +73,7 @@ class DBusCommunicationTest: public ::testing::Test {
}
virtual void TearDown() {
+ usleep(30000);
}
std::shared_ptr<CommonAPI::Runtime> runtime_;
@@ -83,7 +84,7 @@ class DBusCommunicationTest: public ::testing::Test {
static const std::string nonstandardAddress_;
};
-const std::string DBusCommunicationTest::serviceAddress_ = "local:commonapi.tests.TestInterface:commonapi.tests.TestInterface";
+const std::string DBusCommunicationTest::serviceAddress_ = "local:CommonAPI.DBus.tests.DBusProxyTestInterface:CommonAPI.DBus.tests.DBusProxyTestService";
const std::string DBusCommunicationTest::nonstandardAddress_ = "local:non.standard.ServiceName:non.standard.participand.ID";
@@ -93,10 +94,18 @@ TEST_F(DBusCommunicationTest, RemoteMethodCallSucceeds) {
ASSERT_TRUE((bool)defaultTestProxy);
auto stub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
- bool success = stubFactory_->registerService(stub, serviceAddress_);
- ASSERT_TRUE(success);
- sleep(1);
+ bool serviceRegistered = stubFactory_->registerService(stub, serviceAddress_);
+ for(unsigned int i = 0; !serviceRegistered && i < 100; ++i) {
+ serviceRegistered = stubFactory_->registerService(stub, serviceAddress_);
+ 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 ;)";
@@ -114,10 +123,18 @@ TEST_F(DBusCommunicationTest, RemoteMethodCallWithNonstandardAddressSucceeds) {
ASSERT_TRUE((bool)defaultTestProxy);
auto stub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
- bool success = stubFactory_->registerService(stub, nonstandardAddress_);
- ASSERT_TRUE(success);
- sleep(1);
+ bool serviceRegistered = stubFactory_->registerService(stub, nonstandardAddress_);
+ for(unsigned int i = 0; !serviceRegistered && i < 100; ++i) {
+ serviceRegistered = stubFactory_->registerService(stub, nonstandardAddress_);
+ 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 = "Hai :)";
@@ -129,6 +146,94 @@ TEST_F(DBusCommunicationTest, RemoteMethodCallWithNonstandardAddressSucceeds) {
}
+//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";
+//static const std::string interfaceName = "CommonAPI.DBus.tests.DBusProxyTestInterface";
+//static const std::string busName = "CommonAPI.DBus.tests.DBusProxyTestService";
+//static const std::string objectPath = "/CommonAPI/DBus/tests/DBusProxyTestService";
+
+//TEST_F(DBusCommunicationTest, AsyncCallsAreQueuedCorrectly) {
+// auto proxyDBusConnection = CommonAPI::DBus::DBusConnection::getSessionBus();
+// ASSERT_TRUE(proxyDBusConnection->connect());
+//
+// auto stub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
+//
+// bool serviceRegistered = stubFactory_->registerService(stub, serviceAddress_);
+// for(unsigned int i = 0; !serviceRegistered && i < 100; ++i) {
+// serviceRegistered = stubFactory_->registerService(stub, serviceAddress_);
+// usleep(10000);
+// }
+// ASSERT_TRUE(serviceRegistered);
+//
+// auto defaultTestProxy = std::make_shared<commonapi::tests::TestInterfaceDBusProxy>(
+// commonApiAddress,
+// interfaceName,
+// busName,
+// objectPath,
+// proxyDBusConnection);
+//
+// for(unsigned int i = 0; !defaultTestProxy->isAvailable() && i < 100; ++i) {
+// usleep(10000);
+// }
+// ASSERT_TRUE(defaultTestProxy->isAvailable());
+//
+// auto val1 = commonapi::tests::DerivedTypeCollection::TestEnumExtended2::E_OK;
+// commonapi::tests::DerivedTypeCollection::TestMap val2;
+// CommonAPI::CallStatus status;
+// unsigned int numCalled = 0;
+// const unsigned int maxNumCalled = 1000;
+// for(unsigned int i = 0; i < maxNumCalled/2; ++i) {
+// defaultTestProxy->testVoidDerivedTypeMethodAsync(val1, val2,
+// [&] (CommonAPI::CallStatus stat) {
+// if(stat == CommonAPI::CallStatus::SUCCESS) {
+// numCalled++;
+// }
+// }
+// );
+// }
+//
+// proxyDBusConnection->suspendDispatching();
+//
+// for(unsigned int i = maxNumCalled/2; i < maxNumCalled; ++i) {
+// defaultTestProxy->testVoidDerivedTypeMethodAsync(val1, val2,
+// [&] (CommonAPI::CallStatus stat) {
+// if(stat == CommonAPI::CallStatus::SUCCESS) {
+// numCalled++;
+// }
+// }
+// );
+// }
+// sleep(2);
+//
+// proxyDBusConnection->resumeDispatching();
+//
+// sleep(2);
+//
+// ASSERT_EQ(maxNumCalled, numCalled);
+//
+// numCalled = 0;
+//
+// defaultTestProxy->getTestPredefinedTypeBroadcastEvent().subscribe(
+// [&] (uint32_t, std::string) {
+// numCalled++;
+// }
+// );
+//
+// proxyDBusConnection->suspendDispatching();
+//
+// for(unsigned int i = 0; i < maxNumCalled; ++i) {
+// stub->fireTestPredefinedTypeBroadcastEvent(0, "Nonething");
+// }
+//
+// sleep(2);
+// proxyDBusConnection->resumeDispatching();
+// sleep(2);
+//
+// ASSERT_EQ(maxNumCalled, numCalled);
+//}
+
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/src/test/DBusConnectionTest.cpp b/src/test/DBusConnectionTest.cpp
index 0b85009..19a02a8 100644
--- a/src/test/DBusConnectionTest.cpp
+++ b/src/test/DBusConnectionTest.cpp
@@ -4,195 +4,275 @@
* 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 <common-api-dbus/dbus-connection.h>
-#include <common-api-dbus/dbus-output-message-stream.h>
+#include <CommonAPI/DBus/DBusConnection.h>
+#include <CommonAPI/DBus/DBusProxyAsyncCallbackHandler.h>
#include <gtest/gtest.h>
+#include <dbus/dbus.h>
#include <cstring>
-#define ASSERT_DBUSMESSAGE_EQ(_dbusMessage1, _dbusMessage2) \
- ASSERT_FALSE(_dbusMessage1.getSignatureString() == NULL); \
- ASSERT_FALSE(_dbusMessage2.getSignatureString() == NULL); \
- ASSERT_STREQ(_dbusMessage1.getSignatureString(), _dbusMessage2.getSignatureString()); \
- ASSERT_EQ(_dbusMessage1.getBodyLength(), _dbusMessage2.getBodyLength()); \
- ASSERT_FALSE(_dbusMessage1.getBodyData() == NULL); \
- ASSERT_FALSE(_dbusMessage2.getBodyData() == NULL); \
- ASSERT_EQ(memcmp(_dbusMessage1.getBodyData(), _dbusMessage2.getBodyData(), _dbusMessage1.getBodyLength()), 0)
-
-
-namespace {
-
class DBusConnectionTest: public ::testing::Test {
- public:
- void onConnectionStatusEvent(const common::api::AvailabilityStatus& newConnectionStatus) {
- connectionStatusEventCount_++;
- connectionStatus_ = newConnectionStatus;
- }
-
- bool onInterfaceHandlerDBusMessageReply(const common::api::dbus::DBusMessage& dbusMessage,
- const std::shared_ptr<common::api::dbus::DBusConnection>& dbusConnection) {
- interfaceHandlerDBusMessageCount_++;
- interfaceHandlerDBusMessage_ = dbusMessage;
- interfaceHandlerDBusMessageReply_ = dbusMessage.createMethodReturn("si");
-
- common::api::dbus::DBusOutputMessageStream dbusOutputMessageStream(interfaceHandlerDBusMessageReply_);
- dbusOutputMessageStream << "This is a default message reply!" << interfaceHandlerDBusMessageCount_;
- dbusOutputMessageStream.flush();
-
- dbusConnection->sendDBusMessage(interfaceHandlerDBusMessageReply_);
-
- return true;
- }
-
- void onDBusMessageHandler(const common::api::dbus::DBusMessage& dbusMessage) {
- dbusMessageHandlerCount_++;
- dbusMessageHandlerDBusMessage_ = dbusMessage;
- }
-
protected:
virtual void SetUp() {
- dbusConnection_ = common::api::dbus::DBusConnection::getSessionBus();
- connectionStatusEventCount_ = 0;
- interfaceHandlerDBusMessageCount_ = 0;
- dbusMessageHandlerCount_ = 0;
}
virtual void TearDown() {
- if (dbusConnection_ && dbusConnection_->isConnected())
- dbusConnection_->disconnect();
-
- // reset DBusMessage
- interfaceHandlerDBusMessage_ = common::api::dbus::DBusMessage();
- interfaceHandlerDBusMessageReply_ = common::api::dbus::DBusMessage();
-
- dbusMessageHandlerDBusMessage_ = common::api::dbus::DBusMessage();
}
-
-
- std::shared_ptr<common::api::dbus::DBusConnection> dbusConnection_;
-
- uint32_t connectionStatusEventCount_;
- common::api::AvailabilityStatus connectionStatus_;
-
- uint32_t interfaceHandlerDBusMessageCount_;
- common::api::dbus::DBusMessage interfaceHandlerDBusMessage_;
- common::api::dbus::DBusMessage interfaceHandlerDBusMessageReply_;
-
- uint32_t dbusMessageHandlerCount_;
- common::api::dbus::DBusMessage dbusMessageHandlerDBusMessage_;
};
-TEST_F(DBusConnectionTest, IsInitiallyDisconnected) {
- ASSERT_FALSE(dbusConnection_->isConnected());
+//TEST_F(DBusConnectionTest, IsInitiallyDisconnected) {
+// ASSERT_FALSE(dbusConnection_->isConnected());
+//}
+//
+//TEST_F(DBusConnectionTest, ConnectAndDisconnectWork) {
+// ASSERT_TRUE(dbusConnection_->connect());
+// ASSERT_TRUE(dbusConnection_->isConnected());
+//
+// dbusConnection_->disconnect();
+// ASSERT_FALSE(dbusConnection_->isConnected());
+//}
+//
+//TEST_F(DBusConnectionTest, ConnectionStatusEventWorks) {
+// ASSERT_EQ(connectionStatusEventCount_, 0);
+//
+// auto connectionStatusSubscription = dbusConnection_->getConnectionStatusEvent().subscribe(std::bind(
+// &DBusConnectionTest::onConnectionStatusEvent,
+// this,
+// 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());
+// ASSERT_EQ(connectionStatusEventCount_, ++expectedEventCount);
+// ASSERT_EQ(connectionStatus_, common::api::AvailabilityStatus::AVAILABLE);
+//
+// dbusConnection_->disconnect();
+// ASSERT_FALSE(dbusConnection_->isConnected());
+// ASSERT_EQ(connectionStatusEventCount_, ++expectedEventCount);
+// ASSERT_EQ(connectionStatus_, common::api::AvailabilityStatus::NOT_AVAILABLE);
+// }
+//
+// dbusConnection_->getConnectionStatusEvent().unsubscribe(connectionStatusSubscription);
+// 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);
+//}
+//
+//TEST_F(DBusConnectionTest, SendingAsyncDBusMessagesWorks) {
+// const char* busName = "common.api.dbus.test.TestInterfaceHandler";
+// const char* objectPath = "/common/api/dbus/test/TestObject";
+// const char* interfaceName = "common.api.dbus.test.TestInterface";
+// const char* methodName = "TestMethod";
+//
+// auto interfaceHandlerDBusConnection = common::api::dbus::DBusConnection::getSessionBus();
+//
+// ASSERT_TRUE(interfaceHandlerDBusConnection->connect());
+// ASSERT_TRUE(interfaceHandlerDBusConnection->requestServiceNameAndBlock(busName));
+//
+// auto interfaceHandlerToken = interfaceHandlerDBusConnection->registerInterfaceHandler(
+// objectPath,
+// interfaceName,
+// std::bind(&DBusConnectionTest::onInterfaceHandlerDBusMessageReply,
+// this,
+// std::placeholders::_1,
+// interfaceHandlerDBusConnection));
+//
+//
+// ASSERT_TRUE(dbusConnection_->connect());
+//
+// for (uint32_t expectedDBusMessageCount = 1; expectedDBusMessageCount <= 10; expectedDBusMessageCount++) {
+// auto dbusMessageCall = common::api::dbus::DBusMessage::createMethodCall(
+// busName,
+// objectPath,
+// interfaceName,
+// methodName,
+// "si");
+// ASSERT_TRUE(dbusMessageCall);
+//
+// common::api::dbus::DBusOutputMessageStream dbusOutputMessageStream(dbusMessageCall);
+// dbusOutputMessageStream << "This is a test async call"
+// << expectedDBusMessageCount;
+// dbusOutputMessageStream.flush();
+//
+// dbusConnection_->sendDBusMessageWithReplyAsync(
+// dbusMessageCall,
+// std::bind(&DBusConnectionTest::onDBusMessageHandler, this, std::placeholders::_1));
+//
+// for (int i = 0; i < 10 && interfaceHandlerDBusMessageCount_ < expectedDBusMessageCount; i++)
+// interfaceHandlerDBusConnection->readWriteDispatch(100);
+//
+// ASSERT_EQ(interfaceHandlerDBusMessageCount_, expectedDBusMessageCount);
+// ASSERT_DBUSMESSAGE_EQ(dbusMessageCall, interfaceHandlerDBusMessage_);
+//
+// for (int i = 0; i < 10 && dbusMessageHandlerCount_ < expectedDBusMessageCount; i++)
+// dbusConnection_->readWriteDispatch(100);
+//
+// ASSERT_EQ(dbusMessageHandlerCount_, expectedDBusMessageCount);
+// ASSERT_DBUSMESSAGE_EQ(dbusMessageHandlerDBusMessage_, interfaceHandlerDBusMessageReply_);
+// }
+//
+// dbusConnection_->disconnect();
+//
+//
+// interfaceHandlerDBusConnection->unregisterInterfaceHandler(interfaceHandlerToken);
+//
+// ASSERT_TRUE(interfaceHandlerDBusConnection->releaseServiceName(busName));
+// interfaceHandlerDBusConnection->disconnect();
+//}
+
+
+void dispatch(::DBusConnection* libdbusConnection) {
+ dbus_bool_t success = TRUE;
+ while(success) {
+ success = dbus_connection_read_write_dispatch(libdbusConnection, 1);
+ }
}
-TEST_F(DBusConnectionTest, ConnectAndDisconnectWork) {
- ASSERT_TRUE(dbusConnection_->connect());
- ASSERT_TRUE(dbusConnection_->isConnected());
+std::promise<bool> promise;
+std::future<bool> future = promise.get_future();
- dbusConnection_->disconnect();
- ASSERT_FALSE(dbusConnection_->isConnected());
+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, ConnectionStatusEventWorks) {
- ASSERT_EQ(connectionStatusEventCount_, 0);
+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);
- auto connectionStatusSubscription = dbusConnection_->getConnectionStatusEvent().subscribe(std::bind(
- &DBusConnectionTest::onConnectionStatusEvent,
- this,
- std::placeholders::_1));
+ assert(libdbusConnection);
+ dbus_connection_set_exit_on_disconnect(libdbusConnection, false);
- ASSERT_FALSE(dbusConnection_->isConnected());
- ASSERT_EQ(connectionStatusEventCount_, 0);
+ auto dispatchThread = std::thread(&dispatch, libdbusConnection);
- uint32_t expectedEventCount = 0;
- while (expectedEventCount < 10) {
- ASSERT_TRUE(dbusConnection_->connect());
- ASSERT_TRUE(dbusConnection_->isConnected());
- ASSERT_EQ(connectionStatusEventCount_, ++expectedEventCount);
- ASSERT_EQ(connectionStatus_, common::api::AvailabilityStatus::AVAILABLE);
+ ::DBusMessage* libdbusMessageCall = dbus_message_new_method_call(
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "ListNames");
- dbusConnection_->disconnect();
- ASSERT_FALSE(dbusConnection_->isConnected());
- ASSERT_EQ(connectionStatusEventCount_, ++expectedEventCount);
- ASSERT_EQ(connectionStatus_, common::api::AvailabilityStatus::NOT_AVAILABLE);
- }
+ dbus_message_set_signature(libdbusMessageCall, "");
- dbusConnection_->getConnectionStatusEvent().unsubscribe(connectionStatusSubscription);
- ASSERT_EQ(connectionStatusEventCount_, expectedEventCount);
+ DBusPendingCall* libdbusPendingCall;
+ dbus_bool_t libdbusSuccess;
- ASSERT_TRUE(dbusConnection_->connect());
- ASSERT_TRUE(dbusConnection_->isConnected());
- ASSERT_EQ(connectionStatusEventCount_, expectedEventCount);
+ dbus_connection_send_with_reply(
+ libdbusConnection,
+ libdbusMessageCall,
+ &libdbusPendingCall,
+ 500);
- dbusConnection_->disconnect();
- ASSERT_FALSE(dbusConnection_->isConnected());
- ASSERT_EQ(connectionStatusEventCount_, expectedEventCount);
-}
+ dbus_pending_call_set_notify(
+ libdbusPendingCall,
+ notifyThunk,
+ libdbusConnection,
+ NULL);
-TEST_F(DBusConnectionTest, SendingAsyncDBusMessagesWorks) {
- const char* busName = "common.api.dbus.test.TestInterfaceHandler";
- const char* objectPath = "/common/api/dbus/test/TestObject";
- const char* interfaceName = "common.api.dbus.test.TestInterface";
- const char* methodName = "TestMethod";
-
- auto interfaceHandlerDBusConnection = common::api::dbus::DBusConnection::getSessionBus();
+ ASSERT_EQ(true, future.get());
+ dispatchThread.join();
+}
- ASSERT_TRUE(interfaceHandlerDBusConnection->connect());
- ASSERT_TRUE(interfaceHandlerDBusConnection->requestServiceNameAndBlock(busName));
- auto interfaceHandlerToken = interfaceHandlerDBusConnection->registerInterfaceHandler(
- objectPath,
- interfaceName,
- std::bind(&DBusConnectionTest::onInterfaceHandlerDBusMessageReply,
- this,
- std::placeholders::_1,
- interfaceHandlerDBusConnection));
+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);
+}
- ASSERT_TRUE(dbusConnection_->connect());
+void noPartnerCleanup(void* data) {
+ std::cout << "Cleanup" << std::endl;
+ promise3.set_value(true);
+}
- for (uint32_t expectedDBusMessageCount = 1; expectedDBusMessageCount <= 10; expectedDBusMessageCount++) {
- auto dbusMessageCall = common::api::dbus::DBusMessage::createMethodCall(
- busName,
- objectPath,
- interfaceName,
- methodName,
- "si");
- ASSERT_TRUE(dbusMessageCall);
+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);
- common::api::dbus::DBusOutputMessageStream dbusOutputMessageStream(dbusMessageCall);
- dbusOutputMessageStream << "This is a test async call"
- << expectedDBusMessageCount;
- dbusOutputMessageStream.flush();
+ assert(libdbusConnection);
+ dbus_connection_set_exit_on_disconnect(libdbusConnection, false);
- dbusConnection_->sendDBusMessageWithReplyAsync(
- dbusMessageCall,
- std::bind(&DBusConnectionTest::onDBusMessageHandler, this, std::placeholders::_1));
+ auto dispatchThread = std::thread(&dispatch, libdbusConnection);
- for (int i = 0; i < 10 && interfaceHandlerDBusMessageCount_ < expectedDBusMessageCount; i++)
- interfaceHandlerDBusConnection->readWriteDispatch(100);
+ ::DBusMessage* libdbusMessageCall = dbus_message_new_method_call(
+ "some.connection.somewhere",
+ "/some/non/existing/object",
+ "some.interface.somewhere.but.same.place",
+ "NoReasonableMethod");
- ASSERT_EQ(interfaceHandlerDBusMessageCount_, expectedDBusMessageCount);
- ASSERT_DBUSMESSAGE_EQ(dbusMessageCall, interfaceHandlerDBusMessage_);
+ dbus_message_set_signature(libdbusMessageCall, "");
- for (int i = 0; i < 10 && dbusMessageHandlerCount_ < expectedDBusMessageCount; i++)
- dbusConnection_->readWriteDispatch(100);
+ bool hasHappened = false;
- ASSERT_EQ(dbusMessageHandlerCount_, expectedDBusMessageCount);
- ASSERT_DBUSMESSAGE_EQ(dbusMessageHandlerDBusMessage_, interfaceHandlerDBusMessageReply_);
- }
+ DBusPendingCall* libdbusPendingCall;
+ dbus_bool_t libdbusSuccess;
- dbusConnection_->disconnect();
+ dbus_connection_send_with_reply(
+ libdbusConnection,
+ libdbusMessageCall,
+ &libdbusPendingCall,
+ 5000);
+ dbus_pending_call_set_notify(
+ libdbusPendingCall,
+ noPartnerCallback,
+ libdbusConnection,
+ noPartnerCleanup);
- interfaceHandlerDBusConnection->unregisterInterfaceHandler(interfaceHandlerToken);
+ ASSERT_EQ(true, future2.get());
+ dispatchThread.join();
+}
- ASSERT_TRUE(interfaceHandlerDBusConnection->releaseServiceName(busName));
- interfaceHandlerDBusConnection->disconnect();
+//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());
+//}
+
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
}
-} // namespace
diff --git a/src/test/DBusDaemonProxyTest.cpp b/src/test/DBusDaemonProxyTest.cpp
index c25098e..16338f5 100644
--- a/src/test/DBusDaemonProxyTest.cpp
+++ b/src/test/DBusDaemonProxyTest.cpp
@@ -25,8 +25,6 @@ class DBusDaemonProxyTest: public ::testing::Test {
}
virtual void TearDown() {
- if (dbusConnection_ && dbusConnection_->isConnected()) {
- }
}
std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_;
@@ -56,7 +54,7 @@ TEST_F(DBusDaemonProxyTest, ListNamesAsync) {
promise.set_value(std::tuple<CommonAPI::CallStatus, std::vector<std::string>>(callStatus, std::move(busNames)));
});
- auto status = future.wait_for(std::chrono::milliseconds(200));
+ auto status = future.wait_for(std::chrono::milliseconds(500));
bool waitResult = CommonAPI::DBus::checkReady(status);
ASSERT_EQ(waitResult, true);
@@ -98,12 +96,6 @@ TEST_F(DBusDaemonProxyTest, NameHasOwnerAsync) {
promise.set_value(std::tuple<CommonAPI::CallStatus, bool>(callStatus, std::move(nameHasOwner)));
});
- //while (readWriteDispatchCount_ < 5) {
- // ASSERT_TRUE(doReadWriteDispatch());
- //if (callStatusFuture.wait_for(std::chrono::milliseconds(100)) == std::future_status::ready)
- // break;
- //}
- //ASSERT_NE(readWriteDispatchCount_, 5);
auto status = future.wait_for(std::chrono::milliseconds(100));
const bool waitResult = CommonAPI::DBus::checkReady(status);
ASSERT_EQ(waitResult, true);
@@ -122,7 +114,7 @@ TEST_F(DBusDaemonProxyTest, NameOwnerChangedEvent) {
std::promise<bool> promise;
auto future = promise.get_future();
- dbusDaemonProxy_->getNameOwnerChangedEvent().subscribe(
+ auto subscription = dbusDaemonProxy_->getNameOwnerChangedEvent().subscribe(
[&](const std::string& name, const std::string& oldOwner, const std::string& newOwner) {
static bool promiseIsSet = false;
if(!promiseIsSet) {
@@ -134,14 +126,9 @@ TEST_F(DBusDaemonProxyTest, NameOwnerChangedEvent) {
// Trigger NameOwnerChanged using a new DBusConnection
ASSERT_TRUE(CommonAPI::DBus::DBusConnection::getSessionBus()->connect());
- //while (readWriteDispatchCount_ < 5) {
- // ASSERT_TRUE(doReadWriteDispatch());
- //if (future.wait_for(std::chrono::milliseconds(100)) == std::future_status::ready)
- // break;
- //}
-
- //ASSERT_NE(readWriteDispatchCount_, 5);
ASSERT_TRUE(future.get());
+
+ dbusDaemonProxy_->getNameOwnerChangedEvent().unsubscribe(subscription);
}
} // namespace
diff --git a/src/test/DBusFactoryTest.cpp b/src/test/DBusFactoryTest.cpp
index d99cb6b..52330a9 100644
--- a/src/test/DBusFactoryTest.cpp
+++ b/src/test/DBusFactoryTest.cpp
@@ -45,6 +45,7 @@ class DBusProxyFactoryTest: public ::testing::Test {
}
virtual void TearDown() {
+ usleep(30000);
}
std::shared_ptr<CommonAPI::Runtime> runtime_;
diff --git a/src/test/DBusMainLoopIntegrationTest.cpp b/src/test/DBusMainLoopIntegrationTest.cpp
new file mode 100644
index 0000000..1a16171
--- /dev/null
+++ b/src/test/DBusMainLoopIntegrationTest.cpp
@@ -0,0 +1,613 @@
+/* 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 <cassert>
+#include <cstdint>
+#include <iostream>
+#include <functional>
+#include <memory>
+#include <stdint.h>
+#include <string>
+#include <utility>
+#include <tuple>
+#include <type_traits>
+#include <glib.h>
+
+#include <CommonAPI/types.h>
+#include <CommonAPI/AttributeExtension.h>
+#include <CommonAPI/Runtime.h>
+
+#include <CommonAPI/DBus/DBusConnection.h>
+#include <CommonAPI/DBus/DBusProxy.h>
+#include <CommonAPI/DBus/DBusRuntime.h>
+
+#include "DBusTestUtils.h"
+#include "DemoMainLoop.h"
+
+#include "commonapi/tests/PredefinedTypeCollection.h"
+#include "commonapi/tests/DerivedTypeCollection.h"
+#include "commonapi/tests/TestInterfaceProxy.h"
+#include "commonapi/tests/TestInterfaceStubDefault.h"
+#include "commonapi/tests/TestInterfaceDBusStubAdapter.h"
+
+#include "commonapi/tests/TestInterfaceDBusProxy.h"
+
+
+const std::string testAddress1 = "local:my.first.test:commonapi.address.one";
+const std::string testAddress2 = "local:my.second.test:commonapi.address.two";
+const std::string testAddress3 = "local:my.third.test:commonapi.address.three";
+const std::string testAddress4 = "local:my.fourth.test:commonapi.address.four";
+const std::string testAddress5 = "local:my.fifth.test:commonapi.address.five";
+const std::string testAddress6 = "local:my.sixth.test:commonapi.address.six";
+const std::string testAddress7 = "local:my.seventh.test:commonapi.address.seven";
+const std::string testAddress8 = "local:my.eigth.test:commonapi.address.eight";
+
+//####################################################################################################################
+
+class DBusBasicMainLoopTest: public ::testing::Test {
+protected:
+ virtual void SetUp() {
+ }
+
+ virtual void TearDown() {
+ }
+};
+
+
+TEST_F(DBusBasicMainLoopTest, MainloopContextCanBeCreated) {
+ std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load();
+ ASSERT_TRUE((bool) runtime);
+
+ std::shared_ptr<CommonAPI::MainLoopContext> context = runtime->getNewMainLoopContext();
+ ASSERT_TRUE((bool) context);
+}
+
+
+TEST_F(DBusBasicMainLoopTest, SeveralMainloopContextsCanBeCreated) {
+ std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load();
+ ASSERT_TRUE((bool)runtime);
+
+ std::shared_ptr<CommonAPI::MainLoopContext> context1 = runtime->getNewMainLoopContext();
+ ASSERT_TRUE((bool) context1);
+ std::shared_ptr<CommonAPI::MainLoopContext> context2 = runtime->getNewMainLoopContext();
+ ASSERT_TRUE((bool) context2);
+ std::shared_ptr<CommonAPI::MainLoopContext> context3 = runtime->getNewMainLoopContext();
+ ASSERT_TRUE((bool) context3);
+
+ ASSERT_NE(context1, context2);
+ ASSERT_NE(context1, context3);
+ ASSERT_NE(context2, context3);
+}
+
+struct TestSource: public CommonAPI::DispatchSource {
+ TestSource(const std::string value, std::string& result): value_(value), result_(result) {}
+
+ bool prepare(int64_t& timeout) {
+ return true;
+ }
+ bool check() {
+ return true;
+ }
+ bool dispatch() {
+ result_.append(value_);
+ return false;
+ }
+
+ private:
+ std::string value_;
+ std::string& result_;
+};
+
+TEST_F(DBusBasicMainLoopTest, PrioritiesAreHandledCorrectlyInDemoMainloop) {
+ std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load();
+ ASSERT_TRUE((bool) runtime);
+
+ std::shared_ptr<CommonAPI::MainLoopContext> context = runtime->getNewMainLoopContext();
+ ASSERT_TRUE((bool) context);
+
+ auto mainLoop = new CommonAPI::MainLoop(context);
+
+ std::string result = "";
+
+ TestSource* testSource1Default = new TestSource("A", result);
+ TestSource* testSource2Default = new TestSource("B", result);
+ TestSource* testSource1High = new TestSource("C", result);
+ TestSource* testSource1Low = new TestSource("D", result);
+ TestSource* testSource1VeryHigh = new TestSource("E", result);
+ context->registerDispatchSource(testSource1Default);
+ context->registerDispatchSource(testSource2Default, CommonAPI::DispatchPriority::DEFAULT);
+ context->registerDispatchSource(testSource1High, CommonAPI::DispatchPriority::HIGH);
+ context->registerDispatchSource(testSource1Low, CommonAPI::DispatchPriority::LOW);
+ context->registerDispatchSource(testSource1VeryHigh, CommonAPI::DispatchPriority::VERY_HIGH);
+
+ mainLoop->doSingleIteration(CommonAPI::TIMEOUT_INFINITE);
+
+ std::string reference("ECABD");
+ ASSERT_EQ(reference, result);
+}
+
+
+//####################################################################################################################
+
+class DBusMainLoopTest: public ::testing::Test {
+protected:
+ virtual void SetUp() {
+ runtime_ = CommonAPI::Runtime::load();
+ ASSERT_TRUE((bool) runtime_);
+
+ context_ = runtime_->getNewMainLoopContext();
+ ASSERT_TRUE((bool) context_);
+ mainLoop_ = new CommonAPI::MainLoop(context_);
+
+ mainloopFactory_ = runtime_->createFactory(context_);
+ ASSERT_TRUE((bool) mainloopFactory_);
+ standardFactory_ = runtime_->createFactory();
+ ASSERT_TRUE((bool) standardFactory_);
+ }
+
+ virtual void TearDown() {
+ delete mainLoop_;
+ }
+
+ std::shared_ptr<CommonAPI::Runtime> runtime_;
+ std::shared_ptr<CommonAPI::MainLoopContext> context_;
+ std::shared_ptr<CommonAPI::Factory> mainloopFactory_;
+ std::shared_ptr<CommonAPI::Factory> standardFactory_;
+ CommonAPI::MainLoop* mainLoop_;
+};
+
+
+TEST_F(DBusMainLoopTest, ServiceInDemoMainloopCanBeAddressed) {
+ std::shared_ptr<commonapi::tests::TestInterfaceStubDefault> stub = std::make_shared<
+ commonapi::tests::TestInterfaceStubDefault>();
+ ASSERT_TRUE(mainloopFactory_->registerService(stub, testAddress1));
+
+ auto proxy = standardFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(testAddress1);
+ ASSERT_TRUE((bool) proxy);
+
+ while (!proxy->isAvailable()) {
+ mainLoop_->doSingleIteration(50000);
+ }
+
+ uint32_t uint32Value = 42;
+ std::string stringValue = "Hai :)";
+
+ std::future<CommonAPI::CallStatus> futureStatus = proxy->testVoidPredefinedTypeMethodAsync(
+ uint32Value,
+ stringValue,
+ [&] (const CommonAPI::CallStatus& status) {
+ EXPECT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(status));
+ mainLoop_->stop();
+ }
+ );
+
+ mainLoop_->run();
+
+ ASSERT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(futureStatus.get()));
+
+ mainloopFactory_->unregisterService(testAddress1);
+}
+
+
+TEST_F(DBusMainLoopTest, ProxyInDemoMainloopCanCallMethods) {
+ std::shared_ptr<commonapi::tests::TestInterfaceStubDefault> stub = std::make_shared<
+ commonapi::tests::TestInterfaceStubDefault>();
+ ASSERT_TRUE(standardFactory_->registerService(stub, testAddress2));
+
+ usleep(500000);
+
+ auto proxy = mainloopFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(testAddress2);
+ ASSERT_TRUE((bool) proxy);
+
+ while (!proxy->isAvailable()) {
+ mainLoop_->doSingleIteration();
+ usleep(50000);
+ }
+
+ uint32_t uint32Value = 42;
+ std::string stringValue = "Hai :)";
+
+ std::future<CommonAPI::CallStatus> futureStatus = proxy->testVoidPredefinedTypeMethodAsync(
+ uint32Value,
+ stringValue,
+ [&] (const CommonAPI::CallStatus& status) {
+ EXPECT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(status));
+ mainLoop_->stop();
+ }
+ );
+
+ mainLoop_->run();
+
+ ASSERT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(futureStatus.get()));
+
+ standardFactory_->unregisterService(testAddress2);
+}
+
+TEST_F(DBusMainLoopTest, ProxyAndServiceInSameDemoMainloopCanCommunicate) {
+ std::shared_ptr<commonapi::tests::TestInterfaceStubDefault> stub = std::make_shared<
+ commonapi::tests::TestInterfaceStubDefault>();
+ ASSERT_TRUE(mainloopFactory_->registerService(stub, testAddress4));
+
+ auto proxy = mainloopFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(testAddress4);
+ ASSERT_TRUE((bool) proxy);
+
+ while (!proxy->isAvailable()) {
+ mainLoop_->doSingleIteration();
+ usleep(50000);
+ }
+
+ uint32_t uint32Value = 42;
+ std::string stringValue = "Hai :)";
+ bool running = true;
+
+ std::future<CommonAPI::CallStatus> futureStatus = proxy->testVoidPredefinedTypeMethodAsync(
+ uint32Value,
+ stringValue,
+ [&] (const CommonAPI::CallStatus& status) {
+ EXPECT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(status));
+ mainLoop_->stop();
+ }
+ );
+
+ mainLoop_->run();
+
+ ASSERT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(futureStatus.get()));
+
+ mainloopFactory_->unregisterService(testAddress4);
+}
+
+
+class BigDataTestStub: public commonapi::tests::TestInterfaceStubDefault {
+ void testDerivedTypeMethod(
+ commonapi::tests::DerivedTypeCollection::TestEnumExtended2 testEnumExtended2InValue,
+ commonapi::tests::DerivedTypeCollection::TestMap testMapInValue,
+ commonapi::tests::DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue,
+ commonapi::tests::DerivedTypeCollection::TestMap& testMapOutValue) {
+ testEnumExtended2OutValue = testEnumExtended2InValue;
+ testMapOutValue = testMapInValue;
+ }
+};
+
+
+TEST_F(DBusMainLoopTest, ProxyAndServiceInSameDemoMainloopCanHandleBigData) {
+ std::shared_ptr<BigDataTestStub> stub = std::make_shared<
+ BigDataTestStub>();
+ ASSERT_TRUE(mainloopFactory_->registerService(stub, testAddress8));
+
+ auto proxy = mainloopFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(testAddress8);
+ ASSERT_TRUE((bool) proxy);
+
+ while (!proxy->isAvailable()) {
+ mainLoop_->doSingleIteration();
+ usleep(50000);
+ }
+
+ uint32_t uint32Value = 42;
+ std::string stringValue = "Hai :)";
+ bool running = true;
+
+ commonapi::tests::DerivedTypeCollection::TestEnumExtended2 testEnumExtended2InValue =
+ commonapi::tests::DerivedTypeCollection::TestEnumExtended2::E_OK;
+ commonapi::tests::DerivedTypeCollection::TestMap testMapInValue;
+
+ // Estimated amount of data (differring padding at beginning/end of Map/Array etc. not taken into account):
+ // 4 + 4 + 100 * (4 + (4 + 4 + 100 * (11 + 1 + 4)) + 4 ) = 161608
+ for(uint32_t i = 0; i < 500; ++i) {
+ commonapi::tests::DerivedTypeCollection::TestArrayTestStruct testArrayTestStruct;
+ for(uint32_t j = 0; j < 100; ++j) {
+ commonapi::tests::DerivedTypeCollection::TestStruct testStruct("Hai all (:", j);
+ testArrayTestStruct.push_back(testStruct);
+ }
+ testMapInValue.insert( {i, testArrayTestStruct} );
+ }
+
+ std::future<CommonAPI::CallStatus> futureStatus = proxy->testDerivedTypeMethodAsync(
+ testEnumExtended2InValue,
+ testMapInValue,
+ [&] (const CommonAPI::CallStatus& status,
+ commonapi::tests::DerivedTypeCollection::TestEnumExtended2 testEnumExtended2OutValue,
+ commonapi::tests::DerivedTypeCollection::TestMap testMapOutValue) {
+ EXPECT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(status));
+ EXPECT_EQ(testEnumExtended2InValue, testEnumExtended2OutValue);
+ EXPECT_EQ(testMapInValue.size(), testMapOutValue.size());
+ mainLoop_->stop();
+ }
+ );
+
+ mainLoop_->run();
+
+ ASSERT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(futureStatus.get()));
+
+ mainloopFactory_->unregisterService(testAddress8);
+}
+
+TEST_F(DBusMainLoopTest, DemoMainloopClientsHandleNonavailableServices) {
+ auto proxy = mainloopFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(testAddress3);
+ ASSERT_TRUE((bool) proxy);
+
+ uint32_t uint32Value = 42;
+ std::string stringValue = "Hai :)";
+
+ std::future<CommonAPI::CallStatus> futureStatus = proxy->testVoidPredefinedTypeMethodAsync(
+ uint32Value,
+ stringValue,
+ [&] (const CommonAPI::CallStatus& status) {
+ //Will never be called, @see DBusProxyAsyncCallbackHandler
+ EXPECT_EQ(toString(CommonAPI::CallStatus::NOT_AVAILABLE), toString(status));
+ }
+ );
+
+ ASSERT_EQ(toString(CommonAPI::CallStatus::NOT_AVAILABLE), toString(futureStatus.get()));
+}
+
+//##################################################################################################
+
+class GDispatchWrapper: public GSource {
+ public:
+ GDispatchWrapper(CommonAPI::DispatchSource* dispatchSource): dispatchSource_(dispatchSource) {}
+ CommonAPI::DispatchSource* dispatchSource_;
+};
+
+gboolean dispatchPrepare(GSource* source, gint* timeout) {
+ int64_t eventTimeout;
+ return static_cast<GDispatchWrapper*>(source)->dispatchSource_->prepare(eventTimeout);
+}
+
+gboolean dispatchCheck(GSource* source) {
+ return static_cast<GDispatchWrapper*>(source)->dispatchSource_->check();
+}
+
+gboolean dispatchExecute(GSource* source, GSourceFunc callback, gpointer userData) {
+ static_cast<GDispatchWrapper*>(source)->dispatchSource_->dispatch();
+ return true;
+}
+
+gboolean gWatchDispatcher(GIOChannel *source, GIOCondition condition, gpointer userData) {
+ CommonAPI::Watch* watch = static_cast<CommonAPI::Watch*>(userData);
+ watch->dispatch(condition);
+ return true;
+}
+
+gboolean gTimeoutDispatcher(void* userData) {
+ return static_cast<CommonAPI::DispatchSource*>(userData)->dispatch();
+}
+
+
+static GSourceFuncs standardGLibSourceCallbackFuncs = {
+ dispatchPrepare,
+ dispatchCheck,
+ dispatchExecute,
+ NULL
+};
+
+
+class DBusInGLibMainLoopTest: public ::testing::Test {
+ protected:
+ virtual void SetUp() {
+ running_ = true;
+
+ std::shared_ptr<CommonAPI::Runtime> runtime_ = CommonAPI::Runtime::load();
+ ASSERT_TRUE((bool) runtime_);
+
+ context_ = runtime_->getNewMainLoopContext();
+ ASSERT_TRUE((bool) context_);
+
+ doSubscriptions();
+
+ mainloopFactory_ = runtime_->createFactory(context_);
+ ASSERT_TRUE((bool) mainloopFactory_);
+ standardFactory_ = runtime_->createFactory();
+ ASSERT_TRUE((bool) standardFactory_);
+ }
+
+ virtual void TearDown() {
+ }
+
+ void doSubscriptions() {
+ context_->subscribeForTimeouts(
+ std::bind(&DBusInGLibMainLoopTest::timeoutAddedCallback, this, std::placeholders::_1, std::placeholders::_2),
+ std::bind(&DBusInGLibMainLoopTest::timeoutRemovedCallback, this, std::placeholders::_1)
+ );
+
+ context_->subscribeForWatches(
+ std::bind(&DBusInGLibMainLoopTest::watchAddedCallback, this, std::placeholders::_1, std::placeholders::_2),
+ std::bind(&DBusInGLibMainLoopTest::watchRemovedCallback, this, std::placeholders::_1)
+ );
+
+ context_->subscribeForWakeupEvents(
+ std::bind(&DBusInGLibMainLoopTest::wakeupMain, this)
+ );
+ }
+
+
+ public:
+ std::shared_ptr<CommonAPI::MainLoopContext> context_;
+ std::shared_ptr<CommonAPI::Factory> mainloopFactory_;
+ std::shared_ptr<CommonAPI::Factory> standardFactory_;
+ bool running_;
+ static constexpr bool mayBlock_ = true;
+
+ std::map<CommonAPI::DispatchSource*, GSource*> gSourceMappings;
+
+ GIOChannel* dbusChannel_;
+
+ void watchAddedCallback(CommonAPI::Watch* watch, const CommonAPI::DispatchPriority dispatchPriority) {
+ const pollfd& fileDesc = watch->getAssociatedFileDescriptor();
+ dbusChannel_ = g_io_channel_unix_new(fileDesc.fd);
+
+ GSource* gWatch = g_io_create_watch(dbusChannel_, static_cast<GIOCondition>(fileDesc.events));
+ g_source_set_callback(gWatch, reinterpret_cast<GSourceFunc>(&gWatchDispatcher), watch, NULL);
+
+ const auto& dependentSources = watch->getDependentDispatchSources();
+ for (auto dependentSourceIterator = dependentSources.begin();
+ dependentSourceIterator != dependentSources.end();
+ dependentSourceIterator++) {
+ GSource* gDispatchSource = g_source_new(&standardGLibSourceCallbackFuncs, sizeof(GDispatchWrapper));
+ static_cast<GDispatchWrapper*>(gDispatchSource)->dispatchSource_ = *dependentSourceIterator;
+
+ g_source_add_child_source(gWatch, gDispatchSource);
+
+ gSourceMappings.insert( {*dependentSourceIterator, gDispatchSource} );
+ }
+ g_source_attach(gWatch, NULL);
+ }
+
+ void watchRemovedCallback(CommonAPI::Watch* watch) {
+ g_source_remove_by_user_data(watch);
+
+ if(dbusChannel_) {
+ g_io_channel_unref(dbusChannel_);
+ dbusChannel_ = NULL;
+ }
+
+ const auto& dependentSources = watch->getDependentDispatchSources();
+ for (auto dependentSourceIterator = dependentSources.begin();
+ dependentSourceIterator != dependentSources.end();
+ dependentSourceIterator++) {
+ GSource* gDispatchSource = g_source_new(&standardGLibSourceCallbackFuncs, sizeof(GDispatchWrapper));
+ GSource* gSource = gSourceMappings.find(*dependentSourceIterator)->second;
+ g_source_destroy(gSource);
+ g_source_unref(gSource);
+ }
+ }
+
+ void timeoutAddedCallback(CommonAPI::Timeout* commonApiTimeoutSource, const CommonAPI::DispatchPriority dispatchPriority) {
+ GSource* gTimeoutSource = g_timeout_source_new(commonApiTimeoutSource->getTimeoutInterval());
+ g_source_set_callback(gTimeoutSource, &gTimeoutDispatcher, commonApiTimeoutSource, NULL);
+ g_source_attach(gTimeoutSource, NULL);
+ }
+
+ void timeoutRemovedCallback(CommonAPI::Timeout* timeout) {
+ g_source_remove_by_user_data(timeout);
+ }
+
+ void wakeupMain() {
+ g_main_context_wakeup(NULL);
+ }
+};
+
+
+TEST_F(DBusInGLibMainLoopTest, ProxyInGLibMainloopCanCallMethods) {
+ auto proxy = mainloopFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(testAddress5);
+ ASSERT_TRUE((bool) proxy);
+
+ std::shared_ptr<commonapi::tests::TestInterfaceStubDefault> stub = std::make_shared<
+ commonapi::tests::TestInterfaceStubDefault>();
+ ASSERT_TRUE(standardFactory_->registerService(stub, testAddress5));
+
+ while(!proxy->isAvailable()) {
+ g_main_context_iteration(NULL, mayBlock_);
+ usleep(50000);
+ }
+
+ uint32_t uint32Value = 24;
+ std::string stringValue = "Hai :)";
+
+ std::future<CommonAPI::CallStatus> futureStatus = proxy->testVoidPredefinedTypeMethodAsync(
+ uint32Value,
+ stringValue,
+ [&] (const CommonAPI::CallStatus& status) {
+ EXPECT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(status));
+ running_ = false;
+ }
+ );
+
+ while(running_) {
+ g_main_context_iteration(NULL, mayBlock_);
+ usleep(50000);
+ }
+
+ ASSERT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(futureStatus.get()));
+
+ standardFactory_->unregisterService(testAddress5);
+}
+
+
+TEST_F(DBusInGLibMainLoopTest, ServiceInGLibMainloopCanBeAddressed) {
+ auto proxy = standardFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(testAddress6);
+ ASSERT_TRUE((bool) proxy);
+
+ std::shared_ptr<commonapi::tests::TestInterfaceStubDefault> stub = std::make_shared<
+ commonapi::tests::TestInterfaceStubDefault>();
+ ASSERT_TRUE(mainloopFactory_->registerService(stub, testAddress6));
+
+ uint32_t uint32Value = 42;
+ std::string stringValue = "Ciao (:";
+
+ while(!proxy->isAvailable()) {
+ g_main_context_iteration(NULL, mayBlock_);
+ usleep(50000);
+ }
+
+ std::future<CommonAPI::CallStatus> futureStatus = proxy->testVoidPredefinedTypeMethodAsync(
+ uint32Value,
+ stringValue,
+ [&] (const CommonAPI::CallStatus& status) {
+ EXPECT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(status));
+ running_ = false;
+ //Wakeup needed as the service will be in a poll-block when the client
+ //call returns, and no other timeout is present to get him out of there.
+ g_main_context_wakeup(NULL);
+ }
+ );
+
+ while(running_) {
+ g_main_context_iteration(NULL, mayBlock_);
+ usleep(50000);
+ }
+
+ ASSERT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(futureStatus.get()));
+
+ mainloopFactory_->unregisterService(testAddress6);
+}
+
+
+TEST_F(DBusInGLibMainLoopTest, ProxyAndServiceInSameGlibMainloopCanCommunicate) {
+ auto proxy = mainloopFactory_->buildProxy<commonapi::tests::TestInterfaceProxy>(testAddress7);
+ ASSERT_TRUE((bool) proxy);
+
+ std::shared_ptr<commonapi::tests::TestInterfaceStubDefault> stub = std::make_shared<
+ commonapi::tests::TestInterfaceStubDefault>();
+ ASSERT_TRUE(mainloopFactory_->registerService(stub, testAddress7));
+
+ uint32_t uint32Value = 42;
+ std::string stringValue = "Ciao (:";
+
+ while(!proxy->isAvailable()) {
+ g_main_context_iteration(NULL, mayBlock_);
+ usleep(50000);
+ }
+
+ std::future<CommonAPI::CallStatus> futureStatus = proxy->testVoidPredefinedTypeMethodAsync(
+ uint32Value,
+ stringValue,
+ [&] (const CommonAPI::CallStatus& status) {
+ EXPECT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(status));
+ running_ = false;
+ //Wakeup needed as the service will be in a poll-block when the client
+ //call returns, and no other timeout is present to get him out of there.
+ g_main_context_wakeup(NULL);
+ }
+ );
+
+ while(running_) {
+ g_main_context_iteration(NULL, mayBlock_);
+ usleep(50000);
+ }
+
+ ASSERT_EQ(toString(CommonAPI::CallStatus::SUCCESS), toString(futureStatus.get()));
+
+ mainloopFactory_->unregisterService(testAddress7);
+}
+
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/src/test/DBusMultipleConnectionTest.cpp b/src/test/DBusMultipleConnectionTest.cpp
index a0cc497..382470a 100644
--- a/src/test/DBusMultipleConnectionTest.cpp
+++ b/src/test/DBusMultipleConnectionTest.cpp
@@ -35,16 +35,25 @@ class DBusMultipleConnectionTest: public ::testing::Test {
ASSERT_TRUE((bool)stubFactory);
stub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
- bool success = stubFactory->registerService(stub, serviceAddress);
- ASSERT_TRUE(success);
+ bool serviceNameAcquired = stubFactory->registerService(stub, serviceAddress);
+
+ for(unsigned int i = 0; !serviceNameAcquired && i < 100; i++) {
+ usleep(10000);
+ serviceNameAcquired = stubFactory->registerService(stub, serviceAddress);
+ }
+ ASSERT_TRUE(serviceNameAcquired);
proxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>(serviceAddress);
ASSERT_TRUE((bool)proxy);
+
+ for(unsigned int i = 0; !proxy->isAvailable() && i < 100; ++i) {
+ usleep(10000);
+ }
}
virtual void TearDown() {
stubFactory->unregisterService(serviceAddress);
- sleep(1);
+ usleep(30000);
}
std::shared_ptr<CommonAPI::Factory> proxyFactory;
@@ -71,7 +80,7 @@ TEST_F(DBusMultipleConnectionTest, Broadcast) {
std::promise<bool> promise;
auto future = promise.get_future();
- proxy->getTestPredefinedTypeBroadcastEvent().subscribe([&](
+ auto subscription = proxy->getTestPredefinedTypeBroadcastEvent().subscribe([&](
const uint32_t intVal, const std::string& strVal) {
v3 = intVal;
promise.set_value(true);
@@ -81,6 +90,8 @@ TEST_F(DBusMultipleConnectionTest, Broadcast) {
ASSERT_TRUE(future.get());
ASSERT_EQ(v1, v3);
+
+ proxy->getTestPredefinedTypeBroadcastEvent().unsubscribe(subscription);
}
TEST_F(DBusMultipleConnectionTest, SetAttribute) {
@@ -100,7 +111,7 @@ TEST_F(DBusMultipleConnectionTest, SetAttributeBroadcast) {
std::promise<bool> promise;
auto future = promise.get_future();
- proxy->getTestPredefinedTypeAttributeAttribute().getChangedEvent().subscribe([&](
+ auto subscription = proxy->getTestPredefinedTypeAttributeAttribute().getChangedEvent().subscribe([&](
const uint32_t intVal) {
v3 = intVal;
promise.set_value(true);
@@ -113,12 +124,15 @@ TEST_F(DBusMultipleConnectionTest, SetAttributeBroadcast) {
ASSERT_TRUE(future.get());
ASSERT_EQ(v1, v3);
+
+ proxy->getTestPredefinedTypeAttributeAttribute().getChangedEvent().unsubscribe(subscription);
}
TEST_F(DBusMultipleConnectionTest, GetAttribute) {
uint32_t v1;
- CommonAPI::CallStatus stat = proxy->getTestPredefinedTypeAttributeAttribute().getValue(v1);
+ CommonAPI::CallStatus stat;
+ proxy->getTestPredefinedTypeAttributeAttribute().getValue(stat, v1);
ASSERT_EQ(CommonAPI::CallStatus::SUCCESS, stat);
}
diff --git a/src/test/DBusProxyTest.cpp b/src/test/DBusProxyTest.cpp
index 7efdda9..a45f6f2 100644
--- a/src/test/DBusProxyTest.cpp
+++ b/src/test/DBusProxyTest.cpp
@@ -13,12 +13,13 @@
#include <CommonAPI/DBus/DBusProxy.h>
#include <CommonAPI/DBus/DBusConnection.h>
#include <CommonAPI/DBus/DBusStubAdapter.h>
-#include <CommonAPI/DBus/DBusUtils.h>
#include <commonapi/tests/TestInterfaceDBusProxy.h>
#include <commonapi/tests/TestInterfaceDBusStubAdapter.h>
#include <commonapi/tests/TestInterfaceStubDefault.h>
+#include "DBusTestUtils.h"
+
#include <gtest/gtest.h>
#include <algorithm>
@@ -52,14 +53,13 @@ protected:
}
virtual void TearDown() {
+ usleep(30000);
}
void registerTestStub() {
stubDBusConnection_ = CommonAPI::DBus::DBusConnection::getSessionBus();
ASSERT_TRUE(stubDBusConnection_->connect());
- ASSERT_TRUE(stubDBusConnection_->requestServiceNameAndBlock(busName));
-
auto stubDefault = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
stubAdapter_ = std::make_shared<commonapi::tests::TestInterfaceDBusStubAdapter>(
commonApiAddress,
@@ -69,6 +69,15 @@ protected:
stubDBusConnection_,
stubDefault);
stubAdapter_->init();
+
+ bool serviceNameAcquired = stubDBusConnection_->requestServiceNameAndBlock(busName);
+
+ for(unsigned int i = 0; !serviceNameAcquired && i < 100; i++) {
+ usleep(10000);
+ serviceNameAcquired = stubDBusConnection_->requestServiceNameAndBlock(busName);
+ }
+ ASSERT_TRUE(serviceNameAcquired);
+ usleep(500000);
}
void deregisterTestStub() {
@@ -84,22 +93,21 @@ protected:
void proxyRegisterForAvailabilityStatus() {
proxyAvailabilityStatus_ = CommonAPI::AvailabilityStatus::UNKNOWN;
- proxy_->getProxyStatusEvent().subscribe([&](const CommonAPI::AvailabilityStatus& availabilityStatus) {
+ proxyStatusSubscription_ = proxy_->getProxyStatusEvent().subscribe([&](const CommonAPI::AvailabilityStatus& availabilityStatus) {
proxyAvailabilityStatus_ = availabilityStatus;
});
+ usleep(100000);
}
- bool proxyWaitForAvailabilityStatus(const CommonAPI::AvailabilityStatus& availabilityStatus) const {
- std::chrono::milliseconds loopWaitDuration(100);
-
- if (proxyAvailabilityStatus_ == availabilityStatus)
- return true;
+ void proxyDeregisterForAvailabilityStatus() {
+ proxy_->getProxyStatusEvent().unsubscribe(proxyStatusSubscription_);
+ }
+ bool proxyWaitForAvailabilityStatus(const CommonAPI::AvailabilityStatus& availabilityStatus) const {
for (int i = 0; i < 10; i++) {
- std::this_thread::sleep_for(loopWaitDuration);
-
if (proxyAvailabilityStatus_ == availabilityStatus)
return true;
+ usleep(100000);
}
return false;
@@ -109,6 +117,8 @@ protected:
std::shared_ptr<commonapi::tests::TestInterfaceDBusProxy> proxy_;
CommonAPI::AvailabilityStatus proxyAvailabilityStatus_;
+ CommonAPI::ProxyStatusEvent::Subscription proxyStatusSubscription_;
+
std::shared_ptr<CommonAPI::DBus::DBusConnection> stubDBusConnection_;
std::shared_ptr<commonapi::tests::TestInterfaceDBusStubAdapter> stubAdapter_;
};
@@ -133,7 +143,11 @@ TEST_F(ProxyTest, IsNotAvailable) {
EXPECT_FALSE(isAvailable);
}
-TEST_F(ProxyTest, ServiceRegistry) {
+TEST_F(ProxyTest, IsConnected) {
+ ASSERT_TRUE(proxy_->getDBusConnection()->isConnected());
+}
+
+TEST_F(ProxyTest, AssociatedConnectionHasServiceRegistry) {
std::shared_ptr<CommonAPI::DBus::DBusProxyConnection> connection = proxy_->getDBusConnection();
auto registry = connection->getDBusServiceRegistry();
ASSERT_FALSE(!registry);
@@ -153,6 +167,7 @@ TEST_F(ProxyTest, DBusProxyStatusEventBeforeServiceIsRegistered) {
EXPECT_TRUE(proxyWaitForAvailabilityStatus(CommonAPI::AvailabilityStatus::NOT_AVAILABLE));
deregisterTestStub();
+ proxyDeregisterForAvailabilityStatus();
}
TEST_F(ProxyTest, DBusProxyStatusEventAfterServiceIsRegistered) {
@@ -171,6 +186,7 @@ TEST_F(ProxyTest, DBusProxyStatusEventAfterServiceIsRegistered) {
EXPECT_TRUE(proxyWaitForAvailabilityStatus(CommonAPI::AvailabilityStatus::NOT_AVAILABLE));
deregisterTestStub();
+ proxyDeregisterForAvailabilityStatus();
}
TEST_F(ProxyTest, ServiceStatus) {
@@ -178,6 +194,7 @@ TEST_F(ProxyTest, ServiceStatus) {
std::vector<std::string> availableDBusServices;
+ //Service actually IS available!
for (int i = 0; i < 5; i++) {
availableDBusServices = proxyDBusConnection_->getDBusServiceRegistry()->getAvailableServiceInstances(
commonApiServiceName,
@@ -187,7 +204,7 @@ TEST_F(ProxyTest, ServiceStatus) {
break;
}
}
- sleep(1);
+
auto found = std::find(availableDBusServices.begin(), availableDBusServices.end(), commonApiAddress);
EXPECT_TRUE(availableDBusServices.begin() != availableDBusServices.end());
@@ -214,14 +231,12 @@ TEST_F(ProxyTest, isServiceInstanceAlive) {
TEST_F(ProxyTest, IsAvailableBlocking) {
registerTestStub();
- // blocking in terms of "if it's still uknown"
- bool isAvailable = proxy_->isAvailableBlocking();
- for (int i = 0; !isAvailable && i < 10; i++) {
- std::this_thread::sleep_for(std::chrono::milliseconds(200));
- isAvailable = proxy_->isAvailableBlocking();
+ // blocking in terms of "if it's still unknown"
+ for (int i = 0; !proxy_->isAvailableBlocking() && i < 3; i++) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
- EXPECT_TRUE(isAvailable);
+ EXPECT_TRUE(proxy_->isAvailableBlocking());
deregisterTestStub();
}
@@ -231,30 +246,27 @@ TEST_F(ProxyTest, HasNecessaryAttributesAndEvents) {
CommonAPI::ProxyStatusEvent& statusEvent = (proxy_->getProxyStatusEvent());
}
-TEST_F(ProxyTest, IsConnected) {
- ASSERT_TRUE(proxy_->getDBusConnection()->isConnected());
-}
-
TEST_F(ProxyTest, TestInterfaceVersionAttribute) {
CommonAPI::InterfaceVersionAttribute& versionAttribute = proxy_->getInterfaceVersionAttribute();
CommonAPI::Version version;
- CommonAPI::CallStatus status = versionAttribute.getValue(version);
+ CommonAPI::CallStatus status;
+ ASSERT_NO_THROW(versionAttribute.getValue(status, version));
ASSERT_EQ(CommonAPI::CallStatus::NOT_AVAILABLE, status);
}
TEST_F(ProxyTest, AsyncCallbacksAreCalledIfServiceNotAvailable) {
commonapi::tests::DerivedTypeCollection::TestEnumExtended2 testInputStruct;
commonapi::tests::DerivedTypeCollection::TestMap testInputMap;
- bool wasCalled = false;
+ std::promise<bool> wasCalledPromise;
+ std::future<bool> wasCalledFuture = wasCalledPromise.get_future();
proxy_->testDerivedTypeMethodAsync(testInputStruct, testInputMap, [&] (const CommonAPI::CallStatus& callStatus,
const commonapi::tests::DerivedTypeCollection::TestEnumExtended2&,
const commonapi::tests::DerivedTypeCollection::TestMap&) {
ASSERT_EQ(callStatus, CommonAPI::CallStatus::NOT_AVAILABLE);
- wasCalled = true;
+ wasCalledPromise.set_value(true);
}
);
- sleep(1);
- ASSERT_TRUE(wasCalled);
+ ASSERT_TRUE(wasCalledFuture.get());
}
int main(int argc, char** argv) {
diff --git a/src/test/DBusServiceRegistryTest.cpp b/src/test/DBusServiceRegistryTest.cpp
index c6036eb..2955eb6 100644
--- a/src/test/DBusServiceRegistryTest.cpp
+++ b/src/test/DBusServiceRegistryTest.cpp
@@ -82,6 +82,7 @@ TEST_F(DBusServiceRegistryTest, CanBeConstructed) {
std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection = CommonAPI::DBus::DBusConnection::getSessionBus();
CommonAPI::DBus::DBusServiceRegistry* registry = new CommonAPI::DBus::DBusServiceRegistry(dbusConnection);
ASSERT_TRUE(registry != NULL);
+ delete registry;
}
@@ -138,7 +139,7 @@ TEST_F(DBusServiceRegistryTest, PredefinedInstances) {
auto stubDBusConnection = CommonAPI::DBus::DBusConnection::getSessionBus();
ASSERT_TRUE(stubDBusConnection->connect());
- stubDBusConnection->requestServiceNameAndBlock(dbusServiceName);
+ ASSERT_TRUE(stubDBusConnection->requestServiceNameAndBlock(dbusServiceName));
auto proxyDBusConnection = CommonAPI::DBus::DBusConnection::getSessionBus();
auto dbusServiceRegistry = proxyDBusConnection->getDBusServiceRegistry();
@@ -188,8 +189,8 @@ TEST_F(DBusServiceRegistryTest, PredefinedInstances) {
bool isInstanceAlive = dbusServiceRegistry->isServiceInstanceAlive(dbusInterfaceName, dbusServiceName, dbusObjectPath);
- for (int i = 0; !isInstanceAlive && i < 5; i++) {
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
+ for (int i = 0; !isInstanceAlive && i < 100; i++) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
isInstanceAlive = dbusServiceRegistry->isServiceInstanceAlive(dbusInterfaceName, dbusServiceName, dbusObjectPath);
}
@@ -223,7 +224,13 @@ class DBusServiceRegistryTestWithPredefinedRemote: public ::testing::Test {
auto stub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
- dbusStubConnection_->requestServiceNameAndBlock("test.instance.name");
+ bool serviceNameAcquired = dbusStubConnection_->requestServiceNameAndBlock("test.instance.name");
+ for(unsigned int i = 0; !serviceNameAcquired && i < 100; ++i) {
+ usleep(10000);
+ serviceNameAcquired = dbusStubConnection_->requestServiceNameAndBlock("test.instance.name");
+ }
+ ASSERT_TRUE(serviceNameAcquired);
+
stubAdapter_ = std::make_shared<commonapi::tests::TestInterfaceDBusStubAdapter>(
"local:test.service.name:test.instance.name",
"test.service.name",
@@ -232,10 +239,12 @@ class DBusServiceRegistryTestWithPredefinedRemote: public ::testing::Test {
dbusStubConnection_,
stub);
stubAdapter_->init();
+ usleep(200000);
}
virtual void TearDown() {
stubAdapter_->deinit();
+ usleep(30000);
}
std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_;
@@ -247,13 +256,11 @@ class DBusServiceRegistryTestWithPredefinedRemote: public ::testing::Test {
TEST_F(DBusServiceRegistryTestWithPredefinedRemote, RecognizesCommonAPIDBusServiceInstanceAsAlive) {
- sleep(1);
ASSERT_TRUE(dbusServiceRegistry_->isServiceInstanceAlive("test.service.name", "test.instance.name", "/test/instance/name"));
}
TEST_F(DBusServiceRegistryTestWithPredefinedRemote, FindsCommonAPIDBusServiceInstance) {
- sleep(1);
auto availableServices = dbusServiceRegistry_->getAvailableServiceInstances("test.service.name", "local");
ASSERT_EQ(1, availableServices.size());
bool serviceFound;
diff --git a/src/test/DBusStubAdapterTest.cpp b/src/test/DBusStubAdapterTest.cpp
index 984132b..45cabe1 100644
--- a/src/test/DBusStubAdapterTest.cpp
+++ b/src/test/DBusStubAdapterTest.cpp
@@ -220,6 +220,7 @@ int main(void) {
}
assert(dispatchedMessageCount > 0);
+ testStubAdapter->deinit();
return 0;
}
diff --git a/src/test/DBusTestUtils.h b/src/test/DBusTestUtils.h
index 8b0cbf9..a1140e4 100644
--- a/src/test/DBusTestUtils.h
+++ b/src/test/DBusTestUtils.h
@@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <dbus/dbus.h>
+#include <CommonAPI/DBus/DBusServiceRegistry.h>
inline char eliminateZeroes(char val) {
@@ -32,3 +33,43 @@ inline void printLibdbusMessage(DBusMessage* libdbusMessage) {
printLibdbusMessage(libdbusMessage, 0, dbus_message_get_body_length(libdbusMessage));
}
+inline std::string toString(CommonAPI::DBus::DBusServiceRegistry::DBusServiceState state) {
+ switch(state) {
+ case CommonAPI::DBus::DBusServiceRegistry::DBusServiceState::AVAILABLE:
+ return "AVAILABLE";
+ case CommonAPI::DBus::DBusServiceRegistry::DBusServiceState::NOT_AVAILABLE:
+ return "NOT_AVAILABLE";
+ case CommonAPI::DBus::DBusServiceRegistry::DBusServiceState::RESOLVED:
+ return "RESOLVED";
+ case CommonAPI::DBus::DBusServiceRegistry::DBusServiceState::RESOLVING:
+ return "RESOLVING";
+ case CommonAPI::DBus::DBusServiceRegistry::DBusServiceState::UNKNOWN:
+ return "UNKNOWN";
+ }
+}
+
+inline std::string toString(CommonAPI::AvailabilityStatus state) {
+ switch(state) {
+ case CommonAPI::AvailabilityStatus::AVAILABLE:
+ return "AVAILABLE";
+ case CommonAPI::AvailabilityStatus::NOT_AVAILABLE:
+ return "NOT_AVAILABLE";
+ case CommonAPI::AvailabilityStatus::UNKNOWN:
+ return "UNKNOWN";
+ }
+}
+
+inline std::string toString(CommonAPI::CallStatus state) {
+ switch(state) {
+ case CommonAPI::CallStatus::CONNECTION_FAILED:
+ return "CONNECTION_FAILED";
+ case CommonAPI::CallStatus::NOT_AVAILABLE:
+ return "NOT_AVAILABLE";
+ case CommonAPI::CallStatus::OUT_OF_MEMORY:
+ return "OUT_OF_MEMORY";
+ case CommonAPI::CallStatus::REMOTE_ERROR:
+ return "REMOTE_ERROR";
+ case CommonAPI::CallStatus::SUCCESS:
+ return "SUCCESS";
+ }
+}
diff --git a/src/test/DemoMainLoop.h b/src/test/DemoMainLoop.h
new file mode 100644
index 0000000..4cbf47a
--- /dev/null
+++ b/src/test/DemoMainLoop.h
@@ -0,0 +1,334 @@
+/* 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 DEMO_MAIN_LOOP_H_
+#define DEMO_MAIN_LOOP_H_
+
+
+#include <CommonAPI/MainLoopContext.h>
+
+#include <vector>
+#include <set>
+#include <map>
+#include <poll.h>
+#include <unistd.h>
+#include <sys/eventfd.h>
+#include <cassert>
+
+
+namespace CommonAPI {
+
+class MainLoop {
+ public:
+ MainLoop() = delete;
+ MainLoop(const MainLoop&) = delete;
+ MainLoop& operator=(const MainLoop&) = delete;
+ MainLoop(MainLoop&&) = delete;
+ MainLoop& operator=(MainLoop&&) = delete;
+
+ explicit MainLoop(std::shared_ptr<MainLoopContext> context) :
+ context_(context), currentMinimalTimeoutInterval_(TIMEOUT_INFINITE), running_(false), breakLoop_(false) {
+ wakeFd_.fd = eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK);
+ wakeFd_.events = POLLIN | POLLOUT | POLLERR;
+
+ assert(wakeFd_.fd != -1);
+ registerFileDescriptor(wakeFd_);
+
+ dispatchSourceListenerSubscription_ = context_->subscribeForDispatchSources(
+ std::bind(&CommonAPI::MainLoop::registerDispatchSource, this, std::placeholders::_1, std::placeholders::_2),
+ std::bind(&CommonAPI::MainLoop::deregisterDispatchSource, this, std::placeholders::_1));
+ watchListenerSubscription_ = context_->subscribeForWatches(
+ std::bind(&CommonAPI::MainLoop::registerWatch, this, std::placeholders::_1, std::placeholders::_2),
+ std::bind(&CommonAPI::MainLoop::deregisterWatch, this, std::placeholders::_1));
+ timeoutSourceListenerSubscription_ = context_->subscribeForTimeouts(
+ std::bind(&CommonAPI::MainLoop::registerTimeout, this, std::placeholders::_1, std::placeholders::_2),
+ std::bind(&CommonAPI::MainLoop::deregisterTimeout, this, std::placeholders::_1));
+ wakeupListenerSubscription_ = context_->subscribeForWakeupEvents(
+ std::bind(&CommonAPI::MainLoop::wakeup, this));
+ }
+
+ ~MainLoop() {
+ deregisterFileDescriptor(wakeFd_);
+
+ context_->unsubscribeForDispatchSources(dispatchSourceListenerSubscription_);
+ context_->unsubscribeForWatches(watchListenerSubscription_);
+ context_->unsubscribeForTimeouts(timeoutSourceListenerSubscription_);
+ context_->unsubscribeForWakeupEvents(wakeupListenerSubscription_);
+
+ close(wakeFd_.fd);
+ }
+
+ /**
+ * The given timeout will be overridden if a timeout-event is present that defines an earlier ready time.
+ */
+ void run(const int64_t& timeoutInterval = TIMEOUT_INFINITE) {
+ running_ = true;
+ while(running_) {
+ doSingleIteration(timeoutInterval);
+ }
+ }
+
+ void stop() {
+ running_ = false;
+ wakeup();
+ }
+
+ /**
+ * \brief Executes a single cycle of the mainloop.
+ *
+ * Subsequently calls prepare(), poll(), check() and, if necessary, dispatch().
+ * The given timeout (milliseconds) represents the maximum time
+ * this iteration will remain in the poll state. All other steps
+ * are handled in a non-blocking way. Note however that a source
+ * might claim to have infinite amounts of data to dispatch.
+ * This demo-implementation of a Mainloop will dispatch a source
+ * until it no longer claims to have data to dispatch.
+ * Dispatch will not be called if no sources, watches and timeouts
+ * claim to be ready during the check()-phase.
+ *
+ * @param timeout The maximum poll-timeout for this iteration.
+ */
+ void doSingleIteration(const int64_t& timeout = TIMEOUT_INFINITE) {
+ prepare(timeout);
+ poll();
+ if(check()) {
+ dispatch();
+ }
+ }
+
+ /*
+ * The given timeout is a maximum timeout in ms, measured from the current time in the future
+ * (a value of 0 means "no timeout"). It will be overridden if a timeout-event is present
+ * that defines an earlier ready time.
+ */
+ void prepare(const int64_t& timeout = TIMEOUT_INFINITE) {
+ currentMinimalTimeoutInterval_ = timeout;
+
+ for (auto dispatchSourceIterator = registeredDispatchSources_.begin();
+ dispatchSourceIterator != registeredDispatchSources_.end();
+ dispatchSourceIterator++) {
+
+ int64_t dispatchTimeout = TIMEOUT_INFINITE;
+ if(dispatchSourceIterator->second->prepare(dispatchTimeout)) {
+ sourcesToDispatch_.insert(*dispatchSourceIterator);
+ } else if (dispatchTimeout < currentMinimalTimeoutInterval_) {
+ currentMinimalTimeoutInterval_ = dispatchTimeout;
+ }
+ }
+
+ int64_t currentContextTime = getCurrentTimeInMs();
+
+ for (auto timeoutPriorityRange = registeredTimeouts_.begin();
+ timeoutPriorityRange != registeredTimeouts_.end();
+ timeoutPriorityRange++) {
+
+ int64_t intervalToReady = timeoutPriorityRange->second->getReadyTime() - currentContextTime;
+
+ if (intervalToReady <= 0) {
+ timeoutsToDispatch_.insert(*timeoutPriorityRange);
+ currentMinimalTimeoutInterval_ = TIMEOUT_NONE;
+ } else if (intervalToReady < currentMinimalTimeoutInterval_) {
+ currentMinimalTimeoutInterval_ = intervalToReady;
+ }
+ }
+ }
+
+ void poll() {
+ for (auto fileDescriptor = managedFileDescriptors_.begin() + 1; fileDescriptor != managedFileDescriptors_.end(); ++fileDescriptor) {
+ (*fileDescriptor).revents = 0;
+ }
+
+ auto numReadyFileDescriptors = ::poll(&(managedFileDescriptors_[0]), managedFileDescriptors_.size(), currentMinimalTimeoutInterval_);
+
+ // If no FileDescriptors are ready, poll returned because of a timeout that has expired.
+ // The only case in which this is not the reason is when the timeout handed in "prepare"
+ // expired before any other timeouts.
+ if(!numReadyFileDescriptors) {
+ int64_t currentContextTime = getCurrentTimeInMs();
+
+ for (auto timeoutPriorityRange = registeredTimeouts_.begin();
+ timeoutPriorityRange != registeredTimeouts_.end();
+ timeoutPriorityRange++) {
+
+ int64_t intervalToReady = timeoutPriorityRange->second->getReadyTime() - currentContextTime;
+
+ if (intervalToReady <= 0) {
+ timeoutsToDispatch_.insert(*timeoutPriorityRange);
+ }
+ }
+ }
+
+ if (wakeFd_.revents) {
+ acknowledgeWakeup();
+ }
+ }
+
+ bool check() {
+ //The first file descriptor always is the loop's wakeup-descriptor. All others need to be linked to a watch.
+ for (auto fileDescriptor = managedFileDescriptors_.begin() + 1; fileDescriptor != managedFileDescriptors_.end(); ++fileDescriptor) {
+ for(auto registeredWatchIterator = registeredWatches_.begin();
+ registeredWatchIterator != registeredWatches_.end();
+ registeredWatchIterator++) {
+ const auto& correspondingWatchPriority = registeredWatchIterator->first;
+ const auto& correspondingWatchPair = registeredWatchIterator->second;
+
+ if (std::get<0>(correspondingWatchPair) == fileDescriptor->fd && fileDescriptor->revents) {
+ watchesToDispatch_.insert( { correspondingWatchPriority, {std::get<1>(correspondingWatchPair), fileDescriptor->revents} } );
+ }
+ }
+ }
+
+ for(auto dispatchSourceIterator = registeredDispatchSources_.begin(); dispatchSourceIterator != registeredDispatchSources_.end(); ++dispatchSourceIterator) {
+ if((std::get<1>(*dispatchSourceIterator))->check()) {
+ sourcesToDispatch_.insert( {std::get<0>(*dispatchSourceIterator), std::get<1>(*dispatchSourceIterator)});
+ }
+ }
+
+ return !timeoutsToDispatch_.empty() || !watchesToDispatch_.empty() || !sourcesToDispatch_.empty();
+ }
+
+ void dispatch() {
+ for (auto timeoutIterator = timeoutsToDispatch_.begin();
+ timeoutIterator != timeoutsToDispatch_.end();
+ timeoutIterator++) {
+ std::get<1>(*timeoutIterator)->dispatch();
+ }
+
+ for (auto watchIterator = watchesToDispatch_.begin();
+ watchIterator != watchesToDispatch_.end();
+ watchIterator++) {
+ Watch* watch = std::get<0>(watchIterator->second);
+ const unsigned int flags = std::get<1>(watchIterator->second);
+ const auto& dependentSources = watch->getDependentDispatchSources();
+ watch->dispatch(flags);
+
+ for (auto dependentSourceIterator = dependentSources.begin();
+ dependentSourceIterator != dependentSources.end();
+ dependentSourceIterator++) {
+ if((*dependentSourceIterator)->check()) {
+ sourcesToDispatch_.insert( {watchIterator->first, *dependentSourceIterator} );
+ }
+ }
+ }
+
+ breakLoop_ = false;
+ for (auto dispatchSourceIterator = sourcesToDispatch_.begin();
+ dispatchSourceIterator != sourcesToDispatch_.end() && !breakLoop_;
+ dispatchSourceIterator++) {
+
+ while(std::get<1>(*dispatchSourceIterator)->dispatch());
+ }
+
+ timeoutsToDispatch_.clear();
+ sourcesToDispatch_.clear();
+ watchesToDispatch_.clear();
+ }
+
+ void wakeup() {
+ uint32_t wake = 1;
+ ::write(wakeFd_.fd, &wake, sizeof(uint32_t));
+ }
+
+ private:
+ void registerFileDescriptor(const pollfd& fileDescriptor) {
+ managedFileDescriptors_.push_back(fileDescriptor);
+ }
+
+ void deregisterFileDescriptor(const pollfd& fileDescriptor) {
+ for (auto it = managedFileDescriptors_.begin(); it != managedFileDescriptors_.end(); it++) {
+ if ((*it).fd == fileDescriptor.fd) {
+ managedFileDescriptors_.erase(it);
+ break;
+ }
+ }
+ }
+
+ void registerDispatchSource(DispatchSource* dispatchSource, const DispatchPriority dispatchPriority) {
+ registeredDispatchSources_.insert( {dispatchPriority, dispatchSource} );
+ }
+
+ void deregisterDispatchSource(DispatchSource* dispatchSource) {
+ for(auto dispatchSourceIterator = registeredDispatchSources_.begin();
+ dispatchSourceIterator != registeredDispatchSources_.end();
+ dispatchSourceIterator++) {
+
+ if(dispatchSourceIterator->second == dispatchSource) {
+ registeredDispatchSources_.erase(dispatchSourceIterator);
+ break;
+ }
+ }
+ breakLoop_ = true;
+ }
+
+ void registerWatch(Watch* watch, const DispatchPriority dispatchPriority) {
+ registerFileDescriptor(watch->getAssociatedFileDescriptor());
+ registeredWatches_.insert( { dispatchPriority, {watch->getAssociatedFileDescriptor().fd, watch} } );
+ }
+
+ void deregisterWatch(Watch* watch) {
+ deregisterFileDescriptor(watch->getAssociatedFileDescriptor());
+
+ for(auto watchIterator = registeredWatches_.begin();
+ watchIterator != registeredWatches_.end();
+ watchIterator++) {
+
+ if(watchIterator->second.first == watch->getAssociatedFileDescriptor().fd) {
+ registeredWatches_.erase(watchIterator);
+ break;
+ }
+ }
+ }
+
+ void registerTimeout(Timeout* timeout, const DispatchPriority dispatchPriority) {
+ registeredTimeouts_.insert( {dispatchPriority, timeout} );
+ }
+
+ void deregisterTimeout(Timeout* timeout) {
+ for(auto timeoutIterator = registeredTimeouts_.begin();
+ timeoutIterator != registeredTimeouts_.end();
+ timeoutIterator++) {
+
+ if(timeoutIterator->second == timeout) {
+ registeredTimeouts_.erase(timeoutIterator);
+ break;
+ }
+ }
+ }
+
+ void acknowledgeWakeup() {
+ uint32_t buffer;
+ while (::read(wakeFd_.fd, &buffer, sizeof(uint32_t)) == sizeof(buffer));
+ }
+
+ std::shared_ptr<MainLoopContext> context_;
+
+ std::vector<pollfd> managedFileDescriptors_;
+
+ std::multimap<DispatchPriority, DispatchSource*> registeredDispatchSources_;
+ std::multimap<DispatchPriority, std::pair<int, Watch*>> registeredWatches_;
+ std::multimap<DispatchPriority, Timeout*> registeredTimeouts_;
+
+ std::set<std::pair<DispatchPriority, DispatchSource*>> sourcesToDispatch_;
+ std::set<std::pair<DispatchPriority, std::pair<Watch*, unsigned short>>> watchesToDispatch_;
+ std::set<std::pair<DispatchPriority, Timeout*>> timeoutsToDispatch_;
+
+ DispatchSourceListenerSubscription dispatchSourceListenerSubscription_;
+ WatchListenerSubscription watchListenerSubscription_;
+ TimeoutSourceListenerSubscription timeoutSourceListenerSubscription_;
+ WakeupListenerSubscription wakeupListenerSubscription_;
+
+ int64_t currentMinimalTimeoutInterval_;
+ bool breakLoop_;
+ bool running_;
+
+ pollfd wakeFd_;
+};
+
+
+} // namespace CommonAPI
+
+#endif /* DEMO_MAIN_LOOP_H_ */
diff --git a/src/test/commonapi/tests/DerivedTypeCollection.cpp b/src/test/commonapi/tests/DerivedTypeCollection.cpp
index 1ad1cce..14b083e 100644
--- a/src/test/commonapi/tests/DerivedTypeCollection.cpp
+++ b/src/test/commonapi/tests/DerivedTypeCollection.cpp
@@ -7,10 +7,9 @@ namespace commonapi {
namespace tests {
namespace DerivedTypeCollection {
-TestStructExtended::TestStructExtended(const PredefinedTypeCollection::TestString& testStringValue, const uint16_t& uintValueValue, const TestEnumExtended2& testEnumExtended2Value, const PredefinedTypeCollection::WeirdStrangeAlienEnum& alienEnumValue):
+TestStructExtended::TestStructExtended(const PredefinedTypeCollection::TestString& testStringValue, const uint16_t& uintValueValue, const TestEnumExtended2& testEnumExtended2Value):
TestStruct(testStringValue, uintValueValue),
- testEnumExtended2(testEnumExtended2Value),
- alienEnum(alienEnumValue)
+ testEnumExtended2(testEnumExtended2Value)
{
}
@@ -20,21 +19,18 @@ bool operator==(const TestStructExtended& lhs, const TestStructExtended& rhs) {
return
static_cast<TestStructExtended::TestStruct>(lhs) == static_cast<TestStructExtended::TestStruct>(rhs) &&
- lhs.testEnumExtended2 == rhs.testEnumExtended2 &&
- lhs.alienEnum == rhs.alienEnum
+ lhs.testEnumExtended2 == rhs.testEnumExtended2
;
}
void TestStructExtended::readFromInputStream(CommonAPI::InputStream& inputStream) {
TestStruct::readFromInputStream(inputStream);
inputStream >> testEnumExtended2;
- inputStream >> alienEnum;
}
void TestStructExtended::writeToOutputStream(CommonAPI::OutputStream& outputStream) const {
TestStruct::writeToOutputStream(outputStream);
outputStream << testEnumExtended2;
- outputStream << alienEnum;
}
TestStruct::TestStruct(const PredefinedTypeCollection::TestString& testStringValue, const uint16_t& uintValueValue):
testString(testStringValue),
diff --git a/src/test/commonapi/tests/DerivedTypeCollection.h b/src/test/commonapi/tests/DerivedTypeCollection.h
index b1cd43f..26409d6 100644
--- a/src/test/commonapi/tests/DerivedTypeCollection.h
+++ b/src/test/commonapi/tests/DerivedTypeCollection.h
@@ -8,7 +8,7 @@
#include <CommonAPI/OutputStream.h>
#include <CommonAPI/SerializableStruct.h>
#include <CommonAPI/types.h>
-#include "PredefinedTypeCollection.h"
+#include <commonapi/tests/PredefinedTypeCollection.h>
#include <cstdint>
#include <string>
#include <unordered_map>
@@ -18,6 +18,26 @@ namespace commonapi {
namespace tests {
namespace DerivedTypeCollection {
+ struct TestStruct: CommonAPI::SerializableStruct {
+ PredefinedTypeCollection::TestString testString;
+ uint16_t uintValue;
+
+ TestStruct() = default;
+ TestStruct(const PredefinedTypeCollection::TestString& testString, const uint16_t& uintValue);
+
+ virtual void readFromInputStream(CommonAPI::InputStream& inputStream);
+ virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const;
+
+ static inline void writeToTypeOutputStream(CommonAPI::TypeOutputStream& typeOutputStream) {
+ typeOutputStream.writeStringType();
+ typeOutputStream.writeUInt16Type();
+ }
+ };
+
+ typedef std::vector<TestStruct> TestArrayTestStruct;
+
+ typedef std::unordered_map<uint32_t, TestArrayTestStruct> TestMap;
+
enum class TestEnum: int32_t {
E_UNKNOWN = 0,
E_OK = 1,
@@ -27,6 +47,7 @@ namespace DerivedTypeCollection {
// XXX 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 {
E_UNKNOWN = TestEnum::E_UNKNOWN,
E_OK = TestEnum::E_OK,
@@ -38,23 +59,7 @@ namespace DerivedTypeCollection {
// XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1
struct TestEnumExtendedComparator;
- typedef std::unordered_map<TestEnum, std::string> TestEnumMap;
- struct TestStruct: CommonAPI::SerializableStruct {
- PredefinedTypeCollection::TestString testString;
- uint16_t uintValue;
-
- TestStruct() = default;
- TestStruct(const PredefinedTypeCollection::TestString& testString, const uint16_t& uintValue);
- virtual void readFromInputStream(CommonAPI::InputStream& inputStream);
- virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const;
-
- static inline void writeToTypeOutputStream(CommonAPI::TypeOutputStream& typeOutputStream) {
- typeOutputStream.writeStringType();
- typeOutputStream.writeUInt16Type();
- }
- };
- typedef std::vector<TestStruct> TestArrayTestStruct;
enum class TestEnumExtended2: int32_t {
E_UNKNOWN = TestEnum::E_UNKNOWN,
E_OK = TestEnum::E_OK,
@@ -68,12 +73,12 @@ namespace DerivedTypeCollection {
// XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1
struct TestEnumExtended2Comparator;
+
struct TestStructExtended: TestStruct {
TestEnumExtended2 testEnumExtended2;
- PredefinedTypeCollection::WeirdStrangeAlienEnum alienEnum;
TestStructExtended() = default;
- TestStructExtended(const PredefinedTypeCollection::TestString& testString, const uint16_t& uintValue, const TestEnumExtended2& testEnumExtended2, const PredefinedTypeCollection::WeirdStrangeAlienEnum& alienEnum);
+ TestStructExtended(const PredefinedTypeCollection::TestString& testString, const uint16_t& uintValue, const TestEnumExtended2& testEnumExtended2);
virtual void readFromInputStream(CommonAPI::InputStream& inputStream);
virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const;
@@ -81,10 +86,11 @@ namespace DerivedTypeCollection {
static inline void writeToTypeOutputStream(CommonAPI::TypeOutputStream& typeOutputStream) {
TestStruct::writeToTypeOutputStream(typeOutputStream);
typeOutputStream.writeInt32Type();
- typeOutputStream.writeInt32Type();
}
};
- typedef std::unordered_map<uint32_t, TestArrayTestStruct> TestMap;
+
+ typedef std::unordered_map<TestEnum, std::string> TestEnumMap;
+
enum class TestEnumMissingValue: int32_t {
E1 = 10,
E2,
@@ -93,7 +99,9 @@ namespace DerivedTypeCollection {
// XXX 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;
+
bool operator==(const TestStructExtended& lhs, const TestStructExtended& rhs);
inline bool operator!=(const TestStructExtended& lhs, const TestStructExtended& rhs) {
diff --git a/src/test/commonapi/tests/PredefinedTypeCollection.h b/src/test/commonapi/tests/PredefinedTypeCollection.h
index ee9c1ec..f1d3cc2 100644
--- a/src/test/commonapi/tests/PredefinedTypeCollection.h
+++ b/src/test/commonapi/tests/PredefinedTypeCollection.h
@@ -5,8 +5,6 @@
#define COMMONAPI_TESTS_PREDEFINED_TYPE_COLLECTION_H_
#include <CommonAPI/ByteBuffer.h>
-#include <CommonAPI/InputStream.h>
-#include <CommonAPI/OutputStream.h>
#include <CommonAPI/types.h>
#include <cstdint>
#include <string>
@@ -16,40 +14,31 @@ namespace tests {
namespace PredefinedTypeCollection {
typedef uint8_t TestUInt8;
+
typedef uint16_t TestUInt16;
+
typedef uint32_t TestUInt32;
+
typedef uint64_t TestUInt64;
+
typedef int8_t TestInt8;
+
typedef int16_t TestInt16;
+
typedef int32_t TestInt32;
+
typedef int64_t TestInt64;
+
typedef bool TestBoolean;
+
typedef CommonAPI::ByteBuffer TestByteBuffer;
+
typedef double TestDouble;
+
typedef float TestFloat;
+
typedef std::string TestString;
- enum class WeirdStrangeAlienEnum: int32_t {
- WEIRD,
- STRANGE,
- ALIEN
- };
- // XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1
- struct WeirdStrangeAlienEnumComparator;
-
-inline CommonAPI::InputStream& operator>>(CommonAPI::InputStream& inputStream, WeirdStrangeAlienEnum& enumValue) {
- return inputStream.readEnumValue<int32_t>(enumValue);
-}
-
-inline CommonAPI::OutputStream& operator<<(CommonAPI::OutputStream& outputStream, const WeirdStrangeAlienEnum& enumValue) {
- return outputStream.writeEnumValue(static_cast<int32_t>(enumValue));
-}
-
-struct WeirdStrangeAlienEnumComparator {
- inline bool operator()(const WeirdStrangeAlienEnum& lhs, const WeirdStrangeAlienEnum& rhs) const {
- return static_cast<int32_t>(lhs) < static_cast<int32_t>(rhs);
- }
-};
@@ -65,37 +54,11 @@ static inline const char* getTypeCollectionName() {
namespace CommonAPI {
- template<>
- struct BasicTypeWriter<commonapi::tests::PredefinedTypeCollection::WeirdStrangeAlienEnum> {
- inline static void writeType (CommonAPI::TypeOutputStream& typeStream) {
- typeStream.writeInt32EnumType();
- }
- };
-
- template<>
- struct InputStreamVectorHelper<commonapi::tests::PredefinedTypeCollection::WeirdStrangeAlienEnum> {
- static void beginReadVector(InputStream& inputStream, const std::vector<commonapi::tests::PredefinedTypeCollection::WeirdStrangeAlienEnum>& vectorValue) {
- inputStream.beginReadInt32EnumVector();
- }
- };
-
- template <>
- struct OutputStreamVectorHelper<commonapi::tests::PredefinedTypeCollection::WeirdStrangeAlienEnum> {
- static void beginWriteVector(OutputStream& outputStream, const std::vector<commonapi::tests::PredefinedTypeCollection::WeirdStrangeAlienEnum>& vectorValue) {
- outputStream.beginWriteInt32EnumVector(vectorValue.size());
- }
- };
}
namespace std {
- template<>
- struct hash<commonapi::tests::PredefinedTypeCollection::WeirdStrangeAlienEnum> {
- inline size_t operator()(const commonapi::tests::PredefinedTypeCollection::WeirdStrangeAlienEnum& weirdStrangeAlienEnum) const {
- return static_cast<int32_t>(weirdStrangeAlienEnum);
- }
- };
}
#endif // COMMONAPI_TESTS_PREDEFINED_TYPE_COLLECTION_H_
diff --git a/src/test/commonapi/tests/TestInterfaceDBusProxy.cpp b/src/test/commonapi/tests/TestInterfaceDBusProxy.cpp
index 34981e0..f5460d1 100644
--- a/src/test/commonapi/tests/TestInterfaceDBusProxy.cpp
+++ b/src/test/commonapi/tests/TestInterfaceDBusProxy.cpp
@@ -28,7 +28,7 @@ TestInterfaceDBusProxy::TestInterfaceDBusProxy(
const std::shared_ptr<CommonAPI::DBus::DBusProxyConnection>& dbusProxyconnection):
CommonAPI::DBus::DBusProxy(commonApiAddress, interfaceName, busName, objectPath, dbusProxyconnection)
, testPredefinedTypeAttribute_(*this, "onTestPredefinedTypeAttributeAttributeChanged", "setTestPredefinedTypeAttributeAttribute", "u", "getTestPredefinedTypeAttributeAttribute"),
- testDerivedStructAttribute_(*this, "onTestDerivedStructAttributeAttributeChanged", "setTestDerivedStructAttributeAttribute", "(sqii)", "getTestDerivedStructAttributeAttribute"),
+ testDerivedStructAttribute_(*this, "onTestDerivedStructAttributeAttributeChanged", "setTestDerivedStructAttributeAttribute", "(sqi)", "getTestDerivedStructAttributeAttribute"),
testDerivedArrayAttribute_(*this, "onTestDerivedArrayAttributeAttributeChanged", "setTestDerivedArrayAttributeAttribute", "at", "getTestDerivedArrayAttributeAttribute")
, testPredefinedTypeBroadcast_(*this, "TestPredefinedTypeBroadcast", "us")
{
@@ -48,6 +48,23 @@ TestInterfaceDBusProxy::TestPredefinedTypeBroadcastEvent& TestInterfaceDBusProxy
return testPredefinedTypeBroadcast_;
}
+void TestInterfaceDBusProxy::testEmptyMethod(CommonAPI::CallStatus& callStatus) {
+ CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<>,
+ CommonAPI::DBus::DBusSerializableArguments<> >::callMethodWithReply(
+ *this,
+ "testEmptyMethod",
+ "",
+ callStatus
+ );
+}
+std::future<CommonAPI::CallStatus> TestInterfaceDBusProxy::testEmptyMethodAsync(TestEmptyMethodAsyncCallback callback) {
+ return CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<>,
+ CommonAPI::DBus::DBusSerializableArguments<> >::callMethodAsync(
+ *this,
+ "testEmptyMethod",
+ "",
+ std::move(callback));
+}
void TestInterfaceDBusProxy::testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus) {
CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<uint32_t, std::string>,
CommonAPI::DBus::DBusSerializableArguments<> >::callMethodWithReply(
diff --git a/src/test/commonapi/tests/TestInterfaceDBusProxy.h b/src/test/commonapi/tests/TestInterfaceDBusProxy.h
index cf3fd76..1ec27be 100644
--- a/src/test/commonapi/tests/TestInterfaceDBusProxy.h
+++ b/src/test/commonapi/tests/TestInterfaceDBusProxy.h
@@ -4,7 +4,7 @@
#ifndef COMMONAPI_TESTS_TEST_INTERFACE_DBUS_PROXY_H_
#define COMMONAPI_TESTS_TEST_INTERFACE_DBUS_PROXY_H_
-#include "TestInterfaceProxyBase.h"
+#include <commonapi/tests/TestInterfaceProxyBase.h>
#include <CommonAPI/DBus/DBusFactory.h>
#include <CommonAPI/DBus/DBusProxy.h>
#include <CommonAPI/DBus/DBusAttribute.h>
@@ -24,7 +24,7 @@ class TestInterfaceDBusProxy: virtual public TestInterfaceProxyBase, virtual pub
const std::string& objectPath,
const std::shared_ptr<CommonAPI::DBus::DBusProxyConnection>& dbusProxyconnection);
- virtual ~TestInterfaceDBusProxy() { }
+ virtual ~TestInterfaceDBusProxy() {}
virtual TestPredefinedTypeAttributeAttribute& getTestPredefinedTypeAttributeAttribute();
virtual TestDerivedStructAttributeAttribute& getTestDerivedStructAttributeAttribute();
@@ -32,19 +32,17 @@ class TestInterfaceDBusProxy: virtual public TestInterfaceProxyBase, virtual pub
virtual TestPredefinedTypeBroadcastEvent& getTestPredefinedTypeBroadcastEvent();
-
+ virtual void testEmptyMethod(CommonAPI::CallStatus& callStatus);
+ virtual std::future<CommonAPI::CallStatus> testEmptyMethodAsync(TestEmptyMethodAsyncCallback callback);
virtual void testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus);
virtual std::future<CommonAPI::CallStatus> testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback);
-
virtual void testPredefinedTypeMethod(const uint32_t& uint32InValue, const std::string& stringInValue, CommonAPI::CallStatus& callStatus, uint32_t& uint32OutValue, std::string& stringOutValue);
virtual std::future<CommonAPI::CallStatus> testPredefinedTypeMethodAsync(const uint32_t& uint32InValue, const std::string& stringInValue, TestPredefinedTypeMethodAsyncCallback callback);
-
virtual void testVoidDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, CommonAPI::CallStatus& callStatus);
virtual std::future<CommonAPI::CallStatus> testVoidDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, TestVoidDerivedTypeMethodAsyncCallback callback);
-
virtual void testDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, CommonAPI::CallStatus& callStatus, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue);
virtual std::future<CommonAPI::CallStatus> testDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, TestDerivedTypeMethodAsyncCallback callback);
-
+
virtual void getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const;
private:
diff --git a/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp b/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp
index 869560e..9145d2c 100644
--- a/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp
+++ b/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp
@@ -2,7 +2,7 @@
* 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 "TestInterfaceDBusStubAdapter.h"
-#include "TestInterface.h"
+#include <commonapi/tests/TestInterface.h>
namespace commonapi {
namespace tests {
@@ -45,14 +45,14 @@ const char* TestInterfaceDBusStubAdapter::getMethodsDBusIntrospectionXmlData() c
"<arg name=\"changedValue\" type=\"u\" />\n"
"</signal>\n"
"<method name=\"getTestDerivedStructAttributeAttribute\">\n"
- "<arg name=\"value\" type=\"(sqii)\" direction=\"out\" />"
+ "<arg name=\"value\" type=\"(sqi)\" direction=\"out\" />"
"</method>\n"
"<method name=\"setTestDerivedStructAttributeAttribute\">\n"
- "<arg name=\"requestedValue\" type=\"(sqii)\" direction=\"in\" />\n"
- "<arg name=\"setValue\" type=\"(sqii)\" direction=\"out\" />\n"
+ "<arg name=\"requestedValue\" type=\"(sqi)\" direction=\"in\" />\n"
+ "<arg name=\"setValue\" type=\"(sqi)\" direction=\"out\" />\n"
"</method>\n"
"<signal name=\"onTestDerivedStructAttributeAttributeChanged\">\n"
- "<arg name=\"changedValue\" type=\"(sqii)\" />\n"
+ "<arg name=\"changedValue\" type=\"(sqi)\" />\n"
"</signal>\n"
"<method name=\"getTestDerivedArrayAttributeAttribute\">\n"
"<arg name=\"value\" type=\"at\" direction=\"out\" />"
@@ -68,6 +68,8 @@ const char* TestInterfaceDBusStubAdapter::getMethodsDBusIntrospectionXmlData() c
"<arg name=\"uint32Value\" type=\"u\" />\n"
"<arg name=\"stringValue\" type=\"s\" />\n"
"</signal>\n"
+ "<method name=\"testEmptyMethod\">\n"
+ "</method>\n"
"<method name=\"testVoidPredefinedTypeMethod\">\n"
"<arg name=\"uint32Value\" type=\"u\" direction=\"in\" />\n"
"<arg name=\"stringValue\" type=\"s\" direction=\"in\" />\n"
@@ -109,7 +111,7 @@ static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher<
static CommonAPI::DBus::DBusGetAttributeStubDispatcher<
TestInterfaceStub,
DerivedTypeCollection::TestStructExtended
- > getTestDerivedStructAttributeAttributeStubDispatcher(&TestInterfaceStub::getTestDerivedStructAttributeAttribute, "(sqii)");
+ > getTestDerivedStructAttributeAttributeStubDispatcher(&TestInterfaceStub::getTestDerivedStructAttributeAttribute, "(sqi)");
static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher<
TestInterfaceStub,
DerivedTypeCollection::TestStructExtended
@@ -118,7 +120,7 @@ static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher<
&TestInterfaceStubRemoteEvent::onRemoteSetTestDerivedStructAttributeAttribute,
&TestInterfaceStubRemoteEvent::onRemoteTestDerivedStructAttributeAttributeChanged,
&TestInterfaceStubAdapter::fireTestDerivedStructAttributeAttributeChanged,
- "(sqii)");
+ "(sqi)");
static CommonAPI::DBus::DBusGetAttributeStubDispatcher<
TestInterfaceStub,
@@ -137,6 +139,12 @@ static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher<
static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
TestInterfaceStub,
+ std::tuple<>,
+ std::tuple<>
+ > testEmptyMethodStubDispatcher(&TestInterfaceStub::testEmptyMethod, "");
+
+static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
+ TestInterfaceStub,
std::tuple<uint32_t, std::string>,
std::tuple<>
> testVoidPredefinedTypeMethodStubDispatcher(&TestInterfaceStub::testVoidPredefinedTypeMethod, "");
@@ -165,10 +173,11 @@ const TestInterfaceDBusStubAdapterHelper::StubDispatcherTable TestInterfaceDBusS
{ { "getTestPredefinedTypeAttributeAttribute", "" }, &commonapi::tests::getTestPredefinedTypeAttributeAttributeStubDispatcher }
, { { "setTestPredefinedTypeAttributeAttribute", "u" }, &commonapi::tests::setTestPredefinedTypeAttributeAttributeStubDispatcher },
{ { "getTestDerivedStructAttributeAttribute", "" }, &commonapi::tests::getTestDerivedStructAttributeAttributeStubDispatcher }
- , { { "setTestDerivedStructAttributeAttribute", "(sqii)" }, &commonapi::tests::setTestDerivedStructAttributeAttributeStubDispatcher },
+ , { { "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 },
@@ -189,7 +198,7 @@ void TestInterfaceDBusStubAdapter::fireTestDerivedStructAttributeAttributeChange
::sendSignal(
*this,
"onTestDerivedStructAttributeAttributeChanged",
- "(sqii)",
+ "(sqi)",
value
);
}
diff --git a/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h b/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h
index 7a809ad..651a22b 100644
--- a/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h
+++ b/src/test/commonapi/tests/TestInterfaceDBusStubAdapter.h
@@ -4,7 +4,7 @@
#ifndef COMMONAPI_TESTS_TEST_INTERFACE_DBUS_STUB_ADAPTER_H_
#define COMMONAPI_TESTS_TEST_INTERFACE_DBUS_STUB_ADAPTER_H_
-#include "TestInterfaceStub.h"
+#include <commonapi/tests/TestInterfaceStub.h>
#include <CommonAPI/DBus/DBusStubAdapterHelper.h>
#include <CommonAPI/DBus/DBusFactory.h>
diff --git a/src/test/commonapi/tests/TestInterfaceProxy.h b/src/test/commonapi/tests/TestInterfaceProxy.h
index 0e0c54c..7ab5cdc 100644
--- a/src/test/commonapi/tests/TestInterfaceProxy.h
+++ b/src/test/commonapi/tests/TestInterfaceProxy.h
@@ -17,31 +17,153 @@ class TestInterfaceProxy: virtual public TestInterface, virtual public TestInter
TestInterfaceProxy(std::shared_ptr<CommonAPI::Proxy> delegate);
~TestInterfaceProxy();
+ /// Returns the wrapper class that provides access to the attribute TestPredefinedTypeAttribute.
virtual TestPredefinedTypeAttributeAttribute& getTestPredefinedTypeAttributeAttribute();
+ /// Returns the wrapper class that provides access to the attribute TestDerivedStructAttribute.
virtual TestDerivedStructAttributeAttribute& getTestDerivedStructAttributeAttribute();
+ /// Returns the wrapper class that provides access to the attribute TestDerivedArrayAttribute.
virtual TestDerivedArrayAttributeAttribute& getTestDerivedArrayAttributeAttribute();
+ /// Returns the wrapper class that provides access to the broadcast TestPredefinedTypeBroadcast.
virtual TestPredefinedTypeBroadcastEvent& getTestPredefinedTypeBroadcastEvent();
+ /**
+ * Calls testEmptyMethod with synchronous semantics.
+ *
+ * The CallStatus will be filled when the method returns and indicate either
+ * "SUCCESS" or which type of error has occurred. In case of an error, ONLY the CallStatus
+ * will be set.
+ * Synchronous calls are not supported (will block indefinitely) when mainloop integration is used.
+ */
+ virtual void testEmptyMethod(CommonAPI::CallStatus& callStatus);
+ /**
+ * Calls testEmptyMethod with asynchronous semantics.
+ *
+ * The provided callback will be called when the reply to this call arrives or
+ * an error occurs during the call. The CallStatus will indicate either "SUCCESS"
+ * or which type of error has occurred. In case of any error, ONLY the CallStatus
+ * will have a defined value.
+ * The std::future returned by this method will be fulfilled at arrival of the reply.
+ * It will provide the same value for CallStatus as will be handed to the callback.
+ */
+ virtual std::future<CommonAPI::CallStatus> testEmptyMethodAsync(TestEmptyMethodAsyncCallback callback);
+
+ /**
+ * Calls testVoidPredefinedTypeMethod with synchronous semantics.
+ *
+ * All const parameters are input parameters to this method.
+ * The CallStatus will be filled when the method returns and indicate either
+ * "SUCCESS" or which type of error has occurred. In case of an error, ONLY the CallStatus
+ * will be set.
+ * Synchronous calls are not supported (will block indefinitely) when mainloop integration is used.
+ */
virtual void testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus);
+ /**
+ * Calls testVoidPredefinedTypeMethod with asynchronous semantics.
+ *
+ * The provided callback will be called when the reply to this call arrives or
+ * an error occurs during the call. The CallStatus will indicate either "SUCCESS"
+ * or which type of error has occurred. In case of any error, ONLY the CallStatus
+ * will have a defined value.
+ * The std::future returned by this method will be fulfilled at arrival of the reply.
+ * It will provide the same value for CallStatus as will be handed to the callback.
+ */
virtual std::future<CommonAPI::CallStatus> testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback);
+ /**
+ * Calls testPredefinedTypeMethod with synchronous semantics.
+ *
+ * All const parameters are input parameters to this method.
+ * All non-const parameters will be filled with the returned values.
+ * The CallStatus will be filled when the method returns and indicate either
+ * "SUCCESS" or which type of error has occurred. In case of an error, ONLY the CallStatus
+ * will be set.
+ * Synchronous calls are not supported (will block indefinitely) when mainloop integration is used.
+ */
virtual void testPredefinedTypeMethod(const uint32_t& uint32InValue, const std::string& stringInValue, CommonAPI::CallStatus& callStatus, uint32_t& uint32OutValue, std::string& stringOutValue);
+ /**
+ * Calls testPredefinedTypeMethod with asynchronous semantics.
+ *
+ * The provided callback will be called when the reply to this call arrives or
+ * an error occurs during the call. The CallStatus will indicate either "SUCCESS"
+ * or which type of error has occurred. In case of any error, ONLY the CallStatus
+ * will have a defined value.
+ * The std::future returned by this method will be fulfilled at arrival of the reply.
+ * It will provide the same value for CallStatus as will be handed to the callback.
+ */
virtual std::future<CommonAPI::CallStatus> testPredefinedTypeMethodAsync(const uint32_t& uint32InValue, const std::string& stringInValue, TestPredefinedTypeMethodAsyncCallback callback);
+ /**
+ * Calls testVoidDerivedTypeMethod with synchronous semantics.
+ *
+ * All const parameters are input parameters to this method.
+ * The CallStatus will be filled when the method returns and indicate either
+ * "SUCCESS" or which type of error has occurred. In case of an error, ONLY the CallStatus
+ * will be set.
+ * Synchronous calls are not supported (will block indefinitely) when mainloop integration is used.
+ */
virtual void testVoidDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, CommonAPI::CallStatus& callStatus);
+ /**
+ * Calls testVoidDerivedTypeMethod with asynchronous semantics.
+ *
+ * The provided callback will be called when the reply to this call arrives or
+ * an error occurs during the call. The CallStatus will indicate either "SUCCESS"
+ * or which type of error has occurred. In case of any error, ONLY the CallStatus
+ * will have a defined value.
+ * The std::future returned by this method will be fulfilled at arrival of the reply.
+ * It will provide the same value for CallStatus as will be handed to the callback.
+ */
virtual std::future<CommonAPI::CallStatus> testVoidDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, TestVoidDerivedTypeMethodAsyncCallback callback);
+ /**
+ * Calls testDerivedTypeMethod with synchronous semantics.
+ *
+ * All const parameters are input parameters to this method.
+ * All non-const parameters will be filled with the returned values.
+ * The CallStatus will be filled when the method returns and indicate either
+ * "SUCCESS" or which type of error has occurred. In case of an error, ONLY the CallStatus
+ * will be set.
+ * Synchronous calls are not supported (will block indefinitely) when mainloop integration is used.
+ */
virtual void testDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, CommonAPI::CallStatus& callStatus, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue);
+ /**
+ * Calls testDerivedTypeMethod with asynchronous semantics.
+ *
+ * The provided callback will be called when the reply to this call arrives or
+ * an error occurs during the call. The CallStatus will indicate either "SUCCESS"
+ * or which type of error has occurred. In case of any error, ONLY the CallStatus
+ * will have a defined value.
+ * The std::future returned by this method will be fulfilled at arrival of the reply.
+ * It will provide the same value for CallStatus as will be handed to the callback.
+ */
virtual std::future<CommonAPI::CallStatus> testDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, TestDerivedTypeMethodAsyncCallback callback);
+ /// Returns the CommonAPI address of the remote partner this proxy communicates with.
virtual std::string getAddress() const;
+
+ /// Returns the domain of the remote partner this proxy communicates with.
virtual const std::string& getDomain() const;
+
+ /// Returns the service ID of the remote partner this proxy communicates with.
virtual const std::string& getServiceId() const;
+
+ /// Returns the instance ID of the remote partner this proxy communicates with.
virtual const std::string& getInstanceId() const;
+
+ /// Returns true if the remote partner for this proxy is available.
virtual bool isAvailable() const;
+
+ /**
+ * Returns the wrapper class that is used to (de-)register for notifications about
+ * the availability of the remote partner of this proxy.
+ */
virtual CommonAPI::ProxyStatusEvent& getProxyStatusEvent();
+
+ /**
+ * Returns the wrapper class that is used to access version information of the remote
+ * partner of this proxy.
+ */
virtual CommonAPI::InterfaceVersionAttribute& getInterfaceVersionAttribute();
private:
@@ -144,6 +266,16 @@ typename TestInterfaceProxy<_AttributeExtensions...>::TestPredefinedTypeBroadcas
template <typename ... _AttributeExtensions>
+void TestInterfaceProxy<_AttributeExtensions...>::testEmptyMethod(CommonAPI::CallStatus& callStatus) {
+ delegate_->testEmptyMethod(callStatus);
+}
+
+template <typename ... _AttributeExtensions>
+std::future<CommonAPI::CallStatus> TestInterfaceProxy<_AttributeExtensions...>::testEmptyMethodAsync(TestEmptyMethodAsyncCallback callback) {
+ return delegate_->testEmptyMethodAsync(callback);
+}
+
+template <typename ... _AttributeExtensions>
void TestInterfaceProxy<_AttributeExtensions...>::testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus) {
delegate_->testVoidPredefinedTypeMethod(uint32Value, stringValue, callStatus);
}
diff --git a/src/test/commonapi/tests/TestInterfaceProxyBase.h b/src/test/commonapi/tests/TestInterfaceProxyBase.h
index 4210e25..6ae5263 100644
--- a/src/test/commonapi/tests/TestInterfaceProxyBase.h
+++ b/src/test/commonapi/tests/TestInterfaceProxyBase.h
@@ -7,8 +7,7 @@
#include "TestInterface.h"
#include <unordered_map>
#include <cstdint>
-#include "PredefinedTypeCollection.h"
-#include "DerivedTypeCollection.h"
+#include <commonapi/tests/DerivedTypeCollection.h>
#include <CommonAPI/InputStream.h>
#include <vector>
#include <CommonAPI/OutputStream.h>
@@ -27,6 +26,7 @@ class TestInterfaceProxyBase: virtual public CommonAPI::Proxy {
typedef CommonAPI::ObservableAttribute<DerivedTypeCollection::TestStructExtended> TestDerivedStructAttributeAttribute;
typedef CommonAPI::ObservableAttribute<DerivedTypeCollection::TestArrayUInt64> TestDerivedArrayAttributeAttribute;
typedef CommonAPI::Event<uint32_t, std::string> TestPredefinedTypeBroadcastEvent;
+ typedef std::function<void(const CommonAPI::CallStatus&)> TestEmptyMethodAsyncCallback;
typedef std::function<void(const CommonAPI::CallStatus&)> TestVoidPredefinedTypeMethodAsyncCallback;
typedef std::function<void(const CommonAPI::CallStatus&, const uint32_t&, const std::string&)> TestPredefinedTypeMethodAsyncCallback;
typedef std::function<void(const CommonAPI::CallStatus&)> TestVoidDerivedTypeMethodAsyncCallback;
@@ -39,6 +39,9 @@ class TestInterfaceProxyBase: virtual public CommonAPI::Proxy {
virtual TestPredefinedTypeBroadcastEvent& getTestPredefinedTypeBroadcastEvent() = 0;
+ virtual void testEmptyMethod(CommonAPI::CallStatus& callStatus) = 0;
+ virtual std::future<CommonAPI::CallStatus> testEmptyMethodAsync(TestEmptyMethodAsyncCallback callback) = 0;
+
virtual void testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus) = 0;
virtual std::future<CommonAPI::CallStatus> testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback) = 0;
diff --git a/src/test/commonapi/tests/TestInterfaceStub.h b/src/test/commonapi/tests/TestInterfaceStub.h
index ac34f79..6d078ed 100644
--- a/src/test/commonapi/tests/TestInterfaceStub.h
+++ b/src/test/commonapi/tests/TestInterfaceStub.h
@@ -6,8 +6,7 @@
#include <unordered_map>
#include <cstdint>
-#include "PredefinedTypeCollection.h"
-#include "DerivedTypeCollection.h"
+#include <commonapi/tests/DerivedTypeCollection.h>
#include <CommonAPI/InputStream.h>
#include <vector>
#include <CommonAPI/OutputStream.h>
@@ -17,45 +16,92 @@
namespace commonapi {
namespace tests {
+/**
+ * Receives messages from remote and handles all dispatching of deserialized calls
+ * to a stub for the service TestInterface. Also provides means to send broadcasts
+ * and attribute-changed-notifications of observable attributes as defined by this service.
+ * An application developer should not need to bother with this class.
+ */
class TestInterfaceStubAdapter: virtual public CommonAPI::StubAdapter, public TestInterface {
public:
+ ///Notifies all remote listeners about a change of value of the attribute TestPredefinedTypeAttribute.
virtual void fireTestPredefinedTypeAttributeAttributeChanged(const uint32_t& TestPredefinedTypeAttribute) = 0;
+ ///Notifies all remote listeners about a change of value of the attribute TestDerivedStructAttribute.
virtual void fireTestDerivedStructAttributeAttributeChanged(const DerivedTypeCollection::TestStructExtended& TestDerivedStructAttribute) = 0;
+ ///Notifies all remote listeners about a change of value of the attribute TestDerivedArrayAttribute.
virtual void fireTestDerivedArrayAttributeAttributeChanged(const DerivedTypeCollection::TestArrayUInt64& TestDerivedArrayAttribute) = 0;
+ /**
+ * Sends a broadcast event for TestPredefinedTypeBroadcast. Should not be called directly.
+ * Instead, the "fire<broadcastName>Event" methods of the stub should be used.
+ */
virtual void fireTestPredefinedTypeBroadcastEvent(const uint32_t& uint32Value, const std::string& stringValue) = 0;
};
+/**
+ * Defines the necessary callbacks to handle remote set events related to the attributes
+ * defined in the IDL description for TestInterface.
+ * For each attribute two callbacks are defined:
+ * - a verification callback that allows to verify the requested value and to prevent setting
+ * e.g. an invalid value ("onRemoteSet<AttributeName>").
+ * - an action callback to do local work after the attribute value has been changed
+ * ("onRemote<AttributeName>Changed").
+ *
+ * This class and the one below are the ones an application developer needs to have
+ * a look at if he wants to implement a service.
+ */
class TestInterfaceStubRemoteEvent {
public:
virtual ~TestInterfaceStubRemoteEvent() { }
+ /// Verification callback for remote set requests on the attribute TestPredefinedTypeAttribute.
virtual bool onRemoteSetTestPredefinedTypeAttributeAttribute(uint32_t TestPredefinedTypeAttribute) = 0;
+ /// Action callback for remote set requests on the attribute TestPredefinedTypeAttribute.
virtual void onRemoteTestPredefinedTypeAttributeAttributeChanged() = 0;
+ /// Verification callback for remote set requests on the attribute TestDerivedStructAttribute.
virtual bool onRemoteSetTestDerivedStructAttributeAttribute(DerivedTypeCollection::TestStructExtended TestDerivedStructAttribute) = 0;
+ /// Action callback for remote set requests on the attribute TestDerivedStructAttribute.
virtual void onRemoteTestDerivedStructAttributeAttributeChanged() = 0;
+ /// Verification callback for remote set requests on the attribute TestDerivedArrayAttribute.
virtual bool onRemoteSetTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 TestDerivedArrayAttribute) = 0;
+ /// Action callback for remote set requests on the attribute TestDerivedArrayAttribute.
virtual void onRemoteTestDerivedArrayAttributeAttributeChanged() = 0;
};
+/**
+ * Defines the interface that must be implemented by any class that should provide
+ * the service TestInterface to remote clients.
+ * This class and the one above are the ones an application developer needs to have
+ * a look at if he wants to implement a service.
+ */
class TestInterfaceStub : public CommonAPI::Stub<TestInterfaceStubAdapter , TestInterfaceStubRemoteEvent> {
public:
virtual ~TestInterfaceStub() { }
+ /// Provides getter access to the attribute TestPredefinedTypeAttribute.
virtual const uint32_t& getTestPredefinedTypeAttributeAttribute() = 0;
+ /// Provides getter access to the attribute TestDerivedStructAttribute.
virtual const DerivedTypeCollection::TestStructExtended& getTestDerivedStructAttributeAttribute() = 0;
+ /// Provides getter access to the attribute TestDerivedArrayAttribute.
virtual const DerivedTypeCollection::TestArrayUInt64& getTestDerivedArrayAttributeAttribute() = 0;
+ /// This is the method that will be called on remote calls on the method testEmptyMethod.
+ virtual void testEmptyMethod() = 0;
+ /// This is the method that will be called on remote calls on the method testVoidPredefinedTypeMethod.
virtual void testVoidPredefinedTypeMethod(uint32_t uint32Value, std::string stringValue) = 0;
+ /// This is the method that will be called on remote calls on the method testPredefinedTypeMethod.
virtual void testPredefinedTypeMethod(uint32_t uint32InValue, std::string stringInValue, uint32_t& uint32OutValue, std::string& stringOutValue) = 0;
+ /// This is the method that will be called on remote calls on the method testVoidDerivedTypeMethod.
virtual void testVoidDerivedTypeMethod(DerivedTypeCollection::TestEnumExtended2 testEnumExtended2Value, DerivedTypeCollection::TestMap testMapValue) = 0;
+ /// This is the method that will be called on remote calls on the method testDerivedTypeMethod.
virtual void testDerivedTypeMethod(DerivedTypeCollection::TestEnumExtended2 testEnumExtended2InValue, DerivedTypeCollection::TestMap testMapInValue, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue) = 0;
+ /// Sends a broadcast event for TestPredefinedTypeBroadcast.
virtual void fireTestPredefinedTypeBroadcastEvent(const uint32_t& uint32Value, const std::string& stringValue) = 0;
};
diff --git a/src/test/commonapi/tests/TestInterfaceStubDefault.cpp b/src/test/commonapi/tests/TestInterfaceStubDefault.cpp
index c5e7e35..d852c0c 100644
--- a/src/test/commonapi/tests/TestInterfaceStubDefault.cpp
+++ b/src/test/commonapi/tests/TestInterfaceStubDefault.cpp
@@ -1,7 +1,7 @@
/* 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 "TestInterfaceStubDefault.h"
+#include <commonapi/tests/TestInterfaceStubDefault.h>
namespace commonapi {
namespace tests {
@@ -15,10 +15,6 @@ TestInterfaceStubRemoteEvent* TestInterfaceStubDefault::initStubAdapter(const st
return &remoteEventHandler_;
}
-void TestInterfaceStubDefault::deinitStubAdapter() {
- stubAdapter_.reset();
-}
-
const uint32_t& TestInterfaceStubDefault::getTestPredefinedTypeAttributeAttribute() {
return testPredefinedTypeAttributeAttributeValue_;
}
@@ -46,6 +42,14 @@ bool TestInterfaceStubDefault::validateTestPredefinedTypeAttributeAttributeReque
return true;
}
+bool TestInterfaceStubDefault::RemoteEventHandler::onRemoteSetTestPredefinedTypeAttributeAttribute(uint32_t value) {
+ return defaultStub_->trySetTestPredefinedTypeAttributeAttribute(std::move(value));
+}
+
+void TestInterfaceStubDefault::RemoteEventHandler::onRemoteTestPredefinedTypeAttributeAttributeChanged() {
+ defaultStub_->onRemoteTestPredefinedTypeAttributeAttributeChanged();
+}
+
const DerivedTypeCollection::TestStructExtended& TestInterfaceStubDefault::getTestDerivedStructAttributeAttribute() {
return testDerivedStructAttributeAttributeValue_;
}
@@ -73,6 +77,14 @@ bool TestInterfaceStubDefault::validateTestDerivedStructAttributeAttributeReques
return true;
}
+bool TestInterfaceStubDefault::RemoteEventHandler::onRemoteSetTestDerivedStructAttributeAttribute(DerivedTypeCollection::TestStructExtended value) {
+ return defaultStub_->trySetTestDerivedStructAttributeAttribute(std::move(value));
+}
+
+void TestInterfaceStubDefault::RemoteEventHandler::onRemoteTestDerivedStructAttributeAttributeChanged() {
+ defaultStub_->onRemoteTestDerivedStructAttributeAttributeChanged();
+}
+
const DerivedTypeCollection::TestArrayUInt64& TestInterfaceStubDefault::getTestDerivedArrayAttributeAttribute() {
return testDerivedArrayAttributeAttributeValue_;
}
@@ -100,6 +112,18 @@ bool TestInterfaceStubDefault::validateTestDerivedArrayAttributeAttributeRequest
return true;
}
+bool TestInterfaceStubDefault::RemoteEventHandler::onRemoteSetTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 value) {
+ return defaultStub_->trySetTestDerivedArrayAttributeAttribute(std::move(value));
+}
+
+void TestInterfaceStubDefault::RemoteEventHandler::onRemoteTestDerivedArrayAttributeAttributeChanged() {
+ defaultStub_->onRemoteTestDerivedArrayAttributeAttributeChanged();
+}
+
+
+void TestInterfaceStubDefault::testEmptyMethod() {
+ // No operation in default
+}
void TestInterfaceStubDefault::testVoidPredefinedTypeMethod(uint32_t uint32Value, std::string stringValue) {
// No operation in default
@@ -126,30 +150,5 @@ TestInterfaceStubDefault::RemoteEventHandler::RemoteEventHandler(TestInterfaceSt
defaultStub_(defaultStub) {
}
-bool TestInterfaceStubDefault::RemoteEventHandler::onRemoteSetTestPredefinedTypeAttributeAttribute(uint32_t value) {
- return defaultStub_->trySetTestPredefinedTypeAttributeAttribute(std::move(value));
-}
-
-void TestInterfaceStubDefault::RemoteEventHandler::onRemoteTestPredefinedTypeAttributeAttributeChanged() {
- defaultStub_->onRemoteTestPredefinedTypeAttributeAttributeChanged();
-}
-
-bool TestInterfaceStubDefault::RemoteEventHandler::onRemoteSetTestDerivedStructAttributeAttribute(DerivedTypeCollection::TestStructExtended value) {
- return defaultStub_->trySetTestDerivedStructAttributeAttribute(std::move(value));
-}
-
-void TestInterfaceStubDefault::RemoteEventHandler::onRemoteTestDerivedStructAttributeAttributeChanged() {
- defaultStub_->onRemoteTestDerivedStructAttributeAttributeChanged();
-}
-
-bool TestInterfaceStubDefault::RemoteEventHandler::onRemoteSetTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 value) {
- return defaultStub_->trySetTestDerivedArrayAttributeAttribute(std::move(value));
-}
-
-void TestInterfaceStubDefault::RemoteEventHandler::onRemoteTestDerivedArrayAttributeAttributeChanged() {
- defaultStub_->onRemoteTestDerivedArrayAttributeAttributeChanged();
-}
-
-
} // namespace tests
} // namespace commonapi
diff --git a/src/test/commonapi/tests/TestInterfaceStubDefault.h b/src/test/commonapi/tests/TestInterfaceStubDefault.h
index bc5cdff..3f0aeff 100644
--- a/src/test/commonapi/tests/TestInterfaceStubDefault.h
+++ b/src/test/commonapi/tests/TestInterfaceStubDefault.h
@@ -4,17 +4,26 @@
#ifndef COMMONAPI_TESTS_TEST_INTERFACE_STUB_DEFAULT_H_
#define COMMONAPI_TESTS_TEST_INTERFACE_STUB_DEFAULT_H_
-#include "TestInterfaceStub.h"
+#include <commonapi/tests/TestInterfaceStub.h>
namespace commonapi {
namespace tests {
+/**
+ * Provides a default implementation for TestInterfaceStubRemoteEvent and
+ * TestInterfaceStub. Method callbacks have an empty implementation,
+ * remote set calls on attributes will always change the value of the attribute
+ * to the one received.
+ *
+ * Override this stub if you only want to provide a subset of the functionality
+ * that would be defined for this service, and/or if you do not need any non-default
+ * behaviour.
+ */
class TestInterfaceStubDefault : public TestInterfaceStub {
public:
TestInterfaceStubDefault();
TestInterfaceStubRemoteEvent* initStubAdapter(const std::shared_ptr<TestInterfaceStubAdapter>& stubAdapter);
- void deinitStubAdapter();
virtual const uint32_t& getTestPredefinedTypeAttributeAttribute();
virtual void setTestPredefinedTypeAttributeAttribute(uint32_t value);
@@ -26,6 +35,8 @@ class TestInterfaceStubDefault : public TestInterfaceStub {
virtual void setTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 value);
+ virtual void testEmptyMethod();
+
virtual void testVoidPredefinedTypeMethod(uint32_t uint32Value, std::string stringValue);
virtual void testPredefinedTypeMethod(uint32_t uint32InValue, std::string stringInValue, uint32_t& uint32OutValue, std::string& stringOutValue);
diff --git a/src/test/fakeLegacyService/sendToFakeLegacyService.py b/src/test/fakeLegacyService/sendToFakeLegacyService.py
index ea23a74..79c1445 100644
--- a/src/test/fakeLegacyService/sendToFakeLegacyService.py
+++ b/src/test/fakeLegacyService/sendToFakeLegacyService.py
@@ -13,11 +13,21 @@ import dbus
import dbus.service
def finish():
- bus = dbus.SessionBus()
- remote_object = bus.get_object('fake.legacy.service.connection','/some/legacy/path/6259504')
- iface = dbus.Interface(remote_object, 'fake.legacy.service.LegacyInterface')
- iface.finish()
+ try:
+ bus = dbus.SessionBus()
+ remote_object = bus.get_object('fake.legacy.service.connection','/some/legacy/path/6259504')
+ iface = dbus.Interface(remote_object, 'fake.legacy.service.LegacyInterface')
+ iface.finish()
+ return 0
+ except:
+ print "Service not existing, therefore could not be stopped"
+ return 1
-command=sys.argv[1]
-if command=="finish":
- finish()
+def main():
+ command=sys.argv[1]
+ if command=="finish":
+ return finish()
+
+ return 0
+
+sys.exit(main()) \ No newline at end of file
diff --git a/src/test/test-derived-types.fidl b/src/test/test-derived-types.fidl
index 7b8c477..da82e80 100644
--- a/src/test/test-derived-types.fidl
+++ b/src/test/test-derived-types.fidl
@@ -6,6 +6,15 @@ package commonapi.tests
import commonapi.tests.* from "test-predefined-types.fidl"
typeCollection DerivedTypeCollection {
+
+ map TestMap { UInt32 to TestArrayTestStruct }
+
+ struct TestStructExtended extends TestStruct {
+ TestEnumExtended2 testEnumExtended2
+ }
+
+ map TestEnumMap { TestEnum to String }
+
<** @description : Common errors. **>
enumeration TestEnum {
<** @description : default **>
@@ -18,6 +27,13 @@ typeCollection DerivedTypeCollection {
E_NOT_USED = "0x03"
}
+ array TestArrayTestStruct of TestStruct
+
+ enumeration TestEnumExtended2 extends TestEnumExtended {
+ <** @description : new error **>
+ E_NEW2 = "0x05"
+ }
+
enumeration TestEnumMissingValue {
<** @description : default **>
E1 = "A"
@@ -29,11 +45,8 @@ typeCollection DerivedTypeCollection {
<** @description : new error **>
E_NEW = "0x04"
}
-
- enumeration TestEnumExtended2 extends TestEnumExtended {
- <** @description : new error **>
- E_NEW2 = "0x05"
- }
+
+ array TestArrayUInt64 of UInt64
struct TestStruct {
<** @description : the name of the property **>
@@ -42,15 +55,6 @@ typeCollection DerivedTypeCollection {
<** @description : the actual value **>
UInt16 uintValue
}
-
- struct TestStructExtended extends TestStruct {
- TestEnumExtended2 testEnumExtended2
- }
-
- array TestArrayUInt64 of UInt64
- array TestArrayTestStruct of TestStruct
-
- map TestMap { UInt32 to TestArrayTestStruct }
}
diff --git a/src/test/test-interface-proxy.fidl b/src/test/test-interface-proxy.fidl
index 88d4874..774c1a8 100644
--- a/src/test/test-interface-proxy.fidl
+++ b/src/test/test-interface-proxy.fidl
@@ -12,6 +12,9 @@ interface TestInterface {
attribute DerivedTypeCollection.TestStructExtended TestDerivedStructAttribute
attribute DerivedTypeCollection.TestArrayUInt64 TestDerivedArrayAttribute
+ method testEmptyMethod {
+ }
+
method testVoidPredefinedTypeMethod {
in {
UInt32 uint32Value