rev 54588 : 8212975: ClassDesc should have a full name method
Reviewed-by: vromero

   1 /*
   2  * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.lang.invoke.MethodHandles;
  25 import java.lang.constant.ClassDesc;
  26 import java.lang.constant.ConstantDescs;
  27 import java.lang.reflect.Array;
  28 import java.lang.reflect.Field;
  29 import java.lang.reflect.Modifier;
  30 import java.util.Arrays;
  31 import java.util.List;
  32 import java.util.Map;
  33 
  34 import org.testng.annotations.Test;
  35 
  36 import static org.testng.Assert.assertEquals;
  37 import static org.testng.Assert.assertFalse;
  38 import static org.testng.Assert.assertNotEquals;
  39 import static org.testng.Assert.assertNull;
  40 import static org.testng.Assert.assertTrue;
  41 import static org.testng.Assert.fail;
  42 
  43 /**
  44  * @test
  45  * @bug 8215510
  46  * @compile ClassDescTest.java
  47  * @run testng ClassDescTest
  48  * @summary unit tests for java.lang.constant.ClassDesc
  49  */
  50 @Test
  51 public class ClassDescTest extends SymbolicDescTest {
  52 
  53     private void testClassDesc(ClassDesc r) throws ReflectiveOperationException {
  54         testSymbolicDesc(r);
  55 
  56         // Test descriptor accessor, factory, equals
  57         assertEquals(r, ClassDesc.ofDescriptor(r.descriptorString()));
  58 
  59         if (!r.descriptorString().equals("V")) {
  60             assertEquals(r, r.arrayType().componentType());
  61             // Commutativity: array -> resolve -> componentType -> toSymbolic
  62             assertEquals(r, ((Class<?>) r.arrayType().resolveConstantDesc(LOOKUP)).getComponentType().describeConstable().orElseThrow());
  63             // Commutativity: resolve -> array -> toSymbolic -> component type
  64             assertEquals(r, Array.newInstance(((Class<?>) r.resolveConstantDesc(LOOKUP)), 0).getClass().describeConstable().orElseThrow().componentType());
  65         }
  66 
  67         if (r.isArray()) {
  68             assertEquals(r, r.componentType().arrayType());
  69             assertEquals(r, ((Class<?>) r.resolveConstantDesc(LOOKUP)).getComponentType().describeConstable().orElseThrow().arrayType());
  70             assertEquals(r, Array.newInstance(((Class<?>) r.componentType().resolveConstantDesc(LOOKUP)), 0).getClass().describeConstable().orElseThrow());
  71         }
  72     }
  73 
  74     private void testClassDesc(ClassDesc r, Class<?> c) throws ReflectiveOperationException {
  75         testClassDesc(r);
  76 
  77         assertEquals(r.resolveConstantDesc(LOOKUP), c);
  78         assertEquals(c.describeConstable().orElseThrow(), r);
  79         assertEquals(ClassDesc.ofDescriptor(c.descriptorString()), r);
  80     }
  81 
  82     public void testSymbolicDescsConstants() throws ReflectiveOperationException {
  83         int tested = 0;
  84         Field[] fields = ConstantDescs.class.getDeclaredFields();
  85         for (Field f : fields) {
  86             try {
  87                 if (f.getType().equals(ClassDesc.class)
  88                     && ((f.getModifiers() & Modifier.STATIC) != 0)
  89                     && ((f.getModifiers() & Modifier.PUBLIC) != 0)) {
  90                     ClassDesc cr = (ClassDesc) f.get(null);
  91                     Class c = (Class)cr.resolveConstantDesc(MethodHandles.lookup());
  92                     testClassDesc(cr, c);
  93                     ++tested;
  94                 }
  95             }
  96             catch (Throwable e) {
  97                 System.out.println(e.getMessage());
  98                 fail("Error testing field " + f.getName(), e);
  99             }
 100         }
 101 
 102         assertTrue(tested > 0);
 103     }
 104 
 105     public void testPrimitiveClassDesc() throws ReflectiveOperationException {
 106         for (Primitives p : Primitives.values()) {
 107             List<ClassDesc> descs = List.of(ClassDesc.ofDescriptor(p.descriptor),
 108                                            p.classDesc,
 109                                            (ClassDesc) p.clazz.describeConstable().orElseThrow());
 110             for (ClassDesc c : descs) {
 111                 testClassDesc(c, p.clazz);
 112                 assertTrue(c.isPrimitive());
 113                 assertEquals(p.descriptor, c.descriptorString());
 114                 assertEquals(p.name, c.displayName());
 115                 descs.forEach(cc -> assertEquals(c, cc));
 116                 if (p != Primitives.VOID) {
 117                     testClassDesc(c.arrayType(), p.arrayClass);
 118                     assertEquals(c, ((ClassDesc) p.arrayClass.describeConstable().orElseThrow()).componentType());
 119                     assertEquals(c, p.classDesc.arrayType().componentType());
 120                 }
 121             }
 122 
 123             for (Primitives other : Primitives.values()) {
 124                 ClassDesc otherDescr = ClassDesc.ofDescriptor(other.descriptor);
 125                 if (p != other)
 126                     descs.forEach(c -> assertNotEquals(c, otherDescr));
 127                 else
 128                     descs.forEach(c -> assertEquals(c, otherDescr));
 129             }
 130         }
 131     }
 132 
 133     public void testSimpleClassDesc() throws ReflectiveOperationException {
 134 
 135         List<ClassDesc> stringClassDescs = Arrays.asList(ClassDesc.ofDescriptor("Ljava/lang/String;"),
 136                                                         ClassDesc.of("java.lang", "String"),
 137                                                         ClassDesc.of("java.lang.String"),
 138                                                         ClassDesc.of("java.lang.String").arrayType().componentType(),
 139                                                         String.class.describeConstable().orElseThrow());
 140         for (ClassDesc r : stringClassDescs) {
 141             testClassDesc(r, String.class);
 142             assertFalse(r.isPrimitive());
 143             assertEquals("Ljava/lang/String;", r.descriptorString());
 144             assertEquals("String", r.displayName());
 145             assertEquals(r.arrayType().resolveConstantDesc(LOOKUP), String[].class);
 146             stringClassDescs.forEach(rr -> assertEquals(r, rr));
 147         }
 148 
 149         testClassDesc(ClassDesc.of("java.lang.String").arrayType(), String[].class);
 150         testClassDesc(ClassDesc.of("java.util.Map").nested("Entry"), Map.Entry.class);
 151 
 152         ClassDesc thisClassDesc = ClassDesc.ofDescriptor("LClassDescTest;");
 153         assertEquals(thisClassDesc, ClassDesc.of("", "ClassDescTest"));
 154         assertEquals(thisClassDesc, ClassDesc.of("ClassDescTest"));
 155         assertEquals(thisClassDesc.displayName(), "ClassDescTest");
 156         testClassDesc(thisClassDesc, ClassDescTest.class);
 157     }
 158 
 159     public void testPackageName() {
 160         assertEquals("com.foo", ClassDesc.of("com.foo.Bar").packageName());
 161         assertEquals("com.foo", ClassDesc.of("com.foo.Bar").nested("Baz").packageName());
 162         assertEquals("", ClassDesc.of("Bar").packageName());
 163         assertEquals("", ClassDesc.of("Bar").nested("Baz").packageName());
 164         assertEquals("", ClassDesc.of("Bar").nested("Baz", "Foo").packageName());
 165 
 166         assertEquals("", ConstantDescs.CD_int.packageName());
 167         assertEquals("", ConstantDescs.CD_int.arrayType().packageName());
 168         assertEquals("", ConstantDescs.CD_String.arrayType().packageName());
 169         assertEquals("", ClassDesc.of("Bar").arrayType().packageName());
 170     }
 171 
 172     public void testFullDisplayName() {
 173         assertEquals(ClassDesc.ofDescriptor("Ljava/lang/String;").displayName(true), "java.lang.String");
 174         assertEquals(ClassDesc.ofDescriptor("[Ljava/lang/String;").displayName(true), "java.lang.String[]");
 175         assertEquals(ClassDesc.ofDescriptor("[[Ljava/lang/String;").displayName(true), "java.lang.String[][]");
 176         assertEquals(ClassDesc.ofDescriptor("I").displayName(true), "int");
 177     }
 178 
 179     private void testBadArrayRank(ClassDesc cr) {
 180         try {
 181             cr.arrayType(-1);
 182             fail("");
 183         } catch (IllegalArgumentException e) {
 184             // good
 185         }
 186         try {
 187             cr.arrayType(0);
 188             fail("");
 189         } catch (IllegalArgumentException e) {
 190             // good
 191         }
 192     }
 193 
 194     public void testArrayClassDesc() throws ReflectiveOperationException {
 195         for (String d : basicDescs) {
 196             ClassDesc a0 = ClassDesc.ofDescriptor(d);
 197             ClassDesc a1 = a0.arrayType();
 198             ClassDesc a2 = a1.arrayType();
 199 
 200             testClassDesc(a0);
 201             testClassDesc(a1);
 202             testClassDesc(a2);
 203             assertFalse(a0.isArray());
 204             assertTrue(a1.isArray());
 205             assertTrue(a2.isArray());
 206             assertFalse(a1.isPrimitive());
 207             assertFalse(a2.isPrimitive());
 208             assertEquals(a0.descriptorString(), d);
 209             assertEquals(a1.descriptorString(), "[" + a0.descriptorString());
 210             assertEquals(a2.descriptorString(), "[[" + a0.descriptorString());
 211 
 212             assertNull(a0.componentType());
 213             assertEquals(a0, a1.componentType());
 214             assertEquals(a1, a2.componentType());
 215 
 216             assertNotEquals(a0, a1);
 217             assertNotEquals(a1, a2);
 218 
 219             assertEquals(a1, ClassDesc.ofDescriptor("[" + d));
 220             assertEquals(a2, ClassDesc.ofDescriptor("[[" + d));
 221             assertEquals(classToDescriptor((Class<?>) a0.resolveConstantDesc(LOOKUP)), a0.descriptorString());
 222             assertEquals(classToDescriptor((Class<?>) a1.resolveConstantDesc(LOOKUP)), a1.descriptorString());
 223             assertEquals(classToDescriptor((Class<?>) a2.resolveConstantDesc(LOOKUP)), a2.descriptorString());
 224 
 225             testBadArrayRank(ConstantDescs.CD_int);
 226             testBadArrayRank(ConstantDescs.CD_String);
 227             testBadArrayRank(ClassDesc.of("Bar"));
 228         }
 229     }
 230 
 231     public void testBadClassDescs() {
 232         List<String> badDescriptors = List.of("II", "I;", "Q", "L", "",
 233                                               "java.lang.String", "[]", "Ljava/lang/String",
 234                                               "Ljava.lang.String;", "java/lang/String");
 235 
 236         for (String d : badDescriptors) {
 237             try {
 238                 ClassDesc constant = ClassDesc.ofDescriptor(d);
 239                 fail(d);
 240             }
 241             catch (IllegalArgumentException e) {
 242                 // good
 243             }
 244         }
 245 
 246         List<String> badBinaryNames = List.of("I;", "[]", "Ljava/lang/String",
 247                 "Ljava.lang.String;", "java/lang/String");
 248         for (String d : badBinaryNames) {
 249             try {
 250                 ClassDesc constant = ClassDesc.of(d);
 251                 fail(d);
 252             } catch (IllegalArgumentException e) {
 253                 // good
 254             }
 255         }
 256 
 257         for (Primitives p : Primitives.values()) {
 258             testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any");
 259             testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any", "other");
 260         }
 261 
 262         ClassDesc stringDesc = ClassDesc.ofDescriptor("Ljava/lang/String;");
 263         ClassDesc stringArrDesc = stringDesc.arrayType(255);
 264         try {
 265             ClassDesc arrGreaterThan255 = stringArrDesc.arrayType();
 266             fail("can't create an array type descriptor with more than 255 dimensions");
 267         } catch (IllegalStateException e) {
 268             // good
 269         }
 270         String descWith255ArrayDims = new String(new char[255]).replace('\0', '[');
 271         try {
 272             ClassDesc arrGreaterThan255 = ClassDesc.ofDescriptor(descWith255ArrayDims + "[Ljava/lang/String;");
 273             fail("can't create an array type descriptor with more than 255 dimensions");
 274         } catch (IllegalArgumentException e) {
 275             // good
 276         }
 277         try {
 278             ClassDesc arrWith255Dims = ClassDesc.ofDescriptor(descWith255ArrayDims + "Ljava/lang/String;");
 279             arrWith255Dims.arrayType(1);
 280             fail("can't create an array type descriptor with more than 255 dimensions");
 281         } catch (IllegalArgumentException e) {
 282             // good
 283         }
 284     }
 285 
 286     private void testBadNestedClasses(ClassDesc cr, String firstNestedName, String... moreNestedNames) {
 287         try {
 288             cr.nested(firstNestedName, moreNestedNames);
 289             fail("");
 290         } catch (IllegalStateException e) {
 291             // good
 292         }
 293     }
 294 
 295     public void testLangClasses() {
 296         Double d = 1.0;
 297         assertEquals(d.resolveConstantDesc(LOOKUP), d);
 298         assertEquals(d.describeConstable().get(), d);
 299 
 300         Integer i = 1;
 301         assertEquals(i.resolveConstantDesc(LOOKUP), i);
 302         assertEquals(i.describeConstable().get(), i);
 303 
 304         Float f = 1.0f;
 305         assertEquals(f.resolveConstantDesc(LOOKUP), f);
 306         assertEquals(f.describeConstable().get(), f);
 307 
 308         Long l = 1L;
 309         assertEquals(l.resolveConstantDesc(LOOKUP), l);
 310         assertEquals(l.describeConstable().get(), l);
 311 
 312         String s = "";
 313         assertEquals(s.resolveConstantDesc(LOOKUP), s);
 314         assertEquals(s.describeConstable().get(), s);
 315     }
 316 }
--- EOF ---