package com.lambdaworks.redis.cluster; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.*; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import com.lambdaworks.redis.ReadFrom; import com.lambdaworks.redis.RedisChannelWriter; import com.lambdaworks.redis.RedisException; import com.lambdaworks.redis.RedisURI; import com.lambdaworks.redis.api.StatefulRedisConnection; import com.lambdaworks.redis.api.sync.RedisCommands; import com.lambdaworks.redis.cluster.ClusterConnectionProvider.Intent; import com.lambdaworks.redis.cluster.models.partitions.Partitions; import com.lambdaworks.redis.cluster.models.partitions.RedisClusterNode; import com.lambdaworks.redis.codec.Utf8StringCodec; /** * @author Mark Paluch */ @RunWith(MockitoJUnitRunner.class) public class PooledClusterConnectionProviderTest { public static final Utf8StringCodec CODEC = new Utf8StringCodec(); private PooledClusterConnectionProvider<String, String> sut; @Mock private RedisClusterClient clientMock; @Mock private RedisChannelWriter<String, String> writerMock; @Mock StatefulRedisConnection<String, String> nodeConnectionMock; @Mock RedisCommands<String, String> commandsMock; private Partitions partitions = new Partitions(); @Before public void before() throws Exception { sut = new PooledClusterConnectionProvider<>(clientMock, writerMock, CODEC); List<Integer> slots1 = IntStream.range(0, 8192).boxed().collect(Collectors.toList()); List<Integer> slots2 = IntStream.range(8192, SlotHash.SLOT_COUNT).boxed().collect(Collectors.toList()); partitions.add(new RedisClusterNode(RedisURI.create("localhost", 1), "1", true, null, 0, 0, 0, slots1, Collections.singleton(RedisClusterNode.NodeFlag.MASTER))); partitions.add(new RedisClusterNode(RedisURI.create("localhost", 2), "2", true, "1", 0, 0, 0, slots2, Collections.singleton(RedisClusterNode.NodeFlag.SLAVE))); sut.setPartitions(partitions); when(nodeConnectionMock.sync()).thenReturn(commandsMock); } @Test public void shouldObtainConnection() throws Exception { when(clientMock.connectToNode(eq(CODEC), eq("localhost:1"), any(), any())).thenReturn(nodeConnectionMock); StatefulRedisConnection<String, String> connection = sut.getConnection(Intent.READ, 1); assertThat(connection).isSameAs(nodeConnectionMock); verify(connection).setAutoFlushCommands(true); verifyNoMoreInteractions(connection); } @Test public void shouldObtainConnectionReadFromSlave() throws Exception { when(clientMock.connectToNode(eq(CODEC), eq("localhost:2"), any(), any())).thenReturn(nodeConnectionMock); sut.setReadFrom(ReadFrom.SLAVE); StatefulRedisConnection<String, String> connection = sut.getConnection(Intent.READ, 1); assertThat(connection).isSameAs(nodeConnectionMock); verify(connection).sync(); verify(commandsMock).readOnly(); verify(connection).setAutoFlushCommands(true); } @Test public void shouldCloseConnectionOnConnectFailure() throws Exception { when(clientMock.connectToNode(eq(CODEC), eq("localhost:2"), any(), any())).thenReturn(nodeConnectionMock); doThrow(new RuntimeException()).when(commandsMock).readOnly(); sut.setReadFrom(ReadFrom.SLAVE); try { sut.getConnection(Intent.READ, 1); fail("Missing RedisException"); } catch (RedisException e) { assertThat(e).hasRootCauseInstanceOf(RuntimeException.class); } verify(nodeConnectionMock).close(); verify(clientMock).connectToNode(eq(CODEC), eq("localhost:2"), any(), any()); } @Test public void shouldRetryConnectionAttemptAfterConnectionAttemptWasBroken() throws Exception { when(clientMock.connectToNode(eq(CODEC), eq("localhost:2"), any(), any())).thenReturn(nodeConnectionMock); doThrow(new RuntimeException()).when(commandsMock).readOnly(); sut.setReadFrom(ReadFrom.SLAVE); try { sut.getConnection(Intent.READ, 1); fail("Missing RedisException"); } catch (RedisException e) { assertThat(e).hasRootCauseInstanceOf(RuntimeException.class); } verify(nodeConnectionMock).close(); doReturn("OK").when(commandsMock).readOnly(); sut.getConnection(Intent.READ, 1); verify(clientMock, times(2)).connectToNode(eq(CODEC), eq("localhost:2"), any(), any()); } }