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