You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by bp...@apache.org on 2015/12/19 10:01:01 UTC

celix git commit: CELIX-329: fix framework service_registry tests

Repository: celix
Updated Branches:
  refs/heads/develop bc5930a03 -> fddc16c04


CELIX-329: fix framework service_registry tests


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

Branch: refs/heads/develop
Commit: fddc16c04d5bad5a0f230e15156a393c2d37d955
Parents: bc5930a
Author: Bjoern Petri <bp...@apache.org>
Authored: Sat Dec 19 10:00:11 2015 +0100
Committer: Bjoern Petri <bp...@apache.org>
Committed: Sat Dec 19 10:00:11 2015 +0100

----------------------------------------------------------------------
 .../private/include/service_registry_private.h  |   2 +-
 framework/private/mock/service_registry_mock.c  |  58 --
 framework/private/src/service_registry.c        |  35 +-
 .../private/test/service_reference_test.cpp     | 582 ++++++++++++++--
 .../private/test/service_registry_test.cpp      | 697 +++++++++++++------
 framework/private/test/service_tracker_test.cpp | 106 ++-
 framework/public/include/service_registry.h     |   3 -
 7 files changed, 1142 insertions(+), 341 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/fddc16c0/framework/private/include/service_registry_private.h
----------------------------------------------------------------------
diff --git a/framework/private/include/service_registry_private.h b/framework/private/include/service_registry_private.h
index 28c6148..8726ff7 100644
--- a/framework/private/include/service_registry_private.h
+++ b/framework/private/include/service_registry_private.h
@@ -35,7 +35,7 @@ struct serviceRegistry {
 	framework_pt framework;
 	registry_callback_t callback;
 
-	hash_map_pt serviceRegistrations; //key = bundle (reg owner), value = registration
+	hash_map_pt serviceRegistrations; //key = bundle (reg owner), value = list ( registration )
 	hash_map_pt serviceReferences; //key = bundle, value = map (key = registration, value = reference)
 
 	bool checkDeletedReferences; //If enabled. check if provided service references are still valid

http://git-wip-us.apache.org/repos/asf/celix/blob/fddc16c0/framework/private/mock/service_registry_mock.c
----------------------------------------------------------------------
diff --git a/framework/private/mock/service_registry_mock.c b/framework/private/mock/service_registry_mock.c
index 7204942..81be4c5 100644
--- a/framework/private/mock/service_registry_mock.c
+++ b/framework/private/mock/service_registry_mock.c
@@ -86,13 +86,6 @@ celix_status_t serviceRegistry_unregisterService(service_registry_pt registry, b
 	return mock_c()->returnValue().value.intValue;
 }
 
-celix_status_t serviceRegistry_unregisterServices(service_registry_pt registry, bundle_pt bundle) {
-	mock_c()->actualCall("serviceRegistry_unregisterServices")
-			->withPointerParameters("registry", registry)
-			->withPointerParameters("bundle", bundle);
-	return mock_c()->returnValue().value.intValue;
-}
-
 celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry, bundle_pt bundle, const char *serviceName, filter_pt filter, array_list_pt *references) {
 	mock_c()->actualCall("serviceRegistry_getServiceReferences")
 			->withPointerParameters("registry", registry)
@@ -116,13 +109,6 @@ celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registr
 	return mock_c()->returnValue().value.intValue;
 }
 
