| /* |
| * Copyright 2008 Google Inc. |
| * |
| * Licensed 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 com.google.gwt.dev.javac.typemodel; |
| |
| import com.google.gwt.core.ext.TreeLogger; |
| import com.google.gwt.core.ext.UnableToCompleteException; |
| import com.google.gwt.core.ext.typeinfo.HasAnnotations; |
| import com.google.gwt.core.ext.typeinfo.JPrimitiveType; |
| import com.google.gwt.core.ext.typeinfo.JType; |
| import com.google.gwt.core.ext.typeinfo.NotFoundException; |
| import com.google.gwt.dev.javac.typemodel.test.AnnotatedClass; |
| import com.google.gwt.dev.javac.typemodel.test.ClassAnnotatedWithBinaryOnlyAnnotation; |
| import com.google.gwt.dev.javac.typemodel.test.ClassLiteralReferenceAnnotation; |
| import com.google.gwt.dev.javac.typemodel.test.PrimitiveValuesAnnotation; |
| import com.google.gwt.dev.javac.typemodel.test.PrimitivesAnnotatedClass; |
| import com.google.gwt.dev.javac.typemodel.test.SourceRetentionAnnotation; |
| import com.google.gwt.dev.javac.typemodel.test.TestAnnotation; |
| import com.google.gwt.dev.util.log.PrintWriterTreeLogger; |
| |
| import junit.framework.TestCase; |
| |
| import java.io.File; |
| import java.lang.annotation.Annotation; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.Method; |
| |
| /** |
| * Test cases for the {@link TypeOracle}'s {@link Annotation} support. |
| * |
| * Array annotations Enum annotations String from field annotations |
| */ |
| public class TypeOracleAnnotationSupportTest extends TestCase { |
| |
| private static void validateAnnotation(HasAnnotations annotatedElement, |
| String testAnnotationValue, String nestedAnnotationValue, |
| TestAnnotation realAnnotation) { |
| assertNotNull(annotatedElement); |
| |
| assertNull(annotatedElement.getAnnotation(SourceRetentionAnnotation.class)); |
| |
| TestAnnotation testAnnotation = annotatedElement.getAnnotation(TestAnnotation.class); |
| assertNotNull(testAnnotation); |
| |
| // Check our proxy objects against the real thing. |
| assertEquals(realAnnotation, testAnnotation); |
| assertEquals(realAnnotation.hashCode(), testAnnotation.hashCode()); |
| |
| // tobyr doesn't like this. |
| // assertEquals(realAnnotation.toString(), testAnnotation.toString()); |
| |
| // checks default value |
| assertEquals(testAnnotationValue, testAnnotation.value()); |
| assertEquals(nestedAnnotationValue, |
| testAnnotation.nestedAnnotation().value()); |
| |
| // Tests default values using conditional statements. |
| assertEquals(realAnnotation.longValue(), testAnnotation.longValue()); |
| |
| // Tests default value of array type. |
| assertEquals(realAnnotation.intArrayValue().length, |
| testAnnotation.intArrayValue().length); |
| |
| // Tests default value which is a field reference. |
| assertEquals(realAnnotation.stringValue(), testAnnotation.stringValue()); |
| |
| // Tests default value that is a class literal. |
| assertEquals(realAnnotation.classLiteral(), testAnnotation.classLiteral()); |
| |
| // Tests implicit array initializers |
| Class<?>[] expectedArrayValue = realAnnotation.arrayWithImplicitArrayInitializer(); |
| Class<?>[] actualArrayValue = testAnnotation.arrayWithImplicitArrayInitializer(); |
| assertTrue(expectedArrayValue.length > 0); |
| assertEquals(expectedArrayValue.length, actualArrayValue.length); |
| assertEquals(expectedArrayValue[0], actualArrayValue[0]); |
| |
| // Tests that empty array initializers are also handled correctly. |
| assertEquals(realAnnotation.emptyArray().length, |
| testAnnotation.emptyArray().length); |
| } |
| |
| private final boolean logToConsole = false; |
| private final ModuleContext moduleContext = new ModuleContext(logToConsole |
| ? new PrintWriterTreeLogger() : TreeLogger.NULL, |
| "com.google.gwt.dev.javac.typemodel.TypeOracleTest"); |
| |
| private final TypeOracle typeOracle = moduleContext.getOracle(); |
| |
| public TypeOracleAnnotationSupportTest() throws UnableToCompleteException { |
| } |
| |
| /** |
| * Test that a class can be annotated. |
| */ |
| public void testAnnotatedClass() throws NotFoundException { |
| JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName()); |
| |
| TestAnnotation realAnnotation = AnnotatedClass.class.getAnnotation(TestAnnotation.class); |
| validateAnnotation(annotatedClass, "Class", "Foo", realAnnotation); |
| |
| ClassLiteralReferenceAnnotation classReferenceAnnotation = annotatedClass.getAnnotation(ClassLiteralReferenceAnnotation.class); |
| assertEquals(ClassLiteralReferenceAnnotation.Foo.class, |
| classReferenceAnnotation.value()); |
| |
| assertEquals(2, annotatedClass.getAnnotations().length); |
| } |
| |
| /** |
| * Test that a constructor can be annotated. |
| */ |
| public void testAnnotatedConstructor() throws NotFoundException, |
| SecurityException, NoSuchMethodException { |
| JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName()); |
| JConstructor ctor = annotatedClass.getConstructor(TypeOracle.NO_JTYPES); |
| |
| Constructor<AnnotatedClass> constructor = AnnotatedClass.class.getConstructor(); |
| TestAnnotation realAnnotation = constructor.getAnnotation(TestAnnotation.class); |
| |
| validateAnnotation(ctor, "Constructor", "Not assigned", realAnnotation); |
| } |
| |
| /** |
| * Test that a field can be annotated. |
| */ |
| public void testAnnotatedField() throws NotFoundException, SecurityException, |
| NoSuchFieldException { |
| JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName()); |
| JField annotatedField = annotatedClass.getField("annotatedField"); |
| |
| Field field = AnnotatedClass.class.getDeclaredField("annotatedField"); |
| TestAnnotation realAnnotation = field.getAnnotation(TestAnnotation.class); |
| |
| validateAnnotation(annotatedField, "Field", "Not assigned", realAnnotation); |
| } |
| |
| /** |
| * Tests that methods can be annotated. |
| */ |
| public void testAnnotatedMethod() throws NotFoundException, |
| SecurityException, NoSuchMethodException { |
| JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName()); |
| JMethod annotatedMethod = annotatedClass.getMethod("annotatedMethod", |
| TypeOracle.NO_JTYPES); |
| |
| Method method = AnnotatedClass.class.getDeclaredMethod("annotatedMethod"); |
| TestAnnotation realAnnotation = method.getAnnotation(TestAnnotation.class); |
| |
| validateAnnotation(annotatedMethod, "Method", "Not assigned", |
| realAnnotation); |
| } |
| |
| /** |
| * Tests that packages can be annotated. This necessitates the existence of a |
| * package-info.java file in the package that you wish to annotate. |
| */ |
| public void testAnnotatedPackage() throws NotFoundException, |
| ClassNotFoundException { |
| JPackage annotatedPackage = typeOracle.getPackage("com.google.gwt.dev.javac.typemodel.test"); |
| assertNotNull(annotatedPackage); |
| |
| TestAnnotation realAnnotation = Class.forName( |
| "com.google.gwt.dev.javac.typemodel.test.package-info", false, |
| TypeOracleAnnotationSupportTest.class.getClassLoader()).getAnnotation( |
| TestAnnotation.class); |
| |
| validateAnnotation(annotatedPackage, "Package", "Not assigned", |
| realAnnotation); |
| } |
| |
| /** |
| * Tests that parameters can be annotated. |
| */ |
| public void testAnnotatedParameter() throws NotFoundException, |
| SecurityException, NoSuchMethodException { |
| JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName()); |
| JMethod jmethod = annotatedClass.getMethod("methodWithAnnotatedParameter", |
| new JType[]{JPrimitiveType.INT}); |
| JParameter parameter = jmethod.getParameters()[0]; |
| |
| Method method = AnnotatedClass.class.getDeclaredMethod( |
| "methodWithAnnotatedParameter", int.class); |
| Annotation[][] paramAnnotations = method.getParameterAnnotations(); |
| TestAnnotation realAnnotation = (TestAnnotation) paramAnnotations[0][0]; |
| |
| validateAnnotation(parameter, "Parameter", "Not assigned", realAnnotation); |
| } |
| |
| public void testAnnotatedWithArrayOfClasses() throws NotFoundException, |
| SecurityException, NoSuchMethodException { |
| JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName()); |
| JMethod annotatedMethod = annotatedClass.getMethod( |
| "annotatedWithArrayOfClasses", TypeOracle.NO_JTYPES); |
| |
| Method method = AnnotatedClass.class.getDeclaredMethod("annotatedWithArrayOfClasses"); |
| TestAnnotation realAnnotation = method.getAnnotation(TestAnnotation.class); |
| |
| validateAnnotation(annotatedMethod, "Method", "Not assigned", |
| realAnnotation); |
| } |
| |
| /** |
| * Tests translatable classes that are annotated with annotations for which we |
| * have no source. |
| */ |
| public void testBinaryOnlyAnnotation() throws NotFoundException { |
| // It is an error if we fail to get the type. |
| JClassType classType = typeOracle.getType(ClassAnnotatedWithBinaryOnlyAnnotation.class.getCanonicalName()); |
| |
| BinaryOnlyAnnotation annotation = classType.getAnnotation(BinaryOnlyAnnotation.class); |
| assertNotNull(annotation); |
| assertEquals(File.class, annotation.jreClassLiteralReference()); |
| } |
| |
| /** |
| * Ensures that we properly handle primitive value attributes on annotations. |
| * (Special-cased, because of how JDT handles char/numeric literals) |
| */ |
| public void testPrimitiveValuesAnnotations() throws NotFoundException { |
| JClassType primitivesAnnotatedClass = typeOracle.getType(PrimitivesAnnotatedClass.class.getName()); |
| PrimitiveValuesAnnotation annotation = primitivesAnnotatedClass.getAnnotation(PrimitiveValuesAnnotation.class); |
| |
| boolean bool = annotation.bool(); |
| assertTrue(bool); |
| |
| byte b = annotation.b(); |
| assertTrue(b > 0); |
| |
| char c = annotation.c(); |
| assertTrue(c > 0); |
| |
| double d = annotation.d(); |
| assertTrue(d > 0); |
| |
| float f = annotation.f(); |
| assertTrue(f > 0); |
| |
| int i = annotation.i(); |
| assertTrue(i > 0); |
| |
| long l = annotation.l(); |
| assertTrue(l > 0); |
| |
| short s = annotation.s(); |
| assertTrue(s > 0); |
| |
| int[] ia = annotation.ia(); |
| assertEquals(3, ia.length); |
| for (int it = 0; it < 3; ++it) { |
| assertEquals(it, ia[it]); |
| } |
| } |
| } |