1   package com.lexicalscope.jewel.cli.validation;
2   
3   import static com.lexicalscope.fluent.FluentDollar.$;
4   import static com.lexicalscope.jewel.cli.ValidationFailureMatcher.validationError;
5   import static com.lexicalscope.jewel.cli.parser.DefaultArgumentParserFactory.createDefaultArgumentParser;
6   import static java.util.Arrays.asList;
7   import static org.hamcrest.Matchers.contains;
8   import static org.junit.Assert.*;
9   
10  import com.lexicalscope.jewel.cli.ArgumentCollectionBuilder;
11  import com.lexicalscope.jewel.cli.ArgumentValidationException;
12  import com.lexicalscope.jewel.cli.Option;
13  import com.lexicalscope.jewel.cli.Unparsed;
14  import com.lexicalscope.jewel.cli.ValidationErrorBuilder;
15  import com.lexicalscope.jewel.cli.ValidationFailureType;
16  import com.lexicalscope.jewel.cli.examples.RmExample;
17  import com.lexicalscope.jewel.cli.specification.OptionsSpecification;
18  import com.lexicalscope.jewel.cli.specification.ParsedOptionSpecification;
19  
20  import java.util.Collections;
21  import java.util.List;
22  
23  import org.jmock.Expectations;
24  import org.jmock.auto.Mock;
25  import org.jmock.integration.junit4.JUnitRuleMockery;
26  import org.junit.Before;
27  import org.junit.Ignore;
28  import org.junit.Rule;
29  import org.junit.Test;
30  
31  public class TestArgumentValidatorImpl<O> {
32      @Rule public final JUnitRuleMockery context = new JUnitRuleMockery();
33  
34      @Mock public OptionsSpecification<O> specification;
35      @Mock public ValidationErrorBuilder validationErrorBuilder;
36  
37      @Mock public ParsedOptionSpecification option;
38  
39      private ArgumentValidatorImpl<O> argumentValidator;
40  
41      @Before
42      public void setup() {
43          argumentValidator = new ArgumentValidatorImpl<O>(specification, validationErrorBuilder);
44      }
45  
46      public interface NoValue {
47          @Option boolean getName0();
48  
49          @Option boolean getName1();
50      }
51  
52      public interface SingleValue {
53          @Option String getName();
54      }
55  
56      public interface MultipleValue {
57          @Option List<String> getName();
58  
59          @Unparsed List<String> getUnparsed();
60      }
61  
62      public interface ExtraValue {
63          @Option List<String> getName0();
64  
65          @Option String getName1();
66  
67          @Unparsed List<String> getUnparsed();
68      }
69  
70      public interface OptionalOption {
71          @Option String getName0();
72  
73          @Option String getName1();
74          boolean isName1();
75      }
76  
77      public interface OptionAndUnparsed {
78          @Option String getName0();
79  
80          @Unparsed List<String> getRemainingArguments();
81      }
82  
83      @Test @Ignore public void testMissingOption() {
84          context.checking(new Expectations() {{
85              oneOf(validationErrorBuilder).validate();
86              oneOf(specification).getMandatoryOptions(); will(returnValue($.asList(option)));
87              oneOf(validationErrorBuilder).missingOption(option);
88              oneOf(validationErrorBuilder).validate();
89          }});
90          argumentValidator.finishedProcessing();
91      }
92  
93      @Test @Ignore public void noUnparsedSpecificationAndNoUnparsedOptionsIsValid() {
94          context.checking(new Expectations() {{
95              oneOf(specification).hasUnparsedSpecification(); will(returnValue(false));
96          }});
97          argumentValidator.processUnparsed(Collections.<String>emptyList());
98      }
99  
100     @Test @Ignore public void testMultipleValue() throws ArgumentValidationException {
101         context.checking(new Expectations() {{
102             oneOf(specification).isSpecified("name"); will(returnValue(true));
103             oneOf(specification).getSpecification("name"); will(returnValue(option));
104             oneOf(option).isHelpOption(); will(returnValue(false));
105             oneOf(option).allowedThisManyValues(2); will(returnValue(true));
106 
107             oneOf(option).allowedValue("a"); will(returnValue(true));
108             oneOf(option).allowedValue("b"); will(returnValue(true));
109 
110             oneOf(validationErrorBuilder).validate();
111             oneOf(specification).getMandatoryOptions(); will(returnValue($.asList(option)));
112             oneOf(validationErrorBuilder).validate();
113         }});
114 
115         argumentValidator.processOption("name", asList("a", "b"));
116         argumentValidator.finishedProcessing();
117     }
118 
119     @Test @Ignore public void testMultipleValueEndOfArguments() throws ArgumentValidationException {
120         final OptionCollectionImpl validated =
121                 validate(new String[] { "--name", "a", "b", "--", "c", "d" }, MultipleValue.class);
122         assertEquals(2, validated.getUnparsed().size());
123         assertEquals(2, validated.getValues("name").size());
124     }
125 
126     @Test @Ignore public void testMultipleValueNotEndOfArguments() throws ArgumentValidationException {
127         final OptionCollectionImpl validated =
128                 validate(
129                         new String[] { "--name0", "a", "b", "--name1", "c", "d", "e", "--", "f", "g" },
130                         ExtraValue.class);
131         assertEquals(4, validated.getUnparsed().size());
132         assertEquals(2, validated.getValues("name0").size());
133         assertEquals(1, validated.getValues("name1").size());
134     }
135 
136     @Test @Ignore public void testAdjacentShortOptions() throws ArgumentValidationException {
137         final OptionCollectionImpl validated = validate(new String[] { "-vrf", "./" }, RmExample.class);
138         assertEquals(1, validated.getUnparsed().size());
139     }
140 
141     @Test @Ignore public void testSingleValue() throws ArgumentValidationException {
142         validate(new String[] { "--name", "a" }, MultipleValue.class);
143     }
144 
145     @Test @Ignore public void testExtraOption() {
146         try {
147             validate(new String[] { "--name1", "value", "wrong", "--name0" }, ExtraValue.class);
148             fail();
149         } catch (final ArgumentValidationException e) {
150             assertThat(e.getValidationFailures(), contains(validationError(ValidationFailureType.UnexpectedAdditionalValue)));
151         }
152     }
153 
154     @Test @Ignore public void testMissingValue() {
155         try {
156             validate(new String[] { "--name" }, SingleValue.class);
157             fail();
158         } catch (final ArgumentValidationException e) {
159             assertThat(e.getValidationFailures(), contains(validationError(ValidationFailureType.MissingValue)));
160         }
161     }
162 
163     @Test @Ignore public void testUnexpectedValue() {
164         try {
165             validate(new String[] { "--name1", "value", "--name0" }, NoValue.class);
166             fail();
167         } catch (final ArgumentValidationException e) {
168             assertThat(e.getValidationFailures(), contains(validationError(ValidationFailureType.UnexpectedValue)));
169         }
170     }
171 
172     @Test @Ignore public void testMissingMultipleValue() throws ArgumentValidationException {
173         validate(new String[] { "--name" }, MultipleValue.class);
174         // TODO[tim]:support minimum/maximum value list lengths
175     }
176 
177     @Test @Ignore public void testOptionAndUnparsed() throws ArgumentValidationException {
178         final OptionCollectionImpl validated =
179                 validate(new String[] { "--name0", "value0", "remaining0" }, OptionAndUnparsed.class);
180         assertEquals(1, validated.getUnparsed().size());
181     }
182 
183     private <O> OptionCollectionImpl validate(final String[] arguments, final Class<O> klass)
184             throws ArgumentValidationException {
185         final ArgumentValidatorImpl<O> impl = null;
186 //                new ArgumentValidatorImpl<O>(
187 //                        InterfaceOptionsSpecificationParser.<O>createOptionsSpecificationImpl(type(klass)));
188 
189         final ArgumentCollectionBuilder parsedArguments = new ArgumentCollectionBuilder();
190         createDefaultArgumentParser().parseArguments(parsedArguments, arguments);
191 
192         return (OptionCollectionImpl) parsedArguments.processArguments(impl);
193     }
194 }