/*
* Copyright (c) 2011-2015 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.core.cli.impl;
import io.vertx.core.cli.*;
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
/**
* Test based on the commons-cli parser tests.
*/
public class IntensiveDefaultParserTest {
private DefaultCLI cli;
@Before
public void setUp() {
cli = new DefaultCLI();
cli.setName("test").setHidden(false).setDescription("A test command");
cli.addOption(new TypedOption<Boolean>().setType(Boolean.class).setShortName("a").setLongName("enable-a")
.setFlag(true).setDescription("turn [a] on or off"));
cli.addOption(new TypedOption<String>().setType(String.class).setShortName("b").setLongName("bfile").setSingleValued(true)
.setDescription("set the value of [b]"));
cli.addOption(new TypedOption<Boolean>().setType(Boolean.class).setShortName("c").setLongName("copt").setSingleValued(false)
.setDescription("turn [c] on or off"));
}
private boolean getBooleanOption(CommandLine evaluatedCLI, String name) {
return evaluatedCLI.getOptionValue(name);
}
private String getStringOption(CommandLine evaluatedCLI, String name) {
return evaluatedCLI.getOptionValue(name);
}
@Test
public void testSimpleShort() throws Exception {
String[] args = new String[]{
"-a",
"-b", "toast",
"foo", "bar"};
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getBooleanOption(evaluated, "a")).isTrue();
assertThat(getStringOption(evaluated, "b")).isEqualTo("toast");
assertThat(getBooleanOption(evaluated, "c")).isFalse();
assertThat(evaluated.allArguments()).contains("foo", "bar").hasSize(2);
}
@Test
public void testSimpleLong() throws Exception {
String[] args = new String[]{"--enable-a",
"--bfile", "toast",
"foo", "bar"};
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getBooleanOption(evaluated, "a")).isTrue();
assertThat(getStringOption(evaluated, "b")).isEqualTo("toast");
assertThat(getStringOption(evaluated, "bfile")).isEqualTo("toast");
assertThat(getBooleanOption(evaluated, "c")).isFalse();
assertThat(evaluated.allArguments()).contains("foo", "bar").hasSize(2);
}
@Test
public void testArgumentsInTheMiddle() throws Exception {
String[] args = new String[]{"-c",
"foobar",
"-b", "toast"};
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getBooleanOption(evaluated, "c")).isTrue();
assertThat(getStringOption(evaluated, "b")).isEqualTo("toast");
assertThat(evaluated.allArguments()).contains("foobar").hasSize(1);
}
@Test
public void testUnrecognizedOption() throws Exception {
String[] args = new String[]{"-a", "-d", "-b", "toast", "foo", "bar"};
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(evaluated.allArguments()).contains("-d", "foo", "bar").hasSize(3);
}
@Test
public void testMissingValue() throws Exception {
String[] args = new String[]{"-b"};
try {
CommandLine evaluated = cli.parse(Arrays.asList(args));
fail("Exception expected");
} catch (MissingValueException e) {
assertThat(e.getOption().getShortName()).isEqualToIgnoringCase("b");
}
}
@Test
public void testDoubleDash1() throws Exception {
String[] args = new String[]{
"--copt",
"--",
"-b", "toast"};
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getBooleanOption(evaluated, "c")).isTrue();
assertThat(getStringOption(evaluated, "b")).isNull();
assertThat(evaluated.allArguments()).hasSize(2).contains("-b", "toast");
}
@Test
public void testMissingValueBecauseOfDoubleDash() throws Exception {
cli.addOption(new TypedOption<String>().setType(String.class).setShortName("n").setSingleValued(true));
cli.addOption(new TypedOption<String>().setType(String.class).setShortName("m").setSingleValued(false));
try {
cli.parse(Arrays.asList("-n", "--", "-m"));
fail("Exception expected");
} catch (MissingValueException e) {
assertThat(e.getOption().getShortName()).isEqualTo("n");
}
}
@Test
public void testSingleDash() throws Exception {
String[] args = new String[]{"--copt",
"-b", "-",
"-a",
"-"};
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getBooleanOption(evaluated, "a")).isTrue();
assertThat(getStringOption(evaluated, "b")).isEqualTo("-");
assertThat(getBooleanOption(evaluated, "c")).isTrue();
assertThat(evaluated.allArguments()).contains("-").hasSize(1);
}
@Test
public void testNegativeArgument() throws Exception {
String[] args = new String[]{"-b", "-1"};
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getStringOption(evaluated, "b")).isEqualTo("-1");
}
@Test
public void testNegativeOption() throws Exception {
String[] args = new String[]{"-b", "-1"};
cli.addOption(new TypedOption<Boolean>().setType(Boolean.class).setSingleValued(false).setShortName("1"));
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getStringOption(evaluated, "b")).isEqualTo("-1");
assertThat(getBooleanOption(evaluated, "1")).isFalse();
evaluated = cli.parse(Collections.singletonList("-1"));
assertThat(getBooleanOption(evaluated, "1")).isTrue();
assertThat(getStringOption(evaluated, "b")).isNull();
}
@Test
public void testArgumentStartingWithHyphen() throws Exception {
String[] args = new String[]{"-b", "-foo"};
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getStringOption(evaluated, "b")).isEqualTo("-foo");
}
@Test
public void testShortWithEqual() throws Exception {
String[] args = new String[]{"-f=bar"};
cli.addOption(new TypedOption<String>().setType(String.class).setSingleValued(true)
.setLongName("foo").setShortName("f"));
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getStringOption(evaluated, "foo")).isEqualTo("bar");
}
@Test
public void testShortWithoutEqual() throws Exception {
String[] args = new String[]{"-fbar"};
cli.addOption(new TypedOption<String>().setType(String.class).setSingleValued(true)
.setLongName("foo").setShortName("f"));
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getStringOption(evaluated, "foo")).isEqualTo("bar");
}
@Test
public void testLongWithEqualDoubleDash() throws Exception {
String[] args = new String[]{"--foo=bar"};
cli.addOption(new TypedOption<String>().setType(String.class).setSingleValued(true)
.setLongName("foo").setShortName("f"));
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getStringOption(evaluated, "foo")).isEqualTo("bar");
}
@Test
public void testLongWithEqualSingleDash() throws Exception {
String[] args = new String[]{"-foo=bar"};
cli.addOption(new TypedOption<String>().setType(String.class).setSingleValued(true)
.setLongName("foo").setShortName("f"));
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getStringOption(evaluated, "foo")).isEqualTo("bar");
}
@Test
public void testLongWithoutEqualSingleDash() throws Exception {
String[] args = new String[]{"-foobar"};
cli.addOption(new TypedOption<String>().setType(String.class).setSingleValued(true)
.setLongName("foo").setShortName("f"));
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getStringOption(evaluated, "foo")).isEqualTo("bar");
}
@Test
public void testAmbiguousLongWithoutEqualSingleDash() throws Exception {
String[] args = new String[]{"-b", "-foobar"};
TypedOption<String> f =
new TypedOption<String>().setType(String.class).setLongName("foo").setShortName("f").setSingleValued(true);
TypedOption<Boolean> b =
new TypedOption<Boolean>().setType(Boolean.class).setLongName("bar").setShortName("b")
.setFlag(true);
cli.removeOption("b").addOption(f).addOption(b);
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat((boolean) evaluated.getOptionValue("bar")).isTrue();
assertThat((String) evaluated.getOptionValue("foo")).isEqualTo("bar");
}
@Test
public void testLongWithoutEqualDoubleDash() throws Exception {
String[] args = new String[]{"--foobar"};
TypedOption<String> f = new TypedOption<String>()
.setType(String.class).setLongName("foo").setShortName("f").setSingleValued(true);
cli.addOption(f);
CommandLine evaluated = cli.parse(Arrays.asList(args));
// foo isn't expected to be recognized with a double dash
assertThat((String) evaluated.getOptionValue("foo")).isNull();
}
@Test
public void testLongWithUnexpectedArgument1() throws Exception {
String[] args = new String[]{"--foo=bar"};
TypedOption<Boolean> f = new TypedOption<Boolean>().setLongName("foo").setShortName("f")
.setType(Boolean.class)
.setSingleValued(false) // No value accepted here.
.setFlag(true);
cli.addOption(f);
try {
CommandLine evaluated = cli.parse(Arrays.asList(args));
fail("Exception expected");
} catch (InvalidValueException e) {
assertThat(e.getOption().getShortName()).isEqualToIgnoringCase("f");
assertThat(e.getValue()).isEqualToIgnoringCase("bar");
}
}
@Test
public void testLongWithUnexpectedArgument2() throws Exception {
String[] args = new String[]{"-foobar"};
TypedOption<Boolean> f = new TypedOption<Boolean>().setLongName("foo").setShortName("f").setType(Boolean.class)
.setSingleValued(false) // No value accepted here.
;
cli.addOption(f);
try {
CommandLine evaluated = cli.parse(Arrays.asList(args));
fail("Exception expected");
} catch (InvalidValueException e) {
assertThat(e.getOption().getShortName()).isEqualToIgnoringCase("f");
assertThat(e.getValue()).isEqualToIgnoringCase("bar");
}
}
@Test
public void testShortWithUnexpectedArgument() throws Exception {
String[] args = new String[]{"-f=bar"};
TypedOption<Boolean> f = new TypedOption<Boolean>().setLongName("foo").setShortName("f").setType(Boolean.class)
.setSingleValued(false) // No value accepted here.
;
cli.addOption(f);
try {
CommandLine evaluated = cli.parse(Arrays.asList(args));
fail("Exception expected");
} catch (InvalidValueException e) {
assertThat(e.getOption().getShortName()).isEqualToIgnoringCase("f");
assertThat(e.getValue()).isEqualToIgnoringCase("bar");
}
}
@Test
public void testPropertiesOption1() throws Exception {
String[] args = new String[]{"-Jsource=1.5", "-J", "target", "1.5", "foo"};
TypedOption<String> f = new TypedOption<String>().setShortName("J")
.setType(String.class)
.setMultiValued(true);
cli.addOption(f);
CommandLine evaluated = cli.parse(Arrays.asList(args));
List<String> values = evaluated.getOptionValues("J");
assertThat(values).hasSize(4).containsExactly("source=1.5", "target", "1.5", "foo");
}
@Test
public void testUnambiguousPartialLongOption1() throws Exception {
String[] args = new String[]{"--ver"};
TypedOption<Boolean> v = new TypedOption<Boolean>().setLongName("version").setType(Boolean.class)
.setSingleValued(false);
TypedOption<Boolean> h = new TypedOption<Boolean>().setLongName("help").setType(Boolean.class)
.setSingleValued(false);
cli.addOption(v).addOption(h);
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getBooleanOption(evaluated, "version")).isTrue();
}
@Test
public void testUnambiguousPartialLongOption2() throws Exception {
String[] args = new String[]{"-ver"};
TypedOption<Boolean> v = new TypedOption<Boolean>().setLongName("version").setType(Boolean.class)
.setSingleValued(false);
TypedOption<Boolean> h = new TypedOption<Boolean>().setLongName("help").setType(Boolean.class)
.setSingleValued(false);
cli.addOption(v).addOption(h);
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getBooleanOption(evaluated, "version")).isTrue();
}
@Test
public void testUnambiguousPartialLongOption3() throws Exception {
String[] args = new String[]{"--ver=1"};
TypedOption<Integer> v = new TypedOption<Integer>().setLongName("verbose")
.setSingleValued(true)
.setType(Integer.class);
TypedOption<Boolean> h = new TypedOption<Boolean>().setLongName("help").setType(Boolean.class)
.setSingleValued(false);
cli.addOption(v).addOption(h);
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat((int) evaluated.getOptionValue("verbose")).isEqualTo(1);
}
@Test
public void testUnambiguousPartialLongOption4() throws Exception {
String[] args = new String[]{"-ver=1"};
TypedOption<Integer> v = new TypedOption<Integer>().setLongName("verbose")
.setSingleValued(true)
.setType(Integer.class);
TypedOption<Boolean> h = new TypedOption<Boolean>().setLongName("help")
.setType(Boolean.class)
.setSingleValued(false);
cli.addOption(v).addOption(h);
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat((int) evaluated.getOptionValue("verbose")).isEqualTo(1);
}
@Test
public void testAmbiguousPartialLongOption1() throws Exception {
String[] args = new String[]{"--ver"};
TypedOption<Integer> v1 = new TypedOption<Integer>().setLongName("verbose")
.setSingleValued(true)
.setType(Integer.class);
TypedOption<Boolean> v2 = new TypedOption<Boolean>().setLongName("version")
.setType(Boolean.class)
.setSingleValued(false);
cli.addOption(v1).addOption(v2);
try {
cli.parse(Arrays.asList(args));
fail("Exception expected");
} catch (AmbiguousOptionException e) {
assertThat(e.getToken()).isEqualTo("--ver");
assertThat(e.getOptions()).hasSize(2);
}
}
@Test
public void testAmbiguousPartialLongOption2() throws Exception {
String[] args = new String[]{"-ver"};
TypedOption<Integer> v1 = new TypedOption<Integer>().setLongName("verbose")
.setSingleValued(true)
.setType(Integer.class);
TypedOption<Boolean> v2 = new TypedOption<Boolean>().setLongName("version").setType(Boolean.class)
.setSingleValued(false);
cli.addOption(v1).addOption(v2);
try {
cli.parse(Arrays.asList(args));
fail("Exception expected");
} catch (AmbiguousOptionException e) {
assertThat(e.getToken()).isEqualTo("-ver");
assertThat(e.getOptions()).hasSize(2);
}
}
@Test
public void testAmbiguousPartialLongOption3() throws Exception {
String[] args = new String[]{"--ver=1"};
TypedOption<Integer> v1 = new TypedOption<Integer>().setLongName("verbose")
.setSingleValued(true)
.setType(Integer.class);
TypedOption<Boolean> v2 = new TypedOption<Boolean>().setLongName("version").setType(Boolean.class)
.setSingleValued(false);
cli.addOption(v1).addOption(v2);
try {
cli.parse(Arrays.asList(args));
fail("Exception expected");
} catch (AmbiguousOptionException e) {
assertThat(e.getToken()).isEqualTo("--ver");
assertThat(e.getOptions()).hasSize(2);
}
}
@Test
public void testAmbiguousPartialLongOption4() throws Exception {
String[] args = new String[]{"-ver=1"};
TypedOption<Integer> v1 = new TypedOption<Integer>().setLongName("verbose")
.setSingleValued(true)
.setType(Integer.class);
TypedOption<Boolean> v2 = new TypedOption<Boolean>().setLongName("version").setType(Boolean.class)
.setSingleValued(false);
cli.addOption(v1).addOption(v2);
try {
cli.parse(Arrays.asList(args));
fail("Exception expected");
} catch (AmbiguousOptionException e) {
assertThat(e.getToken()).isEqualTo("-ver");
assertThat(e.getOptions()).hasSize(2);
}
}
@Test
public void testPartialLongOptionSingleDash() throws Exception {
String[] args = new String[]{"-ver"};
TypedOption<Boolean> v2 = new TypedOption<Boolean>().setLongName("version").setType(Boolean.class)
.setSingleValued(false);
TypedOption<Integer> v1 = new TypedOption<Integer>().setSingleValued(true)
.setShortName("v")
.setType(Integer.class);
cli.addOption(v1).addOption(v2);
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat((Object) evaluated.getOptionValue("v")).isNull();
assertThat((boolean) evaluated.getOptionValue("version")).isTrue();
}
@Test
public void testWithRequiredOption() throws Exception {
String[] args = new String[]{"-b", "file"};
TypedOption<String> b = new TypedOption<String>().setShortName("b").setLongName("bfile").setSingleValued(true)
.setDescription("set the value of [b]").setType(String.class).setRequired(true);
cli.removeOption("b").addOption(b);
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getBooleanOption(evaluated, "a")).isFalse();
assertThat((String) evaluated.getOptionValue("b")).isEqualTo("file");
assertThat(evaluated.allArguments()).isEmpty();
}
@Test
public void testOptionAndRequiredOption() throws Exception {
String[] args = new String[]{"-a", "-b", "file"};
TypedOption<String> b = new TypedOption<String>().setShortName("b").setLongName("bfile").setSingleValued(true)
.setDescription("set the value of [b]").setType(String.class).setRequired(true);
cli.removeOption("b").addOption(b);
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getBooleanOption(evaluated, "a")).isTrue();
assertThat(getStringOption(evaluated, "b")).isEqualTo("file");
assertThat(evaluated.allArguments()).isEmpty();
}
@Test
public void testMissingRequiredOption() throws Exception {
String[] args = new String[]{"-a"};
TypedOption<String> b = new TypedOption<String>().setShortName("b").setLongName("bfile")
.setSingleValued(true)
.setDescription("set the value of [b]").setType(String.class).setRequired(true);
cli.removeOption("b").addOption(b);
try {
cli.parse(Arrays.asList(args));
fail("exception expected");
} catch (MissingOptionException e) {
assertThat(e.getExpected()).hasSize(1);
}
}
@Test
public void testMissingRequiredOptions() throws CLIException {
String[] args = new String[]{"-a"};
TypedOption<String> b = new TypedOption<String>().setShortName("b").setLongName("bfile").setSingleValued(true)
.setDescription("set the value of [b]").setType(String.class).setRequired(true);
TypedOption<Boolean> c = new TypedOption<Boolean>().setShortName("c").setLongName("copt").setSingleValued(false)
.setDescription("turn [c] on or off").setType(Boolean.class).setRequired(true);
cli.removeOption("b").addOption(b).removeOption("c").addOption(c);
try {
CommandLine evaluated = cli.parse(Arrays.asList(args));
fail("exception expected");
} catch (MissingOptionException e) {
assertThat(e.getExpected()).hasSize(2);
}
}
@Test
public void testBursting() throws Exception {
String[] args = new String[]{"-acbtoast", "foo", "bar"};
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(getBooleanOption(evaluated, "a")).isTrue();
assertThat(getBooleanOption(evaluated, "c")).isTrue();
assertThat(getStringOption(evaluated, "b")).isEqualTo("toast");
assertThat(evaluated.allArguments()).hasSize(2).contains("foo", "bar");
}
@Test
public void testUnrecognizedOptionWithBursting() throws Exception {
String[] args = new String[]{"-adbtoast", "foo", "bar"};
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(evaluated.allArguments()).contains("-adbtoast", "foo", "bar").hasSize(3);
}
@Test
public void testMissingArgWithBursting() throws Exception {
String[] args = new String[]{"-acb"};
try {
CommandLine evaluated = cli.parse(Arrays.asList(args));
fail("exception expected");
} catch (MissingValueException e) {
assertThat(e.getOption().getShortName()).isEqualTo("b");
}
}
@Test
public void testMultiValues() throws Exception {
String[] args = new String[]{"-e", "one", "two", "-f", "1"};
TypedOption<String> e = new TypedOption<String>().setShortName("e")
.setMultiValued(true).setType(String.class);
TypedOption<Integer> f = new TypedOption<Integer>().setShortName("f")
.setMultiValued(true).setType(Integer.class);
cli.addOption(e).addOption(f);
CommandLine evaluated = cli.parse(Arrays.asList(args));
assertThat(evaluated.getOptionValues("e")).contains("one", "two").hasSize(2);
assertThat(evaluated.getOptionValues("f")).contains(1).hasSize(1);
}
}