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;
main(String[] args)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;
Gen1()56     Gen1() {
57         System.out.println("Gen1<tt> ctor called");
58     }
method1(tt p1)59     tt method1(tt p1) {
60         Gen1<String> xxx = null;
61         System.out.println("method1: param is " + p1);
62         return p1;
63     }
method2()64     String method2() {
65         String str = "This local variable is not generic";
66         return str;
67     }
68 }
69 
70 class Sub1 extends Gen1<String> {
method1(String p1)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 
GenericsTest(String args[])84     GenericsTest (String args[]) {
85         super(args);
86     }
87 
main(String[] args)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 
runTests()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 }
344