/* * Copyright Terracotta, Inc. * * 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.ehcache.impl.internal.classes; import org.ehcache.spi.service.ServiceProvider; import org.ehcache.spi.service.Service; import org.ehcache.spi.service.ServiceConfiguration; import org.junit.Test; import java.io.Closeable; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; import static org.hamcrest.core.Is.is; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; /** * @author Ludovic Orban */ public class ClassInstanceProviderTest { @SuppressWarnings("unchecked") private Class<ClassInstanceConfiguration<TestService>> configClass = (Class)ClassInstanceConfiguration.class; @Test public void testNewInstanceUsingAliasAndNoArgs() throws Exception { ClassInstanceProvider<String, TestService> classInstanceProvider = new ClassInstanceProvider<String, TestService>(null, configClass); classInstanceProvider.preconfigured.put("test stuff", new ClassInstanceConfiguration<TestService>(TestService.class)); TestService obj = classInstanceProvider.newInstance("test stuff", (ServiceConfiguration) null); assertThat(obj.theString, is(nullValue())); } @Test public void testNewInstanceUsingAliasAndArg() throws Exception { ClassInstanceProvider<String, TestService> classInstanceProvider = new ClassInstanceProvider<String, TestService>(null, configClass); classInstanceProvider.preconfigured.put("test stuff", new ClassInstanceConfiguration<TestService>(TestService.class, "test string")); TestService obj = classInstanceProvider.newInstance("test stuff", (ServiceConfiguration<?>) null); assertThat(obj.theString, equalTo("test string")); } @Test public void testNewInstanceUsingServiceConfig() throws Exception { ClassInstanceProvider<String, TestService> classInstanceProvider = new ClassInstanceProvider<String, TestService>(null, configClass); TestServiceConfiguration config = new TestServiceConfiguration(); TestService obj = classInstanceProvider.newInstance("test stuff", config); assertThat(obj.theString, is(nullValue())); } @Test public void testNewInstanceUsingServiceConfigFactory() throws Exception { TestServiceProviderConfiguration factoryConfig = new TestServiceProviderConfiguration(); factoryConfig.getDefaults().put("test stuff", new ClassInstanceConfiguration<TestService>(TestService.class)); ClassInstanceProvider<String, TestService> classInstanceProvider = new ClassInstanceProvider<String, TestService>(factoryConfig, configClass); classInstanceProvider.start(null); TestService obj = classInstanceProvider.newInstance("test stuff", (ServiceConfiguration) null); assertThat(obj.theString, is(nullValue())); } @Test(expected = IllegalArgumentException.class) public void testReleaseInstanceByAnotherProvider() throws Exception { ClassInstanceProvider<String, String> classInstanceProvider = new ClassInstanceProvider<String, String>(null, null); classInstanceProvider.releaseInstance("foo"); } @Test(expected = IllegalArgumentException.class) public void testReleaseSameInstanceMultipleTimesThrows() throws Exception { ClassInstanceProvider<String, String> classInstanceProvider = new ClassInstanceProvider<String, String>(null, null); classInstanceProvider.providedVsCount.put("foo", new AtomicInteger(1)); classInstanceProvider.releaseInstance("foo"); classInstanceProvider.releaseInstance("foo"); } @Test public void testReleaseCloseableInstance() throws Exception { ClassInstanceProvider<String, Closeable> classInstanceProvider = new ClassInstanceProvider<String, Closeable>(null, null); Closeable closeable = mock(Closeable.class); classInstanceProvider.providedVsCount.put(closeable, new AtomicInteger(1)); classInstanceProvider.instantiated.add(closeable); classInstanceProvider.releaseInstance(closeable); verify(closeable).close(); } @Test(expected = IOException.class) public void testReleaseCloseableInstanceThrows() throws Exception { ClassInstanceProvider<String, Closeable> classInstanceProvider = new ClassInstanceProvider<String, Closeable>(null, null); Closeable closeable = mock(Closeable.class); doThrow(IOException.class).when(closeable).close(); classInstanceProvider.providedVsCount.put(closeable, new AtomicInteger(1)); classInstanceProvider.instantiated.add(closeable); classInstanceProvider.releaseInstance(closeable); } @Test public void testNewInstanceWithActualInstanceInServiceConfig() throws Exception { ClassInstanceProvider<String, TestService> classInstanceProvider = new ClassInstanceProvider<String, TestService>(null, configClass); TestService service = new TestService(); TestServiceConfiguration config = new TestServiceConfiguration(service); TestService newService = classInstanceProvider.newInstance("test stuff", config); assertThat(newService, sameInstance(service)); } @Test public void testSameInstanceRetrievedMultipleTimesUpdatesTheProvidedCount() throws Exception { ClassInstanceProvider<String, TestService> classInstanceProvider = new ClassInstanceProvider<String, TestService>(null, configClass); TestService service = new TestService(); TestServiceConfiguration config = new TestServiceConfiguration(service); TestService newService = classInstanceProvider.newInstance("test stuff", config); assertThat(newService, sameInstance(service)); assertThat(classInstanceProvider.providedVsCount.get(service).get(), is(1)); newService = classInstanceProvider.newInstance("test stuff", config); assertThat(newService, sameInstance(service)); assertThat(classInstanceProvider.providedVsCount.get(service).get(), is(2)); } @Test public void testInstancesNotCreatedByProviderDoesNotClose() throws IOException { @SuppressWarnings("unchecked") Class<ClassInstanceConfiguration<TestCloaseableService>> configClass = (Class) ClassInstanceConfiguration.class; ClassInstanceProvider<String, TestCloaseableService> classInstanceProvider = new ClassInstanceProvider<String, TestCloaseableService>(null, configClass); TestCloaseableService service = mock(TestCloaseableService.class); TestCloaseableServiceConfig config = new TestCloaseableServiceConfig(service); TestCloaseableService newService = classInstanceProvider.newInstance("testClose", config); assertThat(newService, sameInstance(service)); classInstanceProvider.releaseInstance(newService); verify(service, times(0)).close(); } public static abstract class TestCloaseableService implements Service, Closeable { } public static class TestCloaseableServiceConfig extends ClassInstanceConfiguration<TestCloaseableService> implements ServiceConfiguration<TestCloaseableService> { public TestCloaseableServiceConfig() { super(TestCloaseableService.class); } public TestCloaseableServiceConfig(TestCloaseableService testCloaseableService) { super(testCloaseableService); } @Override public Class<TestCloaseableService> getServiceType() { return TestCloaseableService.class; } } public static class TestService implements Service { public final String theString; public TestService() { this(null); } public TestService(String theString) { this.theString = theString; } @Override public void start(ServiceProvider<Service> serviceProvider) { } @Override public void stop() { } } public static class TestServiceConfiguration extends ClassInstanceConfiguration<TestService> implements ServiceConfiguration<TestService> { public TestServiceConfiguration() { super(TestService.class); } public TestServiceConfiguration(TestService service) { super(service); } @Override public Class<TestService> getServiceType() { return TestService.class; } } public static class TestServiceProviderConfiguration extends ClassInstanceProviderConfiguration<String, TestService> implements ServiceConfiguration<TestService> { @Override public Class<TestService> getServiceType() { return TestService.class; } } }