package org.corfudb.infrastructure;
import org.corfudb.runtime.CorfuRuntime;
import org.corfudb.runtime.clients.TestRule;
import org.corfudb.runtime.view.AbstractViewTest;
import org.corfudb.runtime.view.Layout;
import org.junit.Before;
import org.junit.Test;
import java.util.HashSet;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests the Periodic Polling Policy.
* <p>
* Created by zlokhandwala on 10/26/16.
*/
public class PeriodicPollPolicyTest extends AbstractViewTest {
private IFailureDetectorPolicy failureDetectorPolicy = null;
private Layout layout = null;
private CorfuRuntime corfuRuntime = null;
@Before
public void pollingEnvironmentSetup() {
addServer(SERVERS.PORT_0);
addServer(SERVERS.PORT_1);
addServer(SERVERS.PORT_2);
layout = new TestLayoutBuilder()
.setEpoch(1L)
.addLayoutServer(SERVERS.PORT_0)
.addLayoutServer(SERVERS.PORT_1)
.addLayoutServer(SERVERS.PORT_2)
.addSequencer(SERVERS.PORT_0)
.addSequencer(SERVERS.PORT_1)
.addSequencer(SERVERS.PORT_2)
.buildSegment()
.buildStripe()
.addLogUnit(SERVERS.PORT_0)
.addLogUnit(SERVERS.PORT_1)
.addLogUnit(SERVERS.PORT_2)
.addToSegment()
.addToLayout()
.build();
bootstrapAllServers(layout);
getManagementServer(SERVERS.PORT_0).shutdown();
getManagementServer(SERVERS.PORT_1).shutdown();
getManagementServer(SERVERS.PORT_2).shutdown();
corfuRuntime = new CorfuRuntime();
layout.getLayoutServers().forEach(corfuRuntime::addLayoutServer);
corfuRuntime.connect();
layout.getAllServers().forEach(serverEndpoint -> {
corfuRuntime.getRouter(serverEndpoint).setTimeoutConnect(PARAMETERS.TIMEOUT_VERY_SHORT.toMillis());
corfuRuntime.getRouter(serverEndpoint).setTimeoutResponse(PARAMETERS.TIMEOUT_VERY_SHORT.toMillis());
corfuRuntime.getRouter(serverEndpoint).setTimeoutRetry(PARAMETERS.TIMEOUT_VERY_SHORT.toMillis());
});
failureDetectorPolicy = new PeriodicPollPolicy();
}
/**
* Polls 3 running servers. Poll returns no failures.
*
* @throws InterruptedException Sleep interrupted
*/
@Test
public void successfulPolling() throws InterruptedException {
for (int i = 0; i < PARAMETERS.CONCURRENCY_SOME; i++) {
failureDetectorPolicy.executePolicy(layout, corfuRuntime);
Thread.sleep(PARAMETERS.TIMEOUT_VERY_SHORT.toMillis());
}
// A little more than responseTimeout for periodicPolling
Thread.sleep(PARAMETERS.TIMEOUT_SHORT.toMillis());
PollReport result = failureDetectorPolicy.getServerStatus();
assertThat(result.getIsFailurePresent()).isFalse();
}
/**
* Polls 3 failed servers.
* Returns failed status for the 3 servers.
* We then restart server SERVERS.PORT_0, run polls again.
* Assert only 2 failures. SERVERS.PORT_1 & SERVERS.PORT_2
*
* @throws InterruptedException
*/
@Test
public void failedPolling() throws InterruptedException {
addServerRule(SERVERS.PORT_0, new TestRule().always().drop());
addServerRule(SERVERS.PORT_1, new TestRule().always().drop());
addServerRule(SERVERS.PORT_2, new TestRule().always().drop());
Set<String> expectedResult = new HashSet<>();
expectedResult.add(getEndpoint(SERVERS.PORT_0));
expectedResult.add(getEndpoint(SERVERS.PORT_1));
expectedResult.add(getEndpoint(SERVERS.PORT_2));
pollAndMatchExpectedResult(expectedResult);
/*
* Restarting the server SERVERS.PORT_0. Pings should work normally now.
* This is also to demonstrate that we no longer receive the failed
* nodes' status in the result map for SERVERS.PORT_0.
*/
clearServerRules(SERVERS.PORT_0);
// Has only SERVERS.PORT_1 & SERVERS.PORT_2
expectedResult.remove(getEndpoint(SERVERS.PORT_0));
pollAndMatchExpectedResult(expectedResult);
}
private void pollAndMatchExpectedResult(Set<String> expectedResult)
throws InterruptedException {
final int pollsToDeclareFailure = 10;
for (int i = 0; i < pollsToDeclareFailure; i++) {
failureDetectorPolicy.executePolicy(layout, corfuRuntime);
Thread.sleep(PARAMETERS.TIMEOUT_VERY_SHORT.toMillis());
}
Set<String> actualResult = new HashSet<>();
for (int i = 0; i < PARAMETERS.NUM_ITERATIONS_LARGE; i++) {
Set<String> tempResult = failureDetectorPolicy.getServerStatus().getFailingNodes();
if (tempResult != null) {
tempResult.forEach(actualResult::add);
}
Thread.sleep(PARAMETERS.TIMEOUT_SHORT.toMillis());
if (actualResult.equals(expectedResult)) break;
}
assertThat(actualResult).isEqualTo(expectedResult);
}
}