1 /*
   2  * Copyright (c) 2003, 2004, 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 /**
  25  *  @test
  26  *  @bug 4421040
  27  *  @summary  JPDA: Add support for JSR-014 Generics
  28  *
  29  *  @author jjh
  30  *
  31  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
  32  *  @run compile -g GenericsTest.java
  33  *  @run driver GenericsTest
  34  */
  35 import com.sun.jdi.*;
  36 import com.sun.jdi.event.*;
  37 import com.sun.jdi.request.*;
  38 
  39 import java.util.*;
  40 
  41     /********** target program **********/
  42 
  43 class GenericsTarg {
  44     static Gen1<String> genField = new Gen1<String>();;
  45     static Sub1 sub1Field = new Sub1();
  46 
  47     String[] strArray = null;
  48     int intField = 0;
  49     Object objField;
  50     public static void main(String[] args){
  51         //genField.print();
  52         System.out.println("Goodbye from GenericsTarg!");
  53     }
  54 }
  55 class Gen1<tt> {
  56     tt field1;
  57     Gen1() {
  58         System.out.println("Gen1<tt> ctor called");
  59     }
  60     tt method1(tt p1) {
  61         Gen1<String> xxx = null;
  62         System.out.println("method1: param is " + p1);
  63         return p1;
  64     }
  65     String method2() {
  66         String str = "This local variable is not generic";
  67         return str;
  68     }
  69 }
  70 
  71 class Sub1 extends Gen1<String> {
  72     String method1(String p1) {
  73         System.out.println("method1 has been overridden: param is " + p1);
  74         return "hi";
  75     }
  76 }
  77 
  78     /********** test program **********/
  79 
  80 public class GenericsTest extends TestScaffold {
  81     ReferenceType targetClass;
  82     ThreadReference mainThread;
  83     static boolean useOld;
  84 
  85     GenericsTest (String args[]) {
  86         super(args);
  87     }
  88 
  89     public static void main(String[] args) throws Exception {
  90         /*
  91          * The 1.5 FE must be able to talk to a 1.4 BE, ie, JDWP version <= 1.4.
  92          * This is hard to test since this test file must be compiled with
  93          * -source 1.5 which will cause its class file to be version 49 which
  94          * won't run on a pre 1.5 JDK.   We can simulate this though
  95          * by passing
  96          *      -xjdk <pathname>
  97          * to this test which causes the debuggee to be run on that JDK.
  98          * This should be a version of 1.5 that accepts classfile version 49,
  99          * but which still contains the 1.4 version of JDWP.
 100          * This trick verifies that the calls to genericSignature() methods
 101          * in the test do not cause the generic JDWP commands to be issued.
 102          * The value to use for this is currently:
 103          * /java/re/jdk/1.5/promoted/all/b17/binaries/solaris-sparc
 104          */
 105         if (args.length > 1 && args[0].equals("-xjdk")) {
 106             System.setProperty("java.home", args[1]);
 107             useOld = true;
 108 
 109             // Delete this arg
 110             String[] args1 = new String[args.length - 2];
 111             for (int ii = 0; ii < args.length -2; ii++) {
 112                 args1[ii] = args[ii + 2];
 113             }
 114             args = args1;
 115         }
 116 
 117         new GenericsTest(args).startTests();
 118     }
 119 
 120     /********** test core **********/
 121 
 122     protected void runTests() throws Exception {
 123         /*
 124          * Get to the top of main()
 125          * to determine targetClass and mainThread
 126          */
 127         BreakpointEvent bpe = startToMain("GenericsTarg");
 128         targetClass = bpe.location().declaringType();
 129         {
 130             /*
 131              * Prove that arrays aren't broken and that
 132              * null is returned if there is no generic signature
 133              */
 134             Field strArray = targetClass.fieldByName("strArray");
 135             ReferenceType fieldType = (ReferenceType)(strArray.type());
 136             String genSig = fieldType.genericSignature();
 137             System.out.println("strArray name = " + strArray);
 138             System.out.println("         type = " + fieldType);
 139             System.out.println("          sig = " + fieldType.signature());
 140             System.out.println("       genSig = " + genSig);
 141             if (!useOld && genSig != null) {
 142                 failure("FAILED: Expected generic signature = null for "
 143                         + fieldType.name() + ", received: " + genSig);
 144             }
 145         }
 146         {
 147             // prove that primitives aren't broken.
 148             Field intField = targetClass.fieldByName("intField");
 149             Type fieldType = (Type)(intField.type());
 150             System.out.println("intField name = " + intField);
 151             System.out.println("         type = " + fieldType);
 152             System.out.println("          sig = " + fieldType.signature());
 153         }
 154 
 155         Field genField = targetClass.fieldByName("genField");
 156         ReferenceType gen1Class = (ReferenceType)(genField.type());
 157         String genSig;
 158         String expected;
 159         {
 160             // Verify genericSignature for a class
 161             expected = "<tt:Ljava/lang/Object;>Ljava/lang/Object;";
 162             genSig = gen1Class.genericSignature();
 163             System.out.println("genField name = " + genField);
 164             System.out.println("         type = " + gen1Class);
 165             System.out.println("          sig = " + gen1Class.signature());
 166             System.out.println("       genSig = " + genSig);
 167             if (!useOld && !expected.equals(genSig)) {
 168                 failure("FAILED: Expected generic signature for gen1: " +
 169                         expected + ", received: " + genSig);
 170             }
 171         }
 172         {
 173             // Verify genericSignature() for a field
 174             List genFields = gen1Class.fields();
 175             Field field1 = (Field)genFields.get(0);
 176             // there is only one field
 177             expected = "Ttt;";
 178             genSig = field1.genericSignature();
 179             System.out.println("field1 name = " + field1);
 180             System.out.println("       type = " + gen1Class.signature());
 181             System.out.println("        sig = " + field1.signature());
 182             System.out.println("    gen sig = " + genSig);
 183             if (!useOld && !expected.equals(genSig)) {
 184                 failure("FAILED: Expected generic signature for field1: " +
 185                         expected + ", received: " + genSig);
 186             }
 187         }
 188         {
 189             // Verify genericSignature() for a method
 190             List genMethods = gen1Class.methodsByName("method1");
 191             // There is only uno
 192             Method method1 = (Method)genMethods.get(0);
 193             expected = "(Ttt;)Ttt;";
 194             genSig = method1.genericSignature();
 195             System.out.println("method1 name = " + method1);
 196             System.out.println("        type = " + gen1Class.signature());
 197             System.out.println("         sig = " + method1.signature());
 198             System.out.println("     gen sig = " + genSig);
 199             System.out.println("     bridge  = " + method1.isBridge());
 200             if (!useOld && !expected.equals(genSig)) {
 201                 failure("FAILED: Expected generic signature for method1: " +
 202                         expected + ", received: " + genSig);
 203             }
 204 
 205             // Verify this is not a bridge method
 206             if (method1.isBridge()) {
 207                 failure("FAILED: Expected gen1.method1 to not be a bridge"
 208                          + " method but it is");
 209             }
 210 
 211             // Verify genericSignature for a local var
 212             List localVars = method1.variables();
 213             String[] expectedGenSigs = { "Ttt", "Gen1<String>" };
 214             for ( int ii = 0 ; ii < localVars.size(); ii++) {
 215                 expected = expectedGenSigs[ii];
 216                 LocalVariable pp = (LocalVariable)localVars.get(ii);
 217                 genSig = pp.genericSignature();
 218                 System.out.println("   local var " + ii + " = " + pp.name());
 219                 System.out.println("      sig      = " + pp.signature());
 220                 System.out.println("      gen sig  = " + genSig);
 221                 //jjh Uncomment when generics for local vars are available from
 222                 //jjh javac and hotspot.  See:
 223                 //jjh   4914602 LVT entries for classfile version > 49 must be converted
 224                 //jjh if (!useOld && !expected.equals(genSig)) {
 225                 //jjh    failure("FAILED: Expected generic signature for local var: " +
 226                 //jjh            expected + ", received: " + genSig);
 227                 //jjh }
 228             }
 229         }
 230         {
 231             // Verify genericSignature() for a method2
 232             List genMethods = gen1Class.methodsByName("method2");
 233             // There is only uno
 234             Method method2 = (Method)genMethods.get(0);
 235             expected = "null";
 236             genSig = method2.genericSignature();
 237             genSig = (genSig == null) ? "null" : genSig;
 238             System.out.println("method2 name = " + method2);
 239             System.out.println("        type = " + gen1Class.signature());
 240             System.out.println("         sig = " + method2.signature());
 241             System.out.println("     gen sig = " + genSig);
 242             System.out.println("     bridge  = " + method2.isBridge());
 243             if (!useOld && !expected.equals(genSig)) {
 244                 failure("FAILED: Expected generic signature for method2: " +
 245                         expected + ", received: " + genSig);
 246             }
 247 
 248             // Verify this is not a bridge method
 249             if (method2.isBridge()) {
 250                 failure("FAILED: Expected gen1.method2 to not be a bridge"
 251                          + " method but it is");
 252             }
 253 
 254             // Verify genericSignature for a local var
 255             List localVars = method2.variables();
 256             expected = "null";
 257             for ( int ii = 0 ; ii < localVars.size(); ii++) {
 258                 LocalVariable pp = (LocalVariable)localVars.get(ii);
 259                 genSig = pp.genericSignature();
 260                 genSig = (genSig == null) ? "null" : genSig;
 261 
 262                 System.out.println("   local var " + ii + " = " + pp.name());
 263                 System.out.println("      sig      = " + pp.signature());
 264                 System.out.println("      gen sig  = " + genSig);
 265                 if (!useOld && !expected.equals(genSig)) {
 266                    failure("FAILED: Expected generic signature for local var: " +
 267                            expected + ", received: " + genSig);
 268                 }
 269             }
 270         }
 271         {
 272             Field sub1Field = targetClass.fieldByName("sub1Field");
 273             ReferenceType sub1Class = (ReferenceType)(sub1Field.type());
 274             List<Method> sub1Methods = sub1Class.methodsByName("method1");
 275             for (Method mm: sub1Methods) {
 276                 System.out.println("method is: " + mm);
 277             }
 278             /*
 279              * There should be two methods - the first is the
 280              * method1 defined in Sub1, and the 2nd is a javac generated
 281              * bridge method.
 282              */
 283             Method method1 = (Method)sub1Methods.get(1);
 284             System.out.println("\nmethod1 name = " + method1);
 285             System.out.println("         sig = " + method1.signature());
 286             System.out.println("      bridge = " + method1.isBridge());
 287             if (!useOld && !method1.isBridge()) {
 288                 failure("FAILED: Expected Sub1.method1 to be a bridge method"
 289                          + " but it isn't");
 290             }
 291 
 292         }
 293         {
 294             // Verify genericSignature for a non generic class
 295             genSig = targetClass.genericSignature();
 296             if (genSig != null) {
 297                 failure("FAILED: Expected generic signature = null for "
 298                         + targetClass.name() + ", received: " + genSig);
 299             }
 300         }
 301         {
 302             // Verify genericSignature for a non generic field
 303             Field objField = targetClass.fieldByName("objField");
 304             genSig = objField.genericSignature();
 305             if (genSig != null) {
 306                 failure("FAILED: Expected generic signature = null for "
 307                         + objField.name() + ", received: " + genSig);
 308             }
 309         }
 310         {
 311             // Verify genericSignature for a non generic method
 312             List methods = targetClass.methodsByName("main");
 313             Method main = (Method)methods.get(0);
 314             genSig = main.genericSignature();
 315             if (genSig != null) {
 316                 failure("FAILED: Expected generic signature = null for "
 317                         + main.name() + ", received: " + genSig);
 318             }
 319         }
 320         if (0 == 1) {
 321             mainThread = bpe.thread();
 322             EventRequestManager erm = vm().eventRequestManager();
 323             StepRequest request = erm.createStepRequest(mainThread,
 324                                                     StepRequest.STEP_LINE,
 325                                                     StepRequest.STEP_INTO);
 326             request.enable();
 327         }
 328 
 329         /*
 330          * resume the target listening for events
 331          */
 332         listenUntilVMDisconnect();
 333 
 334         /*
 335          * deal with results of test
 336          * if anything has called failure("foo") testFailed will be true
 337          */
 338         if (!testFailed) {
 339             println("GenericsTest: passed");
 340         } else {
 341             throw new Exception("GenericsTest: failed");
 342         }
 343     }
 344 }