1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 /* 25 * @test 26 * @summary Test core reflection, dynamic proxy and lambdas that generates 27 * classes dynamically that reference Q-type and L-type 28 * @compile -XDallowWithFieldOperator Point.java Line.java MutablePath.java 29 * @compile -XDallowWithFieldOperator NonFlattenValue.java 30 * @run testng/othervm -XX:+EnableValhalla -Dsun.reflect.inflationThreshold=0 QTypeDescriptorTest 31 */ 32 33 import java.lang.invoke.MethodHandle; 34 import java.lang.invoke.MethodHandles; 35 import java.lang.invoke.MethodType; 36 import java.lang.reflect.*; 37 import java.util.function.*; 38 39 import org.testng.annotations.DataProvider; 40 import org.testng.annotations.Test; 41 import static org.testng.Assert.*; 42 43 public class QTypeDescriptorTest { 44 static final Point P0 = Point.makePoint(10, 20); 45 static final Point P1 = Point.makePoint(30, 40); 46 static final NonFlattenValue NFV = NonFlattenValue.make(30, 40); 47 48 @Test 49 public static void testLambda() { 50 newArray(Point[]::new, 2); 51 newArray(Point[][]::new, 1); 52 53 newArray(NonFlattenValue[]::new, 3); 54 newArray(MutablePath[]::new, 4); 55 56 Function<Point[], T> f = 57 (points) -> { return new T(points); }; 58 f.apply(new Point[] { P0, P1}); 59 } 60 61 @Test 62 public static void testMethodInvoke() throws Exception { 63 Class<?> pointQType = Point.class.asValueType(); 64 Class<?> nonFlattenValueQType = NonFlattenValue.class.asValueType(); 65 Method m = QTypeDescriptorTest.class 66 .getDeclaredMethod("toLine", pointQType, nonFlattenValueQType); 67 makeLine(m, P0, NFV); 68 69 m = QTypeDescriptorTest.class 70 .getDeclaredMethod("toLine", Point[].class); 71 makeLine(m, (Object) new Point[] { P0, P1}); 72 } 73 74 private static void makeLine(Method m, Object... args) throws Exception { 75 Line l = (Line) m.invoke(null, args); 76 assertEquals(l.p1, P0); 77 assertEquals(l.p2, NFV.pointValue()); 78 } 79 80 @Test 81 public static void testStaticMethod() throws Throwable { 82 // static method in a value type with no parameter and void return type 83 Runnable r = () -> ValueTest.run(); 84 r.run(); 85 86 // via Method::invoke 87 Method m = ValueTest.class.getMethod("run"); 88 m.invoke(null); 89 90 // via MethodHandle 91 MethodHandle mh = MethodHandles.lookup() 92 .findStatic(ValueTest.class, "run", MethodType.methodType(void.class)); 93 mh.invokeExact(); 94 } 95 96 @Test 97 public static void testConstructor() throws Exception { 98 Constructor<T> ctor = T.class.getDeclaredConstructor(Point[].class); 99 Point[] points = new Point[] { P0, P1 }; 100 T test = (T) ctor.newInstance((Object)points); 101 assertEquals(test.points[0], P0); 102 assertEquals(test.points[1], P1); 103 } 104 105 @Test 106 public static void testProxy() throws Exception { 107 InvocationHandler handler = new InvocationHandler() { 108 @Override 109 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 110 if (method.getName().equals("toLine")) { 111 return toLine((Point)args[0], (NonFlattenValue)args[1]); 112 } 113 throw new UnsupportedOperationException(method.toString()); 114 } 115 }; 116 117 Class<?>[] intfs = new Class<?>[] { I.class }; 118 I intf = (I) Proxy.newProxyInstance(QTypeDescriptorTest.class.getClassLoader(), intfs, handler); 119 Line l = intf.toLine(P0, NFV); 120 assertEquals(l.p1, P0); 121 assertEquals(l.p2, NFV.pointValue()); 122 } 123 124 private static <T> T[] newArray(IntFunction<T[]> arrayCreator, int size) { 125 return arrayCreator.apply(size); 126 } 127 128 private static Line toLine(Point p, NonFlattenValue nfv) { 129 return Line.makeLine(p, nfv.pointValue()); 130 } 131 132 private static Line toLine(Point[] points) { 133 assertTrue(points.length == 2); 134 return Line.makeLine(points[0], points[1]); 135 } 136 137 static class T { 138 final Point[] points; 139 T(Point[] points) { 140 this.points = points; 141 } 142 } 143 144 interface I { 145 Line toLine(Point p, NonFlattenValue nfv); 146 } 147 148 static value class ValueTest { 149 private final int value; 150 public ValueTest() { this.value = 0; } 151 152 public static void run() { 153 Runnable r = () -> { 154 System.out.println("called ValueTest::run"); 155 }; 156 r.run(); 157 } 158 } 159 160 }