ARTEMIS-1384 adding CLI command (stat) to display basic queue stats
Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/87b570f7 Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/87b570f7 Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/87b570f7 Branch: refs/heads/master Commit: 87b570f7ce6269f415635944435db0decb789f2d Parents: dd6a5ab Author: Pat Fox <[email protected]> Authored: Sat Sep 2 01:29:04 2017 +0200 Committer: Clebert Suconic <[email protected]> Committed: Tue Sep 5 14:22:36 2017 -0400 ---------------------------------------------------------------------- .../apache/activemq/artemis/cli/Artemis.java | 5 +- .../artemis/cli/commands/queue/StatQueue.java | 262 ++++++++++++++ .../apache/activemq/cli/test/ArtemisTest.java | 343 +++++++++++++++++++ .../activemq/cli/test/TestActionContext.java | 8 + 4 files changed, 616 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/87b570f7/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java index d52507d..6abf1b6 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java @@ -30,6 +30,7 @@ import org.apache.activemq.artemis.cli.commands.InputAbstract; import org.apache.activemq.artemis.cli.commands.InvalidOptionsError; import org.apache.activemq.artemis.cli.commands.Kill; import org.apache.activemq.artemis.cli.commands.Mask; +import org.apache.activemq.artemis.cli.commands.queue.StatQueue; import org.apache.activemq.artemis.cli.commands.Run; import org.apache.activemq.artemis.cli.commands.Stop; import org.apache.activemq.artemis.cli.commands.address.CreateAddress; @@ -152,8 +153,8 @@ public class Artemis { String instance = artemisInstance != null ? artemisInstance.getAbsolutePath() : System.getProperty("artemis.instance"); Cli.CliBuilder<Action> builder = Cli.<Action>builder("artemis").withDescription("ActiveMQ Artemis Command Line").withCommand(HelpAction.class).withCommand(Producer.class).withCommand(Consumer.class).withCommand(Browse.class).withCommand(Mask.class).withDefaultCommand(HelpAction.class); - builder.withGroup("queue").withDescription("Queue tools group (create|delete|update) (example ./artemis queue create)"). - withDefaultCommand(HelpQueue.class).withCommands(CreateQueue.class, DeleteQueue.class, UpdateQueue.class); + builder.withGroup("queue").withDescription("Queue tools group (create|delete|update|stat) (example ./artemis queue create)"). + withDefaultCommand(HelpQueue.class).withCommands(CreateQueue.class, DeleteQueue.class, UpdateQueue.class, StatQueue.class); builder.withGroup("address").withDescription("Address tools group (create|delete|update|show) (example ./artemis address create)"). withDefaultCommand(HelpAddress.class).withCommands(CreateAddress.class, DeleteAddress.class, UpdateAddress.class, ShowAddress.class); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/87b570f7/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java new file mode 100644 index 0000000..1813033 --- /dev/null +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java @@ -0,0 +1,262 @@ +/* + * 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.activemq.artemis.cli.commands.queue; + +import io.airlift.airline.Command; +import io.airlift.airline.Option; +import org.apache.activemq.artemis.api.core.JsonUtil; +import org.apache.activemq.artemis.api.core.client.ClientMessage; +import org.apache.activemq.artemis.api.core.management.ManagementHelper; +import org.apache.activemq.artemis.cli.commands.AbstractAction; +import org.apache.activemq.artemis.cli.commands.ActionContext; + +import javax.json.JsonArray; +import javax.json.JsonObject; +import java.util.Arrays; +import java.util.HashMap; + +@Command(name = "stat", description = "prints out basic stats associated with queues. Output includes CONSUMER_COUNT (number of consumers), MESSAGE_COUNT (current message count on the queue, including scheduled, paged and in-delivery messages), MESSAGES_ADDED (messages added to the queue), DELIVERING_COUNT (messages broker is currently delivering to consumer(s)), MESSAGES_ACKED (messages acknowledged from the consumer(s))." + " Queues can be filtered using EITHER '--queueName X' where X is contained in the queue name OR using a full filter '--field NAME --operation EQUALS --value X'." + +) +public class StatQueue extends AbstractAction { + + public enum FIELD { + + NAME("name"), ADDRESS("address"), CONSUMER_COUNT("consumerCount"), MESSAGE_COUNT("messageCount"), MESSAGES_ADDED("messagesAdded"), DELIVERING_COUNT("deliveringCount"), MESSAGES_ACKED("messagesAcked"); + + private String jsonId; + + FIELD(String jsonId) { + this.jsonId = jsonId; + } + + String getJsonId() { + return this.jsonId; + } + + } + + public enum OPERATION { + CONTAINS, EQUALS + } + + @Option(name = "--queueName", description = "display queue stats for queue(s) with names containing this string.") + private String queueName; + + @Option(name = "--field", description = "field to use in filter. Possible values NAME, ADDRESS, MESSAGE_COUNT, MESSAGES_ADDED, DELIVERING_COUNT, MESSAGES_ACKED.") + private String fieldName; + + @Option(name = "--operation", description = "operation to use in filter. Possible values CONTAINS, EQUALS.") + private String operationName; + + @Option(name = "--value", description = "value to use in the filter.") + private String value; + + @Option(name = "--maxRows", description = "max number of queues displayed. Default is 50.") + private int maxRows = 50; + + //easier for testing + public void setQueueName(String queueName) { + this.queueName = queueName; + } + + public void setOperationName(String operationName) { + this.operationName = operationName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public void setValue(String value) { + this.value = value; + } + + public void setMaxRows(int maxRows) { + this.maxRows = maxRows; + } + + public void setUser(String user) { + this.user = user; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setverbose(boolean verbose) { + this.verbose = verbose; + } + + @Override + public Object execute(ActionContext context) throws Exception { + super.execute(context); + String filter = createFilter(); + + //should always get an initialised filter back when values correct + if (filter == null) { + return null; + } + + if (verbose) { + context.out.println("filter is '" + filter + "'"); + context.out.println("maxRows='" + maxRows + "'"); + } + printStats(context, filter, maxRows); + return null; + } + + private void printStats(final ActionContext context, final String filter, int maxRows) throws Exception { + performCoreManagement(new ManagementCallback<ClientMessage>() { + @Override + public void setUpInvocation(ClientMessage message) throws Exception { + ManagementHelper.putOperationInvocation(message, "broker", "listQueues", filter, 1, maxRows); + } + + @Override + public void requestSuccessful(ClientMessage reply) throws Exception { + final String result = (String) ManagementHelper.getResult(reply, String.class); + printStats(result); + } + + @Override + public void requestFailed(ClientMessage reply) throws Exception { + String errMsg = (String) ManagementHelper.getResult(reply, String.class); + context.err.println("Failed to get Stats for Queues. Reason: " + errMsg); + } + }); + } + + private void printStats(String result) { + printHeadings(); + + //should not happen but... + if (result == null) { + if (verbose) { + context.err.println("printStats(): got NULL result string."); + } + return; + } + + JsonObject queuesAsJsonObject = JsonUtil.readJsonObject(result); + JsonArray array = (JsonArray) queuesAsJsonObject.get("data"); + + for (int i = 0; i < array.size(); i++) { + printQueueStats(array.getJsonObject(i)); + } + } + + private void printHeadings() { + + StringBuilder stringBuilder = new StringBuilder(134).append('|').append(paddingString(new StringBuilder(FIELD.NAME.toString()), 25)).append('|').append(paddingString(new StringBuilder(FIELD.ADDRESS.toString()), 25)).append('|').append(paddingString(new StringBuilder(FIELD.CONSUMER_COUNT.toString() + " "), 15)).append('|').append(paddingString(new StringBuilder(FIELD.MESSAGE_COUNT.toString() + " "), 14)).append('|').append(paddingString(new StringBuilder(FIELD.MESSAGES_ADDED.toString() + " "), 15)).append('|').append(paddingString(new StringBuilder(FIELD.DELIVERING_COUNT.toString() + " "), 17)).append('|').append(paddingString(new StringBuilder(FIELD.MESSAGES_ACKED.toString() + " "), 15)).append('|'); + + context.out.println(stringBuilder); + } + + private void printQueueStats(JsonObject jsonObject) { + + //should not happen but just in case.. + if (jsonObject == null) { + if (verbose) { + context.err.println("printQueueStats(): jsonObject is null"); + } + return; + } + + StringBuilder stringBuilder = new StringBuilder(134).append('|').append(paddingString(new StringBuilder(jsonObject.getString(FIELD.NAME.getJsonId())), 25)).append('|').append(paddingString(new StringBuilder(jsonObject.getString(FIELD.ADDRESS.getJsonId())), 25)).append('|').append(paddingString(new StringBuilder(jsonObject.getString(FIELD.CONSUMER_COUNT.getJsonId())), 15)).append('|').append(paddingString(new StringBuilder(jsonObject.getString(FIELD.MESSAGE_COUNT.getJsonId())), 14)).append('|').append(paddingString(new StringBuilder(jsonObject.getString(FIELD.MESSAGES_ADDED.getJsonId())), 15)).append('|').append(paddingString(new StringBuilder(jsonObject.getString(FIELD.DELIVERING_COUNT.getJsonId())), 17)).append('|').append(paddingString(new StringBuilder(jsonObject.getString(FIELD.MESSAGES_ACKED.getJsonId())), 15)).append('|'); + + context.out.println(stringBuilder); + } + + private StringBuilder paddingString(StringBuilder value, int size) { + + //should not happen but just in case ... + if (value == null) { + return new StringBuilder(size); + } + + //would expect to have some data + if (value.length() == 0) { + value.append("NO DATA"); + } + + int length = value.length(); + if (length >= size) { + //no padding required + return value; + } + + for (int i = 1; (i + length) <= size; i++) { + value.append(' '); + } + + return value; + } + + //creates filter used for listQueues() + private String createFilter() { + + HashMap<String, Object> filterMap = new HashMap<>(); + + if (((fieldName != null) && (fieldName.trim().length() > 0)) && ((queueName != null && queueName.trim().length() > 0))) { + context.err.println("'--field' and '--queueName' cannot be specified together."); + return null; + } + + if ((fieldName != null) && (fieldName.trim().length() > 0)) { + try { + FIELD field = FIELD.valueOf(fieldName); + filterMap.put("field", field.toString()); + } catch (IllegalArgumentException ex) { + context.err.println("'--field' must be set to one of the following " + Arrays.toString(FIELD.values())); + return null; + } + + //full filter being set ensure value is set + if (value == null || value.trim().length() == 0) { + context.err.println("'--value' needs to be set when '--field' is specified"); + return null; + } + filterMap.put("value", value); + + if (operationName == null) { + context.err.println("'--operation' must be set when '--field' is specified " + Arrays.toString(OPERATION.values())); + return null; + } + + try { + OPERATION operation = OPERATION.valueOf(operationName); + filterMap.put("operation", operation.toString()); + } catch (IllegalArgumentException ex) { + context.err.println("'--operation' must be set to one of the following " + Arrays.toString(OPERATION.values())); + return null; + } + + } else if (queueName != null && queueName.trim().length() > 0) { + filterMap.put("field", FIELD.NAME.toString()); + filterMap.put("value", queueName); + filterMap.put("operation", OPERATION.CONTAINS.toString()); + } else { + filterMap.put("field", ""); + filterMap.put("value", ""); + filterMap.put("operation", ""); + } + + JsonObject filterJsonObject = JsonUtil.toJsonObject(filterMap); + return filterJsonObject.toString(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/87b570f7/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java index 8b4098a..bb2ab5a 100644 --- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java +++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java @@ -17,15 +17,22 @@ package org.apache.activemq.cli.test; import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TextMessage; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; import java.nio.file.Files; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -38,6 +45,7 @@ import org.apache.activemq.artemis.cli.CLIException; import org.apache.activemq.artemis.cli.commands.ActionContext; import org.apache.activemq.artemis.cli.commands.Create; import org.apache.activemq.artemis.cli.commands.Mask; +import org.apache.activemq.artemis.cli.commands.queue.StatQueue; import org.apache.activemq.artemis.cli.commands.Run; import org.apache.activemq.artemis.cli.commands.user.AddUser; import org.apache.activemq.artemis.cli.commands.user.ListUser; @@ -630,6 +638,341 @@ public class ArtemisTest extends CliTestBase { } + @Test + public void testQstat() throws Exception { + + File instanceQstat = new File(temporaryFolder.getRoot(), "instanceQStat"); + setupAuth(instanceQstat); + Run.setEmbedded(true); + Artemis.main("create", instanceQstat.getAbsolutePath(), "--silent", "--no-fsync", "--no-autotune", "--no-web", "--require-login"); + System.setProperty("artemis.instance", instanceQstat.getAbsolutePath()); + Artemis.internalExecute("run"); + + try (ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616"); Connection connection = cf.createConnection("admin", "admin");) { + + //set up some queues with messages and consumers + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + connection.start(); + sendMessages(session, "Test1", 15); + sendMessages(session, "Test11", 1); + sendMessages(session, "Test12", 1); + sendMessages(session, "Test20", 20); + MessageConsumer consumer = session.createConsumer(ActiveMQDestination.createDestination("queue://Test1", ActiveMQDestination.TYPE.QUEUE)); + MessageConsumer consumer2 = session.createConsumer(ActiveMQDestination.createDestination("queue://Test1", ActiveMQDestination.TYPE.QUEUE)); + + for (int i = 0; i < 5; i++) { + Message message = consumer.receive(100); + } + + //check all queues containing "Test1" are displayed + TestActionContext context = new TestActionContext(); + StatQueue statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setQueueName("Test1"); + statQueue.execute(context); + ArrayList<String> lines = getOutputLines(context, false); + // Header line + 3 queues + Assert.assertEquals("rows returned using queueName=Test1", 4, lines.size()); + + //check all queues are displayed when no Filter set + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.execute(context); + lines = getOutputLines(context, false); + // Header line + 4 queues (at least - possibly other infra queues as well) + Assert.assertTrue("rows returned filtering no name ", 5 <= lines.size()); + + //check all queues containing "Test1" are displayed using Filter field NAME + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("NAME"); + statQueue.setOperationName("CONTAINS"); + statQueue.setValue("Test1"); + statQueue.execute(context); + lines = getOutputLines(context, false); + // Header line + 3 queues + Assert.assertEquals("rows returned filtering by NAME ", 4, lines.size()); + + //check only queue named "Test1" is displayed using Filter field NAME and operation EQUALS + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("NAME"); + statQueue.setOperationName("EQUALS"); + statQueue.setValue("Test1"); + statQueue.execute(context); + lines = getOutputLines(context, false); + //Header line + 1 queue only + Assert.assertEquals("rows returned filtering by NAME operation EQUALS", 2, lines.size()); + //verify contents of queue stat line is correct + String queueTest1 = lines.get(1); + String[] parts = queueTest1.split("\\|"); + Assert.assertEquals("queue name", "Test1", parts[1].trim()); + Assert.assertEquals("address name", "Test1", parts[2].trim()); + Assert.assertEquals("Consumer count", "2", parts[3].trim()); + Assert.assertEquals("Message count", "10", parts[4].trim()); + Assert.assertEquals("Added count", "15", parts[5].trim()); + Assert.assertEquals("Delivering count", "10", parts[6].trim()); + Assert.assertEquals("Acked count", "5", parts[7].trim()); + + //check all queues containing address "Test1" are displayed using Filter field ADDRESS + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("ADDRESS"); + statQueue.setOperationName("CONTAINS"); + statQueue.setValue("Test1"); + statQueue.execute(context); + lines = getOutputLines(context, false); + // Header line + 3 queues + Assert.assertEquals("rows returned filtering by ADDRESS", 4, lines.size()); + + //check all queues containing address "Test1" are displayed using Filter field MESSAGE_COUNT + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("MESSAGE_COUNT"); + statQueue.setOperationName("CONTAINS"); + statQueue.setValue("10"); + statQueue.execute(context); + lines = getOutputLines(context, false); + + // Header line + 1 queues + Assert.assertEquals("rows returned filtering by MESSAGE_COUNT", 2, lines.size()); + String[] columns = lines.get(1).split("\\|"); + Assert.assertEquals("queue name filtering by MESSAGE_COUNT ", "Test1", columns[2].trim()); + + //check all queues containing address "Test1" are displayed using Filter field MESSAGE_ADDED + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("MESSAGES_ADDED"); + statQueue.setOperationName("CONTAINS"); + statQueue.setValue("20"); + statQueue.execute(context); + lines = getOutputLines(context, false); + // Header line + 1 queues + Assert.assertEquals("rows returned filtering by MESSAGES_ADDED", 2, lines.size()); + columns = lines.get(1).split("\\|"); + Assert.assertEquals("queue name filtered by MESSAGE_ADDED", "Test20", columns[2].trim()); + + //check all queues containing address "Test1" are displayed using Filter field DELIVERING_COUNT + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("DELIVERING_COUNT"); + statQueue.setOperationName("EQUALS"); + statQueue.setValue("10"); + statQueue.execute(context); + lines = getOutputLines(context, false); + columns = lines.get(1).split("\\|"); + // Header line + 1 queues + Assert.assertEquals("rows returned filtering by DELIVERING_COUNT", 2, lines.size()); + Assert.assertEquals("queue name filtered by DELIVERING_COUNT ", "Test1", columns[2].trim()); + + //check all queues containing address "Test1" are displayed using Filter field CONSUMER_COUNT + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("CONSUMER_COUNT"); + statQueue.setOperationName("EQUALS"); + statQueue.setValue("2"); + statQueue.execute(context); + lines = getOutputLines(context, false); + columns = lines.get(1).split("\\|"); + // Header line + 1 queues + Assert.assertEquals("rows returned filtering by CONSUMER_COUNT ", 2, lines.size()); + Assert.assertEquals("queue name filtered by CONSUMER_COUNT ", "Test1", columns[2].trim()); + + //check all queues containing address "Test1" are displayed using Filter field MESSAGE_ACKED + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("MESSAGES_ACKED"); + statQueue.setOperationName("EQUALS"); + statQueue.setValue("5"); + statQueue.execute(context); + lines = getOutputLines(context, false); + columns = lines.get(1).split("\\|"); + // Header line + 1 queues + Assert.assertEquals("rows returned filtering by MESSAGE_ACKED ", 2, lines.size()); + Assert.assertEquals("queue name filtered by MESSAGE_ACKED", "Test1", columns[2].trim()); + + //check no queues are displayed when name does not match + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setQueueName("no_queue_name"); + statQueue.execute(context); + lines = getOutputLines(context, false); + // Header line + 0 queues + Assert.assertEquals("rows returned by queueName for no Matching queue ", 1, lines.size()); + + //check maxrows is taking effect" + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setQueueName("Test1"); + statQueue.setMaxRows(1); + statQueue.execute(context); + lines = getOutputLines(context, false); + // Header line + 1 queue only + Assert.assertEquals("rows returned by maxRows=1", 2, lines.size()); + + } finally { + stopServer(); + } + + } + + @Test + public void testQstatErrors() throws Exception { + + File instanceQstat = new File(temporaryFolder.getRoot(), "instanceQStatErrors"); + setupAuth(instanceQstat); + Run.setEmbedded(true); + Artemis.main("create", instanceQstat.getAbsolutePath(), "--silent", "--no-fsync", "--no-autotune", "--no-web", "--require-login"); + System.setProperty("artemis.instance", instanceQstat.getAbsolutePath()); + Artemis.internalExecute("run"); + try { + + //check err when FIELD wrong" + TestActionContext context = new TestActionContext(); + StatQueue statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("WRONG_FILE"); + statQueue.setOperationName("EQUALS"); + statQueue.setValue("5"); + statQueue.execute(context); + ArrayList<String> lines = getOutputLines(context, false); + // Header line + 0 queue + Assert.assertEquals("No stdout for wrong FIELD", 0, lines.size()); + + lines = getOutputLines(context, true); + // 1 error line + Assert.assertEquals("stderr for wrong FIELD", 1, lines.size()); + Assert.assertTrue("'FIELD incorrect' error messsage", lines.get(0).contains("'--field' must be set to one of the following")); + + //Test err when OPERATION wrong + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("MESSAGE_COUNT"); + statQueue.setOperationName("WRONG_OPERATION"); + statQueue.setValue("5"); + statQueue.execute(context); + lines = getOutputLines(context, false); + // Header line + 0 queue + Assert.assertEquals("No stdout for wrong OPERATION", 0, lines.size()); + + lines = getOutputLines(context, true); + // 1 error line + Assert.assertEquals("stderr for wrong OPERATION", 1, lines.size()); + Assert.assertTrue("'OPERATION incorrect' error message", lines.get(0).contains("'--operation' must be set to one of the following")); + + //Test err when queueName and field set together + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setQueueName("DLQ"); + statQueue.setFieldName("MESSAGE_COUNT"); + statQueue.setOperationName("CONTAINS"); + statQueue.setValue("5"); + statQueue.execute(context); + lines = getOutputLines(context, false); + // Header line + 0 queue + Assert.assertEquals("No stdout for --field and --queueName both set", 0, lines.size()); + + lines = getOutputLines(context, true); + // 1 error line + Assert.assertEquals("stderr for --field and --queueName both set", 1, lines.size()); + Assert.assertTrue("field and queueName error message", lines.get(0).contains("'--field' and '--queueName' cannot be specified together")); + + //Test err when field set but no value + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("MESSAGE_COUNT"); + statQueue.setOperationName("CONTAINS"); + statQueue.execute(context); + lines = getOutputLines(context, false); + // Header line + 0 queue + Assert.assertEquals("No stdout for --field set BUT no --value", 0, lines.size()); + lines = getOutputLines(context, true); + // 1 error line + Assert.assertEquals("stderr for --field set BUT no --value", 1, lines.size()); + Assert.assertTrue("NO VALUE error message", lines.get(0).contains("'--value' needs to be set when '--field' is specified")); + + //Test err when field set but no operation + context = new TestActionContext(); + statQueue = new StatQueue(); + statQueue.setUser("admin"); + statQueue.setPassword("admin"); + statQueue.setFieldName("MESSAGE_COUNT"); + statQueue.setValue("5"); + statQueue.execute(context); + lines = getOutputLines(context, false); + // Header line + 0 queue + Assert.assertEquals("No stdout for --field set BUT no --operation", 0, lines.size()); + lines = getOutputLines(context, true); + // 1 error line + Assert.assertEquals("stderr for --field set BUT no --operation", 1, lines.size()); + Assert.assertTrue("OPERATION incorrect error message", lines.get(0).contains("'--operation' must be set when '--field' is specified ")); + + } finally { + stopServer(); + } + + } + + //read individual lines from byteStream + private ArrayList<String> getOutputLines(TestActionContext context, boolean errorOutput) throws IOException { + byte[] bytes; + + if (errorOutput) { + bytes = context.getStdErrBytes(); + } else { + bytes = context.getStdoutBytes(); + } + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes))); + ArrayList<String> lines = new ArrayList<>(); + + String currentLine = bufferedReader.readLine(); + while (currentLine != null) { + lines.add(currentLine); + currentLine = bufferedReader.readLine(); + } + + return lines; + } + + private void sendMessages(Session session, String queueName, int messageCount) throws JMSException { + MessageProducer producer = session.createProducer(ActiveMQDestination.createDestination("queue://" + queueName, ActiveMQDestination.TYPE.QUEUE)); + + TextMessage message = session.createTextMessage("sample message"); + for (int i = 0; i < messageCount; i++) { + producer.send(message); + } + } + private void testCli(String... args) { try { Artemis.main(args); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/87b570f7/artemis-cli/src/test/java/org/apache/activemq/cli/test/TestActionContext.java ---------------------------------------------------------------------- diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/TestActionContext.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/TestActionContext.java index 0a2da11..9a41fa6 100644 --- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/TestActionContext.java +++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/TestActionContext.java @@ -44,7 +44,15 @@ public class TestActionContext extends ActionContext { return stdout.toString(); } + public byte[] getStdoutBytes() { + return stdout.toByteArray(); + } + public String getStderr() { return stderr.toString(); } + + public byte[] getStdErrBytes() { + return stderr.toByteArray(); + } }
