1/*
2 * Copyright (C) 2008 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 tests.api.java.lang.reflect;
18
19
20import java.lang.reflect.Method;
21import java.lang.reflect.ParameterizedType;
22import java.lang.reflect.Type;
23import java.lang.reflect.TypeVariable;
24import java.lang.reflect.WildcardType;
25
26import dalvik.annotation.TestLevel;
27import dalvik.annotation.TestTargetClass;
28import dalvik.annotation.TestTargetNew;
29
30/**
31 * Tests bounded type parameters declared on methods and bounded wildcards.
32 */
33@TestTargetClass(WildcardType.class)
34public class WildcardTypeTest extends GenericReflectionTestsBase {
35    @SuppressWarnings({"unchecked", "hiding"})
36    static class BoundedWildcardsGenericMethods<T> {
37
38        public <T extends BoundedWildcardsGenericMethods> void lowerBoundedParamNoReturn( BoundedWildcardsGenericMethods<? super T> param) {}
39
40        public <T extends BoundedWildcardsGenericMethods> void upperBoundedParamNoReturn( BoundedWildcardsGenericMethods<? extends T> param) {}
41
42        public <T extends BoundedWildcardsGenericMethods> T lowerBoundedParamReturn(BoundedWildcardsGenericMethods<? super T> param) { return (T) new Object(); }
43
44        public <T extends BoundedWildcardsGenericMethods> T upperBoundedParamReturn(BoundedWildcardsGenericMethods<? extends T> param) { return (T) new Object();}
45    }
46
47    @SuppressWarnings("unchecked")
48    private static Class<? extends BoundedWildcardsGenericMethods> clazz = BoundedWildcardsGenericMethods.class;
49
50//    /**
51//     * Tests that there are is one Type Parameter on the Class itself.
52//     */
53//    @TestInfo(
54//      level = TestLevel.PARTIAL,
55//      purpose = "Doesn't check GenericSignatureFormatError.",
56//      targets = {
57//        @TestTarget(
58//          methodName = "getTypeParameters",
59//          methodArgs = {}
60//        )
61//    })
62    @TestTargetNew(
63        level = TestLevel.PARTIAL,
64        notes = "",
65        clazz = Class.class,
66        method = "getTypeParameters",
67        args = {}
68    )
69    public void testBoundedGenericMethods() {
70        assertLenghtOne(clazz.getTypeParameters());
71    }
72
73    /**
74     * Tests whether the type parameter is bounded by BoundedGenericMethods like:
75     * <T extends BoundedGenericMethods>.
76     * @param method the declaring method
77     */
78    private void checkBoundedTypeParameter(Method method) {
79        TypeVariable<Method> typeParameter = getTypeParameter(method);
80        assertEquals("T", typeParameter.getName());
81        assertEquals(method, typeParameter.getGenericDeclaration());
82
83        Type[] bounds = typeParameter.getBounds();
84        assertLenghtOne(bounds);
85        Type bound = bounds[0];
86        assertEquals(BoundedWildcardsGenericMethods.class, bound);
87    }
88
89    private void checkLowerBoundedParameter(Method method) {
90        Type genericParameterType = method.getGenericParameterTypes()[0];
91        assertInstanceOf(ParameterizedType.class, genericParameterType);
92
93        ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
94
95        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
96        assertLenghtOne(actualTypeArguments);
97        assertInstanceOf(WildcardType.class, actualTypeArguments[0]);
98
99        WildcardType wildcardType = (WildcardType) actualTypeArguments[0];
100
101        Type[] lowerBounds = wildcardType.getLowerBounds();
102        assertLenghtOne(lowerBounds);
103        Type lowerBound = lowerBounds[0];
104        assertEquals(getTypeParameter(method), lowerBound);
105
106        Type[] upperBounds = wildcardType.getUpperBounds();
107        assertEquals(Object.class, upperBounds[0]);
108    }
109
110    private void checkUpperBoundedParameter(Method method) {
111        assertLenghtOne(method.getGenericParameterTypes());
112        Type genericParameterType = method.getGenericParameterTypes()[0];
113        assertInstanceOf(ParameterizedType.class, genericParameterType);
114
115        ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
116        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
117        assertLenghtOne(actualTypeArguments);
118        assertInstanceOf(WildcardType.class, actualTypeArguments[0]);
119
120        WildcardType wildcardType = (WildcardType) actualTypeArguments[0];
121        assertLenghtZero(wildcardType.getLowerBounds());
122
123        Type[] upperBounds = wildcardType.getUpperBounds();
124        assertLenghtOne(upperBounds);
125        Type upperBound = upperBounds[0];
126        assertEquals(getTypeParameter(method), upperBound);
127    }
128
129    @SuppressWarnings("unchecked")
130    private void checkReturnType(Method method) {
131        Type genericReturnType = method.getGenericReturnType();
132        assertEquals(getTypeParameter(method), genericReturnType);
133        assertTrue(genericReturnType instanceof TypeVariable);
134
135        TypeVariable<Method> returnTypeVariable = (TypeVariable<Method>) genericReturnType;
136        assertEquals(method, returnTypeVariable.getGenericDeclaration());
137
138        Type[] bounds = returnTypeVariable.getBounds();
139        assertLenghtOne(bounds);
140        Type bound = bounds[0];
141
142        assertEquals(BoundedWildcardsGenericMethods.class, bound);
143    }
144
145    @TestTargetNew(
146        level = TestLevel.SUFFICIENT,
147        notes = "Missing tests for TypeNotPresentException, MalformedParametrizedTypeException",
148        method = "getUpperBounds",
149        args = {}
150    )
151    public void testUpperBoundedParamNoReturn() throws Exception {
152        Method method = clazz.getMethod("upperBoundedParamNoReturn", BoundedWildcardsGenericMethods.class);
153        checkBoundedTypeParameter(method);
154        checkUpperBoundedParameter(method);
155    }
156
157    @TestTargetNew(
158        level = TestLevel.SUFFICIENT,
159        notes = "Missing tests for TypeNotPresentException, MalformedParametrizedTypeException",
160        method = "getLowerBounds",
161        args = {}
162    )
163    public void testLowerBoundedParamReturn() throws Exception {
164        Method method = clazz.getMethod("lowerBoundedParamReturn", BoundedWildcardsGenericMethods.class);
165        checkBoundedTypeParameter(method);
166        checkLowerBoundedParameter(method);
167        checkReturnType(method);
168    }
169
170    @TestTargetNew(
171        level = TestLevel.SUFFICIENT,
172        notes = "Missing tests for TypeNotPresentException, MalformedParametrizedTypeException",
173        method = "getUpperBounds",
174        args = {}
175    )
176    public void testUpperBoundedParamReturn() throws Exception {
177        Method method = clazz.getMethod("upperBoundedParamReturn", BoundedWildcardsGenericMethods.class);
178        checkBoundedTypeParameter(method);
179        checkUpperBoundedParameter(method);
180        checkReturnType(method);
181    }
182
183    @TestTargetNew(
184        level = TestLevel.SUFFICIENT,
185        notes = "Missing tests for TypeNotPresentException, MalformedParametrizedTypeException",
186        method = "getLowerBounds",
187        args = {}
188    )
189    public void testLowerBoundedParamNoReturn() throws Exception {
190        Method method = clazz.getMethod("lowerBoundedParamNoReturn", BoundedWildcardsGenericMethods.class);
191        checkBoundedTypeParameter(method);
192        assertLenghtOne(method.getGenericParameterTypes());
193        checkLowerBoundedParameter(method);
194    }
195
196}
197