1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.cli;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertNull;
22 import static org.junit.Assert.fail;
23
24 import java.io.ByteArrayOutputStream;
25 import java.io.PrintWriter;
26 import java.io.StringWriter;
27
28 import org.junit.Test;
29
30
31
32
33 public class HelpFormatterTest {
34 private static final String EOL = System.lineSeparator();
35
36 @Test
37 public void testAccessors() {
38 final HelpFormatter formatter = new HelpFormatter();
39
40 formatter.setArgName("argname");
41 assertEquals("arg name", "argname", formatter.getArgName());
42
43 formatter.setDescPadding(3);
44 assertEquals("desc padding", 3, formatter.getDescPadding());
45
46 formatter.setLeftPadding(7);
47 assertEquals("left padding", 7, formatter.getLeftPadding());
48
49 formatter.setLongOptPrefix("~~");
50 assertEquals("long opt prefix", "~~", formatter.getLongOptPrefix());
51
52 formatter.setNewLine("\n");
53 assertEquals("new line", "\n", formatter.getNewLine());
54
55 formatter.setOptPrefix("~");
56 assertEquals("opt prefix", "~", formatter.getOptPrefix());
57
58 formatter.setSyntaxPrefix("-> ");
59 assertEquals("syntax prefix", "-> ", formatter.getSyntaxPrefix());
60
61 formatter.setWidth(80);
62 assertEquals("width", 80, formatter.getWidth());
63 }
64
65 @Test
66 public void testAutomaticUsage() {
67 final HelpFormatter hf = new HelpFormatter();
68 Options options;
69 String expected = "usage: app [-a]";
70 final ByteArrayOutputStream out = new ByteArrayOutputStream();
71 final PrintWriter pw = new PrintWriter(out);
72
73 options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa");
74 hf.printUsage(pw, 60, "app", options);
75 pw.flush();
76 assertEquals("simple auto usage", expected, out.toString().trim());
77 out.reset();
78
79 expected = "usage: app [-a] [-b]";
80 options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa").addOption("b", false, "bbb");
81 hf.printUsage(pw, 60, "app", options);
82 pw.flush();
83 assertEquals("simple auto usage", expected, out.toString().trim());
84 out.reset();
85 }
86
87 @Test
88 public void testDefaultArgName() {
89 final Option option = Option.builder("f").hasArg().required(true).build();
90
91 final Options options = new Options();
92 options.addOption(option);
93
94 final StringWriter out = new StringWriter();
95
96 final HelpFormatter formatter = new HelpFormatter();
97 formatter.setArgName("argument");
98 formatter.printUsage(new PrintWriter(out), 80, "app", options);
99
100 assertEquals("usage: app -f <argument>" + EOL, out.toString());
101 }
102
103 @Test
104 public void testFindWrapPos() {
105 final HelpFormatter hf = new HelpFormatter();
106
107 String text = "This is a test.";
108
109 assertEquals("wrap position", 7, hf.findWrapPos(text, 8, 0));
110
111
112 assertEquals("wrap position 2", -1, hf.findWrapPos(text, 8, 8));
113
114
115 text = "aaaa aa";
116 assertEquals("wrap position 3", 3, hf.findWrapPos(text, 3, 0));
117
118
119 text = "aaaaaa aaaaaa";
120 assertEquals("wrap position 4", 6, hf.findWrapPos(text, 6, 0));
121 assertEquals("wrap position 4", -1, hf.findWrapPos(text, 6, 7));
122
123 text = "aaaaaa\n aaaaaa";
124 assertEquals("wrap position 5", 7, hf.findWrapPos(text, 6, 0));
125
126 text = "aaaaaa\t aaaaaa";
127 assertEquals("wrap position 6", 7, hf.findWrapPos(text, 6, 0));
128 }
129
130 @Test
131 public void testHeaderStartingWithLineSeparator() {
132
133 final Options options = new Options();
134 final HelpFormatter formatter = new HelpFormatter();
135 final String header = EOL + "Header";
136 final String footer = "Footer";
137 final StringWriter out = new StringWriter();
138 formatter.printHelp(new PrintWriter(out), 80, "foobar", header, options, 2, 2, footer, true);
139
140 assertEquals(
141 "usage: foobar" + EOL +
142 "" + EOL +
143 "Header" + EOL +
144 "" + EOL +
145 "Footer" + EOL,
146 out.toString());
147
148 }
149
150 @Test
151 public void testHelpWithLongOptSeparator() {
152 final Options options = new Options();
153 options.addOption("f", true, "the file");
154 options.addOption(Option.builder("s").longOpt("size").desc("the size").hasArg().argName("SIZE").build());
155 options.addOption(Option.builder().longOpt("age").desc("the age").hasArg().build());
156
157 final HelpFormatter formatter = new HelpFormatter();
158 assertEquals(HelpFormatter.DEFAULT_LONG_OPT_SEPARATOR, formatter.getLongOptSeparator());
159 formatter.setLongOptSeparator("=");
160 assertEquals("=", formatter.getLongOptSeparator());
161
162 final StringWriter out = new StringWriter();
163
164 formatter.printHelp(new PrintWriter(out), 80, "create", "header", options, 2, 2, "footer");
165
166
167 assertEquals(
168 "usage: create" + EOL +
169 "header" + EOL +
170 " --age=<arg> the age" + EOL +
171 " -f <arg> the file" + EOL +
172 " -s,--size=<SIZE> the size" + EOL +
173 "footer" + EOL,
174 out.toString());
175
176 }
177
178 @Test
179 public void testIndentedHeaderAndFooter() {
180
181 final Options options = new Options();
182 final HelpFormatter formatter = new HelpFormatter();
183 final String header = " Header1\n Header2";
184 final String footer = " Footer1\n Footer2";
185 final StringWriter out = new StringWriter();
186 formatter.printHelp(new PrintWriter(out), 80, "foobar", header, options, 2, 2, footer, true);
187
188 assertEquals(
189 "usage: foobar" + EOL +
190 " Header1" + EOL +
191 " Header2" + EOL +
192 "" + EOL +
193 " Footer1" + EOL +
194 " Footer2" + EOL,
195 out.toString());
196
197 }
198
199 @Test
200 public void testOptionWithoutShortFormat() {
201
202 final Options options = new Options();
203 options.addOption(new Option("a", "aaa", false, "aaaaaaa"));
204 options.addOption(new Option(null, "bbb", false, "bbbbbbb"));
205 options.addOption(new Option("c", null, false, "ccccccc"));
206
207 final HelpFormatter formatter = new HelpFormatter();
208 final StringWriter out = new StringWriter();
209 formatter.printHelp(new PrintWriter(out), 80, "foobar", "", options, 2, 2, "", true);
210
211 assertEquals(
212 "usage: foobar [-a] [--bbb] [-c]" + EOL +
213 " -a,--aaa aaaaaaa" + EOL +
214 " --bbb bbbbbbb" + EOL +
215 " -c ccccccc" + EOL,
216 out.toString());
217
218 }
219
220 @Test
221 public void testOptionWithoutShortFormat2() {
222
223 final Option help = new Option("h", "help", false, "print this message");
224 final Option version = new Option("v", "version", false, "print version information");
225 final Option newRun = new Option("n", "new", false, "Create NLT cache entries only for new items");
226 final Option trackerRun = new Option("t", "tracker", false, "Create NLT cache entries only for tracker items");
227
228
229 final Option timeLimit = Option.builder("l")
230 .longOpt("limit")
231 .hasArg()
232 .valueSeparator()
233 .desc("Set time limit for execution, in mintues")
234 .build();
235
236 final Option age = Option.builder("a").longOpt("age")
237 .hasArg()
238 .valueSeparator()
239 .desc("Age (in days) of cache item before being recomputed")
240 .build();
241
242 final Option server = Option.builder("s").longOpt("server")
243 .hasArg()
244 .valueSeparator()
245 .desc("The NLT server address")
246 .build();
247
248 final Option numResults = Option.builder("r").longOpt("results")
249 .hasArg()
250 .valueSeparator()
251 .desc("Number of results per item")
252 .build();
253
254 final Option configFile = Option.builder().longOpt("config")
255 .hasArg()
256 .valueSeparator()
257 .desc("Use the specified configuration file")
258 .build();
259
260
261 final Options mOptions = new Options();
262 mOptions.addOption(help);
263 mOptions.addOption(version);
264 mOptions.addOption(newRun);
265 mOptions.addOption(trackerRun);
266 mOptions.addOption(timeLimit);
267 mOptions.addOption(age);
268 mOptions.addOption(server);
269 mOptions.addOption(numResults);
270 mOptions.addOption(configFile);
271
272 final HelpFormatter formatter = new HelpFormatter();
273 final String eol = System.lineSeparator();
274 final StringWriter out = new StringWriter();
275 formatter.printHelp(new PrintWriter(out), 80, "commandline", "header", mOptions, 2, 2, "footer", true);
276
277 assertEquals(
278 "usage: commandline [-a <arg>] [--config <arg>] [-h] [-l <arg>] [-n] [-r <arg>]" + eol +
279 " [-s <arg>] [-t] [-v]" + eol +
280 "header" + eol +
281 " -a,--age <arg> Age (in days) of cache item before being recomputed" + eol +
282 " --config <arg> Use the specified configuration file" + eol +
283 " -h,--help print this message" + eol +
284 " -l,--limit <arg> Set time limit for execution, in mintues" + eol +
285 " -n,--new Create NLT cache entries only for new items" + eol +
286 " -r,--results <arg> Number of results per item" + eol +
287 " -s,--server <arg> The NLT server address" + eol +
288 " -t,--tracker Create NLT cache entries only for tracker items" + eol +
289 " -v,--version print version information" + eol +
290 "footer" + eol,
291 out.toString());
292
293 }
294
295 @Test
296 public void testPrintHelpNewlineFooter() {
297 final HelpFormatter formatter = new HelpFormatter();
298 final ByteArrayOutputStream out = new ByteArrayOutputStream();
299 final PrintWriter pw = new PrintWriter(out);
300
301 final Options options = new Options();
302 options.addOption("a", "b");
303
304 formatter.printHelp(
305 pw,
306 80,
307 "test" + EOL,
308 "header" + EOL,
309 options,
310 0,
311 0,
312 EOL
313 );
314 final String expected = "usage: test" + EOL +
315 "header" + EOL +
316 "-ab" + EOL +
317 EOL;
318 pw.flush();
319 assertEquals("footer newline", expected, out.toString());
320 }
321
322 @Test
323 public void testPrintHelpNewlineHeader() {
324 final HelpFormatter formatter = new HelpFormatter();
325 final ByteArrayOutputStream out = new ByteArrayOutputStream();
326 final PrintWriter pw = new PrintWriter(out);
327
328 final Options options = new Options();
329 options.addOption("a", "b");
330
331 formatter.printHelp(
332 pw,
333 80,
334 "test" + EOL,
335 EOL,
336 options,
337 0,
338 0,
339 "footer" + EOL
340 );
341 final String expected = "usage: test" + EOL +
342 EOL +
343 "-ab" + EOL +
344 "footer" + EOL;
345 pw.flush();
346 assertEquals("header newline", expected, out.toString());
347 }
348
349 @Test
350 public void testPrintHelpWithEmptySyntax() {
351 final HelpFormatter formatter = new HelpFormatter();
352 try {
353 formatter.printHelp(null, new Options());
354 fail("null command line syntax should be rejected");
355 } catch (final IllegalArgumentException e) {
356
357 }
358
359 try {
360 formatter.printHelp("", new Options());
361 fail("empty command line syntax should be rejected");
362 } catch (final IllegalArgumentException e) {
363
364 }
365 }
366
367 @Test
368 public void testPrintOptionGroupUsage() {
369 final OptionGroup group = new OptionGroup();
370 group.addOption(Option.builder("a").build());
371 group.addOption(Option.builder("b").build());
372 group.addOption(Option.builder("c").build());
373
374 final Options options = new Options();
375 options.addOptionGroup(group);
376
377 final StringWriter out = new StringWriter();
378
379 final HelpFormatter formatter = new HelpFormatter();
380 formatter.printUsage(new PrintWriter(out), 80, "app", options);
381
382 assertEquals("usage: app [-a | -b | -c]" + EOL, out.toString());
383 }
384
385 @Test
386 public void testPrintOptions() {
387 final StringBuffer sb = new StringBuffer();
388 final HelpFormatter hf = new HelpFormatter();
389 final int leftPad = 1;
390 final int descPad = 3;
391 final String lpad = hf.createPadding(leftPad);
392 final String dpad = hf.createPadding(descPad);
393 Options options;
394 String expected;
395
396 options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa");
397 expected = lpad + "-a" + dpad + "aaaa aaaa aaaa aaaa aaaa";
398 hf.renderOptions(sb, 60, options, leftPad, descPad);
399 assertEquals("simple non-wrapped option", expected, sb.toString());
400
401 int nextLineTabStop = leftPad + descPad + "-a".length();
402 expected = lpad + "-a" + dpad + "aaaa aaaa aaaa" + EOL + hf.createPadding(nextLineTabStop) + "aaaa aaaa";
403 sb.setLength(0);
404 hf.renderOptions(sb, nextLineTabStop + 17, options, leftPad, descPad);
405 assertEquals("simple wrapped option", expected, sb.toString());
406
407 options = new Options().addOption("a", "aaa", false, "dddd dddd dddd dddd");
408 expected = lpad + "-a,--aaa" + dpad + "dddd dddd dddd dddd";
409 sb.setLength(0);
410 hf.renderOptions(sb, 60, options, leftPad, descPad);
411 assertEquals("long non-wrapped option", expected, sb.toString());
412
413 nextLineTabStop = leftPad + descPad + "-a,--aaa".length();
414 expected = lpad + "-a,--aaa" + dpad + "dddd dddd" + EOL + hf.createPadding(nextLineTabStop) + "dddd dddd";
415 sb.setLength(0);
416 hf.renderOptions(sb, 25, options, leftPad, descPad);
417 assertEquals("long wrapped option", expected, sb.toString());
418
419 options = new Options().addOption("a", "aaa", false, "dddd dddd dddd dddd").addOption("b", false, "feeee eeee eeee eeee");
420 expected = lpad + "-a,--aaa" + dpad + "dddd dddd" + EOL + hf.createPadding(nextLineTabStop) + "dddd dddd" + EOL + lpad + "-b " + dpad
421 + "feeee eeee" + EOL + hf.createPadding(nextLineTabStop) + "eeee eeee";
422 sb.setLength(0);
423 hf.renderOptions(sb, 25, options, leftPad, descPad);
424 assertEquals("multiple wrapped options", expected, sb.toString());
425 }
426
427 @Test
428 public void testPrintOptionWithEmptyArgNameUsage() {
429 final Option option = new Option("f", true, null);
430 option.setArgName("");
431 option.setRequired(true);
432
433 final Options options = new Options();
434 options.addOption(option);
435
436 final StringWriter out = new StringWriter();
437
438 final HelpFormatter formatter = new HelpFormatter();
439 formatter.printUsage(new PrintWriter(out), 80, "app", options);
440
441 assertEquals("usage: app -f" + EOL, out.toString());
442 }
443
444 @Test
445 public void testPrintRequiredOptionGroupUsage() {
446 final OptionGroup group = new OptionGroup();
447 group.addOption(Option.builder("a").build());
448 group.addOption(Option.builder("b").build());
449 group.addOption(Option.builder("c").build());
450 group.setRequired(true);
451
452 final Options options = new Options();
453 options.addOptionGroup(group);
454
455 final StringWriter out = new StringWriter();
456
457 final HelpFormatter formatter = new HelpFormatter();
458 formatter.printUsage(new PrintWriter(out), 80, "app", options);
459
460 assertEquals("usage: app -a | -b | -c" + EOL, out.toString());
461 }
462
463
464 @Test
465 public void testPrintSortedUsage() {
466 final Options opts = new Options();
467 opts.addOption(new Option("a", "first"));
468 opts.addOption(new Option("b", "second"));
469 opts.addOption(new Option("c", "third"));
470
471 final HelpFormatter helpFormatter = new HelpFormatter();
472 helpFormatter.setOptionComparator((opt1, opt2) -> opt2.getKey().compareToIgnoreCase(opt1.getKey()));
473
474 final StringWriter out = new StringWriter();
475 helpFormatter.printUsage(new PrintWriter(out), 80, "app", opts);
476
477 assertEquals("usage: app [-c] [-b] [-a]" + EOL, out.toString());
478 }
479
480 @Test
481 public void testPrintSortedUsageWithNullComparator() {
482 final Options opts = new Options();
483 opts.addOption(new Option("c", "first"));
484 opts.addOption(new Option("b", "second"));
485 opts.addOption(new Option("a", "third"));
486
487 final HelpFormatter helpFormatter = new HelpFormatter();
488 helpFormatter.setOptionComparator(null);
489
490 final StringWriter out = new StringWriter();
491 helpFormatter.printUsage(new PrintWriter(out), 80, "app", opts);
492
493 assertEquals("usage: app [-c] [-b] [-a]" + EOL, out.toString());
494 }
495
496
497
498 @Test
499 public void testPrintUsage() {
500 final Option optionA = new Option("a", "first");
501 final Option optionB = new Option("b", "second");
502 final Option optionC = new Option("c", "third");
503 final Options opts = new Options();
504 opts.addOption(optionA);
505 opts.addOption(optionB);
506 opts.addOption(optionC);
507 final HelpFormatter helpFormatter = new HelpFormatter();
508 final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
509 try (PrintWriter printWriter = new PrintWriter(bytesOut)) {
510 helpFormatter.printUsage(printWriter, 80, "app", opts);
511 }
512 assertEquals("usage: app [-a] [-b] [-c]" + EOL, bytesOut.toString());
513 }
514
515 @Test
516 public void testRenderWrappedTextMultiLine() {
517
518 final int width = 16;
519 final int padding = 0;
520
521 final String expected = "aaaa aaaa aaaa" + EOL +
522 "aaaaaa" + EOL +
523 "aaaaa";
524
525
526 final StringBuffer sb = new StringBuffer();
527 new HelpFormatter().renderWrappedText(sb, width, padding, expected);
528 assertEquals("multi line text", expected, sb.toString());
529 }
530
531 @Test
532 public void testRenderWrappedTextMultiLinePadded() {
533
534 final int width = 16;
535 final int padding = 4;
536
537 final String text = "aaaa aaaa aaaa" + EOL +
538 "aaaaaa" + EOL +
539 "aaaaa";
540 final String expected = "aaaa aaaa aaaa" + EOL +
541 " aaaaaa" + EOL +
542 " aaaaa";
543
544
545 final StringBuffer sb = new StringBuffer();
546 new HelpFormatter().renderWrappedText(sb, width, padding, text);
547 assertEquals("multi-line padded text", expected, sb.toString());
548 }
549
550 @Test
551 public void testRenderWrappedTextSingleLine() {
552
553 final int width = 12;
554 final int padding = 0;
555 final String text = "This is a test.";
556 final String expected = "This is a" + EOL + "test.";
557
558 final StringBuffer sb = new StringBuffer();
559 new HelpFormatter().renderWrappedText(sb, width, padding, text);
560 assertEquals("single line text", expected, sb.toString());
561 }
562
563 @Test
564 public void testRenderWrappedTextSingleLinePadded() {
565
566 final int width = 12;
567 final int padding = 4;
568 final String text = "This is a test.";
569 final String expected = "This is a" + EOL + " test.";
570
571 final StringBuffer sb = new StringBuffer();
572 new HelpFormatter().renderWrappedText(sb, width, padding, text);
573 assertEquals("single line padded text", expected, sb.toString());
574 }
575
576 @Test
577 public void testRenderWrappedTextSingleLinePadded2() {
578
579 final int width = 53;
580 final int padding = 24;
581
582 final String text = " -p,--period <PERIOD> PERIOD is time duration of form " +
583 "DATE[-DATE] where DATE has form YYYY[MM[DD]]";
584 final String expected = " -p,--period <PERIOD> PERIOD is time duration of" + EOL +
585 " form DATE[-DATE] where DATE" + EOL +
586 " has form YYYY[MM[DD]]";
587
588
589 final StringBuffer sb = new StringBuffer();
590 new HelpFormatter().renderWrappedText(sb, width, padding, text);
591 assertEquals("single line padded text 2", expected, sb.toString());
592 }
593
594 @Test
595 public void testRenderWrappedTextWordCut() {
596 final int width = 7;
597 final int padding = 0;
598 final String text = "Thisisatest.";
599 final String expected = "Thisisa" + EOL + "test.";
600
601 final StringBuffer sb = new StringBuffer();
602 new HelpFormatter().renderWrappedText(sb, width, padding, text);
603 assertEquals("cut and wrap", expected, sb.toString());
604 }
605
606 @Test
607 public void testRtrim() {
608 final HelpFormatter formatter = new HelpFormatter();
609
610 assertNull(formatter.rtrim(null));
611 assertEquals("", formatter.rtrim(""));
612 assertEquals(" foo", formatter.rtrim(" foo "));
613 }
614
615 @Test
616 public void testUsageWithLongOptSeparator() {
617 final Options options = new Options();
618 options.addOption("f", true, "the file");
619 options.addOption(Option.builder("s").longOpt("size").desc("the size").hasArg().argName("SIZE").build());
620 options.addOption(Option.builder().longOpt("age").desc("the age").hasArg().build());
621
622 final HelpFormatter formatter = new HelpFormatter();
623 formatter.setLongOptSeparator("=");
624
625 final StringWriter out = new StringWriter();
626
627 formatter.printUsage(new PrintWriter(out), 80, "create", options);
628
629 assertEquals("usage: create [--age=<arg>] [-f <arg>] [-s <SIZE>]", out.toString().trim());
630 }
631 }