package com.liveramp.hank.partition_assigner;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import com.liveramp.hank.coordinator.Domain;
import com.liveramp.hank.coordinator.Host;
import com.liveramp.hank.coordinator.PartitionServerAddress;
import com.liveramp.hank.coordinator.mock.MockDomain;
import com.liveramp.hank.test.BaseTestCase;
import com.liveramp.hank.test.coordinator.MockHost;
import static org.junit.Assert.assertEquals;
public class TestRendezVousPartitionAssigner extends BaseTestCase {
private final Host host1 = new MockHost(new PartitionServerAddress("host1", 0));
private final Host host2 = new MockHost(new PartitionServerAddress("host2", 0));
private final Host host3 = new MockHost(new PartitionServerAddress("host3", 0));
@Test
public void testMain() {
Map<Integer, Host> mappings;
mappings = getPartitionAssignment(1, host1);
assertEquals(1, mappings.size());
assertEquals(host1, mappings.get(0));
mappings = getPartitionAssignment(1, host1, host2, host3);
assertEquals(1, numPartitionsAssigned(host1, mappings));
mappings = getPartitionAssignment(2, host1, host2, host3);
assertEquals(2, mappings.size());
assertEquals(1, numPartitionsAssigned(host1, mappings));
assertEquals(0, numPartitionsAssigned(host2, mappings));
assertEquals(1, numPartitionsAssigned(host3, mappings));
mappings = getPartitionAssignment(3, host1, host2, host3);
assertEquals(3, mappings.size());
assertEquals(1, numPartitionsAssigned(host1, mappings));
assertEquals(1, numPartitionsAssigned(host2, mappings));
assertEquals(1, numPartitionsAssigned(host3, mappings));
mappings = getPartitionAssignment(4, host1, host2, host3);
assertEquals(4, mappings.size());
assertEquals(2, numPartitionsAssigned(host1, mappings));
assertEquals(0, numPartitionsAssigned(host2, mappings));
assertEquals(2, numPartitionsAssigned(host3, mappings));
mappings = getPartitionAssignment(5, host1, host2, host3);
assertEquals(5, mappings.size());
assertEquals(2, numPartitionsAssigned(host1, mappings));
assertEquals(2, numPartitionsAssigned(host2, mappings));
assertEquals(1, numPartitionsAssigned(host3, mappings));
mappings = getPartitionAssignment(6, host1, host2, host3);
assertEquals(6, mappings.size());
assertEquals(2, numPartitionsAssigned(host1, mappings));
assertEquals(2, numPartitionsAssigned(host2, mappings));
assertEquals(2, numPartitionsAssigned(host3, mappings));
}
private int numPartitionsAssigned(Host host, Map<Integer, Host> mapppings) {
int result = 0;
for (Map.Entry<Integer, Host> entry : mapppings.entrySet()) {
if (entry.getValue().equals(host)) {
++result;
}
}
return result;
}
@Test
public void testConsistency() {
final int numPartitions = 1000;
Map<Integer, Host> mappingsA = getPartitionAssignment(numPartitions, host1, host2, host3);
assertEquals(numPartitions, mappingsA.size());
Map<Integer, Host> mappingsB = getPartitionAssignment(numPartitions, host1, null, host3);
assertEquals(numPartitions, mappingsB.size());
int consistent = 0;
for (int partitionId = 0; partitionId < numPartitions; ++partitionId) {
if (mappingsA.get(partitionId).equals(mappingsB.get(partitionId))) {
++consistent;
}
}
assertEquals(665, consistent);
}
@Test
public void testDependsOnlyOnOrder() {
final int numPartitions = 1000;
Map<Integer, Host> mappingsA = getPartitionAssignment(numPartitions, host1, host2, host3);
assertEquals(numPartitions, mappingsA.size());
Map<Integer, Host> mappingsB = getPartitionAssignment(numPartitions, host2, host3, host1);
assertEquals(numPartitions, mappingsB.size());
assertEquals(partitionsAssignedTo(host1, mappingsA), partitionsAssignedTo(host2, mappingsB));
assertEquals(partitionsAssignedTo(host2, mappingsA), partitionsAssignedTo(host3, mappingsB));
assertEquals(partitionsAssignedTo(host3, mappingsA), partitionsAssignedTo(host1, mappingsB));
}
private List<Integer> partitionsAssignedTo(Host host, Map<Integer, Host> assignments) {
List<Integer> result = new ArrayList<Integer>();
for (Map.Entry<Integer, Host> entry : assignments.entrySet()) {
if (entry.getValue().equals(host)) {
result.add(entry.getKey());
}
}
return result;
}
private Map<Integer, Host> getPartitionAssignment(int numPartitions, Host... hosts) {
List<AbstractMappingPartitionAssigner.HostAndIndexInRing> hostAndIndexInRings = new ArrayList<AbstractMappingPartitionAssigner.HostAndIndexInRing>();
for (int i = 0; i < hosts.length; ++i) {
Host host = hosts[i];
if (host != null) {
hostAndIndexInRings.add(new AbstractMappingPartitionAssigner.HostAndIndexInRing(host, i));
}
}
RendezVousPartitionAssigner partitionAssigner = new RendezVousPartitionAssigner();
Domain domain = new MockDomain("domain", 0, numPartitions, null, null, null, null);
return partitionAssigner.getPartitionsAssignment(domain, hostAndIndexInRings);
}
}