@Test
  public void testAttemptsToStopAllServicesOnCloseFailure() {
    Service s1 = mock(CacheProvider.class);
    Service s2 = mock(FooProvider.class);
    Service s3 = mock(CacheLoaderWriterProvider.class);

    ServiceLocator locator = new ServiceLocator(s1, s2, s3);
    try {
      locator.startAllServices();
    } catch (Exception e) {
      fail();
    }
    final RuntimeException thrown = new RuntimeException();
    doThrow(thrown).when(s1).stop();

    try {
      locator.stopAllServices();
      fail();
    } catch (Exception e) {
      assertThat(e, CoreMatchers.<Exception>sameInstance(thrown));
    }
    verify(s1).stop();
    verify(s2).stop();
    verify(s3).stop();
  }
  @Test
  public void testServicesInstanciatedOnceAndStartedOnce() throws Exception {

    @ServiceDependencies(TestProvidedService.class)
    class Consumer1 implements Service {
      @Override
      public void start(ServiceProvider<Service> serviceProvider) {}

      @Override
      public void stop() {}
    }

    @ServiceDependencies(TestProvidedService.class)
    class Consumer2 implements Service {
      TestProvidedService testProvidedService;

      @Override
      public void start(ServiceProvider<Service> serviceProvider) {
        testProvidedService = serviceProvider.getService(TestProvidedService.class);
      }

      @Override
      public void stop() {}
    }

    Consumer1 consumer1 = spy(new Consumer1());
    Consumer2 consumer2 = new Consumer2();
    ServiceLocator serviceLocator = new ServiceLocator();

    // add some services
    serviceLocator.addService(consumer1);
    serviceLocator.addService(consumer2);
    serviceLocator.addService(
        new TestService() {
          @Override
          public void start(ServiceProvider<Service> serviceProvider) {}

          @Override
          public void stop() {
            // no-op
          }
        });

    // simulate what is done in ehcachemanager
    serviceLocator.loadDependenciesOf(TestServiceConsumerService.class);
    serviceLocator.startAllServices();

    serviceLocator.stopAllServices();

    verify(consumer1, times(1)).start(serviceLocator);
    verify(consumer1, times(1)).stop();

    assertThat(consumer2.testProvidedService.ctors(), greaterThanOrEqualTo(1));
    assertThat(consumer2.testProvidedService.stops(), equalTo(1));
    assertThat(consumer2.testProvidedService.starts(), equalTo(1));
  }
  @Test
  public void testStopAllServicesOnlyStopsEachServiceOnce() throws Exception {
    Service s1 =
        mock(CacheProvider.class, withSettings().extraInterfaces(CacheLoaderWriterProvider.class));

    ServiceLocator locator = new ServiceLocator(s1);
    try {
      locator.startAllServices();
    } catch (Exception e) {
      fail();
    }

    locator.stopAllServices();
    verify(s1, times(1)).stop();
  }
  @Test
  public void testAttemptsToStopStartedServicesOnInitFailure() {
    Service s1 = new ParentTestService();
    FancyCacheProvider s2 = new FancyCacheProvider();

    ServiceLocator locator = new ServiceLocator(s1, s2);
    try {
      locator.startAllServices();
      fail();
    } catch (Exception e) {
      // see org.ehcache.spi.ParentTestService.start()
      assertThat(e, instanceOf(RuntimeException.class));
      assertThat(e.getMessage(), is("Implement me!"));
    }
    assertThat(s2.startStopCounter, is(0));
  }
  @Test
  public void testCanOverrideServiceDependencyWithoutOrderingProblem() throws Exception {
    final AtomicBoolean started = new AtomicBoolean(false);
    ServiceLocator serviceLocator = new ServiceLocator(new TestServiceConsumerService());
    serviceLocator.addService(
        new TestService() {
          @Override
          public void start(ServiceProvider<Service> serviceProvider) {
            started.set(true);
          }

          @Override
          public void stop() {
            // no-op
          }
        });
    serviceLocator.startAllServices();
    assertThat(started.get(), is(true));
  }
  @Test
  public void testCircularDeps() throws Exception {

    final class StartStopCounter {
      final AtomicInteger startCounter = new AtomicInteger(0);
      final AtomicReference<ServiceProvider<Service>> startServiceProvider =
          new AtomicReference<ServiceProvider<Service>>();
      final AtomicInteger stopCounter = new AtomicInteger(0);

      public void countStart(ServiceProvider<Service> serviceProvider) {
        startCounter.incrementAndGet();
        startServiceProvider.set(serviceProvider);
      }

      public void countStop() {
        stopCounter.incrementAndGet();
      }
    }

    @ServiceDependencies(TestProvidedService.class)
    class Consumer1 implements Service {
      final StartStopCounter startStopCounter = new StartStopCounter();

      @Override
      public void start(ServiceProvider<Service> serviceProvider) {
        assertThat(serviceProvider.getService(TestProvidedService.class), is(notNullValue()));
        startStopCounter.countStart(serviceProvider);
      }

      @Override
      public void stop() {
        startStopCounter.countStop();
      }
    }

    @ServiceDependencies(Consumer1.class)
    class Consumer2 implements Service {
      final StartStopCounter startStopCounter = new StartStopCounter();

      @Override
      public void start(ServiceProvider<Service> serviceProvider) {
        assertThat(serviceProvider.getService(Consumer1.class), is(notNullValue()));
        startStopCounter.countStart(serviceProvider);
      }

      @Override
      public void stop() {
        startStopCounter.countStop();
      }
    }

    @ServiceDependencies(Consumer2.class)
    class MyTestProvidedService extends DefaultTestProvidedService {
      final StartStopCounter startStopCounter = new StartStopCounter();

      @Override
      public void start(ServiceProvider<Service> serviceProvider) {
        assertThat(serviceProvider.getService(Consumer2.class), is(notNullValue()));
        startStopCounter.countStart(serviceProvider);
        super.start(serviceProvider);
      }

      @Override
      public void stop() {
        startStopCounter.countStop();
        super.stop();
      }
    }

    @ServiceDependencies(DependsOnMe.class)
    class DependsOnMe implements Service {
      final StartStopCounter startStopCounter = new StartStopCounter();

      @Override
      public void start(ServiceProvider<Service> serviceProvider) {
        assertThat(serviceProvider.getService(DependsOnMe.class), sameInstance(this));
        startStopCounter.countStart(serviceProvider);
      }

      @Override
      public void stop() {
        startStopCounter.countStop();
      }
    }

    ServiceLocator serviceLocator = new ServiceLocator();

    Consumer1 consumer1 = new Consumer1();
    Consumer2 consumer2 = new Consumer2();
    MyTestProvidedService myTestProvidedService = new MyTestProvidedService();
    DependsOnMe dependsOnMe = new DependsOnMe();

    // add some services
    serviceLocator.addService(consumer1);
    serviceLocator.addService(consumer2);
    serviceLocator.addService(myTestProvidedService);
    serviceLocator.addService(dependsOnMe);

    // simulate what is done in ehcachemanager
    serviceLocator.startAllServices();

    serviceLocator.stopAllServices();

    assertThat(consumer1.startStopCounter.startCounter.get(), is(1));
    assertThat(
        consumer1.startStopCounter.startServiceProvider.get(),
        CoreMatchers.<ServiceProvider<Service>>is(serviceLocator));
    assertThat(consumer2.startStopCounter.startCounter.get(), is(1));
    assertThat(
        consumer2.startStopCounter.startServiceProvider.get(),
        CoreMatchers.<ServiceProvider<Service>>is(serviceLocator));
    assertThat(myTestProvidedService.startStopCounter.startCounter.get(), is(1));
    assertThat(
        myTestProvidedService.startStopCounter.startServiceProvider.get(),
        CoreMatchers.<ServiceProvider<Service>>is(serviceLocator));
    assertThat(dependsOnMe.startStopCounter.startCounter.get(), is(1));
    assertThat(
        dependsOnMe.startStopCounter.startServiceProvider.get(),
        CoreMatchers.<ServiceProvider<Service>>is(serviceLocator));

    assertThat(consumer1.startStopCounter.stopCounter.get(), is(1));
    assertThat(consumer2.startStopCounter.stopCounter.get(), is(1));
    assertThat(myTestProvidedService.startStopCounter.stopCounter.get(), is(1));
    assertThat(dependsOnMe.startStopCounter.stopCounter.get(), is(1));
  }
  @Test
  public void testRedefineDefaultServiceWhileDependingOnIt() throws Exception {
    ServiceLocator serviceLocator = new ServiceLocator(new YetAnotherCacheProvider());

    serviceLocator.startAllServices();
  }