001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.configuration.beanutils; 019 020 import static org.junit.Assert.assertEquals; 021 import static org.junit.Assert.assertFalse; 022 import static org.junit.Assert.assertNotNull; 023 import static org.junit.Assert.assertNull; 024 import static org.junit.Assert.assertTrue; 025 import static org.junit.Assert.fail; 026 027 import java.util.Arrays; 028 import java.util.HashMap; 029 import java.util.List; 030 031 import junitx.framework.ObjectAssert; 032 033 import org.apache.commons.beanutils.DynaProperty; 034 import org.apache.commons.configuration.BaseConfiguration; 035 import org.apache.commons.configuration.Configuration; 036 import org.apache.commons.configuration.MapConfiguration; 037 import org.junit.Before; 038 import org.junit.Test; 039 040 /** 041 * <p>Test Case for the <code>ConfigurationDynaBean</code> implementation class. 042 * These tests were based on the ones in <code>BasicDynaBeanTestCase</code> 043 * because the two classes provide similar levels of functionality.</p> 044 * 045 * @author <a href="mailto:ricardo.gladwell@btinternet.com">Ricardo Gladwell</a> 046 * @version $Id: TestConfigurationDynaBean.java 1225349 2011-12-28 21:36:59Z oheger $ 047 */ 048 public class TestConfigurationDynaBean 049 { 050 /** 051 * The basic test bean for each test. 052 */ 053 private ConfigurationDynaBean bean; 054 055 /** 056 * The set of property names we expect to have returned when calling 057 * <code>getDynaProperties()</code>. You should update this list 058 * when new properties are added to TestBean. 059 */ 060 String[] properties = { 061 "booleanProperty", 062 "booleanSecond", 063 "doubleProperty", 064 "floatProperty", 065 "intProperty", 066 "longProperty", 067 "mappedProperty.key1", 068 "mappedProperty.key2", 069 "mappedProperty.key3", 070 "mappedIntProperty.key1", 071 "shortProperty", 072 "stringProperty", 073 "byteProperty", 074 "charProperty" 075 }; 076 077 Object[] values = { 078 Boolean.TRUE, 079 Boolean.TRUE, 080 new Double(Double.MAX_VALUE), 081 new Float(Float.MAX_VALUE), 082 new Integer(Integer.MAX_VALUE), 083 new Long(Long.MAX_VALUE), 084 "First Value", 085 "Second Value", 086 "Third Value", 087 new Integer(Integer.MAX_VALUE), 088 new Short(Short.MAX_VALUE), 089 "This is a string", 090 new Byte(Byte.MAX_VALUE), 091 new Character(Character.MAX_VALUE) 092 }; 093 094 int[] intArray = {0, 10, 20, 30, 40}; 095 boolean[] booleanArray = {true, false, true, false, true}; 096 char[] charArray = {'a', 'b', 'c', 'd', 'e'}; 097 byte[] byteArray = {0, 10, 20, 30, 40}; 098 long[] longArray = {0, 10, 20, 30, 40}; 099 short[] shortArray = {0, 10, 20, 30, 40}; 100 float[] floatArray = {0, 10, 20, 30, 40}; 101 double[] doubleArray = {0.0, 10.0, 20.0, 30.0, 40.0}; 102 String[] stringArray = {"String 0", "String 1", "String 2", "String 3", "String 4"}; 103 104 105 /** 106 * Set up instance variables required by this test case. 107 */ 108 @Before 109 public void setUp() throws Exception 110 { 111 Configuration configuration = createConfiguration(); 112 113 for (int i = 0; i < properties.length; i++) 114 { 115 configuration.setProperty(properties[i], values[i]); 116 } 117 118 for (int a = 0; a < intArray.length; a++) 119 { 120 configuration.addProperty("intIndexed", new Integer(intArray[a])); 121 } 122 123 for (int a = 0; a < stringArray.length; a++) 124 { 125 configuration.addProperty("stringIndexed", stringArray[a]); 126 } 127 128 List<String> list = Arrays.asList(stringArray); 129 configuration.addProperty("listIndexed", list); 130 131 bean = new ConfigurationDynaBean(configuration); 132 133 bean.set("listIndexed", list); 134 bean.set("intArray", intArray); 135 bean.set("booleanArray", booleanArray); 136 bean.set("charArray", charArray); 137 bean.set("longArray", longArray); 138 bean.set("shortArray", shortArray); 139 bean.set("floatArray", floatArray); 140 bean.set("doubleArray", doubleArray); 141 bean.set("byteArray", byteArray); 142 bean.set("stringArray", stringArray); 143 } 144 145 /** 146 * Creates the underlying configuration object for the dyna bean. 147 * @return the underlying configuration object 148 */ 149 protected Configuration createConfiguration() 150 { 151 return new BaseConfiguration(); 152 } 153 154 /** 155 * Corner cases on getDynaProperty invalid arguments. 156 */ 157 @Test(expected = IllegalArgumentException.class) 158 public void testGetDescriptorArguments() 159 { 160 DynaProperty descriptor = bean.getDynaClass().getDynaProperty("unknown"); 161 assertNull("Unknown property descriptor should be null", descriptor); 162 bean.getDynaClass().getDynaProperty(null); 163 } 164 165 /** 166 * Positive getDynaProperty on property <code>booleanProperty</code>. 167 */ 168 @Test 169 public void testGetDescriptorBoolean() 170 { 171 testGetDescriptorBase("booleanProperty", Boolean.TYPE); 172 } 173 174 /** 175 * Positive getDynaProperty on property <code>doubleProperty</code>. 176 */ 177 @Test 178 public void testGetDescriptorDouble() 179 { 180 testGetDescriptorBase("doubleProperty", Double.TYPE); 181 } 182 183 /** 184 * Positive getDynaProperty on property <code>floatProperty</code>. 185 */ 186 @Test 187 public void testGetDescriptorFloat() 188 { 189 testGetDescriptorBase("floatProperty", Float.TYPE); 190 } 191 192 /** 193 * Positive getDynaProperty on property <code>intProperty</code>. 194 */ 195 @Test 196 public void testGetDescriptorInt() 197 { 198 testGetDescriptorBase("intProperty", Integer.TYPE); 199 } 200 201 /** 202 * Positive getDynaProperty on property <code>longProperty</code>. 203 */ 204 @Test 205 public void testGetDescriptorLong() 206 { 207 testGetDescriptorBase("longProperty", Long.TYPE); 208 } 209 210 /** 211 * Positive getDynaProperty on property <code>booleanSecond</code> 212 * that uses an "is" method as the getter. 213 */ 214 @Test 215 public void testGetDescriptorSecond() 216 { 217 testGetDescriptorBase("booleanSecond", Boolean.TYPE); 218 } 219 220 /** 221 * Positive getDynaProperty on property <code>shortProperty</code>. 222 */ 223 @Test 224 public void testGetDescriptorShort() 225 { 226 testGetDescriptorBase("shortProperty", Short.TYPE); 227 } 228 229 /** 230 * Positive getDynaProperty on property <code>stringProperty</code>. 231 */ 232 @Test 233 public void testGetDescriptorString() 234 { 235 testGetDescriptorBase("stringProperty", String.class); 236 } 237 238 /** 239 * Positive test for getDynaPropertys(). Each property name 240 * listed in <code>properties</code> should be returned exactly once. 241 */ 242 @Test 243 public void testGetDescriptors() 244 { 245 DynaProperty pd[] = bean.getDynaClass().getDynaProperties(); 246 assertNotNull("Got descriptors", pd); 247 int count[] = new int[properties.length]; 248 for (int i = 0; i < pd.length; i++) 249 { 250 String name = pd[i].getName(); 251 for (int j = 0; j < properties.length; j++) 252 { 253 if (name.equals(properties[j])) 254 { 255 count[j]++; 256 } 257 } 258 } 259 260 for (int j = 0; j < properties.length; j++) 261 { 262 if (count[j] < 0) 263 { 264 fail("Missing property " + properties[j]); 265 } 266 else if (count[j] > 1) 267 { 268 fail("Duplicate property " + properties[j]); 269 } 270 } 271 } 272 273 /** 274 * Corner cases on getIndexedProperty invalid arguments. 275 */ 276 @Test(expected = IndexOutOfBoundsException.class) 277 public void testGetIndexedArguments() 278 { 279 bean.get("intArray", -1); 280 } 281 282 /** 283 * Positive and negative tests on getIndexedProperty valid arguments. 284 */ 285 @Test 286 public void testGetIndexedValues() 287 { 288 for (int i = 0; i < 5; i++) 289 { 290 Object value = bean.get("intArray", i); 291 292 assertNotNull("intArray index " + i + " did not return value.", value); 293 ObjectAssert.assertInstanceOf("intArray index " + i, Integer.class, value); 294 assertEquals("intArray " + i + " returned incorrect value.", i * 10, ((Integer) value).intValue()); 295 296 value = bean.get("intIndexed", i); 297 298 assertNotNull("intIndexed index " + i + "returned value " + i, value); 299 ObjectAssert.assertInstanceOf("intIndexed index " + i, Integer.class, value); 300 assertEquals("intIndexed index " + i + "returned correct " + i, i * 10, ((Integer) value).intValue()); 301 302 value = bean.get("listIndexed", i); 303 304 assertNotNull("listIndexed index " + i + "returned value " + i, value); 305 ObjectAssert.assertInstanceOf("list index " + i, String.class, value); 306 assertEquals("listIndexed index " + i + "returned correct " + i, "String " + i, value); 307 308 value = bean.get("stringArray", i); 309 310 assertNotNull("stringArray index " + i + " returnde null.", value); 311 assertFalse("stringArray index " + i + " returned array instead of String.", value.getClass().isArray()); 312 ObjectAssert.assertInstanceOf("stringArray index " + i, String.class, value); 313 assertEquals("stringArray returned correct " + i, "String " + i, value); 314 315 value = bean.get("stringIndexed", i); 316 317 assertNotNull("stringIndexed returned value " + i, value); 318 ObjectAssert.assertInstanceOf("stringIndexed", String.class, value); 319 assertEquals("stringIndexed returned correct " + i, "String " + i, value); 320 } 321 } 322 323 /** 324 * Corner cases on getMappedProperty invalid arguments. 325 */ 326 @Test 327 public void testGetMappedArguments() 328 { 329 try 330 { 331 Object value = bean.get("mappedProperty", "unknown"); 332 assertNull("Should not return a value", value); 333 } 334 catch (Throwable t) 335 { 336 fail("Threw " + t + " instead of returning null"); 337 } 338 } 339 340 /** 341 * Positive and negative tests on getMappedProperty valid arguments. 342 */ 343 @Test 344 public void testGetMappedValues() 345 { 346 Object value = bean.get("mappedProperty", "key1"); 347 assertEquals("Can find first value", "First Value", value); 348 349 value = bean.get("mappedProperty", "key2"); 350 assertEquals("Can find second value", "Second Value", value); 351 352 value = bean.get("mappedProperty", "key3"); 353 assertNotNull("Cannot find third value", value); 354 } 355 356 /** 357 * Corner cases on getSimpleProperty invalid arguments. 358 */ 359 @Test(expected = IllegalArgumentException.class) 360 public void testGetSimpleArguments() 361 { 362 bean.get("a non existing property"); 363 } 364 365 /** 366 * Test getSimpleProperty on a boolean property. 367 */ 368 @Test 369 public void testGetSimpleBoolean() 370 { 371 Object value = bean.get("booleanProperty"); 372 assertNotNull("Got a value", value); 373 ObjectAssert.assertInstanceOf("Got correct type", Boolean.class, value); 374 assertTrue("Got correct value", ((Boolean) value).booleanValue()); 375 } 376 377 /** 378 * Test getSimpleProperty on a double property. 379 */ 380 @Test 381 public void testGetSimpleDouble() 382 { 383 Object value = bean.get("doubleProperty"); 384 assertNotNull("Got a value", value); 385 ObjectAssert.assertInstanceOf("Got correct type", Double.class, value); 386 assertEquals("Got correct value", ((Double) value).doubleValue(), Double.MAX_VALUE, 0.005); 387 } 388 389 /** 390 * Test getSimpleProperty on a float property. 391 */ 392 @Test 393 public void testGetSimpleFloat() 394 { 395 Object value = bean.get("floatProperty"); 396 assertNotNull("Got a value", value); 397 ObjectAssert.assertInstanceOf("Got correct type", Float.class, value); 398 assertEquals("Got correct value", ((Float) value).floatValue(), Float.MAX_VALUE, 0.005f); 399 } 400 401 /** 402 * Test getSimpleProperty on a int property. 403 */ 404 @Test 405 public void testGetSimpleInt() 406 { 407 Object value = bean.get("intProperty"); 408 assertNotNull("Failed to get value", value); 409 ObjectAssert.assertInstanceOf("Incorrect type", Integer.class, value); 410 assertEquals("Incorrect value", ((Integer) value).intValue(), Integer.MAX_VALUE); 411 } 412 413 /** 414 * Test getSimpleProperty on a long property. 415 */ 416 @Test 417 public void testGetSimpleLong() 418 { 419 Object value = bean.get("longProperty"); 420 assertNotNull("Got a value", value); 421 ObjectAssert.assertInstanceOf("Returned incorrect type", Long.class, value); 422 assertEquals("Returned value of Incorrect value", ((Long) value).longValue(), Long.MAX_VALUE); 423 } 424 425 /** 426 * Test getSimpleProperty on a short property. 427 */ 428 @Test 429 public void testGetSimpleShort() 430 { 431 Object value = bean.get("shortProperty"); 432 assertNotNull("Got a value", value); 433 ObjectAssert.assertInstanceOf("Got correct type", Short.class, value); 434 assertEquals("Got correct value", ((Short) value).shortValue(), Short.MAX_VALUE); 435 } 436 437 /** 438 * Test getSimpleProperty on a String property. 439 */ 440 @Test 441 public void testGetSimpleString() 442 { 443 Object value = bean.get("stringProperty"); 444 assertNotNull("Got a value", value); 445 ObjectAssert.assertInstanceOf("Got correct type", String.class, value); 446 assertEquals("Got correct value", value, "This is a string"); 447 } 448 449 /** 450 * Test <code>contains()</code> method for mapped properties. 451 */ 452 @Test 453 public void testMappedContains() 454 { 455 assertTrue("Can't see first key", bean.contains("mappedProperty", "key1")); 456 assertTrue("Can see unknown key", !bean.contains("mappedProperty", "Unknown Key")); 457 } 458 459 /** 460 * Test <code>remove()</code> method for mapped properties. 461 */ 462 @Test 463 public void testMappedRemove() 464 { 465 assertTrue("Can see first key", bean.contains("mappedProperty", "key1")); 466 bean.remove("mappedProperty", "key1"); 467 assertTrue("Can not see first key", !bean.contains("mappedProperty", "key1")); 468 469 assertTrue("Can not see unknown key", !bean.contains("mappedProperty", "key4")); 470 bean.remove("mappedProperty", "key4"); 471 assertTrue("Can not see unknown key", !bean.contains("mappedProperty", "key4")); 472 } 473 474 /** 475 * Corner cases on setIndexedProperty invalid arguments. 476 */ 477 @Test(expected = IndexOutOfBoundsException.class) 478 public void testSetIndexedArguments() 479 { 480 bean.set("intArray", -1, new Integer(0)); 481 } 482 483 /** 484 * Positive and negative tests on setIndexedProperty valid arguments. 485 */ 486 @Test 487 public void testSetIndexedValues() 488 { 489 bean.set("intArray", 0, new Integer(1)); 490 Object value = bean.get("intArray", 0); 491 492 assertNotNull("Returned new value 0", value); 493 ObjectAssert.assertInstanceOf("Returned Integer new value 0", Integer.class, value); 494 assertEquals("Returned correct new value 0", 1, ((Integer) value).intValue()); 495 496 497 bean.set("intIndexed", 1, new Integer(11)); 498 value = bean.get("intIndexed", 1); 499 500 assertNotNull("Returned new value 1", value); 501 ObjectAssert.assertInstanceOf("Returned Integer new value 1", Integer.class, value); 502 assertEquals("Returned correct new value 1", 11, ((Integer) value).intValue()); 503 504 505 bean.set("listIndexed", 2, "New Value 2"); 506 value = bean.get("listIndexed", 2); 507 508 assertNotNull("Returned new value 2", value); 509 ObjectAssert.assertInstanceOf("Returned String new value 2", String.class, value); 510 assertEquals("Returned correct new value 2", "New Value 2", value); 511 512 513 bean.set("stringArray", 3, "New Value 3"); 514 value = bean.get("stringArray", 3); 515 516 assertNotNull("Returned new value 3", value); 517 ObjectAssert.assertInstanceOf("Returned String new value 3", String.class, value); 518 assertEquals("Returned correct new value 3", "New Value 3", value); 519 520 521 bean.set("stringIndexed", 4, "New Value 4"); 522 value = bean.get("stringIndexed", 4); 523 524 assertNotNull("Returned new value 4", value); 525 ObjectAssert.assertInstanceOf("Returned String new value 4", String.class, value); 526 assertEquals("Returned correct new value 4", "New Value 4", value); 527 } 528 529 /** 530 * Test the modification of a configuration property stored internally as an array. 531 */ 532 @Test 533 public void testSetArrayValue() 534 { 535 MapConfiguration configuration = new MapConfiguration(new HashMap<String, Object>()); 536 configuration.getMap().put("objectArray", new Object[] {"value1", "value2", "value3"}); 537 538 ConfigurationDynaBean bean = new ConfigurationDynaBean(configuration); 539 540 bean.set("objectArray", 1, "New Value 1"); 541 Object value = bean.get("objectArray", 1); 542 543 assertNotNull("Returned new value 1", value); 544 ObjectAssert.assertInstanceOf("Returned String new value 1", String.class, value); 545 assertEquals("Returned correct new value 1", "New Value 1", value); 546 } 547 548 /** 549 * Positive and negative tests on setMappedProperty valid arguments. 550 */ 551 @Test 552 public void testSetMappedValues() 553 { 554 bean.set("mappedProperty", "First Key", "New First Value"); 555 assertEquals("Can replace old value", "New First Value", bean.get("mappedProperty", "First Key")); 556 557 bean.set("mappedProperty", "Fourth Key", "Fourth Value"); 558 assertEquals("Can set new value", "Fourth Value", bean.get("mappedProperty", "Fourth Key")); 559 } 560 561 /** 562 * Test setSimpleProperty on a boolean property. 563 */ 564 @Test 565 public void testSetSimpleBoolean() 566 { 567 boolean oldValue = ((Boolean) bean.get("booleanProperty")).booleanValue(); 568 boolean newValue = !oldValue; 569 bean.set("booleanProperty", new Boolean(newValue)); 570 assertTrue("Matched new value", newValue == ((Boolean) bean.get("booleanProperty")).booleanValue()); 571 } 572 573 /** 574 * Test setSimpleProperty on a double property. 575 */ 576 @Test 577 public void testSetSimpleDouble() 578 { 579 double oldValue = ((Double) bean.get("doubleProperty")).doubleValue(); 580 double newValue = oldValue + 1.0; 581 bean.set("doubleProperty", new Double(newValue)); 582 assertEquals("Matched new value", newValue, ((Double) bean.get("doubleProperty")).doubleValue(), 0.005); 583 } 584 585 /** 586 * Test setSimpleProperty on a float property. 587 */ 588 @Test 589 public void testSetSimpleFloat() 590 { 591 float oldValue = ((Float) bean.get("floatProperty")).floatValue(); 592 float newValue = oldValue + (float) 1.0; 593 bean.set("floatProperty", new Float(newValue)); 594 assertEquals("Matched new value", newValue, ((Float) bean.get("floatProperty")).floatValue(), 0.005f); 595 } 596 597 /** 598 * Test setSimpleProperty on a int property. 599 */ 600 @Test 601 public void testSetSimpleInt() 602 { 603 int oldValue = ((Integer) bean.get("intProperty")).intValue(); 604 int newValue = oldValue + 1; 605 bean.set("intProperty", new Integer(newValue)); 606 assertEquals("Matched new value", newValue, ((Integer) bean.get("intProperty")).intValue()); 607 } 608 609 /** 610 * Test setSimpleProperty on a long property. 611 */ 612 @Test 613 public void testSetSimpleLong() 614 { 615 long oldValue = ((Long) bean.get("longProperty")).longValue(); 616 long newValue = oldValue + 1; 617 bean.set("longProperty", new Long(newValue)); 618 assertEquals("Matched new value", newValue, ((Long) bean.get("longProperty")).longValue()); 619 } 620 621 /** 622 * Test setSimpleProperty on a short property. 623 */ 624 @Test 625 public void testSetSimpleShort() 626 { 627 short oldValue = ((Short) bean.get("shortProperty")).shortValue(); 628 short newValue = (short) (oldValue + 1); 629 bean.set("shortProperty", new Short(newValue)); 630 assertEquals("Matched new value", newValue, ((Short) bean.get("shortProperty")).shortValue()); 631 } 632 633 /** 634 * Test setSimpleProperty on a String property. 635 */ 636 @Test 637 public void testSetSimpleString() 638 { 639 String oldValue = (String) bean.get("stringProperty"); 640 String newValue = oldValue + " Extra Value"; 641 bean.set("stringProperty", newValue); 642 assertEquals("Matched new value", newValue, bean.get("stringProperty")); 643 } 644 645 /** 646 * Tests set on a null value: should throw NPE. 647 */ 648 @Test(expected = NullPointerException.class) 649 public void testAddNullPropertyValue() 650 { 651 bean.set("nullProperty", null); 652 } 653 654 /** 655 * Test the retrieval of a non-existent property. 656 */ 657 @Test(expected = IllegalArgumentException.class) 658 public void testGetNonExistentProperty() 659 { 660 bean.get("nonexistProperty"); 661 } 662 663 /** 664 * Base for testGetDescriptorXxxxx() series of tests. 665 * 666 * @param name Name of the property to be retrieved 667 * @param type Expected class type of this property 668 */ 669 protected void testGetDescriptorBase(String name, Class<?> type) 670 { 671 DynaProperty descriptor = bean.getDynaClass().getDynaProperty(name); 672 673 assertNotNull("Failed to get descriptor", descriptor); 674 assertEquals("Got incorrect type", type, descriptor.getType()); 675 } 676 677 /** 678 * Tests whether nested properties can be accessed. 679 */ 680 @Test 681 public void testNestedPropeties() 682 { 683 ConfigurationDynaBean nested = (ConfigurationDynaBean) bean.get("mappedProperty"); 684 685 String value = (String) nested.get("key1"); 686 assertEquals("Can find first value", "First Value", value); 687 688 nested.set("key1", "undefined"); 689 assertEquals("Incorrect value returned", "undefined", bean.get("mappedProperty.key1")); 690 } 691 692 /** 693 * Tests if reading a non-indexed property using the index 694 * get method throws an IllegalArgumentException as it 695 * should. 696 */ 697 @Test(expected = IllegalArgumentException.class) 698 public void testGetNonIndexedProperties() 699 { 700 bean.get("booleanProperty", 0); 701 } 702 703 /** 704 * Tests whether accessing a non-indexed string property using the index get 705 * method causes an exception. 706 */ 707 @Test(expected = IllegalArgumentException.class) 708 public void testGetIndexedString() 709 { 710 bean.set("stringProp", "value"); 711 bean.get("stringProp", 0); 712 } 713 714 /** 715 * Tests whether an indexed access to a non-existing property causes an 716 * exception. 717 */ 718 @Test(expected = IllegalArgumentException.class) 719 public void testGetIndexedNonExisting() 720 { 721 bean.get("Non existing property", 0); 722 } 723 724 /** 725 * Tests if writing a non-indexed property using the index 726 * set method with an index > 0 throws an IllegalArgumentException as it 727 * should. 728 */ 729 @Test(expected = IllegalArgumentException.class) 730 public void testSetNonIndexedProperties() 731 { 732 bean.set("booleanProperty", 1, Boolean.TRUE); 733 } 734 }