1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.cli.help;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertThrows;
21
22 import java.io.IOException;
23 import java.io.StringReader;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.LinkedList;
28 import java.util.List;
29 import java.util.Queue;
30
31 import org.apache.commons.io.IOUtils;
32 import org.junit.jupiter.api.BeforeEach;
33 import org.junit.jupiter.api.Test;
34 import org.junit.jupiter.params.ParameterizedTest;
35 import org.junit.jupiter.params.provider.MethodSource;
36
37
38
39
40 public final class TextHelpAppendableTest {
41
42 private StringBuilder sb;
43 private TextHelpAppendable underTest;
44
45 @BeforeEach
46 public void setUp() {
47 sb = new StringBuilder();
48 underTest = new TextHelpAppendable(sb);
49 }
50
51 @Test
52 void testAdjustTableFormat() {
53
54
55 final TableDefinition tableDefinition = TableDefinition.from("Testing",
56 Collections.singletonList(TextStyle.builder().setMaxWidth(3).get()),
57 Collections.singletonList("header"),
58
59 Collections.singletonList(Collections.singletonList("data"))
60 );
61
62 final TableDefinition actual = underTest.adjustTableFormat(tableDefinition);
63 assertEquals("header".length(), actual.columnTextStyles().get(0).getMaxWidth());
64 assertEquals("header".length(), actual.columnTextStyles().get(0).getMinWidth());
65 }
66
67 @Test
68 void testAppend() throws IOException {
69 final char c = (char) 0x1F44D;
70 underTest.append(c);
71 assertEquals(1, sb.length());
72 assertEquals(String.valueOf(c), sb.toString());
73
74 sb.setLength(0);
75 underTest.append("Hello");
76 assertEquals("Hello", sb.toString());
77 }
78
79 @Test
80 void testAppendHeader() throws IOException {
81 final String[] expected = { " Hello World", " ===========", "" };
82
83 sb.setLength(0);
84 underTest.appendHeader(1, "Hello World");
85 List<String> actual = IOUtils.readLines(new StringReader(sb.toString()));
86 assertEquals(Arrays.asList(expected), actual, "header 1 failed");
87
88 sb.setLength(0);
89 underTest.appendHeader(2, "Hello World");
90 actual = IOUtils.readLines(new StringReader(sb.toString()));
91 expected[1] = " %%%%%%%%%%%";
92 assertEquals(Arrays.asList(expected), actual, "header 2 failed");
93
94 sb.setLength(0);
95 underTest.appendHeader(3, "Hello World");
96 actual = IOUtils.readLines(new StringReader(sb.toString()));
97 expected[1] = " +++++++++++";
98 assertEquals(Arrays.asList(expected), actual, "header 3 failed");
99
100 sb.setLength(0);
101 underTest.appendHeader(4, "Hello World");
102 actual = IOUtils.readLines(new StringReader(sb.toString()));
103 expected[1] = " ___________";
104 assertEquals(Arrays.asList(expected), actual, "header 4 failed");
105
106 sb.setLength(0);
107 underTest.appendHeader(5, "Hello World");
108 actual = IOUtils.readLines(new StringReader(sb.toString()));
109 assertEquals(Arrays.asList(expected), actual, "header 5 failed");
110
111 sb.setLength(0);
112 assertThrows(IllegalArgumentException.class, () -> underTest.appendHeader(0, "Hello World"));
113
114 sb.setLength(0);
115 underTest.appendHeader(5, "");
116 assertEquals(0, sb.length(), "empty string test failed");
117
118 sb.setLength(0);
119 underTest.appendHeader(5, null);
120 assertEquals(0, sb.length(), "null test failed");
121 }
122
123 @Test
124 void testAppendList() throws IOException {
125 final List<String> expected = new ArrayList<>();
126 final String[] entries = { "one", "two", "three" };
127 for (int i = 0; i < entries.length; i++) {
128 expected.add(String.format(" %s. %s", i + 1, entries[i]));
129 }
130 expected.add("");
131
132 sb.setLength(0);
133 underTest.appendList(true, Arrays.asList(entries));
134 List<String> actual = IOUtils.readLines(new StringReader(sb.toString()));
135 assertEquals(expected, actual, "ordered list failed");
136
137 sb.setLength(0);
138 expected.clear();
139 for (final String entry : entries) {
140 expected.add(String.format(" * %s", entry));
141 }
142 expected.add("");
143 underTest.appendList(false, Arrays.asList(entries));
144 actual = IOUtils.readLines(new StringReader(sb.toString()));
145 assertEquals(expected, actual, "unordered list failed");
146
147 sb.setLength(0);
148 expected.clear();
149 underTest.appendList(false, Collections.emptyList());
150 actual = IOUtils.readLines(new StringReader(sb.toString()));
151 assertEquals(expected, actual, "empty list failed");
152
153 sb.setLength(0);
154 expected.clear();
155 underTest.appendList(false, null);
156 actual = IOUtils.readLines(new StringReader(sb.toString()));
157 assertEquals(expected, actual, "null list failed");
158 }
159
160 @Test
161 void testAppendParagraph() throws IOException {
162 final String[] expected = { " Hello World", "" };
163
164 sb.setLength(0);
165 underTest.appendParagraph("Hello World");
166 final List<String> actual = IOUtils.readLines(new StringReader(sb.toString()));
167 assertEquals(Arrays.asList(expected), actual);
168
169 sb.setLength(0);
170 underTest.appendParagraph("");
171 assertEquals(0, sb.length(), "empty string test failed");
172
173 sb.setLength(0);
174 underTest.appendParagraph(null);
175 assertEquals(0, sb.length(), "null test failed");
176 }
177
178 @Test
179 void testAppendParagraphFormat() throws IOException {
180 final String[] expected = { " Hello Joe World 309", "" };
181
182 sb.setLength(0);
183 underTest.appendParagraphFormat("Hello %s World %,d", "Joe", 309);
184 final List<String> actual = IOUtils.readLines(new StringReader(sb.toString()));
185 assertEquals(Arrays.asList(expected), actual);
186
187 sb.setLength(0);
188 underTest.appendParagraphFormat("");
189 assertEquals(0, sb.length(), "empty string test failed");
190 }
191
192 @Test
193 void testAppendTable() throws IOException {
194 final TextStyle.Builder styleBuilder = TextStyle.builder();
195 final List<TextStyle> styles = new ArrayList<>();
196 styles.add(styleBuilder.setIndent(2).get());
197 styles.add(styleBuilder.setIndent(0).setLeftPad(5).setAlignment(TextStyle.Alignment.RIGHT).get());
198 final String[] headers = { "fox", "time" };
199
200 final List<List<String>> rows = Arrays.asList(
201 Arrays.asList("The quick brown fox jumps over the lazy dog",
202 "Now is the time for all good people to come to the aid of their country"),
203 Arrays.asList("Léimeann an sionnach donn gasta thar an madra leisciúil",
204 "Anois an t-am do na daoine maithe go léir teacht i gcabhair ar a dtír")
205 );
206
207
208 List<String> expected = new ArrayList<>();
209 expected.add(" Common Phrases");
210 expected.add("");
211 expected.add(" fox time ");
212 expected.add(" The quick brown fox jumps over Now is the time for all good people to");
213 expected.add(" the lazy dog come to the aid of their country");
214 expected.add(" Léimeann an sionnach donn gasta Anois an t-am do na daoine maithe go léir");
215 expected.add(" thar an madra leisciúil teacht i gcabhair ar a dtír");
216 expected.add("");
217
218 TableDefinition table = TableDefinition.from("Common Phrases", styles, Arrays.asList(headers), rows);
219 sb.setLength(0);
220 underTest.setMaxWidth(80);
221 underTest.appendTable(table);
222 List<String> actual = IOUtils.readLines(new StringReader(sb.toString()));
223 assertEquals(expected, actual, "full table failed");
224
225 table = TableDefinition.from(null, styles, Arrays.asList(headers), rows);
226 expected.remove(1);
227 expected.remove(0);
228 sb.setLength(0);
229 underTest.appendTable(table);
230 actual = IOUtils.readLines(new StringReader(sb.toString()));
231 assertEquals(expected, actual);
232
233 table = TableDefinition.from(null, styles, Arrays.asList(headers), Collections.emptyList());
234 expected = new ArrayList<>();
235 expected.add(" fox time");
236 expected.add("");
237 sb.setLength(0);
238 underTest.appendTable(table);
239 actual = IOUtils.readLines(new StringReader(sb.toString()));
240 assertEquals(expected, actual, "no rows test failed");
241 }
242
243 @Test
244 void testAppendTitle() throws IOException {
245 final String[] expected = { " Hello World", " ###########", "" };
246
247 sb.setLength(0);
248 underTest.appendTitle("Hello World");
249 final List<String> actual = IOUtils.readLines(new StringReader(sb.toString()));
250 assertEquals(Arrays.asList(expected), actual);
251
252 sb.setLength(0);
253 underTest.appendTitle("");
254 assertEquals(0, sb.length(), "empty string test failed");
255
256 sb.setLength(0);
257 underTest.appendTitle(null);
258 assertEquals(0, sb.length(), "null test failed");
259
260 }
261
262 @Test
263 void testGetStyleBuilder() {
264 final TextStyle.Builder builder = underTest.getTextStyleBuilder();
265 assertEquals(TextHelpAppendable.DEFAULT_INDENT, builder.getIndent(), "Default indent value was changed, some tests may fail");
266 assertEquals(TextHelpAppendable.DEFAULT_LEFT_PAD, builder.getLeftPad(), "Default left pad value was changed, some tests may fail");
267 assertEquals(TextHelpAppendable.DEFAULT_WIDTH, builder.getMaxWidth(), "Default width value was changed, some tests may fail");
268 }
269
270 @Test
271 void testindexOfWrapPos() {
272 final String testString = "The quick brown fox jumps over\tthe lazy dog";
273
274 assertEquals(9, TextHelpAppendable.indexOfWrap(testString, 10, 0), "did not find end of word");
275 assertEquals(9, TextHelpAppendable.indexOfWrap(testString, 14, 0), "did not backup to end of word");
276 assertEquals(15, TextHelpAppendable.indexOfWrap(testString, 15, 0), "did not find word at 15");
277 assertEquals(15, TextHelpAppendable.indexOfWrap(testString, 16, 0));
278 assertEquals(30, TextHelpAppendable.indexOfWrap(testString, 15, 20), "did not find break character");
279 assertEquals(30, TextHelpAppendable.indexOfWrap(testString, 150, 0), "did not handle text shorter than width");
280
281 assertThrows(IllegalArgumentException.class, () -> TextHelpAppendable.indexOfWrap("", 0, 0));
282 assertEquals(3, TextHelpAppendable.indexOfWrap("Hello", 4, 0));
283 }
284
285 @ParameterizedTest
286 @MethodSource("org.apache.commons.cli.help.UtilTest#charArgs")
287 void testindexOfWrapPosWithWhitespace(final Character c, final boolean isWhitespace) {
288 final String text = String.format("Hello%cWorld", c);
289 assertEquals(isWhitespace ? 5 : 6, TextHelpAppendable.indexOfWrap(text, 7, 0));
290 }
291
292 @Test
293 void testMakeColumnQueue() {
294 final String text = "The quick brown fox jumps over the lazy dog";
295 final TextStyle.Builder styleBuilder = TextStyle.builder().setMaxWidth(10).setIndent(0).setLeftPad(0);
296
297 Queue<String> expected = new LinkedList<>();
298 expected.add("The quick ");
299 expected.add("brown fox ");
300 expected.add("jumps over");
301 expected.add("the lazy ");
302 expected.add("dog ");
303
304 Queue<String> result = underTest.makeColumnQueue(text, styleBuilder.get());
305 assertEquals(expected, result, "left aligned failed");
306
307 expected.clear();
308 expected.add(" The quick");
309 expected.add(" brown fox");
310 expected.add("jumps over");
311 expected.add(" the lazy");
312 expected.add(" dog");
313 styleBuilder.setAlignment(TextStyle.Alignment.RIGHT);
314
315 result = underTest.makeColumnQueue(text, styleBuilder.get());
316 assertEquals(expected, result, "right aligned failed");
317
318 expected.clear();
319 expected.add("The quick ");
320 expected.add("brown fox ");
321 expected.add("jumps over");
322 expected.add(" the lazy ");
323 expected.add(" dog ");
324 styleBuilder.setAlignment(TextStyle.Alignment.CENTER);
325
326 result = underTest.makeColumnQueue(text, styleBuilder.get());
327 assertEquals(expected, result, "center aligned failed");
328
329 expected = new LinkedList<>();
330 expected.add(" The quick");
331 expected.add(" brown");
332 expected.add(" fox");
333 expected.add(" jumps");
334 expected.add(" over the");
335 expected.add(" lazy dog");
336 styleBuilder.setAlignment(TextStyle.Alignment.RIGHT).setLeftPad(5).setIndent(2);
337
338 result = underTest.makeColumnQueue(text, styleBuilder.get());
339 assertEquals(expected, result, "right aligned failed");
340 }
341
342 @Test
343 void testMakeColumnQueueWithMultipleTrailingLineBreaks() {
344
345 final String text = "Header\t" + (char) Character.PARAGRAPH_SEPARATOR;
346 final TextStyle.Builder styleBuilder = TextStyle.builder().setMaxWidth(10).setIndent(0).setLeftPad(0);
347
348 final Queue<String> expected = new LinkedList<>();
349 expected.add("Header ");
350 expected.add(" ");
351
352 final Queue<String> result = underTest.makeColumnQueue(text, styleBuilder.get());
353 assertEquals(expected, result, "left aligned failed");
354 }
355
356 @Test
357 void testPrintWrapped() throws IOException {
358 String text = "The quick brown fox jumps over the lazy dog";
359 final TextStyle.Builder styleBuilder = TextStyle.builder().setMaxWidth(10).setIndent(0).setLeftPad(0);
360
361 final List<String> expected = new ArrayList<>();
362 expected.add("The quick");
363 expected.add("brown fox");
364 expected.add("jumps over");
365 expected.add("the lazy");
366 expected.add("dog");
367 underTest.printWrapped(text, styleBuilder.get());
368 List<String> actual = IOUtils.readLines(new StringReader(sb.toString()));
369 assertEquals(expected, actual, "left aligned failed");
370
371 sb.setLength(0);
372 expected.clear();
373 expected.add(" The quick");
374 expected.add(" brown fox");
375 expected.add("jumps over");
376 expected.add(" the lazy");
377 expected.add(" dog");
378 styleBuilder.setAlignment(TextStyle.Alignment.RIGHT);
379
380 underTest.printWrapped(text, styleBuilder.get());
381 actual = IOUtils.readLines(new StringReader(sb.toString()));
382 assertEquals(expected, actual, "right aligned failed");
383
384 sb.setLength(0);
385 expected.clear();
386 expected.add("The quick");
387 expected.add("brown fox");
388 expected.add("jumps over");
389 expected.add(" the lazy");
390 expected.add(" dog");
391 styleBuilder.setAlignment(TextStyle.Alignment.CENTER);
392
393 underTest.printWrapped(text, styleBuilder.get());
394 actual = IOUtils.readLines(new StringReader(sb.toString()));
395 assertEquals(expected, actual, "center aligned failed");
396
397 sb.setLength(0);
398 expected.clear();
399 expected.add(" The quick brown fox jumps over the lazy dog");
400
401 assertEquals(1, underTest.getLeftPad(), "unexpected page left pad");
402 assertEquals(3, underTest.getIndent(), "unexpected page indent");
403 assertEquals(74, underTest.getMaxWidth(), "unexpected page width");
404 underTest.printWrapped(text);
405 actual = IOUtils.readLines(new StringReader(sb.toString()));
406 assertEquals(expected, actual, "default format aligned failed");
407
408 sb.setLength(0);
409 text += ".\nNow is the time for all good people to come to the aid of their country.";
410 expected.clear();
411 expected.add(" The quick brown fox jumps over the lazy dog.");
412 expected.add(" Now is the time for all good people to come to the aid of their");
413 expected.add(" country.");
414 underTest.printWrapped(text);
415 actual = IOUtils.readLines(new StringReader(sb.toString()));
416 assertEquals(expected, actual, "default format aligned failed");
417 }
418
419 @Test
420 void testResize() {
421 TextStyle.Builder tsBuilder = TextStyle.builder().setIndent(2).setMaxWidth(3);
422 underTest.resize(tsBuilder, 0.5);
423 assertEquals(0, tsBuilder.getIndent());
424
425 tsBuilder = TextStyle.builder().setIndent(4).setMaxWidth(6);
426 underTest.resize(tsBuilder, 0.5);
427 assertEquals(1, tsBuilder.getIndent());
428 }
429
430 @Test
431 void testResizeTableFormat() {
432 underTest.setMaxWidth(150);
433 final TableDefinition tableDefinition = TableDefinition.from("Caption",
434 Collections.singletonList(TextStyle.builder().setMinWidth(20).setMaxWidth(100).get()), Collections.singletonList("header"),
435 Collections.singletonList(Collections.singletonList("one")));
436 final TableDefinition result = underTest.adjustTableFormat(tableDefinition);
437 assertEquals(20, result.columnTextStyles().get(0).getMinWidth(), "Minimum width should not be reset");
438 assertEquals(100, result.columnTextStyles().get(0).getMaxWidth(), "Maximum width should not be reset");
439 }
440
441 @Test
442 void testSetIndent() {
443 assertEquals(TextHelpAppendable.DEFAULT_INDENT, underTest.getIndent(), "Default indent value was changed, some tests may fail");
444 underTest.setIndent(TextHelpAppendable.DEFAULT_INDENT + 2);
445 assertEquals(underTest.getIndent(), TextHelpAppendable.DEFAULT_INDENT + 2);
446 }
447
448 @Test
449 void testWriteColumnQueues() throws IOException {
450 final List<Queue<String>> queues = new ArrayList<>();
451
452 Queue<String> queue = new LinkedList<>();
453 queue.add("The quick ");
454 queue.add("brown fox ");
455 queue.add("jumps over");
456 queue.add("the lazy ");
457 queue.add("dog ");
458
459 queues.add(queue);
460
461 queue = new LinkedList<>();
462 queue.add(" Now is the");
463 queue.add(" time for ");
464 queue.add(" all good ");
465 queue.add(" people to ");
466 queue.add(" come to ");
467 queue.add(" the aid of");
468 queue.add(" their ");
469 queue.add(" country ");
470
471 queues.add(queue);
472
473 final TextStyle.Builder styleBuilder = TextStyle.builder().setMaxWidth(10).setIndent(0).setLeftPad(0);
474
475 final List<TextStyle> columns = new ArrayList<>();
476 columns.add(styleBuilder.get());
477 columns.add(styleBuilder.setLeftPad(5).get());
478
479 final List<String> expected = new ArrayList<>();
480 expected.add(" The quick Now is the");
481 expected.add(" brown fox time for ");
482 expected.add(" jumps over all good ");
483 expected.add(" the lazy people to ");
484 expected.add(" dog come to ");
485 expected.add(" the aid of");
486 expected.add(" their ");
487 expected.add(" country ");
488
489 sb.setLength(0);
490 underTest.writeColumnQueues(queues, columns);
491 final List<String> actual = IOUtils.readLines(new StringReader(sb.toString()));
492 assertEquals(expected, actual);
493 }
494 }