1 package org.oxerr.spring.cache.redis.scored.score.resolver.annotated.impl; 2 3 import static org.junit.jupiter.api.Assertions.assertEquals; 4 import static org.junit.jupiter.api.Assertions.assertNotNull; 5 import static org.junit.jupiter.api.Assertions.assertThrows; 6 7 import java.lang.annotation.Annotation; 8 import java.lang.reflect.Field; 9 import java.sql.Timestamp; 10 import java.time.Instant; 11 import java.time.LocalDate; 12 import java.util.Map; 13 import java.util.Optional; 14 15 import org.apache.commons.lang3.SerializationUtils; 16 import org.apache.commons.lang3.reflect.FieldUtils; 17 import org.junit.jupiter.api.Test; 18 import org.oxerr.spring.cache.redis.scored.score.resolver.annotated.AnnotatedScoreResolver; 19 import org.oxerr.spring.cache.redis.scored.score.resolver.annotated.annotation.Score; 20 import org.springframework.core.annotation.Order; 21 22 class AnnotatedScoreResolverTest { 23 24 private final AnnotatedScoreResolver scoreResolver = new AnnotatedScoreResolver(Score.class); 25 26 @Test 27 void testSerialization() throws IllegalArgumentException, IllegalAccessException { 28 scoreResolver.resolveScore(new Object() { 29 }); 30 31 Field annotatedElementsField = FieldUtils.getDeclaredField(scoreResolver.getClass(), "annotatedElements", true); 32 Field annotationTypeField = FieldUtils.getDeclaredField(scoreResolver.getClass(), "annotationType", true); 33 34 @SuppressWarnings("unchecked") 35 Map<Class<?>, ?> annotatedElementsBefore = (Map<Class<?>, ?>) annotatedElementsField.get(scoreResolver); 36 @SuppressWarnings("unchecked") 37 Class<? extends Annotation> annotationTypeBefore = (Class<? extends Annotation>) annotationTypeField.get(scoreResolver); 38 39 assertNotNull(annotatedElementsBefore); 40 assertNotNull(annotationTypeBefore); 41 42 assertEquals(1, annotatedElementsBefore.size()); 43 44 AnnotatedScoreResolver deserialized = SerializationUtils.roundtrip(scoreResolver); 45 46 @SuppressWarnings("unchecked") 47 Map<Class<?>, ?> annotatedElementsAfter = (Map<Class<?>, ?>) annotatedElementsField.get(deserialized); 48 @SuppressWarnings("unchecked") 49 Class<? extends Annotation> annotationTypeAfter = (Class<? extends Annotation>) annotationTypeField.get(deserialized); 50 51 assertNotNull(annotatedElementsAfter); 52 assertNotNull(annotationTypeAfter); 53 54 assertEquals(0, annotatedElementsAfter.size()); 55 56 assertEquals(annotationTypeBefore, annotationTypeAfter); 57 } 58 59 @Test 60 void testResolveScoreNull() { 61 assertEquals(Optional.empty(), scoreResolver.resolveScore(null)); 62 } 63 64 @Test 65 void testResolveScoreFromMethod() { 66 assertEquals(1, scoreResolver.resolveScore(new Object() { 67 68 @Score 69 private long getVersion() { 70 return 1L; 71 } 72 73 }).get().longValue()); 74 } 75 76 @Test 77 void testResolveScoreFromMethodFirst() { 78 assertEquals(2, scoreResolver.resolveScore(new Object() { 79 80 @Score 81 private long version = 1L; 82 83 @Score 84 private long getVersion() { 85 return 2L; 86 } 87 88 }).get().longValue()); 89 } 90 91 @Test 92 void testResolveScoreFromMethodNullAndFieldGiveUp() { 93 assertEquals(Optional.empty(), this.scoreResolver.resolveScore(new Object() { 94 95 @Score 96 private long version = 1; 97 98 @Score 99 private Long getVersion2() { 100 return null; 101 } 102 103 })); 104 } 105 106 @Test 107 void testResolveScoreFromField() { 108 assertEquals(1, scoreResolver.resolveScore(new Object() { 109 110 @Score 111 private long version = 1L; 112 113 }).get().longValue()); 114 } 115 116 @Test 117 void testResolveScoreFromMethodOrder() { 118 assertEquals(1L, this.scoreResolver.resolveScore(new Object() { 119 120 @Score 121 @Order(0) 122 private long getVersion() { 123 return 1L; 124 } 125 126 @Score 127 @Order(1) 128 private long getVersion2() { 129 return 2L; 130 } 131 132 }).get().longValue()); 133 } 134 135 @Test 136 void testResolveScoreFromFieldOrder() { 137 assertEquals(1L, this.scoreResolver.resolveScore(new Object() { 138 139 @Score 140 @Order(0) 141 private long version = 1L; 142 143 @Score 144 @Order(1) 145 private long version2 = 2L; 146 147 }).get().longValue()); 148 } 149 150 @Test 151 void testResolveScoreOrderDefault() { 152 assertEquals(2L, this.scoreResolver.resolveScore(new Object() { 153 154 @Score 155 private long version = 1L; 156 157 @Score 158 @Order(1) 159 private long version2 = 2L; 160 161 }).get().longValue()); 162 } 163 164 @Test 165 void testResolveScoreTypeTimestamp() { 166 Timestamp now = Timestamp.from(Instant.now()); 167 assertEquals( 168 Double.parseDouble(String.format("%d.%d", now.getTime(), now.getNanos())), 169 this.scoreResolver.resolveScore(new Object() { 170 171 @Score 172 private Timestamp version = now; 173 174 }).get() 175 ); 176 } 177 178 @Test 179 void testResolveScoreTypeInstant() { 180 Instant now = Instant.now(); 181 assertEquals( 182 Double.parseDouble(String.format("%d.%d", now.toEpochMilli(), now.getNano())), 183 this.scoreResolver.resolveScore(new Object() { 184 185 @Score 186 private Instant version = now; 187 188 }).get() 189 ); 190 } 191 192 @Test 193 void testResolveScoreTypeUnsupported() { 194 Object o = new Object() { 195 196 @Score 197 private LocalDate version = LocalDate.now(); 198 199 }; 200 assertThrows(IllegalArgumentException.class, () -> this.scoreResolver.resolveScore(o)); 201 } 202 203 }