1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.commons.reflect;
18
19 import static java.lang.annotation.ElementType.*;
20 import static java.lang.annotation.RetentionPolicy.*;
21 import static org.apache.juneau.commons.reflect.ConstructorInfo.*;
22 import static org.apache.juneau.commons.utils.CollectionUtils.*;
23 import static org.junit.jupiter.api.Assertions.*;
24
25 import java.lang.annotation.*;
26 import java.lang.reflect.*;
27 import java.util.*;
28 import java.util.function.*;
29 import java.util.stream.*;
30
31 import org.apache.juneau.*;
32 import org.junit.jupiter.api.*;
33
34 class ConstructorInfo_Test extends TestBase {
35
36 private static void check(String expected, Object o) {
37 assertEquals(expected, TO_STRING.apply(o));
38 }
39
40 private static final Function<Object,String> TO_STRING = new Function<>() {
41 @Override
42 public String apply(Object t) {
43 if (t == null)
44 return null;
45 if (t instanceof Iterable)
46 return StreamSupport.stream(((Iterable<?>)t).spliterator(), false).map(this).collect(Collectors.joining(","));
47 if (t instanceof ClassInfo)
48 return ((ClassInfo)t).getNameSimple();
49 if (t instanceof ConstructorInfo)
50 return ((ConstructorInfo)t).getShortName();
51 if (t instanceof Constructor)
52 return ConstructorInfo.of((Constructor<?>)t).getShortName();
53 return t.toString();
54 }
55 };
56
57 private static ConstructorInfo ofc(Class<?> c, Class<?>...pt) {
58 try {
59 return of(c.getConstructor(pt));
60 } catch (NoSuchMethodException | SecurityException e) {
61 fail(e.getLocalizedMessage());
62 }
63 return null;
64 }
65
66
67
68
69
70 static class A {
71 public A() {}
72 }
73 static ConstructorInfo a = ofc(A.class);
74
75 public static class B {
76 private String f;
77 public B() {}
78 public B(String f) {
79 this.f = f;
80 }
81 public B(String f, String f2) {
82 this.f = f;
83 }
84 protected B(int f) {}
85 @Override
86 public String toString() {
87 return f;
88 }
89 }
90 static ClassInfo b = ClassInfo.of(B.class);
91 static ConstructorInfo
92 b_c1 = b.getPublicConstructor(cons -> cons.getParameterCount() == 0).get(),
93 b_c2 = b.getPublicConstructor(x -> x.hasParameterTypes(String.class)).get(),
94 b_c3 = b.getDeclaredConstructor(x -> x.hasParameterTypes(int.class)).get(),
95 b_c4 = b.getPublicConstructor(x -> x.hasParameterTypes(String.class, String.class)).get();
96
97 @Target({CONSTRUCTOR})
98 @Retention(RUNTIME)
99 public static @interface TestAnnotation {
100 String value() default "";
101 }
102
103 @Target({CONSTRUCTOR})
104 @Retention(RUNTIME)
105 public static @interface DeprecatedAnnotation {}
106
107 public static class DeprecatedClass {
108 @Deprecated
109 public DeprecatedClass() {}
110 }
111
112 public static class VarArgsClass {
113 public VarArgsClass(String...args) {}
114 }
115
116 public static class ExceptionClass {
117 public ExceptionClass() throws Exception {}
118 }
119
120 public static class EqualsTestClass {
121 public EqualsTestClass() {}
122 public EqualsTestClass(String param) {}
123 }
124
125
126
127
128 @Test
129 void a001_accessible() throws Exception {
130
131 b_c3.accessible();
132 assertEquals(null, b_c3.newInstanceLenient(123).toString());
133
134
135 var result = b_c3.accessible();
136 assertSame(b_c3, result);
137 }
138
139
140
141
142 @Test
143 void a002_canAccept() {
144
145 assertTrue(b_c2.canAccept("test"));
146 assertFalse(b_c2.canAccept(123));
147 assertFalse(b_c2.canAccept("test", "extra"));
148
149
150 assertTrue(b_c1.canAccept());
151 assertFalse(b_c1.canAccept("test"));
152
153
154 assertTrue(b_c4.canAccept("test1", "test2"));
155 assertFalse(b_c4.canAccept("test1"));
156 }
157
158
159
160
161 @Test
162 void a003_compareTo() {
163 var s = new TreeSet<>(l(b_c1, b_c2, b_c3, b_c4, a));
164 check("A(),B(),B(int),B(String),B(String,String)", s);
165 }
166
167
168
169
170 @Test
171 void a004_getAnnotatedExceptionTypes() {
172 var ci = ClassInfo.of(ExceptionClass.class);
173 var ctor = ci.getPublicConstructor(x -> x.getParameterCount() == 0).get();
174 var types = ctor.getAnnotatedExceptionTypes();
175 assertNotNull(types);
176 assertEquals(1, types.length);
177 assertEquals(Exception.class, types[0].getType());
178 }
179
180
181
182
183 @Test
184 void a005_getAnnotatedParameterTypes() {
185 var types = b_c2.getAnnotatedParameterTypes();
186 assertNotNull(types);
187 assertEquals(1, types.length);
188 assertEquals(String.class, types[0].getType());
189 }
190
191
192
193
194 @Test
195 void a006_getAnnotatedReceiverType() {
196
197 var receiverType = b_c1.getAnnotatedReceiverType();
198 assertNull(receiverType);
199 }
200
201
202
203
204 @Test
205 void a007_getAnnotatableType() {
206 assertEquals(AnnotatableType.CONSTRUCTOR_TYPE, b_c1.getAnnotatableType());
207 }
208
209
210
211
212 @Test
213 void a008_getDeclaredAnnotations() {
214 var annotations = b_c1.getDeclaredAnnotations();
215 assertNotNull(annotations);
216
217 assertTrue(annotations.isEmpty());
218 }
219
220
221
222
223 @Test
224 void a009_getDeclaredAnnotations_typed() {
225 var annotations = b_c1.getDeclaredAnnotations(TestAnnotation.class);
226 assertNotNull(annotations);
227 assertEquals(0, annotations.count());
228 }
229
230
231
232
233 @Test
234 void a010_getDeclaringClass() {
235 check("A", a.getDeclaringClass());
236 check("B", b_c1.getDeclaringClass());
237 }
238
239
240
241
242 @Test
243 void a011_getExceptionTypes() {
244 var ci = ClassInfo.of(ExceptionClass.class);
245 var ctor = ci.getPublicConstructor(x -> x.getParameterCount() == 0).get();
246 var exceptions = ctor.getExceptionTypes();
247 assertNotNull(exceptions);
248 assertEquals(1, exceptions.size());
249 assertEquals(Exception.class, exceptions.get(0).inner());
250 }
251
252
253
254
255 @Test
256 void a012_getFullName() {
257 var fullName = b_c2.getFullName();
258 assertNotNull(fullName);
259 assertTrue(fullName.contains("B"));
260 assertTrue(fullName.contains("String"));
261 }
262
263
264
265
266 @Test
267 void a013_getLabel() {
268 var label = b_c1.getLabel();
269 assertNotNull(label);
270 assertTrue(label.contains("B"));
271 assertTrue(label.contains("()"));
272 }
273
274
275
276
277 @Test
278 void a014_getParameter() {
279 var param = b_c2.getParameter(0);
280 assertNotNull(param);
281 assertEquals(String.class, param.getParameterType().inner());
282
283
284 assertThrows(IndexOutOfBoundsException.class, () -> b_c2.getParameter(1));
285 assertThrows(IndexOutOfBoundsException.class, () -> b_c1.getParameter(0));
286 }
287
288
289
290
291 @Test
292 void a015_getParameterCount() {
293 assertEquals(0, b_c1.getParameterCount());
294 assertEquals(1, b_c2.getParameterCount());
295 assertEquals(2, b_c4.getParameterCount());
296 }
297
298
299
300
301 @Test
302 void a016_getParameters() {
303 var params = b_c2.getParameters();
304 assertNotNull(params);
305 assertEquals(1, params.size());
306 assertEquals(String.class, params.get(0).getParameterType().inner());
307
308
309 int[] count = {0};
310 b_c4.getParameters().stream().filter(x -> true).forEach(x -> count[0]++);
311 assertEquals(2, count[0]);
312 }
313
314
315
316
317 @Test
318 void a017_getShortName() {
319 check("A()", a);
320 check("B()", b_c1);
321 check("B(String)", b_c2);
322 check("B(String,String)", b_c4);
323 }
324
325
326
327
328 @Test
329 void a018_getSimpleName() {
330 assertEquals("A", a.getSimpleName());
331 assertEquals("B", b_c1.getSimpleName());
332 }
333
334
335
336
337 @Test
338 void a019_getTypeParameters() {
339 var typeParams = b_c1.getTypeParameters();
340 assertNotNull(typeParams);
341 assertEquals(0, typeParams.length);
342 }
343
344
345
346
347 @Test
348 void a020_hasAnnotation() {
349 assertFalse(b_c1.hasAnnotation(TestAnnotation.class));
350 }
351
352
353
354
355 @Test
356 void a021_hasAnyName_collection() {
357 assertTrue(b_c1.hasAnyName(Arrays.asList("B", "C")));
358 assertFalse(b_c1.hasAnyName(Arrays.asList("C", "D")));
359 }
360
361
362
363
364 @Test
365 void a022_hasAnyName_varargs() {
366 assertTrue(b_c1.hasAnyName("B", "C"));
367 assertFalse(b_c1.hasAnyName("C", "D"));
368 }
369
370
371
372
373 @Test
374 void a023_hasMatchingParameters() {
375 var params1 = b_c2.getParameters();
376 assertTrue(b_c2.hasMatchingParameters(params1));
377
378 var params2 = b_c4.getParameters();
379 assertFalse(b_c2.hasMatchingParameters(params2));
380 }
381
382
383
384
385 @Test
386 void a024_hasName() {
387 assertTrue(b_c1.hasName("B"));
388 assertFalse(b_c1.hasName("A"));
389 }
390
391
392
393
394 @Test
395 void a025_hasNumParameters() {
396 assertTrue(b_c1.hasNumParameters(0));
397 assertTrue(b_c2.hasNumParameters(1));
398 assertFalse(b_c1.hasNumParameters(1));
399 }
400
401
402
403
404 @Test
405 void a026_hasParameters() {
406 assertFalse(b_c1.hasParameters());
407 assertTrue(b_c2.hasParameters());
408 }
409
410
411
412
413 @Test
414 void a027_hasParameterTypeParents_class() {
415
416 assertTrue(b_c2.hasParameterTypeParents(String.class));
417
418 assertFalse(b_c2.hasParameterTypeParents(Object.class));
419 assertFalse(b_c2.hasParameterTypeParents(Integer.class));
420 }
421
422
423
424
425 @Test
426 void a028_hasParameterTypeParents_classInfo() {
427 var stringClass = ClassInfo.of(String.class);
428 var objectClass = ClassInfo.of(Object.class);
429 var integerClass = ClassInfo.of(Integer.class);
430 assertTrue(b_c2.hasParameterTypeParents(stringClass));
431 assertFalse(b_c2.hasParameterTypeParents(objectClass));
432 assertFalse(b_c2.hasParameterTypeParents(integerClass));
433 }
434
435
436
437
438 @Test
439 void a029_hasParameterTypes_class() {
440 assertTrue(b_c2.hasParameterTypes(String.class));
441 assertFalse(b_c2.hasParameterTypes(Integer.class));
442 assertFalse(b_c2.hasParameterTypes(String.class, String.class));
443 }
444
445
446
447
448 @Test
449 void a030_hasParameterTypes_classInfo() {
450 var stringClass = ClassInfo.of(String.class);
451 var integerClass = ClassInfo.of(Integer.class);
452 assertTrue(b_c2.hasParameterTypes(stringClass));
453 assertFalse(b_c2.hasParameterTypes(integerClass));
454 }
455
456
457
458
459 @Test
460 void a031_hasParameterTypesLenient_class() {
461
462 assertTrue(b_c2.hasParameterTypesLenient(String.class));
463
464 assertFalse(b_c2.hasParameterTypesLenient(Object.class));
465 assertFalse(b_c2.hasParameterTypesLenient(Integer.class));
466 }
467
468
469
470
471 @Test
472 void a032_hasParameterTypesLenient_classInfo() {
473 var stringClass = ClassInfo.of(String.class);
474 var objectClass = ClassInfo.of(Object.class);
475 var integerClass = ClassInfo.of(Integer.class);
476 assertTrue(b_c2.hasParameterTypesLenient(stringClass));
477 assertFalse(b_c2.hasParameterTypesLenient(objectClass));
478 assertFalse(b_c2.hasParameterTypesLenient(integerClass));
479 }
480
481
482
483
484 @Test
485 void a033_inner() {
486 var ctor = b_c1.inner();
487 assertNotNull(ctor);
488 assertEquals(B.class, ctor.getDeclaringClass());
489 }
490
491
492
493
494 @Test
495 void a034_is() {
496 assertTrue(b_c1.is(ElementFlag.CONSTRUCTOR));
497 assertFalse(b_c1.is(ElementFlag.NOT_CONSTRUCTOR));
498 assertTrue(b_c1.is(ElementFlag.HAS_NO_PARAMS));
499 assertFalse(b_c1.is(ElementFlag.HAS_PARAMS));
500 assertTrue(b_c2.is(ElementFlag.HAS_PARAMS));
501 assertFalse(b_c2.is(ElementFlag.HAS_NO_PARAMS));
502 }
503
504
505
506
507 @Test
508 void a035_isAccessible() {
509
510 var privateBefore = b_c3.isAccessible();
511
512
513 b_c3.setAccessible();
514
515
516 var privateAfter = b_c3.isAccessible();
517
518
519 assertTrue(privateAfter || !privateBefore, "After setAccessible(), isAccessible() should return true (Java 9+) or false (Java 8)");
520
521
522 var publicAccessible = b_c1.isAccessible();
523 assertNotNull(publicAccessible);
524 }
525
526
527
528
529 @Test
530 void a036_isAll() {
531 assertTrue(b_c1.isAll(ElementFlag.CONSTRUCTOR, ElementFlag.HAS_NO_PARAMS));
532 assertFalse(b_c1.isAll(ElementFlag.CONSTRUCTOR, ElementFlag.HAS_PARAMS));
533 }
534
535
536
537
538 @Test
539 void a037_isAny() {
540 assertTrue(b_c1.isAny(ElementFlag.CONSTRUCTOR, ElementFlag.HAS_PARAMS));
541 assertFalse(b_c1.isAny(ElementFlag.HAS_PARAMS, ElementFlag.SYNTHETIC));
542 }
543
544
545
546
547 @Test
548 void a038_isConstructor() {
549 assertTrue(b_c1.isConstructor());
550 }
551
552
553
554
555 @Test
556 void a039_isDeprecated() {
557 var ci = ClassInfo.of(DeprecatedClass.class);
558 var ctor = ci.getPublicConstructor(x -> x.getParameterCount() == 0).get();
559 assertTrue(ctor.isDeprecated());
560 assertFalse(b_c1.isDeprecated());
561 }
562
563
564
565
566 @Test
567 void a040_isNotDeprecated() {
568 var ci = ClassInfo.of(DeprecatedClass.class);
569 var ctor = ci.getPublicConstructor(x -> x.getParameterCount() == 0).get();
570 assertFalse(ctor.isNotDeprecated());
571 assertTrue(b_c1.isNotDeprecated());
572 }
573
574
575
576
577 @Test
578 void a041_isSynthetic() {
579
580 assertFalse(b_c1.isSynthetic());
581 }
582
583
584
585
586 @Test
587 void a042_isVarArgs() {
588 var ci = ClassInfo.of(VarArgsClass.class);
589 var ctor = ci.getPublicConstructor(x -> x.hasParameterTypes(String[].class)).get();
590 assertTrue(ctor.isVarArgs());
591 assertFalse(b_c1.isVarArgs());
592 }
593
594
595
596
597 @Test
598 void a043_isVisible() {
599
600 assertTrue(b_c1.isVisible(Visibility.PUBLIC));
601 assertTrue(b_c1.isVisible(Visibility.PROTECTED));
602 assertTrue(b_c1.isVisible(Visibility.PRIVATE));
603 assertTrue(b_c1.isVisible(Visibility.DEFAULT));
604
605
606 assertFalse(b_c3.isVisible(Visibility.PUBLIC));
607 assertTrue(b_c3.isVisible(Visibility.PROTECTED));
608 assertTrue(b_c3.isVisible(Visibility.PRIVATE));
609 assertTrue(b_c3.isVisible(Visibility.DEFAULT));
610 }
611
612
613
614
615 @Test
616 void a044_newInstance() throws Exception {
617 assertEquals(null, b_c1.newInstance().toString());
618 assertEquals("foo", b_c2.newInstance("foo").toString());
619 }
620
621
622
623
624 @Test
625 void a045_newInstanceLenient() throws Exception {
626 assertEquals(null, b_c1.newInstanceLenient().toString());
627 assertEquals("foo", b_c2.newInstanceLenient("foo").toString());
628 }
629
630
631
632
633 @Test
634 void a046_of_withDeclaringClass() {
635 check("A()", ConstructorInfo.of(ClassInfo.of(A.class), a.inner()));
636 }
637
638
639
640
641 @Test
642 void a047_of_noDeclaringClass() {
643 check("A()", a.inner());
644
645
646 assertThrows(IllegalArgumentException.class, () -> ConstructorInfo.of((Constructor<?>)null));
647 assertThrows(IllegalArgumentException.class, () -> ConstructorInfo.of((ClassInfo)null, null));
648 }
649
650
651
652
653 @Test
654 void a048_parameterMatchesLenientCount_class() {
655
656 assertEquals(1, b_c2.parameterMatchesLenientCount(String.class));
657
658 assertEquals(-1, b_c2.parameterMatchesLenientCount(Object.class));
659
660 assertEquals(-1, b_c2.parameterMatchesLenientCount(Integer.class));
661 }
662
663
664
665
666 @Test
667 void a049_parameterMatchesLenientCount_classInfo() {
668 var stringClass = ClassInfo.of(String.class);
669 var objectClass = ClassInfo.of(Object.class);
670 var integerClass = ClassInfo.of(Integer.class);
671
672 assertEquals(1, b_c2.parameterMatchesLenientCount(stringClass));
673
674 assertEquals(-1, b_c2.parameterMatchesLenientCount(objectClass));
675 assertEquals(-1, b_c2.parameterMatchesLenientCount(integerClass));
676 }
677
678
679
680
681 @Test
682 void a050_parameterMatchesLenientCount_object() {
683
684 assertEquals(1, b_c2.parameterMatchesLenientCount("test"));
685
686
687
688 assertEquals(-1, b_c2.parameterMatchesLenientCount(new Object()));
689 assertEquals(-1, b_c2.parameterMatchesLenientCount(123));
690 }
691
692
693
694
695 @Test
696 void a051_setAccessible() throws Exception {
697
698 var result = b_c3.setAccessible();
699 assertTrue(result);
700 assertEquals(null, b_c3.newInstanceLenient(123).toString());
701 }
702
703
704
705
706 @Test
707 void a052_toGenericString() {
708 var str = b_c2.toGenericString();
709 assertNotNull(str);
710 assertTrue(str.contains("B"));
711 assertTrue(str.contains("String"));
712 }
713
714
715
716
717 @Test
718 void a053_toString() {
719 check("A()", a.toString());
720 check("B()", b_c1.toString());
721 check("B(String)", b_c2.toString());
722 }
723
724
725
726
727 @Test
728 void a054_equals_hashCode() throws Exception {
729
730 Constructor<?> c1 = EqualsTestClass.class.getConstructor();
731 ConstructorInfo ci1a = ConstructorInfo.of(c1);
732 ConstructorInfo ci1b = ConstructorInfo.of(c1);
733
734 Constructor<?> c2 = EqualsTestClass.class.getConstructor(String.class);
735 ConstructorInfo ci2 = ConstructorInfo.of(c2);
736
737
738 assertEquals(ci1a, ci1b);
739 assertEquals(ci1a.hashCode(), ci1b.hashCode());
740
741
742 assertNotEquals(ci1a, ci2);
743 assertNotEquals(ci1a, null);
744 assertNotEquals(ci1a, "not a ConstructorInfo");
745
746
747 assertEquals(ci1a, ci1a);
748
749
750 assertEquals(ci1a, ci1b);
751 assertEquals(ci1b, ci1a);
752
753
754 ConstructorInfo ci1c = ConstructorInfo.of(c1);
755 assertEquals(ci1a, ci1b);
756 assertEquals(ci1b, ci1c);
757 assertEquals(ci1a, ci1c);
758
759
760 Map<ConstructorInfo, String> map = new HashMap<>();
761 map.put(ci1a, "value1");
762 assertEquals("value1", map.get(ci1b));
763 assertEquals("value1", map.get(ci1c));
764
765
766 map.put(ci2, "value2");
767 assertEquals("value2", map.get(ci2));
768 assertNotEquals("value2", map.get(ci1a));
769
770
771 Set<ConstructorInfo> set = new HashSet<>();
772 set.add(ci1a);
773 assertTrue(set.contains(ci1b));
774 assertTrue(set.contains(ci1c));
775 assertFalse(set.contains(ci2));
776 }
777 }
778