/**
 *
 * 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);
        }
    }
}
