J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2001-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 21 | * have any questions. |
| 22 | */ |
| 23 | |
| 24 | /** |
| 25 | * @test |
| 26 | * @bug 4409241 4432820 |
| 27 | * @summary Test the bug fix for: MethodExitEvents disappear when Object-Methods are called from main |
| 28 | * @author Tim Bell |
| 29 | * |
| 30 | * @run build TestScaffold VMConnection TargetListener TargetAdapter |
| 31 | * @run compile -g MethodEntryExitEvents.java |
| 32 | * @run main MethodEntryExitEvents SUSPEND_EVENT_THREAD MethodEntryExitEventsDebugee |
| 33 | * @run main MethodEntryExitEvents SUSPEND_NONE MethodEntryExitEventsDebugee |
| 34 | * @run main MethodEntryExitEvents SUSPEND_ALL MethodEntryExitEventsDebugee |
| 35 | */ |
| 36 | import com.sun.jdi.*; |
| 37 | import com.sun.jdi.event.*; |
| 38 | import com.sun.jdi.request.*; |
| 39 | import java.util.*; |
| 40 | |
| 41 | class t2 { |
| 42 | public static void sayHello1(int i, int j) { |
| 43 | sayHello2(i, j); |
| 44 | } |
| 45 | public static void sayHello2(int i, int j) { |
| 46 | sayHello3(i, j); |
| 47 | } |
| 48 | public static void sayHello3(int i, int j) { |
| 49 | sayHello4(i, j); |
| 50 | } |
| 51 | public static void sayHello4(int i, int j) { |
| 52 | sayHello5(i, j); |
| 53 | } |
| 54 | public static void sayHello5(int i, int j) { |
| 55 | if (i < 2) { |
| 56 | sayHello1(++i, j); |
| 57 | } else { |
| 58 | System.out.print ("MethodEntryExitEventsDebugee: "); |
| 59 | System.out.print (" -->> Hello. j is: "); |
| 60 | System.out.print (j); |
| 61 | System.out.println(" <<--"); |
| 62 | } |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | class MethodEntryExitEventsDebugee { |
| 67 | public static void loopComplete () { |
| 68 | /* |
| 69 | * The implementation here is deliberately inefficient |
| 70 | * because the debugger is still watching this method. |
| 71 | */ |
| 72 | StringBuffer sb = new StringBuffer(); |
| 73 | sb.append ("MethodEntryExitEventsDebugee: "); |
| 74 | sb.append ("Executing loopComplete method for a graceful shutdown..."); |
| 75 | String s = sb.toString(); |
| 76 | for (int i = 0; i < s.length(); i++) { |
| 77 | char c = s.charAt(i); |
| 78 | System.out.print(c); |
| 79 | } |
| 80 | System.out.println(); |
| 81 | } |
| 82 | public static void main(String[] args) { |
| 83 | t2 test = new t2(); |
| 84 | for (int j = 0; j < 3; j++) { |
| 85 | test.sayHello1(0, j); |
| 86 | } |
| 87 | loopComplete(); |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | |
| 92 | public class MethodEntryExitEvents extends TestScaffold { |
| 93 | int sessionSuspendPolicy = EventRequest.SUSPEND_ALL; |
| 94 | StepRequest stepReq = null; //Only one step request allowed per thread |
| 95 | boolean finishedCounting = false; |
| 96 | |
| 97 | /* |
| 98 | * Enter main() , then t2.<init>, then sayHello[1,2,3,4,5] 15 times 3 loops, |
| 99 | * then loopComplete() |
| 100 | */ |
| 101 | final int expectedEntryCount = 1 + 1 + (15 * 3) + 1; |
| 102 | int methodEntryCount = 0; |
| 103 | |
| 104 | /* |
| 105 | * Exit t2.<init>, then sayHello[1,2,3,4,5] 15 times 3 loopa |
| 106 | * (event monitoring is cancelled before we exit loopComplete() or main()) |
| 107 | */ |
| 108 | final int expectedExitCount = 1 + (15 * 3); |
| 109 | int methodExitCount = 0; |
| 110 | |
| 111 | /* |
| 112 | * Class patterns for which we don't want events (copied |
| 113 | * from the "Trace.java" example): |
| 114 | * http://java.sun.com/javase/technologies/core/toolsapis/jpda/ |
| 115 | */ |
| 116 | private String[] excludes = {"java.*", "javax.*", "sun.*", |
| 117 | "com.sun.*"}; |
| 118 | |
| 119 | MethodEntryExitEvents (String args[]) { |
| 120 | super(args); |
| 121 | } |
| 122 | |
| 123 | private void usage(String[] args) throws Exception { |
| 124 | StringBuffer sb = new StringBuffer("Usage: "); |
| 125 | sb.append(System.getProperty("line.separator")); |
| 126 | sb.append(" java "); |
| 127 | sb.append(getClass().getName()); |
| 128 | sb.append(" [SUSPEND_NONE | SUSPEND_EVENT_THREAD | SUSPEND_ALL]"); |
| 129 | sb.append(" [MethodEntryExitEventsDebugee | -connect <connector options...>] "); |
| 130 | throw new Exception (sb.toString()); |
| 131 | } |
| 132 | |
| 133 | public static void main(String[] args) throws Exception { |
| 134 | MethodEntryExitEvents meee = new MethodEntryExitEvents (args); |
| 135 | meee.startTests(); |
| 136 | } |
| 137 | |
| 138 | public void exceptionThrown(ExceptionEvent event) { |
| 139 | System.out.println("Exception: " + event.exception()); |
| 140 | System.out.println(" at catch location: " + event.catchLocation()); |
| 141 | |
| 142 | // Step to the catch |
| 143 | if (stepReq == null) { |
| 144 | stepReq = |
| 145 | eventRequestManager().createStepRequest(event.thread(), |
| 146 | StepRequest.STEP_MIN, |
| 147 | StepRequest.STEP_INTO); |
| 148 | stepReq.addCountFilter(1); // next step only |
| 149 | stepReq.setSuspendPolicy(EventRequest.SUSPEND_ALL); |
| 150 | } |
| 151 | stepReq.enable(); |
| 152 | } |
| 153 | public void stepCompleted(StepEvent event) { |
| 154 | System.out.println("stepCompleted: line#=" + |
| 155 | event.location().lineNumber() + |
| 156 | " event=" + event); |
| 157 | // disable the step and then run to completion |
| 158 | //eventRequestManager().deleteEventRequest(event.request()); |
| 159 | StepRequest str= (StepRequest)event.request(); |
| 160 | str.disable(); |
| 161 | } |
| 162 | public void methodEntered(MethodEntryEvent event) { |
| 163 | if (! finishedCounting) { |
| 164 | // We have to count the entry to loopComplete, but |
| 165 | // not the exit |
| 166 | methodEntryCount++; |
| 167 | System.out.print (" Method entry number: "); |
| 168 | System.out.print (methodEntryCount); |
| 169 | System.out.print (" : "); |
| 170 | System.out.println(event); |
| 171 | if ("loopComplete".equals(event.method().name())) { |
| 172 | finishedCounting = true; |
| 173 | } |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | public void methodExited(MethodExitEvent event) { |
| 178 | if (! finishedCounting){ |
| 179 | methodExitCount++; |
| 180 | System.out.print (" Method exit number: "); |
| 181 | System.out.print (methodExitCount); |
| 182 | System.out.print (" : "); |
| 183 | System.out.println(event); |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | protected void runTests() throws Exception { |
| 188 | if (args.length < 1) { |
| 189 | usage(args); |
| 190 | } |
| 191 | //Pick up the SUSPEND_xxx in first argument |
| 192 | if ("SUSPEND_NONE".equals(args[0])) { |
| 193 | sessionSuspendPolicy = EventRequest.SUSPEND_NONE; |
| 194 | } else if ("SUSPEND_EVENT_THREAD".equals(args[0])) { |
| 195 | sessionSuspendPolicy = EventRequest.SUSPEND_EVENT_THREAD; |
| 196 | } else if ("SUSPEND_ALL".equals(args[0])) { |
| 197 | sessionSuspendPolicy = EventRequest.SUSPEND_ALL; |
| 198 | } else { |
| 199 | usage(args); |
| 200 | } |
| 201 | System.out.print("Suspend policy is: "); |
| 202 | System.out.println(args[0]); |
| 203 | |
| 204 | // Skip the test arg |
| 205 | String[] args2 = new String[args.length - 1]; |
| 206 | System.arraycopy(args, 1, args2, 0, args.length - 1); |
| 207 | |
| 208 | if (args2.length < 1) { |
| 209 | usage(args2); |
| 210 | } |
| 211 | List argList = new ArrayList(Arrays.asList(args2)); |
| 212 | System.out.println("run args: " + argList); |
| 213 | connect((String[]) argList.toArray(args2)); |
| 214 | waitForVMStart(); |
| 215 | |
| 216 | try { |
| 217 | |
| 218 | /* |
| 219 | * Ask for Exception events |
| 220 | */ |
| 221 | ExceptionRequest exceptionRequest = |
| 222 | eventRequestManager().createExceptionRequest(null, // refType (null == all instances) |
| 223 | true, // notifyCaught |
| 224 | true);// notifyUncaught |
| 225 | exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); |
| 226 | exceptionRequest.enable(); |
| 227 | |
| 228 | /* |
| 229 | * Ask for method entry events |
| 230 | */ |
| 231 | MethodEntryRequest entryRequest = |
| 232 | eventRequestManager().createMethodEntryRequest(); |
| 233 | for (int i=0; i<excludes.length; ++i) { |
| 234 | entryRequest.addClassExclusionFilter(excludes[i]); |
| 235 | } |
| 236 | entryRequest.setSuspendPolicy(sessionSuspendPolicy); |
| 237 | entryRequest.enable(); |
| 238 | |
| 239 | /* |
| 240 | * Ask for method exit events |
| 241 | */ |
| 242 | MethodExitRequest exitRequest = |
| 243 | eventRequestManager().createMethodExitRequest(); |
| 244 | |
| 245 | for (int i=0; i<excludes.length; ++i) { |
| 246 | exitRequest.addClassExclusionFilter(excludes[i]); |
| 247 | } |
| 248 | exitRequest.setSuspendPolicy(sessionSuspendPolicy); |
| 249 | exitRequest.enable(); |
| 250 | |
| 251 | /* |
| 252 | * We are now set up to receive the notifications we want. |
| 253 | * Here we go. This adds 'this' as a listener so |
| 254 | * that our handlers above will be called. |
| 255 | */ |
| 256 | |
| 257 | listenUntilVMDisconnect(); |
| 258 | System.out.println("All done..."); |
| 259 | |
| 260 | } catch (Exception ex){ |
| 261 | ex.printStackTrace(); |
| 262 | testFailed = true; |
| 263 | } |
| 264 | |
| 265 | if ((methodEntryCount != expectedEntryCount) || |
| 266 | (methodExitCount != expectedExitCount)) { |
| 267 | testFailed = true; |
| 268 | } |
| 269 | if (!testFailed) { |
| 270 | System.out.println(); |
| 271 | System.out.println("MethodEntryExitEvents: passed"); |
| 272 | System.out.print (" Method entry count: "); |
| 273 | System.out.println(methodEntryCount); |
| 274 | System.out.print (" Method exit count: "); |
| 275 | System.out.println(methodExitCount); |
| 276 | } else { |
| 277 | System.out.println(); |
| 278 | System.out.println("MethodEntryExitEvents: failed"); |
| 279 | System.out.print (" expected method entry count: "); |
| 280 | System.out.println(expectedEntryCount); |
| 281 | System.out.print (" observed method entry count: "); |
| 282 | System.out.println(methodEntryCount); |
| 283 | System.out.print (" expected method exit count: "); |
| 284 | System.out.println(expectedExitCount); |
| 285 | System.out.print (" observed method exit count: "); |
| 286 | System.out.println(methodExitCount); |
| 287 | throw new Exception("MethodEntryExitEvents: failed"); |
| 288 | } |
| 289 | } |
| 290 | } |