• 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  * <p>
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  * <p>
10  * http://www.apache.org/licenses/LICENSE-2.0
11  * <p>
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 com.beust.jcommander.args.*;
22 import com.beust.jcommander.args.ArgsEnum.ChoiceType;
23 import com.beust.jcommander.command.CommandAdd;
24 import com.beust.jcommander.command.CommandCommit;
25 import com.beust.jcommander.command.CommandMain;
26 import com.beust.jcommander.converters.FileConverter;
27 import com.beust.jcommander.internal.Lists;
28 import com.beust.jcommander.internal.Maps;
29 import org.testng.Assert;
30 import org.testng.annotations.DataProvider;
31 import org.testng.annotations.Test;
32 
33 import java.io.*;
34 import java.math.BigDecimal;
35 import java.nio.charset.Charset;
36 import java.text.ParseException;
37 import java.text.SimpleDateFormat;
38 import java.util.*;
39 import java.util.ResourceBundle;
40 
41 @Test
42 public class JCommanderTest {
43 
44     @Test
testLongMainParameterDescription()45     public void testLongMainParameterDescription() {
46         //setup
47         JCommander jc = new JCommander(new ArgsLongMainParameterDescription());
48         StringBuilder sb = new StringBuilder();
49 
50         //action
51         jc.usage(sb);
52 
53         //verify
54         for (String line : sb.toString().split("\n")) {
55             Assert.assertTrue(line.length() <= jc.getColumnSize(), "line length < column size");
56         }
57     }
58 
59     @Test
testLongCommandDescription()60     public void testLongCommandDescription() throws Exception {
61         //setup
62         JCommander jc = new JCommander();
63         jc.addCommand(new ArgsLongCommandDescription());
64         StringBuilder sb = new StringBuilder();
65 
66         //action
67         jc.usage(sb);
68 
69         //verify
70         for (String line : sb.toString().split("\n")) {
71             Assert.assertTrue(line.length() <= jc.getColumnSize(), "line length < column size");
72         }
73     }
74 
75     @Test
testDescriptionWrappingLongWord()76     public void testDescriptionWrappingLongWord() {
77         //setup
78         StringBuilder sb = new StringBuilder();
79         final JCommander jc = new JCommander(new ArgsLongDescription());
80 
81         //action
82         jc.usage(sb);
83 
84         //verify
85         for (String line : sb.toString().split("\n")) {
86             Assert.assertTrue(line.length() <= jc.getColumnSize(), "line length < column size");
87         }
88     }
89 
simpleArgs()90     public void simpleArgs() throws ParseException {
91         Args1 args = new Args1();
92         String[] argv = {"-debug", "-log", "2", "-float", "1.2", "-double", "1.3", "-bigdecimal", "1.4",
93                 "-date", "2011-10-26", "-groups", "unit", "a", "b", "c"};
94         new JCommander(args, argv);
95 
96         Assert.assertTrue(args.debug);
97         Assert.assertEquals(args.verbose.intValue(), 2);
98         Assert.assertEquals(args.groups, "unit");
99         Assert.assertEquals(args.parameters, Arrays.asList("a", "b", "c"));
100         Assert.assertEquals(args.floa, 1.2f, 0.1f);
101         Assert.assertEquals(args.doub, 1.3f, 0.1f);
102         Assert.assertEquals(args.bigd, new BigDecimal("1.4"));
103         Assert.assertEquals(args.date, new SimpleDateFormat("yyyy-MM-dd").parse("2011-10-26"));
104     }
105 
106     @DataProvider
alternateNamesListArgs()107     public Object[][] alternateNamesListArgs() {
108         return new Object[][]{
109                 new String[][]{new String[]{"--servers", "1", "-s", "2", "--servers", "3"}},
110                 new String[][]{new String[]{"-s", "1", "-s", "2", "--servers", "3"}},
111                 new String[][]{new String[]{"--servers", "1", "--servers", "2", "-s", "3"}},
112                 new String[][]{new String[]{"-s", "1", "--servers", "2", "-s", "3"}},
113                 new String[][]{new String[]{"-s", "1", "-s", "2", "--servers", "3"}},
114         };
115     }
116 
117     /**
118      * Confirm that List<?> parameters with alternate names return the correct
119      * List regardless of how the arguments are specified
120      */
121 
122     @Test(dataProvider = "alternateNamesListArgs")
testAlternateNamesForListParameters(String[] argv)123     public void testAlternateNamesForListParameters(String[] argv) {
124         AlternateNamesForListArgs args = new AlternateNamesForListArgs();
125 
126         new JCommander(args, argv);
127 
128         Assert.assertEquals(args.serverNames.size(), 3);
129         Assert.assertEquals(args.serverNames.get(0), argv[1]);
130         Assert.assertEquals(args.serverNames.get(1), argv[3]);
131         Assert.assertEquals(args.serverNames.get(2), argv[5]);
132     }
133 
134 
135     /**
136      * Make sure that if there are args with multiple names (e.g. "-log" and "-verbose"),
137      * the usage will only display it once.
138      */
repeatedArgs()139     public void repeatedArgs() {
140         Args1 args = new Args1();
141         String[] argv = {"-log", "2"};
142         JCommander jc = new JCommander(args, argv);
143         Assert.assertEquals(jc.getParameters().size(), 8);
144     }
145 
146     /**
147      * Not specifying a required option should throw an exception.
148      */
149     @Test(expectedExceptions = ParameterException.class)
requiredFields1Fail()150     public void requiredFields1Fail() {
151         Args1 args = new Args1();
152         String[] argv = {"-debug"};
153         new JCommander(args, argv);
154     }
155 
156     /**
157      * Getting the description of a nonexistent command should throw an exception.
158      */
159     @Test(expectedExceptions = ParameterException.class)
nonexistentCommandShouldThrow()160     public void nonexistentCommandShouldThrow() {
161         String[] argv = {};
162         JCommander jc = new JCommander(new Object(), argv);
163         jc.getCommandDescription("foo");
164     }
165 
166     /**
167      * Required options with multiple names should work with all names.
168      */
multipleNames(String option)169     private void multipleNames(String option) {
170         Args1 args = new Args1();
171         String[] argv = {option, "2"};
172         new JCommander(args, argv);
173         Assert.assertEquals(args.verbose.intValue(), 2);
174     }
175 
multipleNames1()176     public void multipleNames1() {
177         multipleNames("-log");
178     }
179 
multipleNames2()180     public void multipleNames2() {
181         multipleNames("-verbose");
182     }
183 
i18n1(String bundleName, Locale locale, String expectedString)184     private void i18n1(String bundleName, Locale locale, String expectedString) {
185         ResourceBundle bundle = locale != null ? ResourceBundle.getBundle(bundleName, locale)
186                 : null;
187 
188         ArgsI18N1 i18n = new ArgsI18N1();
189         String[] argv = {"-host", "localhost"};
190         JCommander jc = new JCommander(i18n, bundle, argv);
191 
192         ParameterDescription pd = jc.getParameters().get(0);
193         Assert.assertEquals(pd.getDescription(), expectedString);
194     }
195 
i18nNoLocale()196     public void i18nNoLocale() {
197         i18n1("MessageBundle", null, "Host");
198     }
199 
i18nUsLocale()200     public void i18nUsLocale() {
201         i18n1("MessageBundle", new Locale("en", "US"), "Host");
202     }
203 
i18nFrLocale()204     public void i18nFrLocale() {
205         i18n1("MessageBundle", new Locale("fr", "FR"), "Hôte");
206     }
207 
i18n2(Object i18n)208     private void i18n2(Object i18n) {
209         String[] argv = {"-host", "localhost"};
210         Locale.setDefault(new Locale("fr", "FR"));
211         JCommander jc = new JCommander(i18n, argv);
212         ParameterDescription pd = jc.getParameters().get(0);
213         Assert.assertEquals(pd.getDescription(), "Hôte");
214     }
215 
i18nWithResourceAnnotation()216     public void i18nWithResourceAnnotation() {
217         i18n2(new ArgsI18N2());
218     }
219 
i18nWithResourceAnnotationNew()220     public void i18nWithResourceAnnotationNew() {
221         i18n2(new ArgsI18N2New());
222     }
223 
i18MissingKeyForCommand()224     public void i18MissingKeyForCommand() {
225         ResourceBundle bundle = ResourceBundle.getBundle("MessageBundle", new Locale("en", "US"));
226         JCommander jc = new JCommander(new ArgsHelp(), bundle);
227         jc.addCommand(new ArgsLongCommandDescription());
228         StringBuilder sb = new StringBuilder();
229         jc.usage(sb);
230         String usage = sb.toString();
231         Assert.assertTrue(usage.contains("text"));
232     }
233 
noParseConstructor()234     public void noParseConstructor() {
235         JCommander jCommander = new JCommander(new ArgsMainParameter1());
236         jCommander.usage(new StringBuilder());
237         // Before fix, this parse would throw an exception, because it calls createDescription, which
238         // was already called by usage(), and can only be called once.
239         jCommander.parse();
240     }
241 
242     /**
243      * Test a use case where there are required parameters, but you still want
244      * to interrogate the options which are specified.
245      */
usageWithRequiredArgsAndResourceBundle()246     public void usageWithRequiredArgsAndResourceBundle() {
247         ArgsHelp argsHelp = new ArgsHelp();
248         JCommander jc = new JCommander(new Object[]{argsHelp, new ArgsRequired()},
249                 java.util.ResourceBundle.getBundle("MessageBundle"));
250         // Should be able to display usage without triggering validation
251         jc.usage(new StringBuilder());
252         try {
253             jc.parse("-h");
254             Assert.fail("Should have thrown a required parameter exception");
255         } catch (ParameterException e) {
256             Assert.assertTrue(e.getMessage().contains("are required"));
257         }
258         Assert.assertTrue(argsHelp.help);
259     }
260 
multiObjects()261     public void multiObjects() {
262         ArgsMaster m = new ArgsMaster();
263         ArgsSlave s = new ArgsSlave();
264         String[] argv = {"-master", "master", "-slave", "slave"};
265         new JCommander(new Object[]{m, s}, argv);
266 
267         Assert.assertEquals(m.master, "master");
268         Assert.assertEquals(s.slave, "slave");
269     }
270 
271     @Test(expectedExceptions = ParameterException.class)
multiObjectsWithDuplicatesFail()272     public void multiObjectsWithDuplicatesFail() {
273         ArgsMaster m = new ArgsMaster();
274         ArgsSlave s = new ArgsSlaveBogus();
275         String[] argv = {"-master", "master", "-slave", "slave"};
276         new JCommander(new Object[]{m, s}, argv);
277     }
278 
arityString()279     public void arityString() {
280         ArgsArityString args = new ArgsArityString();
281         String[] argv = {"-pairs", "pair0", "pair1", "rest"};
282         new JCommander(args, argv);
283 
284         Assert.assertEquals(args.pairs.size(), 2);
285         Assert.assertEquals(args.pairs.get(0), "pair0");
286         Assert.assertEquals(args.pairs.get(1), "pair1");
287         Assert.assertEquals(args.rest.size(), 1);
288         Assert.assertEquals(args.rest.get(0), "rest");
289     }
290 
291     @Test(expectedExceptions = ParameterException.class)
arity2Fail()292     public void arity2Fail() {
293         ArgsArityString args = new ArgsArityString();
294         String[] argv = {"-pairs", "pair0"};
295         new JCommander(args, argv);
296     }
297 
298     @Test(expectedExceptions = ParameterException.class)
multipleUnparsedFail()299     public void multipleUnparsedFail() {
300         ArgsMultipleUnparsed args = new ArgsMultipleUnparsed();
301         String[] argv = {};
302         new JCommander(args, argv);
303     }
304 
privateArgs()305     public void privateArgs() {
306         ArgsPrivate args = new ArgsPrivate();
307         new JCommander(args, "-verbose", "3");
308         Assert.assertEquals(args.getVerbose().intValue(), 3);
309     }
310 
311     @Test(
312             expectedExceptions = ParameterException.class,
313             expectedExceptionsMessageRegExp = "Cannot use final field .*#_foo as a parameter;"
314                     + " compile-time constant inlining may hide new values written to it.")
finalArgs()315     public void finalArgs() {
316         Object args = new Object() {
317             @Parameter(names = "-foo")
318             final int _foo = 0;
319         };
320         new JCommander(args).usage();
321     }
322 
converterArgs()323     public void converterArgs() {
324         ArgsConverter args = new ArgsConverter();
325         String fileName = "a";
326         new JCommander(args, "-file", "/tmp/" + fileName,
327                 "-listStrings", "Tuesday,Thursday",
328                 "-listInts", "-1,8",
329                 "-listBigDecimals", "-11.52,100.12");
330         Assert.assertEquals(args.file.getName(), fileName);
331         Assert.assertEquals(args.listStrings.size(), 2);
332         Assert.assertEquals(args.listStrings.get(0), "Tuesday");
333         Assert.assertEquals(args.listStrings.get(1), "Thursday");
334         Assert.assertEquals(args.listInts.size(), 2);
335         Assert.assertEquals(args.listInts.get(0).intValue(), -1);
336         Assert.assertEquals(args.listInts.get(1).intValue(), 8);
337         Assert.assertEquals(args.listBigDecimals.size(), 2);
338         Assert.assertEquals(args.listBigDecimals.get(0), new BigDecimal("-11.52"));
339         Assert.assertEquals(args.listBigDecimals.get(1), new BigDecimal("100.12"));
340     }
341 
hiddenConverter()342     public void hiddenConverter() {
343         class Args {
344             @Parameter(names = "--path", converter = HiddenConverter.class)
345             public String path;
346         }
347 
348         new JCommander(new Args(), "--path", "/tmp/a");
349     }
350 
hiddenArgs()351     public void hiddenArgs() {
352         new JCommander(new HiddenArgs(), "--input", "/tmp/a", "--output", "/tmp/b");
353     }
354 
hiddenSplitter()355     public void hiddenSplitter() {
356         class Args {
357             @Parameter(names = "--extensions", splitter = HiddenParameterSplitter.class)
358             public List<String> extensions;
359         }
360         if (HiddenParameterSplitter.class.getConstructors().length == 0) {
361             return; // Compiler has optimised away the private constructor
362         }
363 
364         Args args = new Args();
365         new JCommander(args, "--extensions", ".txt;.md");
366         Assert.assertEquals(Arrays.asList(".txt", ".md"), args.extensions);
367     }
368 
argsBoolean1(String[] params, Boolean expected)369     private void argsBoolean1(String[] params, Boolean expected) {
370         ArgsBooleanArity args = new ArgsBooleanArity();
371         new JCommander(args, params);
372         Assert.assertEquals(args.debug, expected);
373     }
374 
argsBoolean0(String[] params, Boolean expected)375     private void argsBoolean0(String[] params, Boolean expected) {
376         ArgsBooleanArity0 args = new ArgsBooleanArity0();
377         new JCommander(args, params);
378         Assert.assertEquals(args.debug, expected);
379     }
380 
booleanArity1()381     public void booleanArity1() {
382         argsBoolean1(new String[]{}, Boolean.FALSE);
383         argsBoolean1(new String[]{"-debug", "true"}, Boolean.TRUE);
384     }
385 
booleanArity0()386     public void booleanArity0() {
387         argsBoolean0(new String[]{}, Boolean.FALSE);
388         argsBoolean0(new String[]{"-debug"}, Boolean.TRUE);
389     }
390 
391     @Test(expectedExceptions = ParameterException.class)
badParameterShouldThrowParameter1Exception()392     public void badParameterShouldThrowParameter1Exception() {
393         Args1 args = new Args1();
394         String[] argv = {"-log", "foo"};
395         new JCommander(args, argv);
396     }
397 
398     @Test(expectedExceptions = ParameterException.class)
badParameterShouldThrowParameter2Exception()399     public void badParameterShouldThrowParameter2Exception() {
400         Args1 args = new Args1();
401         String[] argv = {"-long", "foo"};
402         new JCommander(args, argv);
403     }
404 
listParameters()405     public void listParameters() {
406         Args2 a = new Args2();
407         String[] argv = {"-log", "2", "-groups", "unit", "a", "b", "c", "-host", "host2"};
408         new JCommander(a, argv);
409         Assert.assertEquals(a.verbose.intValue(), 2);
410         Assert.assertEquals(a.groups, "unit");
411         Assert.assertEquals(a.hosts, Arrays.asList("host2"));
412         Assert.assertEquals(a.parameters, Arrays.asList("a", "b", "c"));
413     }
414 
separatorEqual()415     public void separatorEqual() {
416         SeparatorEqual s = new SeparatorEqual();
417         String[] argv = {"-log=3", "--longoption=10"};
418         new JCommander(s, argv);
419         Assert.assertEquals(s.log.intValue(), 3);
420         Assert.assertEquals(s.longOption.intValue(), 10);
421     }
422 
separatorColon()423     public void separatorColon() {
424         SeparatorColon s = new SeparatorColon();
425         String[] argv = {"-verbose:true"};
426         new JCommander(s, argv);
427         Assert.assertTrue(s.verbose);
428     }
429 
separatorBoth()430     public void separatorBoth() {
431         SeparatorColon s = new SeparatorColon();
432         SeparatorEqual s2 = new SeparatorEqual();
433         String[] argv = {"-verbose:true", "-log=3"};
434         new JCommander(new Object[]{s, s2}, argv);
435         Assert.assertTrue(s.verbose);
436         Assert.assertEquals(s2.log.intValue(), 3);
437     }
438 
separatorMixed1()439     public void separatorMixed1() {
440         SeparatorMixed s = new SeparatorMixed();
441         String[] argv = {"-long:1", "-level=42"};
442         new JCommander(s, argv);
443         Assert.assertEquals(s.l.longValue(), 1l);
444         Assert.assertEquals(s.level.intValue(), 42);
445     }
446 
slashParameters()447     public void slashParameters() {
448         SlashSeparator a = new SlashSeparator();
449         String[] argv = {"/verbose", "/file", "/tmp/a"};
450         new JCommander(a, argv);
451         Assert.assertTrue(a.verbose);
452         Assert.assertEquals(a.file, "/tmp/a");
453     }
454 
inheritance()455     public void inheritance() {
456         ArgsInherited args = new ArgsInherited();
457         String[] argv = {"-log", "3", "-child", "2"};
458         new JCommander(args, argv);
459         Assert.assertEquals(args.child.intValue(), 2);
460         Assert.assertEquals(args.log.intValue(), 3);
461     }
462 
negativeNumber()463     public void negativeNumber() {
464         Args1 a = new Args1();
465         String[] argv = {"-verbose", "-3"};
466         new JCommander(a, argv);
467         Assert.assertEquals(a.verbose.intValue(), -3);
468     }
469 
470     @Test(expectedExceptions = ParameterException.class)
requiredMainParameters()471     public void requiredMainParameters() {
472         ArgsRequired a = new ArgsRequired();
473         String[] argv = {};
474         new JCommander(a, argv);
475     }
476 
usageShouldNotChange()477     public void usageShouldNotChange() {
478         JCommander jc = new JCommander(new Args1(), "-log", "1");
479         StringBuilder sb = new StringBuilder();
480         jc.usage(sb);
481         String expected = sb.toString();
482         jc = new JCommander(new Args1(), "-debug", "-log", "2", "-long", "5");
483         sb = new StringBuilder();
484         jc.usage(sb);
485         String actual = sb.toString();
486         Assert.assertEquals(actual, expected);
487     }
488 
verifyCommandOrdering(String[] commandNames, Object[] commands)489     private void verifyCommandOrdering(String[] commandNames, Object[] commands) {
490         CommandMain cm = new CommandMain();
491         JCommander jc = new JCommander(cm);
492 
493         for (int i = 0; i < commands.length; i++) {
494             jc.addCommand(commandNames[i], commands[i]);
495         }
496 
497         Map<String, JCommander> c = jc.getCommands();
498         Assert.assertEquals(c.size(), commands.length);
499 
500         Iterator<String> it = c.keySet().iterator();
501         for (int i = 0; i < commands.length; i++) {
502             Assert.assertEquals(it.next(), commandNames[i]);
503         }
504     }
505 
commandsShouldBeShownInOrderOfInsertion()506     public void commandsShouldBeShownInOrderOfInsertion() {
507         verifyCommandOrdering(new String[]{"add", "commit"},
508                 new Object[]{new CommandAdd(), new CommandCommit()});
509         verifyCommandOrdering(new String[]{"commit", "add"},
510                 new Object[]{new CommandCommit(), new CommandAdd()});
511     }
512 
513     @DataProvider
f()514     public static Object[][] f() {
515         return new Integer[][]{
516                 new Integer[]{3, 5, 1},
517                 new Integer[]{3, 8, 1},
518                 new Integer[]{3, 12, 2},
519                 new Integer[]{8, 12, 2},
520                 new Integer[]{9, 10, 1},
521         };
522     }
523 
524     @Test(expectedExceptions = ParameterException.class)
arity1Fail()525     public void arity1Fail() {
526         final Arity1 arguments = new Arity1();
527         final JCommander jCommander = new JCommander(arguments);
528         final String[] commands = {
529                 "-inspect"
530         };
531         jCommander.parse(commands);
532     }
533 
arity1Success1()534     public void arity1Success1() {
535         final Arity1 arguments = new Arity1();
536         final JCommander jCommander = new JCommander(arguments);
537         final String[] commands = {
538                 "-inspect", "true"
539         };
540         jCommander.parse(commands);
541         Assert.assertTrue(arguments.inspect);
542     }
543 
arity1Success2()544     public void arity1Success2() {
545         final Arity1 arguments = new Arity1();
546         final JCommander jCommander = new JCommander(arguments);
547         final String[] commands = {
548                 "-inspect", "false"
549         };
550         jCommander.parse(commands);
551         Assert.assertFalse(arguments.inspect);
552     }
553 
554     @Parameters(commandDescription = "Help for the given commands.")
555     public static class Help {
556         public static final String NAME = "help";
557 
558         @Parameter(description = "List of commands.")
559         public List<String> commands = new ArrayList<>();
560     }
561 
562     @Test(expectedExceptions = ParameterException.class,
563             description = "Verify that the main parameter's type is checked to be a List")
wrongMainTypeShouldThrow()564     public void wrongMainTypeShouldThrow() {
565         JCommander jc = new JCommander(new ArgsRequiredWrongMain());
566         jc.parse("f1", "f2");
567     }
568 
569     @Test(description = "This used to run out of memory")
oom()570     public void oom() {
571         JCommander jc = new JCommander(new ArgsOutOfMemory());
572         jc.usage(new StringBuilder());
573     }
574 
575     @Test
getParametersShouldNotNpe()576     public void getParametersShouldNotNpe() {
577         JCommander jc = new JCommander(new Args1());
578         List<ParameterDescription> parameters = jc.getParameters();
579     }
580 
validationShouldWork1()581     public void validationShouldWork1() {
582         ArgsValidate1 a = new ArgsValidate1();
583         JCommander jc = new JCommander(a);
584         jc.parse("-age", "2 ");
585         Assert.assertEquals(a.age, new Integer(2));
586     }
587 
588     @Test(expectedExceptions = ParameterException.class)
validationShouldWorkWithDefaultValues()589     public void validationShouldWorkWithDefaultValues() {
590         ArgsValidate2 a = new ArgsValidate2();
591         new JCommander(a).usage();
592     }
593 
594     @Test
multipleValidators()595     public void multipleValidators() {
596         for (int i = 1; i < 100; i += 2) {
597             ArgsMultiValidate a = new ArgsMultiValidate();
598             JCommander jc = new JCommander(a);
599             jc.parse("-age", String.valueOf(i));
600         }
601     }
602 
603     @Test(expectedExceptions = ParameterException.class)
multipleValidatorsFails1()604     public void multipleValidatorsFails1() {
605         ArgsMultiValidate a = new ArgsMultiValidate();
606         JCommander jc = new JCommander(a);
607         jc.parse("-age", "131");
608     }
609 
610     @Test(expectedExceptions = ParameterException.class)
multipleValidatorsFails2()611     public void multipleValidatorsFails2() {
612         ArgsMultiValidate a = new ArgsMultiValidate();
613         JCommander jc = new JCommander(a);
614         jc.parse("-age", "0");
615     }
616 
617     @Test(expectedExceptions = ParameterException.class)
validationShouldWork2()618     public void validationShouldWork2() {
619         ArgsValidate1 a = new ArgsValidate1();
620         JCommander jc = new JCommander(a);
621         jc.parse("-age", "-2 ");
622     }
623 
624     @Test
validationShouldReceiveRightParameterName()625     public void validationShouldReceiveRightParameterName() {
626         ArgMultiNameValidator validator = new ArgMultiNameValidator();
627         JCommander jc = new JCommander(validator);
628         String paramName = "-name2";
629         jc.parse(paramName, "param1");
630         Assert.assertEquals(ArgMultiNameValidator.MultiNameValidator.parsedName, paramName);
631     }
632 
atFileCanContainEmptyLines()633     public void atFileCanContainEmptyLines() throws IOException {
634         File f = File.createTempFile("JCommander", null);
635         f.deleteOnExit();
636         FileWriter fw = new FileWriter(f);
637         fw.write("-log\n");
638         fw.write("\n");
639         fw.write("2\n");
640         fw.close();
641         new JCommander(new Args1(), "@" + f.getAbsolutePath());
642     }
643 
atFileWithInNonDefaultCharset()644     public void atFileWithInNonDefaultCharset() throws IOException {
645         final Charset utf32 = Charset.forName("UTF-32");
646         final File f = File.createTempFile("JCommander", null);
647         f.deleteOnExit();
648         try (OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(f), utf32)) {
649             fw.write("-log\n");
650             fw.write("2\n");
651             fw.write("-groups\n");
652             fw.write("\u9731\n");
653         }
654         final Args1 args1 = new Args1();
655         final JCommander jc = new JCommander(args1);
656         try {
657             jc.parse("@" + f.getAbsolutePath());
658             throw new IllegalStateException("Expected exception to be thrown");
659         } catch (ParameterException expected) {
660             Assert.assertTrue(expected.getMessage().startsWith("Could not read file"));
661         }
662         jc.setAtFileCharset(utf32);
663         jc.parse("@" + f.getAbsolutePath());
664         Assert.assertEquals("\u9731", args1.groups);
665     }
666 
handleEqualSigns()667     public void handleEqualSigns() {
668         ArgsEquals a = new ArgsEquals();
669         JCommander jc = new JCommander(a);
670         jc.parse("-args=a=b,b=c");
671         Assert.assertEquals(a.args, "a=b,b=c");
672     }
673 
674     @SuppressWarnings("serial")
handleSets()675     public void handleSets() {
676         ArgsWithSet a = new ArgsWithSet();
677         new JCommander(a, "-s", "3,1,2");
678         Assert.assertEquals(a.set, new TreeSet<Integer>() {{
679             add(1);
680             add(2);
681             add(3);
682         }});
683     }
684 
685     private static final List<String> V = Arrays.asList("a", "b", "c", "d");
686 
687     @DataProvider
variable()688     public Object[][] variable() {
689         return new Object[][]{
690                 //new Object[]{0, V.subList(0, 0), V},
691                 new Object[]{1, V.subList(0, 1), V.subList(1, 4)},
692                 new Object[]{2, V.subList(0, 2), V.subList(2, 4)},
693                 new Object[]{3, V.subList(0, 3), V.subList(3, 4)},
694                 new Object[]{4, V.subList(0, 4), V.subList(4, 4)},
695         };
696     }
697 
698     @Test(dataProvider = "variable")
variableArity(int count, List<String> var, List<String> main)699     public void variableArity(int count, List<String> var, List<String> main) {
700         VariableArity va = new VariableArity(count);
701         new JCommander(va).parse("-variable", "a", "b", "c", "d");
702         Assert.assertEquals(var, va.var);
703         Assert.assertEquals(main, va.main);
704     }
705 
706     @Test(expectedExceptions = ParameterException.class)
variableArityZeroNonBoolean()707     public void variableArityZeroNonBoolean() {
708         VariableArity va = new VariableArity(0);
709         new JCommander(va).parse("-variable", "a", "b", "c", "d");
710     }
711 
enumArgs()712     public void enumArgs() {
713         ArgsEnum args = new ArgsEnum();
714         String[] argv = {"-choice", "ONE", "-choices", "ONE", "Two"};
715         JCommander jc = new JCommander(args, argv);
716 
717         Assert.assertEquals(args.choice, ArgsEnum.ChoiceType.ONE);
718 
719         List<ChoiceType> expected = Arrays.asList(ChoiceType.ONE, ChoiceType.Two);
720         Assert.assertEquals(expected, args.choices);
721 
722         for (ParameterDescription param : jc.getParameters()) {
723             // order can vary depending on JDK version
724             if (param.getLongestName().equals("-choice")) {
725                 Assert.assertEquals(param.getDescription(),
726                         "Options: " + EnumSet.allOf((Class<? extends Enum>) ArgsEnum.ChoiceType.class));
727                 return;
728             }
729         }
730         Assert.fail("Could not find -choice parameter.");
731     }
732 
enumArgs2()733     public void enumArgs2() {
734         // issue #266
735         ArgsEnum args = new ArgsEnum();
736         new JCommander(args, "-choices", "ONE,Two");
737         Assert.assertEquals(Arrays.asList(ChoiceType.ONE, ChoiceType.Two), args.choices);
738     }
739 
enumArgsCaseInsensitive()740     public void enumArgsCaseInsensitive() {
741         ArgsEnum args = new ArgsEnum();
742         String[] argv = {"-choice", "one"};
743         JCommander jc = new JCommander(args, argv);
744 
745         Assert.assertEquals(args.choice, ArgsEnum.ChoiceType.ONE);
746     }
747 
748     @Test(expectedExceptions = ParameterException.class)
enumArgsFail()749     public void enumArgsFail() {
750         ArgsEnum args = new ArgsEnum();
751         String[] argv = {"-choice", "A"};
752         new JCommander(args, argv);
753     }
754 
755     @Test
testDefaultListConverterForString()756     public void testDefaultListConverterForString() {
757         ArgsList al = new ArgsList();
758         JCommander j = new JCommander(al);
759         j.parse("-groups", "a,b");
760         Assert.assertEquals(al.groups.get(0), "a");
761         Assert.assertEquals(al.groups.get(1), "b");
762     }
763 
764     @Test
testDefaultListConverterForStandardType()765     public void testDefaultListConverterForStandardType() {
766         ArgsList al = new ArgsList();
767         JCommander j = new JCommander(al);
768         j.parse("-ints", "41,42");
769         Assert.assertEquals(al.ints.get(0).intValue(), 41);
770         Assert.assertEquals(al.ints.get(1).intValue(), 42);
771     }
772 
773     @Test
testDefaultListConverterWithCustomConverterAndSplitter()774     public void testDefaultListConverterWithCustomConverterAndSplitter() {
775         ArgsList al = new ArgsList();
776         JCommander j = new JCommander(al);
777         j.parse("-hp", "localhost:1000;example.com:1001");
778         Assert.assertEquals(al.hostPorts.get(0).host, "localhost");
779         Assert.assertEquals(al.hostPorts.get(0).port.intValue(), 1000);
780         Assert.assertEquals(al.hostPorts.get(1).host, "example.com");
781         Assert.assertEquals(al.hostPorts.get(1).port.intValue(), 1001);
782     }
783 
784     @Test
testDefaultListConverterWithCustomConverterAndDefaultSplitter()785     public void testDefaultListConverterWithCustomConverterAndDefaultSplitter() {
786         ArgsList al = new ArgsList();
787         JCommander j = new JCommander(al);
788         j.parse("-hp2", "localhost:1000,example.com:1001");
789         Assert.assertEquals(al.hp2.get(1).host, "example.com");
790         Assert.assertEquals(al.hp2.get(1).port.intValue(), 1001);
791     }
792 
793     @Test
testCustomListConverter()794     public void testCustomListConverter() {
795         ArgsList al = new ArgsList();
796         JCommander j = new JCommander(al);
797         j.parse("-uppercase", "ab,cd");
798         Assert.assertEquals(al.uppercase.get(0), "AB");
799         Assert.assertEquals(al.uppercase.get(1), "CD");
800     }
801 
802     @Test(expectedExceptions = ParameterException.class)
shouldThrowIfUnknownOption()803     public void shouldThrowIfUnknownOption() {
804         class A {
805             @Parameter(names = "-long")
806             public long l;
807         }
808         A a = new A();
809         new JCommander(a).parse("-lon", "32");
810     }
811 
812     @Test(expectedExceptions = ParameterException.class)
mainParameterShouldBeValidate()813     public void mainParameterShouldBeValidate() {
814         class V implements IParameterValidator {
815 
816             @Override
817             public void validate(String name, String value) throws ParameterException {
818                 Assert.assertEquals("a", value);
819             }
820         }
821 
822         class A {
823             @Parameter(validateWith = V.class)
824             public List<String> m;
825         }
826 
827         A a = new A();
828         new JCommander(a).parse("b");
829     }
830 
831     @Parameters(commandNames = {"--configure"})
832     public static class ConfigureArgs {
833     }
834 
835     public static class BaseArgs {
836         @Parameter(names = {"-h", "--help"}, description = "Show this help screen")
837         private boolean help = false;
838 
839         @Parameter(names = {"--version", "-version"}, description = "Show the program version")
840         private boolean version;
841     }
842 
commandsWithSamePrefixAsOptionsShouldWork()843     public void commandsWithSamePrefixAsOptionsShouldWork() {
844         BaseArgs a = new BaseArgs();
845         ConfigureArgs conf = new ConfigureArgs();
846         JCommander jc = new JCommander(a);
847         jc.addCommand(conf);
848         jc.parse("--configure");
849     }
850 
dynamicParameters()851     public void dynamicParameters() {
852         class Command {
853             @DynamicParameter(names = {"-P"}, description = "Additional command parameters")
854             private Map<String, String> params = Maps.newHashMap();
855         }
856         JCommander commander = new JCommander();
857         Command c = new Command();
858         commander.addCommand("command", c);
859         commander.parse("command", "-Pparam='name=value'");
860         Assert.assertEquals(c.params.get("param"), "'name=value'");
861     }
862 
exeParser()863     public void exeParser() {
864         class Params {
865             @Parameter(names = "-i")
866             private String inputFile;
867         }
868 
869         String args[] = {"-i", ""};
870         Params p = new Params();
871         new JCommander(p, args);
872     }
873 
multiVariableArityList()874     public void multiVariableArityList() {
875         class Params {
876             @Parameter(names = "-paramA", description = "ParamA", variableArity = true)
877             private List<String> paramA = Lists.newArrayList();
878 
879             @Parameter(names = "-paramB", description = "ParamB", variableArity = true)
880             private List<String> paramB = Lists.newArrayList();
881         }
882 
883         {
884             String args[] = {"-paramA", "a1", "a2", "-paramB", "b1", "b2", "b3"};
885             Params p = new Params();
886             new JCommander(p, args).parse();
887             Assert.assertEquals(p.paramA, Arrays.asList("a1", "a2"));
888             Assert.assertEquals(p.paramB, Arrays.asList("b1", "b2", "b3"));
889         }
890 
891         {
892             String args[] = {"-paramA", "a1", "a2", "-paramB", "b1", "-paramA", "a3"};
893             Params p = new Params();
894             new JCommander(p, args).parse();
895             Assert.assertEquals(p.paramA, Arrays.asList("a1", "a2", "a3"));
896             Assert.assertEquals(p.paramB, Arrays.asList("b1"));
897         }
898     }
899 
900     @Test(enabled = false,
901             description = "Need to double check that the command description is i18n'ed in the usage")
commandKey()902     public void commandKey() {
903         @Parameters(resourceBundle = "MessageBundle", commandDescriptionKey = "command")
904         class Args {
905             @Parameter(names = "-myoption", descriptionKey = "myoption")
906             private boolean option;
907         }
908         JCommander j = new JCommander();
909         Args a = new Args();
910         j.addCommand("comm", a);
911         j.usage();
912     }
913 
914     @Test(expectedExceptions = ParameterException.class,
915             expectedExceptionsMessageRegExp = "Was passed main parameter '' but no main parameter was defined.*")
tmp()916     public void tmp() {
917         class A {
918             @Parameter(names = "-b")
919             public String b;
920         }
921         new JCommander(new A()).parse("");
922     }
923 
924     @Test(expectedExceptions = ParameterException.class, expectedExceptionsMessageRegExp = "\"--b\": couldn't convert \"ThisIsATest\" to an integer")
multipleParameterNames()925     public void multipleParameterNames() {
926         class MultipleParameterNames {
927             @Parameter(names = {"-b", "--b"})
928             public Integer b;
929         }
930         new JCommander(new MultipleParameterNames()).parse("--b", "ThisIsATest");
931     }
932 
unknownOptionWithDifferentPrefix()933     public void unknownOptionWithDifferentPrefix() {
934         @Parameters
935         class SlashSeparator {
936 
937             @Parameter(names = "/verbose")
938             public boolean verbose = false;
939 
940             @Parameter(names = "/file")
941             public String file;
942         }
943         SlashSeparator ss = new SlashSeparator();
944         try {
945             new JCommander(ss).parse("/notAParam");
946         } catch (ParameterException ex) {
947             boolean result = ex.getMessage().contains("in your arg class");
948             Assert.assertTrue(result);
949         }
950     }
951 
equalSeparator()952     public void equalSeparator() {
953         @Parameters(separators = "=", commandDescription = "My command")
954         class MyClass {
955 
956             @Parameter(names = {"-p", "--param"}, required = true, description = "param desc...")
957             private String param;
958         }
959         MyClass c = new MyClass();
960         String expected = "\"hello\"world";
961         new JCommander(c).parse("--param=" + expected);
962         Assert.assertEquals(expected, c.param);
963     }
964 
simpleArgsSetter()965     public void simpleArgsSetter() throws ParseException {
966         Args1Setter args = new Args1Setter();
967         String[] argv = {"-debug", "-log", "2", "-float", "1.2", "-double", "1.3", "-bigdecimal", "1.4",
968                 "-date", "2011-10-26", "-groups", "unit", "a", "b", "c"};
969         new JCommander(args, argv);
970 
971         Assert.assertTrue(args.debug);
972         Assert.assertEquals(args.verbose.intValue(), 2);
973         Assert.assertEquals(args.groups, "unit");
974         Assert.assertEquals(args.parameters, Arrays.asList("a", "b", "c"));
975         Assert.assertEquals(args.floa, 1.2f, 0.1f);
976         Assert.assertEquals(args.doub, 1.3f, 0.1f);
977         Assert.assertEquals(args.bigd, new BigDecimal("1.4"));
978         Assert.assertEquals(args.date, new SimpleDateFormat("yyyy-MM-dd").parse("2011-10-26"));
979     }
980 
verifyHelp()981     public void verifyHelp() {
982         class Arg {
983             @Parameter(names = "--help", help = true)
984             public boolean help = false;
985 
986             @Parameter(names = "file", required = true)
987             public String file;
988         }
989         Arg arg = new Arg();
990         String[] argv = {"--help"};
991         new JCommander(arg, argv);
992 
993         Assert.assertTrue(arg.help);
994     }
995 
helpTest()996     public void helpTest() {
997         class Arg {
998             @Parameter(names = {"?", "-help", "--help"}, description = "Shows help", help = true)
999             private boolean help = false;
1000         }
1001         Arg arg = new Arg();
1002         JCommander jc = new JCommander(arg);
1003         jc.parse("-help");
1004     }
1005 
1006     @Test
doNotDisplayHelpDefaultValue()1007     public void doNotDisplayHelpDefaultValue() {
1008         class Arg {
1009             @Parameter(names = "--help", help = true)
1010             public boolean help = false;
1011         }
1012         Arg arg = new Arg();
1013         String[] argv = {"--help"};
1014         JCommander jc = new JCommander(arg, argv);
1015 
1016         StringBuilder sb = new StringBuilder();
1017 
1018         jc.usage(sb);
1019 
1020         Assert.assertFalse(sb.toString().contains("Default"));
1021     }
1022 
1023     @Test(enabled = false, description = "Should only be enable once multiple parameters are allowed")
duplicateParameterNames()1024     public void duplicateParameterNames() {
1025         class ArgBase {
1026             @Parameter(names = {"-host"})
1027             protected String host;
1028         }
1029 
1030         class Arg1 extends ArgBase {
1031         }
1032         Arg1 arg1 = new Arg1();
1033 
1034         class Arg2 extends ArgBase {
1035         }
1036         Arg2 arg2 = new Arg2();
1037 
1038         JCommander jc = new JCommander(new Object[]{arg1, arg2});
1039         jc.parse("-host", "foo");
1040         Assert.assertEquals(arg1.host, "foo");
1041         Assert.assertEquals(arg2.host, "foo");
1042     }
1043 
1044     @Test(enabled = true, description = "Disable top-level @/ampersand file expansion")
disabledAtSignExpansionTest()1045     public void disabledAtSignExpansionTest() {
1046         class Params {
1047             @Parameter(names = {"-username"})
1048             protected String username;
1049         }
1050 
1051         Params params = new Params();
1052 
1053         JCommander jc = new JCommander(params);
1054         jc.setExpandAtSign(false);
1055         jc.parse("-username", "@tzellman");
1056         Assert.assertEquals(params.username, "@tzellman");
1057     }
1058 
1059     @Test(enabled = true, description = "Enable top-level @/ampersand file expansion, which should throw in this case",
1060             expectedExceptions = ParameterException.class)
enabledAtSignExpansionTest()1061     public void enabledAtSignExpansionTest() {
1062         class Params {
1063             @Parameter(names = {"-username"})
1064             protected String username;
1065         }
1066 
1067         Params params = new Params();
1068 
1069         JCommander jc = new JCommander(params);
1070         jc.parse("-username", "@tzellman");
1071         Assert.assertEquals(params.username, "@tzellman");
1072     }
1073 
parameterWithOneDoubleQuote()1074     public void parameterWithOneDoubleQuote() {
1075         @Parameters(separators = "=")
1076         class Arg {
1077             @Parameter(names = {"-p", "--param"})
1078             private String param;
1079         }
1080         JCommander jc = new JCommander(new MyClass());
1081         jc.parse("-p=\"");
1082     }
1083 
emptyStringAsDefault()1084     public void emptyStringAsDefault() {
1085         class Arg {
1086             @Parameter(names = "-x")
1087             String s = "";
1088         }
1089         Arg a = new Arg();
1090         StringBuilder sb = new StringBuilder();
1091         new JCommander(a).usage(sb);
1092         Assert.assertTrue(sb.toString().contains("Default: <empty string>"));
1093     }
1094 
1095     @Test
emptyStringShouldBeConsideredAsParameter()1096     public void emptyStringShouldBeConsideredAsParameter() {
1097         class Arg {
1098             @Parameter(description = "parameters")
1099             List<String> params;
1100         }
1101 
1102         Arg a = new Arg();
1103         String[] args = {""};
1104 
1105         new JCommander(a).parse(args);
1106         Assert.assertEquals(a.params.size(), 1);
1107 //    Assert.assertEquals();
1108     }
1109 
1110     @Test
doubleQuotedStringShouldBeConsideredAsParameter()1111     public void doubleQuotedStringShouldBeConsideredAsParameter() {
1112         class Arg {
1113             @Parameter(description = "parameters")
1114             List<String> params;
1115         }
1116 
1117         Arg a = new Arg();
1118         String[] args = {"\"\""};
1119 
1120         new JCommander(a).parse(args);
1121         Assert.assertEquals(a.params.size(), 1);
1122 //    Assert.assertEquals();
1123     }
1124 
spaces()1125     public void spaces() {
1126         class Arg {
1127             @Parameter(names = "-rule", description = "rule")
1128             private List<String> rules = new ArrayList<>();
1129         }
1130         Arg a = new Arg();
1131         new JCommander(a, "-rule", "some test");
1132         Assert.assertEquals(a.rules, Arrays.asList("some test"));
1133     }
1134 
1135     static class V2 implements IParameterValidator2 {
1136         final static List<String> names = Lists.newArrayList();
1137         static boolean validateCalled = false;
1138 
1139         @Override
validate(String name, String value)1140         public void validate(String name, String value) throws ParameterException {
1141             validateCalled = true;
1142         }
1143 
1144         @Override
validate(String name, String value, ParameterDescription pd)1145         public void validate(String name, String value, ParameterDescription pd)
1146                 throws ParameterException {
1147             names.addAll(Arrays.asList(pd.getParameter().names()));
1148         }
1149     }
1150 
validator2()1151     public void validator2() {
1152         class Arg {
1153             @Parameter(names = {"-h", "--host"}, validateWith = V2.class)
1154             String host;
1155         }
1156         Arg a = new Arg();
1157         V2.names.clear();
1158         V2.validateCalled = false;
1159         JCommander jc = new JCommander(a, "--host", "h");
1160         jc.setAcceptUnknownOptions(true);
1161         Assert.assertEquals(V2.names, Arrays.asList("-h", "--host"));
1162         Assert.assertTrue(V2.validateCalled);
1163     }
1164 
usageCommandsUnderUsage()1165     public void usageCommandsUnderUsage() {
1166         class Arg {
1167         }
1168         @Parameters(commandDescription = "command a")
1169         class ArgCommandA {
1170             @Parameter(description = "command a parameters")
1171             List<String> parameters;
1172         }
1173         @Parameters(commandDescription = "command b")
1174         class ArgCommandB {
1175             @Parameter(description = "command b parameters")
1176             List<String> parameters;
1177         }
1178 
1179         Arg a = new Arg();
1180 
1181         JCommander c = new JCommander(a);
1182         c.addCommand("a", new ArgCommandA());
1183         c.addCommand("b", new ArgCommandB());
1184 
1185         StringBuilder sb = new StringBuilder();
1186         c.usage(sb);
1187         Assert.assertTrue(sb.toString().contains("[command options]\n  Commands:"));
1188     }
1189 
usageWithEmpytLine()1190     public void usageWithEmpytLine() {
1191         class Arg {
1192         }
1193         @Parameters(commandDescription = "command a")
1194         class ArgCommandA {
1195             @Parameter(description = "command a parameters")
1196             List<String> parameters;
1197         }
1198         @Parameters(commandDescription = "command b")
1199         class ArgCommandB {
1200             @Parameter(description = "command b parameters")
1201             List<String> parameters;
1202         }
1203 
1204         Arg a = new Arg();
1205 
1206         JCommander c = new JCommander(a);
1207         c.addCommand("a", new ArgCommandA());
1208         c.addCommand("b", new ArgCommandB());
1209 
1210         StringBuilder sb = new StringBuilder();
1211         c.usage(sb);
1212         Assert.assertTrue(sb.toString().contains("command a parameters\n\n    b"));
1213     }
1214 
usageWithSubCommands()1215     public void usageWithSubCommands() {
1216         class Arg {
1217         }
1218         @Parameters(commandDescription = "command a")
1219         class ArgCommandA {
1220             @Parameter(description = "command a parameters")
1221             List<String> parameters;
1222         }
1223         @Parameters(commandDescription = "command b")
1224         class ArgCommandB {
1225             @Parameter(description = "command b parameters")
1226             List<String> parameters;
1227         }
1228 
1229         Arg a = new Arg();
1230 
1231         JCommander c = new JCommander(a);
1232         c.setColumnSize(100);
1233         c.addCommand("a", new ArgCommandA());
1234 
1235         // b is a sub-command of a
1236         JCommander aCommand = c.getCommands().get("a");
1237         aCommand.addCommand("b", new ArgCommandB());
1238 
1239         StringBuilder sb = new StringBuilder();
1240         c.usage(sb);
1241         Assert.assertTrue(sb.toString().contains("command a parameters\n        Commands:"));
1242         Assert.assertTrue(sb.toString().contains("command b\n            Usage:"));
1243     }
1244 
partialValidation()1245     public void partialValidation() {
1246         class Arg {
1247             @Parameter(names = {"-h", "--host"})
1248             String host;
1249         }
1250         Arg a = new Arg();
1251         JCommander jc = new JCommander();
1252         jc.setAcceptUnknownOptions(true);
1253         jc.addObject(a);
1254         jc.parse("-a", "foo", "-h", "host");
1255         Assert.assertEquals(a.host, "host");
1256         Assert.assertEquals(jc.getUnknownOptions(), Lists.newArrayList("-a", "foo"));
1257     }
1258 
1259     /**
1260      * GITHUB-137.
1261      */
listArgShouldBeCleared()1262     public void listArgShouldBeCleared() {
1263         class Args {
1264             @Parameter(description = "[endpoint]")
1265             public List<String> endpoint = Lists.newArrayList("prod");
1266         }
1267         Args a = new Args();
1268         new JCommander(a, "dev");
1269         Assert.assertEquals(a.endpoint, Lists.newArrayList("dev"));
1270     }
1271 
1272     @Test
dashDashEmpty()1273     public void dashDashEmpty() {
1274         class Parameters {
1275             @Parameter
1276             public List<String> mainParameters = new ArrayList<>();
1277         }
1278 
1279         Parameters a = new Parameters();
1280         new JCommander(a, "--");
1281         Assert.assertTrue(a.mainParameters.isEmpty());
1282     }
1283 
1284     @Test
dashDashDashDash()1285     public void dashDashDashDash() {
1286         class Parameters {
1287             @Parameter
1288             public List<String> mainParameters = new ArrayList<>();
1289         }
1290 
1291         Parameters a = new Parameters();
1292         new JCommander(a, "--", "--");
1293         Assert.assertEquals(a.mainParameters.size(), 1);
1294         Assert.assertEquals(a.mainParameters.get(0), "--");
1295     }
1296 
dashDashParameter()1297     public void dashDashParameter() {
1298         class Parameters {
1299             @Parameter(names = {"-name"})
1300             public String name;
1301             @Parameter
1302             public List<String> mainParameters;
1303         }
1304 
1305         Parameters a = new Parameters();
1306         new JCommander(a, "-name", "theName", "--", "param1", "param2");
1307         Assert.assertEquals(a.name, "theName");
1308         Assert.assertEquals(a.mainParameters.size(), 2);
1309         Assert.assertEquals(a.mainParameters.get(0), "param1");
1310         Assert.assertEquals(a.mainParameters.get(1), "param2");
1311     }
1312 
dashDashParameter2()1313     public void dashDashParameter2() {
1314         class Parameters {
1315             @Parameter(names = {"-name"})
1316             public String name;
1317             @Parameter
1318             public List<String> mainParameters;
1319         }
1320 
1321         Parameters a = new Parameters();
1322         new JCommander(a, "param1", "param2", "--", "param3", "-name", "theName");
1323         Assert.assertNull(a.name);
1324         Assert.assertEquals(a.mainParameters.size(), 5);
1325         Assert.assertEquals(a.mainParameters.get(0), "param1");
1326         Assert.assertEquals(a.mainParameters.get(1), "param2");
1327         Assert.assertEquals(a.mainParameters.get(2), "param3");
1328         Assert.assertEquals(a.mainParameters.get(3), "-name");
1329         Assert.assertEquals(a.mainParameters.get(4), "theName");
1330     }
1331 
access()1332     public void access() {
1333         class Parameters {
1334             private int bar;
1335 
1336             @Parameter(names = {"-bar", "-foo"})
1337             private void setBar(int value) {
1338                 bar = value;
1339             }
1340 
1341             @Parameter(names = "-otherName")
1342             private String otherName;
1343         }
1344 
1345         Parameters a = new Parameters();
1346         new JCommander(a, "-bar", "1");
1347         Assert.assertEquals(a.bar, 1);
1348     }
1349 
noDash()1350     public void noDash() {
1351         class Parameters {
1352             private int bar;
1353 
1354             @Parameter(names = {"bar", "foo"})
1355             private void setBar(int value) {
1356                 bar = value;
1357             }
1358 
1359             @Parameter(names = "otherName")
1360             private String otherName;
1361         }
1362 
1363         Parameters a = new Parameters();
1364         new JCommander(a, "bar", "1");
1365         Assert.assertEquals(a.bar, 1);
1366     }
1367 
commitTest()1368     public void commitTest() {
1369         CommandCommit cc = new CommandCommit();
1370         new JCommander(cc, "--author=cedric");
1371         Assert.assertEquals(cc.author, "cedric");
1372     }
1373 
1374     static class CommandTemplate {
1375         @Parameter
1376         private List<String> parameters = new ArrayList<>();
1377 
1378         @Parameter(names = "help", help = true)
1379         private boolean help;
1380     }
1381 
noDashCommand()1382     public void noDashCommand() {
1383         class P1 {
1384             @Parameter(names = "hello")
1385             private int test;
1386         }
1387         P1 p1 = new P1();
1388         JCommander j = new JCommander();
1389         j.addCommand("p1", p1);
1390         j.parse("p1", "hello", "47");
1391         Assert.assertEquals(p1.test, 47);
1392     }
1393 
1394     static class ValuesValidator implements IValueValidator<List<Integer>> {
1395         @Override
validate(String name, List<Integer> values)1396         public void validate(String name, List<Integer> values) throws ParameterException {
1397             int previous = Integer.MIN_VALUE;
1398             for (Integer i : values) {
1399                 if (i <= previous) {
1400                     throw new ParameterException("Invalid: values should be strictly increasing.");
1401                 }
1402                 previous = i;
1403             }
1404         }
1405     }
1406 
1407     @Test(expectedExceptions = ParameterException.class, expectedExceptionsMessageRegExp = ".*strictly.*")
issue()1408     public void issue() {
1409         class Parameters {
1410             @Parameter(names = {"-v", "--values"},
1411                     required = true,
1412                     variableArity = true,
1413                     validateValueWith = ValuesValidator.class)
1414             private List<Integer> values;
1415         }
1416 
1417         String[] commands = "-v 1 5 2".split("\\s+");
1418         Parameters arg = new Parameters();
1419         new JCommander(arg, commands);
1420     }
1421 
1422     static class MvParameters {
1423         @SubParameter(order = 0)
1424         String from;
1425         @SubParameter(order = 1)
1426         String to;
1427     }
1428 
1429     @Test
arity()1430     public void arity() {
1431         class Parameters {
1432             @Parameter(names = {"--mv"}, arity = 2)
1433             private MvParameters mvParameters;
1434         }
1435 
1436         Parameters args = new Parameters();
1437         JCommander.newBuilder()
1438                 .addObject(args)
1439                 .args(new String[]{"--mv", "from", "to"})
1440                 .build();
1441 
1442         Assert.assertNotNull(args.mvParameters);
1443         Assert.assertEquals(args.mvParameters.from, "from");
1444         Assert.assertEquals(args.mvParameters.to, "to");
1445     }
1446 
programName()1447     public void programName() {
1448         JCommander jcommander = new JCommander();
1449         String programName = "main";
1450         jcommander.setProgramName(programName);
1451         StringBuilder sb = new StringBuilder();
1452         jcommander.usage(sb);
1453 
1454         Assert.assertTrue(sb.toString().contains(programName));
1455         Assert.assertEquals(jcommander.getProgramName(), programName);
1456     }
1457 
dontShowOptionUsageIfThereAreNoOptions()1458     public void dontShowOptionUsageIfThereAreNoOptions() {
1459         class CommandTemplate {
1460             @Parameter
1461             List<String> parameters = new ArrayList<>();
1462         }
1463 
1464         CommandTemplate template = new CommandTemplate();
1465         JCommander jcommander = new JCommander(template);
1466         jcommander.setProgramName("main");
1467         StringBuilder sb = new StringBuilder();
1468         jcommander.usage(sb);
1469         Assert.assertEquals(sb.toString().indexOf("options"), -1);
1470     }
1471 
1472     @Test
annotationsAndDynamicParameters()1473     public void annotationsAndDynamicParameters() {
1474         class DSimple {
1475             @DynamicParameter(names = "-D", description = "Dynamic parameters go here")
1476             public Map<String, String> params = Maps.newHashMap();
1477 
1478             @DynamicParameter(names = "-A", assignment = "@")
1479             public Map<String, String> params2 = Maps.newHashMap();
1480         }
1481 
1482         new JCommander(new DSimple()).usage(new StringBuilder());
1483     }
1484 
1485     @Test
twoCommandsSameOption()1486     public void twoCommandsSameOption() {
1487         class GenerateOption {
1488             @Parameter(names = {"--config"}, required = true, converter = FileConverter.class)
1489             public File configFile;
1490         }
1491 
1492         class RegenerateOption {
1493             @Parameter(names = {"--config"}, required = true, converter = FileConverter.class)
1494             public File configFile;
1495         }
1496 
1497         GenerateOption generateOption = new GenerateOption();
1498         RegenerateOption regenerateOption = new RegenerateOption();
1499         JCommander.newBuilder()
1500                 .addCommand("--generate", generateOption)
1501                 .addCommand("--regenerate", regenerateOption)
1502                 .args(new String[]{"--generate", "--config", "foo.txt"})
1503                 .build();
1504         Assert.assertEquals(generateOption.configFile.getName(), "foo.txt");
1505     }
1506 
1507     @Test
invertedBoolean()1508     public void invertedBoolean() {
1509         class Args {
1510             @Parameter(names = {"--f"})
1511             private boolean f = true;
1512         }
1513         Args args = new Args();
1514         JCommander.newBuilder()
1515                 .addObject(args)
1516                 .args(new String[]{"--f"})
1517                 .build();
1518         Assert.assertEquals(args.f, false);
1519     }
1520 
1521     @Test(enabled = false)
main(String[] args)1522     public static void main(String[] args) {
1523 
1524         CommandTemplate template = new CommandTemplate();
1525         JCommander jcommander = new JCommander(template);
1526         jcommander.setProgramName("prog");
1527         jcommander.parse("help");
1528 
1529         if (template.help) {
1530             jcommander.usage();
1531         }
1532     }
1533 }
1534