• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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