package org.robotninjas.barge;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.nio.ByteBuffer;
import java.util.List;
import javax.annotation.Nonnull;
public class StartStopTest {
private static final Logger LOGGER = LoggerFactory.getLogger(StartStopTest.class);
private File TEST_TMP_DIR;
private final NettyReplica[] replicas = new NettyReplica[] { NettyReplica.fromString("localhost:10001") };
private List<Server> allServers = Lists.newArrayList();
Server buildServer(int id) {
File logDir = new File(TEST_TMP_DIR, "log" + id);
assertThat(logDir.exists() || logDir.mkdirs()).isTrue();
ServerState state = new ServerState();
NettyClusterConfig clusterConfig = NettyClusterConfig.from(replicas[0]);
NettyRaftService raftService = NettyRaftService.newBuilder(clusterConfig).logDir(logDir).timeout(500).build(state);
Server server = new Server(raftService, logDir, state);
allServers.add(server);
return server;
}
@Test(timeout = 10000)
public void canStartAndStop() throws Exception {
{
Server server = buildServer(1);
server.start();
while (!server.isLeader()) {
Thread.sleep(50);
}
server.setState("A");
server.stop();
}
{
Server server = buildServer(1);
server.start();
while (!server.isLeader()) {
Thread.sleep(50);
}
assertThat(server.getState()).isEqualTo("A");
server.stop();
}
}
@Before
public void prepare() throws Exception {
TEST_TMP_DIR = Files.createTempDir();
}
@After
public void cleanup() throws Exception {
for (Server server : allServers) {
switch (server.raftService.state()) {
case RUNNING:
case STOPPING:
case STARTING:
server.stop();
break;
}
}
org.robotninjas.barge.utils.Files.delete(TEST_TMP_DIR);
}
class Server {
final NettyRaftService raftService;
final File logDirectory;
final ServerState state;
public Server(NettyRaftService raftService, File logDirectory, ServerState state) {
this.raftService = raftService;
this.logDirectory = logDirectory;
this.state = state;
}
public void start() {
LOGGER.info("Starting server");
raftService.startAsync().awaitRunning();
}
public void stop() {
LOGGER.info("Stopping server");
raftService.stopAsync().awaitTerminated();
}
public void setState(String s) throws RaftException, InterruptedException {
raftService.commit(s.getBytes(Charsets.UTF_8));
}
public String getState() {
ByteBuffer bb = state.getState();
byte[] v = new byte[bb.remaining()];
bb.get(v);
return new String(v, Charsets.UTF_8);
}
public boolean isLeader() {
return raftService.isLeader();
}
}
public static class ServerState implements StateMachine {
private ByteBuffer state;
@Override
public Object applyOperation(@Nonnull ByteBuffer entry) {
this.state = entry;
return 0;
}
public ByteBuffer getState() {
return state.duplicate();
}
}
}