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