diff --git a/kernel/project.xml b/kernel/project.xml
index ba892bc..397742a 100644
--- a/kernel/project.xml
+++ b/kernel/project.xml
@@ -64,6 +64,12 @@
             <artifactId>backport-util-concurrent</artifactId>
             <version>2.0_01_pd</version>
         </dependency>
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib-nodep</artifactId>
+            <version>2.1_2</version>
+            <type>test</type>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/kernel/src/java/org/gbean/kernel/standard/ServiceManagerRegistry.java b/kernel/src/java/org/gbean/kernel/standard/ServiceManagerRegistry.java
index c910622..c65e622 100644
--- a/kernel/src/java/org/gbean/kernel/standard/ServiceManagerRegistry.java
+++ b/kernel/src/java/org/gbean/kernel/standard/ServiceManagerRegistry.java
@@ -76,8 +76,9 @@
 
         List managerFutures;
         synchronized (serviceManagers) {
-            managerFutures = new ArrayList();
+            managerFutures = new ArrayList(serviceManagers.values());
             serviceManagers.clear();
+
         }
 
         List managers = new ArrayList(managerFutures.size());
diff --git a/kernel/src/test/org/gbean/kernel/standard/ServiceManagerRegistryTest.java b/kernel/src/test/org/gbean/kernel/standard/ServiceManagerRegistryTest.java
new file mode 100644
index 0000000..042fdea
--- /dev/null
+++ b/kernel/src/test/org/gbean/kernel/standard/ServiceManagerRegistryTest.java
@@ -0,0 +1,846 @@
+/**
+ *
+ * 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 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;
+
+/**
+ * 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 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));
+            assertEquals(serviceManager, registry.getServiceManager(SERVICE_NAME));
+        } 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());
+            }
+        }
+        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());
+            }
+        } else {
+            assertTrue(registry.isRegistered(SERVICE_NAME));
+            assertEquals(serviceManager, registry.getServiceManager(SERVICE_NAME));
+        }
+        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(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 MockServiceManager() {
+            super(null, null, null, null, null, null, 0, null);
+        }
+
+        private synchronized void reset() {
+            initializeCalled = false;
+            destroyCalled = false;
+            stopCalled = false;
+            initializeException = null;
+            destroyException = null;
+            stopException = null;
+        }
+
+        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);
+        }
+    }
+}
