/* * 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.geode.management.internal.cli; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.apache.geode.management.internal.cli.exceptions.CliCommandOptionException; import org.apache.geode.management.internal.cli.exceptions.CliCommandOptionMissingException; import org.apache.geode.management.internal.cli.exceptions.CliCommandOptionNotApplicableException; import org.apache.geode.management.internal.cli.parser.Argument; import org.apache.geode.management.internal.cli.parser.Option; import org.apache.geode.management.internal.cli.parser.OptionSet; import org.apache.geode.management.internal.cli.parser.jopt.JoptOptionParser; import org.apache.geode.test.junit.categories.UnitTest; @Category(UnitTest.class) @RunWith(JUnitParamsRunner.class) public class JoptOptionParserTest { private JoptOptionParser emptyOptionParser; private OptionSet emptyOptionSet; private Argument requiredArgument; private Argument optionalArgument; private Option requiredOption; private Option optionalOption; private JoptOptionParser simpleOptionParser; private JoptOptionParser exampleOptionParser; @Before public void setUp() throws Exception { this.emptyOptionParser = new JoptOptionParser(); this.emptyOptionSet = new OptionSet(); defineSimpleOptionParser(); defineExampleOptionParser(); } @Test public void getArgumentsIsEmptyByDefault() throws Exception { assertThat(this.emptyOptionParser.getArguments()).isEmpty(); } @Test public void getOptionsIsNullByDefault() throws Exception { assertThat(this.emptyOptionParser.getOptions()).isNull(); } @Test public void parseNullReturnsDefaultOptionSet() throws Exception { OptionSet optionSet = this.emptyOptionParser.parse(null); assertThat(optionSet.areArgumentsPresent()).isEqualTo(emptyOptionSet.areArgumentsPresent()); assertThat(optionSet.areOptionsPresent()).isEqualTo(emptyOptionSet.areOptionsPresent()); assertThat(optionSet.getNoOfSpacesRemoved()).isEqualTo(emptyOptionSet.getNoOfSpacesRemoved()); assertThat(optionSet.getSplit()).isEqualTo(emptyOptionSet.getSplit()); assertThat(optionSet.getNoOfSpacesRemoved()).isEqualTo(emptyOptionSet.getNoOfSpacesRemoved()); assertThat(optionSet.getUserInput()).isEqualTo(""); // emptyOptionSet.getUserInput()); assertThat(optionSet.getValue((Argument) null)) .isEqualTo(emptyOptionSet.getValue((Argument) null)); assertThat(optionSet.getValue((Option) null)).isEqualTo(emptyOptionSet.getValue((Option) null)); } @Test public void parseEmptyThrowsNullPointerException() throws Exception { assertThatThrownBy(() -> this.emptyOptionParser.parse("")) .isInstanceOf(NullPointerException.class); } @Test public void setArgumentsShouldCreateCopy() throws Exception { Argument argument = mock(Argument.class); when(argument.isRequired()).thenReturn(true); LinkedList<Argument> arguments = new LinkedList<>(); arguments.add(argument); this.emptyOptionParser.setArguments(arguments); assertThat(this.emptyOptionParser.getArguments()).isNotSameAs(arguments); assertThat(this.emptyOptionParser.getArguments()).hasSize(1); arguments.clear(); assertThat(arguments).hasSize(0); assertThat(this.emptyOptionParser.getArguments()).hasSize(1); } @Test public void setArgumentsShouldKeepRequiredBeforeOptional() throws Exception { Argument requiredArgument1 = mock(Argument.class); when(requiredArgument1.isRequired()).thenReturn(true); Argument optionalArgument1 = mock(Argument.class); when(optionalArgument1.isRequired()).thenReturn(false); LinkedList<Argument> arguments = new LinkedList<>(); arguments.add(requiredArgument1); arguments.add(optionalArgument1); this.emptyOptionParser.setArguments(arguments); LinkedList<Argument> argumentsReturned = this.emptyOptionParser.getArguments(); assertThat(argumentsReturned).hasSize(2); assertThat(argumentsReturned.getFirst()).isSameAs(requiredArgument1); assertThat(argumentsReturned.getLast()).isSameAs(optionalArgument1); } @Test public void setArgumentsShouldMoveRequiredBeforeOptional() throws Exception { Argument requiredArgument1 = mock(Argument.class); when(requiredArgument1.isRequired()).thenReturn(true); Argument optionalArgument1 = mock(Argument.class); when(optionalArgument1.isRequired()).thenReturn(false); LinkedList<Argument> arguments = new LinkedList<>(); arguments.add(optionalArgument1); arguments.add(requiredArgument1); this.emptyOptionParser.setArguments(arguments); LinkedList<Argument> argumentsReturned = this.emptyOptionParser.getArguments(); assertThat(argumentsReturned).hasSize(2); assertThat(argumentsReturned.getFirst()).isSameAs(requiredArgument1); assertThat(argumentsReturned.getLast()).isSameAs(optionalArgument1); } @Test public void setOptionsShouldKeepSameInstance() throws Exception { Option option = mock(Option.class); ArrayList aggregate = new ArrayList<String>(); aggregate.add("option"); when(option.getAggregate()).thenReturn(aggregate); when(option.getHelp()).thenReturn("help text"); LinkedList<Option> options = new LinkedList<>(); options.add(option); this.emptyOptionParser.setOptions(options); assertThat(this.emptyOptionParser.getOptions()).isSameAs(options); assertThat(this.emptyOptionParser.getOptions()).hasSize(1); options.clear(); assertThat(options).hasSize(0); assertThat(this.emptyOptionParser.getOptions()).hasSize(0); } @Test public void parseInputWithDefinedArgumentShouldWork() throws Exception { LinkedList<Argument> arguments = new LinkedList<>(); LinkedList<Option> options = new LinkedList<>(); arguments.add(this.requiredArgument); JoptOptionParser optionParser = new JoptOptionParser(); optionParser.setArguments(arguments); optionParser.setOptions(options); OptionSet optionSet = optionParser.parse("command1 argument1_value"); assertThat(optionSet.areArgumentsPresent()).isTrue(); assertThat(optionSet.hasArgument(this.requiredArgument)).isTrue(); } @Test public void parseInputWithOneArgumentShouldFindJustOneArgument() throws Exception { LinkedList<Argument> arguments = new LinkedList<>(); LinkedList<Option> options = new LinkedList<>(); arguments.add(this.requiredArgument); JoptOptionParser optionParser = new JoptOptionParser(); optionParser.setArguments(arguments); optionParser.setOptions(options); OptionSet optionSet = optionParser.parse("command1 argument1_value"); assertThat(optionSet.areArgumentsPresent()).isTrue(); assertThat(optionSet.hasArgument(this.requiredArgument)).isTrue(); assertThat(optionSet.hasArgument(this.optionalArgument)).isFalse(); } @Test public void parseInputWithTwoArgumentsShouldFindTwoArguments() throws Exception { LinkedList<Argument> arguments = new LinkedList<>(); LinkedList<Option> options = new LinkedList<>(); arguments.add(this.requiredArgument); arguments.add(this.optionalArgument); JoptOptionParser optionParser = new JoptOptionParser(); optionParser.setArguments(arguments); optionParser.setOptions(options); OptionSet optionSet = optionParser.parse("command1 argument1_value? argument2_value"); assertThat(optionSet.areArgumentsPresent()).isTrue(); assertThat(optionSet.hasArgument(this.requiredArgument)).isTrue(); assertThat(optionSet.hasArgument(this.optionalArgument)).isTrue(); } @Test public void parseInputWithUndefinedArgumentShouldNotThrow() throws Exception { LinkedList<Argument> arguments = new LinkedList<>(); LinkedList<Option> options = new LinkedList<>(); arguments.add(this.requiredArgument); JoptOptionParser optionParser = new JoptOptionParser(); optionParser.setArguments(arguments); optionParser.setOptions(options); OptionSet optionSet = optionParser.parse("command1 argument1_value? argument2_value"); assertThat(optionSet.getUserInput()).isEqualTo("command1 argument1_value? argument2_value"); } @Test public void parseInputShouldIgnoreUndefinedOption() throws Exception { // one fix for GEODE-1598 has a side effect of preventing our detection of undefined options OptionSet optionSet = this.simpleOptionParser.parse("command1 argument1_value argument2_value --undefinedOption"); assertThat(optionSet.areOptionsPresent()).isFalse(); assertThat(optionSet.hasOption(this.requiredOption)).isFalse(); assertThat(optionSet.hasOption(this.optionalOption)).isFalse(); } @Test public void parseInputWithOneOptionShouldFindOneOption() throws Exception { OptionSet optionSet = this.simpleOptionParser.parse("command1 argument1_value --option1"); assertThat(optionSet.areOptionsPresent()).isTrue(); assertThat(optionSet.hasOption(this.requiredOption)).isTrue(); assertThat(optionSet.hasOption(this.optionalOption)).isFalse(); } @Test public void parseInputWithTwoOptionsShouldFindTwoOptions() throws Exception { OptionSet optionSet = this.simpleOptionParser.parse("command1 argument1_value --option1 --option2"); assertThat(optionSet.areOptionsPresent()).isTrue(); assertThat(optionSet.hasOption(this.requiredOption)).isTrue(); assertThat(optionSet.hasOption(this.optionalOption)).isTrue(); } @Test public void parseInputWithOptionWithValueShouldFindOption() throws Exception { OptionSet optionSet = this.simpleOptionParser.parse("command1 argument1_value --option1=value"); assertThat(optionSet.areOptionsPresent()).isTrue(); assertThat(optionSet.hasOption(this.requiredOption)).isTrue(); } @Test public void parseInputWithOptionWithoutValueShouldFindOption() throws Exception { OptionSet optionSet = this.simpleOptionParser.parse("command1 argument1_value --option1"); assertThat(optionSet.areOptionsPresent()).isTrue(); assertThat(optionSet.hasOption(this.requiredOption)).isTrue(); } @Test public void parseInputWithoutOptionShouldNotFindOptions() throws Exception { LinkedList<Argument> arguments = new LinkedList<>(); LinkedList<Option> options = new LinkedList<>(); arguments.add(this.requiredArgument); JoptOptionParser optionParser = new JoptOptionParser(); optionParser.setArguments(arguments); optionParser.setOptions(options); OptionSet optionSet = optionParser.parse("command1 argument1_value"); assertThat(optionSet.areOptionsPresent()).isFalse(); assertThat(optionSet.hasOption(this.requiredOption)).isFalse(); } @Test @Parameters(method = "exampleInputParameters") public void parseInputWithExampleInputParametesr(String command, boolean expectException, boolean hasArguments, boolean hasOptions) throws Exception { if (expectException) { assertThatThrownBy(() -> this.exampleOptionParser.parse(command)) .isExactlyInstanceOf(CliCommandOptionMissingException.class); return; } OptionSet options = this.exampleOptionParser.parse(command); assertThat(options).isNotNull(); assertThat(options.areArgumentsPresent()).isEqualTo(hasArguments); assertThat(options.areOptionsPresent()).isEqualTo(hasOptions); } private static Object[] exampleInputParameters() { return new Object[] { // 0 new Object[] {" ARGUMENT1_VALUE —option1=somevalue", false, true, false}, // 1 new Object[] {" ARGUMENT1_VALUE? ARGUMENT2_VALUE -- ----------", false, true, false}, // 2 new Object[] {" --option1=value", false, false, true}, // 3 new Object[] { " ARGUMENT1_VALUE? ARGUMENT2_VALUE --option1=option1value --option2", false, true, true}, // 4 new Object[] { " ARGUMENT1_VALUE? ARGUMENT2_VALUE --option1=option1value --option2=option2value --option3=option3value", false, true, true}, // 5 new Object[] { " --string=string1 --stringArray=1,2 --stringArray=3,4 --stringList=11,12,13 --integer=10 --stringArray=5 --stringList=14,15", false, false, true}, // 6 new Object[] {" --stringArray=1,2 --stringArray='3,4'", false, false, true}, // 7 new Object[] { " --string=\"1\" --colonArray=2:3:4 --stringArray=5,\"6,7\",8 --stringList=\"9,10,11,12\"", false, false, true}, // 8 new Object[] {" --string=string1 --stringArray=1,2 --string=string2", false, false, true}, // 9 new Object[] {" this is just one argument?this is a second argument", false, true, false}}; } private void defineSimpleOptionParser() { LinkedList<Argument> arguments = new LinkedList<Argument>(); LinkedList<Option> options = new LinkedList<Option>(); this.requiredArgument = mock(Argument.class); when(this.requiredArgument.getArgumentName()).thenReturn("argument1"); when(this.requiredArgument.getContext()).thenReturn("context for argument1"); when(this.requiredArgument.getHelp()).thenReturn("help for argument1"); when(this.requiredArgument.isRequired()).thenReturn(true); arguments.add(this.requiredArgument); this.optionalArgument = mock(Argument.class); when(this.optionalArgument.getArgumentName()).thenReturn("argument2"); when(this.optionalArgument.getContext()).thenReturn("context for argument2"); when(this.optionalArgument.getHelp()).thenReturn("help for argument2"); when(this.optionalArgument.isRequired()).thenReturn(false); when(this.optionalArgument.getUnspecifiedDefaultValue()) .thenReturn("{unspecified default value for argument2}"); when(this.optionalArgument.isSystemProvided()).thenReturn(false); arguments.add(this.optionalArgument); this.requiredOption = mock(Option.class); when(this.requiredOption.getLongOption()).thenReturn("--option1"); List<String> aggregate = new ArrayList<>(); aggregate.add("option1"); when(this.requiredOption.getAggregate()).thenReturn(aggregate); when(this.requiredOption.getLongOption()).thenReturn("option1"); when(this.requiredOption.getHelp()).thenReturn("help for option1"); when(this.requiredOption.getValueSeparator()).thenReturn("="); when(this.requiredOption.isRequired()).thenReturn(true); assertThat(this.requiredOption.getAggregate()).isNotEmpty(); options.add(this.requiredOption); this.optionalOption = mock(Option.class); when(this.optionalOption.getLongOption()).thenReturn("--option2"); aggregate = new ArrayList<>(); aggregate.add("option2"); when(this.optionalOption.getAggregate()).thenReturn(aggregate); when(this.optionalOption.getLongOption()).thenReturn("option2"); when(this.optionalOption.getHelp()).thenReturn("help for option2"); when(this.optionalOption.getValueSeparator()).thenReturn("="); when(this.optionalOption.isRequired()).thenReturn(false); assertThat(this.optionalOption.getAggregate()).isNotEmpty(); options.add(this.optionalOption); this.simpleOptionParser = new JoptOptionParser(); this.simpleOptionParser.setArguments(arguments); this.simpleOptionParser.setOptions(options); } private void defineExampleOptionParser() { LinkedList<Argument> arguments = new LinkedList<Argument>(); LinkedList<Option> options = new LinkedList<Option>(); Argument argument1 = mock(Argument.class); when(argument1.getArgumentName()).thenReturn("argument1"); when(argument1.getContext()).thenReturn("context for argument1"); when(argument1.getHelp()).thenReturn("help for argument1"); when(argument1.isRequired()).thenReturn(true); arguments.add(argument1); Argument argument2 = mock(Argument.class); when(argument2.getArgumentName()).thenReturn("argument2"); when(argument2.getContext()).thenReturn("context for argument2"); when(argument2.getHelp()).thenReturn("help for argument2"); when(argument2.isRequired()).thenReturn(false); when(argument2.getUnspecifiedDefaultValue()) .thenReturn("{unspecified default value for argument2}"); when(argument2.isSystemProvided()).thenReturn(false); arguments.add(argument2); Argument argument3 = mock(Argument.class); when(argument3.getArgumentName()).thenReturn("argument3"); when(argument3.getContext()).thenReturn("context for argument3"); when(argument3.getHelp()).thenReturn("help for argument3"); when(argument3.isRequired()).thenReturn(false); when(argument3.getUnspecifiedDefaultValue()) .thenReturn("{unspecified default value for argument3}"); when(argument2.isSystemProvided()).thenReturn(false); arguments.add(argument3); Option option1 = mock(Option.class); when(option1.getLongOption()).thenReturn("--option1"); List<String> aggregate1 = new ArrayList<>(); aggregate1.add("option1"); when(option1.getAggregate()).thenReturn(aggregate1); when(option1.getLongOption()).thenReturn("option1"); when(option1.getHelp()).thenReturn("help for option1"); when(option1.getValueSeparator()).thenReturn("="); when(option1.isRequired()).thenReturn(false); assertThat(option1.getAggregate()).isNotEmpty(); options.add(option1); Option option2 = mock(Option.class); when(option2.getLongOption()).thenReturn("--option2"); List<String> aggregate2 = new ArrayList<>(); aggregate2.add("option2"); when(option2.getAggregate()).thenReturn(aggregate2); when(option2.getLongOption()).thenReturn("option2"); when(option2.getHelp()).thenReturn("help for option2"); when(option2.getValueSeparator()).thenReturn("="); when(option2.isRequired()).thenReturn(false); assertThat(option2.getAggregate()).isNotEmpty(); options.add(option2); Option option3 = mock(Option.class); when(option3.getLongOption()).thenReturn("--option3"); List<String> aggregate3 = new ArrayList<>(); aggregate3.add("option3"); when(option3.getAggregate()).thenReturn(aggregate3); when(option3.getLongOption()).thenReturn("option3"); when(option3.getHelp()).thenReturn("help for option3"); when(option3.getValueSeparator()).thenReturn("="); when(option3.isRequired()).thenReturn(false); assertThat(option3.getAggregate()).isNotEmpty(); options.add(option3); Option stringOption = mock(Option.class); when(stringOption.getLongOption()).thenReturn("--string"); List<String> aggregateStringOption = new ArrayList<>(); aggregateStringOption.add("string"); when(stringOption.getAggregate()).thenReturn(aggregateStringOption); when(stringOption.getLongOption()).thenReturn("string"); when(stringOption.getHelp()).thenReturn("help for string"); when(stringOption.getValueSeparator()).thenReturn("="); when(stringOption.isRequired()).thenReturn(false); assertThat(stringOption.getAggregate()).isNotEmpty(); options.add(stringOption); Option stringArrayOption = mock(Option.class); when(stringArrayOption.getLongOption()).thenReturn("--stringArray"); List<String> aggregateStringArrayOption = new ArrayList<>(); aggregateStringArrayOption.add("stringArray"); when(stringArrayOption.getAggregate()).thenReturn(aggregateStringArrayOption); when(stringArrayOption.getLongOption()).thenReturn("stringArray"); when(stringArrayOption.getHelp()).thenReturn("help for stringArray"); when(stringArrayOption.getValueSeparator()).thenReturn("="); when(stringArrayOption.isRequired()).thenReturn(false); assertThat(stringArrayOption.getAggregate()).isNotEmpty(); options.add(stringArrayOption); Option stringListOption = mock(Option.class); when(stringListOption.getLongOption()).thenReturn("--stringList"); List<String> aggregateStringListOption = new ArrayList<>(); aggregateStringListOption.add("stringList"); when(stringListOption.getAggregate()).thenReturn(aggregateStringListOption); when(stringListOption.getLongOption()).thenReturn("stringList"); when(stringListOption.getHelp()).thenReturn("help for stringList"); when(stringListOption.getValueSeparator()).thenReturn("="); when(stringListOption.isRequired()).thenReturn(false); assertThat(stringListOption.getAggregate()).isNotEmpty(); options.add(stringListOption); Option integerOption = mock(Option.class); when(integerOption.getLongOption()).thenReturn("--integer"); List<String> aggregateIntegerOption = new ArrayList<>(); aggregateIntegerOption.add("integer"); when(integerOption.getAggregate()).thenReturn(aggregateIntegerOption); when(integerOption.getLongOption()).thenReturn("integer"); when(integerOption.getHelp()).thenReturn("help for integer"); when(integerOption.getValueSeparator()).thenReturn("="); when(integerOption.isRequired()).thenReturn(false); assertThat(integerOption.getAggregate()).isNotEmpty(); options.add(integerOption); Option colonArrayOption = mock(Option.class); when(colonArrayOption.getLongOption()).thenReturn("--colonArray"); List<String> aggregateColonArrayOption = new ArrayList<>(); aggregateColonArrayOption.add("colonArray"); when(colonArrayOption.getAggregate()).thenReturn(aggregateColonArrayOption); when(colonArrayOption.getLongOption()).thenReturn("colonArray"); when(colonArrayOption.getHelp()).thenReturn("help for colonArray"); when(colonArrayOption.getValueSeparator()).thenReturn("="); when(colonArrayOption.isRequired()).thenReturn(false); assertThat(colonArrayOption.getAggregate()).isNotEmpty(); options.add(colonArrayOption); this.exampleOptionParser = new JoptOptionParser(); this.exampleOptionParser.setArguments(arguments); this.exampleOptionParser.setOptions(options); } }