package com.netflix.eureka.cluster;
import java.util.List;
import java.util.concurrent.TimeUnit;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.discovery.shared.transport.ClusterSampleData;
import com.netflix.eureka.EurekaServerConfig;
import com.netflix.eureka.registry.PeerAwareInstanceRegistry;
import com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl.Action;
import com.netflix.eureka.cluster.TestableHttpReplicationClient.HandledRequest;
import com.netflix.eureka.cluster.TestableHttpReplicationClient.RequestType;
import com.netflix.eureka.cluster.protocol.ReplicationInstance;
import com.netflix.eureka.cluster.protocol.ReplicationList;
import com.netflix.eureka.resources.ASGResource.ASGStatus;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
/**
* @author Tomasz Bak
*/
public class PeerEurekaNodeTest {
private static final int BATCH_SIZE = 10;
private static final long MAX_BATCHING_DELAY_MS = 10;
private final PeerAwareInstanceRegistry registry = mock(PeerAwareInstanceRegistry.class);
private final TestableHttpReplicationClient httpReplicationClient = new TestableHttpReplicationClient();
private final InstanceInfo instanceInfo = ClusterSampleData.newInstanceInfo(1);
private PeerEurekaNode peerEurekaNode;
@Before
public void setUp() throws Exception {
httpReplicationClient.withNetworkStatusCode(200);
httpReplicationClient.withBatchReply(200);
}
@After
public void tearDown() throws Exception {
if (peerEurekaNode != null) {
peerEurekaNode.shutDown();
}
}
@Test
public void testRegistrationBatchReplication() throws Exception {
createPeerEurekaNode().register(instanceInfo);
ReplicationInstance replicationInstance = expectSingleBatchRequest();
assertThat(replicationInstance.getAction(), is(equalTo(Action.Register)));
}
@Test
public void testCancelBatchReplication() throws Exception {
createPeerEurekaNode().cancel(instanceInfo.getAppName(), instanceInfo.getId());
ReplicationInstance replicationInstance = expectSingleBatchRequest();
assertThat(replicationInstance.getAction(), is(equalTo(Action.Cancel)));
}
@Test
public void testHeartbeatBatchReplication() throws Throwable {
createPeerEurekaNode().heartbeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null, false);
ReplicationInstance replicationInstance = expectSingleBatchRequest();
assertThat(replicationInstance.getAction(), is(equalTo(Action.Heartbeat)));
}
@Test
public void testHeartbeatReplicationFailure() throws Throwable {
httpReplicationClient.withNetworkStatusCode(200, 200);
httpReplicationClient.withBatchReply(404); // Not found, to trigger registration
createPeerEurekaNode().heartbeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null, false);
// Heartbeat replied with an error
ReplicationInstance replicationInstance = expectSingleBatchRequest();
assertThat(replicationInstance.getAction(), is(equalTo(Action.Heartbeat)));
// Second, registration task is scheduled
replicationInstance = expectSingleBatchRequest();
assertThat(replicationInstance.getAction(), is(equalTo(Action.Register)));
}
@Test
public void testHeartbeatWithInstanceInfoFromPeer() throws Throwable {
InstanceInfo instanceInfoFromPeer = ClusterSampleData.newInstanceInfo(2);
httpReplicationClient.withNetworkStatusCode(200);
httpReplicationClient.withBatchReply(400);
httpReplicationClient.withInstanceInfo(instanceInfoFromPeer);
// InstanceInfo in response from peer will trigger local registry call
createPeerEurekaNode().heartbeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null, false);
expectRequestType(RequestType.Batch);
// Check that registry has instanceInfo from peer
verify(registry, timeout(1000).times(1)).register(instanceInfoFromPeer, true);
}
@Test
public void testAsgStatusUpdate() throws Throwable {
createPeerEurekaNode().statusUpdate(instanceInfo.getASGName(), ASGStatus.DISABLED);
Object newAsgStatus = expectRequestType(RequestType.AsgStatusUpdate);
assertThat(newAsgStatus, is(equalTo((Object) ASGStatus.DISABLED)));
}
@Test
public void testStatusUpdateBatchReplication() throws Throwable {
createPeerEurekaNode().statusUpdate(instanceInfo.getAppName(), instanceInfo.getId(), InstanceStatus.DOWN, instanceInfo);
ReplicationInstance replicationInstance = expectSingleBatchRequest();
assertThat(replicationInstance.getAction(), is(equalTo(Action.StatusUpdate)));
}
@Test
public void testDeleteStatusOverrideBatchReplication() throws Throwable {
createPeerEurekaNode().deleteStatusOverride(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo);
ReplicationInstance replicationInstance = expectSingleBatchRequest();
assertThat(replicationInstance.getAction(), is(equalTo(Action.DeleteStatusOverride)));
}
private PeerEurekaNode createPeerEurekaNode() {
EurekaServerConfig config = ClusterSampleData.newEurekaServerConfig();
peerEurekaNode = new PeerEurekaNode(
registry, "test", "http://test.host.com",
httpReplicationClient,
config,
BATCH_SIZE,
MAX_BATCHING_DELAY_MS,
ClusterSampleData.RETRY_SLEEP_TIME_MS,
ClusterSampleData.SERVER_UNAVAILABLE_SLEEP_TIME_MS
);
return peerEurekaNode;
}
private Object expectRequestType(RequestType requestType) throws InterruptedException {
HandledRequest handledRequest = httpReplicationClient.nextHandledRequest(60, TimeUnit.SECONDS);
assertThat(handledRequest, is(notNullValue()));
assertThat(handledRequest.getRequestType(), is(equalTo(requestType)));
return handledRequest.getData();
}
private ReplicationInstance expectSingleBatchRequest() throws InterruptedException {
HandledRequest handledRequest = httpReplicationClient.nextHandledRequest(30, TimeUnit.SECONDS);
assertThat(handledRequest, is(notNullValue()));
assertThat(handledRequest.getRequestType(), is(equalTo(RequestType.Batch)));
Object data = handledRequest.getData();
assertThat(data, is(instanceOf(ReplicationList.class)));
List<ReplicationInstance> replications = ((ReplicationList) data).getReplicationList();
assertThat(replications.size(), is(equalTo(1)));
return replications.get(0);
}
}