Home | History | Annotate | Download | only in features
      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 junit.framework.TestCase;
     20 
     21 import java.lang.annotation.Annotation;
     22 import java.lang.annotation.Inherited;
     23 import java.lang.annotation.Retention;
     24 import java.lang.annotation.RetentionPolicy;
     25 import java.lang.reflect.Method;
     26 
     27 /**
     28  * Since annotations have some reusability issues that force copy and paste
     29  * all over the place, it's worth having a test to ensure that all our Feature
     30  * enums have their annotations correctly set up.
     31  *
     32  * @author George van den Driessche
     33  */
     34 public class FeatureEnumTest extends TestCase {
     35   private static void assertGoodTesterAnnotation(
     36       Class<? extends Annotation> annotationClass) {
     37     assertNotNull(
     38         String.format("%s must be annotated with @TesterAnnotation.",
     39             annotationClass),
     40         annotationClass.getAnnotation(TesterAnnotation.class));
     41     final Retention retentionPolicy =
     42         annotationClass.getAnnotation(Retention.class);
     43     assertNotNull(
     44         String.format("%s must have a @Retention annotation.", annotationClass),
     45         retentionPolicy);
     46     assertEquals(
     47         String.format("%s must have RUNTIME RetentionPolicy.", annotationClass),
     48         RetentionPolicy.RUNTIME, retentionPolicy.value());
     49     assertNotNull(
     50         String.format("%s must be inherited.", annotationClass),
     51         annotationClass.getAnnotation(Inherited.class));
     52 
     53     for (String propertyName : new String[]{"value", "absent"}) {
     54       Method method = null;
     55       try {
     56         method = annotationClass.getMethod(propertyName);
     57       } catch (NoSuchMethodException e) {
     58         fail(String.format("%s must have a property named '%s'.",
     59             annotationClass, propertyName));
     60       }
     61       final Class<?> returnType = method.getReturnType();
     62       assertTrue(String.format("%s.%s() must return an array.",
     63           annotationClass, propertyName),
     64           returnType.isArray());
     65       assertSame(String.format("%s.%s() must return an array of %s.",
     66           annotationClass, propertyName, annotationClass.getDeclaringClass()),
     67           annotationClass.getDeclaringClass(), returnType.getComponentType());
     68     }
     69   }
     70 
     71   // This is public so that tests for Feature enums we haven't yet imagined
     72   // can reuse it.
     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(String.format("Feature enum %s contains a class named " +
     82               "'Require' but it is not an annotation.", featureEnumClass));
     83         }
     84         return;
     85       }
     86     }
     87     fail(String.format("Feature enum %s should contain an " +
     88         "annotation named 'Require'.", featureEnumClass));
     89   }
     90 
     91   @SuppressWarnings("unchecked")
     92   private static Class<? extends Annotation> asAnnotation(Class<?> clazz) {
     93     if (clazz.isAnnotation()) {
     94       return (Class<? extends Annotation>) clazz;
     95     } else {
     96       throw new IllegalArgumentException(
     97           String.format("%s is not an annotation.", clazz));
     98     }
     99   }
    100 
    101   public void testFeatureEnums() throws Exception {
    102     assertGoodFeatureEnum(CollectionFeature.class);
    103     assertGoodFeatureEnum(ListFeature.class);
    104     assertGoodFeatureEnum(SetFeature.class);
    105     assertGoodFeatureEnum(CollectionSize.class);
    106     assertGoodFeatureEnum(MapFeature.class);
    107   }
    108 }
    109