package tests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import com.sun.tools.javac.processing.JavacProcessingEnvironment; import com.sun.tools.javac.util.Context; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.type.TypeMirror; import org.checkerframework.framework.source.SourceChecker; import org.checkerframework.framework.util.AnnotationBuilder; import org.checkerframework.javacutil.AnnotationUtils; import org.checkerframework.javacutil.ErrorReporter; import org.junit.Ignore; import org.junit.Test; import testlib.util.AnnoWithStringArg; import testlib.util.Encrypted; import testlib.util.TestChecker; public class AnnotationBuilderTest { private final ProcessingEnvironment env; public AnnotationBuilderTest() { env = JavacProcessingEnvironment.instance(new Context()); ErrorReporter.setHandler(new TestChecker()); } @Test public void createAnnoWithoutValues() { AnnotationBuilder builder = new AnnotationBuilder(env, Encrypted.class); // AnnotationMirror anno = builder.build(); } @Test public void createAnnoWithoutValues1() { AnnotationBuilder builder = new AnnotationBuilder(env, AnnoWithStringArg.class); AnnotationMirror anno = builder.build(); assertEquals(0, anno.getElementValues().size()); } @Test public void createAnnoWithValues0() { AnnotationBuilder builder = new AnnotationBuilder(env, AnnoWithStringArg.class); builder.setValue("value", "m"); AnnotationMirror anno = builder.build(); assertEquals(1, anno.getElementValues().size()); } @Test(expected = SourceChecker.CheckerError.class) public void buildingTwice() { AnnotationBuilder builder = new AnnotationBuilder(env, Encrypted.class); builder.build(); builder.build(); } @Test(expected = SourceChecker.CheckerError.class) public void addingValuesAfterBuilding() { AnnotationBuilder builder = new AnnotationBuilder(env, AnnoWithStringArg.class); builder.setValue("value", "m"); // AnnotationMirror anno = builder.build(); builder.setValue("value", "n"); } @Test(expected = SourceChecker.CheckerError.class) public void notFoundElements() { AnnotationBuilder builder = new AnnotationBuilder(env, AnnoWithStringArg.class); builder.setValue("n", "m"); } @Test(expected = SourceChecker.CheckerError.class) public void illegalValue() { AnnotationBuilder builder = new AnnotationBuilder(env, AnnoWithStringArg.class); builder.setValue("value", 1); } public static @interface A { int[] numbers(); } public static @interface B { String[] strings(); } @Test public void listArrayPrimitive() { AnnotationBuilder builder = new AnnotationBuilder(env, A.class); builder.setValue("numbers", new Integer[] {34, 32, 43}); assertEquals(1, builder.build().getElementValues().size()); } @Test public void listArrayObject() { AnnotationBuilder builder = new AnnotationBuilder(env, B.class); builder.setValue("strings", new String[] {"m", "n"}); assertEquals(1, builder.build().getElementValues().size()); } @Test(expected = SourceChecker.CheckerError.class) public void listArrayObjectWrongType() { AnnotationBuilder builder = new AnnotationBuilder(env, B.class); builder.setValue("strings", new Object[] {"m", "n", 1}); assertEquals(1, builder.build().getElementValues().size()); } @Test(expected = SourceChecker.CheckerError.class) public void listArrayObjectWrongType1() { AnnotationBuilder builder = new AnnotationBuilder(env, B.class); builder.setValue("strings", 1); assertEquals(1, builder.build().getElementValues().size()); } public static @interface Prim { int a(); } @Test public void primitiveValue() { AnnotationBuilder builder = new AnnotationBuilder(env, Prim.class); builder.setValue("a", 3); assertEquals(1, builder.build().getElementValues().size()); } @Test(expected = SourceChecker.CheckerError.class) public void primitiveValueWithException() { AnnotationBuilder builder = new AnnotationBuilder(env, A.class); builder.setValue("a", 3.0); assertEquals(1, builder.build().getElementValues().size()); } // Multiple values public static @interface Mult { int a(); String b(); } @Test public void multiple1() { AnnotationBuilder builder = new AnnotationBuilder(env, Mult.class); builder.setValue("a", 2); assertEquals(1, builder.build().getElementValues().size()); } @Test(expected = SourceChecker.CheckerError.class) public void multiple2() { AnnotationBuilder builder = new AnnotationBuilder(env, Mult.class); builder.setValue("a", "m"); assertEquals(1, builder.build().getElementValues().size()); } @Test public void multiple3() { AnnotationBuilder builder = new AnnotationBuilder(env, Mult.class); builder.setValue("a", 1); builder.setValue("b", "mark"); assertEquals(2, builder.build().getElementValues().size()); } public static @interface ClassElt { Class<?> value(); } @Test public void testClassPositive() { AnnotationBuilder builder = new AnnotationBuilder(env, ClassElt.class); builder.setValue("value", String.class); builder.setValue("value", int.class); builder.setValue("value", int[].class); builder.setValue("value", void.class); Object storedValue = builder.build().getElementValues().values().iterator().next().getValue(); assertTrue("storedValue is " + storedValue.getClass(), storedValue instanceof TypeMirror); } @Test(expected = SourceChecker.CheckerError.class) public void testClassNegative() { AnnotationBuilder builder = new AnnotationBuilder(env, ClassElt.class); builder.setValue("value", 2); } public static @interface RestrictedClassElt { Class<? extends Number> value(); } @Test public void testRestClassPositive() { AnnotationBuilder builder = new AnnotationBuilder(env, RestrictedClassElt.class); builder.setValue("value", Integer.class); } // Failing test for now. AnnotationBuilder is a bit permissive // It doesn't not check type argument subtyping @Test(expected = SourceChecker.CheckerError.class) @Ignore // bug for now public void testRetClassNegative() { AnnotationBuilder builder = new AnnotationBuilder(env, RestrictedClassElt.class); builder.setValue("value", String.class); } enum MyEnum { OK, NOT; } enum OtherEnum { TEST; } public static @interface EnumElt { MyEnum value(); } @Test public void testEnumPositive() { AnnotationBuilder builder = new AnnotationBuilder(env, EnumElt.class); builder.setValue("value", MyEnum.OK); builder.setValue("value", MyEnum.NOT); } @Test(expected = SourceChecker.CheckerError.class) public void testEnumNegative() { AnnotationBuilder builder = new AnnotationBuilder(env, EnumElt.class); builder.setValue("value", 2); } @Test(expected = SourceChecker.CheckerError.class) public void testEnumNegative2() { AnnotationBuilder builder = new AnnotationBuilder(env, EnumElt.class); builder.setValue("value", OtherEnum.TEST); } public static @interface Anno { String value(); int[] can(); } @Test public void testToString1() { AnnotationBuilder builder = new AnnotationBuilder(env, Anno.class); assertEquals("@tests.AnnotationBuilderTest.Anno", builder.build().toString()); } @Test public void testToString2() { AnnotationBuilder builder = new AnnotationBuilder(env, Anno.class); builder.setValue("value", "string"); assertEquals("@tests.AnnotationBuilderTest.Anno(\"string\")", builder.build().toString()); } @Test public void testToString3() { AnnotationBuilder builder = new AnnotationBuilder(env, Anno.class); builder.setValue("can", new Object[] {1}); assertEquals("@tests.AnnotationBuilderTest.Anno(can={1})", builder.build().toString()); } @Test public void testToString4() { AnnotationBuilder builder = new AnnotationBuilder(env, Anno.class); builder.setValue("value", "m"); builder.setValue("can", new Object[] {1}); assertEquals( "@tests.AnnotationBuilderTest.Anno(value=\"m\", can={1})", builder.build().toString()); } @Test public void testToString5() { AnnotationBuilder builder = new AnnotationBuilder(env, Anno.class); builder.setValue("can", new Object[] {1}); builder.setValue("value", "m"); assertEquals( "@tests.AnnotationBuilderTest.Anno(can={1}, value=\"m\")", builder.build().toString()); } public static @interface MyAnno {} public static @interface ContainingAnno { MyAnno value(); } @Test public void testAnnoAsArgPositive() { AnnotationMirror anno = AnnotationUtils.fromClass(env.getElementUtils(), MyAnno.class); AnnotationBuilder builder = new AnnotationBuilder(env, ContainingAnno.class); builder.setValue("value", anno); assertEquals( "@tests.AnnotationBuilderTest.ContainingAnno(@tests.AnnotationBuilderTest.MyAnno)", builder.build().toString()); } @Test(expected = SourceChecker.CheckerError.class) public void testAnnoAsArgNegative() { AnnotationMirror anno = AnnotationUtils.fromClass(env.getElementUtils(), Anno.class); AnnotationBuilder builder = new AnnotationBuilder(env, ContainingAnno.class); builder.setValue("value", anno); } }