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