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
240 ClassFinder classFinder = new ClassFinder(
241 new And(new MainCodeResourcePathFilter(),
242 new TestFileNameFilter()),
243 new Not((FileNameFilter)new TestFileNameFilter()),
244 new And(new PublicClassFilter(),
245 new Not(new TestClassFilter()),
246 new Not(new GeneratedClassFilter()),
247 new Not(new IsInterfaceStabilityClassFilter()),
248 new Not(new InterfaceAudienceAnnotatedClassFilter()),
249 new Not(new CloverInstrumentationFilter()))
250 );
251
252 Set<Class<?>> classes = classFinder.findClasses(false);
253
254 LOG.info("These are the classes that DO NOT have @InterfaceAudience annotation:");
255 for (Class<?> clazz : classes) {
256 LOG.info(clazz);
257 }
258
259 Assert.assertEquals("All classes should have @InterfaceAudience annotation",
260 0, classes.size());
261 }
262
263
264
265
266
267 @Test
268 public void testInterfaceStabilityAnnotation()
269 throws ClassNotFoundException, IOException, LinkageError {
270
271
272
273
274
275
276
277
278
279 ClassFinder classFinder = new ClassFinder(
280 new And(new MainCodeResourcePathFilter(),
281 new TestFileNameFilter()),
282 new Not((FileNameFilter)new TestFileNameFilter()),
283 new And(new PublicClassFilter(),
284 new Not(new TestClassFilter()),
285 new Not(new GeneratedClassFilter()),
286 new InterfaceAudiencePublicAnnotatedClassFilter(),
287 new Not(new IsInterfaceStabilityClassFilter()),
288 new Not(new InterfaceStabilityAnnotatedClassFilter()))
289 );
290
291 Set<Class<?>> classes = classFinder.findClasses(false);
292
293 LOG.info("These are the classes that DO NOT have @InterfaceStability annotation:");
294 for (Class<?> clazz : classes) {
295 LOG.info(clazz);
296 }
297
298 Assert.assertEquals("All classes that are marked with @InterfaceAudience.Public should "
299 + "have @InterfaceStability annotation as well",
300 0, classes.size());
301 }
302 }