Path: blob/master/test/langtools/jdk/jshell/ExceptionsTest.java
40931 views
/*1* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @summary Tests for exceptions26* @bug 8198801 8212167 821052727* @modules jdk.compiler/com.sun.tools.javac.api28* jdk.compiler/com.sun.tools.javac.main29* jdk.jdeps/com.sun.tools.javap30* @library /tools/lib31* @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask32* @build KullaTesting TestingInputStream Compiler33* @run testng ExceptionsTest34*/3536import java.io.IOException;37import java.io.PrintWriter;38import java.io.StringWriter;39import jdk.jshell.EvalException;40import jdk.jshell.JShellException;41import jdk.jshell.Snippet;42import jdk.jshell.SnippetEvent;43import jdk.jshell.UnresolvedReferenceException;4445import java.nio.file.Path;46import java.nio.file.Paths;4748import org.testng.annotations.Test;4950import static org.testng.Assert.*;5152@Test53public class ExceptionsTest extends KullaTesting {5455private final Compiler compiler = new Compiler();56private final Path outDir = Paths.get("test_class_path");5758public void throwUncheckedException() {59String message = "error_message";60SnippetEvent cr = assertEvalException("throw new RuntimeException(\"" + message + "\");");61assertExceptionMatch(cr,62new ExceptionInfo(RuntimeException.class, message,63newStackTraceElement("", "", cr.snippet(), 1)));64}6566public void throwCheckedException() {67String message = "error_message";68SnippetEvent cr = assertEvalException("throw new Exception(\"" + message + "\");");69assertExceptionMatch(cr,70new ExceptionInfo(Exception.class, message,71newStackTraceElement("", "", cr.snippet(), 1)));72}7374public void throwFromStaticMethodOfClass() {75String message = "error_message";76Snippet s1 = methodKey(assertEval("void f() { throw new RuntimeException(\"" + message + "\"); }"));77Snippet s2 = classKey(assertEval("class A { static void g() { f(); } }"));78SnippetEvent cr3 = assertEvalException("A.g();");79assertExceptionMatch(cr3,80new ExceptionInfo(RuntimeException.class, message,81newStackTraceElement("", "f", s1, 1),82newStackTraceElement("A", "g", s2, 1),83newStackTraceElement("", "", cr3.snippet(), 1)));84}8586public void throwFromStaticMethodOfInterface() {87String message = "error_message";88Snippet s1 = methodKey(assertEval("void f() { throw new RuntimeException(\"" + message + "\"); }"));89Snippet s2 = classKey(assertEval("interface A { static void g() { f(); } }"));90SnippetEvent cr3 = assertEvalException("A.g();");91assertExceptionMatch(cr3,92new ExceptionInfo(RuntimeException.class, message,93newStackTraceElement("", "f", s1, 1),94newStackTraceElement("A", "g", s2, 1),95newStackTraceElement("", "", cr3.snippet(), 1)));96}9798public void throwChained() {99String message1 = "error_message1";100String message2 = "error_message2";101Snippet s1 = methodKey(assertEval("void p() throws Exception { ((String) null).toString(); }"));102Snippet s2 = methodKey(assertEval("void n() throws Exception { try { p(); } catch (Exception ex) { throw new java.io.IOException(\"" + message2 + "\", ex); }}"));103Snippet s3 = methodKey(assertEval("void m() {\n"104+ "try { n(); }\n"105+ "catch (Exception ex) {\n"106+ " throw new RuntimeException(\"" + message1 + "\", ex);\n"107+ "}}"));108SnippetEvent cr4 = assertEvalException("m();");109assertExceptionMatch(cr4,110new ExceptionInfo(RuntimeException.class, message1,111new ExceptionInfo(IOException.class, message2,112new ExceptionInfo(NullPointerException.class, null,113newStackTraceElement("", "p", s1, 1),114newStackTraceElement("", "n", s2, 1),115newStackTraceElement("", "m", s3, 2),116newStackTraceElement("", "", cr4.snippet(), 1)),117newStackTraceElement("", "n", s2, 1),118newStackTraceElement("", "m", s3, 2),119newStackTraceElement("", "", cr4.snippet(), 1)),120newStackTraceElement("", "m", s3, 4),121newStackTraceElement("", "", cr4.snippet(), 1)));122}123124public void throwChainedUnresolved() {125String message1 = "error_message1";126String message2 = "error_message2";127Snippet s1 = methodKey(assertEval("void p() throws Exception { ((String) null).toString(); }"));128Snippet s2 = methodKey(assertEval("void n() throws Exception { try { p(); } catch (Exception ex) { throw new java.io.IOException(\"" + message2 + "\", ex); }}"));129Snippet s3 = methodKey(assertEval("void m() {\n"130+ "try { n(); }\n"131+ "catch (Exception ex) {\n"132+ " throw new RuntimeException(\"" + message1 + "\", ex);\n"133+ "}}"));134getState().drop(s1);135SnippetEvent cr4 = assertEvalException("m();");136assertExceptionMatch(cr4,137new ExceptionInfo(RuntimeException.class, message1,138new UnresolvedExceptionInfo(s2,139newStackTraceElement("", "n", s2, 1),140newStackTraceElement("", "m", s3, 2),141newStackTraceElement("", "", cr4.snippet(), 1)),142newStackTraceElement("", "m", s3, 4),143newStackTraceElement("", "", cr4.snippet(), 1)));144}145146public void throwFromConstructor() {147String message = "error_message";148Snippet s1 = methodKey(assertEval("void f() { throw new RuntimeException(\"" + message + "\"); }"));149Snippet s2 = classKey(assertEval("class A { A() { f(); } }"));150SnippetEvent cr3 = assertEvalException("new A();");151assertExceptionMatch(cr3,152new ExceptionInfo(RuntimeException.class, message,153newStackTraceElement("", "f", s1, 1),154newStackTraceElement("A", "<init>", s2, 1),155newStackTraceElement("", "", cr3.snippet(), 1)));156}157158public void throwFromDefaultMethodOfInterface() {159String message = "error_message";160Snippet s1 = methodKey(assertEval("void f() { throw new RuntimeException(\"" + message + "\"); }"));161Snippet s2 = classKey(assertEval("interface A { default void g() { f(); } }"));162SnippetEvent cr3 = assertEvalException("new A() { }.g();");163assertExceptionMatch(cr3,164new ExceptionInfo(RuntimeException.class, message,165newStackTraceElement("", "f", s1, 1),166newStackTraceElement("A", "g", s2, 1),167newStackTraceElement("", "", cr3.snippet(), 1)));168}169170public void throwFromLambda() {171String message = "lambda";172Snippet s1 = varKey(assertEval(173"Runnable run = () -> {\n" +174" throw new RuntimeException(\"" + message + "\");\n" +175"};"176));177SnippetEvent cr2 = assertEvalException("run.run();");178assertExceptionMatch(cr2,179new ExceptionInfo(RuntimeException.class, message,180newStackTraceElement("", "lambda$", s1, 2),181newStackTraceElement("", "", cr2.snippet(), 1)));182}183184public void throwFromAnonymousClass() {185String message = "anonymous";186Snippet s1 = varKey(assertEval(187"Runnable run = new Runnable() {\n" +188" public void run() {\n"+189" throw new RuntimeException(\"" + message + "\");\n" +190" }\n" +191"};"192));193SnippetEvent cr2 = assertEvalException("run.run();");194assertExceptionMatch(cr2,195new ExceptionInfo(RuntimeException.class, message,196newStackTraceElement("1", "run", s1, 3),197newStackTraceElement("", "", cr2.snippet(), 1)));198}199200public void throwFromLocalClass() {201String message = "local";202Snippet s1 = methodKey(assertEval(203"void f() {\n" +204" class A {\n" +205" void f() {\n"+206" throw new RuntimeException(\"" + message + "\");\n" +207" }\n" +208" }\n" +209" new A().f();\n" +210"}"211));212SnippetEvent cr2 = assertEvalException("f();");213assertExceptionMatch(cr2,214new ExceptionInfo(RuntimeException.class, message,215newStackTraceElement("1A", "f", s1, 4),216newStackTraceElement("", "f", s1, 7),217newStackTraceElement("", "", cr2.snippet(), 1)));218}219220// test 8210527221public void throwFromWithoutSource() {222String message = "show this";223SnippetEvent se = assertEvalException("java.lang.reflect.Proxy.newProxyInstance(" +224"Thread.currentThread().getContextClassLoader(), new Class[] {}," +225"(p, m, a) -> { throw new IllegalStateException(\"" + message + "\"); }).hashCode()");226assertExceptionMatch(se,227new ExceptionInfo(IllegalStateException.class, message,228newStackTraceElement("", "lambda$do_it$$0", se.snippet(), 1),229new StackTraceElement("jdk.proxy1.$Proxy0", "hashCode", null, -1),230newStackTraceElement("", "", se.snippet(), 1)));231}232233// test 8210527234public void throwFromNoSource() {235Path path = outDir.resolve("fail");236compiler.compile(path,237"package fail;\n" +238"public class Fail {\n" +239" static { int x = 1 / 0; }\n" +240"}\n");241addToClasspath(compiler.getPath(path));242SnippetEvent se = assertEvalException("Class.forName(\"fail.Fail\")");243assertExceptionMatch(se,244new ExceptionInfo(ExceptionInInitializerError.class, null,245new StackTraceElement("java.lang.Class", "forName0", "Class.java", -2),246new StackTraceElement("java.lang.Class", "forName", "Class.java", -2),247newStackTraceElement("", "", se.snippet(), 1)));248}249250// test 8212167251public void throwLineFormat1() {252SnippetEvent se = assertEvalException(253"if (true) { \n" +254" int x = 10; \n" +255" int y = 10 / 0;}"256);257assertExceptionMatch(se,258new ExceptionInfo(ArithmeticException.class, "/ by zero",259newStackTraceElement("", "", se.snippet(), 3)));260}261262public void throwLineFormat3() {263Snippet sp = methodKey(assertEval(264"int p() \n" +265" { return 4/0; }"));266Snippet sm = methodKey(assertEval(267"int m(int x)\n" +268" \n" +269" {\n" +270" return p() + x; \n" +271" }"));272Snippet sn = methodKey(assertEval(273"int n(int x) {\n" +274" try {\n" +275" return m(x);\n" +276" }\n" +277" catch (Throwable ex) {\n" +278" throw new IllegalArgumentException( \"GOT:\", ex);\n" +279" }\n" +280" }"));281SnippetEvent se = assertEvalException("n(33);");282assertExceptionMatch(se,283new ExceptionInfo(IllegalArgumentException.class, null,284new ExceptionInfo(ArithmeticException.class, "/ by zero",285newStackTraceElement("", "p", sp, 2),286newStackTraceElement("", "m", sm, 4),287newStackTraceElement("", "n", sn, 3),288newStackTraceElement("", "", se.snippet(), 1)),289newStackTraceElement("", "n", sn, 6),290newStackTraceElement("", "", se.snippet(), 1)));291}292293@Test(enabled = false) // TODO 8129427294public void outOfMemory() {295assertEval("import java.util.*;");296assertEval("List<byte[]> list = new ArrayList<>();");297assertExecuteException("while (true) { list.add(new byte[10000]); }", OutOfMemoryError.class);298}299300public void stackOverflow() {301assertEval("void f() { f(); }");302assertExecuteException("f();", StackOverflowError.class);303}304305private StackTraceElement newStackTraceElement(String className, String methodName, Snippet key, int lineNumber) {306return new StackTraceElement(className, methodName, "#" + key.id(), lineNumber);307}308309private static class AnyExceptionInfo {310311public final StackTraceElement[] stackTraceElements;312313public AnyExceptionInfo(StackTraceElement... stackTraceElements) {314this.stackTraceElements = stackTraceElements.length == 0 ? null : stackTraceElements;315}316}317318private static class UnresolvedExceptionInfo extends AnyExceptionInfo {319320public final Snippet sn;321322public UnresolvedExceptionInfo(Snippet sn, StackTraceElement... stackTraceElements) {323super(stackTraceElements);324this.sn = sn;325}326}327328private static class ExceptionInfo extends AnyExceptionInfo {329330public final Class<? extends Throwable> exception;331public final String message;332public final AnyExceptionInfo cause;333334public ExceptionInfo(Class<? extends Throwable> exception, String message,335StackTraceElement... stackTraceElements) {336this(exception, message, null, stackTraceElements);337}338339public ExceptionInfo(Class<? extends Throwable> exception, String message,340AnyExceptionInfo cause, StackTraceElement... stackTraceElements) {341super(stackTraceElements);342this.exception = exception;343this.message = message;344this.cause = cause;345}346}347348private void assertExecuteException(String input, Class<? extends Throwable> exception) {349assertExceptionMatch(assertEvalException(input), new ExceptionInfo(exception, null));350}351352private void assertExceptionMatch(SnippetEvent cr, ExceptionInfo exceptionInfo) {353assertExceptionMatch(cr.exception(), cr.snippet().source(), exceptionInfo);354}355356private void assertExceptionMatch(Throwable exception, String source, ExceptionInfo exceptionInfo) {357assertNotNull(exception, "Expected exception was not thrown: " + exceptionInfo.exception);358if (exception instanceof EvalException) {359EvalException ex = (EvalException) exception;360String actualException = ex.getExceptionClassName();361String expectedException = exceptionInfo.exception.getCanonicalName();362assertEquals(actualException, expectedException,363String.format("Given \"%s\" expected exception: %s, got: %s%nStack trace:%n%s",364source, expectedException, actualException, getStackTrace(ex)));365if (exceptionInfo.message != null) {366assertEquals(ex.getMessage(), exceptionInfo.message,367String.format("Given \"%s\" expected message: %s, got: %s",368source, exceptionInfo.message, ex.getMessage()));369}370assertStackMatch(ex, source, exceptionInfo);371if (exceptionInfo.cause != null) {372assertAnyExceptionMatch(exception.getCause(), exceptionInfo.cause);373}374} else {375fail("Unexpected exception: " + exception + " or exceptionInfo: " + exceptionInfo);376}377}378379private void assertStackMatch(JShellException exception, String source, AnyExceptionInfo exceptionInfo) {380if (exceptionInfo.stackTraceElements != null) {381assertStackTrace(exception.getStackTrace(), exceptionInfo.stackTraceElements,382String.format("Given \"%s\"%nStack trace:%n%s%n",383source, getStackTrace(exception)));384}385}386387private void assertAnyExceptionMatch(Throwable exception, AnyExceptionInfo exceptionInfo) {388if (exceptionInfo instanceof ExceptionInfo) {389assertExceptionMatch(exception, "", (ExceptionInfo) exceptionInfo);390} else {391assertTrue(exceptionInfo instanceof UnresolvedExceptionInfo, "Bad exceptionInfo: " + exceptionInfo);392assertTrue(exception instanceof UnresolvedReferenceException,393"Expected UnresolvedReferenceException: " + exception);394UnresolvedExceptionInfo uei = (UnresolvedExceptionInfo) exceptionInfo;395UnresolvedReferenceException ure = (UnresolvedReferenceException) exception;396assertEquals(ure.getSnippet(), uei.sn);397assertStackMatch(ure, "", exceptionInfo);398}399}400401private void assertStackTrace(StackTraceElement[] actual, StackTraceElement[] expected, String message) {402if (actual != expected) {403if (actual == null || expected == null) {404fail(message);405} else {406assertEquals(actual.length, expected.length, message + " : arrays do not have the same size");407for (int i = 0; i < actual.length; ++i) {408StackTraceElement actualElement = actual[i];409StackTraceElement expectedElement = expected[i];410assertEquals(actualElement.getClassName(), expectedElement.getClassName(), message + " : class names [" + i + "]");411String expectedMethodName = expectedElement.getMethodName();412if (expectedMethodName.startsWith("lambda$")) {413assertTrue(actualElement.getMethodName().startsWith("lambda$"), message + " : method names");414} else {415assertEquals(actualElement.getMethodName(), expectedElement.getMethodName(), message + " : method names [" + i + "]");416}417assertEquals(actualElement.getFileName(), expectedElement.getFileName(), message + " : file names [" + i + "]");418if (expectedElement.getLineNumber() >= 0) {419assertEquals(actualElement.getLineNumber(), expectedElement.getLineNumber(), message + " : line numbers [" + i + "]"420+ " -- actual: " + actualElement.getLineNumber() + ", expected: " + expectedElement.getLineNumber() +421" -- in: " + actualElement.getClassName());422}423}424}425}426}427428private String getStackTrace(Throwable ex) {429StringWriter st = new StringWriter();430ex.printStackTrace(new PrintWriter(st));431return st.toString();432}433}434435436