54c06d2d91
Reviewed-by: kevinw, lmesnik
430 lines
16 KiB
Java
430 lines
16 KiB
Java
/*
|
|
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/**
|
|
* @test
|
|
* @bug 4407397
|
|
* @key intermittent
|
|
* @summary Test the requesting of exception events
|
|
* @author Robert Field
|
|
*
|
|
* @run build TestScaffold VMConnection
|
|
* @run compile -g ExceptionEvents.java
|
|
*
|
|
* @run driver ExceptionEvents N A StackOverflowCaughtTarg java.lang.Exception
|
|
* @run driver ExceptionEvents C A StackOverflowCaughtTarg null
|
|
* @run driver ExceptionEvents C A StackOverflowCaughtTarg java.lang.Error
|
|
* @run driver ExceptionEvents C A StackOverflowCaughtTarg java.lang.StackOverflowError
|
|
* @run driver ExceptionEvents N A StackOverflowCaughtTarg java.lang.NullPointerException
|
|
|
|
* @run driver ExceptionEvents N T StackOverflowCaughtTarg java.lang.Exception
|
|
* @run driver ExceptionEvents C T StackOverflowCaughtTarg null
|
|
* @run driver ExceptionEvents C T StackOverflowCaughtTarg java.lang.Error
|
|
* @run driver ExceptionEvents C T StackOverflowCaughtTarg java.lang.StackOverflowError
|
|
* @run driver ExceptionEvents N T StackOverflowCaughtTarg java.lang.NullPointerException
|
|
|
|
* @run driver ExceptionEvents N N StackOverflowCaughtTarg java.lang.Exception
|
|
* @run driver ExceptionEvents C N StackOverflowCaughtTarg null
|
|
* @run driver ExceptionEvents C N StackOverflowCaughtTarg java.lang.Error
|
|
* @run driver ExceptionEvents C N StackOverflowCaughtTarg java.lang.StackOverflowError
|
|
* @run driver ExceptionEvents N N StackOverflowCaughtTarg java.lang.NullPointerException
|
|
|
|
* @run driver ExceptionEvents N A StackOverflowUncaughtTarg java.lang.Exception
|
|
* @run driver ExceptionEvents U A StackOverflowUncaughtTarg null
|
|
* @run driver ExceptionEvents U A StackOverflowUncaughtTarg java.lang.Error
|
|
* @run driver ExceptionEvents U A StackOverflowUncaughtTarg java.lang.StackOverflowError
|
|
* @run driver ExceptionEvents N A StackOverflowUncaughtTarg java.lang.NullPointerException
|
|
|
|
* @run driver ExceptionEvents N T StackOverflowUncaughtTarg java.lang.NullPointerException
|
|
* @run driver ExceptionEvents N N StackOverflowUncaughtTarg java.lang.NullPointerException
|
|
|
|
*/
|
|
import com.sun.jdi.*;
|
|
import com.sun.jdi.event.*;
|
|
import com.sun.jdi.request.*;
|
|
import java.util.*;
|
|
|
|
class StackOverflowCaughtTarg {
|
|
public static void main(String[] args) {
|
|
try {
|
|
throw new StackOverflowError();
|
|
} catch (Throwable exc) {
|
|
// ignore
|
|
}
|
|
}
|
|
}
|
|
|
|
class StackOverflowUncaughtTarg {
|
|
public static void main(String[] args) {
|
|
thrower();
|
|
}
|
|
static void thrower() {
|
|
throw new StackOverflowError();
|
|
}
|
|
}
|
|
|
|
public class ExceptionEvents extends TestScaffold {
|
|
static int failureCount = 0;
|
|
static StringBuffer tooManySummary = new StringBuffer();
|
|
static StringBuffer notSentSummary = new StringBuffer();
|
|
static StringBuffer unexpectedSummary = new StringBuffer();
|
|
static int globalSuspendPolicy = -1;
|
|
static String[] flags;
|
|
|
|
final String target;
|
|
final String exceptionName;
|
|
final boolean caught;
|
|
final boolean uncaught;
|
|
final int suspendPolicy;
|
|
|
|
int eventCount = 0;
|
|
ExceptionRequest request;
|
|
|
|
ExceptionEvents(String target,
|
|
String exceptionName,
|
|
boolean caught, boolean uncaught,
|
|
int suspendPolicy) {
|
|
super(flags);
|
|
this.target = target;
|
|
this.exceptionName = exceptionName;
|
|
this.caught = caught;
|
|
this.uncaught = uncaught;
|
|
this.suspendPolicy = suspendPolicy;
|
|
}
|
|
|
|
static void everything() throws Exception {
|
|
goNeither("StackOverflowCaughtTarg", "java.lang.Exception");
|
|
goCaught("StackOverflowCaughtTarg", null);
|
|
goCaught("StackOverflowCaughtTarg", "java.lang.Error");
|
|
goCaught("StackOverflowCaughtTarg", "java.lang.StackOverflowError");
|
|
goNeither("StackOverflowCaughtTarg", "java.lang.NullPointerException");
|
|
|
|
goNeither("StackOverflowUncaughtTarg", "java.lang.Exception");
|
|
goUncaught("StackOverflowUncaughtTarg", null);
|
|
goUncaught("StackOverflowUncaughtTarg", "java.lang.Error");
|
|
goUncaught("StackOverflowUncaughtTarg", "java.lang.StackOverflowError");
|
|
goNeither("StackOverflowUncaughtTarg", "java.lang.NullPointerException");
|
|
}
|
|
|
|
static void usage() throws Exception {
|
|
System.err.println("Use either with no arguments or");
|
|
System.err.println(" c|u|n a|t|n <TargetClass> <Exception>|null");
|
|
System.err.println("or for verbose folk");
|
|
System.err.println(" caught|uncaught|neither all|thread|none <TargetClass> <Exception>|null");
|
|
throw new IllegalArgumentException("see usage");
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
StringBuffer testName = new StringBuffer("ExceptionEvents(");
|
|
List flagList = new ArrayList();
|
|
List argList = new ArrayList();
|
|
|
|
for (int i = 0; i < args.length; ++i) {
|
|
String arg = args[i];
|
|
if (arg.startsWith("-")) {
|
|
flagList.add(arg);
|
|
} else {
|
|
argList.add(arg);
|
|
}
|
|
}
|
|
flags = (String[])flagList.toArray(new String[0]);
|
|
args = (String[])argList.toArray(new String[0]);
|
|
if (args.length == 0) {
|
|
everything();
|
|
testName.append("Full Test");
|
|
} else if (args.length == 4) {
|
|
switch (args[1].toLowerCase().charAt(0)) {
|
|
case 'a':
|
|
globalSuspendPolicy = EventRequest.SUSPEND_ALL;
|
|
break;
|
|
case 't':
|
|
globalSuspendPolicy = EventRequest.SUSPEND_EVENT_THREAD;
|
|
break;
|
|
case 'n':
|
|
globalSuspendPolicy = EventRequest.SUSPEND_NONE;
|
|
break;
|
|
default:
|
|
usage();
|
|
}
|
|
String excString = args[3];
|
|
if (excString.equals("null")) {
|
|
excString = null;
|
|
}
|
|
switch (args[0].toLowerCase().charAt(0)) {
|
|
case 'c':
|
|
goCaught(args[2], excString);
|
|
break;
|
|
case 'u':
|
|
goUncaught(args[2], excString);
|
|
break;
|
|
case 'n':
|
|
goNeither(args[2], excString);
|
|
break;
|
|
default:
|
|
usage();
|
|
}
|
|
testName.append(args[0]);
|
|
testName.append(" ");
|
|
testName.append(args[1]);
|
|
testName.append(" ");
|
|
testName.append(args[2]);
|
|
} else {
|
|
usage();
|
|
}
|
|
testName.append(")");
|
|
|
|
summarize(testName.toString());
|
|
}
|
|
|
|
static void summarize(String testName) throws Exception {
|
|
// final analyse
|
|
if (tooManySummary.length() > 0) {
|
|
System.out.println("\nSummary of tests with too many events:\n" +
|
|
tooManySummary.toString());
|
|
}
|
|
if (notSentSummary.length() > 0) {
|
|
System.out.println("\nSummary of tests with expected events not sent:\n" +
|
|
notSentSummary.toString());
|
|
}
|
|
if (unexpectedSummary.length() > 0) {
|
|
System.out.println("\nSummary of tests with events when none expected:\n" +
|
|
unexpectedSummary.toString());
|
|
}
|
|
|
|
if (failureCount > 0) {
|
|
throw new Exception(testName + " FAILED " +
|
|
failureCount + " tests!");
|
|
} else {
|
|
System.out.println("\n" + testName + " test PASSED");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Target throws caught exception.
|
|
* Events if caught enabled.
|
|
*/
|
|
static void goCaught(String target,
|
|
String exceptionName) throws Exception {
|
|
goSuspendPolicy(target, true, exceptionName,
|
|
true, true);
|
|
goSuspendPolicy(target, true, exceptionName,
|
|
true, false);
|
|
goSuspendPolicy(target, false, exceptionName,
|
|
false, true);
|
|
goSuspendPolicy(target, false, exceptionName,
|
|
false, false);
|
|
}
|
|
|
|
/**
|
|
* Target throws uncaught exception.
|
|
* Events if uncaught enabled.
|
|
*/
|
|
static void goUncaught(String target,
|
|
String exceptionName) throws Exception {
|
|
goSuspendPolicy(target, true, exceptionName,
|
|
true, true);
|
|
goSuspendPolicy(target, true, exceptionName,
|
|
false, true);
|
|
goSuspendPolicy(target, false, exceptionName,
|
|
true, false);
|
|
goSuspendPolicy(target, false, exceptionName,
|
|
false, false);
|
|
}
|
|
|
|
/**
|
|
* Target doesn't throw named exception. No events.
|
|
*/
|
|
static void goNeither(String target,
|
|
String exceptionName) throws Exception {
|
|
goSuspendPolicy(target, false, exceptionName,
|
|
true, true);
|
|
goSuspendPolicy(target, false, exceptionName,
|
|
false, true);
|
|
goSuspendPolicy(target, false, exceptionName,
|
|
true, false);
|
|
goSuspendPolicy(target, false, exceptionName,
|
|
false, false);
|
|
}
|
|
|
|
/**
|
|
* Suspend policy should make no difference.
|
|
* Iterate over all of them.
|
|
*/
|
|
static void goSuspendPolicy(String target,
|
|
boolean expectedEvent,
|
|
String exceptionName,
|
|
boolean caught, boolean uncaught) throws Exception {
|
|
if (globalSuspendPolicy != -1) {
|
|
go(target, expectedEvent, exceptionName,
|
|
caught, uncaught, globalSuspendPolicy);
|
|
} else {
|
|
go(target, expectedEvent, exceptionName,
|
|
caught, uncaught, EventRequest.SUSPEND_ALL);
|
|
go(target, expectedEvent, exceptionName,
|
|
caught, uncaught, EventRequest.SUSPEND_EVENT_THREAD);
|
|
go(target, expectedEvent, exceptionName,
|
|
caught, uncaught, EventRequest.SUSPEND_NONE);
|
|
}
|
|
}
|
|
|
|
static void go(String target,
|
|
boolean expectedEvent,
|
|
String exceptionName,
|
|
boolean caught, boolean uncaught,
|
|
int suspendPolicy) throws Exception {
|
|
String description = target + " with " +
|
|
exceptionName +
|
|
"/caught=" + caught +
|
|
"/uncaught=" + uncaught +
|
|
" suspend=";
|
|
switch (suspendPolicy) {
|
|
case EventRequest.SUSPEND_ALL:
|
|
description += "All";
|
|
break;
|
|
case EventRequest.SUSPEND_EVENT_THREAD:
|
|
description += "Thread";
|
|
break;
|
|
case EventRequest.SUSPEND_NONE:
|
|
description += "None";
|
|
break;
|
|
default:
|
|
throw new Exception("Test failure: bad suspend policy - " +
|
|
suspendPolicy);
|
|
}
|
|
description += "\n";
|
|
|
|
System.out.print("\nTesting " + description);
|
|
|
|
ExceptionEvents aRun = new ExceptionEvents(
|
|
target,
|
|
exceptionName, caught, uncaught,
|
|
suspendPolicy);
|
|
aRun.startTests();
|
|
aRun.analyse(expectedEvent, description);
|
|
}
|
|
|
|
void analyse(boolean expectedEvent, String description) {
|
|
if (expectedEvent) {
|
|
if (eventCount == 1) {
|
|
println("pass: got expected event");
|
|
} else if (eventCount > 1) {
|
|
failure("FAILURE: expected only one event got: " +
|
|
eventCount);
|
|
tooManySummary.append(description);
|
|
++failureCount;
|
|
} else {
|
|
failure("FAILURE: expected event not sent");
|
|
notSentSummary.append(description);
|
|
++failureCount;
|
|
}
|
|
} else {
|
|
if (eventCount > 0) {
|
|
failure("FAILURE: unexpected event sent");
|
|
unexpectedSummary.append(description);
|
|
++failureCount;
|
|
} else {
|
|
println("pass: as expected no event sent");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/********** event handlers **********/
|
|
|
|
public void exceptionThrown(ExceptionEvent event) {
|
|
if (event.request() == request) {
|
|
try {
|
|
System.out.print("ExceptionEvent: ");
|
|
System.out.print("" + event.exception().referenceType().name());
|
|
Location loc = event.location();
|
|
System.out.print(" @ " + loc.method().name());
|
|
System.out.print(":" + loc.lineNumber());
|
|
} catch (VMDisconnectedException exc) {
|
|
System.out.print("Oops - " + exc.toString());
|
|
}
|
|
System.out.println();
|
|
eventCount++;
|
|
} else {
|
|
System.out.print("alien exception: ");
|
|
try {
|
|
println(event.toString());
|
|
} catch (VMDisconnectedException exc) {
|
|
println("Oops - " + exc.toString());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Turn off default Exception Handling
|
|
*/
|
|
protected void createDefaultExceptionRequest() {
|
|
}
|
|
|
|
/********** test core **********/
|
|
|
|
@Override
|
|
protected boolean allowedExitValue(int exitValue) {
|
|
// If the exception is caught, we expect exitValue == 0. For uncaught we
|
|
// we expect exitValue == 1.
|
|
if (target.equals("StackOverflowCaughtTarg")) {
|
|
return exitValue == 0;
|
|
} else {
|
|
return exitValue == 1;
|
|
}
|
|
}
|
|
|
|
protected void runTests() throws Exception {
|
|
/*
|
|
* Get to the top of main()
|
|
*/
|
|
startToMain(target);
|
|
|
|
ReferenceType exceptionClass;
|
|
|
|
if (exceptionName == null) {
|
|
exceptionClass = null;
|
|
} else {
|
|
exceptionClass = findReferenceType(exceptionName);
|
|
if (exceptionName == null) {
|
|
throw new Exception("test failure - cannot find: " +
|
|
exceptionName);
|
|
}
|
|
}
|
|
|
|
request = eventRequestManager().createExceptionRequest(exceptionClass,
|
|
caught, uncaught);
|
|
request.addClassExclusionFilter("java.*");
|
|
request.addClassExclusionFilter("javax.*");
|
|
request.addClassExclusionFilter("sun.*");
|
|
request.addClassExclusionFilter("com.sun.*");
|
|
request.addClassExclusionFilter("com.oracle.*");
|
|
request.addClassExclusionFilter("oracle.*");
|
|
request.addClassExclusionFilter("jdk.internal.*");
|
|
request.addClassExclusionFilter("jdk.vm.ci.hotspot.*");
|
|
request.setSuspendPolicy(suspendPolicy);
|
|
request.enable();
|
|
|
|
listenUntilVMDisconnect();
|
|
}
|
|
}
|