LambdaImplementationTest.java revision 923866595bd9ed27eff087d61843299f387ff5d9
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; 30923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.util.Arrays; 31923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.util.HashSet; 32923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.util.List; 33923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.util.Set; 34923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerimport java.util.concurrent.Callable; 35923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 36923866595bd9ed27eff087d61843299f387ff5d9Neil Fullerpublic class LambdaImplementationTest extends TestCase { 37923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 38923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static final String MSG = "Hello World"; 39923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 40923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testNonCapturingLambda() throws Exception { 41923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = () -> MSG; 42923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 43923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class); 44923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 45923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(r1); 46923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertCallableBehavior(r1, MSG); 47923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 48923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r2 = () -> MSG; 49923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertMultipleInstanceCharacteristics(r1, r2); 50923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 51923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 52923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller interface Condition<T> { 53923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller boolean check(T arg); 54923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 55923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 56923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testInstanceMethodReferenceLambda() throws Exception { 57923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Condition<String> c = String::isEmpty; 58923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Class<?> lambdaClass = c.getClass(); 59923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(c); 60923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(c, Condition.class); 61923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(c, Condition.class); 62923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(c); 63923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 64923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check the behavior of the lambda's method. 65923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(c.check("")); 66923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(c.check("notEmpty")); 67923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 68923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method implCallMethod = lambdaClass.getMethod( 69923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller "check", Object.class /* type erasure => not String.class */); 70923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue((Boolean) implCallMethod.invoke(c, "")); 71923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse((Boolean) implCallMethod.invoke(c, "notEmpty")); 72923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 73923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method interfaceCallMethod = Condition.class.getDeclaredMethod( 74923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller "check", Object.class /* type erasure => not String.class */); 75923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue((Boolean) interfaceCallMethod.invoke(c, "")); 76923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse((Boolean) interfaceCallMethod.invoke(c, "notEmpty")); 77923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 78923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 79923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testStaticMethodReferenceLambda() throws Exception { 80923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = LambdaImplementationTest::staticMethod; 81923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 82923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class); 83923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 84923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(r1); 85923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 86923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertCallableBehavior(r1, MSG); 87923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 88923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r2 = LambdaImplementationTest::staticMethod; 89923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertMultipleInstanceCharacteristics(r1, r2); 90923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 91923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 92923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testObjectMethodReferenceLambda() throws Exception { 93923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller StringBuilder o = new StringBuilder(MSG); 94923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = o::toString; 95923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 96923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class); 97923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 98923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(r1); 99923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 100923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertCallableBehavior(r1, MSG); 101923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 102923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r2 = o::toString; 103923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertMultipleInstanceCharacteristics(r1, r2); 104923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 105923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 106923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testArgumentCapturingLambda() throws Exception { 107923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller String msg = MSG; 108923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = () -> msg; 109923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 110923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class); 111923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 112923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(r1); 113923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 114923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertCallableBehavior(r1, MSG); 115923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 116923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r2 = () -> msg; 117923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertMultipleInstanceCharacteristics(r1, r2); 118923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 119923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 120923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testSerializableLambda_withoutState() throws Exception { 121923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = (Callable<String> & Serializable) () -> MSG; 122923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 123923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class, Serializable.class); 124923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 125923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSerializableLambdaCharacteristics(r1); 126923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 127923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertCallableBehavior(r1, MSG); 128923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 129923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r2 = (Callable<String> & Serializable) () -> MSG; 130923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertMultipleInstanceCharacteristics(r1, r2); 131923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 132923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 133923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testSerializableLambda_withState() throws Exception { 134923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller final int state = 123; 135923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = (Callable<String> & Serializable) () -> MSG + state; 136923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 137923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class, Serializable.class); 138923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 139923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSerializableLambdaCharacteristics(r1); 140923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 141923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertCallableBehavior(r1, MSG + state); 142923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 143923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> deserializedR1 = roundtripSerialization(r1); 144923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(r1.call(), deserializedR1.call()); 145923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 146923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 147923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testBadSerializableLambda() throws Exception { 148923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller final Object state = new Object(); // Not Serializable 149923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = (Callable<String> & Serializable) () -> "Hello world: " + state; 150923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 151923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 152923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class, Serializable.class); 153923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 154923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller try { 155923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller serializeObject(r1); 156923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller fail(); 157923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } catch (NotSerializableException expected) { 158923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 159923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 160923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 161923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller public void testMultipleInterfaceLambda() throws Exception { 162923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Callable<String> r1 = (Callable<String> & MarkerInterface) () -> MSG; 163923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(r1 instanceof MarkerInterface); 164923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertGeneralLambdaClassCharacteristics(r1); 165923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaMethodCharacteristics(r1, Callable.class); 166923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertLambdaImplementsInterfaces(r1, Callable.class, MarkerInterface.class); 167923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNonSerializableLambdaCharacteristics(r1); 168923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 169923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertCallableBehavior(r1, MSG); 170923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 171923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 172923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static void assertSerializableLambdaCharacteristics(Object r1) throws Exception { 173923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(r1 instanceof Serializable); 174923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 175923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Object deserializedR1 = roundtripSerialization(r1); 176923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(deserializedR1.equals(r1)); 177923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotSame(deserializedR1, r1); 178923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 179923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 180923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller @SuppressWarnings("unchecked") 181923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static <T> T roundtripSerialization(T r1) throws Exception { 182923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller byte[] bytes = serializeObject(r1); 183923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 184923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller try (ObjectInputStream is = new ObjectInputStream(bais)) { 185923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller return (T) is.readObject(); 186923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 187923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 188923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 189923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static <T> byte[] serializeObject(T r1) throws IOException { 190923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller ByteArrayOutputStream baos = new ByteArrayOutputStream(); 191923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller try (ObjectOutputStream os = new ObjectOutputStream(baos)) { 192923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller os.writeObject(r1); 193923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller os.flush(); 194923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 195923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller return baos.toByteArray(); 196923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 197923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 198923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static <T> void assertLambdaImplementsInterfaces(T r1, Class<?>... expectedInterfaces) 199923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller throws Exception { 200923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Class<?> lambdaClass = r1.getClass(); 201923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 202923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check directly implemented interfaces. Ordering is well-defined. 203923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Class<?>[] actualInterfaces = lambdaClass.getInterfaces(); 204923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedInterfaces.length, actualInterfaces.length); 205923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller List<Class<?>> actual = Arrays.asList(actualInterfaces); 206923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller List<Class<?>> expected = Arrays.asList(expectedInterfaces); 207923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expected, actual); 208923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 209923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Confirm that the only method declared on the lambda's class are those defined by 210923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // interfaces it implements. i.e. there's no additional public contract. 211923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Set<Method> declaredMethods = new HashSet<>(); 212923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller addNonStaticPublicMethods(lambdaClass, declaredMethods); 213923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Set<Method> expectedMethods = new HashSet<>(); 214923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller for (Class<?> interfaceClass : expectedInterfaces) { 215923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Obtain methods declared by super-interfaces too. 216923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller while (interfaceClass != null) { 217923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller addNonStaticPublicMethods(interfaceClass, expectedMethods); 218923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller interfaceClass = interfaceClass.getSuperclass(); 219923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 220923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 221923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedMethods.size(), declaredMethods.size()); 222923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 223923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check the method signatures are compatible. 224923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller for (Method expectedMethod : expectedMethods) { 225923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method actualMethod = 226923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller lambdaClass.getMethod(expectedMethod.getName(), 227923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller expectedMethod.getParameterTypes()); 228923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedMethod.getReturnType(), actualMethod.getReturnType()); 229923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 230923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 231923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 232923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static void addNonStaticPublicMethods(Class<?> clazz, Set<Method> methodSet) { 233923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller for (Method interfaceMethod : clazz.getDeclaredMethods()) { 234923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller int modifiers = interfaceMethod.getModifiers(); 235923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller if ((!Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { 236923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller methodSet.add(interfaceMethod); 237923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 238923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 239923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 240923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 241923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static void assertNonSerializableLambdaCharacteristics(Object r1) throws Exception { 242923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller ByteArrayOutputStream baos = new ByteArrayOutputStream(); 243923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller try (ObjectOutputStream os = new ObjectOutputStream(baos)) { 244923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller os.writeObject(r1); 245923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller os.flush(); 246923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller fail(); 247923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } catch (NotSerializableException expected) { 248923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 249923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 250923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 251923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static void assertMultipleInstanceCharacteristics(Object r1, Object r2) 252923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller throws Exception { 253923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 254923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Unclear if any of this is *guaranteed* to be true. 255923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 256923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check the objects are not the same and do not equal. This could influence collection 257923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // behavior. 258923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotSame(r1, r2); 259923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(!r1.equals(r2)); 260923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 261923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Confirm the classes differ. 262923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Class<?> lambda1Class = r1.getClass(); 263923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Class<?> lambda2Class = r2.getClass(); 264923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotSame(lambda1Class, lambda2Class); 265923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 266923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 267923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static void assertGeneralLambdaClassCharacteristics(Object r1) throws Exception { 268923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Class<?> lambdaClass = r1.getClass(); 269923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 270923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Lambda objects have classes that have names. 271923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotNull(lambdaClass.getName()); 272923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotNull(lambdaClass.getSimpleName()); 273923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotNull(lambdaClass.getCanonicalName()); 274923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 275923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Lambda classes are "synthetic classes" that are not arrays. 276923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(lambdaClass.isAnnotation()); 277923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(lambdaClass.isInterface()); 278923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(lambdaClass.isArray()); 279923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(lambdaClass.isEnum()); 280923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(lambdaClass.isPrimitive()); 281923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(lambdaClass.isSynthetic()); 282923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNull(lambdaClass.getComponentType()); 283923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 284923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Expected modifiers 285923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller int classModifiers = lambdaClass.getModifiers(); 286923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(Modifier.isFinal(classModifiers)); 287923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 288923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Unexpected modifiers 289923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isPrivate(classModifiers)); 290923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isPublic(classModifiers)); 291923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isProtected(classModifiers)); 292923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isStatic(classModifiers)); 293923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isSynchronized(classModifiers)); 294923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isVolatile(classModifiers)); 295923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isTransient(classModifiers)); 296923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isNative(classModifiers)); 297923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isInterface(classModifiers)); 298923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isAbstract(classModifiers)); 299923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(Modifier.isStrict(classModifiers)); 300923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 301923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check the classloader, inheritance hierarchy and package. 302923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSame(LambdaImplementationTest.class.getClassLoader(), lambdaClass.getClassLoader()); 303923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSame(Object.class, lambdaClass.getSuperclass()); 304923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSame(Object.class, lambdaClass.getGenericSuperclass()); 305923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(LambdaImplementationTest.class.getPackage(), lambdaClass.getPackage()); 306923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 307923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Check the implementation of the non-final public methods that all Objects possess. 308923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotNull(r1.toString()); 309923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertTrue(r1.equals(r1)); 310923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(System.identityHashCode(r1), r1.hashCode()); 311923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 312923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 313923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static <T> void assertLambdaMethodCharacteristics(T r1, Class<?> samInterfaceClass) 314923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller throws Exception { 315923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Find the single abstract method on the interface. 316923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method singleAbstractMethod = null; 317923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller for (Method method : samInterfaceClass.getDeclaredMethods()) { 318923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller if (Modifier.isAbstract(method.getModifiers())) { 319923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller singleAbstractMethod = method; 320923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller break; 321923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 322923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 323923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertNotNull(singleAbstractMethod); 324923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 325923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller // Confirm the lambda implements the method as expected. 326923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method implementationMethod = r1.getClass().getMethod( 327923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller singleAbstractMethod.getName(), singleAbstractMethod.getParameterTypes()); 328923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSame(singleAbstractMethod.getReturnType(), implementationMethod.getReturnType()); 329923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertSame(r1.getClass(), implementationMethod.getDeclaringClass()); 330923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(implementationMethod.isSynthetic()); 331923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(implementationMethod.isBridge()); 332923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertFalse(implementationMethod.isDefault()); 333923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 334923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 335923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static String staticMethod() { 336923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller return MSG; 337923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 338923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 339923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private interface MarkerInterface { 340923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 341923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 342923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller private static <T> void assertCallableBehavior(Callable<T> r1, T expectedResult) 343923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller throws Exception { 344923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedResult, r1.call()); 345923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 346923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method implCallMethod = r1.getClass().getDeclaredMethod("call"); 347923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedResult, implCallMethod.invoke(r1)); 348923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller 349923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller Method interfaceCallMethod = Callable.class.getDeclaredMethod("call"); 350923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller assertEquals(expectedResult, interfaceCallMethod.invoke(r1)); 351923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller } 352923866595bd9ed27eff087d61843299f387ff5d9Neil Fuller} 353