--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jdi/MethodEntryExitEvents.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 4409241 4432820
+ * @summary Test the bug fix for: MethodExitEvents disappear when Object-Methods are called from main
+ * @author Tim Bell
+ *
+ * @run build TestScaffold VMConnection TargetListener TargetAdapter
+ * @run compile -g MethodEntryExitEvents.java
+ * @run main MethodEntryExitEvents SUSPEND_EVENT_THREAD MethodEntryExitEventsDebugee
+ * @run main MethodEntryExitEvents SUSPEND_NONE MethodEntryExitEventsDebugee
+ * @run main MethodEntryExitEvents SUSPEND_ALL MethodEntryExitEventsDebugee
+ */
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+import java.util.*;
+
+class t2 {
+ public static void sayHello1(int i, int j) {
+ sayHello2(i, j);
+ }
+ public static void sayHello2(int i, int j) {
+ sayHello3(i, j);
+ }
+ public static void sayHello3(int i, int j) {
+ sayHello4(i, j);
+ }
+ public static void sayHello4(int i, int j) {
+ sayHello5(i, j);
+ }
+ public static void sayHello5(int i, int j) {
+ if (i < 2) {
+ sayHello1(++i, j);
+ } else {
+ System.out.print ("MethodEntryExitEventsDebugee: ");
+ System.out.print (" -->> Hello. j is: ");
+ System.out.print (j);
+ System.out.println(" <<--");
+ }
+ }
+}
+
+class MethodEntryExitEventsDebugee {
+ public static void loopComplete () {
+ /*
+ * The implementation here is deliberately inefficient
+ * because the debugger is still watching this method.
+ */
+ StringBuffer sb = new StringBuffer();
+ sb.append ("MethodEntryExitEventsDebugee: ");
+ sb.append ("Executing loopComplete method for a graceful shutdown...");
+ String s = sb.toString();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ System.out.print(c);
+ }
+ System.out.println();
+ }
+ public static void main(String[] args) {
+ t2 test = new t2();
+ for (int j = 0; j < 3; j++) {
+ test.sayHello1(0, j);
+ }
+ loopComplete();
+ }
+}
+
+
+public class MethodEntryExitEvents extends TestScaffold {
+ int sessionSuspendPolicy = EventRequest.SUSPEND_ALL;
+ StepRequest stepReq = null; //Only one step request allowed per thread
+ boolean finishedCounting = false;
+
+ /*
+ * Enter main() , then t2.<init>, then sayHello[1,2,3,4,5] 15 times 3 loops,
+ * then loopComplete()
+ */
+ final int expectedEntryCount = 1 + 1 + (15 * 3) + 1;
+ int methodEntryCount = 0;
+
+ /*
+ * Exit t2.<init>, then sayHello[1,2,3,4,5] 15 times 3 loopa
+ * (event monitoring is cancelled before we exit loopComplete() or main())
+ */
+ final int expectedExitCount = 1 + (15 * 3);
+ int methodExitCount = 0;
+
+ /*
+ * Class patterns for which we don't want events (copied
+ * from the "Trace.java" example):
+ * http://java.sun.com/javase/technologies/core/toolsapis/jpda/
+ */
+ private String[] excludes = {"java.*", "javax.*", "sun.*",
+ "com.sun.*"};
+
+ MethodEntryExitEvents (String args[]) {
+ super(args);
+ }
+
+ private void usage(String[] args) throws Exception {
+ StringBuffer sb = new StringBuffer("Usage: ");
+ sb.append(System.getProperty("line.separator"));
+ sb.append(" java ");
+ sb.append(getClass().getName());
+ sb.append(" [SUSPEND_NONE | SUSPEND_EVENT_THREAD | SUSPEND_ALL]");
+ sb.append(" [MethodEntryExitEventsDebugee | -connect <connector options...>] ");
+ throw new Exception (sb.toString());
+ }
+
+ public static void main(String[] args) throws Exception {
+ MethodEntryExitEvents meee = new MethodEntryExitEvents (args);
+ meee.startTests();
+ }
+
+ public void exceptionThrown(ExceptionEvent event) {
+ System.out.println("Exception: " + event.exception());
+ System.out.println(" at catch location: " + event.catchLocation());
+
+ // Step to the catch
+ if (stepReq == null) {
+ stepReq =
+ eventRequestManager().createStepRequest(event.thread(),
+ StepRequest.STEP_MIN,
+ StepRequest.STEP_INTO);
+ stepReq.addCountFilter(1); // next step only
+ stepReq.setSuspendPolicy(EventRequest.SUSPEND_ALL);
+ }
+ stepReq.enable();
+ }
+ public void stepCompleted(StepEvent event) {
+ System.out.println("stepCompleted: line#=" +
+ event.location().lineNumber() +
+ " event=" + event);
+ // disable the step and then run to completion
+ //eventRequestManager().deleteEventRequest(event.request());
+ StepRequest str= (StepRequest)event.request();
+ str.disable();
+ }
+ public void methodEntered(MethodEntryEvent event) {
+ if (! finishedCounting) {
+ // We have to count the entry to loopComplete, but
+ // not the exit
+ methodEntryCount++;
+ System.out.print (" Method entry number: ");
+ System.out.print (methodEntryCount);
+ System.out.print (" : ");
+ System.out.println(event);
+ if ("loopComplete".equals(event.method().name())) {
+ finishedCounting = true;
+ }
+ }
+ }
+
+ public void methodExited(MethodExitEvent event) {
+ if (! finishedCounting){
+ methodExitCount++;
+ System.out.print (" Method exit number: ");
+ System.out.print (methodExitCount);
+ System.out.print (" : ");
+ System.out.println(event);
+ }
+ }
+
+ protected void runTests() throws Exception {
+ if (args.length < 1) {
+ usage(args);
+ }
+ //Pick up the SUSPEND_xxx in first argument
+ if ("SUSPEND_NONE".equals(args[0])) {
+ sessionSuspendPolicy = EventRequest.SUSPEND_NONE;
+ } else if ("SUSPEND_EVENT_THREAD".equals(args[0])) {
+ sessionSuspendPolicy = EventRequest.SUSPEND_EVENT_THREAD;
+ } else if ("SUSPEND_ALL".equals(args[0])) {
+ sessionSuspendPolicy = EventRequest.SUSPEND_ALL;
+ } else {
+ usage(args);
+ }
+ System.out.print("Suspend policy is: ");
+ System.out.println(args[0]);
+
+ // Skip the test arg
+ String[] args2 = new String[args.length - 1];
+ System.arraycopy(args, 1, args2, 0, args.length - 1);
+
+ if (args2.length < 1) {
+ usage(args2);
+ }
+ List argList = new ArrayList(Arrays.asList(args2));
+ System.out.println("run args: " + argList);
+ connect((String[]) argList.toArray(args2));
+ waitForVMStart();
+
+ try {
+
+ /*
+ * Ask for Exception events
+ */
+ ExceptionRequest exceptionRequest =
+ eventRequestManager().createExceptionRequest(null, // refType (null == all instances)
+ true, // notifyCaught
+ true);// notifyUncaught
+ exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
+ exceptionRequest.enable();
+
+ /*
+ * Ask for method entry events
+ */
+ MethodEntryRequest entryRequest =
+ eventRequestManager().createMethodEntryRequest();
+ for (int i=0; i<excludes.length; ++i) {
+ entryRequest.addClassExclusionFilter(excludes[i]);
+ }
+ entryRequest.setSuspendPolicy(sessionSuspendPolicy);
+ entryRequest.enable();
+
+ /*
+ * Ask for method exit events
+ */
+ MethodExitRequest exitRequest =
+ eventRequestManager().createMethodExitRequest();
+
+ for (int i=0; i<excludes.length; ++i) {
+ exitRequest.addClassExclusionFilter(excludes[i]);
+ }
+ exitRequest.setSuspendPolicy(sessionSuspendPolicy);
+ exitRequest.enable();
+
+ /*
+ * We are now set up to receive the notifications we want.
+ * Here we go. This adds 'this' as a listener so
+ * that our handlers above will be called.
+ */
+
+ listenUntilVMDisconnect();
+ System.out.println("All done...");
+
+ } catch (Exception ex){
+ ex.printStackTrace();
+ testFailed = true;
+ }
+
+ if ((methodEntryCount != expectedEntryCount) ||
+ (methodExitCount != expectedExitCount)) {
+ testFailed = true;
+ }
+ if (!testFailed) {
+ System.out.println();
+ System.out.println("MethodEntryExitEvents: passed");
+ System.out.print (" Method entry count: ");
+ System.out.println(methodEntryCount);
+ System.out.print (" Method exit count: ");
+ System.out.println(methodExitCount);
+ } else {
+ System.out.println();
+ System.out.println("MethodEntryExitEvents: failed");
+ System.out.print (" expected method entry count: ");
+ System.out.println(expectedEntryCount);
+ System.out.print (" observed method entry count: ");
+ System.out.println(methodEntryCount);
+ System.out.print (" expected method exit count: ");
+ System.out.println(expectedExitCount);
+ System.out.print (" observed method exit count: ");
+ System.out.println(methodExitCount);
+ throw new Exception("MethodEntryExitEvents: failed");
+ }
+ }
+}