1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.io.IOException;
22 import java.lang.annotation.Annotation;
23 import java.lang.reflect.Modifier;
24 import java.util.Set;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.hbase.classification.InterfaceAudience;
29 import org.apache.hadoop.hbase.classification.InterfaceStability;
30 import org.apache.hadoop.hbase.testclassification.SmallTests;
31 import org.apache.hadoop.hbase.ClassFinder.And;
32 import org.apache.hadoop.hbase.ClassFinder.FileNameFilter;
33 import org.apache.hadoop.hbase.ClassFinder.Not;
34 import org.apache.hadoop.hbase.ClassTestFinder.TestClassFilter;
35 import org.apache.hadoop.hbase.ClassTestFinder.TestFileNameFilter;
36 import org.junit.Assert;
37 import org.junit.Test;
38 import org.junit.experimental.categories.Category;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 @Category(SmallTests.class)
60 public class TestInterfaceAudienceAnnotations {
61
62 private static final Log LOG = LogFactory.getLog(TestInterfaceAudienceAnnotations.class);
63
64
65 class GeneratedClassFilter implements ClassFinder.ClassFilter {
66 @Override
67 public boolean isCandidateClass(Class<?> c) {
68 return c.getPackage().getName().contains("generated");
69 }
70 }
71
72
73
74
75 class InterfaceAudienceAnnotatedClassFilter implements ClassFinder.ClassFilter {
76 @Override
77 public boolean isCandidateClass(Class<?> c) {
78 if (getAnnotation(c) != null) {
79
80 return true;
81 }
82
83
84
85 return isAnnotatedPrivate(c.getEnclosingClass());
86 }
87
88 private boolean isAnnotatedPrivate(Class<?> c) {
89 if (c == null) {
90 return false;
91 }
92
93 Class<?> ann = getAnnotation(c);
94 if (ann != null &&
95 !InterfaceAudience.Public.class.equals(ann)) {
96 return true;
97 }
98
99 return isAnnotatedPrivate(c.getEnclosingClass());
100 }
101
102 protected Class<?> getAnnotation(Class<?> c) {
103
104 Annotation[] anns = c.getDeclaredAnnotations();
105
106 for (Annotation ann : anns) {
107
108
109 Class<?> type = ann.annotationType();
110 if (isInterfaceAudienceClass(type)) {
111 return type;
112 }
113 }
114 return null;
115 }
116 }
117
118
119
120
121 class InterfaceStabilityAnnotatedClassFilter implements ClassFinder.ClassFilter {
122 @Override
123 public boolean isCandidateClass(Class<?> c) {
124 if (getAnnotation(c) != null) {
125
126 return true;
127 }
128 return false;
129 }
130
131 protected Class<?> getAnnotation(Class<?> c) {
132
133 Annotation[] anns = c.getDeclaredAnnotations();
134
135 for (Annotation ann : anns) {
136
137
138 Class<?> type = ann.annotationType();
139 if (isInterfaceStabilityClass(type)) {
140 return type;
141 }
142 }
143 return null;
144 }
145 }
146
147
148
149
150 class InterfaceAudiencePublicAnnotatedClassFilter extends InterfaceAudienceAnnotatedClassFilter {
151 @Override
152 public boolean isCandidateClass(Class<?> c) {
153 return (InterfaceAudience.Public.class.equals(getAnnotation(c)));
154 }
155 }
156
157
158
159
160 class IsInterfaceStabilityClassFilter implements ClassFinder.ClassFilter {
161 @Override
162 public boolean isCandidateClass(Class<?> c) {
163 return
164 isInterfaceAudienceClass(c) ||
165 isInterfaceStabilityClass(c);
166 }
167 }
168
169 private boolean isInterfaceAudienceClass(Class<?> c) {
170 return
171 c.equals(InterfaceAudience.Public.class) ||
172 c.equals(InterfaceAudience.Private.class) ||
173 c.equals(InterfaceAudience.LimitedPrivate.class);
174 }
175
176 private boolean isInterfaceStabilityClass(Class<?> c) {
177 return
178 c.equals(InterfaceStability.Stable.class) ||
179 c.equals(InterfaceStability.Unstable.class) ||
180 c.equals(InterfaceStability.Evolving.class);
181 }
182
183
184 class PublicClassFilter implements ClassFinder.ClassFilter {
185 @Override
186 public boolean isCandidateClass(Class<?> c) {
187 int mod = c.getModifiers();
188 return Modifier.isPublic(mod);
189 }
190 }
191
192
193 class MainCodeResourcePathFilter implements ClassFinder.ResourcePathFilter {
194 @Override
195 public boolean isCandidatePath(String resourcePath, boolean isJar) {
196 return !resourcePath.contains("test-classes") &&
197 !resourcePath.contains("tests.jar");
198 }
199 }
200
201
202
203
204
205
206
207
208
209
210 class CloverInstrumentationFilter implements ClassFinder.ClassFilter {
211 @Override
212 public boolean isCandidateClass(Class<?> clazz) {
213 boolean clover = false;
214 final Class<?> enclosing = clazz.getEnclosingClass();
215 if (enclosing != null) {
216 if (!(enclosing.isInterface())) {
217 clover = clazz.getSimpleName().startsWith("__CLR");
218 }
219 }
220 return clover;
221 }
222 }
223
224
225
226
227
228 @Test
229 public void testInterfaceAudienceAnnotation()
230 throws ClassNotFoundException, IOException, LinkageError {
231
232
233
234
235
236
237
238
239 ClassFinder classFinder = new ClassFinder(
240 new MainCodeResourcePathFilter(),
241 new Not((FileNameFilter)new TestFileNameFilter()),
242 new And(new PublicClassFilter(),
243 new Not(new TestClassFilter()),
244 new Not(new GeneratedClassFilter()),
245 new Not(new IsInterfaceStabilityClassFilter()),
246 new Not(new InterfaceAudienceAnnotatedClassFilter()),
247 new Not(new CloverInstrumentationFilter()))
248 );
249
250 Set<Class<?>> classes = classFinder.findClasses(false);
251
252 LOG.info("These are the classes that DO NOT have @InterfaceAudience annotation:");
253 for (Class<?> clazz : classes) {
254 LOG.info(clazz);
255 }
256
257 Assert.assertEquals("All classes should have @InterfaceAudience annotation",
258 0, classes.size());
259 }
260
261
262
263
264
265 @Test
266 public void testInterfaceStabilityAnnotation()
267 throws ClassNotFoundException, IOException, LinkageError {
268
269
270
271
272
273
274
275
276 ClassFinder classFinder = new ClassFinder(
277 new MainCodeResourcePathFilter(),
278 new Not((FileNameFilter)new TestFileNameFilter()),
279 new And(new PublicClassFilter(),
280 new Not(new TestClassFilter()),
281 new Not(new GeneratedClassFilter()),
282 new InterfaceAudiencePublicAnnotatedClassFilter(),
283 new Not(new IsInterfaceStabilityClassFilter()),
284 new Not(new InterfaceStabilityAnnotatedClassFilter()))
285 );
286
287 Set<Class<?>> classes = classFinder.findClasses(false);
288
289 LOG.info("These are the classes that DO NOT have @InterfaceStability annotation:");
290 for (Class<?> clazz : classes) {
291 LOG.info(clazz);
292 }
293
294 Assert.assertEquals("All classes that are marked with @InterfaceAudience.Public should "
295 + "have @InterfaceStability annotation as well",
296 0, classes.size());
297 }
298 }