BeansLinkerTest.java revision 1551:f3b883bec2d0
1100966Siwasaki/* 2100966Siwasaki * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3100966Siwasaki * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4100966Siwasaki * 5100966Siwasaki * This code is free software; you can redistribute it and/or modify it 6100966Siwasaki * under the terms of the GNU General Public License version 2 only, as 7217365Sjkim * published by the Free Software Foundation. Oracle designates this 8245582Sjkim * particular file as subject to the "Classpath" exception as provided 9100966Siwasaki * by Oracle in the LICENSE file that accompanied this code. 10100966Siwasaki * 11217365Sjkim * This code is distributed in the hope that it will be useful, but WITHOUT 12217365Sjkim * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13217365Sjkim * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14217365Sjkim * version 2 for more details (a copy is included in the LICENSE file that 15217365Sjkim * accompanied this code). 16217365Sjkim * 17217365Sjkim * You should have received a copy of the GNU General Public License version 18217365Sjkim * 2 along with this work; if not, write to the Free Software Foundation, 19217365Sjkim * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20217365Sjkim * 21217365Sjkim * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22217365Sjkim * or visit www.oracle.com if you need additional information or have any 23217365Sjkim * questions. 24217365Sjkim */ 25100966Siwasakipackage jdk.dynalink.beans.test; 26217365Sjkim 27217365Sjkimimport static jdk.dynalink.StandardOperation.CALL; 28217365Sjkimimport static jdk.dynalink.StandardOperation.GET_ELEMENT; 29100966Siwasakiimport static jdk.dynalink.StandardOperation.GET_METHOD; 30217365Sjkimimport static jdk.dynalink.StandardOperation.GET_PROPERTY; 31217365Sjkimimport static jdk.dynalink.StandardOperation.SET_ELEMENT; 32217365Sjkimimport static jdk.dynalink.StandardOperation.SET_PROPERTY; 33217365Sjkim 34217365Sjkimimport java.lang.invoke.MethodHandles; 35217365Sjkimimport java.lang.invoke.MethodType; 36217365Sjkimimport java.util.Collections; 37217365Sjkimimport java.util.HashMap; 38217365Sjkimimport java.util.Map; 39217365Sjkimimport java.util.function.Consumer; 40217365Sjkimimport java.util.function.Predicate; 41217365Sjkimimport java.util.regex.Pattern; 42217365Sjkimimport java.util.stream.Stream; 43100966Siwasakiimport jdk.dynalink.CallSiteDescriptor; 44100966Siwasakiimport jdk.dynalink.CompositeOperation; 45100966Siwasakiimport jdk.dynalink.DynamicLinkerFactory; 46100966Siwasakiimport jdk.dynalink.NamedOperation; 47193341Sjkimimport jdk.dynalink.Operation; 48100966Siwasakiimport jdk.dynalink.StandardOperation; 49100966Siwasakiimport jdk.dynalink.support.SimpleRelinkableCallSite; 50100966Siwasakiimport org.testng.Assert; 51100966Siwasakiimport org.testng.annotations.Test; 52100966Siwasaki 53100966Siwasakipublic class BeansLinkerTest { 54167802Sjkim public static class Bean1 { 55100966Siwasaki public final int answer = 42; 56217365Sjkim 57217365Sjkim public String getName() { 58217365Sjkim return "bean1"; 59217365Sjkim } 60217365Sjkim 61128212Snjl public String someMethod(final String x) { 62217365Sjkim return x + "-foo"; 63167802Sjkim } 64167802Sjkim } 65167802Sjkim 66229989Sjkim @Test 67167802Sjkim public static void testPublicFieldPropertyUnnamedGetter() { 68209746Sjkim testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals(42, call(op, new Bean1(), "answer"))); 69100966Siwasaki } 70167802Sjkim 71100966Siwasaki @Test 72209746Sjkim public static void testPublicFieldPropertyNamedGetter() { 73209746Sjkim testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals(42, call(named("answer", op), new Bean1()))); 74209746Sjkim } 75209746Sjkim 76209746Sjkim @Test 77209746Sjkim public static void testGetterPropertyUnnamedGetter() { 78209746Sjkim testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals("bean1", call(op, new Bean1(), "name"))); 79209746Sjkim } 80209746Sjkim 81167802Sjkim @Test 82167802Sjkim public static void testGetterPropertyNamedGetter() { 83228110Sjkim testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals("bean1", call(named("name", op), new Bean1()))); 84228110Sjkim } 85167802Sjkim 86228110Sjkim @Test 87228110Sjkim public static void testMethodUnnamedGetter() { 88228110Sjkim testGetterPermutations(GET_METHOD, (op) -> Assert.assertEquals("bar-foo", call(call(op, new Bean1(), "someMethod"), new Bean1(), "bar"))); 89167802Sjkim } 90228110Sjkim 91228110Sjkim @Test 92228110Sjkim public static void testMethodNamedGetter() { 93228110Sjkim testGetterPermutations(GET_METHOD, (op) -> Assert.assertEquals("bar-foo", call(call(named("someMethod", op), new Bean1()), new Bean1(), "bar"))); 94228110Sjkim } 95228110Sjkim 96228110Sjkim private static final Map<String, String> MAP1 = new HashMap<>(); 97228110Sjkim static { 98228110Sjkim MAP1.put("foo", "bar"); 99228110Sjkim } 100228110Sjkim 101228110Sjkim @Test 102228110Sjkim public static void testElementUnnamedGetter() { 103228110Sjkim testGetterPermutations(GET_ELEMENT, (op) -> Assert.assertEquals("bar", call(op, MAP1, "foo"))); 104228110Sjkim } 105228110Sjkim 106228110Sjkim @Test 107228110Sjkim public static void testElementNamedGetter() { 108228110Sjkim testGetterPermutations(GET_ELEMENT, (op) -> Assert.assertEquals("bar", call(named("foo", op), MAP1))); 109228110Sjkim } 110228110Sjkim 111252279Sjkim public static class Bean2 { 112228110Sjkim public int answer; 113228110Sjkim private String name; 114228110Sjkim 115228110Sjkim public void setName(final String name) { 116228110Sjkim this.name = name; 117228110Sjkim } 118228110Sjkim } 119228110Sjkim 120228110Sjkim @Test 121228110Sjkim public static void testUnnamedFieldSetter() { 122228110Sjkim testSetterPermutations(SET_PROPERTY, (op) -> { 123228110Sjkim final Bean2 bean2 = new Bean2(); 124228110Sjkim call(op, bean2, "answer", 12); 125228110Sjkim Assert.assertEquals(bean2.answer, 12); 126228110Sjkim }); 127228110Sjkim } 128228110Sjkim 129228110Sjkim @Test 130228110Sjkim public static void testNamedFieldSetter() { 131228110Sjkim testSetterPermutations(SET_PROPERTY, (op) -> { 132228110Sjkim final Bean2 bean2 = new Bean2(); 133228110Sjkim call(named("answer", op), bean2, 14); 134228110Sjkim Assert.assertEquals(bean2.answer, 14); 135228110Sjkim }); 136228110Sjkim } 137228110Sjkim 138228110Sjkim @Test 139228110Sjkim public static void testUnnamedPropertySetter() { 140228110Sjkim testSetterPermutations(SET_PROPERTY, (op) -> { 141228110Sjkim final Bean2 bean2 = new Bean2(); 142228110Sjkim call(op, bean2, "name", "boo"); 143228110Sjkim Assert.assertEquals(bean2.name, "boo"); 144228110Sjkim }); 145228110Sjkim } 146228110Sjkim 147228110Sjkim @Test 148228110Sjkim public static void testNamedPropertySetter() { 149228110Sjkim testSetterPermutations(SET_PROPERTY, (op) -> { 150228110Sjkim final Bean2 bean2 = new Bean2(); 151228110Sjkim call(named("name", op), bean2, "blah"); 152228110Sjkim Assert.assertEquals(bean2.name, "blah"); 153228110Sjkim }); 154228110Sjkim } 155228110Sjkim 156228110Sjkim private static final Pattern GET_ELEMENT_THEN_PROPERTY_PATTERN = Pattern.compile(".*GET_ELEMENT.*GET_PROPERTY.*"); 157228110Sjkim 158228110Sjkim @Test 159228110Sjkim public static void testUnnamedElementAndPropertyGetter() { 160228110Sjkim final Map<String, Object> map = new HashMap<>(); 161167802Sjkim map.put("empty", true); 162193267Sjkim testGetterPermutations(GET_ELEMENT_THEN_PROPERTY_PATTERN, 4, (op) -> Assert.assertEquals(true, call(op, map, "empty"))); 163167802Sjkim } 164167802Sjkim 165209746Sjkim @Test 166209746Sjkim public static void testNamedElementAndPropertyGetter() { 167209746Sjkim final Map<String, Object> map = new HashMap<>(); 168209746Sjkim map.put("empty", true); 169167802Sjkim testGetterPermutations(GET_ELEMENT_THEN_PROPERTY_PATTERN, 4, (op) -> Assert.assertEquals(true, call(named("empty", op), map))); 170167802Sjkim } 171167802Sjkim 172193267Sjkim private static final Pattern GET_PROPERTY_THEN_ELEMENT_PATTERN = Pattern.compile(".*GET_PROPERTY.*GET_ELEMENT.*"); 173193267Sjkim 174209746Sjkim @Test 175209746Sjkim public static void testUnnamedPropertyAndElementGetter() { 176167802Sjkim final Map<String, Object> map = new HashMap<>(); 177167802Sjkim map.put("empty", true); 178167802Sjkim testGetterPermutations(GET_PROPERTY_THEN_ELEMENT_PATTERN, 4, (op) -> Assert.assertEquals(false, call(op, map, "empty"))); 179167802Sjkim } 180167802Sjkim 181100966Siwasaki @Test 182100966Siwasaki public static void testNamedPropertyAndElementGetter() { 183100966Siwasaki final Map<String, Object> map = new HashMap<>(); 184167802Sjkim map.put("empty", true); 185167802Sjkim testGetterPermutations(GET_PROPERTY_THEN_ELEMENT_PATTERN, 4, (op) -> Assert.assertEquals(false, call(named("empty", op), map))); 186100966Siwasaki } 187167802Sjkim 188151937Sjkim public static class MapWithProperty extends HashMap<String, Object> { 189100966Siwasaki private String name; 190100966Siwasaki 191100966Siwasaki public void setName(final String name) { 192209746Sjkim this.name = name; 193209746Sjkim } 194209746Sjkim } 195209746Sjkim 196100966Siwasaki @Test 197100966Siwasaki public static void testUnnamedPropertyAndElementSetter() { 198100966Siwasaki final MapWithProperty map = new MapWithProperty(); 199100966Siwasaki map.put("name", "element"); 200100966Siwasaki 201209746Sjkim call(ops(SET_PROPERTY, SET_ELEMENT), map, "name", "property"); 202209746Sjkim Assert.assertEquals("property", map.name); 203100966Siwasaki Assert.assertEquals("element", map.get("name")); 204228110Sjkim 205228110Sjkim call(ops(SET_ELEMENT, SET_PROPERTY), map, "name", "element2"); 206228110Sjkim Assert.assertEquals("property", map.name); 207228110Sjkim Assert.assertEquals("element2", map.get("name")); 208228110Sjkim } 209209746Sjkim 210167802Sjkim private static Operation[] GETTER_PERMUTATIONS = new Operation[] { 211167802Sjkim GET_PROPERTY, 212167802Sjkim GET_METHOD, 213167802Sjkim GET_ELEMENT, 214100966Siwasaki ops(GET_PROPERTY, GET_ELEMENT), 215167802Sjkim ops(GET_PROPERTY, GET_METHOD), 216167802Sjkim ops(GET_ELEMENT, GET_PROPERTY), 217167802Sjkim ops(GET_ELEMENT, GET_METHOD), 218167802Sjkim ops(GET_METHOD, GET_PROPERTY), 219167802Sjkim ops(GET_METHOD, GET_ELEMENT), 220167802Sjkim ops(GET_PROPERTY, GET_ELEMENT, GET_METHOD), 221167802Sjkim ops(GET_PROPERTY, GET_METHOD, GET_ELEMENT), 222167802Sjkim ops(GET_ELEMENT, GET_PROPERTY, GET_METHOD), 223167802Sjkim ops(GET_ELEMENT, GET_METHOD, GET_PROPERTY), 224167802Sjkim ops(GET_METHOD, GET_PROPERTY, GET_ELEMENT), 225167802Sjkim ops(GET_METHOD, GET_ELEMENT, GET_PROPERTY), 226167802Sjkim }; 227167802Sjkim 228167802Sjkim private static Operation[] SETTER_PERMUTATIONS = new Operation[] { 229167802Sjkim SET_PROPERTY, 230167802Sjkim SET_ELEMENT, 231167802Sjkim ops(SET_PROPERTY, SET_ELEMENT), 232167802Sjkim ops(SET_ELEMENT, SET_PROPERTY) 233167802Sjkim }; 234167802Sjkim 235193267Sjkim private static void testPermutations(final Operation[] ops, final StandardOperation requiredOp, final int expectedCount, final Consumer<Operation> test) { 236228110Sjkim testPermutationsWithFilter(ops, (op)->CompositeOperation.contains(op, requiredOp), expectedCount, test); 237167802Sjkim } 238167802Sjkim 239239340Sjkim private static void testPermutations(final Operation[] ops, final Pattern regex, final int expectedCount, final Consumer<Operation> test) { 240239340Sjkim testPermutationsWithFilter(ops, (op)->regex.matcher(op.toString()).matches(), expectedCount, test); 241245582Sjkim } 242239340Sjkim 243239340Sjkim private static void testPermutationsWithFilter(final Operation[] ops, final Predicate<Operation> filter, final int expectedCount, final Consumer<Operation> test) { 244239340Sjkim final int[] counter = new int[1]; 245239340Sjkim Stream.of(ops).filter(filter).forEach((op)-> { counter[0]++; test.accept(op); }); 246239340Sjkim Assert.assertEquals(counter[0], expectedCount); 247167802Sjkim } 248167802Sjkim 249167802Sjkim private static void testGetterPermutations(final StandardOperation requiredOp, final Consumer<Operation> test) { 250167802Sjkim testPermutations(GETTER_PERMUTATIONS, requiredOp, 11, test); 251167802Sjkim } 252167802Sjkim 253193267Sjkim private static void testGetterPermutations(final Pattern regex, final int expectedCount, final Consumer<Operation> test) { 254197104Sjkim testPermutations(GETTER_PERMUTATIONS, regex, expectedCount, test); 255228110Sjkim } 256167802Sjkim 257193267Sjkim private static void testSetterPermutations(final StandardOperation requiredOp, final Consumer<Operation> test) { 258193267Sjkim testPermutations(SETTER_PERMUTATIONS, requiredOp, 3, test); 259193267Sjkim } 260209746Sjkim 261167802Sjkim private static Object call(final Operation op, final Object... args) { 262167802Sjkim try { 263167802Sjkim return new DynamicLinkerFactory().createLinker().link( 264193267Sjkim new SimpleRelinkableCallSite(new CallSiteDescriptor( 265228110Sjkim MethodHandles.publicLookup(), op, t(args.length)))) 266228110Sjkim .dynamicInvoker().invokeWithArguments(args); 267228110Sjkim } catch (final Error|RuntimeException e) { 268228110Sjkim throw e; 269228110Sjkim } catch (final Throwable t) { 270167802Sjkim throw new RuntimeException(t); 271228110Sjkim } 272167802Sjkim } 273193267Sjkim 274193267Sjkim private static Object call(final Object... args) { 275193267Sjkim return call(CALL, args); 276197104Sjkim } 277193267Sjkim 278193267Sjkim private static Operation named(final Object name, final Operation... ops) { 279193267Sjkim return new NamedOperation(ops(ops), name); 280193267Sjkim } 281193267Sjkim 282197104Sjkim private static Operation ops(final Operation... ops) { 283167802Sjkim return ops.length == 1 ? ops[0] : new CompositeOperation(ops); 284197104Sjkim } 285197104Sjkim 286197104Sjkim private static MethodType t(final int argCount) { 287197104Sjkim return MethodType.methodType(Object.class, Collections.nCopies(argCount, Object.class)); 288197104Sjkim } 289197104Sjkim} 290197104Sjkim