From 77c84a606c0f0eef007fd23463b956d4dabafa87 Mon Sep 17 00:00:00 2001 From: Howard Gao Date: Thu, 19 Jan 2017 22:19:06 +0800 Subject: [PATCH] ARTEMIS-929 Artemis cli tools does not check non-existing options --- .../apache/activemq/artemis/cli/Artemis.java | 22 +++- .../activemq/artemis/cli/commands/Action.java | 1 + .../artemis/cli/commands/ActionAbstract.java | 6 + .../activemq/artemis/cli/commands/Create.java | 1 - .../artemis/cli/commands/HelpAction.java | 6 + .../artemis/cli/commands/InputAbstract.java | 1 - .../cli/commands/InvalidOptionsError.java | 24 ++++ .../activemq/artemis/cli/commands/Mask.java | 7 ++ .../cli/commands/address/HelpAddress.java | 7 ++ .../artemis/cli/commands/queue/HelpQueue.java | 7 ++ .../artemis/cli/commands/tools/HelpData.java | 7 ++ .../cli/commands/tools/LockAbstract.java | 3 +- .../artemis/cli/commands/user/HelpUser.java | 7 ++ .../activemq/artemis/util/OptionsUtil.java | 67 ++++++++++ .../apache/activemq/cli/test/ArtemisTest.java | 49 ++------ .../apache/activemq/cli/test/CliTestBase.java | 68 +++++++++++ .../cli/test/OptionsValidationTest.java | 115 ++++++++++++++++++ 17 files changed, 350 insertions(+), 48 deletions(-) create mode 100644 artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InvalidOptionsError.java create mode 100644 artemis-cli/src/main/java/org/apache/activemq/artemis/util/OptionsUtil.java create mode 100644 artemis-cli/src/test/java/org/apache/activemq/cli/test/CliTestBase.java create mode 100644 artemis-cli/src/test/java/org/apache/activemq/cli/test/OptionsValidationTest.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 6d5354c527..e813ffcb1c 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 @@ -27,6 +27,7 @@ import org.apache.activemq.artemis.cli.commands.ActionContext; import org.apache.activemq.artemis.cli.commands.Create; import org.apache.activemq.artemis.cli.commands.HelpAction; 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.Run; @@ -84,12 +85,13 @@ public class Artemis { return execute(false, artemisHome, artemisInstance, args.toArray(new String[args.size()])); } - public static Object execute(boolean inputEnabled, File artemisHome, File artemisInstance, String... args) throws Exception { + public static Object execute(boolean inputEnabled, File artemisHome, File artemisInstance, ActionContext context, String... args) throws Exception { + if (inputEnabled) { InputAbstract.enableInput(); } try { - return internalExecute(artemisHome, artemisInstance, args); + return internalExecute(artemisHome, artemisInstance, args, context); } catch (ConfigurationException configException) { System.err.println(configException.getMessage()); System.out.println(); @@ -104,22 +106,31 @@ public class Artemis { // this is a programming error that must be visualized and corrected e.printStackTrace(); return e; - } catch (RuntimeException re) { + } catch (RuntimeException | InvalidOptionsError re) { System.err.println(re.getMessage()); System.out.println(); Cli parser = builder(null).build(); - parser.parse("help").execute(ActionContext.system()); + parser.parse("help").execute(context); return re; } } + public static Object execute(boolean inputEnabled, File artemisHome, File artemisInstance, String... args) throws Exception { + return execute(inputEnabled, artemisHome, artemisInstance, ActionContext.system(), args); + } + /** * This method is used to validate exception returns. * Useful on test cases */ public static Object internalExecute(File artemisHome, File artemisInstance, String[] args) throws Exception { + return internalExecute(artemisHome, artemisInstance, args, ActionContext.system()); + } + + public static Object internalExecute(File artemisHome, File artemisInstance, String[] args, ActionContext context) throws Exception { + Action action = builder(artemisInstance).build().parse(args); action.setHomeValues(artemisHome, artemisInstance); @@ -132,7 +143,8 @@ public class Artemis { System.out.println("Home::" + action.getBrokerHome() + ", Instance::" + action.getBrokerInstance()); } - return action.execute(ActionContext.system()); + action.checkOptions(args); + return action.execute(context); } private static Cli.CliBuilder builder(File artemisInstance) { diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java index 72e6c73f9b..29ddd08808 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java @@ -30,4 +30,5 @@ public interface Action { String getBrokerHome(); + void checkOptions(String[] options) throws InvalidOptionsError; } diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/ActionAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/ActionAbstract.java index 17888ad371..ce90c23698 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/ActionAbstract.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/ActionAbstract.java @@ -20,6 +20,7 @@ import java.io.File; import java.net.URI; import io.airlift.airline.Option; +import org.apache.activemq.artemis.util.OptionsUtil; public abstract class ActionAbstract implements Action { @@ -111,4 +112,9 @@ public abstract class ActionAbstract implements Action { return null; } + @Override + public void checkOptions(String[] options) throws InvalidOptionsError { + OptionsUtil.checkCommandOptions(this.getClass(), options); + } + } diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java index 6d8a6543cd..5691c6813b 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java @@ -1017,5 +1017,4 @@ public class Create extends InputAbstract { c = is.read(buffer); } } - } diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/HelpAction.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/HelpAction.java index 41f91f9944..a15449402f 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/HelpAction.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/HelpAction.java @@ -19,6 +19,7 @@ package org.apache.activemq.artemis.cli.commands; import java.io.File; import io.airlift.airline.Help; +import org.apache.activemq.artemis.util.OptionsUtil; public class HelpAction extends Help implements Action { @@ -42,6 +43,11 @@ public class HelpAction extends Help implements Action { return null; } + @Override + public void checkOptions(String[] options) throws InvalidOptionsError { + OptionsUtil.checkCommandOptions(this.getClass(), options); + } + @Override public Object execute(ActionContext context) throws Exception { super.run(); diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InputAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InputAbstract.java index 9e788f7249..ec76255344 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InputAbstract.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InputAbstract.java @@ -126,5 +126,4 @@ public class InputAbstract extends ActionAbstract { return null; } - } diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InvalidOptionsError.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InvalidOptionsError.java new file mode 100644 index 0000000000..1a4edba482 --- /dev/null +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InvalidOptionsError.java @@ -0,0 +1,24 @@ +/** + * 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; + +public class InvalidOptionsError extends Exception { + + public InvalidOptionsError(String msg) { + super(msg); + } +} diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Mask.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Mask.java index 7b845a2e5b..d90536edfe 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Mask.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Mask.java @@ -19,6 +19,7 @@ package org.apache.activemq.artemis.cli.commands; import io.airlift.airline.Arguments; import io.airlift.airline.Command; import io.airlift.airline.Option; +import org.apache.activemq.artemis.util.OptionsUtil; import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec; import org.apache.activemq.artemis.utils.PasswordMaskingUtil; @@ -98,4 +99,10 @@ public class Mask implements Action { public DefaultSensitiveStringCodec getCodec() { return codec; } + + @Override + public void checkOptions(String[] options) throws InvalidOptionsError { + OptionsUtil.checkCommandOptions(this.getClass(), options); + } + } diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/HelpAddress.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/HelpAddress.java index c086c01abf..c89621e03e 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/HelpAddress.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/HelpAddress.java @@ -24,6 +24,8 @@ import java.util.List; import io.airlift.airline.Help; import org.apache.activemq.artemis.cli.commands.Action; import org.apache.activemq.artemis.cli.commands.ActionContext; +import org.apache.activemq.artemis.cli.commands.InvalidOptionsError; +import org.apache.activemq.artemis.util.OptionsUtil; public class HelpAddress extends Help implements Action { @@ -46,6 +48,11 @@ public class HelpAddress extends Help implements Action { return null; } + @Override + public void checkOptions(String[] options) throws InvalidOptionsError { + OptionsUtil.checkCommandOptions(this.getClass(), options); + } + @Override public Object execute(ActionContext context) throws Exception { List commands = new ArrayList<>(1); diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/HelpQueue.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/HelpQueue.java index 687e0f4421..f106a1848d 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/HelpQueue.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/HelpQueue.java @@ -24,6 +24,8 @@ import java.util.List; import io.airlift.airline.Help; import org.apache.activemq.artemis.cli.commands.Action; import org.apache.activemq.artemis.cli.commands.ActionContext; +import org.apache.activemq.artemis.cli.commands.InvalidOptionsError; +import org.apache.activemq.artemis.util.OptionsUtil; public class HelpQueue extends Help implements Action { @@ -46,6 +48,11 @@ public class HelpQueue extends Help implements Action { return null; } + @Override + public void checkOptions(String[] options) throws InvalidOptionsError { + OptionsUtil.checkCommandOptions(this.getClass(), options); + } + @Override public Object execute(ActionContext context) throws Exception { List commands = new ArrayList<>(1); diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/HelpData.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/HelpData.java index 43534f34b8..a7a27a6ae2 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/HelpData.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/HelpData.java @@ -24,6 +24,8 @@ import java.util.List; import io.airlift.airline.Help; import org.apache.activemq.artemis.cli.commands.Action; import org.apache.activemq.artemis.cli.commands.ActionContext; +import org.apache.activemq.artemis.cli.commands.InvalidOptionsError; +import org.apache.activemq.artemis.util.OptionsUtil; public class HelpData extends Help implements Action { @@ -56,4 +58,9 @@ public class HelpData extends Help implements Action { return null; } + @Override + public void checkOptions(String[] options) throws InvalidOptionsError { + OptionsUtil.checkCommandOptions(this.getClass(), options); + } + } diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/LockAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/LockAbstract.java index 602b55a47b..5bffb36644 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/LockAbstract.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/LockAbstract.java @@ -23,10 +23,9 @@ import java.nio.channels.FileLock; import java.nio.channels.OverlappingFileLockException; import org.apache.activemq.artemis.cli.CLIException; -import org.apache.activemq.artemis.cli.commands.Action; import org.apache.activemq.artemis.cli.commands.ActionContext; -public abstract class LockAbstract extends DataAbstract implements Action { +public abstract class LockAbstract extends DataAbstract { // There should be one lock per VM // These will be locked as long as the VM is running diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/HelpUser.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/HelpUser.java index 7a898bead6..36c034841d 100644 --- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/HelpUser.java +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/HelpUser.java @@ -19,6 +19,8 @@ package org.apache.activemq.artemis.cli.commands.user; import io.airlift.airline.Help; import org.apache.activemq.artemis.cli.commands.Action; import org.apache.activemq.artemis.cli.commands.ActionContext; +import org.apache.activemq.artemis.cli.commands.InvalidOptionsError; +import org.apache.activemq.artemis.util.OptionsUtil; import java.io.File; import java.util.ArrayList; @@ -45,6 +47,11 @@ public class HelpUser extends Help implements Action { return null; } + @Override + public void checkOptions(String[] options) throws InvalidOptionsError { + OptionsUtil.checkCommandOptions(this.getClass(), options); + } + @Override public Object execute(ActionContext context) throws Exception { List commands = new ArrayList<>(1); diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/util/OptionsUtil.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/util/OptionsUtil.java new file mode 100644 index 0000000000..ae0aba34cf --- /dev/null +++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/util/OptionsUtil.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.activemq.artemis.util; + +import io.airlift.airline.Option; +import org.apache.activemq.artemis.cli.commands.Action; +import org.apache.activemq.artemis.cli.commands.InvalidOptionsError; + +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Set; + +public class OptionsUtil { + + public static void findAllOptions(Set options, Class command) { + for (Field field : command.getDeclaredFields()) { + if (field.isAnnotationPresent(Option.class)) { + Option annotation = field.getAnnotation(Option.class); + String[] names = annotation.name(); + for (String n : names) { + options.add(n); + } + } + } + Class parent = command.getSuperclass(); + if (Action.class.isAssignableFrom(parent)) { + findAllOptions(options, parent); + } + } + + public static Set findCommandOptions(Class command) { + Set options = new HashSet<>(); + findAllOptions(options, command); + + return options; + } + + public static void checkCommandOptions(Class cmdClass, String[] options) throws InvalidOptionsError { + Set definedOptions = OptionsUtil.findCommandOptions(cmdClass); + for (String opt : options) { + if (opt.startsWith("--") && !"--".equals(opt.trim())) { + int index = opt.indexOf("="); + if (index > 0) { + opt = opt.substring(0, index); + } + if (!definedOptions.contains(opt)) { + throw new InvalidOptionsError("Found unexpected parameters: [" + opt + "]"); + } + } + } + } +} 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 af5aaae8ac..7a8ee8f635 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 @@ -30,7 +30,6 @@ import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.activemq.artemis.api.core.SimpleString; -import org.apache.activemq.artemis.api.core.client.ActiveMQClient; import org.apache.activemq.artemis.api.core.client.ClientSession; import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; import org.apache.activemq.artemis.api.core.client.ServerLocator; @@ -40,7 +39,6 @@ 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.Run; -import org.apache.activemq.artemis.cli.commands.tools.LockAbstract; import org.apache.activemq.artemis.cli.commands.user.AddUser; import org.apache.activemq.artemis.cli.commands.user.ListUser; import org.apache.activemq.artemis.cli.commands.user.RemoveUser; @@ -52,21 +50,16 @@ import org.apache.activemq.artemis.core.config.impl.FileConfiguration; import org.apache.activemq.artemis.jlibaio.LibaioContext; import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; import org.apache.activemq.artemis.jms.client.ActiveMQDestination; -import org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoader; import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec; -import org.apache.activemq.artemis.utils.ThreadLeakCheckRule; import org.apache.activemq.artemis.utils.HashProcessor; import org.apache.activemq.artemis.utils.PasswordMaskingUtil; import org.apache.activemq.artemis.utils.StringUtil; import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder; import org.apache.commons.configuration2.builder.fluent.Configurations; -import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.SAXException; @@ -79,27 +72,13 @@ import static org.junit.Assert.fail; /** * Test to validate that the CLI doesn't throw improper exceptions when invoked. */ -public class ArtemisTest { - - @Rule - public TemporaryFolder temporaryFolder; - - @Rule - public ThreadLeakCheckRule leakCheckRule = new ThreadLeakCheckRule(); - - private String original = System.getProperty("java.security.auth.login.config"); - - public ArtemisTest() { - File parent = new File("./target/tmp"); - parent.mkdirs(); - temporaryFolder = new TemporaryFolder(parent); - } +public class ArtemisTest extends CliTestBase { @Before + @Override public void setup() throws Exception { setupAuth(); - Run.setEmbedded(true); - PropertiesLoader.resetUsersAndGroupsCache(); + super.setup(); } public void setupAuth() throws Exception { @@ -110,21 +89,6 @@ public class ArtemisTest { System.setProperty("java.security.auth.login.config", folder.getAbsolutePath() + "/etc/login.config"); } - @After - public void cleanup() { - ActiveMQClient.clearThreadPools(); - System.clearProperty("artemis.instance"); - Run.setEmbedded(false); - - if (original == null) { - System.clearProperty("java.security.auth.login.config"); - } else { - System.setProperty("java.security.auth.login.config", original); - } - - LockAbstract.unlock(); - } - @Test public void invalidCliDoesntThrowException() { testCli("--silent", "create"); @@ -159,6 +123,13 @@ public class ArtemisTest { } + @Test + public void testSimpleCreate() throws Exception { + //instance1: default using http + File instance1 = new File(temporaryFolder.getRoot(), "instance1"); + Artemis.main("create", instance1.getAbsolutePath(), "--silent", "--no-fsync"); + } + @Test public void testWebConfig() throws Exception { setupAuth(); diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/CliTestBase.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/CliTestBase.java new file mode 100644 index 0000000000..970adbcff7 --- /dev/null +++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/CliTestBase.java @@ -0,0 +1,68 @@ +/* + * 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.cli.test; + +import org.apache.activemq.artemis.api.core.client.ActiveMQClient; +import org.apache.activemq.artemis.cli.commands.Run; +import org.apache.activemq.artemis.cli.commands.tools.LockAbstract; +import org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoader; +import org.apache.activemq.artemis.utils.ThreadLeakCheckRule; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; + +import java.io.File; + +public class CliTestBase { + + @Rule + public TemporaryFolder temporaryFolder; + + @Rule + public ThreadLeakCheckRule leakCheckRule = new ThreadLeakCheckRule(); + + private String original = System.getProperty("java.security.auth.login.config"); + + public CliTestBase() { + File parent = new File("./target/tmp"); + parent.mkdirs(); + temporaryFolder = new TemporaryFolder(parent); + } + + @Before + public void setup() throws Exception { + Run.setEmbedded(true); + PropertiesLoader.resetUsersAndGroupsCache(); + } + + @After + public void tearDown() throws Exception { + ActiveMQClient.clearThreadPools(); + System.clearProperty("artemis.instance"); + Run.setEmbedded(false); + + if (original == null) { + System.clearProperty("java.security.auth.login.config"); + } else { + System.setProperty("java.security.auth.login.config", original); + } + + LockAbstract.unlock(); + } + +} diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/OptionsValidationTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/OptionsValidationTest.java new file mode 100644 index 0000000000..31935f3668 --- /dev/null +++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/OptionsValidationTest.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.cli.test; + +import io.airlift.airline.ParseArgumentsUnexpectedException; +import org.apache.activemq.artemis.cli.Artemis; +import org.apache.activemq.artemis.cli.commands.ActionContext; +import org.apache.activemq.artemis.cli.commands.InvalidOptionsError; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +@RunWith(value = Parameterized.class) +public class OptionsValidationTest extends CliTestBase { + + private File artemisInstance; + + private String group; + private String command; + private boolean needInstance; + + @Parameterized.Parameters(name = "group={0}, command={1}, need-instance={2}") + public static Collection getParameters() { + return Arrays.asList(new Object[][]{{null, "create", false}, + {null, "run", true}, + {null, "kill", true}, + {null, "stop", true}, + {"address", "create", false}, + {"address", "delete", false}, + {"address", "update", false}, + {"address", "show", false}, + {null, "browser", false}, + {null, "consumer", false}, + {null, "mask", false}, + {null, "help", false}, + {null, "migrate1x", false}, + {null, "producer", false}, + {"queue", "create", false}, + {"queue", "delete", false}, + {"queue", "update", false}, + {"data", "print", false}, + {"data", "print", true}, + {"data", "exp", true}, + {"data", "imp", true}, + {"data", "encode", true}, + {"data", "decode", true}, + {"data", "compact", true}, + {"user", "add", true}, + {"user", "rm", true}, + {"user", "list", true}, + {"user", "reset", true} + }); + } + + public OptionsValidationTest(String group, String command, boolean needInstance) { + this.group = group; + this.command = command; + this.needInstance = needInstance; + } + + @Before + public void setUp() throws Exception { + super.setup(); + this.artemisInstance = new File(temporaryFolder.getRoot() + "instance1"); + } + + @After + @Override + public void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testCommand() throws Exception { + ActionContext context = new TestActionContext(); + String[] invalidArgs = null; + if (group == null) { + invalidArgs = new String[] {command, "--blahblah-" + command, "--rubbish-" + command + "=" + "more-rubbish", "--input=blahblah"}; + } else { + invalidArgs = new String[] {group, command, "--blahblah-" + command, "--rubbish-" + command + "=" + "more-rubbish", "--input=blahblah"}; + } + try { + Artemis.internalExecute(null, needInstance ? this.artemisInstance : null, invalidArgs, context); + fail("cannot detect invalid options"); + } catch (InvalidOptionsError e) { + assertTrue(e.getMessage().contains("Found unexpected parameters")); + } catch (ParseArgumentsUnexpectedException e) { + //airline can detect some invalid args during parsing + //which is fine. + } + } +}