1/*
2 * Copyright (C) 2010 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.io.IOException;
20import java.lang.reflect.Constructor;
21import java.lang.reflect.Method;
22import java.lang.reflect.Type;
23import java.lang.reflect.TypeVariable;
24import java.util.Arrays;
25import java.util.List;
26import junit.framework.TestCase;
27
28public final class GenericExceptionsTest extends TestCase {
29
30    public void testGenericExceptionsOfMethodsWithTypeParameters() throws Exception {
31        Method method = Thrower.class.getMethod("parameterizedMethod");
32        assertEquals(Arrays.<Type>asList(IOException.class),
33                Arrays.asList(method.getGenericExceptionTypes()));
34    }
35
36    public void testGenericExceptionsOfMethodsWithGenericParameters() throws Exception {
37        Method method = Thrower.class.getMethod("genericParameters", List.class);
38        assertEquals(Arrays.<Type>asList(IOException.class),
39                Arrays.asList(method.getGenericExceptionTypes()));
40    }
41
42    public void testGenericExceptionsOfConstructorsWithTypeParameters() throws Exception {
43        Constructor constructor = Thrower.class.getConstructor();
44        assertEquals(Arrays.<Type>asList(IOException.class),
45                Arrays.asList(constructor.getGenericExceptionTypes()));
46    }
47
48    public void testGenericExceptionsOfConstructorsWithGenericParameters() throws Exception {
49        Constructor constructor = Thrower.class.getConstructor(List.class);
50        assertEquals(Arrays.<Type>asList(IOException.class),
51                Arrays.asList(constructor.getGenericExceptionTypes()));
52    }
53
54    public void testConstructorThrowingTypeVariable() throws Exception {
55        Constructor constructor = ThrowerT.class.getConstructor();
56        TypeVariable typeVariable = getOnlyValue(constructor.getGenericExceptionTypes(),
57                TypeVariable.class);
58        assertEquals("T", typeVariable.getName());
59        assertEquals(Arrays.<Type>asList(Throwable.class), Arrays.asList(typeVariable.getBounds()));
60    }
61
62    public void testMethodThrowingTypeVariable() throws Exception {
63        Method method = ThrowerT.class.getMethod("throwsTypeVariable");
64        TypeVariable typeVariable = getOnlyValue(method.getGenericExceptionTypes(),
65                TypeVariable.class);
66        assertEquals("T", typeVariable.getName());
67        assertEquals(Arrays.<Type>asList(Throwable.class), Arrays.asList(typeVariable.getBounds()));
68    }
69
70    public void testThrowingMethodTypeParameter() throws Exception {
71        Method method = ThrowerT.class.getMethod("throwsMethodTypeParameter");
72        TypeVariable typeVariable = getOnlyValue(method.getGenericExceptionTypes(),
73                TypeVariable.class);
74        assertEquals("X", typeVariable.getName());
75        assertEquals(Arrays.<Type>asList(Exception.class), Arrays.asList(typeVariable.getBounds()));
76    }
77
78    public void testThrowingMethodThrowsEverything() throws Exception {
79        Method method = ThrowerT.class.getMethod("throwsEverything");
80        Type[] exceptions = method.getGenericExceptionTypes();
81        TypeVariable t = (TypeVariable) exceptions[0];
82        assertEquals(3, exceptions.length);
83        assertEquals("T", t.getName());
84        assertEquals(Arrays.<Type>asList(Throwable.class), Arrays.asList(t.getBounds()));
85        assertEquals(Exception.class, exceptions[1]);
86        TypeVariable x = (TypeVariable) exceptions[2];
87        assertEquals("X", x.getName());
88        assertEquals(Arrays.<Type>asList(Exception.class), Arrays.asList(x.getBounds()));
89    }
90
91    private <T> T getOnlyValue(Object[] array, Class<T> expectedType) {
92        assertEquals("Expected a " + expectedType.getName() + " but was " + Arrays.toString(array),
93                1, array.length);
94        assertTrue("Expected a " + expectedType.getName() + " but was " + array[0],
95                expectedType.isInstance(array[0]));
96        return expectedType.cast(array[0]);
97    }
98
99    static class Thrower {
100        public <T> Thrower() throws IOException {}
101        public Thrower(List<?> unused) throws IOException {}
102        public <T> void parameterizedMethod() throws IOException {}
103        public void genericParameters(List<?> unused) throws IOException {}
104    }
105
106    static class ThrowerT<T extends Throwable> {
107        public ThrowerT() throws T {}
108        public void throwsTypeVariable() throws T {}
109        public <X extends Exception> void throwsMethodTypeParameter() throws X {}
110        public <X extends Exception> void throwsEverything() throws T, Exception, X{}
111    }
112}
113