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 }