001 package edu.rice.cs.cunit.subAnnot.test;
002
003 import edu.rice.cs.cunit.subAnnot.ClassEx;
004 import edu.rice.cs.cunit.subAnnot.ConstructorEx;
005 import edu.rice.cs.cunit.subAnnot.MethodEx;
006 import junit.framework.TestCase;
007
008 import java.lang.annotation.Annotation;
009 import java.lang.annotation.Retention;
010 import java.lang.annotation.RetentionPolicy;
011 import java.lang.reflect.Method;
012 import java.util.HashMap;
013 import java.util.Iterator;
014 import java.util.Map;
015 import java.util.TreeMap;
016
017 /**
018 * Unit tests for extended Class class to support annotations with subclassing.
019 *
020 * @author Mathias Ricken
021 */
022 public class ClassExTest extends TestCase {
023 public void testAnnotations() throws Exception {
024 doClassTestNoOrder(TestOne.class);
025 }
026 public void testAnnotationsWithDefaults() throws Exception {
027 doClassTestNoOrder(TestDefaults.class);
028 }
029
030 public void testTwoAnnotations() throws Exception {
031 doClassTestNoOrder(TestTwo.class);
032 }
033 public void testTwoAnnotationsWithDefaults() throws Exception {
034 doClassTestNoOrder(TestTwoDefaults.class);
035 }
036
037 @SuppressWarnings("unchecked")
038 private void doClassTestNoOrder(Class cl) throws Exception{
039 Annotation[] aOrig = cl.getAnnotations();
040 ClassEx<TestOne> c = new ClassEx<TestOne>(cl);
041 Annotation[] aExt = c.getAnnotations();
042 assertEquals(aOrig.length, aExt.length);
043 TreeMap<String,TreeMap<String, Object>> orig = new TreeMap<String,TreeMap<String, Object>>();
044 TreeMap<String,TreeMap<String, Object>> ext = new TreeMap<String,TreeMap<String, Object>>();
045 for(int i=0; i<aOrig.length; ++i) {
046 TreeMap<String, Object> mapOrig = new TreeMap<String, Object>();
047 for(Method m: aOrig[i].annotationType().getMethods()) {
048 if ((!m.getDeclaringClass().equals(Annotation.class)) &&
049 (m.getParameterTypes().length==0)) {
050 mapOrig.put(m.getName(), m.invoke(aOrig[i]));
051 }
052 }
053 orig.put(aOrig[i].annotationType().getName(),mapOrig);
054 }
055 for(int i=0; i<aOrig.length; ++i) {
056 TreeMap<String, Object> mapExt = new TreeMap<String, Object>();
057 for(Method m: aExt[i].annotationType().getMethods()) {
058 if ((!m.getDeclaringClass().equals(Annotation.class)) &&
059 (m.getParameterTypes().length==0)) {
060 mapExt.put(m.getName(), m.invoke(aExt[i]));
061 }
062 }
063 ext.put(aExt[i].annotationType().getName(),mapExt);
064 }
065 assertEquals(orig.size(), ext.size());
066 Iterator<Map.Entry<String,TreeMap<String, Object>>> origIt = orig.entrySet().iterator();
067 Iterator<Map.Entry<String,TreeMap<String, Object>>> extIt = ext.entrySet().iterator();
068 for(int i=0; i<orig.size(); ++i) {
069 final Map.Entry<String, TreeMap<String, Object>> origEntry = origIt.next();
070 final Map.Entry<String, TreeMap<String, Object>> extEntry = extIt.next();
071 assertEquals(origEntry.getKey(), extEntry.getKey());
072 TreeMap<String, Object> mapOrig = origEntry.getValue();
073 TreeMap<String, Object> mapExt = extEntry.getValue();
074 assertEquals(mapOrig.size(), mapExt.size());
075 Iterator<Map.Entry<String, Object>> mapOrigIt = mapOrig.entrySet().iterator();
076 Iterator<Map.Entry<String, Object>> mapExtIt = mapExt.entrySet().iterator();
077 for(int j=0; i<mapOrig.size(); ++i) {
078 final Map.Entry<String, Object> mapOrigEntry = mapOrigIt.next();
079 final Map.Entry<String, Object> mapExtEntry = mapExtIt.next();
080 assertEquals(mapOrigEntry.getKey(), mapExtEntry.getKey());
081 Object origV = mapOrigEntry.getValue();
082 Object extV = mapExtEntry.getValue();
083 assertEquals(origV, extV);
084 }
085 }
086 }
087
088 public void testMethodParamAnnots() throws Exception {
089 ClassEx<TestOne> c = new ClassEx<TestOne>(TestOne.class);
090 MethodEx m = c.getMethod("foo", int.class, float.class, Class.class);
091 Annotation[][] as = m.getParameterAnnotations();
092 for(Annotation[] ar: as) {
093 for(Annotation a: ar) {
094 System.out.print(a);
095 System.out.print(" ");
096 }
097 System.out.println();
098 }
099 assertEquals(3, as.length);
100 assertEquals(2, as[0].length);
101 assertEquals(0, as[1].length);
102 assertEquals(1, as[2].length);
103 assertEquals("@edu.rice.cs.cunit.subAnnot.test.TestStringAnnotation(value=xxx)", as[0][0].toString());
104 assertEquals("@edu.rice.cs.cunit.subAnnot.test.TestIntAnnotation(value=5)", as[0][1].toString());
105
106 // assertEquals("@edu.rice.cs.cunit.subAnnot.test.TestDefaultsTwoAnnotation(s=foo, i=123)", as[2][0].toString());
107 Map<String, Object> mapOrig = new HashMap<String, Object>();
108 mapOrig.put("s","foo");
109 mapOrig.put("i", 123);
110 Map<String, Object> mapExt = new HashMap<String, Object>();
111 for(Method mm: as[2][0].annotationType().getMethods()) {
112 if ((!mm.getDeclaringClass().equals(Annotation.class)) &&
113 (mm.getParameterTypes().length==0)) {
114 mapExt.put(mm.getName(), mm.invoke(as[2][0]));
115 }
116 }
117 assertEquals(mapOrig.size(), mapExt.size());
118 for(Map.Entry<String, Object> e: mapOrig.entrySet()) {
119 Object v = mapExt.get(e.getKey());
120 assertEquals(e.getValue(),v);
121 mapExt.remove(e.getKey());
122 }
123 assertEquals(0, mapExt.size());
124 }
125
126 public void testCtorParamAnnots() throws Exception {
127 ClassEx<TestOne> c = new ClassEx<TestOne>(TestOne.class);
128 ConstructorEx<TestOne> ctor = c.getConstructor(int.class, float.class, Class.class);
129 Annotation[][] as = ctor.getParameterAnnotations();
130 for(Annotation[] ar: as) {
131 for(Annotation a: ar) {
132 System.out.print(a);
133 System.out.print(" ");
134 }
135 System.out.println();
136 }
137 assertEquals(3, as.length);
138 assertEquals(2, as[0].length);
139 assertEquals(0, as[1].length);
140 assertEquals(1, as[2].length);
141 assertEquals("@edu.rice.cs.cunit.subAnnot.test.TestStringAnnotation(value=xxx)", as[0][0].toString());
142 assertEquals("@edu.rice.cs.cunit.subAnnot.test.TestIntAnnotation(value=5)", as[0][1].toString());
143
144 // assertEquals("@edu.rice.cs.cunit.subAnnot.test.TestDefaultsTwoAnnotation(s=foo, i=123)", as[2][0].toString());
145 Map<String, Object> mapOrig = new HashMap<String, Object>();
146 mapOrig.put("s","foo");
147 mapOrig.put("i", 123);
148 Map<String, Object> mapExt = new HashMap<String, Object>();
149 for(Method mm: as[2][0].annotationType().getMethods()) {
150 if ((!mm.getDeclaringClass().equals(Annotation.class)) &&
151 (mm.getParameterTypes().length==0)) {
152 mapExt.put(mm.getName(), mm.invoke(as[2][0]));
153 }
154 }
155 assertEquals(mapOrig.size(), mapExt.size());
156 for(Map.Entry<String, Object> e: mapOrig.entrySet()) {
157 Object v = mapExt.get(e.getKey());
158 assertEquals(e.getValue(),v);
159 mapExt.remove(e.getKey());
160 }
161 assertEquals(0, mapExt.size());
162 }
163 }
164
165 @TestStringAnnotation("blabla")
166 @TestIntAnnotation(123)
167 @TestLongAnnotation(7890)
168 @TestCharAnnotation('x')
169 @TestByteAnnotation(15)
170 @TestFloatAnnotation(3.14f)
171 @TestDoubleAnnotation(2.54)
172 @TestBooleanAnnotation(true)
173 @TestClassAnnotation(TestOne.class)
174 @TestEnumAnnotation(RetentionPolicy.RUNTIME)
175 @TestAnnotAnnotation(@TestStringAnnotation("annotation"))
176 @TestArrEnumAnnotation({RetentionPolicy.RUNTIME,RetentionPolicy.CLASS})
177 @TestArrClassAnnotation({TestOne.class, ClassEx.class, RetentionPolicy.class})
178 @TestArrStringAnnotation({"blabla","foobar","snafu"})
179 @TestArrIntAnnotation({123,456})
180 @TestArrLongAnnotation({7890,65536,12345})
181 @TestArrCharAnnotation({'x','y'})
182 @TestArrByteAnnotation({15,16,17,18})
183 @TestArrFloatAnnotation({3.14f})
184 @TestArrDoubleAnnotation({2.54,2.1415})
185 @TestArrBooleanAnnotation({true,false,true})
186 @TestArrAnnotAnnotation({@TestStringAnnotation("annotation"),@TestStringAnnotation("annotation2"),@TestStringAnnotation("annotation3")})
187 class TestOne {
188 public TestOne(@TestStringAnnotation("xxx") @TestIntAnnotation(5) int i, float f, @TestDefaultsTwoAnnotation Class c) { }
189 public void foo(@TestStringAnnotation("xxx") @TestIntAnnotation(5) int i, float f, @TestDefaultsTwoAnnotation Class c) { }
190 }
191
192 @TestTwoAnnotation(s="foo", i=123)
193 class TestTwo {
194 }
195
196 @Retention(RetentionPolicy.RUNTIME)
197 @interface TestStringAnnotation {
198 String value();
199 }
200 @Retention(RetentionPolicy.RUNTIME)
201 @interface TestIntAnnotation {
202 int value();
203 }
204 @Retention(RetentionPolicy.RUNTIME)
205 @interface TestLongAnnotation {
206 long value();
207 }
208 @Retention(RetentionPolicy.RUNTIME)
209 @interface TestCharAnnotation {
210 char value();
211 }
212 @Retention(RetentionPolicy.RUNTIME)
213 @interface TestByteAnnotation {
214 byte value();
215 }
216 @Retention(RetentionPolicy.RUNTIME)
217 @interface TestFloatAnnotation {
218 float value();
219 }
220 @Retention(RetentionPolicy.RUNTIME)
221 @interface TestDoubleAnnotation {
222 double value();
223 }
224 @Retention(RetentionPolicy.RUNTIME)
225 @interface TestBooleanAnnotation {
226 boolean value();
227 }
228 @Retention(RetentionPolicy.RUNTIME)
229 @interface TestClassAnnotation {
230 Class value();
231 }
232 @Retention(RetentionPolicy.RUNTIME)
233 @interface TestEnumAnnotation {
234 RetentionPolicy value();
235 }
236 @Retention(RetentionPolicy.RUNTIME)
237 @interface TestAnnotAnnotation {
238 TestStringAnnotation value();
239 }
240 @Retention(RetentionPolicy.RUNTIME)
241 @interface TestArrEnumAnnotation {
242 RetentionPolicy[] value();
243 }
244 @Retention(RetentionPolicy.RUNTIME)
245 @interface TestArrClassAnnotation {
246 Class[] value();
247 }
248 @Retention(RetentionPolicy.RUNTIME)
249 @interface TestArrStringAnnotation {
250 String[] value();
251 }
252 @Retention(RetentionPolicy.RUNTIME)
253 @interface TestArrIntAnnotation {
254 int[] value();
255 }
256 @Retention(RetentionPolicy.RUNTIME)
257 @interface TestArrLongAnnotation {
258 long[] value();
259 }
260 @Retention(RetentionPolicy.RUNTIME)
261 @interface TestArrCharAnnotation {
262 char[] value();
263 }
264 @Retention(RetentionPolicy.RUNTIME)
265 @interface TestArrByteAnnotation {
266 byte[] value();
267 }
268 @Retention(RetentionPolicy.RUNTIME)
269 @interface TestArrFloatAnnotation {
270 float[] value();
271 }
272 @Retention(RetentionPolicy.RUNTIME)
273 @interface TestArrDoubleAnnotation {
274 double[] value();
275 }
276 @Retention(RetentionPolicy.RUNTIME)
277 @interface TestArrBooleanAnnotation {
278 boolean[] value();
279 }
280 @Retention(RetentionPolicy.RUNTIME)
281 @interface TestArrAnnotAnnotation {
282 TestStringAnnotation[] value();
283 }
284 @Retention(RetentionPolicy.RUNTIME)
285 @interface TestTwoAnnotation {
286 String s();
287 int i();
288 }
289
290 @TestDefaultsStringAnnotation
291 @TestDefaultsIntAnnotation
292 @TestDefaultsLongAnnotation
293 @TestDefaultsCharAnnotation
294 @TestDefaultsByteAnnotation
295 @TestDefaultsFloatAnnotation
296 @TestDefaultsDoubleAnnotation
297 @TestDefaultsBooleanAnnotation
298 @TestDefaultsClassAnnotation
299 @TestDefaultsEnumAnnotation
300 @TestDefaultsAnnotAnnotation
301 @TestDefaultsArrEnumAnnotation
302 @TestDefaultsArrClassAnnotation
303 @TestDefaultsArrStringAnnotation
304 @TestDefaultsArrIntAnnotation
305 @TestDefaultsArrLongAnnotation
306 @TestDefaultsArrCharAnnotation
307 @TestDefaultsArrByteAnnotation
308 @TestDefaultsArrFloatAnnotation
309 @TestDefaultsArrDoubleAnnotation
310 @TestDefaultsArrBooleanAnnotation
311 @TestDefaultsArrAnnotAnnotation
312 class TestDefaults {
313 }
314
315 @TestDefaultsTwoAnnotation
316 class TestTwoDefaults {
317 }
318
319 @Retention(RetentionPolicy.RUNTIME)
320 @interface TestDefaultsStringAnnotation {
321 String value() default "str";
322 }
323 @Retention(RetentionPolicy.RUNTIME)
324 @interface TestDefaultsIntAnnotation {
325 int value() default 7;
326 }
327 @Retention(RetentionPolicy.RUNTIME)
328 @interface TestDefaultsLongAnnotation {
329 long value() default 12345;
330 }
331 @Retention(RetentionPolicy.RUNTIME)
332 @interface TestDefaultsCharAnnotation {
333 char value() default 'x';
334 }
335 @Retention(RetentionPolicy.RUNTIME)
336 @interface TestDefaultsByteAnnotation {
337 byte value() default 15;
338 }
339 @Retention(RetentionPolicy.RUNTIME)
340 @interface TestDefaultsFloatAnnotation {
341 float value() default 1.23f;
342 }
343 @Retention(RetentionPolicy.RUNTIME)
344 @interface TestDefaultsDoubleAnnotation {
345 double value() default 4.5678;
346 }
347 @Retention(RetentionPolicy.RUNTIME)
348 @interface TestDefaultsBooleanAnnotation {
349 boolean value() default true;
350 }
351 @Retention(RetentionPolicy.RUNTIME)
352 @interface TestDefaultsClassAnnotation {
353 Class value() default Class.class;
354 }
355 @Retention(RetentionPolicy.RUNTIME)
356 @interface TestDefaultsEnumAnnotation {
357 RetentionPolicy value() default RetentionPolicy.CLASS;
358 }
359 @Retention(RetentionPolicy.RUNTIME)
360 @interface TestDefaultsAnnotAnnotation {
361 TestDefaultsStringAnnotation value() default @TestDefaultsStringAnnotation;
362 }
363 @Retention(RetentionPolicy.RUNTIME)
364 @interface TestDefaultsArrEnumAnnotation {
365 RetentionPolicy[] value() default {RetentionPolicy.CLASS, RetentionPolicy.RUNTIME};
366 }
367 @Retention(RetentionPolicy.RUNTIME)
368 @interface TestDefaultsArrClassAnnotation {
369 Class[] value() default {Integer.class, Long.class};
370 }
371 @Retention(RetentionPolicy.RUNTIME)
372 @interface TestDefaultsArrStringAnnotation {
373 String[] value() default {"foo","bar"};
374 }
375 @Retention(RetentionPolicy.RUNTIME)
376 @interface TestDefaultsArrIntAnnotation {
377 int[] value() default {1,2,3,4,5};
378 }
379 @Retention(RetentionPolicy.RUNTIME)
380 @interface TestDefaultsArrLongAnnotation {
381 long[] value() default {12345,67890};
382 }
383 @Retention(RetentionPolicy.RUNTIME)
384 @interface TestDefaultsArrCharAnnotation {
385 char[] value() default {'a', 'b', 'c'};
386 }
387 @Retention(RetentionPolicy.RUNTIME)
388 @interface TestDefaultsArrByteAnnotation {
389 byte[] value() default {100,101,102};
390 }
391 @Retention(RetentionPolicy.RUNTIME)
392 @interface TestDefaultsArrFloatAnnotation {
393 float[] value() default {3.14f,2.53f};
394 }
395 @Retention(RetentionPolicy.RUNTIME)
396 @interface TestDefaultsArrDoubleAnnotation {
397 double[] value() default {1.2345,6.7890};
398 }
399 @Retention(RetentionPolicy.RUNTIME)
400 @interface TestDefaultsArrBooleanAnnotation {
401 boolean[] value() default {false,true,false};
402 }
403 @Retention(RetentionPolicy.RUNTIME)
404 @interface TestDefaultsArrAnnotAnnotation {
405 TestDefaultsStringAnnotation[] value() default {@TestDefaultsStringAnnotation("annot1"),@TestDefaultsStringAnnotation("annot2")};
406 }
407 @Retention(RetentionPolicy.RUNTIME)
408 @interface TestDefaultsTwoAnnotation {
409 String s() default "foo";
410 int i() default 123;
411 }