001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package java.lang.reflect;
018:
019: import java.lang.annotation.Annotation;
020: import java.lang.annotation.Inherited;
021: import java.lang.annotation.Retention;
022: import java.lang.annotation.RetentionPolicy;
023:
024: import org.apache.harmony.lang.AnnotatedElementTestFrame;
025: import org.apache.harmony.lang.AnnotatedElementTestFrame.MissingClassValAntn;
026: import org.apache.harmony.lang.AnnotatedElementTestFrame.MissingTypeAntn;
027: import org.apache.harmony.lang.AnnotatedElementTestFrame.TagAntn;
028: import org.apache.harmony.lang.AnnotatedElementTestFrame.ValAntn;
029:
030: /**
031: * @author Alexey V. Varlamov
032: * @version $Revision$
033: */
034: public class Method5Test extends AnnotatedElementTestFrame {
035:
036: protected @Override
037: AnnotatedElement getElement1() throws Throwable {
038: return AnnotatedMethod.class.getMethod("foo");
039: }
040:
041: protected @Override
042: AnnotatedElement getElement2() throws Throwable {
043: return AnnotatedMethod.class.getMethod("bar");
044: }
045:
046: protected @Override
047: AnnotatedElement getElement3() throws Throwable {
048: return AnnotatedMethod.class.getMethod("buz", String.class);
049: }
050:
051: /**
052: * Provides an instance to be tested. The instance must be annotated
053: * by the notfound.MissingAntn.
054: */
055: protected @Override
056: AnnotatedElement getElement4() throws Throwable {
057: return AnnotatedMethod.class.getMethod("i", int.class);
058: }
059:
060: /**
061: * Provides an instance to be tested. The instance must be annotated
062: * by the MissingClassValAntn.
063: */
064: protected @Override
065: AnnotatedElement getElement5() throws Throwable {
066: return AnnotatedMethod.class.getMethod("l", long.class);
067: }
068:
069: /**
070: * Provides an instance to be tested. The instance must be annotated
071: * by the MissingTypeAntn.
072: */
073: protected @Override
074: AnnotatedElement getElement6() throws Throwable {
075: return AnnotatedMethod.class.getMethod("ch", char.class);
076: }
077:
078: public static void main(String[] args) {
079: junit.textui.TestRunner.run(Method5Test.class);
080: }
081:
082: protected final Annotation[][] getParamAnnotations(Member obj)
083: throws Throwable {
084: assertTrue("illegal argument: " + obj, (obj instanceof Method)
085: || (obj instanceof Constructor));
086: Method m = obj.getClass().getMethod("getParameterAnnotations");
087: return (Annotation[][]) m.invoke(obj);
088: }
089:
090: protected Member getParamElement1() throws Throwable {
091: return AnnotatedParamMethod.class.getMethod("foo");
092: }
093:
094: protected Member getParamElement2() throws Throwable {
095: return AnnotatedParamMethod.class.getMethod("bar",
096: Object.class, Class.class, boolean.class);
097: }
098:
099: protected Member getParamElement3() throws Throwable {
100: return AnnotatedParamMethod.class.getMethod("buz",
101: String.class, int.class);
102: }
103:
104: /**
105: * getParameterAnnotations() should return empty array
106: * if member has no parameters.
107: */
108: public void testGetParameterAnnotations1() throws Throwable {
109: Annotation[][] an = getParamAnnotations(getParamElement1());
110: assertNotNull(an);
111: assertEquals(0, an.length);
112: }
113:
114: /**
115: * getParameterAnnotations() should return array of annotation
116: * arrays for member parameters, in declaration order.
117: */
118: public void testGetParameterAnnotations2() throws Throwable {
119: Annotation[][] an = getParamAnnotations(getParamElement2());
120: assertNotNull(an);
121: assertEquals("param num", 3, an.length);
122:
123: assertEquals("1st param annotation num", 1, an[0].length);
124: assertSame("1st param annotation type", P1Antn.class, an[0][0]
125: .annotationType());
126:
127: assertEquals("2nd param annotation num", 1, an[1].length);
128: assertSame("2nd param annotation type", P2Antn.class, an[1][0]
129: .annotationType());
130: assertEquals("2nd param annotation value", 123,
131: ((P2Antn) an[1][0]).value());
132:
133: assertEquals("3rd param annotation num", 2, an[2].length);
134: assertSame("3rd param annotation 1 type", P3Antn.class,
135: an[2][0].annotationType());
136: assertSame("3rd param annotation 2 type", ValAntn.class,
137: an[2][1].annotationType());
138: assertEquals("3rd param annotation 2 value", "xyz",
139: ((ValAntn) an[2][1]).value());
140: }
141:
142: /**
143: * For each parameter having no annotations,
144: * getParameterAnnotations() should return corresponding
145: * nested arrays with zero size.
146: */
147: public void testGetParameterAnnotations3() throws Throwable {
148: Annotation[][] an = getParamAnnotations(getParamElement3());
149: assertNotNull(an);
150: assertEquals("param num", 2, an.length);
151:
152: assertEquals("1st param annotation num", 0, an[0].length);
153:
154: assertEquals("2nd param annotation num", 1, an[1].length);
155: assertSame("2nd param annotation type", TagAntn.class, an[1][0]
156: .annotationType());
157: }
158:
159: /**
160: * getParameterAnnotations() should return cloned arrays
161: * which can be safely modified by a caller.
162: */
163: public void testGetParameterAnnotationsImmutable() throws Throwable {
164: Member m = getParamElement2();
165: Annotation[][] an0 = getParamAnnotations(m);
166: assertNotNull(an0);
167: assertEquals("param num", 3, an0.length);
168: an0[1] = an0[2];
169: an0[1][1] = null;
170: an0[2] = new Annotation[0];
171:
172: Annotation[][] an = getParamAnnotations(m);
173:
174: assertEquals("1st param annotation num", 1, an[0].length);
175: assertSame("1st param annotation type", P1Antn.class, an[0][0]
176: .annotationType());
177:
178: assertEquals("2nd param annotation num", 1, an[1].length);
179: assertSame("2nd param annotation type", P2Antn.class, an[1][0]
180: .annotationType());
181: assertEquals("2nd param annotation value", 123,
182: ((P2Antn) an[1][0]).value());
183:
184: assertEquals("3rd param annotation num", 2, an[2].length);
185: assertSame("3rd param annotation 1 type", P3Antn.class,
186: an[2][0].annotationType());
187: assertSame("3rd param annotation 2 type", ValAntn.class,
188: an[2][1].annotationType());
189: assertEquals("3rd param annotation 2 value", "xyz",
190: ((ValAntn) an[2][1]).value());
191: }
192:
193: static class A {
194: private Object obj;
195:
196: class InA {
197: Object o = obj;
198: }
199: }
200:
201: enum E {
202: E1, E2, E3
203: }
204:
205: static class B1 {
206: public Object foo() {
207: return null;
208: }
209:
210: public Object bar(int i, Object... o) {
211: return null;
212: }
213:
214: public static void main1(String... s) {
215: }
216:
217: public static void main2(String[] s) {
218: }
219: }
220:
221: static class B2 extends B1 {
222: public String foo() {
223: return "";
224: }
225:
226: public String bar(int i, Object... o) {
227: return "";
228: }
229: }
230:
231: /**
232: * isSynthetic() should return true if and only if
233: * the target method does not appear in the source code.
234: */
235: public void testIsSynthetic() throws Exception {
236: assertFalse("case1.1: ordinary method", AnnotatedMethod.class
237: .getMethod("foo").isSynthetic());
238: assertFalse("case1.2: ordinary vararg method", B1.class
239: .getMethod("main1", String[].class).isSynthetic());
240:
241: Method[] ms = A.class.getDeclaredMethods();
242: assertTrue(ms != null && ms.length > 0);
243: for (Method m : ms) {
244: assertTrue("case2: " + m, m.isSynthetic());
245: }
246:
247: // XXX bug in compiler?
248: //assertTrue("case3: EnumType.values()",
249: // E.class.getMethod("values").isSynthetic());
250: }
251:
252: /**
253: * isBridge() should return true if and only if
254: * the target method does not appear in the source code
255: * and overrides covariant return type method.
256: */
257: public void testIsBridge() throws Exception {
258: assertFalse("case1.1: ordinary method", AnnotatedMethod.class
259: .getMethod("foo").isBridge());
260: assertFalse("case1.2: ordinary vararg method", B1.class
261: .getMethod("main1", String[].class).isBridge());
262:
263: Method[] ms = B1.class.getMethods();
264: assertTrue(ms != null && ms.length > 0);
265: for (Method m : ms) {
266: assertFalse("case2.1: " + m, m.isBridge());
267: }
268:
269: ms = B2.class.getDeclaredMethods();
270: assertTrue(ms != null && ms.length > 0);
271: for (Method m : ms) {
272: //System.out.println("case2.2 " + m);
273: assertTrue("case2.2: " + m,
274: m.getReturnType() != Object.class ^ m.isBridge());
275: }
276:
277: assertFalse("case3: EnumType.values()", E.class.getMethod(
278: "values").isBridge());
279: }
280:
281: /**
282: * isVarArgs() should return true if and only if
283: * the target method is declared with varargs.
284: */
285: public void testIsVarargs() throws Exception {
286: assertFalse("case1: ordinary method", AnnotatedMethod.class
287: .getMethod("foo").isVarArgs());
288:
289: assertTrue("case2: varargs method", B1.class.getMethod("main1",
290: String[].class).isVarArgs());
291:
292: assertFalse("case3: ordinary method", B1.class.getMethod(
293: "main2", String[].class).isVarArgs());
294: }
295:
296: static abstract class C {
297: protected abstract <T extends Throwable> OneParamType<? extends T> go(
298: T t) throws T, Error;
299: }
300:
301: /**
302: * toGenericString() should return a string exactly matching
303: * the API specification.
304: */
305: public void testToGenericString() throws Exception {
306: String s = C.class.getDeclaredMethod("go", Throwable.class)
307: .toGenericString();
308: System.out.println(s);
309: assertEquals(
310: // Should method type parameter be followed by a type bound? It is unspecified.
311: // The known reference implementation doesn't do it as well:
312: //"protected abstract <T extends java.lang.Throwable>"
313: "protected abstract <T>"
314: + " java.lang.reflect.OneParamType<? extends T>"
315: + " java.lang.reflect.Method5Test$C.go(T)"
316: + " throws T,java.lang.Error", s);
317: }
318:
319: /**
320: * toGenericString() should return a string exactly matching
321: * the API specification.
322: */
323: public void testToGenericString2() throws Exception {
324: String s = B2.class.getDeclaredMethod("bar", int.class,
325: Object[].class).toGenericString();
326: // it is unspecified which method should be returned:
327: // original (overriden with covariant return) or
328: // compiler-generated bridge.
329: // different implementations behave differently,
330: // so relaxed this check to allow both variants.
331: assertTrue("start: " + s, s.startsWith("public java.lang.")); // String or Object
332: assertTrue("end: " + s, s
333: .endsWith(" java.lang.reflect.Method5Test$B2."
334: + "bar(int,java.lang.Object[])"));
335: }
336: }
337:
338: abstract class AnnotatedMethod {
339: @TagAntn
340: public abstract void foo();
341:
342: @TagAntn
343: @ValAntn
344: public Object[] bar() {
345: return null;
346: }
347:
348: public String buz(String s) {
349: return s;
350: }
351:
352: @notfound.MissingAntn
353: public void i(int i) {
354: }
355:
356: @MissingClassValAntn
357: public void l(long l) {
358: }
359:
360: @MissingTypeAntn
361: public void ch(char ch) {
362: }
363: }
364:
365: @Inherited
366: @Retention(RetentionPolicy.RUNTIME)
367: @interface P1Antn {
368: }
369:
370: @Retention(RetentionPolicy.RUNTIME)
371: @interface P2Antn {
372: int value();
373: }
374:
375: @Inherited
376: @Retention(RetentionPolicy.RUNTIME)
377: @interface P3Antn {
378: String[] meta1() default {};
379:
380: P1Antn meta2() default @P1Antn;
381: }
382:
383: class AnnotatedParamMethod {
384: @TagAntn
385: public void foo() {
386: }
387:
388: @ValAntn("abc")
389: public void bar(@P1Antn
390: Object p1, @P2Antn(123)
391: Class p2, @P3Antn
392: @ValAntn("xyz")
393: boolean p3) {
394: }
395:
396: public void buz(String s, @TagAntn
397: int i) {
398: }
399: }
|