You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2018/11/09 14:26:21 UTC

celix git commit: CELIX-454: Refactors the pubsub tests and adds backtrace printing support for framework_log and loghelper

Repository: celix
Updated Branches:
  refs/heads/feature/CELIX-454-pubsub-disc b2548c845 -> ec7fdcfff


CELIX-454: Refactors the pubsub tests and adds backtrace printing support for framework_log and loghelper


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/ec7fdcff
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/ec7fdcff
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/ec7fdcff

Branch: refs/heads/feature/CELIX-454-pubsub-disc
Commit: ec7fdcfff26ddc3c14d3fe230bba0666c2fa1ceb
Parents: b2548c8
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Thu Nov 8 16:12:47 2018 +0100
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Fri Nov 9 15:25:04 2018 +0100

----------------------------------------------------------------------
 bundles/log_service/src/log_helper.c            |  52 ++++-
 .../pubsub_admin_zmq/src/pubsub_zmq_admin.c     |   6 +-
 .../pubsub_admin_zmq/src/pubsub_zmq_admin.h     |   2 +-
 .../src/pubsub_zmq_topic_sender.c               |   6 +
 .../src/pubsub_zmq_topic_sender.h               |   1 +
 bundles/pubsub/pubsub_api/include/pubsub/api.h  |  28 +++
 bundles/pubsub/pubsub_spi/src/pubsub_utils.c    |   4 +-
 .../src/pubsub_topology_manager.c               |  34 ++-
 bundles/pubsub/test/CMakeLists.txt              | 129 +++--------
 bundles/pubsub/test/meta_data/msg.descriptor    |   9 +
 bundles/pubsub/test/meta_data/ping.properties   |  20 ++
 .../pubsub/test/msg_descriptors/msg.descriptor  |   9 -
 .../pubsub/test/msg_descriptors/sync.descriptor |   9 -
 bundles/pubsub/test/test/sut_activator.c        | 127 ++++++-----
 bundles/pubsub/test/test/sync.h                 |  29 ---
 bundles/pubsub/test/test/test_runner.cc         |  18 ++
 bundles/pubsub/test/test/tst_activator.cc       | 110 +++++++++
 bundles/pubsub/test/test/tst_activator.cpp      | 221 -------------------
 cmake/cmake_celix/ContainerPackaging.cmake      |  47 ++--
 cmake/cmake_celix/runtime_common.sh.in          |   4 +-
 libs/framework/include/celix_bundle_activator.h |   2 +-
 libs/framework/include/celix_log.h              |   2 +
 libs/framework/src/bundle.c                     |   5 +-
 libs/framework/src/bundle_context.c             |   3 +-
 libs/framework/src/bundle_private.h             |   2 +
 libs/framework/src/celix_log.c                  |  31 ++-
 26 files changed, 442 insertions(+), 468 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/log_service/src/log_helper.c
----------------------------------------------------------------------
diff --git a/bundles/log_service/src/log_helper.c b/bundles/log_service/src/log_helper.c
index 6570357..a995f07 100644
--- a/bundles/log_service/src/log_helper.c
+++ b/bundles/log_service/src/log_helper.c
@@ -38,12 +38,43 @@
 #include "log_helper.h"
 
 #define LOGHELPER_ENABLE_STDOUT_FALLBACK_NAME 				"LOGHELPER_ENABLE_STDOUT_FALLBACK"
-#define LOGHELPER_ENABLE_STDOUT_FALLBACK_DEFAULT 			false
+#define LOGHELPER_ENABLE_STDOUT_FALLBACK_DEFAULT 			true
 
 #define LOGHELPER_STDOUT_FALLBACK_INCLUDE_DEBUG_NAME 		"LOGHELPER_STDOUT_FALLBACK_INCLUDE_DEBUG"
 #define LOGHELPER_STDOUT_FALLBACK_INCLUDE_DEBUG_DEFAULT 	false
 
 
