1 /* 2 * Copyright (c) 2016, 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 package runtime.valhalla.valuetypes; 24 25 import java.io.IOException; 26 import java.io.RandomAccessFile; 27 import java.lang.reflect.Field; 28 import java.lang.reflect.Method; 29 import static java.lang.reflect.Modifier.*; 30 import java.net.URL; 31 import java.util.Enumeration; 32 33 import jdk.experimental.value.ValueType; 34 35 import jdk.internal.org.objectweb.asm.*; 36 import static jdk.internal.org.objectweb.asm.Opcodes.*; 37 38 import static jdk.test.lib.Asserts.*; 39 40 /* 41 * @test DeriveValueTypeCreation 42 * @summary Derive Value Type creation test 43 * @library /testlibrary / 44 * @build runtime.valhalla.valuetypes.ValueCapableClass 45 * @run main/othervm -Xint -noverify runtime.valhalla.valuetypes.DeriveValueTypeCreation 46 */ 47 public class DeriveValueTypeCreation { 48 49 public static final String VCC_CLASSNAME = "runtime.valhalla.valuetypes.ValueCapableClass"; 50 51 static final boolean MVT_1_0 = true; // "Some restrictions apply" 52 53 public static void main(String[] args) { 54 DeriveValueTypeCreation test = new DeriveValueTypeCreation(); 55 test.run(); 56 } 57 58 public void run() { 59 loadAndRunTest(); 60 notValueCapableClasses(); 61 } 62 63 void loadAndRunTest() { 64 Class<?> clazz = null; 65 try { 66 clazz = Class.forName(VCC_CLASSNAME, true, getClass().getClassLoader()); 67 clazz.getDeclaredMethod("test").invoke(null); 68 } 69 catch (ClassNotFoundException cnfe) { fail("VCC class missing", cnfe); } 70 catch (NoSuchMethodException nsme) { fail("VCC test method missing", nsme); } 71 catch (Throwable t) { fail("Failed to invoke VCC.test()", t); } 72 73 checkValueCapableClass(clazz); 74 } 75 76 void checkValueCapableClass(Class<?> clazz) { 77 if (!ValueType.classHasValueType(clazz)) { 78 error("!classHasValueType: " + clazz); 79 } 80 81 ValueType<?> vt = ValueType.forClass(clazz); 82 if (vt == null) { 83 error("ValueType.forClass failed"); 84 } 85 86 System.out.println("ValueType: " + vt); 87 88 if (vt.boxClass() != clazz) { 89 error("ValueType.boxClass() failed"); 90 } 91 if (vt.sourceClass() != clazz) { 92 error("ValueType.sourceClass() failed"); 93 } 94 95 // DVT class matches our expectations for the current implementation... 96 Class<?> vtClass = vt.valueClass(); 97 if (!vtClass.getName().equals(clazz.getName() + "$Value")) { 98 error("ValueType.valueClass() failed"); 99 } 100 if (!vtClass.getSuperclass().getName().equals("java.lang.__Value")) { 101 error("ValueType.valueClass() isn't a Value Type class"); 102 } 103 if (MVT_1_0) { 104 if (!valhalla.shady.MinimalValueTypes_1_0.isValueType(vtClass)) { 105 error("ValueType.valueClass() isn't a Value Type class according to MVT1.0"); 106 } 107 } 108 109 // Exercise "Class.getSimpleName()", we've cause problems with it before 110 String sn = vtClass.getSimpleName(); 111 System.out.println("SimpleName: " + sn); 112 113 if (clazz.getClassLoader() != vtClass.getClassLoader()) { 114 error("ClassLoader mismatch"); 115 } 116 if (clazz.getProtectionDomain() != vtClass.getProtectionDomain()) { 117 error("ProtectionDomain mismatch"); 118 } 119 } 120 121 void notValueCapableClasses() { 122 int vccKlassAccess = ACC_SUPER | ACC_PUBLIC | ACC_FINAL; 123 int vccFieldAccess = ACC_PUBLIC | ACC_FINAL; 124 String vccSuperClass = "java/lang/Object"; 125 126 // First a control test to check createTestClass is working 127 try { 128 Class<?> cls = createTestClass("Control_Case_is_a_VCC", vccKlassAccess, vccSuperClass, "I", vccFieldAccess); 129 checkValueCapableClass(cls); 130 } 131 catch (Exception e) { 132 fail("Control test failed", e); 133 } 134 135 testFailCase("Not_a_final_class", ACC_SUPER | ACC_PUBLIC, vccSuperClass, "I", vccFieldAccess, "not a final class"); 136 testFailCase("No_fields", vccKlassAccess, vccSuperClass, null, vccFieldAccess, "has no instance fields"); 137 testFailCase("Not_final_field", vccKlassAccess, vccSuperClass, "I", ACC_PUBLIC, "contains non-final instance field"); 138 testFailCase("Super_not_Object", vccKlassAccess, "java/lang/Throwable", "I", vccFieldAccess, "does not derive from Object"); 139 if (MVT_1_0) { 140 String notSupported = "do not support"; 141 testFailCase("Only_Primitve_Fields_String", vccKlassAccess, vccSuperClass, "Ljava/lang/String;", vccFieldAccess, notSupported); 142 testFailCase("Only_Primitve_Fields_Array", vccKlassAccess, vccSuperClass, "[I", vccFieldAccess, notSupported); 143 } 144 } 145 146 void testFailCase(String clsName, 147 int klassAccess, 148 String superKlass, 149 String fieldType, 150 int fieldAccess, 151 String errMsgRequired) { 152 try { 153 createTestClass(clsName, klassAccess, superKlass, fieldType, fieldAccess); 154 error(clsName + " : failed to fail with Error"); 155 } 156 catch (ClassNotFoundException cnfe) { 157 fail(clsName + " : Unexpected ClassNotFoundException", cnfe); 158 } 159 catch (Error err) { 160 if (!err.getMessage().contains(errMsgRequired)) { 161 fail(clsName + " : Not the error we were looking for", err); 162 } 163 } 164 } 165 166 Class<?> createTestClass(String name, 167 int klassAccess, 168 String superKlass, 169 String fieldType, 170 int fieldAccess) throws ClassNotFoundException { 171 ClassWriter cw = new ClassWriter(0); 172 cw.visit(52, klassAccess, name, null, superKlass, null); 173 cw.visitAnnotation("Ljvm/internal/value/DeriveValueType;", true); 174 if (fieldType != null) { 175 cw.visitField(fieldAccess, "x", fieldType, null, null); 176 } 177 cw.visitEnd(); 178 return new TestClassLoader(name, cw.toByteArray()).loadClass(name); 179 } 180 181 class TestClassLoader extends ClassLoader { 182 183 String name; 184 byte[] classBytes; 185 186 TestClassLoader(String name, byte[] classBytes) { 187 this.name = name; 188 this.classBytes = classBytes; 189 } 190 191 @Override 192 public Class findClass(String name) throws ClassNotFoundException { 193 if (this.name.equals(name)) { 194 return defineClass(name, classBytes, 0, classBytes.length); 195 } 196 throw new ClassNotFoundException(); 197 } 198 } 199 200 /* 201 TODO: Current repo state doesn't pick up the common test/lib Asserts 202 remove this implementation when fixed 203 */ 204 public static void fail(String msg, Throwable thr) { // Missing Asserts.fail(String, Throwable) 205 throw new RuntimeException(msg, thr); 206 } 207 public static void error(String msg) { // Missing Asserts.error(String) 208 throw new RuntimeException(msg); 209 } 210 }