1 /*
2  * Copyright (c) 2001, 2019, 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  * @test
26  * @bug 4407397
27  * @key intermittent
28  * @summary Test the requesting of exception events
29  * @author Robert Field
30  *
31  * @run build TestScaffold VMConnection
32  * @run compile -g ExceptionEvents.java
33  *
34  * @run driver ExceptionEvents N A StackOverflowCaughtTarg java.lang.Exception
35  * @run driver ExceptionEvents C A StackOverflowCaughtTarg null
36  * @run driver ExceptionEvents C A StackOverflowCaughtTarg java.lang.Error
37  * @run driver ExceptionEvents C A StackOverflowCaughtTarg java.lang.StackOverflowError
38  * @run driver ExceptionEvents N A StackOverflowCaughtTarg java.lang.NullPointerException
39 
40  * @run driver ExceptionEvents N T StackOverflowCaughtTarg java.lang.Exception
41  * @run driver ExceptionEvents C T StackOverflowCaughtTarg null
42  * @run driver ExceptionEvents C T StackOverflowCaughtTarg java.lang.Error
43  * @run driver ExceptionEvents C T StackOverflowCaughtTarg java.lang.StackOverflowError
44  * @run driver ExceptionEvents N T StackOverflowCaughtTarg java.lang.NullPointerException
45 
46  * @run driver ExceptionEvents N N StackOverflowCaughtTarg java.lang.Exception
47  * @run driver ExceptionEvents C N StackOverflowCaughtTarg null
48  * @run driver ExceptionEvents C N StackOverflowCaughtTarg java.lang.Error
49  * @run driver ExceptionEvents C N StackOverflowCaughtTarg java.lang.StackOverflowError
50  * @run driver ExceptionEvents N N StackOverflowCaughtTarg java.lang.NullPointerException
51 
52  * @run driver ExceptionEvents N A StackOverflowUncaughtTarg java.lang.Exception
53  * @run driver ExceptionEvents U A StackOverflowUncaughtTarg null
54  * @run driver ExceptionEvents U A StackOverflowUncaughtTarg java.lang.Error
55  * @run driver ExceptionEvents U A StackOverflowUncaughtTarg java.lang.StackOverflowError
56  * @run driver ExceptionEvents N A StackOverflowUncaughtTarg java.lang.NullPointerException
57 
58  * @run driver ExceptionEvents N T StackOverflowUncaughtTarg java.lang.NullPointerException
59  * @run driver ExceptionEvents N N StackOverflowUncaughtTarg java.lang.NullPointerException
60 
61  */
62 import com.sun.jdi.*;
63 import com.sun.jdi.event.*;
64 import com.sun.jdi.request.*;
65 import java.util.*;
66 
67 class StackOverflowCaughtTarg {
main(String[] args)68     public static void main(String[] args) {
69         try {
70             throw new StackOverflowError();
71         } catch (Throwable exc) {
72             // ignore
73         }
74     }
75 }
76 
77 class StackOverflowUncaughtTarg {
main(String[] args)78     public static void main(String[] args) {
79         thrower();
80     }
thrower()81     static void thrower()  {
82         throw new StackOverflowError();
83     }
84 }
85 
86 class StackOverflowIndirectTarg {
main(String[] args)87     public static void main(String[] args) {
88         try {
89             thrower();
90         } catch (Throwable exc) {
91             System.out.println("Got exception: " + exc);
92         }
93     }
thrower()94     static void thrower()  {
95         throw new StackOverflowError();
96     }
97 }
98 
99 public class ExceptionEvents extends TestScaffold {
100     static int failureCount = 0;
101     static StringBuffer tooManySummary = new StringBuffer();
102     static StringBuffer notSentSummary = new StringBuffer();
103     static StringBuffer unexpectedSummary = new StringBuffer();
104     static int globalSuspendPolicy = -1;
105     static String[] flags;
106 
107     final String target;
108     final String exceptionName;
109     final boolean caught;
110     final boolean uncaught;
111     final int suspendPolicy;
112 
113     int eventCount = 0;
114     ExceptionRequest request;
115 
ExceptionEvents(String target, String exceptionName, boolean caught, boolean uncaught, int suspendPolicy)116     ExceptionEvents(String target,
117                     String exceptionName,
118                     boolean caught, boolean uncaught,
119                     int suspendPolicy) {
120         super(flags);
121         this.target = target;
122         this.exceptionName = exceptionName;
123         this.caught = caught;
124         this.uncaught = uncaught;
125         this.suspendPolicy = suspendPolicy;
126     }
127 
everything()128     static void everything() throws Exception {
129         goNeither("StackOverflowCaughtTarg", "java.lang.Exception");
130         goCaught("StackOverflowCaughtTarg", null);
131         goCaught("StackOverflowCaughtTarg", "java.lang.Error");
132         goCaught("StackOverflowCaughtTarg", "java.lang.StackOverflowError");
133         goNeither("StackOverflowCaughtTarg", "java.lang.NullPointerException");
134 
135         goNeither("StackOverflowUncaughtTarg", "java.lang.Exception");
136         goUncaught("StackOverflowUncaughtTarg", null);
137         goUncaught("StackOverflowUncaughtTarg", "java.lang.Error");
138         goUncaught("StackOverflowUncaughtTarg", "java.lang.StackOverflowError");
139         goNeither("StackOverflowUncaughtTarg", "java.lang.NullPointerException");
140     }
141 
usage()142     static void usage() throws Exception {
143         System.err.println("Use either with no arguments or");
144         System.err.println("  c|u|n a|t|n <TargetClass> <Exception>|null");
145         System.err.println("or for verbose folk");
146         System.err.println("  caught|uncaught|neither all|thread|none <TargetClass> <Exception>|null");
147         throw new IllegalArgumentException("see usage");
148     }
149 
main(String[] args)150     public static void main(String[] args) throws Exception {
151         StringBuffer testName = new StringBuffer("ExceptionEvents(");
152         List flagList = new ArrayList();
153         List argList = new ArrayList();
154 
155         for (int i = 0; i < args.length; ++i) {
156             String arg = args[i];
157             if (arg.startsWith("-")) {
158                 flagList.add(arg);
159             } else {
160                 argList.add(arg);
161             }
162         }
163         flags = (String[])flagList.toArray(new String[0]);
164         args = (String[])argList.toArray(new String[0]);
165         if (args.length == 0) {
166             everything();
167             testName.append("Full Test");
168         } else if (args.length == 4) {
169             switch (args[1].toLowerCase().charAt(0)) {
170             case 'a':
171                 globalSuspendPolicy = EventRequest.SUSPEND_ALL;
172                 break;
173             case 't':
174                 globalSuspendPolicy = EventRequest.SUSPEND_EVENT_THREAD;
175                 break;
176             case 'n':
177                 globalSuspendPolicy = EventRequest.SUSPEND_NONE;
178                 break;
179             default:
180                 usage();
181             }
182             String excString = args[3];
183             if (excString.equals("null")) {
184                 excString = null;
185             }
186             switch (args[0].toLowerCase().charAt(0)) {
187             case 'c':
188                 goCaught(args[2], excString);
189                 break;
190             case 'u':
191                 goUncaught(args[2], excString);
192                 break;
193             case 'n':
194                 goNeither(args[2], excString);
195                 break;
196             default:
197                 usage();
198             }
199             testName.append(args[0]);
200             testName.append(" ");
201             testName.append(args[1]);
202             testName.append(" ");
203             testName.append(args[2]);
204         } else {
205             usage();
206         }
207         testName.append(")");
208 
209         summarize(testName.toString());
210     }
211 
summarize(String testName)212     static void summarize(String testName) throws Exception {
213         // final analyse
214         if (tooManySummary.length() > 0) {
215             System.out.println("\nSummary of tests with too many events:\n" +
216                                tooManySummary.toString());
217         }
218         if (notSentSummary.length() > 0) {
219             System.out.println("\nSummary of tests with expected events not sent:\n" +
220                                notSentSummary.toString());
221         }
222         if (unexpectedSummary.length() > 0) {
223             System.out.println("\nSummary of tests with events when none expected:\n" +
224                                unexpectedSummary.toString());
225         }
226 
227         if (failureCount > 0) {
228             throw new Exception(testName + " FAILED " +
229                                 failureCount + " tests!");
230         } else {
231             System.out.println("\n" + testName + " test PASSED");
232        }
233     }
234 
235     /**
236      * Target throws caught exception.
237      * Events if caught enabled.
238      */
goCaught(String target, String exceptionName)239     static void goCaught(String target,
240                          String exceptionName) throws Exception {
241         goSuspendPolicy(target, true, exceptionName,
242                         true, true);
243         goSuspendPolicy(target, true, exceptionName,
244                         true, false);
245         goSuspendPolicy(target, false, exceptionName,
246                         false, true);
247         goSuspendPolicy(target, false, exceptionName,
248                         false, false);
249     }
250 
251     /**
252      * Target throws uncaught exception.
253      * Events if uncaught enabled.
254      */
goUncaught(String target, String exceptionName)255     static void goUncaught(String target,
256                            String exceptionName) throws Exception {
257         goSuspendPolicy(target, true, exceptionName,
258                         true, true);
259         goSuspendPolicy(target, true, exceptionName,
260                         false, true);
261         goSuspendPolicy(target, false, exceptionName,
262                         true, false);
263         goSuspendPolicy(target, false, exceptionName,
264                         false, false);
265     }
266 
267     /**
268      * Target doesn't throw named exception.  No events.
269      */
goNeither(String target, String exceptionName)270     static void goNeither(String target,
271                            String exceptionName) throws Exception {
272         goSuspendPolicy(target, false, exceptionName,
273                         true, true);
274         goSuspendPolicy(target, false, exceptionName,
275                         false, true);
276         goSuspendPolicy(target, false, exceptionName,
277                         true, false);
278         goSuspendPolicy(target, false, exceptionName,
279                         false, false);
280     }
281 
282     /**
283      * Suspend policy should make no difference.
284      * Iterate over all of them.
285      */
goSuspendPolicy(String target, boolean expectedEvent, String exceptionName, boolean caught, boolean uncaught)286     static void goSuspendPolicy(String target,
287                    boolean expectedEvent,
288                    String exceptionName,
289                    boolean caught, boolean uncaught) throws Exception {
290         if (globalSuspendPolicy != -1) {
291             go(target, expectedEvent, exceptionName,
292                caught, uncaught, globalSuspendPolicy);
293         } else {
294             go(target, expectedEvent, exceptionName,
295                caught, uncaught, EventRequest.SUSPEND_ALL);
296             go(target, expectedEvent, exceptionName,
297                caught, uncaught, EventRequest.SUSPEND_EVENT_THREAD);
298             go(target, expectedEvent, exceptionName,
299                caught, uncaught, EventRequest.SUSPEND_NONE);
300         }
301     }
302 
go(String target, boolean expectedEvent, String exceptionName, boolean caught, boolean uncaught, int suspendPolicy)303     static void go(String target,
304                    boolean expectedEvent,
305                    String exceptionName,
306                    boolean caught, boolean uncaught,
307                    int suspendPolicy) throws Exception {
308         String description = target + " with " +
309                            exceptionName +
310                            "/caught=" + caught +
311                            "/uncaught=" + uncaught +
312                            " suspend=";
313         switch (suspendPolicy) {
314         case EventRequest.SUSPEND_ALL:
315             description += "All";
316             break;
317         case EventRequest.SUSPEND_EVENT_THREAD:
318             description += "Thread";
319             break;
320         case EventRequest.SUSPEND_NONE:
321             description += "None";
322             break;
323         default:
324             throw new Exception("Test failure: bad suspend policy - " +
325                                 suspendPolicy);
326         }
327         description += "\n";
328 
329         System.out.print("\nTesting " + description);
330 
331         ExceptionEvents aRun = new ExceptionEvents(
332                              target,
333                              exceptionName, caught, uncaught,
334                              suspendPolicy);
335         aRun.startTests();
336         aRun.analyse(expectedEvent, description);
337     }
338 
analyse(boolean expectedEvent, String description)339     void analyse(boolean expectedEvent, String description) {
340         if (expectedEvent) {
341             if (eventCount == 1) {
342                 println("pass: got expected event");
343             } else if (eventCount > 1) {
344                 failure("FAILURE: expected only one event got: " +
345                                    eventCount);
346                 tooManySummary.append(description);
347                 ++failureCount;
348             } else {
349                 failure("FAILURE: expected event not sent");
350                 notSentSummary.append(description);
351                 ++failureCount;
352             }
353         } else {
354             if (eventCount > 0) {
355                 failure("FAILURE: unexpected event sent");
356                 unexpectedSummary.append(description);
357                 ++failureCount;
358             } else {
359                 println("pass: as expected no event sent");
360             }
361         }
362     }
363 
364 
365     /********** event handlers **********/
366 
exceptionThrown(ExceptionEvent event)367     public void exceptionThrown(ExceptionEvent event) {
368         if (event.request() == request) {
369             try {
370                 System.out.print("ExceptionEvent: ");
371                 System.out.print("" + event.exception().referenceType().name());
372                 Location loc = event.location();
373                 System.out.print(" @ " + loc.method().name());
374                 System.out.print(":" + loc.lineNumber());
375             } catch (VMDisconnectedException exc) {
376                 System.out.print("Oops - " + exc.toString());
377             }
378             System.out.println();
379             eventCount++;
380         } else {
381             System.out.print("alien exception: ");
382             try {
383                 println(event.toString());
384             } catch (VMDisconnectedException exc) {
385                 println("Oops - " + exc.toString());
386             }
387         }
388     }
389 
390     /**
391      * Turn off default Exception Handling
392      */
createDefaultExceptionRequest()393     protected void createDefaultExceptionRequest() {
394     }
395 
396     /********** test core **********/
397 
runTests()398     protected void runTests() throws Exception {
399         /*
400          * Get to the top of main()
401          */
402         startToMain(target);
403 
404         ReferenceType exceptionClass;
405 
406         if (exceptionName == null) {
407             exceptionClass = null;
408         } else {
409             exceptionClass = findReferenceType(exceptionName);
410             if (exceptionName == null) {
411                 throw new Exception("test failure - cannot find: " +
412                                     exceptionName);
413             }
414         }
415 
416         request = eventRequestManager().createExceptionRequest(exceptionClass,
417                                                                caught, uncaught);
418         request.addClassExclusionFilter("java.*");
419         request.addClassExclusionFilter("javax.*");
420         request.addClassExclusionFilter("sun.*");
421         request.addClassExclusionFilter("com.sun.*");
422         request.addClassExclusionFilter("com.oracle.*");
423         request.addClassExclusionFilter("oracle.*");
424         request.addClassExclusionFilter("jdk.internal.*");
425         request.addClassExclusionFilter("jdk.vm.ci.hotspot.*");
426         request.setSuspendPolicy(suspendPolicy);
427         request.enable();
428 
429         listenUntilVMDisconnect();
430     }
431 }
432