xref: /aosp_15_r20/external/jackson-databind/src/test/java/com/fasterxml/jackson/databind/util/ClassUtilTest.java (revision 0ed15c778abdfe0f5f51f6133673e1619d6e56e4)
1 package com.fasterxml.jackson.databind.util;
2 
3 import java.io.*;
4 import java.util.*;
5 
6 import com.fasterxml.jackson.core.JsonFactory;
7 import com.fasterxml.jackson.core.JsonGenerator;
8 import com.fasterxml.jackson.core.type.TypeReference;
9 
10 import com.fasterxml.jackson.databind.BaseMapTest;
11 import com.fasterxml.jackson.databind.JavaType;
12 import com.fasterxml.jackson.databind.type.TypeFactory;
13 import com.fasterxml.jackson.databind.util.ClassUtil;
14 
15 public class ClassUtilTest extends BaseMapTest
16 {
17     /*
18     /**********************************************************
19     /* Test classes, enums
20     /**********************************************************
21      */
22 
23     /* Test classes and interfaces needed for testing class util
24      * methods
25      */
26     static abstract class BaseClass implements Comparable<BaseClass>,
27         BaseInt
28     {
BaseClass(String str)29         BaseClass(String str) { }
30     }
31 
32     interface BaseInt { }
33 
34     interface SubInt extends BaseInt { }
35 
36     enum TestEnum { A; }
37 
38     abstract class InnerNonStatic { }
39 
40     static class Inner {
Inner()41         protected Inner() {
42             throw new IllegalStateException("test");
43         }
44     }
45 
46     static abstract class SubClass
47         extends BaseClass
48         implements SubInt {
SubClass()49         SubClass() { super("x"); }
50     }
51 
52     static abstract class ConcreteAndAbstract {
a()53         public abstract void a();
54 
c()55         public void c() { }
56     }
57 
58     static class MaybeGetters {
staticMethod()59         public static void staticMethod() { }
60 
voidMethod()61         public void voidMethod() { }
62 
getMethod()63         public int getMethod() { return 1; }
setMethod(int x)64         public void setMethod(int x) { }
65     }
66 
67     /*
68     /**********************************************************
69     /* Test methods
70     /**********************************************************
71      */
72 
testIsConcrete()73     public void testIsConcrete() throws Exception
74     {
75         assertTrue(ClassUtil.isConcrete(getClass()));
76         assertFalse(ClassUtil.isConcrete(BaseClass.class));
77         assertFalse(ClassUtil.isConcrete(BaseInt.class));
78 
79         assertFalse(ClassUtil.isConcrete(ConcreteAndAbstract.class.getDeclaredMethod("a")));
80         assertTrue(ClassUtil.isConcrete(ConcreteAndAbstract.class.getDeclaredMethod("c")));
81     }
82 
testCanBeABeanType()83     public void testCanBeABeanType()
84     {
85         assertEquals("annotation", ClassUtil.canBeABeanType(java.lang.annotation.Retention.class));
86         assertEquals("array", ClassUtil.canBeABeanType(String[].class));
87         assertEquals("enum", ClassUtil.canBeABeanType(TestEnum.class));
88         assertEquals("primitive", ClassUtil.canBeABeanType(Integer.TYPE));
89         assertNull(ClassUtil.canBeABeanType(Integer.class));
90 
91         assertEquals("non-static member class", ClassUtil.isLocalType(InnerNonStatic.class, false));
92         assertNull(ClassUtil.isLocalType(Integer.class, false));
93     }
94 
testExceptionHelpers()95     public void testExceptionHelpers()
96     {
97         RuntimeException e = new RuntimeException("test");
98         RuntimeException wrapper = new RuntimeException(e);
99 
100         assertSame(e, ClassUtil.getRootCause(wrapper));
101 
102         try {
103             ClassUtil.throwAsIAE(e);
104             fail("Shouldn't get this far");
105         } catch (RuntimeException e2) {
106             assertSame(e, e2);
107         }
108 
109         Error err = new Error();
110         try {
111             ClassUtil.throwAsIAE(err);
112             fail("Shouldn't get this far");
113         } catch (Error errAct) {
114             assertSame(err, errAct);
115         }
116 
117         try {
118             ClassUtil.unwrapAndThrowAsIAE(wrapper);
119             fail("Shouldn't get this far");
120         } catch (RuntimeException e2) {
121             assertSame(e, e2);
122         }
123     }
124 
testFailedCreateInstance()125     public void testFailedCreateInstance()
126     {
127         try {
128             ClassUtil.createInstance(BaseClass.class, true);
129         } catch (IllegalArgumentException e) {
130             verifyException(e, "has no default");
131         }
132 
133         try {
134             // false means ctor would need to be public
135             ClassUtil.createInstance(Inner.class, false);
136         } catch (IllegalArgumentException e) {
137             verifyException(e, "is not accessible");
138         }
139 
140         // and finally, check that we'll get expected exception...
141         try {
142             ClassUtil.createInstance(Inner.class, true);
143         } catch (IllegalStateException e) {
144             verifyException(e, "test");
145         }
146     }
147 
testPrimitiveDefaultValue()148     public void testPrimitiveDefaultValue()
149     {
150         assertEquals(Integer.valueOf(0), ClassUtil.defaultValue(Integer.TYPE));
151         assertEquals(Long.valueOf(0L), ClassUtil.defaultValue(Long.TYPE));
152         assertEquals(Character.valueOf('\0'), ClassUtil.defaultValue(Character.TYPE));
153         assertEquals(Short.valueOf((short) 0), ClassUtil.defaultValue(Short.TYPE));
154         assertEquals(Byte.valueOf((byte) 0), ClassUtil.defaultValue(Byte.TYPE));
155 
156         assertEquals(Double.valueOf(0.0), ClassUtil.defaultValue(Double.TYPE));
157         assertEquals(Float.valueOf(0.0f), ClassUtil.defaultValue(Float.TYPE));
158 
159         assertEquals(Boolean.FALSE, ClassUtil.defaultValue(Boolean.TYPE));
160 
161         try {
162             ClassUtil.defaultValue(String.class);
163         } catch (IllegalArgumentException e) {
164             verifyException(e, "String is not a primitive type");
165         }
166     }
167 
testPrimitiveWrapperType()168     public void testPrimitiveWrapperType()
169     {
170         assertEquals(Byte.class, ClassUtil.wrapperType(Byte.TYPE));
171         assertEquals(Short.class, ClassUtil.wrapperType(Short.TYPE));
172         assertEquals(Character.class, ClassUtil.wrapperType(Character.TYPE));
173         assertEquals(Integer.class, ClassUtil.wrapperType(Integer.TYPE));
174         assertEquals(Long.class, ClassUtil.wrapperType(Long.TYPE));
175 
176         assertEquals(Double.class, ClassUtil.wrapperType(Double.TYPE));
177         assertEquals(Float.class, ClassUtil.wrapperType(Float.TYPE));
178 
179         assertEquals(Boolean.class, ClassUtil.wrapperType(Boolean.TYPE));
180 
181         try {
182             ClassUtil.wrapperType(String.class);
183             fail("Should not pass");
184         } catch (IllegalArgumentException e) {
185             verifyException(e, "String is not a primitive type");
186         }
187     }
188 
testWrapperToPrimitiveType()189     public void testWrapperToPrimitiveType()
190     {
191         assertEquals(Integer.TYPE, ClassUtil.primitiveType(Integer.class));
192         assertEquals(Long.TYPE, ClassUtil.primitiveType(Long.class));
193         assertEquals(Character.TYPE, ClassUtil.primitiveType(Character.class));
194         assertEquals(Short.TYPE, ClassUtil.primitiveType(Short.class));
195         assertEquals(Byte.TYPE, ClassUtil.primitiveType(Byte.class));
196         assertEquals(Float.TYPE, ClassUtil.primitiveType(Float.class));
197         assertEquals(Double.TYPE, ClassUtil.primitiveType(Double.class));
198         assertEquals(Boolean.TYPE, ClassUtil.primitiveType(Boolean.class));
199 
200         assertNull(ClassUtil.primitiveType(String.class));
201     }
202 
testFindEnumType()203     public void testFindEnumType()
204     {
205         assertEquals(TestEnum.class, ClassUtil.findEnumType(TestEnum.A));
206         // different codepaths for empty and non-empty EnumSets...
207         assertEquals(TestEnum.class, ClassUtil.findEnumType(EnumSet.allOf(TestEnum.class)));
208         assertEquals(TestEnum.class, ClassUtil.findEnumType(EnumSet.noneOf(TestEnum.class)));
209 
210         assertEquals(TestEnum.class, ClassUtil.findEnumType(new EnumMap<TestEnum,Integer>(TestEnum.class)));
211     }
212 
testDescs()213     public void testDescs()
214     {
215         final String stringExp = "`java.lang.String`";
216         assertEquals(stringExp, ClassUtil.getClassDescription("foo"));
217         assertEquals(stringExp, ClassUtil.getClassDescription(String.class));
218         final JavaType stringType = TypeFactory.defaultInstance().constructType(String.class);
219         assertEquals(stringExp, ClassUtil.getTypeDescription(stringType));
220         final JavaType mapType = TypeFactory.defaultInstance().constructType(
221                 new TypeReference<Map<String, Integer>>() { });
222         assertEquals("`java.util.Map<java.lang.String,java.lang.Integer>`",
223                 ClassUtil.getTypeDescription(mapType));
224     }
225 
testSubtypes()226     public void testSubtypes()
227     {
228         final JavaType stringType = TypeFactory.defaultInstance().constructType(String.class);
229         List<JavaType> supers = ClassUtil.findSuperTypes(stringType, Object.class, false);
230         assertEquals(Collections.emptyList(), supers);
231 
232         supers = ClassUtil.findSuperTypes(stringType, Object.class, true);
233         assertEquals(Collections.singletonList(stringType), supers);
234     }
235 
testGetDeclaringClass()236     public void testGetDeclaringClass()
237     {
238         assertEquals(null, ClassUtil.getDeclaringClass(String.class));
239         assertEquals(getClass(), ClassUtil.getDeclaringClass(BaseClass.class));
240     }
241 
testIsXxxType()242     public void testIsXxxType()
243     {
244         assertTrue(ClassUtil.isCollectionMapOrArray(String[].class));
245         assertTrue(ClassUtil.isCollectionMapOrArray(ArrayList.class));
246         assertTrue(ClassUtil.isCollectionMapOrArray(LinkedHashMap.class));
247         assertFalse(ClassUtil.isCollectionMapOrArray(java.net.URL.class));
248 
249         assertTrue(ClassUtil.isBogusClass(Void.class));
250         assertTrue(ClassUtil.isBogusClass(Void.TYPE));
251         assertFalse(ClassUtil.isBogusClass(String.class));
252     }
253 
testEnforceSubtype()254     public void testEnforceSubtype()
255     {
256         try {
257             ClassUtil.verifyMustOverride(Number.class, Boolean.TRUE, "Test");
258         } catch (IllegalStateException e) {
259             verifyException(e, "must override method 'Test'");
260         }
261     }
262 
testCloseEtc()263     public void testCloseEtc() throws Exception
264     {
265         final Exception testExc1 = new IllegalArgumentException("test");
266         // First: without any actual stuff, with an RTE
267         try {
268             ClassUtil.closeOnFailAndThrowAsIOE(null, null, testExc1);
269             fail("Should not pass");
270         } catch (Exception e) {
271             assertSame(testExc1, e);
272         }
273 
274         // then with bogus Closeable and with non-RTE:
275         JsonFactory f = new JsonFactory();
276         ByteArrayOutputStream bytes = new ByteArrayOutputStream();
277         JsonGenerator gen = f.createGenerator(bytes);
278         final Exception testExc2 = new Exception("test");
279         try {
280             ClassUtil.closeOnFailAndThrowAsIOE(gen, bytes, testExc2);
281             fail("Should not pass");
282         } catch (Exception e) {
283             assertEquals(RuntimeException.class, e.getClass());
284             assertSame(testExc2, e.getCause());
285             assertEquals("test", e.getCause().getMessage());
286             assertTrue(gen.isClosed());
287         }
288         gen.close();
289     }
290 
291     /*
292     /**********************************************************
293     /* Test methods, deprecated
294     /**********************************************************
295      */
296 
297     @SuppressWarnings("deprecation")
testSubtypesDeprecated()298     public void testSubtypesDeprecated()
299     {
300         // just for code coverage
301         List<Class<?>> supers = ClassUtil.findSuperTypes(String.class, Object.class);
302         assertFalse(supers.isEmpty()); // serializable/comparable/char-seq
303     }
304 
305     @SuppressWarnings("deprecation")
testHasGetterSignature()306     public void testHasGetterSignature() throws Exception
307     {
308         assertFalse(ClassUtil.hasGetterSignature(MaybeGetters.class.getDeclaredMethod("staticMethod")));
309         assertFalse(ClassUtil.hasGetterSignature(MaybeGetters.class.getDeclaredMethod("voidMethod")));
310         assertFalse(ClassUtil.hasGetterSignature(MaybeGetters.class.getDeclaredMethod("setMethod", Integer.TYPE)));
311         assertTrue(ClassUtil.hasGetterSignature(MaybeGetters.class.getDeclaredMethod("getMethod")));
312     }
313 }
314