17dd252788645e940eada959bdde927426e2531c9Paul Duffin/* 27dd252788645e940eada959bdde927426e2531c9Paul Duffin * Copyright (C) 2008 The Guava Authors 37dd252788645e940eada959bdde927426e2531c9Paul Duffin * 47dd252788645e940eada959bdde927426e2531c9Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License"); 57dd252788645e940eada959bdde927426e2531c9Paul Duffin * you may not use this file except in compliance with the License. 67dd252788645e940eada959bdde927426e2531c9Paul Duffin * You may obtain a copy of the License at 77dd252788645e940eada959bdde927426e2531c9Paul Duffin * 87dd252788645e940eada959bdde927426e2531c9Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0 97dd252788645e940eada959bdde927426e2531c9Paul Duffin * 107dd252788645e940eada959bdde927426e2531c9Paul Duffin * Unless required by applicable law or agreed to in writing, software 117dd252788645e940eada959bdde927426e2531c9Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS, 127dd252788645e940eada959bdde927426e2531c9Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137dd252788645e940eada959bdde927426e2531c9Paul Duffin * See the License for the specific language governing permissions and 147dd252788645e940eada959bdde927426e2531c9Paul Duffin * limitations under the License. 157dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 167dd252788645e940eada959bdde927426e2531c9Paul Duffin 177dd252788645e940eada959bdde927426e2531c9Paul Duffinpackage com.google.common.collect.testing.features; 187dd252788645e940eada959bdde927426e2531c9Paul Duffin 197dd252788645e940eada959bdde927426e2531c9Paul Duffinimport junit.framework.TestCase; 207dd252788645e940eada959bdde927426e2531c9Paul Duffin 217dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.annotation.Annotation; 227dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.annotation.Inherited; 237dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.annotation.Retention; 247dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.annotation.RetentionPolicy; 257dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Method; 267dd252788645e940eada959bdde927426e2531c9Paul Duffin 277dd252788645e940eada959bdde927426e2531c9Paul Duffin/** 287dd252788645e940eada959bdde927426e2531c9Paul Duffin * Since annotations have some reusability issues that force copy and paste 297dd252788645e940eada959bdde927426e2531c9Paul Duffin * all over the place, it's worth having a test to ensure that all our Feature 307dd252788645e940eada959bdde927426e2531c9Paul Duffin * enums have their annotations correctly set up. 317dd252788645e940eada959bdde927426e2531c9Paul Duffin * 327dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author George van den Driessche 337dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 347dd252788645e940eada959bdde927426e2531c9Paul Duffinpublic class FeatureEnumTest extends TestCase { 357dd252788645e940eada959bdde927426e2531c9Paul Duffin private static void assertGoodTesterAnnotation( 367dd252788645e940eada959bdde927426e2531c9Paul Duffin Class<? extends Annotation> annotationClass) { 377dd252788645e940eada959bdde927426e2531c9Paul Duffin assertNotNull( 387dd252788645e940eada959bdde927426e2531c9Paul Duffin String.format("%s must be annotated with @TesterAnnotation.", 397dd252788645e940eada959bdde927426e2531c9Paul Duffin annotationClass), 407dd252788645e940eada959bdde927426e2531c9Paul Duffin annotationClass.getAnnotation(TesterAnnotation.class)); 417dd252788645e940eada959bdde927426e2531c9Paul Duffin final Retention retentionPolicy = 427dd252788645e940eada959bdde927426e2531c9Paul Duffin annotationClass.getAnnotation(Retention.class); 437dd252788645e940eada959bdde927426e2531c9Paul Duffin assertNotNull( 447dd252788645e940eada959bdde927426e2531c9Paul Duffin String.format("%s must have a @Retention annotation.", annotationClass), 457dd252788645e940eada959bdde927426e2531c9Paul Duffin retentionPolicy); 467dd252788645e940eada959bdde927426e2531c9Paul Duffin assertEquals( 477dd252788645e940eada959bdde927426e2531c9Paul Duffin String.format("%s must have RUNTIME RetentionPolicy.", annotationClass), 487dd252788645e940eada959bdde927426e2531c9Paul Duffin RetentionPolicy.RUNTIME, retentionPolicy.value()); 497dd252788645e940eada959bdde927426e2531c9Paul Duffin assertNotNull( 507dd252788645e940eada959bdde927426e2531c9Paul Duffin String.format("%s must be inherited.", annotationClass), 517dd252788645e940eada959bdde927426e2531c9Paul Duffin annotationClass.getAnnotation(Inherited.class)); 527dd252788645e940eada959bdde927426e2531c9Paul Duffin 537dd252788645e940eada959bdde927426e2531c9Paul Duffin for (String propertyName : new String[]{"value", "absent"}) { 547dd252788645e940eada959bdde927426e2531c9Paul Duffin Method method = null; 557dd252788645e940eada959bdde927426e2531c9Paul Duffin try { 567dd252788645e940eada959bdde927426e2531c9Paul Duffin method = annotationClass.getMethod(propertyName); 577dd252788645e940eada959bdde927426e2531c9Paul Duffin } catch (NoSuchMethodException e) { 587dd252788645e940eada959bdde927426e2531c9Paul Duffin fail(String.format("%s must have a property named '%s'.", 597dd252788645e940eada959bdde927426e2531c9Paul Duffin annotationClass, propertyName)); 607dd252788645e940eada959bdde927426e2531c9Paul Duffin } 617dd252788645e940eada959bdde927426e2531c9Paul Duffin final Class<?> returnType = method.getReturnType(); 627dd252788645e940eada959bdde927426e2531c9Paul Duffin assertTrue(String.format("%s.%s() must return an array.", 637dd252788645e940eada959bdde927426e2531c9Paul Duffin annotationClass, propertyName), 647dd252788645e940eada959bdde927426e2531c9Paul Duffin returnType.isArray()); 657dd252788645e940eada959bdde927426e2531c9Paul Duffin assertSame(String.format("%s.%s() must return an array of %s.", 667dd252788645e940eada959bdde927426e2531c9Paul Duffin annotationClass, propertyName, annotationClass.getDeclaringClass()), 677dd252788645e940eada959bdde927426e2531c9Paul Duffin annotationClass.getDeclaringClass(), returnType.getComponentType()); 687dd252788645e940eada959bdde927426e2531c9Paul Duffin } 697dd252788645e940eada959bdde927426e2531c9Paul Duffin } 707dd252788645e940eada959bdde927426e2531c9Paul Duffin 717dd252788645e940eada959bdde927426e2531c9Paul Duffin // This is public so that tests for Feature enums we haven't yet imagined 727dd252788645e940eada959bdde927426e2531c9Paul Duffin // can reuse it. 737dd252788645e940eada959bdde927426e2531c9Paul Duffin public static <E extends Enum<?> & Feature<?>> void assertGoodFeatureEnum( 747dd252788645e940eada959bdde927426e2531c9Paul Duffin Class<E> featureEnumClass) { 757dd252788645e940eada959bdde927426e2531c9Paul Duffin final Class<?>[] classes = featureEnumClass.getDeclaredClasses(); 767dd252788645e940eada959bdde927426e2531c9Paul Duffin for (Class<?> containedClass : classes) { 777dd252788645e940eada959bdde927426e2531c9Paul Duffin if (containedClass.getSimpleName().equals("Require")) { 787dd252788645e940eada959bdde927426e2531c9Paul Duffin if (containedClass.isAnnotation()) { 797dd252788645e940eada959bdde927426e2531c9Paul Duffin assertGoodTesterAnnotation(asAnnotation(containedClass)); 807dd252788645e940eada959bdde927426e2531c9Paul Duffin } else { 817dd252788645e940eada959bdde927426e2531c9Paul Duffin fail(String.format("Feature enum %s contains a class named " + 827dd252788645e940eada959bdde927426e2531c9Paul Duffin "'Require' but it is not an annotation.", featureEnumClass)); 837dd252788645e940eada959bdde927426e2531c9Paul Duffin } 847dd252788645e940eada959bdde927426e2531c9Paul Duffin return; 857dd252788645e940eada959bdde927426e2531c9Paul Duffin } 867dd252788645e940eada959bdde927426e2531c9Paul Duffin } 877dd252788645e940eada959bdde927426e2531c9Paul Duffin fail(String.format("Feature enum %s should contain an " + 887dd252788645e940eada959bdde927426e2531c9Paul Duffin "annotation named 'Require'.", featureEnumClass)); 897dd252788645e940eada959bdde927426e2531c9Paul Duffin } 907dd252788645e940eada959bdde927426e2531c9Paul Duffin 917dd252788645e940eada959bdde927426e2531c9Paul Duffin @SuppressWarnings("unchecked") 927dd252788645e940eada959bdde927426e2531c9Paul Duffin private static Class<? extends Annotation> asAnnotation(Class<?> clazz) { 937dd252788645e940eada959bdde927426e2531c9Paul Duffin if (clazz.isAnnotation()) { 947dd252788645e940eada959bdde927426e2531c9Paul Duffin return (Class<? extends Annotation>) clazz; 957dd252788645e940eada959bdde927426e2531c9Paul Duffin } else { 967dd252788645e940eada959bdde927426e2531c9Paul Duffin throw new IllegalArgumentException( 977dd252788645e940eada959bdde927426e2531c9Paul Duffin String.format("%s is not an annotation.", clazz)); 987dd252788645e940eada959bdde927426e2531c9Paul Duffin } 997dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1007dd252788645e940eada959bdde927426e2531c9Paul Duffin 1017dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testFeatureEnums() throws Exception { 1027dd252788645e940eada959bdde927426e2531c9Paul Duffin assertGoodFeatureEnum(CollectionFeature.class); 1037dd252788645e940eada959bdde927426e2531c9Paul Duffin assertGoodFeatureEnum(ListFeature.class); 1047dd252788645e940eada959bdde927426e2531c9Paul Duffin assertGoodFeatureEnum(SetFeature.class); 1057dd252788645e940eada959bdde927426e2531c9Paul Duffin assertGoodFeatureEnum(CollectionSize.class); 1067dd252788645e940eada959bdde927426e2531c9Paul Duffin assertGoodFeatureEnum(MapFeature.class); 1077dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1087dd252788645e940eada959bdde927426e2531c9Paul Duffin} 109