blob: 864aec75baa5b961e69b5a08200cf4e6b198bc7f [file] [log] [blame]
/**
*
* Copyright 2005 the original author or authors.
*
* Licensed 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.
*/
package org.gbean.kernel.standard;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.SortedSet;
import java.util.TreeSet;
import java.io.Serializable;
import edu.emory.mathcs.backport.java.util.concurrent.Callable;
import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch;
import edu.emory.mathcs.backport.java.util.concurrent.ExecutionException;
import edu.emory.mathcs.backport.java.util.concurrent.FutureTask;
import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
import junit.framework.TestCase;
import org.gbean.kernel.IllegalServiceStateException;
import org.gbean.kernel.KernelErrorsError;
import org.gbean.kernel.ServiceAlreadyExistsException;
import org.gbean.kernel.ServiceFactory;
import org.gbean.kernel.ServiceName;
import org.gbean.kernel.ServiceNotFoundException;
import org.gbean.kernel.ServiceRegistrationException;
import org.gbean.kernel.StaticServiceFactory;
import org.gbean.kernel.StopStrategies;
import org.gbean.kernel.StopStrategy;
import org.gbean.kernel.StringServiceName;
import org.gbean.kernel.UnsatisfiedConditionsException;
import org.gbean.kernel.NullServiceMonitor;
/**
* Test the ServiceManagerRegistry.
*
* @author Dain Sundstrom
* @version $Id$
* @since 1.0
*/
public class ServiceManagerRegistryTest extends TestCase {
private static final int TIMEOUT_DURATION = 5;
private static final TimeUnit TIMEOUT_UNITS = TimeUnit.SECONDS;
private static final StringServiceName SERVICE_NAME = new StringServiceName("Service");
private static final StaticServiceFactory SERVICE_FACTORY = new StaticServiceFactory(new Object());
private static final ClassLoader CLASS_LOADER = new URLClassLoader(new URL[0]);
private static final Class[] EXPECTED_TYPES = new Class[] {
TreeSet.class,
AbstractSet.class,
AbstractCollection.class,
Object.class,
SortedSet.class,
Set.class,
Collection.class,
Cloneable.class,
Serializable.class,
List.class
};
private final MockServiceManager serviceManager = new MockServiceManager();
private final MockServiceManagerFactory serviceManagerFactory = new MockServiceManagerFactory();
private final ServiceManagerRegistry registry = new ServiceManagerRegistry(serviceManagerFactory);
/**
* Tests the initial state of the registry.
*/
public void testInitialState() {
assertFalse(registry.isRegistered(SERVICE_NAME));
try {
assertNull(registry.getServiceManager(SERVICE_NAME));
fail("should have thrown an exception");
} catch (ServiceNotFoundException expected) {
// expected
assertEquals(SERVICE_NAME, expected.getServiceName());
}
assertFalse(serviceManager.isInitializeCalled());
assertFalse(serviceManager.isDestroyCalled());
}
/**
* Test the registration and unregistration.
* Strategy:
* <ul><li>
* Register a service
* </li><li>
* Verify the service was registered and callbacks were made
* <ul><li>
* Unregister the service
* </li><li>
* Verify the service was unregistered and callbacks were made
* </li></ul>
*
* @throws Exception if there is a failure
*/
public void testRegisterUnregister() throws Exception {
register();
unregister();
}
/**
* Tests the destroy method.
* Strategy:
* <ul><li>
* Register a service
* </li><li>
* Verify the service was registered and callbacks were made
* <ul><li>
* Destroy the registry
* </li><li>
* Verify the service was stopped and callbacks were made
* </li></ul>
*
* @throws Exception if there is a failure
*/
public void testDestroy() throws Exception {
register();
destroy();
}
/**
* Tests that an exception is thrown if an attempt is made to register.
*
* @throws Exception if there is a failure
*/
public void testDoubleRegister() throws Exception {
register();
try {
registry.registerService(SERVICE_NAME, SERVICE_FACTORY, CLASS_LOADER);
fail("should have thrown an exception");
} catch (ServiceAlreadyExistsException expected) {
// expected
assertEquals(SERVICE_NAME, expected.getServiceName());
}
}
/**
* Test that an attempt to unregister a service that is not registered throws an exception.
*
* @throws Exception if there is a failure
*/
public void testUnregisterUnknown() throws Exception {
try {
registry.unregisterService(SERVICE_NAME, StopStrategies.SYNCHRONOUS);
} catch (ServiceNotFoundException expected) {
// expected
assertEquals(SERVICE_NAME, expected.getServiceName());
}
}
/**
* Tests that when the initialize method throws an exception the service is not registered.
*
* @throws Exception if there is a failure
*/
public void testRegisterException() throws Exception {
register(new Exception("register exception"));
register(new RuntimeException("register runtime exception"));
register(new Error("register error"));
register();
unregister();
}
/**
* Tests that when the destroy method throws an exception the service is not unregistered.
*
* @throws Exception if there is a failure
*/
public void testUnregisterException() throws Exception {
register();
unregister(new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET));
unregister(new IllegalServiceStateException("destroy exception", SERVICE_NAME));
unregister(new RuntimeException("destroy exception"));
unregister(new Error("destroy exception"));
unregister();
}
/**
* Tests that when the destroy and/or stop methods throw an exception during registry destroy, that destruction
* continues and the exceptions are thrown in a single KernelErrorsError.
*
* @throws Exception if there is a failure
*/
public void testDestroyException() throws Exception {
register();
destroy(new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET), null);
register();
destroy(new RuntimeException("destroy exception"), null);
register();
destroy(new Error("destroy exception"), null);
register();
destroy(new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET), new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET));
register();
destroy(new RuntimeException("destroy exception"), new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET));
register();
destroy(new Error("destroy exception"), new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET));
register();
destroy(null, new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET));
register();
destroy(new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET), new IllegalServiceStateException("destroy exception", SERVICE_NAME));
register();
destroy(new RuntimeException("destroy exception"), new IllegalServiceStateException("destroy exception", SERVICE_NAME));
register();
destroy(new Error("destroy exception"), new IllegalServiceStateException("destroy exception", SERVICE_NAME));
register();
destroy(null, new IllegalServiceStateException("destroy exception", SERVICE_NAME));
register();
destroy(new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET), new RuntimeException("destroy exception"));
register();
destroy(new RuntimeException("destroy exception"), new RuntimeException("destroy exception"));
register();
destroy(new Error("destroy exception"), new RuntimeException("destroy exception"));
register();
destroy(null, new RuntimeException("destroy exception"));
register();
destroy(new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET), new Error("destroy exception"));
register();
destroy(new RuntimeException("destroy exception"), new Error("destroy exception"));
register();
destroy(new Error("destroy exception"), new Error("destroy exception"));
register();
destroy(null, new Error("destroy exception"));
}
/**
* Tests that when a service manager blocks during registration, that the registry blocks isRegistered and
* getServiceManager calls until the registration completes.
*
* @throws Exception if there is a failure
*/
public void testRegisterWaiting() throws Exception {
registerWaiting(null);
}
/**
* Tests that when a service manager blocks during registration and then throws an exception, that the registry
* blocks isRegistered and getServiceManager calls until the registration completes, and then returns the correct
* values for an unregistered service.
*
* @throws Exception if there is a failure
*/
public void testRegisterWaitingException() throws Exception {
registerWaiting(new Exception("register exception"));
registerWaiting(new RuntimeException("register runtime exception"));
registerWaiting(new Error("register error"));
}
/**
* Tests that when a blocking service throws an exception during registration a nother service can wait be waiting
* to take over the registration from the failed thread.
*
* @throws Exception if there is a failure
*/
public void testDoubleRegisterWaiting() throws Exception {
// start thread to attempt to register but throw an exception
FutureTask registerFailTask = registerWaitingTask(new Exception("register exception"));
// start thread to successfully register
final CountDownLatch registerStartedSignal = new CountDownLatch(1);
final MockServiceManager newServiceManager = new MockServiceManager();
newServiceManager.setWait();
FutureTask registerTask = new FutureTask(new Callable() {
public Object call() throws Exception {
registerStartedSignal.countDown();
register(null, newServiceManager);
return Boolean.TRUE;
}
});
Thread registerThread = new Thread(registerTask, "registerTask");
registerThread.setDaemon(true);
registerThread.start();
registerStartedSignal.await(TIMEOUT_DURATION, TIMEOUT_UNITS);
// sleep a bit to assure that the register thread entered the registry code
Thread.sleep(100);
// verify all are not done
assertFalse(registerFailTask.isDone());
assertFalse(registerTask.isDone());
// finish register fail, and verify it failed
serviceManager.signalExit();
assertEquals(Boolean.FALSE, registerFailTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
// verify success registration and verify itworked
newServiceManager.signalExit();
assertEquals(Boolean.TRUE, registerTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
assertTrue(registry.isRegistered(SERVICE_NAME));
assertEquals(newServiceManager, registry.getServiceManager(SERVICE_NAME));
}
/**
* Tests that when a service manager blocks during unregistration, that the registry blocks isRegistered and
* getServiceManager calls until the unregistration completes.
*
* @throws Exception if there is a failure
*/
public void testUnregisterWaiting() throws Exception {
register();
unregisterWaiting(null);
}
/**
* Tests that when a service manager blocks during unregistration and then throws an exception, that the registry
* blocks isRegistered and getServiceManager calls until the unregistration completes, and then returns the correct
* values for an unregistered service.
*
* @throws Exception if there is a failure
*/
public void testUnregisterWaitingException() throws Exception {
register();
unregisterWaiting(new UnsatisfiedConditionsException("destroy exception", SERVICE_NAME, Collections.EMPTY_SET));
unregisterWaiting(new IllegalServiceStateException("destroy exception", SERVICE_NAME));
unregisterWaiting(new RuntimeException("destroy exception"));
unregisterWaiting(new Error("destroy exception"));
unregisterWaiting(null);
}
/**
* Tests that when a service manager blocks during destroy, that the registry does not block isRegistered and
* getServiceManager calls, and then returns the correct values for an unregistered service.
*
* @throws Exception if there is a failure
*/
public void testDestroyWaiting() throws Exception {
register();
// start thread to destroy and wait
FutureTask destroyTask = destroyWaitingTask();
// verify all are not done
assertFalse(destroyTask.isDone());
// verify that the service already appears to be unregistered
assertFalse(registry.isRegistered(SERVICE_NAME));
try {
assertNull(registry.getServiceManager(SERVICE_NAME));
fail("should have thrown an exception");
} catch (ServiceNotFoundException expected) {
// expected
assertEquals(SERVICE_NAME, expected.getServiceName());
}
// finish register
serviceManager.signalExit();
// verify registration worked
assertEquals(Boolean.TRUE, destroyTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
assertFalse(registry.isRegistered(SERVICE_NAME));
try {
assertNull(registry.getServiceManager(SERVICE_NAME));
fail("should have thrown an exception");
} catch (ServiceNotFoundException expected) {
// expected
assertEquals(SERVICE_NAME, expected.getServiceName());
}
}
private void registerWaiting(Throwable throwable) throws Exception {
// start thread to register and wait
FutureTask registerTask = registerWaitingTask(throwable);
// start thread to attempt getService
FutureTask getServiceManagerTask = getServiceWaiting();
// start thread to attempt isRegistered
FutureTask isRegisteredTask = isRegisteredWaiting();
// not necessary, but sleep a bit anyway
Thread.sleep(100);
// verify all are not done
assertFalse(registerTask.isDone());
assertFalse(getServiceManagerTask.isDone());
assertFalse(isRegisteredTask.isDone());
// finish register
serviceManager.signalExit();
if (throwable == null) {
// verify registration worked
assertEquals(Boolean.TRUE, registerTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
assertTrue(registry.isRegistered(SERVICE_NAME));
assertEquals(serviceManager, registry.getServiceManager(SERVICE_NAME));
// verify waiting isRegistered worked
assertEquals(Boolean.TRUE, isRegisteredTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
// verify getServiceManager worked
assertEquals(serviceManager, getServiceManagerTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
} else {
// verify registration failed
assertEquals(Boolean.FALSE, registerTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
assertFalse(registry.isRegistered(SERVICE_NAME));
try {
assertNull(registry.getServiceManager(SERVICE_NAME));
fail("should have thrown an exception");
} catch (ServiceNotFoundException expected) {
// expected
assertEquals(SERVICE_NAME, expected.getServiceName());
}
// verify waiting isRegistered worked
assertEquals(Boolean.FALSE, isRegisteredTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
// verify getServiceManager worked
try {
getServiceManagerTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS);
fail("should have thrown an exception");
} catch (ExecutionException e) {
assertTrue(e.getCause() instanceof ServiceNotFoundException);
ServiceNotFoundException serviceNotFoundException = (ServiceNotFoundException) e.getCause();
assertSame(SERVICE_NAME, serviceNotFoundException.getServiceName());
}
}
}
private FutureTask registerWaitingTask(final Throwable throwable) throws InterruptedException {
serviceManager.setWait();
FutureTask registerTask = new FutureTask(new Callable() {
public Object call() throws Exception {
register(throwable);
return Boolean.valueOf(throwable == null);
}
});
Thread registerThread = new Thread(registerTask, throwable == null ? "registerTask" : "registerExceptionTask");
registerThread.setDaemon(true);
registerThread.start();
// wait for register to block
assertTrue(serviceManager.awaitEnterSignal());
return registerTask;
}
private void unregisterWaiting(Throwable throwable) throws Exception {
// start thread to unregister and wait
FutureTask unregisterTask = unregisterWaitingTask(throwable);
// start thread to attempt getService
FutureTask getServiceManagerTask = getServiceWaiting();
// start thread to attempt isRegistered
FutureTask isRegisteredTask = isRegisteredWaiting();
// not necessary, but sleep a bit anyway
Thread.sleep(100);
// verify all are not done
assertFalse(unregisterTask.isDone());
assertFalse(getServiceManagerTask.isDone());
assertFalse(isRegisteredTask.isDone());
// finish register
serviceManager.signalExit();
if (throwable == null) {
// verify registration worked
assertEquals(Boolean.TRUE, unregisterTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
assertFalse(registry.isRegistered(SERVICE_NAME));
try {
assertNull(registry.getServiceManager(SERVICE_NAME));
fail("should have thrown an exception");
} catch (ServiceNotFoundException expected) {
// expected
assertEquals(SERVICE_NAME, expected.getServiceName());
}
// verify waiting isRegistered worked
assertEquals(Boolean.FALSE, isRegisteredTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
// verify getServiceManager worked
try {
getServiceManagerTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS);
fail("should have thrown an exception");
} catch (ExecutionException e) {
assertTrue(e.getCause() instanceof ServiceNotFoundException);
ServiceNotFoundException serviceNotFoundException = (ServiceNotFoundException) e.getCause();
assertSame(SERVICE_NAME, serviceNotFoundException.getServiceName());
}
} else {
// verify unregistration failed
assertEquals(Boolean.FALSE, unregisterTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
assertTrue(registry.isRegistered(SERVICE_NAME));
assertEquals(serviceManager, registry.getServiceManager(SERVICE_NAME));
// verify waiting isRegistered worked
assertEquals(Boolean.TRUE, isRegisteredTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
// verify getServiceManager worked
assertEquals(serviceManager, getServiceManagerTask.get(TIMEOUT_DURATION, TIMEOUT_UNITS));
}
}
private FutureTask unregisterWaitingTask(final Throwable throwable) throws InterruptedException {
serviceManager.setWait();
FutureTask unregisterTask = new FutureTask(new Callable() {
public Object call() throws Exception {
unregister(throwable);
return Boolean.valueOf(throwable == null);
}
});
Thread unregisterThread = new Thread(unregisterTask, throwable == null ? "unregisterTask" : "unregisterExceptionTask");
unregisterThread.setDaemon(true);
unregisterThread.start();
// wait for register to block
assertTrue(serviceManager.awaitEnterSignal());
return unregisterTask;
}
private FutureTask destroyWaitingTask() throws InterruptedException {
serviceManager.setWait();
FutureTask unregisterTask = new FutureTask(new Callable() {
public Object call() throws Exception {
destroy();
return Boolean.TRUE;
}
});
Thread destroyThread = new Thread(unregisterTask, "destroyTask");
destroyThread.setDaemon(true);
destroyThread.start();
// wait for register to block
assertTrue(serviceManager.awaitEnterSignal());
return unregisterTask;
}
private FutureTask getServiceWaiting() throws InterruptedException {
final CountDownLatch getServiceManagerSignal = new CountDownLatch(1);
FutureTask getServiceManagerTask = new FutureTask(new Callable() {
public Object call() throws Exception {
getServiceManagerSignal.countDown();
return registry.getServiceManager(SERVICE_NAME);
}
});
Thread getServiceManagerThread = new Thread(getServiceManagerTask, "getServiceManagerTask");
getServiceManagerThread.setDaemon(true);
getServiceManagerThread.start();
// wait for thread started
getServiceManagerSignal.await(TIMEOUT_DURATION, TIMEOUT_UNITS);
return getServiceManagerTask;
}
private FutureTask isRegisteredWaiting() throws InterruptedException {
final CountDownLatch isRegisteredSignal = new CountDownLatch(1);
FutureTask isRegisteredTask = new FutureTask(new Callable() {
public Object call() throws Exception {
isRegisteredSignal.countDown();
return Boolean.valueOf(registry.isRegistered(SERVICE_NAME));
}
});
Thread isRegisteredThread = new Thread(isRegisteredTask, "isRegisteredTask");
isRegisteredThread.setDaemon(true);
isRegisteredThread.start();
// wait for thread started
isRegisteredSignal.await(TIMEOUT_DURATION, TIMEOUT_UNITS);
return isRegisteredTask;
}
private void register() throws Exception {
register(null, serviceManager);
}
private void register(Throwable throwable) throws Exception {
register(throwable, serviceManager);
}
private void register(Throwable throwable, MockServiceManager serviceManager) throws Exception {
serviceManager.reset();
serviceManager.setInitializeException(throwable);
serviceManagerFactory.addServiceManager(serviceManager);
try {
registry.registerService(SERVICE_NAME, SERVICE_FACTORY, CLASS_LOADER);
assertNull(throwable);
} catch (ServiceRegistrationException expected) {
// expected
assertSame(throwable, expected.getCause());
assertSame(SERVICE_NAME, expected.getServiceName());
}
if (throwable == null) {
assertTrue(registry.isRegistered(SERVICE_NAME));
assertSame(serviceManager, registry.getServiceManager(SERVICE_NAME));
for (int i = 0; i < EXPECTED_TYPES.length; i++) {
assertSame(serviceManager, registry.getServiceManager(EXPECTED_TYPES[i]));
assertTrue(registry.getServiceManagers(EXPECTED_TYPES[i]).contains(serviceManager));
}
} else {
assertFalse(registry.isRegistered(SERVICE_NAME));
try {
assertNull(registry.getServiceManager(SERVICE_NAME));
fail("should have thrown an exception");
} catch (ServiceNotFoundException expected) {
// expected
assertEquals(SERVICE_NAME, expected.getServiceName());
}
for (int i = 0; i < EXPECTED_TYPES.length; i++) {
assertNull(registry.getServiceManager(EXPECTED_TYPES[i]));
assertTrue(registry.getServiceManagers(EXPECTED_TYPES[i]).isEmpty());
}
}
assertTrue(serviceManager.isInitializeCalled());
assertFalse(serviceManager.isDestroyCalled());
}
private void unregister() throws ServiceNotFoundException {
unregister(null);
}
private void unregister(Throwable throwable) throws ServiceNotFoundException {
serviceManager.reset();
serviceManager.setDestroyException(throwable);
try {
registry.unregisterService(SERVICE_NAME, StopStrategies.SYNCHRONOUS);
assertNull(throwable);
} catch (ServiceRegistrationException expected) {
// expected
assertSame(SERVICE_NAME, expected.getServiceName());
assertSame(throwable, expected.getCause());
}
if (throwable == null) {
assertFalse(registry.isRegistered(SERVICE_NAME));
try {
assertNull(registry.getServiceManager(SERVICE_NAME));
fail("should have thrown an exception");
} catch (ServiceNotFoundException expected) {
// expected
assertEquals(SERVICE_NAME, expected.getServiceName());
}
for (int i = 0; i < EXPECTED_TYPES.length; i++) {
assertNull(registry.getServiceManager(EXPECTED_TYPES[i]));
assertTrue(registry.getServiceManagers(EXPECTED_TYPES[i]).isEmpty());
}
} else {
assertTrue(registry.isRegistered(SERVICE_NAME));
assertSame(serviceManager, registry.getServiceManager(SERVICE_NAME));
for (int i = 0; i < EXPECTED_TYPES.length; i++) {
assertSame(serviceManager, registry.getServiceManager(EXPECTED_TYPES[i]));
assertTrue(registry.getServiceManagers(EXPECTED_TYPES[i]).contains(serviceManager));
}
}
assertFalse(serviceManager.isInitializeCalled());
assertTrue(serviceManager.isDestroyCalled());
}
private void destroy() {
destroy(null, null);
}
private void destroy(Throwable stopException, Throwable destroyException) {
serviceManager.reset();
serviceManager.setStopException(stopException);
serviceManager.setDestroyException(destroyException);
try {
registry.destroy();
assertNull(stopException);
assertNull(destroyException);
} catch (KernelErrorsError kernelErrorsError) {
List errors = new ArrayList(kernelErrorsError.getErrors());
if (stopException != null) {
assertTrue(errors.size() >= 3);
assertTrue(errors.get(0) instanceof AssertionError);
assertSame(stopException, ((AssertionError) errors.get(0)).getCause());
assertTrue(errors.get(1) instanceof AssertionError);
assertSame(stopException, ((AssertionError) errors.get(1)).getCause());
assertTrue(errors.get(2) instanceof AssertionError);
assertSame(stopException, ((AssertionError) errors.get(2)).getCause());
errors = errors.subList(3, errors.size());
}
if (destroyException != null) {
assertEquals(1, errors.size());
assertTrue(errors.get(0) instanceof AssertionError);
assertSame(destroyException, ((AssertionError) errors.get(0)).getCause());
errors = Collections.EMPTY_LIST;
}
assertEquals(Collections.EMPTY_LIST, errors);
}
assertFalse(registry.isRegistered(SERVICE_NAME));
try {
assertNull(registry.getServiceManager(SERVICE_NAME));
fail("should have thrown an exception");
} catch (ServiceNotFoundException expected) {
// expected
assertEquals(SERVICE_NAME, expected.getServiceName());
}
assertFalse(serviceManager.isInitializeCalled());
assertTrue(serviceManager.isStopCalled());
assertTrue(serviceManager.isDestroyCalled());
}
private static class MockServiceManagerFactory extends ServiceManagerFactory {
private final LinkedList serviceManagers = new LinkedList();
private MockServiceManagerFactory() {
super(null, null, null, 0, null);
}
public ServiceManager createServiceManager(long serviceId, ServiceName serviceName, ServiceFactory serviceFactory, ClassLoader classLoader) {
assertEquals(SERVICE_NAME, serviceName);
assertEquals(SERVICE_FACTORY, serviceFactory);
assertEquals(CLASS_LOADER, classLoader);
synchronized (serviceManagers) {
return (ServiceManager) serviceManagers.removeFirst();
}
}
public void addServiceManager(ServiceManager serviceManager) {
synchronized (serviceManagers) {
serviceManagers.add(serviceManager);
}
}
}
private static class MockServiceManager extends ServiceManager {
private boolean initializeCalled;
private boolean destroyCalled;
private boolean stopCalled;
private Throwable initializeException;
private Throwable destroyException;
private Throwable stopException;
private CountDownLatch enterWaiting = new CountDownLatch(1);
private CountDownLatch exitWaiting = new CountDownLatch(0);
private static final Set TYPES = Collections.unmodifiableSet(new HashSet(Arrays.asList(
new Class[] {TreeSet.class, List.class} )));
private MockServiceManager() {
super(null,
0,
new StringServiceName("MockService"),
new StaticServiceFactory(new Object()),
null,
new NullServiceMonitor(),
0,
null);
}
private synchronized void reset() {
initializeCalled = false;
destroyCalled = false;
stopCalled = false;
initializeException = null;
destroyException = null;
stopException = null;
}
public Set getServiceTypes() {
return TYPES;
}
public void initialize() throws IllegalServiceStateException, UnsatisfiedConditionsException, Exception {
synchronized (this) {
assertFalse(initializeCalled);
initializeCalled = true;
}
signalEnter();
awaitExitSignal();
synchronized (this) {
if (initializeException instanceof Exception) {
throw (Exception) initializeException;
} else if (initializeException instanceof Error) {
throw (Error) initializeException;
}
}
}
public void destroy(StopStrategy stopStrategy) throws IllegalServiceStateException, UnsatisfiedConditionsException {
synchronized (this) {
assertFalse(destroyCalled);
destroyCalled = true;
}
try {
signalEnter();
awaitExitSignal();
} catch (InterruptedException e) {
fail("destroyCondition.await() threw an exception");
}
synchronized (this) {
if (destroyException instanceof UnsatisfiedConditionsException) {
throw (UnsatisfiedConditionsException) destroyException;
} else if (destroyException instanceof IllegalServiceStateException) {
throw (IllegalServiceStateException) destroyException;
} else if (destroyException instanceof RuntimeException) {
throw (RuntimeException) destroyException;
} else if (destroyException instanceof Error) {
throw (Error) destroyException;
}
}
}
public synchronized boolean stop(StopStrategy stopStrategy) throws UnsatisfiedConditionsException {
stopCalled = true;
if (stopException instanceof UnsatisfiedConditionsException) {
throw (UnsatisfiedConditionsException) stopException;
} else if (stopException instanceof RuntimeException) {
throw (RuntimeException) stopException;
} else if (stopException instanceof Error) {
throw (Error) stopException;
}
return true;
}
public synchronized boolean isInitializeCalled() {
return initializeCalled;
}
public synchronized boolean isDestroyCalled() {
return destroyCalled;
}
public synchronized boolean isStopCalled() {
return stopCalled;
}
public synchronized void setInitializeException(Throwable initializeException) {
this.initializeException = initializeException;
}
public synchronized void setDestroyException(Throwable destroyException) {
this.destroyException = destroyException;
}
public synchronized void setStopException(Throwable stopException) {
this.stopException = stopException;
}
public boolean awaitEnterSignal() throws InterruptedException {
CountDownLatch signal;
synchronized (this) {
signal = enterWaiting;
}
boolean worked = signal.await(TIMEOUT_DURATION, TIMEOUT_UNITS);
return worked;
}
private void signalEnter() {
CountDownLatch signal;
synchronized (this) {
signal = enterWaiting;
}
signal.countDown();
}
public synchronized void setWait() {
exitWaiting = new CountDownLatch(1);
enterWaiting = new CountDownLatch(1);
}
public void signalExit() {
CountDownLatch signal;
synchronized (this) {
signal = exitWaiting;
}
signal.countDown();
}
private void awaitExitSignal() throws InterruptedException {
CountDownLatch signal;
synchronized (this) {
signal = exitWaiting;
}
signal.await(TIMEOUT_DURATION, TIMEOUT_UNITS);
}
}
}