1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.beanutils2;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertNotNull;
21 import static org.junit.jupiter.api.Assertions.assertTrue;
22 import static org.junit.jupiter.api.Assertions.fail;
23 import static org.junit.jupiter.api.Assumptions.assumeFalse;
24
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.Method;
27 import java.util.Map;
28 import java.util.function.Function;
29
30 import org.apache.commons.beanutils2.bugs.other.Jira87BeanFactory;
31 import org.apache.commons.collections4.map.AbstractMapTest;
32
33
34
35
36 public class BeanMapTest extends AbstractMapTest<BeanMap, String, Object> {
37
38 public static class BeanThrowingExceptions extends BeanWithProperties {
39
40 public String getValueThrowingException() {
41 throw new TestException();
42 }
43
44 public void setValueThrowingException(final String value) {
45 throw new TestException();
46 }
47 }
48
49 public static class BeanWithProperties {
50 private int someInt;
51 private long someLong;
52 private double someDouble;
53 private float someFloat;
54 private short someShort;
55 private byte someByte;
56 private char someChar;
57 private Integer someInteger;
58 private String someString;
59 private Object someObject;
60
61 public byte getSomeByteValue() {
62 return someByte;
63 }
64
65 public char getSomeCharValue() {
66 return someChar;
67 }
68
69 public double getSomeDoubleValue() {
70 return someDouble;
71 }
72
73 public float getSomeFloatValue() {
74 return someFloat;
75 }
76
77 public Integer getSomeIntegerValue() {
78 return someInteger;
79 }
80
81 public int getSomeIntValue() {
82 return someInt;
83 }
84
85 public long getSomeLongValue() {
86 return someLong;
87 }
88
89 public Object getSomeObjectValue() {
90 return someObject;
91 }
92
93 public short getSomeShortValue() {
94 return someShort;
95 }
96
97 public String getSomeStringValue() {
98 return someString;
99 }
100
101 public void setSomeByteValue(final byte value) {
102 someByte = value;
103 }
104
105 public void setSomeCharValue(final char value) {
106 someChar = value;
107 }
108
109 public void setSomeDoubleValue(final double value) {
110 someDouble = value;
111 }
112
113 public void setSomeFloatValue(final float value) {
114 someFloat = value;
115 }
116
117 public void setSomeIntegerValue(final Integer value) {
118 someInteger = value;
119 }
120
121 public void setSomeIntValue(final int value) {
122 someInt = value;
123 }
124
125 public void setSomeLongValue(final long value) {
126 someLong = value;
127 }
128
129 public void setSomeObjectValue(final Object value) {
130 someObject = value;
131 }
132
133 public void setSomeShortValue(final short value) {
134 someShort = value;
135 }
136
137 public void setSomeStringValue(final String value) {
138 someString = value;
139 }
140 }
141
142
143
144
145 public static class TestException extends RuntimeException {
146 private static final long serialVersionUID = 1L;
147 }
148
149
150
151
152
153 private final Object objectInFullMap = new Object();
154
155
156
157
158
159
160
161
162
163 public BeanMapTest() {
164 }
165
166 @Override
167 protected Object computeIfAbsent(final String key, final Function<? super String, ? extends Object> mappingFunction) {
168 if (getMap().getBean() == null) {
169
170 throw new IllegalArgumentException();
171 }
172 return super.computeIfAbsent(key, mappingFunction);
173 }
174
175 @Override
176 public Object[] getNewSampleValues() {
177 final Object[] values = { Integer.valueOf(223), Long.valueOf(23341928234L), Double.valueOf(23423.34), Float.valueOf(213332.12f),
178 Short.valueOf((short) 234), Byte.valueOf((byte) 20), Character.valueOf('b'), Integer.valueOf(232), "SomeNewStringValue", new Object(), null, };
179 return values;
180 }
181
182
183
184
185
186
187
188
189
190
191
192 @Override
193 public String[] getSampleKeys() {
194 final String[] keys = { "someIntValue", "someLongValue", "someDoubleValue", "someFloatValue", "someShortValue", "someByteValue", "someCharValue",
195 "someIntegerValue", "someStringValue", "someObjectValue", "class", };
196 return keys;
197 }
198
199
200 @Override
201 public Object[] getSampleValues() {
202 final Object[] values = { Integer.valueOf(1234), Long.valueOf(1298341928234L), Double.valueOf(123423.34), Float.valueOf(1213332.12f),
203 Short.valueOf((short) 134), Byte.valueOf((byte) 10), Character.valueOf('a'), Integer.valueOf(1432), "SomeStringValue", objectInFullMap,
204 BeanWithProperties.class, };
205 return values;
206 }
207
208 public String[] ignoredTests() {
209
210 return new String[] { "TestBeanMap.bulkTestMapEntrySet.testCanonicalEmptyCollectionExists",
211 "TestBeanMap.bulkTestMapEntrySet.testCanonicalFullCollectionExists", "TestBeanMap.bulkTestMapKeySet.testCanonicalEmptyCollectionExists",
212 "TestBeanMap.bulkTestMapKeySet.testCanonicalFullCollectionExists", "TestBeanMap.bulkTestMapValues.testCanonicalEmptyCollectionExists",
213 "TestBeanMap.bulkTestMapValues.testCanonicalFullCollectionExists", "TestBeanMap.bulkTestMapEntrySet.testSimpleSerialization",
214 "TestBeanMap.bulkTestMapKeySet.testSimpleSerialization", "TestBeanMap.bulkTestMapEntrySet.testSerializeDeserializeThenCompare",
215 "TestBeanMap.bulkTestMapKeySet.testSerializeDeserializeThenCompare" };
216 }
217
218
219
220
221
222 @Override
223 public boolean isPutAddSupported() {
224 return false;
225 }
226
227
228
229
230
231 @Override
232 public boolean isRemoveSupported() {
233 return false;
234 }
235
236 @Override
237 public BeanMap makeFullMap() {
238
239
240 final BeanWithProperties bean = new BeanWithProperties();
241 bean.setSomeIntValue(1234);
242 bean.setSomeLongValue(1298341928234L);
243 bean.setSomeDoubleValue(123423.34);
244 bean.setSomeFloatValue(1213332.12f);
245 bean.setSomeShortValue((short) 134);
246 bean.setSomeByteValue((byte) 10);
247 bean.setSomeCharValue('a');
248 bean.setSomeIntegerValue(Integer.valueOf(1432));
249 bean.setSomeStringValue("SomeStringValue");
250 bean.setSomeObjectValue(objectInFullMap);
251 return new BeanMap(bean);
252 }
253
254 @Override
255 public BeanMap makeObject() {
256 return new BeanMap();
257 }
258
259 @Override
260 protected Object putIfAbsent(final String key, final Object value) {
261 if (getMap().getBean() == null) {
262
263 throw new IllegalArgumentException();
264 }
265 return super.putIfAbsent(key, value);
266 }
267
268 public void testBeanMapClone() {
269 final BeanMap map = (BeanMap) makeFullMap();
270 try {
271 final BeanMap map2 = (BeanMap) map.clone();
272
273
274
275 final Object[] keys = getSampleKeys();
276 for (final Object key : keys) {
277 assertTrue(map2.containsKey(key), "Cloned BeanMap should contain the same keys");
278 }
279 } catch (final CloneNotSupportedException exception) {
280 fail("BeanMap.clone() should not throw a " + "CloneNotSupportedException when clone should succeed.");
281 }
282 }
283
284 public void testBeanMapPutAllWriteable() {
285 final BeanMap map1 = (BeanMap) makeFullMap();
286 final BeanMap map2 = (BeanMap) makeFullMap();
287 map2.put("someIntValue", Integer.valueOf(0));
288 map1.putAllWriteable(map2);
289 assertEquals(map1.get("someIntValue"), Integer.valueOf(0));
290 }
291
292
293
294
295 public void testExceptionThrowFromClear() {
296 try {
297 final Object bean = Jira87BeanFactory.createMappedPropertyBean();
298 final BeanMap map = new BeanMap(bean);
299 map.clear();
300 fail("clear() - expected UnsupportedOperationException");
301 } catch (final UnsupportedOperationException e) {
302 Throwable cause = null;
303 try {
304 cause = (Throwable) PropertyUtils.getProperty(e, "cause");
305 } catch (final Exception e2) {
306 fail("Retrieving the cause threw " + e2);
307 }
308 assertNotNull(cause, "Cause null");
309 assertEquals(IllegalAccessException.class, cause.getClass(), "Cause");
310 }
311 }
312
313
314
315
316 public void testExceptionThrowFromClone() {
317
318 try {
319 final Object bean = Jira87BeanFactory.createMappedPropertyBean();
320 final BeanMap map = new BeanMap(bean);
321 map.clone();
322 fail("Non-public bean clone() - expected CloneNotSupportedException");
323 } catch (final CloneNotSupportedException e) {
324 Throwable cause = null;
325 try {
326 cause = (Throwable) PropertyUtils.getProperty(e, "cause");
327 } catch (final Exception e2) {
328 fail("Non-public bean - retrieving the cause threw " + e2);
329 }
330 assertNotNull(cause, "Non-public bean cause null");
331 assertEquals(IllegalAccessException.class, cause.getClass(), "Non-public bean cause");
332 }
333
334
335 try {
336 final BeanMap map = new BeanMap(new BeanThrowingExceptions());
337 map.clone();
338 fail("Setter Exception clone() - expected CloneNotSupportedException");
339 } catch (final CloneNotSupportedException e) {
340 Throwable cause = null;
341 try {
342 cause = (Throwable) PropertyUtils.getProperty(e, "cause");
343 } catch (final Exception e2) {
344 fail("Setter Exception - retrieving the cause threw " + e2);
345 }
346 assertNotNull(cause, "Setter Exception cause null");
347 assertEquals(IllegalArgumentException.class, cause.getClass(), "Setter Exception cause");
348 }
349 }
350
351
352
353
354 public void testExceptionThrowFromPut() {
355 try {
356 final Map<String, Object> map = new BeanMap(new BeanThrowingExceptions());
357 map.put("valueThrowingException", "value");
358 fail("Setter exception - expected IllegalArgumentException");
359 } catch (final IllegalArgumentException e) {
360 Throwable cause1 = null;
361 Throwable cause2 = null;
362 try {
363 cause1 = (Throwable) PropertyUtils.getProperty(e, "cause");
364 cause2 = (Throwable) PropertyUtils.getProperty(e, "cause.cause");
365 } catch (final Exception e2) {
366 fail("Setter exception - retrieving the cause threw " + e2);
367 }
368 assertNotNull(cause1, "Setter exception cause 1 null");
369 assertEquals(InvocationTargetException.class, cause1.getClass(), "Setter exception cause 1");
370 assertNotNull(cause2, "Setter exception cause 2 null");
371 assertEquals(TestException.class, cause2.getClass(), "Setter exception cause 2");
372 }
373 }
374
375
376
377
378 public void testGetTypeTransformerMethod() {
379 final BeanMap beanMap = new BeanMap();
380 assertEquals(Boolean.TRUE, beanMap.getTypeTransformer(Boolean.TYPE).apply("true"), "Boolean.TYPE");
381 assertEquals(Character.valueOf('B'), beanMap.getTypeTransformer(Character.TYPE).apply("BCD"), "Character.TYPE");
382 assertEquals(Byte.valueOf((byte) 1), beanMap.getTypeTransformer(Byte.TYPE).apply("1"), "Byte.TYPE");
383 assertEquals(Short.valueOf((short) 2), beanMap.getTypeTransformer(Short.TYPE).apply("2"), "Short.TYPE");
384 assertEquals(Integer.valueOf(3), beanMap.getTypeTransformer(Integer.TYPE).apply("3"), "Integer.TYPE");
385 assertEquals(Long.valueOf(4), beanMap.getTypeTransformer(Long.TYPE).apply("4"), "Long.TYPE");
386 assertEquals(Float.valueOf("5"), beanMap.getTypeTransformer(Float.TYPE).apply("5"), "Float.TYPE");
387 assertEquals(Double.valueOf("6"), beanMap.getTypeTransformer(Double.TYPE).apply("6"), "Double.TYPE");
388 }
389
390
391
392
393
394
395 @Override
396 public void testMapClear() {
397
398
399 }
400
401
402
403
404 @Override
405 public void testMapPut() {
406
407 }
408
409 public void testMethodAccessor() throws Exception {
410 final BeanMap map = (BeanMap) makeFullMap();
411 final Method method = BeanWithProperties.class.getDeclaredMethod("getSomeIntegerValue");
412 assertEquals(method, map.getReadMethod("someIntegerValue"));
413 }
414
415 public void testMethodMutator() throws Exception {
416 final BeanMap map = (BeanMap) makeFullMap();
417 final Method method = BeanWithProperties.class.getDeclaredMethod("setSomeIntegerValue", Integer.class);
418 assertEquals(method, map.getWriteMethod("someIntegerValue"));
419 }
420
421 @Override
422 public void testReplaceAll() {
423 assumeFalse(getMap().keySet().stream().anyMatch(k -> getMap().getWriteMethod(k) == null));
424 super.testReplaceAll();
425 }
426
427
428
429
430 @Override
431 public void verifyValues() {
432 values = map.values();
433 super.verifyValues();
434 }
435 }