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