Home | History | Annotate | Download | only in jcommander
      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 {
     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
    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")
    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    */
    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)
    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)
    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    */
    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 
    170   public void multipleNames1() {
    171     multipleNames("-log");
    172   }
    173 
    174   public void multipleNames2() {
    175     multipleNames("-verbose");
    176   }
    177 
    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 
    191   public void i18nNoLocale() {
    192     i18n1("MessageBundle", null, "Host");
    193   }
    194 
    195   public void i18nUsLocale() {
    196     i18n1("MessageBundle", new Locale("en", "US"), "Host");
    197   }
    198 
    199   public void i18nFrLocale() {
    200     i18n1("MessageBundle", new Locale("fr", "FR"), "Hte");
    201   }
    202 
    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(), "Hte");
    209   }
    210 
    211   public void i18nWithResourceAnnotation() {
    212     i18n2(new ArgsI18N2());
    213   }
    214 
    215   public void i18nWithResourceAnnotationNew() {
    216     i18n2(new ArgsI18N2New());
    217   }
    218 
    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    */
    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 
    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)
    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 
    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)
    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)
    284   public void multipleUnparsedFail() {
    285     ArgsMultipleUnparsed args = new ArgsMultipleUnparsed();
    286     String[] argv = { };
    287     new JCommander(args, argv);
    288   }
    289 
    290   public void privateArgs() {
    291     ArgsPrivate args = new ArgsPrivate();
    292     new JCommander(args, "-verbose", "3");
    293     Assert.assertEquals(args.getVerbose().intValue(), 3);
    294   }
    295 
    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 
    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 
    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 
    327   public void booleanArity1() {
    328     argsBoolean1(new String[] {}, Boolean.FALSE);
    329     argsBoolean1(new String[] { "-debug", "true" }, Boolean.TRUE);
    330   }
    331 
    332   public void booleanArity0() {
    333     argsBoolean0(new String[] {}, Boolean.FALSE);
    334     argsBoolean0(new String[] { "-debug"}, Boolean.TRUE);
    335   }
    336 
    337   @Test(expectedExceptions = ParameterException.class)
    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)
    345   public void badParameterShouldThrowParameter2Exception() {
    346     Args1 args = new Args1();
    347     String[] argv = { "-long", "foo" };
    348     new JCommander(args, argv);
    349   }
    350 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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)
    417   public void requiredMainParameters() {
    418     ArgsRequired a = new ArgsRequired();
    419     String[] argv = {};
    420     new JCommander(a, argv);
    421   }
    422 
    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 
    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 
    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
    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)
    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 
    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 
    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")
    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")
    516   public void oom() {
    517     JCommander jc = new JCommander(new ArgsOutOfMemory());
    518     jc.usage(new StringBuilder());
    519   }
    520 
    521   @Test
    522   public void getParametersShouldNotNpe() {
    523     JCommander jc = new JCommander(new Args1());
    524     List<ParameterDescription> parameters = jc.getParameters();
    525   }
    526 
    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)
    535   public void validationShouldWorkWithDefaultValues() {
    536     ArgsValidate2 a = new ArgsValidate2();
    537     new JCommander(a);
    538   }
    539 
    540   @Test(expectedExceptions = ParameterException.class)
    541   public void validationShouldWork2() {
    542     ArgsValidate1 a = new ArgsValidate1();
    543     JCommander jc = new JCommander(a);
    544     jc.parse(new String[] { "-age", "-2 "});
    545   }
    546 
    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 
    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")
    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
    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")
    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 
    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 
    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)
    616   public void enumArgsFail() {
    617     ArgsEnum args = new ArgsEnum();
    618     String[] argv = { "-choice", "A" };
    619     new JCommander(args, argv);
    620   }
    621 
    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)
    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)
    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 
    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")
    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 
    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 
    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 
    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")
    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 
    779   public void tmp() {
    780     class A {
    781       @Parameter(names = "-b")
    782       public String b;
    783     }
    784     new JCommander(new A()).parse("");
    785   }
    786 
    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 
    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 
    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 
    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 
    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")
    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 
    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 
    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 
    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
    916     public void validate(String name, String value) throws ParameterException {
    917       validateCalled = true;
    918     }
    919 
    920     @Override
    921     public void validate(String name, String value, ParameterDescription pd)
    922         throws ParameterException {
    923       names.addAll(Arrays.asList(pd.getParameter().names()));
    924     }
    925   }
    926 
    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 
    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 
    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 
    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    */
   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 
   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 
   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)
   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