1923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller/* 2923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * Copyright (C) 2016 The Android Open Source Project 3923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * 4923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * Licensed under the Apache License, Version 2.0 (the "License"); 5923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * you may not use this file except in compliance with the License. 6923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * You may obtain a copy of the License at 7923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * 8923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * http://www.apache.org/licenses/LICENSE-2.0 9923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * 10923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * Unless required by applicable law or agreed to in writing, software 11923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * distributed under the License is distributed on an "AS IS" BASIS, 12923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * See the License for the specific language governing permissions and 14923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller * limitations under the License. 15923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller */ 16923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 17923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerpackage libcore.java.lang; 18923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 19923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport junit.framework.TestCase; 20923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 21923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.io.ByteArrayInputStream; 22923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.io.ByteArrayOutputStream; 23923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.io.IOException; 24923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.io.NotSerializableException; 25923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.io.ObjectInputStream; 26923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.io.ObjectOutputStream; 27923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.io.Serializable; 28923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.lang.reflect.Method; 29923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.lang.reflect.Modifier; 30ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fullerimport java.util.ArrayList; 31923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.util.Arrays; 32923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.util.HashSet; 33923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.util.List; 34923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.util.Set; 35923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.util.concurrent.Callable; 36923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 37923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerpublic class LambdaImplementationTest extends TestCase { 38923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 39ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller private static final String STATIC_METHOD_RESPONSE = "StaticMethodResponse"; 40923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 41923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testNonCapturingLambda() throws Exception { 42ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller Callable<String> r1 = () -> "Hello World"; 43923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 44923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class); 45923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 46923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(r1); 47ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertCallableBehavior(r1, "Hello World"); 48923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 49ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller List<Callable<String>> callables = new ArrayList<>(); 50ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller for (int i = 0; i < 2; i++) { 51ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller callables.add(() -> "Hello World"); 52ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller } 53ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleDefinitionCharacteristics(r1, callables.get(0)); 54ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1)); 55923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 56923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 57923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller interface Condition<T> { 58923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller boolean check(T arg); 59923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 60923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 61923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testInstanceMethodReferenceLambda() throws Exception { 62923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Condition<String> c = String::isEmpty; 63923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Class<?> lambdaClass = c.getClass(); 64923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(c); 65923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(c, Condition.class); 66923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(c, Condition.class); 67923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(c); 68923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 69923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check the behavior of the lambda's method. 70923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(c.check("")); 71923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(c.check("notEmpty")); 72923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 73923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method implCallMethod = lambdaClass.getMethod( 74923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller "check", Object.class /* type erasure => not String.class */); 75923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue((Boolean) implCallMethod.invoke(c, "")); 76923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse((Boolean) implCallMethod.invoke(c, "notEmpty")); 77923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 78923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method interfaceCallMethod = Condition.class.getDeclaredMethod( 79923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller "check", Object.class /* type erasure => not String.class */); 80923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue((Boolean) interfaceCallMethod.invoke(c, "")); 81923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse((Boolean) interfaceCallMethod.invoke(c, "notEmpty")); 82923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 83923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 84923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testStaticMethodReferenceLambda() throws Exception { 85923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = LambdaImplementationTest::staticMethod; 86923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 87923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class); 88923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 89923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(r1); 90923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 91ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertCallableBehavior(r1, STATIC_METHOD_RESPONSE); 92923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 93ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller List<Callable<String>> callables = new ArrayList<>(); 94ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller for (int i = 0; i < 2; i++) { 95ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller callables.add(LambdaImplementationTest::staticMethod); 96ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller } 97ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleDefinitionCharacteristics(r1, callables.get(0)); 98ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1)); 99923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 100923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 101923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testObjectMethodReferenceLambda() throws Exception { 102ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller String msg = "Hello"; 103ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller StringBuilder o = new StringBuilder(msg); 104923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = o::toString; 105923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 106923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class); 107923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 108923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(r1); 109923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 110ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertCallableBehavior(r1, msg); 111923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 112ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller List<Callable<String>> callables = new ArrayList<>(); 113ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller for (int i = 0; i < 2; i++) { 114ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller callables.add(o::toString); 115ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller } 116ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleDefinitionCharacteristics(r1, callables.get(0)); 117ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1)); 118923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 119923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 120923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testArgumentCapturingLambda() throws Exception { 121ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller checkArgumentCapturingLambda("Argument"); 122ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller } 123ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller 124ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller private void checkArgumentCapturingLambda(String msg) throws Exception { 125923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = () -> msg; 126923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 127923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class); 128923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 129923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(r1); 130923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 131ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertCallableBehavior(r1, msg); 132923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 133ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller List<Callable<String>> callables = new ArrayList<>(); 134ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller for (int i = 0; i < 2; i++) { 135ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller callables.add(() -> msg); 136ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller } 137ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleDefinitionCharacteristics(r1, callables.get(0)); 138ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1)); 139923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 140923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 141923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testSerializableLambda_withoutState() throws Exception { 142ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller Callable<String> r1 = (Callable<String> & Serializable) () -> "No State"; 143923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 144923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class, Serializable.class); 145923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 146923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSerializableLambdaCharacteristics(r1); 147923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 148ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertCallableBehavior(r1, "No State"); 149923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 150ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller List<Callable<String>> callables = new ArrayList<>(); 151ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller for (int i = 0; i < 2; i++) { 152ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller Callable<String> callable = (Callable<String> & Serializable) () -> "No State"; 153ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertLambdaImplementsInterfaces(callable, Callable.class, Serializable.class); 154ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller callables.add(callable); 155ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller } 156ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleDefinitionCharacteristics(r1, callables.get(0)); 157ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1)); 158923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 159923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 160923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testSerializableLambda_withState() throws Exception { 161ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller final long state = System.currentTimeMillis(); 162ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller Callable<String> r1 = (Callable<String> & Serializable) () -> "State:" + state; 163923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 164923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class, Serializable.class); 165923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 166923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSerializableLambdaCharacteristics(r1); 167923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 168ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertCallableBehavior(r1, "State:" + state); 169923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 170923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> deserializedR1 = roundtripSerialization(r1); 171923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(r1.call(), deserializedR1.call()); 172ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller 173ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller List<Callable<String>> callables = new ArrayList<>(); 174ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller for (int i = 0; i < 2; i++) { 175ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller Callable<String> callable = (Callable<String> & Serializable) () -> "State:" + state; 176ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertLambdaImplementsInterfaces(callable, Callable.class, Serializable.class); 177ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller callables.add(callable); 178ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller } 179ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleDefinitionCharacteristics(r1, callables.get(0)); 180ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1)); 181923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 182923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 183923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testBadSerializableLambda() throws Exception { 184923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller final Object state = new Object(); // Not Serializable 185923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = (Callable<String> & Serializable) () -> "Hello world: " + state; 186923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 187923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 188923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class, Serializable.class); 189923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 190923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller try { 191923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller serializeObject(r1); 192923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller fail(); 193923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } catch (NotSerializableException expected) { 194923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 195923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 196923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 197923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testMultipleInterfaceLambda() throws Exception { 198ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller Callable<String> r1 = (Callable<String> & MarkerInterface) () -> "MultipleInterfaces"; 199923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(r1 instanceof MarkerInterface); 200923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 201923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 202923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class, MarkerInterface.class); 203923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(r1); 204923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 205ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertCallableBehavior(r1, "MultipleInterfaces"); 206ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller 207ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller List<Callable<String>> callables = new ArrayList<>(); 208ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller for (int i = 0; i < 2; i++) { 209ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller Callable<String> callable = 210ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller (Callable<String> & MarkerInterface) () -> "MultipleInterfaces"; 211ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertLambdaImplementsInterfaces(callable, Callable.class, MarkerInterface.class); 212ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller callables.add(callable); 213ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller } 214ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertLambdaImplementsInterfaces(r1, Callable.class, MarkerInterface.class); 215ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleDefinitionCharacteristics(r1, callables.get(0)); 216ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1)); 217923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 218923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 219923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static void assertSerializableLambdaCharacteristics(Object r1) throws Exception { 220923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(r1 instanceof Serializable); 221923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 222923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Object deserializedR1 = roundtripSerialization(r1); 223923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(deserializedR1.equals(r1)); 224923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotSame(deserializedR1, r1); 225923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 226923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 227923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller @SuppressWarnings("unchecked") 228923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static <T> T roundtripSerialization(T r1) throws Exception { 229923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller byte[] bytes = serializeObject(r1); 230923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 231923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller try (ObjectInputStream is = new ObjectInputStream(bais)) { 232923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller return (T) is.readObject(); 233923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 234923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 235923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 236923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static <T> byte[] serializeObject(T r1) throws IOException { 237923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller ByteArrayOutputStream baos = new ByteArrayOutputStream(); 238923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller try (ObjectOutputStream os = new ObjectOutputStream(baos)) { 239923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller os.writeObject(r1); 240923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller os.flush(); 241923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 242923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller return baos.toByteArray(); 243923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 244923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 245923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static <T> void assertLambdaImplementsInterfaces(T r1, Class<?>... expectedInterfaces) 246923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller throws Exception { 247923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Class<?> lambdaClass = r1.getClass(); 248923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 249923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check directly implemented interfaces. Ordering is well-defined. 250923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Class<?>[] actualInterfaces = lambdaClass.getInterfaces(); 251923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedInterfaces.length, actualInterfaces.length); 252923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller List<Class<?>> actual = Arrays.asList(actualInterfaces); 253923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller List<Class<?>> expected = Arrays.asList(expectedInterfaces); 254923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expected, actual); 255923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 256923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Confirm that the only method declared on the lambda's class are those defined by 257923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // interfaces it implements. i.e. there's no additional public contract. 258923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Set<Method> declaredMethods = new HashSet<>(); 259923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller addNonStaticPublicMethods(lambdaClass, declaredMethods); 260923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Set<Method> expectedMethods = new HashSet<>(); 261923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller for (Class<?> interfaceClass : expectedInterfaces) { 262923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Obtain methods declared by super-interfaces too. 263923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller while (interfaceClass != null) { 264923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller addNonStaticPublicMethods(interfaceClass, expectedMethods); 265923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller interfaceClass = interfaceClass.getSuperclass(); 266923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 267923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 268923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedMethods.size(), declaredMethods.size()); 269923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 270923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check the method signatures are compatible. 271923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller for (Method expectedMethod : expectedMethods) { 272923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method actualMethod = 273923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller lambdaClass.getMethod(expectedMethod.getName(), 274923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller expectedMethod.getParameterTypes()); 275923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedMethod.getReturnType(), actualMethod.getReturnType()); 276923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 277923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 278923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 279923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static void addNonStaticPublicMethods(Class<?> clazz, Set<Method> methodSet) { 280923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller for (Method interfaceMethod : clazz.getDeclaredMethods()) { 281923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller int modifiers = interfaceMethod.getModifiers(); 282923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller if ((!Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { 283923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller methodSet.add(interfaceMethod); 284923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 285923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 286923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 287923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 288923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static void assertNonSerializableLambdaCharacteristics(Object r1) throws Exception { 289923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller ByteArrayOutputStream baos = new ByteArrayOutputStream(); 290923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller try (ObjectOutputStream os = new ObjectOutputStream(baos)) { 291923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller os.writeObject(r1); 292923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller os.flush(); 293923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller fail(); 294923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } catch (NotSerializableException expected) { 295923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 296923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 297923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 298ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller /** 299ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller * Asserts that necessary conditions hold when there are two lambdas with separate but identical 300ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller * definitions. 301ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller */ 302ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller private static void assertMultipleDefinitionCharacteristics( 303ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller Callable<String> r1, Callable<String> r2) throws Exception { 304ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller 305ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller // Sanity check that the lambdas do the same thing. 306ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertEquals(r1.call(), r2.call()); 307923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 308afaca2675a3cd159ef0d210476926c0085895136Neil Fuller // Two lambdas from different definitions can share the same class or may not so there are 309afaca2675a3cd159ef0d210476926c0085895136Neil Fuller // no assertions about the classes for the instances. See JLS 15.27.4. 310afaca2675a3cd159ef0d210476926c0085895136Neil Fuller 311afaca2675a3cd159ef0d210476926c0085895136Neil Fuller // We cannot assert anything about the reference equality or equals() behavior of the 312afaca2675a3cd159ef0d210476926c0085895136Neil Fuller // instances themselves either. 313afaca2675a3cd159ef0d210476926c0085895136Neil Fuller // Implementations are free to return the same object or different if the lambdas are 314afaca2675a3cd159ef0d210476926c0085895136Neil Fuller // equivalent. It may affect collections behavior so no code should assume anything about 315afaca2675a3cd159ef0d210476926c0085895136Neil Fuller // the identity of the lambda instance. 316afaca2675a3cd159ef0d210476926c0085895136Neil Fuller // See the JSR-000335, Part E: Typing and Evaluation. Sharing of stateless instances is not 317afaca2675a3cd159ef0d210476926c0085895136Neil Fuller // explicitly called out in the JLS. 318ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller } 319ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller 320ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller /** 321ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller * Asserts that necessary conditions hold when there are two lambdas created from the same 322ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller * definition. 323ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller */ 324ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller private static void assertMultipleInstanceCharacteristics( 325ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller Callable<String> r1, Callable<String> r2) throws Exception { 326ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller 327ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller // Sanity check that the lambdas do the same thing. 328ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller assertEquals(r1.call(), r2.call()); 329ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller 330ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller // There doesn't appear to be anything else that is safe to assert here. Two lambdas 331ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller // created from the same definition can be the same, as can their class, but they can also 332ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller // be different. See JLS 15.27.4. 333923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 334923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 335923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static void assertGeneralLambdaClassCharacteristics(Object r1) throws Exception { 336923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Class<?> lambdaClass = r1.getClass(); 337923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 338923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Lambda objects have classes that have names. 339923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotNull(lambdaClass.getName()); 340923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotNull(lambdaClass.getSimpleName()); 341923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotNull(lambdaClass.getCanonicalName()); 342923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 343923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Lambda classes are "synthetic classes" that are not arrays. 344923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(lambdaClass.isAnnotation()); 345923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(lambdaClass.isInterface()); 346923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(lambdaClass.isArray()); 347923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(lambdaClass.isEnum()); 348923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(lambdaClass.isPrimitive()); 349923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(lambdaClass.isSynthetic()); 350923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNull(lambdaClass.getComponentType()); 351923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 352923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Expected modifiers 353923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller int classModifiers = lambdaClass.getModifiers(); 354923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(Modifier.isFinal(classModifiers)); 355923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 356ebca9ee057f3eeef1d50289693a11b59baf0f890Neil Fuller // We have seen optimizations that make lambdas public so we do not make any assertions 357ebca9ee057f3eeef1d50289693a11b59baf0f890Neil Fuller // about class visibility: they can be package-private or public. http://b/73255857 358ebca9ee057f3eeef1d50289693a11b59baf0f890Neil Fuller 359923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Unexpected modifiers 360923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isPrivate(classModifiers)); 361923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isProtected(classModifiers)); 362923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isStatic(classModifiers)); 363923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isSynchronized(classModifiers)); 364923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isVolatile(classModifiers)); 365923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isTransient(classModifiers)); 366923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isNative(classModifiers)); 367923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isInterface(classModifiers)); 368923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isAbstract(classModifiers)); 369923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isStrict(classModifiers)); 370923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 371923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check the classloader, inheritance hierarchy and package. 372923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSame(LambdaImplementationTest.class.getClassLoader(), lambdaClass.getClassLoader()); 373923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSame(Object.class, lambdaClass.getSuperclass()); 374923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSame(Object.class, lambdaClass.getGenericSuperclass()); 375923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(LambdaImplementationTest.class.getPackage(), lambdaClass.getPackage()); 376923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 377923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check the implementation of the non-final public methods that all Objects possess. 378923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotNull(r1.toString()); 379923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(r1.equals(r1)); 380923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(System.identityHashCode(r1), r1.hashCode()); 381923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 382923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 383923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static <T> void assertLambdaMethodCharacteristics(T r1, Class<?> samInterfaceClass) 384923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller throws Exception { 385923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Find the single abstract method on the interface. 386923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method singleAbstractMethod = null; 387923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller for (Method method : samInterfaceClass.getDeclaredMethods()) { 388923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller if (Modifier.isAbstract(method.getModifiers())) { 389923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller singleAbstractMethod = method; 390923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller break; 391923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 392923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 393923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotNull(singleAbstractMethod); 394923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 395923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Confirm the lambda implements the method as expected. 396923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method implementationMethod = r1.getClass().getMethod( 397923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller singleAbstractMethod.getName(), singleAbstractMethod.getParameterTypes()); 398923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSame(singleAbstractMethod.getReturnType(), implementationMethod.getReturnType()); 399923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSame(r1.getClass(), implementationMethod.getDeclaringClass()); 400923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(implementationMethod.isSynthetic()); 401923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(implementationMethod.isBridge()); 402923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(implementationMethod.isDefault()); 403923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 404923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 405923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static String staticMethod() { 406ab09ee69a6fdf14d828a6089ccb0261a6463ad0bNeil Fuller return STATIC_METHOD_RESPONSE; 407923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 408923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 409923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private interface MarkerInterface { 410923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 411923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 412923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static <T> void assertCallableBehavior(Callable<T> r1, T expectedResult) 413923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller throws Exception { 414923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedResult, r1.call()); 415923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 416923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method implCallMethod = r1.getClass().getDeclaredMethod("call"); 417923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedResult, implCallMethod.invoke(r1)); 418923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 419923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method interfaceCallMethod = Callable.class.getDeclaredMethod("call"); 420923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedResult, interfaceCallMethod.invoke(r1)); 421923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 422923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller} 423