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