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