Review request for type annotation reflection test

Charlie Wang charlie.wang at oracle.com
Tue May 21 14:29:12 PDT 2013


OK, thanks.
I will create a TestUtil.java (as attached file). Extract the common 
part and put them in it. And Add comments on data provider.
I'm on a very tight schedule, so this time I just send out two of the 
updated files (attached files) for review so I can get a quick response. 
If it is OK, I will use it as a template on other tests.
Please take a look and send me your comments as soon as possible.


Thanks,
Charlie


On 2013/5/22 2:24, Alex Buckley wrote:
> Please keep one source file per tested API method, because it is easy 
> to navigate. The problem is the body of the test() method in each 
> source file. It should call utility methods to inspect annotations, 
> rather that repeating more or less the same 'for' loops as every other 
> test() method.
>
> As for data providers, I believe they are a TestNG thing. Please add 
> comments to each source file to describe what the data provider 
> represents.
>
> Finally, when you make a "little update", you should give a short 
> description of what has changed. If you don't, someone who looked at 
> the previous version has no idea what changed and will have to look at 
> everything again.
>
> Alex
>
> On 5/21/2013 3:10 AM, Charlie Wang wrote:
>> Yes, that make sense. What do you think if I combine the tests? It would
>> then have 1 unified data provider and test method, thus solve the 2
>> problems.
>>
>> Regards,
>> Charlie
>> On 2013/5/21 14:56, Werner Dietl wrote:
>>> I agree with Alex's first two comments. The code duplication for the
>>> test logic and all the different annotation types seems hard to
>>> maintain and update.
>>>
>>> cu, WMD.
>>>
>>> On Mon, May 20, 2013 at 7:56 PM, Charlie Wang
>>> <charlie.wang at oracle.com> wrote:
>>>> Hi,
>>>>    Here's the latest one with a little update:
>>>> http://cr.openjdk.java.net/~ssides/8013497/webrev.03/
>>>>    Please provide comments as soon as possible now that due date is
>>>> approaching.
>>>>
>>>>
>>>> Regards,
>>>> Charlie
>>>>
>>>>
>>>>
>>>> On 2013/5/19 14:10, Charlie Wang wrote:
>>>>
>>>> Hi,
>>>>    Here's test for core reflection support of type-annotations
>>>> JDK-8013497.
>>>> Please take a look.
>>>>
>>>> http://cr.openjdk.java.net/~ssides/8013497/webrev.02/
>>>>
>>>>
>>>> Regards,
>>>> Charlie
>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>

