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.util.ArrayList;
23 import java.util.List;
24 import java.util.function.BiFunction;
25 import java.util.function.Function;
26 import java.util.stream.Stream;
27
28 import org.apache.commons.cli.DeprecatedAttributes;
29 import org.apache.commons.cli.Option;
30 import org.junit.jupiter.api.Test;
31 import org.junit.jupiter.params.ParameterizedTest;
32 import org.junit.jupiter.params.provider.Arguments;
33 import org.junit.jupiter.params.provider.MethodSource;
34
35
36
37
38 class OptionFormatterTest {
39
40 public static Stream<Arguments> deprecatedAttributesData() {
41 final List<Arguments> lst = new ArrayList<>();
42
43 final DeprecatedAttributes.Builder daBuilder = DeprecatedAttributes.builder();
44 lst.add(Arguments.of(daBuilder.get(), "[Deprecated]"));
45
46 daBuilder.setSince("now");
47 lst.add(Arguments.of(daBuilder.get(), "[Deprecated since now]"));
48
49 daBuilder.setForRemoval(true);
50 lst.add(Arguments.of(daBuilder.get(), "[Deprecated for removal since now]"));
51
52 daBuilder.setSince(null);
53 lst.add(Arguments.of(daBuilder.get(), "[Deprecated for removal]"));
54
55 daBuilder.setForRemoval(false);
56 daBuilder.setDescription("Use something else");
57 lst.add(Arguments.of(daBuilder.get(), "[Deprecated. Use something else]"));
58
59 daBuilder.setForRemoval(true);
60 lst.add(Arguments.of(daBuilder.get(), "[Deprecated for removal. Use something else]"));
61
62 daBuilder.setForRemoval(false);
63 daBuilder.setSince("then");
64 lst.add(Arguments.of(daBuilder.get(), "[Deprecated since then. Use something else]"));
65
66 daBuilder.setForRemoval(true);
67 lst.add(Arguments.of(daBuilder.get(), "[Deprecated for removal since then. Use something else]"));
68
69 return lst.stream();
70 }
71
72 private void assertEquivalent(final OptionFormatter formatter, final OptionFormatter formatter2) {
73 assertEquals(formatter.toSyntaxOption(), formatter2.toSyntaxOption());
74 assertEquals(formatter.toSyntaxOption(true), formatter2.toSyntaxOption(true));
75 assertEquals(formatter.toSyntaxOption(false), formatter2.toSyntaxOption(false));
76 assertEquals(formatter.getOpt(), formatter2.getOpt());
77 assertEquals(formatter.getLongOpt(), formatter2.getLongOpt());
78 assertEquals(formatter.getBothOpt(), formatter2.getBothOpt());
79 assertEquals(formatter.getDescription(), formatter2.getDescription());
80 assertEquals(formatter.getArgName(), formatter2.getArgName());
81 assertEquals(formatter.toOptional("foo"), formatter2.toOptional("foo"));
82 }
83
84 @Test
85 void testAsOptional() {
86 OptionFormatter underTest;
87 final Option option = Option.builder().option("o").longOpt("opt").hasArg().get();
88
89 underTest = OptionFormatter.from(option);
90 assertEquals("[what]", underTest.toOptional("what"));
91 assertEquals("", underTest.toOptional(""), "enpty string should return empty string");
92 assertEquals("", underTest.toOptional(null), "null should return empty string");
93
94 underTest = OptionFormatter.builder().setOptionalDelimiters("-> ", " <-").build(option);
95 assertEquals("-> what <-", underTest.toOptional("what"));
96
97 }
98
99 @Test
100 void testAsSyntaxOption() {
101 OptionFormatter underTest;
102
103 Option option = Option.builder().option("o").longOpt("opt").hasArg().get();
104 underTest = OptionFormatter.from(option);
105 assertEquals("[-o <arg>]", underTest.toSyntaxOption(), "optional arg failed");
106
107 option = Option.builder().option("o").longOpt("opt").hasArg().argName("other").get();
108 underTest = OptionFormatter.from(option);
109 assertEquals("[-o <other>]", underTest.toSyntaxOption(), "optional 'other' arg failed");
110
111 option = Option.builder().option("o").longOpt("opt").hasArg().required().argName("other").get();
112 underTest = OptionFormatter.from(option);
113 assertEquals("-o <other>", underTest.toSyntaxOption(), "required 'other' arg failed");
114
115 option = Option.builder().option("o").longOpt("opt").required().argName("other").get();
116 underTest = OptionFormatter.from(option);
117 assertEquals("-o", underTest.toSyntaxOption(), "required no arg failed");
118
119 option = Option.builder().option("o").argName("other").get();
120 underTest = OptionFormatter.from(option);
121 assertEquals("[-o]", underTest.toSyntaxOption(), "optional no arg arg failed");
122
123 option = Option.builder().longOpt("opt").hasArg().argName("other").get();
124 underTest = OptionFormatter.from(option);
125 assertEquals("[--opt <other>]", underTest.toSyntaxOption(), "optional longOpt 'other' arg failed");
126
127 option = Option.builder().longOpt("opt").required().hasArg().argName("other").get();
128 underTest = OptionFormatter.from(option);
129 assertEquals("--opt <other>", underTest.toSyntaxOption(), "required longOpt 'other' arg failed");
130
131 option = Option.builder().option("ot").longOpt("opt").hasArg().get();
132 underTest = OptionFormatter.from(option);
133 assertEquals("[-ot <arg>]", underTest.toSyntaxOption(), "optional multi char opt arg failed");
134 }
135
136 @Test
137 void testCli343Part1() {
138 assertThrows(IllegalStateException.class, () -> Option.builder().required(false).build());
139 assertThrows(IllegalStateException.class, () -> Option.builder().required(false).get());
140 }
141
142 @Test
143 void testCli343Part2() {
144 assertThrows(IllegalStateException.class, () -> Option.builder().desc("description").build());
145 assertThrows(IllegalStateException.class, () -> Option.builder().desc("description").get());
146 }
147
148 @ParameterizedTest(name = "{index} {0}")
149 @MethodSource("deprecatedAttributesData")
150 void testComplexDeprecationFormat(final DeprecatedAttributes da, final String expected) {
151 final Option.Builder builder = Option.builder("o").deprecated(da);
152 final Option.Builder builderWithDesc = Option.builder("o").desc("The description").deprecated(da);
153
154 assertEquals(expected, OptionFormatter.COMPLEX_DEPRECATED_FORMAT.apply(builder.get()));
155 assertEquals(expected + " The description", OptionFormatter.COMPLEX_DEPRECATED_FORMAT.apply(builderWithDesc.get()));
156 }
157
158 @Test
159 void testCopyConstructor() {
160 final Function<Option, String> depFunc = o -> "Ooo Deprecated";
161 final BiFunction<OptionFormatter, Boolean, String> fmtFunc = (o, b) -> "Yep, it worked";
162
163 final OptionFormatter.Builder builder = OptionFormatter.builder()
164 .setLongOptPrefix("l")
165 .setOptPrefix("s")
166 .setArgumentNameDelimiters("{", "}")
167 .setDefaultArgName("Some Argument")
168 .setOptSeparator(" and ")
169 .setOptionalDelimiters("?>", "<?")
170 .setSyntaxFormatFunction(fmtFunc)
171 .setDeprecatedFormatFunction(depFunc);
172
173
174 Option option = Option.builder("o").longOpt("opt").get();
175
176 OptionFormatter formatter = builder.build(option);
177 OptionFormatter.Builder builder2 = new OptionFormatter.Builder(formatter);
178 assertEquivalent(formatter, builder2.build(option));
179
180 option = Option.builder("o").longOpt("opt").deprecated().required().get();
181 formatter = builder.build(option);
182 builder2 = new OptionFormatter.Builder(formatter);
183 assertEquivalent(formatter, builder2.build(option));
184 }
185
186 @Test
187 void testDefaultSyntaxFormat() {
188
189 Option option = Option.builder().option("o").longOpt("opt").hasArg().get();
190 OptionFormatter formatter = OptionFormatter.from(option);
191 assertEquals("[-o <arg>]", formatter.toSyntaxOption());
192 assertEquals("-o <arg>", formatter.toSyntaxOption(true));
193
194 option = Option.builder().option("o").longOpt("opt").hasArg().required().get();
195 formatter = OptionFormatter.from(option);
196 assertEquals("-o <arg>", formatter.toSyntaxOption());
197 assertEquals("[-o <arg>]", formatter.toSyntaxOption(false));
198 }
199
200 @Test
201 void testGetBothOpt() {
202 OptionFormatter underTest;
203
204 Option option = Option.builder().option("o").longOpt("opt").hasArg().get();
205 underTest = OptionFormatter.from(option);
206 assertEquals("-o, --opt", underTest.getBothOpt());
207
208 option = Option.builder().longOpt("opt").hasArg().get();
209 underTest = OptionFormatter.from(option);
210 assertEquals("--opt", underTest.getBothOpt());
211
212 option = Option.builder().option("o").hasArg().get();
213 underTest = OptionFormatter.from(option);
214 assertEquals("-o", underTest.getBothOpt());
215 }
216
217 @Test
218 void testGetDescription() {
219 final Option normalOption = Option.builder().option("o").longOpt("one").hasArg().desc("The description").get();
220
221 final Option deprecatedOption = Option.builder().option("o").longOpt("one").hasArg().desc("The description").deprecated().get();
222
223 final Option deprecatedOptionWithAttributes = Option.builder().option("o").longOpt("one").hasArg().desc("The description")
224 .deprecated(DeprecatedAttributes.builder().setForRemoval(true).setSince("now").setDescription("Use something else").get()).get();
225
226 assertEquals("The description", OptionFormatter.from(normalOption).getDescription(), "normal option failure");
227 assertEquals("The description", OptionFormatter.from(deprecatedOption).getDescription(), "deprecated option failure");
228 assertEquals("The description", OptionFormatter.from(deprecatedOptionWithAttributes).getDescription(), "complex deprecated option failure");
229
230 OptionFormatter.Builder builder = OptionFormatter.builder().setDeprecatedFormatFunction(OptionFormatter.SIMPLE_DEPRECATED_FORMAT);
231
232 assertEquals("The description", builder.build(normalOption).getDescription(), "normal option failure");
233 assertEquals("[Deprecated] The description", builder.build(deprecatedOption).getDescription(), "deprecated option failure");
234 assertEquals("[Deprecated] The description", builder.build(deprecatedOptionWithAttributes).getDescription(), "complex deprecated option failure");
235
236 builder = OptionFormatter.builder().setDeprecatedFormatFunction(OptionFormatter.COMPLEX_DEPRECATED_FORMAT);
237
238 assertEquals("The description", builder.build(normalOption).getDescription(), "normal option failure");
239 assertEquals("[Deprecated] The description", builder.build(deprecatedOption).getDescription(), "deprecated option failure");
240 assertEquals("[Deprecated for removal since now. Use something else] The description", builder.build(deprecatedOptionWithAttributes).getDescription(),
241 "complex deprecated option failure");
242 }
243
244 @Test
245 void testSetArgumentNameDelimiters() {
246 final Option option = Option.builder().option("o").longOpt("opt").hasArg().get();
247 OptionFormatter.Builder builder = OptionFormatter.builder().setArgumentNameDelimiters("with argument named ", ".");
248 assertEquals("with argument named arg.", builder.build(option).getArgName());
249
250 builder = OptionFormatter.builder().setArgumentNameDelimiters(null, "");
251 assertEquals("arg", builder.build(option).getArgName());
252
253 builder = OptionFormatter.builder().setArgumentNameDelimiters("", null);
254 assertEquals("arg", builder.build(option).getArgName());
255
256 }
257
258 @Test
259 void testSetDefaultArgName() {
260 final Option option = Option.builder().option("o").longOpt("opt").hasArg().get();
261 OptionFormatter.Builder builder = OptionFormatter.builder().setDefaultArgName("foo");
262 assertEquals("<foo>", builder.build(option).getArgName());
263
264 builder = OptionFormatter.builder().setDefaultArgName("");
265 assertEquals("<arg>", builder.build(option).getArgName());
266
267 builder = OptionFormatter.builder().setDefaultArgName(null);
268 assertEquals("<arg>", builder.build(option).getArgName());
269 }
270
271 @Test
272 void testSetLongOptPrefix() {
273 final Option option = Option.builder().option("o").longOpt("opt").hasArg().get();
274 OptionFormatter.Builder builder = OptionFormatter.builder().setLongOptPrefix("fo");
275 assertEquals("foopt", builder.build(option).getLongOpt());
276
277 builder = OptionFormatter.builder().setLongOptPrefix("");
278 assertEquals("opt", builder.build(option).getLongOpt());
279
280 builder = OptionFormatter.builder().setLongOptPrefix(null);
281 assertEquals("opt", builder.build(option).getLongOpt());
282 }
283
284 @Test
285 void testSetOptArgumentSeparator() {
286 final Option option = Option.builder().option("o").longOpt("opt").hasArg().get();
287 OptionFormatter.Builder builder = OptionFormatter.builder().setOptArgSeparator(" with argument named ");
288 assertEquals("[-o with argument named <arg>]", builder.build(option).toSyntaxOption());
289
290 builder = OptionFormatter.builder().setOptArgSeparator(null);
291 assertEquals("[-o<arg>]", builder.build(option).toSyntaxOption());
292
293 builder = OptionFormatter.builder().setOptArgSeparator("=");
294 assertEquals("[-o=<arg>]", builder.build(option).toSyntaxOption());
295 }
296
297 @Test
298 void testSetOptSeparator() {
299 final Option option = Option.builder().option("o").longOpt("opt").hasArg().get();
300 OptionFormatter.Builder builder = OptionFormatter.builder().setOptSeparator(" and ");
301 assertEquals("-o and --opt", builder.build(option).getBothOpt());
302
303 builder = OptionFormatter.builder().setOptSeparator("");
304 assertEquals("-o--opt", builder.build(option).getBothOpt(), "Empty string should return default");
305
306 builder = OptionFormatter.builder().setOptSeparator(null);
307 assertEquals("-o--opt", builder.build(option).getBothOpt(), "null string should return default");
308 }
309
310 @Test
311 void testSetSyntaxFormatFunction() {
312 final BiFunction<OptionFormatter, Boolean, String> func = (o, b) -> "Yep, it worked";
313 final Option option = Option.builder().option("o").longOpt("opt").hasArg().get();
314
315 OptionFormatter.Builder builder = OptionFormatter.builder().setSyntaxFormatFunction(func);
316 assertEquals("Yep, it worked", builder.build(option).toSyntaxOption());
317
318 builder = OptionFormatter.builder().setSyntaxFormatFunction(null);
319 assertEquals("[-o <arg>]", builder.build(option).toSyntaxOption());
320 }
321 }