1 /*
2  * Copyright (c) 2001, 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 /**
26  * @test
27  * @bug 4359247
28  * @summary Breakpoints on multiple threads have problems.
29  * @author tbell, jjh
30  *
31  * @build TestScaffold VMConnection TargetListener TargetAdapter
32  * @run compile -g MultiBreakpointsTest.java
33  * @run driver MultiBreakpointsTest
34  */
35 
36 /*
37  * This test runs a debuggee with n threads each of which just loops
38  * doing some printlns and calling a method.  The debugger sets
39  * bkpts on these methods and verifies that they are all hit.
40  * The default number of threads is 4.  To change it to say 10,
41  * pass this to the testcase on the cmd line:
42  *      -Dnthreads=10
43  * The current max allowed value of nthreads is 30.
44  * You can also do this, for example,
45  *     -Dnhits=30
46  * to change the number of times the bkpts are to be hit from
47  * the default of 100 to 30.
48  */
49 import com.sun.jdi.*;
50 import com.sun.jdi.event.*;
51 import com.sun.jdi.request.*;
52 
53 import java.util.*;
54 
55 /********** target program **********/
56 
57 import java.io.*;
58 import java.text.*;
59 
60 class MultiBreakpointsTarg {
61 
MultiBreakpointsTarg(int numThreads, int numHits)62     MultiBreakpointsTarg(int numThreads, int numHits) {
63         for (int ii = 0; ii < numThreads; ii++) {
64             console(ii, numHits);
65         }
66     }
67 
main(String args[])68     public static void main(String args[]) {
69 
70         int nthreads;
71         int nhits;
72         String nStr = System.getProperty("nthreads");
73 
74         if (nStr == null) {
75             throw new RuntimeException("nthreads = null in debuggee");
76         }
77         nthreads = Integer.parseInt(nStr);
78 
79         nStr = System.getProperty("nhits");
80         if (nStr == null) {
81             throw new RuntimeException("nhits = null in debuggee");
82         }
83         nhits = Integer.parseInt(nStr);
84 
85         System.out.println("Debuggee: nthreads = " + nthreads + ", nhits = " + nhits);
86 
87         MultiBreakpointsTarg ptr = new MultiBreakpointsTarg(nthreads, nhits);
88 
89 //         for (int i = 0; i < nthreads; i++) {
90 //             ptr.console(i);
91 //         }
92     }
93 
94     // The brute force approach for simplicity - don't use reflection
95     // nor set thread specific bkpts.  Use of those features would
96     // make for interesting tests too, and maybe would prove that
97     // we don't really have to bother doing it this dumb way.
98 
bkpt0()99     void bkpt0() {}
bkpt1()100     void bkpt1() {}
bkpt2()101     void bkpt2() {}
bkpt3()102     void bkpt3() {}
bkpt4()103     void bkpt4() {}
bkpt5()104     void bkpt5() {}
bkpt6()105     void bkpt6() {}
bkpt7()106     void bkpt7() {}
bkpt8()107     void bkpt8() {}
bkpt9()108     void bkpt9() {}
bkpt10()109     void bkpt10() {}
bkpt11()110     void bkpt11() {}
bkpt12()111     void bkpt12() {}
bkpt13()112     void bkpt13() {}
bkpt14()113     void bkpt14() {}
bkpt15()114     void bkpt15() {}
bkpt16()115     void bkpt16() {}
bkpt17()116     void bkpt17() {}
bkpt18()117     void bkpt18() {}
bkpt19()118     void bkpt19() {}
bkpt20()119     void bkpt20() {}
bkpt21()120     void bkpt21() {}
bkpt22()121     void bkpt22() {}
bkpt23()122     void bkpt23() {}
bkpt24()123     void bkpt24() {}
bkpt25()124     void bkpt25() {}
bkpt26()125     void bkpt26() {}
bkpt27()126     void bkpt27() {}
bkpt28()127     void bkpt28() {}
bkpt29()128     void bkpt29() {}
129 
console(final int num, final int nhits)130     void console(final int num, final int nhits) {
131         final InputStreamReader isr = new InputStreamReader(System.in);
132         final BufferedReader    br  = new BufferedReader(isr);
133 
134         // Create the threads
135         //
136         //final String threadName = "DebuggeeThread: " + num;
137         final String threadName = "" + num;
138         Thread thrd = new Thread( threadName ) {
139                 public void run() {
140                     synchronized( isr ) {
141                         boolean done = false;
142                         try {
143                             // For each thread, run until numHits bkpts have been hit
144                             for( int i = 0; i < nhits; i++ ) {
145                                 // This is a tendril from the original jdb test.
146                                 // It could probably be deleted.
147                                 System.out.println("Thread " + threadName + " Enter a string: ");
148                                 String s = "test" + num;
149                                 switch (num) {
150                                 case 0: bkpt0(); break;
151                                 case 1: bkpt1(); break;
152                                 case 2: bkpt2(); break;
153                                 case 3: bkpt3(); break;
154                                 case 4: bkpt4(); break;
155                                 case 5: bkpt5(); break;
156                                 case 6: bkpt6(); break;
157                                 case 7: bkpt7(); break;
158                                 case 8: bkpt8(); break;
159                                 case 9: bkpt9(); break;
160                                 case 10: bkpt10(); break;
161                                 case 11: bkpt11(); break;
162                                 case 12: bkpt12(); break;
163                                 case 13: bkpt13(); break;
164                                 case 14: bkpt14(); break;
165                                 case 15: bkpt15(); break;
166                                 case 16: bkpt16(); break;
167                                 case 17: bkpt17(); break;
168                                 case 18: bkpt18(); break;
169                                 case 19: bkpt19(); break;
170                                 case 20: bkpt20(); break;
171                                 case 21: bkpt21(); break;
172                                 case 22: bkpt22(); break;
173                                 case 23: bkpt23(); break;
174                                 case 24: bkpt24(); break;
175                                 case 25: bkpt25(); break;
176                                 case 26: bkpt26(); break;
177                                 case 27: bkpt27(); break;
178                                 case 28: bkpt28(); break;
179                                 case 29: bkpt29(); break;
180                                 }
181                                 System.out.println("Thread " + threadName + " You entered : " + s);
182 
183                                 if( s.compareTo( "quit" ) == 0 )
184                                     done = true;
185                             }
186                         } catch(Exception e) {
187                             System.out.println("WOOPS");
188                         }
189                     }
190                 }
191             };
192         thrd.setPriority(Thread.MAX_PRIORITY-1);
193         thrd.start();
194     }
195 }
196 
197 /********** test program **********/
198 
199 public class MultiBreakpointsTest extends TestScaffold {
200     ReferenceType targetClass;
201     ThreadReference mainThread;
202     EventRequestManager erm;
203 
204     static int nthreads;
205     static int nhits;
206 
207     BreakpointRequest bkpts[];
208     int hits[];
209 
MultiBreakpointsTest(String args[])210     MultiBreakpointsTest (String args[]) {
211         super(args);
212         bkpts = new BreakpointRequest[nthreads];
213         hits = new int[nthreads];
214     }
215 
main(String[] args)216     public static void main(String[] args)      throws Exception {
217         String countStr = System.getProperty("nthreads");
218         if (countStr == null) {
219             nthreads = 4;
220         } else {
221             nthreads = Integer.parseInt(countStr);
222         }
223         if ( nthreads > 30) {
224             throw new RuntimeException("nthreads is greater than 30: " + nthreads);
225         }
226         countStr = System.getProperty("nhits");
227         if (countStr == null) {
228             nhits = 100;
229         } else {
230             nhits = Integer.parseInt(countStr);
231         }
232 
233         args = new String[] { "-J-Dnthreads=" + nthreads, "-J-Dnhits=" + nhits} ;
234         new MultiBreakpointsTest(args).startTests();
235     }
236 
237     /********** event handlers **********/
238 
239 
breakpointReached(BreakpointEvent event)240     public void breakpointReached(BreakpointEvent event) {
241         BreakpointRequest req = (BreakpointRequest)event.request();
242         for ( int ii = 0; ii < nthreads; ii++) {
243             if (req == bkpts[ii]) {
244                 println("Hit bkpt on thread: " +ii+ ": " +  ++hits[ii]);
245                 break;
246             }
247         }
248     }
249 
250 
setBreakpoint(String clsName, String methodName, String methodSignature)251     public BreakpointRequest setBreakpoint(String clsName,
252                                            String methodName,
253                                            String methodSignature) {
254         ReferenceType rt = findReferenceType(clsName);
255         if (rt == null) {
256             rt = resumeToPrepareOf(clsName).referenceType();
257         }
258 
259         Method method = findMethod(rt, methodName, methodSignature);
260         if (method == null) {
261             throw new IllegalArgumentException("Bad method name/signature");
262         }
263         BreakpointRequest bpr = erm.createBreakpointRequest(method.location());
264         bpr.setSuspendPolicy(EventRequest.SUSPEND_ALL);
265         //bpr.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
266         bpr.enable();
267         return bpr;
268     }
269 
270     /********** test core **********/
271 
runTests()272     protected void runTests() throws Exception {
273         /*
274          * Get to the top of main()
275          * to determine targetClass and mainThread
276          */
277 
278         BreakpointEvent bpe = startToMain("MultiBreakpointsTarg");
279 
280         targetClass = bpe.location().declaringType();
281         mainThread = bpe.thread();
282         erm = vm().eventRequestManager();
283 
284         for (int ii = 0 ; ii < nthreads; ii++) {
285             bkpts[ii] = setBreakpoint("MultiBreakpointsTarg",
286                               "bkpt" + ii,
287                               "()V");
288         }
289         /*
290          * resume the target listening for events
291          */
292         listenUntilVMDisconnect();
293 
294         for ( int ii = 0; ii < nthreads; ii++) {
295             if (hits[ii] != nhits) {
296                 failure("FAILED: Expected " + nhits + " breakpoints for thread " + ii + " but only got " + hits[ii]);
297             }
298         }
299 
300         /*
301          * deal with results of test
302          * if anything has called failure("foo") testFailed will be true
303          */
304         if (!testFailed) {
305             println("MultiBreakpointsTest: passed");
306         } else {
307             throw new Exception("MultiBreakpointsTest: failed");
308         }
309     }
310 }
311