1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.commons.utils;
18
19 import static org.apache.juneau.commons.utils.AnnotationUtils.hash;
20 import static org.apache.juneau.commons.utils.AnnotationUtils.streamRepeated;
21 import static org.junit.jupiter.api.Assertions.*;
22
23 import java.lang.annotation.*;
24 import java.util.List;
25 import java.util.stream.Collectors;
26
27 import org.junit.jupiter.api.*;
28
29 class AnnotationUtils_Test {
30
31
32
33
34 @Test
35 void a00_constructor() {
36
37
38 var instance = new AnnotationUtils();
39 assertNotNull(instance);
40 }
41
42
43
44
45 @Target({ElementType.TYPE, ElementType.METHOD})
46 @Retention(RetentionPolicy.RUNTIME)
47 @interface SimpleAnnotation {
48 String value() default "";
49 }
50
51 @SimpleAnnotation("test")
52 static class TestClass1 {}
53
54 @SimpleAnnotation("test")
55 static class TestClass2 {}
56
57 @SimpleAnnotation("different")
58 static class TestClass3 {}
59
60 @Target({ElementType.TYPE, ElementType.METHOD})
61 @Retention(RetentionPolicy.RUNTIME)
62 @interface DifferentAnnotation {
63 String value() default "";
64 }
65
66 @DifferentAnnotation("test")
67 static class TestClass4 {}
68
69 @Target({ElementType.TYPE, ElementType.METHOD})
70 @Retention(RetentionPolicy.RUNTIME)
71 @interface MultiMemberAnnotation {
72 String name() default "";
73 int count() default 0;
74 boolean active() default false;
75 }
76
77 @MultiMemberAnnotation(name = "test", count = 5, active = true)
78 static class TestClass5 {}
79
80 @MultiMemberAnnotation(name = "test", count = 5, active = true)
81 static class TestClass6 {}
82
83 @MultiMemberAnnotation(name = "test", count = 5, active = false)
84 static class TestClass7 {}
85
86 @MultiMemberAnnotation(name = "different", count = 5, active = true)
87 static class TestClass8 {}
88
89 @MultiMemberAnnotation(name = "test", count = 10, active = true)
90 static class TestClass9 {}
91
92 @Target({ElementType.TYPE, ElementType.METHOD})
93 @Retention(RetentionPolicy.RUNTIME)
94 @interface ArrayAnnotation {
95 String[] values() default {};
96 int[] numbers() default {};
97 }
98
99 @ArrayAnnotation(values = {"a", "b", "c"}, numbers = {1, 2, 3})
100 static class TestClass10 {}
101
102 @ArrayAnnotation(values = {"a", "b", "c"}, numbers = {1, 2, 3})
103 static class TestClass11 {}
104
105 @ArrayAnnotation(values = {"a", "b"}, numbers = {1, 2, 3})
106 static class TestClass12 {}
107
108 @ArrayAnnotation(values = {"a", "b", "c"}, numbers = {1, 2})
109 static class TestClass13 {}
110
111 @ArrayAnnotation(values = {"a", "b", "d"}, numbers = {1, 2, 3})
112 static class TestClass14 {}
113
114 @ArrayAnnotation(values = {"a", "b", "c"}, numbers = {1, 2, 4})
115 static class TestClass15 {}
116
117 @ArrayAnnotation
118 static class TestClass16 {}
119
120 @Target({ElementType.TYPE, ElementType.METHOD})
121 @Retention(RetentionPolicy.RUNTIME)
122 @interface PrimitiveArrayAnnotation {
123 byte[] bytes() default {};
124 short[] shorts() default {};
125 long[] longs() default {};
126 float[] floats() default {};
127 double[] doubles() default {};
128 char[] chars() default {};
129 boolean[] booleans() default {};
130 }
131
132 @PrimitiveArrayAnnotation(
133 bytes = {1, 2, 3},
134 shorts = {10, 20},
135 longs = {100L, 200L},
136 floats = {1.0f, 2.0f},
137 doubles = {1.0, 2.0},
138 chars = {'a', 'b'},
139 booleans = {true, false}
140 )
141 static class TestClass17 {}
142
143 @PrimitiveArrayAnnotation(
144 bytes = {1, 2, 3},
145 shorts = {10, 20},
146 longs = {100L, 200L},
147 floats = {1.0f, 2.0f},
148 doubles = {1.0, 2.0},
149 chars = {'a', 'b'},
150 booleans = {true, false}
151 )
152 static class TestClass18 {}
153
154 @PrimitiveArrayAnnotation(
155 bytes = {1, 2, 4},
156 shorts = {10, 20},
157 longs = {100L, 200L},
158 floats = {1.0f, 2.0f},
159 doubles = {1.0, 2.0},
160 chars = {'a', 'b'},
161 booleans = {true, false}
162 )
163 static class TestClass19 {}
164
165 @Target({ElementType.TYPE, ElementType.METHOD})
166 @Retention(RetentionPolicy.RUNTIME)
167 @interface NestedAnnotation {
168 SimpleAnnotation nested() default @SimpleAnnotation;
169 }
170
171 @Target({ElementType.TYPE, ElementType.METHOD})
172 @Retention(RetentionPolicy.RUNTIME)
173 @interface NestedArrayAnnotation {
174 SimpleAnnotation[] nested() default {};
175 }
176
177 @NestedAnnotation(nested = @SimpleAnnotation("test"))
178 static class TestClass20 {}
179
180 @NestedAnnotation(nested = @SimpleAnnotation("test"))
181 static class TestClass21 {}
182
183 @NestedAnnotation(nested = @SimpleAnnotation("different"))
184 static class TestClass22 {}
185
186 @NestedArrayAnnotation(nested = {@SimpleAnnotation("a"), @SimpleAnnotation("b")})
187 static class TestClass23 {}
188
189 @NestedArrayAnnotation(nested = {@SimpleAnnotation("a"), @SimpleAnnotation("b")})
190 static class TestClass24 {}
191
192 @NestedArrayAnnotation(nested = {@SimpleAnnotation("a"), @SimpleAnnotation("c")})
193 static class TestClass25 {}
194
195 @Target({ElementType.TYPE, ElementType.METHOD})
196 @Retention(RetentionPolicy.RUNTIME)
197 @interface EmptyAnnotation {
198 }
199
200 @EmptyAnnotation
201 static class TestClass26 {}
202
203 @Target({ElementType.TYPE, ElementType.METHOD})
204 @Retention(RetentionPolicy.RUNTIME)
205 @interface DefaultValueAnnotation {
206 String value() default "default";
207 int count() default 42;
208 }
209
210 @DefaultValueAnnotation
211 static class TestClass27 {}
212
213 @DefaultValueAnnotation(value = "default", count = 42)
214 static class TestClass28 {}
215
216 @Target({ElementType.TYPE, ElementType.METHOD})
217 @Retention(RetentionPolicy.RUNTIME)
218 @interface NullableMemberAnnotation {
219 String value() default "default";
220 }
221
222 @NullableMemberAnnotation
223 static class TestClass29 {}
224
225 @Target({ElementType.TYPE, ElementType.METHOD})
226 @Retention(RetentionPolicy.RUNTIME)
227 @interface MemberEqualsTestAnnotation {
228 String value() default "test";
229 }
230
231 @MemberEqualsTestAnnotation
232 static class TestClass31 {}
233
234 @Test
235 void a001_equals() {
236
237 var a1 = TestClass1.class.getAnnotation(SimpleAnnotation.class);
238 assertTrue(AnnotationUtils.equals(a1, a1));
239
240
241 var a2 = TestClass2.class.getAnnotation(SimpleAnnotation.class);
242 assertTrue(AnnotationUtils.equals(a1, a2));
243
244
245 var a3 = TestClass3.class.getAnnotation(SimpleAnnotation.class);
246 assertFalse(AnnotationUtils.equals(a1, a3));
247
248
249 assertTrue(AnnotationUtils.equals(null, null));
250
251
252 assertFalse(AnnotationUtils.equals(null, a1));
253
254
255 assertFalse(AnnotationUtils.equals(a1, null));
256
257
258 var a4 = TestClass4.class.getAnnotation(DifferentAnnotation.class);
259 assertFalse(AnnotationUtils.equals(a1, a4));
260
261
262 var a5 = TestClass5.class.getAnnotation(MultiMemberAnnotation.class);
263 var a6 = TestClass6.class.getAnnotation(MultiMemberAnnotation.class);
264 assertTrue(AnnotationUtils.equals(a5, a6));
265
266
267 var a7 = TestClass7.class.getAnnotation(MultiMemberAnnotation.class);
268 assertFalse(AnnotationUtils.equals(a5, a7));
269
270
271 var a8 = TestClass8.class.getAnnotation(MultiMemberAnnotation.class);
272 assertFalse(AnnotationUtils.equals(a5, a8));
273
274
275 var a9 = TestClass9.class.getAnnotation(MultiMemberAnnotation.class);
276 assertFalse(AnnotationUtils.equals(a5, a9));
277
278
279 var a10 = TestClass10.class.getAnnotation(ArrayAnnotation.class);
280 var a11 = TestClass11.class.getAnnotation(ArrayAnnotation.class);
281 assertTrue(AnnotationUtils.equals(a10, a11));
282
283
284 var a12 = TestClass12.class.getAnnotation(ArrayAnnotation.class);
285 assertFalse(AnnotationUtils.equals(a10, a12));
286
287
288 var a13 = TestClass13.class.getAnnotation(ArrayAnnotation.class);
289 assertFalse(AnnotationUtils.equals(a10, a13));
290
291
292 var a14 = TestClass14.class.getAnnotation(ArrayAnnotation.class);
293 assertFalse(AnnotationUtils.equals(a10, a14));
294
295
296 var a15 = TestClass15.class.getAnnotation(ArrayAnnotation.class);
297 assertFalse(AnnotationUtils.equals(a10, a15));
298
299
300 var a16 = TestClass16.class.getAnnotation(ArrayAnnotation.class);
301 var a16b = TestClass16.class.getAnnotation(ArrayAnnotation.class);
302 assertTrue(AnnotationUtils.equals(a16, a16b));
303
304
305 var a17 = TestClass17.class.getAnnotation(PrimitiveArrayAnnotation.class);
306 var a18 = TestClass18.class.getAnnotation(PrimitiveArrayAnnotation.class);
307 assertTrue(AnnotationUtils.equals(a17, a18));
308
309
310 var a19 = TestClass19.class.getAnnotation(PrimitiveArrayAnnotation.class);
311 assertFalse(AnnotationUtils.equals(a17, a19));
312
313
314 var a20 = TestClass20.class.getAnnotation(NestedAnnotation.class);
315 var a21 = TestClass21.class.getAnnotation(NestedAnnotation.class);
316 assertTrue(AnnotationUtils.equals(a20, a21));
317
318
319 var a22 = TestClass22.class.getAnnotation(NestedAnnotation.class);
320 assertFalse(AnnotationUtils.equals(a20, a22));
321
322
323 var a23 = TestClass23.class.getAnnotation(NestedArrayAnnotation.class);
324 var a24 = TestClass24.class.getAnnotation(NestedArrayAnnotation.class);
325 assertTrue(AnnotationUtils.equals(a23, a24));
326
327
328 var a25 = TestClass25.class.getAnnotation(NestedArrayAnnotation.class);
329 assertFalse(AnnotationUtils.equals(a23, a25));
330
331
332 var a27 = TestClass27.class.getAnnotation(DefaultValueAnnotation.class);
333 var a28 = TestClass28.class.getAnnotation(DefaultValueAnnotation.class);
334 assertTrue(AnnotationUtils.equals(a27, a28));
335
336
337 try {
338 var a29 = TestClass29.class.getAnnotation(NullableMemberAnnotation.class);
339
340
341 Annotation nullMember1 = (Annotation) java.lang.reflect.Proxy.newProxyInstance(
342 MemberEqualsTestAnnotation.class.getClassLoader(),
343 new Class<?>[] { MemberEqualsTestAnnotation.class },
344 (proxy, method, args) -> {
345 if (method.getName().equals("value")) {
346 return null;
347 }
348 if (method.getName().equals("annotationType")) {
349 return MemberEqualsTestAnnotation.class;
350 }
351 if (method.getName().equals("toString")) {
352 return "@MemberEqualsTestAnnotation(null)";
353 }
354 if (method.getName().equals("hashCode")) {
355 return 0;
356 }
357 if (method.getName().equals("equals")) {
358 return proxy == args[0];
359 }
360 return method.invoke(a29, args);
361 }
362 );
363
364
365 Annotation nonNullMember = (Annotation) java.lang.reflect.Proxy.newProxyInstance(
366 MemberEqualsTestAnnotation.class.getClassLoader(),
367 new Class<?>[] { MemberEqualsTestAnnotation.class },
368 (proxy, method, args) -> {
369 if (method.getName().equals("value")) {
370 return "test";
371 }
372 if (method.getName().equals("annotationType")) {
373 return MemberEqualsTestAnnotation.class;
374 }
375 if (method.getName().equals("toString")) {
376 return "@MemberEqualsTestAnnotation(test)";
377 }
378 if (method.getName().equals("hashCode")) {
379 return 0;
380 }
381 if (method.getName().equals("equals")) {
382 return proxy == args[0];
383 }
384 return method.invoke(a29, args);
385 }
386 );
387
388
389 assertFalse(AnnotationUtils.equals(nullMember1, nonNullMember));
390 assertFalse(AnnotationUtils.equals(nonNullMember, nullMember1));
391 } catch (Exception e) {
392
393 }
394 }
395
396
397
398
399 @Test
400 void a002_hash() {
401
402 var a1 = TestClass1.class.getAnnotation(SimpleAnnotation.class);
403 var a2 = TestClass2.class.getAnnotation(SimpleAnnotation.class);
404 assertEquals(hash(a1), hash(a2));
405
406
407 var a3 = TestClass3.class.getAnnotation(SimpleAnnotation.class);
408 assertNotEquals(hash(a1), hash(a3));
409
410
411 var a5 = TestClass5.class.getAnnotation(MultiMemberAnnotation.class);
412 var a6 = TestClass6.class.getAnnotation(MultiMemberAnnotation.class);
413 assertEquals(hash(a5), hash(a6));
414
415
416 var a10 = TestClass10.class.getAnnotation(ArrayAnnotation.class);
417 var a11 = TestClass11.class.getAnnotation(ArrayAnnotation.class);
418 assertEquals(hash(a10), hash(a11));
419
420
421 var a17 = TestClass17.class.getAnnotation(PrimitiveArrayAnnotation.class);
422 var a18 = TestClass18.class.getAnnotation(PrimitiveArrayAnnotation.class);
423 assertEquals(hash(a17), hash(a18));
424
425
426 var a20 = TestClass20.class.getAnnotation(NestedAnnotation.class);
427 var a21 = TestClass21.class.getAnnotation(NestedAnnotation.class);
428 assertEquals(hash(a20), hash(a21));
429
430
431 var a23 = TestClass23.class.getAnnotation(NestedArrayAnnotation.class);
432 var a24 = TestClass24.class.getAnnotation(NestedArrayAnnotation.class);
433 assertEquals(hash(a23), hash(a24));
434
435
436 assertTrue(AnnotationUtils.equals(a1, a2));
437 assertEquals(hash(a1), hash(a2));
438 assertTrue(AnnotationUtils.equals(a5, a6));
439 assertEquals(hash(a5), hash(a6));
440 assertTrue(AnnotationUtils.equals(a10, a11));
441 assertEquals(hash(a10), hash(a11));
442
443
444 var a26 = TestClass26.class.getAnnotation(EmptyAnnotation.class);
445 int hashCode = hash(a26);
446 assertTrue(hashCode >= 0 || hashCode < 0);
447
448
449 var a27 = TestClass27.class.getAnnotation(DefaultValueAnnotation.class);
450 var a28 = TestClass28.class.getAnnotation(DefaultValueAnnotation.class);
451 assertTrue(AnnotationUtils.equals(a27, a28));
452 assertEquals(hash(a27), hash(a28));
453
454
455 try {
456 var a29 = TestClass29.class.getAnnotation(NullableMemberAnnotation.class);
457
458
459 Annotation nullMemberAnnotation = (Annotation) java.lang.reflect.Proxy.newProxyInstance(
460 NullableMemberAnnotation.class.getClassLoader(),
461 new Class<?>[] { NullableMemberAnnotation.class },
462 (proxy, method, args) -> {
463 if (method.getName().equals("value")) {
464 return null;
465 }
466 if (method.getName().equals("annotationType")) {
467 return NullableMemberAnnotation.class;
468 }
469 if (method.getName().equals("toString")) {
470 return "@NullableMemberAnnotation(null)";
471 }
472 if (method.getName().equals("hashCode")) {
473 return 0;
474 }
475 if (method.getName().equals("equals")) {
476 return proxy == args[0];
477 }
478 return method.invoke(a29, args);
479 }
480 );
481
482
483 int hashNull = hash(nullMemberAnnotation);
484
485 assertTrue(hashNull != 0 || hashNull == 0);
486 } catch (Exception e) {
487
488 }
489 }
490
491
492
493
494 @Test
495 void a003_streamRepeated() {
496
497 var a1 = TestClass1.class.getAnnotation(SimpleAnnotation.class);
498 List<Annotation> result1 = streamRepeated(a1).collect(Collectors.toList());
499 assertEquals(1, result1.size());
500 assertSame(a1, result1.get(0));
501
502
503 var a26 = TestClass26.class.getAnnotation(EmptyAnnotation.class);
504 List<Annotation> result2 = streamRepeated(a26).collect(Collectors.toList());
505 assertEquals(1, result2.size());
506 assertSame(a26, result2.get(0));
507
508
509 var a5 = TestClass5.class.getAnnotation(MultiMemberAnnotation.class);
510 List<Annotation> result3 = streamRepeated(a5).collect(Collectors.toList());
511 assertEquals(1, result3.size());
512 assertSame(a5, result3.get(0));
513 }
514 }
515