-------------- next part --------------
/*
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.annotation.AnnotationFormatError;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedArrayType;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.AnnotatedTypeVariable;
import java.lang.reflect.AnnotatedWildcardType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.testng.Assert.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.NoInjection;
import org.testng.annotations.Test;

public class TestUtil {
    
    // check annotation
    public static void validateAnno(Annotation[] annotations
            , Object[] annotationCheck) throws Exception{
        for (int i = 0; i < annotations.length; i++) {
            Annotation anno = annotations[i];
            assertEquals(anno.annotationType(), annotationCheck[i * 2]);
            Object value = "";
            try {
                Method valueMethod = anno.annotationType().getMethod("value"
                        , new Class[]{});
                value = valueMethod.invoke(anno, new Object[]{});
            } catch (NoSuchMethodException e) {
                //expected exception for TypeAnno3
            }
            if (annotationCheck[i * 2 + 1] instanceof String) {
                assertEquals(value, annotationCheck[i * 2 + 1]);
            } else {
                //for repeated anno
                Annotation[] av = (Annotation[]) value;
                Object[] ac = (Object[]) annotationCheck[i * 2 + 1];
                assertEquals(av.length, ac.length / 2);
                for (int j = 0; j < av.length; j++) {
                    assertEquals(av[j].annotationType(), ac[j * 2]);
                    Method vm = av[j].annotationType().getMethod("value"
                            , new Class[]{});
                    Object v = vm.invoke(av[j], new Object[]{});
                    assertEquals(v, ac[j * 2 + 1]);
                }
            }
        }
    }

    // vlidate AnnotatedArrayType
    public static void validateArrayAT(AnnotatedType at, Object[][] annotationCheck) 
            throws Exception {
        for (int i = 0; i < annotationCheck.length; i++) {
            Annotation[] annos = at.getAnnotations();
            assertEquals(annos.length, annotationCheck[i].length / 2);
            for (int j = 0; j < annotationCheck[i].length; j+=2) {
                Method valueMethod = annos[j / 2].annotationType().getMethod(
                        "value", new Class[]{});
                Object value = valueMethod.invoke(annos[j / 2], new Object[]{});
                if (value instanceof String) {
                    assertEquals(annos[j / 2].annotationType()
                            , annotationCheck[i][j]);
                    assertEquals(value, annotationCheck[i][j + 1]);
                } else {
                    Annotation[] av = (Annotation[]) value;
                    Object[] ac = (Object[]) annotationCheck[i][j + 1];
                    assertEquals(av.length, ac.length / 2);
                    for (int k = 0; k < av.length; k++) {
                        assertEquals(av[k].annotationType(), ac[k * 2]);
                        Method vm = av[k].annotationType().getMethod(
                                "value", new Class[]{});
                        Object v = vm.invoke(av[k], new Object[]{});
                        assertEquals(v, ac[k * 2 + 1]);
                    }
                }
            }

            if (at instanceof AnnotatedArrayType) {
                at = ((AnnotatedArrayType) at)
                        .getAnnotatedGenericComponentType();
            }
        }
    }
    
    // check AnnotatedType type and value 
    public static void validateAT(AnnotatedType at,  Object[] annotationCheck) 
            throws Exception{
        Annotation[] annotations = at.getAnnotations();
        assertEquals(annotations.length, annotationCheck.length / 2);
        validateAnno(annotations, annotationCheck);
    }
    
    // check multiple AnnotatedType type and value 
    public static void validateMultipleAT(AnnotatedType[] as
            , Object[][] annotationCheck) throws Exception{
        assertEquals(as.length, annotationCheck.length);
        for (int i = 0; i < as.length; i++) {
            validateAT(as[i],  (Object[]) annotationCheck[i]);
        }
    }
    
}
 
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(TypeAnno1Container.class)
@interface TypeAnno1 {

    String value();
}

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(TypeAnno2Container.class)
@interface TypeAnno2 {

    String value();
}

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(TypeAnno3Container.class)
@interface TypeAnno3 {
}

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno4 {
    String value();
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno5 {
    String value();
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno6 {
    String value();
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno7 {
    String value();
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno8 {
    String value();
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno9 {
    String value();
}

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno1Container {

    TypeAnno1[] value();
}

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno2Container {

    TypeAnno2[] value();
}

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TypeAnno3Container {

    TypeAnno3[] value();
}

-------------- next part --------------
/*
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/**
 * @test @summary test for Class.getAnnotatedInterfaces()
 * @bug 8013497
 * @(#) GetAnnotatedInterfacesTest.java
 * @build TestUtil
 * @run testng GetAnnotatedInterfacesTest
 */
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
import static org.testng.Assert.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class GetAnnotatedInterfacesTest {

    @Test(dataProvider = "annotationsData")
    public void test(Class c, Object[][] annotationCheck) throws Exception {
        AnnotatedType[] as = c.getAnnotatedInterfaces();
        assertEquals(as.length, annotationCheck.length);
        TestUtil.validateMultipleAT(as, annotationCheck);
    }

    @DataProvider
    public Object[][] annotationsData() {
        // first item of every row represents the class to invoke 
        // getannotatedInterfaces() on (e.g. Object.class.getannotatedInterfaces())
        // , second one represents the result
        return new Object[][]{
            // invoke getannotatedInterfaces() on Object.class, should get empty
            // array
            {Object.class, new Object[][]{}},
            {int.class, new Object[][]{}},
            {void.class, new Object[][]{}},
            {AnnotationTypeTest01.class, new Object[][]{}},
            {AnnotationTypeTest02.class, new Object[][]{}},
            {AnnotationTypeTest03.class, new Object[][]{{new Object[]{}}}},
            {AnnotationTypeTest04.class, new Object[][]{{new Object[]{}}}},
            {AnnotationTypeTest05.class, new Object[][]{
                    {TypeAnno1.class, "TypeAnno1"}}},
            {int[].class, new Object[][]{{}, {}}},
            {AnnotationTypeTest06.class, new Object[][]{
                    {TypeAnno1.class, "TypeAnno1", TypeAnno2.class, "TypeAnno2"}}},
            {AnnotationTypeTest07.class, new Object[][]{
                    {TypeAnno1.class, "TypeAnno1"},
                    {TypeAnno2.class, "TypeAnno2"}}},
            {AnnotationTypeTest08.class, new Object[][]{
                    {TypeAnno1.class, "TypeAnno1", TypeAnno3.class, ""}}},
            {AnnotationTypeTest09.class, new Object[][]{
                    {TypeAnno1.class, "TypeAnno1", TypeAnno2Container.class
                            , new Object[]{TypeAnno2.class, "TypeAnno21"
                                    , TypeAnno2.class, "TypeAnno22"}}}}
        };
    }
}

interface Interface1 {
}

interface Interface2 {
}

class Object1 {
}

class Object2 {
}

class AnnotationTypeTest01 {
}

class AnnotationTypeTest02 extends Object1 {
}

class AnnotationTypeTest03 implements Interface1 {
}

class AnnotationTypeTest04 extends Object1 implements Interface1 {
}

interface AnnotationTypeTest05 extends @TypeAnno1("TypeAnno1") Interface1 {
}

interface AnnotationTypeTest06 extends 
    @TypeAnno1("TypeAnno1")
    @TypeAnno2("TypeAnno2")
    Interface1 {
}

class AnnotationTypeTest07 implements 
    @TypeAnno1("TypeAnno1")
    Interface1 , @TypeAnno2("TypeAnno2")
    Interface2 {
}

class AnnotationTypeTest08 implements 
    @TypeAnno1("TypeAnno1")
    @TypeAnno3
    Interface1 {
}

class AnnotationTypeTest09 implements 
    @TypeAnno1("TypeAnno1")
    @TypeAnno2("TypeAnno21")
    @TypeAnno2("TypeAnno22")
    Interface1 {
}


More information about the type-annotations-dev mailing list