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