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 package org.apache.commons.collections;
18 
19 import java.io.Serializable;
20 import java.lang.reflect.Method;
21 import java.util.Map;
22 
23 import junit.framework.Test;
24 import junit.textui.TestRunner;
25 
26 import org.apache.commons.collections.map.AbstractTestMap;
27 
28 /**
29  * Test cases for BeanMap
30  *
31  * @version $Revision: 646780 $ $Date: 2008-04-10 14:48:07 +0200 (Thu, 10 Apr 2008) $
32  *
33  * @author Morgan Delagrange
34  * @author Stephen Colebourne
35  */
36 public class TestBeanMap extends AbstractTestMap {
37 
TestBeanMap(String testName)38     public TestBeanMap(String testName) {
39         super(testName);
40     }
41 
main(String[] args)42     public static void main(String[] args) {
43         TestRunner.run(suite());
44     }
45 
suite()46     public static Test suite() {
47         return BulkTest.makeSuite(TestBeanMap.class);
48     }
49 
50 /*
51   note to self.  The getter and setter methods were generated by copying the
52   field declarations and using the following regular expression search and
53   replace:
54 
55   From:
56         private \(.*\) some\(.*\);
57   To:
58         public \1 getSome\2Value() {
59             return some\2;
60         }
61         public void setSome\2Value(\1 value) {
62             some\2 = value;
63         }
64 
65   Also note:  The sample keys and mappings were generated manually.
66 */
67 
68 
69     public static class BeanWithProperties implements Serializable {
70         private int someInt;
71         private long someLong;
72         private double someDouble;
73         private float someFloat;
74         private short someShort;
75         private byte someByte;
76         private char someChar;
77         private Integer someInteger;
78         private String someString;
79         private Object someObject;
80 
getSomeIntValue()81         public int getSomeIntValue() {
82             return someInt;
83         }
setSomeIntValue(int value)84         public void setSomeIntValue(int value) {
85             someInt = value;
86         }
87 
getSomeLongValue()88         public long getSomeLongValue() {
89             return someLong;
90         }
setSomeLongValue(long value)91         public void setSomeLongValue(long value) {
92             someLong = value;
93         }
94 
getSomeDoubleValue()95         public double getSomeDoubleValue() {
96             return someDouble;
97         }
setSomeDoubleValue(double value)98         public void setSomeDoubleValue(double value) {
99             someDouble = value;
100         }
101 
getSomeFloatValue()102         public float getSomeFloatValue() {
103             return someFloat;
104         }
setSomeFloatValue(float value)105         public void setSomeFloatValue(float value) {
106             someFloat = value;
107         }
108 
getSomeShortValue()109         public short getSomeShortValue() {
110             return someShort;
111         }
setSomeShortValue(short value)112         public void setSomeShortValue(short value) {
113             someShort = value;
114         }
115 
getSomeByteValue()116         public byte getSomeByteValue() {
117             return someByte;
118         }
setSomeByteValue(byte value)119         public void setSomeByteValue(byte value) {
120             someByte = value;
121         }
122 
getSomeCharValue()123         public char getSomeCharValue() {
124             return someChar;
125         }
setSomeCharValue(char value)126         public void setSomeCharValue(char value) {
127             someChar = value;
128         }
129 
getSomeStringValue()130         public String getSomeStringValue() {
131             return someString;
132         }
setSomeStringValue(String value)133         public void setSomeStringValue(String value) {
134             someString = value;
135         }
136 
getSomeIntegerValue()137         public Integer getSomeIntegerValue() {
138             return someInteger;
139         }
setSomeIntegerValue(Integer value)140         public void setSomeIntegerValue(Integer value) {
141             someInteger = value;
142         }
143 
getSomeObjectValue()144         public Object getSomeObjectValue() {
145             return someObject;
146         }
setSomeObjectValue(Object value)147         public void setSomeObjectValue(Object value) {
148             someObject = value;
149         }
150     }
151 
152     // note to self.  The Sample keys were generated by copying the field
153     // declarations and using the following regular expression search and replace:
154     //
155     // From:
156     //    private \(.*\) some\(.*\);
157     // To:
158     //    "some\2Value",
159     //
160     // Then, I manually added the "class" key, which is a property that exists for
161     // all beans (and all objects for that matter.
getSampleKeys()162     public Object[] getSampleKeys() {
163         Object[] keys = new Object[] {
164             "someIntValue",
165             "someLongValue",
166             "someDoubleValue",
167             "someFloatValue",
168             "someShortValue",
169             "someByteValue",
170             "someCharValue",
171             "someIntegerValue",
172             "someStringValue",
173             "someObjectValue",
174             "class",
175         };
176         return keys;
177     }
178 
179     /**
180      *  An object value that will be stored in the bean map as a value.  Need
181      *  to save this externally so that we can make sure the object instances
182      *  are equivalent since getSampleValues() would otherwise construct a new
183      *  and different Object each time.
184      **/
185     private Object objectInFullMap = new Object();
186 
187     // note to self: the sample values were created manually
getSampleValues()188     public Object[] getSampleValues() {
189         Object[] values = new Object[] {
190             new Integer(1234),
191             new Long(1298341928234L),
192             new Double(123423.34),
193             new Float(1213332.12f),
194             new Short((short)134),
195             new Byte((byte)10),
196             new Character('a'),
197             new Integer(1432),
198             "SomeStringValue",
199             objectInFullMap,
200             BeanWithProperties.class,
201         };
202         return values;
203     }
204 
getNewSampleValues()205     public Object[] getNewSampleValues() {
206         Object[] values = new Object[] {
207             new Integer(223),
208             new Long(23341928234L),
209             new Double(23423.34),
210             new Float(213332.12f),
211             new Short((short)234),
212             new Byte((byte)20),
213             new Character('b'),
214             new Integer(232),
215             "SomeNewStringValue",
216             new Object(),
217             null,
218         };
219         return values;
220     }
221 
222     /**
223      * Values is a dead copy in BeanMap, so refresh each time.
224      */
verifyValues()225     public void verifyValues() {
226         values = map.values();
227         super.verifyValues();
228     }
229 
230     /**
231      * The mappings in a BeanMap are fixed on the properties the underlying
232      * bean has.  Adding and removing mappings is not possible, thus this
233      * method is overridden to return false.
234      */
isPutAddSupported()235     public boolean isPutAddSupported() {
236         return false;
237     }
238 
239     /**
240      * The mappings in a BeanMap are fixed on the properties the underlying
241      * bean has.  Adding and removing mappings is not possible, thus this
242      * method is overridden to return false.
243      */
isRemoveSupported()244     public boolean isRemoveSupported() {
245         return false;
246     }
247 
makeFullMap()248     public Map makeFullMap() {
249         // note: These values must match (i.e. .equals() must return true)
250         // those returned from getSampleValues().
251         BeanWithProperties bean = new BeanWithProperties();
252         bean.setSomeIntValue(1234);
253         bean.setSomeLongValue(1298341928234L);
254         bean.setSomeDoubleValue(123423.34);
255         bean.setSomeFloatValue(1213332.12f);
256         bean.setSomeShortValue((short)134);
257         bean.setSomeByteValue((byte)10);
258         bean.setSomeCharValue('a');
259         bean.setSomeIntegerValue(new Integer(1432));
260         bean.setSomeStringValue("SomeStringValue");
261         bean.setSomeObjectValue(objectInFullMap);
262         return new BeanMap(bean);
263     }
264 
makeEmptyMap()265     public Map makeEmptyMap() {
266         return new BeanMap();
267     }
268 
ignoredTests()269     public String[] ignoredTests() {
270         // Ignore the serialization tests on collection views.
271         return new String[] {
272          "TestBeanMap.bulkTestMapEntrySet.testCanonicalEmptyCollectionExists",
273          "TestBeanMap.bulkTestMapEntrySet.testCanonicalFullCollectionExists",
274          "TestBeanMap.bulkTestMapKeySet.testCanonicalEmptyCollectionExists",
275          "TestBeanMap.bulkTestMapKeySet.testCanonicalFullCollectionExists",
276          "TestBeanMap.bulkTestMapValues.testCanonicalEmptyCollectionExists",
277          "TestBeanMap.bulkTestMapValues.testCanonicalFullCollectionExists",
278          "TestBeanMap.bulkTestMapEntrySet.testSimpleSerialization",
279          "TestBeanMap.bulkTestMapKeySet.testSimpleSerialization",
280          "TestBeanMap.bulkTestMapEntrySet.testSerializeDeserializeThenCompare",
281          "TestBeanMap.bulkTestMapKeySet.testSerializeDeserializeThenCompare"
282         };
283     }
284 
285     /**
286      * Need to override this method because the "clear()" method on the bean
287      * map just returns the bean properties to their default states.  It does
288      * not actually remove the mappings as per the map contract.  The default
289      * testClear() methods checks that the clear method throws an
290      * UnsupportedOperationException since this class is not add/remove
291      * modifiable.  In our case though, we do not always throw that exception.
292      */
testMapClear()293     public void testMapClear() {
294         //TODO: make sure a call to BeanMap.clear returns the bean to its
295         //default initialization values.
296     }
297 
298     /**
299      * Need to override this method because the "put()" method on the bean
300      * doesn't work for this type of Map.
301      */
testMapPut()302     public void testMapPut() {
303         // see testBeanMapPutAllWriteable
304     }
305 
testBeanMapClone()306     public void testBeanMapClone() {
307         BeanMap map = (BeanMap)makeFullMap();
308         try {
309             BeanMap map2 = (BeanMap)((BeanMap)map).clone();
310 
311             // make sure containsKey is working to verify the bean was cloned
312             // ok, and the read methods were properly initialized
313             Object[] keys = getSampleKeys();
314             for(int i = 0; i < keys.length; i++) {
315                 assertTrue("Cloned BeanMap should contain the same keys",
316                            map2.containsKey(keys[i]));
317             }
318         } catch (CloneNotSupportedException exception) {
319             fail("BeanMap.clone() should not throw a " +
320                  "CloneNotSupportedException when clone should succeed.");
321         }
322     }
323 
testBeanMapPutAllWriteable()324     public void testBeanMapPutAllWriteable() {
325         BeanMap map1 = (BeanMap)makeFullMap();
326         BeanMap map2 = (BeanMap)makeFullMap();
327         map2.put("someIntValue", new Integer(0));
328         map1.putAllWriteable(map2);
329         assertEquals(map1.get("someIntValue"), new Integer(0));
330     }
331 
testMethodAccessor()332     public void testMethodAccessor() throws Exception {
333         BeanMap map = (BeanMap) makeFullMap();
334         Method method = BeanWithProperties.class.getDeclaredMethod("getSomeIntegerValue", (Class[]) null);
335         assertEquals(method, map.getReadMethod("someIntegerValue"));
336     }
337 
testMethodMutator()338     public void testMethodMutator() throws Exception {
339         BeanMap map = (BeanMap) makeFullMap();
340         Method method = BeanWithProperties.class.getDeclaredMethod("setSomeIntegerValue", new Class[] {Integer.class});
341         assertEquals(method, map.getWriteMethod("someIntegerValue"));
342     }
343 
344 }
345