Add test case exposing FELIX-4977
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1693285 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java b/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
index 061a94b..cdc1cb5 100644
--- a/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
@@ -22,13 +22,15 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
+import java.util.Observable;
+import java.util.Observer;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
-import junit.framework.TestCase;
-
import org.apache.felix.framework.ServiceRegistrationImpl.ServiceReferenceImpl;
import org.apache.felix.framework.ServiceRegistry.ServiceHolder;
import org.apache.felix.framework.ServiceRegistry.UsageCount;
@@ -49,6 +51,8 @@
import org.osgi.framework.hooks.service.FindHook;
import org.osgi.framework.hooks.service.ListenerHook;
+import junit.framework.TestCase;
+
public class ServiceRegistryTest extends TestCase
{
public void testRegisterEventHookService()
@@ -65,6 +69,7 @@
ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
EventHook hook = new EventHook()
{
+ @Override
public void event(ServiceEvent event, Collection contexts)
{
}
@@ -133,6 +138,7 @@
ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
FindHook hook = new FindHook()
{
+ @Override
public void find(BundleContext context, String name, String filter,
boolean allServices, Collection references)
{
@@ -201,10 +207,12 @@
ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
ListenerHook hook = new ListenerHook()
{
+ @Override
public void added(Collection listeners)
{
}
+ @Override
public void removed(Collection listener)
{
}
@@ -272,23 +280,28 @@
ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
class CombinedService implements ListenerHook, FindHook, EventHook, Runnable
{
+ @Override
public void added(Collection listeners)
{
}
+ @Override
public void removed(Collection listener)
{
}
+ @Override
public void find(BundleContext context, String name, String filter,
boolean allServices, Collection references)
{
}
+ @Override
public void event(ServiceEvent event, Collection contexts)
{
}
+ @Override
public void run()
{
}
@@ -1033,6 +1046,110 @@
assertSame(uc2, inUseMap.get(b)[0]);
}
+ public void testGetUngetServiceFactory() throws Exception
+ {
+ final ServiceRegistry sr = new ServiceRegistry(null, null);
+ final Bundle regBundle = Mockito.mock(Bundle.class);
+ final ServiceRegistration<?> reg = sr.registerService(regBundle, new String[] {Observer.class.getName()},
+ new ServiceFactory<Observer>()
+ {
+
+ final class ObserverImpl implements Observer
+ {
+
+ public volatile boolean active = true;
+
+ @Override
+ public void update(Observable o, Object arg)
+ {
+ if ( !active )
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ };
+
+ @Override
+ public Observer getService(Bundle bundle, ServiceRegistration<Observer> registration)
+ {
+ return new ObserverImpl();
+ }
+
+ @Override
+ public void ungetService(Bundle bundle, ServiceRegistration<Observer> registration, Observer service)
+ {
+ ((ObserverImpl)service).active = false;
+ }
+ }, null);
+
+ final Bundle clientBundle = Mockito.mock(Bundle.class);
+ Mockito.when(clientBundle.getBundleId()).thenReturn(42L);
+
+ // check simple get/unget
+ final Object obj = sr.getService(clientBundle, reg.getReference(), false);
+ assertNotNull(obj);
+ assertTrue(obj instanceof Observer);
+ ((Observer)obj).update(null, null);
+ sr.ungetService(clientBundle, reg.getReference(), null);
+ try {
+ ((Observer)obj).update(null, null);
+ fail();
+ }
+ catch ( final IllegalArgumentException iae)
+ {
+ // expected
+ }
+
+ // start three threads
+ final int MAX_THREADS = 3;
+ final int MAX_LOOPS = 50000;
+ final CountDownLatch latch = new CountDownLatch(MAX_THREADS);
+ final Thread[] threads = new Thread[MAX_THREADS];
+ final List<Exception> exceptions = Collections.synchronizedList(new ArrayList<Exception>());
+ for(int i=0; i<MAX_THREADS; i++)
+ {
+ threads[i] = new Thread(new Runnable()
+ {
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ Thread.currentThread().sleep(50);
+ }
+ catch (InterruptedException e1)
+ {
+ // ignore
+ }
+ for(int i=0; i < MAX_LOOPS; i++)
+ {
+ try
+ {
+ final Object obj = sr.getService(clientBundle, reg.getReference(), false);
+ ((Observer)obj).update(null, null);
+ sr.ungetService(clientBundle, reg.getReference(), null);
+ }
+ catch ( final Exception e)
+ {
+ exceptions.add(e);
+ }
+ }
+ latch.countDown();
+ }
+ });
+ }
+ for(int i=0; i<MAX_THREADS; i++)
+ {
+ threads[i].start();
+ }
+
+ latch.await();
+
+ assertTrue("" + exceptions.size(), exceptions.isEmpty());
+ }
+
private Object getPrivateField(Object obj, String fieldName) throws NoSuchFieldException,
IllegalAccessException
{