/* * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /** * @test * @bug 4421040 * @summary JPDA: Add support for JSR-014 Generics * * @author jjh * * @run build TestScaffold VMConnection TargetListener TargetAdapter * @run compile -g GenericsTest.java * @run main GenericsTest */ import com.sun.jdi.*; import com.sun.jdi.event.*; import com.sun.jdi.request.*; import java.util.*; /********** target program **********/ class GenericsTarg { static Gen1<String> genField = new Gen1<String>();; static Sub1 sub1Field = new Sub1(); String[] strArray = null; int intField = 0; Object objField; public static void main(String[] args){ //genField.print(); System.out.println("Goodbye from GenericsTarg!"); } } class Gen1<tt> { tt field1; Gen1() { System.out.println("Gen1<tt> ctor called"); } tt method1(tt p1) { Gen1<String> xxx = null; System.out.println("method1: param is " + p1); return p1; } String method2() { String str = "This local variable is not generic"; return str; } } class Sub1 extends Gen1<String> { String method1(String p1) { System.out.println("method1 has been overridden: param is " + p1); return "hi"; } } /********** test program **********/ public class GenericsTest extends TestScaffold { ReferenceType targetClass; ThreadReference mainThread; static boolean useOld; GenericsTest (String args[]) { super(args); } public static void main(String[] args) throws Exception { /* * The 1.5 FE must be able to talk to a 1.4 BE, ie, JDWP version <= 1.4. * This is hard to test since this test file must be compiled with * -source 1.5 which will cause its class file to be version 49 which * won't run on a pre 1.5 JDK. We can simulate this though * by passing * -xjdk <pathname> * to this test which causes the debuggee to be run on that JDK. * This should be a version of 1.5 that accepts classfile version 49, * but which still contains the 1.4 version of JDWP. * This trick verifies that the calls to genericSignature() methods * in the test do not cause the generic JDWP commands to be issued. * The value to use for this is currently: * /java/re/jdk/1.5/promoted/all/b17/binaries/solaris-sparc */ if (args.length > 1 && args[0].equals("-xjdk")) { System.setProperty("java.home", args[1]); useOld = true; // Delete this arg String[] args1 = new String[args.length - 2]; for (int ii = 0; ii < args.length -2; ii++) { args1[ii] = args[ii + 2]; } args = args1; } new GenericsTest(args).startTests(); } /********** test core **********/ protected void runTests() throws Exception { /* * Get to the top of main() * to determine targetClass and mainThread */ BreakpointEvent bpe = startToMain("GenericsTarg"); targetClass = bpe.location().declaringType(); { /* * Prove that arrays aren't broken and that * null is returned if there is no generic signature */ Field strArray = targetClass.fieldByName("strArray"); ReferenceType fieldType = (ReferenceType)(strArray.type()); String genSig = fieldType.genericSignature(); System.out.println("strArray name = " + strArray); System.out.println(" type = " + fieldType); System.out.println(" sig = " + fieldType.signature()); System.out.println(" genSig = " + genSig); if (!useOld && genSig != null) { failure("FAILED: Expected generic signature = null for " + fieldType.name() + ", received: " + genSig); } } { // prove that primitives aren't broken. Field intField = targetClass.fieldByName("intField"); Type fieldType = (Type)(intField.type()); System.out.println("intField name = " + intField); System.out.println(" type = " + fieldType); System.out.println(" sig = " + fieldType.signature()); } Field genField = targetClass.fieldByName("genField"); ReferenceType gen1Class = (ReferenceType)(genField.type()); String genSig; String expected; { // Verify genericSignature for a class expected = "<tt:Ljava/lang/Object;>Ljava/lang/Object;"; genSig = gen1Class.genericSignature(); System.out.println("genField name = " + genField); System.out.println(" type = " + gen1Class); System.out.println(" sig = " + gen1Class.signature()); System.out.println(" genSig = " + genSig); if (!useOld && !expected.equals(genSig)) { failure("FAILED: Expected generic signature for gen1: " + expected + ", received: " + genSig); } } { // Verify genericSignature() for a field List genFields = gen1Class.fields(); Field field1 = (Field)genFields.get(0); // there is only one field expected = "Ttt;"; genSig = field1.genericSignature(); System.out.println("field1 name = " + field1); System.out.println(" type = " + gen1Class.signature()); System.out.println(" sig = " + field1.signature()); System.out.println(" gen sig = " + genSig); if (!useOld && !expected.equals(genSig)) { failure("FAILED: Expected generic signature for field1: " + expected + ", received: " + genSig); } } { // Verify genericSignature() for a method List genMethods = gen1Class.methodsByName("method1"); // There is only uno Method method1 = (Method)genMethods.get(0); expected = "(Ttt;)Ttt;"; genSig = method1.genericSignature(); System.out.println("method1 name = " + method1); System.out.println(" type = " + gen1Class.signature()); System.out.println(" sig = " + method1.signature()); System.out.println(" gen sig = " + genSig); System.out.println(" bridge = " + method1.isBridge()); if (!useOld && !expected.equals(genSig)) { failure("FAILED: Expected generic signature for method1: " + expected + ", received: " + genSig); } // Verify this is not a bridge method if (method1.isBridge()) { failure("FAILED: Expected gen1.method1 to not be a bridge" + " method but it is"); } // Verify genericSignature for a local var List localVars = method1.variables(); String[] expectedGenSigs = { "Ttt", "Gen1<String>" }; for ( int ii = 0 ; ii < localVars.size(); ii++) { expected = expectedGenSigs[ii]; LocalVariable pp = (LocalVariable)localVars.get(ii); genSig = pp.genericSignature(); System.out.println(" local var " + ii + " = " + pp.name()); System.out.println(" sig = " + pp.signature()); System.out.println(" gen sig = " + genSig); //jjh Uncomment when generics for local vars are available from //jjh javac and hotspot. See: //jjh 4914602 LVT entries for classfile version > 49 must be converted //jjh if (!useOld && !expected.equals(genSig)) { //jjh failure("FAILED: Expected generic signature for local var: " + //jjh expected + ", received: " + genSig); //jjh } } } { // Verify genericSignature() for a method2 List genMethods = gen1Class.methodsByName("method2"); // There is only uno Method method2 = (Method)genMethods.get(0); expected = "null"; genSig = method2.genericSignature(); genSig = (genSig == null) ? "null" : genSig; System.out.println("method2 name = " + method2); System.out.println(" type = " + gen1Class.signature()); System.out.println(" sig = " + method2.signature()); System.out.println(" gen sig = " + genSig); System.out.println(" bridge = " + method2.isBridge()); if (!useOld && !expected.equals(genSig)) { failure("FAILED: Expected generic signature for method2: " + expected + ", received: " + genSig); } // Verify this is not a bridge method if (method2.isBridge()) { failure("FAILED: Expected gen1.method2 to not be a bridge" + " method but it is"); } // Verify genericSignature for a local var List localVars = method2.variables(); expected = "null"; for ( int ii = 0 ; ii < localVars.size(); ii++) { LocalVariable pp = (LocalVariable)localVars.get(ii); genSig = pp.genericSignature(); genSig = (genSig == null) ? "null" : genSig; System.out.println(" local var " + ii + " = " + pp.name()); System.out.println(" sig = " + pp.signature()); System.out.println(" gen sig = " + genSig); if (!useOld && !expected.equals(genSig)) { failure("FAILED: Expected generic signature for local var: " + expected + ", received: " + genSig); } } } { Field sub1Field = targetClass.fieldByName("sub1Field"); ReferenceType sub1Class = (ReferenceType)(sub1Field.type()); List<Method> sub1Methods = sub1Class.methodsByName("method1"); for (Method mm: sub1Methods) { System.out.println("method is: " + mm); } /* * There should be two methods - the first is the * method1 defined in Sub1, and the 2nd is a javac generated * bridge method. */ Method method1 = (Method)sub1Methods.get(1); System.out.println("\nmethod1 name = " + method1); System.out.println(" sig = " + method1.signature()); System.out.println(" bridge = " + method1.isBridge()); if (!useOld && !method1.isBridge()) { failure("FAILED: Expected Sub1.method1 to be a bridge method" + " but it isn't"); } } { // Verify genericSignature for a non generic class genSig = targetClass.genericSignature(); if (genSig != null) { failure("FAILED: Expected generic signature = null for " + targetClass.name() + ", received: " + genSig); } } { // Verify genericSignature for a non generic field Field objField = targetClass.fieldByName("objField"); genSig = objField.genericSignature(); if (genSig != null) { failure("FAILED: Expected generic signature = null for " + objField.name() + ", received: " + genSig); } } { // Verify genericSignature for a non generic method List methods = targetClass.methodsByName("main"); Method main = (Method)methods.get(0); genSig = main.genericSignature(); if (genSig != null) { failure("FAILED: Expected generic signature = null for " + main.name() + ", received: " + genSig); } } if (0 == 1) { mainThread = bpe.thread(); EventRequestManager erm = vm().eventRequestManager(); StepRequest request = erm.createStepRequest(mainThread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); request.enable(); } /* * resume the target listening for events */ listenUntilVMDisconnect(); /* * deal with results of test * if anything has called failure("foo") testFailed will be true */ if (!testFailed) { println("GenericsTest: passed"); } else { throw new Exception("GenericsTest: failed"); } } }