Path: blob/master/test/functional/Jsr292/src/com/ibm/j9/jsr292/MethodHandleProxiesTest.java
6007 views
/*******************************************************************************1* Copyright (c) 2001, 2019 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/21package com.ibm.j9.jsr292;2223import org.testng.annotations.Test;24import org.testng.AssertJUnit;25import java.lang.invoke.MethodHandle;26import java.lang.invoke.MethodHandleProxies;27import java.lang.invoke.MethodHandles;28import java.lang.invoke.MethodType;29import examples.CrossPackageSingleMethodInterfaceExample;30import examples.PackageExamples;3132/**33* @author mesbah34* This class contains tests for the MethodHandleProxies API.35*/36public class MethodHandleProxiesTest {3738/********************************39* Tests for asInterfaceInstance40********************************/4142/**43* Tests asInterfaceInstance using a public single method interface from the same package and followed by one from a different package.44* Wrapper is a public virtual method from same package and cross-package respectively.45* @throws Throwable46*/47@Test(groups = { "level.extended" })48public void test_asInterfaceInstance_VirtualMethod() throws Throwable {49//same package test50MethodHandle mh = MethodHandles.lookup().findVirtual( SamePackageExample.class, "addPublic", MethodType.methodType( int.class, int.class, int.class ) );51mh = mh.bindTo( new SamePackageExample() );52SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );53AssertJUnit.assertEquals( 3, interfaceInstance.singleMethodAdd( 1, 2 ) );5455//cross package test56MethodHandle mh2 = MethodHandles.lookup().findVirtual( PackageExamples.class, "addPublic", MethodType.methodType( int.class, int.class, int.class ) );57mh2 = mh2.bindTo( new PackageExamples() );58CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );59AssertJUnit.assertEquals( 3, interfaceInstanceCrossPackage.singleMethodAdd( 1, 2 ) );60}6162/**63* Tests asInterfaceInstance using a public single method interface from the same package and followed by one from a different package.64* Wrapper is a public static method from same package and cross-package respectively.65* @throws Throwable66*/67@Test(groups = { "level.extended" })68public void test_asInterfaceInstance_StaticMethod() throws Throwable {69//same package test70MethodHandle mh = MethodHandles.lookup().findStatic( SamePackageExample.class, "addPublicStatic", MethodType.methodType( int.class, int.class, int.class ) );71SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );72AssertJUnit.assertEquals( 3, interfaceInstance.singleMethodAdd( 1, 2 ) );7374//cross package test75MethodHandle mh2 = MethodHandles.lookup().findStatic( PackageExamples.class, "addPublicStatic", MethodType.methodType( int.class, int.class, int.class ) );76CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );77AssertJUnit.assertEquals( 3, interfaceInstanceCrossPackage.singleMethodAdd( 1, 2 ) );78}7980/**81* Tests asInterfaceInstance using a public single method interface from the same package and followed by one from a different package.82* Wrapper is a public virtual method defined in an inner class from same package and cross-package respectively.83* @throws Throwable84*/85@Test(groups = { "level.extended" })86public void test_asInterfaceInstance_InnerClass() throws Throwable {87//same package test88MethodHandle mh = MethodHandles.lookup().findVirtual( SamePackageExample.SamePackageInnerClass.class, "addPublicInner", MethodType.methodType( int.class, int.class, int.class ) );89SamePackageExample x = new SamePackageExample();90SamePackageExample.SamePackageInnerClass i = x.new SamePackageInnerClass();91mh = mh.bindTo( i );92SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );93AssertJUnit.assertEquals( 3, interfaceInstance.singleMethodAdd( 1, 2 ) );9495//cross package test96MethodHandle mh2 = MethodHandles.lookup().findVirtual( PackageExamples.CrossPackageInnerClass.class, "addPublicInner", MethodType.methodType( int.class, int.class, int.class ) );97PackageExamples y = new PackageExamples();98mh2 = mh2.bindTo( y.new CrossPackageInnerClass() );99CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );100AssertJUnit.assertEquals( 3, interfaceInstanceCrossPackage.singleMethodAdd( 1, 2 ) );101}102103104/******************************105*Tests for isWrapperInstance106******************************/107108/**109* Tests isWrapperInstance using a public single method interface from the same package and followed by one from a different package.110* Wrapper is a public virtual method defined in an inner class from same package and cross-package respectively.111* @throws Throwable112*/113@Test(groups = { "level.extended" })114public void test_isWrapperInstance_VirtualMethod() throws Throwable {115//same package test116MethodHandle mh = MethodHandles.lookup().findVirtual( SamePackageExample.class, "addPublic", MethodType.methodType( int.class, int.class, int.class ) );117mh = mh.bindTo( new SamePackageExample() );118SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );119AssertJUnit.assertTrue( MethodHandleProxies.isWrapperInstance( interfaceInstance ) );120121//cross package test122MethodHandle mh2 = MethodHandles.lookup().findVirtual( PackageExamples.class, "addPublic", MethodType.methodType( int.class, int.class, int.class ) );123mh2 = mh2.bindTo( new PackageExamples() );124CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );125AssertJUnit.assertTrue( MethodHandleProxies.isWrapperInstance( interfaceInstanceCrossPackage ) );126}127128/**129* Tests isWrapperInstance using a public single method interface from the same package and followed by one from a different package.130* Wrapper is a public static method from same package and cross-package respectively.131* @throws Throwable132*/133@Test(groups = { "level.extended" })134public void test_isWrapperInstance_StaticMethod() throws Throwable {135//same package test136MethodHandle mh = MethodHandles.lookup().findStatic( SamePackageExample.class, "addPublicStatic", MethodType.methodType( int.class, int.class, int.class ) );137SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );138AssertJUnit.assertTrue( MethodHandleProxies.isWrapperInstance( interfaceInstance ) );139140//cross package test141MethodHandle mh2 = MethodHandles.lookup().findStatic( PackageExamples.class, "addPublicStatic", MethodType.methodType( int.class, int.class, int.class ) );142CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );143AssertJUnit.assertTrue( MethodHandleProxies.isWrapperInstance( interfaceInstanceCrossPackage ) );144}145146/**147* Tests isWrapperInstance using a public single method interface from the same package and followed by one from a different package.148* Wrapper is a public virtual method defined in an inner class from same package and cross-package respectively.149* @throws Throwable150*/151@Test(groups = { "level.extended" })152public void test_isWrapperInstance_InnerClass() throws Throwable {153//same package test154MethodHandle mh = MethodHandles.lookup().findVirtual( SamePackageExample.SamePackageInnerClass.class, "addPublicInner", MethodType.methodType( int.class, int.class, int.class ) );155SamePackageExample x = new SamePackageExample();156SamePackageExample.SamePackageInnerClass i = x.new SamePackageInnerClass();157mh = mh.bindTo( i );158SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );159AssertJUnit.assertTrue( MethodHandleProxies.isWrapperInstance( interfaceInstance ) );160161//cross package test162MethodHandle mh2 = MethodHandles.lookup().findVirtual( PackageExamples.CrossPackageInnerClass.class, "addPublicInner", MethodType.methodType( int.class, int.class, int.class ) );163PackageExamples y = new PackageExamples();164mh2 = mh2.bindTo( y.new CrossPackageInnerClass() );165CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );166AssertJUnit.assertTrue( MethodHandleProxies.isWrapperInstance( interfaceInstanceCrossPackage ) );167}168169/**170* Negative test : verify isWrapperInstance returns false for non-wrapper objects.171* @throws Throwable172*/173@Test(groups = { "level.extended" })174public void test_isWrapperInstance_NegativeTest() throws Throwable {175//same package test176AssertJUnit.assertFalse( MethodHandleProxies.isWrapperInstance( new SamePackageSingleMethodInterfaceExample() {177178@Override179public int singleMethodAdd( int a, int b ) {180return 0;181}182} ) );183184//cross package test185AssertJUnit.assertFalse( MethodHandleProxies.isWrapperInstance( new PackageExamples() ) );186}187188/****************************************189* Tests for wrapperInstanceTarget190* *************************************/191192/**193* Tests wrapperInstanceTarget using single method interface and wrapper types from same package and cross-package194* @throws Throwable195*/196@Test(groups = { "level.extended" })197public void test_wrapperInstanceTarget_VirtualMethod() throws Throwable {198//same package test199MethodHandle mh = MethodHandles.lookup().findVirtual( SamePackageExample.class, "addPublic", MethodType.methodType( int.class, int.class, int.class ) );200mh = mh.bindTo( new SamePackageExample() );201SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );202MethodHandle retrievedTarget = MethodHandleProxies.wrapperInstanceTarget( interfaceInstance );203AssertJUnit.assertEquals( 4, ( int )retrievedTarget.invokeExact( 1, 3 ) );204205//cross package test206MethodHandle mh2 = MethodHandles.lookup().findVirtual( PackageExamples.class, "addPublic", MethodType.methodType( int.class, int.class, int.class ) );207mh2 = mh2.bindTo( new PackageExamples() );208CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );209MethodHandle retrievedTarget2 = MethodHandleProxies.wrapperInstanceTarget( interfaceInstanceCrossPackage );210AssertJUnit.assertEquals( 4, retrievedTarget2.invoke( 1, 3 ) );211}212213/**214* Tests wrapperInstanceTarget using single method interface and static wrapper methods from same package and cross-package215* @throws Throwable216*/217@Test(groups = { "level.extended" })218public void test_wrapperInstanceTarget_StaticMethod() throws Throwable {219//same package test220MethodHandle mh = MethodHandles.lookup().findStatic( SamePackageExample.class, "addPublicStatic", MethodType.methodType( int.class, int.class, int.class ) );221SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );222MethodHandle retrievedTarget = MethodHandleProxies.wrapperInstanceTarget( interfaceInstance );223AssertJUnit.assertEquals( 4, retrievedTarget.invoke( 1, 3 ) );224225//cross package test226MethodHandle mh2 = MethodHandles.lookup().findStatic( PackageExamples.class, "addPublicStatic", MethodType.methodType( int.class, int.class, int.class ) );227CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );228MethodHandle retrievedTarget2 = MethodHandleProxies.wrapperInstanceTarget( interfaceInstanceCrossPackage );229AssertJUnit.assertEquals( 4, ( int )retrievedTarget2.invokeExact( 1, 3 ) );230}231232/**233* Tests wrapperInstanceTarget using single method interface and inner-class wrapper types from same package and cross-package234* @throws Throwable235*/236@Test(groups = { "level.extended" })237public void test_wrapperInstanceTarget_InnerClass() throws Throwable {238//same package test239MethodHandle mh = MethodHandles.lookup().findVirtual( SamePackageExample.SamePackageInnerClass.class, "addPublicInner", MethodType.methodType( int.class, int.class, int.class ) );240SamePackageExample x = new SamePackageExample();241SamePackageExample.SamePackageInnerClass i = x.new SamePackageInnerClass();242mh = mh.bindTo( i );243SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );244MethodHandle retrievedTarget = MethodHandleProxies.wrapperInstanceTarget( interfaceInstance );245AssertJUnit.assertEquals( 4, ( int )retrievedTarget.invokeExact( 1, 3 ) );246247//cross package test248MethodHandle mh2 = MethodHandles.lookup().findVirtual( PackageExamples.CrossPackageInnerClass.class, "addPublicInner", MethodType.methodType( int.class, int.class, int.class ) );249PackageExamples y = new PackageExamples();250mh2 = mh2.bindTo( y.new CrossPackageInnerClass() );251CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );252MethodHandle retrievedTarget2 = MethodHandleProxies.wrapperInstanceTarget( interfaceInstanceCrossPackage );253AssertJUnit.assertEquals( 4, retrievedTarget2.invoke( 1, 3 ) );254}255256/**257* Negative test for verifying target retrieval failure for wrapperInstanceTarget method in case of non-wrapper instances.258* @throws Throwable259*/260@Test(groups = { "level.extended" })261public void test_wrapperInstanceTarget_NegativeTest() throws Throwable {262boolean notAWrapperInstance = false;263try {264MethodHandle retrievedTarget = MethodHandleProxies.wrapperInstanceTarget( new SamePackageExample() );265AssertJUnit.assertEquals( 4, ( int )retrievedTarget.invokeExact( 1, 3 ) );266}267catch( IllegalArgumentException e ) {268notAWrapperInstance = true;269}270271AssertJUnit.assertTrue( notAWrapperInstance );272}273274/**********************************275* Tests for wrapperInstanceType276* *******************************/277278/**279* Tests wrapperInstanceType using public virtual wrappers and single method interfaces from same package and cross-package.280* @throws Throwable281*/282@Test(groups = { "level.extended" })283public void test_wrapperInstanceType_VirtualMethod() throws Throwable {284//same package test285MethodHandle mh = MethodHandles.lookup().findVirtual( SamePackageExample.class, "addPublic", MethodType.methodType( int.class, int.class, int.class ) );286mh = mh.bindTo( new SamePackageExample() );287SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );288Class<?> retrievedTargetType = MethodHandleProxies.wrapperInstanceType( interfaceInstance );289AssertJUnit.assertEquals( SamePackageSingleMethodInterfaceExample.class, retrievedTargetType );290291//cross package test292MethodHandle mh2 = MethodHandles.lookup().findVirtual( PackageExamples.class, "addPublic", MethodType.methodType( int.class, int.class, int.class ) );293mh2 = mh2.bindTo( new PackageExamples() );294CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );295Class<?> retrievedTargetType2 = MethodHandleProxies.wrapperInstanceType( interfaceInstanceCrossPackage );296AssertJUnit.assertEquals( CrossPackageSingleMethodInterfaceExample.class, retrievedTargetType2 );297}298299/**300* Tests wrapperInstanceType using public static wrappers and single method interfaces from same package and cross-package.301* @throws Throwable302*/303@Test(groups = { "level.extended" })304public void test_wrapperInstanceType_StaticMethod() throws Throwable {305//same package test306MethodHandle mh = MethodHandles.lookup().findStatic( SamePackageExample.class, "addPublicStatic", MethodType.methodType( int.class, int.class, int.class ) );307SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );308Class<?> retrievedTargetType = MethodHandleProxies.wrapperInstanceType( interfaceInstance );309AssertJUnit.assertEquals( SamePackageSingleMethodInterfaceExample.class, retrievedTargetType );310311//cross package test312MethodHandle mh2 = MethodHandles.lookup().findStatic( PackageExamples.class, "addPublicStatic", MethodType.methodType( int.class, int.class, int.class ) );313CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );314Class<?> retrievedTargetType2 = MethodHandleProxies.wrapperInstanceType( interfaceInstanceCrossPackage );315AssertJUnit.assertEquals( CrossPackageSingleMethodInterfaceExample.class, retrievedTargetType2 );316}317318/**319* Tests wrapperInstanceType using inner-class wrappers and single method interfaces from same package and cross-package.320* @throws Throwable321*/322@Test(groups = { "level.extended" })323public void test_wrapperInstanceType_InnerClass() throws Throwable {324//same package test325MethodHandle mh = MethodHandles.lookup().findVirtual( SamePackageExample.SamePackageInnerClass.class, "addPublicInner", MethodType.methodType( int.class, int.class, int.class ) );326SamePackageExample x = new SamePackageExample();327SamePackageExample.SamePackageInnerClass i = x.new SamePackageInnerClass();328mh = mh.bindTo( i );329SamePackageSingleMethodInterfaceExample interfaceInstance = MethodHandleProxies.asInterfaceInstance( SamePackageSingleMethodInterfaceExample.class, mh );330Class<?> retrievedTargetType = MethodHandleProxies.wrapperInstanceType( interfaceInstance );331AssertJUnit.assertEquals( SamePackageSingleMethodInterfaceExample.class, retrievedTargetType );332333//cross package test334MethodHandle mh2 = MethodHandles.lookup().findVirtual( PackageExamples.CrossPackageInnerClass.class, "addPublicInner", MethodType.methodType( int.class, int.class, int.class ) );335PackageExamples y = new PackageExamples();336mh2 = mh2.bindTo( y.new CrossPackageInnerClass() );337CrossPackageSingleMethodInterfaceExample interfaceInstanceCrossPackage = MethodHandleProxies.asInterfaceInstance( CrossPackageSingleMethodInterfaceExample.class, mh2 );338Class<?> retrievedTargetType2 = MethodHandleProxies.wrapperInstanceType( interfaceInstanceCrossPackage );339AssertJUnit.assertEquals( CrossPackageSingleMethodInterfaceExample.class, retrievedTargetType2 );340}341342/**343* Negative test for wrapperInstanceType using non-wrapper types344* @throws Throwable345*/346@Test(groups = { "level.extended" })347public void test_wrapperInstanceType_NegativeTest() throws Throwable {348boolean notAWrapperInstance = false;349try {350Class<?> retrievedTargetType = MethodHandleProxies.wrapperInstanceType( new PackageExamples() );351AssertJUnit.assertEquals( SamePackageSingleMethodInterfaceExample.class, retrievedTargetType );352}353catch( IllegalArgumentException e ) {354notAWrapperInstance = true;355}356AssertJUnit.assertTrue( notAWrapperInstance );357}358}359360361