Java
116 строк · 4.4 Кб
1/*
2* Copyright (C) 2008 The Guava Authors
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17package com.google.common.collect.testing.features;
18
19import java.lang.annotation.Annotation;
20import java.lang.annotation.Inherited;
21import java.lang.annotation.Retention;
22import java.lang.annotation.RetentionPolicy;
23import java.lang.reflect.Method;
24import java.util.Locale;
25import junit.framework.TestCase;
26
27/**
28* Since annotations have some reusability issues that force copy and paste all over the place, it's
29* worth having a test to ensure that all our Feature enums have their annotations correctly set up.
30*
31* @author George van den Driessche
32*/
33public class FeatureEnumTest extends TestCase {
34private static void assertGoodTesterAnnotation(Class<? extends Annotation> annotationClass) {
35assertNotNull(
36rootLocaleFormat("%s must be annotated with @TesterAnnotation.", annotationClass),
37annotationClass.getAnnotation(TesterAnnotation.class));
38final Retention retentionPolicy = annotationClass.getAnnotation(Retention.class);
39assertNotNull(
40rootLocaleFormat("%s must have a @Retention annotation.", annotationClass),
41retentionPolicy);
42assertEquals(
43rootLocaleFormat("%s must have RUNTIME RetentionPolicy.", annotationClass),
44RetentionPolicy.RUNTIME,
45retentionPolicy.value());
46assertNotNull(
47rootLocaleFormat("%s must be inherited.", annotationClass),
48annotationClass.getAnnotation(Inherited.class));
49
50for (String propertyName : new String[] {"value", "absent"}) {
51Method method = null;
52try {
53method = annotationClass.getMethod(propertyName);
54} catch (NoSuchMethodException e) {
55fail(
56rootLocaleFormat("%s must have a property named '%s'.", annotationClass, propertyName));
57}
58final Class<?> returnType = method.getReturnType();
59assertTrue(
60rootLocaleFormat("%s.%s() must return an array.", annotationClass, propertyName),
61returnType.isArray());
62assertSame(
63rootLocaleFormat(
64"%s.%s() must return an array of %s.",
65annotationClass, propertyName, annotationClass.getDeclaringClass()),
66annotationClass.getDeclaringClass(),
67returnType.getComponentType());
68}
69}
70
71// This is public so that tests for Feature enums we haven't yet imagined
72// can reuse it.
73public static <E extends Enum<?> & Feature<?>> void assertGoodFeatureEnum(
74Class<E> featureEnumClass) {
75final Class<?>[] classes = featureEnumClass.getDeclaredClasses();
76for (Class<?> containedClass : classes) {
77if (containedClass.getSimpleName().equals("Require")) {
78if (containedClass.isAnnotation()) {
79assertGoodTesterAnnotation(asAnnotation(containedClass));
80} else {
81fail(
82rootLocaleFormat(
83"Feature enum %s contains a class named "
84+ "'Require' but it is not an annotation.",
85featureEnumClass));
86}
87return;
88}
89}
90fail(
91rootLocaleFormat(
92"Feature enum %s should contain an " + "annotation named 'Require'.",
93featureEnumClass));
94}
95
96@SuppressWarnings("unchecked")
97private static Class<? extends Annotation> asAnnotation(Class<?> clazz) {
98if (clazz.isAnnotation()) {
99return (Class<? extends Annotation>) clazz;
100} else {
101throw new IllegalArgumentException(rootLocaleFormat("%s is not an annotation.", clazz));
102}
103}
104
105public void testFeatureEnums() throws Exception {
106assertGoodFeatureEnum(CollectionFeature.class);
107assertGoodFeatureEnum(ListFeature.class);
108assertGoodFeatureEnum(SetFeature.class);
109assertGoodFeatureEnum(CollectionSize.class);
110assertGoodFeatureEnum(MapFeature.class);
111}
112
113private static String rootLocaleFormat(String format, Object... args) {
114return String.format(Locale.ROOT, format, args);
115}
116}
117