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 17 package com.google.common.collect.testing.features; 18 19 import java.lang.annotation.Annotation; 20 import java.lang.annotation.Inherited; 21 import java.lang.annotation.Retention; 22 import java.lang.annotation.RetentionPolicy; 23 import java.lang.reflect.Method; 24 import java.util.Locale; 25 import 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 */ 33 public class FeatureEnumTest extends TestCase { assertGoodTesterAnnotation(Class<? extends Annotation> annotationClass)34 private static void assertGoodTesterAnnotation(Class<? extends Annotation> annotationClass) { 35 assertNotNull( 36 rootLocaleFormat("%s must be annotated with @TesterAnnotation.", annotationClass), 37 annotationClass.getAnnotation(TesterAnnotation.class)); 38 final Retention retentionPolicy = annotationClass.getAnnotation(Retention.class); 39 assertNotNull( 40 rootLocaleFormat("%s must have a @Retention annotation.", annotationClass), 41 retentionPolicy); 42 assertEquals( 43 rootLocaleFormat("%s must have RUNTIME RetentionPolicy.", annotationClass), 44 RetentionPolicy.RUNTIME, 45 retentionPolicy.value()); 46 assertNotNull( 47 rootLocaleFormat("%s must be inherited.", annotationClass), 48 annotationClass.getAnnotation(Inherited.class)); 49 50 for (String propertyName : new String[] {"value", "absent"}) { 51 Method method = null; 52 try { 53 method = annotationClass.getMethod(propertyName); 54 } catch (NoSuchMethodException e) { 55 fail( 56 rootLocaleFormat("%s must have a property named '%s'.", annotationClass, propertyName)); 57 } 58 final Class<?> returnType = method.getReturnType(); 59 assertTrue( 60 rootLocaleFormat("%s.%s() must return an array.", annotationClass, propertyName), 61 returnType.isArray()); 62 assertSame( 63 rootLocaleFormat( 64 "%s.%s() must return an array of %s.", 65 annotationClass, propertyName, annotationClass.getDeclaringClass()), 66 annotationClass.getDeclaringClass(), 67 returnType.getComponentType()); 68 } 69 } 70 71 // This is public so that tests for Feature enums we haven't yet imagined 72 // can reuse it. assertGoodFeatureEnum( Class<E> featureEnumClass)73 public static <E extends Enum<?> & Feature<?>> void assertGoodFeatureEnum( 74 Class<E> featureEnumClass) { 75 final Class<?>[] classes = featureEnumClass.getDeclaredClasses(); 76 for (Class<?> containedClass : classes) { 77 if (containedClass.getSimpleName().equals("Require")) { 78 if (containedClass.isAnnotation()) { 79 assertGoodTesterAnnotation(asAnnotation(containedClass)); 80 } else { 81 fail( 82 rootLocaleFormat( 83 "Feature enum %s contains a class named " 84 + "'Require' but it is not an annotation.", 85 featureEnumClass)); 86 } 87 return; 88 } 89 } 90 fail( 91 rootLocaleFormat( 92 "Feature enum %s should contain an " + "annotation named 'Require'.", 93 featureEnumClass)); 94 } 95 96 @SuppressWarnings("unchecked") asAnnotation(Class<?> clazz)97 private static Class<? extends Annotation> asAnnotation(Class<?> clazz) { 98 if (clazz.isAnnotation()) { 99 return (Class<? extends Annotation>) clazz; 100 } else { 101 throw new IllegalArgumentException(rootLocaleFormat("%s is not an annotation.", clazz)); 102 } 103 } 104 testFeatureEnums()105 public void testFeatureEnums() throws Exception { 106 assertGoodFeatureEnum(CollectionFeature.class); 107 assertGoodFeatureEnum(ListFeature.class); 108 assertGoodFeatureEnum(SetFeature.class); 109 assertGoodFeatureEnum(CollectionSize.class); 110 assertGoodFeatureEnum(MapFeature.class); 111 } 112 rootLocaleFormat(String format, Object... args)113 private static String rootLocaleFormat(String format, Object... args) { 114 return String.format(Locale.ROOT, format, args); 115 } 116 } 117