blob: 32387f18e0930df6d5bb75b99fd43af4adc24604 [file] [log] [blame]
/*
* 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 org.apache.harmony.lang.annotation;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import org.apache.harmony.lang.AnnotatedElementTestFrame.MissingClassValAntn;
import junit.framework.TestCase;
/**
* The test of annotation implementation, covering all possible types of elements.
*
* @author Alexey V. Varlamov
*/
@AllTypesAntn
public class AllTypesTest extends TestCase {
public static void main(String[] args) {
junit.textui.TestRunner.run(AllTypesTest.class);
}
/**
* The annotation instance should return correct default values
* of elements if no actual values were specified.
*/
public void testGetAnnotation_ByDefault() throws Throwable {
AllTypesAntn antn = AllTypesAntn.class.getAnnotation(AllTypesAntn.class);
assertNotNull("the annotation", antn);
Method[] ms = AllTypesAntn.class.getDeclaredMethods();
for (Method m : ms) {
Object defaultValue = m.getDefaultValue();
String name = m.getName();
assertNotNull("null defaultValue of " + name, defaultValue);
Object value = m.invoke(antn);
assertNotNull("null value of " + name, value);
Class<?> def = m.getReturnType();
Class<?> real = value.getClass();
if (def.isAnnotation()) {
assertTrue("nested antn value type : def=" + def + "; real=" + real, def.isInstance(value));
} else if (def.isPrimitive()) {
assertSame("unboxed value type", def, real.getField("TYPE").get(null));
} else {
assertSame("value type", def, real);
}
if (m.getReturnType().isArray()) {
int len = Array.getLength(defaultValue);
assertEquals("array length of " + m.getName(), len, Array.getLength(value));
for (int i = 0; i < len; i++) {
assertEquals(m.getName() + "["+i+"]", Array.get(defaultValue, i), Array.get(value, i));
}
} else {
assertEquals(m.getName(), defaultValue, value);
}
}
}
/**
* The annotation instance should return correct actual values
* of elements overriding their defaults.
*/
public void testGetAnnotation_NoDefault() throws Throwable {
AllTypesAntn2 antn = AllTypesAntn2.class.getAnnotation(AllTypesAntn2.class);
assertNotNull("the annotation", antn);
Method[] ms = AllTypesAntn2.class.getDeclaredMethods();
for (Method m : ms) {
Object defaultValue = m.getDefaultValue();
String name = m.getName();
assertNull("defaultValue of " + name, defaultValue);
Object value = m.invoke(antn);
assertNotNull("null value of " + name, value);
Class<?> def = m.getReturnType();
Class<?> real = value.getClass();
if (def.isAnnotation()) {
assertTrue("nested antn value type : def=" + def + "; real=" + real, def.isInstance(value));
} else if (def.isPrimitive()) {
assertSame("unboxed value type", def, real.getField("TYPE").get(null));
} else {
assertSame("value type", def, real);
}
}
}
/**
* The equals() method of annotation instance
* must true if equivalent annotation instance is passed, false otherwise.
*/
@AllTypesAntn(intArrayValue=346546)
public void testEquals() throws Throwable {
AllTypesAntn antn = AllTypesAntn.class.getAnnotation(AllTypesAntn.class);
assertTrue("case1", antn.equals(antn));
Object obj = this.getClass().getAnnotation(AllTypesAntn.class);
assertEquals("case2", obj, antn);
assertEquals("case2_1", obj.hashCode(), antn.hashCode());
AllTypesAntn2 antn2 = AllTypesAntn2.class.getAnnotation(AllTypesAntn2.class);
assertEquals("case3", antn2, AllTypesAntn2.class.getAnnotation(AllTypesAntn2.class));
assertFalse("case4", antn.equals(antn2));
assertFalse("case5", antn.equals(
this.getClass().getMethod("testEquals").getAnnotation(AllTypesAntn.class)));
}
/**
* The equals() method of annotation instance
* must correctly work with alternative implementations.
*/
public void testEquals_ForeignImpl() throws Throwable {
AllTypesAntn antn = AllTypesAntn.class.getAnnotation(AllTypesAntn.class);
assertTrue(antn.equals(new AllTypesAntn.MockedImpl()));
}
/**
* The toString() method of annotation instance
* must return meaningful description.
*/
public void testToString() throws Throwable {
String s = AllTypesAntn.class.getAnnotation(AllTypesAntn.class).toString();
assertNotNull(s);
assertTrue(s.length() != 0);
assertTrue(s.startsWith("@org.apache.harmony.lang.annotation.AllTypesAntn"));
}
/**
* The annotationType() method of annotation instance
* must return correct Class.
*/
public void testAnnotationType() throws Throwable {
assertSame(AllTypesAntn.class,
AllTypesAntn.class.getAnnotation(AllTypesAntn.class).annotationType());
}
/**
* An annotation should defer throwing TypeNotPresentException
* for a Class-valued member until the member accessed.
*/
@MissingClassValAntn
public void testAnnotation_ElementError() throws Throwable {
MissingClassValAntn antn = this.getClass().getMethod(
"testAnnotation_ElementError").getAnnotation(MissingClassValAntn.class);
try {
antn.clss();
fail("Misconfigured test: "
+ "notfound.MissingClass should not be in classpath");
} catch (TypeNotPresentException tnpe) {
assertTrue("reported type name: " + tnpe.typeName(),
tnpe.typeName().matches("notfound.MissingClass"));
}
try {
antn.clssArray();
fail("Misconfigured test: "
+ "notfound.MissingClass should not be in classpath");
} catch (TypeNotPresentException tnpe) {
assertTrue("reported type name: " + tnpe.typeName(),
tnpe.typeName().matches("notfound.MissingClass"));
}
}
/**
* Tests that annotation can be serialized and deserialized without
* exceptions, and that deserialization really produces deeply cloned
* objects.
*/
public void testSerialization() throws Throwable {
Object[] arr = new Object[] {
AllTypesAntn.class.getAnnotation(AllTypesAntn.class),
AllTypesAntn2.class.getAnnotation(AllTypesAntn2.class)
};
for (Object data : arr) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
putObjectToStream(data, bos);
ByteArrayInputStream bis = new ByteArrayInputStream(bos
.toByteArray());
assertEquals(data, getObjectFromStream(bis));
}
}
/**
* Serializes specified object to an output stream.
*/
static void putObjectToStream(Object obj, OutputStream os)
throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(obj);
oos.flush();
oos.close();
}
/**
* Deserializes single object from an input stream.
*/
static Object getObjectFromStream(InputStream is) throws IOException,
ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(is);
Object result = ois.readObject();
ois.close();
return result;
}
}