• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.loganalysis.util.config;
18 
19 import junit.framework.TestCase;
20 
21 import java.io.File;
22 import java.io.IOException;
23 import java.lang.reflect.Field;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.Map;
28 
29 /**
30  * Unit tests for {@link OptionSetter}.
31  */
32 public class OptionSetterTest extends TestCase {
33 
34     /** Option source with generic type. */
35     private static class GenericTypeOptionSource {
36         @Option(name = "my_option", shortName = 'o')
37         private Collection<?> mMyOption;
38     }
39 
40     /** Option source with unparameterized type. */
41     @SuppressWarnings("rawtypes")
42     private static class CollectionTypeOptionSource {
43         @Option(name = "my_option", shortName = 'o')
44         private Collection mMyOption;
45     }
46 
47     private static class MyGeneric<T> {
48     }
49 
50     /** Option source with unparameterized type. */
51     private static class NonCollectionGenericTypeOptionSource {
52         @Option(name = "my_option", shortName = 'o')
53         private MyGeneric<String> mMyOption;
54     }
55 
56     /** Option source with options with same name. */
57     private static class DuplicateOptionSource {
58         @Option(name = "string", shortName = 's')
59         private String mMyOption;
60 
61         @Option(name = "string", shortName = 's')
62         private String mMyDuplicateOption;
63     }
64 
65     /** Option source with an option with same name as AllTypesOptionSource. */
66     @OptionClass(alias = "shared")
67     private static class SharedOptionSource {
68         @Option(name = "string", shortName = 's')
69         private String mMyOption;
70 
71         @Option(name = "enum")
72         private DefaultEnumClass mEnum = null;
73 
74         @Option(name = "string_collection")
75         private Collection<String> mStringCollection = new ArrayList<String>();
76 
77         @Option(name = "enumMap")
78         private Map<DefaultEnumClass, CustomEnumClass> mEnumMap =
79                 new HashMap<DefaultEnumClass, CustomEnumClass>();
80 
81         @Option(name = "enumCollection")
82         private Collection<DefaultEnumClass> mEnumCollection =
83                 new ArrayList<DefaultEnumClass>();
84     }
85 
86     /**
87      * Option source with an option with same name as AllTypesOptionSource, but a different type.
88      */
89     private static class SharedOptionWrongTypeSource {
90         @Option(name = "string", shortName = 's')
91         private int mMyOption;
92     }
93 
94     /** option source with all supported types. */
95     @OptionClass(alias = "all")
96     private static class AllTypesOptionSource {
97         @Option(name = "string_collection")
98         private final Collection<String> mStringCollection = new ArrayList<String>();
99 
100         @Option(name = "string_string_map")
101         private Map<String, String> mStringMap = new HashMap<String, String>();
102 
103         @Option(name = "string")
104         private String mString = null;
105 
106         @Option(name = "boolean")
107         private boolean mBool = false;
108 
109         @Option(name = "booleanObj")
110         private Boolean mBooleanObj = false;
111 
112         @Option(name = "byte")
113         private byte mByte = 0;
114 
115         @Option(name = "byteObj")
116         private Byte mByteObj = 0;
117 
118         @Option(name = "short")
119         private short mShort = 0;
120 
121         @Option(name = "shortObj")
122         private Short mShortObj = null;
123 
124         @Option(name = "int")
125         private int mInt = 0;
126 
127         @Option(name = "intObj")
128         private Integer mIntObj = 0;
129 
130         @Option(name = "long")
131         private long mLong = 0;
132 
133         @Option(name = "longObj")
134         private Long mLongObj = null;
135 
136         @Option(name = "float")
137         private float mFloat = 0;
138 
139         @Option(name = "floatObj")
140         private Float mFloatObj = null;
141 
142         @Option(name = "double")
143         private double mDouble = 0;
144 
145         @Option(name = "doubleObj")
146         private Double mDoubleObj = null;
147 
148         @Option(name = "file")
149         private File mFile = null;
150 
151         @Option(name = "enum")
152         private DefaultEnumClass mEnum = null;
153 
154         @Option(name = "customEnum")
155         private CustomEnumClass mCustomEnum = null;
156 
157         @Option(name = "enumMap")
158         private Map<DefaultEnumClass, CustomEnumClass> mEnumMap =
159                 new HashMap<DefaultEnumClass, CustomEnumClass>();
160 
161         @Option(name = "enumCollection")
162         private Collection<DefaultEnumClass> mEnumCollection =
163                 new ArrayList<DefaultEnumClass>();
164     }
165 
166     private static class ParentOptionSource {
167         @Option(name = "string")
168         private String mString = null;
169 
getParentString()170         protected String getParentString() {
171             return mString;
172         }
173     }
174 
175     private static class ChildOptionSource extends ParentOptionSource {
176         @Option(name = "child-string")
177         private String mChildString = null;
178     }
179 
180     /**
181      * Option source with invalid option name.
182      */
183     private static class BadOptionNameSource {
184         @Option(name = "bad:string", shortName = 's')
185         private int mMyOption;
186     }
187 
188     private static enum DefaultEnumClass {
189         VAL1, VAL3, VAL2;
190     }
191 
192     private static enum CustomEnumClass {
193         VAL1(42);
194 
195         private int mVal;
196 
CustomEnumClass(int val)197         CustomEnumClass(int val) {
198             mVal = val;
199         }
200 
getVal()201         public int getVal() {
202             return mVal;
203         }
204     }
205 
206     private static class FinalOption {
207         @Option(name = "final-string", description="final field, not allowed")
208         private final String mFinal= "foo";
209     }
210 
211     /**
212      * Test creating an {@link OptionSetter} for a source with invalid option type.
213      */
testOptionSetter_noType()214     public void testOptionSetter_noType() {
215         try {
216             new OptionSetter(new GenericTypeOptionSource());
217             fail("ConfigurationException not thrown");
218         } catch (ConfigurationException e) {
219             // expected
220         }
221     }
222 
223     /**
224      * Test creating an {@link OptionSetter} for a source with duplicate option names.
225      */
testOptionSetter_duplicateOptions()226     public void testOptionSetter_duplicateOptions() {
227         try {
228             new OptionSetter(new DuplicateOptionSource());
229             fail("ConfigurationException not thrown");
230         } catch (ConfigurationException e) {
231             // expected
232         }
233     }
234 
235     /**
236      * Test option with same name can be used in multiple option sources.
237      */
testOptionSetter_sharedOptions()238     public void testOptionSetter_sharedOptions() throws ConfigurationException {
239         AllTypesOptionSource object1 = new AllTypesOptionSource();
240         SharedOptionSource object2 = new SharedOptionSource();
241         OptionSetter setter = new OptionSetter(object1, object2);
242         setter.setOptionValue("string", "test");
243         assertEquals("test", object1.mString);
244         assertEquals("test", object2.mMyOption);
245     }
246 
247     /**
248      * Test {@link OptionSetter#setOptionValue(String, String)} for Enums used as the key and value
249      * of a {@link Map}.
250      */
testOptionSetter_sharedEnumMap()251     public void testOptionSetter_sharedEnumMap() throws ConfigurationException {
252         AllTypesOptionSource object1 = new AllTypesOptionSource();
253         SharedOptionSource object2 = new SharedOptionSource();
254 
255         final String key = "VAL1";
256         final String value = "VAL1";
257         final DefaultEnumClass expectedKey = DefaultEnumClass.VAL1;
258         final CustomEnumClass expectedValue = CustomEnumClass.VAL1;
259 
260         // Actually set the key/value pair
261         OptionSetter parser = new OptionSetter(object1, object2);
262         parser.setOptionMapValue("enumMap", key, value);
263 
264         // verify object1
265         assertEquals(1, object1.mEnumMap.size());
266         assertNotNull(object1.mEnumMap.get(expectedKey));
267         assertEquals(expectedValue, object1.mEnumMap.get(expectedKey));
268 
269         // verify object2
270         assertEquals(1, object2.mEnumMap.size());
271         assertNotNull(object2.mEnumMap.get(expectedKey));
272         assertEquals(expectedValue, object2.mEnumMap.get(expectedKey));
273     }
274 
275 
276     /**
277      * Test {@link OptionSetter#setOptionValue(String, String)} for Enums used as the key and value
278      * of a {@link Map}.
279      */
testOptionSetter_sharedEnumCollection()280     public void testOptionSetter_sharedEnumCollection() throws ConfigurationException {
281         AllTypesOptionSource object1 = new AllTypesOptionSource();
282         SharedOptionSource object2 = new SharedOptionSource();
283 
284         final String value = "VAL1";
285         final DefaultEnumClass expectedValue = DefaultEnumClass.VAL1;
286 
287         // Actually add the element
288         OptionSetter parser = new OptionSetter(object1, object2);
289         parser.setOptionValue("enumCollection", value);
290 
291         // verify object1
292         assertEquals(1, object1.mEnumCollection.size());
293         assertTrue(object1.mEnumCollection.contains(expectedValue));
294 
295         // verify object2
296         assertEquals(1, object2.mEnumCollection.size());
297         assertTrue(object2.mEnumCollection.contains(expectedValue));
298     }
299 
300 
301     /**
302      * Test that multiple options with same name must have the same type.
303      */
testOptionSetter_sharedOptionsDiffType()304     public void testOptionSetter_sharedOptionsDiffType() {
305         try {
306             new OptionSetter(new AllTypesOptionSource(), new SharedOptionWrongTypeSource());
307             fail("ConfigurationException not thrown");
308         } catch (ConfigurationException e) {
309             // expected
310         }
311     }
312 
313     /**
314      * Test namespaced options using class names.
315      */
testOptionSetter_namespacedClassName()316     public void testOptionSetter_namespacedClassName() throws ConfigurationException {
317         AllTypesOptionSource object1 = new AllTypesOptionSource();
318         SharedOptionSource object2 = new SharedOptionSource();
319         OptionSetter setter = new OptionSetter(object1, object2);
320         setter.setOptionValue(AllTypesOptionSource.class.getName() + ":string", "alltest");
321         setter.setOptionValue(SharedOptionSource.class.getName() + ":string", "sharedtest");
322         assertEquals("alltest", object1.mString);
323         assertEquals("sharedtest", object2.mMyOption);
324     }
325 
326     /**
327      * Test namespaced options using OptionClass aliases
328      */
testOptionSetter_namespacedAlias()329     public void testOptionSetter_namespacedAlias() throws ConfigurationException {
330         AllTypesOptionSource object1 = new AllTypesOptionSource();
331         SharedOptionSource object2 = new SharedOptionSource();
332         OptionSetter setter = new OptionSetter(object1, object2);
333         setter.setOptionValue("all:string", "alltest");
334         setter.setOptionValue("shared:string", "sharedtest");
335         assertEquals("alltest", object1.mString);
336         assertEquals("sharedtest", object2.mMyOption);
337     }
338 
339     /**
340      * Test creating an {@link OptionSetter} for a Collection with no type.
341      */
testOptionSetter_unparamType()342     public void testOptionSetter_unparamType() {
343         try {
344             new OptionSetter(new CollectionTypeOptionSource());
345             fail("ConfigurationException not thrown");
346         } catch (ConfigurationException e) {
347             // expected
348         }
349     }
350 
351     /**
352      * Test creating an {@link OptionSetter} for a non collection option with generic type
353      */
testOptionSetter_genericType()354     public void testOptionSetter_genericType() {
355         try {
356             new OptionSetter(new NonCollectionGenericTypeOptionSource());
357             fail("ConfigurationException not thrown");
358         } catch (ConfigurationException e) {
359             // expected
360         }
361     }
362 
363     /**
364      * Test creating an {@link OptionSetter} for class with inherited options
365      */
testOptionSetter_inheritedOptions()366     public void testOptionSetter_inheritedOptions() throws ConfigurationException {
367         ChildOptionSource source = new ChildOptionSource();
368         OptionSetter setter = new OptionSetter(source);
369         setter.setOptionValue("string", "parent");
370         setter.setOptionValue("child-string", "child");
371         assertEquals("parent", source.getParentString());
372         assertEquals("child", source.mChildString);
373     }
374 
375     /**
376      * Test that options with {@link OptionSetter#NAMESPACE_SEPARATOR} are rejected
377      */
testOptionSetter_badOptionName()378     public void testOptionSetter_badOptionName() {
379         try {
380             new OptionSetter(new BadOptionNameSource());
381             fail("ConfigurationException not thrown");
382         } catch (ConfigurationException e) {
383             // expected
384         }
385     }
386 
387     /**
388      * Test {@link OptionSetter#isBooleanOption(String)} when passed an unknown option name
389      */
testIsBooleanOption_unknown()390     public void testIsBooleanOption_unknown() throws ConfigurationException {
391         OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
392         try {
393             parser.isBooleanOption("unknown");
394             fail("ConfigurationException not thrown");
395         } catch (ConfigurationException e) {
396             // expected
397         }
398     }
399 
400     /**
401      * Test {@link OptionSetter#isBooleanOption(String)} when passed boolean option name
402      */
testIsBooleanOption_true()403     public void testIsBooleanOption_true() throws ConfigurationException {
404         OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
405         assertTrue(parser.isBooleanOption("boolean"));
406     }
407 
408     /**
409      * Test {@link OptionSetter#isBooleanOption(String)} when passed boolean option name for a
410      * Boolean object
411      */
testIsBooleanOption_objTrue()412     public void testIsBooleanOption_objTrue() throws ConfigurationException {
413         OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
414         assertTrue(parser.isBooleanOption("booleanObj"));
415     }
416 
417     /**
418      * Test {@link OptionSetter#isBooleanOption(String)} when passed non-boolean option
419      */
testIsBooleanOption_false()420     public void testIsBooleanOption_false() throws ConfigurationException {
421         OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
422         assertFalse(parser.isBooleanOption("string"));
423     }
424 
425     /**
426      * Test {@link OptionSetter#setOptionValue(String, String)} when passed an unknown option name
427      */
testSetOptionValue_unknown()428     public void testSetOptionValue_unknown() throws ConfigurationException {
429         OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
430         try {
431             parser.setOptionValue("unknown", "foo");
432             fail("ConfigurationException not thrown");
433         } catch (ConfigurationException e) {
434             // expected
435         }
436     }
437 
438     /**
439      * Test setting a value for a option with an unknown generic type.
440      */
testSetOptionValue_unknownType()441     public void testSetOptionValue_unknownType() throws ConfigurationException {
442         OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
443         try {
444             parser.setOptionValue("my_option", "foo");
445             fail("ConfigurationException not thrown");
446         } catch (ConfigurationException e) {
447             // expected
448         }
449     }
450 
451     /**
452      * Test setting a value for a non-parameterized Collection
453      */
testSetOptionValue_unparameterizedType()454     public void testSetOptionValue_unparameterizedType() throws ConfigurationException {
455         OptionSetter parser = new OptionSetter(new AllTypesOptionSource());
456         try {
457             parser.setOptionValue("my_option", "foo");
458             fail("ConfigurationException not thrown");
459         } catch (ConfigurationException e) {
460             // expected
461         }
462     }
463 
464     /**
465      * Test {@link OptionSetter#setOptionValue(String, String)} for a String.
466      */
testSetOptionValue_string()467     public void testSetOptionValue_string() throws ConfigurationException {
468         AllTypesOptionSource optionSource = new AllTypesOptionSource();
469         final String expectedValue = "stringvalue";
470         assertSetOptionValue(optionSource, "string", expectedValue);
471         assertEquals(expectedValue, optionSource.mString);
472     }
473 
474     /**
475      * Test {@link OptionSetter#setOptionValue(String, String)} for a Collection.
476      */
testSetOptionValue_collection()477     public void testSetOptionValue_collection() throws ConfigurationException {
478         AllTypesOptionSource optionSource = new AllTypesOptionSource();
479         final String expectedValue = "stringvalue";
480         assertSetOptionValue(optionSource, "string_collection", expectedValue);
481         assertEquals(1, optionSource.mStringCollection.size());
482         assertTrue(optionSource.mStringCollection.contains(expectedValue));
483     }
484 
485     /**
486      * Test {@link OptionSetter#setOptionValue(String, String)} for a Map.
487      */
testSetOptionValue_map()488     public void testSetOptionValue_map() throws ConfigurationException {
489         AllTypesOptionSource optionSource = new AllTypesOptionSource();
490         final String expectedKey = "stringkey";
491         final String expectedValue = "stringvalue";
492 
493         // Actually set the key/value pair
494         OptionSetter parser = new OptionSetter(optionSource);
495         parser.setOptionMapValue("string_string_map", expectedKey, expectedValue);
496 
497         assertEquals(1, optionSource.mStringMap.size());
498         assertNotNull(optionSource.mStringMap.get(expectedKey));
499         assertEquals(expectedValue, optionSource.mStringMap.get(expectedKey));
500     }
501 
502     /**
503      * Test {@link OptionSetter#setOptionValue(String, String)} for a boolean.
504      */
testSetOptionValue_boolean()505     public void testSetOptionValue_boolean() throws ConfigurationException {
506         AllTypesOptionSource optionSource = new AllTypesOptionSource();
507         assertSetOptionValue(optionSource, "boolean", "true");
508         assertEquals(true, optionSource.mBool);
509     }
510 
511     /**
512      * Test {@link OptionSetter#setOptionValue(String, String)} for a boolean for a non-boolean
513      * value.
514      */
testSetOptionValue_booleanInvalid()515     public void testSetOptionValue_booleanInvalid() {
516         AllTypesOptionSource optionSource = new AllTypesOptionSource();
517         assertSetOptionValueInvalid(optionSource, "boolean", "blah");
518     }
519 
520     /**
521      * Test {@link OptionSetter#setOptionValue(String, String)} for a Boolean.
522      */
testSetOptionValue_booleanObj()523     public void testSetOptionValue_booleanObj() throws ConfigurationException {
524         AllTypesOptionSource optionSource = new AllTypesOptionSource();
525         assertSetOptionValue(optionSource, "booleanObj", "true");
526         assertTrue(optionSource.mBooleanObj);
527     }
528 
529     /**
530      * Test {@link OptionSetter#setOptionValue(String, String)} for a byte.
531      */
testSetOptionValue_byte()532     public void testSetOptionValue_byte() throws ConfigurationException {
533         AllTypesOptionSource optionSource = new AllTypesOptionSource();
534         assertSetOptionValue(optionSource, "byte", "2");
535         assertEquals(2, optionSource.mByte);
536     }
537 
538     /**
539      * Test {@link OptionSetter#setOptionValue(String, String)} for a byte for an invalid value.
540      */
testSetOptionValue_byteInvalid()541     public void testSetOptionValue_byteInvalid() {
542         AllTypesOptionSource optionSource = new AllTypesOptionSource();
543         assertSetOptionValueInvalid(optionSource, "byte", "blah");
544     }
545 
546     /**
547      * Test {@link OptionSetter#setOptionValue(String, String)} for a Byte.
548      */
testSetOptionValue_byteObj()549     public void testSetOptionValue_byteObj() throws ConfigurationException {
550         AllTypesOptionSource optionSource = new AllTypesOptionSource();
551         assertSetOptionValue(optionSource, "byteObj", "2");
552         assertTrue(2 == optionSource.mByteObj);
553     }
554 
555     /**
556      * Test {@link OptionSetter#setOptionValue(String, String)} for a short.
557      */
testSetOptionValue_short()558     public void testSetOptionValue_short() throws ConfigurationException {
559         AllTypesOptionSource optionSource = new AllTypesOptionSource();
560         assertSetOptionValue(optionSource, "short", "2");
561         assertTrue(2 == optionSource.mShort);
562     }
563 
564     /**
565      * Test {@link OptionSetter#setOptionValue(String, String)} for a Short.
566      */
testSetOptionValue_shortObj()567     public void testSetOptionValue_shortObj() throws ConfigurationException {
568         AllTypesOptionSource optionSource = new AllTypesOptionSource();
569         assertSetOptionValue(optionSource, "shortObj", "2");
570         assertTrue(2 == optionSource.mShortObj);
571     }
572 
573     /**
574      * Test {@link OptionSetter#setOptionValue(String, String)} for a short for an invalid value.
575      */
testSetOptionValue_shortInvalid()576     public void testSetOptionValue_shortInvalid() {
577         AllTypesOptionSource optionSource = new AllTypesOptionSource();
578         assertSetOptionValueInvalid(optionSource, "short", "blah");
579     }
580 
581     /**
582      * Test {@link OptionSetter#setOptionValue(String, String)} for a int.
583      */
testSetOptionValue_int()584     public void testSetOptionValue_int() throws ConfigurationException {
585         AllTypesOptionSource optionSource = new AllTypesOptionSource();
586         assertSetOptionValue(optionSource, "int", "2");
587         assertTrue(2 == optionSource.mInt);
588     }
589 
590     /**
591      * Test {@link OptionSetter#setOptionValue(String, String)} for a Integer.
592      */
testSetOptionValue_intObj()593     public void testSetOptionValue_intObj() throws ConfigurationException {
594         AllTypesOptionSource optionSource = new AllTypesOptionSource();
595         assertSetOptionValue(optionSource, "intObj", "2");
596         assertTrue(2 == optionSource.mIntObj);
597     }
598 
599     /**
600      * Test {@link OptionSetter#setOptionValue(String, String)} for a int for an invalid value.
601      */
testSetOptionValue_intInvalid()602     public void testSetOptionValue_intInvalid() {
603         AllTypesOptionSource optionSource = new AllTypesOptionSource();
604         assertSetOptionValueInvalid(optionSource, "int", "blah");
605     }
606 
607     /**
608      * Test {@link OptionSetter#setOptionValue(String, String)} for a long.
609      */
testSetOptionValue_long()610     public void testSetOptionValue_long() throws ConfigurationException {
611         AllTypesOptionSource optionSource = new AllTypesOptionSource();
612         assertSetOptionValue(optionSource, "long", "2");
613         assertTrue(2 == optionSource.mLong);
614     }
615 
616     /**
617      * Test {@link OptionSetter#setOptionValue(String, String)} for a Long.
618      */
testSetOptionValue_longObj()619     public void testSetOptionValue_longObj() throws ConfigurationException {
620         AllTypesOptionSource optionSource = new AllTypesOptionSource();
621         assertSetOptionValue(optionSource, "longObj", "2");
622         assertTrue(2 == optionSource.mLongObj);
623     }
624 
625     /**
626      * Test {@link OptionSetter#setOptionValue(String, String)} for a long for an invalid value.
627      */
testSetOptionValue_longInvalid()628     public void testSetOptionValue_longInvalid() {
629         AllTypesOptionSource optionSource = new AllTypesOptionSource();
630         assertSetOptionValueInvalid(optionSource, "long", "blah");
631     }
632 
633     /**
634      * Test {@link OptionSetter#setOptionValue(String, String)} for a float.
635      */
testSetOptionValue_float()636     public void testSetOptionValue_float() throws ConfigurationException {
637         AllTypesOptionSource optionSource = new AllTypesOptionSource();
638         assertSetOptionValue(optionSource, "float", "2.1");
639         assertEquals(2.1, optionSource.mFloat, 0.01);
640     }
641 
642     /**
643      * Test {@link OptionSetter#setOptionValue(String, String)} for a Float.
644      */
testSetOptionValue_floatObj()645     public void testSetOptionValue_floatObj() throws ConfigurationException {
646         AllTypesOptionSource optionSource = new AllTypesOptionSource();
647         assertSetOptionValue(optionSource, "floatObj", "2.1");
648         assertEquals(2.1, optionSource.mFloatObj, 0.01);
649     }
650 
651     /**
652      * Test {@link OptionSetter#setOptionValue(String, String)} for a float for an invalid value.
653      */
testSetOptionValue_floatInvalid()654     public void testSetOptionValue_floatInvalid() {
655         AllTypesOptionSource optionSource = new AllTypesOptionSource();
656         assertSetOptionValueInvalid(optionSource, "float", "blah");
657     }
658 
659     /**
660      * Test {@link OptionSetter#setOptionValue(String, String)} for a float.
661      */
testSetOptionValue_double()662     public void testSetOptionValue_double() throws ConfigurationException {
663         AllTypesOptionSource optionSource = new AllTypesOptionSource();
664         assertSetOptionValue(optionSource, "double", "2.1");
665         assertEquals(2.1, optionSource.mDouble, 0.01);
666     }
667 
668     /**
669      * Test {@link OptionSetter#setOptionValue(String, String)} for a Float.
670      */
testSetOptionValue_doubleObj()671     public void testSetOptionValue_doubleObj() throws ConfigurationException {
672         AllTypesOptionSource optionSource = new AllTypesOptionSource();
673         assertSetOptionValue(optionSource, "doubleObj", "2.1");
674         assertEquals(2.1, optionSource.mDoubleObj, 0.01);
675     }
676 
677     /**
678      * Test {@link OptionSetter#setOptionValue(String, String)} for a double for an invalid value.
679      */
testSetOptionValue_doubleInvalid()680     public void testSetOptionValue_doubleInvalid() {
681         AllTypesOptionSource optionSource = new AllTypesOptionSource();
682         assertSetOptionValueInvalid(optionSource, "double", "blah");
683     }
684 
685     /**
686      * Test {@link OptionSetter#setOptionValue(String, String)} for a File.
687      */
testSetOptionValue_file()688     public void testSetOptionValue_file() throws ConfigurationException, IOException {
689         AllTypesOptionSource optionSource = new AllTypesOptionSource();
690         File tmpFile = File.createTempFile("testSetOptionValue_file", "txt");
691         try {
692             assertSetOptionValue(optionSource, "file", tmpFile.getAbsolutePath());
693             assertEquals(tmpFile.getAbsolutePath(), optionSource.mFile.getAbsolutePath());
694         } finally {
695             tmpFile.delete();
696         }
697     }
698 
699     /**
700      * Test {@link OptionSetter#setOptionValue(String, String)} for an Enum.
701      */
testSetOptionValue_enum()702     public void testSetOptionValue_enum() throws ConfigurationException {
703         AllTypesOptionSource optionSource = new AllTypesOptionSource();
704         assertSetOptionValue(optionSource, "enum", "VAL1");
705         assertEquals(DefaultEnumClass.VAL1, optionSource.mEnum);
706     }
707 
708     /**
709      * Test {@link OptionSetter#setOptionValue(String, String)} for an Enum.  Specifically make sure
710      * that we fall back properly, so that a mixed-case value will be silently mapped to an
711      * uppercase version, since Enum constants tend to be uppercase by convention.
712      */
testSetOptionValue_enumMixedCase()713     public void testSetOptionValue_enumMixedCase() throws ConfigurationException {
714         AllTypesOptionSource optionSource = new AllTypesOptionSource();
715         assertSetOptionValue(optionSource, "enum", "Val1");
716         assertEquals(DefaultEnumClass.VAL1, optionSource.mEnum);
717     }
718 
719     /**
720      * Test {@link OptionSetter#setOptionValue(String, String)} for an Enum with custom values.
721      */
testSetOptionValue_customEnum()722     public void testSetOptionValue_customEnum() throws ConfigurationException {
723         AllTypesOptionSource optionSource = new AllTypesOptionSource();
724         assertSetOptionValue(optionSource, "customEnum", "VAL1");
725         assertEquals(CustomEnumClass.VAL1, optionSource.mCustomEnum);
726         assertEquals(42, optionSource.mCustomEnum.getVal());
727     }
728 
729     /**
730      * Test {@link OptionSetter#setOptionValue(String, String)} for Enums used as the key and value
731      * of a {@link Map}.
732      */
testSetOptionValue_enumMap()733     public void testSetOptionValue_enumMap() throws ConfigurationException {
734         AllTypesOptionSource optionSource = new AllTypesOptionSource();
735 
736         final String key = "VAL1";
737         final String value = "VAL1";
738         final DefaultEnumClass expectedKey = DefaultEnumClass.VAL1;
739         final CustomEnumClass expectedValue = CustomEnumClass.VAL1;
740 
741         // Actually set the key/value pair
742         OptionSetter parser = new OptionSetter(optionSource);
743         parser.setOptionMapValue("enumMap", key, value);
744 
745         assertEquals(1, optionSource.mEnumMap.size());
746         assertNotNull(optionSource.mEnumMap.get(expectedKey));
747         assertEquals(expectedValue, optionSource.mEnumMap.get(expectedKey));
748     }
749 
750 
751     /**
752      * Test {@link OptionSetter#setOptionValue(String, String)} for Enums used as the key and value
753      * of a {@link Map}.
754      */
testSetOptionValue_enumCollection()755     public void testSetOptionValue_enumCollection() throws ConfigurationException {
756         AllTypesOptionSource optionSource = new AllTypesOptionSource();
757 
758         final String value = "VAL1";
759         final DefaultEnumClass expectedValue = DefaultEnumClass.VAL1;
760 
761         assertSetOptionValue(optionSource, "enumCollection", value);
762 
763         assertEquals(1, optionSource.mEnumCollection.size());
764         assertTrue(optionSource.mEnumCollection.contains(expectedValue));
765     }
766 
767 
768     /**
769      * Test {@link OptionSetter#setOptionValue(String, String)} for an Enum.
770      */
testSetOptionValue_enumBadValue()771     public void testSetOptionValue_enumBadValue() {
772         AllTypesOptionSource optionSource = new AllTypesOptionSource();
773         try {
774             assertSetOptionValue(optionSource, "enum", "noexist");
775             fail("ConfigurationException not thrown");
776         } catch (ConfigurationException e) {
777             // expected
778         }
779     }
780 
781     /**
782      * Make sure that Enum documentation shows the defaults properly
783      */
testEnumDocs()784     public void testEnumDocs() throws Exception {
785         // We assume here that the fields are returned in declaration order, as documented in the
786         // {@link Enum} javadoc.
787         String expectedValues = " Valid values: [VAL1, VAL3, VAL2]";
788         Field field = AllTypesOptionSource.class.getDeclaredField("mEnum");
789         String actualValues = OptionSetter.getEnumFieldValuesAsString(field);
790         assertEquals(expectedValues, actualValues);
791     }
792 
793     /**
794      * Test {@link OptionSetter} for a final field
795      */
testOptionSetter_finalField()796     public void testOptionSetter_finalField() {
797         FinalOption optionSource = new FinalOption();
798         try {
799             new OptionSetter(optionSource);
800             fail("ConfigurationException not thrown");
801         } catch (ConfigurationException e) {
802             // expected
803         }
804     }
805 
806     /**
807      * Perform {@link OptionSetter#setOptionValue(String, String)} for a given option.
808      */
assertSetOptionValue(AllTypesOptionSource optionSource, final String optionName, final String expectedValue)809     private void assertSetOptionValue(AllTypesOptionSource optionSource, final String optionName,
810             final String expectedValue) throws ConfigurationException {
811         OptionSetter parser = new OptionSetter(optionSource);
812         parser.setOptionValue(optionName, expectedValue);
813     }
814 
815     /**
816      * Perform {@link OptionSetter#setOptionValue(String, String)} for a given option, with an
817      * invalid value for the option type.
818      */
assertSetOptionValueInvalid(AllTypesOptionSource optionSource, final String optionName, final String expectedValue)819     private void assertSetOptionValueInvalid(AllTypesOptionSource optionSource,
820             final String optionName, final String expectedValue) {
821         try {
822             assertSetOptionValue(optionSource, optionName, expectedValue);
823             fail("ConfigurationException not thrown");
824         } catch (ConfigurationException e) {
825             // expected
826         }
827     }
828 }
829