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