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 a9c63015 RATIS-1580. Add ratis-shell peer and election command unit 
test (#645)
a9c63015 is described below

commit a9c63015503c2785f56e138453ccab1b074c62e7
Author: Yaolong Liu <[email protected]>
AuthorDate: Fri May 13 17:57:52 2022 +0800

    RATIS-1580. Add ratis-shell peer and election command unit test (#645)
---
 .../apache/ratis/shell/cli/sh/peer/AddCommand.java |  37 +++++--
 .../ratis/shell/cli/sh/peer/RemoveCommand.java     |  28 +++--
 .../TestElectionCommandIntegrationWithGrpc.java    |  26 +++++
 .../cli/TestPeerCommandIntegrationWithGrpc.java    |  26 +++++
 .../sh/AbstractCommandIntegrationTestWithGrpc.java |  41 +++++++
 ...st.java => ElectionCommandIntegrationTest.java} |  87 ++++++++-------
 .../shell/cli/sh/GroupCommandIntegrationTest.java  |  30 ++---
 .../shell/cli/sh/PeerCommandIntegrationTest.java   | 123 +++++++++++++++++++++
 .../cli/sh/SnapshotCommandIntegrationTest.java     |  26 +----
 9 files changed, 325 insertions(+), 99 deletions(-)

diff --git 
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java 
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java
index 9c87f691..31723353 100644
--- 
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java
+++ 
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java
@@ -30,6 +30,7 @@ import org.apache.ratis.shell.cli.sh.command.Context;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -42,6 +43,7 @@ import java.util.stream.Stream;
 public class AddCommand extends AbstractRatisCommand {
 
   public static final String ADDRESS_OPTION_NAME = "address";
+  public static final String PEER_ID_OPTION_NAME = "peerId";
   /**
    * @param context command context
    */
@@ -58,8 +60,25 @@ public class AddCommand extends AbstractRatisCommand {
   public int run(CommandLine cl) throws IOException {
     super.run(cl);
     final Map<RaftPeerId, InetSocketAddress> peersInfo = new HashMap<>();
-    final List<RaftPeerId> ids =
-        getIds(cl.getOptionValue(ADDRESS_OPTION_NAME).split(","), 
peersInfo::put);
+    List<RaftPeerId> ids;
+
+    if (cl.hasOption(ADDRESS_OPTION_NAME) && 
cl.hasOption(PEER_ID_OPTION_NAME)) {
+      ids = Arrays.stream(cl.getOptionValue(PEER_ID_OPTION_NAME).split(","))
+          .map(RaftPeerId::getRaftPeerId).collect(Collectors.toList());
+      List<InetSocketAddress> addresses =
+          Arrays.stream(cl.getOptionValue(ADDRESS_OPTION_NAME).split(","))
+              .map(s -> 
parseInetSocketAddress(s)).collect(Collectors.toList());
+      assert ids.size() == addresses.size();
+      for (int i = 0; i < ids.size(); i++) {
+        peersInfo.put(ids.get(i), addresses.get(i));
+      }
+    } else if (cl.hasOption(ADDRESS_OPTION_NAME)) {
+      ids = getIds(cl.getOptionValue(ADDRESS_OPTION_NAME).split(","), 
peersInfo::put);
+    } else {
+      throw new IllegalArgumentException(
+          "Both " + PEER_ID_OPTION_NAME + " and " + ADDRESS_OPTION_NAME + " 
options are missing.");
+    }
+
     try (RaftClient client = RaftUtils.createClient(getRaftGroup())) {
       final Stream<RaftPeer> remaining = getRaftGroup().getPeers().stream();
       final Stream<RaftPeer> adding = ids.stream().map(raftPeerId -> 
RaftPeer.newBuilder()
@@ -80,8 +99,9 @@ public class AddCommand extends AbstractRatisCommand {
     return String.format("%s"
             + " -%s 
<PEER0_HOST:PEER0_PORT,PEER1_HOST:PEER1_PORT,PEER2_HOST:PEER2_PORT>"
             + " [-%s <RAFT_GROUP_ID>]"
-            + " -%s <PEER_HOST:PEER_PORT>",
-        getCommandName(), PEER_OPTION_NAME, GROUPID_OPTION_NAME, 
ADDRESS_OPTION_NAME);
+            + " <[-%s <PEER0_HOST:PEER0_PORT>]|[-%s <peerId>]>",
+        getCommandName(), PEER_OPTION_NAME, GROUPID_OPTION_NAME,
+        ADDRESS_OPTION_NAME, PEER_ID_OPTION_NAME);
   }
 
   @Override
@@ -91,12 +111,15 @@ public class AddCommand extends AbstractRatisCommand {
 
   @Override
   public Options getOptions() {
-    return super.getOptions().addOption(
-        Option.builder()
+    return super.getOptions()
+        .addOption(Option.builder()
             .option(ADDRESS_OPTION_NAME)
             .hasArg()
-            .required()
             .desc("The address information of ratis peers")
+            .build())
+        .addOption(Option.builder()
+            .option(PEER_ID_OPTION_NAME).hasArg()
+            .desc("The peer id of ratis peers")
             .build());
   }
 
diff --git 
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java
 
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java
index 0ab198dd..d8cc7627 100644
--- 
a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java
+++ 
b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java
@@ -29,6 +29,7 @@ import 
org.apache.ratis.shell.cli.sh.command.AbstractRatisCommand;
 import org.apache.ratis.shell.cli.sh.command.Context;
 
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -38,6 +39,7 @@ import java.util.stream.Collectors;
 public class RemoveCommand extends AbstractRatisCommand {
 
   public static final String ADDRESS_OPTION_NAME = "address";
+  public static final String PEER_ID_OPTION_NAME = "peerId";
   /**
    * @param context command context
    */
@@ -53,8 +55,16 @@ public class RemoveCommand extends AbstractRatisCommand {
   @Override
   public int run(CommandLine cl) throws IOException {
     super.run(cl);
-    final List<RaftPeerId> ids =
-        getIds(cl.getOptionValue(ADDRESS_OPTION_NAME).split(","), (a, b) -> 
{});
+    final List<RaftPeerId> ids;
+    if (cl.hasOption(PEER_ID_OPTION_NAME)) {
+      ids = Arrays.stream(cl.getOptionValue(PEER_ID_OPTION_NAME).split(","))
+          .map(RaftPeerId::getRaftPeerId).collect(Collectors.toList());
+    } else if (cl.hasOption(ADDRESS_OPTION_NAME)) {
+      ids = getIds(cl.getOptionValue(ADDRESS_OPTION_NAME).split(","), (a, b) 
-> {});
+    } else {
+      throw new IllegalArgumentException(
+          "Both " + PEER_ID_OPTION_NAME + " and " + ADDRESS_OPTION_NAME + " 
options are missing.");
+    }
     try (RaftClient client = RaftUtils.createClient(getRaftGroup())) {
       final List<RaftPeer> remaining = getRaftGroup().getPeers().stream()
           .filter(raftPeer -> 
!ids.contains(raftPeer.getId())).collect(Collectors.toList());
@@ -70,8 +80,9 @@ public class RemoveCommand extends AbstractRatisCommand {
     return String.format("%s"
             + " -%s 
<PEER0_HOST:PEER0_PORT,PEER1_HOST:PEER1_PORT,PEER2_HOST:PEER2_PORT>"
             + " [-%s <RAFT_GROUP_ID>]"
-            + " -%s <PEER_HOST:PEER_PORT>",
-        getCommandName(), PEER_OPTION_NAME, GROUPID_OPTION_NAME, 
ADDRESS_OPTION_NAME);
+            + " <[-%s <PEER0_HOST:PEER0_PORT>]|[-%s <peerId>]>",
+        getCommandName(), PEER_OPTION_NAME, GROUPID_OPTION_NAME,
+        ADDRESS_OPTION_NAME, PEER_ID_OPTION_NAME);
   }
 
   @Override
@@ -81,12 +92,15 @@ public class RemoveCommand extends AbstractRatisCommand {
 
   @Override
   public Options getOptions() {
-    return super.getOptions().addOption(
-        Option.builder()
+    return super.getOptions()
+        .addOption(Option.builder()
             .option(ADDRESS_OPTION_NAME)
             .hasArg()
-            .required()
             .desc("The address information of ratis peers")
+            .build())
+        .addOption(Option.builder()
+            .option(PEER_ID_OPTION_NAME).hasArg()
+            .desc("The peer id of ratis peers")
             .build());
   }
 
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/grpc/cli/TestElectionCommandIntegrationWithGrpc.java
 
b/ratis-test/src/test/java/org/apache/ratis/grpc/cli/TestElectionCommandIntegrationWithGrpc.java
new file mode 100644
index 00000000..35478624
--- /dev/null
+++ 
b/ratis-test/src/test/java/org/apache/ratis/grpc/cli/TestElectionCommandIntegrationWithGrpc.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.cli;
+
+import org.apache.ratis.grpc.MiniRaftClusterWithGrpc;
+import org.apache.ratis.shell.cli.sh.ElectionCommandIntegrationTest;
+
+public class TestElectionCommandIntegrationWithGrpc
+    extends ElectionCommandIntegrationTest<MiniRaftClusterWithGrpc>
+    implements MiniRaftClusterWithGrpc.FactoryGet{
+}
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/grpc/cli/TestPeerCommandIntegrationWithGrpc.java
 
b/ratis-test/src/test/java/org/apache/ratis/grpc/cli/TestPeerCommandIntegrationWithGrpc.java
new file mode 100644
index 00000000..ec2de799
--- /dev/null
+++ 
b/ratis-test/src/test/java/org/apache/ratis/grpc/cli/TestPeerCommandIntegrationWithGrpc.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.cli;
+
+import org.apache.ratis.grpc.MiniRaftClusterWithGrpc;
+import org.apache.ratis.shell.cli.sh.PeerCommandIntegrationTest;
+
+public class TestPeerCommandIntegrationWithGrpc
+    extends PeerCommandIntegrationTest<MiniRaftClusterWithGrpc>
+    implements MiniRaftClusterWithGrpc.FactoryGet{
+}
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/AbstractCommandIntegrationTestWithGrpc.java
 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/AbstractCommandIntegrationTestWithGrpc.java
new file mode 100644
index 00000000..eeee5b3a
--- /dev/null
+++ 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/AbstractCommandIntegrationTestWithGrpc.java
@@ -0,0 +1,41 @@
+/**
+ * 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.shell.cli.sh;
+
+import org.apache.ratis.BaseTest;
+import org.apache.ratis.server.RaftServer;
+import org.apache.ratis.server.impl.MiniRaftCluster;
+
+public abstract class AbstractCommandIntegrationTestWithGrpc extends BaseTest {
+
+  static final int NUM_SERVERS = 3;
+
+  public String getClusterAddress(MiniRaftCluster cluster) {
+    String address = cluster.getLeader().getPeer().getAdminAddress();
+    StringBuilder sb = new StringBuilder();
+    for (RaftServer.Division division : cluster.getFollowers()) {
+      sb.append(division.getPeer().getAdminAddress());
+      sb.append(",");
+    }
+    sb.append(address);
+    return sb.toString();
+  }
+
+
+
+}
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/ElectionCommandIntegrationTest.java
similarity index 50%
copy from 
ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
copy to 
ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/ElectionCommandIntegrationTest.java
index edcc71a4..d68300b2 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/ElectionCommandIntegrationTest.java
@@ -18,7 +18,6 @@
 package org.apache.ratis.shell.cli.sh;
 
 import org.apache.log4j.Level;
-import org.apache.ratis.BaseTest;
 import org.apache.ratis.RaftTestUtil;
 import org.apache.ratis.client.RaftClient;
 import org.apache.ratis.conf.RaftProperties;
@@ -28,24 +27,24 @@ import org.apache.ratis.server.impl.MiniRaftCluster;
 import org.apache.ratis.server.raftlog.RaftLog;
 import org.apache.ratis.statemachine.SimpleStateMachine4Testing;
 import org.apache.ratis.statemachine.StateMachine;
+import org.apache.ratis.util.JavaUtils;
 import org.apache.ratis.util.Log4jUtils;
 import org.apache.ratis.util.SizeInBytes;
-
+import org.apache.ratis.util.TimeDuration;
 import org.junit.Assert;
 import org.junit.Test;
 
-public abstract class GroupCommandIntegrationTest<CLUSTER extends 
MiniRaftCluster>
-    extends BaseTest
-    implements MiniRaftCluster.Factory.Get<CLUSTER> {
+import java.util.concurrent.TimeUnit;
+
+public abstract class ElectionCommandIntegrationTest <CLUSTER extends 
MiniRaftCluster>
+    extends AbstractCommandIntegrationTestWithGrpc implements 
MiniRaftCluster.Factory.Get<CLUSTER>{
+
   {
     Log4jUtils.setLogLevel(RaftServer.Division.LOG, Level.WARN);
     Log4jUtils.setLogLevel(RaftLog.LOG, Level.WARN);
     Log4jUtils.setLogLevel(RaftClient.LOG, Level.WARN);
   }
 
-  static final int NUM_SERVERS = 3;
-  static final String NEW_LINE = System.lineSeparator();
-
   {
     final RaftProperties prop = getProperties();
     prop.setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY,
@@ -54,54 +53,56 @@ public abstract class GroupCommandIntegrationTest<CLUSTER 
extends MiniRaftCluste
   }
 
   @Test
-  public void testGroupListCommand() throws Exception {
-    runWithNewCluster(NUM_SERVERS, this::runTestGroupListCommand);
+  public void testElectionTransferCommand() throws Exception {
+    runWithNewCluster(NUM_SERVERS, this::runTestElectionTransferCommand);
   }
 
-  void runTestGroupListCommand(MiniRaftCluster cluster) throws Exception {
+  void runTestElectionTransferCommand(MiniRaftCluster cluster) throws 
Exception {
     final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
-    String address = cluster.getLeader().getPeer().getAdminAddress();
-    StringBuffer sb = new StringBuffer();
-    for (RaftServer.Division division : cluster.getFollowers()) {
-      sb.append(division.getPeer().getAdminAddress());
-      sb.append(",");
-    }
-    sb.append(address);
+    String address = getClusterAddress(cluster);
+    RaftServer.Division newLeader = cluster.getFollowers().get(0);
     final StringPrintStream out = new StringPrintStream();
     RatisShell shell = new RatisShell(out.getPrintStream());
-    int ret = shell.run("group", "list", "-peers", sb.toString(), "-peerId",
-        leader.getPeer().getId().toString());
+    Assert.assertNotEquals(cluster.getLeader().getId(), newLeader.getId());
+    int ret = shell.run("election", "transfer", "-peers", address, "-address",
+        newLeader.getPeer().getAddress());
+
     Assert.assertEquals(0, ret);
-    String info = out.toString().trim();
-    String expected = String.format("The peerId %s (server %s) is in 1 groups, 
and the groupIds is: [%s]",
-        leader.getId(), leader.getPeer().getAddress(), 
leader.getGroup().getGroupId());
-    Assert.assertEquals(expected, info);
+    JavaUtils.attempt(() -> {
+      Assert.assertEquals(cluster.getLeader().getId(), newLeader.getId());
+    }, 10, TimeDuration.valueOf(1, TimeUnit.SECONDS), 
"testElectionTransferCommand", LOG);
   }
 
   @Test
-  public void testGroupInfoCommand() throws Exception {
-    runWithNewCluster(NUM_SERVERS, this::runTestGroupInfoCommand);
+  public void testElectionPauseResumeCommand() throws Exception {
+    runWithNewCluster(NUM_SERVERS, this::runTestElectionPauseResumeCommand);
   }
 
-  void runTestGroupInfoCommand(MiniRaftCluster cluster) throws Exception {
+  void runTestElectionPauseResumeCommand(MiniRaftCluster cluster) throws 
Exception {
     final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
-    final String address = cluster.getLeader().getPeer().getAdminAddress();
-    StringBuffer sb = new StringBuffer();
-    for (RaftServer.Division division : cluster.getFollowers()) {
-      sb.append(division.getPeer().getAdminAddress());
-      sb.append(",");
-    }
-    sb.append(address);
-
+    String sb = getClusterAddress(cluster);
+    RaftServer.Division newLeader = cluster.getFollowers().get(0);
     final StringPrintStream out = new StringPrintStream();
     RatisShell shell = new RatisShell(out.getPrintStream());
-    int ret = shell.run("group", "info", "-peers", sb.toString());
-    Assert.assertEquals(0 , ret);
-    String result = out.toString().trim();
-    String hearder = String.format("group id: %s%sleader info: %s(%s)%s%s",
-        cluster.getGroupId().getUuid(), NEW_LINE, leader.getId(),
-        cluster.getLeader().getPeer().getAddress(), NEW_LINE, NEW_LINE);
-    String info = result.substring(0, hearder.length());
-    Assert.assertEquals(hearder, info);
+    Assert.assertNotEquals(cluster.getLeader().getId(), newLeader.getId());
+    int ret = shell.run("election", "pause", "-peers", sb.toString(), 
"-address",
+        newLeader.getPeer().getAddress());
+
+    Assert.assertEquals(0, ret);
+    ret = shell.run("peer", "setPriority", "-peers", sb.toString(), 
"-addressPriority",
+        newLeader.getPeer().getAddress() + "|" + 2);
+    Assert.assertEquals(0, ret);
+
+    JavaUtils.attempt(() -> {
+      Assert.assertNotEquals(cluster.getLeader().getId(), newLeader.getId());
+    }, 10, TimeDuration.valueOf(1, TimeUnit.SECONDS), 
"testElectionPauseResumeCommand", LOG);
+
+    ret = shell.run("election", "resume", "-peers", sb.toString(), "-address",
+        newLeader.getPeer().getAddress());
+    Assert.assertEquals(0, ret);
+
+    JavaUtils.attempt(() -> {
+      Assert.assertEquals(cluster.getLeader().getId(), newLeader.getId());
+    }, 10, TimeDuration.valueOf(1, TimeUnit.SECONDS), 
"testElectionPauseResumeCommand", LOG);
   }
 }
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
index edcc71a4..515cbcae 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/GroupCommandIntegrationTest.java
@@ -18,7 +18,6 @@
 package org.apache.ratis.shell.cli.sh;
 
 import org.apache.log4j.Level;
-import org.apache.ratis.BaseTest;
 import org.apache.ratis.RaftTestUtil;
 import org.apache.ratis.client.RaftClient;
 import org.apache.ratis.conf.RaftProperties;
@@ -35,17 +34,17 @@ import org.junit.Assert;
 import org.junit.Test;
 
 public abstract class GroupCommandIntegrationTest<CLUSTER extends 
MiniRaftCluster>
-    extends BaseTest
+    extends AbstractCommandIntegrationTestWithGrpc
     implements MiniRaftCluster.Factory.Get<CLUSTER> {
+
+  static final String NEW_LINE = System.lineSeparator();
+
   {
     Log4jUtils.setLogLevel(RaftServer.Division.LOG, Level.WARN);
     Log4jUtils.setLogLevel(RaftLog.LOG, Level.WARN);
     Log4jUtils.setLogLevel(RaftClient.LOG, Level.WARN);
   }
 
-  static final int NUM_SERVERS = 3;
-  static final String NEW_LINE = System.lineSeparator();
-
   {
     final RaftProperties prop = getProperties();
     prop.setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY,
@@ -60,16 +59,10 @@ public abstract class GroupCommandIntegrationTest<CLUSTER 
extends MiniRaftCluste
 
   void runTestGroupListCommand(MiniRaftCluster cluster) throws Exception {
     final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
-    String address = cluster.getLeader().getPeer().getAdminAddress();
-    StringBuffer sb = new StringBuffer();
-    for (RaftServer.Division division : cluster.getFollowers()) {
-      sb.append(division.getPeer().getAdminAddress());
-      sb.append(",");
-    }
-    sb.append(address);
+    final String address = getClusterAddress(cluster);
     final StringPrintStream out = new StringPrintStream();
     RatisShell shell = new RatisShell(out.getPrintStream());
-    int ret = shell.run("group", "list", "-peers", sb.toString(), "-peerId",
+    int ret = shell.run("group", "list", "-peers", address, "-peerId",
         leader.getPeer().getId().toString());
     Assert.assertEquals(0, ret);
     String info = out.toString().trim();
@@ -85,17 +78,10 @@ public abstract class GroupCommandIntegrationTest<CLUSTER 
extends MiniRaftCluste
 
   void runTestGroupInfoCommand(MiniRaftCluster cluster) throws Exception {
     final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
-    final String address = cluster.getLeader().getPeer().getAdminAddress();
-    StringBuffer sb = new StringBuffer();
-    for (RaftServer.Division division : cluster.getFollowers()) {
-      sb.append(division.getPeer().getAdminAddress());
-      sb.append(",");
-    }
-    sb.append(address);
-
+    final String address = getClusterAddress(cluster);
     final StringPrintStream out = new StringPrintStream();
     RatisShell shell = new RatisShell(out.getPrintStream());
-    int ret = shell.run("group", "info", "-peers", sb.toString());
+    int ret = shell.run("group", "info", "-peers", address);
     Assert.assertEquals(0 , ret);
     String result = out.toString().trim();
     String hearder = String.format("group id: %s%sleader info: %s(%s)%s%s",
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
new file mode 100644
index 00000000..285d431e
--- /dev/null
+++ 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/PeerCommandIntegrationTest.java
@@ -0,0 +1,123 @@
+/**
+ * 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.shell.cli.sh;
+
+import org.apache.log4j.Level;
+import org.apache.ratis.RaftTestUtil;
+import org.apache.ratis.client.RaftClient;
+import org.apache.ratis.conf.RaftProperties;
+import org.apache.ratis.protocol.RaftPeer;
+import org.apache.ratis.server.RaftServer;
+import org.apache.ratis.server.RaftServerConfigKeys;
+import org.apache.ratis.server.impl.MiniRaftCluster;
+import org.apache.ratis.server.impl.RaftServerTestUtil;
+import org.apache.ratis.server.raftlog.RaftLog;
+import org.apache.ratis.statemachine.SimpleStateMachine4Testing;
+import org.apache.ratis.statemachine.StateMachine;
+import org.apache.ratis.thirdparty.com.google.common.collect.ObjectArrays;
+import org.apache.ratis.util.JavaUtils;
+import org.apache.ratis.util.Log4jUtils;
+import org.apache.ratis.util.SizeInBytes;
+import org.apache.ratis.util.TimeDuration;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+public abstract class PeerCommandIntegrationTest <CLUSTER extends 
MiniRaftCluster>
+    extends AbstractCommandIntegrationTestWithGrpc implements 
MiniRaftCluster.Factory.Get<CLUSTER> {
+
+  {
+    Log4jUtils.setLogLevel(RaftServer.Division.LOG, Level.WARN);
+    Log4jUtils.setLogLevel(RaftLog.LOG, Level.WARN);
+    Log4jUtils.setLogLevel(RaftClient.LOG, Level.WARN);
+  }
+
+  {
+    final RaftProperties prop = getProperties();
+    prop.setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY,
+        SimpleStateMachine4Testing.class, StateMachine.class);
+    RaftServerConfigKeys.Log.setSegmentSizeMax(prop, 
SizeInBytes.valueOf("8KB"));
+  }
+
+  @Test
+  public void testPeerAddRemoveCommand() throws Exception {
+    runWithNewCluster(NUM_SERVERS, this::runTestPeerRemoveCommand);
+    runWithNewCluster(NUM_SERVERS, this::runTestPeerAddCommand);
+  }
+
+  void runTestPeerRemoveCommand(MiniRaftCluster cluster) throws Exception {
+    final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
+    final String address = getClusterAddress(cluster);
+    RaftServer.Division toRemove = cluster.getFollowers().get(0);
+    RaftPeer[] peers = new RaftPeer[]{cluster.getFollowers().get(1).getPeer(), 
leader.getPeer()};
+    final StringPrintStream out = new StringPrintStream();
+    RatisShell shell = new RatisShell(out.getPrintStream());
+    Assert.assertTrue(cluster.getFollowers().contains(toRemove));
+    int ret = shell.run("peer", "remove", "-peers", address, "-peerId",
+        toRemove.getPeer().getId().toString());
+
+    Assert.assertEquals(0, ret);
+    RaftServerTestUtil.waitAndCheckNewConf(cluster, peers,1, null);
+  }
+
+  void runTestPeerAddCommand(MiniRaftCluster cluster) throws Exception {
+    LOG.info("Start testMultiGroup" + cluster.printServers());
+
+    final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
+    RaftPeer[] peers = cluster.getPeers().toArray(new RaftPeer[0]);
+    RaftPeer[] newPeers = cluster.addNewPeers(1, true).newPeers;
+    RaftServerTestUtil.waitAndCheckNewConf(cluster, peers, 0, null);
+    StringBuffer sb = new StringBuffer();
+    for (RaftPeer peer : peers) {
+      sb.append(peer.getAdminAddress());
+      sb.append(",");
+    }
+    final StringPrintStream out = new StringPrintStream();
+    RatisShell shell = new RatisShell(out.getPrintStream());
+
+    int ret = shell.run("peer", "add", "-peers", sb.toString(), "-address",
+        newPeers[0].getAdminAddress(), "-peerId", 
newPeers[0].getId().toString());
+
+    Assert.assertEquals(0, ret);
+    RaftServerTestUtil.waitAndCheckNewConf(cluster, ObjectArrays.concat(peers, 
newPeers[0]), 0, null);
+
+  }
+
+  @Test
+  public void testPeerSetPriorityCommand() throws Exception {
+    runWithNewCluster(NUM_SERVERS, this::runTestPeerSetPriorityCommand);
+  }
+
+  void runTestPeerSetPriorityCommand(MiniRaftCluster cluster) throws Exception 
{
+    final RaftServer.Division leader = RaftTestUtil.waitForLeader(cluster);
+    final String address = getClusterAddress(cluster);
+
+    RaftServer.Division newLeader = cluster.getFollowers().get(0);
+    final StringPrintStream out = new StringPrintStream();
+    RatisShell shell = new RatisShell(out.getPrintStream());
+    Assert.assertTrue(cluster.getFollowers().contains(newLeader));
+    int ret = shell.run("peer", "setPriority", "-peers", address, 
"-addressPriority",
+        newLeader.getPeer().getAddress()+ "|" + 2);
+    Assert.assertEquals(0, ret);
+    JavaUtils.attempt(() -> {
+      Assert.assertEquals(cluster.getLeader().getId(), newLeader.getId());
+    }, 10, TimeDuration.valueOf(1, TimeUnit.SECONDS), 
"testPeerSetPriorityCommand", LOG);
+  }
+
+}
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/SnapshotCommandIntegrationTest.java
 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/SnapshotCommandIntegrationTest.java
index 58a3b51b..fbb804a4 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/SnapshotCommandIntegrationTest.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/shell/cli/sh/SnapshotCommandIntegrationTest.java
@@ -18,7 +18,6 @@
 package org.apache.ratis.shell.cli.sh;
 
 import org.apache.log4j.Level;
-import org.apache.ratis.BaseTest;
 import org.apache.ratis.RaftTestUtil;
 import org.apache.ratis.client.RaftClient;
 import org.apache.ratis.conf.RaftProperties;
@@ -38,16 +37,15 @@ import org.junit.Test;
 import java.io.File;
 
 public abstract class SnapshotCommandIntegrationTest <CLUSTER extends 
MiniRaftCluster>
-    extends BaseTest
+    extends AbstractCommandIntegrationTestWithGrpc
     implements MiniRaftCluster.Factory.Get<CLUSTER> {
+
   {
     Log4jUtils.setLogLevel(RaftServer.Division.LOG, Level.WARN);
     Log4jUtils.setLogLevel(RaftLog.LOG, Level.WARN);
     Log4jUtils.setLogLevel(RaftClient.LOG, Level.WARN);
   }
 
-  static final int NUM_SERVERS = 3;
-
   {
     final RaftProperties prop = getProperties();
     prop.setClass(MiniRaftCluster.STATEMACHINE_CLASS_KEY,
@@ -72,16 +70,10 @@ public abstract class SnapshotCommandIntegrationTest 
<CLUSTER extends MiniRaftCl
         Assert.assertTrue(reply.isSuccess());
       }
     }
-    String address = cluster.getLeader().getPeer().getAdminAddress();
-    StringBuffer sb = new StringBuffer();
-    for (RaftServer.Division division : cluster.getFollowers()) {
-      sb.append(division.getPeer().getAdminAddress());
-      sb.append(",");
-    }
-    sb.append(address);
+    final String address = getClusterAddress(cluster);
     final StringPrintStream out = new StringPrintStream();
     RatisShell shell = new RatisShell(out.getPrintStream());
-    int ret = shell.run("snapshot", "create", "-peers", sb.toString(), 
"-peerId",
+    int ret = shell.run("snapshot", "create", "-peers", address, "-peerId",
         leader.getPeer().getId().toString());
     Assert.assertEquals(0, ret);
     String[] str = out.toString().trim().split(" ");
@@ -102,17 +94,11 @@ public abstract class SnapshotCommandIntegrationTest 
<CLUSTER extends MiniRaftCl
         Assert.assertTrue(reply.isSuccess());
       }
     }
-    String address = cluster.getLeader().getPeer().getAdminAddress();
-    StringBuffer sb = new StringBuffer();
-    for (RaftServer.Division division : cluster.getFollowers()) {
-      sb.append(division.getPeer().getAdminAddress());
-      sb.append(",");
-    }
-    sb.append(address);
+    final String address = getClusterAddress(cluster);
     final StringPrintStream out = new StringPrintStream();
     RatisShell shell = new RatisShell(out.getPrintStream());
     Assert.assertEquals(2, cluster.getFollowers().size());
-    int ret = shell.run("snapshot", "create", "-peers", sb.toString(), 
"-peerId",
+    int ret = shell.run("snapshot", "create", "-peers", address, "-peerId",
         cluster.getFollowers().get(0).getId().toString());
     Assert.assertEquals(0, ret);
     String[] str = out.toString().trim().split(" ");

Reply via email to