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