1 package com.lexicalscope.jewel.cli;
2
3 import static com.lexicalscope.fluentreflection.FluentReflection.*;
4 import static org.hamcrest.Matchers.contains;
5 import static org.junit.Assert.*;
6
7 import java.lang.reflect.Method;
8 import java.util.List;
9
10 import org.junit.Rule;
11 import org.junit.Test;
12 import org.junit.rules.ExpectedException;
13
14 import com.lexicalscope.jewel.cli.specification.ParsedOptionSpecification;
15
16 public class TestOptionSpecificationImpl {
17 @Rule public ExpectedException exception = ExpectedException.none();
18
19 public interface HasShortName {
20 @Option(shortName = "n") String getName1();
21
22 @Option String getName2();
23 }
24
25 public interface ShortName {
26 @Option(shortName = "") String getName0();
27
28 @Option(shortName = "n") String getName1();
29
30 @Option(shortName = "excessive") String getName2();
31 }
32
33 public interface LongName {
34 @Option() String getName0();
35
36 @Option(longName = "totallyDifferent") String getName1();
37
38 @Option(longName = "name2") String getName2();
39 }
40
41 public interface MultipleLongNames {
42 @Option(longName = { "name", "alternativename" }) String getName();
43 }
44
45 public interface InvalidLongName {
46 @Option(longName = "") String getName0();
47 }
48
49 public interface Value {
50 @Option String getName();
51
52 @Option boolean getDebug();
53 }
54
55 public interface Name {
56 @Option String getName();
57
58 @Option String name();
59
60 @Option boolean isDebug();
61
62 @Option boolean debug();
63 }
64
65 public interface Type {
66 @Option String getString();
67
68 @Option Integer getInteger();
69
70 @Option int getInt();
71
72 @Option List<String> getStringList();
73
74 @SuppressWarnings("rawtypes") @Option List getList();
75 }
76
77 public interface MultiValued {
78 @Option List<String> getStringList();
79
80 @SuppressWarnings("rawtypes") @Option List getList();
81 }
82
83 public interface HasOptionalOption {
84 @Option String getName1();
85
86 @Option String getName2();
87
88 boolean isName2();
89 }
90
91 public interface ToString {
92 @Option(longName = "aLongName") String getLongName();
93
94 @Option(longName = { "aLongName", "alternativeLongName" }) String getMultipleLongNames();
95
96 @Option(shortName = "s") String getShortName();
97
98 @Option String getOptional();
99 boolean isOptional();
100
101 @Option List<String> getOptionalMulti();
102 boolean isOptionalMulti();
103
104 @Option(description = "this is a description") List<String> getDescription();
105
106 @Option(description = "this is a description", shortName = "a") List<String> getAll();
107 boolean isAll();
108 }
109
110 public interface Summary {
111 @Option(shortName = "s") String getShortName();
112
113 @Option(longName = "aLongName") String getLongName();
114
115 @Option(description = "this is a description") String getWithDescription();
116
117 @Option(longName = "aLongName", shortName = "s") String getLongNameShortName();
118
119 @Option(pattern = "[a-z]") char getPattern();
120
121 @Option String getOptional();
122 boolean isOptional();
123
124 @Option List<String> getList();
125
126 @Option List<String> getOptionalList();
127 boolean isOptionalList();
128
129 @Option(longName = "aLongName", shortName = "s") List<String> getOptionalListShortNameLongName();
130 boolean isOptionalListShortNameLongName();
131 }
132
133 @Test public void testSumary() throws NoSuchMethodException {
134 checkSummary("getShortName", "--shortName -s value");
135 checkSummary("getLongName", "--aLongName value");
136 checkSummary("getWithDescription", "--withDescription value : this is a description");
137 checkSummary("getLongNameShortName", "--aLongName -s value");
138 checkSummary("getOptional", "[--optional value]");
139 checkSummary("getList", "--list value...");
140 checkSummary("getOptionalList", "[--optionalList value...]");
141 checkSummary("getOptionalListShortNameLongName", "[--aLongName -s value...]");
142 checkSummary("getPattern", "--pattern /[a-z]/");
143
144
145
146 }
147
148 private void checkSummary(final String method, final String expectedSummary) throws NoSuchMethodException {
149 assertEquals(expectedSummary, new ParsedOptionSummary(createOption(Summary.class, method)).toString());
150 }
151
152 @Test public void testToString() throws NoSuchMethodException {
153 assertEquals("--aLongName value", createOption(ToString.class, "getLongName").toString());
154 assertEquals("--aLongName --alternativeLongName value", createOption(ToString.class, "getMultipleLongNames")
155 .toString());
156 assertEquals("--shortName -s value", createOption(ToString.class, "getShortName").toString());
157 assertEquals("[--optional value]", createOption(ToString.class, "getOptional").toString());
158 assertEquals("[--optionalMulti value...]", createOption(ToString.class, "getOptionalMulti").toString());
159 assertEquals("--description value... : this is a description", createOption(ToString.class, "getDescription")
160 .toString());
161 assertEquals("[--all -a value...] : this is a description", createOption(ToString.class, "getAll").toString());
162 }
163
164 @Test public void testIsMultiValued() throws NoSuchMethodException {
165 assertTrue(createOption(MultiValued.class, "getStringList").isMultiValued());
166 assertTrue(createOption(MultiValued.class, "getList").isMultiValued());
167 }
168
169 @Test public void testGetType() throws NoSuchMethodException {
170 assertEquals(String.class, createOption(Type.class, "getString").getType());
171 assertEquals(Integer.class, createOption(Type.class, "getInteger").getType());
172 assertEquals(int.class, createOption(Type.class, "getInt").getType());
173 assertEquals(String.class, createOption(Type.class, "getStringList").getType());
174 assertEquals(String.class, createOption(Type.class, "getList").getType());
175 }
176
177 @Test public void testGetName() throws SecurityException, NoSuchMethodException {
178 assertThat(createOption(Name.class, "getName").getLongName(), contains("name"));
179 assertThat(createOption(Name.class, "name").getLongName(), contains("name"));
180 assertThat(createOption(Name.class, "isDebug").getLongName(), contains("debug"));
181 assertThat(createOption(Name.class, "debug").getLongName(), contains("debug"));
182 }
183
184 @Test public void testGetShortName() throws SecurityException, NoSuchMethodException {
185 assertEquals(0, createOption(ShortName.class, "getName0").getShortNames().size());
186 assertEquals("n", createOption(ShortName.class, "getName1").getShortNames().get(0));
187 assertEquals("e", createOption(ShortName.class, "getName2").getShortNames().get(0));
188 }
189
190 @Test public void testGetLongName() throws SecurityException, NoSuchMethodException {
191 assertThat(createOption(LongName.class, "getName0").getLongName(), contains("name0"));
192 assertThat(createOption(LongName.class, "getName1").getLongName(), contains("totallyDifferent"));
193 assertThat(createOption(LongName.class, "getName2").getLongName(), contains("name2"));
194 }
195
196 @Test public void testMultipleLongNames() throws SecurityException, NoSuchMethodException {
197 assertThat(createOption(MultipleLongNames.class, "getName").getLongName(), contains("name", "alternativename"));
198 }
199
200 @Test public void testEmptyLongNameIsNotAllowed() throws SecurityException, NoSuchMethodException {
201 exception.expect(InvalidOptionSpecificationException.class);
202 exception.expectMessage("option public java.lang.String getName0() long name cannot be blank");
203
204 createOption(InvalidLongName.class, "getName0");
205 }
206
207 @Test public void testHasValue() throws SecurityException, NoSuchMethodException {
208 assertTrue(createOption(Value.class, "getName").hasValue());
209 assertFalse(createOption(Value.class, "getDebug").hasValue());
210 }
211
212 @Test public void testHasShortName() throws SecurityException, NoSuchMethodException {
213 assertTrue(createOption(HasShortName.class, "getName1").hasShortName());
214 assertFalse(createOption(HasShortName.class, "getName2").hasShortName());
215 }
216
217 @Test public void testIsOptional() throws SecurityException, NoSuchMethodException {
218 assertFalse(createOption(HasOptionalOption.class, "getName1").isOptional());
219 assertTrue(createOption(HasOptionalOption.class, "getName2").isOptional());
220 }
221
222 private ParsedOptionSpecification createOption(final Class<?> klass, final String methodName)
223 throws NoSuchMethodException {
224 final Method method = klass.getMethod(methodName, (Class[]) null);
225
226 return new ConvertGetterMethodToParsedOptionSpecification(type(klass)).convert(method(method));
227 }
228 }