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 org.apache.harmony.lang;
018:
019: import java.lang.annotation.Annotation;
020: import java.lang.annotation.Retention;
021: import java.lang.annotation.RetentionPolicy;
022: import java.lang.reflect.AnnotatedElement;
023: import java.util.Arrays;
024: import java.util.List;
025:
026: import notfound.MissingAntn;
027: import notfound.MissingClass;
028: import notfound.MissingEnum;
029:
030: import junit.framework.TestCase;
031:
032: /**
033: * Basic framework for testing implementations of the
034: * {@link java.lang.reflect.AnnotatedElement AnnotatedElement} interface.
035: * Expected usage: concrete test extending this class should only provide
036: * objects to be tested, via realization of several abstract methods.
037: * @see #getElement1()
038: * @see #getElement2()
039: * @see #getElement3()
040: * @see #getElement4()
041: * @see #getElement5()
042: * @see #getElement6()
043: *
044: * @author Alexey V. Varlamov
045: * @version $Revision$
046: */
047: public abstract class AnnotatedElementTestFrame extends TestCase {
048:
049: @Retention(RetentionPolicy.RUNTIME)
050: public @interface TagAntn {
051: }
052:
053: @Retention(RetentionPolicy.RUNTIME)
054: public @interface ValAntn {
055: String value() default "<unspecified>";
056: }
057:
058: @Retention(RetentionPolicy.RUNTIME)
059: public @interface None {
060: }
061:
062: @Retention(RetentionPolicy.RUNTIME)
063: public @interface MissingClassValAntn {
064: Class clss() default MissingClass.class;
065:
066: Class[] clssArray() default MissingClass.class;
067: }
068:
069: @Retention(RetentionPolicy.RUNTIME)
070: public @interface MissingTypeAntn {
071: MissingAntn antn() default @MissingAntn;
072:
073: MissingEnum enm() default MissingEnum.A;
074:
075: MissingAntn[] antnArray() default @MissingAntn;
076:
077: MissingEnum[] enmArray() default MissingEnum.A;
078: }
079:
080: /**
081: * Provides an instance to be tested. The instance must be annotated
082: * exactly by the single type {@link TagAntn TagAntn}.
083: */
084: protected abstract AnnotatedElement getElement1() throws Throwable;
085:
086: /**
087: * Provides an instance to be tested. The instance must be annotated
088: * exactly by the two types {@link TagAntn TagAntn} and {@link ValAntn ValAntn}.
089: */
090: protected abstract AnnotatedElement getElement2() throws Throwable;
091:
092: /**
093: * Provides an instance to be tested. The instance must not be annotated.
094: */
095: protected abstract AnnotatedElement getElement3() throws Throwable;
096:
097: /**
098: * Provides an instance to be tested. The instance must be annotated
099: * by the notfound.MissingAntn.
100: */
101: protected abstract AnnotatedElement getElement4() throws Throwable;
102:
103: /**
104: * Provides an instance to be tested. The instance must be annotated
105: * by the MissingClassValAntn.
106: */
107: protected abstract AnnotatedElement getElement5() throws Throwable;
108:
109: /**
110: * Provides an instance to be tested. The instance must be annotated
111: * by the MissingTypeAntn.
112: */
113: protected abstract AnnotatedElement getElement6() throws Throwable;
114:
115: /**
116: * getAnnotation(Class) should return
117: * an annotation presented on the element1.
118: */
119: public void testGetAnnotation() throws Throwable {
120: Annotation an = getElement1().getAnnotation(TagAntn.class);
121: assertNotNull(an);
122: assertSame(TagAntn.class, an.annotationType());
123: }
124:
125: /**
126: * getAnnotation(Class) should return
127: * an annotation presented on the element2.
128: */
129: public void testGetAnnotation2() throws Throwable {
130: Annotation an = getElement2().getAnnotation(ValAntn.class);
131: assertNotNull(an);
132: assertSame(ValAntn.class, an.annotationType());
133: }
134:
135: /**
136: * getAnnotation(Class) should return
137: * null for unexpected annotation type.
138: */
139: public void testGetAnnotation_Negative() throws Throwable {
140: assertNull("case 1", getElement2().getAnnotation(None.class));
141: assertNull("case 2", getElement2().getAnnotation(None.class));
142: }
143:
144: /**
145: * getAnnotation(Class) should return
146: * null for non-annotated instance.
147: */
148: public void testGetAnnotation_Negative2() throws Throwable {
149: assertNull("case 1", getElement3().getAnnotation(TagAntn.class));
150: assertNull("case 2", getElement3().getAnnotation(None.class));
151: }
152:
153: /**
154: * getAnnotation(Class) should throw NPE on null argument.
155: */
156: public void testGetAnnotation_Null() throws Throwable {
157: try {
158: getElement1().getAnnotation(null);
159: fail("failed to throw NPE");
160: } catch (NullPointerException ok) {
161: }
162: }
163:
164: /**
165: * getDeclaredAnnotations() should return
166: * all annotations presented on the element1.
167: */
168: public void testGetDeclaredAnnotations() throws Throwable {
169: Annotation[] an = getElement1().getDeclaredAnnotations();
170: assertNotNull(an);
171: assertEquals("number of Declared Annotations", 1, an.length);
172: assertSame(TagAntn.class, an[0].annotationType());
173: }
174:
175: /**
176: * getDeclaredAnnotations() should return
177: * all annotations presented on the element2.
178: */
179: public void testGetDeclaredAnnotations2() throws Throwable {
180: Annotation[] an = getElement2().getDeclaredAnnotations();
181: assertNotNull(an);
182: assertEquals("number of Declared Annotations", 2, an.length);
183: List<Class> la = Arrays.asList(new Class[] {
184: an[0].annotationType(), an[1].annotationType() });
185: assertTrue("1st annotation", la.contains(TagAntn.class));
186: assertTrue("2nd annotation", la.contains(ValAntn.class));
187: }
188:
189: /**
190: * getDeclaredAnnotations() should return
191: * empty array for the element3.
192: */
193: public void testGetDeclaredAnnotations3() throws Throwable {
194: Annotation[] an = getElement3().getDeclaredAnnotations();
195: assertNotNull(an);
196: assertEquals(0, an.length);
197: }
198:
199: /**
200: * getDeclaredAnnotations() should return cloned array
201: * which can be safely modified by a caller.
202: */
203: public void testGetDeclaredAnnotationsImmutable() throws Throwable {
204: AnnotatedElement el = getElement1();
205: Annotation[] an = el.getDeclaredAnnotations();
206: assertNotNull(an);
207: assertEquals("number of Declared Annotations", 1, an.length);
208: assertSame(TagAntn.class, an[0].annotationType());
209: an[0] = null;
210: Annotation[] an2 = el.getDeclaredAnnotations();
211: assertNotNull(an2);
212: assertEquals("number of second Declared Annotations", 1,
213: an2.length);
214: assertNotNull("array is not immutable", an2[0]);
215: assertSame(TagAntn.class, an2[0].annotationType());
216: }
217:
218: /**
219: * getAnnotations() should return
220: * all annotations presented on the element1.
221: */
222: public void testGetAnnotations() throws Throwable {
223: Annotation[] an = getElement1().getAnnotations();
224: assertNotNull(an);
225: assertEquals("number of Annotations", 1, an.length);
226: assertSame(TagAntn.class, an[0].annotationType());
227: }
228:
229: /**
230: * getAnnotations() should return
231: * all annotations presented on the element2.
232: */
233: public void testGetAnnotations2() throws Throwable {
234: Annotation[] an = getElement2().getAnnotations();
235: assertNotNull(an);
236: assertEquals("number of Annotations", 2, an.length);
237: List<Class> la = Arrays.asList(new Class[] {
238: an[0].annotationType(), an[1].annotationType() });
239: assertTrue("1st annotation", la.contains(TagAntn.class));
240: assertTrue("2nd annotation", la.contains(ValAntn.class));
241: }
242:
243: /**
244: * getAnnotations() should return
245: * empty array for the element3.
246: */
247: public void testGetAnnotations3() throws Throwable {
248: Annotation[] an = getElement3().getAnnotations();
249: assertNotNull(an);
250: assertEquals(0, an.length);
251: }
252:
253: /**
254: * getAnnotations() should skip unresolved annotation
255: * thus should return empty array for the element4.
256: */
257: public void testGetAnnotations4() throws Throwable {
258: Annotation[] an = getElement4().getAnnotations();
259: assertNotNull(an);
260: assertEquals(0, an.length);
261: }
262:
263: /**
264: * getAnnotations() should return
265: * all annotations presented on the element5.
266: */
267: public void testGetAnnotations5() throws Throwable {
268: Annotation[] an = getElement5().getAnnotations();
269: assertNotNull(an);
270: assertEquals("number of Annotations", 1, an.length);
271: assertSame(MissingClassValAntn.class, an[0].annotationType());
272: }
273:
274: /**
275: * getAnnotations() should throw NoClassDefFoundError
276: * for the element6.
277: */
278: public void testGetAnnotations6() throws Throwable {
279: try {
280: getElement6().getAnnotations();
281: fail("Misconfigured test");
282: } catch (TypeNotPresentException tnpe) {
283: assertTrue("reported type name: " + tnpe.typeName(), tnpe
284: .typeName().matches("notfound.Missing(.)+"));
285: } catch (NoClassDefFoundError e) {
286: assertTrue("reported type name: " + e.getMessage(), e
287: .getMessage().matches("notfound.Missing(.)+"));
288: }
289: }
290:
291: /**
292: * getAnnotations() should return cloned array
293: * which can be safely modified by a caller.
294: */
295: public void testGetAnnotationsImmutable() throws Throwable {
296: AnnotatedElement el = getElement1();
297: Annotation[] an = el.getAnnotations();
298: assertNotNull(an);
299: assertEquals("number of Annotations", 1, an.length);
300: assertSame(TagAntn.class, an[0].annotationType());
301: an[0] = null;
302: Annotation[] an2 = el.getAnnotations();
303: assertNotNull(an2);
304: assertEquals("number of second Annotations", 1, an2.length);
305: assertNotNull("array is not immutable", an2[0]);
306: assertSame(TagAntn.class, an2[0].annotationType());
307: }
308:
309: /**
310: * isAnnotationPresent(Class) should return true
311: * for the annotation(s) presented.
312: */
313: public void testIsAnnotationPresent() throws Throwable {
314: assertTrue("case 1", getElement1().isAnnotationPresent(
315: TagAntn.class));
316: assertTrue("case 2", getElement2().isAnnotationPresent(
317: TagAntn.class));
318: assertTrue("case 3", getElement2().isAnnotationPresent(
319: ValAntn.class));
320: }
321:
322: /**
323: * isAnnotationPresent(Class) should return false
324: * for the annotation(s) not presented.
325: */
326: public void testIsAnnotationPresent_Negative() throws Throwable {
327: assertFalse("case 1", getElement1().isAnnotationPresent(
328: ValAntn.class));
329: assertFalse("case 2", getElement1().isAnnotationPresent(
330: None.class));
331: assertFalse("case 3", getElement2().isAnnotationPresent(
332: None.class));
333: assertFalse("case 4", getElement3().isAnnotationPresent(
334: TagAntn.class));
335: }
336:
337: /**
338: * isAnnotationPresent(Class) should throw NPE on null argument
339: */
340: public void testIsAnnotationPresent_Null() throws Throwable {
341: try {
342: getElement1().isAnnotationPresent(null);
343: fail("failed to throw NPE");
344: } catch (NullPointerException ok) {
345: }
346: }
347: }
|