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    *     https://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.bug;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  import static org.junit.jupiter.api.Assertions.fail;
27  
28  import java.io.ByteArrayOutputStream;
29  import java.io.PrintStream;
30  import java.io.PrintWriter;
31  import java.util.Iterator;
32  import java.util.Properties;
33  
34  import org.apache.commons.cli.CommandLine;
35  import org.apache.commons.cli.CommandLineParser;
36  import org.apache.commons.cli.GnuParser;
37  import org.apache.commons.cli.HelpFormatter;
38  import org.apache.commons.cli.MissingArgumentException;
39  import org.apache.commons.cli.Option;
40  import org.apache.commons.cli.OptionBuilder;
41  import org.apache.commons.cli.OptionGroup;
42  import org.apache.commons.cli.Options;
43  import org.apache.commons.cli.ParseException;
44  import org.apache.commons.cli.Parser;
45  import org.apache.commons.cli.PosixParser;
46  import org.apache.commons.lang3.ArrayUtils;
47  import org.junit.jupiter.api.Test;
48  
49  @SuppressWarnings("deprecation") // tests some deprecated classes
50  class BugsTest {
51      @Test
52      void test11456() throws Exception {
53          // POSIX
54          Options options = new Options();
55          options.addOption(OptionBuilder.hasOptionalArg().create('a'));
56          options.addOption(OptionBuilder.hasArg().create('b'));
57          String[] args = {"-a", "-bvalue"};
58  
59          CommandLineParser parser = new PosixParser();
60  
61          CommandLine cmd = parser.parse(options, args);
62          assertEquals(cmd.getOptionValue('b'), "value");
63  
64          // GNU
65          options = new Options();
66          options.addOption(OptionBuilder.hasOptionalArg().create('a'));
67          options.addOption(OptionBuilder.hasArg().create('b'));
68          args = new String[] {"-a", "-b", "value"};
69  
70          parser = new GnuParser();
71  
72          cmd = parser.parse(options, args);
73          assertEquals(cmd.getOptionValue('b'), "value");
74      }
75  
76      @Test
77      void test11457() throws Exception {
78          final Options options = new Options();
79          options.addOption(OptionBuilder.withLongOpt("verbose").create());
80          final String[] args = {"--verbose"};
81  
82          final CommandLineParser parser = new PosixParser();
83  
84          final CommandLine cmd = parser.parse(options, args);
85          assertTrue(cmd.hasOption("verbose"));
86      }
87  
88      @Test
89      void test11458() throws Exception {
90          final Options options = new Options();
91          options.addOption(OptionBuilder.withValueSeparator('=').hasArgs().create('D'));
92          options.addOption(OptionBuilder.withValueSeparator(':').hasArgs().create('p'));
93          final String[] args = {"-DJAVA_HOME=/opt/java", "-pfile1:file2:file3"};
94  
95          final CommandLineParser parser = new PosixParser();
96  
97          final CommandLine cmd = parser.parse(options, args);
98  
99          String[] values = cmd.getOptionValues('D');
100 
101         assertEquals(values[0], "JAVA_HOME");
102         assertEquals(values[1], "/opt/java");
103 
104         values = cmd.getOptionValues('p');
105 
106         assertEquals(values[0], "file1");
107         assertEquals(values[1], "file2");
108         assertEquals(values[2], "file3");
109 
110         final Iterator<Option> iter = cmd.iterator();
111         while (iter.hasNext()) {
112             final Option opt = iter.next();
113             switch (opt.getId()) {
114             case 'D':
115                 assertEquals(opt.getValue(0), "JAVA_HOME");
116                 assertEquals(opt.getValue(1), "/opt/java");
117                 break;
118             case 'p':
119                 assertEquals(opt.getValue(0), "file1");
120                 assertEquals(opt.getValue(1), "file2");
121                 assertEquals(opt.getValue(2), "file3");
122                 break;
123             default:
124                 fail("-D option not found");
125             }
126         }
127     }
128 
129     @Test
130     void test11680() throws Exception {
131         final Options options = new Options();
132         final Option optionF = options.addOption("f", true, "foobar").getOption("f");
133         final Option optionM = options.addOption("m", true, "missing").getOption("m");
134         final String[] args = { "-f", "foo" };
135         final CommandLineParser parser = new PosixParser();
136         final CommandLine cmd = parser.parse(options, args);
137         // 1.7.0 API:
138         cmd.getOptionValue(optionF, () -> "default f");
139         cmd.getOptionValue(optionM, () -> "default m");
140         // 1.7.0 API:
141         cmd.getOptionValue('f', () -> "default f");
142         cmd.getOptionValue('m', () -> "default m");
143         // 1.5.0 API:
144         cmd.getOptionValue(optionF, "default f");
145         cmd.getOptionValue(optionM, "default m");
146         // Original API:
147         cmd.getOptionValue("f", "default f");
148         cmd.getOptionValue("m", "default m");
149         //
150         assertNull(cmd.getOptionValue((String) null, (String) null));
151         assertEquals("default", cmd.getOptionValue((String) null, "default"));
152     }
153 
154     @Test
155     void test12210() throws Exception {
156         // create the main options object which will handle the first parameter
157         final Options mainOptions = new Options();
158         // There can be 2 main exclusive options: -exec|-rep
159 
160         // Therefore, place them in an option group
161 
162         String[] argv = {"-exec", "-exec_opt1", "-exec_opt2"};
163         final OptionGroup optionGroup = new OptionGroup();
164 
165         optionGroup.addOption(new Option("exec", false, "description for this option"));
166 
167         optionGroup.addOption(new Option("rep", false, "description for this option"));
168 
169         mainOptions.addOptionGroup(optionGroup);
170 
171         // for the exec option, there are 2 options...
172         final Options execOptions = new Options();
173         execOptions.addOption("exec_opt1", false, " desc");
174         execOptions.addOption("exec_opt2", false, " desc");
175 
176         // similarly, for rep there are 2 options...
177         final Options repOptions = new Options();
178         repOptions.addOption("repopto", false, "desc");
179         repOptions.addOption("repoptt", false, "desc");
180 
181         // create the parser
182         final GnuParser parser = new GnuParser();
183 
184         // finally, parse the arguments:
185 
186         // first parse the main options to see what the user has specified
187         // We set stopAtNonOption to true so it does not touch the remaining
188         // options
189         CommandLine cmd = parser.parse(mainOptions, argv, true);
190         // get the remaining options...
191         argv = cmd.getArgs();
192 
193         if (cmd.hasOption("exec")) {
194             cmd = parser.parse(execOptions, argv, false);
195             // process the exec_op1 and exec_opt2...
196             assertTrue(cmd.hasOption("exec_opt1"));
197             assertTrue(cmd.hasOption("exec_opt2"));
198         } else if (cmd.hasOption("rep")) {
199             cmd = parser.parse(repOptions, argv, false);
200             // process the rep_op1 and rep_opt2...
201         } else {
202             fail("exec option not found");
203         }
204     }
205 
206     @Test
207     void test13425() throws Exception {
208         final Options options = new Options();
209         //@formatter:off
210         final Option oldpass = OptionBuilder.withLongOpt("old-password")
211             .withDescription("Use this option to specify the old password")
212             .hasArg()
213             .create('o');
214         final Option newpass = OptionBuilder.withLongOpt("new-password")
215             .withDescription("Use this option to specify the new password")
216             .hasArg()
217             .create('n');
218         //@formatter:on
219         final String[] args = {"-o", "-n", "newpassword"};
220         options.addOption(oldpass);
221         options.addOption(newpass);
222         assertThrows(MissingArgumentException.class, () -> new PosixParser().parse(options, args));
223     }
224 
225     @Test
226     void test13666() throws Exception {
227         final Options options = new Options();
228         final Option dirOption = OptionBuilder.withDescription("dir").hasArg().create('d');
229         options.addOption(dirOption);
230         final PrintStream oldSystemOut = System.out;
231         try {
232             final ByteArrayOutputStream baos = new ByteArrayOutputStream();
233             final String eol = System.lineSeparator();
234             System.setOut(new PrintStream(baos));
235             final HelpFormatter formatter = new HelpFormatter();
236             formatter.printHelp("dir", options);
237             assertEquals("usage: dir" + eol + " -d <arg>   dir" + eol, baos.toString());
238         } finally {
239             System.setOut(oldSystemOut);
240         }
241     }
242 
243     @Test
244     void test13666_Builder() throws Exception {
245         final Options options = new Options();
246         final Option dirOption = OptionBuilder.withDescription("dir").hasArg().create('d');
247         options.addOption(dirOption);
248         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
249         final String eol = System.lineSeparator();
250         final HelpFormatter formatter = HelpFormatter.builder().setPrintWriter(new PrintWriter(baos)).get();
251         formatter.printHelp("dir", options);
252         assertEquals("usage: dir" + eol + " -d <arg>   dir" + eol, baos.toString());
253     }
254 
255     @Test
256     void test13935() throws Exception {
257         final OptionGroup directions = new OptionGroup();
258 
259         final Option left = new Option("l", "left", false, "go left");
260         final Option right = new Option("r", "right", false, "go right");
261         final Option straight = new Option("s", "straight", false, "go straight");
262         final Option forward = new Option("f", "forward", false, "go forward");
263         forward.setRequired(true);
264 
265         directions.addOption(left);
266         directions.addOption(right);
267         directions.setRequired(true);
268 
269         final Options opts = new Options();
270         opts.addOptionGroup(directions);
271         opts.addOption(straight);
272 
273         final CommandLineParser parser = new PosixParser();
274 
275         assertThrows(ParseException.class, () -> parser.parse(opts, ArrayUtils.EMPTY_STRING_ARRAY));
276         assertThrows(ParseException.class, () -> parser.parse(opts, new String[] {"-s"}));
277 
278         String[] args = {"-s", "-l"};
279         CommandLine line = parser.parse(opts, args);
280         assertNotNull(line);
281 
282         opts.addOption(forward);
283         args = new String[] {"-s", "-l", "-f"};
284         line = parser.parse(opts, args);
285         assertNotNull(line);
286     }
287 
288     @Test
289     void test14786() throws Exception {
290         final Option o = OptionBuilder.isRequired().withDescription("test").create("test");
291         final Options opts = new Options();
292         opts.addOption(o);
293         opts.addOption(o);
294 
295         final CommandLineParser parser = new GnuParser();
296 
297         final String[] args = {"-test"};
298 
299         final CommandLine line = parser.parse(opts, args);
300         assertTrue(line.hasOption("test"));
301     }
302 
303     @Test
304     void test15046() throws Exception {
305         final CommandLineParser parser = new PosixParser();
306         final String[] cliArgs = {"-z", "c"};
307 
308         final Options options = new Options();
309         options.addOption(new Option("z", "timezone", true, "affected option"));
310 
311         parser.parse(options, cliArgs);
312 
313         // now add conflicting option
314         options.addOption("c", "conflict", true, "conflict option");
315         final CommandLine line = parser.parse(options, cliArgs);
316         assertEquals(line.getOptionValue('z'), "c");
317         assertFalse(line.hasOption("c"));
318     }
319 
320     @Test
321     void test15648() throws Exception {
322         final CommandLineParser parser = new PosixParser();
323         final String[] args = {"-m", "\"Two Words\""};
324         final Option m = OptionBuilder.hasArgs().create("m");
325         final Options options = new Options();
326         options.addOption(m);
327         final CommandLine line = parser.parse(options, args);
328         assertEquals("Two Words", line.getOptionValue("m"));
329     }
330 
331     @Test
332     void test31148() throws ParseException {
333         final Option multiArgOption = new Option("o", "option with multiple args");
334         multiArgOption.setArgs(1);
335 
336         final Options options = new Options();
337         options.addOption(multiArgOption);
338 
339         final Parser parser = new PosixParser();
340         final String[] args = {};
341         final Properties props = new Properties();
342         props.setProperty("o", "ovalue");
343         final CommandLine cl = parser.parse(options, args, props);
344 
345         assertTrue(cl.hasOption('o'));
346         assertEquals("ovalue", cl.getOptionValue('o'));
347     }
348 
349 }