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

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


The following commit(s) were added to refs/heads/master by this push:
     new 548fd22b32b [improve][cli] pulsar-perf: refactor to reduce code 
duplication (#19279)
548fd22b32b is described below

commit 548fd22b32bef8d64b4733954de0e2945d3895b0
Author: Paul Gier <[email protected]>
AuthorDate: Mon May 22 14:31:12 2023 -0500

    [improve][cli] pulsar-perf: refactor to reduce code duplication (#19279)
---
 .../apache/pulsar/testclient/PerfClientUtils.java  |   1 -
 .../testclient/PerformanceBaseArguments.java       |  69 +++++++++++++-
 .../pulsar/testclient/PerformanceConsumer.java     | 105 +++++----------------
 .../pulsar/testclient/PerformanceProducer.java     |  61 +-----------
 .../pulsar/testclient/PerformanceReader.java       |  67 +++----------
 .../testclient/PerformanceTopicListArguments.java  |  67 +++++++++++++
 .../pulsar/testclient/PerformanceTransaction.java  |  24 +----
 .../pulsar/testclient/PerfClientUtilsTest.java     |  32 +++----
 .../testclient/PerformanceBaseArgumentsTest.java   |   3 +-
 9 files changed, 186 insertions(+), 243 deletions(-)

diff --git 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerfClientUtils.java
 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerfClientUtils.java
index e40e9610bf4..f9e5d5ee7e6 100644
--- 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerfClientUtils.java
+++ 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerfClientUtils.java
@@ -119,5 +119,4 @@ public class PerfClientUtils {
         return pulsarAdminBuilder;
     }
 
-
 }
diff --git 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceBaseArguments.java
 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceBaseArguments.java
index ce402884d5c..5ae79fb0bf9 100644
--- 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceBaseArguments.java
+++ 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceBaseArguments.java
@@ -20,20 +20,26 @@ package org.apache.pulsar.testclient;
 
 import static org.apache.commons.lang3.StringUtils.isBlank;
 import static org.apache.pulsar.testclient.PerfClientUtils.exit;
+import com.beust.jcommander.JCommander;
 import com.beust.jcommander.Parameter;
+import com.beust.jcommander.ParameterException;
+import java.io.File;
 import java.io.FileInputStream;
 import java.util.Properties;
 import lombok.SneakyThrows;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.pulsar.client.api.ProxyProtocol;
 
-
+/**
+ * PerformanceBaseArguments contains common CLI arguments and parsing logic 
available to all sub-commands.
+ * Sub-commands should create Argument subclasses and override the `validate` 
method as necessary.
+ */
 public abstract class PerformanceBaseArguments {
 
-    @Parameter(names = { "-h", "--help" }, description = "Help message", help 
= true)
+    @Parameter(names = { "-h", "--help" }, description = "Print help message", 
help = true)
     boolean help;
 
-    @Parameter(names = { "-cf", "--conf-file" }, description = "Configuration 
file")
+    @Parameter(names = { "-cf", "--conf-file" }, description = "Pulsar 
configuration file")
     public String confFile;
 
     @Parameter(names = { "-u", "--service-url" }, description = "Pulsar 
Service URL")
@@ -94,6 +100,9 @@ public abstract class PerformanceBaseArguments {
     @Parameter(names = { "--proxy-protocol" }, description = "Proxy protocol 
to select type of routing at proxy.")
     ProxyProtocol proxyProtocol = null;
 
+    @Parameter(names = { "--auth_plugin" }, description = "Authentication 
plugin class name", hidden = true)
+    public String deprecatedAuthPluginClassName;
+
     public abstract void fillArgumentsFromProperties(Properties prop);
 
     @SneakyThrows
@@ -165,4 +174,58 @@ public abstract class PerformanceBaseArguments {
         fillArgumentsFromProperties(prop);
     }
 
+    /**
+     * Validate the CLI arguments.  Default implementation provides validation 
for the common arguments.
+     * Each subclass should call super.validate() and provide validation code 
specific to the sub-command.
+     * @throws Exception
+     */
+    public void validate() throws Exception {
+        if (confFile != null && !confFile.isBlank()) {
+            File configFile = new File(confFile);
+            if (!configFile.exists()) {
+                throw new Exception("config file '" + confFile + "', does not 
exist");
+            }
+            if (configFile.isDirectory()) {
+                throw new Exception("config file '" + confFile + "', is a 
directory");
+            }
+        }
+    }
+
+    /**
+     * Parse the command line args.
+     * @param cmdName used for the help message
+     * @param args String[] of CLI args
+     * @throws ParameterException If there is a problem parsing the arguments
+     */
+    public void parseCLI(String cmdName, String[] args) {
+        JCommander jc = new JCommander(this);
+        jc.setProgramName(cmdName);
+
+        try {
+            jc.parse(args);
+        } catch (ParameterException e) {
+            System.out.println("error: " + e.getMessage());
+            jc.usage();
+            PerfClientUtils.exit(1);
+        }
+
+        if (help) {
+            jc.usage();
+            PerfClientUtils.exit(0);
+        }
+
+        fillArgumentsFromProperties();
+
+        if (isBlank(authPluginClassName) && 
!isBlank(deprecatedAuthPluginClassName)) {
+            authPluginClassName = deprecatedAuthPluginClassName;
+        }
+
+        try {
+            validate();
+        } catch (Exception e) {
+            System.out.println("error: " + e.getMessage());
+            PerfClientUtils.exit(1);
+        }
+    }
+
 }
diff --git 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceConsumer.java
 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceConsumer.java
index 11a23ca05e0..59dabc93026 100644
--- 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceConsumer.java
+++ 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceConsumer.java
@@ -18,11 +18,8 @@
  */
 package org.apache.pulsar.testclient;
 
-import static org.apache.commons.lang3.StringUtils.isBlank;
 import static org.apache.commons.lang3.StringUtils.isNotBlank;
-import com.beust.jcommander.JCommander;
 import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterException;
 import com.beust.jcommander.Parameters;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectWriter;
@@ -86,14 +83,7 @@ public class PerformanceConsumer {
     private static final Recorder cumulativeRecorder = new 
Recorder(MAX_LATENCY, 5);
 
     @Parameters(commandDescription = "Test pulsar consumer performance.")
-    static class Arguments extends PerformanceBaseArguments {
-
-        @Parameter(description = "persistent://prop/ns/my-topic", required = 
true)
-        public List<String> topic;
-
-        @Parameter(names = { "-t", "--num-topics" }, description = "Number of 
topics",
-                validateWith = PositiveNumberParameterValidator.class)
-        public int numTopics = 1;
+    static class Arguments extends PerformanceTopicListArguments {
 
         @Parameter(names = { "-n", "--num-consumers" }, description = "Number 
of consumers (per subscription), only "
                 + "one consumer is allowed when subscriptionType is Exclusive",
@@ -143,9 +133,6 @@ public class PerformanceConsumer {
                 description = "Number of messages to consume in total. If <= 
0, it will keep consuming")
         public long numMessages = 0;
 
-        @Parameter(names = { "--auth_plugin" }, description = "Authentication 
plugin class name", hidden = true)
-        public String deprecatedAuthPluginClassName;
-
         @Parameter(names = { "-mc", "--max_chunked_msg" }, description = "Max 
pending chunk messages")
         private int maxPendingChunkedMessage = 0;
 
@@ -199,79 +186,35 @@ public class PerformanceConsumer {
         @Override
         public void fillArgumentsFromProperties(Properties prop) {
         }
-    }
-
-    public static void main(String[] args) throws Exception {
-        final Arguments arguments = new Arguments();
-        JCommander jc = new JCommander(arguments);
-        jc.setProgramName("pulsar-perf consume");
-
-        try {
-            jc.parse(args);
-        } catch (ParameterException e) {
-            System.out.println(e.getMessage());
-            jc.usage();
-            PerfClientUtils.exit(1);
-        }
-
-        if (arguments.help) {
-            jc.usage();
-            PerfClientUtils.exit(1);
-        }
 
-        if (isBlank(arguments.authPluginClassName) && 
!isBlank(arguments.deprecatedAuthPluginClassName)) {
-            arguments.authPluginClassName = 
arguments.deprecatedAuthPluginClassName;
-        }
-
-        for (String arg : arguments.topic) {
-            if (arg.startsWith("-")) {
-                System.out.printf("invalid option: '%s'\nTo use a topic with 
the name '%s', "
-                        + "please use a fully qualified topic name\n", arg, 
arg);
-                jc.usage();
-                PerfClientUtils.exit(1);
+        @Override
+        public void validate() throws Exception {
+            super.validate();
+            if (subscriptionType == SubscriptionType.Exclusive && numConsumers 
> 1) {
+                throw new Exception("Only one consumer is allowed when 
subscriptionType is Exclusive");
             }
-        }
 
-        if (arguments.topic != null && arguments.topic.size() != 
arguments.numTopics) {
-            // keep compatibility with the previous version
-            if (arguments.topic.size() == 1) {
-                String prefixTopicName = 
TopicName.get(arguments.topic.get(0)).toString().trim();
-                List<String> defaultTopics = new ArrayList<>();
-                for (int i = 0; i < arguments.numTopics; i++) {
-                    defaultTopics.add(String.format("%s-%d", prefixTopicName, 
i));
+            if (subscriptions != null && subscriptions.size() != 
numSubscriptions) {
+                // keep compatibility with the previous version
+                if (subscriptions.size() == 1) {
+                    if (subscriberName == null) {
+                        subscriberName = subscriptions.get(0);
+                    }
+                    List<String> defaultSubscriptions = new ArrayList<>();
+                    for (int i = 0; i < numSubscriptions; i++) {
+                        defaultSubscriptions.add(String.format("%s-%d", 
subscriberName, i));
+                    }
+                    subscriptions = defaultSubscriptions;
+                } else {
+                    throw new Exception("The size of subscriptions list should 
be equal to --num-subscriptions");
                 }
-                arguments.topic = defaultTopics;
-            } else {
-                System.out.println("The size of topics list should be equal to 
--num-topics");
-                jc.usage();
-                PerfClientUtils.exit(1);
             }
         }
+    }
 
-        if (arguments.subscriptionType == SubscriptionType.Exclusive && 
arguments.numConsumers > 1) {
-            System.out.println("Only one consumer is allowed when 
subscriptionType is Exclusive");
-            jc.usage();
-            PerfClientUtils.exit(1);
-        }
-
-        if (arguments.subscriptions != null && arguments.subscriptions.size() 
!= arguments.numSubscriptions) {
-            // keep compatibility with the previous version
-            if (arguments.subscriptions.size() == 1) {
-                if (arguments.subscriberName == null) {
-                    arguments.subscriberName = arguments.subscriptions.get(0);
-                }
-                List<String> defaultSubscriptions = new ArrayList<>();
-                for (int i = 0; i < arguments.numSubscriptions; i++) {
-                    defaultSubscriptions.add(String.format("%s-%d", 
arguments.subscriberName, i));
-                }
-                arguments.subscriptions = defaultSubscriptions;
-            } else {
-                System.out.println("The size of subscriptions list should be 
equal to --num-subscriptions");
-                jc.usage();
-                PerfClientUtils.exit(1);
-            }
-        }
-        arguments.fillArgumentsFromProperties();
+    public static void main(String[] args) throws Exception {
+        final Arguments arguments = new Arguments();
+        arguments.parseCLI("pulsar-perf consume", args);
 
         // Dump config variables
         PerfClientUtils.printJVMInformation(log);
@@ -449,7 +392,7 @@ public class PerformanceConsumer {
         }
 
         for (int i = 0; i < arguments.numTopics; i++) {
-            final TopicName topicName = TopicName.get(arguments.topic.get(i));
+            final TopicName topicName = TopicName.get(arguments.topics.get(i));
 
             log.info("Adding {} consumers per subscription on topic {}", 
arguments.numConsumers, topicName);
 
diff --git 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceProducer.java
 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceProducer.java
index 0c56f1d5c73..6513f0684b2 100644
--- 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceProducer.java
+++ 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceProducer.java
@@ -24,9 +24,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
 import static 
org.apache.pulsar.client.impl.conf.ProducerConfigurationData.DEFAULT_BATCHING_MAX_MESSAGES;
 import static 
org.apache.pulsar.client.impl.conf.ProducerConfigurationData.DEFAULT_MAX_PENDING_MESSAGES;
 import static 
org.apache.pulsar.client.impl.conf.ProducerConfigurationData.DEFAULT_MAX_PENDING_MESSAGES_ACROSS_PARTITIONS;
-import com.beust.jcommander.JCommander;
 import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterException;
 import com.beust.jcommander.Parameters;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectWriter;
@@ -103,10 +101,7 @@ public class PerformanceProducer {
     private static IMessageFormatter messageFormatter = null;
 
     @Parameters(commandDescription = "Test pulsar producer performance.")
-    static class Arguments extends PerformanceBaseArguments {
-
-        @Parameter(description = "persistent://prop/ns/my-topic", required = 
true)
-        public List<String> topics;
+    static class Arguments extends PerformanceTopicListArguments {
 
         @Parameter(names = { "-threads", "--num-test-threads" }, description = 
"Number of test threads",
                 validateWith = PositiveNumberParameterValidator.class)
@@ -118,10 +113,6 @@ public class PerformanceProducer {
         @Parameter(names = { "-s", "--size" }, description = "Message size 
(bytes)")
         public int msgSize = 1024;
 
-        @Parameter(names = { "-t", "--num-topic" }, description = "Number of 
topics",
-                validateWith = PositiveNumberParameterValidator.class)
-        public int numTopics = 1;
-
         @Parameter(names = { "-n", "--num-producers" }, description = "Number 
of producers (per topic)",
                 validateWith = PositiveNumberParameterValidator.class)
         public int numProducers = 1;
@@ -139,9 +130,6 @@ public class PerformanceProducer {
         @Parameter(names = { "-au", "--admin-url" }, description = "Pulsar 
Admin URL")
         public String adminURL;
 
-        @Parameter(names = { "--auth_plugin" }, description = "Authentication 
plugin class name", hidden = true)
-        public String deprecatedAuthPluginClassName;
-
         @Parameter(names = { "-ch",
                 "--chunking" }, description = "Should split the message and 
publish in chunks if message size is "
                 + "larger than allowed max size")
@@ -272,52 +260,7 @@ public class PerformanceProducer {
     public static void main(String[] args) throws Exception {
 
         final Arguments arguments = new Arguments();
-        JCommander jc = new JCommander(arguments);
-        jc.setProgramName("pulsar-perf produce");
-
-        try {
-            jc.parse(args);
-        } catch (ParameterException e) {
-            System.out.println(e.getMessage());
-            jc.usage();
-            PerfClientUtils.exit(1);
-        }
-
-        if (arguments.help) {
-            jc.usage();
-            PerfClientUtils.exit(1);
-        }
-
-        if (isBlank(arguments.authPluginClassName) && 
!isBlank(arguments.deprecatedAuthPluginClassName)) {
-            arguments.authPluginClassName = 
arguments.deprecatedAuthPluginClassName;
-        }
-
-        for (String arg : arguments.topics) {
-            if (arg.startsWith("-")) {
-                System.out.printf("invalid option: '%s'\nTo use a topic with 
the name '%s', "
-                        + "please use a fully qualified topic name\n", arg, 
arg);
-                jc.usage();
-                PerfClientUtils.exit(1);
-            }
-        }
-
-        if (arguments.topics != null && arguments.topics.size() != 
arguments.numTopics) {
-            // keep compatibility with the previous version
-            if (arguments.topics.size() == 1) {
-                String prefixTopicName = arguments.topics.get(0);
-                List<String> defaultTopics = new ArrayList<>();
-                for (int i = 0; i < arguments.numTopics; i++) {
-                    defaultTopics.add(String.format("%s%s%d", prefixTopicName, 
arguments.separator, i));
-                }
-                arguments.topics = defaultTopics;
-            } else {
-                System.out.println("The size of topics list should be equal to 
--num-topic");
-                jc.usage();
-                PerfClientUtils.exit(1);
-            }
-        }
-
-        arguments.fillArgumentsFromProperties();
+        arguments.parseCLI("pulsar-perf produce", args);
 
         // Dump config variables
         PerfClientUtils.printJVMInformation(log);
diff --git 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceReader.java
 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceReader.java
index 78d8e5f5915..ed5cc37644a 100644
--- 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceReader.java
+++ 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceReader.java
@@ -18,9 +18,7 @@
  */
 package org.apache.pulsar.testclient;
 
-import com.beust.jcommander.JCommander;
 import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterException;
 import com.beust.jcommander.Parameters;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectWriter;
@@ -62,15 +60,7 @@ public class PerformanceReader {
     private static Recorder cumulativeRecorder = new 
Recorder(TimeUnit.DAYS.toMillis(10), 5);
 
     @Parameters(commandDescription = "Test pulsar reader performance.")
-    static class Arguments extends PerformanceBaseArguments {
-
-
-        @Parameter(description = "persistent://prop/ns/my-topic", required = 
true)
-        public List<String> topic;
-
-        @Parameter(names = { "-t", "--num-topics" }, description = "Number of 
topics",
-                validateWith = PositiveNumberParameterValidator.class)
-        public int numTopics = 1;
+    static class Arguments extends PerformanceTopicListArguments {
 
         @Parameter(names = { "-r", "--rate" }, description = "Simulate a slow 
message reader (rate in msg/s)")
         public double rate = 0;
@@ -102,51 +92,21 @@ public class PerformanceReader {
                 useTls = Boolean.parseBoolean(prop.getProperty("useTls"));
             }
         }
+        @Override
+        public void validate() throws Exception {
+            super.validate();
+            if (startMessageId != "earliest" && startMessageId != "latest"
+                    && (startMessageId.split(":")).length != 2) {
+                String errMsg = String.format("invalid start message ID '%s', 
must be either either 'earliest', "
+                        + "'latest' or a specific message id by using 
'lid:eid'", startMessageId);
+                throw new Exception(errMsg);
+            }
+        }
     }
 
     public static void main(String[] args) throws Exception {
         final Arguments arguments = new Arguments();
-        JCommander jc = new JCommander(arguments);
-        jc.setProgramName("pulsar-perf read");
-
-        try {
-            jc.parse(args);
-        } catch (ParameterException e) {
-            System.out.println(e.getMessage());
-            jc.usage();
-            PerfClientUtils.exit(1);
-        }
-
-        if (arguments.help) {
-            jc.usage();
-            PerfClientUtils.exit(1);
-        }
-
-        for (String arg : arguments.topic) {
-            if (arg.startsWith("-")) {
-                System.out.printf("invalid option: '%s'\nTo use a topic with 
the name '%s', "
-                        + "please use a fully qualified topic name\n", arg, 
arg);
-                jc.usage();
-                PerfClientUtils.exit(1);
-            }
-        }
-
-        if (arguments.topic != null && arguments.topic.size() != 
arguments.numTopics) {
-            // keep compatibility with the previous version
-            if (arguments.topic.size() == 1) {
-                String prefixTopicName = arguments.topic.get(0);
-                List<String> defaultTopics = new ArrayList<>();
-                for (int i = 0; i < arguments.numTopics; i++) {
-                    defaultTopics.add(String.format("%s-%d", prefixTopicName, 
i));
-                }
-                arguments.topic = defaultTopics;
-            } else {
-                System.out.println("The size of topics list should be equal to 
--num-topics");
-                jc.usage();
-                PerfClientUtils.exit(1);
-            }
-        }
-        arguments.fillArgumentsFromProperties();
+        arguments.parseCLI("pulsar-perf read", args);
 
         // Dump config variables
         PerfClientUtils.printJVMInformation(log);
@@ -202,7 +162,7 @@ public class PerformanceReader {
                 .startMessageId(startMessageId);
 
         for (int i = 0; i < arguments.numTopics; i++) {
-            final TopicName topicName = TopicName.get(arguments.topic.get(i));
+            final TopicName topicName = TopicName.get(arguments.topics.get(i));
 
             
futures.add(readerBuilder.clone().topic(topicName.toString()).createAsync());
         }
@@ -230,7 +190,6 @@ public class PerformanceReader {
             timer.schedule(timoutTask, arguments.testTime * 1000);
         }
 
-
         long oldTime = System.nanoTime();
         Histogram reportHistogram = null;
 
diff --git 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTopicListArguments.java
 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTopicListArguments.java
new file mode 100644
index 00000000000..a2f8b6af082
--- /dev/null
+++ 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTopicListArguments.java
@@ -0,0 +1,67 @@
+/*
+ * 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.pulsar.testclient;
+
+import com.beust.jcommander.Parameter;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.pulsar.common.naming.TopicName;
+
+/**
+ * PerformanceTopicListArguments provides common topic list arguments which 
are used
+ * by the consumer, producer, and reader commands, but not by the transaction 
test command.
+ */
+public abstract class PerformanceTopicListArguments extends 
PerformanceBaseArguments {
+
+    @Parameter(description = "persistent://prop/ns/my-topic", required = true)
+    public List<String> topics;
+
+    @Parameter(names = { "-t", "--num-topics", "--num-topic" }, description = 
"Number of topics.  Must match"
+            + "the given number of topic arguments.",
+            validateWith = PositiveNumberParameterValidator.class)
+    public int numTopics = 1;
+
+    @Override
+    public void validate() throws Exception {
+        super.validate();
+        for (String arg : topics) {
+            if (arg.startsWith("-")) {
+                String errMsg = String.format("invalid option: '%s', to use a 
topic with the name '%s', "
+                        + "please use a fully qualified topic name", arg, arg);
+                throw new Exception(errMsg);
+            }
+        }
+
+        if (topics.size() != numTopics) {
+            // keep compatibility with the previous version
+            if (topics.size() == 1) {
+                String prefixTopicName = 
TopicName.get(topics.get(0)).toString().trim();
+                List<String> defaultTopics = new ArrayList<>();
+                for (int i = 0; i < numTopics; i++) {
+                    defaultTopics.add(String.format("%s-%d", prefixTopicName, 
i));
+                }
+                topics = defaultTopics;
+            } else {
+                String errMsg = String.format("the number of topic names (%d) 
must be equal to --num-topics (%d)",
+                        topics.size(), numTopics);
+                throw new Exception(errMsg);
+            }
+        }
+    }
+}
diff --git 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTransaction.java
 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTransaction.java
index a1495a617fb..469e6ab1f3f 100644
--- 
a/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTransaction.java
+++ 
b/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceTransaction.java
@@ -19,9 +19,7 @@
 package org.apache.pulsar.testclient;
 
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import com.beust.jcommander.JCommander;
 import com.beust.jcommander.Parameter;
-import com.beust.jcommander.ParameterException;
 import com.beust.jcommander.Parameters;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectWriter;
@@ -70,7 +68,6 @@ import org.slf4j.LoggerFactory;
 
 public class PerformanceTransaction {
 
-
     private static final LongAdder totalNumEndTxnOpFailed = new LongAdder();
     private static final LongAdder totalNumEndTxnOpSuccess = new LongAdder();
     private static final LongAdder numTxnOpSuccess = new LongAdder();
@@ -92,9 +89,8 @@ public class PerformanceTransaction {
     private static final Recorder messageSendRCumulativeRecorder =
             new Recorder(TimeUnit.SECONDS.toMicros(120000), 5);
 
-
     @Parameters(commandDescription = "Test pulsar transaction performance.")
-    static class Arguments  extends PerformanceBaseArguments {
+    static class Arguments extends PerformanceBaseArguments {
 
         @Parameter(names = "--topics-c", description = "All topics that need 
ack for a transaction", required =
                 true)
@@ -187,26 +183,10 @@ public class PerformanceTransaction {
     public static void main(String[] args)
             throws IOException, PulsarAdminException, ExecutionException, 
InterruptedException {
         final Arguments arguments = new Arguments();
-        JCommander jc = new JCommander(arguments);
-        jc.setProgramName("pulsar-perf transaction");
-
-        try {
-            jc.parse(args);
-        } catch (ParameterException e) {
-            System.out.println(e.getMessage());
-            jc.usage();
-            PerfClientUtils.exit(1);
-        }
-
-        if (arguments.help) {
-            jc.usage();
-            PerfClientUtils.exit(1);
-        }
-        arguments.fillArgumentsFromProperties();
+        arguments.parseCLI("pulsar-perf transaction", args);
 
         // Dump config variables
         PerfClientUtils.printJVMInformation(log);
-
         ObjectMapper m = new ObjectMapper();
         ObjectWriter w = m.writerWithDefaultPrettyPrinter();
         log.info("Starting Pulsar perf transaction with config: {}", 
w.writeValueAsString(arguments));
diff --git 
a/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/PerfClientUtilsTest.java
 
b/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/PerfClientUtilsTest.java
index 3a8bba1bccb..3d734b1f910 100644
--- 
a/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/PerfClientUtilsTest.java
+++ 
b/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/PerfClientUtilsTest.java
@@ -55,11 +55,7 @@ public class PerfClientUtilsTest {
     @Test
     public void testClientCreation() throws Exception {
 
-        final PerformanceBaseArguments args = new PerformanceBaseArguments() {
-            @Override
-            public void fillArgumentsFromProperties(Properties prop) {
-            }
-        };
+        final PerformanceBaseArguments args = new 
PerformanceArgumentsTestDefault();
 
         args.tlsHostnameVerificationEnable = true;
         args.authPluginClassName = MyAuth.class.getName();
@@ -99,11 +95,7 @@ public class PerfClientUtilsTest {
     @Test
     public void testClientCreationWithProxy() throws Exception {
 
-        final PerformanceBaseArguments args = new PerformanceBaseArguments() {
-            @Override
-            public void fillArgumentsFromProperties(Properties prop) {
-            }
-        };
+        final PerformanceBaseArguments args = new 
PerformanceArgumentsTestDefault();
 
         args.serviceURL = "pulsar+ssl://my-pulsar:6651";
         args.proxyServiceURL = "pulsar+ssl://my-proxy-pulsar:4443";
@@ -126,11 +118,7 @@ public class PerfClientUtilsTest {
                     + "proxyServiceUrl=pulsar+ssl://my-proxy-pulsar:4443\n"
                     + "proxyProtocol=SNI");
 
-            final PerformanceBaseArguments args = new 
PerformanceBaseArguments() {
-                @Override
-                public void fillArgumentsFromProperties(Properties prop) {
-                }
-            };
+            final PerformanceBaseArguments args = new 
PerformanceArgumentsTestDefault();
 
             args.confFile = testConf.toString();
             args.fillArgumentsFromProperties();
@@ -155,11 +143,7 @@ public class PerfClientUtilsTest {
                     + "proxyServiceUrl=\n"
                     + "proxyProtocol=");
 
-            final PerformanceBaseArguments args = new 
PerformanceBaseArguments() {
-                @Override
-                public void fillArgumentsFromProperties(Properties prop) {
-                }
-            };
+            final PerformanceBaseArguments args = new 
PerformanceArgumentsTestDefault();
 
             args.confFile = testConf.toString();
             args.fillArgumentsFromProperties();
@@ -174,4 +158,10 @@ public class PerfClientUtilsTest {
             Files.deleteIfExists(testConf);
         }
     }
-}
\ No newline at end of file
+}
+
+class PerformanceArgumentsTestDefault extends PerformanceBaseArguments {
+    @Override
+    public void fillArgumentsFromProperties(Properties prop) {
+    }
+}
diff --git 
a/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/PerformanceBaseArgumentsTest.java
 
b/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/PerformanceBaseArgumentsTest.java
index 6c60cbd90f8..42c93be3430 100644
--- 
a/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/PerformanceBaseArgumentsTest.java
+++ 
b/pulsar-testclient/src/test/java/org/apache/pulsar/testclient/PerformanceBaseArgumentsTest.java
@@ -158,5 +158,4 @@ public class PerformanceBaseArgumentsTest {
             tempConfigFile.delete();
         }
     }
-
-}
\ No newline at end of file
+}

Reply via email to