1f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson/*
2f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson * Copyright (C) 2010 The Android Open Source Project
3f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson *
4f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson * you may not use this file except in compliance with the License.
6f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson * You may obtain a copy of the License at
7f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson *
8f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson *
10f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson * See the License for the specific language governing permissions and
14f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson * limitations under the License.
15f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson */
16f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
174557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonpackage libcore.java.lang.reflect;
18f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
194557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport java.lang.reflect.Method;
20f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilsonimport java.util.Arrays;
214aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilsonimport java.util.Collection;
22f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilsonimport java.util.Collections;
23f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilsonimport java.util.HashSet;
24f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilsonimport java.util.Set;
25f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilsonimport junit.framework.TestCase;
26f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
27f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilsonpublic class MethodOverridesTest extends TestCase {
28f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
29f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testName() throws NoSuchMethodException {
30f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Method method = StringBuilder.class.getMethod("append", char.class);
31f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        assertEquals("append", method.getName());
32f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
33f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
34f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testParameterTypes() throws NoSuchMethodException {
35f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Method method = StringBuilder.class.getMethod("append", char.class);
36f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        assertEquals(Arrays.<Class<?>>asList(char.class),
37f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson                Arrays.asList(method.getParameterTypes()));
38f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
39f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
40f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testDeclaringClass() throws NoSuchMethodException {
41f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Method method = StringBuilder.class.getMethod("append", char.class);
42f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        assertEquals(StringBuilder.class, method.getDeclaringClass());
43f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
44f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
45f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testReturnType() throws NoSuchMethodException {
46f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Method method = StringBuilder.class.getMethod("append", char.class);
47f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        assertEquals(StringBuilder.class, method.getReturnType());
48f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
49f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
50f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testThrownExceptions() throws NoSuchMethodException {
51f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Method method = StringBuilder.class.getMethod("append", char.class);
52f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        assertEquals(Collections.<Class<?>>emptyList(), Arrays.asList(method.getExceptionTypes()));
53f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
54f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
55f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testGetMethodsIncludesInheritedMethods() {
56f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Set<String> signatures = signatures(Sub.class.getMethods());
574aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertContains(signatures, "void notOverridden[] throws []");
58f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
59f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
60f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testGetDeclaredMethodsDoesNotIncludeInheritedMethods() {
61f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Set<String> signatures = signatures(Sub.class.getDeclaredMethods());
62f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        assertFalse(signatures.contains("void notOverridden[] throws []"));
63f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
64f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
65f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testGetDeclaringClassReturnsOverridingClass() throws NoSuchMethodException {
66f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        assertEquals(Sub.class, Sub.class.getMethod("unchanged").getDeclaringClass());
67f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        assertEquals(Sub.class, Sub.class.getDeclaredMethod("unchanged").getDeclaringClass());
68f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
69f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
70f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testGetMethodsDoesNotIncludeExceptionChanges() throws NoSuchMethodException {
71f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Set<String> signatures = signatures(Sub.class.getMethods());
724aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertContains(signatures, "void thrower[] throws []");
73f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        assertFalse(signatures.contains("void thrower[] throws [java.lang.Exception]"));
744aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertEquals(Sub.class, Sub.class.getMethod("thrower").getDeclaringClass());
75f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
76f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
77f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testGetMethodsIncludesSyntheticMethods() throws NoSuchMethodException {
78f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Set<String> signatures = signatures(Sub.class.getMethods());
794aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertContains(signatures, "java.lang.String returner[] throws []");
804aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertContains(signatures, "java.lang.Object returner[] throws []");
814aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson
824aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        Method method = Sub.class.getMethod("returner");
834aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertEquals(Sub.class, method.getDeclaringClass());
844aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertFalse(method.isSynthetic());
85f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
86f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
87f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testGetDeclaredMethodsIncludesSyntheticMethods() throws NoSuchMethodException {
88f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Set<String> signatures = signatures(Sub.class.getDeclaredMethods());
894aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertContains(signatures, "java.lang.String returner[] throws []");
904aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertContains(signatures, "java.lang.Object returner[] throws []");
914aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson
924aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        Method method = Sub.class.getMethod("returner");
934aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertEquals(Sub.class, method.getDeclaringClass());
944aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertFalse(method.isSynthetic());
95f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
96f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
97f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public void testSubclassChangesVisibility() throws NoSuchMethodException {
98f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Method[] methods = Sub.class.getMethods();
99f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        int count = 0;
100f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        for (Method method : methods) {
101f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson            if (signature(method).equals("void visibility[] throws []")) {
1024aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson                assertEquals(Sub.class, method.getDeclaringClass());
1034aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson                assertFalse(method.isSynthetic());
1044aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson                count++;
1054aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson            }
1064aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        }
1074aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertEquals(1, count);
1084aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson
1094aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        Method method = Sub.class.getMethod("visibility");
1104aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertEquals(Sub.class, method.getDeclaringClass());
1114aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertFalse(method.isSynthetic());
1124aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson    }
1134aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson
1144aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson    public void testMoreVisibleSubclassChangesVisibility() throws NoSuchMethodException {
1154aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        Method[] methods = PublicSub.class.getMethods();
1164aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        int count = 0;
1174aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        for (Method method : methods) {
1184aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson            if (signature(method).equals("void unchanged[] throws []")) {
1194aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson                assertEquals(PublicSub.class, method.getDeclaringClass());
1204aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson                assertTrue(method.isSynthetic());
121f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson                count++;
122f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson            }
123f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        }
124f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        assertEquals(1, count);
1254aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson
1264aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        Method method = PublicSub.class.getMethod("unchanged");
1274aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertEquals(PublicSub.class, method.getDeclaringClass());
1284aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertTrue(method.isSynthetic());
129f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
130f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
131f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public static class Super {
132f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        public void notOverridden() {}
133f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        public void unchanged() {}
134f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        public void thrower() throws Exception {}
135f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        public Object returner() {
136f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson            return null;
137f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        }
138f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        protected void visibility() {}
139f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
140f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
141f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    public static class Sub extends Super {
142f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        @Override public void unchanged() {}
143f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        @Override public void thrower() {}
144f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        @Override public String returner() {
145f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson            return null;
146f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        }
147f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        @Override public void visibility() {}
148f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
149f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
1504aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson    static class PackageSuper {
1514aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        public void unchanged() {}
1524aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson    }
1534aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson
1544aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson    public static class PublicSub extends PackageSuper {}
1554aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson
156f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    /**
157f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson     * Returns a method signature of this form:
158f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson     * {@code java.lang.String concat[class java.lang.String] throws []}.
159f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson     */
160f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    private String signature(Method method) {
161f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        return method.getReturnType().getName() + " " + method.getName()
162f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson                + Arrays.toString(method.getParameterTypes())
163f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson                + " throws " + Arrays.toString(method.getExceptionTypes());
164f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
165f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson
166f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    private Set<String> signatures(Method[] methods) {
167f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        Set<String> signatures = new HashSet<String>();
168f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        for (Method method : methods) {
169f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson            signatures.add(signature(method));
170f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        }
171f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson        return signatures;
172f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson    }
1734aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson
1744aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson    private <T> void assertContains(Collection<T> elements, T value) {
1754aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson        assertTrue("Expected " + value + " in " + elements, elements.contains(value));
1764aa863a08a4fed2f8b8967f63e0df61d72f28b79Jesse Wilson    }
177f0c42694d45de3d263ca8c123ec37e02818fefb0Jesse Wilson}
178