http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftReconfigurationWithGrpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftReconfigurationWithGrpc.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftReconfigurationWithGrpc.java new file mode 100644 index 0000000..29f8bea --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftReconfigurationWithGrpc.java @@ -0,0 +1,36 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.log4j.Level; +import org.apache.ratis.grpc.server.GrpcServerProtocolService; +import org.apache.ratis.server.impl.RaftReconfigurationBaseTest; +import org.apache.ratis.util.LogUtils; + +import java.io.IOException; + +public class TestRaftReconfigurationWithGrpc extends RaftReconfigurationBaseTest { + static { + LogUtils.setLogLevel(GrpcServerProtocolService.LOG, Level.DEBUG); + } + + @Override + public MiniRaftClusterWithGrpc getCluster(int peerNum) { + return MiniRaftClusterWithGrpc.FACTORY.newCluster(peerNum, prop); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftServerWithGrpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftServerWithGrpc.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftServerWithGrpc.java new file mode 100644 index 0000000..2ec7ae8 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftServerWithGrpc.java @@ -0,0 +1,59 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.ratis.BaseTest; +import org.apache.ratis.RaftTestUtil; +import org.apache.ratis.conf.RaftProperties; +import org.apache.ratis.protocol.RaftPeerId; +import org.apache.ratis.server.impl.ServerImplUtils; +import org.apache.ratis.statemachine.StateMachine; +import org.junit.Test; + +import java.io.IOException; +import java.nio.channels.OverlappingFileLockException; + +public class TestRaftServerWithGrpc extends BaseTest { + + @Test + public void testServerRestartOnException() throws Exception { + RaftProperties properties = new RaftProperties(); + final MiniRaftClusterWithGrpc cluster + = MiniRaftClusterWithGrpc.FACTORY.newCluster(1, properties); + cluster.start(); + RaftPeerId leaderId = RaftTestUtil.waitForLeader(cluster).getId(); + GrpcConfigKeys.Server.setPort(properties, cluster.getLeader().getServerRpc().getInetSocketAddress().getPort()); + // Create a raft server proxy with server rpc bound to a different address + // compared to leader. This helps in locking the raft storage directory to + // be used by next raft server proxy instance. + final StateMachine stateMachine = cluster.getLeader().getStateMachine(); + ServerImplUtils.newRaftServer(leaderId, cluster.getGroup(), gid -> stateMachine, properties, null); + // Close the server rpc for leader so that new raft server can be bound to it. + cluster.getLeader().getServerRpc().close(); + + // Create a raft server proxy with server rpc bound to same address as + // the leader. This step would fail as the raft storage has been locked by + // the raft server proxy created earlier. Raft server proxy should close + // the rpc server on failure. + testFailureCase("start a new server with the same address", + () -> ServerImplUtils.newRaftServer(leaderId, cluster.getGroup(), gid -> stateMachine, properties, null).start(), + IOException.class, OverlappingFileLockException.class); + // Try to start a raft server rpc at the leader address. + cluster.getServer(leaderId).getFactory().newRaftServerRpc(cluster.getServer(leaderId)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftSnapshotWithGrpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftSnapshotWithGrpc.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftSnapshotWithGrpc.java new file mode 100644 index 0000000..a960478 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftSnapshotWithGrpc.java @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.ratis.MiniRaftCluster; +import org.apache.ratis.statemachine.RaftSnapshotBaseTest; + +public class TestRaftSnapshotWithGrpc extends RaftSnapshotBaseTest { + @Override + public MiniRaftCluster.Factory<?> getFactory() { + return MiniRaftClusterWithGrpc.FACTORY; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftStateMachineExceptionWithGrpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftStateMachineExceptionWithGrpc.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftStateMachineExceptionWithGrpc.java new file mode 100644 index 0000000..c8789a7 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftStateMachineExceptionWithGrpc.java @@ -0,0 +1,26 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.ratis.server.impl.RaftStateMachineExceptionTests; + +public class TestRaftStateMachineExceptionWithGrpc + extends RaftStateMachineExceptionTests<MiniRaftClusterWithGrpc> + implements MiniRaftClusterWithGrpc.FactoryGet { + +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftStream.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftStream.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftStream.java new file mode 100644 index 0000000..ba31b2b --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftStream.java @@ -0,0 +1,311 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.log4j.Level; +import org.apache.ratis.BaseTest; +import org.apache.ratis.RaftTestUtil; +import org.apache.ratis.conf.RaftProperties; +import org.apache.ratis.grpc.client.GrpcClientStreamer; +import org.apache.ratis.grpc.client.GrpcOutputStream; +import org.apache.ratis.protocol.ClientId; +import org.apache.ratis.server.impl.RaftServerImpl; +import org.apache.ratis.server.protocol.TermIndex; +import org.apache.ratis.server.storage.RaftLog; +import org.apache.ratis.proto.RaftProtos; +import org.apache.ratis.util.LogUtils; +import org.apache.ratis.util.SizeInBytes; +import org.apache.ratis.util.StringUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; + +import static org.apache.ratis.RaftTestUtil.waitForLeader; +import static org.junit.Assert.fail; + +@Ignore +public class TestRaftStream extends BaseTest { + static { + LogUtils.setLogLevel(GrpcClientStreamer.LOG, Level.ALL); + } + + private static final RaftProperties prop = new RaftProperties(); + private static final int NUM_SERVERS = 3; + private static final byte[] BYTES = new byte[4]; + + private MiniRaftClusterWithGrpc cluster; + + @After + public void tearDown() { + if (cluster != null) { + cluster.shutdown(); + } + } + + private byte[] toBytes(int i) { + return toBytes(i, BYTES); + } + private byte[] toBytes(int i, byte[] b) { + b[0] = (byte) ((i >>> 24) & 0xFF); + b[1] = (byte) ((i >>> 16) & 0xFF); + b[2] = (byte) ((i >>> 8) & 0xFF); + b[3] = (byte) (i & 0xFF); + return b; + } + + @Test + public void testSimpleWrite() throws Exception { + final int numRequests = 500; + LOG.info("Running testSimpleWrite, numRequests=" + numRequests); + + // default 64K is too large for a test + GrpcConfigKeys.OutputStream.setBufferSize(prop, SizeInBytes.valueOf(4)); + cluster = MiniRaftClusterWithGrpc.FACTORY.newCluster(NUM_SERVERS, prop); + + cluster.start(); + RaftServerImpl leader = waitForLeader(cluster); + + try (GrpcOutputStream out = new GrpcOutputStream(prop, ClientId.randomId(), + cluster.getGroup(), leader.getId())) { + for (int i = 0; i < numRequests; i++) { // generate requests + out.write(toBytes(i)); + } + } + + // check the leader's raft log + final RaftLog raftLog = leader.getState().getLog(); + final AtomicInteger i = new AtomicInteger(); + checkLog(raftLog, numRequests, () -> toBytes(i.getAndIncrement())); + } + + private void checkLog(RaftLog raftLog, long expectedCommittedIndex, + Supplier<byte[]> s) throws IOException { + long committedIndex = raftLog.getLastCommittedIndex(); + Assert.assertEquals(expectedCommittedIndex, committedIndex); + // check the log content + TermIndex[] entries = raftLog.getEntries(1, expectedCommittedIndex + 1); + for (TermIndex entry : entries) { + RaftProtos.LogEntryProto log = raftLog.get(entry.getIndex()); + byte[] logData = log.getStateMachineLogEntry().getLogData().toByteArray(); + byte[] expected = s.get(); + LOG.info("log " + entry + " " + log.getLogEntryBodyCase() + " " + StringUtils.bytes2HexString(logData)); + Assert.assertEquals(expected.length, logData.length); + Assert.assertArrayEquals(expected, logData); + } + } + + @Test + public void testWriteAndFlush() throws Exception { + LOG.info("Running testWriteAndFlush"); + + GrpcConfigKeys.OutputStream.setBufferSize(prop, SizeInBytes.valueOf(ByteValue.BUFFERSIZE)); + cluster = MiniRaftClusterWithGrpc.FACTORY.newCluster(NUM_SERVERS, prop); + cluster.start(); + + RaftServerImpl leader = waitForLeader(cluster); + GrpcOutputStream out = new GrpcOutputStream(prop, ClientId.randomId(), + cluster.getGroup(), leader.getId()); + + int[] lengths = new int[]{1, 500, 1023, 1024, 1025, 2048, 3000, 3072}; + ByteValue[] values = new ByteValue[lengths.length]; + for (int i = 0; i < values.length; i++) { + values[i] = new ByteValue(lengths[i], (byte) 9); + } + + List<byte[]> expectedTxs = new ArrayList<>(); + for (ByteValue v : values) { + byte[] data = v.genData(); + expectedTxs.addAll(v.getTransactions()); + out.write(data); + out.flush(); + + // make sure after the flush the data has been committed + Assert.assertEquals(expectedTxs.size(), + leader.getState().getLastAppliedIndex()); + } + out.close(); + + try { + out.write(0); + fail("The OutputStream has been closed"); + } catch (IOException ignored) { + } + + LOG.info("Start to check leader's log"); + final AtomicInteger index = new AtomicInteger(0); + checkLog(leader.getState().getLog(), expectedTxs.size(), + () -> expectedTxs.get(index.getAndIncrement())); + } + + private static class ByteValue { + final static int BUFFERSIZE = 1024; + + final int length; + final byte value; + final int numTx; + byte[] data; + + ByteValue(int length, byte value) { + this.length = length; + this.value = value; + numTx = (length - 1) / BUFFERSIZE + 1; + } + + byte[] genData() { + data = new byte[length]; + Arrays.fill(data, value); + return data; + } + + Collection<byte[]> getTransactions() { + if (data.length <= BUFFERSIZE) { + return Collections.singletonList(data); + } else { + List<byte[]> list = new ArrayList<>(); + for (int i = 0; i < numTx; i++) { + int txSize = Math.min(BUFFERSIZE, length - BUFFERSIZE * i); + byte[] t = new byte[txSize]; + Arrays.fill(t, value); + list.add(t); + } + return list; + } + } + } + + @Test + public void testWriteWithOffset() throws Exception { + LOG.info("Running testWriteWithOffset"); + GrpcConfigKeys.OutputStream.setBufferSize(prop, SizeInBytes.valueOf(ByteValue.BUFFERSIZE)); + + cluster = MiniRaftClusterWithGrpc.FACTORY.newCluster(NUM_SERVERS, prop); + cluster.start(); + RaftServerImpl leader = waitForLeader(cluster); + + GrpcOutputStream out = new GrpcOutputStream(prop, ClientId.randomId(), + cluster.getGroup(), leader.getId()); + + byte[] b1 = new byte[ByteValue.BUFFERSIZE / 2]; + Arrays.fill(b1, (byte) 1); + byte[] b2 = new byte[ByteValue.BUFFERSIZE]; + Arrays.fill(b2, (byte) 2); + byte[] b3 = new byte[ByteValue.BUFFERSIZE * 2 + ByteValue.BUFFERSIZE / 2]; + Arrays.fill(b3, (byte) 3); + byte[] b4 = new byte[ByteValue.BUFFERSIZE * 4]; + Arrays.fill(b3, (byte) 4); + + byte[] expected = new byte[ByteValue.BUFFERSIZE * 8]; + byte[][] data = new byte[][]{b1, b2, b3, b4}; + final Random random = new Random(); + int totalSize = 0; + for (byte[] b : data) { + System.arraycopy(b, 0, expected, totalSize, b.length); + totalSize += b.length; + + int written = 0; + while (written < b.length) { + int toWrite = random.nextInt(b.length - written) + 1; + LOG.info("write {} bytes", toWrite); + out.write(b, written, toWrite); + written += toWrite; + } + } + out.close(); + + final RaftLog log = leader.getState().getLog(); + // 0.5 + 1 + 2.5 + 4 = 8 + Assert.assertEquals(8, leader.getState().getLastAppliedIndex()); + Assert.assertEquals(8, log.getLastCommittedIndex()); + TermIndex[] entries = log.getEntries(1, 9); + byte[] actual = new byte[ByteValue.BUFFERSIZE * 8]; + totalSize = 0; + for (TermIndex e : entries) { + byte[] eValue = log.get(e.getIndex()).getStateMachineLogEntry().getLogData().toByteArray(); + Assert.assertEquals(ByteValue.BUFFERSIZE, eValue.length); + System.arraycopy(eValue, 0, actual, totalSize, eValue.length); + totalSize += eValue.length; + } + Assert.assertArrayEquals(expected, actual); + } + + /** + * Write while leader is killed + */ + @Test + public void testKillLeader() throws Exception { + LOG.info("Running testChangeLeader"); + + GrpcConfigKeys.OutputStream.setBufferSize(prop, SizeInBytes.valueOf(4)); + cluster = MiniRaftClusterWithGrpc.FACTORY.newCluster(NUM_SERVERS, prop); + cluster.start(); + final RaftServerImpl leader = waitForLeader(cluster); + + final AtomicBoolean running = new AtomicBoolean(true); + final AtomicReference<Boolean> success = new AtomicReference<>(); + final AtomicInteger result = new AtomicInteger(0); + final CountDownLatch latch = new CountDownLatch(1); + + new Thread(() -> { + LOG.info("Writer thread starts"); + int count = 0; + try (GrpcOutputStream out = new GrpcOutputStream(prop, ClientId.randomId(), + cluster.getGroup(), leader.getId())) { + while (running.get()) { + out.write(toBytes(count++)); + Thread.sleep(10); + } + success.set(true); + result.set(count); + } catch (Exception e) { + LOG.info("Got exception when writing", e); + success.set(false); + } finally { + latch.countDown(); + } + }).start(); + + // force change the leader + Thread.sleep(500); + RaftTestUtil.waitAndKillLeader(cluster); + final RaftServerImpl newLeader = waitForLeader(cluster); + Assert.assertNotEquals(leader.getId(), newLeader.getId()); + Thread.sleep(500); + + running.set(false); + latch.await(5, TimeUnit.SECONDS); + LOG.info("Writer success? " + success.get()); + Assert.assertTrue(success.get()); + // total number of tx should be >= result + 2, where 2 means two NoOp from + // leaders. It may be larger than result+2 because the client may resend + // requests and we do not have retry cache on servers yet. + LOG.info("last applied index: {}. total number of requests: {}", + newLeader.getState().getLastAppliedIndex(), result.get()); + Assert.assertTrue( + newLeader.getState().getLastAppliedIndex() >= result.get() + 1); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftWithGrpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftWithGrpc.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftWithGrpc.java new file mode 100644 index 0000000..d98be53 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRaftWithGrpc.java @@ -0,0 +1,110 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.ratis.MiniRaftCluster; +import org.apache.ratis.RaftBasicTests; +import org.apache.ratis.RaftTestUtil; +import org.apache.ratis.client.RaftClient; +import org.apache.ratis.protocol.RaftClientReply; +import org.apache.ratis.server.impl.BlockRequestHandlingInjection; +import org.apache.ratis.server.impl.RaftServerTestUtil; +import org.apache.ratis.server.protocol.TermIndex; +import org.apache.ratis.statemachine.SimpleStateMachine4Testing; +import org.apache.ratis.statemachine.StateMachine; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; + +import static org.apache.ratis.RaftTestUtil.waitForLeader; + +public class TestRaftWithGrpc + extends RaftBasicTests<MiniRaftClusterWithGrpc> + implements MiniRaftClusterWithGrpc.FactoryGet { + + { + getProperties().setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY, + SimpleStateMachine4Testing.class, StateMachine.class); + } + + @Override + @Test + public void testWithLoad() throws Exception { + super.testWithLoad(); + BlockRequestHandlingInjection.getInstance().unblockAll(); + } + + @Test + public void testRequestTimeout() throws Exception { + try(MiniRaftClusterWithGrpc cluster = newCluster(NUM_SERVERS)) { + cluster.start(); + testRequestTimeout(false, cluster, LOG); + } + } + + @Test + public void testUpdateViaHeartbeat() throws Exception { + LOG.info("Running testUpdateViaHeartbeat"); + final MiniRaftClusterWithGrpc cluster = newCluster(NUM_SERVERS); + cluster.start(); + waitForLeader(cluster); + long waitTime = 5000; + try (final RaftClient client = cluster.createClient()) { + // block append requests + cluster.getServerAliveStream() + .filter(impl -> !impl.isLeader()) + .map(SimpleStateMachine4Testing::get) + .forEach(SimpleStateMachine4Testing::blockWriteStateMachineData); + + CompletableFuture<RaftClientReply> + replyFuture = client.sendAsync(new RaftTestUtil.SimpleMessage("abc")); + Thread.sleep(waitTime); + // replyFuture should not be completed until append request is unblocked. + Assert.assertTrue(!replyFuture.isDone()); + // unblock append request. + cluster.getServerAliveStream() + .filter(impl -> !impl.isLeader()) + .map(SimpleStateMachine4Testing::get) + .forEach(SimpleStateMachine4Testing::unblockWriteStateMachineData); + + long index = cluster.getLeader().getState().getLog().getNextIndex(); + TermIndex[] leaderEntries = cluster.getLeader().getState().getLog().getEntries(0, Integer.MAX_VALUE); + // The entries have been appended in the followers + // although the append entry timed out at the leader + cluster.getServerAliveStream().forEach(raftServer -> { + Assert.assertEquals(raftServer.getState().getLog().getNextIndex(), index); + if (!raftServer.isLeader()) { + TermIndex[] serverEntries = raftServer.getState().getLog().getEntries(0, Integer.MAX_VALUE); + Assert.assertArrayEquals(serverEntries, leaderEntries); + } + }); + + // Wait for heartbeats from leader to be received by followers + Thread.sleep(500); + RaftServerTestUtil.getLogAppenders(cluster.getLeader()).forEach(logAppender -> { + // FollowerInfo in the leader state should have updated next and match index. + final long followerMatchIndex = logAppender.getFollower().getMatchIndex(); + Assert.assertTrue(followerMatchIndex >= index - 1); + Assert.assertEquals(followerMatchIndex + 1, logAppender.getFollower().getNextIndex()); + }); + } + cluster.shutdown(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestRetryCacheWithGrpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestRetryCacheWithGrpc.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRetryCacheWithGrpc.java new file mode 100644 index 0000000..cd04b43 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestRetryCacheWithGrpc.java @@ -0,0 +1,115 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.apache.log4j.Level; +import org.apache.ratis.MiniRaftCluster; +import org.apache.ratis.RaftTestUtil; +import org.apache.ratis.RetryCacheTests; +import org.apache.ratis.client.RaftClient; +import org.apache.ratis.client.RaftClientRpc; +import org.apache.ratis.protocol.ClientId; +import org.apache.ratis.protocol.RaftClientRequest; +import org.apache.ratis.protocol.RaftPeerId; +import org.apache.ratis.server.impl.RaftServerImpl; +import org.apache.ratis.proto.RaftProtos; +import org.apache.ratis.util.LogUtils; +import org.junit.Assert; +import org.junit.Test; + +public class TestRetryCacheWithGrpc extends RetryCacheTests { + static { + LogUtils.setLogLevel(RaftServerImpl.LOG, Level.DEBUG); + } + + private final MiniRaftClusterWithGrpc cluster; + + public TestRetryCacheWithGrpc() throws IOException { + cluster = MiniRaftClusterWithGrpc.FACTORY.newCluster( + NUM_SERVERS, properties); + Assert.assertNull(cluster.getLeader()); + } + + @Override + public MiniRaftClusterWithGrpc getCluster() { + return cluster; + } + + @Test + public void testAsyncRetryWithReplicatedAll() throws Exception { + final MiniRaftCluster cluster = getCluster(); + RaftTestUtil.waitForLeader(cluster); + + final RaftPeerId leaderId = cluster.getLeaderAndSendFirstMessage().getId(); + long oldLastApplied = cluster.getLeader().getState().getLastAppliedIndex(); + + // Kill a follower + final RaftPeerId killedFollower = cluster.getFollowers().get(0).getId(); + cluster.killServer(killedFollower); + + final long callId = 999; + final long seqNum = 111; + final ClientId clientId = ClientId.randomId(); + + // Retry with the same clientId and callId + final List<CompletableFuture<RaftClient>> futures = new ArrayList<>(); + futures.addAll(sendRetry(clientId, leaderId, callId, seqNum, cluster)); + futures.addAll(sendRetry(clientId, leaderId, callId, seqNum, cluster)); + + // restart the killed follower + cluster.restartServer(killedFollower, false); + for(CompletableFuture<RaftClient> f : futures) { + f.join().close(); + } + assertServer(cluster, clientId, callId, oldLastApplied); + } + + List<CompletableFuture<RaftClient>> sendRetry( + ClientId clientId, RaftPeerId leaderId, long callId, long seqNum, MiniRaftCluster cluster) + throws Exception { + List<CompletableFuture<RaftClient>> futures = new ArrayList<>(); + final int numRequest = 3; + for (int i = 0; i < numRequest; i++) { + final RaftClient client = cluster.createClient(leaderId, cluster.getGroup(), clientId); + final RaftClientRpc rpc = client.getClientRpc(); + final RaftClientRequest request = cluster.newRaftClientRequest(client.getId(), leaderId, + callId, seqNum, new RaftTestUtil.SimpleMessage("message"), RaftProtos.ReplicationLevel.ALL); + + LOG.info("{} sendRequestAsync {}", i, request); + futures.add(rpc.sendRequestAsync(request) + .thenApply(reply -> assertReply(reply, client, callId))); + } + + for(CompletableFuture<RaftClient> f : futures) { + try { + f.get(200, TimeUnit.MILLISECONDS); + Assert.fail("It should timeout for ReplicationLevel.ALL since a follower is down"); + } catch(TimeoutException te) { + LOG.info("Expected " + te); + } + } + return futures; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestServerInformationWithGrpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestServerInformationWithGrpc.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestServerInformationWithGrpc.java new file mode 100644 index 0000000..30be724 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestServerInformationWithGrpc.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.ratis.server.impl.ServerInformationBaseTest; + +public class TestServerInformationWithGrpc + extends ServerInformationBaseTest<MiniRaftClusterWithGrpc> + implements MiniRaftClusterWithGrpc.FactoryGet { +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestServerRestartWithGrpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestServerRestartWithGrpc.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestServerRestartWithGrpc.java new file mode 100644 index 0000000..682b3ba --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestServerRestartWithGrpc.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.ratis.server.ServerRestartTests; + +public class TestServerRestartWithGrpc + extends ServerRestartTests<MiniRaftClusterWithGrpc> + implements MiniRaftClusterWithGrpc.FactoryGet { +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestStateMachineShutdownWithGrpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestStateMachineShutdownWithGrpc.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestStateMachineShutdownWithGrpc.java new file mode 100644 index 0000000..d8d1d0d --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestStateMachineShutdownWithGrpc.java @@ -0,0 +1,26 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.ratis.server.impl.StateMachineShutdownTests; + +public class TestStateMachineShutdownWithGrpc + extends StateMachineShutdownTests<MiniRaftClusterWithGrpc> + implements MiniRaftClusterWithGrpc.FactoryGet{ + +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/grpc/TestWatchRequestWithGrpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/grpc/TestWatchRequestWithGrpc.java b/ratis-test/src/test/java/org/apache/ratis/grpc/TestWatchRequestWithGrpc.java new file mode 100644 index 0000000..7b9061b --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/grpc/TestWatchRequestWithGrpc.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.grpc; + +import org.apache.ratis.WatchRequestTests; + +public class TestWatchRequestWithGrpc + extends WatchRequestTests<MiniRaftClusterWithGrpc> + implements MiniRaftClusterWithGrpc.FactoryGet { +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/netty/TestGroupManagementWithNetty.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/netty/TestGroupManagementWithNetty.java b/ratis-test/src/test/java/org/apache/ratis/netty/TestGroupManagementWithNetty.java new file mode 100644 index 0000000..e049e32 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/netty/TestGroupManagementWithNetty.java @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.netty; + +import org.apache.ratis.MiniRaftCluster; +import org.apache.ratis.server.impl.GroupManagementBaseTest; + +public class TestGroupManagementWithNetty extends GroupManagementBaseTest { + @Override + public MiniRaftCluster.Factory<? extends MiniRaftCluster> getClusterFactory() { + return MiniRaftClusterWithNetty.FACTORY; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/netty/TestLeaderElectionWithNetty.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/netty/TestLeaderElectionWithNetty.java b/ratis-test/src/test/java/org/apache/ratis/netty/TestLeaderElectionWithNetty.java new file mode 100644 index 0000000..6d40b60 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/netty/TestLeaderElectionWithNetty.java @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.netty; + +import org.apache.ratis.server.impl.BlockRequestHandlingInjection; +import org.apache.ratis.server.impl.LeaderElectionTests; +import org.junit.Test; + +public class TestLeaderElectionWithNetty + extends LeaderElectionTests<MiniRaftClusterWithNetty> + implements MiniRaftClusterWithNetty.FactoryGet { + @Override + @Test + public void testEnforceLeader() throws Exception { + super.testEnforceLeader(); + + MiniRaftClusterWithNetty.sendServerRequest.clear(); + BlockRequestHandlingInjection.getInstance().unblockAll(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftExceptionWithNetty.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftExceptionWithNetty.java b/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftExceptionWithNetty.java new file mode 100644 index 0000000..3414a65 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftExceptionWithNetty.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.netty; + +import org.apache.ratis.RaftExceptionBaseTest; + +public class TestRaftExceptionWithNetty + extends RaftExceptionBaseTest<MiniRaftClusterWithNetty> + implements MiniRaftClusterWithNetty.FactoryGet { +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftReconfigurationWithNetty.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftReconfigurationWithNetty.java b/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftReconfigurationWithNetty.java new file mode 100644 index 0000000..15fa8e6 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftReconfigurationWithNetty.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.netty; + +import java.io.IOException; + +import org.apache.ratis.MiniRaftCluster; +import org.apache.ratis.server.impl.RaftReconfigurationBaseTest; + +public class TestRaftReconfigurationWithNetty + extends RaftReconfigurationBaseTest { + @Override + public MiniRaftCluster getCluster(int peerNum) throws IOException { + return MiniRaftClusterWithNetty.FACTORY.newCluster(peerNum, prop); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftSnapshotWithNetty.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftSnapshotWithNetty.java b/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftSnapshotWithNetty.java new file mode 100644 index 0000000..da861d5 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftSnapshotWithNetty.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.netty; + +import org.apache.ratis.MiniRaftCluster; +import org.apache.ratis.conf.RaftProperties; +import org.apache.ratis.statemachine.RaftSnapshotBaseTest; + +import java.io.IOException; + +public class TestRaftSnapshotWithNetty extends RaftSnapshotBaseTest { + @Override + public MiniRaftCluster.Factory<?> getFactory() { + return MiniRaftClusterWithNetty.FACTORY; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftStateMachineExceptionWithNetty.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftStateMachineExceptionWithNetty.java b/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftStateMachineExceptionWithNetty.java new file mode 100644 index 0000000..34fddc9 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftStateMachineExceptionWithNetty.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.netty; + +import org.apache.ratis.server.impl.RaftStateMachineExceptionTests; + +public class TestRaftStateMachineExceptionWithNetty + extends RaftStateMachineExceptionTests<MiniRaftClusterWithNetty> + implements MiniRaftClusterWithNetty.FactoryGet { +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftWithNetty.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftWithNetty.java b/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftWithNetty.java new file mode 100644 index 0000000..28815d7 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/netty/TestRaftWithNetty.java @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.netty; + +import org.apache.ratis.RaftBasicTests; +import org.apache.ratis.server.impl.BlockRequestHandlingInjection; +import org.junit.Test; + +public class TestRaftWithNetty + extends RaftBasicTests<MiniRaftClusterWithNetty> + implements MiniRaftClusterWithNetty.FactoryGet { + + @Override + @Test + public void testWithLoad() throws Exception { + super.testWithLoad(); + BlockRequestHandlingInjection.getInstance().unblockAll(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/netty/TestRetryCacheWithNettyRpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/netty/TestRetryCacheWithNettyRpc.java b/ratis-test/src/test/java/org/apache/ratis/netty/TestRetryCacheWithNettyRpc.java new file mode 100644 index 0000000..659e426 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/netty/TestRetryCacheWithNettyRpc.java @@ -0,0 +1,45 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.netty; + +import java.io.IOException; + +import org.apache.log4j.Level; +import org.apache.ratis.RetryCacheTests; +import org.apache.ratis.client.RaftClient; +import org.apache.ratis.server.impl.RaftServerImpl; +import org.apache.ratis.util.LogUtils; + +public class TestRetryCacheWithNettyRpc extends RetryCacheTests { + static { + LogUtils.setLogLevel(RaftServerImpl.LOG, Level.DEBUG); + LogUtils.setLogLevel(RaftClient.LOG, Level.DEBUG); + } + + private final MiniRaftClusterWithNetty cluster; + + public TestRetryCacheWithNettyRpc() throws IOException { + cluster = MiniRaftClusterWithNetty.FACTORY.newCluster( + NUM_SERVERS, getProperties()); + } + + @Override + public MiniRaftClusterWithNetty getCluster() { + return cluster; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/netty/TestServerInformationWithNetty.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/netty/TestServerInformationWithNetty.java b/ratis-test/src/test/java/org/apache/ratis/netty/TestServerInformationWithNetty.java new file mode 100644 index 0000000..d1bcae4 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/netty/TestServerInformationWithNetty.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.netty; + +import org.apache.ratis.server.impl.ServerInformationBaseTest; + +public class TestServerInformationWithNetty + extends ServerInformationBaseTest<MiniRaftClusterWithNetty> + implements MiniRaftClusterWithNetty.FactoryGet { +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/netty/TestServerRestartWithNetty.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/netty/TestServerRestartWithNetty.java b/ratis-test/src/test/java/org/apache/ratis/netty/TestServerRestartWithNetty.java new file mode 100644 index 0000000..15dc688 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/netty/TestServerRestartWithNetty.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.netty; + +import org.apache.ratis.server.ServerRestartTests; + +public class TestServerRestartWithNetty + extends ServerRestartTests<MiniRaftClusterWithNetty> + implements MiniRaftClusterWithNetty.FactoryGet { +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/protocol/TestRaftId.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/protocol/TestRaftId.java b/ratis-test/src/test/java/org/apache/ratis/protocol/TestRaftId.java new file mode 100644 index 0000000..30b7ed5 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/protocol/TestRaftId.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.protocol; + +import org.apache.ratis.BaseTest; +import org.apache.ratis.thirdparty.com.google.protobuf.ByteString; +import org.junit.Assert; +import org.junit.Test; + +public class TestRaftId extends BaseTest { + @Override + public int getGlobalTimeoutSeconds() { + return 1; + } + + @Test + public void testClientId() { + final ClientId id = ClientId.randomId(); + final ByteString bytes = id.toByteString(); + Assert.assertEquals(bytes, id.toByteString()); + Assert.assertEquals(id, ClientId.valueOf(bytes)); + } + + @Test + public void testRaftGroupId() { + final RaftGroupId id = RaftGroupId.randomId(); + final ByteString bytes = id.toByteString(); + Assert.assertEquals(bytes, id.toByteString()); + Assert.assertEquals(id, RaftGroupId.valueOf(bytes)); + } + + @Test + public void testRaftPeerId() { + final RaftPeerId id = RaftPeerId.valueOf("abc"); + final ByteString bytes = id.toByteString(); + Assert.assertEquals(bytes, id.toByteString()); + Assert.assertEquals(id, RaftPeerId.valueOf(bytes)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/TestRaftLogMetrics.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/TestRaftLogMetrics.java b/ratis-test/src/test/java/org/apache/ratis/server/TestRaftLogMetrics.java new file mode 100644 index 0000000..58e319d --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/TestRaftLogMetrics.java @@ -0,0 +1,119 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ratis.server; + +import com.codahale.metrics.Timer; +import org.apache.log4j.Level; +import org.apache.ratis.BaseTest; +import org.apache.ratis.MiniRaftCluster; +import org.apache.ratis.RaftTestUtil; +import org.apache.ratis.client.RaftClient; +import org.apache.ratis.metrics.RatisMetricsRegistry; +import org.apache.ratis.server.impl.RaftServerImpl; +import org.apache.ratis.server.simulation.MiniRaftClusterWithSimulatedRpc; +import org.apache.ratis.server.storage.RaftStorageTestUtils; +import org.apache.ratis.statemachine.StateMachine; +import org.apache.ratis.statemachine.impl.BaseStateMachine; +import org.apache.ratis.util.JavaUtils; +import org.apache.ratis.util.LogUtils; +import org.junit.Assert; +import org.junit.Test; + +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicInteger; + +public class TestRaftLogMetrics extends BaseTest + implements MiniRaftClusterWithSimulatedRpc.FactoryGet { + + { + LogUtils.setLogLevel(RaftServerImpl.LOG, Level.DEBUG); + } + + public static final int NUM_SERVERS = 3; + + { + getProperties().setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY, + MetricsStateMachine.class, StateMachine.class); + } + + static class MetricsStateMachine extends BaseStateMachine { + static MetricsStateMachine get(RaftServerImpl s) { + return (MetricsStateMachine)s.getStateMachine(); + } + + private final AtomicInteger flushCount = new AtomicInteger(); + + int getFlushCount() { + return flushCount.get(); + } + + @Override + public CompletableFuture<Void> flushStateMachineData(long index) { + flushCount.incrementAndGet(); + return super.flushStateMachineData(index); + } + } + + @Test + public void testFlushMetric() throws Exception { + try(final MiniRaftCluster cluster = newCluster(NUM_SERVERS)) { + cluster.start(); + runTestFlushMetric(cluster); + } + } + + static void runTestFlushMetric(MiniRaftCluster cluster) throws Exception { + int numMsg = 2; + final RaftTestUtil.SimpleMessage[] messages = RaftTestUtil.SimpleMessage.create(numMsg); + + try (final RaftClient client = cluster.createClient()) { + for (RaftTestUtil.SimpleMessage message : messages) { + client.send(message); + } + } + + // For leader, flush must happen before client can get replies. + assertFlushCount(cluster.getLeader()); + + // For followers, flush can be lagged behind. Attempt multiple times. + for(RaftServerImpl f : cluster.getFollowers()) { + JavaUtils.attempt(() -> assertFlushCount(f), 10, 100, f.getId() + "-assertFlushCount", null); + } + } + + static void assertFlushCount(RaftServerImpl server) throws Exception { + final String flushTimeMetric = RaftStorageTestUtils.getLogFlushTimeMetric(server.getId()); + Timer tm = RatisMetricsRegistry.getRegistry().getTimers().get(flushTimeMetric); + Assert.assertNotNull(tm); + + final MetricsStateMachine stateMachine = MetricsStateMachine.get(server); + final int expectedFlush = stateMachine.getFlushCount(); + + Assert.assertEquals(expectedFlush, tm.getCount()); + Assert.assertTrue(tm.getMeanRate() > 0); + + // Test jmx + ObjectName oname = new ObjectName("metrics", "name", flushTimeMetric); + Assert.assertEquals(expectedFlush, + ((Long) ManagementFactory.getPlatformMBeanServer().getAttribute(oname, "Count")) + .intValue()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/TestRaftServerConfigKeys.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/TestRaftServerConfigKeys.java b/ratis-test/src/test/java/org/apache/ratis/server/TestRaftServerConfigKeys.java new file mode 100644 index 0000000..53c8871 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/TestRaftServerConfigKeys.java @@ -0,0 +1,98 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ratis.server; + +import org.apache.ratis.BaseTest; +import org.apache.ratis.conf.RaftProperties; +import org.apache.ratis.util.FileUtils; +import org.apache.ratis.util.JavaUtils; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * Test cases to verify RaftServerConfigKeys. + */ +public class TestRaftServerConfigKeys { + + private static final Supplier<File> rootTestDir = JavaUtils.memoize( + () -> new File(BaseTest.getRootTestDir(), + TestRaftServerConfigKeys.class.getSimpleName() + + Integer.toHexString(ThreadLocalRandom.current().nextInt()))); + + @AfterClass + public static void tearDown() throws IOException { + FileUtils.deleteFully(rootTestDir.get()); + } + + /** + * Sets the value to <code>raft.server.storage.dir</code> via + * RaftServerConfigKeys and verifies it by reading directly from property. + */ + @Test + public void testStorageDirsProperty() { + final File testDir = new File( + rootTestDir.get(), UUID.randomUUID().toString()); + final List<File> directories = new ArrayList<>(); + final RaftProperties properties = new RaftProperties(); + + IntStream.range(0, 10).mapToObj((i) -> new File(testDir, + Integer.toString(i))).forEach(directories::add); + RaftServerConfigKeys.setStorageDirs(properties, directories); + + final String expected = directories.stream().map(File::getAbsolutePath) + .collect(Collectors.joining(",")); + final String actual = properties.get(RaftServerConfigKeys.STORAGE_DIR_KEY); + Assert.assertEquals(expected, actual); + } + + /** + * Sets the value to <code>raft.server.storage.dir</code> via + * RaftServerConfigKeys and also verifies the same via RaftServerConfigKeys. + */ + @Test + public void testStorageDirs() { + final File testDir = new File( + rootTestDir.get(), UUID.randomUUID().toString()); + final List<File> directories = new ArrayList<>(); + IntStream.range(0, 10).mapToObj((i) -> new File(testDir, + Integer.toString(i))).forEach(directories::add); + RaftProperties properties = new RaftProperties(); + RaftServerConfigKeys.setStorageDirs(properties, directories); + + final List<File> storageDirs = RaftServerConfigKeys.storageDirs(properties); + final List<String> expectedDirs = directories.stream() + .map(File::getAbsolutePath).collect(Collectors.toList()); + final List<String> actualDirs = storageDirs.stream() + .map(File::getAbsolutePath).collect(Collectors.toList()); + actualDirs.removeAll(expectedDirs); + Assert.assertEquals(directories.size(), storageDirs.size()); + Assert.assertEquals(0, actualDirs.size()); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/impl/TestRaftServerJmx.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/impl/TestRaftServerJmx.java b/ratis-test/src/test/java/org/apache/ratis/server/impl/TestRaftServerJmx.java new file mode 100644 index 0000000..f060645 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/impl/TestRaftServerJmx.java @@ -0,0 +1,109 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.server.impl; + +import org.apache.ratis.BaseTest; +import org.apache.ratis.conf.RaftProperties; +import org.apache.ratis.protocol.RaftGroupId; +import org.apache.ratis.protocol.RaftPeerId; +import org.apache.ratis.server.RaftServerMXBean; +import org.apache.ratis.server.simulation.MiniRaftClusterWithSimulatedRpc; +import org.apache.ratis.util.JmxRegister; +import org.junit.Assert; +import org.junit.Test; + +import javax.management.JMException; +import javax.management.MBeanServer; +import javax.management.ObjectInstance; +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.util.List; +import java.util.Set; + +import static org.apache.ratis.RaftTestUtil.waitForLeader; + +public class TestRaftServerJmx extends BaseTest { + @Test(timeout = 30000) + public void testJmxBeans() throws Exception { + final int NUM_SERVERS = 3; + final MiniRaftClusterWithSimulatedRpc cluster + = MiniRaftClusterWithSimulatedRpc.FACTORY.newCluster(3, new RaftProperties()); + cluster.start(); + waitForLeader(cluster); + + MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer(); + Set<ObjectInstance> objectInstances = platformMBeanServer.queryMBeans(new ObjectName("Ratis:*"), null); + Assert.assertEquals(NUM_SERVERS, objectInstances.size()); + + for (ObjectInstance instance : objectInstances) { + Object groupId = platformMBeanServer.getAttribute(instance.getObjectName(), "GroupId"); + Assert.assertEquals(cluster.getGroupId().toString(), groupId); + } + cluster.shutdown(); + } + + @Test(timeout = 30000) + public void testRegister() throws JMException { + { + final JmxRegister jmx = new JmxRegister(); + runUnregister(false, jmx); + + runRegister(true, "abc", jmx); + runRegister(false, "abc", jmx); + runUnregister(true, jmx); + runUnregister(false, jmx); + + runRegister(true, "abc", jmx); + runUnregister(true, jmx); + runUnregister(false, jmx); + } + + { + final JmxRegister jmx = new JmxRegister(); + runRegister(true, "host:1234", jmx); + runUnregister(true, jmx); + runUnregister(false, jmx); + } + } + + static void runRegister(boolean expectToSucceed, String name, JmxRegister jmx) { + final RaftServerMXBean mBean = new RaftServerMXBean() { + @Override + public String getId() { return null; } + @Override + public String getLeaderId() { return null; } + @Override + public long getCurrentTerm() { return 0; } + @Override + public String getGroupId() { return null; } + @Override + public String getRole() { return null; } + @Override + public List<String> getFollowers() { return null; } + }; + final RaftPeerId id = RaftPeerId.valueOf(name); + final RaftGroupId groupId = RaftGroupId.randomId(); + final boolean succeeded = RaftServerImpl.registerMBean(id, groupId, mBean, jmx); + Assert.assertEquals(expectToSucceed, succeeded); + } + + static void runUnregister(boolean expectToSucceed, JmxRegister jmx) throws JMException { + final boolean succeeded = jmx.unregister(); + Assert.assertEquals(expectToSucceed, succeeded); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/impl/TestServerState.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/impl/TestServerState.java b/ratis-test/src/test/java/org/apache/ratis/server/impl/TestServerState.java new file mode 100644 index 0000000..5801d2b --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/impl/TestServerState.java @@ -0,0 +1,127 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ratis.server.impl; + +import org.apache.ratis.BaseTest; +import org.apache.ratis.util.FileUtils; +import org.apache.ratis.util.JavaUtils; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Supplier; +import java.util.stream.IntStream; + +/** + * Test cases to verify ServerState. + */ +public class TestServerState { + + private static final Supplier<File> rootTestDir = JavaUtils.memoize( + () -> new File(BaseTest.getRootTestDir(), + TestServerState.class.getSimpleName() + + Integer.toHexString(ThreadLocalRandom.current().nextInt()))); + + @AfterClass + public static void tearDown() throws IOException { + FileUtils.deleteFully(rootTestDir.get()); + } + + /** + * Tests choosing of storage directory when only one volume is configured. + * + * @throws IOException in case of exception. + */ + @Test + public void testChooseStorageDirWithOneVolume() throws IOException { + File testDir = new File(rootTestDir.get(), UUID.randomUUID().toString()); + List<File> directories = Collections.singletonList(testDir); + String subDirOne = UUID.randomUUID().toString(); + String subDirTwo = UUID.randomUUID().toString(); + File storageDirOne = ServerState.chooseStorageDir(directories, subDirOne); + File storageDirTwo = ServerState.chooseStorageDir(directories, subDirTwo); + File expectedOne = new File(testDir, subDirOne); + File expectedTwo = new File(testDir, subDirTwo); + Assert.assertEquals(expectedOne.getCanonicalPath(), + storageDirOne.getCanonicalPath()); + Assert.assertEquals(expectedTwo.getCanonicalPath(), + storageDirTwo.getCanonicalPath()); + } + + /** + * Tests choosing of storage directory when multiple volumes are configured. + * + * @throws IOException in case of exception. + */ + @Test + public void testChooseStorageDirWithMultipleVolumes() throws IOException { + File testDir = new File(rootTestDir.get(), UUID.randomUUID().toString()); + List<File> directories = new ArrayList<>(); + IntStream.range(0, 10).mapToObj((i) -> new File(testDir, + Integer.toString(i))).forEach((dir) -> { + try { + FileUtils.createDirectories(dir); + directories.add(dir); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + + directories.stream().filter((dir) -> Integer.parseInt(dir.getName()) != 6) + .forEach( + (dir) -> { + try { + FileUtils.createDirectories( + new File(dir, UUID.randomUUID().toString())); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + String subDir = UUID.randomUUID().toString(); + File storageDirectory = ServerState.chooseStorageDir(directories, subDir); + File expected = new File(directories.get(6), subDir); + Assert.assertEquals(expected.getCanonicalPath(), + storageDirectory.getCanonicalPath()); + } + + /** + * Tests choosing of storage directory when only no volume is configured. + * + * @throws IOException in case of exception. + */ + @Test + public void testChooseStorageDirWithNoVolume() { + try { + ServerState.chooseStorageDir( + Collections.emptyList(), UUID.randomUUID().toString()); + Assert.fail(); + } catch (IOException ex) { + String expectedErrMsg = "No storage directory found."; + Assert.assertEquals(expectedErrMsg, ex.getMessage()); + } + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestGroupManagementWithSimulatedRpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestGroupManagementWithSimulatedRpc.java b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestGroupManagementWithSimulatedRpc.java new file mode 100644 index 0000000..73fbae9 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestGroupManagementWithSimulatedRpc.java @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.server.simulation; + +import org.apache.ratis.MiniRaftCluster; +import org.apache.ratis.server.impl.GroupManagementBaseTest; + +public class TestGroupManagementWithSimulatedRpc extends GroupManagementBaseTest { + @Override + public MiniRaftCluster.Factory<? extends MiniRaftCluster> getClusterFactory() { + return MiniRaftClusterWithSimulatedRpc.FACTORY; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestLeaderElectionWithSimulatedRpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestLeaderElectionWithSimulatedRpc.java b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestLeaderElectionWithSimulatedRpc.java new file mode 100644 index 0000000..7ea273b --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestLeaderElectionWithSimulatedRpc.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.server.simulation; + +import org.apache.ratis.server.impl.LeaderElectionTests; + +public class TestLeaderElectionWithSimulatedRpc + extends LeaderElectionTests<MiniRaftClusterWithSimulatedRpc> + implements MiniRaftClusterWithSimulatedRpc.FactoryGet { +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftExceptionWithSimulation.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftExceptionWithSimulation.java b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftExceptionWithSimulation.java new file mode 100644 index 0000000..f328ea3 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftExceptionWithSimulation.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.server.simulation; + +import org.apache.ratis.RaftExceptionBaseTest; + +public class TestRaftExceptionWithSimulation + extends RaftExceptionBaseTest<MiniRaftClusterWithSimulatedRpc> + implements MiniRaftClusterWithSimulatedRpc.FactoryGet { +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftReconfigurationWithSimulatedRpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftReconfigurationWithSimulatedRpc.java b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftReconfigurationWithSimulatedRpc.java new file mode 100644 index 0000000..b1bb26a --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftReconfigurationWithSimulatedRpc.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.server.simulation; + +import java.io.IOException; + +import org.apache.ratis.MiniRaftCluster; +import org.apache.ratis.server.impl.RaftReconfigurationBaseTest; + +public class TestRaftReconfigurationWithSimulatedRpc + extends RaftReconfigurationBaseTest { + @Override + public MiniRaftCluster getCluster(int peerNum) throws IOException { + return MiniRaftClusterWithSimulatedRpc.FACTORY.newCluster(peerNum, prop); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftSnapshotWithSimulatedRpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftSnapshotWithSimulatedRpc.java b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftSnapshotWithSimulatedRpc.java new file mode 100644 index 0000000..8345872 --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftSnapshotWithSimulatedRpc.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.server.simulation; + +import org.apache.ratis.MiniRaftCluster; +import org.apache.ratis.conf.RaftProperties; +import org.apache.ratis.statemachine.RaftSnapshotBaseTest; + +import java.io.IOException; + +public class TestRaftSnapshotWithSimulatedRpc extends RaftSnapshotBaseTest { + @Override + public MiniRaftCluster.Factory<?> getFactory() { + return MiniRaftClusterWithSimulatedRpc.FACTORY; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftStateMachineExceptionWithSimulatedRpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftStateMachineExceptionWithSimulatedRpc.java b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftStateMachineExceptionWithSimulatedRpc.java new file mode 100644 index 0000000..d8ca86f --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftStateMachineExceptionWithSimulatedRpc.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.server.simulation; + +import org.apache.ratis.server.impl.RaftStateMachineExceptionTests; + +public class TestRaftStateMachineExceptionWithSimulatedRpc extends + RaftStateMachineExceptionTests<MiniRaftClusterWithSimulatedRpc> + implements MiniRaftClusterWithSimulatedRpc.FactoryGet { +} http://git-wip-us.apache.org/repos/asf/incubator-ratis/blob/5c37675f/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftWithSimulatedRpc.java ---------------------------------------------------------------------- diff --git a/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftWithSimulatedRpc.java b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftWithSimulatedRpc.java new file mode 100644 index 0000000..391a6fa --- /dev/null +++ b/ratis-test/src/test/java/org/apache/ratis/server/simulation/TestRaftWithSimulatedRpc.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ratis.server.simulation; + +import org.apache.ratis.RaftBasicTests; + +public class TestRaftWithSimulatedRpc + extends RaftBasicTests<MiniRaftClusterWithSimulatedRpc> + implements MiniRaftClusterWithSimulatedRpc.FactoryGet { +}
