package com.lambdaworks.redis.cluster.topology; import static com.lambdaworks.redis.cluster.topology.TopologyComparators.isChanged; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.util.Lists.newArrayList; import java.util.*; import com.lambdaworks.redis.RedisURI; import org.junit.Test; import com.lambdaworks.redis.cluster.models.partitions.ClusterPartitionParser; import com.lambdaworks.redis.cluster.models.partitions.Partitions; import com.lambdaworks.redis.cluster.models.partitions.RedisClusterNode; import com.lambdaworks.redis.internal.LettuceLists; /** * @author Mark Paluch */ public class TopologyComparatorsTest { private RedisClusterNodeSnapshot node1 = createNode("1"); private RedisClusterNodeSnapshot node2 = createNode("2"); private RedisClusterNodeSnapshot node3 = createNode("3"); private static RedisClusterNodeSnapshot createNode(String nodeId) { RedisClusterNodeSnapshot result = new RedisClusterNodeSnapshot(); result.setNodeId(nodeId); result.setUri(RedisURI.create("localhost", Integer.parseInt(nodeId))); return result; } @Test public void latenciesForAllNodes() throws Exception { Map<String, Long> map = new HashMap<>(); map.put(node1.getNodeId(), 1L); map.put(node2.getNodeId(), 2L); map.put(node3.getNodeId(), 3L); runTest(map, newArrayList(node1, node2, node3), newArrayList(node3, node1, node2)); runTest(map, newArrayList(node1, node2, node3), newArrayList(node1, node2, node3)); runTest(map, newArrayList(node1, node2, node3), newArrayList(node3, node2, node1)); } @Test public void latenciesForTwoNodes_N1_N2() throws Exception { Map<String, Long> map = new HashMap<>(); map.put(node1.getNodeId(), 1L); map.put(node2.getNodeId(), 2L); runTest(map, newArrayList(node1, node2, node3), newArrayList(node3, node1, node2)); runTest(map, newArrayList(node1, node2, node3), newArrayList(node1, node2, node3)); runTest(map, newArrayList(node1, node2, node3), newArrayList(node3, node2, node1)); } @Test public void latenciesForTwoNodes_N2_N3() throws Exception { Map<String, Long> map = new HashMap<>(); map.put(node3.getNodeId(), 1L); map.put(node2.getNodeId(), 2L); runTest(map, newArrayList(node3, node2, node1), newArrayList(node3, node1, node2)); runTest(map, newArrayList(node3, node2, node1), newArrayList(node1, node2, node3)); runTest(map, newArrayList(node3, node2, node1), newArrayList(node3, node2, node1)); } @Test public void latenciesForOneNode() throws Exception { Map<String, Long> map = Collections.singletonMap(node2.getNodeId(), 2L); runTest(map, newArrayList(node2, node3, node1), newArrayList(node3, node1, node2)); runTest(map, newArrayList(node2, node1, node3), newArrayList(node1, node2, node3)); runTest(map, newArrayList(node2, node3, node1), newArrayList(node3, node2, node1)); } @Test(expected = AssertionError.class) public void shouldFail() throws Exception { Map<String, Long> map = Collections.singletonMap(node2.getNodeId(), 2L); runTest(map, newArrayList(node2, node1, node3), newArrayList(node3, node1, node2)); } @Test public void testLatencyComparator() throws Exception { RedisClusterNodeSnapshot node1 = new RedisClusterNodeSnapshot(); node1.setLatencyNs(1L); RedisClusterNodeSnapshot node2 = new RedisClusterNodeSnapshot(); node2.setLatencyNs(2L); RedisClusterNodeSnapshot node3 = new RedisClusterNodeSnapshot(); node3.setLatencyNs(3L); List<RedisClusterNodeSnapshot> list = LettuceLists.newList(node2, node3, node1); Collections.sort(list, TopologyComparators.LatencyComparator.INSTANCE); assertThat(list).containsSequence(node1, node2, node3); } @Test public void testLatencyComparatorWithSomeNodesWithoutStats() throws Exception { RedisClusterNodeSnapshot node1 = new RedisClusterNodeSnapshot(); node1.setLatencyNs(1L); RedisClusterNodeSnapshot node2 = new RedisClusterNodeSnapshot(); node2.setLatencyNs(2L); RedisClusterNodeSnapshot node3 = new RedisClusterNodeSnapshot(); RedisClusterNodeSnapshot node4 = new RedisClusterNodeSnapshot(); List<RedisClusterNodeSnapshot> list = LettuceLists.newList(node2, node3, node4, node1); Collections.sort(list, TopologyComparators.LatencyComparator.INSTANCE); assertThat(list).containsSequence(node1, node2, node3, node4); } @Test public void testClientComparator() throws Exception { RedisClusterNodeSnapshot node1 = new RedisClusterNodeSnapshot(); node1.setConnectedClients(1); RedisClusterNodeSnapshot node2 = new RedisClusterNodeSnapshot(); node2.setConnectedClients(2); RedisClusterNodeSnapshot node3 = new RedisClusterNodeSnapshot(); node3.setConnectedClients(3); List<RedisClusterNodeSnapshot> list = LettuceLists.newList(node2, node3, node1); Collections.sort(list, TopologyComparators.ClientCountComparator.INSTANCE); assertThat(list).containsSequence(node1, node2, node3); } @Test public void testClientComparatorWithSomeNodesWithoutStats() throws Exception { RedisClusterNodeSnapshot node1 = new RedisClusterNodeSnapshot(); node1.setConnectedClients(1); RedisClusterNodeSnapshot node2 = new RedisClusterNodeSnapshot(); node2.setConnectedClients(2); RedisClusterNodeSnapshot node3 = new RedisClusterNodeSnapshot(); RedisClusterNodeSnapshot node4 = new RedisClusterNodeSnapshot(); List<RedisClusterNodeSnapshot> list = LettuceLists.newList(node2, node3, node4, node1); Collections.sort(list, TopologyComparators.ClientCountComparator.INSTANCE); assertThat(list).containsSequence(node1, node2, node3, node4); } @Test public void testLatencyComparatorWithoutClients() throws Exception { RedisClusterNodeSnapshot node1 = new RedisClusterNodeSnapshot(); node1.setConnectedClients(1); RedisClusterNodeSnapshot node2 = new RedisClusterNodeSnapshot(); node2.setConnectedClients(null); RedisClusterNodeSnapshot node3 = new RedisClusterNodeSnapshot(); node3.setConnectedClients(3); List<RedisClusterNodeSnapshot> list = LettuceLists.newList(node2, node3, node1); Collections.sort(list, TopologyComparators.LatencyComparator.INSTANCE); assertThat(list).containsSequence(node1, node3, node2); } @Test public void testFixedOrdering1() throws Exception { List<RedisClusterNode> list = LettuceLists.newList(node2, node3, node1); List<RedisURI> fixedOrder = LettuceLists.newList(node1.getUri(), node2.getUri(), node3.getUri()); assertThat(TopologyComparators.predefinedSort(list, fixedOrder)).containsSequence(node1, node2, node3); } @Test public void testFixedOrdering2() throws Exception { List<RedisClusterNode> list = LettuceLists.newList(node2, node3, node1); List<RedisURI> fixedOrder = LettuceLists.newList(node3.getUri(), node2.getUri(), node1.getUri()); assertThat(TopologyComparators.predefinedSort(list, fixedOrder)).containsSequence(node3, node2, node1); } @Test public void testFixedOrderingNoFixedPart() throws Exception { List<RedisClusterNode> list = LettuceLists.newList(node2, node3, node1); List<RedisURI> fixedOrder = LettuceLists.newList(); assertThat(TopologyComparators.predefinedSort(list, fixedOrder)).containsSequence(node1, node2, node3); } @Test public void testFixedOrderingPartiallySpecifiedOrder() throws Exception { List<RedisClusterNode> list = LettuceLists.newList(node2, node3, node1); List<RedisURI> fixedOrder = LettuceLists.newList(node3.getUri(), node1.getUri()); assertThat(TopologyComparators.predefinedSort(list, fixedOrder)).containsSequence(node3, node1, node2); } @Test public void isChangedSamePartitions() throws Exception { String nodes = "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n" + "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 master - 0 1401258245007 2 disconnected 8000-11999\n"; Partitions partitions1 = ClusterPartitionParser.parse(nodes); Partitions partitions2 = ClusterPartitionParser.parse(nodes); assertThat(isChanged(partitions1, partitions2)).isFalse(); } @Test public void isChangedDifferentOrder() throws Exception { String nodes1 = "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 master,myself - 0 1401258245007 2 disconnected 8000-11999\n" + "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n"; String nodes2 = "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master,myself - 111 1401258245007 222 connected 7000 12000 12002-16383\n" + "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 master - 0 1401258245007 2 disconnected 8000-11999\n"; assertThat(nodes1).isNotEqualTo(nodes2); Partitions partitions1 = ClusterPartitionParser.parse(nodes1); Partitions partitions2 = ClusterPartitionParser.parse(nodes2); assertThat(isChanged(partitions1, partitions2)).isFalse(); } @Test public void isChangedPortChanged() throws Exception { String nodes1 = "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7382 master - 0 1401258245007 2 disconnected 8000-11999\n" + "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n"; String nodes2 = "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n" + "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 master - 0 1401258245007 2 disconnected 8000-11999\n"; Partitions partitions1 = ClusterPartitionParser.parse(nodes1); Partitions partitions2 = ClusterPartitionParser.parse(nodes2); assertThat(isChanged(partitions1, partitions2)).isFalse(); } @Test public void isChangedSlotsChanged() throws Exception { String nodes1 = "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 master - 0 1401258245007 2 disconnected 8000-11999\n" + "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n"; String nodes2 = "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 master - 0 1401258245007 2 disconnected 8000-11999\n" + "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12001-16383\n"; Partitions partitions1 = ClusterPartitionParser.parse(nodes1); Partitions partitions2 = ClusterPartitionParser.parse(nodes2); assertThat(isChanged(partitions1, partitions2)).isTrue(); } @Test public void isChangedNodeIdChanged() throws Exception { String nodes1 = "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 master - 0 1401258245007 2 disconnected 8000-11999\n" + "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n"; String nodes2 = "3d005a179da7d8dc1adae6409d47b39c369e992aa 127.0.0.1:7380 master - 0 1401258245007 2 disconnected 8000-11999\n" + "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n"; Partitions partitions1 = ClusterPartitionParser.parse(nodes1); Partitions partitions2 = ClusterPartitionParser.parse(nodes2); assertThat(isChanged(partitions1, partitions2)).isTrue(); } @Test public void isChangedFlagsChangedSlaveToMaster() throws Exception { String nodes1 = "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 slave - 0 1401258245007 2 disconnected 8000-11999\n" + "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n"; String nodes2 = "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 master - 0 1401258245007 2 disconnected 8000-11999\n" + "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n"; Partitions partitions1 = ClusterPartitionParser.parse(nodes1); Partitions partitions2 = ClusterPartitionParser.parse(nodes2); assertThat(isChanged(partitions1, partitions2)).isTrue(); } @Test public void isChangedFlagsChangedMasterToSlave() throws Exception { String nodes1 = "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 master - 0 1401258245007 2 disconnected 8000-11999\n" + "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n"; String nodes2 = "3d005a179da7d8dc1adae6409d47b39c369e992b 127.0.0.1:7380 slave - 0 1401258245007 2 disconnected 8000-11999\n" + "c37ab8396be428403d4e55c0d317348be27ed973 127.0.0.1:7381 master - 111 1401258245007 222 connected 7000 12000 12002-16383\n"; Partitions partitions1 = ClusterPartitionParser.parse(nodes1); Partitions partitions2 = ClusterPartitionParser.parse(nodes2); assertThat(isChanged(partitions1, partitions2)).isTrue(); } protected void runTest(Map<String, Long> map, List<RedisClusterNodeSnapshot> expectation, List<RedisClusterNodeSnapshot> nodes) { for (RedisClusterNodeSnapshot node : nodes) { node.setLatencyNs(map.get(node.getNodeId())); } List<RedisClusterNode> result = TopologyComparators.sortByLatency((Iterable) nodes); assertThat(result).containsExactly(expectation.toArray(new RedisClusterNodeSnapshot[expectation.size()])); } }