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