1   package org.djutils.reflection;
2   
3   import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4   import static org.junit.jupiter.api.Assertions.assertEquals;
5   import static org.junit.jupiter.api.Assertions.assertFalse;
6   import static org.junit.jupiter.api.Assertions.assertNotEquals;
7   import static org.junit.jupiter.api.Assertions.assertNotNull;
8   import static org.junit.jupiter.api.Assertions.assertNull;
9   import static org.junit.jupiter.api.Assertions.assertTrue;
10  import static org.junit.jupiter.api.Assertions.fail;
11  
12  import java.lang.annotation.Annotation;
13  import java.lang.annotation.ElementType;
14  import java.lang.annotation.Retention;
15  import java.lang.annotation.RetentionPolicy;
16  import java.lang.annotation.Target;
17  import java.lang.reflect.Constructor;
18  import java.lang.reflect.Field;
19  import java.lang.reflect.InvocationTargetException;
20  import java.lang.reflect.Method;
21  import java.lang.reflect.Modifier;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Set;
26  
27  import org.djutils.reflection.TestClass.InnerPublic;
28  import org.djutils.test.UnitTest;
29  import org.junit.jupiter.api.Test;
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  public class ClassUtilTest
43  {
44      
45      @Test
46      public void testClassUtilClass()
47      {
48          assertEquals(0, ClassUtil.getClass(null).length);
49          assertEquals(String.class, ClassUtil.getClass(new Object[] {"Peter"})[0]);
50          
51          assertArrayEquals(new Class<?>[] {String.class, Double.class, Integer.class, Integer.class},
52                  ClassUtil.getClass(new Object[] {"X", 1.0d, 5, Integer.valueOf(5)}));
53          assertArrayEquals(new Class<?>[] {String.class, Double.class, null, Integer.class},
54                  ClassUtil.getClass(new Object[] {"X", 1.0d, null, 5}));
55      }
56  
57      
58  
59  
60      @Test
61      public void testToDescriptor()
62      {
63          assertEquals("I", FieldSignature.toDescriptor(int.class));
64          assertEquals("D", FieldSignature.toDescriptor(double.class));
65          assertEquals("Z", FieldSignature.toDescriptor(boolean.class));
66          assertEquals("C", FieldSignature.toDescriptor(char.class));
67          assertEquals("B", FieldSignature.toDescriptor(byte.class));
68          assertEquals("F", FieldSignature.toDescriptor(float.class));
69          assertEquals("J", FieldSignature.toDescriptor(long.class));
70          assertEquals("S", FieldSignature.toDescriptor(short.class));
71          assertEquals("[I", FieldSignature.toDescriptor(int[].class));
72          
73          assertEquals("Ljava/lang/Integer;", FieldSignature.toDescriptor(Integer.class));
74      }
75  
76      
77  
78  
79  
80      @Test
81      public void testToClass() throws ClassNotFoundException
82      {
83          assertEquals(int.class, FieldSignature.toClass("int"));
84          assertEquals(int.class, FieldSignature.toClass("I"));
85          assertEquals(double.class, FieldSignature.toClass("double"));
86          assertEquals(double.class, FieldSignature.toClass("D"));
87          assertEquals(boolean.class, FieldSignature.toClass("boolean"));
88          assertEquals(boolean.class, FieldSignature.toClass("Z"));
89          assertEquals(char.class, FieldSignature.toClass("C"));
90          assertEquals(char.class, FieldSignature.toClass("char"));
91          assertEquals(byte.class, FieldSignature.toClass("B"));
92          assertEquals(byte.class, FieldSignature.toClass("byte"));
93          assertEquals(float.class, FieldSignature.toClass("F"));
94          assertEquals(float.class, FieldSignature.toClass("float"));
95          assertEquals(long.class, FieldSignature.toClass("J"));
96          assertEquals(long.class, FieldSignature.toClass("long"));
97          assertEquals(short.class, FieldSignature.toClass("S"));
98          assertEquals(short.class, FieldSignature.toClass("short"));
99          assertEquals(int[].class, FieldSignature.toClass("[I"));
100         assertEquals(int[].class, FieldSignature.toClass("[I")); 
101         assertEquals(Integer.class, FieldSignature.toClass("Ljava/lang/Integer;"));
102         assertEquals(void.class, FieldSignature.toClass("void"));
103         assertEquals(void.class, FieldSignature.toClass("V"));
104         try
105         {
106             assertNull(FieldSignature.toClass("XXX"));
107             fail("name of non existant class should have thrown a ClassNotFoundException");
108         }
109         catch (ClassNotFoundException cnfe)
110         {
111             
112         }
113     }
114 
115     
116 
117 
118 
119     @Test
120     public void testFieldSignature() throws ClassNotFoundException
121     {
122         FieldSignature fs = new FieldSignature("[J");
123         assertEquals("[J", fs.toString());
124         assertEquals("[J", fs.getStringValue());
125         assertEquals(long[].class, fs.getClassValue());
126         FieldSignature fs2 = new FieldSignature(double[].class);
127         assertEquals("[D", fs2.toString());
128         assertEquals("[D", fs2.getStringValue());
129         assertEquals(double[].class, fs2.getClassValue());
130     }
131 
132     
133 
134 
135 
136 
137 
138     @Test
139     public void testMethodSignature() throws NoSuchMethodException, SecurityException, ClassNotFoundException
140     {
141         MethodSignature ms = new MethodSignature(String.class.getConstructor(String.class));
142         assertEquals(String.class, ms.getReturnType());
143         Class<?>[] parameterTypes = ms.getParameterTypes();
144         assertEquals(1, parameterTypes.length);
145         assertEquals(String.class, parameterTypes[0]);
146         assertEquals("Ljava/lang/String;", ms.getParameterDescriptor());
147         ms = new MethodSignature(String.class.getConstructor()); 
148         assertEquals(String.class, ms.getReturnType());
149         parameterTypes = ms.getParameterTypes();
150         assertEquals(0, parameterTypes.length);
151         ms = new MethodSignature("(I)[D");
152         assertEquals(double[].class, ms.getReturnType());
153         parameterTypes = ms.getParameterTypes();
154         assertEquals(1, parameterTypes.length);
155         assertEquals(int.class, parameterTypes[0]);
156         ms = new MethodSignature(String.class.getMethod("length"));
157         parameterTypes = ms.getParameterTypes();
158         assertEquals(0, parameterTypes.length);
159         Class<?> returnType = ms.getReturnType();
160         assertEquals(int.class, returnType);
161         Method[] methods = String.class.getMethods();
162         
163         Method substring = null;
164         for (Method m : methods)
165         {
166             if (m.getName().equals("substring") && m.getParameterCount() == 2)
167             {
168                 substring = m;
169             }
170         }
171         if (null == substring)
172         {
173             System.err.println("Could not find substring(int from, int to) method");
174         }
175         else
176         {
177             ms = new MethodSignature(substring);
178             parameterTypes = ms.getParameterTypes();
179             assertEquals(2, parameterTypes.length);
180             assertEquals(int.class, parameterTypes[0]);
181             assertEquals(int.class, parameterTypes[1]);
182             returnType = ms.getReturnType();
183             assertEquals(String.class, returnType);
184             assertEquals("II", ms.getParameterDescriptor());
185             assertEquals("Ljava/lang/String;", ms.getReturnDescriptor());
186             assertEquals("(II)Ljava/lang/String;", ms.toString());
187         }
188         ms = new MethodSignature(String.class.getMethod("getBytes"));
189         returnType = ms.getReturnType();
190         assertEquals(byte[].class, returnType);
191         ms = new MethodSignature(String.class.getConstructor(byte[].class));
192         parameterTypes = ms.getParameterTypes();
193         assertEquals(1, parameterTypes.length);
194         assertEquals(byte[].class, parameterTypes[0]);
195         assertEquals("[B", ms.getParameterDescriptor());
196     }
197 
198     
199 
200 
201 
202 
203 
204 
205 
206     @Test
207     public void testClassUtilConstructors() throws NoSuchMethodException, InstantiationException, IllegalAccessException,
208             IllegalArgumentException, InvocationTargetException
209     {
210         Constructor<TestClass> c1 = ClassUtil.resolveConstructor(TestClass.class, new Class<?>[] {});
211         TestClass o1 = c1.newInstance();
212         assertEquals("<init>", o1.getState());
213 
214         Constructor<TestClass> c2 = ClassUtil.resolveConstructor(TestClass.class, new Class<?>[] {String.class});
215         TestClass o2 = c2.newInstance("c2");
216         assertEquals("c2", o2.getState());
217 
218         Constructor<InnerPublic> c3 = ClassUtil.resolveConstructor(InnerPublic.class, new Class<?>[] {});
219         InnerPublic o3 = c3.newInstance();
220         assertEquals("<initInnerPublic>", o3.getInnerState());
221 
222         Constructor<InnerPublic> c4 = ClassUtil.resolveConstructor(InnerPublic.class, new Class<?>[] {String.class});
223         InnerPublic o4 = c4.newInstance("inner");
224         assertEquals("inner", o4.getInnerState());
225 
226         
227         Constructor<InnerPublic> c4a = ClassUtil.resolveConstructor(InnerPublic.class, new Class<?>[] {String.class});
228         InnerPublic o4a = c4a.newInstance("inner2");
229         assertEquals("inner2", o4a.getInnerState());
230 
231         
232         try
233         {
234             ClassUtil.resolveConstructor(TestClass.class, new Class<?>[] {Integer.class});
235             fail("Constructor TestClass(int) does not exist and resolving should throw an exception");
236         }
237         catch (NoSuchMethodException e)
238         {
239             
240         }
241 
242         
243         ClassUtil.resolveConstructor(TestClass.class, new Class<?>[] {boolean.class});
244         ClassUtil.resolveConstructor(TestClass.class, ClassUtilTest.class, new Class<?>[] {String.class});
245         try
246         {
247             ClassUtil.resolveConstructor(TestClass.class, ClassUtilTest.class, new Class<?>[] {boolean.class});
248             fail("Constructor TestClass(boolean) is private and resolving should throw an exception");
249         }
250         catch (IllegalAccessException e)
251         {
252             
253         }
254 
255         assertEquals(3, ClassUtil.getAllConstructors(TestClass.class).length);
256     }
257 
258     
259 
260 
261 
262 
263 
264 
265 
266     @Test
267     public void testClassUtilConstructor() throws NoSuchMethodException, InstantiationException, IllegalAccessException,
268             IllegalArgumentException, InvocationTargetException
269     {
270         Constructor<Sup>[] cArr = ClassUtil.getAllConstructors(Sup.class);
271         assertEquals(2, cArr.length);
272         
273         cArr = ClassUtil.getAllConstructors(Sup.class);
274         assertEquals(2, cArr.length);
275         Constructor<Sup> c1 = ClassUtil.resolveConstructor(Sup.class, new Class<?>[] {String.class, int.class});
276         assertNotNull(c1);
277         
278         Constructor<Sup> c1a = ClassUtil.resolveConstructor(Sup.class, new Class<?>[] {String.class, int.class});
279         assertEquals(c1, c1a);
280         Constructor<Sup> c2 = ClassUtil.resolveConstructor(Sup.class, new Object[] {"abc", 1, 2.0d});
281         assertNotNull(c2);
282         
283         Constructor<Sup> c2a = ClassUtil.resolveConstructor(Sup.class, new Object[] {"abc", 1, 2.0d});
284         assertEquals(c2, c2a);
285         Constructor<Sub> c2b = ClassUtil.resolveConstructor(Sub.class, new Object[] {"abc", 1, 2.0d});
286         assertNotEquals(c2a, c2b);
287         assertTrue(ClassUtil.isMoreSpecific(c2b, c2a));
288         
289         assertFalse(ClassUtil.isMoreSpecific(c2a, c1));
290         assertFalse(ClassUtil.isMoreSpecific(c1, c2a));
291         assertFalse(ClassUtil.isMoreSpecific(c1, c2b));
292 
293         UnitTest.testFail(new UnitTest.Execution()
294         {
295             @Override
296             public void execute() throws Throwable
297             {
298                 Constructor<Sup> cx = ClassUtil.resolveConstructor(Sup.class, new Class<?>[] {String.class, float.class});
299                 fail("illegal retrieval of constructor " + cx.toString());
300             }
301         });
302         UnitTest.testFail(new UnitTest.Execution()
303         {
304             @Override
305             public void execute() throws Throwable
306             {
307                 Constructor<Sup> cx = ClassUtil.resolveConstructor(Sup.class, new Object[] {1.2f});
308                 fail("illegal retrieval of constructor " + cx.toString());
309             }
310         });
311 
312         Sub sup = new Sub("a", 1);
313         Constructor<Sub.Inner> csi2 = ClassUtil.resolveConstructor(Sub.Inner.class, new Object[] {sup, 123L});
314         assertNotNull(csi2);
315     }
316 
317     
318 
319 
320 
321     @Test
322     public void testClassUtilField() throws NoSuchFieldException
323     {
324         Set<Field> fSet = ClassUtil.getAllFields(Sup.class);
325         removeJacoco(fSet);
326         assertEquals(7, fSet.size());
327 
328         testField(Sup.class, "staticFinalString", Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC);
329         testField(Sup.class, "finalString", Modifier.FINAL, Modifier.PUBLIC);
330         testField(Sup.class, "publicInt", Modifier.PUBLIC);
331         testField(Sup.class, "protectedLong", Modifier.PROTECTED);
332         testField(Sup.class, "packageDouble");
333         testField(Sup.class, "privateFloat", Modifier.PRIVATE);
334         testField(Sup.class, "publicSubInt", Modifier.PUBLIC);
335 
336         testField(Sub.class, "staticFinalString", Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC);
337         testField(Sub.class, "finalString", Modifier.FINAL, Modifier.PUBLIC);
338         testField(Sub.class, "publicInt", Modifier.PUBLIC);
339         testField(Sub.class, "protectedLong", Modifier.PROTECTED);
340         testField(Sub.class, "packageDouble");
341         testField(Sub.class, "privateFloat", Modifier.PRIVATE);
342         testField(Sub.class, "publicSuperInt", Modifier.PUBLIC);
343         testField(Sub.class, "publicSubInt", Modifier.PUBLIC);
344 
345         Sub sup = new Sub("a", 1);
346         testField(sup, "staticFinalString", Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC);
347         testField(sup, "finalString", Modifier.FINAL, Modifier.PUBLIC);
348         testField(sup, "publicInt", Modifier.PUBLIC);
349         testField(sup, "protectedLong", Modifier.PROTECTED);
350         testField(sup, "packageDouble");
351         testField(sup, "privateFloat", Modifier.PRIVATE);
352         testField(sup, "publicSuperInt", Modifier.PUBLIC);
353         testField(sup, "publicSubInt", Modifier.PUBLIC);
354 
355         UnitTest.testFail(new UnitTest.Execution()
356         {
357             @Override
358             public void execute() throws Throwable
359             {
360                 testField(sup, "xyz", Modifier.PUBLIC);
361             }
362         });
363         UnitTest.testFail(new UnitTest.Execution()
364         {
365             @Override
366             public void execute() throws Throwable
367             {
368                 testField(Sub.class, "xyz", Modifier.PUBLIC);
369             }
370         });
371         Field f1 = ClassUtil.resolveField(Sub.class, this.getClass(), "publicInt");
372         assertNotNull(f1);
373         UnitTest.testFail(new UnitTest.Execution()
374         {
375             @Override
376             public void execute() throws Throwable
377             {
378                 Field f2 = ClassUtil.resolveField(Sub.class, this.getClass(), "privateFloat");
379                 fail("should not be able to resolve private field " + f2);
380             }
381         });
382 
383         Sub.Inner supInn = new Sub("a", 1).new Inner(12L);
384         testField(supInn, "publicInnerLong", Modifier.PUBLIC);
385         testField(supInn, "staticFinalString", Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC);
386         testField(supInn, "finalString", Modifier.FINAL, Modifier.PUBLIC);
387         testField(supInn, "publicInt", Modifier.PUBLIC);
388         testField(supInn, "protectedLong", Modifier.PROTECTED);
389         testField(supInn, "packageDouble");
390         testField(supInn, "privateFloat", Modifier.PRIVATE);
391         testField(supInn, "publicSuperInt", Modifier.PUBLIC);
392         testField(supInn, "publicSubInt", Modifier.PUBLIC);
393 
394         UnitTest.testFail(new UnitTest.Execution()
395         {
396             @Override
397             public void execute() throws Throwable
398             {
399                 Field f3 = ClassUtil.resolveField((Class<?>) null, "publicSubInt");
400                 fail("should not be able to resolve field from null object" + f3);
401             }
402         });
403         UnitTest.testFail(new UnitTest.Execution()
404         {
405             @Override
406             public void execute() throws Throwable
407             {
408                 Field f3 = ClassUtil.resolveField(Sub.class, null);
409                 fail("should not be able to resolve field from null object" + f3);
410             }
411         });
412         UnitTest.testFail(new UnitTest.Execution()
413         {
414             @Override
415             public void execute() throws Throwable
416             {
417                 Field f3 = ClassUtil.resolveField((Object) null, "publicSubInt");
418                 fail("should not be able to resolve field from null object" + f3);
419             }
420         });
421         UnitTest.testFail(new UnitTest.Execution()
422         {
423             @Override
424             public void execute() throws Throwable
425             {
426                 Field f3 = ClassUtil.resolveField(supInn, null);
427                 fail("should not be able to resolve field from null object" + f3);
428             }
429         });
430     }
431 
432     
433 
434 
435 
436     @SuppressWarnings("checkstyle:methodlength")
437     @Test
438     public void testClassUtilMethod() throws NoSuchMethodException
439     {
440         List<Method> mList0 = ClassUtil.getAllMethods(Object.class);
441         removeJacoco(mList0);
442         List<Method> mList1 = ClassUtil.getAllMethods(Sup.class);
443         removeJacoco(mList1);
444         
445         assertEquals(mList0.size() + 12, mList1.size());
446         List<Method> mList2 = ClassUtil.getAllMethods(Sup.class, "privateVoid");
447         assertEquals(1, mList2.size());
448 
449         testMethod(Sup.class, "publicVoid", new Class<?>[] {}, Modifier.PUBLIC);
450         testMethod(Sup.class, "publicInt", new Class<?>[] {}, Modifier.PUBLIC);
451         testMethod(Sup.class, "publicArgs", new Class<?>[] {String.class, double.class}, Modifier.PUBLIC);
452         testMethod(Sup.class, "protectedVoid", new Class<?>[] {}, Modifier.PROTECTED);
453         testMethod(Sup.class, "protectedInt", new Class<?>[] {}, Modifier.PROTECTED);
454         testMethod(Sup.class, "protectedArgs", new Class<?>[] {String.class, double.class}, Modifier.PROTECTED);
455         testMethod(Sup.class, "packageVoid", new Class<?>[] {});
456         testMethod(Sup.class, "packageInt", new Class<?>[] {});
457         testMethod(Sup.class, "packageArgs", new Class<?>[] {String.class, double.class});
458         testMethod(Sup.class, "privateVoid", new Class<?>[] {}, Modifier.PRIVATE);
459         testMethod(Sup.class, "privateInt", new Class<?>[] {}, Modifier.PRIVATE);
460         testMethod(Sup.class, "privateArgs", new Class<?>[] {String.class, double.class}, Modifier.PRIVATE);
461 
462         testMethod(Sub.class, "publicVoid", new Class<?>[] {}, Modifier.PUBLIC);
463         testMethod(Sub.class, "publicInt", new Class<?>[] {}, Modifier.PUBLIC);
464         testMethod(Sub.class, "publicArgs", new Class<?>[] {String.class, double.class}, Modifier.PUBLIC);
465         testMethod(Sub.class, "publicArgs", new Class<?>[] {String.class}, Modifier.PUBLIC);
466         testMethod(Sub.class, "protectedVoid", new Class<?>[] {}, Modifier.PROTECTED);
467         testMethod(Sub.class, "protectedInt", new Class<?>[] {}, Modifier.PROTECTED);
468         testMethod(Sub.class, "protectedArgs", new Class<?>[] {String.class, double.class}, Modifier.PROTECTED);
469         testMethod(Sub.class, "packageVoid", new Class<?>[] {});
470         testMethod(Sub.class, "packageInt", new Class<?>[] {});
471         testMethod(Sub.class, "packageArgs", new Class<?>[] {String.class, double.class});
472         testMethod(Sub.class, "privateVoid", new Class<?>[] {}, Modifier.PRIVATE);
473         testMethod(Sub.class, "privateInt", new Class<?>[] {}, Modifier.PRIVATE);
474         testMethod(Sub.class, "privateArgs", new Class<?>[] {String.class, double.class}, Modifier.PRIVATE);
475 
476         Sub sup = new Sub("a", 1);
477         testMethod(sup, "publicVoid", new Class<?>[] {}, Modifier.PUBLIC);
478         testMethod(sup, "publicInt", new Class<?>[] {}, Modifier.PUBLIC);
479         testMethod(sup, "publicArgs", new Class<?>[] {String.class, double.class}, Modifier.PUBLIC);
480         testMethod(sup, "publicArgs", new Class<?>[] {String.class}, Modifier.PUBLIC);
481         testMethod(sup, "protectedVoid", new Class<?>[] {}, Modifier.PROTECTED);
482         testMethod(sup, "protectedInt", new Class<?>[] {}, Modifier.PROTECTED);
483         testMethod(sup, "protectedArgs", new Class<?>[] {String.class, double.class}, Modifier.PROTECTED);
484         testMethod(sup, "packageVoid", new Class<?>[] {});
485         testMethod(sup, "packageInt", new Class<?>[] {});
486         testMethod(sup, "packageArgs", new Class<?>[] {String.class, double.class});
487         testMethod(sup, "privateVoid", new Class<?>[] {}, Modifier.PRIVATE);
488         testMethod(sup, "privateInt", new Class<?>[] {}, Modifier.PRIVATE);
489         testMethod(sup, "privateArgs", new Class<?>[] {String.class, double.class}, Modifier.PRIVATE);
490 
491         testMethod(sup, "publicVoid", new Object[] {}, Modifier.PUBLIC);
492         testMethod(sup, "publicInt", new Object[] {}, Modifier.PUBLIC);
493         testMethod(sup, "publicArgs", new Object[] {"abc", 12.0d}, Modifier.PUBLIC);
494         testMethod(sup, "publicArgs", new Object[] {"def"}, Modifier.PUBLIC);
495         testMethod(sup, "protectedVoid", new Object[] {}, Modifier.PROTECTED);
496         testMethod(sup, "protectedInt", new Object[] {}, Modifier.PROTECTED);
497         testMethod(sup, "protectedArgs", new Object[] {"ghi", 13.0d}, Modifier.PROTECTED);
498         testMethod(sup, "packageVoid", new Object[] {});
499         testMethod(sup, "packageInt", new Object[] {});
500         testMethod(sup, "packageArgs", new Object[] {"jkl", 14.0d});
501         testMethod(sup, "privateVoid", new Object[] {}, Modifier.PRIVATE);
502         testMethod(sup, "privateInt", new Object[] {}, Modifier.PRIVATE);
503         testMethod(sup, "privateArgs", new Object[] {"mno", 15.0d}, Modifier.PRIVATE);
504 
505         UnitTest.testFail(new UnitTest.Execution()
506         {
507             @Override
508             public void execute() throws Throwable
509             {
510                 testMethod(sup, "xyz", new Class<?>[] {}, Modifier.PUBLIC);
511             }
512         });
513         UnitTest.testFail(new UnitTest.Execution()
514         {
515             @Override
516             public void execute() throws Throwable
517             {
518                 testMethod(sup, "publicArgs", new Class<?>[] {float.class}, Modifier.PUBLIC);
519             }
520         });
521         UnitTest.testFail(new UnitTest.Execution()
522         {
523             @Override
524             public void execute() throws Throwable
525             {
526                 testMethod(sup, "xyz", new Object[] {}, Modifier.PUBLIC);
527             }
528         });
529         UnitTest.testFail(new UnitTest.Execution()
530         {
531             @Override
532             public void execute() throws Throwable
533             {
534                 testMethod(sup, "publicArgs", new Object[] {12L}, Modifier.PUBLIC);
535             }
536         });
537         UnitTest.testFail(new UnitTest.Execution()
538         {
539             @Override
540             public void execute() throws Throwable
541             {
542                 testMethod(Sub.class, "xyz", new Class<?>[] {}, Modifier.PUBLIC);
543             }
544         });
545         UnitTest.testFail(new UnitTest.Execution()
546         {
547             @Override
548             public void execute() throws Throwable
549             {
550                 testMethod(Sub.class, "publicArgs", new Class<?>[] {float.class}, Modifier.PUBLIC);
551             }
552         });
553 
554         Method m1 = ClassUtil.resolveMethod(Sub.class, this.getClass(), "publicArgs", new Class<?>[] {String.class});
555         assertNotNull(m1);
556         UnitTest.testFail(new UnitTest.Execution()
557         {
558             @Override
559             public void execute() throws Throwable
560             {
561                 Method m2 = ClassUtil.resolveMethod(Sub.class, this.getClass(), "privateArgs", new Class<?>[] {});
562                 fail("should not be able to resolve private field " + m2);
563             }
564         });
565 
566         Sub.Inner supInn = new Sub("a", 1).new Inner(12L);
567         testMethod(supInn, "publicInnerMethod", new Class<?>[] {long.class}, Modifier.PUBLIC);
568         testMethod(supInn, "publicVoid", new Class<?>[] {}, Modifier.PUBLIC);
569         testMethod(supInn, "publicInt", new Class<?>[] {}, Modifier.PUBLIC);
570         testMethod(supInn, "publicArgs", new Class<?>[] {String.class, double.class}, Modifier.PUBLIC);
571         testMethod(supInn, "publicArgs", new Class<?>[] {String.class}, Modifier.PUBLIC);
572         testMethod(supInn, "protectedVoid", new Class<?>[] {}, Modifier.PROTECTED);
573         testMethod(supInn, "protectedInt", new Class<?>[] {}, Modifier.PROTECTED);
574         testMethod(supInn, "protectedArgs", new Class<?>[] {String.class, double.class}, Modifier.PROTECTED);
575         testMethod(supInn, "packageVoid", new Class<?>[] {});
576         testMethod(supInn, "packageInt", new Class<?>[] {});
577         testMethod(supInn, "packageArgs", new Class<?>[] {String.class, double.class});
578         testMethod(supInn, "privateVoid", new Class<?>[] {}, Modifier.PRIVATE);
579         testMethod(supInn, "privateInt", new Class<?>[] {}, Modifier.PRIVATE);
580         testMethod(supInn, "privateArgs", new Class<?>[] {String.class, double.class}, Modifier.PRIVATE);
581 
582         testMethod(supInn, "publicInnerMethod", new Object[] {12L}, Modifier.PUBLIC);
583         testMethod(supInn, "publicVoid", new Object[] {}, Modifier.PUBLIC);
584         testMethod(supInn, "publicInt", new Object[] {}, Modifier.PUBLIC);
585         testMethod(supInn, "publicArgs", new Object[] {"abc", 12.0d}, Modifier.PUBLIC);
586         testMethod(supInn, "publicArgs", new Object[] {"def"}, Modifier.PUBLIC);
587         testMethod(supInn, "protectedVoid", new Object[] {}, Modifier.PROTECTED);
588         testMethod(supInn, "protectedInt", new Object[] {}, Modifier.PROTECTED);
589         testMethod(supInn, "protectedArgs", new Object[] {"ghi", 13.0d}, Modifier.PROTECTED);
590         testMethod(supInn, "packageVoid", new Object[] {});
591         testMethod(supInn, "packageInt", new Object[] {});
592         testMethod(supInn, "packageArgs", new Object[] {"jkl", 14.0d});
593         testMethod(supInn, "privateVoid", new Object[] {}, Modifier.PRIVATE);
594         testMethod(supInn, "privateInt", new Object[] {}, Modifier.PRIVATE);
595         testMethod(supInn, "privateArgs", new Object[] {"mno", 15.0d}, Modifier.PRIVATE);
596 
597         UnitTest.testFail(new UnitTest.Execution()
598         {
599             @Override
600             public void execute() throws Throwable
601             {
602                 Method m3 = ClassUtil.resolveMethod((Class<?>) null, "publicInt", new Class<?>[] {});
603                 fail("should not be able to resolve field from null object" + m3);
604             }
605         });
606         UnitTest.testFail(new UnitTest.Execution()
607         {
608             @Override
609             public void execute() throws Throwable
610             {
611                 Method m3 = ClassUtil.resolveMethod(Sub.class, null, new Class<?>[] {});
612                 fail("should not be able to resolve field from null object" + m3);
613             }
614         });
615         UnitTest.testFail(new UnitTest.Execution()
616         {
617             @Override
618             public void execute() throws Throwable
619             {
620                 Method m3 = ClassUtil.resolveMethod((Object) null, "publicInt", new Class<?>[] {});
621                 fail("should not be able to resolve field from null object" + m3);
622             }
623         });
624         UnitTest.testFail(new UnitTest.Execution()
625         {
626             @Override
627             public void execute() throws Throwable
628             {
629                 Method m3 = ClassUtil.resolveMethod(supInn, null, new Class<?>[] {});
630                 fail("should not be able to resolve field from null object" + m3);
631             }
632         });
633         UnitTest.testFail(new UnitTest.Execution()
634         {
635             @Override
636             public void execute() throws Throwable
637             {
638                 Method m3 = ClassUtil.resolveMethod((Object) null, "publicInt", new Object[] {});
639                 fail("should not be able to resolve field from null object" + m3);
640             }
641         });
642         UnitTest.testFail(new UnitTest.Execution()
643         {
644             @Override
645             public void execute() throws Throwable
646             {
647                 Method m3 = ClassUtil.resolveMethod(supInn, null, new Object[] {});
648                 fail("should not be able to resolve field from null object" + m3);
649             }
650         });
651     }
652 
653     
654 
655 
656     @Test
657     public void testClassUtilAnnotation()
658     {
659         Set<Annotation> aSet0 = ClassUtil.getAllAnnotations(Sub.class);
660         assertEquals(2, aSet0.size());
661 
662         Annotation a1 = ClassUtil.resolveAnnotation(Sub.class, AnnTag.class);
663         assertNotNull(a1);
664         UnitTest.testFail(new UnitTest.Execution()
665         {
666             @Override
667             public void execute() throws Throwable
668             {
669                 Annotation a3 = ClassUtil.resolveAnnotation(Sup.class, AnnTag.class);
670                 fail("should not be able to resolve non-existing annotation " + a3);
671             }
672         });
673         UnitTest.testFail(new UnitTest.Execution()
674         {
675             @Override
676             public void execute() throws Throwable
677             {
678                 Annotation a3 = ClassUtil.resolveAnnotation(null, AnnTag.class);
679                 fail("should not be able to resolve non-existing annotation " + a3);
680             }
681         });
682         UnitTest.testFail(new UnitTest.Execution()
683         {
684             @Override
685             public void execute() throws Throwable
686             {
687                 Annotation a3 = ClassUtil.resolveAnnotation(Sub.class, null);
688                 fail("should not be able to resolve non-existing annotation " + a3);
689             }
690         });
691 
692         Annotation a4 = ClassUtil.resolveAnnotation(Sub.Inner.class, AnnTag.class);
693         assertNotNull(a4);
694 
695         AnnString a5 = (AnnString) ClassUtil.resolveAnnotation(Sub.class, AnnString.class);
696         assertNotNull(a5);
697         assertEquals("avalue", a5.value());
698     }
699 
700     
701 
702 
703 
704     private void removeJacoco(final Set<Field> fields)
705     {
706         for (Iterator<Field> it = fields.iterator(); it.hasNext();)
707         {
708             Field field = it.next();
709             if (field.getName().contains("jacoco"))
710             {
711                 it.remove();
712             }
713         }
714     }
715 
716     
717 
718 
719 
720 
721 
722     protected void testField(final Class<?> clazz, final String fieldName, final int... modifiers) throws NoSuchFieldException
723     {
724         Field field = ClassUtil.resolveField(clazz, fieldName);
725         assertNotNull(field);
726         assertEquals(fieldName, field.getName());
727         Set<Integer> mSet = new HashSet<>();
728         for (int m : modifiers)
729         {
730             assertTrue((field.getModifiers() & m) != 0,
731                     "failed modifier for field " + clazz.getSimpleName() + "." + fieldName + " for modifier " + m);
732             mSet.add(m);
733         }
734         for (int p = 0; p < 12; p++)
735         {
736             int m = 1 << p;
737             if (!mSet.contains(m))
738             {
739                 assertTrue((field.getModifiers() & m) == 0,
740                         "failed modifier for field " + clazz.getSimpleName() + "." + fieldName + " for bit " + p);
741             }
742         }
743     }
744 
745     
746 
747 
748 
749 
750 
751     protected void testField(final Object object, final String fieldName, final int... modifiers) throws NoSuchFieldException
752     {
753         Field field = ClassUtil.resolveField(object, fieldName);
754         assertNotNull(field);
755         assertEquals(fieldName, field.getName());
756         Set<Integer> mSet = new HashSet<>();
757         for (int m : modifiers)
758         {
759             assertTrue((field.getModifiers() & m) != 0,
760                     "failed modifier for field " + object.getClass().getSimpleName() + "." + fieldName + " for modifier " + m);
761             mSet.add(m);
762         }
763         for (int p = 0; p < 12; p++)
764         {
765             int m = 1 << p;
766             if (!mSet.contains(m))
767             {
768                 assertTrue((field.getModifiers() & m) == 0,
769                         "failed modifier for field " + object.getClass().getSimpleName() + "." + fieldName + " for bit " + p);
770             }
771         }
772     }
773 
774     
775 
776 
777 
778     private void removeJacoco(final List<Method> methods)
779     {
780         for (Iterator<Method> it = methods.iterator(); it.hasNext();)
781         {
782             Method method = it.next();
783             if (method.getName().contains("jacoco"))
784             {
785                 it.remove();
786             }
787         }
788     }
789 
790     
791 
792 
793 
794 
795 
796 
797     protected void testMethod(final Class<?> clazz, final String methodName, final Class<?>[] params, final int... modifiers)
798             throws NoSuchMethodException
799     {
800         Method method = ClassUtil.resolveMethod(clazz, methodName, params);
801         assertNotNull(method);
802         assertEquals(methodName, method.getName());
803         Set<Integer> mSet = new HashSet<>();
804         for (int m : modifiers)
805         {
806             assertTrue((method.getModifiers() & m) != 0,
807                     "failed modifier for method " + clazz.getSimpleName() + "." + methodName + " for modifier " + m);
808             mSet.add(m);
809         }
810         for (int p = 0; p < 12; p++)
811         {
812             int m = 1 << p;
813             if (!mSet.contains(m))
814             {
815                 assertTrue((method.getModifiers() & m) == 0,
816                         "failed modifier for method " + clazz.getSimpleName() + "." + methodName + " for bit " + p);
817             }
818         }
819     }
820 
821     
822 
823 
824 
825 
826 
827 
828     protected void testMethod(final Object object, final String methodName, final Class<?>[] params, final int... modifiers)
829             throws NoSuchMethodException
830     {
831         Method method = ClassUtil.resolveMethod(object, methodName, params);
832         assertNotNull(method);
833         assertEquals(methodName, method.getName());
834         Set<Integer> mSet = new HashSet<>();
835         for (int m : modifiers)
836         {
837             assertTrue((method.getModifiers() & m) != 0, "failed modifier for method " + object.getClass().getSimpleName() + "."
838                     + methodName + " for modifier " + m);
839             mSet.add(m);
840         }
841         for (int p = 0; p < 12; p++)
842         {
843             int m = 1 << p;
844             if (!mSet.contains(m))
845             {
846                 assertTrue((method.getModifiers() & m) == 0,
847                         "failed modifier for method " + object.getClass().getSimpleName() + "." + methodName + " for bit " + p);
848             }
849         }
850     }
851 
852     
853 
854 
855 
856 
857 
858 
859     protected void testMethod(final Object object, final String methodName, final Object[] args, final int... modifiers)
860             throws NoSuchMethodException
861     {
862         Method method = ClassUtil.resolveMethod(object, methodName, args);
863         assertNotNull(method);
864         assertEquals(methodName, method.getName());
865         Set<Integer> mSet = new HashSet<>();
866         for (int m : modifiers)
867         {
868             assertTrue((method.getModifiers() & m) != 0, "failed modifier for method " + object.getClass().getSimpleName() + "."
869                     + methodName + " for modifier " + m);
870             mSet.add(m);
871         }
872         for (int p = 0; p < 12; p++)
873         {
874             int m = 1 << p;
875             if (!mSet.contains(m))
876             {
877                 assertTrue((method.getModifiers() & m) == 0,
878                         "failed modifier for method " + object.getClass().getSimpleName() + "." + methodName + " for bit " + p);
879             }
880         }
881     }
882 
883     
884     @SuppressWarnings("unused")
885     protected static class Sup
886     {
887         
888         @SuppressWarnings({"checkstyle:visibilitymodifier", "checkstyle:constantname"})
889         public static final String staticFinalString = "ABC";
890 
891         
892         @SuppressWarnings("checkstyle:visibilitymodifier")
893         public final String finalString = "DEF";
894 
895         
896         @SuppressWarnings("checkstyle:visibilitymodifier")
897         private float privateFloat = 8.0f;
898 
899         
900         @SuppressWarnings("checkstyle:visibilitymodifier")
901         double packageDouble = 4.0d;
902 
903         
904         @SuppressWarnings("checkstyle:visibilitymodifier")
905         protected long protectedLong = 2L;
906 
907         
908         @SuppressWarnings("checkstyle:visibilitymodifier")
909         public int publicInt = 1;
910 
911         
912         @SuppressWarnings("checkstyle:visibilitymodifier")
913         public int publicSubInt = 21;
914 
915         
916 
917 
918 
919 
920         public Sup(final String s, final int i, final double d)
921         {
922             
923         }
924 
925         
926 
927 
928 
929         public Sup(final String s, final int i)
930         {
931             
932         }
933 
934         
935         private void privateVoid()
936         {
937             
938         }
939 
940         
941         void packageVoid()
942         {
943             
944         }
945 
946         
947         protected void protectedVoid()
948         {
949             
950         }
951 
952         
953         public void publicVoid()
954         {
955             
956         }
957 
958         
959 
960 
961         private int privateInt()
962         {
963             return 1;
964         }
965 
966         
967 
968 
969         int packageInt()
970         {
971             return 2;
972         }
973 
974         
975 
976 
977         protected int protectedInt()
978         {
979             return 3;
980         }
981 
982         
983 
984 
985         public int publicInt()
986         {
987             return 4;
988         }
989 
990         
991 
992 
993 
994         private void privateArgs(final String s, final double d)
995         {
996             
997         }
998 
999         
1000 
1001 
1002 
1003         void packageArgs(final String s, final double d)
1004         {
1005             
1006         }
1007 
1008         
1009 
1010 
1011 
1012         protected void protectedArgs(final String s, final double d)
1013         {
1014             
1015         }
1016 
1017         
1018 
1019 
1020 
1021         public void publicArgs(final String s, final double d)
1022         {
1023             
1024         }
1025     }
1026 
1027     
1028     @SuppressWarnings({"hiding", "unused"})
1029     @AnnTag
1030     @AnnString("avalue")
1031     protected static class Sub extends Sup
1032     {
1033         
1034         @SuppressWarnings({"checkstyle:visibilitymodifier", "checkstyle:constantname"})
1035         public static final String staticFinalString = "ABC";
1036 
1037         
1038         @SuppressWarnings("checkstyle:visibilitymodifier")
1039         public final String finalString = "DEF";
1040 
1041         
1042         @SuppressWarnings("checkstyle:visibilitymodifier")
1043         private float privateFloat = 8.0f;
1044 
1045         
1046         @SuppressWarnings("checkstyle:visibilitymodifier")
1047         double packageDouble = 4.0d;
1048 
1049         
1050         @SuppressWarnings("checkstyle:visibilitymodifier")
1051         protected long protectedLong = 2L;
1052 
1053         
1054         @SuppressWarnings("checkstyle:visibilitymodifier")
1055         public int publicInt = 1;
1056 
1057         
1058         @SuppressWarnings("checkstyle:visibilitymodifier")
1059         public int publicSuperInt = 11;
1060 
1061         
1062 
1063 
1064 
1065 
1066         public Sub(final String s, final int i, final double d)
1067         {
1068             super(s, i, d);
1069         }
1070 
1071         
1072 
1073 
1074 
1075         public Sub(final String s, final int i)
1076         {
1077             super(s, i);
1078         }
1079 
1080         
1081         private void privateVoid()
1082         {
1083             
1084         }
1085 
1086         @Override
1087         void packageVoid()
1088         {
1089             
1090         }
1091 
1092         @Override
1093         protected void protectedVoid()
1094         {
1095             
1096         }
1097 
1098         @Override
1099         public void publicVoid()
1100         {
1101             
1102         }
1103 
1104         
1105 
1106 
1107         private int privateInt()
1108         {
1109             return 1;
1110         }
1111 
1112         @Override
1113         int packageInt()
1114         {
1115             return 2;
1116         }
1117 
1118         @Override
1119         protected int protectedInt()
1120         {
1121             return 3;
1122         }
1123 
1124         @Override
1125         public int publicInt()
1126         {
1127             return 4;
1128         }
1129 
1130         
1131 
1132 
1133 
1134         private void privateArgs(final String s, final double d)
1135         {
1136             
1137         }
1138 
1139         @Override
1140         void packageArgs(final String s, final double d)
1141         {
1142             
1143         }
1144 
1145         @Override
1146         protected void protectedArgs(final String s, final double d)
1147         {
1148             
1149         }
1150 
1151         @Override
1152         public void publicArgs(final String s, final double d)
1153         {
1154             
1155         }
1156 
1157         
1158 
1159 
1160         public void publicArgs(final String s)
1161         {
1162             
1163         }
1164 
1165         
1166         @AnnTag
1167         public class Inner
1168         {
1169             
1170 
1171 
1172             Inner(final long l)
1173             {
1174                 
1175             }
1176 
1177             
1178             @SuppressWarnings("checkstyle:visibilitymodifier")
1179             public long publicInnerLong = 123L;
1180 
1181             
1182 
1183 
1184             public void publicInnerMethod(final long l)
1185             {
1186                 
1187             }
1188         }
1189     }
1190 
1191     
1192     @Target(ElementType.TYPE)
1193     @Retention(RetentionPolicy.RUNTIME)
1194     public @interface AnnTag
1195     {
1196         
1197     }
1198 
1199     
1200     @Target(ElementType.TYPE)
1201     @Retention(RetentionPolicy.RUNTIME)
1202     public @interface AnnString
1203     {
1204         
1205         String value();
1206     }
1207 
1208 }