1 /*
   2  * Copyright (c) 2018, 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.Class;
  25 import java.lang.invoke.MethodHandles;
  26 import java.lang.invoke.MethodType;
  27 import java.lang.constant.ClassDesc;
  28 import java.lang.constant.Constable;
  29 import java.lang.constant.ConstantDesc;
  30 import java.lang.constant.ConstantDescs;
  31 import java.util.List;
  32 import java.util.Optional;
  33 import java.util.stream.Stream;
  34 
  35 import static org.testng.Assert.assertEquals;
  36 
  37 /**
  38  * Base class for XxxDesc tests
  39  */
  40 public abstract class SymbolicDescTest {
  41 
  42     public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
  43 
  44     static List<String> someDescs = List.of("Ljava/lang/String;", "Ljava/util/List;");
  45     static String[] basicDescs = Stream.concat(Stream.of(Primitives.values())
  46                                                      .filter(p -> p != Primitives.VOID)
  47                                                      .map(p -> p.descriptor),
  48                                                someDescs.stream())
  49                                        .toArray(String[]::new);
  50     static String[] paramDescs = Stream.of(basicDescs)
  51                                        .flatMap(d -> Stream.of(d, "[" + d))
  52                                        .toArray(String[]::new);
  53     static String[] returnDescs = Stream.concat(Stream.of(paramDescs), Stream.of("V")).toArray(String[]::new);
  54 
  55     enum Primitives {
  56         INT("I", "int", int.class, int[].class, ConstantDescs.CD_int),
  57         LONG("J", "long", long.class, long[].class, ConstantDescs.CD_long),
  58         SHORT("S", "short", short.class, short[].class, ConstantDescs.CD_short),
  59         BYTE("B", "byte", byte.class, byte[].class, ConstantDescs.CD_byte),
  60         CHAR("C", "char", char.class, char[].class, ConstantDescs.CD_char),
  61         FLOAT("F", "float", float.class, float[].class, ConstantDescs.CD_float),
  62         DOUBLE("D", "double", double.class, double[].class, ConstantDescs.CD_double),
  63         BOOLEAN("Z", "boolean", boolean.class, boolean[].class, ConstantDescs.CD_boolean),
  64         VOID("V", "void", void.class, null, ConstantDescs.CD_void);
  65 
  66         public final String descriptor;
  67         public final String name;
  68         public final Class<?> clazz;
  69         public final Class<?> arrayClass;
  70         public final ClassDesc classDesc;
  71 
  72         Primitives(String descriptor, String name, Class<?> clazz, Class<?> arrayClass, ClassDesc desc) {
  73             this.descriptor = descriptor;
  74             this.name = name;
  75             this.clazz = clazz;
  76             this.arrayClass = arrayClass;
  77             classDesc = desc;
  78         }
  79     }
  80 
  81     static String classToDescriptor(Class<?> clazz) {
  82         return MethodType.methodType(clazz).toMethodDescriptorString().substring(2);
  83     }
  84 
  85     static ClassDesc classToDesc(Class<?> c) {
  86         return ClassDesc.ofDescriptor(c.descriptorString());
  87     }
  88 
  89     static<T> void testSymbolicDesc(ConstantDesc desc) throws ReflectiveOperationException {
  90         testSymbolicDesc(desc, false);
  91     }
  92 
  93     static<T> void testSymbolicDescForwardOnly(ConstantDesc desc) throws ReflectiveOperationException {
  94         testSymbolicDesc(desc, true);
  95     }
  96 
  97     private static<T> void testSymbolicDesc(ConstantDesc desc, boolean forwardOnly) throws ReflectiveOperationException {
  98         // Round trip sym -> resolve -> toSymbolicDesc
  99         Constable constable = (Constable) desc.resolveConstantDesc(LOOKUP);
 100         Optional<? extends ConstantDesc> described = constable.describeConstable();
 101         if (!forwardOnly) {
 102             assertEquals(desc, described.orElseThrow());
 103         }
 104 
 105         // Round trip sym -> quoted sym -> resolve
 106         if (desc instanceof Constable) {
 107             Optional<ConstantDesc> opt = (Optional<ConstantDesc>) ((Constable) desc).describeConstable();
 108             ConstantDesc sr = (ConstantDesc) opt.orElseThrow().resolveConstantDesc(LOOKUP);
 109             assertEquals(sr, desc);
 110         }
 111     }
 112 }