| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.beanutils2; |
| |
| import java.io.Serializable; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.Map; |
| |
| import org.apache.commons.beanutils2.bugs.other.Jira87BeanFactory; |
| import org.apache.commons.collections.BulkTest; |
| import org.apache.commons.collections.map.AbstractTestMap; |
| |
| import junit.framework.Test; |
| import junit.textui.TestRunner; |
| |
| /** |
| * Test cases for BeanMap |
| * |
| */ |
| @SuppressWarnings("deprecation") |
| public class BeanMapTestCase extends AbstractTestMap { |
| |
| public BeanMapTestCase(final String testName) { |
| super(testName); |
| } |
| |
| public static void main(final String[] args) { |
| TestRunner.run(suite()); |
| } |
| |
| public static Test suite() { |
| return BulkTest.makeSuite(BeanMapTestCase.class); |
| } |
| |
| /* |
| note to self. The getter and setter methods were generated by copying the |
| field declarations and using the following regular expression search and |
| replace: |
| |
| From: |
| private \(.*\) some\(.*\); |
| To: |
| public \1 getSome\2Value() { |
| return some\2; |
| } |
| public void setSome\2Value(\1 value) { |
| some\2 = value; |
| } |
| |
| Also note: The sample keys and mappings were generated manually. |
| */ |
| |
| |
| public static class BeanWithProperties implements Serializable { |
| private int someInt; |
| private long someLong; |
| private double someDouble; |
| private float someFloat; |
| private short someShort; |
| private byte someByte; |
| private char someChar; |
| private Integer someInteger; |
| private String someString; |
| private Object someObject; |
| |
| public int getSomeIntValue() { |
| return someInt; |
| } |
| public void setSomeIntValue(final int value) { |
| someInt = value; |
| } |
| |
| public long getSomeLongValue() { |
| return someLong; |
| } |
| public void setSomeLongValue(final long value) { |
| someLong = value; |
| } |
| |
| public double getSomeDoubleValue() { |
| return someDouble; |
| } |
| public void setSomeDoubleValue(final double value) { |
| someDouble = value; |
| } |
| |
| public float getSomeFloatValue() { |
| return someFloat; |
| } |
| public void setSomeFloatValue(final float value) { |
| someFloat = value; |
| } |
| |
| public short getSomeShortValue() { |
| return someShort; |
| } |
| public void setSomeShortValue(final short value) { |
| someShort = value; |
| } |
| |
| public byte getSomeByteValue() { |
| return someByte; |
| } |
| public void setSomeByteValue(final byte value) { |
| someByte = value; |
| } |
| |
| public char getSomeCharValue() { |
| return someChar; |
| } |
| public void setSomeCharValue(final char value) { |
| someChar = value; |
| } |
| |
| public String getSomeStringValue() { |
| return someString; |
| } |
| public void setSomeStringValue(final String value) { |
| someString = value; |
| } |
| |
| public Integer getSomeIntegerValue() { |
| return someInteger; |
| } |
| public void setSomeIntegerValue(final Integer value) { |
| someInteger = value; |
| } |
| |
| public Object getSomeObjectValue() { |
| return someObject; |
| } |
| public void setSomeObjectValue(final Object value) { |
| someObject = value; |
| } |
| } |
| |
| public static class BeanThrowingExceptions extends BeanWithProperties { |
| private static final long serialVersionUID = 1L; |
| public void setValueThrowingException(final String value) { |
| throw new TestException(); |
| } |
| public String getValueThrowingException() { |
| throw new TestException(); |
| } |
| } |
| |
| /** |
| * Exception for testing exception handling. |
| */ |
| public static class TestException extends RuntimeException { |
| private static final long serialVersionUID = 1L; |
| } |
| |
| // note to self. The Sample keys were generated by copying the field |
| // declarations and using the following regular expression search and replace: |
| // |
| // From: |
| // private \(.*\) some\(.*\); |
| // To: |
| // "some\2Value", |
| // |
| // Then, I manually added the "class" key, which is a property that exists for |
| // all beans (and all objects for that matter. |
| @Override |
| public Object[] getSampleKeys() { |
| final Object[] keys = new Object[] { |
| "someIntValue", |
| "someLongValue", |
| "someDoubleValue", |
| "someFloatValue", |
| "someShortValue", |
| "someByteValue", |
| "someCharValue", |
| "someIntegerValue", |
| "someStringValue", |
| "someObjectValue", |
| "class", |
| }; |
| return keys; |
| } |
| |
| /** |
| * An object value that will be stored in the bean map as a value. Need |
| * to save this externally so that we can make sure the object instances |
| * are equivalent since getSampleValues() would otherwise construct a new |
| * and different Object each time. |
| **/ |
| private final Object objectInFullMap = new Object(); |
| |
| // note to self: the sample values were created manually |
| @Override |
| public Object[] getSampleValues() { |
| final Object[] values = new Object[] { |
| new Integer(1234), |
| new Long(1298341928234L), |
| new Double(123423.34), |
| new Float(1213332.12f), |
| new Short((short)134), |
| new Byte((byte)10), |
| new Character('a'), |
| new Integer(1432), |
| "SomeStringValue", |
| objectInFullMap, |
| BeanWithProperties.class, |
| }; |
| return values; |
| } |
| |
| @Override |
| public Object[] getNewSampleValues() { |
| final Object[] values = new Object[] { |
| new Integer(223), |
| new Long(23341928234L), |
| new Double(23423.34), |
| new Float(213332.12f), |
| new Short((short)234), |
| new Byte((byte)20), |
| new Character('b'), |
| new Integer(232), |
| "SomeNewStringValue", |
| new Object(), |
| null, |
| }; |
| return values; |
| } |
| |
| /** |
| * Values is a dead copy in BeanMap, so refresh each time. |
| */ |
| @Override |
| public void verifyValues() { |
| values = map.values(); |
| super.verifyValues(); |
| } |
| |
| /** |
| * The mappings in a BeanMap are fixed on the properties the underlying |
| * bean has. Adding and removing mappings is not possible, thus this |
| * method is overridden to return false. |
| */ |
| @Override |
| public boolean isPutAddSupported() { |
| return false; |
| } |
| |
| /** |
| * The mappings in a BeanMap are fixed on the properties the underlying |
| * bean has. Adding and removing mappings is not possible, thus this |
| * method is overridden to return false. |
| */ |
| @Override |
| public boolean isRemoveSupported() { |
| return false; |
| } |
| |
| @Override |
| public Map<Object, Object> makeFullMap() { |
| // note: These values must match (i.e. .equals() must return true) |
| // those returned from getSampleValues(). |
| final BeanWithProperties bean = new BeanWithProperties(); |
| bean.setSomeIntValue(1234); |
| bean.setSomeLongValue(1298341928234L); |
| bean.setSomeDoubleValue(123423.34); |
| bean.setSomeFloatValue(1213332.12f); |
| bean.setSomeShortValue((short)134); |
| bean.setSomeByteValue((byte)10); |
| bean.setSomeCharValue('a'); |
| bean.setSomeIntegerValue(new Integer(1432)); |
| bean.setSomeStringValue("SomeStringValue"); |
| bean.setSomeObjectValue(objectInFullMap); |
| return new BeanMap(bean); |
| } |
| |
| @Override |
| public Map<Object, Object> makeEmptyMap() { |
| return new BeanMap(); |
| } |
| |
| @Override |
| public String[] ignoredTests() { |
| // Ignore the serialization tests on collection views. |
| return new String[] { |
| "TestBeanMap.bulkTestMapEntrySet.testCanonicalEmptyCollectionExists", |
| "TestBeanMap.bulkTestMapEntrySet.testCanonicalFullCollectionExists", |
| "TestBeanMap.bulkTestMapKeySet.testCanonicalEmptyCollectionExists", |
| "TestBeanMap.bulkTestMapKeySet.testCanonicalFullCollectionExists", |
| "TestBeanMap.bulkTestMapValues.testCanonicalEmptyCollectionExists", |
| "TestBeanMap.bulkTestMapValues.testCanonicalFullCollectionExists", |
| "TestBeanMap.bulkTestMapEntrySet.testSimpleSerialization", |
| "TestBeanMap.bulkTestMapKeySet.testSimpleSerialization", |
| "TestBeanMap.bulkTestMapEntrySet.testSerializeDeserializeThenCompare", |
| "TestBeanMap.bulkTestMapKeySet.testSerializeDeserializeThenCompare" |
| }; |
| } |
| |
| /** |
| * Need to override this method because the "clear()" method on the bean |
| * map just returns the bean properties to their default states. It does |
| * not actually remove the mappings as per the map contract. The default |
| * testClear() methods checks that the clear method throws an |
| * UnsupportedOperationException since this class is not add/remove |
| * modifiable. In our case though, we do not always throw that exception. |
| */ |
| @Override |
| public void testMapClear() { |
| //TODO: make sure a call to BeanMap.clear returns the bean to its |
| //default initialization values. |
| } |
| |
| /** |
| * Need to override this method because the "put()" method on the bean |
| * doesn't work for this type of Map. |
| */ |
| @Override |
| public void testMapPut() { |
| // see testBeanMapPutAllWriteable |
| } |
| |
| public void testBeanMapClone() { |
| final BeanMap map = (BeanMap)makeFullMap(); |
| try { |
| final BeanMap map2 = (BeanMap)map.clone(); |
| |
| // make sure containsKey is working to verify the bean was cloned |
| // ok, and the read methods were properly initialized |
| final Object[] keys = getSampleKeys(); |
| for (final Object key : keys) { |
| assertTrue("Cloned BeanMap should contain the same keys", |
| map2.containsKey(key)); |
| } |
| } catch (final CloneNotSupportedException exception) { |
| fail("BeanMap.clone() should not throw a " + |
| "CloneNotSupportedException when clone should succeed."); |
| } |
| } |
| |
| public void testBeanMapPutAllWriteable() { |
| final BeanMap map1 = (BeanMap)makeFullMap(); |
| final BeanMap map2 = (BeanMap)makeFullMap(); |
| map2.put("someIntValue", new Integer(0)); |
| map1.putAllWriteable(map2); |
| assertEquals(map1.get("someIntValue"), new Integer(0)); |
| } |
| |
| public void testMethodAccessor() throws Exception { |
| final BeanMap map = (BeanMap) makeFullMap(); |
| final Method method = BeanWithProperties.class.getDeclaredMethod("getSomeIntegerValue"); |
| assertEquals(method, map.getReadMethod("someIntegerValue")); |
| } |
| |
| public void testMethodMutator() throws Exception { |
| final BeanMap map = (BeanMap) makeFullMap(); |
| final Method method = BeanWithProperties.class.getDeclaredMethod("setSomeIntegerValue", new Class[] {Integer.class}); |
| assertEquals(method, map.getWriteMethod("someIntegerValue")); |
| } |
| |
| /** |
| * Test the default transformers using the getTypeTransformer() method |
| */ |
| public void testGetTypeTransformerMethod() { |
| final BeanMap beanMap = new BeanMap(); |
| assertEquals("Boolean.TYPE", Boolean.TRUE, beanMap.getTypeTransformer(Boolean.TYPE).transform("true")); |
| assertEquals("Character.TYPE", new Character('B'), beanMap.getTypeTransformer(Character.TYPE).transform("BCD")); |
| assertEquals("Byte.TYPE", new Byte((byte)1), beanMap.getTypeTransformer(Byte.TYPE).transform("1")); |
| assertEquals("Short.TYPE", new Short((short)2), beanMap.getTypeTransformer(Short.TYPE).transform("2")); |
| assertEquals("Integer.TYPE", new Integer(3), beanMap.getTypeTransformer(Integer.TYPE).transform("3")); |
| assertEquals("Long.TYPE", new Long(4), beanMap.getTypeTransformer(Long.TYPE).transform("4")); |
| assertEquals("Float.TYPE", new Float("5"), beanMap.getTypeTransformer(Float.TYPE).transform("5")); |
| assertEquals("Double.TYPE", new Double("6"), beanMap.getTypeTransformer(Double.TYPE).transform("6")); |
| } |
| |
| /** |
| * Test that the cause of exception thrown by a clone() is initialised. |
| */ |
| public void testExceptionThrowFromClone() { |
| |
| if (BeanUtilsTestCase.isPre14JVM()) { |
| System.out.println("testExceptionThrowFromClone() skipped on pre 1.4 JVM"); |
| return; |
| } |
| |
| // Test cloning a non-public bean (instantiation exception) |
| try { |
| final Object bean = Jira87BeanFactory.createMappedPropertyBean(); |
| final BeanMap map = new BeanMap(bean); |
| map.clone(); |
| fail("Non-public bean clone() - expected CloneNotSupportedException"); |
| } catch (final CloneNotSupportedException e) { |
| Throwable cause = null; |
| try { |
| cause = (Throwable)PropertyUtils.getProperty(e, "cause"); |
| } catch (final Exception e2) { |
| fail("Non-public bean - retrieving the cause threw " + e2); |
| } |
| assertNotNull("Non-public bean cause null", cause); |
| assertEquals("Non-public bean cause", IllegalAccessException.class, cause.getClass()); |
| } |
| |
| // Test cloning a bean that throws exception |
| try { |
| final BeanMap map = new BeanMap(new BeanThrowingExceptions()); |
| map.clone(); |
| fail("Setter Exception clone() - expected CloneNotSupportedException"); |
| } catch (final CloneNotSupportedException e) { |
| Throwable cause = null; |
| try { |
| cause = (Throwable)PropertyUtils.getProperty(e, "cause"); |
| } catch (final Exception e2) { |
| fail("Setter Exception - retrieving the cause threw " + e2); |
| } |
| assertNotNull("Setter Exception cause null", cause); |
| assertEquals("Setter Exception cause", IllegalArgumentException.class, cause.getClass()); |
| } |
| } |
| |
| /** |
| * Test that the cause of exception thrown by clear() is initialised. |
| */ |
| public void testExceptionThrowFromClear() { |
| |
| if (BeanUtilsTestCase.isPre14JVM()) { |
| System.out.println("testExceptionThrowFromClear() skipped on pre 1.4 JVM"); |
| return; |
| } |
| |
| try { |
| final Object bean = Jira87BeanFactory.createMappedPropertyBean(); |
| final BeanMap map = new BeanMap(bean); |
| map.clear(); |
| fail("clear() - expected UnsupportedOperationException"); |
| } catch (final UnsupportedOperationException e) { |
| Throwable cause = null; |
| try { |
| cause = (Throwable)PropertyUtils.getProperty(e, "cause"); |
| } catch (final Exception e2) { |
| fail("Retrieving the cause threw " + e2); |
| } |
| assertNotNull("Cause null", cause); |
| assertEquals("Cause", IllegalAccessException.class, cause.getClass()); |
| } |
| } |
| |
| /** |
| * Test that the cause of exception thrown by put() is initialized. |
| */ |
| public void testExceptionThrowFromPut() { |
| |
| if (BeanUtilsTestCase.isPre14JVM()) { |
| System.out.println("testExceptionThrowFromPut() skipped on pre 1.4 JVM"); |
| return; |
| } |
| |
| try { |
| final Map<Object, Object> map = new BeanMap(new BeanThrowingExceptions()); |
| map.put("valueThrowingException", "value"); |
| fail("Setter exception - expected IllegalArgumentException"); |
| } catch (final IllegalArgumentException e) { |
| Throwable cause1 = null; |
| Throwable cause2 = null; |
| try { |
| cause1 = (Throwable)PropertyUtils.getProperty(e, "cause"); |
| cause2 = (Throwable)PropertyUtils.getProperty(e, "cause.cause"); |
| } catch (final Exception e2) { |
| fail("Setter exception - retrieving the cause threw " + e2); |
| } |
| assertNotNull("Setter exception cause 1 null", cause1); |
| assertEquals("Setter exception cause 1", InvocationTargetException.class, cause1.getClass()); |
| assertNotNull("Setter exception cause 2 null", cause2); |
| assertEquals("Setter exception cause 2", TestException.class, cause2.getClass()); |
| } |
| } |
| } |