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  * @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 {
  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 {
  78     public static void main(String[] args) {
  79         thrower();
  80     }
  81     static void thrower()  {
  82         throw new StackOverflowError();
  83     }
  84 }
  85 
  86 class StackOverflowIndirectTarg {
  87     public static void main(String[] args) {
  88         try {
  89             thrower();
  90         } catch (Throwable exc) {
  91             System.out.println("Got exception: " + exc);
  92         }
  93     }
  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 
 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 
 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 
 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 
 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 
 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      */
 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      */
 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      */
 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      */
 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 
 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 
 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 
 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      */
 393     protected void createDefaultExceptionRequest() {
 394     }
 395 
 396     /********** test core **********/
 397 
 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.setSuspendPolicy(suspendPolicy);
 426         request.enable();
 427 
 428         listenUntilVMDisconnect();
 429     }
 430 }