1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.java.lang.reflect;
18
19import java.lang.reflect.Method;
20
21import junit.framework.TestCase;
22
23public final class MethodTest extends TestCase {
24    public void test_getExceptionTypes() throws Exception {
25        Method method = MethodTestHelper.class.getMethod("m1", new Class[0]);
26        Class[] exceptions = method.getExceptionTypes();
27        assertEquals(1, exceptions.length);
28        assertEquals(IndexOutOfBoundsException.class, exceptions[0]);
29        // Check that corrupting our array doesn't affect other callers.
30        exceptions[0] = NullPointerException.class;
31        exceptions = method.getExceptionTypes();
32        assertEquals(1, exceptions.length);
33        assertEquals(IndexOutOfBoundsException.class, exceptions[0]);
34    }
35
36    public void test_getParameterTypes() throws Exception {
37        Class[] expectedParameters = new Class[] { Object.class };
38        Method method = MethodTestHelper.class.getMethod("m2", expectedParameters);
39        Class[] parameters = method.getParameterTypes();
40        assertEquals(1, parameters.length);
41        assertEquals(expectedParameters[0], parameters[0]);
42        // Check that corrupting our array doesn't affect other callers.
43        parameters[0] = String.class;
44        parameters = method.getParameterTypes();
45        assertEquals(1, parameters.length);
46        assertEquals(expectedParameters[0], parameters[0]);
47    }
48
49    public void testGetMethodWithPrivateMethodAndInterfaceMethod() throws Exception {
50        assertEquals(InterfaceA.class, Sub.class.getMethod("a").getDeclaringClass());
51    }
52
53    public void testGetMethodReturnsIndirectlyImplementedInterface() throws Exception {
54        assertEquals(InterfaceA.class, ImplementsC.class.getMethod("a").getDeclaringClass());
55        assertEquals(InterfaceA.class, ExtendsImplementsC.class.getMethod("a").getDeclaringClass());
56    }
57
58    public void testGetDeclaredMethodReturnsIndirectlyImplementedInterface() throws Exception {
59        try {
60            ImplementsC.class.getDeclaredMethod("a").getDeclaringClass();
61            fail();
62        } catch (NoSuchMethodException expected) {
63        }
64        try {
65            ExtendsImplementsC.class.getDeclaredMethod("a").getDeclaringClass();
66            fail();
67        } catch (NoSuchMethodException expected) {
68        }
69    }
70
71    public void testGetMethodWithConstructorName() throws Exception {
72        try {
73            MethodTestHelper.class.getMethod("<init>");
74            fail();
75        } catch (NoSuchMethodException expected) {
76        }
77    }
78
79    public void testGetMethodWithNullName() throws Exception {
80        try {
81            MethodTestHelper.class.getMethod(null);
82            fail();
83        } catch (NullPointerException expected) {
84        }
85    }
86
87    public void testGetMethodWithNullArgumentsArray() throws Exception {
88        Method m1 = MethodTestHelper.class.getMethod("m1", (Class[]) null);
89        assertEquals(0, m1.getParameterTypes().length);
90    }
91
92    public void testGetMethodWithNullArgument() throws Exception {
93        try {
94            MethodTestHelper.class.getMethod("m2", new Class[] { null });
95            fail();
96        } catch (NoSuchMethodException expected) {
97        }
98    }
99
100    public void testGetMethodReturnsInheritedStaticMethod() throws Exception {
101        Method b = Sub.class.getMethod("b");
102        assertEquals(void.class, b.getReturnType());
103    }
104
105    public void testGetDeclaredMethodReturnsPrivateMethods() throws Exception {
106        Method method = Super.class.getDeclaredMethod("a");
107        assertEquals(void.class, method.getReturnType());
108    }
109
110    public void testGetDeclaredMethodDoesNotReturnSuperclassMethods() throws Exception {
111        try {
112            Sub.class.getDeclaredMethod("a");
113            fail();
114        } catch (NoSuchMethodException expected) {
115        }
116    }
117
118    public void testGetDeclaredMethodDoesNotReturnImplementedInterfaceMethods() throws Exception {
119        try {
120            InterfaceB.class.getDeclaredMethod("a");
121            fail();
122        } catch (NoSuchMethodException expected) {
123        }
124    }
125
126    public void testImplementedInterfaceMethodOfAnonymousClass() throws Exception {
127        Object anonymous = new InterfaceA() {
128            @Override public void a() {
129            }
130        };
131        Method method = anonymous.getClass().getMethod("a");
132        assertEquals(anonymous.getClass(), method.getDeclaringClass());
133    }
134
135    public void testPublicMethodOfAnonymousClass() throws Exception {
136        Object anonymous = new Object() {
137            public void a() {
138            }
139        };
140        Method method = anonymous.getClass().getMethod("a");
141        assertEquals(anonymous.getClass(), method.getDeclaringClass());
142    }
143
144    public void testGetMethodDoesNotReturnPrivateMethodOfAnonymousClass() throws Exception {
145        Object anonymous = new Object() {
146            private void a() {
147            }
148        };
149        try {
150            anonymous.getClass().getMethod("a");
151            fail();
152        } catch (NoSuchMethodException expected) {
153        }
154    }
155
156    public void testGetDeclaredMethodReturnsPrivateMethodOfAnonymousClass() throws Exception {
157        Object anonymous = new Object() {
158            private void a() {
159            }
160        };
161        Method method = anonymous.getClass().getDeclaredMethod("a");
162        assertEquals(anonymous.getClass(), method.getDeclaringClass());
163    }
164
165    public void testEqualMethodEqualsAndHashCode() throws Exception {
166        Method m1 = MethodTestHelper.class.getMethod("m1");
167        Method m2 = MethodTestHelper.class.getMethod("m1");
168        assertEquals(m1, m2);
169        assertEquals(m1.hashCode(), m2.hashCode());
170        assertEquals(MethodTestHelper.class.getName().hashCode() ^ "m1".hashCode(), m1.hashCode());
171    }
172
173    public void testHashCodeSpec() throws Exception {
174        Method m1 = MethodTestHelper.class.getMethod("m1");
175        assertEquals(MethodTestHelper.class.getName().hashCode() ^ "m1".hashCode(), m1.hashCode());
176    }
177
178    public void testDifferentMethodEqualsAndHashCode() throws Exception {
179        Method m1 = MethodTestHelper.class.getMethod("m1");
180        Method m2 = MethodTestHelper.class.getMethod("m2", Object.class);
181        assertFalse(m1.equals(m2));
182        assertFalse(m1.hashCode() == m2.hashCode());
183    }
184
185    // http://b/1045939
186    public void testMethodToString() throws Exception {
187        assertEquals("public final native void java.lang.Object.notify()",
188                Object.class.getMethod("notify", new Class[] { }).toString());
189        assertEquals("public java.lang.String java.lang.Object.toString()",
190                Object.class.getMethod("toString", new Class[] { }).toString());
191        assertEquals("public final native void java.lang.Object.wait(long,int)"
192                + " throws java.lang.InterruptedException",
193                Object.class.getMethod("wait", new Class[] { long.class, int.class }).toString());
194        assertEquals("public boolean java.lang.Object.equals(java.lang.Object)",
195                Object.class.getMethod("equals", new Class[] { Object.class }).toString());
196        assertEquals("public static java.lang.String java.lang.String.valueOf(char[])",
197                String.class.getMethod("valueOf", new Class[] { char[].class }).toString());
198        assertEquals( "public java.lang.Process java.lang.Runtime.exec(java.lang.String[])"
199                + " throws java.io.IOException",
200                Runtime.class.getMethod("exec", new Class[] { String[].class }).toString());
201        // http://b/18488857
202        assertEquals(
203                "public int java.lang.String.compareTo(java.lang.Object)",
204                String.class.getMethod("compareTo", Object.class).toString());
205    }
206
207    // Tests that the "varargs" modifier is handled correctly.
208    // The underlying constant value for it is the same as for the "transient" field modifier.
209    // http://b/18488857
210    public void testVarargsModifier() throws NoSuchMethodException {
211        Method stringFormatMethod = String.class.getMethod(
212                "format", new Class[] { String.class, Object[].class });
213        assertTrue(stringFormatMethod.isVarArgs());
214        assertEquals(
215                "public static java.lang.String java.lang.String.format("
216                        + "java.lang.String,java.lang.Object[])",
217                stringFormatMethod.toString());
218    }
219
220    public static class MethodTestHelper {
221        public void m1() throws IndexOutOfBoundsException { }
222        public void m2(Object o) { }
223    }
224
225    public static class Super {
226        private void a() {}
227        public static void b() {}
228    }
229    public static interface InterfaceA {
230        void a();
231    }
232    public static abstract class Sub extends Super implements InterfaceA {
233    }
234
235    public static interface InterfaceB extends InterfaceA {}
236    public static interface InterfaceC extends InterfaceB {}
237    public static abstract class ImplementsC implements InterfaceC {}
238    public static abstract class ExtendsImplementsC extends ImplementsC {}
239}
240