5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /* @test
25 * @summary unit tests for java.lang.invoke.MethodHandles
26 * @library /test/lib /java/lang/invoke/common
27 * @compile MethodHandlesTest.java MethodHandlesGeneralTest.java remote/RemoteExample.java
28 * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions
29 * -XX:-VerifyDependencies
30 * -esa
31 * test.java.lang.invoke.MethodHandlesGeneralTest
32 */
33
34 package test.java.lang.invoke;
35
36 import org.junit.*;
37 import test.java.lang.invoke.lib.CodeCacheOverflowProcessor;
38 import test.java.lang.invoke.remote.RemoteExample;
39
40 import java.lang.invoke.MethodHandle;
41 import java.lang.invoke.MethodHandleProxies;
42 import java.lang.invoke.MethodHandles;
43 import java.lang.invoke.MethodType;
44 import java.lang.invoke.WrongMethodTypeException;
647 testGetter(false, lookup,
648 new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
649 null, testMode);
650 }
651 }
652
653 public void testGetter(boolean positive, MethodHandles.Lookup lookup,
654 Object fieldRef, Object value, int testMode) throws Throwable {
655 testAccessor(positive, lookup, fieldRef, value, testMode);
656 }
657
658 public void testAccessor(boolean positive0, MethodHandles.Lookup lookup,
659 Object fieldRef, Object value, int testMode0) throws Throwable {
660 if (verbosity >= 4)
661 System.out.println("testAccessor"+Arrays.deepToString(new Object[]{positive0, lookup, fieldRef, value, testMode0}));
662 boolean isGetter = ((testMode0 & TEST_SETTER) == 0);
663 boolean doBound = ((testMode0 & TEST_BOUND) != 0);
664 boolean testNPE = ((testMode0 & TEST_NPE) != 0);
665 int testMode = testMode0 & ~(TEST_SETTER | TEST_BOUND | TEST_NPE);
666 boolean positive = positive0 && !testNPE;
667 boolean isStatic;
668 Class<?> fclass;
669 String fname;
670 Class<?> ftype;
671 Field f = (fieldRef instanceof Field ? (Field)fieldRef : null);
672 if (f != null) {
673 isStatic = Modifier.isStatic(f.getModifiers());
674 fclass = f.getDeclaringClass();
675 fname = f.getName();
676 ftype = f.getType();
677 } else {
678 Object[] scnt = (Object[]) fieldRef;
679 isStatic = (Boolean) scnt[0];
680 fclass = (Class<?>) scnt[1];
681 fname = (String) scnt[2];
682 ftype = (Class<?>) scnt[3];
683 try {
684 f = fclass.getDeclaredField(fname);
685 } catch (ReflectiveOperationException ex) {
686 f = null;
687 }
688 }
689 if (!testModeMatches(testMode, isStatic)) return;
690 if (f == null && testMode == TEST_UNREFLECT) return;
691 if (testNPE && isStatic) return;
692 countTest(positive);
693 MethodType expType;
694 if (isGetter)
695 expType = MethodType.methodType(ftype, HasFields.class);
696 else
697 expType = MethodType.methodType(void.class, HasFields.class, ftype);
698 if (isStatic) expType = expType.dropParameterTypes(0, 1);
699 Exception noAccess = null;
703 case TEST_UNREFLECT: mh = lookup.unreflectGetter(f); break;
704 case TEST_FIND_FIELD: mh = lookup.findGetter(fclass, fname, ftype); break;
705 case TEST_FIND_STATIC: mh = lookup.findStaticGetter(fclass, fname, ftype); break;
706 case TEST_SETTER|
707 TEST_UNREFLECT: mh = lookup.unreflectSetter(f); break;
708 case TEST_SETTER|
709 TEST_FIND_FIELD: mh = lookup.findSetter(fclass, fname, ftype); break;
710 case TEST_SETTER|
711 TEST_FIND_STATIC: mh = lookup.findStaticSetter(fclass, fname, ftype); break;
712 default:
713 throw new InternalError("testMode="+testMode);
714 }
715 } catch (ReflectiveOperationException ex) {
716 mh = null;
717 noAccess = ex;
718 assertExceptionClass(
719 (fname.contains("bogus"))
720 ? NoSuchFieldException.class
721 : IllegalAccessException.class,
722 noAccess);
723 if (verbosity >= 5) ex.printStackTrace(System.out);
724 }
725 if (verbosity >= 3)
726 System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype
727 +" => "+mh
728 +(noAccess == null ? "" : " !! "+noAccess));
729 if (positive && !testNPE && noAccess != null) throw new RuntimeException(noAccess);
730 assertEquals(positive0 ? "positive test" : "negative test erroneously passed", positive0, mh != null);
731 if (!positive && !testNPE) return; // negative access test failed as expected
732 assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount());
733
734
735 assertSame(mh.type(), expType);
736 //assertNameStringContains(mh, fname); // This does not hold anymore with LFs
737 HasFields fields = new HasFields();
738 HasFields fieldsForMH = fields;
739 if (testNPE) fieldsForMH = null; // perturb MH argument to elicit expected error
740 if (doBound)
741 mh = mh.bindTo(fieldsForMH);
742 Object sawValue;
743 Class<?> vtype = ftype;
744 if (ftype != int.class) vtype = Object.class;
745 if (isGetter) {
746 mh = mh.asType(mh.type().generic()
747 .changeReturnType(vtype));
748 } else {
749 int last = mh.type().parameterCount() - 1;
750 mh = mh.asType(mh.type().generic()
751 .changeReturnType(void.class)
752 .changeParameterType(last, vtype));
753 }
754 if (f != null && f.getDeclaringClass() == HasFields.class) {
761 sawValue = null; // make DA rules happy under try/catch
762 try {
763 if (isStatic || doBound) {
764 if (ftype == int.class)
765 sawValue = (int) mh.invokeExact(); // do these exactly
766 else
767 sawValue = mh.invokeExact();
768 } else {
769 if (ftype == int.class)
770 sawValue = (int) mh.invokeExact((Object) fieldsForMH);
771 else
772 sawValue = mh.invokeExact((Object) fieldsForMH);
773 }
774 } catch (RuntimeException ex) {
775 if (ex instanceof NullPointerException && testNPE) {
776 caughtEx = ex;
777 break;
778 }
779 }
780 assertEquals(sawValue, expValue);
781 if (f != null && f.getDeclaringClass() == HasFields.class
782 && !Modifier.isFinal(f.getModifiers())) {
783 Object random = randomArg(ftype);
784 f.set(fields, random);
785 expValue = random;
786 } else {
787 break;
788 }
789 }
790 } else {
791 for (int i = 0; i <= 1; i++) {
792 Object putValue = randomArg(ftype);
793 try {
794 if (isStatic || doBound) {
795 if (ftype == int.class)
796 mh.invokeExact((int)putValue); // do these exactly
797 else
798 mh.invokeExact(putValue);
799 } else {
800 if (ftype == int.class)
801 mh.invokeExact((Object) fieldsForMH, (int)putValue);
802 else
803 mh.invokeExact((Object) fieldsForMH, putValue);
804 }
805 } catch (RuntimeException ex) {
806 if (ex instanceof NullPointerException && testNPE) {
807 caughtEx = ex;
808 break;
809 }
810 }
811 if (f != null && f.getDeclaringClass() == HasFields.class) {
812 assertEquals(f.get(fields), putValue);
813 }
814 }
815 }
816 if (f != null && f.getDeclaringClass() == HasFields.class) {
817 f.set(fields, value); // put it back
818 }
819 if (testNPE) {
820 if (caughtEx == null || !(caughtEx instanceof NullPointerException))
821 throw new RuntimeException("failed to catch NPE exception"+(caughtEx == null ? " (caughtEx=null)" : ""), caughtEx);
822 caughtEx = null; // nullify expected exception
823 }
824 if (caughtEx != null) {
825 throw new RuntimeException("unexpected exception", caughtEx);
826 }
827 }
828
829 @Test
830 public void testUnreflectSetter() throws Throwable {
831 CodeCacheOverflowProcessor.runMHTest(this::testUnreflectSetter0);
832 }
833
834 public void testUnreflectSetter0() throws Throwable {
835 if (CAN_SKIP_WORKING) return;
836 startTest("unreflectSetter");
837 testSetter(TEST_UNREFLECT);
845 public void testFindSetter0() throws Throwable {
846 if (CAN_SKIP_WORKING) return;
847 startTest("findSetter");
848 testSetter(TEST_FIND_FIELD);
849 testSetter(TEST_FIND_FIELD | TEST_BOUND);
850 }
851
852 @Test
853 public void testFindStaticSetter() throws Throwable {
854 CodeCacheOverflowProcessor.runMHTest(this::testFindStaticSetter0);
855 }
856
857 public void testFindStaticSetter0() throws Throwable {
858 if (CAN_SKIP_WORKING) return;
859 startTest("findStaticSetter");
860 testSetter(TEST_FIND_STATIC);
861 }
862
863 public void testSetter(int testMode) throws Throwable {
864 Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
865 startTest("unreflectSetter");
866 for (Object[] c : HasFields.CASES) {
867 boolean positive = (c[1] != Error.class);
868 testSetter(positive, lookup, c[0], c[1], testMode);
869 if (positive)
870 testSetter(positive, lookup, c[0], c[1], testMode | TEST_NPE);
871 }
872 for (int isStaticN = 0; isStaticN <= 1; isStaticN++) {
873 testSetter(false, lookup,
874 new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
875 null, testMode);
876 }
877 }
878
879 public void testSetter(boolean positive, MethodHandles.Lookup lookup,
880 Object fieldRef, Object value, int testMode) throws Throwable {
881 testAccessor(positive, lookup, fieldRef, value, testMode | TEST_SETTER);
882 }
883
884 @Test
885 public void testArrayElementGetter() throws Throwable {
|
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /* @test
25 * @bug 8216558
26 * @summary unit tests for java.lang.invoke.MethodHandles
27 * @library /test/lib /java/lang/invoke/common
28 * @compile MethodHandlesTest.java MethodHandlesGeneralTest.java remote/RemoteExample.java
29 * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions
30 * -XX:-VerifyDependencies
31 * -esa
32 * test.java.lang.invoke.MethodHandlesGeneralTest
33 */
34
35 package test.java.lang.invoke;
36
37 import org.junit.*;
38 import test.java.lang.invoke.lib.CodeCacheOverflowProcessor;
39 import test.java.lang.invoke.remote.RemoteExample;
40
41 import java.lang.invoke.MethodHandle;
42 import java.lang.invoke.MethodHandleProxies;
43 import java.lang.invoke.MethodHandles;
44 import java.lang.invoke.MethodType;
45 import java.lang.invoke.WrongMethodTypeException;
648 testGetter(false, lookup,
649 new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
650 null, testMode);
651 }
652 }
653
654 public void testGetter(boolean positive, MethodHandles.Lookup lookup,
655 Object fieldRef, Object value, int testMode) throws Throwable {
656 testAccessor(positive, lookup, fieldRef, value, testMode);
657 }
658
659 public void testAccessor(boolean positive0, MethodHandles.Lookup lookup,
660 Object fieldRef, Object value, int testMode0) throws Throwable {
661 if (verbosity >= 4)
662 System.out.println("testAccessor"+Arrays.deepToString(new Object[]{positive0, lookup, fieldRef, value, testMode0}));
663 boolean isGetter = ((testMode0 & TEST_SETTER) == 0);
664 boolean doBound = ((testMode0 & TEST_BOUND) != 0);
665 boolean testNPE = ((testMode0 & TEST_NPE) != 0);
666 int testMode = testMode0 & ~(TEST_SETTER | TEST_BOUND | TEST_NPE);
667 boolean positive = positive0 && !testNPE;
668 boolean isFinal;
669 boolean isStatic;
670 Class<?> fclass;
671 String fname;
672 Class<?> ftype;
673 Field f = (fieldRef instanceof Field ? (Field)fieldRef : null);
674 if (f != null) {
675 isStatic = Modifier.isStatic(f.getModifiers());
676 isFinal = Modifier.isFinal(f.getModifiers());
677 fclass = f.getDeclaringClass();
678 fname = f.getName();
679 ftype = f.getType();
680 } else {
681 Object[] scnt = (Object[]) fieldRef;
682 isStatic = (Boolean) scnt[0];
683 isFinal = false;
684 fclass = (Class<?>) scnt[1];
685 fname = (String) scnt[2];
686 ftype = (Class<?>) scnt[3];
687 try {
688 f = fclass.getDeclaredField(fname);
689 } catch (ReflectiveOperationException ex) {
690 f = null;
691 }
692 }
693 if (!testModeMatches(testMode, isStatic)) return;
694 if (f == null && testMode == TEST_UNREFLECT) return;
695 if (testNPE && isStatic) return;
696 countTest(positive);
697 MethodType expType;
698 if (isGetter)
699 expType = MethodType.methodType(ftype, HasFields.class);
700 else
701 expType = MethodType.methodType(void.class, HasFields.class, ftype);
702 if (isStatic) expType = expType.dropParameterTypes(0, 1);
703 Exception noAccess = null;
707 case TEST_UNREFLECT: mh = lookup.unreflectGetter(f); break;
708 case TEST_FIND_FIELD: mh = lookup.findGetter(fclass, fname, ftype); break;
709 case TEST_FIND_STATIC: mh = lookup.findStaticGetter(fclass, fname, ftype); break;
710 case TEST_SETTER|
711 TEST_UNREFLECT: mh = lookup.unreflectSetter(f); break;
712 case TEST_SETTER|
713 TEST_FIND_FIELD: mh = lookup.findSetter(fclass, fname, ftype); break;
714 case TEST_SETTER|
715 TEST_FIND_STATIC: mh = lookup.findStaticSetter(fclass, fname, ftype); break;
716 default:
717 throw new InternalError("testMode="+testMode);
718 }
719 } catch (ReflectiveOperationException ex) {
720 mh = null;
721 noAccess = ex;
722 assertExceptionClass(
723 (fname.contains("bogus"))
724 ? NoSuchFieldException.class
725 : IllegalAccessException.class,
726 noAccess);
727 if (((testMode0 & TEST_SETTER) != 0) && (isFinal && isStatic)) return; // Final static field setter test failed as intended.
728 if (verbosity >= 5) ex.printStackTrace(System.out);
729 }
730 if (verbosity >= 3)
731 System.out.println((((testMode0 & TEST_UNREFLECT) != 0)?"unreflect":"find")
732 +(((testMode0 & TEST_FIND_STATIC) != 0)?"Static":"")
733 +(isGetter?"Getter":"Setter")
734 +" "+fclass.getName()+"."+fname+"/"+ftype
735 +" => "+mh
736 +(noAccess == null ? "" : " !! "+noAccess));
737 if (positive && !testNPE && noAccess != null) throw new RuntimeException(noAccess);
738 assertEquals(positive0 ? "positive test" : "negative test erroneously passed", positive0, mh != null);
739 assertFalse("Setter methods should throw an exception if passed a final static field.", ((testMode0 & TEST_SETTER) != 0) && (isFinal && isStatic));
740 if (!positive && !testNPE) return; // negative access test failed as expected
741 assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount());
742 assertSame(mh.type(), expType);
743 //assertNameStringContains(mh, fname); // This does not hold anymore with LFs
744 HasFields fields = new HasFields();
745 HasFields fieldsForMH = fields;
746 if (testNPE) fieldsForMH = null; // perturb MH argument to elicit expected error
747 if (doBound)
748 mh = mh.bindTo(fieldsForMH);
749 Object sawValue;
750 Class<?> vtype = ftype;
751 if (ftype != int.class) vtype = Object.class;
752 if (isGetter) {
753 mh = mh.asType(mh.type().generic()
754 .changeReturnType(vtype));
755 } else {
756 int last = mh.type().parameterCount() - 1;
757 mh = mh.asType(mh.type().generic()
758 .changeReturnType(void.class)
759 .changeParameterType(last, vtype));
760 }
761 if (f != null && f.getDeclaringClass() == HasFields.class) {
768 sawValue = null; // make DA rules happy under try/catch
769 try {
770 if (isStatic || doBound) {
771 if (ftype == int.class)
772 sawValue = (int) mh.invokeExact(); // do these exactly
773 else
774 sawValue = mh.invokeExact();
775 } else {
776 if (ftype == int.class)
777 sawValue = (int) mh.invokeExact((Object) fieldsForMH);
778 else
779 sawValue = mh.invokeExact((Object) fieldsForMH);
780 }
781 } catch (RuntimeException ex) {
782 if (ex instanceof NullPointerException && testNPE) {
783 caughtEx = ex;
784 break;
785 }
786 }
787 assertEquals(sawValue, expValue);
788 if (f != null && f.getDeclaringClass() == HasFields.class && !isFinal) {
789 Object random = randomArg(ftype);
790 f.set(fields, random);
791 expValue = random;
792 } else {
793 break;
794 }
795 }
796 } else {
797 for (int i = 0; i <= 1; i++) {
798 Object putValue = randomArg(ftype);
799 try {
800 if (isStatic || doBound) {
801 if (ftype == int.class)
802 mh.invokeExact((int)putValue); // do these exactly
803 else
804 mh.invokeExact(putValue);
805 } else {
806 if (ftype == int.class)
807 mh.invokeExact((Object) fieldsForMH, (int)putValue);
808 else
809 mh.invokeExact((Object) fieldsForMH, putValue);
810 }
811 } catch (RuntimeException ex) {
812 if (ex instanceof NullPointerException && testNPE) {
813 caughtEx = ex;
814 break;
815 }
816 }
817 if (f != null && f.getDeclaringClass() == HasFields.class) {
818 assertEquals(f.get(fields), putValue);
819 }
820 }
821 }
822 if ((f != null) && (f.getDeclaringClass() == HasFields.class) && !isFinal) {
823 f.set(fields, value); // put it back if we changed it.
824 }
825 if (testNPE) {
826 if (caughtEx == null || !(caughtEx instanceof NullPointerException))
827 throw new RuntimeException("failed to catch NPE exception"+(caughtEx == null ? " (caughtEx=null)" : ""), caughtEx);
828 caughtEx = null; // nullify expected exception
829 }
830 if (caughtEx != null) {
831 throw new RuntimeException("unexpected exception", caughtEx);
832 }
833 }
834
835 @Test
836 public void testUnreflectSetter() throws Throwable {
837 CodeCacheOverflowProcessor.runMHTest(this::testUnreflectSetter0);
838 }
839
840 public void testUnreflectSetter0() throws Throwable {
841 if (CAN_SKIP_WORKING) return;
842 startTest("unreflectSetter");
843 testSetter(TEST_UNREFLECT);
851 public void testFindSetter0() throws Throwable {
852 if (CAN_SKIP_WORKING) return;
853 startTest("findSetter");
854 testSetter(TEST_FIND_FIELD);
855 testSetter(TEST_FIND_FIELD | TEST_BOUND);
856 }
857
858 @Test
859 public void testFindStaticSetter() throws Throwable {
860 CodeCacheOverflowProcessor.runMHTest(this::testFindStaticSetter0);
861 }
862
863 public void testFindStaticSetter0() throws Throwable {
864 if (CAN_SKIP_WORKING) return;
865 startTest("findStaticSetter");
866 testSetter(TEST_FIND_STATIC);
867 }
868
869 public void testSetter(int testMode) throws Throwable {
870 Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
871 for (Object[] c : HasFields.CASES) {
872 boolean positive = (c[1] != Error.class);
873 testSetter(positive, lookup, c[0], c[1], testMode);
874 if (positive)
875 testSetter(positive, lookup, c[0], c[1], testMode | TEST_NPE);
876 }
877 for (int isStaticN = 0; isStaticN <= 1; isStaticN++) {
878 testSetter(false, lookup,
879 new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
880 null, testMode);
881 }
882 }
883
884 public void testSetter(boolean positive, MethodHandles.Lookup lookup,
885 Object fieldRef, Object value, int testMode) throws Throwable {
886 testAccessor(positive, lookup, fieldRef, value, testMode | TEST_SETTER);
887 }
888
889 @Test
890 public void testArrayElementGetter() throws Throwable {
|