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.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertNull;
23 import static org.junit.jupiter.api.Assertions.assertThrows;
24 import static org.mockito.Mockito.spy;
25 import static org.mockito.Mockito.when;
26
27 import java.io.ByteArrayOutputStream;
28 import java.io.IOException;
29 import java.io.OutputStreamWriter;
30 import java.io.PrintWriter;
31 import java.io.StringWriter;
32 import java.io.UncheckedIOException;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.stream.Stream;
36
37 import org.apache.commons.cli.HelpFormatter.Builder;
38 import org.junit.jupiter.api.Test;
39 import org.junit.jupiter.params.ParameterizedTest;
40 import org.junit.jupiter.params.provider.Arguments;
41 import org.junit.jupiter.params.provider.MethodSource;
42
43
44
45
46
47 public class HelpFormatterTest {
48 private static final String EOL = System.lineSeparator();
49
50 static Stream<Arguments> deprecatedOptionsProvider() {
51 final List<Arguments> lst = new ArrayList<>();
52 Option option = Option.builder("a").longOpt("aaa").desc("dddd dddd dddd")
53 .deprecated(DeprecatedAttributes.builder().setForRemoval(true).setSince("now")
54 .setDescription("Why why why").get())
55 .build();
56
57 HelpFormatter hf = HelpFormatter.builder().get();
58 lst.add(Arguments.of(hf, option, "[Deprecated] dddd dddd dddd"));
59
60
61 hf = HelpFormatter.builder().setShowDeprecated(false).get();
62 lst.add(Arguments.of(hf, option, "dddd dddd dddd"));
63
64 hf = HelpFormatter.builder().setShowDeprecated(true).get();
65 lst.add(Arguments.of(hf, option, "[Deprecated] dddd dddd dddd"));
66
67 hf = HelpFormatter.builder().setShowDeprecated(o -> String.format("%s [%s]", HelpFormatter.getDescription(o), o.getDeprecated())).get();
68 lst.add(Arguments.of(hf, option, "dddd dddd dddd [Deprecated for removal since now: Why why why]"));
69
70 option = Option.builder("a").longOpt("aaa")
71 .deprecated(DeprecatedAttributes.builder().setForRemoval(true).setSince("now")
72 .setDescription("Why why why").get())
73 .build();
74
75 hf = HelpFormatter.builder().get();
76 lst.add(Arguments.of(hf, option, "[Deprecated]"));
77
78 hf = HelpFormatter.builder().setShowDeprecated(false).get();
79 lst.add(Arguments.of(hf, option, ""));
80
81 hf = HelpFormatter.builder().setShowDeprecated(true).get();
82 lst.add(Arguments.of(hf, option, "[Deprecated]"));
83
84 hf = HelpFormatter.builder().setShowDeprecated(o -> String.format("%s [%s]", HelpFormatter.getDescription(o), o.getDeprecated())).get();
85 lst.add(Arguments.of(hf, option, "[Deprecated for removal since now: Why why why]"));
86
87 return lst.stream();
88 }
89
90 @Test
91 public void testAccessors() {
92 final HelpFormatter formatter = new HelpFormatter();
93
94 formatter.setArgName("argname");
95 assertEquals("argname", formatter.getArgName(), "arg name");
96
97 formatter.setDescPadding(3);
98 assertEquals(3, formatter.getDescPadding(), "desc padding");
99
100 formatter.setLeftPadding(7);
101 assertEquals(7, formatter.getLeftPadding(), "left padding");
102
103 formatter.setLongOptPrefix("~~");
104 assertEquals("~~", formatter.getLongOptPrefix(), "long opt prefix");
105
106 formatter.setNewLine("\n");
107 assertEquals("\n", formatter.getNewLine(), "new line");
108
109 formatter.setOptPrefix("~");
110 assertEquals("~", formatter.getOptPrefix(), "opt prefix");
111
112 formatter.setSyntaxPrefix("-> ");
113 assertEquals("-> ", formatter.getSyntaxPrefix(), "syntax prefix");
114
115 formatter.setWidth(80);
116 assertEquals(80, formatter.getWidth(), "width");
117 }
118
119 @Test
120 public void testAutomaticUsage() {
121 final HelpFormatter hf = new HelpFormatter();
122 Options options;
123 String expected = "usage: app [-a]";
124 final ByteArrayOutputStream out = new ByteArrayOutputStream();
125 final PrintWriter pw = new PrintWriter(out);
126
127 options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa");
128 hf.printUsage(pw, 60, "app", options);
129 pw.flush();
130 assertEquals(expected, out.toString().trim(), "simple auto usage");
131 out.reset();
132
133 expected = "usage: app [-a] [-b]";
134 options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa").addOption("b", false, "bbb");
135 hf.printUsage(pw, 60, "app", options);
136 pw.flush();
137 assertEquals(expected, out.toString().trim(), "simple auto usage");
138 out.reset();
139 }
140
141 @Test
142 public void testDefaultArgName() {
143 final Option option = Option.builder("f").hasArg().required(true).build();
144
145 final Options options = new Options();
146 options.addOption(option);
147
148 final StringWriter out = new StringWriter();
149
150 final HelpFormatter formatter = new HelpFormatter();
151 formatter.setArgName("argument");
152 formatter.printUsage(new PrintWriter(out), 80, "app", options);
153
154 assertEquals("usage: app -f <argument>" + EOL, out.toString());
155 }
156
157 @Test
158 public void testFindWrapPos() {
159 final HelpFormatter hf = new HelpFormatter();
160
161 String text = "This is a test.";
162
163 assertEquals(7, hf.findWrapPos(text, 8, 0), "wrap position");
164
165
166 assertEquals(-1, hf.findWrapPos(text, 8, 8), "wrap position 2");
167
168
169 text = "aaaa aa";
170 assertEquals(3, hf.findWrapPos(text, 3, 0), "wrap position 3");
171
172
173 text = "aaaaaa aaaaaa";
174 assertEquals(6, hf.findWrapPos(text, 6, 0), "wrap position 4");
175 assertEquals(-1, hf.findWrapPos(text, 6, 7), "wrap position 4");
176
177 text = "aaaaaa\n aaaaaa";
178 assertEquals(7, hf.findWrapPos(text, 6, 0), "wrap position 5");
179
180 text = "aaaaaa\t aaaaaa";
181 assertEquals(7, hf.findWrapPos(text, 6, 0), "wrap position 6");
182 }
183
184 @Test
185 public void testHeaderStartingWithLineSeparator0() {
186
187 final Options options = new Options();
188 final HelpFormatter formatter = new HelpFormatter();
189 final String header = EOL + "Header";
190 final String footer = "Footer";
191 final StringWriter out = new StringWriter();
192 formatter.printHelp(new PrintWriter(out), 80, "foobar", header, options, 2, 2, footer, true);
193
194 assertEquals(
195 "usage: foobar" + EOL +
196 EOL +
197 "Header" + EOL +
198 EOL +
199 "Footer" + EOL,
200 out.toString());
201
202 }
203
204 @Test
205 public void testHeaderStartingWithLineSeparator1() {
206
207 final Options options = new Options();
208 final String header = EOL + "Header";
209 final String footer = "Footer";
210 final Builder builder = HelpFormatter.builder();
211 StringWriter out = new StringWriter();
212 builder.setPrintWriter(new PrintWriter(out)).get().printHelp(new PrintWriter(out), 80, "foobar", header, options, 2, 2, footer, true);
213
214 assertEquals(
215 "usage: foobar" + EOL +
216 "" + EOL +
217 "Header" + EOL +
218 "" + EOL +
219 "Footer" + EOL,
220 out.toString());
221
222 out = new StringWriter();
223 builder.setPrintWriter(new PrintWriter(out)).get().printHelp("foobar", header, options, footer);
224
225 assertEquals(
226 "usage: foobar" + EOL +
227 EOL +
228 "Header" + EOL +
229 EOL +
230 "Footer" + EOL,
231 out.toString());
232
233 out = new StringWriter();
234 builder.setPrintWriter(new PrintWriter(out)).get().printHelp(80, "foobar", header, options, footer);
235
236 assertEquals(
237 "usage: foobar" + EOL +
238 EOL +
239 "Header" + EOL +
240 EOL +
241 "Footer" + EOL,
242 out.toString());
243
244 out = new StringWriter();
245 builder.setPrintWriter(new PrintWriter(out)).get().printHelp("foobar", header, options, footer, false);
246
247 assertEquals(
248 "usage: foobar" + EOL +
249 EOL +
250 "Header" + EOL +
251 EOL +
252 "Footer" + EOL,
253 out.toString());
254
255 out = new StringWriter();
256 builder.setPrintWriter(new PrintWriter(out)).get().printHelp("foobar", header, options, footer, true);
257
258 assertEquals(
259 "usage: foobar" + EOL +
260 EOL +
261 "Header" + EOL +
262 EOL +
263 "Footer" + EOL,
264 out.toString());
265
266 out = new StringWriter();
267 builder.setPrintWriter(new PrintWriter(out)).get().printHelp("foobar", options, false);
268
269 assertEquals(
270 "usage: foobar" + EOL +
271 "" + EOL,
272 out.toString());
273
274 }
275
276 @Test
277 public void testHelpWithLongOptSeparator() {
278 final Options options = new Options();
279 options.addOption("f", true, "the file");
280 options.addOption(Option.builder("s").longOpt("size").desc("the size").hasArg().argName("SIZE").build());
281 options.addOption(Option.builder().longOpt("age").desc("the age").hasArg().build());
282
283 final HelpFormatter formatter = new HelpFormatter();
284 assertEquals(HelpFormatter.DEFAULT_LONG_OPT_SEPARATOR, formatter.getLongOptSeparator());
285 formatter.setLongOptSeparator("=");
286 assertEquals("=", formatter.getLongOptSeparator());
287
288 final StringWriter out = new StringWriter();
289
290 formatter.printHelp(new PrintWriter(out), 80, "create", "header", options, 2, 2, "footer");
291
292
293 assertEquals(
294 "usage: create" + EOL +
295 "header" + EOL +
296 " --age=<arg> the age" + EOL +
297 " -f <arg> the file" + EOL +
298 " -s,--size=<SIZE> the size" + EOL +
299 "footer" + EOL,
300 out.toString());
301
302 }
303
304 @Test
305 public void testIndentedHeaderAndFooter() {
306
307 final Options options = new Options();
308 final HelpFormatter formatter = new HelpFormatter();
309 final String header = " Header1\n Header2";
310 final String footer = " Footer1\n Footer2";
311 final StringWriter out = new StringWriter();
312 formatter.printHelp(new PrintWriter(out), 80, "foobar", header, options, 2, 2, footer, true);
313
314 assertEquals(
315 "usage: foobar" + EOL +
316 " Header1" + EOL +
317 " Header2" + EOL +
318 "" + EOL +
319 " Footer1" + EOL +
320 " Footer2" + EOL,
321 out.toString());
322
323 }
324
325 @Test
326 public void testOptionWithoutShortFormat() {
327
328 final Options options = new Options();
329 options.addOption(new Option("a", "aaa", false, "aaaaaaa"));
330 options.addOption(new Option(null, "bbb", false, "bbbbbbb"));
331 options.addOption(new Option("c", null, false, "ccccccc"));
332
333 final HelpFormatter formatter = new HelpFormatter();
334 final StringWriter out = new StringWriter();
335 formatter.printHelp(new PrintWriter(out), 80, "foobar", "", options, 2, 2, "", true);
336
337 assertEquals(
338 "usage: foobar [-a] [--bbb] [-c]" + EOL +
339 " -a,--aaa aaaaaaa" + EOL +
340 " --bbb bbbbbbb" + EOL +
341 " -c ccccccc" + EOL,
342 out.toString());
343
344 }
345
346 @Test
347 public void testOptionWithoutShortFormat2() {
348
349 final Option help = new Option("h", "help", false, "print this message");
350 final Option version = new Option("v", "version", false, "print version information");
351 final Option newRun = new Option("n", "new", false, "Create NLT cache entries only for new items");
352 final Option trackerRun = new Option("t", "tracker", false, "Create NLT cache entries only for tracker items");
353
354 final Option timeLimit = Option.builder("l")
355 .longOpt("limit")
356 .hasArg()
357 .valueSeparator()
358 .desc("Set time limit for execution, in mintues")
359 .build();
360 final Option age = Option.builder("a").longOpt("age")
361 .hasArg()
362 .valueSeparator()
363 .desc("Age (in days) of cache item before being recomputed")
364 .build();
365 final Option server = Option.builder("s").longOpt("server")
366 .hasArg()
367 .valueSeparator()
368 .desc("The NLT server address")
369 .build();
370 final Option numResults = Option.builder("r").longOpt("results")
371 .hasArg()
372 .valueSeparator()
373 .desc("Number of results per item")
374 .build();
375 final Option configFile = Option.builder().longOpt("config")
376 .hasArg()
377 .valueSeparator()
378 .desc("Use the specified configuration file")
379 .build();
380
381
382 final Options mOptions = new Options();
383 mOptions.addOption(help);
384 mOptions.addOption(version);
385 mOptions.addOption(newRun);
386 mOptions.addOption(trackerRun);
387 mOptions.addOption(timeLimit);
388 mOptions.addOption(age);
389 mOptions.addOption(server);
390 mOptions.addOption(numResults);
391 mOptions.addOption(configFile);
392
393 final HelpFormatter formatter = new HelpFormatter();
394 final String eol = System.lineSeparator();
395 final StringWriter out = new StringWriter();
396 formatter.printHelp(new PrintWriter(out), 80, "commandline", "header", mOptions, 2, 2, "footer", true);
397
398 assertEquals(
399 "usage: commandline [-a <arg>] [--config <arg>] [-h] [-l <arg>] [-n] [-r <arg>]" + eol +
400 " [-s <arg>] [-t] [-v]" + eol +
401 "header" + eol +
402 " -a,--age <arg> Age (in days) of cache item before being recomputed" + eol +
403 " --config <arg> Use the specified configuration file" + eol +
404 " -h,--help print this message" + eol +
405 " -l,--limit <arg> Set time limit for execution, in mintues" + eol +
406 " -n,--new Create NLT cache entries only for new items" + eol +
407 " -r,--results <arg> Number of results per item" + eol +
408 " -s,--server <arg> The NLT server address" + eol +
409 " -t,--tracker Create NLT cache entries only for tracker items" + eol +
410 " -v,--version print version information" + eol +
411 "footer" + eol,
412 out.toString());
413
414 }
415
416 @ParameterizedTest
417 @MethodSource("deprecatedOptionsProvider")
418 public void testPrintDeprecatedOptions(final HelpFormatter hf, final Option option, final String expectedTxt) {
419 final StringBuffer sb = new StringBuffer();
420
421 final int leftPad = 1;
422 final int descPad = 3;
423 final String lpad = hf.createPadding(leftPad);
424 final String dpad = hf.createPadding(descPad);
425 Options options;
426 final StringBuilder expected = new StringBuilder().append(lpad).append("-a,--aaa");
427
428 options = new Options().addOption(option);
429 if (expectedTxt.length() > 0) {
430 expected.append(dpad).append(expectedTxt);
431 }
432 hf.renderOptions(sb, 160, options, leftPad, descPad);
433 assertEquals(expected.toString(), sb.toString());
434 }
435
436 @Test
437 public void testPrintHelpNewlineFooter() {
438 final HelpFormatter formatter = new HelpFormatter();
439 final ByteArrayOutputStream out = new ByteArrayOutputStream();
440 final PrintWriter pw = new PrintWriter(out);
441
442 final Options options = new Options();
443 options.addOption("a", "b");
444
445 formatter.printHelp(
446 pw,
447 80,
448 "test" + EOL,
449 "header" + EOL,
450 options,
451 0,
452 0,
453 EOL
454 );
455 final String expected = "usage: test" + EOL +
456 "header" + EOL +
457 "-ab" + EOL +
458 EOL;
459 pw.flush();
460 assertEquals(expected, out.toString(), "footer newline");
461 }
462
463 @Test
464 public void testPrintHelpNewlineHeader() {
465 final HelpFormatter formatter = new HelpFormatter();
466 final ByteArrayOutputStream out = new ByteArrayOutputStream();
467 final PrintWriter pw = new PrintWriter(out);
468
469 final Options options = new Options();
470 options.addOption("a", "b");
471
472 formatter.printHelp(
473 pw,
474 80,
475 "test" + EOL,
476 EOL,
477 options,
478 0,
479 0,
480 "footer" + EOL
481 );
482 final String expected = "usage: test" + EOL +
483 EOL +
484 "-ab" + EOL +
485 "footer" + EOL;
486 pw.flush();
487 assertEquals(expected, out.toString(), "header newline");
488 }
489
490 @Test
491 public void testPrintHelpWithEmptySyntax() {
492 final HelpFormatter formatter = new HelpFormatter();
493 assertThrows(IllegalArgumentException.class, () -> formatter.printHelp(null, new Options()), "null command line syntax should be rejected");
494 assertThrows(IllegalArgumentException.class, () -> formatter.printHelp(null, new Options(), true), "null command line syntax should be rejected");
495 assertThrows(IllegalArgumentException.class, () -> formatter.printHelp(null, new Options(), false), "null command line syntax should be rejected");
496 assertThrows(IllegalArgumentException.class, () -> formatter.printHelp("", new Options(), true), "null command line syntax should be rejected");
497 assertThrows(IllegalArgumentException.class, () -> formatter.printHelp("", new Options(), false), "null command line syntax should be rejected");
498 }
499
500 @Test
501 public void testPrintHelpWithSince() {
502 final String [] expected = {"usage: Command syntax", "Header", "Options Since Description",
503 " -n,--no-since - Description for n", " -W,--with-since 1.19.0 Descripton for W", "footer"};
504 final Options options = new Options()
505 .addOption(Option.builder("W").longOpt("with-since").since("1.19.0").desc("Descripton for W").build())
506 .addOption(Option.builder("n").longOpt("no-since").desc("Description for n").build());
507
508 final HelpFormatter formatter = HelpFormatter.builder().setShowSince(true).get();
509 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
510 try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos))) {
511 formatter.printHelp(pw, 80, "Command syntax", "Header", options, 2, 5, "footer", false);
512 }
513 assertArrayEquals(expected, baos.toString().split(System.lineSeparator()));
514 }
515
516 @Test
517 public void testPrintOptionGroupUsage() {
518 final OptionGroup group = new OptionGroup();
519 group.addOption(Option.builder("a").build());
520 group.addOption(Option.builder("b").build());
521 group.addOption(Option.builder("c").build());
522
523 final Options options = new Options();
524 options.addOptionGroup(group);
525
526 final StringWriter out = new StringWriter();
527
528 final HelpFormatter formatter = new HelpFormatter();
529 formatter.printUsage(new PrintWriter(out), 80, "app", options);
530
531 assertEquals("usage: app [-a | -b | -c]" + EOL, out.toString());
532 }
533
534 @Test
535 public void testPrintOptions() {
536 final StringBuffer sb = new StringBuffer();
537 final HelpFormatter hf = new HelpFormatter();
538 final int leftPad = 1;
539 final int descPad = 3;
540 final String lpad = hf.createPadding(leftPad);
541 final String dpad = hf.createPadding(descPad);
542 Options options;
543 String expected;
544
545 options = new Options().addOption("a", false, "aaaa aaaa aaaa aaaa aaaa");
546 expected = lpad + "-a" + dpad + "aaaa aaaa aaaa aaaa aaaa";
547 hf.renderOptions(sb, 60, options, leftPad, descPad);
548 assertEquals(expected, sb.toString(), "simple non-wrapped option");
549
550 int nextLineTabStop = leftPad + descPad + "-a".length();
551 expected = lpad + "-a" + dpad + "aaaa aaaa aaaa" + EOL + hf.createPadding(nextLineTabStop) + "aaaa aaaa";
552 sb.setLength(0);
553 hf.renderOptions(sb, nextLineTabStop + 17, options, leftPad, descPad);
554 assertEquals(expected, sb.toString(), "simple wrapped option");
555
556 options = new Options().addOption("a", "aaa", false, "dddd dddd dddd dddd");
557 expected = lpad + "-a,--aaa" + dpad + "dddd dddd dddd dddd";
558 sb.setLength(0);
559 hf.renderOptions(sb, 60, options, leftPad, descPad);
560 assertEquals(expected, sb.toString(), "long non-wrapped option");
561
562 nextLineTabStop = leftPad + descPad + "-a,--aaa".length();
563 expected = lpad + "-a,--aaa" + dpad + "dddd dddd" + EOL + hf.createPadding(nextLineTabStop) + "dddd dddd";
564 sb.setLength(0);
565 hf.renderOptions(sb, 25, options, leftPad, descPad);
566 assertEquals(expected, sb.toString(), "long wrapped option");
567
568 options = new Options().addOption("a", "aaa", false, "dddd dddd dddd dddd").addOption("b", false, "feeee eeee eeee eeee");
569 expected = lpad + "-a,--aaa" + dpad + "dddd dddd" + EOL + hf.createPadding(nextLineTabStop) + "dddd dddd" + EOL + lpad + "-b " + dpad
570 + "feeee eeee" + EOL + hf.createPadding(nextLineTabStop) + "eeee eeee";
571 sb.setLength(0);
572 hf.renderOptions(sb, 25, options, leftPad, descPad);
573 assertEquals(expected, sb.toString(), "multiple wrapped options");
574 }
575
576 @Test
577 public void testPrintOptionWithEmptyArgNameUsage() {
578 final Option option = new Option("f", true, null);
579 option.setArgName("");
580 option.setRequired(true);
581
582 final Options options = new Options();
583 options.addOption(option);
584
585 final StringWriter out = new StringWriter();
586
587 final HelpFormatter formatter = new HelpFormatter();
588 formatter.printUsage(new PrintWriter(out), 80, "app", options);
589
590 assertEquals("usage: app -f" + EOL, out.toString());
591 }
592
593 @Test
594 public void testPrintRequiredOptionGroupUsage() {
595 final OptionGroup group = new OptionGroup();
596 group.addOption(Option.builder("a").build());
597 group.addOption(Option.builder("b").build());
598 group.addOption(Option.builder("c").build());
599 group.setRequired(true);
600
601 final Options options = new Options();
602 options.addOptionGroup(group);
603
604 final StringWriter out = new StringWriter();
605
606 final HelpFormatter formatter = new HelpFormatter();
607 formatter.printUsage(new PrintWriter(out), 80, "app", options);
608
609 assertEquals("usage: app -a | -b | -c" + EOL, out.toString());
610 }
611
612
613 @Test
614 public void testPrintSortedUsage() {
615 final Options opts = new Options();
616 opts.addOption(new Option("a", "first"));
617 opts.addOption(new Option("b", "second"));
618 opts.addOption(new Option("c", "third"));
619
620 final HelpFormatter helpFormatter = new HelpFormatter();
621 helpFormatter.setOptionComparator((opt1, opt2) -> opt2.getKey().compareToIgnoreCase(opt1.getKey()));
622
623 final StringWriter out = new StringWriter();
624 helpFormatter.printUsage(new PrintWriter(out), 80, "app", opts);
625
626 assertEquals("usage: app [-c] [-b] [-a]" + EOL, out.toString());
627 }
628
629 @Test
630 public void testPrintSortedUsageWithNullComparator() {
631 final Options opts = new Options();
632 opts.addOption(new Option("c", "first"));
633 opts.addOption(new Option("b", "second"));
634 opts.addOption(new Option("a", "third"));
635
636 final HelpFormatter helpFormatter = new HelpFormatter();
637 helpFormatter.setOptionComparator(null);
638
639 final StringWriter out = new StringWriter();
640 helpFormatter.printUsage(new PrintWriter(out), 80, "app", opts);
641
642 assertEquals("usage: app [-c] [-b] [-a]" + EOL, out.toString());
643 }
644
645
646
647 @Test
648 public void testPrintUsage() {
649 final Option optionA = new Option("a", "first");
650 final Option optionB = new Option("b", "second");
651 final Option optionC = new Option("c", "third");
652 final Options opts = new Options();
653 opts.addOption(optionA);
654 opts.addOption(optionB);
655 opts.addOption(optionC);
656 final HelpFormatter helpFormatter = new HelpFormatter();
657 final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
658 try (PrintWriter printWriter = new PrintWriter(bytesOut)) {
659 helpFormatter.printUsage(printWriter, 80, "app", opts);
660 }
661 assertEquals("usage: app [-a] [-b] [-c]" + EOL, bytesOut.toString());
662 }
663
664 @Test
665 public void testRenderSince() throws IOException {
666 final String[] expected = {"Options Since Description", " -n,--no-since - Description for n",
667 " -W,--with-since 1.19.0 Descripton for W"};
668 final Options options = new Options()
669 .addOption(Option.builder("W").longOpt("with-since").since("1.19.0").desc("Descripton for W").build())
670 .addOption(Option.builder("n").longOpt("no-since").desc("Description for n").build());
671 final HelpFormatter formatter = HelpFormatter.builder().setShowSince(true).get();
672
673 final StringBuffer sb = new StringBuffer();
674 formatter.renderOptions(sb, 50, options, 2, 5);
675 assertArrayEquals(expected, sb.toString().split(System.lineSeparator()));
676
677 final HelpFormatter spy = spy(formatter);
678 when(spy.appendOptions(sb, 50, options, 2, 5)).thenThrow(IOException.class);
679 assertThrows(UncheckedIOException.class, () -> spy.renderOptions(sb, 50, options, 2, 5));
680 }
681
682 @Test
683 public void testRenderWrappedTextMultiLine() {
684
685 final int width = 16;
686 final int padding = 0;
687
688 final String expected = "aaaa aaaa aaaa" + EOL +
689 "aaaaaa" + EOL +
690 "aaaaa";
691
692
693 final StringBuffer sb = new StringBuffer();
694 new HelpFormatter().renderWrappedText(sb, width, padding, expected);
695 assertEquals(expected, sb.toString(), "multi line text");
696 }
697
698 @Test
699 public void testRenderWrappedTextMultiLinePadded() {
700
701 final int width = 16;
702 final int padding = 4;
703
704 final String text = "aaaa aaaa aaaa" + EOL +
705 "aaaaaa" + EOL +
706 "aaaaa";
707 final String expected = "aaaa aaaa aaaa" + EOL +
708 " aaaaaa" + EOL +
709 " aaaaa";
710
711
712 final StringBuffer sb = new StringBuffer();
713 new HelpFormatter().renderWrappedText(sb, width, padding, text);
714 assertEquals(expected, sb.toString(), "multi-line padded text");
715 }
716
717 @Test
718 public void testRenderWrappedTextSingleLine() throws IOException {
719
720 final int width = 12;
721 final int padding = 0;
722 final String text = "This is a test.";
723 final String expected = "This is a" + EOL + "test.";
724
725 final StringBuffer sb = new StringBuffer();
726 new HelpFormatter().renderWrappedText(sb, width, padding, text);
727 assertEquals(expected, sb.toString(), "single line text");
728
729 final HelpFormatter spy = spy(new HelpFormatter());
730 when(spy.appendWrappedText(sb, width, padding, text)).thenThrow(IOException.class);
731 assertThrows(UncheckedIOException.class, () -> spy.renderWrappedText(sb, width, padding, text));
732
733 }
734
735 @Test
736 public void testRenderWrappedTextSingleLinePadded() {
737
738 final int width = 12;
739 final int padding = 4;
740 final String text = "This is a test.";
741 final String expected = "This is a" + EOL + " test.";
742
743 final StringBuffer sb = new StringBuffer();
744 new HelpFormatter().renderWrappedText(sb, width, padding, text);
745 assertEquals(expected, sb.toString(), "single line padded text");
746 }
747
748 @Test
749 public void testRenderWrappedTextSingleLinePadded2() {
750
751 final int width = 53;
752 final int padding = 24;
753
754 final String text = " -p,--period <PERIOD> PERIOD is time duration of form " +
755 "DATE[-DATE] where DATE has form YYYY[MM[DD]]";
756 final String expected = " -p,--period <PERIOD> PERIOD is time duration of" + EOL +
757 " form DATE[-DATE] where DATE" + EOL +
758 " has form YYYY[MM[DD]]";
759
760
761 final StringBuffer sb = new StringBuffer();
762 new HelpFormatter().renderWrappedText(sb, width, padding, text);
763 assertEquals(expected, sb.toString(), "single line padded text 2");
764 }
765
766 @Test
767 public void testRenderWrappedTextWordCut() {
768 final int width = 7;
769 final int padding = 0;
770 final String text = "Thisisatest.";
771 final String expected = "Thisisa" + EOL + "test.";
772
773 final StringBuffer sb = new StringBuffer();
774 new HelpFormatter().renderWrappedText(sb, width, padding, text);
775 assertEquals(expected, sb.toString(), "cut and wrap");
776 }
777
778 @Test
779 public void testRtrim() {
780 final HelpFormatter formatter = new HelpFormatter();
781
782 assertNull(formatter.rtrim(null));
783 assertEquals("", formatter.rtrim(""));
784 assertEquals(" foo", formatter.rtrim(" foo "));
785 }
786
787 @Test
788 public void testUsageWithLongOptSeparator() {
789 final Options options = new Options();
790 options.addOption("f", true, "the file");
791 options.addOption(Option.builder("s").longOpt("size").desc("the size").hasArg().argName("SIZE").build());
792 options.addOption(Option.builder().longOpt("age").desc("the age").hasArg().build());
793
794 final HelpFormatter formatter = new HelpFormatter();
795 formatter.setLongOptSeparator("=");
796
797 final StringWriter out = new StringWriter();
798
799 formatter.printUsage(new PrintWriter(out), 80, "create", options);
800
801 assertEquals("usage: create [--age=<arg>] [-f <arg>] [-s <SIZE>]", out.toString().trim());
802 }
803 }