You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2017/11/11 12:19:41 UTC
[1/2] logging-log4j2 git commit: LOG4J2-2088 Upgrade picocli to 2.0.3
from 0.9.8
Repository: logging-log4j2
Updated Branches:
refs/heads/master 7d52f131e -> 23bcd257f
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/23bcd257/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineTest.java
index 5b482a4..561ce73 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineTest.java
@@ -104,10 +104,10 @@ public class CommandLineTest {
}
@Test
public void testVersion() {
- assertEquals("2.0.0", CommandLine.VERSION);
+ assertEquals("2.0.3", CommandLine.VERSION);
}
- private static class SupportedTypes {
+ static class SupportedTypes {
@Option(names = "-boolean") boolean booleanField;
@Option(names = "-Boolean") Boolean aBooleanField;
@Option(names = "-byte") byte byteField;
@@ -362,20 +362,6 @@ public class CommandLineTest {
assertEquals(34, bean.longField);
assertEquals(Long.valueOf(34), bean.aLongField);
}
- @Test(expected = MissingParameterException.class)
- public void testSingleValueFieldDefaultMinArityIs1() {
- CommandLine.populateCommand(new SupportedTypes(), "-Long");
- }
- @Test
- public void testSingleValueFieldDefaultMinArityIsOne() {
- try {
- CommandLine.populateCommand(new SupportedTypes(), "-Long", "-boolean");
- fail("should fail");
- } catch (ParameterException ex) {
- assertEquals("Could not convert '-boolean' to Long for option '-Long'" +
- ": java.lang.NumberFormatException: For input string: \"-boolean\"", ex.getMessage());
- }
- }
@Test
public void testTimeFormatHHmmSupported() throws ParseException {
SupportedTypes bean = CommandLine.populateCommand(new SupportedTypes(), "-Time", "23:59");
@@ -535,7 +521,7 @@ public class CommandLineTest {
assertEquals(args[0], app.globField.glob);
}
- static class EnumParams {
+ private static class EnumParams {
@Option(names = "-timeUnit") TimeUnit timeUnit;
@Option(names = "-timeUnitArray", arity = "2") TimeUnit[] timeUnitArray;
@Option(names = "-timeUnitList", type = TimeUnit.class, arity = "3") List<TimeUnit> timeUnitList;
@@ -543,9 +529,9 @@ public class CommandLineTest {
@Test
public void testEnumTypeConversionSuceedsForValidInput() {
EnumParams params = CommandLine.populateCommand(new EnumParams(),
- "-timeUnit DAYS -timeUnitArray HOURS MINUTES -timeUnitList SECONDS MICROSECONDS NANOSECONDS".split(" "));
- assertEquals(DAYS, params.timeUnit);
- assertArrayEquals(new TimeUnit[]{HOURS, TimeUnit.MINUTES}, params.timeUnitArray);
+ "-timeUnit SECONDS -timeUnitArray MILLISECONDS SECONDS -timeUnitList SECONDS MICROSECONDS NANOSECONDS".split(" "));
+ assertEquals(SECONDS, params.timeUnit);
+ assertArrayEquals(new TimeUnit[]{MILLISECONDS, TimeUnit.SECONDS}, params.timeUnitArray);
List<TimeUnit> expected = new ArrayList<TimeUnit>(Arrays.asList(TimeUnit.SECONDS, TimeUnit.MICROSECONDS, TimeUnit.NANOSECONDS));
assertEquals(expected, params.timeUnitList);
}
@@ -555,17 +541,20 @@ public class CommandLineTest {
CommandLine.populateCommand(new EnumParams(), "-timeUnit", "xyz");
fail("Accepted invalid timeunit");
} catch (Exception ex) {
- assertEquals("Could not convert 'xyz' to TimeUnit for option '-timeUnit'" +
- ": java.lang.IllegalArgumentException: No enum constant java.util.concurrent.TimeUnit.xyz", ex.getMessage());
+ String prefix = "Could not convert 'xyz' to TimeUnit for option '-timeUnit'" +
+ ": java.lang.IllegalArgumentException: No enum cons";
+ String suffix = " java.util.concurrent.TimeUnit.xyz";
+ assertEquals(prefix, ex.getMessage().substring(0, prefix.length()));
+ assertEquals(suffix, ex.getMessage().substring(ex.getMessage().length() - suffix.length(), ex.getMessage().length()));
}
}
@Ignore("Requires #14 case-insensitive enum parsing")
@Test
public void testEnumTypeConversionIsCaseInsensitive() {
EnumParams params = CommandLine.populateCommand(new EnumParams(),
- "-timeUnit daYS -timeUnitArray hours miNutEs -timeUnitList SEConds MiCROsEconds nanoSEConds".split(" "));
- assertEquals(DAYS, params.timeUnit);
- assertArrayEquals(new TimeUnit[]{HOURS, TimeUnit.MINUTES}, params.timeUnitArray);
+ "-timeUnit sEcONds -timeUnitArray milliSeconds miCroSeConds -timeUnitList SEConds MiCROsEconds nanoSEConds".split(" "));
+ assertEquals(SECONDS, params.timeUnit);
+ assertArrayEquals(new TimeUnit[]{MILLISECONDS, TimeUnit.MICROSECONDS}, params.timeUnitArray);
List<TimeUnit> expected = new ArrayList<TimeUnit>(Arrays.asList(TimeUnit.SECONDS, TimeUnit.MICROSECONDS, TimeUnit.NANOSECONDS));
assertEquals(expected, params.timeUnitList);
}
@@ -575,19 +564,24 @@ public class CommandLineTest {
CommandLine.populateCommand(new EnumParams(), "-timeUnitArray", "a", "b");
fail("Accepted invalid timeunit");
} catch (Exception ex) {
- assertEquals("Could not convert 'a' to TimeUnit for option '-timeUnitArray' at index 0 (<timeUnitArray>)" +
- ": java.lang.IllegalArgumentException: No enum constant java.util.concurrent.TimeUnit.a", ex.getMessage());
+ String prefix = "Could not convert 'a' to TimeUnit for option '-timeUnitArray' at index 0 (<timeUnitArray>)" +
+ ": java.lang.IllegalArgumentException: No enum const";
+ String suffix = " java.util.concurrent.TimeUnit.a";
+ assertEquals(prefix, ex.getMessage().substring(0, prefix.length()));
+ assertEquals(suffix, ex.getMessage().substring(ex.getMessage().length() - suffix.length(), ex.getMessage().length()));
}
}
@Test
public void testEnumListTypeConversionFailsForInvalidInput() {
try {
- CommandLine.populateCommand(new EnumParams(), "-timeUnitList", "DAYS", "b", "c");
+ CommandLine.populateCommand(new EnumParams(), "-timeUnitList", "SECONDS", "b", "c");
fail("Accepted invalid timeunit");
} catch (Exception ex) {
- assertEquals("Could not convert 'b' to TimeUnit for option '-timeUnitList' at index 1 (<timeUnitList>)" +
- ": java.lang.IllegalArgumentException: No enum constant java.util.concurrent.TimeUnit.b",
- ex.getMessage());
+ String prefix = "Could not convert 'b' to TimeUnit for option '-timeUnitList' at index 1 (<timeUnitList>)" +
+ ": java.lang.IllegalArgumentException: No enum const";
+ String suffix = " java.util.concurrent.TimeUnit.b";
+ assertEquals(prefix, ex.getMessage().substring(0, prefix.length()));
+ assertEquals(suffix, ex.getMessage().substring(ex.getMessage().length() - suffix.length(), ex.getMessage().length()));
}
}
@@ -595,23 +589,23 @@ public class CommandLineTest {
public void testArrayOptionParametersAreAlwaysInstantiated() {
EnumParams params = new EnumParams();
TimeUnit[] array = params.timeUnitArray;
- new CommandLine(params).parse("-timeUnitArray", "DAYS", "HOURS");
+ new CommandLine(params).parse("-timeUnitArray", "SECONDS", "MILLISECONDS");
assertNotSame(array, params.timeUnitArray);
}
@Test
public void testListOptionParametersAreInstantiatedIfNull() {
EnumParams params = new EnumParams();
assertNull(params.timeUnitList);
- new CommandLine(params).parse("-timeUnitList", "DAYS", "HOURS", "DAYS");
- assertEquals(Arrays.asList(DAYS, HOURS, DAYS), params.timeUnitList);
+ new CommandLine(params).parse("-timeUnitList", "SECONDS", "MICROSECONDS", "MILLISECONDS");
+ assertEquals(Arrays.asList(SECONDS, MICROSECONDS, MILLISECONDS), params.timeUnitList);
}
@Test
public void testListOptionParametersAreReusedInstantiatedIfNonNull() {
EnumParams params = new EnumParams();
List<TimeUnit> list = new ArrayList<TimeUnit>();
params.timeUnitList = list;
- new CommandLine(params).parse("-timeUnitList", "DAYS", "HOURS", "DAYS");
- assertEquals(Arrays.asList(DAYS, HOURS, DAYS), params.timeUnitList);
+ new CommandLine(params).parse("-timeUnitList", "SECONDS", "MICROSECONDS", "SECONDS");
+ assertEquals(Arrays.asList(SECONDS, MICROSECONDS, SECONDS), params.timeUnitList);
assertSame(list, params.timeUnitList);
}
@Test
@@ -626,7 +620,7 @@ public class CommandLineTest {
assertNotSame(array, params.array);
assertArrayEquals(new int[]{0, 0, 0, 3, 2, 1}, params.array);
}
- class ListPositionalParams {
+ private class ListPositionalParams {
@Parameters(type = Integer.class) List<Integer> list;
}
@Test
@@ -894,134 +888,6 @@ public class CommandLineTest {
assertFalse("version info requested", parsedCommands.get(0).isVersionHelpRequested());
}
@Test
- public void testMissingRequiredParams() {
- class Example {
- @Parameters(index = "1", arity = "0..1") String optional;
- @Parameters(index = "0") String mandatory;
- }
- try { CommandLine.populateCommand(new Example(), new String[] {"mandatory"}); }
- catch (MissingParameterException ex) { fail(); }
-
- try {
- CommandLine.populateCommand(new Example(), new String[0]);
- fail("Should not accept missing mandatory parameter");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameter: <mandatory>", ex.getMessage());
- }
- }
- @Test
- public void testMissingRequiredParams1() {
- class Tricky1 {
- @Parameters(index = "2") String anotherMandatory;
- @Parameters(index = "1", arity = "0..1") String optional;
- @Parameters(index = "0") String mandatory;
- }
- try {
- CommandLine.populateCommand(new Tricky1(), new String[0]);
- fail("Should not accept missing mandatory parameter");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameters: <mandatory>, <anotherMandatory>", ex.getMessage());
- }
- try {
- CommandLine.populateCommand(new Tricky1(), new String[] {"firstonly"});
- fail("Should not accept missing mandatory parameter");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameter: <anotherMandatory>", ex.getMessage());
- }
- }
- @Test
- public void testMissingRequiredParams2() {
- class Tricky2 {
- @Parameters(index = "2", arity = "0..1") String anotherOptional;
- @Parameters(index = "1", arity = "0..1") String optional;
- @Parameters(index = "0") String mandatory;
- }
- try { CommandLine.populateCommand(new Tricky2(), new String[] {"mandatory"}); }
- catch (MissingParameterException ex) { fail(); }
-
- try {
- CommandLine.populateCommand(new Tricky2(), new String[0]);
- fail("Should not accept missing mandatory parameter");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameter: <mandatory>", ex.getMessage());
- }
- }
- @Test
- public void testMissingRequiredParamsWithOptions() {
- class Tricky3 {
- @Option(names="-v") boolean more;
- @Option(names="-t") boolean any;
- @Parameters(index = "1") String alsoMandatory;
- @Parameters(index = "0") String mandatory;
- }
- try {
- CommandLine.populateCommand(new Tricky3(), new String[] {"-t", "-v", "mandatory"});
- fail("Should not accept missing mandatory parameter");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameter: <alsoMandatory>", ex.getMessage());
- }
-
- try {
- CommandLine.populateCommand(new Tricky3(), new String[] { "-t", "-v"});
- fail("Should not accept missing two mandatory parameters");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameters: <mandatory>, <alsoMandatory>", ex.getMessage());
- }
- }
- @Test
- public void testMissingRequiredParamWithOption() {
- class Tricky3 {
- @Option(names="-t") boolean any;
- @Parameters(index = "0") String mandatory;
- }
- try {
- CommandLine.populateCommand(new Tricky3(), new String[] {"-t"});
- fail("Should not accept missing mandatory parameter");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameter: <mandatory>", ex.getMessage());
- }
- }
- @Test
- public void testNoMissingRequiredParamErrorIfHelpOptionSpecified() {
- class App {
- @Parameters(hidden = true) // "hidden": don't show this parameter in usage help message
- List<String> allParameters; // no "index" attribute: captures _all_ arguments (as Strings)
-
- @Parameters(index = "0") InetAddress host;
- @Parameters(index = "1") int port;
- @Parameters(index = "2..*") File[] files;
-
- @Option(names = "-?", help = true) boolean help;
- }
- CommandLine.populateCommand(new App(), new String[] {"-?"});
- try {
- CommandLine.populateCommand(new App(), new String[0]);
- fail("Should not accept missing mandatory parameter");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameters: <host>, <port>", ex.getMessage());
- }
- }
- @Test
- public void testNoMissingRequiredParamErrorWithLabelIfHelpOptionSpecified() {
- class App {
- @Parameters(hidden = true) // "hidden": don't show this parameter in usage help message
- List<String> allParameters; // no "index" attribute: captures _all_ arguments (as Strings)
-
- @Parameters(index = "0", paramLabel = "HOST") InetAddress host;
- @Parameters(index = "1", paramLabel = "PORT") int port;
- @Parameters(index = "2..*", paramLabel = "FILES") File[] files;
-
- @Option(names = "-?", help = true) boolean help;
- }
- CommandLine.populateCommand(new App(), new String[] {"-?"});
- try {
- CommandLine.populateCommand(new App(), new String[0]);
- fail("Should not accept missing mandatory parameter");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameters: HOST, PORT", ex.getMessage());
- }
- }
- @Test
public void testHelpRequestedFlagResetWhenParsing_staticMethod() {
RequiredField requiredField = CommandLine.populateCommand(new RequiredField(), "-?");
assertTrue("help requested", requiredField.isHelpRequested);
@@ -1090,6 +956,9 @@ public class CommandLineTest {
compact = CommandLine.populateCommand(new CompactFields(), "-r -v -oout p1 p2".split(" "));
verifyCompact(compact, true, true, "out", fileArray("p1", "p2"));
+ compact = CommandLine.populateCommand(new CompactFields(), "-rv -o out p1 p2".split(" ")); //#233
+ verifyCompact(compact, true, true, "out", fileArray("p1", "p2"));
+
compact = CommandLine.populateCommand(new CompactFields(), "-oout -r -v p1 p2".split(" "));
verifyCompact(compact, true, true, "out", fileArray("p1", "p2"));
@@ -1147,7 +1016,7 @@ public class CommandLineTest {
@Test
public void testShortOptionsWithSeparatorButNoValueAssignsEmptyStringEvenIfNotLast() {
CompactFields compact = CommandLine.populateCommand(new CompactFields(), "-ro= -v".split(" "));
- verifyCompact(compact, true, true, "", null);
+ verifyCompact(compact, false, true, "-v", null);
}
@Test
public void testShortOptionsWithColonSeparatorButNoValueAssignsEmptyStringEvenIfNotLast() {
@@ -1155,11 +1024,33 @@ public class CommandLineTest {
CommandLine cmd = new CommandLine(compact);
cmd.setSeparator(":");
cmd.parse("-ro: -v".split(" "));
+ verifyCompact(compact, false, true, "-v", null);
+ }
+ @Test
+ public void testShortOptionsWithSeparatorButNoValueFailsIfValueRequired() {
+ try {
+ CommandLine.populateCommand(new CompactFields(), "-rvo=".split(" "));
+ fail("Expected exception");
+ } catch (ParameterException ex) {
+ assertEquals("Missing required parameter for option '-o' (<outputFile>)", ex.getMessage());
+ }
+ }
+ @Test
+ public void testShortOptionsWithSeparatorButNoValueAssignsQuotedEmptyStringEvenIfNotLast() {
+ CompactFields compact = CommandLine.populateCommand(new CompactFields(), "-ro=\"\" -v".split(" "));
verifyCompact(compact, true, true, "", null);
}
@Test
- public void testShortOptionsWithSeparatorButNoValueAssignsEmptyStringIfLast() {
- CompactFields compact = CommandLine.populateCommand(new CompactFields(), "-rvo=".split(" "));
+ public void testShortOptionsWithColonSeparatorButNoValueAssignsQuotedEmptyStringEvenIfNotLast() {
+ CompactFields compact = new CompactFields();
+ CommandLine cmd = new CommandLine(compact);
+ cmd.setSeparator(":");
+ cmd.parse("-ro:\"\" -v".split(" "));
+ verifyCompact(compact, true, true, "", null);
+ }
+ @Test
+ public void testShortOptionsWithSeparatorButNoValueAssignsEmptyQuotedStringIfLast() {
+ CompactFields compact = CommandLine.populateCommand(new CompactFields(), "-rvo=\"\"".split(" "));
verifyCompact(compact, true, true, "", null);
}
@@ -1197,19 +1088,19 @@ public class CommandLineTest {
"[picocli INFO] Found end-of-options delimiter '--'. Treating remainder as positional parameters.%n" +
"[picocli DEBUG] Processing next arg as a positional parameter at index=0. Remainder=[-r, -v, p1, p2]%n" +
"[picocli DEBUG] Position 0 is in index range 0..*. Trying to assign args to java.io.File[] %1$s$CompactFields.inputFiles, arity=0..1%n" +
- "[picocli INFO] Adding [-r] to File[] field 'CompactFields.inputFiles' for args[0..*]%n" +
+ "[picocli INFO] Adding [-r] to File[] field 'CompactFields.inputFiles' for args[0..*] at position 0%n" +
"[picocli DEBUG] Consumed 1 arguments, moving position to index 1.%n" +
"[picocli DEBUG] Processing next arg as a positional parameter at index=1. Remainder=[-v, p1, p2]%n" +
"[picocli DEBUG] Position 1 is in index range 0..*. Trying to assign args to java.io.File[] %1$s$CompactFields.inputFiles, arity=0..1%n" +
- "[picocli INFO] Adding [-v] to File[] field 'CompactFields.inputFiles' for args[0..*]%n" +
+ "[picocli INFO] Adding [-v] to File[] field 'CompactFields.inputFiles' for args[0..*] at position 1%n" +
"[picocli DEBUG] Consumed 1 arguments, moving position to index 2.%n" +
"[picocli DEBUG] Processing next arg as a positional parameter at index=2. Remainder=[p1, p2]%n" +
"[picocli DEBUG] Position 2 is in index range 0..*. Trying to assign args to java.io.File[] %1$s$CompactFields.inputFiles, arity=0..1%n" +
- "[picocli INFO] Adding [p1] to File[] field 'CompactFields.inputFiles' for args[0..*]%n" +
+ "[picocli INFO] Adding [p1] to File[] field 'CompactFields.inputFiles' for args[0..*] at position 2%n" +
"[picocli DEBUG] Consumed 1 arguments, moving position to index 3.%n" +
"[picocli DEBUG] Processing next arg as a positional parameter at index=3. Remainder=[p2]%n" +
"[picocli DEBUG] Position 3 is in index range 0..*. Trying to assign args to java.io.File[] %1$s$CompactFields.inputFiles, arity=0..1%n" +
- "[picocli INFO] Adding [p2] to File[] field 'CompactFields.inputFiles' for args[0..*]%n" +
+ "[picocli INFO] Adding [p2] to File[] field 'CompactFields.inputFiles' for args[0..*] at position 3%n" +
"[picocli DEBUG] Consumed 1 arguments, moving position to index 4.%n",
CommandLineTest.class.getName(), new File("/home/rpopma/picocli"));
String actual = new String(baos.toByteArray(), "UTF8");
@@ -1254,461 +1145,6 @@ public class CommandLineTest {
assertArrayEquals(new int[] {1, 2, 3, 4}, params.intParams);
}
- @Test
- public void testArityConstructor_fixedRange() {
- Range arity = new Range(1, 23, false, false, null);
- assertEquals("min", 1, arity.min);
- assertEquals("max", 23, arity.max);
- assertEquals("1..23", arity.toString());
- assertEquals(Range.valueOf("1..23"), arity);
- }
- @Test
- public void testArityConstructor_variableRange() {
- Range arity = new Range(1, Integer.MAX_VALUE, true, false, null);
- assertEquals("min", 1, arity.min);
- assertEquals("max", Integer.MAX_VALUE, arity.max);
- assertEquals("1..*", arity.toString());
- assertEquals(Range.valueOf("1..*"), arity);
- }
- @Test
- public void testArityForOption_booleanFieldImplicitArity0() throws Exception {
- Range arity = Range.optionArity(SupportedTypes.class.getDeclaredField("booleanField"));
- assertEquals(Range.valueOf("0"), arity);
- assertEquals("0", arity.toString());
- }
- @Test
- public void testArityForOption_intFieldImplicitArity1() throws Exception {
- Range arity = Range.optionArity(SupportedTypes.class.getDeclaredField("intField"));
- assertEquals(Range.valueOf("1"), arity);
- assertEquals("1", arity.toString());
- }
- @Test
- public void testArityForOption_isExplicitlyDeclaredValue() throws Exception {
- Range arity = Range.optionArity(EnumParams.class.getDeclaredField("timeUnitList"));
- assertEquals(Range.valueOf("3"), arity);
- assertEquals("3", arity.toString());
- }
- @Test
- public void testArityForOption_listFieldImplicitArity1() throws Exception {
- class ImplicitList { @Option(names = "-a") List<Integer> listIntegers; }
- Range arity = Range.optionArity(ImplicitList.class.getDeclaredField("listIntegers"));
- assertEquals(Range.valueOf("1"), arity);
- assertEquals("1", arity.toString());
- }
- @Test
- public void testArityForOption_arrayFieldImplicitArity1() throws Exception {
- class ImplicitList { @Option(names = "-a") int[] intArray; }
- Range arity = Range.optionArity(ImplicitList.class.getDeclaredField("intArray"));
- assertEquals(Range.valueOf("1"), arity);
- assertEquals("1", arity.toString());
- }
- @Test
- public void testArityForParameters_booleanFieldImplicitArity1() throws Exception {
- class ImplicitBoolField { @Parameters boolean boolSingleValue; }
- Range arity = Range.parameterArity(ImplicitBoolField.class.getDeclaredField("boolSingleValue"));
- assertEquals(Range.valueOf("1"), arity);
- assertEquals("1", arity.toString());
- }
- @Test
- public void testArityForParameters_intFieldImplicitArity1() throws Exception {
- class ImplicitSingleField { @Parameters int intSingleValue; }
- Range arity = Range.parameterArity(ImplicitSingleField.class.getDeclaredField("intSingleValue"));
- assertEquals(Range.valueOf("1"), arity);
- assertEquals("1", arity.toString());
- }
- @Test
- public void testArityForParameters_listFieldImplicitArity0_1() throws Exception {
- Range arity = Range.parameterArity(ListPositionalParams.class.getDeclaredField("list"));
- assertEquals(Range.valueOf("0..1"), arity);
- assertEquals("0..1", arity.toString());
- }
- @Test
- public void testArityForParameters_arrayFieldImplicitArity0_1() throws Exception {
- Range arity = Range.parameterArity(CompactFields.class.getDeclaredField("inputFiles"));
- assertEquals(Range.valueOf("0..1"), arity);
- assertEquals("0..1", arity.toString());
- }
- @Test
- public void testArrayOptionsWithArity0_nConsumeAllArguments() {
- final double[] DEFAULT_PARAMS = new double[] {1, 2};
- class ArrayOptionsArity0_nAndParameters {
- @Parameters double[] doubleParams = DEFAULT_PARAMS;
- @Option(names = "-doubles", arity = "0..*") double[] doubleOptions;
- }
- ArrayOptionsArity0_nAndParameters
- params = CommandLine.populateCommand(new ArrayOptionsArity0_nAndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[] {1.1, 2.2, 3.3, 4.4}, params.doubleOptions, 0.000001);
- assertArrayEquals(DEFAULT_PARAMS, params.doubleParams, 0.000001);
- }
-
- @Test
- public void testArrayOptionsWithArity1_nConsumeAllArguments() {
- class ArrayOptionsArity1_nAndParameters {
- @Parameters double[] doubleParams;
- @Option(names = "-doubles", arity = "1..*") double[] doubleOptions;
- }
- ArrayOptionsArity1_nAndParameters
- params = CommandLine.populateCommand(new ArrayOptionsArity1_nAndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[] {1.1, 2.2, 3.3, 4.4}, params.doubleOptions, 0.000001);
- assertArrayEquals(null, params.doubleParams, 0.000001);
- }
-
- @Test
- public void testArrayOptionsWithArity2_nConsumeAllArguments() {
- class ArrayOptionsArity2_nAndParameters {
- @Parameters double[] doubleParams;
- @Option(names = "-doubles", arity = "2..*") double[] doubleOptions;
- }
- ArrayOptionsArity2_nAndParameters
- params = CommandLine.populateCommand(new ArrayOptionsArity2_nAndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[] {1.1, 2.2, 3.3, 4.4}, params.doubleOptions, 0.000001);
- assertArrayEquals(null, params.doubleParams, 0.000001);
- }
-
- @Test
- public void testArrayOptionArity2_nConsumesAllArgumentsUpToClusteredOption() {
- class ArrayOptionsArity2_nAndParameters {
- @Parameters String[] stringParams;
- @Option(names = "-s", arity = "2..*") String[] stringOptions;
- @Option(names = "-v") boolean verbose;
- @Option(names = "-f") File file;
- }
- ArrayOptionsArity2_nAndParameters
- params = CommandLine.populateCommand(new ArrayOptionsArity2_nAndParameters(), "-s 1.1 2.2 3.3 4.4 -vfFILE 5.5".split(" "));
- assertArrayEquals(Arrays.toString(params.stringOptions),
- new String[] {"1.1", "2.2", "3.3", "4.4"}, params.stringOptions);
- assertTrue(params.verbose);
- assertEquals(new File("FILE"), params.file);
- assertArrayEquals(new String[] {"5.5"}, params.stringParams);
- }
-
- @Test
- public void testArrayOptionArity2_nConsumesAllArgumentIncludingQuotedSimpleOption() {
- class ArrayOptionArity2_nAndParameters {
- @Parameters String[] stringParams;
- @Option(names = "-s", arity = "2..*") String[] stringOptions;
- @Option(names = "-v") boolean verbose;
- @Option(names = "-f") File file;
- }
- ArrayOptionArity2_nAndParameters
- params = CommandLine.populateCommand(new ArrayOptionArity2_nAndParameters(), "-s 1.1 2.2 3.3 4.4 \"-v\" \"-f\" \"FILE\" 5.5".split(" "));
- assertArrayEquals(Arrays.toString(params.stringOptions),
- new String[] {"1.1", "2.2", "3.3", "4.4", "-v", "-f", "FILE", "5.5"}, params.stringOptions);
- assertFalse("verbose", params.verbose);
- assertNull("file", params.file);
- assertArrayEquals(null, params.stringParams);
- }
-
- @Test
- public void testArrayOptionArity2_nConsumesAllArgumentIncludingQuotedClusteredOption() {
- class ArrayOptionArity2_nAndParameters {
- @Parameters String[] stringParams;
- @Option(names = "-s", arity = "2..*") String[] stringOptions;
- @Option(names = "-v") boolean verbose;
- @Option(names = "-f") File file;
- }
- ArrayOptionArity2_nAndParameters
- params = CommandLine.populateCommand(new ArrayOptionArity2_nAndParameters(), "-s 1.1 2.2 3.3 4.4 \"-vfFILE\" 5.5".split(" "));
- assertArrayEquals(Arrays.toString(params.stringOptions),
- new String[] {"1.1", "2.2", "3.3", "4.4", "-vfFILE", "5.5"}, params.stringOptions);
- assertFalse("verbose", params.verbose);
- assertNull("file", params.file);
- assertArrayEquals(null, params.stringParams);
- }
-
- @Test
- public void testArrayOptionArity2_nConsumesAllArgumentsUpToNextSimpleOption() {
- class ArrayOptionArity2_nAndParameters {
- @Parameters double[] doubleParams;
- @Option(names = "-s", arity = "2..*") String[] stringOptions;
- @Option(names = "-v") boolean verbose;
- @Option(names = "-f") File file;
- }
- ArrayOptionArity2_nAndParameters
- params = CommandLine.populateCommand(new ArrayOptionArity2_nAndParameters(), "-s 1.1 2.2 3.3 4.4 -v -f=FILE 5.5".split(" "));
- assertArrayEquals(Arrays.toString(params.stringOptions),
- new String[] {"1.1", "2.2", "3.3", "4.4"}, params.stringOptions);
- assertTrue(params.verbose);
- assertEquals(new File("FILE"), params.file);
- assertArrayEquals(new double[] {5.5}, params.doubleParams, 0.000001);
- }
-
- @Test
- public void testArrayOptionArity2_nConsumesAllArgumentsUpToNextOptionWithAttachment() {
- class ArrayOptionArity2_nAndParameters {
- @Parameters double[] doubleParams;
- @Option(names = "-s", arity = "2..*") String[] stringOptions;
- @Option(names = "-v") boolean verbose;
- @Option(names = "-f") File file;
- }
- ArrayOptionArity2_nAndParameters
- params = CommandLine.populateCommand(new ArrayOptionArity2_nAndParameters(), "-s 1.1 2.2 3.3 4.4 -f=FILE -v 5.5".split(" "));
- assertArrayEquals(Arrays.toString(params.stringOptions),
- new String[] {"1.1", "2.2", "3.3", "4.4"}, params.stringOptions);
- assertTrue(params.verbose);
- assertEquals(new File("FILE"), params.file);
- assertArrayEquals(new double[] {5.5}, params.doubleParams, 0.000001);
- }
-
- @Test
- public void testArrayOptionArityNConsumeAllArguments() {
- class ArrayOptionArityNAndParameters {
- @Parameters char[] charParams;
- @Option(names = "-chars", arity = "*") char[] charOptions;
- }
- ArrayOptionArityNAndParameters
- params = CommandLine.populateCommand(new ArrayOptionArityNAndParameters(), "-chars a b c d".split(" "));
- assertArrayEquals(Arrays.toString(params.charOptions),
- new char[] {'a', 'b', 'c', 'd'}, params.charOptions);
- assertArrayEquals(null, params.charParams);
- }
-
- private static class BooleanOptionsArity0_nAndParameters {
- @Parameters String[] params;
- @Option(names = "-bool", arity = "0..*") boolean bool;
- @Option(names = {"-v", "-other"}, arity="0..*") boolean vOrOther;
- @Option(names = "-r") boolean rBoolean;
- }
- @Test
- public void testBooleanOptionsArity0_nConsume1ArgumentIfPossible() { // ignores varargs
- BooleanOptionsArity0_nAndParameters
- params = CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-bool false false true".split(" "));
- assertFalse(params.bool);
- assertArrayEquals(new String[]{ "false", "true"}, params.params);
- }
- @Test
- public void testBooleanOptionsArity0_nRequiresNoArgument() { // ignores varargs
- BooleanOptionsArity0_nAndParameters
- params = CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-bool".split(" "));
- assertTrue(params.bool);
- }
- @Test
- public void testBooleanOptionsArity0_nConsume0ArgumentsIfNextArgIsOption() { // ignores varargs
- BooleanOptionsArity0_nAndParameters
- params = CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-bool -other".split(" "));
- assertTrue(params.bool);
- assertTrue(params.vOrOther);
- }
- @Test
- public void testBooleanOptionsArity0_nConsume0ArgumentsIfNextArgIsParameter() { // ignores varargs
- BooleanOptionsArity0_nAndParameters
- params = CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-bool 123 -other".split(" "));
- assertTrue(params.bool);
- assertTrue(params.vOrOther);
- assertArrayEquals(new String[]{ "123"}, params.params);
- }
- @Test
- public void testBooleanOptionsArity0_nFailsIfAttachedParamNotABoolean() { // ignores varargs
- try {
- CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-bool=123 -other".split(" "));
- fail("was able to assign 123 to boolean");
- } catch (ParameterException ex) {
- assertEquals("'123' is not a boolean for option '-bool'", ex.getMessage());
- }
- }
- @Test
- public void testBooleanOptionsArity0_nShortFormFailsIfAttachedParamNotABoolean() { // ignores varargs
- try {
- CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-rv234 -bool".split(" "));
- fail("Expected exception");
- } catch (UnmatchedArgumentException ok) {
- assertEquals("Unmatched argument [-234]", ok.getMessage());
- }
- }
- @Test
- public void testBooleanOptionsArity0_nShortFormFailsIfAttachedParamNotABooleanWithUnmatchedArgsAllowed() { // ignores varargs
- setTraceLevel("OFF");
- CommandLine cmd = new CommandLine(new BooleanOptionsArity0_nAndParameters()).setUnmatchedArgumentsAllowed(true);
- cmd.parse("-rv234 -bool".split(" "));
- assertEquals(Arrays.asList("-234"), cmd.getUnmatchedArguments());
- }
- @Test
- public void testBooleanOptionsArity0_nShortFormFailsIfAttachedWithSepParamNotABoolean() { // ignores varargs
- try {
- CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-rv=234 -bool".split(" "));
- fail("was able to assign 234 to boolean");
- } catch (ParameterException ex) {
- assertEquals("'234' is not a boolean for option '-v'", ex.getMessage());
- }
- }
-
- private static class BooleanOptionsArity1_nAndParameters {
- @Parameters boolean[] boolParams;
- @Option(names = "-bool", arity = "1..*") boolean aBoolean;
- }
- @Test
- public void testBooleanOptionsArity1_nConsume1Argument() { // ignores varargs
- BooleanOptionsArity1_nAndParameters
- params = CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool false false true".split(" "));
- assertFalse(params.aBoolean);
- assertArrayEquals(new boolean[]{ false, true}, params.boolParams);
-
- params = CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool true false true".split(" "));
- assertTrue(params.aBoolean);
- assertArrayEquals(new boolean[]{ false, true}, params.boolParams);
- }
- @Test
- public void testBooleanOptionsArity1_nCaseInsensitive() { // ignores varargs
- BooleanOptionsArity1_nAndParameters
- params = CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool fAlsE false true".split(" "));
- assertFalse(params.aBoolean);
- assertArrayEquals(new boolean[]{ false, true}, params.boolParams);
-
- params = CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool FaLsE false true".split(" "));
- assertFalse(params.aBoolean);
- assertArrayEquals(new boolean[]{ false, true}, params.boolParams);
-
- params = CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool tRuE false true".split(" "));
- assertTrue(params.aBoolean);
- assertArrayEquals(new boolean[]{ false, true}, params.boolParams);
- }
- @Test
- public void testBooleanOptionsArity1_nErrorIfValueNotTrueOrFalse() { // ignores varargs
- try {
- CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool abc".split(" "));
- fail("Invalid format abc was accepted for boolean");
- } catch (ParameterException expected) {
- assertEquals("'abc' is not a boolean for option '-bool'", expected.getMessage());
- }
- }
- @Test
- public void testBooleanOptionsArity1_nErrorIfValueMissing() {
- try {
- CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool".split(" "));
- fail("Missing param was accepted for boolean with arity=1");
- } catch (ParameterException expected) {
- assertEquals("Missing required parameter for option '-bool' at index 0 (<aBoolean>)", expected.getMessage());
- }
- }
-
- @Test
- public void testBooleanOptionArity0Consumes0Arguments() {
- class BooleanOptionArity0AndParameters {
- @Parameters boolean[] boolParams;
- @Option(names = "-bool", arity = "0") boolean aBoolean;
- }
- BooleanOptionArity0AndParameters
- params = CommandLine.populateCommand(new BooleanOptionArity0AndParameters(), "-bool true false true".split(" "));
- assertTrue(params.aBoolean);
- assertArrayEquals(new boolean[]{true, false, true}, params.boolParams);
- }
-
- @Test
- public void testIntOptionArity1_nConsumes1Argument() { // ignores varargs
- class IntOptionArity1_nAndParameters {
- @Parameters int[] intParams;
- @Option(names = "-int", arity = "1..*") int anInt;
- }
- IntOptionArity1_nAndParameters
- params = CommandLine.populateCommand(new IntOptionArity1_nAndParameters(), "-int 23 42 7".split(" "));
- assertEquals(23, params.anInt);
- assertArrayEquals(new int[]{ 42, 7}, params.intParams);
- }
-
- @Test
- public void testArrayOptionsWithArity0Consume0Arguments() {
- class OptionsArray0ArityAndParameters {
- @Parameters double[] doubleParams;
- @Option(names = "-doubles", arity = "0") double[] doubleOptions;
- }
- OptionsArray0ArityAndParameters
- params = CommandLine.populateCommand(new OptionsArray0ArityAndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[0], params.doubleOptions, 0.000001);
- assertArrayEquals(new double[]{1.1, 2.2, 3.3, 4.4}, params.doubleParams, 0.000001);
- }
-
- @Test
- public void testArrayOptionWithArity1Consumes1Argument() {
- class Options1ArityAndParameters {
- @Parameters double[] doubleParams;
- @Option(names = "-doubles", arity = "1") double[] doubleOptions;
- }
- Options1ArityAndParameters
- params = CommandLine.populateCommand(new Options1ArityAndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[] {1.1}, params.doubleOptions, 0.000001);
- assertArrayEquals(new double[]{2.2, 3.3, 4.4}, params.doubleParams, 0.000001);
-
- // repeated occurrence
- params = CommandLine.populateCommand(new Options1ArityAndParameters(), "-doubles 1.1 -doubles 2.2 -doubles 3.3 4.4".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[] {1.1, 2.2, 3.3}, params.doubleOptions, 0.000001);
- assertArrayEquals(new double[]{4.4}, params.doubleParams, 0.000001);
-
- }
-
- private static class ArrayOptionArity2AndParameters {
- @Parameters double[] doubleParams;
- @Option(names = "-doubles", arity = "2") double[] doubleOptions;
- }
- @Test
- public void testArrayOptionWithArity2Consumes2Arguments() {
- ArrayOptionArity2AndParameters
- params = CommandLine.populateCommand(new ArrayOptionArity2AndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[] {1.1, 2.2, }, params.doubleOptions, 0.000001);
- assertArrayEquals(new double[]{3.3, 4.4}, params.doubleParams, 0.000001);
-
- // repeated occurrence
- params = CommandLine.populateCommand(new ArrayOptionArity2AndParameters(), "-doubles 1.1 2.2 -doubles 3.3 4.4 0".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[] {1.1, 2.2, 3.3, 4.4 }, params.doubleOptions, 0.000001);
- assertArrayEquals(new double[]{ 0.0 }, params.doubleParams, 0.000001);
- }
- @Test
- public void testArrayOptionsWithArity2Consume2ArgumentsEvenIfFirstIsAttached() {
- ArrayOptionArity2AndParameters
- params = CommandLine.populateCommand(new ArrayOptionArity2AndParameters(), "-doubles=1.1 2.2 3.3 4.4".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[] {1.1, 2.2, }, params.doubleOptions, 0.000001);
- assertArrayEquals(new double[]{3.3, 4.4}, params.doubleParams, 0.000001);
-
- // repeated occurrence
- params = CommandLine.populateCommand(new ArrayOptionArity2AndParameters(), "-doubles=1.1 2.2 -doubles=3.3 4.4 0".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[] {1.1, 2.2, 3.3, 4.4}, params.doubleOptions, 0.000001);
- assertArrayEquals(new double[]{0}, params.doubleParams, 0.000001);
- }
- /** Arity should not limit the total number of values put in an array or collection #191 */
- @Test
- public void testArrayOptionsWithArity2MayContainMoreThan2Values() {
- ArrayOptionArity2AndParameters
- params = CommandLine.populateCommand(new ArrayOptionArity2AndParameters(), "-doubles=1 2 -doubles 3 4 -doubles 5 6".split(" "));
- assertArrayEquals(Arrays.toString(params.doubleOptions),
- new double[] {1, 2, 3, 4, 5, 6 }, params.doubleOptions, 0.000001);
- assertArrayEquals(null, params.doubleParams, 0.000001);
- }
-
- @Test
- public void testArrayOptionWithoutArityConsumesOneArgument() { // #192
- class OptionsNoArityAndParameters {
- @Parameters char[] charParams;
- @Option(names = "-chars") char[] charOptions;
- }
- OptionsNoArityAndParameters
- params = CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars a b c d".split(" "));
- assertArrayEquals(Arrays.toString(params.charOptions),
- new char[] {'a', }, params.charOptions);
- assertArrayEquals(Arrays.toString(params.charParams), new char[] {'b', 'c', 'd'}, params.charParams);
-
- // repeated occurrence
- params = CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars a -chars b c d".split(" "));
- assertArrayEquals(Arrays.toString(params.charOptions),
- new char[] {'a', 'b', }, params.charOptions);
- assertArrayEquals(Arrays.toString(params.charParams), new char[] {'c', 'd'}, params.charParams);
-
- try {
- CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars".split(" "));
- fail("expected MissingParameterException");
- } catch (MissingParameterException ok) {
- assertEquals("Missing required parameter for option '-chars' (<charOptions>)", ok.getMessage());
- }
- }
-
@Test(expected = MissingTypeConverterException.class)
public void testMissingTypeConverter() {
class MissingConverter {
@@ -1718,191 +1154,6 @@ public class CommandLineTest {
}
@Test
- public void testArrayParametersWithDefaultArity() {
- class ArrayParamsDefaultArity {
- @Parameters
- List<String> params;
- }
- ArrayParamsDefaultArity params = CommandLine.populateCommand(new ArrayParamsDefaultArity(), "a", "b", "c");
- assertEquals(Arrays.asList("a", "b", "c"), params.params);
-
- params = CommandLine.populateCommand(new ArrayParamsDefaultArity(), "a");
- assertEquals(Arrays.asList("a"), params.params);
-
- params = CommandLine.populateCommand(new ArrayParamsDefaultArity());
- assertEquals(null, params.params);
- }
-
- @Test
- public void testArrayParametersWithArityMinusOneToN() {
- class ArrayParamsNegativeArity {
- @Parameters(arity = "-1..*")
- List<String> params;
- }
- ArrayParamsNegativeArity params = CommandLine.populateCommand(new ArrayParamsNegativeArity(), "a", "b", "c");
- assertEquals(Arrays.asList("a", "b", "c"), params.params);
-
- params = CommandLine.populateCommand(new ArrayParamsNegativeArity(), "a");
- assertEquals(Arrays.asList("a"), params.params);
-
- params = CommandLine.populateCommand(new ArrayParamsNegativeArity());
- assertEquals(null, params.params);
- }
-
- @Test
- public void testArrayParametersArity0_n() {
- class ArrayParamsArity0_n {
- @Parameters(arity = "0..*")
- List<String> params;
- }
- ArrayParamsArity0_n params = CommandLine.populateCommand(new ArrayParamsArity0_n(), "a", "b", "c");
- assertEquals(Arrays.asList("a", "b", "c"), params.params);
-
- params = CommandLine.populateCommand(new ArrayParamsArity0_n(), "a");
- assertEquals(Arrays.asList("a"), params.params);
-
- params = CommandLine.populateCommand(new ArrayParamsArity0_n());
- assertEquals(null, params.params);
- }
-
- @Test
- public void testArrayParametersArity1_n() {
- class ArrayParamsArity1_n {
- @Parameters(arity = "1..*")
- List<String> params;
- }
- ArrayParamsArity1_n params = CommandLine.populateCommand(new ArrayParamsArity1_n(), "a", "b", "c");
- assertEquals(Arrays.asList("a", "b", "c"), params.params);
-
- params = CommandLine.populateCommand(new ArrayParamsArity1_n(), "a");
- assertEquals(Arrays.asList("a"), params.params);
-
- try {
- params = CommandLine.populateCommand(new ArrayParamsArity1_n());
- fail("Should not accept input with missing parameter");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameters at positions 0..*: <params>", ex.getMessage());
- }
- }
-
- @Test
- public void testArrayParametersArity2_n() {
- class ArrayParamsArity2_n {
- @Parameters(arity = "2..*")
- List<String> params;
- }
- ArrayParamsArity2_n params = CommandLine.populateCommand(new ArrayParamsArity2_n(), "a", "b", "c");
- assertEquals(Arrays.asList("a", "b", "c"), params.params);
-
- try {
- params = CommandLine.populateCommand(new ArrayParamsArity2_n(), "a");
- fail("Should not accept input with missing parameter");
- } catch (MissingParameterException ex) {
- assertEquals("positional parameter at index 0..* (<params>) requires at least 2 values, but only 1 were specified: [a]", ex.getMessage());
- }
-
- try {
- params = CommandLine.populateCommand(new ArrayParamsArity2_n());
- fail("Should not accept input with missing parameter");
- } catch (MissingParameterException ex) {
- assertEquals("positional parameter at index 0..* (<params>) requires at least 2 values, but none were specified.", ex.getMessage());
- }
- }
-
- @Test
- public void testNonVarargArrayParametersWithNegativeArityConsumesZeroArguments() {
- class NonVarArgArrayParamsNegativeArity {
- @Parameters(arity = "-1")
- List<String> params;
- }
- try {
- CommandLine.populateCommand(new NonVarArgArrayParamsNegativeArity(), "a", "b", "c");
- fail("Expected UnmatchedArgumentException");
- } catch (UnmatchedArgumentException ex) {
- assertEquals("Unmatched arguments [a, b, c]", ex.getMessage());
- }
- try {
- CommandLine.populateCommand(new NonVarArgArrayParamsNegativeArity(), "a");
- fail("Expected UnmatchedArgumentException");
- } catch (UnmatchedArgumentException ex) {
- assertEquals("Unmatched argument [a]", ex.getMessage());
- }
- NonVarArgArrayParamsNegativeArity params = CommandLine.populateCommand(new NonVarArgArrayParamsNegativeArity());
- assertEquals(null, params.params);
- }
-
- @Test
- public void testNonVarargArrayParametersWithArity0() {
- class NonVarArgArrayParamsZeroArity {
- @Parameters(arity = "0")
- List<String> params;
- }
- try {
- CommandLine.populateCommand(new NonVarArgArrayParamsZeroArity(), "a", "b", "c");
- fail("Expected UnmatchedArgumentException");
- } catch (UnmatchedArgumentException ex) {
- assertEquals("Unmatched arguments [a, b, c]", ex.getMessage());
- }
- try {
- CommandLine.populateCommand(new NonVarArgArrayParamsZeroArity(), "a");
- fail("Expected UnmatchedArgumentException");
- } catch (UnmatchedArgumentException ex) {
- assertEquals("Unmatched argument [a]", ex.getMessage());
- }
- NonVarArgArrayParamsZeroArity params = CommandLine.populateCommand(new NonVarArgArrayParamsZeroArity());
- assertEquals(null, params.params);
- }
-
- @Test
- public void testNonVarargArrayParametersWithArity1() {
- class NonVarArgArrayParamsArity1 {
- @Parameters(arity = "1")
- List<String> params;
- }
- NonVarArgArrayParamsArity1 actual = CommandLine.populateCommand(new NonVarArgArrayParamsArity1(), "a", "b", "c");
- assertEquals(Arrays.asList("a", "b", "c"), actual.params);
-
- NonVarArgArrayParamsArity1 params = CommandLine.populateCommand(new NonVarArgArrayParamsArity1(), "a");
- assertEquals(Arrays.asList("a"), params.params);
-
- try {
- params = CommandLine.populateCommand(new NonVarArgArrayParamsArity1());
- fail("Should not accept input with missing parameter");
- } catch (MissingParameterException ex) {
- assertEquals("Missing required parameter: <params>", ex.getMessage());
- }
- }
-
- @Test
- public void testNonVarargArrayParametersWithArity2() {
- class NonVarArgArrayParamsArity2 {
- @Parameters(arity = "2")
- List<String> params;
- }
- NonVarArgArrayParamsArity2 params = null;
- try {
- CommandLine.populateCommand(new NonVarArgArrayParamsArity2(), "a", "b", "c");
- fail("expected MissingParameterException");
- } catch (MissingParameterException ex) {
- assertEquals("positional parameter at index 0..* (<params>) requires at least 2 values, but only 1 were specified: [c]", ex.getMessage());
- }
-
- try {
- params = CommandLine.populateCommand(new NonVarArgArrayParamsArity2(), "a");
- fail("Should not accept input with missing parameter");
- } catch (MissingParameterException ex) {
- assertEquals("positional parameter at index 0..* (<params>) requires at least 2 values, but only 1 were specified: [a]", ex.getMessage());
- }
-
- try {
- params = CommandLine.populateCommand(new NonVarArgArrayParamsArity2());
- fail("Should not accept input with missing parameter");
- } catch (MissingParameterException ex) {
- assertEquals("positional parameter at index 0..* (<params>) requires at least 2 values, but none were specified.", ex.getMessage());
- }
- }
-
- @Test
public void testParametersDeclaredOutOfOrderWithNoArgs() {
class WithParams {
@Parameters(index = "1") String param1;
@@ -2701,9 +1952,9 @@ public class CommandLineTest {
"[picocli INFO] Setting File field 'Git.gitDir' to '%s' (was 'null') for option --git-dir%n" +
"[picocli INFO] Adding [Fixed typos] to List<String> field 'GitCommit.message' for option -m%n" +
"[picocli INFO] Found end-of-options delimiter '--'. Treating remainder as positional parameters.%n" +
- "[picocli INFO] Adding [src1.java] to List<File> field 'GitCommit.files' for args[0..*]%n" +
- "[picocli INFO] Adding [src2.java] to List<File> field 'GitCommit.files' for args[0..*]%n" +
- "[picocli INFO] Adding [src3.java] to List<File> field 'GitCommit.files' for args[0..*]%n",
+ "[picocli INFO] Adding [src1.java] to List<File> field 'GitCommit.files' for args[0..*] at position 0%n" +
+ "[picocli INFO] Adding [src2.java] to List<File> field 'GitCommit.files' for args[0..*] at position 1%n" +
+ "[picocli INFO] Adding [src3.java] to List<File> field 'GitCommit.files' for args[0..*] at position 2%n",
new File("/home/rpopma/picocli"));
String actual = new String(baos.toByteArray(), "UTF8");
//System.out.println(actual);
@@ -2743,15 +1994,15 @@ public class CommandLineTest {
"[picocli INFO] Found end-of-options delimiter '--'. Treating remainder as positional parameters.%n" +
"[picocli DEBUG] Processing next arg as a positional parameter at index=0. Remainder=[src1.java, src2.java, src3.java]%n" +
"[picocli DEBUG] Position 0 is in index range 0..*. Trying to assign args to java.util.List %1$s$GitCommit.files, arity=0..1%n" +
- "[picocli INFO] Adding [src1.java] to List<File> field 'GitCommit.files' for args[0..*]%n" +
+ "[picocli INFO] Adding [src1.java] to List<File> field 'GitCommit.files' for args[0..*] at position 0%n" +
"[picocli DEBUG] Consumed 1 arguments, moving position to index 1.%n" +
"[picocli DEBUG] Processing next arg as a positional parameter at index=1. Remainder=[src2.java, src3.java]%n" +
"[picocli DEBUG] Position 1 is in index range 0..*. Trying to assign args to java.util.List %1$s$GitCommit.files, arity=0..1%n" +
- "[picocli INFO] Adding [src2.java] to List<File> field 'GitCommit.files' for args[0..*]%n" +
+ "[picocli INFO] Adding [src2.java] to List<File> field 'GitCommit.files' for args[0..*] at position 1%n" +
"[picocli DEBUG] Consumed 1 arguments, moving position to index 2.%n" +
"[picocli DEBUG] Processing next arg as a positional parameter at index=2. Remainder=[src3.java]%n" +
"[picocli DEBUG] Position 2 is in index range 0..*. Trying to assign args to java.util.List %1$s$GitCommit.files, arity=0..1%n" +
- "[picocli INFO] Adding [src3.java] to List<File> field 'GitCommit.files' for args[0..*]%n" +
+ "[picocli INFO] Adding [src3.java] to List<File> field 'GitCommit.files' for args[0..*] at position 2%n" +
"[picocli DEBUG] Consumed 1 arguments, moving position to index 3.%n",
Demo.class.getName(), new File("/home/rpopma/picocli"));
String actual = new String(baos.toByteArray(), "UTF8");
@@ -2828,7 +2079,7 @@ public class CommandLineTest {
static class CustomType implements ITypeConverter<CustomType> {
private final String val;
private CustomType(String val) { this.val = val; }
- @Override public CustomType convert(String value) { return new CustomType(value); }
+ public CustomType convert(String value) { return new CustomType(value); }
}
private static CommandLine createNestedCommand() {
CommandLine commandLine = new CommandLine(new MainCommand());
@@ -3222,8 +2473,7 @@ public class CommandLineTest {
"Usage: <main class> [--foo-bar-baz=<foo>]\n" +
" --foo-bar-baz=<foo> Default:\n" +
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" +
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" +
- "\n";
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n";
assertEquals(expectedOutput, content);
}
@@ -3511,7 +2761,7 @@ public class CommandLineTest {
"-d", "/path/to/file",
"-e", "12345=67890",
"-f", "12345=67.89",
- "-g", "DAYS=12.34");
+ "-g", "MILLISECONDS=12.34");
assertEquals(app.a.size(), 2);
assertEquals(URI.create("/path"), app.a.get(8));
assertEquals(URI.create("/path/to/resource"), app.a.get(98765432));
@@ -3532,7 +2782,7 @@ public class CommandLineTest {
assertEquals(67.89f, app.f.get(new Long(12345)));
assertEquals(app.g.size(), 1);
- assertEquals(12.34f, app.g.get(TimeUnit.DAYS));
+ assertEquals(12.34f, app.g.get(TimeUnit.MILLISECONDS));
}
@Test
public void testUseTypeAttributeInsteadOfFieldType() {
@@ -3671,6 +2921,7 @@ public class CommandLineTest {
assertEquals("Unmatched argument [--ccd]", ex.getMessage());
}
}
+
@Test
public void test149OnlyUnmatchedOptionStoredOthersParsed() throws Exception {
class App {
@@ -3755,55 +3006,6 @@ public class CommandLineTest {
}
@Test
- public void test130MixPositionalParamsWithOptions() {
- @Command(name = "test-command", description = "tests help from a command script")
- class Arg {
-
- @Parameters(description = "some parameters")
- List<String> parameters;
-
- @Option(names = {"-cp", "--codepath"}, description = "the codepath")
- List<String> codepath;
- }
- Arg result = CommandLine.populateCommand(new Arg(), "--codepath", "/usr/x.jar", "placeholder", "-cp", "/bin/y.jar", "another");
- assertEquals(Arrays.asList("/usr/x.jar", "/bin/y.jar"), result.codepath);
- assertEquals(Arrays.asList("placeholder", "another"), result.parameters);
- }
-
- @Test
- public void test130MixPositionalParamsWithOptions1() {
- class Arg {
- @Parameters List<String> parameters;
- @Option(names = "-o") List<String> options;
- }
- Arg result = CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3");
- assertEquals(Arrays.asList("v1", "v2"), result.options);
- assertEquals(Arrays.asList("p1", "p2", "p3"), result.parameters);
- }
-
- @Test
- public void test130MixPositionalParamsWithOptionsArity() {
- class Arg {
- @Parameters(arity = "2") List<String> parameters;
- @Option(names = "-o") List<String> options;
- }
- Arg result = CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3", "p4");
- assertEquals(Arrays.asList("v1", "v2"), result.options);
- assertEquals(Arrays.asList("p1", "p2", "p3", "p4"), result.parameters);
-
- Arg result2 = CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "-o", "v2", "p3");
- assertEquals(Arrays.asList("v1"), result2.options);
- assertEquals(Arrays.asList("p1", "-o", "v2", "p3"), result2.parameters);
-
- try {
- CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3");
- fail("Expected MissingParameterException");
- } catch (MissingParameterException ex) {
- assertEquals("positional parameter at index 0..* (<parameters>) requires at least 2 values, but only 1 were specified: [p3]", ex.getMessage());
- }
- }
-
- @Test
public void testIssue203InconsistentExceptions() {
class Example {
@Option(names = {"-h", "--help"}, help = true, // NOTE: this should be usageHelp = true
@@ -3945,4 +3147,21 @@ public class CommandLineTest {
assertEquals("OPT", ((Top) parsed.get(0).getCommand()).option);
assertEquals("ABC", ((Sub207A) parsed.get(1).getCommand()).x);
}
+ @Test
+ public void testIssue226EmptyStackWithClusteredOptions() {
+ class Options {
+ @Option(names = "-b")
+ private boolean buffered = false;
+
+ @Option(names = "-o")
+ private boolean overwriteOutput = true;
+
+ @Option(names = "-v")
+ private boolean verbose = false;
+ }
+ Options options = CommandLine.populateCommand(new Options(), "-bov");
+ assertTrue(options.buffered);
+ assertFalse(options.overwriteOutput);
+ assertTrue(options.verbose);
+ }
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/23bcd257/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/Demo.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/Demo.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/Demo.java
index 6f593e2..73caa9d 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/Demo.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/Demo.java
@@ -33,6 +33,9 @@ import java.util.concurrent.Callable;
/**
* Demonstrates picocli subcommands.
+ * <p>
+ * Banner ascii art thanks to <a href="http://patorjk.com/software/taag/">http://patorjk.com/software/taag/</a>.
+ * </p>
*/
@Command(name = "picocli.Demo", sortOptions = false,
header = {
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/23bcd257/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 070e4a1..184432b 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -52,9 +52,6 @@
<action issue="LOG4J2-2100" dev="ggregory" type="fix">
LevelMixIn class for Jackson is coded incorrectly
</action>
- <action issue="LOG4J2-2088" dev="rpopma" type="update">
- Upgrade picocli to 2.0 from 0.9.8.
- </action>
<action issue="LOG4J2-2087" dev="rpopma" type="fix" due-to="Andy Gumbrecht">
Jansi now needs to be enabled explicitly (by setting system property `log4j.skipJansi` to `false`). To avoid causing problems for web applications, Log4j will no longer automatically try to load Jansi without explicit configuration.
</action>
@@ -64,6 +61,9 @@
<action issue="LOG4J2-2076" dev="mikes" type="update">
Split up log4j-nosql into one module per appender.
</action>
+ <action issue="LOG4J2-2088" dev="rpopma" type="update">
+ Upgrade picocli to 2.0.3 from 0.9.8.
+ </action>
<action issue="LOG4J2-2062" dev="mikes" type="add" due-to="Jorge Sanchez">
Add possibility of sending the key of a message to Kafka using KafkaAppender.
</action>
[2/2] logging-log4j2 git commit: LOG4J2-2088 Upgrade picocli to 2.0.3
from 0.9.8
Posted by rp...@apache.org.
LOG4J2-2088 Upgrade picocli to 2.0.3 from 0.9.8
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/23bcd257
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/23bcd257
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/23bcd257
Branch: refs/heads/master
Commit: 23bcd257f7fa2617827c5210b0b1e074d42480cf
Parents: 7d52f13
Author: rpopma <rp...@apache.org>
Authored: Sat Nov 11 21:19:15 2017 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sat Nov 11 21:19:15 2017 +0900
----------------------------------------------------------------------
.../log4j/core/tools/picocli/CommandLine.java | 241 +++--
.../tools/picocli/CommandLineArityTest.java | 934 ++++++++++++++++++
.../core/tools/picocli/CommandLineHelpTest.java | 93 +-
.../core/tools/picocli/CommandLineTest.java | 963 ++-----------------
.../logging/log4j/core/tools/picocli/Demo.java | 3 +
src/changes/changes.xml | 6 +-
6 files changed, 1281 insertions(+), 959 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/23bcd257/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/picocli/CommandLine.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/picocli/CommandLine.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/picocli/CommandLine.java
index ed6cec1..b8a19ab 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/picocli/CommandLine.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/picocli/CommandLine.java
@@ -55,7 +55,6 @@ import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
@@ -133,7 +132,7 @@ import static org.apache.logging.log4j.core.tools.picocli.CommandLine.Help.Colum
*/
public class CommandLine {
/** This is picocli version {@value}. */
- public static final String VERSION = "2.0.0";
+ public static final String VERSION = "2.0.3";
private final Tracer tracer = new Tracer();
private final Interpreter interpreter;
@@ -1791,10 +1790,10 @@ public class CommandLine {
}
}
static void init(Class<?> cls,
- List<Field> requiredFields,
- Map<String, Field> optionName2Field,
- Map<Character, Field> singleCharOption2Field,
- List<Field> positionalParametersFields) {
+ List<Field> requiredFields,
+ Map<String, Field> optionName2Field,
+ Map<Character, Field> singleCharOption2Field,
+ List<Field> positionalParametersFields) {
Field[] declaredFields = cls.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
@@ -1863,6 +1862,7 @@ public class CommandLine {
Interpreter(Object command) {
converterRegistry.put(Path.class, new BuiltIn.PathConverter());
+ converterRegistry.put(Object.class, new BuiltIn.StringConverter());
converterRegistry.put(String.class, new BuiltIn.StringConverter());
converterRegistry.put(StringBuilder.class, new BuiltIn.StringBuilderConverter());
converterRegistry.put(CharSequence.class, new BuiltIn.CharSequenceConverter());
@@ -2109,7 +2109,7 @@ public class CommandLine {
if (tracer.isDebug()) {tracer.debug("Position %d is in index range %s. Trying to assign args to %s, arity=%s%n", position, indexRange, positionalParam, arity);}
assertNoMissingParameters(positionalParam, arity.min, argsCopy);
int originalSize = argsCopy.size();
- applyOption(positionalParam, Parameters.class, arity, false, argsCopy, initialized, "args[" + indexRange + "]");
+ applyOption(positionalParam, Parameters.class, arity, false, argsCopy, initialized, "args[" + indexRange + "] at position " + position);
int count = originalSize - argsCopy.size();
if (count > 0) { required.remove(positionalParam); }
consumed = Math.max(consumed, count);
@@ -2162,16 +2162,15 @@ public class CommandLine {
if (arity.min > 0 && !empty(cluster)) {
if (tracer.isDebug()) {tracer.debug("Trying to process '%s' as option parameter%n", cluster);}
}
- args.push(cluster); // interpret remainder as option parameter (CAUTION: may be empty string!)
// arity may be >= 1, or
// arity <= 0 && !cluster.startsWith(separator)
// e.g., boolean @Option("-v", arity=0, varargs=true); arg "-rvTRUE", remainder cluster="TRUE"
- if (!args.isEmpty() && args.peek().length() == 0 && !paramAttachedToOption) {
- args.pop(); // throw out empty string we get at the end of a group of clustered short options
+ if (!empty(cluster)) {
+ args.push(cluster); // interpret remainder as option parameter
}
int consumed = applyOption(field, Option.class, arity, paramAttachedToOption, args, initialized, argDescription);
// only return if cluster (and maybe more) was consumed, otherwise continue do-while loop
- if (consumed > 0) {
+ if (empty(cluster) || consumed > 0 || args.isEmpty()) {
return;
}
cluster = args.pop();
@@ -2270,7 +2269,7 @@ public class CommandLine {
initialized.add(field);
}
if (tracer.level.isEnabled(level)) { level.print(tracer, traceMessage, field.getType().getSimpleName(),
- field.getDeclaringClass().getSimpleName(), field.getName(), String.valueOf(oldValue), String.valueOf(newValue), argDescription);
+ field.getDeclaringClass().getSimpleName(), field.getName(), String.valueOf(oldValue), String.valueOf(newValue), argDescription);
}
field.set(command, newValue);
return result;
@@ -2620,8 +2619,8 @@ public class CommandLine {
return value == null
? null
: (value.length() > 1 && value.startsWith("\"") && value.endsWith("\""))
- ? value.substring(1, value.length() - 1)
- : value;
+ ? value.substring(1, value.length() - 1)
+ : value;
}
}
private static class PositionalParametersSorter implements Comparator<Field> {
@@ -3163,6 +3162,21 @@ public class CommandLine {
return layout.toString();
}
+ private static String heading(Ansi ansi, String values, Object... params) {
+ StringBuilder sb = join(ansi, new String[] {values}, new StringBuilder(), params);
+ String result = sb.toString();
+ result = result.endsWith(System.getProperty("line.separator"))
+ ? result.substring(0, result.length() - System.getProperty("line.separator").length()) : result;
+ return result + new String(spaces(countTrailingSpaces(values)));
+ }
+ private static char[] spaces(int length) { char[] result = new char[length]; Arrays.fill(result, ' '); return result; }
+ private static int countTrailingSpaces(String str) {
+ if (str == null) {return 0;}
+ int trailingSpaces = 0;
+ for (int i = str.length() - 1; i >= 0 && str.charAt(i) == ' '; i--) { trailingSpaces++; }
+ return trailingSpaces;
+ }
+
/** Formats each of the specified values and appends it to the specified StringBuilder.
* @param ansi whether the result should contain ANSI escape codes or not
* @param values the values to format and append to the StringBuilder
@@ -3174,12 +3188,16 @@ public class CommandLine {
TextTable table = new TextTable(ansi, usageHelpWidth);
table.indentWrappedLines = 0;
for (String summaryLine : values) {
- table.addRowValues(ansi.new Text(String.format(summaryLine, params)));
+ Text[] lines = ansi.new Text(format(summaryLine, params)).splitLines();
+ for (Text line : lines) { table.addRowValues(line); }
}
table.toString(sb);
}
return sb;
}
+ private static String format(String formatString, Object... params) {
+ return formatString == null ? "" : String.format(formatString, params);
+ }
/** Returns command custom synopsis as a string. A custom synopsis can be zero or more lines, and can be
* specified declaratively with the {@link Command#customSynopsis()} annotation attribute or programmatically
* by setting the Help instance's {@link Help#customSynopsis} field.
@@ -3221,14 +3239,14 @@ public class CommandLine {
* @param params the parameters to use to format the header heading
* @return the formatted header heading */
public String headerHeading(Object... params) {
- return ansi().new Text(format(headerHeading, params)).toString();
+ return heading(ansi(), headerHeading, params);
}
/** Returns the text displayed before the synopsis text; the result of {@code String.format(synopsisHeading, params)}.
* @param params the parameters to use to format the synopsis heading
* @return the formatted synopsis heading */
public String synopsisHeading(Object... params) {
- return ansi().new Text(format(synopsisHeading, params)).toString();
+ return heading(ansi(), synopsisHeading, params);
}
/** Returns the text displayed before the description text; an empty string if there is no description,
@@ -3236,7 +3254,7 @@ public class CommandLine {
* @param params the parameters to use to format the description heading
* @return the formatted description heading */
public String descriptionHeading(Object... params) {
- return empty(descriptionHeading) ? "" : ansi().new Text(format(descriptionHeading, params)).toString();
+ return empty(descriptionHeading) ? "" : heading(ansi(), descriptionHeading, params);
}
/** Returns the text displayed before the positional parameter list; an empty string if there are no positional
@@ -3244,7 +3262,7 @@ public class CommandLine {
* @param params the parameters to use to format the parameter list heading
* @return the formatted parameter list heading */
public String parameterListHeading(Object... params) {
- return positionalParametersFields.isEmpty() ? "" : ansi().new Text(format(parameterListHeading, params)).toString();
+ return positionalParametersFields.isEmpty() ? "" : heading(ansi(), parameterListHeading, params);
}
/** Returns the text displayed before the option list; an empty string if there are no options,
@@ -3252,7 +3270,7 @@ public class CommandLine {
* @param params the parameters to use to format the option list heading
* @return the formatted option list heading */
public String optionListHeading(Object... params) {
- return optionFields.isEmpty() ? "" : ansi().new Text(format(optionListHeading, params)).toString();
+ return optionFields.isEmpty() ? "" : heading(ansi(), optionListHeading, params);
}
/** Returns the text displayed before the command list; an empty string if there are no commands,
@@ -3260,17 +3278,14 @@ public class CommandLine {
* @param params the parameters to use to format the command list heading
* @return the formatted command list heading */
public String commandListHeading(Object... params) {
- return commands.isEmpty() ? "" : ansi().new Text(format(commandListHeading, params)).toString();
+ return commands.isEmpty() ? "" : heading(ansi(), commandListHeading, params);
}
/** Returns the text displayed before the footer text; the result of {@code String.format(footerHeading, params)}.
* @param params the parameters to use to format the footer heading
* @return the formatted footer heading */
public String footerHeading(Object... params) {
- return ansi().new Text(format(footerHeading, params)).toString();
- }
- private String format(String formatString, Object[] params) {
- return formatString == null ? "" : String.format(formatString, params);
+ return heading(ansi(), footerHeading, params);
}
/** Returns a 2-column list with command names and the first line of their header or (if absent) description.
* @return a usage help section describing the added commands */
@@ -3441,27 +3456,25 @@ public class CommandLine {
static class DefaultOptionRenderer implements IOptionRenderer {
public String requiredMarker = " ";
public Object command;
+ private String sep;
+ private boolean showDefault;
public Text[][] render(Option option, Field field, IParamLabelRenderer paramLabelRenderer, ColorScheme scheme) {
String[] names = ShortestFirst.sort(option.names());
int shortOptionCount = names[0].length() == 2 ? 1 : 0;
String shortOption = shortOptionCount > 0 ? names[0] : "";
- Text paramLabelText = paramLabelRenderer.renderParameterLabel(field, scheme.ansi(), scheme.optionParamStyles);
+ sep = shortOptionCount > 0 && names.length > 1 ? "," : "";
+
String longOption = join(names, shortOptionCount, names.length - shortOptionCount, ", ");
- String sep = shortOptionCount > 0 && names.length > 1 ? "," : "";
+ Text longOptionText = createLongOptionText(field, paramLabelRenderer, scheme, longOption);
+
+ showDefault = command != null && !option.help() && !isBoolean(field.getType());
+ Object defaultValue = createDefaultValue(field);
- // if no long option, fill in the space between the short option name and the param label value
- if (paramLabelText.length > 0 && longOption.length() == 0) {
- sep = paramLabelRenderer.separator();
- // #181 paramLabelText may be =LABEL or [=LABEL...]
- int sepStart = paramLabelText.plainString().indexOf(sep);
- Text prefix = paramLabelText.substring(0, sepStart);
- paramLabelText = prefix.append(paramLabelText.substring(sepStart + sep.length()));
- }
- Text longOptionText = scheme.optionText(longOption);
- longOptionText = longOptionText.append(paramLabelText);
String requiredOption = option.required() ? requiredMarker : "";
+ return renderDescriptionLines(option, scheme, requiredOption, shortOption, longOptionText, defaultValue);
+ }
- boolean showDefault = command != null && !option.help() && !isBoolean(field.getType());
+ private Object createDefaultValue(Field field) {
Object defaultValue = null;
try {
defaultValue = field.get(command);
@@ -3476,22 +3489,57 @@ public class CommandLine {
} catch (Exception ex) {
showDefault = false;
}
- final int descriptionCount = Math.max(1, option.description().length);
- final int ROW_COUNT = showDefault ? descriptionCount + 1 : descriptionCount;
- final int COLUMN_COUNT = 5;
+ return defaultValue;
+ }
+
+ private Text createLongOptionText(Field field, IParamLabelRenderer renderer, ColorScheme scheme, String longOption) {
+ Text paramLabelText = renderer.renderParameterLabel(field, scheme.ansi(), scheme.optionParamStyles);
+
+ // if no long option, fill in the space between the short option name and the param label value
+ if (paramLabelText.length > 0 && longOption.length() == 0) {
+ sep = renderer.separator();
+ // #181 paramLabelText may be =LABEL or [=LABEL...]
+ int sepStart = paramLabelText.plainString().indexOf(sep);
+ Text prefix = paramLabelText.substring(0, sepStart);
+ paramLabelText = prefix.append(paramLabelText.substring(sepStart + sep.length()));
+ }
+ Text longOptionText = scheme.optionText(longOption);
+ longOptionText = longOptionText.append(paramLabelText);
+ return longOptionText;
+ }
+
+ private Text[][] renderDescriptionLines(Option option,
+ ColorScheme scheme,
+ String requiredOption,
+ String shortOption,
+ Text longOptionText,
+ Object defaultValue) {
Text EMPTY = Ansi.EMPTY_TEXT;
- Text[][] result = new Text[ROW_COUNT][COLUMN_COUNT];
- result[0] = new Text[] { scheme.optionText(requiredOption), scheme.optionText(shortOption),
- scheme.ansi().new Text(sep), longOptionText, scheme.ansi().new Text(str(option.description(), 0)) };
+ List<Text[]> result = new ArrayList<Text[]>();
+ Text[] descriptionFirstLines = scheme.ansi().new Text(str(option.description(), 0)).splitLines();
+ if (descriptionFirstLines.length == 0) {
+ if (showDefault) {
+ descriptionFirstLines = new Text[]{scheme.ansi().new Text(" Default: " + defaultValue)};
+ showDefault = false; // don't show the default value twice
+ } else {
+ descriptionFirstLines = new Text[]{ EMPTY };
+ }
+ }
+ result.add(new Text[] { scheme.optionText(requiredOption), scheme.optionText(shortOption),
+ scheme.ansi().new Text(sep), longOptionText, descriptionFirstLines[0] });
+ for (int i = 1; i < descriptionFirstLines.length; i++) {
+ result.add(new Text[] { EMPTY, EMPTY, EMPTY, EMPTY, descriptionFirstLines[i] });
+ }
for (int i = 1; i < option.description().length; i++) {
- result[i] = new Text[] { EMPTY, EMPTY, EMPTY, EMPTY, scheme.ansi().new Text(option.description()[i]) };
+ Text[] descriptionNextLines = scheme.ansi().new Text(option.description()[i]).splitLines();
+ for (Text line : descriptionNextLines) {
+ result.add(new Text[] { EMPTY, EMPTY, EMPTY, EMPTY, line });
+ }
}
if (showDefault) {
- Arrays.fill(result[result.length - 1], EMPTY);
- int row = empty(result[ROW_COUNT - 2][COLUMN_COUNT - 1]) ? ROW_COUNT - 2 : ROW_COUNT - 1;
- result[row][COLUMN_COUNT - 1] = scheme.ansi().new Text(" Default: " + defaultValue);
+ result.add(new Text[] { EMPTY, EMPTY, EMPTY, EMPTY, scheme.ansi().new Text(" Default: " + defaultValue) });
}
- return result;
+ return result.toArray(new Text[result.size()][]);
}
}
/** The MinimalOptionRenderer converts {@link Option Options} to a single row with two columns of text: an
@@ -3502,7 +3550,7 @@ public class CommandLine {
Text paramLabelText = parameterLabelRenderer.renderParameterLabel(field, scheme.ansi(), scheme.optionParamStyles);
optionText = optionText.append(paramLabelText);
return new Text[][] {{ optionText,
- scheme.ansi().new Text(option.description().length == 0 ? "" : option.description()[0]) }};
+ scheme.ansi().new Text(option.description().length == 0 ? "" : option.description()[0]) }};
}
}
/** The MinimalParameterRenderer converts {@link Parameters Parameters} to a single row with two columns of
@@ -3546,14 +3594,21 @@ public class CommandLine {
Text label = paramLabelRenderer.renderParameterLabel(field, scheme.ansi(), scheme.parameterStyles);
Text requiredParameter = scheme.parameterText(Range.parameterArity(field).min > 0 ? requiredMarker : "");
- final int COLUMN_COUNT = 5;
- final Text EMPTY = Ansi.EMPTY_TEXT;
- Text[][] result = new Text[Math.max(1, params.description().length)][COLUMN_COUNT];
- result[0] = new Text[] { requiredParameter, EMPTY, EMPTY, label, scheme.ansi().new Text(str(params.description(), 0)) };
+ Text EMPTY = Ansi.EMPTY_TEXT;
+ List<Text[]> result = new ArrayList<Text[]>();
+ Text[] descriptionFirstLines = scheme.ansi().new Text(str(params.description(), 0)).splitLines();
+ if (descriptionFirstLines.length == 0) { descriptionFirstLines = new Text[]{ EMPTY }; }
+ result.add(new Text[] { requiredParameter, EMPTY, EMPTY, label, descriptionFirstLines[0] });
+ for (int i = 1; i < descriptionFirstLines.length; i++) {
+ result.add(new Text[] { EMPTY, EMPTY, EMPTY, EMPTY, descriptionFirstLines[i] });
+ }
for (int i = 1; i < params.description().length; i++) {
- result[i] = new Text[] { EMPTY, EMPTY, EMPTY, EMPTY, scheme.ansi().new Text(params.description()[i]) };
+ Text[] descriptionNextLines = scheme.ansi().new Text(params.description()[i]).splitLines();
+ for (Text line : descriptionNextLines) {
+ result.add(new Text[] { EMPTY, EMPTY, EMPTY, EMPTY, line });
+ }
}
- return result;
+ return result.toArray(new Text[result.size()][]);
}
}
/** When customizing online usage help for an option parameter or a positional parameter, a custom
@@ -3830,12 +3885,12 @@ public class CommandLine {
public TextTable(Ansi ansi) {
// "* -c, --create Creates a ...."
this(ansi, new Column[] {
- new Column(2, 0, TRUNCATE), // "*"
- new Column(2, 0, TRUNCATE), // "-c"
- new Column(1, 0, TRUNCATE), // ","
- new Column(optionsColumnWidth - 2 - 2 - 1 , 1, SPAN), // " --create"
- new Column(usageHelpWidth - optionsColumnWidth, 1, WRAP) // " Creates a ..."
- });
+ new Column(2, 0, TRUNCATE), // "*"
+ new Column(2, 0, TRUNCATE), // "-c"
+ new Column(1, 0, TRUNCATE), // ","
+ new Column(optionsColumnWidth - 2 - 2 - 1 , 1, SPAN), // " --create"
+ new Column(usageHelpWidth - optionsColumnWidth, 1, WRAP) // " Creates a ..."
+ });
}
/** Constructs a new TextTable with columns with the specified width, all SPANning multiple columns on
@@ -3976,7 +4031,6 @@ public class CommandLine {
private static int length(Text str) {
return str.length; // TODO count some characters as double length
}
- private char[] spaces(int length) { char[] result = new char[length]; Arrays.fill(result, ' '); return result; }
private int copy(BreakIterator line, Text text, Text columnValue, int offset) {
// Deceive the BreakIterator to ensure no line breaks after '-' character
@@ -4211,7 +4265,7 @@ public class CommandLine {
public String on() { return CSI + startCode + "m"; }
public String off() { return CSI + endCode + "m"; }
- /** Returns the concatenated ANSI escape codes for turning all specified styles on.
+ /** Returns the concatenated ANSI escape codes for turning all specified styles on.
* @param styles the styles to generate ANSI escape codes for
* @return the concatenated ANSI escape codes for turning all specified styles on */
public static String on(IStyle... styles) {
@@ -4221,7 +4275,7 @@ public class CommandLine {
}
return result.toString();
}
- /** Returns the concatenated ANSI escape codes for turning all specified styles off.
+ /** Returns the concatenated ANSI escape codes for turning all specified styles off.
* @param styles the styles to generate ANSI escape codes for
* @return the concatenated ANSI escape codes for turning all specified styles off */
public static String off(IStyle... styles) {
@@ -4231,25 +4285,25 @@ public class CommandLine {
}
return result.toString();
}
- /** Parses the specified style markup and returns the associated style.
- * The markup may be one of the Style enum value names, or it may be one of the Style enum value
- * names when {@code "fg_"} is prepended, or it may be one of the indexed colors in the 256 color palette.
+ /** Parses the specified style markup and returns the associated style.
+ * The markup may be one of the Style enum value names, or it may be one of the Style enum value
+ * names when {@code "fg_"} is prepended, or it may be one of the indexed colors in the 256 color palette.
* @param str the case-insensitive style markup to convert, e.g. {@code "blue"} or {@code "fg_blue"},
* or {@code "46"} (indexed color) or {@code "0;5;0"} (RGB components of an indexed color)
- * @return the IStyle for the specified converter
- */
+ * @return the IStyle for the specified converter
+ */
public static IStyle fg(String str) {
try { return Style.valueOf(str.toLowerCase(ENGLISH)); } catch (Exception ignored) {}
try { return Style.valueOf("fg_" + str.toLowerCase(ENGLISH)); } catch (Exception ignored) {}
return new Palette256Color(true, str);
}
- /** Parses the specified style markup and returns the associated style.
- * The markup may be one of the Style enum value names, or it may be one of the Style enum value
- * names when {@code "bg_"} is prepended, or it may be one of the indexed colors in the 256 color palette.
- * @param str the case-insensitive style markup to convert, e.g. {@code "blue"} or {@code "bg_blue"},
+ /** Parses the specified style markup and returns the associated style.
+ * The markup may be one of the Style enum value names, or it may be one of the Style enum value
+ * names when {@code "bg_"} is prepended, or it may be one of the indexed colors in the 256 color palette.
+ * @param str the case-insensitive style markup to convert, e.g. {@code "blue"} or {@code "bg_blue"},
* or {@code "46"} (indexed color) or {@code "0;5;0"} (RGB components of an indexed color)
- * @return the IStyle for the specified converter
- */
+ * @return the IStyle for the specified converter
+ */
public static IStyle bg(String str) {
try { return Style.valueOf(str.toLowerCase(ENGLISH)); } catch (Exception ignored) {}
try { return Style.valueOf("bg_" + str.toLowerCase(ENGLISH)); } catch (Exception ignored) {}
@@ -4404,6 +4458,27 @@ public class CommandLine {
try { return super.clone(); } catch (CloneNotSupportedException e) { throw new IllegalStateException(e); }
}
+ public Text[] splitLines() {
+ List<Text> result = new ArrayList<Text>();
+ boolean trailingEmptyString = false;
+ int start = 0, end = 0;
+ for (int i = 0; i < plain.length(); i++, end = i) {
+ char c = plain.charAt(i);
+ boolean eol = c == '\n';
+ eol |= (c == '\r' && i + 1 < plain.length() && plain.charAt(i + 1) == '\n' && ++i > 0); // \r\n
+ eol |= c == '\r';
+ if (eol) {
+ result.add(this.substring(start, end));
+ trailingEmptyString = i == plain.length() - 1;
+ start = i + 1;
+ }
+ }
+ if (start < plain.length() || trailingEmptyString) {
+ result.add(this.substring(start, plain.length()));
+ }
+ return result.toArray(new Text[result.size()]);
+ }
+
/** Returns a new {@code Text} instance that is a substring of this Text. Does not modify this instance!
* @param start index in the plain text where to start the substring
* @return a new Text instance that is a substring of this Text */
@@ -4536,7 +4611,7 @@ public class CommandLine {
if (tracer.level.isEnabled(this)) { tracer.stream.printf(prefix(msg), params); }
}
private String prefix(String msg) { return "[picocli " + this + "] " + msg; }
- static TraceLevel lookup(String key) { return key == null ? WARN : empty(key) ? INFO : valueOf(key); }
+ static TraceLevel lookup(String key) { return key == null ? WARN : empty(key) || "true".equalsIgnoreCase(key) ? INFO : valueOf(key); }
}
private static class Tracer {
TraceLevel level = TraceLevel.lookup(System.getProperty("picocli.trace"));
@@ -4569,11 +4644,11 @@ public class CommandLine {
private final CommandLine commandLine;
public ExecutionException(CommandLine commandLine, String msg) {
super(msg);
- this.commandLine = Objects.requireNonNull(commandLine, "commandLine");
+ this.commandLine = Assert.notNull(commandLine, "commandLine");
}
public ExecutionException(CommandLine commandLine, String msg, Exception ex) {
super(msg, ex);
- this.commandLine = Objects.requireNonNull(commandLine, "commandLine");
+ this.commandLine = Assert.notNull(commandLine, "commandLine");
}
/** Returns the {@code CommandLine} object for the (sub)command that could not be invoked.
* @return the {@code CommandLine} object for the (sub)command where invocation failed.
@@ -4597,7 +4672,7 @@ public class CommandLine {
* @since 2.0 */
public ParameterException(CommandLine commandLine, String msg) {
super(msg);
- this.commandLine = Objects.requireNonNull(commandLine, "commandLine");
+ this.commandLine = Assert.notNull(commandLine, "commandLine");
}
/** Constructs a new ParameterException with the specified CommandLine and error message.
* @param commandLine the command or subcommand whose input was invalid
@@ -4606,7 +4681,7 @@ public class CommandLine {
* @since 2.0 */
public ParameterException(CommandLine commandLine, String msg, Exception ex) {
super(msg, ex);
- this.commandLine = Objects.requireNonNull(commandLine, "commandLine");
+ this.commandLine = Assert.notNull(commandLine, "commandLine");
}
/** Returns the {@code CommandLine} object for the (sub)command whose input could not be parsed.
@@ -4643,8 +4718,8 @@ public class CommandLine {
}
private static String describe(Field field, String separator) {
String prefix = (field.isAnnotationPresent(Option.class))
- ? field.getAnnotation(Option.class).names()[0] + separator
- : "params[" + field.getAnnotation(Parameters.class).index() + "]" + separator;
+ ? field.getAnnotation(Option.class).names()[0] + separator
+ : "params[" + field.getAnnotation(Parameters.class).index() + "]" + separator;
return prefix + Help.DefaultParamLabelRenderer.renderParameterName(field);
}
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/23bcd257/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineArityTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineArityTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineArityTest.java
new file mode 100644
index 0000000..c9b435e
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineArityTest.java
@@ -0,0 +1,934 @@
+/*
+ * 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.logging.log4j.core.tools.picocli;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.nio.charset.Charset;
+import java.sql.Time;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.apache.logging.log4j.core.tools.picocli.CommandLine.*;
+
+import static java.util.concurrent.TimeUnit.*;
+import static org.junit.Assert.*;
+import static org.apache.logging.log4j.core.tools.picocli.CommandLine.*;
+
+public class CommandLineArityTest {
+ @Before public void setUp() { System.clearProperty("picocli.trace"); }
+ @After public void tearDown() { System.clearProperty("picocli.trace"); }
+
+ private static void setTraceLevel(String level) {
+ System.setProperty("picocli.trace", level);
+ }
+ @Test
+ public void testArityConstructor_fixedRange() {
+ Range arity = new Range(1, 23, false, false, null);
+ assertEquals("min", 1, arity.min);
+ assertEquals("max", 23, arity.max);
+ assertEquals("1..23", arity.toString());
+ assertEquals(Range.valueOf("1..23"), arity);
+ }
+ @Test
+ public void testArityConstructor_variableRange() {
+ Range arity = new Range(1, Integer.MAX_VALUE, true, false, null);
+ assertEquals("min", 1, arity.min);
+ assertEquals("max", Integer.MAX_VALUE, arity.max);
+ assertEquals("1..*", arity.toString());
+ assertEquals(Range.valueOf("1..*"), arity);
+ }
+ @Test
+ public void testArityForOption_booleanFieldImplicitArity0() throws Exception {
+ Range arity = Range.optionArity(CommandLineTest.SupportedTypes.class.getDeclaredField("booleanField"));
+ assertEquals(Range.valueOf("0"), arity);
+ assertEquals("0", arity.toString());
+ }
+ @Test
+ public void testArityForOption_intFieldImplicitArity1() throws Exception {
+ Range arity = Range.optionArity(CommandLineTest.SupportedTypes.class.getDeclaredField("intField"));
+ assertEquals(Range.valueOf("1"), arity);
+ assertEquals("1", arity.toString());
+ }
+ @Test
+ public void testArityForOption_isExplicitlyDeclaredValue() throws Exception {
+ class Params {
+ @Option(names = "-timeUnitList", type = TimeUnit.class, arity = "3") List<TimeUnit> timeUnitList;
+ }
+ Range arity = Range.optionArity(Params.class.getDeclaredField("timeUnitList"));
+ assertEquals(Range.valueOf("3"), arity);
+ assertEquals("3", arity.toString());
+ }
+ @Test
+ public void testArityForOption_listFieldImplicitArity1() throws Exception {
+ class ImplicitList { @Option(names = "-a") List<Integer> listIntegers; }
+ Range arity = Range.optionArity(ImplicitList.class.getDeclaredField("listIntegers"));
+ assertEquals(Range.valueOf("1"), arity);
+ assertEquals("1", arity.toString());
+ }
+ @Test
+ public void testArityForOption_arrayFieldImplicitArity1() throws Exception {
+ class ImplicitList { @Option(names = "-a") int[] intArray; }
+ Range arity = Range.optionArity(ImplicitList.class.getDeclaredField("intArray"));
+ assertEquals(Range.valueOf("1"), arity);
+ assertEquals("1", arity.toString());
+ }
+ @Test
+ public void testArityForParameters_booleanFieldImplicitArity1() throws Exception {
+ class ImplicitBoolField { @Parameters boolean boolSingleValue; }
+ Range arity = Range.parameterArity(ImplicitBoolField.class.getDeclaredField("boolSingleValue"));
+ assertEquals(Range.valueOf("1"), arity);
+ assertEquals("1", arity.toString());
+ }
+ @Test
+ public void testArityForParameters_intFieldImplicitArity1() throws Exception {
+ class ImplicitSingleField { @Parameters int intSingleValue; }
+ Range arity = Range.parameterArity(ImplicitSingleField.class.getDeclaredField("intSingleValue"));
+ assertEquals(Range.valueOf("1"), arity);
+ assertEquals("1", arity.toString());
+ }
+ @Test
+ public void testArityForParameters_listFieldImplicitArity0_1() throws Exception {
+ class Params {
+ @Parameters(type = Integer.class) List<Integer> list;
+ }
+ Range arity = Range.parameterArity(Params.class.getDeclaredField("list"));
+ assertEquals(Range.valueOf("0..1"), arity);
+ assertEquals("0..1", arity.toString());
+ }
+ @Test
+ public void testArityForParameters_arrayFieldImplicitArity0_1() throws Exception {
+ class Args {
+ @Parameters File[] inputFiles;
+ }
+ Range arity = Range.parameterArity(Args.class.getDeclaredField("inputFiles"));
+ assertEquals(Range.valueOf("0..1"), arity);
+ assertEquals("0..1", arity.toString());
+ }
+ @Test
+ public void testArrayOptionsWithArity0_nConsumeAllArguments() {
+ final double[] DEFAULT_PARAMS = new double[] {1, 2};
+ class ArrayOptionsArity0_nAndParameters {
+ @Parameters double[] doubleParams = DEFAULT_PARAMS;
+ @Option(names = "-doubles", arity = "0..*") double[] doubleOptions;
+ }
+ ArrayOptionsArity0_nAndParameters
+ params = CommandLine.populateCommand(new ArrayOptionsArity0_nAndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[] {1.1, 2.2, 3.3, 4.4}, params.doubleOptions, 0.000001);
+ assertArrayEquals(DEFAULT_PARAMS, params.doubleParams, 0.000001);
+ }
+
+ @Test
+ public void testArrayOptionsWithArity1_nConsumeAllArguments() {
+ class ArrayOptionsArity1_nAndParameters {
+ @Parameters double[] doubleParams;
+ @Option(names = "-doubles", arity = "1..*") double[] doubleOptions;
+ }
+ ArrayOptionsArity1_nAndParameters
+ params = CommandLine.populateCommand(new ArrayOptionsArity1_nAndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[] {1.1, 2.2, 3.3, 4.4}, params.doubleOptions, 0.000001);
+ assertArrayEquals(null, params.doubleParams, 0.000001);
+ }
+
+ @Test
+ public void testArrayOptionsWithArity2_nConsumeAllArguments() {
+ class ArrayOptionsArity2_nAndParameters {
+ @Parameters double[] doubleParams;
+ @Option(names = "-doubles", arity = "2..*") double[] doubleOptions;
+ }
+ ArrayOptionsArity2_nAndParameters
+ params = CommandLine.populateCommand(new ArrayOptionsArity2_nAndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[] {1.1, 2.2, 3.3, 4.4}, params.doubleOptions, 0.000001);
+ assertArrayEquals(null, params.doubleParams, 0.000001);
+ }
+
+ @Test
+ public void testArrayOptionArity2_nConsumesAllArgumentsUpToClusteredOption() {
+ class ArrayOptionsArity2_nAndParameters {
+ @Parameters String[] stringParams;
+ @Option(names = "-s", arity = "2..*") String[] stringOptions;
+ @Option(names = "-v") boolean verbose;
+ @Option(names = "-f") File file;
+ }
+ ArrayOptionsArity2_nAndParameters
+ params = CommandLine.populateCommand(new ArrayOptionsArity2_nAndParameters(), "-s 1.1 2.2 3.3 4.4 -vfFILE 5.5".split(" "));
+ assertArrayEquals(Arrays.toString(params.stringOptions),
+ new String[] {"1.1", "2.2", "3.3", "4.4"}, params.stringOptions);
+ assertTrue(params.verbose);
+ assertEquals(new File("FILE"), params.file);
+ assertArrayEquals(new String[] {"5.5"}, params.stringParams);
+ }
+
+ @Test
+ public void testArrayOptionArity2_nConsumesAllArgumentIncludingQuotedSimpleOption() {
+ class ArrayOptionArity2_nAndParameters {
+ @Parameters String[] stringParams;
+ @Option(names = "-s", arity = "2..*") String[] stringOptions;
+ @Option(names = "-v") boolean verbose;
+ @Option(names = "-f") File file;
+ }
+ ArrayOptionArity2_nAndParameters
+ params = CommandLine.populateCommand(new ArrayOptionArity2_nAndParameters(), "-s 1.1 2.2 3.3 4.4 \"-v\" \"-f\" \"FILE\" 5.5".split(" "));
+ assertArrayEquals(Arrays.toString(params.stringOptions),
+ new String[] {"1.1", "2.2", "3.3", "4.4", "-v", "-f", "FILE", "5.5"}, params.stringOptions);
+ assertFalse("verbose", params.verbose);
+ assertNull("file", params.file);
+ assertArrayEquals(null, params.stringParams);
+ }
+
+ @Test
+ public void testArrayOptionArity2_nConsumesAllArgumentIncludingQuotedClusteredOption() {
+ class ArrayOptionArity2_nAndParameters {
+ @Parameters String[] stringParams;
+ @Option(names = "-s", arity = "2..*") String[] stringOptions;
+ @Option(names = "-v") boolean verbose;
+ @Option(names = "-f") File file;
+ }
+ ArrayOptionArity2_nAndParameters
+ params = CommandLine.populateCommand(new ArrayOptionArity2_nAndParameters(), "-s 1.1 2.2 3.3 4.4 \"-vfFILE\" 5.5".split(" "));
+ assertArrayEquals(Arrays.toString(params.stringOptions),
+ new String[] {"1.1", "2.2", "3.3", "4.4", "-vfFILE", "5.5"}, params.stringOptions);
+ assertFalse("verbose", params.verbose);
+ assertNull("file", params.file);
+ assertArrayEquals(null, params.stringParams);
+ }
+
+ @Test
+ public void testArrayOptionArity2_nConsumesAllArgumentsUpToNextSimpleOption() {
+ class ArrayOptionArity2_nAndParameters {
+ @Parameters double[] doubleParams;
+ @Option(names = "-s", arity = "2..*") String[] stringOptions;
+ @Option(names = "-v") boolean verbose;
+ @Option(names = "-f") File file;
+ }
+ ArrayOptionArity2_nAndParameters
+ params = CommandLine.populateCommand(new ArrayOptionArity2_nAndParameters(), "-s 1.1 2.2 3.3 4.4 -v -f=FILE 5.5".split(" "));
+ assertArrayEquals(Arrays.toString(params.stringOptions),
+ new String[] {"1.1", "2.2", "3.3", "4.4"}, params.stringOptions);
+ assertTrue(params.verbose);
+ assertEquals(new File("FILE"), params.file);
+ assertArrayEquals(new double[] {5.5}, params.doubleParams, 0.000001);
+ }
+
+ @Test
+ public void testArrayOptionArity2_nConsumesAllArgumentsUpToNextOptionWithAttachment() {
+ class ArrayOptionArity2_nAndParameters {
+ @Parameters double[] doubleParams;
+ @Option(names = "-s", arity = "2..*") String[] stringOptions;
+ @Option(names = "-v") boolean verbose;
+ @Option(names = "-f") File file;
+ }
+ ArrayOptionArity2_nAndParameters
+ params = CommandLine.populateCommand(new ArrayOptionArity2_nAndParameters(), "-s 1.1 2.2 3.3 4.4 -f=FILE -v 5.5".split(" "));
+ assertArrayEquals(Arrays.toString(params.stringOptions),
+ new String[] {"1.1", "2.2", "3.3", "4.4"}, params.stringOptions);
+ assertTrue(params.verbose);
+ assertEquals(new File("FILE"), params.file);
+ assertArrayEquals(new double[] {5.5}, params.doubleParams, 0.000001);
+ }
+
+ @Test
+ public void testArrayOptionArityNConsumeAllArguments() {
+ class ArrayOptionArityNAndParameters {
+ @Parameters char[] charParams;
+ @Option(names = "-chars", arity = "*") char[] charOptions;
+ }
+ ArrayOptionArityNAndParameters
+ params = CommandLine.populateCommand(new ArrayOptionArityNAndParameters(), "-chars a b c d".split(" "));
+ assertArrayEquals(Arrays.toString(params.charOptions),
+ new char[] {'a', 'b', 'c', 'd'}, params.charOptions);
+ assertArrayEquals(null, params.charParams);
+ }
+ @Test
+ public void testMissingRequiredParams() {
+ class Example {
+ @Parameters(index = "1", arity = "0..1") String optional;
+ @Parameters(index = "0") String mandatory;
+ }
+ try { CommandLine.populateCommand(new Example(), new String[] {"mandatory"}); }
+ catch (MissingParameterException ex) { fail(); }
+
+ try {
+ CommandLine.populateCommand(new Example(), new String[0]);
+ fail("Should not accept missing mandatory parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameter: <mandatory>", ex.getMessage());
+ }
+ }
+ @Test
+ public void testMissingRequiredParams1() {
+ class Tricky1 {
+ @Parameters(index = "2") String anotherMandatory;
+ @Parameters(index = "1", arity = "0..1") String optional;
+ @Parameters(index = "0") String mandatory;
+ }
+ try {
+ CommandLine.populateCommand(new Tricky1(), new String[0]);
+ fail("Should not accept missing mandatory parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameters: <mandatory>, <anotherMandatory>", ex.getMessage());
+ }
+ try {
+ CommandLine.populateCommand(new Tricky1(), new String[] {"firstonly"});
+ fail("Should not accept missing mandatory parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameter: <anotherMandatory>", ex.getMessage());
+ }
+ }
+ @Test
+ public void testMissingRequiredParams2() {
+ class Tricky2 {
+ @Parameters(index = "2", arity = "0..1") String anotherOptional;
+ @Parameters(index = "1", arity = "0..1") String optional;
+ @Parameters(index = "0") String mandatory;
+ }
+ try { CommandLine.populateCommand(new Tricky2(), new String[] {"mandatory"}); }
+ catch (MissingParameterException ex) { fail(); }
+
+ try {
+ CommandLine.populateCommand(new Tricky2(), new String[0]);
+ fail("Should not accept missing mandatory parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameter: <mandatory>", ex.getMessage());
+ }
+ }
+ @Test
+ public void testMissingRequiredParamsWithOptions() {
+ class Tricky3 {
+ @Option(names="-v") boolean more;
+ @Option(names="-t") boolean any;
+ @Parameters(index = "1") String alsoMandatory;
+ @Parameters(index = "0") String mandatory;
+ }
+ try {
+ CommandLine.populateCommand(new Tricky3(), new String[] {"-t", "-v", "mandatory"});
+ fail("Should not accept missing mandatory parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameter: <alsoMandatory>", ex.getMessage());
+ }
+
+ try {
+ CommandLine.populateCommand(new Tricky3(), new String[] { "-t", "-v"});
+ fail("Should not accept missing two mandatory parameters");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameters: <mandatory>, <alsoMandatory>", ex.getMessage());
+ }
+ }
+ @Test
+ public void testMissingRequiredParamWithOption() {
+ class Tricky3 {
+ @Option(names="-t") boolean any;
+ @Parameters(index = "0") String mandatory;
+ }
+ try {
+ CommandLine.populateCommand(new Tricky3(), new String[] {"-t"});
+ fail("Should not accept missing mandatory parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameter: <mandatory>", ex.getMessage());
+ }
+ }
+ @Test
+ public void testNoMissingRequiredParamErrorIfHelpOptionSpecified() {
+ class App {
+ @Parameters(hidden = true) // "hidden": don't show this parameter in usage help message
+ List<String> allParameters; // no "index" attribute: captures _all_ arguments (as Strings)
+
+ @Parameters(index = "0") InetAddress host;
+ @Parameters(index = "1") int port;
+ @Parameters(index = "2..*") File[] files;
+
+ @Option(names = "-?", help = true) boolean help;
+ }
+ CommandLine.populateCommand(new App(), new String[] {"-?"});
+ try {
+ CommandLine.populateCommand(new App(), new String[0]);
+ fail("Should not accept missing mandatory parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameters: <host>, <port>", ex.getMessage());
+ }
+ }
+ @Test
+ public void testNoMissingRequiredParamErrorWithLabelIfHelpOptionSpecified() {
+ class App {
+ @Parameters(hidden = true) // "hidden": don't show this parameter in usage help message
+ List<String> allParameters; // no "index" attribute: captures _all_ arguments (as Strings)
+
+ @Parameters(index = "0", paramLabel = "HOST") InetAddress host;
+ @Parameters(index = "1", paramLabel = "PORT") int port;
+ @Parameters(index = "2..*", paramLabel = "FILES") File[] files;
+
+ @Option(names = "-?", help = true) boolean help;
+ }
+ CommandLine.populateCommand(new App(), new String[] {"-?"});
+ try {
+ CommandLine.populateCommand(new App(), new String[0]);
+ fail("Should not accept missing mandatory parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameters: HOST, PORT", ex.getMessage());
+ }
+ }
+
+ private static class BooleanOptionsArity0_nAndParameters {
+ @Parameters String[] params;
+ @Option(names = "-bool", arity = "0..*") boolean bool;
+ @Option(names = {"-v", "-other"}, arity="0..*") boolean vOrOther;
+ @Option(names = "-r") boolean rBoolean;
+ }
+ @Test
+ public void testBooleanOptionsArity0_nConsume1ArgumentIfPossible() { // ignores varargs
+ BooleanOptionsArity0_nAndParameters
+ params = CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-bool false false true".split(" "));
+ assertFalse(params.bool);
+ assertArrayEquals(new String[]{ "false", "true"}, params.params);
+ }
+ @Test
+ public void testBooleanOptionsArity0_nRequiresNoArgument() { // ignores varargs
+ BooleanOptionsArity0_nAndParameters
+ params = CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-bool".split(" "));
+ assertTrue(params.bool);
+ }
+ @Test
+ public void testBooleanOptionsArity0_nConsume0ArgumentsIfNextArgIsOption() { // ignores varargs
+ BooleanOptionsArity0_nAndParameters
+ params = CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-bool -other".split(" "));
+ assertTrue(params.bool);
+ assertTrue(params.vOrOther);
+ }
+ @Test
+ public void testBooleanOptionsArity0_nConsume0ArgumentsIfNextArgIsParameter() { // ignores varargs
+ BooleanOptionsArity0_nAndParameters
+ params = CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-bool 123 -other".split(" "));
+ assertTrue(params.bool);
+ assertTrue(params.vOrOther);
+ assertArrayEquals(new String[]{ "123"}, params.params);
+ }
+ @Test
+ public void testBooleanOptionsArity0_nFailsIfAttachedParamNotABoolean() { // ignores varargs
+ try {
+ CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-bool=123 -other".split(" "));
+ fail("was able to assign 123 to boolean");
+ } catch (CommandLine.ParameterException ex) {
+ assertEquals("'123' is not a boolean for option '-bool'", ex.getMessage());
+ }
+ }
+ @Test
+ public void testBooleanOptionsArity0_nShortFormFailsIfAttachedParamNotABoolean() { // ignores varargs
+ try {
+ CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-rv234 -bool".split(" "));
+ fail("Expected exception");
+ } catch (UnmatchedArgumentException ok) {
+ assertEquals("Unmatched argument [-234]", ok.getMessage());
+ }
+ }
+ @Test
+ public void testBooleanOptionsArity0_nShortFormFailsIfAttachedParamNotABooleanWithUnmatchedArgsAllowed() { // ignores varargs
+ setTraceLevel("OFF");
+ CommandLine cmd = new CommandLine(new BooleanOptionsArity0_nAndParameters()).setUnmatchedArgumentsAllowed(true);
+ cmd.parse("-rv234 -bool".split(" "));
+ assertEquals(Arrays.asList("-234"), cmd.getUnmatchedArguments());
+ }
+ @Test
+ public void testBooleanOptionsArity0_nShortFormFailsIfAttachedWithSepParamNotABoolean() { // ignores varargs
+ try {
+ CommandLine.populateCommand(new BooleanOptionsArity0_nAndParameters(), "-rv=234 -bool".split(" "));
+ fail("was able to assign 234 to boolean");
+ } catch (CommandLine.ParameterException ex) {
+ assertEquals("'234' is not a boolean for option '-v'", ex.getMessage());
+ }
+ }
+
+ private static class BooleanOptionsArity1_nAndParameters {
+ @Parameters boolean[] boolParams;
+ @Option(names = "-bool", arity = "1..*") boolean aBoolean;
+ }
+ @Test
+ public void testBooleanOptionsArity1_nConsume1Argument() { // ignores varargs
+ BooleanOptionsArity1_nAndParameters
+ params = CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool false false true".split(" "));
+ assertFalse(params.aBoolean);
+ assertArrayEquals(new boolean[]{ false, true}, params.boolParams);
+
+ params = CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool true false true".split(" "));
+ assertTrue(params.aBoolean);
+ assertArrayEquals(new boolean[]{ false, true}, params.boolParams);
+ }
+ @Test
+ public void testBooleanOptionsArity1_nCaseInsensitive() { // ignores varargs
+ BooleanOptionsArity1_nAndParameters
+ params = CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool fAlsE false true".split(" "));
+ assertFalse(params.aBoolean);
+ assertArrayEquals(new boolean[]{ false, true}, params.boolParams);
+
+ params = CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool FaLsE false true".split(" "));
+ assertFalse(params.aBoolean);
+ assertArrayEquals(new boolean[]{ false, true}, params.boolParams);
+
+ params = CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool tRuE false true".split(" "));
+ assertTrue(params.aBoolean);
+ assertArrayEquals(new boolean[]{ false, true}, params.boolParams);
+ }
+ @Test
+ public void testBooleanOptionsArity1_nErrorIfValueNotTrueOrFalse() { // ignores varargs
+ try {
+ CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool abc".split(" "));
+ fail("Invalid format abc was accepted for boolean");
+ } catch (CommandLine.ParameterException expected) {
+ assertEquals("'abc' is not a boolean for option '-bool'", expected.getMessage());
+ }
+ }
+ @Test
+ public void testBooleanOptionsArity1_nErrorIfValueMissing() {
+ try {
+ CommandLine.populateCommand(new BooleanOptionsArity1_nAndParameters(), "-bool".split(" "));
+ fail("Missing param was accepted for boolean with arity=1");
+ } catch (CommandLine.ParameterException expected) {
+ assertEquals("Missing required parameter for option '-bool' at index 0 (<aBoolean>)", expected.getMessage());
+ }
+ }
+
+ @Test
+ public void testBooleanOptionArity0Consumes0Arguments() {
+ class BooleanOptionArity0AndParameters {
+ @Parameters boolean[] boolParams;
+ @Option(names = "-bool", arity = "0") boolean aBoolean;
+ }
+ BooleanOptionArity0AndParameters
+ params = CommandLine.populateCommand(new BooleanOptionArity0AndParameters(), "-bool true false true".split(" "));
+ assertTrue(params.aBoolean);
+ assertArrayEquals(new boolean[]{true, false, true}, params.boolParams);
+ }
+ @Test(expected = MissingParameterException.class)
+ public void testSingleValueFieldDefaultMinArityIs1() {
+ CommandLine.populateCommand(new CommandLineTest.SupportedTypes(), "-Long");
+ }
+ @Test
+ public void testSingleValueFieldDefaultMinArityIsOne() {
+ try {
+ CommandLine.populateCommand(new CommandLineTest.SupportedTypes(), "-Long", "-boolean");
+ fail("should fail");
+ } catch (CommandLine.ParameterException ex) {
+ assertEquals("Could not convert '-boolean' to Long for option '-Long'" +
+ ": java.lang.NumberFormatException: For input string: \"-boolean\"", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testIntOptionArity1_nConsumes1Argument() { // ignores varargs
+ class IntOptionArity1_nAndParameters {
+ @Parameters int[] intParams;
+ @Option(names = "-int", arity = "1..*") int anInt;
+ }
+ IntOptionArity1_nAndParameters
+ params = CommandLine.populateCommand(new IntOptionArity1_nAndParameters(), "-int 23 42 7".split(" "));
+ assertEquals(23, params.anInt);
+ assertArrayEquals(new int[]{ 42, 7}, params.intParams);
+ }
+
+ @Test
+ public void testArrayOptionsWithArity0Consume0Arguments() {
+ class OptionsArray0ArityAndParameters {
+ @Parameters double[] doubleParams;
+ @Option(names = "-doubles", arity = "0") double[] doubleOptions;
+ }
+ OptionsArray0ArityAndParameters
+ params = CommandLine.populateCommand(new OptionsArray0ArityAndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[0], params.doubleOptions, 0.000001);
+ assertArrayEquals(new double[]{1.1, 2.2, 3.3, 4.4}, params.doubleParams, 0.000001);
+ }
+
+ @Test
+ public void testArrayOptionWithArity1Consumes1Argument() {
+ class Options1ArityAndParameters {
+ @Parameters double[] doubleParams;
+ @Option(names = "-doubles", arity = "1") double[] doubleOptions;
+ }
+ Options1ArityAndParameters
+ params = CommandLine.populateCommand(new Options1ArityAndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[] {1.1}, params.doubleOptions, 0.000001);
+ assertArrayEquals(new double[]{2.2, 3.3, 4.4}, params.doubleParams, 0.000001);
+
+ // repeated occurrence
+ params = CommandLine.populateCommand(new Options1ArityAndParameters(), "-doubles 1.1 -doubles 2.2 -doubles 3.3 4.4".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[] {1.1, 2.2, 3.3}, params.doubleOptions, 0.000001);
+ assertArrayEquals(new double[]{4.4}, params.doubleParams, 0.000001);
+
+ }
+
+ private static class ArrayOptionArity2AndParameters {
+ @Parameters double[] doubleParams;
+ @Option(names = "-doubles", arity = "2") double[] doubleOptions;
+ }
+ @Test
+ public void testArrayOptionWithArity2Consumes2Arguments() {
+ ArrayOptionArity2AndParameters
+ params = CommandLine.populateCommand(new ArrayOptionArity2AndParameters(), "-doubles 1.1 2.2 3.3 4.4".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[] {1.1, 2.2, }, params.doubleOptions, 0.000001);
+ assertArrayEquals(new double[]{3.3, 4.4}, params.doubleParams, 0.000001);
+
+ // repeated occurrence
+ params = CommandLine.populateCommand(new ArrayOptionArity2AndParameters(), "-doubles 1.1 2.2 -doubles 3.3 4.4 0".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[] {1.1, 2.2, 3.3, 4.4 }, params.doubleOptions, 0.000001);
+ assertArrayEquals(new double[]{ 0.0 }, params.doubleParams, 0.000001);
+ }
+ @Test
+ public void testArrayOptionsWithArity2Consume2ArgumentsEvenIfFirstIsAttached() {
+ ArrayOptionArity2AndParameters
+ params = CommandLine.populateCommand(new ArrayOptionArity2AndParameters(), "-doubles=1.1 2.2 3.3 4.4".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[] {1.1, 2.2, }, params.doubleOptions, 0.000001);
+ assertArrayEquals(new double[]{3.3, 4.4}, params.doubleParams, 0.000001);
+
+ // repeated occurrence
+ params = CommandLine.populateCommand(new ArrayOptionArity2AndParameters(), "-doubles=1.1 2.2 -doubles=3.3 4.4 0".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[] {1.1, 2.2, 3.3, 4.4}, params.doubleOptions, 0.000001);
+ assertArrayEquals(new double[]{0}, params.doubleParams, 0.000001);
+ }
+ /** Arity should not limit the total number of values put in an array or collection #191 */
+ @Test
+ public void testArrayOptionsWithArity2MayContainMoreThan2Values() {
+ ArrayOptionArity2AndParameters
+ params = CommandLine.populateCommand(new ArrayOptionArity2AndParameters(), "-doubles=1 2 -doubles 3 4 -doubles 5 6".split(" "));
+ assertArrayEquals(Arrays.toString(params.doubleOptions),
+ new double[] {1, 2, 3, 4, 5, 6 }, params.doubleOptions, 0.000001);
+ assertArrayEquals(null, params.doubleParams, 0.000001);
+ }
+
+ @Test
+ public void testArrayOptionWithoutArityConsumesOneArgument() { // #192
+ class OptionsNoArityAndParameters {
+ @Parameters char[] charParams;
+ @Option(names = "-chars") char[] charOptions;
+ }
+ OptionsNoArityAndParameters
+ params = CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars a b c d".split(" "));
+ assertArrayEquals(Arrays.toString(params.charOptions),
+ new char[] {'a', }, params.charOptions);
+ assertArrayEquals(Arrays.toString(params.charParams), new char[] {'b', 'c', 'd'}, params.charParams);
+
+ // repeated occurrence
+ params = CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars a -chars b c d".split(" "));
+ assertArrayEquals(Arrays.toString(params.charOptions),
+ new char[] {'a', 'b', }, params.charOptions);
+ assertArrayEquals(Arrays.toString(params.charParams), new char[] {'c', 'd'}, params.charParams);
+
+ try {
+ CommandLine.populateCommand(new OptionsNoArityAndParameters(), "-chars".split(" "));
+ fail("expected MissingParameterException");
+ } catch (MissingParameterException ok) {
+ assertEquals("Missing required parameter for option '-chars' (<charOptions>)", ok.getMessage());
+ }
+ }
+
+ @Test
+ public void testArrayParametersWithDefaultArity() {
+ class ArrayParamsDefaultArity {
+ @Parameters
+ List<String> params;
+ }
+ ArrayParamsDefaultArity params = CommandLine.populateCommand(new ArrayParamsDefaultArity(), "a", "b", "c");
+ assertEquals(Arrays.asList("a", "b", "c"), params.params);
+
+ params = CommandLine.populateCommand(new ArrayParamsDefaultArity(), "a");
+ assertEquals(Arrays.asList("a"), params.params);
+
+ params = CommandLine.populateCommand(new ArrayParamsDefaultArity());
+ assertEquals(null, params.params);
+ }
+
+ @Test
+ public void testArrayParametersWithArityMinusOneToN() {
+ class ArrayParamsNegativeArity {
+ @Parameters(arity = "-1..*")
+ List<String> params;
+ }
+ ArrayParamsNegativeArity params = CommandLine.populateCommand(new ArrayParamsNegativeArity(), "a", "b", "c");
+ assertEquals(Arrays.asList("a", "b", "c"), params.params);
+
+ params = CommandLine.populateCommand(new ArrayParamsNegativeArity(), "a");
+ assertEquals(Arrays.asList("a"), params.params);
+
+ params = CommandLine.populateCommand(new ArrayParamsNegativeArity());
+ assertEquals(null, params.params);
+ }
+
+ @Test
+ public void testArrayParametersArity0_n() {
+ class ArrayParamsArity0_n {
+ @Parameters(arity = "0..*")
+ List<String> params;
+ }
+ ArrayParamsArity0_n params = CommandLine.populateCommand(new ArrayParamsArity0_n(), "a", "b", "c");
+ assertEquals(Arrays.asList("a", "b", "c"), params.params);
+
+ params = CommandLine.populateCommand(new ArrayParamsArity0_n(), "a");
+ assertEquals(Arrays.asList("a"), params.params);
+
+ params = CommandLine.populateCommand(new ArrayParamsArity0_n());
+ assertEquals(null, params.params);
+ }
+
+ @Test
+ public void testArrayParametersArity1_n() {
+ class ArrayParamsArity1_n {
+ @Parameters(arity = "1..*")
+ List<String> params;
+ }
+ ArrayParamsArity1_n params = CommandLine.populateCommand(new ArrayParamsArity1_n(), "a", "b", "c");
+ assertEquals(Arrays.asList("a", "b", "c"), params.params);
+
+ params = CommandLine.populateCommand(new ArrayParamsArity1_n(), "a");
+ assertEquals(Arrays.asList("a"), params.params);
+
+ try {
+ params = CommandLine.populateCommand(new ArrayParamsArity1_n());
+ fail("Should not accept input with missing parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameters at positions 0..*: <params>", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testArrayParametersArity2_n() {
+ class ArrayParamsArity2_n {
+ @Parameters(arity = "2..*")
+ List<String> params;
+ }
+ ArrayParamsArity2_n params = CommandLine.populateCommand(new ArrayParamsArity2_n(), "a", "b", "c");
+ assertEquals(Arrays.asList("a", "b", "c"), params.params);
+
+ try {
+ params = CommandLine.populateCommand(new ArrayParamsArity2_n(), "a");
+ fail("Should not accept input with missing parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("positional parameter at index 0..* (<params>) requires at least 2 values, but only 1 were specified: [a]", ex.getMessage());
+ }
+
+ try {
+ params = CommandLine.populateCommand(new ArrayParamsArity2_n());
+ fail("Should not accept input with missing parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("positional parameter at index 0..* (<params>) requires at least 2 values, but none were specified.", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testNonVarargArrayParametersWithNegativeArityConsumesZeroArguments() {
+ class NonVarArgArrayParamsNegativeArity {
+ @Parameters(arity = "-1")
+ List<String> params;
+ }
+ try {
+ CommandLine.populateCommand(new NonVarArgArrayParamsNegativeArity(), "a", "b", "c");
+ fail("Expected UnmatchedArgumentException");
+ } catch (UnmatchedArgumentException ex) {
+ assertEquals("Unmatched arguments [a, b, c]", ex.getMessage());
+ }
+ try {
+ CommandLine.populateCommand(new NonVarArgArrayParamsNegativeArity(), "a");
+ fail("Expected UnmatchedArgumentException");
+ } catch (UnmatchedArgumentException ex) {
+ assertEquals("Unmatched argument [a]", ex.getMessage());
+ }
+ NonVarArgArrayParamsNegativeArity params = CommandLine.populateCommand(new NonVarArgArrayParamsNegativeArity());
+ assertEquals(null, params.params);
+ }
+
+ @Test
+ public void testNonVarargArrayParametersWithArity0() {
+ class NonVarArgArrayParamsZeroArity {
+ @Parameters(arity = "0")
+ List<String> params;
+ }
+ try {
+ CommandLine.populateCommand(new NonVarArgArrayParamsZeroArity(), "a", "b", "c");
+ fail("Expected UnmatchedArgumentException");
+ } catch (UnmatchedArgumentException ex) {
+ assertEquals("Unmatched arguments [a, b, c]", ex.getMessage());
+ }
+ try {
+ CommandLine.populateCommand(new NonVarArgArrayParamsZeroArity(), "a");
+ fail("Expected UnmatchedArgumentException");
+ } catch (UnmatchedArgumentException ex) {
+ assertEquals("Unmatched argument [a]", ex.getMessage());
+ }
+ NonVarArgArrayParamsZeroArity params = CommandLine.populateCommand(new NonVarArgArrayParamsZeroArity());
+ assertEquals(null, params.params);
+ }
+
+ @Test
+ public void testNonVarargArrayParametersWithArity1() {
+ class NonVarArgArrayParamsArity1 {
+ @Parameters(arity = "1")
+ List<String> params;
+ }
+ NonVarArgArrayParamsArity1 actual = CommandLine.populateCommand(new NonVarArgArrayParamsArity1(), "a", "b", "c");
+ assertEquals(Arrays.asList("a", "b", "c"), actual.params);
+
+ NonVarArgArrayParamsArity1 params = CommandLine.populateCommand(new NonVarArgArrayParamsArity1(), "a");
+ assertEquals(Arrays.asList("a"), params.params);
+
+ try {
+ params = CommandLine.populateCommand(new NonVarArgArrayParamsArity1());
+ fail("Should not accept input with missing parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameter: <params>", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testNonVarargArrayParametersWithArity2() {
+ class NonVarArgArrayParamsArity2 {
+ @Parameters(arity = "2")
+ List<String> params;
+ }
+ NonVarArgArrayParamsArity2 params = null;
+ try {
+ CommandLine.populateCommand(new NonVarArgArrayParamsArity2(), "a", "b", "c");
+ fail("expected MissingParameterException");
+ } catch (MissingParameterException ex) {
+ assertEquals("positional parameter at index 0..* (<params>) requires at least 2 values, but only 1 were specified: [c]", ex.getMessage());
+ }
+
+ try {
+ params = CommandLine.populateCommand(new NonVarArgArrayParamsArity2(), "a");
+ fail("Should not accept input with missing parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("positional parameter at index 0..* (<params>) requires at least 2 values, but only 1 were specified: [a]", ex.getMessage());
+ }
+
+ try {
+ params = CommandLine.populateCommand(new NonVarArgArrayParamsArity2());
+ fail("Should not accept input with missing parameter");
+ } catch (MissingParameterException ex) {
+ assertEquals("positional parameter at index 0..* (<params>) requires at least 2 values, but none were specified.", ex.getMessage());
+ }
+ }
+ @Test
+ public void testMixPositionalParamsWithOptions_ParamsUnboundedArity_isGreedy() {
+ class Arg {
+ @Parameters(arity = "1..*") List<String> parameters;
+ @Option(names = "-o") List<String> options;
+ }
+ Arg result = CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3", "p4");
+ assertEquals(Arrays.asList("p1", "p2", "-o", "v2", "p3", "p4"), result.parameters);
+ assertEquals(Arrays.asList("v1"), result.options);
+
+ Arg result2 = CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "-o", "v2", "p3");
+ assertEquals(Arrays.asList("p1", "-o", "v2", "p3"), result2.parameters);
+ assertEquals(Arrays.asList("v1"), result2.options);
+
+ try {
+ CommandLine.populateCommand(new Arg(), "-o", "v1", "-o", "v2");
+ fail("Expected MissingParameterException");
+ } catch (MissingParameterException ex) {
+ assertEquals("Missing required parameters at positions 0..*: <parameters>", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void test130MixPositionalParamsWithOptions() {
+ @CommandLine.Command(name = "test-command", description = "tests help from a command script")
+ class Arg {
+
+ @Parameters(description = "some parameters")
+ List<String> parameters;
+
+ @Option(names = {"-cp", "--codepath"}, description = "the codepath")
+ List<String> codepath;
+ }
+ Arg result = CommandLine.populateCommand(new Arg(), "--codepath", "/usr/x.jar", "placeholder", "-cp", "/bin/y.jar", "another");
+ assertEquals(Arrays.asList("/usr/x.jar", "/bin/y.jar"), result.codepath);
+ assertEquals(Arrays.asList("placeholder", "another"), result.parameters);
+ }
+
+ @Test
+ public void test130MixPositionalParamsWithOptions1() {
+ class Arg {
+ @Parameters List<String> parameters;
+ @Option(names = "-o") List<String> options;
+ }
+ Arg result = CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3");
+ assertEquals(Arrays.asList("v1", "v2"), result.options);
+ assertEquals(Arrays.asList("p1", "p2", "p3"), result.parameters);
+ }
+
+ @Test
+ public void test130MixPositionalParamsWithOptionsArity() {
+ class Arg {
+ @Parameters(arity = "2") List<String> parameters;
+ @Option(names = "-o") List<String> options;
+ }
+ Arg result = CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3", "p4");
+ assertEquals(Arrays.asList("v1", "v2"), result.options);
+ assertEquals(Arrays.asList("p1", "p2", "p3", "p4"), result.parameters);
+
+ Arg result2 = CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "-o", "v2", "p3");
+ assertEquals(Arrays.asList("v1"), result2.options);
+ assertEquals(Arrays.asList("p1", "-o", "v2", "p3"), result2.parameters);
+
+ try {
+ CommandLine.populateCommand(new Arg(), "-o", "v1", "p1", "p2", "-o", "v2", "p3");
+ fail("Expected MissingParameterException");
+ } catch (MissingParameterException ex) {
+ assertEquals("positional parameter at index 0..* (<parameters>) requires at least 2 values, but only 1 were specified: [p3]", ex.getMessage());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/23bcd257/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineHelpTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineHelpTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineHelpTest.java
index d0bb609..3651b22 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineHelpTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/tools/picocli/CommandLineHelpTest.java
@@ -2190,7 +2190,98 @@ public class CommandLineHelpTest {
assertEquals(ansi.new Text("@|bold abc|@@|underline DE|@"), txt2.substring(0,5));
assertEquals(ansi.new Text("@|bold bc|@@|underline DE|@"), txt2.substring(1,5));
}
-
+ @Test
+ public void testTextSplitLines() {
+ Help.Ansi ansi = Help.Ansi.ON;
+ Text[] all = {
+ ansi.new Text("@|bold 012\n34|@").append("5\nAA\n6").append("@|underline 78\n90|@"),
+ ansi.new Text("@|bold 012\r34|@").append("5\rAA\r6").append("@|underline 78\r90|@"),
+ ansi.new Text("@|bold 012\r\n34|@").append("5\r\nAA\r\n6").append("@|underline 78\r\n90|@"),
+ };
+ for (Text text : all) {
+ Text[] lines = text.splitLines();
+ int i = 0;
+ assertEquals(ansi.new Text("@|bold 012|@"), lines[i++]);
+ assertEquals(ansi.new Text("@|bold 34|@5"), lines[i++]);
+ assertEquals(ansi.new Text("AA"), lines[i++]);
+ assertEquals(ansi.new Text("6@|underline 78|@"), lines[i++]);
+ assertEquals(ansi.new Text("@|underline 90|@"), lines[i++]);
+ }
+ }
+ @Test
+ public void testTextSplitLinesStartEnd() {
+ Help.Ansi ansi = Help.Ansi.ON;
+ Text[] all = {
+ ansi.new Text("\n@|bold 012\n34|@").append("5\nAA\n6").append("@|underline 78\n90|@\n"),
+ ansi.new Text("\r@|bold 012\r34|@").append("5\rAA\r6").append("@|underline 78\r90|@\r"),
+ ansi.new Text("\r\n@|bold 012\r\n34|@").append("5\r\nAA\r\n6").append("@|underline 78\r\n90|@\r\n"),
+ };
+ for (Text text : all) {
+ Text[] lines = text.splitLines();
+ int i = 0;
+ assertEquals(ansi.new Text(""), lines[i++]);
+ assertEquals(ansi.new Text("@|bold 012|@"), lines[i++]);
+ assertEquals(ansi.new Text("@|bold 34|@5"), lines[i++]);
+ assertEquals(ansi.new Text("AA"), lines[i++]);
+ assertEquals(ansi.new Text("6@|underline 78|@"), lines[i++]);
+ assertEquals(ansi.new Text("@|underline 90|@"), lines[i++]);
+ assertEquals(ansi.new Text(""), lines[i++]);
+ }
+ }
+ @Test
+ public void testTextSplitLinesStartEndIntermediate() {
+ Help.Ansi ansi = Help.Ansi.ON;
+ Text[] all = {
+ ansi.new Text("\n@|bold 012\n\n\n34|@").append("5\n\n\nAA\n\n\n6").append("@|underline 78\n90|@\n"),
+ ansi.new Text("\r@|bold 012\r\r\r34|@").append("5\r\r\rAA\r\r\r6").append("@|underline 78\r90|@\r"),
+ ansi.new Text("\r\n@|bold 012\r\n\r\n\r\n34|@").append("5\r\n\r\n\r\nAA\r\n\r\n\r\n6").append("@|underline 78\r\n90|@\r\n"),
+ };
+ for (Text text : all) {
+ Text[] lines = text.splitLines();
+ int i = 0;
+ assertEquals(ansi.new Text(""), lines[i++]);
+ assertEquals(ansi.new Text("@|bold 012|@"), lines[i++]);
+ assertEquals(ansi.new Text(""), lines[i++]);
+ assertEquals(ansi.new Text(""), lines[i++]);
+ assertEquals(ansi.new Text("@|bold 34|@5"), lines[i++]);
+ assertEquals(ansi.new Text(""), lines[i++]);
+ assertEquals(ansi.new Text(""), lines[i++]);
+ assertEquals(ansi.new Text("AA"), lines[i++]);
+ assertEquals(ansi.new Text(""), lines[i++]);
+ assertEquals(ansi.new Text(""), lines[i++]);
+ assertEquals(ansi.new Text("6@|underline 78|@"), lines[i++]);
+ assertEquals(ansi.new Text("@|underline 90|@"), lines[i++]);
+ assertEquals(ansi.new Text(""), lines[i++]);
+ }
+ }
+ @Test
+ public void testEmbeddedNewLinesInUsageSections() throws UnsupportedEncodingException {
+ @Command(description = "first line\nsecond line\nthird line", headerHeading = "headerHeading1\nheaderHeading2",
+ header = "header1\nheader2", descriptionHeading = "descriptionHeading1\ndescriptionHeading2",
+ footerHeading = "footerHeading1\nfooterHeading2", footer = "footer1\nfooter2")
+ class App {
+ @Option(names = {"-v", "--verbose"}, description = "optionDescription1\noptionDescription2") boolean v;
+ @Parameters(description = "paramDescription1\nparamDescription2") String file;
+ }
+ String actual = usageString(new App(), Help.Ansi.OFF);
+ String expected = String.format("" +
+ "headerHeading1%n" +
+ "headerHeading2header1%n" +
+ "header2%n" +
+ "Usage: <main class> [-v] <file>%n" +
+ "descriptionHeading1%n" +
+ "descriptionHeading2first line%n" +
+ "second line%n" +
+ "third line%n" +
+ " <file> paramDescription1%n" +
+ " paramDescription2%n" +
+ " -v, --verbose optionDescription1%n" +
+ " optionDescription2%n" +
+ "footerHeading1%n" +
+ "footerHeading2footer1%n" +
+ "footer2%n");
+ assertEquals(expected, actual);
+ }
@Test
public void testTextWithMultipleStyledSections() {
assertEquals("\u001B[1m<main class>\u001B[21m\u001B[0m [\u001B[33m-v\u001B[39m\u001B[0m] [\u001B[33m-c\u001B[39m\u001B[0m [\u001B[3m<count>\u001B[23m\u001B[0m]]",