1 /*
2  * Copyright (c) 2003, 2018, 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 package nsk.jdi.Method.isBridge;
25 
26 import com.sun.jdi.*;
27 
28 import java.io.*;
29 import java.util.*;
30 
31 import nsk.share.*;
32 import nsk.share.jpda.*;
33 import nsk.share.jdi.*;
34 
35 /**
36  * The test exercises the JDI method<br>
37  * <b>com.sun.jdi.Method.isBridge()</b></br>
38  * It verifies that 'bridge methods' generated during translation of
39  * generic classes are determinated properly by the method.
40  * Here are the rules from the spec "Adding Generics to the Java
41  * Programming Language: Public Draft Specification, Version 2.0"
42  * followed by the test:<br><pre>
43  *
44  *     6.2 Translation of Methods
45  *     ...
46  *     <li> If C.m is directly overridden by a method D.m in D, and the
47  *       erasure of the return type or argument types of D.m differs from
48  *       the erasure of the corresponding types in C.m, a bridge method
49  *       needs to be generated.
50  *
51  *     <li> A bridge method also needs to be generated if C.m is not
52  *       directly overridden in D, unless C.m is abstract.
53  * </pre><br>
54  * The test works as follows. Debuggee contains several dummy superclasses
55  * and subclasses. Some of their methods fall under the rules above.
56  * Debugger verifies that the JDI Method.isBridge() returns true for all
57  * generated bridge methods and false for the non-bridge ones.
58  * The list of the class methods is obtained through the JDI
59  * ReferenceType.methods() which must return each method declared directly
60  * in this type including any synthetic methods created by the compiler.
61  */
62 public class isbridge001 {
63     static final String DEBUGGEE_CLASS =
64         "nsk.jdi.Method.isBridge.isbridge001t";
65 
66     static final String COMMAND_READY = "ready";
67     static final String COMMAND_QUIT = "quit";
68 
69     static final String[][][] methods = {
70 // nsk.jdi.Method.isBridge.isbridge001aa
71        {{"<init>",
72             "()V",
73             "false",
74             "0"},
75         {"isbridge001aMeth",
76             "(Ljava/lang/Double;)V",
77             "false",
78             "0"}},
79 
80 // nsk.jdi.Method.isBridge.isbridge001bb
81        {{"<init>",
82             "()V",
83             "false",
84             "0"},
85         {"isbridge001bMeth",
86             "(Ljava/lang/Number;)Ljava/lang/Number;",
87             "false",
88             "0"},
89         {"isbridge001bMeth2",
90             "(Ljava/lang/Number;I)V",
91             "false",
92             "0"}},
93 
94 // nsk.jdi.Method.isBridge.isbridge001bb2
95        {{"<init>",
96             "()V",
97             "false",
98             "0"},
99         {"isbridge001bMeth",
100             "(Ljava/lang/Byte;)Ljava/lang/Byte;",
101             "false",
102             "0"},
103         {"isbridge001bMeth2",
104             "(Ljava/lang/Byte;I)V",
105             "false",
106             "0"},
107         {"isbridge001bMeth",
108             "(Ljava/lang/Number;)Ljava/lang/Number;",
109             "true",
110             "0"},
111         {"isbridge001bMeth2",
112             "(Ljava/lang/Number;I)V",
113             "true",
114             "0"}},
115 
116 // nsk.jdi.Method.isBridge.isbridge001dd
117        {{"<init>",
118             "()V",
119             "false",
120             "0"}},
121 
122 // nsk.jdi.Method.isBridge.isbridge001dd2
123        {{"<init>",
124             "()V",
125             "false",
126             "0"},
127         {"isbridge001dMeth",
128             "(Ljava/lang/Boolean;Ljava/lang/Character;)Ljava/lang/String;",
129             "false",
130             "0"},
131          {"isbridge001dMeth",
132             "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
133             "true",
134             "0"}}
135     };
136 
137     static final String[] classes = {
138         "nsk.jdi.Method.isBridge.isbridge001aa",
139         "nsk.jdi.Method.isBridge.isbridge001bb",
140         "nsk.jdi.Method.isBridge.isbridge001bb2",
141         "nsk.jdi.Method.isBridge.isbridge001dd",
142         "nsk.jdi.Method.isBridge.isbridge001dd2",
143     };
144 
145     static final int CLS_NUM = classes.length;
146 
147     private IOPipe pipe;
148     private Log log;
149     private Debugee debuggee;
150     private int tot_res = Consts.TEST_PASSED;
151 
main(String argv[])152     public static void main (String argv[]) {
153         System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
154     }
155 
run(String argv[], PrintStream out)156     public static int run(String argv[], PrintStream out) {
157         return new isbridge001().runThis(argv, out);
158     }
159 
runThis(String args[], PrintStream out)160     private int runThis(String args[], PrintStream out) {
161         ArgumentHandler argHandler = new ArgumentHandler(args);
162         log = new Log(out, argHandler);
163         Binder binder = new Binder(argHandler, log);
164 
165         debuggee = binder.bindToDebugee(DEBUGGEE_CLASS);
166         pipe = debuggee.createIOPipe();
167         debuggee.redirectStderr(log, "isbridge001t.err> ");
168         debuggee.resume();
169         String cmd = pipe.readln();
170         if (!cmd.equals(COMMAND_READY)) {
171             tot_res = Consts.TEST_FAILED;
172             log.complain("TEST BUG: unknown debuggee's command: "
173                 + cmd);
174             return quitDebuggee();
175         }
176 
177         for (int i=0; i<CLS_NUM; i++) {
178             ReferenceType rType;
179             List clsMethods;
180 
181             log.display("\n>>>>>> Class " + classes[i]);
182             if ((rType = debuggee.classByName(classes[i])) == null) {
183                 tot_res = Consts.TEST_FAILED;
184                 log.complain("TEST FAILURE: Method Debugee.classByName() returned null for "
185                     + classes[i] + "\n");
186                 return quitDebuggee();
187             }
188             try {
189                 clsMethods = rType.methods();
190             } catch (Exception e) {
191                 tot_res = Consts.TEST_FAILED;
192                 log.complain("TEST FAILURE: ReferenceType.methods: caught " + e
193                     + "\n");
194                 return quitDebuggee();
195             }
196 
197             Iterator iterator = clsMethods.iterator();
198             while(iterator.hasNext()) {
199                 Method meth = (Method) iterator.next();
200                 log.display("\t--> method " + meth
201                     + "\n\t\tname " + meth.name()
202                     + "\n\t\treturn type " + meth.returnTypeName()
203                     + "\n\t\tsignature " + meth.signature());
204 
205                 int idx = findMethod(i, meth.signature());
206                 if (idx != -1) {
207                     try {
208                         int methCounter = Integer.parseInt(methods[i][idx][3]);
209                         methCounter++;
210                         methods[i][idx][3] = String.valueOf(methCounter);
211                     } catch (NumberFormatException e) {
212                         tot_res = Consts.TEST_FAILED;
213                         log.complain("TEST BUG: Integer.parseInt: caught " + e);
214                         return quitDebuggee();
215                     }
216                     boolean bridge = new Boolean(methods[i][idx][2]);
217                     if (bridge == meth.isBridge())
218                         log.display("\tCHECK PASSED: Method.isBridge() returns "
219                             + meth.isBridge() + " as expected\n");
220                     else {
221                         tot_res = Consts.TEST_FAILED;
222                         log.complain("TEST FAILED: Method.isBridge() returns "
223                             + meth.isBridge()
224                             + "\n\tfor the method: " + meth.name()
225                             + " " + meth.signature()
226                             + "\n\tExpected: "+ methods[i][idx][2] + "\n");
227                     }
228                 }
229             }
230 
231             log.display("<<<<<<");
232         }
233 
234         for (int i=0; i<CLS_NUM; i++) {
235             int j = 0;
236 
237             while(true) {
238                 try {
239                     if (methods[i][j][3].equals("0")) {
240                         tot_res = Consts.TEST_FAILED;
241                         log.complain("TEST FAILED: Method " + methods[i][j][0]
242                             + " " + methods[i][j][1]
243                             + "\n\tfrom the class " + classes[i]
244                             + "\n\twas not returned by the ReferenceType.methods()\n");
245                     }
246 
247                     j++;
248                 } catch(ArrayIndexOutOfBoundsException e) {
249                     break;
250                 }
251             }
252         }
253 
254         return quitDebuggee();
255     }
256 
quitDebuggee()257     private int quitDebuggee() {
258         pipe.println(COMMAND_QUIT);
259         debuggee.waitFor();
260         int debStat = debuggee.getStatus();
261         if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) {
262             tot_res = Consts.TEST_FAILED;
263             log.complain("TEST FAILED: debuggee's process finished with status: "
264                 + debStat);
265         } else
266             log.display("Debuggee's process finished with status: "
267                 + debStat);
268 
269         return tot_res;
270     }
271 
findMethod(int clsIdx, String signature)272     private int findMethod(int clsIdx, String signature) {
273         int i=0;
274 
275         while(true) {
276             try {
277                 if (signature.equals(methods[clsIdx][i][1]))
278                     return i; // the tested method found
279 
280                 i++;
281             } catch(ArrayIndexOutOfBoundsException e) {
282                 break;
283             }
284         }
285 
286         return -1; // the tested method not found
287     }
288 }
289