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