+#ifdef __linux__
+//includes for the backtrace function
+#include <execinfo.h>
+#include <stdlib.h>
+#include <stdio.h>
+#endif
+
+#ifdef __linux__
+static char* logHelper_backtrace(void) {
+	void *bbuf[64];
+	int nrOfTraces = backtrace(bbuf, 64);
+	char **lines = backtrace_symbols(bbuf, nrOfTraces);
+
+	char *result = NULL;
+	size_t size = 0;
+	FILE *os = open_memstream(&result, &size);
+	fprintf(os, "Backtrace:\n");
+	for (int i = 0; i < nrOfTraces; ++i) {
+		char *line = lines[i];
+		fprintf(os, "%s\n", line);
+	}
+	free(lines);
+	fclose(os);
+	return result;
+}
+#else
+static void logHelper_logBacktrace(void) {
+	return NULL;
+}
+#endif
+
 struct log_helper {
 	bundle_context_pt bundleContext;
     service_tracker_pt logServiceTracker;
@@ -177,7 +208,12 @@ celix_status_t logHelper_log(log_helper_pt loghelper, log_level_t level, char* m
 	for (; i < arrayList_size(loghelper->logServices); i++) {
 		log_service_pt logService = arrayList_get(loghelper->logServices, i);
 		if (logService != NULL) {
-			(logService->log)(logService->logger, level, msg);
+			(logService->log)(logService->logger, level, msg); //TODO add backtrace to msg if the level is ERROR
+			if (level == OSGI_LOGSERVICE_ERROR) {
+				char *backtrace = logHelper_backtrace();
+				logService->log(logService->logger, level, backtrace);
+				free(backtrace);
+			}
 			logged = true;
 		}
 	}
@@ -206,7 +242,17 @@ celix_status_t logHelper_log(log_helper_pt loghelper, log_level_t level, char* m
         }
 
         if (print) {
-			printf("%s: %s\n", levelStr, msg);
+			if (level == OSGI_LOGSERVICE_ERROR) {
+				fprintf(stderr, "%s: %s\n", levelStr, msg);
+				if (level == OSGI_LOGSERVICE_ERROR) {
+					char *backtrace = logHelper_backtrace();
+					fprintf(stderr, "%s", backtrace);
+					free(backtrace);
+				}
+			} else {
+				printf("%s: %s\n", levelStr, msg);
+			}
+
 		}
     }
 

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c
----------------------------------------------------------------------
diff --git a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c
index 0192bb4..1076ebf 100644
--- a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c
+++ b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c
@@ -439,8 +439,7 @@ celix_status_t pubsub_zmqAdmin_setupTopicReceiver(void *handle, const char *scop
 
     celix_properties_t *newEndpoint = NULL;
 
-    const char *staticConnectUrls = topicProperties != NULL ?
-            celix_properties_get(topicProperties, PUBSUB_ZMQ_STATIC_CONNECT_URLS, NULL) : NULL;
+    const char *staticConnectUrls = celix_properties_get(topicProperties, PUBSUB_ZMQ_STATIC_CONNECT_URLS, NULL);
 
     char *key = pubsubEndpoint_createScopeTopicKey(scope, topic);
     celixThreadMutex_lock(&psa->serializers.mutex);
@@ -640,9 +639,10 @@ celix_status_t pubsub_zmqAdmin_executeCommand(void *handle, char *commandLine __
         const char *scope = pubsub_zmqTopicSender_scope(sender);
         const char *topic = pubsub_zmqTopicSender_topic(sender);
         const char *url = pubsub_zmqTopicSender_url(sender);
+        const char *postUrl = pubsub_zmqTopicSender_isStatic(sender) ? " (static)" : "";
         fprintf(out, "|- Topic Sender %s/%s\n", scope, topic);
         fprintf(out, "   |- serializer type = %s\n", serType);
-        fprintf(out, "   |- url             = %s\n", url);
+        fprintf(out, "   |- url            = %s%s\n", url, postUrl);
     }
     celixThreadMutex_unlock(&psa->topicSenders.mutex);
     celixThreadMutex_unlock(&psa->serializers.mutex);

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h
----------------------------------------------------------------------
diff --git a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h
index 304ad11..a249b5a 100644
--- a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h
+++ b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h
@@ -54,7 +54,7 @@
  * The static url which a subscriber should try to connect to.
  * The urls are space separated
  */
-#define PUBSUB_ZMQ_STATIC_CONNECT_URLS    "zmq.static.connect.url"
+#define PUBSUB_ZMQ_STATIC_CONNECT_URLS    "zmq.static.connect.urls"
 
 
 typedef struct pubsub_zmq_admin pubsub_zmq_admin_t;

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.c
----------------------------------------------------------------------
diff --git a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.c b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.c
index 9ad7783..42d5fec 100644
--- a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.c
+++ b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.c
@@ -54,6 +54,7 @@ struct pubsub_zmq_topic_sender {
     char *topic;
     char scopeAndTopicFilter[5];
     char *url;
+    bool isStatic;
 
     struct {
         celix_thread_mutex_t mutex;
@@ -179,6 +180,7 @@ pubsub_zmq_topic_sender_t* pubsub_zmqTopicSender_create(
                 L_WARN("Error for zmq_bind using static bind url '%s'. %s", staticBindUrl, strerror(errno));
             } else {
                 sender->url = strndup(staticBindUrl, 1024*1024);
+                sender->isStatic = true;
             }
         } else {
 
@@ -288,6 +290,10 @@ const char* pubsub_zmqTopicSender_url(pubsub_zmq_topic_sender_t *sender) {
     return sender->url;
 }
 
+bool pubsub_zmqTopicSender_isStatic(pubsub_zmq_topic_sender_t *sender) {
+    return sender->isStatic;
+}
+
 void pubsub_zmqTopicSender_connectTo(pubsub_zmq_topic_sender_t *sender, const celix_properties_t *endpoint) {
     //TODO subscriber count -> topic info
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.h
----------------------------------------------------------------------
diff --git a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.h b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.h
index af63870..ef09a3d 100644
--- a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.h
+++ b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_topic_sender.h
@@ -39,6 +39,7 @@ void pubsub_zmqTopicSender_destroy(pubsub_zmq_topic_sender_t *sender);
 const char* pubsub_zmqTopicSender_scope(pubsub_zmq_topic_sender_t *sender);
 const char* pubsub_zmqTopicSender_topic(pubsub_zmq_topic_sender_t *sender);
 const char* pubsub_zmqTopicSender_url(pubsub_zmq_topic_sender_t *sender);
+bool pubsub_zmqTopicSender_isStatic(pubsub_zmq_topic_sender_t *sender);
 
 long pubsub_zmqTopicSender_serializerSvcId(pubsub_zmq_topic_sender_t *sender);
 

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/pubsub_api/include/pubsub/api.h
----------------------------------------------------------------------
diff --git a/bundles/pubsub/pubsub_api/include/pubsub/api.h b/bundles/pubsub/pubsub_api/include/pubsub/api.h
new file mode 100644
index 0000000..ef036d9
--- /dev/null
+++ b/bundles/pubsub/pubsub_api/include/pubsub/api.h
@@ -0,0 +1,28 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+
+#ifndef __PUBSUB_API_H_
+#define __PUBSUB_API_H_
+
+#include "pubsub/publisher.h"
+#include "pubsub/subscriber.h"
+
+
+#endif //  __PUBSUB_API_H_

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/pubsub_spi/src/pubsub_utils.c
----------------------------------------------------------------------
diff --git a/bundles/pubsub/pubsub_spi/src/pubsub_utils.c b/bundles/pubsub/pubsub_spi/src/pubsub_utils.c
index 225e3c0..481687a 100644
--- a/bundles/pubsub/pubsub_spi/src/pubsub_utils.c
+++ b/bundles/pubsub/pubsub_spi/src/pubsub_utils.c
@@ -148,10 +148,10 @@ celix_properties_t *pubsub_utils_getTopicProperties(const celix_bundle_t *bundle
 
 		if(bundleRoot != NULL){
 
-			asprintf(&topicPropertiesPath, "%s/META-INF/topics/%s/%s.properties", bundleRoot, isPublisher?"pub":"sub", topic);
+			asprintf(&topicPropertiesPath, "%s/META-INF/topics/%s/%s.properties", bundleRoot, isPublisher? "pub":"sub", topic);
 			topic_props = properties_load(topicPropertiesPath);
 			if(topic_props==NULL){
-				printf("PSEP: Could not load properties for %s on topic %s, bundleId=%ld\n", isPublisher?"publication":"subscription", topic,bundleId);
+				printf("PubSub: Could not load properties for %s on topic %s. Searched location %s, bundleId=%ld\n", isPublisher? "publication":"subscription", topic, topicPropertiesPath, bundleId);
 			}
 
 			free(topicPropertiesPath);

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
----------------------------------------------------------------------
diff --git a/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c b/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
index aff03c7..7d0cfbe 100644
--- a/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
+++ b/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
@@ -288,11 +288,12 @@ void pubsub_topologyManager_subscriberAdded(void *handle, void *svc __attribute_
     const char *scope = celix_properties_get(props, PUBSUB_SUBSCRIBER_SCOPE, "default");
     if (topic == NULL) {
         logHelper_log(manager->loghelper, OSGI_LOGSERVICE_WARNING,
-                      "[PSTM] Warning found subscriber service without mandatory %s property.",
+                      "[PSTM] Warning found subscriber service without mandatory '%s' property.",
                       PUBSUB_SUBSCRIBER_TOPIC);
         return;
     }
 
+    bool triggerCondition = false;
     long bndId = celix_bundle_getId(bnd);
     char *scopeAndTopicKey = NULL;
     scopeAndTopicKey = pubsubEndpoint_createScopeTopicKey(scope, topic);
@@ -316,9 +317,15 @@ void pubsub_topologyManager_subscriberAdded(void *handle, void *svc __attribute_
         hashMap_put(manager->topicReceivers.map, entry->scopeAndTopicKey, entry);
 
         //signal psa handling thread
-        celixThreadCondition_broadcast(&manager->psaHandling.cond);
+        triggerCondition = true;
     }
     celixThreadMutex_unlock(&manager->topicReceivers.mutex);
+
+    if (triggerCondition) {
+        celixThreadMutex_lock(&manager->psaHandling.mutex);
+        celixThreadCondition_broadcast(&manager->psaHandling.cond);
+        celixThreadMutex_unlock(&manager->psaHandling.mutex);
+    }
 }
 
 void pubsub_topologyManager_subscriberRemoved(void *handle, void *svc __attribute__((unused)), const celix_properties_t *props, const celix_bundle_t *bnd) {
@@ -400,6 +407,7 @@ void pubsub_topologyManager_publisherTrackerAdded(void *handle, const celix_serv
     //3) signal psaHandling thread to find a psa and setup TopicSender
 
 
+    bool triggerCondition = false;
     char *topicFromFilter = NULL;
     char *scopeFromFilter = NULL;
     pubsub_getPubSubInfoFromFilter(info->filter->filterStr, &topicFromFilter, &scopeFromFilter);
@@ -436,9 +444,15 @@ void pubsub_topologyManager_publisherTrackerAdded(void *handle, const celix_serv
         hashMap_put(manager->topicSenders.map, entry->scopeAndTopicKey, entry);
 
         //new entry -> wakeup psaHandling thread
-        celixThreadCondition_broadcast(&manager->psaHandling.cond);
+        triggerCondition = true;
     }
     celixThreadMutex_unlock(&manager->topicSenders.mutex);
+
+    if (triggerCondition) {
+        celixThreadMutex_lock(&manager->psaHandling.mutex);
+        celixThreadCondition_broadcast(&manager->psaHandling.cond);
+        celixThreadMutex_unlock(&manager->psaHandling.mutex);
+    }
 }
 
 void pubsub_topologyManager_publisherTrackerRemoved(void *handle, const celix_service_tracker_info_t *info) {
@@ -481,6 +495,7 @@ celix_status_t pubsub_topologyManager_addDiscoveredEndpoint(void *handle, const
     // 1) See if endpoint is already discovered, if so increase usage count.
     // 1) If not, find matching psa using the matchEndpoint
     // 2) if found call addEndpoint of the matching psa
+    bool triggerCondition = false;
 
     if (manager->verbose) {
         logHelper_log(manager->loghelper, OSGI_LOGSERVICE_DEBUG,
@@ -507,11 +522,17 @@ celix_status_t pubsub_topologyManager_addDiscoveredEndpoint(void *handle, const
         hashMap_put(manager->discoveredEndpoints.map, (void *) entry->uuid, entry);
 
         //waking up psa handling thread to select psa
-        celixThreadCondition_broadcast(&manager->psaHandling.cond);
+        triggerCondition = true;
 
     }
     celixThreadMutex_unlock(&manager->discoveredEndpoints.mutex);
 
+    if (triggerCondition) {
+        celixThreadMutex_lock(&manager->psaHandling.mutex);
+        celixThreadCondition_broadcast(&manager->psaHandling.cond);
+        celixThreadMutex_unlock(&manager->psaHandling.mutex);
+    }
+
     return status;
 }
 
@@ -856,6 +877,7 @@ static void pstm_setupTopicReceivers(pubsub_topology_manager_t *manager) {
             if (highestScore > PUBSUB_ADMIN_NO_MATCH_SCORE) {
                 entry->selectedPsaSvcId = selectedPsaSvcId;
                 entry->selectedSerializerSvcId = serializerSvcId;
+                entry->topicProperties = highestMatchTopicProperties;
 
                 bool called = celix_bundleContext_useServiceWithId(manager->context, selectedPsaSvcId, PUBSUB_ADMIN_SERVICE_NAME,
                                                                    entry,
@@ -1006,7 +1028,7 @@ celix_status_t pubsub_topologyManager_shellCommand(void *handle, char *commandLi
         while (hashMapIterator_hasNext(&iter)) {
             pstm_topic_receiver_or_sender_entry_t *entry = hashMapIterator_nextValue(&iter);
             if (entry->endpoint == NULL) {
-                fprintf(os, "|- Pending Topic Sender for scope/topic %s/%s:\n", entry->scope, entry->topic);
+                fprintf(os, "|- Pending Topic Sender for %s/%s:\n", entry->scope, entry->topic);
                 const char *requestedQos = celix_properties_get(entry->topicProperties, PUBSUB_UTILS_QOS_ATTRIBUTE_KEY, "(None)");
                 const char *requestedConfig = celix_properties_get(entry->topicProperties, PUBSUB_ADMIN_TYPE_KEY, "(None)");
                 const char *requestedSer = celix_properties_get(entry->topicProperties, PUBSUB_SERIALIZER_TYPE_KEY, "(None)");
@@ -1029,7 +1051,7 @@ celix_status_t pubsub_topologyManager_shellCommand(void *handle, char *commandLi
         while (hashMapIterator_hasNext(&iter)) {
             pstm_topic_receiver_or_sender_entry_t *entry = hashMapIterator_nextValue(&iter);
             if (entry->endpoint == NULL) {
-                fprintf(os, "|- Topic Receiver for scope/topic %s/%s:\n", entry->scope, entry->topic);
+                fprintf(os, "|- Topic Receiver for %s/%s:\n", entry->scope, entry->topic);
                 const char *requestedQos = celix_properties_get(entry->topicProperties, PUBSUB_UTILS_QOS_ATTRIBUTE_KEY, "(None)");
                 const char *requestedConfig = celix_properties_get(entry->topicProperties, PUBSUB_ADMIN_TYPE_KEY, "(None)");
                 const char *requestedSer = celix_properties_get(entry->topicProperties, PUBSUB_SERIALIZER_TYPE_KEY, "(None)");

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/test/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/bundles/pubsub/test/CMakeLists.txt b/bundles/pubsub/test/CMakeLists.txt
index 39e5575..d67a767 100644
--- a/bundles/pubsub/test/CMakeLists.txt
+++ b/bundles/pubsub/test/CMakeLists.txt
@@ -15,10 +15,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
-find_program(ETCD_CMD NAMES etcd)
-
 find_package(CppUTest REQUIRED)
-include_directories(${CPPUTEST_INCLUDE_DIR})
+find_package(Jansson REQUIRED)
 
 add_celix_bundle(pubsub_sut
     #"Vanilla" bundle which is under test
@@ -27,111 +25,46 @@ add_celix_bundle(pubsub_sut
     VERSION 1.0.0
 )
 target_include_directories(pubsub_sut PRIVATE test)
-target_link_libraries(pubsub_sut PRIVATE Celix::pubsub_spi)
-
+target_link_libraries(pubsub_sut PRIVATE Celix::pubsub_api)
 celix_bundle_files(pubsub_sut
-    msg_descriptors/msg.descriptor
-    msg_descriptors/sync.descriptor
-    DESTINATION "META-INF/descriptors/messages"
-)
-
-add_celix_container(pubsub_udpmc_sut
-    NAME deploy_sut
-    BUNDLES
-        celix_pubsub_serializer_json
-        celix_pubsub_discovery_etcd
-        celix_pubsub_admin_udp_multicast
-        celix_pubsub_topology_manager
-        pubsub_sut
-    DIR ${PROJECT_BINARY_DIR}/runtimes/test/pubsub/udpmc
+    meta_data/msg.descriptor
+    DESTINATION "META-INF/descriptors"
 )
-add_celix_container(pubsub_zmq_sut
-    NAME deploy_sut
-    BUNDLES
-        celix_pubsub_serializer_json
-        celix_pubsub_discovery_etcd
-        celix_pubsub_admin_zmq
-        celix_pubsub_topology_manager
-        pubsub_sut
-    DIR ${PROJECT_BINARY_DIR}/runtimes/test/pubsub/zmq
+celix_bundle_files(pubsub_sut
+    meta_data/ping.properties
+    DESTINATION "META-INF/topics/pub"
 )
 
 add_celix_bundle(pubsub_tst
     #Test bundle containing cpputests and uses celix_test_runner launcher instead of the celix launcher
     SOURCES
-        test/tst_activator.cpp
+        test/tst_activator.cc
     VERSION 1.0.0
 )
-if (APPLE)
-    #Note that the launcher celix_test_runner is linked with CppuTest, not the bundle libs. Default libCppUTest.a is not compiled for relocation 
-    target_link_libraries(pubsub_tst PRIVATE Celix::framework -Wl,-undefined -Wl,dynamic_lookup)
-else ()
-    target_link_libraries(pubsub_tst PRIVATE Celix::framework)
-endif ()
-
+target_link_libraries(pubsub_tst PRIVATE Celix::framework Celix::pubsub_api)
 celix_bundle_files(pubsub_tst
-    msg_descriptors/msg.descriptor
-    msg_descriptors/sync.descriptor
-    DESTINATION "META-INF/descriptors/messages"
+    meta_data/msg.descriptor
+    DESTINATION "META-INF/descriptors"
 )
-add_celix_container(pubsub_udpmc_tst
-    NAME deploy_tst
-    BUNDLES
-        celix_pubsub_serializer_json
-        celix_pubsub_topology_manager
-        celix_pubsub_discovery_etcd
-        celix_pubsub_admin_udp_multicast
-        pubsub_tst
-    #NOTE using $<TARGET_PROPERTY:pubsub_test_udpmc_runtime,RUNTIME_DIR> in DIR not (yet) possible
-    DIR ${PROJECT_BINARY_DIR}/runtimes/test/pubsub/udpmc
-    LAUNCHER celix_test_runner
-)
-add_celix_container(pubsub_zmq_tst
-    NAME deploy_tst
-    BUNDLES
-        celix_pubsub_serializer_json
-        celix_pubsub_topology_manager
-        celix_pubsub_discovery_etcd
-        celix_pubsub_admin_zmq
-        pubsub_tst
-    DIR ${PROJECT_BINARY_DIR}/runtimes/test/pubsub/zmq
-    LAUNCHER celix_test_runner
+celix_bundle_files(pubsub_tst
+    meta_data/ping.properties
+    DESTINATION "META-INF/topics/sub"
 )
 
-if (ETCD_CMD)
-    add_runtime(pubsub_test_udpmc_runtime
-        NAME udpmc
-        GROUP test/pubsub
-        DEPLOYMENTS
-            pubsub_udpmc_sut
-            pubsub_udpmc_tst
-        COMMANDS
-            etcd
-        WAIT_FOR
-            pubsub_udpmc_tst
-        LOG_TO_FILES
-        #USE_TERM
-    )
-    add_test(NAME pubsub_udpmc_test
-	    COMMAND $<TARGET_PROPERTY:pubsub_test_udpmc_runtime,RUNTIME_LOC>/start.sh
-    )
-
-    add_runtime(pubsub_test_zmq_runtime
-        NAME zmq
-        GROUP test/pubsub
-        DEPLOYMENTS
-            pubsub_zmq_sut
-            pubsub_zmq_tst
-        COMMANDS
-            etcd
-        ARGUMENTS
-            pubsub_zmq_tst "-o junit"
-        WAIT_FOR
-            pubsub_zmq_tst
-        LOG_TO_FILES
-        #USE_TERM
-    )
-    add_test(NAME pubsub_zmq_test
-	    COMMAND $<TARGET_PROPERTY:pubsub_test_zmq_runtime,RUNTIME_LOC>/start.sh
-    )
-endif ()
+add_celix_container(pubsub_zmq_tests
+        GEN_BUNDLES_CONFIG #ensures that a config.properties will be created with the launch bundles.
+        LAUNCHER_SRC ${CMAKE_CURRENT_LIST_DIR}/test/test_runner.cc
+        PROPERTIES
+            LOGHELPER_STDOUT_FALLBACK_INCLUDE_DEBUG=true
+)
+target_link_libraries(pubsub_zmq_tests PRIVATE Celix::framework Celix::pubsub_api ${CPPUTEST_LIBRARIES} ${JANSSON_LIBRARIES} Celix::dfi)
+target_include_directories(pubsub_zmq_tests PRIVATE ${CPPUTEST_INCLUDE_DIR})
+celix_container_bundles(pubsub_zmq_tests
+        Celix::pubsub_serializer_json
+        Celix::pubsub_topology_manager
+        Celix::pubsub_admin_zmq
+        pubsub_sut
+        pubsub_tst
+        Celix::shell
+        Celix::shell_tui
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/test/meta_data/msg.descriptor
----------------------------------------------------------------------
diff --git a/bundles/pubsub/test/meta_data/msg.descriptor b/bundles/pubsub/test/meta_data/msg.descriptor
new file mode 100644
index 0000000..0eb28cb
--- /dev/null
+++ b/bundles/pubsub/test/meta_data/msg.descriptor
@@ -0,0 +1,9 @@
+:header
+type=message
+name=msg
+version=1.0.0
+:annotations
+classname=org.example.Msg
+:types
+:message
+{i seqnR}

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/test/meta_data/ping.properties
----------------------------------------------------------------------
diff --git a/bundles/pubsub/test/meta_data/ping.properties b/bundles/pubsub/test/meta_data/ping.properties
new file mode 100644
index 0000000..3a99403
--- /dev/null
+++ b/bundles/pubsub/test/meta_data/ping.properties
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+pubsub.admin=zmq
+zmq.static.bind.url=ipc:///tmp/pubsub-pingtest
+zmq.static.connect.urls=ipc:///tmp/pubsub-pingtest
+

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/test/msg_descriptors/msg.descriptor
----------------------------------------------------------------------
diff --git a/bundles/pubsub/test/msg_descriptors/msg.descriptor b/bundles/pubsub/test/msg_descriptors/msg.descriptor
deleted file mode 100644
index 0eb28cb..0000000
--- a/bundles/pubsub/test/msg_descriptors/msg.descriptor
+++ /dev/null
@@ -1,9 +0,0 @@
-:header
-type=message
-name=msg
-version=1.0.0
-:annotations
-classname=org.example.Msg
-:types
-:message
-{i seqnR}

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/test/msg_descriptors/sync.descriptor
----------------------------------------------------------------------
diff --git a/bundles/pubsub/test/msg_descriptors/sync.descriptor b/bundles/pubsub/test/msg_descriptors/sync.descriptor
deleted file mode 100644
index 529ba71..0000000
--- a/bundles/pubsub/test/msg_descriptors/sync.descriptor
+++ /dev/null
@@ -1,9 +0,0 @@
-:header
-type=message
-name=sync
-version=1.0.0
-:annotations
-classname=org.example.Sync
-:types
-:message
-{F nop}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/test/test/sut_activator.c
----------------------------------------------------------------------
diff --git a/bundles/pubsub/test/test/sut_activator.c b/bundles/pubsub/test/test/sut_activator.c
index 717b540..ca55cef 100644
--- a/bundles/pubsub/test/test/sut_activator.c
+++ b/bundles/pubsub/test/test/sut_activator.c
@@ -20,96 +20,107 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <constants.h>
+#include <unistd.h>
 
-#include "bundle_activator.h"
-#include "service_tracker.h"
-
-#include "pubsub/subscriber.h"
-#include "pubsub/publisher.h"
-
-static int sut_receive(void *handle, const char *msgType, unsigned int msgTypeId, void *msg, pubsub_multipart_callbacks_t *callbacks, bool *release);
-static int sut_pubAdded(void *handle, service_reference_pt reference, void *service);
-static int sut_pubRemoved(void *handle, service_reference_pt reference, void *service);
+#include "celix_api.h"
+#include "pubsub/api.h"
+#include "msg.h"
 
+static void sut_pubAdded(void *handle, void *service);
+static void sut_pubRemoved(void *handle, void *service);
+static void* sut_sendThread(void *data);
 
 struct activator {
-	pubsub_subscriber_t subSvc;
-	service_registration_pt reg;
+	long pubTrkId;
 
-	service_tracker_pt tracker;
+	pthread_t sendThread;
 
 	pthread_mutex_t mutex;
+	bool running;
 	pubsub_publisher_t* pubSvc;
 };
 
-celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
-	struct activator* act = malloc(sizeof(*act));
-	*userData = act;
-	return CELIX_SUCCESS;
-}
-
-celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
-	struct activator* act = (struct activator*) userData;
-
-	properties_pt props = properties_create();
-	properties_set(props, "pubsub.topic", "ping");
-	act->subSvc.handle = act;
-	act->subSvc.receive = sut_receive;
-	act->reg = NULL;
-	bundleContext_registerService(context, PUBSUB_SUBSCRIBER_SERVICE_NAME, &act->subSvc, props, &act->reg);
+celix_status_t bnd_start(struct activator *act, celix_bundle_context_t *ctx) {
 
 	char filter[512];
-	snprintf(filter, 512, "(&(%s=%s)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, PUBSUB_PUBLISHER_SERVICE_NAME, PUBSUB_PUBLISHER_TOPIC, "pong");
-
-	service_tracker_customizer_pt customizer = NULL;
-	serviceTrackerCustomizer_create(act, NULL, sut_pubAdded, NULL, sut_pubRemoved, &customizer);
-	serviceTracker_createWithFilter(context, filter, customizer, &act->tracker);
-	serviceTracker_open(act->tracker);
-
-	return CELIX_SUCCESS;
-}
-
-celix_status_t bundleActivator_stop(void * userData, bundle_context_pt __attribute__((unused)) context) {
-	struct activator* act = userData;
-	serviceTracker_close(act->tracker);
-	return CELIX_SUCCESS;
-}
+	snprintf(filter, 512, "(%s=%s)", PUBSUB_PUBLISHER_TOPIC, "ping");
+	celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
+	opts.add = sut_pubAdded;
+	opts.remove = sut_pubRemoved;
+	opts.callbackHandle = act;
+	opts.filter.serviceName = PUBSUB_PUBLISHER_SERVICE_NAME;
+	opts.filter.filter = filter;
+	opts.filter.ignoreServiceLanguage = true;
+	act->pubTrkId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
+
+	act->running = true;
+	pthread_create(&act->sendThread, NULL, sut_sendThread, act);
 
-celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt  __attribute__((unused)) context) {
-	struct activator* act = userData;
-	serviceTracker_destroy(act->tracker);
 	return CELIX_SUCCESS;
 }
 
-static int sut_receive(void *handle, const char *msgType, unsigned int msgTypeId, void *msg, pubsub_multipart_callbacks_t *callbacks, bool *release) {
-	struct activator* act = handle;
-	printf("Received msg '%s', sending back\n", msgType);
+celix_status_t bnd_stop(struct activator *act, celix_bundle_context_t *ctx) {
 	pthread_mutex_lock(&act->mutex);
-	if (act->pubSvc != NULL) {
-		unsigned int sendId = 0;
-		act->pubSvc->localMsgTypeIdForMsgType(act->pubSvc->handle, msgType, &sendId);
-		act->pubSvc->send(act->pubSvc->handle, sendId, msg);
-	}
+	act->running = false;
 	pthread_mutex_unlock(&act->mutex);
+	pthread_join(act->sendThread, NULL);
+	pthread_mutex_destroy(&act->mutex);
+
+	celix_bundleContext_stopTracker(ctx, act->pubTrkId);
 	return CELIX_SUCCESS;
 }
 
-static int sut_pubAdded(void *handle, service_reference_pt reference, void *service) {
+CELIX_GEN_BUNDLE_ACTIVATOR(struct activator, bnd_start, bnd_stop);
+
+static void sut_pubAdded(void *handle, void *service) {
 	struct activator* act = handle;
 	pthread_mutex_lock(&act->mutex);
 	act->pubSvc = service;
 	pthread_mutex_unlock(&act->mutex);
-	return CELIX_SUCCESS;
-
 }
 
-static int sut_pubRemoved(void *handle, service_reference_pt reference, void *service) {
+static void sut_pubRemoved(void *handle, void *service) {
 	struct activator* act = handle;
 	pthread_mutex_lock(&act->mutex);
 	if (act->pubSvc == service) {
 		act->pubSvc = NULL;
 	}
 	pthread_mutex_unlock(&act->mutex);
-	return CELIX_SUCCESS;
 }
 
+static void* sut_sendThread(void *data) {
+	struct activator *act = data;
+	pthread_mutex_lock(&act->mutex);
+	bool running = act->running;
+	pthread_mutex_unlock(&act->mutex);
+
+	unsigned int msgId = 0;
+	msg_t msg;
+	msg.seqNr = 1;
+
+	while (running) {
+		pthread_mutex_lock(&act->mutex);
+
+		if (act->pubSvc != NULL) {
+		    if (msgId == 0) {
+		        act->pubSvc->localMsgTypeIdForMsgType(act->pubSvc->handle, MSG_NAME, &msgId);
+		    }
+
+		    printf("TODO enable send again -> assert fail in zmsg_send");
+			act->pubSvc->send(act->pubSvc->handle, msgId, &msg);
+            if (msg.seqNr % 1000 == 0) {
+                printf("Send %i messages\n", msg.seqNr);
+            }
+
+		    msg.seqNr += 1;
+
+
+            usleep(10000000);
+        }
+
+		running = act->running;
+		pthread_mutex_unlock(&act->mutex);
+	}
+
+	return NULL;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/test/test/sync.h
----------------------------------------------------------------------
diff --git a/bundles/pubsub/test/test/sync.h b/bundles/pubsub/test/test/sync.h
deleted file mode 100644
index 0f047ca..0000000
--- a/bundles/pubsub/test/test/sync.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef SYNC_H
-#define SYNC_H
-
-#define SYNC_NAME "sync"
-
-typedef struct sync {
-    float nop; //need at least one entry
-} sync_t;
-
-#endif //SYNC_H

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/test/test/test_runner.cc
----------------------------------------------------------------------
diff --git a/bundles/pubsub/test/test/test_runner.cc b/bundles/pubsub/test/test/test_runner.cc
new file mode 100644
index 0000000..b5a2187
--- /dev/null
+++ b/bundles/pubsub/test/test/test_runner.cc
@@ -0,0 +1,18 @@
+#include "celix_api.h"
+
+
+#include <CppUTest/TestHarness.h>
+#include <CppUTest/CommandLineTestRunner.h>
+
+int main(int argc, char **argv) {
+    celix_framework_t *fw = NULL;
+    celixLauncher_launch("config.properties", &fw);
+
+    int rc = RUN_ALL_TESTS(argc, argv);
+
+    celixLauncher_stop(fw);
+    celixLauncher_waitForShutdown(fw);
+    celixLauncher_destroy(fw);
+
+    return rc;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/test/test/tst_activator.cc
----------------------------------------------------------------------
diff --git a/bundles/pubsub/test/test/tst_activator.cc b/bundles/pubsub/test/test/tst_activator.cc
new file mode 100644
index 0000000..b63edf0
--- /dev/null
+++ b/bundles/pubsub/test/test/tst_activator.cc
@@ -0,0 +1,110 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "celix_api.h"
+#include "pubsub/api.h"
+
+#include "msg.h"
+
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+#include <constants.h>
+
+extern "C" {
+
+static int tst_receive(void *handle, const char *msgType, unsigned int msgTypeId, void *msg, bool *release);
+
+struct activator {
+    pubsub_subscriber_t subSvc{};
+    long subSvcId;
+
+    pthread_mutex_t mutex;
+    unsigned int count = 0;
+};
+
+static struct activator *g_act = NULL; //global
+
+celix_status_t bnd_start(struct activator *act, celix_bundle_context_t *ctx) {
+    pthread_mutex_init(&act->mutex, NULL);
+
+    celix_properties_t *props = celix_properties_create();
+    celix_properties_set(props, PUBSUB_SUBSCRIBER_TOPIC, "ping");
+    act->subSvc.handle = &g_act;
+    act->subSvc.receive = tst_receive;
+    act->subSvcId = celix_bundleContext_registerService(ctx, &act->subSvc, PUBSUB_SUBSCRIBER_SERVICE_NAME, props);
+
+    g_act = act;
+
+    return CELIX_SUCCESS;
+}
+
+celix_status_t bnd_stop(struct activator *act, celix_bundle_context_t *ctx) {
+    celix_bundleContext_unregisterService(ctx, act->subSvcId);
+    pthread_mutex_destroy(&act->mutex);
+    return CELIX_SUCCESS;
+}
+
+CELIX_GEN_BUNDLE_ACTIVATOR(struct activator, bnd_start, bnd_stop) ;
+
+
+static int tst_receive(void *handle, const char * /*msgType*/, unsigned int /*msgTypeId*/, void * /*msg*/, bool * /*release*/) {
+    struct activator *act = static_cast<struct activator *>(handle);
+    pthread_mutex_lock(&act->mutex);
+    act->count += 1;
+    pthread_mutex_unlock(&act->mutex);
+    return CELIX_SUCCESS;
+}
+
+} //end extern C
+
+TEST_GROUP(PUBSUB_INT_GROUP)
+{
+	void setup() {
+	    //nop
+	}
+
+	void teardown() {
+		//nop
+	}
+};
+
+TEST(PUBSUB_INT_GROUP, recvTest) {
+    constexpr int TRIES = 25;
+    constexpr int TIMEOUT = 250000;
+
+    int count = 0;
+
+    for (int i = 0; i < TRIES; ++i) {
+        pthread_mutex_lock(&g_act->mutex);
+        count = g_act->count;
+        pthread_mutex_unlock(&g_act->mutex);
+        printf("Current msg count is %i\n", count);
+        if (count >= 100) {
+            break;
+        }
+        usleep(TIMEOUT);
+    }
+    CHECK(count >= 100);
+
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/bundles/pubsub/test/test/tst_activator.cpp
----------------------------------------------------------------------
diff --git a/bundles/pubsub/test/test/tst_activator.cpp b/bundles/pubsub/test/test/tst_activator.cpp
deleted file mode 100644
index 04be892..0000000
--- a/bundles/pubsub/test/test/tst_activator.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "bundle_activator.h"
-#include "service_tracker.h"
-
-#include "pubsub/subscriber.h"
-#include "pubsub/publisher.h"
-
-#include "msg.h"
-#include "sync.h"
-
-#include <CppUTest/TestHarness.h>
-#include <CppUTestExt/MockSupport.h>
-#include <constants.h>
-
-
-static int tst_receive(void *handle, const char *msgType, unsigned int msgTypeId, void *msg, pubsub_multipart_callbacks_t *callbacks, bool *release);
-static int tst_pubAdded(void *handle, service_reference_pt reference, void *service);
-static int tst_pubRemoved(void *handle, service_reference_pt reference, void *service);
-
-struct activator {
-	pubsub_subscriber_t subSvc{};
-	service_registration_pt reg = nullptr;
-
-	service_tracker_pt tracker = nullptr;
-
-	pthread_mutex_t mutex{}; //protects below
-	pubsub_publisher_t* pubSvc = nullptr;
-
-    unsigned int syncId = 0;
-    bool gotSync = 0;
-
-    unsigned int msgId = 0;
-    unsigned int count = 0;
-
-    bool started = false;
-
-};
-
-static struct activator g_act; //global
-
-celix_status_t bundleActivator_create(__attribute__((unused)) bundle_context_pt context, __attribute__((unused)) void **userData) {
-    //memset(&g_act, 0, sizeof(g_act));
-	return CELIX_SUCCESS;
-}
-
-celix_status_t bundleActivator_start(__attribute__((unused)) void * userData, bundle_context_pt context) {
-	properties_pt props = properties_create();
-	properties_set(props, "pubsub.topic", "pong");
-	g_act.subSvc.handle = &g_act;
-	g_act.subSvc.receive = tst_receive;
-	bundleContext_registerService(context, PUBSUB_SUBSCRIBER_SERVICE_NAME, &g_act.subSvc, props, &g_act.reg);
-
-    char filter[512];
-    snprintf(filter, 512, "(&(%s=%s)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, PUBSUB_PUBLISHER_SERVICE_NAME, PUBSUB_PUBLISHER_TOPIC, "ping");
-
-    service_tracker_customizer_pt customizer = NULL;
-	serviceTrackerCustomizer_create(&g_act, NULL, tst_pubAdded, NULL, tst_pubRemoved, &customizer);
-	serviceTracker_createWithFilter(context, filter, customizer, &g_act.tracker);
-	serviceTracker_open(g_act.tracker);
-
-    g_act.started = true;
-
-	return CELIX_SUCCESS;
-}
-
-celix_status_t bundleActivator_stop(__attribute__((unused)) void * userData, bundle_context_pt __attribute__((unused)) context) {
-	serviceTracker_close(g_act.tracker);
-	return CELIX_SUCCESS;
-}
-
-celix_status_t bundleActivator_destroy(__attribute__((unused)) void * userData, bundle_context_pt  __attribute__((unused)) context) {
-	serviceTracker_destroy(g_act.tracker);
-	return CELIX_SUCCESS;
-}
-
-static int tst_receive(void *handle, const char * /*msgType*/, unsigned int msgTypeId, void * /*msg*/, pubsub_multipart_callbacks_t* /*callbacks*/, bool* /*release*/) {
-	struct activator* act = static_cast<struct activator*>(handle);
-    pthread_mutex_lock(&act->mutex);
-    if (msgTypeId == act->syncId) {
-        act->gotSync = true;
-    } else if (msgTypeId == act->msgId) {
-        act->count += 1;
-    }
-    pthread_mutex_unlock(&act->mutex);
-	return CELIX_SUCCESS;
-}
-
-static int tst_pubAdded(void *handle, service_reference_pt /*reference*/, void *service) {
-    struct activator* act = static_cast<struct activator*>(handle);
-    pthread_mutex_lock(&act->mutex);
-	act->pubSvc = static_cast<pubsub_publisher_t*>(service);
-    act->pubSvc->localMsgTypeIdForMsgType(act->pubSvc->handle, MSG_NAME, &act->msgId);
-    act->pubSvc->localMsgTypeIdForMsgType(act->pubSvc->handle, SYNC_NAME, &act->syncId);
-
-	pthread_mutex_unlock(&act->mutex);
-	return CELIX_SUCCESS;
-
-}
-
-static int tst_pubRemoved(void *handle, service_reference_pt /*reference*/, void *service) {
-    struct activator* act = static_cast<struct activator*>(handle);
-    pthread_mutex_lock(&act->mutex);
-	if (act->pubSvc == service) {
-		act->pubSvc = NULL;
-	}
-	pthread_mutex_unlock(&act->mutex);
-	return CELIX_SUCCESS;
-}
-
-
-TEST_GROUP(PUBSUB_INT_GROUP)
-{
-	void setup() {
-        constexpr int TRIES = 25;
-        constexpr int TIMEOUT = 250000;
-
-        pthread_mutex_lock(&g_act.mutex);
-		CHECK_EQUAL(true, g_act.started);
-        g_act.gotSync = false;
-        pthread_mutex_unlock(&g_act.mutex);
-
-        //check if publisher is available
-        unsigned int syncId = 0;
-        for (int i = 0; i < TRIES; ++i) {
-            pthread_mutex_lock(&g_act.mutex);
-            syncId = g_act.syncId;
-            pthread_mutex_unlock(&g_act.mutex);
-            if (syncId == 0) {
-                printf("publisher still nullptr / sync msg type id is still 0, waiting for a while\n");
-                usleep(TIMEOUT);
-            } else {
-                break;
-            }
-        }
-        CHECK(syncId != 0);
-
-        //check if message are returned
-        sync_t syncMsg;
-        bool gotSync = false;
-        for (int i = 0; i < TRIES; ++i) {
-            printf("Sending sync message. Try %d/%d\n", i+1, TRIES);
-            pthread_mutex_lock(&g_act.mutex);
-            g_act.pubSvc->send(g_act.pubSvc->handle, g_act.syncId, &syncMsg);
-            pthread_mutex_unlock(&g_act.mutex);
-            usleep(TIMEOUT);
-            pthread_mutex_lock(&g_act.mutex);
-            gotSync = g_act.gotSync;
-            pthread_mutex_unlock(&g_act.mutex);
-            if (gotSync) {
-                break;
-            }
-        }
-        if (!gotSync) {
-            printf("No sync message received, bailing\n");
-        }
-        CHECK(gotSync);
-	}
-
-	void teardown() {
-		//nop
-	}
-};
-
-TEST(PUBSUB_INT_GROUP, sendRecvTest) {
-    pthread_mutex_lock(&g_act.mutex);
-    g_act.count = 0; //reset counter
-    pthread_mutex_unlock(&g_act.mutex);
-
-    constexpr int COUNT = 50;
-    msg_t msg;
-    for (int i = 0; i < COUNT; ++i) {
-        msg.seqNr = i+1;
-        printf("Sending test msg %d of %d\n", i+1, COUNT);
-        pthread_mutex_lock(&g_act.mutex);
-        g_act.pubSvc->send(g_act.pubSvc->handle, g_act.msgId, &msg);
-        pthread_mutex_unlock(&g_act.mutex);
-        usleep(100000);
-    }
-
-    constexpr int TRIES = 25;
-    constexpr int TIMEOUT = 250000;
-    for (int i = 0; i < TRIES; ++i) {
-        pthread_mutex_lock(&g_act.mutex);
-        int count = g_act.count;
-        pthread_mutex_unlock(&g_act.mutex);
-        if (count == COUNT) {
-            break;
-        } else {
-            printf("Current count is %i, should be %i. Waiting a little\n", count, COUNT);
-            usleep(TIMEOUT);
-        }
-    }
-
-    pthread_mutex_lock(&g_act.mutex);
-    int count = g_act.count;
-    pthread_mutex_unlock(&g_act.mutex);
-    CHECK_EQUAL(COUNT, count);
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/cmake/cmake_celix/ContainerPackaging.cmake
----------------------------------------------------------------------
diff --git a/cmake/cmake_celix/ContainerPackaging.cmake b/cmake/cmake_celix/ContainerPackaging.cmake
index 4c4e967..fa76763 100644
--- a/cmake/cmake_celix/ContainerPackaging.cmake
+++ b/cmake/cmake_celix/ContainerPackaging.cmake
@@ -37,7 +37,7 @@ function(add_celix_container)
     list(GET ARGN 0 CONTAINER_TARGET)
     list(REMOVE_AT ARGN 0)
 
-    set(OPTIONS COPY CXX)
+    set(OPTIONS COPY CXX GEN_BUNDLES_CONFIG)
     set(ONE_VAL_ARGS GROUP NAME LAUNCHER LAUNCHER_SRC DIR)
     set(MULTI_VAL_ARGS BUNDLES PROPERTIES EMBEDDED_PROPERTIES RUNTIME_PROPERTIES)
     cmake_parse_arguments(CONTAINER "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
@@ -79,9 +79,7 @@ function(add_celix_container)
         get_filename_component(SRC_FILENAME ${CONTAINER_LAUNCHER_SRC} NAME)
         set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/containers/${CONTAINER_TARGET}/${SRC_FILENAME}")
         set(LAUNCHER_ORG "${CONTAINER_LAUNCHER_SRC}")
-        add_custom_command(OUTPUT ${LAUNCHER_SRC}
-                COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LAUNCHER_ORG} ${LAUNCHER_SRC}
-        )
+        file(GENERATE OUTPUT "${LAUNCHER_SRC}" INPUT "${LAUNCHER_ORG}")
     else () #generate custom launcher
         if (CONTAINER_CXX)
             set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/containers/${CONTAINER_TARGET}/main.cc")
@@ -132,18 +130,37 @@ $<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_EMBEDDED_PROPERTIES>,\\n\
     #generate config.properties. C
     set(CONTAINER_PROPS "${CONTAINER_LOC}/config.properties")
     set(STAGE1_PROPERTIES "${PROJECT_BINARY_DIR}/celix/gen/containers/${CONTAINER_TARGET}/container-config-stage1.properties")
-    file(GENERATE 
-        OUTPUT "${STAGE1_PROPERTIES}"
-        CONTENT "$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_RUNTIME_PROPERTIES>,
+    if (CONTAINER_GEN_BUNDLES_CONFIG)
+        file(GENERATE
+            OUTPUT "${STAGE1_PROPERTIES}"
+            CONTENT "$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_RUNTIME_PROPERTIES>,
+>
+CELIX_AUTO_START_0=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_0>, >
+CELIX_AUTO_START_1=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_1>, >
+CELIX_AUTO_START_2=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_2>, >
+CELIX_AUTO_START_3=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_3>, >
+CELIX_AUTO_START_4=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_4>, >
+CELIX_AUTO_START_5=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_5>, >
+CELIX_AUTO_START_6=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_6>, >"
+        )
+        file(GENERATE
+            OUTPUT "${CONTAINER_PROPS}"
+            INPUT "${STAGE1_PROPERTIES}"
+        )
+    else ()
+        file(GENERATE
+            OUTPUT "${STAGE1_PROPERTIES}"
+            CONTENT "$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_RUNTIME_PROPERTIES>,
 >
 "
-    )
-    #Condition is there so that config.properties file will only be generated if there are runtime properties
-    file(GENERATE
-        OUTPUT "${CONTAINER_PROPS}"
-        INPUT "${STAGE1_PROPERTIES}"
-        CONDITION $<NOT:$<STREQUAL:,$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_RUNTIME_PROPERTIES>>>
-    )
+        )
+        #Condition is there so that config.properties file will only be generated if there are runtime properties
+        file(GENERATE
+                OUTPUT "${CONTAINER_PROPS}"
+                INPUT "${STAGE1_PROPERTIES}"
+                CONDITION $<NOT:$<STREQUAL:,$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_RUNTIME_PROPERTIES>>>
+        )
+    endif ()
 
     #needed in the release.sh & run.sh files
     #Setting CELIX_LIB_DIRS, CELIX_BIN_DIR and CELIX_LAUNCHER
@@ -294,7 +311,7 @@ function(celix_container_bundles)
     set(BUNDLES_LIST ${BUNDLES_UNPARSED_ARGUMENTS})
 
     if (NOT DEFINED BUNDLES_LEVEL)
-        set(BUNDLES_LEVEL 1)
+        set(BUNDLES_LEVEL 3)
     endif ()
 
     get_target_property(BUNDLES ${CONTAINER_TARGET} "CONTAINER_BUNDLES_LEVEL_${BUNDLES_LEVEL}")

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/cmake/cmake_celix/runtime_common.sh.in
----------------------------------------------------------------------
diff --git a/cmake/cmake_celix/runtime_common.sh.in b/cmake/cmake_celix/runtime_common.sh.in
index 7c4be1d..32d3c33 100644
--- a/cmake/cmake_celix/runtime_common.sh.in
+++ b/cmake/cmake_celix/runtime_common.sh.in
@@ -92,7 +92,9 @@ function rt_run_deployment() {
         echo "  Clearing cache"
         rm -fr .cache
     fi
-    . ./release.sh #run deployment release
+    if [ -e release.sh ] ; then
+        . ./release.sh #run deployment release
+    fi
     echo "  Workdir: ${CONTAINERS_DIR}"
     echo "  Cmd used: '${DEBUG_OPTS} ./${DEPLOYMENT} ${ARGS}'"
     if [ "${USE_TERM}" = "TRUE" ] ; then

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/libs/framework/include/celix_bundle_activator.h
----------------------------------------------------------------------
diff --git a/libs/framework/include/celix_bundle_activator.h b/libs/framework/include/celix_bundle_activator.h
index eb7d514..75e34d2 100644
--- a/libs/framework/include/celix_bundle_activator.h
+++ b/libs/framework/include/celix_bundle_activator.h
@@ -115,7 +115,7 @@ celix_status_t celix_bundleActivator_destroy(void *userData, celix_bundle_contex
 #define CELIX_GEN_BUNDLE_ACTIVATOR(actType, actStart, actStop)                                                         \
 celix_status_t celix_bundleActivator_create(celix_bundle_context_t *ctx __attribute__((unused)), void **userData) {    \
     celix_status_t status = CELIX_SUCCESS;                                                                             \
-    actType *data = calloc(1, sizeof(*data));                                                                          \
+    actType *data = (actType*)calloc(1, sizeof(*data));                                                                          \
     if (data != NULL) {                                                                                                \
         *userData = data;                                                                                              \
     } else {                                                                                                           \

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/libs/framework/include/celix_log.h
----------------------------------------------------------------------
diff --git a/libs/framework/include/celix_log.h b/libs/framework/include/celix_log.h
index 08d096c..4c1d631 100644
--- a/libs/framework/include/celix_log.h
+++ b/libs/framework/include/celix_log.h
@@ -57,7 +57,9 @@ struct framework_logger {
 };
 
 #define fw_log(logger, level, fmsg, args...) framework_log(logger, level, __func__, __FILE__, __LINE__, fmsg, ## args)
+
 #define fw_logCode(logger, level, code, fmsg, args...) framework_logCode(logger, level, __func__, __FILE__, __LINE__, code, fmsg, ## args)
+
 #define framework_logIfError(logger, status, error, fmsg, args...) \
     if (status != CELIX_SUCCESS) { \
         if (error != NULL) { \

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/libs/framework/src/bundle.c
----------------------------------------------------------------------
diff --git a/libs/framework/src/bundle.c b/libs/framework/src/bundle.c
index 6d605d7..4244182 100644
--- a/libs/framework/src/bundle.c
+++ b/libs/framework/src/bundle.c
@@ -32,7 +32,7 @@ celix_status_t bundle_create(bundle_pt * bundle) {
     celix_status_t status;
     bundle_archive_pt archive = NULL;
 
-	*bundle = (bundle_pt) malloc(sizeof(**bundle));
+	*bundle = (bundle_pt) calloc(1, sizeof(**bundle));
 	if (*bundle == NULL) {
 		return CELIX_ENOMEM;
 	}
@@ -64,7 +64,7 @@ celix_status_t bundle_createFromArchive(bundle_pt * bundle, framework_pt framewo
 	
 	celix_status_t status;
 
-	*bundle = (bundle_pt) malloc(sizeof(**bundle));
+	*bundle = (bundle_pt) calloc(1, (sizeof(**bundle)));
 	if (*bundle == NULL) {
 		return CELIX_ENOMEM;
 	}
@@ -395,6 +395,7 @@ celix_status_t bundle_revise(bundle_pt bundle, const char * location, const char
 celix_status_t bundle_addModule(bundle_pt bundle, module_pt module) {
 	arrayList_add(bundle->modules, module);
 	resolver_addModule(module);
+	module_getSymbolicName(module, &bundle->_symbolicName);
 	return CELIX_SUCCESS;
 }
 

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/libs/framework/src/bundle_context.c
----------------------------------------------------------------------
diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c
index 83503a5..03fe1a0 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -500,8 +500,7 @@ void celix_bundleContext_unregisterService(bundle_context_t *ctx, long serviceId
         if (found != NULL) {
             serviceRegistration_unregister(found);
         } else {
-            framework_logIfError(logger, CELIX_ILLEGAL_ARGUMENT, NULL,
-                                 "Provided service id is not used to registered using bundleContext_registerCService/registerServiceForLang");
+            framework_logIfError(logger, CELIX_ILLEGAL_ARGUMENT, NULL, "Provided service id (%li) is not used to registered using celix_bundleContext_registerCService/celix_registerServiceForLang". serviceId);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/libs/framework/src/bundle_private.h
----------------------------------------------------------------------
diff --git a/libs/framework/src/bundle_private.h b/libs/framework/src/bundle_private.h
index 82bf391..b4f9cba 100644
--- a/libs/framework/src/bundle_private.h
+++ b/libs/framework/src/bundle_private.h
@@ -27,6 +27,8 @@
 
 
 struct bundle {
+	const char *_symbolicName; //present to make debugging easier
+
 	bundle_context_pt context;
 	struct celix_bundle_activator *activator;
 	bundle_state_e state;

http://git-wip-us.apache.org/repos/asf/celix/blob/ec7fdcff/libs/framework/src/celix_log.c
----------------------------------------------------------------------
diff --git a/libs/framework/src/celix_log.c b/libs/framework/src/celix_log.c
index c4d51e2..df38b34 100644
--- a/libs/framework/src/celix_log.c
+++ b/libs/framework/src/celix_log.c
@@ -16,18 +16,32 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * celix_log.c
- *
- *  \date       6 Oct 2013
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
 #include <stdarg.h>
 
 #include "celix_errno.h"
 #include "celix_log.h"
 
+#ifdef __linux__
+//includes for the backtrace function
+#include <execinfo.h>
+#include <stdlib.h>
+#endif
+
+#ifdef __linux__
+static void framework_logBacktrace(void) {
+    void *bbuf[64];
+    int nrOfTraces = backtrace(bbuf, 64);
+    char **lines = backtrace_symbols(bbuf, nrOfTraces);
+    for (int i = 0; i < nrOfTraces; ++i) {
+        char *line = lines[i];
+        fprintf(stderr, "%s\n", line);
+    }
+    free(lines);
+}
+#else
+static void framework_logBacktrace(void) {}
+#endif
+
 void framework_log(framework_logger_pt logger, framework_log_level_t level, const char *func, const char *file, int line, const char *fmsg, ...) {
     char msg[512];
     va_list listPointer;
@@ -74,7 +88,8 @@ celix_status_t frameworkLogger_log(framework_log_level_t level, const char *func
     }
 
     if (level == OSGI_FRAMEWORK_LOG_ERROR) {
-        printf("%s: %s\n\tat %s(%s:%d)\n", levelStr, msg, func, file, line);
+        fprintf(stderr, "%s: %s\n\tat %s(%s:%d)\n", levelStr, msg, func, file, line);
+        framework_logBacktrace();
     } else {
         printf("%s: %s\n", levelStr, msg);
     }