test/langtools/jdk/jshell/ExceptionsTest.java
changeset 47216 71c04702a3d5
parent 33362 65ec6de1d6b4
child 49515 083318155ad1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/jshell/ExceptionsTest.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2015, 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
+ * @summary Tests for exceptions
+ * @build KullaTesting TestingInputStream
+ * @run testng ExceptionsTest
+ */
+
+import jdk.jshell.SnippetEvent;
+import jdk.jshell.EvalException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import jdk.jshell.Snippet;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+@Test
+public class ExceptionsTest extends KullaTesting {
+
+    public void throwUncheckedException() {
+        String message = "error_message";
+        SnippetEvent cr = assertEvalException("throw new RuntimeException(\"" + message + "\");");
+        assertExceptionMatch(cr,
+                new ExceptionInfo(RuntimeException.class, message,
+                        newStackTraceElement("", "", cr.snippet(), 1)));
+    }
+
+    public void throwCheckedException() {
+        String message = "error_message";
+        SnippetEvent cr = assertEvalException("throw new Exception(\"" + message + "\");");
+        assertExceptionMatch(cr,
+                new ExceptionInfo(Exception.class, message,
+                        newStackTraceElement("", "", cr.snippet(), 1)));
+    }
+
+    public void throwFromStaticMethodOfClass() {
+        String message = "error_message";
+        Snippet s1 = methodKey(assertEval("void f() { throw new RuntimeException(\"" + message + "\"); }"));
+        Snippet s2 = classKey(assertEval("class A { static void g() { f(); } }"));
+        SnippetEvent cr3 = assertEvalException("A.g();");
+        assertExceptionMatch(cr3,
+                new ExceptionInfo(RuntimeException.class, message,
+                        newStackTraceElement("", "f", s1, 1),
+                        newStackTraceElement("A", "g", s2, 1),
+                        newStackTraceElement("", "", cr3.snippet(), 1)));
+    }
+
+    public void throwFromStaticMethodOfInterface() {
+        String message = "error_message";
+        Snippet s1 = methodKey(assertEval("void f() { throw new RuntimeException(\"" + message + "\"); }"));
+        Snippet s2 = classKey(assertEval("interface A { static void g() { f(); } }"));
+        SnippetEvent cr3 = assertEvalException("A.g();");
+        assertExceptionMatch(cr3,
+                new ExceptionInfo(RuntimeException.class, message,
+                        newStackTraceElement("", "f", s1, 1),
+                        newStackTraceElement("A", "g", s2, 1),
+                        newStackTraceElement("", "", cr3.snippet(), 1)));
+    }
+
+    public void throwFromConstructor() {
+        String message = "error_message";
+        Snippet s1 = methodKey(assertEval("void f() { throw new RuntimeException(\"" + message + "\"); }"));
+        Snippet s2 = classKey(assertEval("class A { A() { f(); } }"));
+        SnippetEvent cr3 = assertEvalException("new A();");
+        assertExceptionMatch(cr3,
+                new ExceptionInfo(RuntimeException.class, message,
+                        newStackTraceElement("", "f", s1, 1),
+                        newStackTraceElement("A", "<init>", s2, 1),
+                        newStackTraceElement("", "", cr3.snippet(), 1)));
+    }
+
+    public void throwFromDefaultMethodOfInterface() {
+        String message = "error_message";
+        Snippet s1 = methodKey(assertEval("void f() { throw new RuntimeException(\"" + message + "\"); }"));
+        Snippet s2 = classKey(assertEval("interface A { default void g() { f(); } }"));
+        SnippetEvent cr3 = assertEvalException("new A() { }.g();");
+        assertExceptionMatch(cr3,
+                new ExceptionInfo(RuntimeException.class, message,
+                        newStackTraceElement("", "f", s1, 1),
+                        newStackTraceElement("A", "g", s2, 1),
+                        newStackTraceElement("", "", cr3.snippet(), 1)));
+    }
+
+    public void throwFromLambda() {
+        String message = "lambda";
+        Snippet s1 = varKey(assertEval(
+                "Runnable run = () -> {\n" +
+                "   throw new RuntimeException(\"" + message + "\");\n" +
+                "};"
+        ));
+        SnippetEvent cr2 = assertEvalException("run.run();");
+        assertExceptionMatch(cr2,
+                new ExceptionInfo(RuntimeException.class, message,
+                        newStackTraceElement("", "lambda$", s1, 2),
+                        newStackTraceElement("", "", cr2.snippet(), 1)));
+    }
+
+    public void throwFromAnonymousClass() {
+        String message = "anonymous";
+        Snippet s1 = varKey(assertEval(
+                "Runnable run = new Runnable() {\n" +
+                "   public void run() {\n"+
+                "       throw new RuntimeException(\"" + message + "\");\n" +
+                "   }\n" +
+                "};"
+        ));
+        SnippetEvent cr2 = assertEvalException("run.run();");
+        assertExceptionMatch(cr2,
+                new ExceptionInfo(RuntimeException.class, message,
+                        newStackTraceElement("1", "run", s1, 3),
+                        newStackTraceElement("", "", cr2.snippet(), 1)));
+    }
+
+    public void throwFromLocalClass() {
+        String message = "local";
+        Snippet s1 = methodKey(assertEval(
+                "void f() {\n" +
+                "   class A {\n" +
+                "       void f() {\n"+
+                "           throw new RuntimeException(\"" + message + "\");\n" +
+                "       }\n" +
+                "   }\n" +
+                "   new A().f();\n" +
+                "}"
+        ));
+        SnippetEvent cr2 = assertEvalException("f();");
+        assertExceptionMatch(cr2,
+                new ExceptionInfo(RuntimeException.class, message,
+                        newStackTraceElement("1A", "f", s1, 4),
+                        newStackTraceElement("", "f", s1, 7),
+                        newStackTraceElement("", "", cr2.snippet(), 1)));
+    }
+
+    @Test(enabled = false) // TODO 8129427
+    public void outOfMemory() {
+        assertEval("import java.util.*;");
+        assertEval("List<byte[]> list = new ArrayList<>();");
+        assertExecuteException("while (true) { list.add(new byte[10000]); }", OutOfMemoryError.class);
+    }
+
+    public void stackOverflow() {
+        assertEval("void f() { f(); }");
+        assertExecuteException("f();", StackOverflowError.class);
+    }
+
+    private StackTraceElement newStackTraceElement(String className, String methodName, Snippet key, int lineNumber) {
+        return new StackTraceElement(className, methodName, "#" + key.id(), lineNumber);
+    }
+
+    private static class ExceptionInfo {
+        public final Class<? extends Throwable> exception;
+        public final String message;
+        public final StackTraceElement[] stackTraceElements;
+
+        public ExceptionInfo(Class<? extends Throwable> exception, String message, StackTraceElement...stackTraceElements) {
+            this.exception = exception;
+            this.message = message;
+            this.stackTraceElements = stackTraceElements.length == 0 ? null : stackTraceElements;
+        }
+    }
+
+    private void assertExecuteException(String input, Class<? extends Throwable> exception) {
+        assertExceptionMatch(assertEvalException(input), new ExceptionInfo(exception, null));
+    }
+
+    private void assertExceptionMatch(SnippetEvent cr, ExceptionInfo exceptionInfo) {
+        assertNotNull(cr.exception(), "Expected exception was not thrown: " + exceptionInfo.exception);
+        if (cr.exception() instanceof EvalException) {
+            EvalException ex = (EvalException) cr.exception();
+            String actualException = ex.getExceptionClassName();
+            String expectedException = exceptionInfo.exception.getCanonicalName();
+            String stackTrace = getStackTrace(ex);
+            String source = cr.snippet().source();
+            assertEquals(actualException, expectedException,
+                    String.format("Given \"%s\" expected exception: %s, got: %s%nStack trace:%n%s",
+                            source, expectedException, actualException, stackTrace));
+            if (exceptionInfo.message != null) {
+                assertEquals(ex.getMessage(), exceptionInfo.message,
+                        String.format("Given \"%s\" expected message: %s, got: %s",
+                                source, exceptionInfo.message, ex.getMessage()));
+            }
+            if (exceptionInfo.stackTraceElements != null) {
+                assertStackTrace(ex.getStackTrace(), exceptionInfo.stackTraceElements,
+                        String.format("Given \"%s\"%nStack trace:%n%s%n",
+                                source, stackTrace));
+            }
+        } else {
+            fail("Unexpected execution exceptionInfo: " + cr.exception());
+        }
+    }
+
+    private void assertStackTrace(StackTraceElement[] actual, StackTraceElement[] expected, String message) {
+        if (actual != expected) {
+            if (actual == null || expected == null) {
+                fail(message);
+            } else {
+                assertEquals(actual.length, expected.length, message + " : arrays do not have the same size");
+                for (int i = 0; i < actual.length; ++i) {
+                    StackTraceElement actualElement = actual[i];
+                    StackTraceElement expectedElement = expected[i];
+                    assertEquals(actualElement.getClassName(), expectedElement.getClassName(), message + " : class names");
+                    String expectedMethodName = expectedElement.getMethodName();
+                    if (expectedMethodName.startsWith("lambda$")) {
+                        assertTrue(actualElement.getMethodName().startsWith("lambda$"), message + " : method names");
+                    } else {
+                        assertEquals(actualElement.getMethodName(), expectedElement.getMethodName(), message + " : method names");
+                    }
+                    assertEquals(actualElement.getFileName(), expectedElement.getFileName(), message + " : file names");
+                    assertEquals(actualElement.getLineNumber(), expectedElement.getLineNumber(), message + " : line numbers");
+                }
+            }
+        }
+    }
+
+    private String getStackTrace(EvalException ex) {
+        StringWriter st = new StringWriter();
+        ex.printStackTrace(new PrintWriter(st));
+        return st.toString();
+    }
+}