package com.lambdaworks.redis.resource; import static com.google.code.tempusfugit.temporal.Duration.seconds; import static com.google.code.tempusfugit.temporal.Timeout.timeout; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import java.util.concurrent.TimeUnit; import org.junit.Test; import com.google.code.tempusfugit.temporal.Condition; import com.google.code.tempusfugit.temporal.WaitFor; import com.lambdaworks.redis.FastShutdown; import com.lambdaworks.redis.event.Event; import com.lambdaworks.redis.event.EventBus; import com.lambdaworks.redis.metrics.CommandLatencyCollector; import com.lambdaworks.redis.metrics.DefaultCommandLatencyCollectorOptions; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.concurrent.EventExecutorGroup; import io.netty.util.concurrent.Future; import rx.observers.TestSubscriber; /** * @author Mark Paluch */ public class DefaultClientResourcesTest { @Test public void testDefaults() throws Exception { DefaultClientResources sut = DefaultClientResources.create(); assertThat(sut.commandLatencyCollector()).isNotNull(); assertThat(sut.commandLatencyCollector().isEnabled()).isTrue(); EventExecutorGroup eventExecutors = sut.eventExecutorGroup(); NioEventLoopGroup eventLoopGroup = sut.eventLoopGroupProvider().allocate(NioEventLoopGroup.class); eventExecutors.next().submit(mock(Runnable.class)); eventLoopGroup.next().submit(mock(Runnable.class)); assertThat(sut.shutdown(0, 0, TimeUnit.SECONDS).get()).isTrue(); assertThat(eventExecutors.isTerminated()).isTrue(); assertThat(eventLoopGroup.isTerminated()).isTrue(); Future<Boolean> shutdown = sut.eventLoopGroupProvider().shutdown(0, 0, TimeUnit.SECONDS); assertThat(shutdown.get()).isTrue(); assertThat(sut.commandLatencyCollector().isEnabled()).isFalse(); } @Test public void testBuilder() throws Exception { DefaultClientResources sut = new DefaultClientResources.Builder().ioThreadPoolSize(4).computationThreadPoolSize(4) .commandLatencyCollectorOptions(DefaultCommandLatencyCollectorOptions.disabled()).build(); EventExecutorGroup eventExecutors = sut.eventExecutorGroup(); NioEventLoopGroup eventLoopGroup = sut.eventLoopGroupProvider().allocate(NioEventLoopGroup.class); assertThat(eventExecutors.iterator()).hasSize(4); assertThat(eventLoopGroup.executorCount()).isEqualTo(4); assertThat(sut.ioThreadPoolSize()).isEqualTo(4); assertThat(sut.commandLatencyCollector()).isNotNull(); assertThat(sut.commandLatencyCollector().isEnabled()).isFalse(); assertThat(sut.shutdown(0, 0, TimeUnit.MILLISECONDS).get()).isTrue(); } @Test public void testDnsResolver() throws Exception { DirContextDnsResolver dirContextDnsResolver = new DirContextDnsResolver("8.8.8.8"); DefaultClientResources sut = new DefaultClientResources.Builder().dnsResolver(dirContextDnsResolver).build(); assertThat(sut.dnsResolver()).isEqualTo(dirContextDnsResolver); } @Test public void testProvidedResources() throws Exception { EventExecutorGroup executorMock = mock(EventExecutorGroup.class); EventLoopGroupProvider groupProviderMock = mock(EventLoopGroupProvider.class); EventBus eventBusMock = mock(EventBus.class); CommandLatencyCollector latencyCollectorMock = mock(CommandLatencyCollector.class); DefaultClientResources sut = new DefaultClientResources.Builder().eventExecutorGroup(executorMock) .eventLoopGroupProvider(groupProviderMock).eventBus(eventBusMock).commandLatencyCollector(latencyCollectorMock) .build(); assertThat(sut.eventExecutorGroup()).isSameAs(executorMock); assertThat(sut.eventLoopGroupProvider()).isSameAs(groupProviderMock); assertThat(sut.eventBus()).isSameAs(eventBusMock); assertThat(sut.shutdown().get()).isTrue(); verifyZeroInteractions(executorMock); verifyZeroInteractions(groupProviderMock); verify(latencyCollectorMock).isEnabled(); verifyNoMoreInteractions(latencyCollectorMock); } @Test public void testSmallPoolSize() throws Exception { DefaultClientResources sut = new DefaultClientResources.Builder().ioThreadPoolSize(1).computationThreadPoolSize(1) .build(); EventExecutorGroup eventExecutors = sut.eventExecutorGroup(); NioEventLoopGroup eventLoopGroup = sut.eventLoopGroupProvider().allocate(NioEventLoopGroup.class); assertThat(eventExecutors.iterator()).hasSize(3); assertThat(eventLoopGroup.executorCount()).isEqualTo(3); assertThat(sut.ioThreadPoolSize()).isEqualTo(3); assertThat(sut.shutdown(0, 0, TimeUnit.MILLISECONDS).get()).isTrue(); } @Test public void testEventBus() throws Exception { DefaultClientResources sut = DefaultClientResources.create(); EventBus eventBus = sut.eventBus(); final TestSubscriber<Event> subject = new TestSubscriber<Event>(); eventBus.get().subscribe(subject); Event event = mock(Event.class); eventBus.publish(event); WaitFor.waitOrTimeout(new Condition() { @Override public boolean isSatisfied() { return !subject.getOnNextEvents().isEmpty(); } }, timeout(seconds(2))); assertThat(subject.getOnNextEvents()).contains(event); assertThat(sut.shutdown(0, 0, TimeUnit.MILLISECONDS).get()).isTrue(); } @Test(expected = IllegalArgumentException.class) public void delayInstanceShouldRejectStatefulDelay() throws Exception { DefaultClientResources.builder().reconnectDelay(Delay.decorrelatedJitter().get()); } @Test public void reconnectDelayCreatesNewForStatefulDelays() throws Exception { DefaultClientResources resources = DefaultClientResources.builder().reconnectDelay(Delay.decorrelatedJitter()).build(); Delay delay1 = resources.reconnectDelay(); Delay delay2 = resources.reconnectDelay(); assertThat(delay1).isNotSameAs(delay2); FastShutdown.shutdown(resources); } @Test public void reconnectDelayReturnsSameInstanceForStatelessDelays() throws Exception { DefaultClientResources resources = DefaultClientResources.builder().reconnectDelay(Delay.exponential()).build(); Delay delay1 = resources.reconnectDelay(); Delay delay2 = resources.reconnectDelay(); assertThat(delay1).isSameAs(delay2); FastShutdown.shutdown(resources); } }