Method5Test.java :  » Apache-Harmony-Java-SE » java-package » java » lang » reflect » Java Open Source

Java Open Source » Apache Harmony Java SE » java package 
java package » java » lang » reflect » Method5Test.java
/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package java.lang.reflect;

import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import org.apache.harmony.lang.AnnotatedElementTestFrame;
import org.apache.harmony.lang.AnnotatedElementTestFrame.MissingClassValAntn;
import org.apache.harmony.lang.AnnotatedElementTestFrame.MissingTypeAntn;
import org.apache.harmony.lang.AnnotatedElementTestFrame.TagAntn;
import org.apache.harmony.lang.AnnotatedElementTestFrame.ValAntn;

/**
 * @author Alexey V. Varlamov
 */ 
public class Method5Test extends AnnotatedElementTestFrame {

    protected @Override AnnotatedElement getElement1() throws Throwable {
        return AnnotatedMethod.class.getMethod("foo");
    }
    
    protected @Override AnnotatedElement getElement2() throws Throwable {
        return AnnotatedMethod.class.getMethod("bar");
    }

    protected @Override AnnotatedElement getElement3() throws Throwable {
        return AnnotatedMethod.class.getMethod("buz", String.class);
    }
    
    /**
     * Provides an instance to be tested. The instance must be annotated
     * by the notfound.MissingAntn.
     */
    protected @Override AnnotatedElement getElement4() throws Throwable {
        return AnnotatedMethod.class.getMethod("i", int.class);
    }

    /**
     * Provides an instance to be tested. The instance must be annotated
     * by the MissingClassValAntn.
     */
    protected @Override AnnotatedElement getElement5() throws Throwable {
        return AnnotatedMethod.class.getMethod("l", long.class);
    }

    /**
     * Provides an instance to be tested. The instance must be annotated
     * by the MissingTypeAntn.
     */
    protected @Override AnnotatedElement getElement6() throws Throwable {
        return AnnotatedMethod.class.getMethod("ch", char.class);
    }


    public static void main(String[] args) {
        junit.textui.TestRunner.run(Method5Test.class);
    }

    protected final Annotation[][] getParamAnnotations(Member obj) throws Throwable {
        assertTrue("illegal argument: " + obj,
                (obj instanceof Method) || (obj instanceof Constructor));
        Method m = obj.getClass().getMethod("getParameterAnnotations");
        return (Annotation[][])m.invoke(obj);
    }

    protected Member getParamElement1() throws Throwable {
        return AnnotatedParamMethod.class.getMethod("foo");
    }
    
    protected Member getParamElement2() throws Throwable {
        return AnnotatedParamMethod.class.getMethod("bar", 
                Object.class, Class.class, boolean.class);
    }
    
    protected Member getParamElement3() throws Throwable {
        return AnnotatedParamMethod.class.getMethod("buz", 
                String.class, int.class);
    }
    
    /**
     * getParameterAnnotations() should return empty array
     * if member has no parameters.
     */
    public void testGetParameterAnnotations1() throws Throwable {
        Annotation[][] an = getParamAnnotations(getParamElement1());
        assertNotNull(an);
        assertEquals(0, an.length);
    }

    /**
     * getParameterAnnotations() should return array of annotation 
     * arrays for member parameters, in declaration order.
     */
    public void testGetParameterAnnotations2() throws Throwable {
        Annotation[][] an = getParamAnnotations(getParamElement2());
        assertNotNull(an);
        assertEquals("param num", 3, an.length);
        
        assertEquals("1st param annotation num", 1, an[0].length);
        assertSame("1st param annotation type", P1Antn.class, 
                an[0][0].annotationType());

        assertEquals("2nd param annotation num", 1, an[1].length);
        assertSame("2nd param annotation type", P2Antn.class, 
                an[1][0].annotationType());
        assertEquals("2nd param annotation value", 123, ((P2Antn)an[1][0]).value());
        
        assertEquals("3rd param annotation num", 2, an[2].length);
        assertSame("3rd param annotation 1 type", P3Antn.class, 
                an[2][0].annotationType());
        assertSame("3rd param annotation 2 type", ValAntn.class, 
                an[2][1].annotationType());
        assertEquals("3rd param annotation 2 value", "xyz", ((ValAntn)an[2][1]).value());
    }

    /**
     * For each parameter having no annotations,
     * getParameterAnnotations() should return corresponding 
     * nested arrays with zero size. 
     */
    public void testGetParameterAnnotations3() throws Throwable {
        Annotation[][] an = getParamAnnotations(getParamElement3());
        assertNotNull(an);
        assertEquals("param num", 2, an.length);
        
        assertEquals("1st param annotation num", 0, an[0].length);

        assertEquals("2nd param annotation num", 1, an[1].length);
        assertSame("2nd param annotation type", TagAntn.class, 
                an[1][0].annotationType());
    }
    
    /**
     * getParameterAnnotations() should return cloned arrays
     * which can be safely modified by a caller.
     */
    public void testGetParameterAnnotationsImmutable() throws Throwable {
        Member m = getParamElement2();
        Annotation[][] an0 = getParamAnnotations(m);
        assertNotNull(an0);
        assertEquals("param num", 3, an0.length);
        an0[1] = an0[2];
        an0[1][1] = null;
        an0[2] = new Annotation[0];
        
        Annotation[][] an = getParamAnnotations(m);
        
        assertEquals("1st param annotation num", 1, an[0].length);
        assertSame("1st param annotation type", P1Antn.class, 
                an[0][0].annotationType());

        assertEquals("2nd param annotation num", 1, an[1].length);
        assertSame("2nd param annotation type", P2Antn.class, 
                an[1][0].annotationType());
        assertEquals("2nd param annotation value", 123, ((P2Antn)an[1][0]).value());
        
        assertEquals("3rd param annotation num", 2, an[2].length);
        assertSame("3rd param annotation 1 type", P3Antn.class, 
                an[2][0].annotationType());
        assertSame("3rd param annotation 2 type", ValAntn.class, 
                an[2][1].annotationType());
        assertEquals("3rd param annotation 2 value", "xyz", ((ValAntn)an[2][1]).value());
    }
    