-celix_status_t serviceRegistry_ungetServiceReferences(service_registry_pt registry, bundle_pt bundle) {
-	mock_c()->actualCall("serviceRegistry_ungetServiceReferences")
-			->withPointerParameters("registry", registry)
-			->withPointerParameters("bundle", bundle);
-	return mock_c()->returnValue().value.intValue;
-}
-
 celix_status_t serviceRegistry_getService(service_registry_pt registry, bundle_pt bundle, service_reference_pt reference, void **service) {
 	mock_c()->actualCall("serviceRegistry_getService")
 		->withPointerParameters("registry", registry)
@@ -140,43 +126,6 @@ celix_status_t serviceRegistry_ungetService(service_registry_pt registry, bundle
 	return mock_c()->returnValue().value.intValue;
 }
 
-void serviceRegistry_ungetServices(service_registry_pt registry, bundle_pt bundle) {
-	mock_c()->actualCall("serviceRegistry_ungetServices")
-			->withPointerParameters("registry", registry)
-			->withPointerParameters("bundle", bundle);
-}
-
-array_list_pt serviceRegistry_getUsingBundles(service_registry_pt registry, service_reference_pt reference) {
-	mock_c()->actualCall("serviceRegistry_getUsingBundles")
-			->withPointerParameters("registry", registry)
-			->withPointerParameters("reference", reference);
-	return mock_c()->returnValue().value.pointerValue;
-}
-
-service_registration_pt serviceRegistry_findRegistration(service_registry_pt registry, service_reference_pt reference) {
-	mock_c()->actualCall("serviceRegistry_findRegistration")
-			->withPointerParameters("registry", registry)
-			->withPointerParameters("reference", reference);
-	return mock_c()->returnValue().value.pointerValue;
-}
-
-celix_status_t serviceRegistry_createServiceReference(service_registry_pt registry, bundle_pt bundle, service_registration_pt registration, service_reference_pt *reference) {
-	mock_c()->actualCall("serviceRegistry_createServiceReference")
-		->withPointerParameters("registry", registry)
-		->withPointerParameters("bundle", bundle)
-		->withPointerParameters("registration", registration)
-		->withOutputParameter("reference", reference);
-	return mock_c()->returnValue().value.intValue;
-}
-
-celix_status_t serviceRegistry_getServiceReferencesForRegistration(service_registry_pt registry, service_registration_pt registration, array_list_pt *references) {
-	mock_c()->actualCall("serviceRegistry_getServiceReferencesForRegistration")
-			->withPointerParameters("registry", registry)
-			->withPointerParameters("registration", registration)
-			->withOutputParameter("references", references);
-	return mock_c()->returnValue().value.intValue;
-}
-
 celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, bundle_pt bundle, array_list_pt *hooks) {
 	mock_c()->actualCall("serviceRegistry_getListenerHooks")
 		->withPointerParameters("registry", registry)
@@ -193,13 +142,6 @@ celix_status_t serviceRegistry_servicePropertiesModified(service_registry_pt reg
 	return mock_c()->returnValue().value.intValue;
 }
 
-celix_status_t serviceRegistry_removeReference(service_reference_pt reference) {
-    mock_c()->actualCall("serviceRegistry_removeReference")
-    		->withPointerParameters("reference", reference);
-    return mock_c()->returnValue().value.intValue;
-}
-
-
 celix_status_t serviceRegistry_getServiceReference(service_registry_pt registry, bundle_pt bundle, service_registration_pt registration, service_reference_pt *reference) {
 	mock_c()->actualCall("serviceRegistry_getServiceReference")
 			->withPointerParameters("registry", registry)

http://git-wip-us.apache.org/repos/asf/celix/blob/fddc16c0/framework/private/src/service_registry.c
----------------------------------------------------------------------
diff --git a/framework/private/src/service_registry.c b/framework/private/src/service_registry.c
index 09fd340..10e4293 100644
--- a/framework/private/src/service_registry.c
+++ b/framework/private/src/service_registry.c
@@ -41,9 +41,9 @@
 #define CHECK_DELETED_REFERENCES true
 #endif
 
-celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, char * serviceName, void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt *registration);
-celix_status_t serviceRegistry_addHooks(service_registry_pt registry, char *serviceName, void *serviceObject, service_registration_pt registration);
-celix_status_t serviceRegistry_removeHook(service_registry_pt registry, service_registration_pt registration);
+static celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, char * serviceName, void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt *registration);
+static celix_status_t serviceRegistry_addHooks(service_registry_pt registry, char *serviceName, void *serviceObject, service_registration_pt registration);
+static celix_status_t serviceRegistry_removeHook(service_registry_pt registry, service_registration_pt registration);
 static void serviceRegistry_logWarningServiceReferenceUsageCount(service_registry_pt registry, size_t usageCount, size_t refCount);
 static void serviceRegistry_logWarningServiceRegistration(service_registry_pt registry, service_registration_pt reg);
 static celix_status_t serviceRegistry_checkReference(service_registry_pt registry, service_reference_pt ref,
@@ -52,7 +52,7 @@ static void serviceRegistry_logIllegalReference(service_registry_pt registry, se
                                                    reference_status_t refStatus);
 static celix_status_t serviceRegistry_setReferenceStatus(service_registry_pt registry, service_reference_pt reference,
                                                   bool deleted);
-static celix_status_t serviceRegistry_getUsingBUndles(service_registry_pt registry, service_registration_pt reg, array_list_pt *bundles);
+static celix_status_t serviceRegistry_getUsingBundles(service_registry_pt registry, service_registration_pt reg, array_list_pt *bundles);
 static celix_status_t serviceRegistry_getServiceReference_internal(service_registry_pt registry, bundle_pt owner, service_registration_pt registration, service_reference_pt *out);
 
 celix_status_t serviceRegistry_create(framework_pt framework, serviceChanged_function_pt serviceChanged, service_registry_pt *out) {
@@ -64,7 +64,7 @@ celix_status_t serviceRegistry_create(framework_pt framework, serviceChanged_fun
 	} else {
 
         reg->callback.handle = reg;
-        reg->callback.getUsingBundles = (void *)serviceRegistry_getUsingBUndles;
+        reg->callback.getUsingBundles = (void *)serviceRegistry_getUsingBundles;
         reg->callback.unregister = (void *) serviceRegistry_unregisterService;
         reg->callback.modified = (void *) serviceRegistry_servicePropertiesModified;
 
@@ -154,7 +154,7 @@ celix_status_t serviceRegistry_registerServiceFactory(service_registry_pt regist
     return serviceRegistry_registerServiceInternal(registry, bundle, serviceName, (void *) factory, dictionary, true, registration);
 }
 
-celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, char * serviceName, void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt *registration) {
+static celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, char * serviceName, void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt *registration) {
 	array_list_pt regs;
 
 	if (isFactory) {
@@ -385,8 +385,8 @@ celix_status_t serviceRegistry_getServiceReferences(service_registry_pt registry
         for (i = 0; i < size; i += 1) {
             service_registration_pt reg = arrayList_get(matchingRegistrations, i);
             service_reference_pt reference = NULL;
-            celix_status_t subStatues = serviceRegistry_getServiceReference(registry, owner, reg, &reference);
-            if (subStatues == CELIX_SUCCESS) {
+            celix_status_t subStatus = serviceRegistry_getServiceReference(registry, owner, reg, &reference);
+            if (subStatus == CELIX_SUCCESS) {
                 arrayList_add(references, reference);
             } else {
                 status = CELIX_BUNDLE_EXCEPTION;
@@ -414,7 +414,7 @@ celix_status_t serviceRegistry_retainServiceReference(service_registry_pt regist
     
     celixThreadRwlock_writeLock(&registry->lock);
     serviceRegistry_checkReference(registry, reference, &refStatus);
-    if (status == REF_ACTIVE) {
+    if (refStatus == REF_ACTIVE) {
         serviceReference_getOwner(reference, &refBundle);
         if (refBundle == bundle) {
             serviceReference_retain(reference);
@@ -488,7 +488,7 @@ celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt registr
     return status;
 }
 
-celix_status_t serviceRegistry_setReferenceStatus(service_registry_pt registry, service_reference_pt reference,
+static celix_status_t serviceRegistry_setReferenceStatus(service_registry_pt registry, service_reference_pt reference,
                                                   bool deleted) {
     //precondition write locked on registry->lock
     if (registry->checkDeletedReferences) {
@@ -503,7 +503,7 @@ static void serviceRegistry_logIllegalReference(service_registry_pt registry __a
            "Error handling service reference %p, status is %i",reference, refStatus);
 }
 
-celix_status_t serviceRegistry_checkReference(service_registry_pt registry, service_reference_pt ref,
+static celix_status_t serviceRegistry_checkReference(service_registry_pt registry, service_reference_pt ref,
                                               reference_status_t *out) {
     //precondition read or write locked on registry->lock
     celix_status_t status = CELIX_SUCCESS;
@@ -524,7 +524,7 @@ celix_status_t serviceRegistry_checkReference(service_registry_pt registry, serv
     return status;
 }
 
-void serviceRegistry_logWarningServiceReferenceUsageCount(service_registry_pt registry __attribute__((unused)), size_t usageCount, size_t refCount) {
+static void serviceRegistry_logWarningServiceReferenceUsageCount(service_registry_pt registry __attribute__((unused)), size_t usageCount, size_t refCount) {
     if (usageCount > 0) {
         fw_log(logger, OSGI_FRAMEWORK_LOG_WARNING, "Service Reference destroyed with usage count is %zu. Look for missing bundleContext_ungetService calls.", usageCount);
     }
@@ -664,7 +664,7 @@ celix_status_t serviceRegistry_ungetService(service_registry_pt registry, bundle
 	return status;
 }
 
-celix_status_t serviceRegistry_addHooks(service_registry_pt registry, char *serviceName, void *serviceObject __attribute__((unused)), service_registration_pt registration) {
+static celix_status_t serviceRegistry_addHooks(service_registry_pt registry, char *serviceName, void *serviceObject __attribute__((unused)), service_registration_pt registration) {
 	celix_status_t status = CELIX_SUCCESS;
 
 	if (strcmp(OSGI_FRAMEWORK_LISTENER_HOOK_SERVICE_NAME, serviceName) == 0) {
@@ -676,7 +676,7 @@ celix_status_t serviceRegistry_addHooks(service_registry_pt registry, char *serv
 	return status;
 }
 
-celix_status_t serviceRegistry_removeHook(service_registry_pt registry, service_registration_pt registration) {
+static celix_status_t serviceRegistry_removeHook(service_registry_pt registry, service_registration_pt registration) {
 	celix_status_t status = CELIX_SUCCESS;
 	char *serviceName = NULL;
 
@@ -733,7 +733,7 @@ celix_status_t serviceRegistry_servicePropertiesModified(service_registry_pt reg
 	return CELIX_SUCCESS;
 }
 
-static celix_status_t serviceRegistry_getUsingBUndles(service_registry_pt registry, service_registration_pt registration, array_list_pt *out) {
+static celix_status_t serviceRegistry_getUsingBundles(service_registry_pt registry, service_registration_pt registration, array_list_pt *out) {
     celix_status_t status;
     array_list_pt bundles = NULL;
     hash_map_iterator_pt iter;
@@ -745,11 +745,12 @@ static celix_status_t serviceRegistry_getUsingBUndles(service_registry_pt regist
         while (hashMapIterator_hasNext(iter)) {
             hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
             bundle_pt registrationUser = hashMapEntry_getKey(entry);
-            service_registration_pt reg = hashMapEntry_getValue(entry);
-            if (registration == reg) {
+            hash_map_pt regMap = hashMapEntry_getValue(entry);
+            if (hashMap_containsKey(regMap, registration)) {
                 arrayList_add(bundles, registrationUser);
             }
         }
+        hashMapIterator_destroy(iter);
         celixThreadRwlock_unlock(&registry->lock);
     }
 

http://git-wip-us.apache.org/repos/asf/celix/blob/fddc16c0/framework/private/test/service_reference_test.cpp
----------------------------------------------------------------------
diff --git a/framework/private/test/service_reference_test.cpp b/framework/private/test/service_reference_test.cpp
index f42cbe3..25165cc 100644
--- a/framework/private/test/service_reference_test.cpp
+++ b/framework/private/test/service_reference_test.cpp
@@ -25,6 +25,7 @@
  */
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "CppUTest/TestHarness.h"
 #include "CppUTest/TestHarness_c.h"
@@ -33,6 +34,8 @@
 
 extern "C" {
 #include "service_reference_private.h"
+#include "service_reference.h"
+#include "constants.h"
 #include "celix_log.h"
 #include "CppUTestExt/MockSupport_c.h"
 
@@ -52,12 +55,29 @@ int main(int argc, char** argv) {
 	return RUN_ALL_TESTS(argc, argv);
 }
 
+static char* my_strdup(const char* s){
+	if(s==NULL){
+		return NULL;
+	}
+
+	size_t len = strlen(s);
+
+	char *d = (char*) calloc (len + 1,sizeof(char));
+
+	if (d == NULL){
+		return NULL;
+	}
+
+	strncpy (d,s,len);
+	return d;
+}
+
+
 TEST_GROUP(service_reference) {
 	void setup(void) {
 	}
 
 	void teardown() {
-		mock().checkExpectations();
 		mock().clear();
 	}
 };
@@ -88,6 +108,159 @@ TEST(service_reference, create) {
 	serviceReference_release(reference, &destroyed);
 
 	CHECK(destroyed);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, retain){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	celixThreadRwlock_create(&reference->lock, NULL);
+	reference->refCount = 1;
+
+    celix_status_t status = serviceReference_retain(reference);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	LONGS_EQUAL(2, reference->refCount);
+
+	celixThreadRwlock_destroy(&reference->lock);
+	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, release){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	celixThreadRwlock_create(&reference->lock, NULL);
+	service_registration_pt registration = (service_registration_pt) 0x20;
+	reference->registration = registration;
+	reference->refCount = 2;
+
+	bool destroyed;
+	celix_status_t status = serviceReference_release(reference, &destroyed);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	CHECK_FALSE(destroyed);
+	LONGS_EQUAL(1, reference->refCount);
+	
+	mock().expectOneCall("serviceRegistration_release")
+			.withParameter("registration", registration);
+	
+	status = serviceReference_release(reference, &destroyed);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	CHECK(destroyed);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, increaseUsage){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	celixThreadRwlock_create(&reference->lock, NULL);
+	reference->usageCount = 1;
+
+	size_t get_count;
+	celix_status_t status = serviceReference_increaseUsage(reference, &get_count);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	CHECK(2 == get_count);
+	CHECK(2 == reference->usageCount);
+
+	celixThreadRwlock_destroy(&reference->lock);
+	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, decreaseUsage){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	celixThreadRwlock_create(&reference->lock, NULL);
+	reference->usageCount = 2;
+
+	//test decreasing usage
+	size_t get_count;
+	celix_status_t status = serviceReference_decreaseUsage(reference, &get_count);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	CHECK(1 == get_count);
+	CHECK(1 == reference->usageCount);
+
+
+	status = serviceReference_decreaseUsage(reference, &get_count);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	CHECK(0 == get_count);
+	CHECK(0 == reference->usageCount);
+
+	//test attempting to decrease usage below 0
+	mock().expectOneCall("framework_log");
+
+	status = serviceReference_decreaseUsage(reference, &get_count);
+	LONGS_EQUAL(CELIX_BUNDLE_EXCEPTION, status);
+	CHECK(0 == get_count);
+	CHECK(0 == reference->usageCount);
+
+	celixThreadRwlock_destroy(&reference->lock);
+	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, getUsageCount){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	celixThreadRwlock_create(&reference->lock, NULL);
+	reference->usageCount = 5;
+
+	size_t get_count;
+	celix_status_t status = serviceReference_getUsageCount(reference, &get_count);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	CHECK(5 == get_count);
+
+	celixThreadRwlock_destroy(&reference->lock);
+	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, getReferenceCount){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	celixThreadRwlock_create(&reference->lock, NULL);
+	reference->refCount = 5;
+
+	size_t get_count;
+	celix_status_t status = serviceReference_getReferenceCount(reference, &get_count);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	CHECK(5 == get_count);
+
+	celixThreadRwlock_destroy(&reference->lock);
+	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, getService){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	celixThreadRwlock_create(&reference->lock, NULL);
+	void * service = (void*) 0x01;
+	reference->service = service;
+
+	void * get_service;
+	celix_status_t status = serviceReference_getService(reference, &get_service);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	POINTERS_EQUAL(service, get_service);
+
+	celixThreadRwlock_destroy(&reference->lock);
+	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, setService){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	celixThreadRwlock_create(&reference->lock, NULL);
+	void * service = (void*) 0x01;
+
+	celix_status_t status = serviceReference_setService(reference, service);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	POINTERS_EQUAL(service, reference->service);
+
+	celixThreadRwlock_destroy(&reference->lock);
+	free(reference);
+
+	mock().checkExpectations();
 }
 
 TEST(service_reference, getBundle) {
@@ -104,6 +277,28 @@ TEST(service_reference, getBundle) {
 
 	celixThreadRwlock_destroy(&reference->lock);
 	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, getOwner){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	celixThreadRwlock_create(&reference->lock, NULL);
+	bundle_pt bundle = (bundle_pt) 0x10;
+	reference->registrationBundle = bundle;
+	bundle_pt owner = (bundle_pt) 0x20;
+	reference->referenceOwner = owner;
+	reference->registration = (service_registration_pt) 0x30;
+
+	bundle_pt actual = NULL;
+	celix_status_t status = serviceReference_getOwner(reference, &actual);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	POINTERS_EQUAL(owner, actual);
+
+	celixThreadRwlock_destroy(&reference->lock);
+	free(reference);
+
+	mock().checkExpectations();
 }
 
 TEST(service_reference, getServiceRegistration) {
@@ -119,78 +314,156 @@ TEST(service_reference, getServiceRegistration) {
 
 	celixThreadRwlock_destroy(&reference->lock);
 	free(reference);
+
+	mock().checkExpectations();
 }
 
-TEST(service_reference, invalidate) {
+TEST(service_reference, getProperty){
 	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
 	service_registration_pt registration = (service_registration_pt) 0x10;
 	reference->registration = registration;
 	celixThreadRwlock_create(&reference->lock, NULL);
+	properties_pt props = (properties_pt) 0x20;
+	char * key = my_strdup("key");
+	char * value = my_strdup("value");
+	char * get_value = (char*) NULL;
 
-	mock().expectOneCall("serviceRegistration_release")
-			.withParameter("registration", registration);
+	//test getting a property
+	mock().expectOneCall("serviceRegistration_getProperties")
+			.withParameter("registration", registration)
+			.withOutputParameterReturning("properties", &props, sizeof(props));
 
-	celix_status_t status = serviceReference_invalidate(reference);
+	mock().expectOneCall("properties_get")
+			.withParameter("key", key)
+			.withParameter("properties", props)
+			.andReturnValue(value);
+
+	celix_status_t status = serviceReference_getProperty(reference, key, &get_value);
 	LONGS_EQUAL(CELIX_SUCCESS, status);
-	POINTERS_EQUAL(NULL, reference->registration);
+	STRCMP_EQUAL(value, get_value);
+
+	//check invalid registration
+	reference->registration = (service_registration_pt) NULL;
+
+	status = serviceReference_getProperty(reference, key, &get_value);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	POINTERS_EQUAL(NULL, get_value);
 
 	celixThreadRwlock_destroy(&reference->lock);
 	free(reference);
+	free(key);
+	free(value);
+
+	mock().checkExpectations();
 }
 
-TEST(service_reference, getUsingBundle) {
+static void mock_register_str(char * str){
+	mock().actualCall("mock_register_str")
+			.withStringParameter("str", str);
+}
+
+TEST(service_reference, getPropertyKeys){
 	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
 	service_registration_pt registration = (service_registration_pt) 0x10;
 	reference->registration = registration;
-	service_registry_pt registry = (service_registry_pt) 0x20;
-	registry_callback_t callback;
-	callback.getUsingBundles = serviceReferenceTest_getUsingBundles;
-	callback.handle = registry;
-	reference->callback = callback;
 	celixThreadRwlock_create(&reference->lock, NULL);
+	properties_pt props = hashMap_create(NULL, NULL, NULL, NULL);
+	char * key = my_strdup("key");
+	char * key2 = my_strdup("key2");
+	char * key3 = my_strdup("key3");
+	hashMap_put(props, key, (void*) 0x01);
+	hashMap_put(props, key2, (void*) 0x02);
+	hashMap_put(props, key3, (void*) 0x03);
+
+	char **keys;
+	unsigned int size;
+	mock().expectOneCall("serviceRegistration_getProperties")
+			.withParameter("registration", registration)
+			.withOutputParameterReturning("properties", &props, sizeof(props));
 
+	serviceReference_getPropertyKeys(reference, &keys, &size);
 
+	UNSIGNED_LONGS_EQUAL(3, size);
+	//check for all 3 keys, in no specific order
+	mock().expectOneCall("mock_register_str")
+			.withParameter("str", key);
+	mock().expectOneCall("mock_register_str")
+			.withParameter("str", key2);
+	mock().expectOneCall("mock_register_str")
+			.withParameter("str", key3);
 
-	array_list_pt bundles = NULL;
-	arrayList_create(&bundles);
-	bundle_pt bundle = (bundle_pt) 0x30;
-	arrayList_add(bundles, bundle);
+	mock_register_str(keys[0]);
+	mock_register_str(keys[1]);
+	mock_register_str(keys[2]);
 
-	mock().expectOneCall("serviceRegistration_retain")
-			.withParameter("registration", registration);
+	hashMap_destroy(props, true, false);
+	celixThreadRwlock_destroy(&reference->lock);
+	free(reference);
+	free(keys);
 
-	mock().expectOneCall("serviceReferenceTest_getUsingBundles")
-			.withParameter("registry", registry)
-			.withParameter("registration", registration)
-			.withOutputParameterReturning("bundles", &bundles, sizeof(bundles));
+	mock().checkExpectations();
+}
+
+TEST(service_reference, invalidate) {
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	service_registration_pt registration = (service_registration_pt) 0x10;
+	reference->registration = registration;
+	celixThreadRwlock_create(&reference->lock, NULL);
 
 	mock().expectOneCall("serviceRegistration_release")
-				.withParameter("registration", registration);
+			.withParameter("registration", registration);
 
-	array_list_pt actual = NULL;
-	celix_status_t status = serviceReference_getUsingBundles(reference, &actual);
-	LONGS_EQUAL(status,CELIX_SUCCESS);
-	POINTERS_EQUAL(bundles, actual);
-	LONGS_EQUAL(1, arrayList_size(actual));
-	POINTERS_EQUAL(bundle, arrayList_get(actual, 0));
+	celix_status_t status = serviceReference_invalidate(reference);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	POINTERS_EQUAL(NULL, reference->registration);
 
+	celixThreadRwlock_destroy(&reference->lock);
+	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, isValid){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	reference->registration = (service_registration_pt) 0x10;
+	celixThreadRwlock_create(&reference->lock, NULL);
+
+	mock().checkExpectations();
+	celix_status_t status;
+	bool result = false;
+
+	//test valid
+	status = serviceReference_isValid(reference, &result);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	CHECK(result);
+
+	//test invalid
+	reference->registration = NULL;
+	status = serviceReference_isValid(reference, &result);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	CHECK_FALSE(result);
 
-	arrayList_destroy(bundles);
 	celixThreadRwlock_destroy(&reference->lock);
 	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, isAssignableTo){
+	bool result = false;
+	result = serviceReference_isAssignableTo(NULL, NULL, NULL);
+	CHECK(result);
 }
 
 TEST(service_reference, equals) {
 	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
-	service_registration_pt registration = (service_registration_pt) 0x10;
-	reference->registration = registration;
+	reference->registration = (service_registration_pt) 0x10;
 	bundle_pt bundle = (bundle_pt) 0x20;
 	reference->registrationBundle = bundle;
 	celixThreadRwlock_create(&reference->lock, NULL);
 
 	service_reference_pt toCompare = (service_reference_pt) malloc(sizeof(*reference));
-	registration = (service_registration_pt) 0x10;
-	toCompare->registration = registration;
+	toCompare->registration = (service_registration_pt) 0x10;
 	bundle = (bundle_pt) 0x30;
 	toCompare->registrationBundle = bundle;
 	celixThreadRwlock_create(&toCompare->lock, NULL);
@@ -200,25 +473,23 @@ TEST(service_reference, equals) {
 	LONGS_EQUAL(CELIX_SUCCESS, status)
 	LONGS_EQUAL(true, equal);
 
-	celixThreadRwlock_destroy(&toCompare->lock);
-	free(toCompare);
-
-	toCompare = (service_reference_pt) malloc(sizeof(*reference));
-	registration = (service_registration_pt) 0x11;
-	toCompare->registration = registration;
-	bundle = (bundle_pt) 0x30;
-	toCompare->registrationBundle = bundle;
-	celixThreadRwlock_create(&toCompare->lock, NULL);
+	toCompare->registration = (service_registration_pt) 0x11;
 
 	equal = true;
 	status = serviceReference_equals(reference, toCompare, &equal);
 	LONGS_EQUAL(CELIX_SUCCESS, status)
 	LONGS_EQUAL(false, equal);
 
+	status = serviceReference_equals(NULL, toCompare, &equal);
+	LONGS_EQUAL(CELIX_ILLEGAL_ARGUMENT, status);
+	LONGS_EQUAL(false, equal);
+
 	celixThreadRwlock_destroy(&toCompare->lock);
 	celixThreadRwlock_destroy(&reference->lock);
 	free(toCompare);
 	free(reference);
+
+	mock().checkExpectations();
 }
 
 TEST(service_reference, equals2) {
@@ -256,6 +527,172 @@ TEST(service_reference, equals2) {
 	celixThreadRwlock_destroy(&reference->lock);
 	free(toCompare);
 	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, compareTo){
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	service_registration_pt registration = (service_registration_pt) 0x10;
+	reference->registration = registration;
+	bundle_pt bundle = (bundle_pt) 0x20;
+	reference->registrationBundle = bundle;
+	properties_pt props = (properties_pt) 0x30;
+	celixThreadRwlock_create(&reference->lock, NULL);
+
+	service_reference_pt reference2 = (service_reference_pt) malloc(sizeof(*reference2));
+	service_registration_pt registration2 = (service_registration_pt) 0x40;
+	reference2->registration = registration2;
+	bundle_pt bundle2 = (bundle_pt) 0x50;
+	reference2->registrationBundle = bundle2;
+	properties_pt props2 = (properties_pt) 0x60;
+	celixThreadRwlock_create(&reference2->lock, NULL);
+
+	int compare;
+
+	mock().expectNCalls(12, "serviceRegistration_getProperties")
+			.withParameter("registration", registration)
+			.withOutputParameterReturning("properties", &props, sizeof(props));
+	mock().expectNCalls(12, "serviceRegistration_getProperties")
+			.withParameter("registration", registration2)
+			.withOutputParameterReturning("properties", &props2, sizeof(props2));
+
+	//service 1 is higher ranked and has a irrelevant ID
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props)
+			.andReturnValue("2");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props2)
+			.andReturnValue("1");
+
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props)
+			.andReturnValue("2");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props2)
+			.andReturnValue("1");
+
+	serviceReference_compareTo(reference, reference2, &compare);
+	LONGS_EQUAL(1, compare);
+
+	//service 1 is equally ranked and has a lower ID
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props)
+			.andReturnValue("1");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props2)
+			.andReturnValue("2");
+
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props)
+			.andReturnValue("1");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props2)
+			.andReturnValue("1");
+
+	serviceReference_compareTo(reference, reference2, &compare);
+	LONGS_EQUAL(1, compare);
+
+	//service 1 is equally ranked and has a higher ID
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props)
+			.andReturnValue("2");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props2)
+			.andReturnValue("1");
+
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props)
+			.andReturnValue("1");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props2)
+			.andReturnValue("1");
+
+	serviceReference_compareTo(reference, reference2, &compare);
+	LONGS_EQUAL(-1, compare);
+
+	//service 1 is lower ranked and has a irrelevant ID
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props)
+			.andReturnValue("1");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props2)
+			.andReturnValue("2");
+
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props)
+			.andReturnValue("1");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props2)
+			.andReturnValue("2");
+
+	serviceReference_compareTo(reference, reference2, &compare);
+	LONGS_EQUAL(-1, compare);
+
+	//service 1 is equal in ID and irrelevantly ranked
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props)
+			.andReturnValue("1);");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props2)
+			.andReturnValue("1");
+
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props)
+			.andReturnValue("1");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props2)
+			.andReturnValue("1");
+
+	serviceReference_compareTo(reference, reference2, &compare);
+	LONGS_EQUAL(0, compare);
+
+	//services have no rank and service 1 has a higher ID
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props)
+			.andReturnValue("2");
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_ID)
+			.withParameter("properties", props2)
+			.andReturnValue("1");
+
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props)
+			.andReturnValue((void*)NULL);
+	mock().expectOneCall("properties_get")
+			.withParameter("key", OSGI_FRAMEWORK_SERVICE_RANKING)
+			.withParameter("properties", props2)
+			.andReturnValue((void*)NULL);
+
+	serviceReference_compareTo(reference, reference2, &compare);
+	LONGS_EQUAL(-1, compare);
+
+	free(reference);
+	free(reference2);
+
+	mock().checkExpectations();
 }
 
 TEST(service_reference, hashCode) {
@@ -271,4 +708,63 @@ TEST(service_reference, hashCode) {
 
 	celixThreadRwlock_destroy(&reference->lock);
 	free(reference);
+
+	mock().checkExpectations();
+}
+
+TEST(service_reference, getUsingBundle) {
+	service_reference_pt reference = (service_reference_pt) malloc(sizeof(*reference));
+	service_registration_pt registration = (service_registration_pt) 0x10;
+	reference->registration = registration;
+	service_registry_pt registry = (service_registry_pt) 0x20;
+	registry_callback_t callback;
+	callback.getUsingBundles = serviceReferenceTest_getUsingBundles;
+	callback.handle = registry;
+	reference->callback = callback;
+	celixThreadRwlock_create(&reference->lock, NULL);
+
+	//test correct functionality
+	array_list_pt bundles = NULL;
+	arrayList_create(&bundles);
+	bundle_pt bundle = (bundle_pt) 0x30;
+	arrayList_add(bundles, bundle);
+
+	mock().expectOneCall("serviceRegistration_retain")
+			.withParameter("registration", registration);
+
+	mock().expectOneCall("serviceReferenceTest_getUsingBundles")
+			.withParameter("registry", registry)
+			.withParameter("registration", registration)
+			.withOutputParameterReturning("bundles", &bundles, sizeof(bundles));
+
+	mock().expectOneCall("serviceRegistration_release")
+			.withParameter("registration", registration);
+
+	array_list_pt actual = NULL;
+	celix_status_t status = serviceReference_getUsingBundles(reference, &actual);
+	LONGS_EQUAL(status,CELIX_SUCCESS);
+	POINTERS_EQUAL(bundles, actual);
+	LONGS_EQUAL(1, arrayList_size(actual));
+	POINTERS_EQUAL(bundle, arrayList_get(actual, 0));
+
+	//test getusingbundles = null
+	callback.getUsingBundles = NULL;
+	reference->callback = callback;
+	actual = NULL;
+
+	mock().expectOneCall("serviceRegistration_retain")
+			.withParameter("registration", registration);
+	mock().expectOneCall("framework_log");
+	mock().expectOneCall("serviceRegistration_release")
+			.withParameter("registration", registration);
+
+	status = serviceReference_getUsingBundles(reference, &actual);
+	LONGS_EQUAL(status,CELIX_BUNDLE_EXCEPTION);
+	POINTERS_EQUAL(NULL, actual);
+
+	celixThreadRwlock_destroy(&reference->lock);
+	arrayList_destroy(bundles);
+	free(reference);
+
+	mock().checkExpectations();
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/fddc16c0/framework/private/test/service_registry_test.cpp
----------------------------------------------------------------------
diff --git a/framework/private/test/service_registry_test.cpp b/framework/private/test/service_registry_test.cpp
index 9fce76f..8a81bbe 100644
--- a/framework/private/test/service_registry_test.cpp
+++ b/framework/private/test/service_registry_test.cpp
@@ -34,6 +34,9 @@
 #include "CppUTestExt/MockSupport_c.h"
 
 extern "C" {
+#include "constants.h"
+#include "listener_hook_service.h"
+#include "service_registry.h"
 #include "service_registry_private.h"
 #include "celix_log.h"
 
@@ -78,7 +81,7 @@ static char * registry_callback_t_toString(const void* object)
 {
 	char buff[512];
 	registry_callback_t callback = *(registry_callback_t*) object;
-	snprintf(buff, 512, "< getUsingBudles: %p, handle: %p, modified: %p, unregister: %p >", callback.getUsingBundles, callback.handle, callback.modified, callback.unregister);
+	snprintf(buff, 512, "getUsingBudles: %p, handle: %p, modified: %p, unregister: %p", callback.getUsingBundles, callback.handle, callback.modified, callback.unregister);
 
 	return my_strdup(buff);
 }
@@ -111,7 +114,6 @@ TEST(service_registry, create) {
 	POINTERS_EQUAL(serviceRegistryTest_serviceChanged, registry->serviceChanged);
 	LONGS_EQUAL(1l, registry->currentServiceId);
 	CHECK(registry->listenerHooks != NULL);
-	//CHECK(registry->mutex != NULL);
 	CHECK(registry->serviceReferences != NULL);
 	CHECK(registry->serviceRegistrations != NULL);
 
@@ -250,18 +252,63 @@ TEST(service_registry, registerServiceFactoryNoProps) {
 	free(factory);
 }
 
+TEST(service_registry, registerServiceListenerHook) {
+	service_registry_pt registry = NULL;
+	framework_pt framework = (framework_pt) 0x01;
+	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
+
+	bundle_pt bundle = (bundle_pt) 0x10;
+	char * serviceName = my_strdup(OSGI_FRAMEWORK_LISTENER_HOOK_SERVICE_NAME);
+	void *service = (void *) 0x20;
+	service_registration_pt reg = (service_registration_pt) 0x30;
+
+	mock()
+		.expectOneCall("serviceRegistration_create")
+		.withParameterOfType("registry_callback_t", "callback", &registry->callback)
+		.withParameter("bundle", bundle)
+		.withParameter("serviceName", serviceName)
+		.withParameter("serviceId", 2)
+		.withParameter("serviceObject", service)
+		.withParameter("dictionary", (void *) NULL)
+		.andReturnValue(reg);
+
+	mock().expectOneCall("serviceRegistryTest_serviceChanged")
+			.withParameter("framework", framework)
+			.withParameter("eventType", OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED)
+			.withParameter("registration", reg)
+			.withParameter("oldprops", (void*)NULL);
+
+	service_registration_pt registration = NULL;
+	serviceRegistry_registerService(registry, bundle, serviceName, service, NULL, &registration);
+	POINTERS_EQUAL(reg, registration);
+	LONGS_EQUAL(1, arrayList_size(registry->listenerHooks));
+	POINTERS_EQUAL(reg, arrayList_get(registry->listenerHooks, 0));
+
+	//cleanup
+	array_list_pt destroy_this = (array_list_pt) hashMap_remove(registry->serviceRegistrations, bundle);
+	arrayList_destroy(destroy_this);
+	arrayList_remove(registry->listenerHooks, 0);
+	serviceRegistry_destroy(registry);
+	free(serviceName);
+}
+
 TEST(service_registry, unregisterService) {
 	service_registry_pt registry = NULL;
 	framework_pt framework = (framework_pt) 0x01;
 	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
 	bundle_pt bundle = (bundle_pt) 0x10;
 	service_registration_pt registration = (service_registration_pt) 0x20;
+
 	array_list_pt registrations = NULL;
 	arrayList_create(&registrations);
 	arrayList_add(registrations, registration);
-
 	hashMap_put(registry->serviceRegistrations, bundle, registrations);
-	properties_pt properties = (properties_pt) 0x30;
+	service_reference_pt reference = (service_reference_pt) 0x30;
+	hash_map_pt references = hashMap_create(NULL, NULL, NULL, NULL);
+
+	hashMap_put(references, registration, reference);
+	hashMap_put(registry->serviceReferences, bundle, references);
+	properties_pt properties = (properties_pt) 0x40;
 
 	mock()
 		.expectOneCall("serviceRegistration_getProperties")
@@ -271,8 +318,8 @@ TEST(service_registry, unregisterService) {
 	mock()
 		.expectOneCall("properties_get")
 		.withParameter("properties", properties)
-		.withParameter("key", "objectClass")
-		.andReturnValue("test");
+		.withParameter("key", (char *)OSGI_FRAMEWORK_OBJECTCLASS)
+		.andReturnValue((char*)OSGI_FRAMEWORK_LISTENER_HOOK_SERVICE_NAME);
 
 	mock()
 		.expectOneCall("serviceRegistryTest_serviceChanged")
@@ -280,6 +327,9 @@ TEST(service_registry, unregisterService) {
 		.withParameter("eventType", OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING)
 		.withParameter("registration", registration)
 		.withParameter("oldprops", (void*) NULL);
+	mock()
+		.expectOneCall("serviceReference_invalidate")
+		.withParameter("reference", reference);
 
 		mock()
 		.expectOneCall("serviceRegistration_invalidate")
@@ -292,58 +342,122 @@ TEST(service_registry, unregisterService) {
 
 
 	serviceRegistry_unregisterService(registry, bundle, registration);
-
+	hashMap_destroy(references, false,false);
 	serviceRegistry_destroy(registry);
 }
 
-/*TEST(service_registry, unregisterServices) {
+TEST(service_registry, clearServiceRegistrations){
 	service_registry_pt registry = NULL;
 	framework_pt framework = (framework_pt) 0x01;
-	serviceRegistry_create(framework, NULL, &registry);
-
-	bundle_pt bundle = (bundle_pt) 0x10;
-	service_registration_pt registration = (service_registration_pt) 0x20;
+	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
 	array_list_pt registrations = NULL;
 	arrayList_create(&registrations);
-	arrayList_add(registrations, registration);
-
+	service_registration_pt reg = (service_registration_pt) 0x10;
+	arrayList_add(registrations, reg);
+	bundle_pt bundle = (bundle_pt) 0x20;
 	hashMap_put(registry->serviceRegistrations, bundle, registrations);
 
+	//removing the first registration
+	char *serviceName = (char *) "test_service";
+	mock()
+		.expectOneCall("serviceRegistration_getServiceName")
+		.withParameter("registration", reg)
+		.withOutputParameterReturning("serviceName", &serviceName, sizeof(serviceName))
+		.andReturnValue(CELIX_SUCCESS);
+
+	mock()
+		.expectOneCall("framework_log");
+
 	mock()
 		.expectOneCall("serviceRegistration_isValid")
-		.withParameter("registration", registration)
+		.withParameter("registration", reg)
 		.andReturnValue(true);
+
+	//this call normally removes the registration from registry->serviceRegistrations
+	//but it remains since the mock does not call the callback->unregister therefore it acts like 2 separate registrations
+	mock().expectOneCall("serviceRegistration_unregister")
+			.withParameter("registration", reg);
+
+	//removing the "second" registration
 	mock()
-		.expectOneCall("serviceRegistration_unregister")
-		.withParameter("registration", registration)
+		.expectOneCall("serviceRegistration_getServiceName")
+		.withParameter("registration", reg)
+		.withOutputParameterReturning("serviceName", &serviceName, sizeof(serviceName))
 		.andReturnValue(CELIX_SUCCESS);
-	serviceRegistry_unregisterService(registry, bundle, );
-	LONGS_EQUAL(0, hashMap_size(registry->serviceRegistrations));
 
-	free(registry);
-}*/
+	mock()
+		.expectOneCall("framework_log");
+
+	mock()
+		.expectOneCall("serviceRegistration_isValid")
+		.withParameter("registration", reg)
+		.andReturnValue(false);
+
+	serviceRegistry_clearServiceRegistrations(registry, bundle);
+
+	//clean up
+	hashMap_remove(registry->serviceRegistrations, bundle);
+	arrayList_destroy(registrations);
+
+	serviceRegistry_destroy(registry);
+}
 
-/*TEST(service_registry, getServiceReferencesForRegistration){
+TEST(service_registry, getServiceReference){
 	service_registry_pt registry = NULL;
 	framework_pt framework = (framework_pt) 0x01;
 	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
 
 	bundle_pt bundle = (bundle_pt) 0x10;
 	service_registration_pt registration = (service_registration_pt) 0x20;
-	array_list_pt registrations = NULL;
-	arrayList_create(&registrations);
-	arrayList_add(registrations, registration);
-	registry->serviceReferences = hashMap_create(NULL, NULL, NULL, NULL);
-	hashMap_put(registry->serviceRegistrations, bundle, registrations);
+	service_reference_pt reference = (service_reference_pt) 0x50;
 
-	properties_pt properties = (properties_pt) 0x30;
-	array_list_pt references = NULL;
-	arrayList_create(&references);
-	service_reference_pt reference = (service_reference_pt) 0x40;
-	arrayList_add(references, reference);
+	hash_map_pt references = hashMap_create(NULL, NULL, NULL, NULL);
+	hashMap_put(references, registration, reference);
+	hashMap_put(registry->serviceReferences, bundle, references);
+
+	mock().expectOneCall("serviceReference_retain")
+			.withParameter("ref", reference);
+
+	service_reference_pt get_reference;
+	celix_status_t status = serviceRegistry_getServiceReference(registry, bundle, registration, &get_reference);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	POINTERS_EQUAL(reference, get_reference);
+
+	hashMap_destroy(references, false, false);
+	serviceRegistry_destroy(registry);
+}
+
+TEST(service_registry, getServiceReference_unknownRef){
+	service_registry_pt registry = NULL;
+	framework_pt framework = (framework_pt) 0x01;
+	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
+
+	bundle_pt bundle = (bundle_pt) 0x10;
+	service_registration_pt registration = (service_registration_pt) 0x20;
+	service_reference_pt reference = (service_reference_pt) 0x50;
+
+	//test getting ref from bundle without refs
+	mock().expectOneCall("serviceRegistration_getBundle")
+				.withParameter("registration", registration)
+				.withOutputParameterReturning("bundle", &bundle, sizeof(bundle));
+
+	mock().expectOneCall("serviceReference_create")
+			.withParameter("referenceOwner", bundle)
+			.withParameter("registration", registration)
+			.withOutputParameterReturning("reference", &reference, sizeof(reference))
+			.ignoreOtherParameters();
+
+
+	service_reference_pt get_reference;
+	celix_status_t status = serviceRegistry_getServiceReference(registry, bundle, registration, &get_reference);
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	POINTERS_EQUAL(reference, get_reference);
 
-	serviceRegistry_getServiceReferencesForRegistration(registry, registration, &references);
-}*/
+	//cleanup
+	hash_map_pt del = (hash_map_pt) hashMap_remove(registry->serviceReferences, bundle);
+	hashMap_destroy(del, false, false);
+	serviceRegistry_destroy(registry);
+}
 
 TEST(service_registry, getServiceReferences) {
 	service_registry_pt registry = NULL;
@@ -358,11 +472,12 @@ TEST(service_registry, getServiceReferences) {
 	hashMap_put(registry->serviceRegistrations, bundle, registrations);
 
 	properties_pt properties = (properties_pt) 0x30;
+	filter_pt filter = (filter_pt) 0x40;
 
-	hash_map_pt usages = hashMap_create(NULL, NULL, NULL, NULL);
-	service_reference_pt reference = (service_reference_pt) 0x30;
-	hashMap_put(usages, registration, reference);
-	hashMap_put(registry->serviceReferences, bundle, usages);
+	hash_map_pt references = hashMap_create(NULL, NULL, NULL, NULL);
+	service_reference_pt reference = (service_reference_pt) 0x50;
+	hashMap_put(references, registration, reference);
+	hashMap_put(registry->serviceReferences, bundle, references);
 
 	mock()
 		.expectOneCall("serviceRegistration_retain")
@@ -373,6 +488,11 @@ TEST(service_registry, getServiceReferences) {
 		.withParameter("registration", registration)
 		.withOutputParameterReturning("properties", &properties, sizeof(properties))
 		.andReturnValue(CELIX_SUCCESS);
+	bool matchResult = true;
+	mock().expectNCalls(2, "filter_match")
+		.withParameter("filter", filter)
+		.withParameter("properties", properties)
+		.withOutputParameterReturning("result", &matchResult, sizeof(matchResult));
 	char *serviceName = (char *) "test";
 	mock()
 		.expectOneCall("serviceRegistration_getServiceName")
@@ -387,20 +507,60 @@ TEST(service_registry, getServiceReferences) {
 	mock()
 		.expectOneCall("serviceReference_retain")
 		.withParameter("ref", reference);
-	/*mock()
-		.expectOneCall("serviceRegistration_getBundle")
-		.withParameter("registration", registration)
-		.withOutputParameterReturning("bundle", &bundle, sizeof(bundle))
-		.andReturnValue(CELIX_SUCCESS)
-		.ignoreOtherParameters();
 
 	mock()
-		.expectOneCall("serviceReference_create")
-		.withParameter("referenceOwner", bundle)
+		.expectOneCall("serviceRegistration_release")
+		.withParameter("registration", registration);
+
+	array_list_pt actual  = NULL;
+
+	serviceRegistry_getServiceReferences(registry, bundle, "test", filter, &actual);
+	LONGS_EQUAL(1, arrayList_size(actual));
+	POINTERS_EQUAL(reference, arrayList_get(actual, 0));
+
+	hashMap_destroy(references, false, false);
+	arrayList_destroy(actual);
+	arrayList_destroy(registrations);
+	hashMap_remove(registry->serviceRegistrations, bundle);
+	serviceRegistry_destroy(registry);
+}
+
+TEST(service_registry, getServiceReferences_noFilterOrName) {
+	service_registry_pt registry = NULL;
+	framework_pt framework = (framework_pt) 0x01;
+	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
+
+	bundle_pt bundle = (bundle_pt) 0x10;
+	service_registration_pt registration = (service_registration_pt) 0x20;
+	array_list_pt registrations = NULL;
+	arrayList_create(&registrations);
+	arrayList_add(registrations, registration);
+	hashMap_put(registry->serviceRegistrations, bundle, registrations);
+
+	properties_pt properties = (properties_pt) 0x30;
+
+	hash_map_pt references = hashMap_create(NULL, NULL, NULL, NULL);
+	service_reference_pt reference = (service_reference_pt) 0x50;
+	hashMap_put(references, registration, reference);
+	hashMap_put(registry->serviceReferences, bundle, references);
+
+	mock()
+		.expectOneCall("serviceRegistration_retain")
+		.withParameter("registration", registration);
+
+	mock()
+		.expectOneCall("serviceRegistration_getProperties")
 		.withParameter("registration", registration)
-		.withOutputParameterReturning("reference", &reference, sizeof(reference))
-		.ignoreOtherParameters();*/
+		.withOutputParameterReturning("properties", &properties, sizeof(properties))
+		.andReturnValue(CELIX_SUCCESS);
+	mock()
+		.expectOneCall("serviceRegistration_isValid")
+		.withParameter("registration", registration)
+		.andReturnValue(true);
 
+	mock()
+		.expectOneCall("serviceReference_retain")
+		.withParameter("ref", reference);
 
 	mock()
 		.expectOneCall("serviceRegistration_release")
@@ -408,17 +568,212 @@ TEST(service_registry, getServiceReferences) {
 
 	array_list_pt actual  = NULL;
 
-	serviceRegistry_getServiceReferences(registry, bundle, "test", NULL, &actual);
+	serviceRegistry_getServiceReferences(registry, bundle, NULL, NULL, &actual);
 	LONGS_EQUAL(1, arrayList_size(actual));
 	POINTERS_EQUAL(reference, arrayList_get(actual, 0));
 
-	hashMap_destroy(usages, false, false);
+	hashMap_destroy(references, false, false);
 	arrayList_destroy(actual);
 	arrayList_destroy(registrations);
 	hashMap_remove(registry->serviceRegistrations, bundle);
 	serviceRegistry_destroy(registry);
 }
 
+TEST(service_registry, retainServiceReference){
+	service_registry_pt registry = NULL;
+	framework_pt framework = (framework_pt) 0x01;
+	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
+
+	service_reference_pt reference = (service_reference_pt) 0x10;
+	bundle_pt bundle = (bundle_pt) 0x20;
+	bundle_pt bundle2 = (bundle_pt) 0x30;
+
+	//test unknown reference (reference not present in registry->deletedServiceReferences)
+	mock().expectOneCall("framework_log");
+
+	serviceRegistry_retainServiceReference(registry, bundle, reference);
+
+	//test known reference, but owner != bundle
+	registry->checkDeletedReferences = false;
+
+	mock().expectOneCall("serviceReference_getOwner")
+			.withParameter("reference", reference)
+			.withOutputParameterReturning("owner", &bundle2, sizeof(bundle2));
+	mock().expectOneCall("framework_log");
+
+	serviceRegistry_retainServiceReference(registry, bundle, reference);
+
+	registry->checkDeletedReferences = true;
+	//test known reference, with owner == bundle
+	hashMap_put(registry->deletedServiceReferences, reference, (void*) false);
+	mock().expectOneCall("serviceReference_getOwner")
+			.withParameter("reference", reference)
+			.withOutputParameterReturning("owner", &bundle, sizeof(bundle));
+	mock().expectOneCall("serviceReference_retain")
+			.withParameter("ref", reference);
+
+	serviceRegistry_retainServiceReference(registry, bundle, reference);
+
+	//cleanup
+	hashMap_remove(registry->deletedServiceReferences, reference);
+	serviceRegistry_destroy(registry);
+}
+
+TEST(service_registry, ungetServiceReference){
+	service_registry_pt registry = NULL;
+	framework_pt framework = (framework_pt) 0x01;
+	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
+
+	service_registration_pt registration = (service_registration_pt) 0x10;
+	service_registration_pt registration2 = (service_registration_pt) 0x20;
+	service_registration_pt registration3 = (service_registration_pt) 0x30;
+	service_reference_pt reference = (service_reference_pt) 0x40;
+	service_reference_pt reference2 = (service_reference_pt) 0x50;
+	service_reference_pt reference3 = (service_reference_pt) 0x60;
+	bundle_pt bundle = (bundle_pt) 0x70;
+	bundle_pt bundle2 = (bundle_pt) 0x80;
+
+	hash_map_pt references = hashMap_create(NULL, NULL, NULL, NULL);
+	hashMap_put(references, registration, reference);
+	hashMap_put(registry->serviceReferences, bundle, references);
+
+	hash_map_pt references2 = hashMap_create(NULL, NULL, NULL, NULL);
+	hashMap_put(references2, registration3, reference3);
+	hashMap_put(registry->serviceReferences, bundle2, references2);
+
+	//test unknown reference (reference not present in registry->deletedServiceReferences)
+	mock().expectOneCall("framework_log");
+
+	serviceRegistry_ungetServiceReference(registry, bundle, reference);
+
+	//test known reference, but destroyed == false
+	size_t count = 0;
+	bool destroyed = false;
+	hashMap_put(registry->deletedServiceReferences, reference, (void*) false);
+
+	mock().expectOneCall("serviceReference_getUsageCount")
+			.withParameter("reference", reference)
+			.withOutputParameterReturning("count", &count, sizeof(count));
+	mock().expectOneCall("serviceReference_release")
+			.withParameter("ref", reference)
+			.withOutputParameterReturning("destroyed", &destroyed, sizeof(destroyed));
+
+	serviceRegistry_ungetServiceReference(registry, bundle, reference);
+
+	//test known reference, destroyed == true, but wrong bundle (cannot find reference in bundle->refsMap)
+	destroyed = true;
+
+	mock().expectOneCall("serviceReference_getUsageCount")
+			.withParameter("reference", reference)
+			.withOutputParameterReturning("count", &count, sizeof(count));
+	mock().expectOneCall("serviceReference_release")
+			.withParameter("ref", reference)
+			.withOutputParameterReturning("destroyed", &destroyed, sizeof(destroyed));
+	mock().expectOneCall("framework_log");
+
+	serviceRegistry_ungetServiceReference(registry, bundle2, reference);
+
+	//test known reference, destroyed == true, but count > 0
+	destroyed = true;
+	count = 5;
+
+	mock().expectOneCall("serviceReference_getUsageCount")
+			.withParameter("reference", reference)
+			.withOutputParameterReturning("count", &count, sizeof(count));
+	mock().expectOneCall("serviceReference_release")
+			.withParameter("ref", reference)
+			.withOutputParameterReturning("destroyed", &destroyed, sizeof(destroyed));
+	mock().expectOneCall("framework_log");
+
+	serviceRegistry_ungetServiceReference(registry, bundle, reference);
+
+	CHECK((bool)hashMap_remove(registry->deletedServiceReferences, reference));
+
+	//test known reference2, destroyed == true, and count == 0
+	references = hashMap_create(NULL, NULL, NULL, NULL);
+	hashMap_put(references, registration, reference);
+	hashMap_put(references, registration2, reference2);
+	hashMap_put(registry->serviceReferences, bundle, references);
+	hashMap_put(registry->deletedServiceReferences, reference2, (void*) false);
+	destroyed = true;
+	count = 0;
+
+	mock().expectOneCall("serviceReference_getUsageCount")
+			.withParameter("reference", reference2)
+			.withOutputParameterReturning("count", &count, sizeof(count));
+	mock().expectOneCall("serviceReference_release")
+			.withParameter("ref", reference2)
+			.withOutputParameterReturning("destroyed", &destroyed, sizeof(destroyed));
+
+	serviceRegistry_ungetServiceReference(registry, bundle, reference2);
+
+	CHECK((bool)hashMap_remove(registry->deletedServiceReferences, reference2));//check that ref2 deleted == true
+	POINTERS_EQUAL(reference, hashMap_remove(references, registration)); //check that ref1 is untouched
+
+	//cleanup
+	hashMap_remove(references2, registration3);
+	hashMap_destroy(references, false, false);
+	hashMap_destroy(references2, false, false);
+	serviceRegistry_destroy(registry);
+}
+
+TEST(service_registry, clearReferencesFor){
+	service_registry_pt registry = NULL;
+	framework_pt framework = (framework_pt) 0x01;
+	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
+
+	service_registration_pt registration = (service_registration_pt) 0x10;
+	service_registration_pt registration2 = (service_registration_pt) 0x20;
+	service_reference_pt reference = (service_reference_pt) 0x40;
+	service_reference_pt reference2 = (service_reference_pt) 0x50;
+	bundle_pt bundle = (bundle_pt) 0x70;
+
+	hash_map_pt references = hashMap_create(NULL, NULL, NULL, NULL);
+	hashMap_put(references, registration, reference);
+	hashMap_put(references, registration2, reference2);
+	hashMap_put(registry->serviceReferences, bundle, references);
+
+	size_t useCount = 0;
+	size_t refCount = 0;
+	bool destroyed = true;
+	hashMap_put(registry->deletedServiceReferences, reference, (void*) false);
+	hashMap_put(registry->deletedServiceReferences, reference2, (void*) false);
+
+	//expected calls for removing reference1
+	mock().expectOneCall("serviceReference_getUsageCount")
+			.withParameter("reference", reference)
+			.withOutputParameterReturning("count", &useCount, sizeof(useCount));
+	mock().expectOneCall("serviceReference_getReferenceCount")
+				.withParameter("reference", reference)
+				.withOutputParameterReturning("count", &refCount, sizeof(refCount));
+	mock().expectOneCall("serviceReference_release")
+			.withParameter("ref", reference)
+			.withOutputParameterReturning("destroyed", &destroyed, sizeof(destroyed));
+
+	//expected calls for removing reference2 (including count error logging)
+	size_t useCount2 = 1;
+	size_t refCount2 = 1;
+	mock().expectOneCall("serviceReference_getUsageCount")
+			.withParameter("reference", reference2)
+			.withOutputParameterReturning("count", &useCount2, sizeof(useCount2));
+	mock().expectOneCall("serviceReference_getReferenceCount")
+			.withParameter("reference", reference2)
+			.withOutputParameterReturning("count", &refCount2, sizeof(refCount2));
+	mock().expectNCalls(2, "framework_log");
+	size_t updatedUseCount = 0;
+	mock().expectOneCall("serviceReference_decreaseUsage")
+			.withParameter("ref", reference2)
+			.withOutputParameterReturning("updatedCount", &updatedUseCount, sizeof(updatedUseCount));
+	mock().expectOneCall("serviceReference_release")
+			.withParameter("ref", reference2)
+			.withOutputParameterReturning("destroyed", &destroyed, sizeof(destroyed));
+
+	serviceRegistry_clearReferencesFor(registry, bundle);
+
+	serviceRegistry_destroy(registry);
+}
+
+
 TEST(service_registry, getService) {
 	service_registry_pt registry = NULL;
 	framework_pt framework = (framework_pt) 0x01;
@@ -434,10 +789,33 @@ TEST(service_registry, getService) {
 
 	service_reference_pt reference = (service_reference_pt) 0x40;
 
+	void * service = (void *) 0x60;
+
+	//test invalid reference
+	mock().expectOneCall("framework_log");
+
+
+	void *actual = (void*) 0x666;//generic non null pointer value
+	celix_status_t status = serviceRegistry_getService(registry, bundle, reference, &actual);
+	LONGS_EQUAL(CELIX_BUNDLE_EXCEPTION, status);
+	//test reference with invalid registration
 	hashMap_put(registry->deletedServiceReferences, reference, (void*) false);
 
-	void * service = (void *) 0x60;
+	mock()
+		.expectOneCall("serviceReference_getServiceRegistration")
+		.withParameter("reference", reference)
+		.withOutputParameterReturning("registration", &registration, sizeof(registration))
+		.andReturnValue(CELIX_SUCCESS);
+	mock()
+		.expectOneCall("serviceRegistration_isValid")
+		.withParameter("registration", registration)
+		.andReturnValue(false);
 
+	actual = (void*) 0x666;//generic non null pointer value
+	serviceRegistry_getService(registry, bundle, reference, &actual);
+	POINTERS_EQUAL(NULL, actual);
+
+	//test reference with valid registration
 	mock()
 		.expectOneCall("serviceReference_getServiceRegistration")
 		.withParameter("reference", reference)
@@ -471,7 +849,7 @@ TEST(service_registry, getService) {
 		.withParameter("reference", reference)
 		.withOutputParameterReturning("service", &service, sizeof(service));
 
-	void *actual = NULL;
+	actual = NULL;
 	serviceRegistry_getService(registry, bundle, reference, &actual);
 	POINTERS_EQUAL(service, actual);
 
@@ -523,11 +901,6 @@ TEST(service_registry, ungetService) {
 		.withParameter("bundle", bundle)
 		.withOutputParameterReturning("service", &service, sizeof(service));
 
-/*	mock()
-		.expectOneCall("serviceRegistration_isValid")
-		.withParameter("registration", registration)
-		.andReturnValue(true);*/
-
 	bool result = false;
 	celix_status_t status;
 	status = serviceRegistry_ungetService(registry, bundle, reference, &result);
@@ -550,155 +923,6 @@ TEST(service_registry, ungetService) {
 	arrayList_destroy(usages);
 }
 
-/*TEST(service_registry, ungetServivces) {
-	service_registry_pt registry = NULL;
-	framework_pt framework = (framework_pt) 0x01;
-	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
-
-	bundle_pt bundle = (bundle_pt) 0x10;
-	service_registration_pt registration = (service_registration_pt) 0x20;
-	array_list_pt registrations = NULL;
-	arrayList_create(&registrations);
-	arrayList_add(registrations, registration);
-
-	hashMap_put(registry->serviceRegistrations, bundle, registrations);
-
-	properties_pt properties = (properties_pt) 0x30;
-	array_list_pt references = NULL;
-	arrayList_create(&references);
-	service_reference_pt reference = (service_reference_pt) 0x40;
-	arrayList_add(references, reference);
-
-	array_list_pt usages = NULL;
-	arrayList_create(&usages);
-	usage_count_pt usage = (usage_count_pt) malloc(sizeof(*usage));
-	usage->reference = reference;
-	usage->count = 1;
-	arrayList_add(usages, usage);
-	hashMap_put(registry->inUseMap, bundle, usages);
-
-	mock()
-		.expectOneCall("serviceReference_getServiceRegistration")
-		.withParameter("reference", reference)
-		.withOutputParameterReturning("registration", &registration, sizeof(registration))
-		.andReturnValue(CELIX_SUCCESS);
-
-	bool out = true;
-	mock()
-			.expectOneCall("serviceReference_equals")
-			.withParameter("reference", reference)
-			.withParameter("compareTo", reference)
-			.withOutputParameterReturning("equal", &out, sizeof(out))
-			.andReturnValue(CELIX_SUCCESS);
-
-	out =  true;
-	mock()
-			.expectOneCall("serviceReference_equals")
-			.withParameter("reference", reference)
-			.withParameter("compareTo", reference)
-			.withOutputParameterReturning("equal", &out, sizeof(out))
-			.andReturnValue(CELIX_SUCCESS);
-
-	mock().expectOneCall("serviceRegistration_ungetService")
-			.withParameter("registration", registration)
-			.withParameter("bundle", bundle)
-			.withOutputParameterReturning("service", &reference, sizeof(reference));
-
-	mock()
-		.expectOneCall("serviceRegistration_isValid")
-		.withParameter("registration", registration)
-		.andReturnValue(true);
-
-	mock()
-		.expectOneCall("serviceReference_getServiceRegistration")
-		.withParameter("reference", reference)
-		.withOutputParameterReturning("registration", &registration, sizeof(registration))
-		.andReturnValue(CELIX_SUCCESS);
-
-	serviceRegistry_ungetServices(registry, bundle);
-
-	free(registry);
-}*/
-
-/*TEST(service_registry, getUsingBundles) {
-	service_registry_pt registry = NULL;
-	framework_pt framework = (framework_pt) 0x01;
-	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
-	bundle_pt bundle = (bundle_pt) 0x10;
-	service_registration_pt registration = (service_registration_pt) 0x20;
-	array_list_pt registrations = NULL;
-	arrayList_create(&registrations);
-	arrayList_add(registrations, registration);
-
-	hashMap_put(registry->serviceRegistrations, bundle, registrations);
-
-	properties_pt properties = (properties_pt) 0x30;
-	array_list_pt references = NULL;
-	arrayList_create(&references);
-	service_reference_pt reference = (service_reference_pt) 0x40;
-	arrayList_add(references, reference);
-
-	array_list_pt usages = NULL;
-	arrayList_create(&usages);
-	usage_count_pt usage = (usage_count_pt) malloc(sizeof(*usage));
-	usage->reference = reference;
-	arrayList_add(usages, usage);
-	hashMap_put(registry->serviceReferences, bundle, usages);
-
-	bool out = true;
-	mock()
-			.expectOneCall("serviceReference_equals")
-			.withParameter("reference", reference)
-			.withParameter("compareTo", reference)
-			.withOutputParameterReturning("equal", &out, sizeof(out))
-			.andReturnValue(CELIX_SUCCESS);
-
-	array_list_pt actual = serviceRegistry_getUsingBundles(registry, reference);
-	LONGS_EQUAL(1, arrayList_size(actual));
-	POINTERS_EQUAL(bundle, arrayList_get(actual, 0));
-
-	free(registry);
-}*/
-
-/*TEST(service_registry, createServiceReference) {
-	service_registry_pt registry = NULL;
-	framework_pt framework = (framework_pt) 0x01;
-	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
-
-	bundle_pt bundle = (bundle_pt) 0x10;
-	service_registration_pt registration = (service_registration_pt) 0x20;*/
-	/*array_list_pt registrations = NULL;
-	arrayList_create(&registrations);
-	arrayList_add(registrations, registration);
-
-	hashMap_put(registry->serviceRegistrations, bundle, registrations);*/
-
-/*	array_list_pt references = NULL;
-	arrayList_create(&references);
-	service_reference_pt reference = (service_reference_pt) 0x40;
-	arrayList_add(references, reference);
-
-	mock()
-		.expectOneCall("serviceRegistration_getBundle")
-		.withParameter("registration", registration)
-		.withOutputParameterReturning("bundle", &bundle, sizeof(bundle))
-		.andReturnValue(CELIX_SUCCESS)
-		.ignoreOtherParameters();
-	mock()
-		.expectOneCall("serviceReference_create")
-		.withParameter("bundle", bundle)
-		.withParameter("registration", registration)
-		.withOutputParameterReturning("reference", &reference, sizeof(reference))
-		.andReturnValue(CELIX_SUCCESS)
-		.ignoreOtherParameters();
-
-	service_reference_pt actual  = NULL;
-	serviceRegistry_createServiceReference(registry, NULL, registration, &actual);
-	POINTERS_EQUAL(reference, actual);
-
-	free(registry);
-}*/
-
 TEST(service_registry, getListenerHooks) {
 	service_registry_pt registry = NULL;
 	framework_pt framework = (framework_pt) 0x01;
@@ -750,3 +974,64 @@ TEST(service_registry, servicePropertiesModified) {
 
 	serviceRegistry_destroy(registry);
 }
+
+TEST(service_registry, getUsingBundles) {
+	service_registry_pt registry = NULL;
+	framework_pt framework = (framework_pt) 0x01;
+	serviceRegistry_create(framework,serviceRegistryTest_serviceChanged, &registry);
+
+	service_registration_pt registration = (service_registration_pt) 0x10;
+	service_registration_pt registration2 = (service_registration_pt) 0x20;
+	service_registration_pt registration3 = (service_registration_pt) 0x30;
+	service_registration_pt registration4 = (service_registration_pt) 0x40;
+	service_reference_pt reference = (service_reference_pt) 0x50;
+	service_reference_pt reference2 = (service_reference_pt) 0x60;
+	service_reference_pt reference3 = (service_reference_pt) 0x70;
+	service_reference_pt reference4 = (service_reference_pt) 0x80;
+	service_reference_pt reference5 = (service_reference_pt) 0x90;
+
+	bundle_pt bundle = (bundle_pt) 0xA0;
+	bundle_pt bundle2 = (bundle_pt) 0xB0;
+	bundle_pt bundle3 = (bundle_pt) 0xC0;
+
+	//only contains registration1
+	hash_map_pt references = hashMap_create(NULL, NULL, NULL, NULL);
+	hashMap_put(references, registration, reference);
+	hashMap_put(registry->serviceReferences, bundle, references);
+
+	//contains registration1 and one other
+	hash_map_pt references2 = hashMap_create(NULL, NULL, NULL, NULL);
+	hashMap_put(references2, registration, reference2);
+	hashMap_put(references2, registration2, reference3);
+	hashMap_put(registry->serviceReferences, bundle2, references2);
+
+	//contains 2 registrations, but not registration1
+	hash_map_pt references3 = hashMap_create(NULL, NULL, NULL, NULL);
+	hashMap_put(references3, registration3, reference4);
+	hashMap_put(references3, registration4, reference5);
+	hashMap_put(registry->serviceReferences, bundle3, references3);
+
+	//call to getUsingBundles
+	array_list_pt get_bundles_list = NULL;
+	registry->callback.getUsingBundles(registry, registration, &get_bundles_list);
+
+	//check that both bundle1 and bundle2 have been found
+	LONGS_EQUAL(2, arrayList_size(get_bundles_list));
+	bundle_pt get_bundle = (bundle_pt) arrayList_get(get_bundles_list, 0);
+	if (get_bundle == bundle){
+		get_bundle = (bundle_pt) arrayList_get(get_bundles_list, 1);
+		POINTERS_EQUAL(bundle2, get_bundle);
+	} else {
+		POINTERS_EQUAL(bundle2, get_bundle);
+		get_bundle = (bundle_pt) arrayList_get(get_bundles_list, 1);
+		POINTERS_EQUAL(bundle, get_bundle);
+	}
+
+	//cleanup
+	arrayList_destroy(get_bundles_list);
+
+	hashMap_destroy(references, false, false);
+	hashMap_destroy(references2, false, false);
+	hashMap_destroy(references3, false, false);
+	serviceRegistry_destroy(registry);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/fddc16c0/framework/private/test/service_tracker_test.cpp
----------------------------------------------------------------------
diff --git a/framework/private/test/service_tracker_test.cpp b/framework/private/test/service_tracker_test.cpp
index ca0981a..45898a1 100644
--- a/framework/private/test/service_tracker_test.cpp
+++ b/framework/private/test/service_tracker_test.cpp
@@ -90,6 +90,28 @@ TEST(service_tracker, create) {
 	free(service);
 }
 
+TEST(service_tracker, createWithCustomizer) {
+	celix_status_t status;
+	service_tracker_pt tracker = NULL;
+	bundle_context_pt context = (bundle_context_pt) 0x123;
+	char * service = my_strdup("service");
+	service_tracker_customizer_pt customizer = (service_tracker_customizer_pt) 0x20;
+	status = serviceTracker_create(context, service, customizer, &tracker);
+
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	POINTERS_EQUAL(context, tracker->context);
+	POINTERS_EQUAL(customizer, tracker->customizer);
+	POINTERS_EQUAL(NULL, tracker->listener);
+	POINTERS_EQUAL(tracker, tracker->tracker);
+	STRCMP_EQUAL("(objectClass=service)", tracker->filter);
+
+	mock().expectOneCall("serviceTrackerCustomizer_destroy")
+			.withParameter("customizer", customizer);
+
+	serviceTracker_destroy(tracker);
+	free(service);
+}
+
 TEST(service_tracker, createWithFilter) {
 	celix_status_t status;
 	service_tracker_pt tracker = NULL;
@@ -108,6 +130,28 @@ TEST(service_tracker, createWithFilter) {
 	free(filter);
 }
 
+TEST(service_tracker, createWithFilterWithCustomizer) {
+	celix_status_t status;
+	service_tracker_pt tracker = NULL;
+	bundle_context_pt context = (bundle_context_pt) 0x123;
+	service_tracker_customizer_pt customizer = (service_tracker_customizer_pt) 0x20;
+	char * filter = my_strdup("(objectClass=test)");
+	status = serviceTracker_createWithFilter(context, filter, customizer, &tracker);
+
+	LONGS_EQUAL(CELIX_SUCCESS, status);
+	POINTERS_EQUAL(context, tracker->context);
+	POINTERS_EQUAL(customizer, tracker->customizer);
+	POINTERS_EQUAL(NULL, tracker->listener);
+	POINTERS_EQUAL(tracker, tracker->tracker);
+	STRCMP_EQUAL("(objectClass=test)", tracker->filter);
+
+	mock().expectOneCall("serviceTrackerCustomizer_destroy")
+			.withParameter("customizer", customizer);
+
+	serviceTracker_destroy(tracker);
+	free(filter);
+}
+
 TEST(service_tracker, destroy) {
 	celix_status_t status;
 	service_tracker_pt tracker = NULL;
@@ -191,6 +235,10 @@ TEST(service_tracker, open_withRefs) {
 		.withParameter("filter", filter)
 		.ignoreOtherParameters();
 	mock()
+		.expectOneCall("bundleContext_retainServiceReference")
+		.withParameter("context", context)
+		.withParameter("reference", ref);
+	mock()
 		.expectOneCall("bundleContext_getService")
 		.withParameter("context", context)
 		.withParameter("reference", ref)
@@ -243,7 +291,10 @@ TEST(service_tracker, open_withRefsAndTracked) {
 		.withParameter("context", context)
 		.withParameter("filter", "(objectClass=service_name)")
 		.ignoreOtherParameters();
-
+	mock()
+		.expectOneCall("bundleContext_retainServiceReference")
+		.withParameter("context", context)
+		.withParameter("reference", ref);
 	bool equal = true;
 	mock()
 		.expectOneCall("serviceReference_equals")
@@ -303,6 +354,10 @@ TEST(service_tracker, close) {
 		.withParameter("reference", ref)
 		.withOutputParameterReturning("result", &result, sizeof(result))
 		.andReturnValue(CELIX_SUCCESS);
+	mock()
+		.expectOneCall("bundleContext_ungetServiceReference")
+		.withParameter("context", context)
+		.withParameter("reference", ref);
 
 	celix_status_t status;
 
@@ -540,6 +595,10 @@ TEST(service_tracker, serviceChangedRegistered) {
 	event->type = OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED;
 	event->reference = ref;
 
+	mock()
+		.expectOneCall("bundleContext_retainServiceReference")
+		.withParameter("context", context)
+		.withParameter("reference", ref);
 	void *src = (void *) 0x345;
 	mock()
 		.expectOneCall("bundleContext_getService")
@@ -586,6 +645,10 @@ TEST(service_tracker, serviceChangedModified) {
 	event->type = OSGI_FRAMEWORK_SERVICE_EVENT_MODIFIED;
 	event->reference = ref;
 
+	mock()
+		.expectOneCall("bundleContext_retainServiceReference")
+		.withParameter("context", context)
+		.withParameter("reference", ref);
 	bool equal = true;
 	mock()
 		.expectOneCall("serviceReference_equals")
@@ -642,6 +705,10 @@ TEST(service_tracker, serviceChangedUnregistering) {
 		.withParameter("reference", ref)
 		.withOutputParameterReturning("result", &result, sizeof(result))
 		.andReturnValue(CELIX_SUCCESS);
+	mock()
+		.expectOneCall("bundleContext_ungetServiceReference")
+		.withParameter("context", context)
+		.withParameter("reference", ref);
 
 	serviceTracker_serviceChanged(listener, event);
 
@@ -705,12 +772,11 @@ TEST(service_tracker, serviceChangedRegisteredCustomizer) {
 	bundle_context_pt context= (bundle_context_pt) 0x01;
 	char * service = my_strdup("service_name");
 	service_tracker_pt tracker = NULL;
-	serviceTracker_create(context, service, NULL, &tracker);
+	service_tracker_customizer_pt customizer = (service_tracker_customizer_pt) 0x20;
+	serviceTracker_create(context, service, customizer, &tracker);
 	service_listener_pt listener = (service_listener_pt) malloc(sizeof(*listener));
 	tracker->listener = listener;
 	listener->handle = tracker;
-	service_tracker_customizer_pt customizer = (service_tracker_customizer_pt) 0x20;
-	tracker->customizer = customizer;
 
 	service_reference_pt ref = (service_reference_pt) 0x51;
 
@@ -718,6 +784,10 @@ TEST(service_tracker, serviceChangedRegisteredCustomizer) {
 	event->type = OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED;
 	event->reference = ref;
 
+	mock()
+		.expectOneCall("bundleContext_retainServiceReference")
+		.withParameter("context", context)
+		.withParameter("reference", ref);
 	void * handle = (void*) 0x60;
 	mock()
 		.expectOneCall("serviceTrackerCustomizer_getHandle")
@@ -775,12 +845,11 @@ TEST(service_tracker, serviceChangedModifiedCustomizer) {
 	bundle_context_pt context= (bundle_context_pt) 0x01;
 	char * service = my_strdup("service_name");
 	service_tracker_pt tracker = NULL;
-	serviceTracker_create(context, service, NULL, &tracker);
+	service_tracker_customizer_pt customizer = (service_tracker_customizer_pt) 0x20;
+	serviceTracker_create(context, service, customizer, &tracker);
 	service_listener_pt listener = (service_listener_pt) malloc(sizeof(*listener));
 	tracker->listener = listener;
 	listener->handle = tracker;
-	service_tracker_customizer_pt customizer = (service_tracker_customizer_pt) 0x20;
-	tracker->customizer = customizer;
 	//adding_callback_pt adding_func = NULL;
 	//added_callback_pt added_func = NULL;
 
@@ -796,6 +865,10 @@ TEST(service_tracker, serviceChangedModifiedCustomizer) {
 
 	bool equal = true;
 	mock()
+		.expectOneCall("bundleContext_retainServiceReference")
+		.withParameter("context", context)
+		.withParameter("reference", ref);
+	mock()
 		.expectOneCall("serviceReference_equals")
 		.withParameter("reference", ref)
 		.withOutputParameterReturning("equal", &equal, sizeof(equal))
@@ -834,6 +907,7 @@ TEST(service_tracker, serviceChangedModifiedCustomizer) {
 			.withOutputParameterReturning("handle", &handle, sizeof(handle))
 			.andReturnValue(CELIX_SUCCESS);
 
+
 	void *function = (void *) serviceDependency_modifiedService;
 	mock()
 		.expectOneCall("serviceTrackerCustomizer_getModifiedFunction")
@@ -870,12 +944,11 @@ TEST(service_tracker, serviceChangedUnregisteringCustomizer) {
 	bundle_context_pt context= (bundle_context_pt) 0x01;
 	char * service = my_strdup("service_name");
 	service_tracker_pt tracker = NULL;
-	serviceTracker_create(context, service, NULL, &tracker);
+	service_tracker_customizer_pt customizer = (service_tracker_customizer_pt) 0x20;
+	serviceTracker_create(context, service, customizer, &tracker);
 	service_listener_pt listener = (service_listener_pt) malloc(sizeof(*listener));
 	tracker->listener = listener;
 	listener->handle = tracker;
-	service_tracker_customizer_pt customizer = (service_tracker_customizer_pt) 0x20;
-	tracker->customizer = customizer;
 
 	tracked_pt entry = (tracked_pt) malloc(sizeof(*entry));
 	entry->service = (void *) 0x31;
@@ -913,6 +986,10 @@ TEST(service_tracker, serviceChangedUnregisteringCustomizer) {
 		.withParameter("context", context)
 		.withParameter("reference", ref)
 		.withOutputParameterReturning("result", &result, sizeof(result));
+	mock()
+		.expectOneCall("bundleContext_ungetServiceReference")
+		.withParameter("context", context)
+		.withParameter("reference", ref);
 
 	serviceTracker_serviceChanged(listener, event);
 
@@ -936,12 +1013,11 @@ TEST(service_tracker, serviceChangedUnregisteringCustomizerNoFunc) {
 	bundle_context_pt context= (bundle_context_pt) 0x01;
 	char * service = my_strdup("service_name");
 	service_tracker_pt tracker = NULL;
-	serviceTracker_create(context, service, NULL, &tracker);
+	service_tracker_customizer_pt customizer = (service_tracker_customizer_pt) 0x20;
+	serviceTracker_create(context, service, customizer, &tracker);
 	service_listener_pt listener = (service_listener_pt) malloc(sizeof(*listener));
 	tracker->listener = listener;
 	listener->handle = tracker;
-	service_tracker_customizer_pt customizer = (service_tracker_customizer_pt) 0x20;
-	tracker->customizer = customizer;
 
 	tracked_pt entry = (tracked_pt) malloc(sizeof(*entry));
 	entry->service = (void *) 0x31;
@@ -975,6 +1051,10 @@ TEST(service_tracker, serviceChangedUnregisteringCustomizerNoFunc) {
 		.withParameter("context", context)
 		.withParameter("reference", ref)
 		.withOutputParameterReturning("result", &result, sizeof(result));
+	mock()
+		.expectOneCall("bundleContext_ungetServiceReference")
+		.withParameter("context", context)
+		.withParameter("reference", ref);
 
 	serviceTracker_serviceChanged(listener, event);
 

http://git-wip-us.apache.org/repos/asf/celix/blob/fddc16c0/framework/public/include/service_registry.h
----------------------------------------------------------------------
diff --git a/framework/public/include/service_registry.h b/framework/public/include/service_registry.h
index 41560b2..506f2bf 100644
--- a/framework/public/include/service_registry.h
+++ b/framework/public/include/service_registry.h
@@ -60,9 +60,6 @@ celix_status_t serviceRegistry_ungetService(service_registry_pt registry, bundle
 
 celix_status_t serviceRegistry_clearReferencesFor(service_registry_pt registry, bundle_pt bundle);
 
-
-service_registration_pt serviceRegistry_findRegistration(service_registry_pt registry, service_reference_pt reference);
-
 celix_status_t serviceRegistry_getListenerHooks(service_registry_pt registry, bundle_pt bundle, array_list_pt *hooks);
 
 celix_status_t serviceRegistry_servicePropertiesModified(service_registry_pt registry, service_registration_pt registration, properties_pt oldprops);