View Javadoc
1   /*
2     Licensed to the Apache Software Foundation (ASF) under one or more
3     contributor license agreements.  See the NOTICE file distributed with
4     this work for additional information regarding copyright ownership.
5     The ASF licenses this file to You under the Apache License, Version 2.0
6     (the "License"); you may not use this file except in compliance with
7     the License.  You may obtain a copy of the License at
8   
9         http://www.apache.org/licenses/LICENSE-2.0
10  
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16   */
17  
18  package org.apache.commons.cli;
19  
20  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertNull;
25  import static org.junit.jupiter.api.Assertions.assertThrows;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  import static org.junit.jupiter.api.Assertions.fail;
28  
29  import java.util.Arrays;
30  import java.util.List;
31  import java.util.Properties;
32  
33  import org.junit.jupiter.api.BeforeEach;
34  import org.junit.jupiter.api.Test;
35  
36  /**
37   * Abstract test case testing common parser features.
38   *
39   * TODO Needs a rework using JUnit parameterized tests.
40   */
41  public abstract class AbstractParserTestCase {
42  
43      protected CommandLineParser parser;
44  
45      protected Options options;
46  
47      @SuppressWarnings("deprecation")
48      private CommandLine parse(final CommandLineParser parser, final Options options, final String[] args, final Properties properties) throws ParseException {
49          if (parser instanceof Parser) {
50              return ((Parser) parser).parse(options, args, properties);
51          }
52          if (parser instanceof DefaultParser) {
53              return ((DefaultParser) parser).parse(options, args, properties);
54          }
55          throw new UnsupportedOperationException("Default options not supported by this parser");
56      }
57  
58      @BeforeEach
59      public void setUp() {
60          //@formatter:off
61          options = new Options()
62              .addOption("a", "enable-a", false, "turn [a] on or off")
63              .addOption("b", "bfile", true, "set the value of [b]")
64              .addOption("c", "copt", false, "turn [c] on or off");
65          //@formatter:on
66      }
67  
68      public void testAmbiguousArgParsing() throws Exception {
69          final String[] args = { "-=-" };
70          final Options options = new Options();
71  
72          assertThrows(UnrecognizedOptionException.class, () -> parser.parse(options, args));
73      }
74  
75      @Test
76      public void testAmbiguousLongWithoutEqualSingleDash() throws Exception {
77          final String[] args = { "-b", "-foobar" };
78  
79          final Options options = new Options();
80          options.addOption(OptionBuilder.withLongOpt("foo").hasOptionalArg().create('f'));
81          options.addOption(OptionBuilder.withLongOpt("bar").hasOptionalArg().create('b'));
82  
83          final CommandLine cl = parser.parse(options, args);
84  
85          assertTrue(cl.hasOption("b"));
86          assertTrue(cl.hasOption("f"));
87          assertEquals("bar", cl.getOptionValue("foo"));
88      }
89  
90      @Test
91      public void testAmbiguousLongWithoutEqualSingleDash2() throws Exception {
92          final String[] args = { "-b", "-foobar" };
93  
94          final Options options = new Options();
95          options.addOption(Option.builder().longOpt("foo").option("f").optionalArg(true).build());
96          options.addOption(Option.builder().longOpt("bar").option("b").optionalArg(false).build());
97  
98          final CommandLine cl = parser.parse(options, args);
99  
100         assertTrue(cl.hasOption("b"));
101         assertTrue(cl.hasOption("f"));
102         assertEquals("bar", cl.getOptionValue("foo"));
103     }
104 
105     @Test
106     public void testAmbiguousPartialLongOption1() throws Exception {
107         final String[] args = { "--ver" };
108 
109         final Options options = new Options();
110         options.addOption(OptionBuilder.withLongOpt("version").create());
111         options.addOption(OptionBuilder.withLongOpt("verbose").create());
112 
113         boolean caught = false;
114 
115         try {
116             parser.parse(options, args);
117         } catch (final AmbiguousOptionException e) {
118             caught = true;
119             assertEquals("--ver", e.getOption(), "Partial option");
120             assertNotNull(e.getMatchingOptions(), "Matching options null");
121             assertEquals(2, e.getMatchingOptions().size(), "Matching options size");
122         }
123 
124         assertTrue(caught, "Confirm MissingArgumentException caught");
125     }
126 
127     @Test
128     public void testAmbiguousPartialLongOption2() throws Exception {
129         final String[] args = { "-ver" };
130 
131         final Options options = new Options();
132         options.addOption(OptionBuilder.withLongOpt("version").create());
133         options.addOption(OptionBuilder.withLongOpt("verbose").create());
134 
135         boolean caught = false;
136 
137         try {
138             parser.parse(options, args);
139         } catch (final AmbiguousOptionException e) {
140             caught = true;
141             assertEquals("-ver", e.getOption(), "Partial option");
142             assertNotNull(e.getMatchingOptions(), "Matching options null");
143             assertEquals(2, e.getMatchingOptions().size(), "Matching options size");
144         }
145 
146         assertTrue(caught, "Confirm MissingArgumentException caught");
147     }
148 
149     @Test
150     public void testAmbiguousPartialLongOption3() throws Exception {
151         final String[] args = { "--ver=1" };
152 
153         final Options options = new Options();
154         options.addOption(OptionBuilder.withLongOpt("version").create());
155         options.addOption(OptionBuilder.withLongOpt("verbose").hasOptionalArg().create());
156 
157         boolean caught = false;
158 
159         try {
160             parser.parse(options, args);
161         } catch (final AmbiguousOptionException e) {
162             caught = true;
163             assertEquals("--ver", e.getOption(), "Partial option");
164             assertNotNull(e.getMatchingOptions(), "Matching options null");
165             assertEquals(2, e.getMatchingOptions().size(), "Matching options size");
166         }
167 
168         assertTrue(caught, "Confirm MissingArgumentException caught");
169     }
170 
171     @Test
172     public void testAmbiguousPartialLongOption4() throws Exception {
173         final String[] args = { "-ver=1" };
174 
175         final Options options = new Options();
176         options.addOption(OptionBuilder.withLongOpt("version").create());
177         options.addOption(OptionBuilder.withLongOpt("verbose").hasOptionalArg().create());
178 
179         boolean caught = false;
180 
181         try {
182             parser.parse(options, args);
183         } catch (final AmbiguousOptionException e) {
184             caught = true;
185             assertEquals("-ver", e.getOption(), "Partial option");
186             assertNotNull(e.getMatchingOptions(), "Matching options null");
187             assertEquals(2, e.getMatchingOptions().size(), "Matching options size");
188         }
189 
190         assertTrue(caught, "Confirm MissingArgumentException caught");
191     }
192 
193     @Test
194     public void testArgumentStartingWithHyphen() throws Exception {
195         final String[] args = { "-b", "-foo" };
196 
197         final CommandLine cl = parser.parse(options, args);
198         assertEquals("-foo", cl.getOptionValue("b"));
199     }
200 
201     @Test
202     public void testBursting() throws Exception {
203         final String[] args = { "-acbtoast", "foo", "bar" };
204 
205         final CommandLine cl = parser.parse(options, args);
206 
207         assertTrue(cl.hasOption("a"), "Confirm -a is set");
208         assertTrue(cl.hasOption("b"), "Confirm -b is set");
209         assertTrue(cl.hasOption("c"), "Confirm -c is set");
210         assertEquals("toast", cl.getOptionValue("b"), "Confirm arg of -b");
211         assertEquals(2, cl.getArgList().size(), "Confirm size of extra args");
212     }
213 
214     @Test
215     public void testDoubleDash1() throws Exception {
216         final String[] args = { "--copt", "--", "-b", "toast" };
217 
218         final CommandLine cl = parser.parse(options, args);
219 
220         assertTrue(cl.hasOption("c"), "Confirm -c is set");
221         assertFalse(cl.hasOption("b"), "Confirm -b is not set");
222         assertEquals(2, cl.getArgList().size(), "Confirm 2 extra args: " + cl.getArgList().size());
223     }
224 
225     @Test
226     public void testDoubleDash2() throws Exception {
227         final Options options = new Options();
228         options.addOption(OptionBuilder.hasArg().create('n'));
229         options.addOption(OptionBuilder.create('m'));
230 
231         try {
232             parser.parse(options, new String[] { "-n", "--", "-m" });
233             fail("MissingArgumentException not thrown for option -n");
234         } catch (final MissingArgumentException e) {
235             assertNotNull(e.getOption(), "option null");
236             assertEquals("n", e.getOption().getOpt());
237         }
238     }
239 
240     @Test
241     public void testLongOptionQuoteHandling() throws Exception {
242         final String[] args = { "--bfile", "\"quoted string\"" };
243         final CommandLine cl = parser.parse(options, args);
244         assertEquals("quoted string", cl.getOptionValue("b"), "Confirm --bfile \"arg\" strips quotes");
245     }
246 
247     @Test
248     public void testLongOptionWithEqualsQuoteHandling() throws Exception {
249         final String[] args = { "--bfile=\"quoted string\"" };
250         final CommandLine cl = parser.parse(options, args);
251         assertEquals("quoted string", cl.getOptionValue("b"), "Confirm --bfile=\"arg\" strips quotes");
252     }
253 
254     @Test
255     public void testLongWithEqualDoubleDash() throws Exception {
256         final String[] args = { "--foo=bar" };
257         final Options options = new Options();
258         options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
259         final CommandLine cl = parser.parse(options, args);
260         assertEquals("bar", cl.getOptionValue("foo"));
261     }
262 
263     @Test
264     public void testLongWithEqualSingleDash() throws Exception {
265         final String[] args = { "-foo=bar" };
266         final Options options = new Options();
267         options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
268         final CommandLine cl = parser.parse(options, args);
269         assertEquals("bar", cl.getOptionValue("foo"));
270     }
271 
272     @Test
273     public void testLongWithoutEqualDoubleDash() throws Exception {
274         final String[] args = { "--foobar" };
275         final Options options = new Options();
276         options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
277         final CommandLine cl = parser.parse(options, args, true);
278         assertFalse(cl.hasOption("foo")); // foo isn't expected to be recognized with a double dash
279     }
280 
281     @Test
282     public void testLongWithoutEqualSingleDash() throws Exception {
283         final String[] args = { "-foobar" };
284         final Options options = new Options();
285         options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
286         final CommandLine cl = parser.parse(options, args);
287         assertEquals("bar", cl.getOptionValue("foo"));
288     }
289 
290     @Test
291     public void testLongWithUnexpectedArgument1() throws Exception {
292         final String[] args = { "--foo=bar" };
293         final Options options = new Options();
294         options.addOption(OptionBuilder.withLongOpt("foo").create('f'));
295         try {
296             parser.parse(options, args);
297         } catch (final UnrecognizedOptionException e) {
298             assertEquals("--foo=bar", e.getOption());
299             return;
300         }
301         fail("UnrecognizedOptionException not thrown");
302     }
303 
304     @Test
305     public void testLongWithUnexpectedArgument2() throws Exception {
306         final String[] args = { "-foobar" };
307         final Options options = new Options();
308         options.addOption(OptionBuilder.withLongOpt("foo").create('f'));
309         try {
310             parser.parse(options, args);
311         } catch (final UnrecognizedOptionException e) {
312             assertEquals("-foobar", e.getOption());
313             return;
314         }
315         fail("UnrecognizedOptionException not thrown");
316     }
317 
318     @Test
319     public void testMissingArg() throws Exception {
320         final String[] args = { "-b" };
321         boolean caught = false;
322         try {
323             parser.parse(options, args);
324         } catch (final MissingArgumentException e) {
325             caught = true;
326             assertEquals("b", e.getOption().getOpt(), "option missing an argument");
327         }
328         assertTrue(caught, "Confirm MissingArgumentException caught");
329     }
330 
331     @Test
332     public void testMissingArgWithBursting() throws Exception {
333         final String[] args = { "-acb" };
334         boolean caught = false;
335         try {
336             parser.parse(options, args);
337         } catch (final MissingArgumentException e) {
338             caught = true;
339             assertEquals("b", e.getOption().getOpt(), "option missing an argument");
340         }
341         assertTrue(caught, "Confirm MissingArgumentException caught");
342     }
343 
344     @Test
345     public void testMissingRequiredGroup() throws Exception {
346         final OptionGroup group = new OptionGroup();
347         group.addOption(OptionBuilder.create("a"));
348         group.addOption(OptionBuilder.create("b"));
349         group.setRequired(true);
350 
351         final Options options = new Options();
352         options.addOptionGroup(group);
353         options.addOption(OptionBuilder.isRequired().create("c"));
354 
355         try {
356             parser.parse(options, new String[] { "-c" });
357             fail("MissingOptionException not thrown");
358         } catch (final MissingOptionException e) {
359             assertEquals(1, e.getMissingOptions().size());
360             assertTrue(e.getMissingOptions().get(0) instanceof OptionGroup);
361         } catch (final ParseException e) {
362             fail("Expected to catch MissingOptionException");
363         }
364     }
365 
366     @Test
367     public void testMissingRequiredOption() {
368         final String[] args = { "-a" };
369 
370         final Options options = new Options();
371         options.addOption("a", "enable-a", false, null);
372         options.addOption(OptionBuilder.withLongOpt("bfile").hasArg().isRequired().create('b'));
373 
374         try {
375             parser.parse(options, args);
376             fail("exception should have been thrown");
377         } catch (final MissingOptionException e) {
378             assertEquals("Missing required option: b", e.getMessage(), "Incorrect exception message");
379             assertTrue(e.getMissingOptions().contains("b"));
380         } catch (final ParseException e) {
381             fail("expected to catch MissingOptionException");
382         }
383     }
384 
385     @Test
386     public void testMissingRequiredOptions() {
387         final String[] args = { "-a" };
388 
389         final Options options = new Options();
390         options.addOption("a", "enable-a", false, null);
391         options.addOption(OptionBuilder.withLongOpt("bfile").hasArg().isRequired().create('b'));
392         options.addOption(OptionBuilder.withLongOpt("cfile").hasArg().isRequired().create('c'));
393 
394         try {
395             parser.parse(options, args);
396             fail("exception should have been thrown");
397         } catch (final MissingOptionException e) {
398             assertEquals("Missing required options: b, c", e.getMessage(), "Incorrect exception message");
399             assertTrue(e.getMissingOptions().contains("b"));
400             assertTrue(e.getMissingOptions().contains("c"));
401         } catch (final ParseException e) {
402             fail("expected to catch MissingOptionException");
403         }
404     }
405 
406     @Test
407     public void testMultiple() throws Exception {
408         final String[] args = { "-c", "foobar", "-b", "toast" };
409 
410         CommandLine cl = parser.parse(options, args, true);
411         assertTrue(cl.hasOption("c"), "Confirm -c is set");
412         assertEquals(3, cl.getArgList().size(), "Confirm  3 extra args: " + cl.getArgList().size());
413 
414         cl = parser.parse(options, cl.getArgs());
415 
416         assertFalse(cl.hasOption("c"), "Confirm -c is not set");
417         assertTrue(cl.hasOption("b"), "Confirm -b is set");
418         assertEquals("toast", cl.getOptionValue("b"), "Confirm arg of -b");
419         assertEquals(1, cl.getArgList().size(), "Confirm  1 extra arg: " + cl.getArgList().size());
420         assertEquals("foobar", cl.getArgList().get(0), "Confirm  value of extra arg: " + cl.getArgList().get(0));
421     }
422 
423     @Test
424     public void testMultipleWithLong() throws Exception {
425         final String[] args = { "--copt", "foobar", "--bfile", "toast" };
426 
427         CommandLine cl = parser.parse(options, args, true);
428         assertTrue(cl.hasOption("c"), "Confirm -c is set");
429         assertEquals(3, cl.getArgList().size(), "Confirm  3 extra args: " + cl.getArgList().size());
430 
431         cl = parser.parse(options, cl.getArgs());
432 
433         assertFalse(cl.hasOption("c"), "Confirm -c is not set");
434         assertTrue(cl.hasOption("b"), "Confirm -b is set");
435         assertEquals("toast", cl.getOptionValue("b"), "Confirm arg of -b");
436         assertEquals(1, cl.getArgList().size(), "Confirm  1 extra arg: " + cl.getArgList().size());
437         assertEquals("foobar", cl.getArgList().get(0), "Confirm  value of extra arg: " + cl.getArgList().get(0));
438     }
439 
440     @Test
441     public void testNegativeArgument() throws Exception {
442         final String[] args = { "-b", "-1" };
443 
444         final CommandLine cl = parser.parse(options, args);
445         assertEquals("-1", cl.getOptionValue("b"));
446     }
447 
448     @Test
449     public void testNegativeOption() throws Exception {
450         final String[] args = { "-b", "-1" };
451 
452         options.addOption("1", false, null);
453 
454         final CommandLine cl = parser.parse(options, args);
455         assertEquals("-1", cl.getOptionValue("b"));
456     }
457 
458     @Test
459     public void testOptionalArgsOptionBuilder() throws Exception {
460         final Options options = new Options();
461         options.addOption(OptionBuilder.hasOptionalArgs(2).create('i'));
462         final Properties properties = new Properties();
463 
464         CommandLine cmd = parse(parser, options, new String[] { "-i" }, properties);
465         assertTrue(cmd.hasOption("i"));
466         assertNull(cmd.getOptionValues("i"));
467 
468         cmd = parse(parser, options, new String[] { "-i", "paper" }, properties);
469         assertTrue(cmd.hasOption("i"));
470         assertArrayEquals(new String[] { "paper" }, cmd.getOptionValues("i"));
471 
472         cmd = parse(parser, options, new String[] { "-i", "paper", "scissors" }, properties);
473         assertTrue(cmd.hasOption("i"));
474         assertArrayEquals(new String[] { "paper", "scissors" }, cmd.getOptionValues("i"));
475 
476         cmd = parse(parser, options, new String[] { "-i", "paper", "scissors", "rock" }, properties);
477         assertTrue(cmd.hasOption("i"));
478         assertArrayEquals(new String[] { "paper", "scissors" }, cmd.getOptionValues("i"));
479         assertArrayEquals(new String[] { "rock" }, cmd.getArgs());
480     }
481 
482     @Test
483     public void testOptionalArgsOptionDotBuilder() throws Exception {
484         final Options options = new Options();
485         options.addOption(Option.builder("i").numberOfArgs(2).optionalArg(true).build());
486         final Properties properties = new Properties();
487 
488         CommandLine cmd = parse(parser, options, new String[] { "-i" }, properties);
489         assertTrue(cmd.hasOption("i"));
490         assertNull(cmd.getOptionValues("i"));
491 
492         cmd = parse(parser, options, new String[] { "-i", "paper" }, properties);
493         assertTrue(cmd.hasOption("i"));
494         assertArrayEquals(new String[] { "paper" }, cmd.getOptionValues("i"));
495 
496         cmd = parse(parser, options, new String[] { "-i", "paper", "scissors" }, properties);
497         assertTrue(cmd.hasOption("i"));
498         assertArrayEquals(new String[] { "paper", "scissors" }, cmd.getOptionValues("i"));
499 
500         cmd = parse(parser, options, new String[] { "-i", "paper", "scissors", "rock" }, properties);
501         assertTrue(cmd.hasOption("i"));
502         assertArrayEquals(new String[] { "paper", "scissors" }, cmd.getOptionValues("i"));
503         assertArrayEquals(new String[] { "rock" }, cmd.getArgs());
504 
505         options.addOption(Option.builder("j").numberOfArgs(3).optionalArg(true).build());
506         cmd = parse(parser, options, new String[] { "-j" }, properties);
507     }
508 
509     @Test
510     public void testOptionAndRequiredOption() throws Exception {
511         final String[] args = { "-a", "-b", "file" };
512 
513         final Options options = new Options();
514         options.addOption("a", "enable-a", false, null);
515         options.addOption(OptionBuilder.withLongOpt("bfile").hasArg().isRequired().create('b'));
516 
517         final CommandLine cl = parser.parse(options, args);
518 
519         assertTrue(cl.hasOption("a"), "Confirm -a is set");
520         assertTrue(cl.hasOption("b"), "Confirm -b is set");
521         assertEquals("file", cl.getOptionValue("b"), "Confirm arg of -b");
522         assertTrue(cl.getArgList().isEmpty(), "Confirm NO of extra args");
523     }
524 
525     @Test
526     public void testOptionGroup() throws Exception {
527         final OptionGroup group = new OptionGroup();
528         group.addOption(OptionBuilder.create("a"));
529         group.addOption(OptionBuilder.create("b"));
530 
531         final Options options = new Options();
532         options.addOptionGroup(group);
533 
534         parser.parse(options, new String[] { "-b" });
535 
536         assertEquals("b", group.getSelected(), "selected option");
537     }
538 
539     @Test
540     public void testOptionGroupLong() throws Exception {
541         final OptionGroup group = new OptionGroup();
542         group.addOption(OptionBuilder.withLongOpt("foo").create());
543         group.addOption(OptionBuilder.withLongOpt("bar").create());
544 
545         final Options options = new Options();
546         options.addOptionGroup(group);
547 
548         final CommandLine cl = parser.parse(options, new String[] { "--bar" });
549 
550         assertTrue(cl.hasOption("bar"));
551         assertEquals("bar", group.getSelected(), "selected option");
552     }
553 
554     @Test
555     public void testPartialLongOptionSingleDash() throws Exception {
556         final String[] args = { "-ver" };
557 
558         final Options options = new Options();
559         options.addOption(OptionBuilder.withLongOpt("version").create());
560         options.addOption(OptionBuilder.hasArg().create('v'));
561 
562         final CommandLine cl = parser.parse(options, args);
563 
564         assertTrue(cl.hasOption("version"), "Confirm --version is set");
565         assertFalse(cl.hasOption("v"), "Confirm -v is not set");
566     }
567 
568     @Test
569     public void testPropertiesOption1() throws Exception {
570         final String[] args = { "-Jsource=1.5", "-J", "target", "1.5", "foo" };
571 
572         final Options options = new Options();
573         options.addOption(OptionBuilder.withValueSeparator().hasArgs(2).create('J'));
574 
575         final CommandLine cl = parser.parse(options, args);
576 
577         final List<String> values = Arrays.asList(cl.getOptionValues("J"));
578         assertNotNull(values, "null values");
579         assertEquals(4, values.size(), "number of values");
580         assertEquals("source", values.get(0), "value 1");
581         assertEquals("1.5", values.get(1), "value 2");
582         assertEquals("target", values.get(2), "value 3");
583         assertEquals("1.5", values.get(3), "value 4");
584 
585         final List<?> argsleft = cl.getArgList();
586         assertEquals(1, argsleft.size(), "Should be 1 arg left");
587         assertEquals("foo", argsleft.get(0), "Expecting foo");
588     }
589 
590     @Test
591     public void testPropertiesOption2() throws Exception {
592         final String[] args = { "-Dparam1", "-Dparam2=value2", "-D" };
593 
594         final Options options = new Options();
595         options.addOption(OptionBuilder.withValueSeparator().hasOptionalArgs(2).create('D'));
596 
597         final CommandLine cl = parser.parse(options, args);
598 
599         final Properties props = cl.getOptionProperties("D");
600         assertNotNull(props, "null properties");
601         assertEquals(2, props.size(), "number of properties in " + props);
602         assertEquals("true", props.getProperty("param1"), "property 1");
603         assertEquals("value2", props.getProperty("param2"), "property 2");
604 
605         final List<?> argsleft = cl.getArgList();
606         assertEquals(0, argsleft.size(), "Should be no arg left");
607     }
608 
609     @Test
610     public void testPropertyOptionFlags() throws Exception {
611         final Options options = new Options();
612         options.addOption("a", false, "toggle -a");
613         options.addOption("c", "c", false, "toggle -c");
614         options.addOption(OptionBuilder.hasOptionalArg().create('e'));
615 
616         Properties properties = new Properties();
617         properties.setProperty("a", "true");
618         properties.setProperty("c", "yes");
619         properties.setProperty("e", "1");
620 
621         CommandLine cmd = parse(parser, options, null, properties);
622         assertTrue(cmd.hasOption("a"));
623         assertTrue(cmd.hasOption("c"));
624         assertTrue(cmd.hasOption("e"));
625 
626         properties = new Properties();
627         properties.setProperty("a", "false");
628         properties.setProperty("c", "no");
629         properties.setProperty("e", "0");
630 
631         cmd = parse(parser, options, null, properties);
632         assertFalse(cmd.hasOption("a"));
633         assertFalse(cmd.hasOption("c"));
634         assertTrue(cmd.hasOption("e")); // this option accepts an argument
635 
636         properties = new Properties();
637         properties.setProperty("a", "TRUE");
638         properties.setProperty("c", "nO");
639         properties.setProperty("e", "TrUe");
640 
641         cmd = parse(parser, options, null, properties);
642         assertTrue(cmd.hasOption("a"));
643         assertFalse(cmd.hasOption("c"));
644         assertTrue(cmd.hasOption("e"));
645 
646         properties = new Properties();
647         properties.setProperty("a", "just a string");
648         properties.setProperty("e", "");
649 
650         cmd = parse(parser, options, null, properties);
651         assertFalse(cmd.hasOption("a"));
652         assertFalse(cmd.hasOption("c"));
653         assertTrue(cmd.hasOption("e"));
654 
655         properties = new Properties();
656         properties.setProperty("a", "0");
657         properties.setProperty("c", "1");
658 
659         cmd = parse(parser, options, null, properties);
660         assertFalse(cmd.hasOption("a"));
661         assertTrue(cmd.hasOption("c"));
662     }
663 
664     @Test
665     public void testPropertyOptionGroup() throws Exception {
666         final Options options = new Options();
667 
668         final OptionGroup group1 = new OptionGroup();
669         group1.addOption(new Option("a", null));
670         group1.addOption(new Option("b", null));
671         options.addOptionGroup(group1);
672 
673         final OptionGroup group2 = new OptionGroup();
674         group2.addOption(new Option("x", null));
675         group2.addOption(new Option("y", null));
676         options.addOptionGroup(group2);
677 
678         final String[] args = { "-a" };
679 
680         final Properties properties = new Properties();
681         properties.put("b", "true");
682         properties.put("x", "true");
683 
684         final CommandLine cmd = parse(parser, options, args, properties);
685 
686         assertTrue(cmd.hasOption("a"));
687         assertFalse(cmd.hasOption("b"));
688         assertTrue(cmd.hasOption("x"));
689         assertFalse(cmd.hasOption("y"));
690     }
691 
692     @Test
693     public void testPropertyOptionMultipleValues() throws Exception {
694         final Options options = new Options();
695         options.addOption(OptionBuilder.hasArgs().withValueSeparator(',').create('k'));
696 
697         final Properties properties = new Properties();
698         properties.setProperty("k", "one,two");
699 
700         final CommandLine cmd = parse(parser, options, null, properties);
701         assertTrue(cmd.hasOption("k"));
702         final String[] values = { "one", "two" };
703         assertArrayEquals(values, cmd.getOptionValues('k'));
704     }
705 
706     @Test
707     public void testPropertyOptionRequired() throws Exception {
708         final Options options = new Options();
709         options.addOption(OptionBuilder.isRequired().create("f"));
710 
711         final Properties properties = new Properties();
712         properties.setProperty("f", "true");
713 
714         final CommandLine cmd = parse(parser, options, null, properties);
715         assertTrue(cmd.hasOption("f"));
716     }
717 
718     @Test
719     public void testPropertyOptionSingularValue() throws Exception {
720         final Options options = new Options();
721         options.addOption(OptionBuilder.hasOptionalArgs(2).withLongOpt("hide").create());
722 
723         final Properties properties = new Properties();
724         properties.setProperty("hide", "seek");
725 
726         final CommandLine cmd = parse(parser, options, null, properties);
727         assertTrue(cmd.hasOption("hide"));
728         assertEquals("seek", cmd.getOptionValue("hide"));
729         assertFalse(cmd.hasOption("fake"));
730     }
731 
732     @Test
733     public void testPropertyOptionUnexpected() throws Exception {
734         final Options options = new Options();
735 
736         final Properties properties = new Properties();
737         properties.setProperty("f", "true");
738 
739         try {
740             parse(parser, options, null, properties);
741             fail("UnrecognizedOptionException expected");
742         } catch (final UnrecognizedOptionException e) {
743             // expected
744         }
745     }
746 
747     @Test
748     public void testPropertyOverrideValues() throws Exception {
749         final Options options = new Options();
750         options.addOption(OptionBuilder.hasOptionalArgs(2).create('i'));
751         options.addOption(OptionBuilder.hasOptionalArgs().create('j'));
752 
753         final String[] args = { "-j", "found", "-i", "ink" };
754 
755         final Properties properties = new Properties();
756         properties.setProperty("j", "seek");
757 
758         final CommandLine cmd = parse(parser, options, args, properties);
759         assertTrue(cmd.hasOption("j"));
760         assertEquals("found", cmd.getOptionValue("j"));
761         assertTrue(cmd.hasOption("i"));
762         assertEquals("ink", cmd.getOptionValue("i"));
763         assertFalse(cmd.hasOption("fake"));
764     }
765 
766     @Test
767     public void testReuseOptionsTwice() throws Exception {
768         final Options options = new Options();
769         options.addOption(OptionBuilder.isRequired().create('v'));
770         // first parsing
771         parser.parse(options, new String[] { "-v" });
772         try {
773             // second parsing, with the same Options instance and an invalid command line
774             parser.parse(options, new String[0]);
775             fail("MissingOptionException not thrown");
776         } catch (final MissingOptionException e) {
777             // expected
778         }
779     }
780 
781     @Test
782     public void testShortOptionConcatenatedQuoteHandling() throws Exception {
783         final CommandLine cl = parser.parse(options, new String[] { "-b\"quoted string\"" });
784         assertEquals("quoted string", cl.getOptionValue("b"), "Confirm -b\"arg\" strips quotes");
785     }
786 
787     @Test
788     public void testShortOptionQuoteHandling() throws Exception {
789         final CommandLine cl = parser.parse(options, new String[] { "-b", "\"quoted string\"" });
790         assertEquals("quoted string", cl.getOptionValue("b"), "Confirm -b \"arg\" strips quotes");
791     }
792 
793     @Test
794     public void testShortWithEqual() throws Exception {
795         final Options options = new Options();
796         options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
797         final CommandLine cl = parser.parse(options, new String[] { "-f=bar" });
798         assertEquals("bar", cl.getOptionValue("foo"));
799     }
800 
801     @Test
802     public void testShortWithoutEqual() throws Exception {
803         final Options options = new Options();
804         options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
805         final CommandLine cl = parser.parse(options, new String[] { "-fbar" });
806         assertEquals("bar", cl.getOptionValue("foo"));
807     }
808 
809     @Test
810     public void testShortWithUnexpectedArgument() throws Exception {
811         final Options options = new Options();
812         options.addOption(OptionBuilder.withLongOpt("foo").create('f'));
813         try {
814             parser.parse(options, new String[] { "-f=bar" });
815         } catch (final UnrecognizedOptionException e) {
816             assertEquals("-f=bar", e.getOption());
817             return;
818         }
819         fail("UnrecognizedOptionException not thrown");
820     }
821 
822     @Test
823     public void testSimpleLong() throws Exception {
824         final CommandLine cl = parser.parse(options, new String[] { "--enable-a", "--bfile", "toast", "foo", "bar" });
825         assertTrue(cl.hasOption("a"), "Confirm -a is set");
826         assertTrue(cl.hasOption("b"), "Confirm -b is set");
827         assertEquals("toast", cl.getOptionValue("b"), "Confirm arg of -b");
828         assertEquals("toast", cl.getOptionValue("bfile"), "Confirm arg of --bfile");
829         assertEquals(2, cl.getArgList().size(), "Confirm size of extra args");
830     }
831 
832     @Test
833     public void testSimpleShort() throws Exception {
834         final CommandLine cl = parser.parse(options, new String[] { "-a", "-b", "toast", "foo", "bar" });
835         assertTrue(cl.hasOption("a"), "Confirm -a is set");
836         assertTrue(cl.hasOption("b"), "Confirm -b is set");
837         assertEquals("toast", cl.getOptionValue("b"), "Confirm arg of -b");
838         assertEquals(2, cl.getArgList().size(), "Confirm size of extra args");
839     }
840 
841     @Test
842     public void testSingleDash() throws Exception {
843         final CommandLine cl = parser.parse(options, new String[] { "--copt", "-b", "-", "-a", "-" });
844         assertTrue(cl.hasOption("a"), "Confirm -a is set");
845         assertTrue(cl.hasOption("b"), "Confirm -b is set");
846         assertEquals("-", cl.getOptionValue("b"), "Confirm arg of -b");
847         assertEquals(1, cl.getArgList().size(), "Confirm 1 extra arg: " + cl.getArgList().size());
848         assertEquals("-", cl.getArgList().get(0), "Confirm value of extra arg: " + cl.getArgList().get(0));
849     }
850 
851     @Test
852     public void testStopAtExpectedArg() throws Exception {
853         final String[] args = { "-b", "foo" };
854         final CommandLine cl = parser.parse(options, args, true);
855         assertTrue(cl.hasOption('b'), "Confirm -b is set");
856         assertEquals("foo", cl.getOptionValue('b'), "Confirm -b is set");
857         assertTrue(cl.getArgList().isEmpty(), "Confirm no extra args: " + cl.getArgList().size());
858     }
859 
860     @Test
861     public void testStopAtNonOptionLong() throws Exception {
862         final String[] args = { "--zop==1", "-abtoast", "--b=bar" };
863         final CommandLine cl = parser.parse(options, args, true);
864         assertFalse(cl.hasOption("a"), "Confirm -a is not set");
865         assertFalse(cl.hasOption("b"), "Confirm -b is not set");
866         assertEquals(3, cl.getArgList().size(), "Confirm  3 extra args: " + cl.getArgList().size());
867     }
868 
869     @Test
870     public void testStopAtNonOptionShort() throws Exception {
871         final CommandLine cl = parser.parse(options, new String[] { "-z", "-a", "-btoast" }, true);
872         assertFalse(cl.hasOption("a"), "Confirm -a is not set");
873         assertEquals(3, cl.getArgList().size(), "Confirm  3 extra args: " + cl.getArgList().size());
874     }
875 
876     @Test
877     public void testStopAtUnexpectedArg() throws Exception {
878         final CommandLine cl = parser.parse(options, new String[] { "-c", "foober", "-b", "toast" }, true);
879         assertTrue(cl.hasOption("c"), "Confirm -c is set");
880         assertEquals(3, cl.getArgList().size(), "Confirm  3 extra args: " + cl.getArgList().size());
881     }
882 
883     @Test
884     public void testStopBursting() throws Exception {
885         final CommandLine cl = parser.parse(options, new String[] { "-azc" }, true);
886         assertTrue(cl.hasOption("a"), "Confirm -a is set");
887         assertFalse(cl.hasOption("c"), "Confirm -c is not set");
888         assertEquals(1, cl.getArgList().size(), "Confirm  1 extra arg: " + cl.getArgList().size());
889         assertTrue(cl.getArgList().contains("zc"));
890     }
891 
892     @Test
893     public void testStopBursting2() throws Exception {
894         CommandLine cl = parser.parse(options, new String[] { "-c", "foobar", "-btoast" }, true);
895         assertTrue(cl.hasOption("c"), "Confirm -c is set");
896         assertEquals(2, cl.getArgList().size(), "Confirm  2 extra args: " + cl.getArgList().size());
897         cl = parser.parse(options, cl.getArgs());
898         assertFalse(cl.hasOption("c"), "Confirm -c is not set");
899         assertTrue(cl.hasOption("b"), "Confirm -b is set");
900         assertEquals("toast", cl.getOptionValue("b"), "Confirm arg of -b");
901         assertEquals(1, cl.getArgList().size(), "Confirm  1 extra arg: " + cl.getArgList().size());
902         assertEquals("foobar", cl.getArgList().get(0), "Confirm  value of extra arg: " + cl.getArgList().get(0));
903     }
904 
905     @Test
906     public void testUnambiguousPartialLongOption1() throws Exception {
907         final Options options = new Options();
908         options.addOption(OptionBuilder.withLongOpt("version").create());
909         options.addOption(OptionBuilder.withLongOpt("help").create());
910         final CommandLine cl = parser.parse(options, new String[] { "--ver" });
911         assertTrue(cl.hasOption("version"), "Confirm --version is set");
912     }
913 
914     @Test
915     public void testUnambiguousPartialLongOption2() throws Exception {
916         final Options options = new Options();
917         options.addOption(OptionBuilder.withLongOpt("version").create());
918         options.addOption(OptionBuilder.withLongOpt("help").create());
919         final CommandLine cl = parser.parse(options, new String[] { "-ver" });
920         assertTrue(cl.hasOption("version"), "Confirm --version is set");
921     }
922 
923     @Test
924     public void testUnambiguousPartialLongOption3() throws Exception {
925         final Options options = new Options();
926         options.addOption(OptionBuilder.withLongOpt("verbose").hasOptionalArg().create());
927         options.addOption(OptionBuilder.withLongOpt("help").create());
928         final CommandLine cl = parser.parse(options, new String[] { "--ver=1" });
929         assertTrue(cl.hasOption("verbose"), "Confirm --verbose is set");
930         assertEquals("1", cl.getOptionValue("verbose"));
931     }
932 
933     @Test
934     public void testUnambiguousPartialLongOption4() throws Exception {
935         final Options options = new Options();
936         options.addOption(OptionBuilder.withLongOpt("verbose").hasOptionalArg().create());
937         options.addOption(OptionBuilder.withLongOpt("help").create());
938         final CommandLine cl = parser.parse(options, new String[] { "-ver=1" });
939         assertTrue(cl.hasOption("verbose"), "Confirm --verbose is set");
940         assertEquals("1", cl.getOptionValue("verbose"));
941     }
942 
943     @Test
944     public void testUnlimitedArgs() throws Exception {
945         final Options options = new Options();
946         options.addOption(OptionBuilder.hasArgs().create("e"));
947         options.addOption(OptionBuilder.hasArgs().create("f"));
948         final CommandLine cl = parser.parse(options, new String[] { "-e", "one", "two", "-f", "alpha" });
949         assertTrue(cl.hasOption("e"), "Confirm -e is set");
950         assertEquals(2, cl.getOptionValues("e").length, "number of arg for -e");
951         assertTrue(cl.hasOption("f"), "Confirm -f is set");
952         assertEquals(1, cl.getOptionValues("f").length, "number of arg for -f");
953     }
954 
955     @Test
956     public void testUnrecognizedOption() throws Exception {
957         try {
958             parser.parse(options, new String[] { "-a", "-d", "-b", "toast", "foo", "bar" });
959             fail("UnrecognizedOptionException wasn't thrown");
960         } catch (final UnrecognizedOptionException e) {
961             assertEquals("-d", e.getOption());
962         }
963     }
964 
965     @Test
966     public void testUnrecognizedOptionWithBursting() throws Exception {
967         try {
968             parser.parse(options, new String[] { "-adbtoast", "foo", "bar" });
969             fail("UnrecognizedOptionException wasn't thrown");
970         } catch (final UnrecognizedOptionException e) {
971             assertEquals("-adbtoast", e.getOption());
972         }
973     }
974 
975     @Test
976     public void testWithRequiredOption() throws Exception {
977         final String[] args = { "-b", "file" };
978         final Options options = new Options();
979         options.addOption("a", "enable-a", false, null);
980         options.addOption(OptionBuilder.withLongOpt("bfile").hasArg().isRequired().create('b'));
981         final CommandLine cl = parser.parse(options, args);
982         assertFalse(cl.hasOption("a"), "Confirm -a is NOT set");
983         assertTrue(cl.hasOption("b"), "Confirm -b is set");
984         assertEquals("file", cl.getOptionValue("b"), "Confirm arg of -b");
985         assertTrue(cl.getArgList().isEmpty(), "Confirm NO of extra args");
986     }
987 }