View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.configuration.beanutils;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertNotNull;
23  import static org.junit.Assert.assertNull;
24  import static org.junit.Assert.assertTrue;
25  import static org.junit.Assert.fail;
26  
27  import java.util.Arrays;
28  import java.util.HashMap;
29  import java.util.List;
30  
31  import junitx.framework.ObjectAssert;
32  
33  import org.apache.commons.beanutils.DynaProperty;
34  import org.apache.commons.configuration.BaseConfiguration;
35  import org.apache.commons.configuration.Configuration;
36  import org.apache.commons.configuration.MapConfiguration;
37  import org.junit.Before;
38  import org.junit.Test;
39  
40  /**
41   * <p>Test Case for the <code>ConfigurationDynaBean</code> implementation class.
42   * These tests were based on the ones in <code>BasicDynaBeanTestCase</code>
43   * because the two classes provide similar levels of functionality.</p>
44   *
45   * @author <a href="mailto:ricardo.gladwell@btinternet.com">Ricardo Gladwell</a>
46   * @version $Id: TestConfigurationDynaBean.java 1225349 2011-12-28 21:36:59Z oheger $
47   */
48  public class TestConfigurationDynaBean
49  {
50      /**
51       * The basic test bean for each test.
52       */
53      private ConfigurationDynaBean bean;
54  
55      /**
56       * The set of property names we expect to have returned when calling
57       * <code>getDynaProperties()</code>.  You should update this list
58       * when new properties are added to TestBean.
59       */
60      String[] properties = {
61              "booleanProperty",
62              "booleanSecond",
63              "doubleProperty",
64              "floatProperty",
65              "intProperty",
66              "longProperty",
67              "mappedProperty.key1",
68              "mappedProperty.key2",
69              "mappedProperty.key3",
70              "mappedIntProperty.key1",
71              "shortProperty",
72              "stringProperty",
73              "byteProperty",
74              "charProperty"
75      };
76  
77      Object[] values = {
78              Boolean.TRUE,
79              Boolean.TRUE,
80              new Double(Double.MAX_VALUE),
81              new Float(Float.MAX_VALUE),
82              new Integer(Integer.MAX_VALUE),
83              new Long(Long.MAX_VALUE),
84              "First Value",
85              "Second Value",
86              "Third Value",
87              new Integer(Integer.MAX_VALUE),
88              new Short(Short.MAX_VALUE),
89              "This is a string",
90              new Byte(Byte.MAX_VALUE),
91              new Character(Character.MAX_VALUE)
92      };
93  
94      int[] intArray = {0, 10, 20, 30, 40};
95      boolean[] booleanArray = {true, false, true, false, true};
96      char[] charArray = {'a', 'b', 'c', 'd', 'e'};
97      byte[] byteArray = {0, 10, 20, 30, 40};
98      long[] longArray = {0, 10, 20, 30, 40};
99      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 &gt; 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 }