    static class A {
        private Object obj;
        class InA {
            Object o = obj; 
        }
    }
    
    enum E { E1, E2, E3}
    
    static class B1 {
        public Object foo() { return null;}
        public Object bar(int i, Object... o) { return null;}
        public static void main1(String... s){}
        public static void main2(String[] s){}
    }

    static class B2 extends B1 {
        public String foo() { return "";}
        public String bar(int i, Object... o) { return "";}
    }
        
    /**
     * isSynthetic() should return true if and only if
     * the target method does not appear in the source code. 
     */
    public void testIsSynthetic() throws Exception {
        assertFalse("case1.1: ordinary method", 
                AnnotatedMethod.class.getMethod("foo").isSynthetic());
        assertFalse("case1.2: ordinary vararg method", 
                B1.class.getMethod("main1", String[].class).isSynthetic());
        
        Method[] ms = A.class.getDeclaredMethods();
        assertTrue(ms != null && ms.length > 0);
        for (Method m : ms){
            assertTrue("case2: " + m, m.isSynthetic());
        }

        // XXX bug in compiler? 
        //assertTrue("case3: EnumType.values()", 
          //      E.class.getMethod("values").isSynthetic());
    }
    
    /**
     * isBridge() should return true if and only if
     * the target method does not appear in the source code
     * and overrides covariant return type method. 
     */
    public void testIsBridge() throws Exception {
        assertFalse("case1.1: ordinary method", 
                AnnotatedMethod.class.getMethod("foo").isBridge());
        assertFalse("case1.2: ordinary vararg method", 
                B1.class.getMethod("main1", String[].class).isBridge());
        
        Method[] ms = B1.class.getMethods();
        assertTrue(ms != null && ms.length > 0);
        for (Method m : ms){
            assertFalse("case2.1: " + m, m.isBridge());
        }
        
        ms = B2.class.getDeclaredMethods();
        assertTrue(ms != null && ms.length > 0);
        for (Method m : ms){
            //System.out.println("case2.2 " + m);
            assertTrue("case2.2: " + m, 
                    m.getReturnType() != Object.class ^ m.isBridge());
        }

        assertFalse("case3: EnumType.values()", 
                E.class.getMethod("values").isBridge());
    }
    
    /**
     * isVarArgs() should return true if and only if
     * the target method is declared with varargs. 
     */
    public void testIsVarargs() throws Exception {
        assertFalse("case1: ordinary method", 
                AnnotatedMethod.class.getMethod("foo").isVarArgs());
        
        assertTrue("case2: varargs method", 
                B1.class.getMethod("main1", String[].class).isVarArgs());

        assertFalse("case3: ordinary method", 
                B1.class.getMethod("main2", String[].class).isVarArgs());
    }
    
    static abstract class C {
        protected abstract <T extends Throwable> 
        OneParamType<? extends T> go(T t) throws T, Error;
    }

    /**
     * toGenericString() should return a string exactly matching
     * the API specification.
     */
    public void testToGenericString() throws Exception {
        String s = C.class.getDeclaredMethod("go", 
                Throwable.class).toGenericString();
        System.out.println(s);
        assertEquals(
                // Should method type parameter be followed by a type bound? It is unspecified.
                // The known reference implementation doesn't do it as well:
                //"protected abstract <T extends java.lang.Throwable>"
                "protected abstract <T>"
                + " java.lang.reflect.OneParamType<? extends T>"
                + " java.lang.reflect.Method5Test$C.go(T)"
                + " throws T,java.lang.Error",
                s);
    }
    
    /**
     * toGenericString() should return a string exactly matching
     * the API specification.
     */
    public void testToGenericString2() throws Exception {
        String s = B2.class.getDeclaredMethod("bar", 
                int.class, Object[].class).toGenericString();
        // it is unspecified which method should be returned:
        // original (overriden with covariant return) or
        // compiler-generated bridge.
        // different implementations behave differently,
        // so relaxed this check to allow both variants.
        assertTrue("start: " + s, s.startsWith("public java.lang.")); // String or Object
        assertTrue("end: " + s, 
                s.endsWith(" java.lang.reflect.Method5Test$B2."
                        + "bar(int,java.lang.Object[])"));
    }
}

abstract class AnnotatedMethod {
    @TagAntn public abstract void foo();
    @TagAntn @ValAntn public Object[] bar() {return null;}
    public String buz(String s){return s;}
    @notfound.MissingAntn public void i(int i) {}
    @MissingClassValAntn public void l(long l){}
    @MissingTypeAntn public void ch(char ch){}
}

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface P1Antn {}

@Retention(RetentionPolicy.RUNTIME)
@interface P2Antn {
    int value();
}

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface P3Antn {
    String[] meta1() default {};
    P1Antn meta2() default @P1Antn;
}

class AnnotatedParamMethod {
    @TagAntn public void foo(){}
    @ValAntn("abc") public void bar(@P1Antn Object p1, 
            @P2Antn(123) Class p2, @P3Antn @ValAntn("xyz") boolean p3){}
    public void buz(String s, @TagAntn int i){}
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.