1   package com.lexicalscope.jewel.cli;
2   
3   import static com.lexicalscope.jewel.cli.ValidationFailureMatcher.validationError;
4   import static org.hamcrest.MatcherAssert.assertThat;
5   import static org.hamcrest.Matchers.*;
6   import static org.junit.Assert.*;
7   
8   import java.util.List;
9   
10  import org.junit.Test;
11  
12  public class TestCliImpl {
13      public interface SingleOption {
14          @Option String getName();
15      }
16  
17      public interface ListOption {
18          @Option List<String> getName();
19      }
20  
21      public interface CharacterValue {
22          @Option Character getName();
23      }
24  
25      public interface SingleBooleanOption {
26          @Option boolean getName0();
27  
28          @Option boolean isName1();
29      }
30  
31      public interface SingleOptionalOption {
32          @Option String getName();
33  
34          boolean isName();
35      }
36  
37      public interface IntegerOption {
38          @Option Integer getName();
39      }
40  
41      public interface IntOption {
42          @Option int getName();
43      }
44  
45      public interface SingleOptionWithArgument {
46          @Option String getName(String argument);
47      }
48  
49      public interface SingleOptionMissingAnnotation {
50          String getName();
51      }
52  
53      public enum TestEnum {
54          Value0, Value1, Value2;
55      }
56  
57      public interface EnumDefaultListOption {
58          @Option(defaultValue = { "Value0", "Value1" }) List<TestEnum> getName();
59      }
60  
61      @Test public void testSingleOption() throws ArgumentValidationException {
62          final SingleOption option =
63                  new CliInterfaceImpl<SingleOption>(SingleOption.class)
64                  .parseArguments(new String[] { "--name", "value" });
65          assertEquals(option.getName(), "value");
66      }
67  
68      @Test public void testSingleBooleanOption() throws ArgumentValidationException {
69          final SingleBooleanOption option =
70                  new CliInterfaceImpl<SingleBooleanOption>(SingleBooleanOption.class)
71                  .parseArguments(new String[] { "--name1" });
72          assertEquals(option.getName0(), false);
73          assertEquals(option.isName1(), true);
74      }
75  
76      @Test public void testIntegerOption() throws ArgumentValidationException {
77          final IntegerOption option =
78                  new CliInterfaceImpl<IntegerOption>(IntegerOption.class)
79                  .parseArguments(new String[] { "--name", "10" });
80          assertEquals(Integer.valueOf(10), option.getName());
81      }
82  
83      @Test public void testInvalidIntegerOption() {
84          try {
85              new CliInterfaceImpl<IntegerOption>(IntegerOption.class).parseArguments(new String[] { "--name", "abc" });
86              fail();
87          } catch (final ArgumentValidationException e) {
88              assertThat(e.getValidationFailures(), contains(validationError(
89                      ValidationFailureType.InvalidValueForType,
90                      "Invalid value (Unsupported number format: For input string: \"abc\"): --name value")));
91          }
92      }
93  
94      @Test public void testInvalidIntOption() {
95          try {
96              new CliInterfaceImpl<IntOption>(IntOption.class).parseArguments(new String[] { "--name", "abc" });
97              fail();
98          } catch (final ArgumentValidationException e) {
99              assertThat(e.getValidationFailures(), contains(validationError(
100                     ValidationFailureType.InvalidValueForType,
101                     "Invalid value (Unsupported number format: For input string: \"abc\"): --name value")));
102         }
103     }
104 
105     @Test public void testInvalidOption() {
106         try {
107             new CliInterfaceImpl<SingleOption>(SingleOption.class)
108             .parseArguments(new String[] { "--invalid", "value" });
109             fail();
110         } catch (final ArgumentValidationException e) {
111             assertThat(e.getValidationFailures(), contains(
112                     validationError(ValidationFailureType.UnexpectedOption)));
113         }
114     }
115 
116     @Test public void testSingleOptionalOption() throws ArgumentValidationException {
117         SingleOptionalOption option =
118                 new CliInterfaceImpl<SingleOptionalOption>(SingleOptionalOption.class).parseArguments(new String[] {
119                         "--name",
120                 "value" });
121         assertEquals(option.getName(), "value");
122         assertTrue(option.isName());
123 
124         option = new CliInterfaceImpl<SingleOptionalOption>(SingleOptionalOption.class).parseArguments(new String[] {});
125         assertFalse(option.isName());
126     }
127 
128     @Test public void testSingleOptionalOptionRequestMissing() throws ArgumentValidationException {
129         final SingleOptionalOption option =
130                 new CliInterfaceImpl<SingleOptionalOption>(SingleOptionalOption.class).parseArguments(new String[] {});
131 
132         assertThat(option.getName(), equalTo(null));
133     }
134 
135     @Test public void testCharacterValue() throws ArgumentValidationException {
136         final CharacterValue option =
137                 new CliInterfaceImpl<CharacterValue>(CharacterValue.class)
138                 .parseArguments(new String[] { "--name", "a" });
139         assertEquals((Character) 'a', option.getName());
140     }
141 
142     @Test public void testInvalidCharacterValue() {
143         try {
144             new CliInterfaceImpl<CharacterValue>(CharacterValue.class).parseArguments(new String[] { "--name", "aa" });
145             fail();
146         } catch (final ArgumentValidationException e) {
147             assertThat(e.getValidationFailures(), contains(validationError(ValidationFailureType.InvalidValueForType)));
148         }
149     }
150 
151     @Test public void testMethodWithArguments() throws ArgumentValidationException {
152         try {
153             new CliInterfaceImpl<SingleOptionWithArgument>(SingleOptionWithArgument.class).parseArguments(new String[] {
154                     "--name",
155             "value" });
156             fail();
157         } catch (final ArgumentValidationException e) {
158             assertThat(e.getValidationFailures(), contains(validationError(ValidationFailureType.UnexpectedOption)));
159         }
160     }
161 
162     @Test public void testMethodWithMissingAnnotation() throws ArgumentValidationException {
163         final SingleOptionMissingAnnotation result =
164                 new CliInterfaceImpl<SingleOptionMissingAnnotation>(SingleOptionMissingAnnotation.class)
165                 .parseArguments(new String[] {});
166 
167         assertThat(result.getName(), equalTo(null));
168     }
169 
170     @Test public void testListOptionMissingValue() throws ArgumentValidationException {
171         new CliInterfaceImpl<ListOption>(ListOption.class).parseArguments(new String[] { "--name" });
172     }
173 
174     @Test public void testEnumDefaultList() throws ArgumentValidationException {
175         final EnumDefaultListOption result =
176                 new CliInterfaceImpl<EnumDefaultListOption>(EnumDefaultListOption.class)
177                 .parseArguments(new String[] {});
178 
179         final List<TestEnum> enumValues = result.getName();
180         assertEquals(2, enumValues.size());
181         assertEquals(TestEnum.Value0, enumValues.get(0));
182         assertEquals(TestEnum.Value1, enumValues.get(1));
183     }
184 }