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 
  62     MultiBreakpointsTarg(int numThreads, int numHits) {
  63         for (int ii = 0; ii < numThreads; ii++) {
  64             console(ii, numHits);
  65         }
  66     }
  67 
  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 
  99     void bkpt0() {}
 100     void bkpt1() {}
 101     void bkpt2() {}
 102     void bkpt3() {}
 103     void bkpt4() {}
 104     void bkpt5() {}
 105     void bkpt6() {}
 106     void bkpt7() {}
 107     void bkpt8() {}
 108     void bkpt9() {}
 109     void bkpt10() {}
 110     void bkpt11() {}
 111     void bkpt12() {}
 112     void bkpt13() {}
 113     void bkpt14() {}
 114     void bkpt15() {}
 115     void bkpt16() {}
 116     void bkpt17() {}
 117     void bkpt18() {}
 118     void bkpt19() {}
 119     void bkpt20() {}
 120     void bkpt21() {}
 121     void bkpt22() {}
 122     void bkpt23() {}
 123     void bkpt24() {}
 124     void bkpt25() {}
 125     void bkpt26() {}
 126     void bkpt27() {}
 127     void bkpt28() {}
 128     void bkpt29() {}
 129 
 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 
 210     MultiBreakpointsTest (String args[]) {
 211         super(args);
 212         bkpts = new BreakpointRequest[nthreads];
 213         hits = new int[nthreads];
 214     }
 215 
 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 
 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 
 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 
 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 }