private void printParser(ParserSpec parser, PrintWriter pw, String indent) { pw.printf("%sParserSpec:%n", indent); indent += " "; pw.printf("%sseparator: '%s'%n", indent, parser.separator()); pw.printf("%sendOfOptionsDelimiter: '%s'%n", indent, parser.endOfOptionsDelimiter()); pw.printf("%sexpandAtFiles: %s%n", indent, parser.expandAtFiles()); pw.printf("%satFileCommentChar: '%s'%n", indent, parser.atFileCommentChar()); pw.printf("%soverwrittenOptionsAllowed: %s%n", indent, parser.overwrittenOptionsAllowed()); pw.printf("%sunmatchedArgumentsAllowed: %s%n", indent, parser.unmatchedArgumentsAllowed()); pw.printf("%sunmatchedOptionsArePositionalParams: %s%n", indent, parser.unmatchedOptionsArePositionalParams()); pw.printf("%sstopAtUnmatched: %s%n", indent, parser.stopAtUnmatched()); pw.printf("%sstopAtPositional: %s%n", indent, parser.stopAtPositional()); pw.printf("%sposixClusteredShortOptionsAllowed: %s%n", indent, parser.posixClusteredShortOptionsAllowed()); pw.printf("%saritySatisfiedByAttachedOptionParam: %s%n", indent, parser.aritySatisfiedByAttachedOptionParam()); pw.printf("%scaseInsensitiveEnumValuesAllowed: %s%n", indent, parser.caseInsensitiveEnumValuesAllowed()); pw.printf("%scollectErrors: %s%n", indent, parser.collectErrors()); pw.printf("%slimitSplit: %s%n", indent, parser.limitSplit()); pw.printf("%stoggleBooleanFlags: %s%n", indent, parser.toggleBooleanFlags()); }
@Test public void testEnumListTypeConversionFailsForInvalidInput() { CommandLine cmd = new CommandLine(new CommandLineTypeConversionTest.EnumParams()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse("-timeUnitList", "SECONDS", "b", "c"); assertEquals(2, cmd.getParseResult().errors().size()); Exception ex = cmd.getParseResult().errors().get(0); String prefix = "Invalid value for option '-timeUnitList' at index 1 (<timeUnitList>): expected one of "; String suffix = " but was 'b'"; assertEquals(prefix, ex.getMessage().substring(0, prefix.length())); assertEquals(suffix, ex.getMessage().substring(ex.getMessage().length() - suffix.length(), ex.getMessage().length())); assertEquals("Unmatched argument: c", cmd.getParseResult().errors().get(1).getMessage()); } @Test
private void assertMissing(List<String> expected, Object command, String... args) { CommandLine cmd = new CommandLine(command); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse(args); List<Exception> errors = cmd.getParseResult().errors(); assertEquals(errors.toString(), expected.size(), errors.size()); int i = 0; for (String msg : expected) { assertEquals(msg, errors.get(i++).getMessage()); } } @Test
@Test public void testUnknownOption() { class App { @Option(names = "-x") int x; @Parameters(index = "0") int first; @Parameters(index = "*") String all; } CommandLine cmd = new CommandLine(new App()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse("NOT_AN_INT", "-x=b", "-unknown", "1", "2", "3"); ParseResult parseResult = cmd.getParseResult(); assertEquals(Arrays.asList("NOT_AN_INT", "-unknown", "2", "3"), parseResult.unmatched()); assertEquals(6, parseResult.errors().size()); assertEquals("Invalid value for positional parameter at index 0 (<first>): 'NOT_AN_INT' is not an int", parseResult.errors().get(0).getMessage()); assertEquals("Invalid value for option '-x': 'b' is not an int", parseResult.errors().get(1).getMessage()); assertEquals("positional parameter at index 0..* (<all>) should be specified only once", parseResult.errors().get(2).getMessage()); assertEquals("positional parameter at index 0..* (<all>) should be specified only once", parseResult.errors().get(3).getMessage()); assertEquals("positional parameter at index 0..* (<all>) should be specified only once", parseResult.errors().get(4).getMessage()); assertEquals("Unmatched arguments: NOT_AN_INT, -unknown, 2, 3", parseResult.errors().get(5).getMessage()); } @Test
@Test public void testAnyExceptionWrappedInParameterException() { class App { @Option(names = "-queue", type = String.class, split = ",") ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(2); } CommandLine cmd = new CommandLine(new App()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse("-queue", "a,b,c"); ParseResult parseResult = cmd.getParseResult(); assertTrue(parseResult.unmatched().isEmpty()); assertEquals(1, parseResult.errors().size()); assertTrue(parseResult.errors().get(0) instanceof ParameterException); assertTrue(parseResult.errors().get(0).getCause() instanceof IllegalStateException); assertEquals("IllegalStateException: Queue full while processing argument " + "at or before arg[1] 'a,b,c' in [-queue, a,b,c]: java.lang.IllegalStateException: Queue full", parseResult.errors().get(0).getMessage()); assertEquals("Queue full", parseResult.errors().get(0).getCause().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; } CommandLine cmd = new CommandLine(new Tricky1()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse(new String[0]); assertEquals(2, cmd.getParseResult().errors().size()); assertEquals("Missing required parameters: <mandatory>, <anotherMandatory>", cmd.getParseResult().errors().get(0).getMessage()); assertEquals("Missing required parameter: <anotherMandatory>", cmd.getParseResult().errors().get(1).getMessage()); cmd.parse(new String[] {"firstonly"}); assertEquals(1, cmd.getParseResult().errors().size()); assertEquals("Missing required parameter: <anotherMandatory>", cmd.getParseResult().errors().get(0).getMessage()); } @Test
@Test public void testNonVarargArrayParametersWithArity0() { class NonVarArgArrayParamsZeroArity { @Parameters(arity = "0") List<String> params; } CommandLine cmd = new CommandLine(new NonVarArgArrayParamsZeroArity()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse("a", "b", "c"); assertEquals(1, cmd.getParseResult().errors().size()); assertEquals("Unmatched arguments: a, b, c", cmd.getParseResult().errors().get(0).getMessage()); cmd.parse("a"); assertEquals(1, cmd.getParseResult().errors().size()); assertEquals("Unmatched argument: a", cmd.getParseResult().errors().get(0).getMessage()); } @Test
@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; } CommandLine cmd = new CommandLine(new Tricky2()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse(new String[0]); assertEquals(1, cmd.getParseResult().errors().size()); assertEquals("Missing required parameter: <mandatory>", cmd.getParseResult().errors().get(0).getMessage()); } @Test
@Test public void testSingleValueFieldDefaultMinArityIsOne() { class App { @Option(names = "-boolean") boolean booleanField; @Option(names = "-Long") Long aLongField; } CommandLine cmd = new CommandLine(new App()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse("-Long", "-boolean"); assertEquals(1, cmd.getParseResult().errors().size()); assertEquals("Invalid value for option '-Long': '-boolean' is not a long", cmd.getParseResult().errors().get(0).getMessage()); } @Test
@Test public void testMultiValuePositionalParamArityAloneIsInsufficient() throws Exception { CommandLine.Model.CommandSpec spec = CommandLine.Model.CommandSpec.create(); CommandLine.Model.PositionalParamSpec positional = CommandLine.Model.PositionalParamSpec.builder().index("0").arity("3").type(int.class).build(); assertFalse(positional.isMultiValue()); spec.addPositional(positional); spec.parser().collectErrors(true); CommandLine commandLine = new CommandLine(spec); commandLine.parse("1", "2", "3"); assertEquals(1, commandLine.getParseResult().errors().size()); assertEquals("Unmatched arguments: 2, 3", commandLine.getParseResult().errors().get(0).getMessage()); } @Test
@Test public void testMissingRequiredParamWithOption() { class Tricky3 { @Option(names="-t") boolean any; @Parameters(index = "0") String mandatory; } CommandLine cmd = new CommandLine(new Tricky3()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse(new String[] {"-t"}); assertEquals(1, cmd.getParseResult().errors().size()); assertEquals("Missing required parameter: <mandatory>", cmd.getParseResult().errors().get(0).getMessage()); }
@Test public void testMissingRequiredParams() { class Example { @Parameters(index = "1", arity = "0..1") String optional; @Parameters(index = "0") String mandatory; } CommandLine cmd = new CommandLine(new Example()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse(new String[0]); assertEquals(1, cmd.getParseResult().errors().size()); assertEquals("Missing required parameter: <mandatory>", cmd.getParseResult().errors().get(0).getMessage()); } @Test
@Test public void testCommandSpecParserSetter() { CommandSpec spec = CommandSpec.wrapWithoutInspection(null); ParserSpec old = spec.parser(); assertSame(old, spec.parser()); assertFalse(spec.parser().collectErrors()); assertFalse(spec.parser().caseInsensitiveEnumValuesAllowed()); ParserSpec update = new ParserSpec().collectErrors(true).caseInsensitiveEnumValuesAllowed(true); spec.parser(update); assertSame(old, spec.parser()); assertTrue(spec.parser().collectErrors()); assertTrue(spec.parser().caseInsensitiveEnumValuesAllowed()); }
@Test public void testTimeFormatHHmmssSSSInvalidError() throws ParseException { CommandLine cmd = new CommandLine(new CommandLineTypeConversionTest.SupportedTypes()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse("-Time", "23:59:58;123"); assertEquals(1, cmd.getParseResult().errors().size()); assertEquals("Invalid value for option '-Time': '23:59:58;123' is not a HH:mm[:ss[.SSS]] time", cmd.getParseResult().errors().get(0).getMessage()); } @Test
@Test public void testBooleanOptionsArity0_nShortFormFailsIfAttachedParamNotABoolean() { // ignores varargs CommandLine cmd = new CommandLine(new CommandLineArityTest.BooleanOptionsArity0_nAndParameters()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse("-rv234 -bool".split(" ")); assertEquals(1, cmd.getParseResult().errors().size()); assertEquals("Unknown option: -234", cmd.getParseResult().errors().get(0).getMessage()); }
@Test public void testMultiValueOptionArityAloneIsInsufficient() throws Exception { CommandLine.Model.CommandSpec spec = CommandLine.Model.CommandSpec.create(); CommandLine.Model.OptionSpec option = CommandLine.Model.OptionSpec.builder("-c", "--count").arity("3").type(int.class).build(); assertFalse(option.isMultiValue()); spec.addOption(option); spec.parser().collectErrors(true); CommandLine commandLine = new CommandLine(spec); commandLine.parse("-c", "1", "2", "3"); assertEquals(1, commandLine.getParseResult().errors().size()); assertEquals("Unmatched arguments: 2, 3", commandLine.getParseResult().errors().get(0).getMessage()); }
@Test public void testAssertNoMissingParametersPositional() { class App { @Parameters(arity = "1") int x; } CommandLine cmd = new CommandLine(new App()); cmd.getCommandSpec().parser().collectErrors(true); ParseResult parseResult = cmd.parseArgs(); List<Exception> errors = parseResult.errors(); assertEquals(1, errors.size()); assertEquals("Missing required parameter: <x>", errors.get(0).getMessage()); }
@Test public void testAssertNoMissingParametersOption() { class App { @Option(names = "-x") int x; } CommandLine cmd = new CommandLine(new App()); cmd.getCommandSpec().parser().collectErrors(true); ParseResult parseResult = cmd.parseArgs("-x"); List<Exception> errors = parseResult.errors(); assertEquals(1, errors.size()); assertEquals("Missing required parameter for option '-x' (<x>)", errors.get(0).getMessage()); }
@Test public void testByteFieldsAreDecimal() { CommandLine cmd = new CommandLine(new CommandLineTypeConversionTest.SupportedTypes()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse("-byte", "0x1F", "-Byte", "0x0F"); assertEquals(2, cmd.getParseResult().errors().size()); assertEquals("Invalid value for option '-byte': '0x1F' is not a byte", cmd.getParseResult().errors().get(0).getMessage()); assertEquals("Invalid value for option '-Byte': '0x0F' is not a byte", cmd.getParseResult().errors().get(1).getMessage()); } @Test
@Test public void testBooleanOptionsArity0_nFailsIfAttachedParamNotABoolean() { // ignores varargs CommandLine cmd = new CommandLine(new CommandLineArityTest.BooleanOptionsArity0_nAndParameters()); cmd.getCommandSpec().parser().collectErrors(true); cmd.parse("-bool=123 -other".split(" ")); assertEquals(1, cmd.getParseResult().errors().size()); assertEquals("Invalid value for option '-bool': '123' is not a boolean", cmd.getParseResult().errors().get(0).getMessage()); } @Test