1 /** 2 * Copyright (C) 2010 the original author or authors. 3 * See the notice.md file distributed with this work for additional 4 * information regarding copyright ownership. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package com.beust.jcommander; 20 21 import java.io.ByteArrayInputStream; 22 import java.io.File; 23 import java.io.FileWriter; 24 import java.io.IOException; 25 import java.io.InputStream; 26 import java.math.BigDecimal; 27 import java.text.ParseException; 28 import java.text.SimpleDateFormat; 29 import java.util.ArrayList; 30 import java.util.Arrays; 31 import java.util.EnumSet; 32 import java.util.Iterator; 33 import java.util.List; 34 import java.util.Locale; 35 import java.util.Map; 36 import java.util.ResourceBundle; 37 import java.util.TreeSet; 38 39 import org.testng.Assert; 40 import org.testng.annotations.DataProvider; 41 import org.testng.annotations.Test; 42 43 import com.beust.jcommander.args.AlternateNamesForListArgs; 44 import com.beust.jcommander.args.Args1; 45 import com.beust.jcommander.args.Args1Setter; 46 import com.beust.jcommander.args.Args2; 47 import com.beust.jcommander.args.ArgsArityString; 48 import com.beust.jcommander.args.ArgsBooleanArity; 49 import com.beust.jcommander.args.ArgsBooleanArity0; 50 import com.beust.jcommander.args.ArgsConverter; 51 import com.beust.jcommander.args.ArgsEnum; 52 import com.beust.jcommander.args.ArgsEnum.ChoiceType; 53 import com.beust.jcommander.args.ArgsEquals; 54 import com.beust.jcommander.args.ArgsHelp; 55 import com.beust.jcommander.args.ArgsI18N1; 56 import com.beust.jcommander.args.ArgsI18N2; 57 import com.beust.jcommander.args.ArgsI18N2New; 58 import com.beust.jcommander.args.ArgsInherited; 59 import com.beust.jcommander.args.ArgsList; 60 import com.beust.jcommander.args.ArgsMainParameter1; 61 import com.beust.jcommander.args.ArgsMaster; 62 import com.beust.jcommander.args.ArgsMultipleUnparsed; 63 import com.beust.jcommander.args.ArgsOutOfMemory; 64 import com.beust.jcommander.args.ArgsPrivate; 65 import com.beust.jcommander.args.ArgsRequired; 66 import com.beust.jcommander.args.ArgsSlave; 67 import com.beust.jcommander.args.ArgsSlaveBogus; 68 import com.beust.jcommander.args.ArgsValidate1; 69 import com.beust.jcommander.args.ArgsWithSet; 70 import com.beust.jcommander.args.Arity1; 71 import com.beust.jcommander.args.SeparatorColon; 72 import com.beust.jcommander.args.SeparatorEqual; 73 import com.beust.jcommander.args.SeparatorMixed; 74 import com.beust.jcommander.args.SlashSeparator; 75 import com.beust.jcommander.args.VariableArity; 76 import com.beust.jcommander.command.CommandAdd; 77 import com.beust.jcommander.command.CommandCommit; 78 import com.beust.jcommander.command.CommandMain; 79 import com.beust.jcommander.internal.Lists; 80 import com.beust.jcommander.internal.Maps; 81 82 @Test 83 public class JCommanderTest { simpleArgs()84 public void simpleArgs() throws ParseException { 85 Args1 args = new Args1(); 86 String[] argv = { "-debug", "-log", "2", "-float", "1.2", "-double", "1.3", "-bigdecimal", "1.4", 87 "-date", "2011-10-26", "-groups", "unit", "a", "b", "c" }; 88 new JCommander(args, argv); 89 90 Assert.assertTrue(args.debug); 91 Assert.assertEquals(args.verbose.intValue(), 2); 92 Assert.assertEquals(args.groups, "unit"); 93 Assert.assertEquals(args.parameters, Arrays.asList("a", "b", "c")); 94 Assert.assertEquals(args.floa, 1.2f, 0.1f); 95 Assert.assertEquals(args.doub, 1.3f, 0.1f); 96 Assert.assertEquals(args.bigd, new BigDecimal("1.4")); 97 Assert.assertEquals(args.date, new SimpleDateFormat("yyyy-MM-dd").parse("2011-10-26")); 98 } 99 100 @DataProvider alternateNamesListArgs()101 public Object[][] alternateNamesListArgs() { 102 return new Object[][] { 103 new String[][] {new String[] {"--servers", "1", "-s", "2", "--servers", "3"}}, 104 new String[][] {new String[] {"-s", "1", "-s", "2", "--servers", "3"}}, 105 new String[][] {new String[] {"--servers", "1", "--servers", "2", "-s", "3"}}, 106 new String[][] {new String[] {"-s", "1", "--servers", "2", "-s", "3"}}, 107 new String[][] {new String[] {"-s", "1", "-s", "2", "--servers", "3"}}, 108 }; 109 } 110 111 /** 112 * Confirm that List<?> parameters with alternate names return the correct 113 * List regardless of how the arguments are specified 114 */ 115 116 @Test(dataProvider = "alternateNamesListArgs") testAlternateNamesForListArguments(String[] argv)117 public void testAlternateNamesForListArguments(String[] argv) { 118 AlternateNamesForListArgs args = new AlternateNamesForListArgs(); 119 120 new JCommander(args, argv); 121 122 Assert.assertEquals(args.serverNames.size(), 3); 123 Assert.assertEquals(args.serverNames.get(0), argv[1]); 124 Assert.assertEquals(args.serverNames.get(1), argv[3]); 125 Assert.assertEquals(args.serverNames.get(2), argv[5]); 126 } 127 128 129 /** 130 * Make sure that if there are args with multiple names (e.g. "-log" and "-verbose"), 131 * the usage will only display it once. 132 */ repeatedArgs()133 public void repeatedArgs() { 134 Args1 args = new Args1(); 135 String[] argv = { "-log", "2" }; 136 JCommander jc = new JCommander(args, argv); 137 Assert.assertEquals(jc.getParameters().size(), 8); 138 } 139 140 /** 141 * Not specifying a required option should throw an exception. 142 */ 143 @Test(expectedExceptions = ParameterException.class) requiredFields1Fail()144 public void requiredFields1Fail() { 145 Args1 args = new Args1(); 146 String[] argv = { "-debug" }; 147 new JCommander(args, argv); 148 } 149 150 /** 151 * Getting the description of a nonexistent command should throw an exception. 152 */ 153 @Test(expectedExceptions = ParameterException.class) nonexistentCommandShouldThrow()154 public void nonexistentCommandShouldThrow() { 155 String[] argv = { }; 156 JCommander jc = new JCommander(new Object(), argv); 157 jc.getCommandDescription("foo"); 158 } 159 160 /** 161 * Required options with multiple names should work with all names. 162 */ multipleNames(String option)163 private void multipleNames(String option) { 164 Args1 args = new Args1(); 165 String[] argv = { option, "2" }; 166 new JCommander(args, argv); 167 Assert.assertEquals(args.verbose.intValue(), 2); 168 } 169 multipleNames1()170 public void multipleNames1() { 171 multipleNames("-log"); 172 } 173 multipleNames2()174 public void multipleNames2() { 175 multipleNames("-verbose"); 176 } 177 i18n1(String bundleName, Locale locale, String expectedString)178 private void i18n1(String bundleName, Locale locale, String expectedString) { 179 ResourceBundle bundle = locale != null ? ResourceBundle.getBundle(bundleName, locale) 180 : null; 181 182 ArgsI18N1 i18n = new ArgsI18N1(); 183 String[] argv = { "-host", "localhost" }; 184 JCommander jc = new JCommander(i18n, bundle, argv); 185 // jc.usage(); 186 187 ParameterDescription pd = jc.getParameters().get(0); 188 Assert.assertEquals(pd.getDescription(), expectedString); 189 } 190 i18nNoLocale()191 public void i18nNoLocale() { 192 i18n1("MessageBundle", null, "Host"); 193 } 194 i18nUsLocale()195 public void i18nUsLocale() { 196 i18n1("MessageBundle", new Locale("en", "US"), "Host"); 197 } 198 i18nFrLocale()199 public void i18nFrLocale() { 200 i18n1("MessageBundle", new Locale("fr", "FR"), "Hôte"); 201 } 202 i18n2(Object i18n)203 private void i18n2(Object i18n) { 204 String[] argv = { "-host", "localhost" }; 205 Locale.setDefault(new Locale("fr", "FR")); 206 JCommander jc = new JCommander(i18n, argv); 207 ParameterDescription pd = jc.getParameters().get(0); 208 Assert.assertEquals(pd.getDescription(), "Hôte"); 209 } 210 i18nWithResourceAnnotation()211 public void i18nWithResourceAnnotation() { 212 i18n2(new ArgsI18N2()); 213 } 214 i18nWithResourceAnnotationNew()215 public void i18nWithResourceAnnotationNew() { 216 i18n2(new ArgsI18N2New()); 217 } 218 noParseConstructor()219 public void noParseConstructor() { 220 JCommander jCommander = new JCommander(new ArgsMainParameter1()); 221 jCommander.usage(new StringBuilder()); 222 // Before fix, this parse would throw an exception, because it calls createDescription, which 223 // was already called by usage(), and can only be called once. 224 jCommander.parse(); 225 } 226 227 /** 228 * Test a use case where there are required parameters, but you still want 229 * to interrogate the options which are specified. 230 */ usageWithRequiredArgsAndResourceBundle()231 public void usageWithRequiredArgsAndResourceBundle() { 232 ArgsHelp argsHelp = new ArgsHelp(); 233 JCommander jc = new JCommander(new Object[]{argsHelp, new ArgsRequired()}, 234 java.util.ResourceBundle.getBundle("MessageBundle")); 235 // Should be able to display usage without triggering validation 236 jc.usage(new StringBuilder()); 237 try { 238 jc.parse("-h"); 239 Assert.fail("Should have thrown a required parameter exception"); 240 } catch (ParameterException e) { 241 Assert.assertTrue(e.getMessage().contains("are required")); 242 } 243 Assert.assertTrue(argsHelp.help); 244 } 245 multiObjects()246 public void multiObjects() { 247 ArgsMaster m = new ArgsMaster(); 248 ArgsSlave s = new ArgsSlave(); 249 String[] argv = { "-master", "master", "-slave", "slave" }; 250 new JCommander(new Object[] { m , s }, argv); 251 252 Assert.assertEquals(m.master, "master"); 253 Assert.assertEquals(s.slave, "slave"); 254 } 255 256 @Test(expectedExceptions = ParameterException.class) multiObjectsWithDuplicatesFail()257 public void multiObjectsWithDuplicatesFail() { 258 ArgsMaster m = new ArgsMaster(); 259 ArgsSlave s = new ArgsSlaveBogus(); 260 String[] argv = { "-master", "master", "-slave", "slave" }; 261 new JCommander(new Object[] { m , s }, argv); 262 } 263 arityString()264 public void arityString() { 265 ArgsArityString args = new ArgsArityString(); 266 String[] argv = { "-pairs", "pair0", "pair1", "rest" }; 267 new JCommander(args, argv); 268 269 Assert.assertEquals(args.pairs.size(), 2); 270 Assert.assertEquals(args.pairs.get(0), "pair0"); 271 Assert.assertEquals(args.pairs.get(1), "pair1"); 272 Assert.assertEquals(args.rest.size(), 1); 273 Assert.assertEquals(args.rest.get(0), "rest"); 274 } 275 276 @Test(expectedExceptions = ParameterException.class) arity2Fail()277 public void arity2Fail() { 278 ArgsArityString args = new ArgsArityString(); 279 String[] argv = { "-pairs", "pair0" }; 280 new JCommander(args, argv); 281 } 282 283 @Test(expectedExceptions = ParameterException.class) multipleUnparsedFail()284 public void multipleUnparsedFail() { 285 ArgsMultipleUnparsed args = new ArgsMultipleUnparsed(); 286 String[] argv = { }; 287 new JCommander(args, argv); 288 } 289 privateArgs()290 public void privateArgs() { 291 ArgsPrivate args = new ArgsPrivate(); 292 new JCommander(args, "-verbose", "3"); 293 Assert.assertEquals(args.getVerbose().intValue(), 3); 294 } 295 converterArgs()296 public void converterArgs() { 297 ArgsConverter args = new ArgsConverter(); 298 String fileName = "a"; 299 new JCommander(args, "-file", "/tmp/" + fileName, 300 "-listStrings", "Tuesday,Thursday", 301 "-listInts", "-1,8", 302 "-listBigDecimals", "-11.52,100.12"); 303 Assert.assertEquals(args.file.getName(), fileName); 304 Assert.assertEquals(args.listStrings.size(), 2); 305 Assert.assertEquals(args.listStrings.get(0), "Tuesday"); 306 Assert.assertEquals(args.listStrings.get(1), "Thursday"); 307 Assert.assertEquals(args.listInts.size(), 2); 308 Assert.assertEquals(args.listInts.get(0).intValue(), -1); 309 Assert.assertEquals(args.listInts.get(1).intValue(), 8); 310 Assert.assertEquals(args.listBigDecimals.size(), 2); 311 Assert.assertEquals(args.listBigDecimals.get(0), new BigDecimal("-11.52")); 312 Assert.assertEquals(args.listBigDecimals.get(1), new BigDecimal("100.12")); 313 } 314 argsBoolean1(String[] params, Boolean expected)315 private void argsBoolean1(String[] params, Boolean expected) { 316 ArgsBooleanArity args = new ArgsBooleanArity(); 317 new JCommander(args, params); 318 Assert.assertEquals(args.debug, expected); 319 } 320 argsBoolean0(String[] params, Boolean expected)321 private void argsBoolean0(String[] params, Boolean expected) { 322 ArgsBooleanArity0 args = new ArgsBooleanArity0(); 323 new JCommander(args, params); 324 Assert.assertEquals(args.debug, expected); 325 } 326 booleanArity1()327 public void booleanArity1() { 328 argsBoolean1(new String[] {}, Boolean.FALSE); 329 argsBoolean1(new String[] { "-debug", "true" }, Boolean.TRUE); 330 } 331 booleanArity0()332 public void booleanArity0() { 333 argsBoolean0(new String[] {}, Boolean.FALSE); 334 argsBoolean0(new String[] { "-debug"}, Boolean.TRUE); 335 } 336 337 @Test(expectedExceptions = ParameterException.class) badParameterShouldThrowParameter1Exception()338 public void badParameterShouldThrowParameter1Exception() { 339 Args1 args = new Args1(); 340 String[] argv = { "-log", "foo" }; 341 new JCommander(args, argv); 342 } 343 344 @Test(expectedExceptions = ParameterException.class) badParameterShouldThrowParameter2Exception()345 public void badParameterShouldThrowParameter2Exception() { 346 Args1 args = new Args1(); 347 String[] argv = { "-long", "foo" }; 348 new JCommander(args, argv); 349 } 350 listParameters()351 public void listParameters() { 352 Args2 a = new Args2(); 353 String[] argv = {"-log", "2", "-groups", "unit", "a", "b", "c", "-host", "host2"}; 354 new JCommander(a, argv); 355 Assert.assertEquals(a.verbose.intValue(), 2); 356 Assert.assertEquals(a.groups, "unit"); 357 Assert.assertEquals(a.hosts, Arrays.asList("host2")); 358 Assert.assertEquals(a.parameters, Arrays.asList("a", "b", "c")); 359 } 360 separatorEqual()361 public void separatorEqual() { 362 SeparatorEqual s = new SeparatorEqual(); 363 String[] argv = { "-log=3", "--longoption=10" }; 364 new JCommander(s, argv); 365 Assert.assertEquals(s.log.intValue(), 3); 366 Assert.assertEquals(s.longOption.intValue(), 10); 367 } 368 separatorColon()369 public void separatorColon() { 370 SeparatorColon s = new SeparatorColon(); 371 String[] argv = { "-verbose:true" }; 372 new JCommander(s, argv); 373 Assert.assertTrue(s.verbose); 374 } 375 separatorBoth()376 public void separatorBoth() { 377 SeparatorColon s = new SeparatorColon(); 378 SeparatorEqual s2 = new SeparatorEqual(); 379 String[] argv = { "-verbose:true", "-log=3" }; 380 new JCommander(new Object[] { s, s2 }, argv); 381 Assert.assertTrue(s.verbose); 382 Assert.assertEquals(s2.log.intValue(), 3); 383 } 384 separatorMixed1()385 public void separatorMixed1() { 386 SeparatorMixed s = new SeparatorMixed(); 387 String[] argv = { "-long:1", "-level=42" }; 388 new JCommander(s, argv); 389 Assert.assertEquals(s.l.longValue(), 1l); 390 Assert.assertEquals(s.level.intValue(), 42); 391 } 392 slashParameters()393 public void slashParameters() { 394 SlashSeparator a = new SlashSeparator(); 395 String[] argv = { "/verbose", "/file", "/tmp/a" }; 396 new JCommander(a, argv); 397 Assert.assertTrue(a.verbose); 398 Assert.assertEquals(a.file, "/tmp/a"); 399 } 400 inheritance()401 public void inheritance() { 402 ArgsInherited args = new ArgsInherited(); 403 String[] argv = { "-log", "3", "-child", "2" }; 404 new JCommander(args, argv); 405 Assert.assertEquals(args.child.intValue(), 2); 406 Assert.assertEquals(args.log.intValue(), 3); 407 } 408 negativeNumber()409 public void negativeNumber() { 410 Args1 a = new Args1(); 411 String[] argv = { "-verbose", "-3" }; 412 new JCommander(a, argv); 413 Assert.assertEquals(a.verbose.intValue(), -3); 414 } 415 416 @Test(expectedExceptions = ParameterException.class) requiredMainParameters()417 public void requiredMainParameters() { 418 ArgsRequired a = new ArgsRequired(); 419 String[] argv = {}; 420 new JCommander(a, argv); 421 } 422 usageShouldNotChange()423 public void usageShouldNotChange() { 424 JCommander jc = new JCommander(new Args1(), new String[]{"-log", "1"}); 425 StringBuilder sb = new StringBuilder(); 426 jc.usage(sb); 427 String expected = sb.toString(); 428 jc = new JCommander(new Args1(), new String[]{"-debug", "-log", "2", "-long", "5"}); 429 sb = new StringBuilder(); 430 jc.usage(sb); 431 String actual = sb.toString(); 432 Assert.assertEquals(actual, expected); 433 } 434 verifyCommandOrdering(String[] commandNames, Object[] commands)435 private void verifyCommandOrdering(String[] commandNames, Object[] commands) { 436 CommandMain cm = new CommandMain(); 437 JCommander jc = new JCommander(cm); 438 439 for (int i = 0; i < commands.length; i++) { 440 jc.addCommand(commandNames[i], commands[i]); 441 } 442 443 Map<String, JCommander> c = jc.getCommands(); 444 Assert.assertEquals(c.size(), commands.length); 445 446 Iterator<String> it = c.keySet().iterator(); 447 for (int i = 0; i < commands.length; i++) { 448 Assert.assertEquals(it.next(), commandNames[i]); 449 } 450 } 451 commandsShouldBeShownInOrderOfInsertion()452 public void commandsShouldBeShownInOrderOfInsertion() { 453 verifyCommandOrdering(new String[] { "add", "commit" }, 454 new Object[] { new CommandAdd(), new CommandCommit() }); 455 verifyCommandOrdering(new String[] { "commit", "add" }, 456 new Object[] { new CommandCommit(), new CommandAdd() }); 457 } 458 459 @DataProvider f()460 public static Object[][] f() { 461 return new Integer[][] { 462 new Integer[] { 3, 5, 1 }, 463 new Integer[] { 3, 8, 1 }, 464 new Integer[] { 3, 12, 2 }, 465 new Integer[] { 8, 12, 2 }, 466 new Integer[] { 9, 10, 1 }, 467 }; 468 } 469 470 @Test(expectedExceptions = ParameterException.class) arity1Fail()471 public void arity1Fail() { 472 final Arity1 arguments = new Arity1(); 473 final JCommander jCommander = new JCommander(arguments); 474 final String[] commands = { 475 "-inspect" 476 }; 477 jCommander.parse(commands); 478 } 479 arity1Success1()480 public void arity1Success1() { 481 final Arity1 arguments = new Arity1(); 482 final JCommander jCommander = new JCommander(arguments); 483 final String[] commands = { 484 "-inspect", "true" 485 }; 486 jCommander.parse(commands); 487 Assert.assertTrue(arguments.inspect); 488 } 489 arity1Success2()490 public void arity1Success2() { 491 final Arity1 arguments = new Arity1(); 492 final JCommander jCommander = new JCommander(arguments); 493 final String[] commands = { 494 "-inspect", "false" 495 }; 496 jCommander.parse(commands); 497 Assert.assertFalse(arguments.inspect); 498 } 499 500 @Parameters(commandDescription = "Help for the given commands.") 501 public static class Help { 502 public static final String NAME = "help"; 503 504 @Parameter(description = "List of commands.") 505 public List<String> commands=new ArrayList<String>(); 506 } 507 508 @Test(expectedExceptions = ParameterException.class, 509 description = "Verify that the main parameter's type is checked to be a List") wrongMainTypeShouldThrow()510 public void wrongMainTypeShouldThrow() { 511 JCommander jc = new JCommander(new ArgsRequiredWrongMain()); 512 jc.parse(new String[] { "f1", "f2" }); 513 } 514 515 @Test(description = "This used to run out of memory") oom()516 public void oom() { 517 JCommander jc = new JCommander(new ArgsOutOfMemory()); 518 jc.usage(new StringBuilder()); 519 } 520 521 @Test getParametersShouldNotNpe()522 public void getParametersShouldNotNpe() { 523 JCommander jc = new JCommander(new Args1()); 524 List<ParameterDescription> parameters = jc.getParameters(); 525 } 526 validationShouldWork1()527 public void validationShouldWork1() { 528 ArgsValidate1 a = new ArgsValidate1(); 529 JCommander jc = new JCommander(a); 530 jc.parse(new String[] { "-age", "2 "}); 531 Assert.assertEquals(a.age, new Integer(2)); 532 } 533 534 @Test(expectedExceptions = ParameterException.class) validationShouldWorkWithDefaultValues()535 public void validationShouldWorkWithDefaultValues() { 536 ArgsValidate2 a = new ArgsValidate2(); 537 new JCommander(a); 538 } 539 540 @Test(expectedExceptions = ParameterException.class) validationShouldWork2()541 public void validationShouldWork2() { 542 ArgsValidate1 a = new ArgsValidate1(); 543 JCommander jc = new JCommander(a); 544 jc.parse(new String[] { "-age", "-2 "}); 545 } 546 atFileCanContainEmptyLines()547 public void atFileCanContainEmptyLines() throws IOException { 548 File f = File.createTempFile("JCommander", null); 549 f.deleteOnExit(); 550 FileWriter fw = new FileWriter(f); 551 fw.write("-log\n"); 552 fw.write("\n"); 553 fw.write("2\n"); 554 fw.close(); 555 new JCommander(new Args1(), "@" + f.getAbsolutePath()); 556 } 557 handleEqualSigns()558 public void handleEqualSigns() { 559 ArgsEquals a = new ArgsEquals(); 560 JCommander jc = new JCommander(a); 561 jc.parse(new String[] { "-args=a=b,b=c" }); 562 Assert.assertEquals(a.args, "a=b,b=c"); 563 } 564 565 @SuppressWarnings("serial") handleSets()566 public void handleSets() { 567 ArgsWithSet a = new ArgsWithSet(); 568 new JCommander(a, new String[] { "-s", "3,1,2" }); 569 Assert.assertEquals(a.set, new TreeSet<Integer>() {{ add(1); add(2); add(3); }}); 570 } 571 572 private static final List<String> V = Arrays.asList("a", "b", "c", "d"); 573 574 @DataProvider variable()575 public Object[][] variable() { 576 return new Object[][] { 577 new Object[] { 0, V.subList(0, 0), V }, 578 new Object[] { 1, V.subList(0, 1), V.subList(1, 4) }, 579 new Object[] { 2, V.subList(0, 2), V.subList(2, 4) }, 580 new Object[] { 3, V.subList(0, 3), V.subList(3, 4) }, 581 new Object[] { 4, V.subList(0, 4), V.subList(4, 4) }, 582 }; 583 } 584 585 @Test(dataProvider = "variable") variableArity(int count, List<String> var, List<String> main)586 public void variableArity(int count, List<String> var, List<String> main) { 587 VariableArity va = new VariableArity(count); 588 new JCommander(va).parse("-variable", "a", "b", "c", "d"); 589 Assert.assertEquals(var, va.var); 590 Assert.assertEquals(main, va.main); 591 } 592 enumArgs()593 public void enumArgs() { 594 ArgsEnum args = new ArgsEnum(); 595 String[] argv = { "-choice", "ONE", "-choices", "ONE", "Two" }; 596 JCommander jc = new JCommander(args, argv); 597 598 Assert.assertEquals(args.choice, ArgsEnum.ChoiceType.ONE); 599 600 List<ChoiceType> expected = Arrays.asList(ChoiceType.ONE, ChoiceType.Two); 601 Assert.assertEquals(expected, args.choices); 602 Assert.assertEquals(jc.getParameters().get(0).getDescription(), 603 "Options: " + EnumSet.allOf((Class<? extends Enum>) ArgsEnum.ChoiceType.class)); 604 605 } 606 enumArgsCaseInsensitive()607 public void enumArgsCaseInsensitive() { 608 ArgsEnum args = new ArgsEnum(); 609 String[] argv = { "-choice", "one"}; 610 JCommander jc = new JCommander(args, argv); 611 612 Assert.assertEquals(args.choice, ArgsEnum.ChoiceType.ONE); 613 } 614 615 @Test(expectedExceptions = ParameterException.class) enumArgsFail()616 public void enumArgsFail() { 617 ArgsEnum args = new ArgsEnum(); 618 String[] argv = { "-choice", "A" }; 619 new JCommander(args, argv); 620 } 621 testListAndSplitters()622 public void testListAndSplitters() { 623 ArgsList al = new ArgsList(); 624 JCommander j = new JCommander(al); 625 j.parse("-groups", "a,b", "-ints", "41,42", "-hp", "localhost:1000;example.com:1001", 626 "-hp2", "localhost:1000,example.com:1001", "-uppercase", "ab,cd"); 627 Assert.assertEquals(al.groups.get(0), "a"); 628 Assert.assertEquals(al.groups.get(1), "b"); 629 Assert.assertEquals(al.ints.get(0).intValue(), 41); 630 Assert.assertEquals(al.ints.get(1).intValue(), 42); 631 Assert.assertEquals(al.hostPorts.get(0).host, "localhost"); 632 Assert.assertEquals(al.hostPorts.get(0).port.intValue(), 1000); 633 Assert.assertEquals(al.hostPorts.get(1).host, "example.com"); 634 Assert.assertEquals(al.hostPorts.get(1).port.intValue(), 1001); 635 Assert.assertEquals(al.hp2.get(1).host, "example.com"); 636 Assert.assertEquals(al.hp2.get(1).port.intValue(), 1001); 637 Assert.assertEquals(al.uppercase.get(0), "AB"); 638 Assert.assertEquals(al.uppercase.get(1), "CD"); 639 } 640 641 @Test(expectedExceptions = ParameterException.class) shouldThrowIfUnknownOption()642 public void shouldThrowIfUnknownOption() { 643 class A { 644 @Parameter(names = "-long") 645 public long l; 646 } 647 A a = new A(); 648 new JCommander(a).parse("-lon", "32"); 649 } 650 651 @Test(expectedExceptions = ParameterException.class) mainParameterShouldBeValidate()652 public void mainParameterShouldBeValidate() { 653 class V implements IParameterValidator { 654 655 @Override 656 public void validate(String name, String value) throws ParameterException { 657 Assert.assertEquals("a", value); 658 } 659 } 660 661 class A { 662 @Parameter(validateWith = V.class) 663 public List<String> m; 664 } 665 666 A a = new A(); 667 new JCommander(a).parse("b"); 668 } 669 670 @Parameters(commandNames = { "--configure" }) 671 public static class ConfigureArgs { 672 } 673 674 public static class BaseArgs { 675 @Parameter(names = { "-h", "--help" }, description = "Show this help screen") 676 private boolean help = false; 677 678 @Parameter(names = { "--version", "-version" }, description = "Show the program version") 679 private boolean version; 680 } 681 commandsWithSamePrefixAsOptionsShouldWork()682 public void commandsWithSamePrefixAsOptionsShouldWork() { 683 BaseArgs a = new BaseArgs(); 684 ConfigureArgs conf = new ConfigureArgs(); 685 JCommander jc = new JCommander(a); 686 jc.addCommand(conf); 687 jc.parse("--configure"); 688 } 689 690 // Tests: 691 // required unparsed parameter 692 @Test(enabled = false, 693 description = "For some reason, this test still asks the password on stdin") askedRequiredPassword()694 public void askedRequiredPassword() { 695 class A { 696 @Parameter(names = { "--password", "-p" }, description = "Private key password", 697 password = true, required = true) 698 public String password; 699 700 @Parameter(names = { "--port", "-o" }, description = "Port to bind server to", 701 required = true) 702 public int port; 703 } 704 A a = new A(); 705 InputStream stdin = System.in; 706 try { 707 System.setIn(new ByteArrayInputStream("password".getBytes())); 708 new JCommander(a,new String[]{"--port", "7","--password"}); 709 Assert.assertEquals(a.port, 7); 710 Assert.assertEquals(a.password, "password"); 711 } finally { 712 System.setIn(stdin); 713 } 714 } 715 dynamicParameters()716 public void dynamicParameters() { 717 class Command { 718 @DynamicParameter(names = {"-P"}, description = "Additional command parameters") 719 private Map<String, String> params = Maps.newHashMap(); 720 } 721 JCommander commander = new JCommander(); 722 Command c = new Command(); 723 commander.addCommand("command", c); 724 commander.parse(new String[] { "command", "-Pparam='name=value'" }); 725 Assert.assertEquals(c.params.get("param"), "'name=value'"); 726 } 727 exeParser()728 public void exeParser() { 729 class Params { 730 @Parameter( names= "-i") 731 private String inputFile; 732 } 733 734 String args[] = { "-i", "" }; 735 Params p = new Params(); 736 new JCommander(p, args); 737 } 738 multiVariableArityList()739 public void multiVariableArityList() { 740 class Params { 741 @Parameter(names = "-paramA", description = "ParamA", variableArity = true) 742 private List<String> paramA = Lists.newArrayList(); 743 744 @Parameter(names = "-paramB", description = "ParamB", variableArity = true) 745 private List<String> paramB = Lists.newArrayList(); 746 } 747 748 { 749 String args[] = { "-paramA", "a1", "a2", "-paramB", "b1", "b2", "b3" }; 750 Params p = new Params(); 751 new JCommander(p, args).parse(); 752 Assert.assertEquals(p.paramA, Arrays.asList(new String[] { "a1", "a2" })); 753 Assert.assertEquals(p.paramB, Arrays.asList(new String[] { "b1", "b2", "b3" })); 754 } 755 756 { 757 String args[] = { "-paramA", "a1", "a2", "-paramB", "b1", "-paramA", "a3" }; 758 Params p = new Params(); 759 new JCommander(p, args).parse(); 760 Assert.assertEquals(p.paramA, Arrays.asList(new String[] { "a1", "a2", "a3" })); 761 Assert.assertEquals(p.paramB, Arrays.asList(new String[] { "b1" })); 762 } 763 } 764 765 @Test(enabled = false, 766 description = "Need to double check that the command description is i18n'ed in the usage") commandKey()767 public void commandKey() { 768 @Parameters(resourceBundle = "MessageBundle", commandDescriptionKey = "command") 769 class Args { 770 @Parameter(names="-myoption", descriptionKey="myoption") 771 private boolean option; 772 } 773 JCommander j = new JCommander(); 774 Args a = new Args(); 775 j.addCommand("comm", a); 776 j.usage(); 777 } 778 tmp()779 public void tmp() { 780 class A { 781 @Parameter(names = "-b") 782 public String b; 783 } 784 new JCommander(new A()).parse(""); 785 } 786 unknownOptionWithDifferentPrefix()787 public void unknownOptionWithDifferentPrefix() { 788 @Parameters(optionPrefixes = "/") 789 class SlashSeparator { 790 791 @Parameter(names = "/verbose") 792 public boolean verbose = false; 793 794 @Parameter(names = "/file") 795 public String file; 796 } 797 SlashSeparator ss = new SlashSeparator(); 798 try { 799 new JCommander(ss).parse("/notAParam"); 800 } catch (ParameterException ex) { 801 boolean result = ex.getMessage().contains("Unknown option"); 802 Assert.assertTrue(result); 803 } 804 } 805 equalSeparator()806 public void equalSeparator() { 807 @Parameters(separators = "=", commandDescription = "My command") 808 class MyClass { 809 810 @Parameter(names = { "-p", "--param" }, required = true, description = "param desc...") 811 private String param; 812 } 813 MyClass c = new MyClass(); 814 String expected = "\"hello\"world"; 815 new JCommander(c).parse("--param=" + expected); 816 Assert.assertEquals(expected, c.param); 817 } 818 simpleArgsSetter()819 public void simpleArgsSetter() throws ParseException { 820 Args1Setter args = new Args1Setter(); 821 String[] argv = { "-debug", "-log", "2", "-float", "1.2", "-double", "1.3", "-bigdecimal", "1.4", 822 "-date", "2011-10-26", "-groups", "unit", "a", "b", "c" }; 823 new JCommander(args, argv); 824 825 Assert.assertTrue(args.debug); 826 Assert.assertEquals(args.verbose.intValue(), 2); 827 Assert.assertEquals(args.groups, "unit"); 828 Assert.assertEquals(args.parameters, Arrays.asList("a", "b", "c")); 829 Assert.assertEquals(args.floa, 1.2f, 0.1f); 830 Assert.assertEquals(args.doub, 1.3f, 0.1f); 831 Assert.assertEquals(args.bigd, new BigDecimal("1.4")); 832 Assert.assertEquals(args.date, new SimpleDateFormat("yyyy-MM-dd").parse("2011-10-26")); 833 } 834 verifyHelp()835 public void verifyHelp() { 836 class Arg { 837 @Parameter(names = "--help", help = true) 838 public boolean help = false; 839 840 @Parameter(names = "file", required = true) 841 public String file; 842 } 843 Arg arg = new Arg(); 844 String[] argv = { "--help" }; 845 new JCommander(arg, argv); 846 847 Assert.assertTrue(arg.help); 848 } 849 helpTest()850 public void helpTest() { 851 class Arg { 852 @Parameter(names = { "?", "-help", "--help" }, description = "Shows help", help = true) 853 private boolean help = false; 854 } 855 Arg arg = new Arg(); 856 JCommander jc = new JCommander(arg); 857 jc.parse(new String[] { "-help" }); 858 // System.out.println("helpTest:" + arg.help); 859 } 860 861 @Test(enabled = false, description = "Should only be enable once multiple parameters are allowed") duplicateParameterNames()862 public void duplicateParameterNames() { 863 class ArgBase { 864 @Parameter(names = { "-host" }) 865 protected String host; 866 } 867 868 class Arg1 extends ArgBase {} 869 Arg1 arg1 = new Arg1(); 870 871 class Arg2 extends ArgBase {} 872 Arg2 arg2 = new Arg2(); 873 874 JCommander jc = new JCommander(new Object[] { arg1, arg2}); 875 jc.parse(new String[] { "-host", "foo" }); 876 Assert.assertEquals(arg1.host, "foo"); 877 Assert.assertEquals(arg2.host, "foo"); 878 } 879 parameterWithOneDoubleQuote()880 public void parameterWithOneDoubleQuote() { 881 @Parameters(separators = "=") 882 class Arg { 883 @Parameter(names = { "-p", "--param" }) 884 private String param; 885 } 886 JCommander jc = new JCommander(new MyClass()); 887 jc.parse("-p=\""); 888 } 889 emptyStringAsDefault()890 public void emptyStringAsDefault() { 891 class Arg { 892 @Parameter(names = "-x") 893 String s = ""; 894 } 895 Arg a = new Arg(); 896 StringBuilder sb = new StringBuilder(); 897 new JCommander(a).usage(sb); 898 Assert.assertTrue(sb.toString().contains("Default: <empty string>")); 899 } 900 spaces()901 public void spaces() { 902 class Arg { 903 @Parameter(names = "-rule", description = "rule") 904 private List<String> rules = new ArrayList<String>(); 905 } 906 Arg a = new Arg(); 907 new JCommander(a, "-rule", "some test"); 908 Assert.assertEquals(a.rules, Arrays.asList("some test")); 909 } 910 911 static class V2 implements IParameterValidator2 { 912 final static List<String> names = Lists.newArrayList(); 913 static boolean validateCalled = false; 914 915 @Override validate(String name, String value)916 public void validate(String name, String value) throws ParameterException { 917 validateCalled = true; 918 } 919 920 @Override validate(String name, String value, ParameterDescription pd)921 public void validate(String name, String value, ParameterDescription pd) 922 throws ParameterException { 923 names.addAll(Arrays.asList(pd.getParameter().names())); 924 } 925 } 926 validator2()927 public void validator2() { 928 class Arg { 929 @Parameter(names = { "-h", "--host" }, validateWith = V2.class) 930 String host; 931 } 932 Arg a = new Arg(); 933 V2.names.clear(); 934 V2.validateCalled = false; 935 JCommander jc = new JCommander(a, "--host", "h"); 936 jc.setAcceptUnknownOptions(true); 937 Assert.assertEquals(V2.names, Arrays.asList(new String[] { "-h", "--host" })); 938 Assert.assertTrue(V2.validateCalled); 939 } 940 usageCommandsUnderUsage()941 public void usageCommandsUnderUsage() { 942 class Arg { 943 } 944 @Parameters(commandDescription = "command a") 945 class ArgCommandA { 946 @Parameter(description = "command a parameters") 947 List<String> parameters; 948 } 949 @Parameters(commandDescription = "command b") 950 class ArgCommandB { 951 @Parameter(description = "command b parameters") 952 List<String> parameters; 953 } 954 955 Arg a = new Arg(); 956 957 JCommander c = new JCommander(a); 958 c.addCommand("a", new ArgCommandA()); 959 c.addCommand("b", new ArgCommandB()); 960 961 StringBuilder sb = new StringBuilder(); 962 c.usage(sb); 963 Assert.assertTrue(sb.toString().contains("[command options]\n Commands:")); 964 } 965 usageWithEmpytLine()966 public void usageWithEmpytLine() { 967 class Arg { 968 } 969 @Parameters(commandDescription = "command a") 970 class ArgCommandA { 971 @Parameter(description = "command a parameters") 972 List<String> parameters; 973 } 974 @Parameters(commandDescription = "command b") 975 class ArgCommandB { 976 @Parameter(description = "command b parameters") 977 List<String> parameters; 978 } 979 980 Arg a = new Arg(); 981 982 JCommander c = new JCommander(a); 983 c.addCommand("a", new ArgCommandA()); 984 c.addCommand("b", new ArgCommandB()); 985 986 StringBuilder sb = new StringBuilder(); 987 c.usage(sb); 988 Assert.assertTrue(sb.toString().contains("command a parameters\n\n b")); 989 } 990 partialValidation()991 public void partialValidation() { 992 class Arg { 993 @Parameter(names = { "-h", "--host" }) 994 String host; 995 } 996 Arg a = new Arg(); 997 JCommander jc = new JCommander(); 998 jc.setAcceptUnknownOptions(true); 999 jc.addObject(a); 1000 jc.parse("-a", "foo", "-h", "host"); 1001 Assert.assertEquals(a.host, "host"); 1002 Assert.assertEquals(jc.getUnknownOptions(), Lists.newArrayList("-a", "foo")); 1003 } 1004 1005 /** 1006 * GITHUB-137. 1007 */ listArgShouldBeCleared()1008 public void listArgShouldBeCleared() { 1009 class Args { 1010 @Parameter(description = "[endpoint]") 1011 public List<String> endpoint = Lists.newArrayList("prod"); 1012 } 1013 Args a = new Args(); 1014 new JCommander(a, new String[] { "dev" }); 1015 Assert.assertEquals(a.endpoint, Lists.newArrayList("dev")); 1016 } 1017 dashDashParameter()1018 public void dashDashParameter() { 1019 class Arguments { 1020 @Parameter(names = { "-name" }) 1021 public String name; 1022 @Parameter 1023 public List<String> mainParameters; 1024 } 1025 1026 Arguments a = new Arguments(); 1027 new JCommander(a, new String[] { 1028 "-name", "theName", "--", "param1", "param2"} 1029 ); 1030 Assert.assertEquals(a.name, "theName"); 1031 Assert.assertEquals(a.mainParameters.size(), 2); 1032 Assert.assertEquals(a.mainParameters.get(0), "param1"); 1033 Assert.assertEquals(a.mainParameters.get(1), "param2"); 1034 } 1035 dashDashParameter2()1036 public void dashDashParameter2() { 1037 class Arguments { 1038 @Parameter(names = { "-name" }) 1039 public String name; 1040 @Parameter 1041 public List<String> mainParameters; 1042 } 1043 1044 Arguments a = new Arguments(); 1045 new JCommander(a, new String[] { 1046 "param1", "param2", "--", "param3", "-name", "theName"} 1047 ); 1048 Assert.assertNull(a.name); 1049 Assert.assertEquals(a.mainParameters.size(), 5); 1050 Assert.assertEquals(a.mainParameters.get(0), "param1"); 1051 Assert.assertEquals(a.mainParameters.get(1), "param2"); 1052 Assert.assertEquals(a.mainParameters.get(2), "param3"); 1053 Assert.assertEquals(a.mainParameters.get(3), "-name"); 1054 Assert.assertEquals(a.mainParameters.get(4), "theName"); 1055 } 1056 1057 @Test(enabled = false) main(String[] args)1058 public static void main(String[] args) throws Exception { 1059 new JCommanderTest().enumArgsFail(); 1060 // class A { 1061 // @Parameter(names = "-short", required = true) 1062 // List<String> parameters; 1063 // 1064 // @Parameter(names = "-long", required = true) 1065 // public long l; 1066 // } 1067 // A a = new A(); 1068 // new JCommander(a).parse(); 1069 // System.out.println(a.l); 1070 // System.out.println(a.parameters); 1071 // ArgsList al = new ArgsList(); 1072 // JCommander j = new JCommander(al); 1073 // j.setColumnSize(40); 1074 // j.usage(); 1075 // new JCommanderTest().testListAndSplitters(); 1076 // new JCommanderTest().converterArgs(); 1077 } 1078 1079 // Tests: 1080 // required unparsed parameter 1081 } 1082