This is an automated email from the ASF dual-hosted git repository.

szetszwo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ratis.git


The following commit(s) were added to refs/heads/master by this push:
     new 85ca5680 RATIS-1619. Validate server id in raft group if the group is 
not empty (#677)
85ca5680 is described below

commit 85ca5680c1548a9b0cefb0cc48859b296131a187
Author: tison <[email protected]>
AuthorDate: Mon Jul 11 05:34:15 2022 +0800

    RATIS-1619. Validate server id in raft group if the group is not empty 
(#677)
---
 .../java/org/apache/ratis/util/Preconditions.java  |   5 +
 .../apache/ratis/server/impl/ServerImplUtils.java  |   5 +
 .../apache/ratis/server/impl/MiniRaftCluster.java  |  30 +++---
 .../server/impl/RaftReconfigurationBaseTest.java   |   2 +-
 .../datastream/DataStreamAsyncClusterTests.java    |   7 +-
 .../org/apache/ratis/server/ServerBuilderTest.java | 102 +++++++++++++++++++++
 .../shell/cli/sh/PeerCommandIntegrationTest.java   |   7 +-
 7 files changed, 139 insertions(+), 19 deletions(-)

diff --git 
a/ratis-common/src/main/java/org/apache/ratis/util/Preconditions.java 
b/ratis-common/src/main/java/org/apache/ratis/util/Preconditions.java
index 196bd992..e9a00261 100644
--- a/ratis-common/src/main/java/org/apache/ratis/util/Preconditions.java
+++ b/ratis-common/src/main/java/org/apache/ratis/util/Preconditions.java
@@ -102,6 +102,11 @@ public interface Preconditions {
         + name + " = " + object + " == null, class = " + object.getClass());
   }
 
+  static <T> T assertNotNull(T object, String format, Object... args) {
+    assertTrue(object != null, format, args);
+    return object;
+  }
+
   static <T> T assertInstanceOf(Object object, Class<T> clazz) {
     assertTrue(clazz.isInstance(object),
         () -> "Required instance of " + clazz + " but object.getClass() is " + 
object.getClass());
diff --git 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerImplUtils.java 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerImplUtils.java
index 8bbdfa68..6777b909 100644
--- 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerImplUtils.java
+++ 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/ServerImplUtils.java
@@ -29,6 +29,7 @@ import org.apache.ratis.server.raftlog.RaftLog;
 import org.apache.ratis.statemachine.StateMachine;
 import org.apache.ratis.util.IOUtils;
 import org.apache.ratis.util.JavaUtils;
+import org.apache.ratis.util.Preconditions;
 import org.apache.ratis.util.TimeDuration;
 
 import java.io.IOException;
@@ -47,6 +48,10 @@ public final class ServerImplUtils {
       RaftPeerId id, RaftGroup group, StateMachine.Registry 
stateMachineRegistry,
       RaftProperties properties, Parameters parameters) throws IOException {
     RaftServer.LOG.debug("newRaftServer: {}, {}", id, group);
+    if (group != null && !group.getPeers().isEmpty()) {
+      Preconditions.assertNotNull(id, "RaftPeerId %s is not in RaftGroup %s", 
id, group);
+      Preconditions.assertNotNull(group.getPeer(id), "RaftPeerId %s is not in 
RaftGroup %s", id, group);
+    }
     final RaftServerProxy proxy = newRaftServer(id, stateMachineRegistry, 
properties, parameters);
     proxy.initGroups(group);
     return proxy;
diff --git 
a/ratis-server/src/test/java/org/apache/ratis/server/impl/MiniRaftCluster.java 
b/ratis-server/src/test/java/org/apache/ratis/server/impl/MiniRaftCluster.java
index d479ae6e..652f26dc 100644
--- 
a/ratis-server/src/test/java/org/apache/ratis/server/impl/MiniRaftCluster.java
+++ 
b/ratis-server/src/test/java/org/apache/ratis/server/impl/MiniRaftCluster.java
@@ -283,8 +283,7 @@ public abstract class MiniRaftCluster implements Closeable {
   public MiniRaftCluster initServers() {
     LOG.info("servers = " + servers);
     if (servers.isEmpty()) {
-      putNewServers(CollectionUtils.as(group.getPeers(), RaftPeer::getId),
-          true, false);
+      putNewServers(CollectionUtils.as(group.getPeers(), RaftPeer::getId), 
true, group);
     }
     return this;
   }
@@ -295,18 +294,10 @@ public abstract class MiniRaftCluster implements 
Closeable {
     return s;
   }
 
-  private Collection<RaftServer> putNewServers(
-      Iterable<RaftPeerId> peers, boolean format, boolean emptyPeer) {
-    if (emptyPeer) {
-      final RaftGroup raftGroup = RaftGroup.valueOf(group.getGroupId(), 
Collections.emptyList());
+  private Collection<RaftServer> putNewServers(Iterable<RaftPeerId> peers, 
boolean format, RaftGroup raftGroup) {
       return StreamSupport.stream(peers.spliterator(), false)
           .map(id -> putNewServer(id, raftGroup, format))
           .collect(Collectors.toList());
-    } else {
-      return StreamSupport.stream(peers.spliterator(), false)
-          .map(id -> putNewServer(id, group, format))
-          .collect(Collectors.toList());
-    }
   }
 
   public void start() throws IOException {
@@ -345,7 +336,7 @@ public abstract class MiniRaftCluster implements Closeable {
 
     List<RaftPeerId> idList = new ArrayList<>(servers.keySet());
     servers.clear();
-    putNewServers(idList, format, false);
+    putNewServers(idList, format, group);
     start();
   }
 
@@ -426,9 +417,20 @@ public abstract class MiniRaftCluster implements Closeable 
{
       boolean emptyPeer) throws IOException {
     LOG.info("Add new peers {}", Arrays.asList(ids));
 
+    final Iterable<RaftPeerId> peerIds = 
CollectionUtils.as(Arrays.asList(ids), RaftPeerId::valueOf);
+    final RaftGroup raftGroup;
+    if (emptyPeer) {
+      raftGroup = RaftGroup.valueOf(group.getGroupId(), 
Collections.emptyList());
+    } else {
+      final Collection<RaftPeer> newPeers = 
StreamSupport.stream(peerIds.spliterator(), false)
+          .map(id -> RaftPeer.newBuilder().setId(id).build())
+          .collect(Collectors.toSet());
+      newPeers.addAll(group.getPeers());
+      raftGroup = RaftGroup.valueOf(group.getGroupId(), newPeers);
+    }
+
     // create and add new RaftServers
-    final Collection<RaftServer> newServers = putNewServers(
-        CollectionUtils.as(Arrays.asList(ids), RaftPeerId::valueOf), true, 
emptyPeer);
+    final Collection<RaftServer> newServers = putNewServers(peerIds, true, 
raftGroup);
 
     startServers(newServers);
     if (!startNewPeer) {
diff --git 
a/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftReconfigurationBaseTest.java
 
b/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftReconfigurationBaseTest.java
index d764988e..abf0292b 100644
--- 
a/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftReconfigurationBaseTest.java
+++ 
b/ratis-server/src/test/java/org/apache/ratis/server/impl/RaftReconfigurationBaseTest.java
@@ -240,7 +240,7 @@ public abstract class RaftReconfigurationBaseTest<CLUSTER 
extends MiniRaftCluste
         CountDownLatch latch = new CountDownLatch(1);
         Thread clientThread = new Thread(() -> {
           try {
-            PeerChanges c1 = cluster.addNewPeers(2, true);
+            PeerChanges c1 = cluster.addNewPeers(2, true, true);
             LOG.info("Start changing the configuration: {}",
                     asList(c1.allPeersInNewConf));
 
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/datastream/DataStreamAsyncClusterTests.java
 
b/ratis-test/src/test/java/org/apache/ratis/datastream/DataStreamAsyncClusterTests.java
index 1f4e8658..e1844874 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/datastream/DataStreamAsyncClusterTests.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/datastream/DataStreamAsyncClusterTests.java
@@ -145,7 +145,12 @@ public abstract class DataStreamAsyncClusterTests<CLUSTER 
extends MiniRaftCluste
 
   long runTestDataStream(CLUSTER cluster, int numStreams, int bufferSize, int 
bufferNum, boolean stepDownLeader) {
     final Iterable<RaftServer> servers = 
CollectionUtils.as(cluster.getServers(), s -> s);
-    final RaftPeerId leader = cluster.getLeader().getId();
+    final RaftPeerId leader;
+    try {
+      leader = RaftTestUtil.waitForLeader(cluster).getId();
+    } catch (InterruptedException e) {
+      throw new CompletionException(e);
+    }
     final List<CompletableFuture<RaftClientReply>> futures = new ArrayList<>();
     final RaftPeer primaryServer = 
CollectionUtils.random(cluster.getGroup().getPeers());
     try(RaftClient client = cluster.createClient(primaryServer)) {
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/server/ServerBuilderTest.java 
b/ratis-test/src/test/java/org/apache/ratis/server/ServerBuilderTest.java
new file mode 100644
index 00000000..dd76a2ec
--- /dev/null
+++ b/ratis-test/src/test/java/org/apache/ratis/server/ServerBuilderTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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 java.io.IOException;
+import org.apache.ratis.BaseTest;
+import org.apache.ratis.conf.RaftProperties;
+import org.apache.ratis.protocol.RaftGroup;
+import org.apache.ratis.protocol.RaftGroupId;
+import org.apache.ratis.protocol.RaftPeer;
+import org.apache.ratis.protocol.RaftPeerId;
+import org.apache.ratis.statemachine.impl.BaseStateMachine;
+import org.apache.ratis.util.Preconditions;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test {@link RaftServer.Builder}.
+ */
+public class ServerBuilderTest extends BaseTest {
+
+    @Test
+    public void testPeerIdInRaftGroup() throws Exception {
+        RaftPeer peer = RaftPeer.newBuilder().setId("n0").build();
+        RaftGroup group = RaftGroup.valueOf(RaftGroupId.randomId(), peer);
+        RaftServer server = RaftServer.newBuilder()
+            .setServerId(peer.getId())
+            .setGroup(group)
+            .setStateMachine(new BaseStateMachine())
+            .setProperties(new RaftProperties())
+            .build();
+        server.close();
+    }
+
+    @Test
+    public void testPeerIdNotInRaftGroup() {
+        RaftPeer peer = RaftPeer.newBuilder().setId("n0").build();
+        RaftGroup group = RaftGroup.valueOf(RaftGroupId.randomId(), peer);
+        try {
+            RaftServer.newBuilder()
+                .setServerId(RaftPeerId.valueOf("n1"))
+                .setGroup(group)
+                .setStateMachine(new BaseStateMachine())
+                .setProperties(new RaftProperties())
+                .build();
+            Assert.fail("did not get expected exception");
+        } catch (IOException e) {
+            Preconditions.assertInstanceOf(e.getCause(), 
IllegalStateException.class);
+        }
+    }
+
+    @Test
+    public void testNullPeerIdWithRaftGroup() {
+        RaftPeer peer = RaftPeer.newBuilder().setId("n0").build();
+        RaftGroup group = RaftGroup.valueOf(RaftGroupId.randomId(), peer);
+        try {
+            RaftServer.newBuilder()
+                .setGroup(group)
+                .setStateMachine(new BaseStateMachine())
+                .setProperties(new RaftProperties())
+                .build();
+            Assert.fail("did not get expected exception");
+        } catch (IOException e) {
+            Preconditions.assertInstanceOf(e.getCause(), 
IllegalStateException.class);
+        }
+    }
+
+    @Test
+    public void testPeerIdWithNullRaftGroup() throws Exception {
+        RaftPeer peer = RaftPeer.newBuilder().setId("n0").build();
+        RaftServer server = RaftServer.newBuilder()
+            .setServerId(peer.getId())
+            .setStateMachine(new BaseStateMachine())
+            .setProperties(new RaftProperties())
+            .build();
+        server.close();
+    }
+
+    @Test
+    public void testNullPeerIdWithNullRaftGroup() throws Exception {
+        RaftServer server = RaftServer.newBuilder()
+            .setStateMachine(new BaseStateMachine())
+            .setProperties(new RaftProperties())
+            .build();
+        server.close();
+    }
+}
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/PeerCommandIntegrationTest.java
 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/PeerCommandIntegrationTest.java
index 285d431e..99d95553 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/PeerCommandIntegrationTest.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/PeerCommandIntegrationTest.java
@@ -79,11 +79,12 @@ public abstract class PeerCommandIntegrationTest <CLUSTER 
extends MiniRaftCluste
   void runTestPeerAddCommand(MiniRaftCluster cluster) throws Exception {
     LOG.info("Start testMultiGroup" + cluster.printServers());
 
-    final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
+    RaftTestUtil.waitForLeader(cluster);
     RaftPeer[] peers = cluster.getPeers().toArray(new RaftPeer[0]);
-    RaftPeer[] newPeers = cluster.addNewPeers(1, true).newPeers;
+    RaftPeer[] newPeers = cluster.addNewPeers(1, true, true).newPeers;
+
     RaftServerTestUtil.waitAndCheckNewConf(cluster, peers, 0, null);
-    StringBuffer sb = new StringBuffer();
+    StringBuilder sb = new StringBuilder();
     for (RaftPeer peer : peers) {
       sb.append(peer.getAdminAddress());
       sb.append(",");

Reply via email to