--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/TryFinallyTest.java Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2015, 2016, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 8139885
+ * @bug 8150824
+ * @bug 8150825
+ * @run testng/othervm -ea -esa test.java.lang.invoke.TryFinallyTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the tryFinally method handle combinator introduced in JEP 274.
+ */
+public class TryFinallyTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testTryFinally() throws Throwable {
+ MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim);
+ assertEquals(TryFinally.MT_hello, hello.type());
+ assertEquals("Hello, world!", hello.invoke("world"));
+ }
+
+ @Test
+ public static void testTryFinallyVoid() throws Throwable {
+ MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore);
+ assertEquals(TryFinally.MT_printHello, tfVoid.type());
+ tfVoid.invoke("world");
+ }
+
+ @Test
+ public static void testTryFinallySublist() throws Throwable {
+ MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore);
+ assertEquals(TryFinally.MT_moreHello, helloMore.type());
+ assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe"));
+ }
+
+ @DataProvider
+ static Object[][] omitTrailingArguments() {
+ MethodHandle c = TryFinally.MH_voidCleanup;
+ return new Object[][]{
+ {c},
+ {MethodHandles.dropArguments(c, 1, int.class)},
+ {MethodHandles.dropArguments(c, 1, int.class, long.class)},
+ {MethodHandles.dropArguments(c, 1, int.class, long.class, Object.class, int.class)},
+ {MethodHandles.dropArguments(c, 1, int.class, long.class, Object.class, int.class, long.class)}
+ };
+ }
+
+ @Test(dataProvider = "omitTrailingArguments")
+ public static void testTryFinallyOmitTrailingArguments(MethodHandle cleanup) throws Throwable {
+ MethodHandle tf = MethodHandles.tryFinally(TryFinally.MH_dummyTarget, cleanup);
+ tf.invoke(1, 2L, "a", 23, 42L, "b");
+ }
+
+ @DataProvider
+ static Object[][] negativeTestData() {
+ MethodHandle intid = MethodHandles.identity(int.class);
+ MethodHandle intco = MethodHandles.constant(int.class, 0);
+ MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class);
+ MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class,
+ int.class, double.class, Object.class);
+ MethodHandle voidTarget = TryFinally.MH_voidTarget;
+ MethodHandle voidICleanup = MethodHandles.dropArguments(TryFinally.MH_voidCleanup, 1, int.class);
+ return new Object[][]{
+ {intid, MethodHandles.identity(double.class),
+ "target and return types must match: double != int"},
+ {intid, MethodHandles.dropArguments(intid, 0, String.class),
+ "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable"},
+ {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class),
+ "cleanup second argument and target return type must match: (Throwable,double,int)int != int"},
+ {errTarget, errCleanup,
+ "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
+ errCleanup.type() + " != " + errTarget.type()},
+ {voidTarget, voidICleanup,
+ "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
+ voidICleanup.type() + " != " + voidTarget.type()}
+ };
+ }
+
+ @Test(dataProvider = "negativeTestData")
+ public static void testTryFinallyNegative(MethodHandle target, MethodHandle cleanup, String expectedMessage) {
+ boolean caught = false;
+ try {
+ MethodHandles.tryFinally(target, cleanup);
+ } catch (IllegalArgumentException iae) {
+ assertEquals(expectedMessage, iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ static class TryFinally {
+
+ static String greet(String whom) {
+ return "Hello, " + whom;
+ }
+
+ static String exclaim(Throwable t, String r, String whom) {
+ return r + "!";
+ }
+
+ static void print(String what) {
+ System.out.print("Hello, " + what);
+ }
+
+ static void printMore(Throwable t, String what) {
+ System.out.println("!");
+ }
+
+ static String greetMore(String first, String second) {
+ return "Hello, " + first + " and " + second;
+ }
+
+ static String exclaimMore(Throwable t, String r, String first) {
+ return r + " (but " + first + " first)!";
+ }
+
+ static void voidTarget() {}
+
+ static void voidCleanup(Throwable t) {}
+
+ static final Class<TryFinally> TRY_FINALLY = TryFinally.class;
+
+ static final MethodType MT_greet = methodType(String.class, String.class);
+ static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class);
+ static final MethodType MT_print = methodType(void.class, String.class);
+ static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class);
+ static final MethodType MT_greetMore = methodType(String.class, String.class, String.class);
+ static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class);
+ static final MethodType MT_voidTarget = methodType(void.class);
+ static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class);
+
+ static final MethodHandle MH_greet;
+ static final MethodHandle MH_exclaim;
+ static final MethodHandle MH_print;
+ static final MethodHandle MH_printMore;
+ static final MethodHandle MH_greetMore;
+ static final MethodHandle MH_exclaimMore;
+ static final MethodHandle MH_voidTarget;
+ static final MethodHandle MH_voidCleanup;
+
+ static final MethodHandle MH_dummyTarget;
+
+ static final MethodType MT_hello = methodType(String.class, String.class);
+ static final MethodType MT_printHello = methodType(void.class, String.class);
+ static final MethodType MT_moreHello = methodType(String.class, String.class, String.class);
+
+ static {
+ try {
+ MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet);
+ MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim);
+ MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print);
+ MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore);
+ MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore);
+ MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore);
+ MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget);
+ MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup);
+ MH_dummyTarget = MethodHandles.dropArguments(MH_voidTarget, 0, int.class, long.class, Object.class,
+ int.class, long.class, Object.class);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+}