/* * Grapht, an open source dependency injector. * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt) * Copyright 2010-2014 Regents of the University of Minnesota * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of the * License, or (at your option) any later version. * * This program 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 for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.grouplens.grapht.util; import com.sun.tools.javac.code.Attribute; import org.grouplens.grapht.annotation.AnnotationBuilder; import org.grouplens.grapht.reflect.internal.types.InterfaceA; import org.junit.Assert; import org.junit.Test; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; public class AnnotationBuilderTest { @Test public void testArrayCloned() { // verify that array values are clones of the original // to prevent contamination, and that returned values are also // clones to prevent post-contamination double[] original = new double[] { 4.0 }; A3 built = new AnnotationBuilder<A3>(A3.class).set("otherValue", original).build(); double[] fromAnnot = built.otherValue(); original[0] = 5.0; Assert.assertEquals(4.0, fromAnnot[0], 0.00001); fromAnnot[0] = 6.0; Assert.assertEquals(4.0, built.otherValue()[0], 0.00001); } @Test public void testDefaultValue() { // verify that a default value is returned when nothing was assigned to it A3 built = new AnnotationBuilder<A3>(A3.class).set("otherValue", new double[0]).build(); Assert.assertEquals("hello", built.value()); } @Test(expected=IllegalArgumentException.class) public void testUnknownAttribute() { // verify that an attribute name not defined in the // annotation fails new AnnotationBuilder<A3>(A3.class).set("notPresent", 4).build(); } @Test(expected=IllegalArgumentException.class) public void testWrongSetter() { // verify that an attribute called with the wrong argument // type fails new AnnotationBuilder<A2>(A2.class).set("value", 6.0).build(); } @Test(expected=IllegalStateException.class) public void testNoValueAssignedForRequiredAttribute() { // verify that not assigning a required fails at build time new AnnotationBuilder<A2>(A2.class).build(); } @Test public void testSetValues() { // verify that all setters set the expected values Types t = new AnnotationBuilder<Types>(Types.class) .set("v1", (byte) 1) .set("v2", (short) 2) .set("v3", 3) .set("v4", 4L) .set("v5", '5') .set("v6", 6f) .set("v7", 7.0) .set("v8", "8") .set("v9", new byte[] { 9 }) .set("v10", new short[] { 10 }) .set("v11", new int[] { 11 }) .set("v12", new long[] { 12 }) .set("v13", new char[] { 't' }) .set("v14", new float[] { 14f }) .set("v15", new double[] { 15.0 }) .set("v16", new String[] { "16" }) .set("v17", new AnnotationBuilder<A2>(A2.class).set("value", 17).build()) .set("v18", new A2[] { new AnnotationBuilder<A2>(A2.class).set("value", 18).build() }) .set("v19", true) .set("v20", new boolean[]{true, false}) .set("v21", new AnnotationBuilder<A5>(A5.class).set("value", 0).build()) .set("v22", new AnnotationBuilder<A6>(A6.class).set("value", Class.class).build()) .build(); Assert.assertEquals((byte) 1, t.v1()); Assert.assertEquals((short) 2, t.v2()); Assert.assertEquals(3, t.v3()); Assert.assertEquals(4L, t.v4()); Assert.assertEquals('5', t.v5()); Assert.assertEquals(6f, t.v6(), 0.00001f); Assert.assertEquals(7.0, t.v7(), 0.00001); Assert.assertEquals("8", t.v8()); Assert.assertEquals(1, t.v9().length); Assert.assertEquals((byte) 9, t.v9()[0]); Assert.assertEquals(1, t.v10().length); Assert.assertEquals((short) 10, t.v10()[0]); Assert.assertEquals(1, t.v11().length); Assert.assertEquals(11, t.v11()[0]); Assert.assertEquals(1, t.v12().length); Assert.assertEquals(12L, t.v12()[0]); Assert.assertEquals(1, t.v13().length); Assert.assertEquals('t', t.v13()[0]); Assert.assertEquals(1, t.v14().length); Assert.assertEquals(14f, t.v14()[0], 0.00001f); Assert.assertEquals(1, t.v15().length); Assert.assertEquals(15.0, t.v15()[0], 0.00001); Assert.assertEquals(1, t.v16().length); Assert.assertEquals("16", t.v16()[0]); Assert.assertEquals(17, t.v17().value()); Assert.assertEquals(1, t.v18().length); Assert.assertEquals(18, t.v18()[0].value()); Assert.assertTrue(t.v19()); Assert.assertEquals(2, t.v20().length); Assert.assertTrue(t.v20()[0]); Assert.assertFalse(t.v20()[1]); Assert.assertEquals(RestrictionType.NONE, t.v21().type()); Assert.assertEquals(Class.class, t.v22().value()); } @Test public void testNoAttributes() { // verify that a no attribute annotation implements // the annotation type, hashCode, and equals properly A1 built = new AnnotationBuilder<A1>(A1.class).build(); Assert.assertEquals(A1.class, built.annotationType()); Assert.assertTrue(built.equals(jvmA1a1)); Assert.assertTrue(jvmA1a1.equals(built)); Assert.assertEquals(jvmA1a1.hashCode(), built.hashCode()); } @Test public void testSingleAttribute() { // verify that a single attribute correctly implements // the annotation type, hashCode, and equals properly A2 equal = new AnnotationBuilder<A2>(A2.class).set("value", 4).build(); A2 notEqual = new AnnotationBuilder<A2>(A2.class).set("value", 0).build(); Assert.assertEquals(A2.class, equal.annotationType()); Assert.assertEquals(A2.class, notEqual.annotationType()); Assert.assertTrue(equal.equals(jvmA2a1)); Assert.assertTrue(jvmA2a1.equals(equal)); Assert.assertEquals(jvmA2a1.hashCode(), equal.hashCode()); Assert.assertFalse(notEqual.equals(jvmA2a1)); Assert.assertFalse(jvmA2a1.equals(notEqual)); Assert.assertFalse(jvmA2a1.hashCode() == notEqual.hashCode()); } @Test public void testMultipleAttribute() { // verify that multiple attributes correctly implements // the annotation type, hashCode, and equals properly A3 equal = new AnnotationBuilder<A3>(A3.class).set("value", "world") .set("otherValue", new double[] { 1.0, 2.0 }) .build(); A3 notEqual = new AnnotationBuilder<A3>(A3.class).set("value", "hoopla") .set("otherValue", new double[] { 1.0, 2.0 }) .build(); Assert.assertEquals(A3.class, equal.annotationType()); Assert.assertEquals(A3.class, notEqual.annotationType()); Assert.assertTrue(equal.equals(jvmA3a1)); Assert.assertTrue(jvmA3a1.equals(equal)); Assert.assertEquals(jvmA3a1.hashCode(), equal.hashCode()); Assert.assertFalse(notEqual.equals(jvmA3a1)); Assert.assertFalse(jvmA3a1.equals(notEqual)); Assert.assertFalse(jvmA3a1.hashCode() == notEqual.hashCode()); } @Test public void testAnnotationArrayAttribute() { // verify that an annotation with annotation arrays implements // the annotation type, hashCode, and equals properly A4 equal = new AnnotationBuilder<A4>(A4.class).set("arrays", new A3[] { new AnnotationBuilder<A3>(A3.class).set("otherValue", new double[] { 0.5 }).build(), new AnnotationBuilder<A3>(A3.class).set("otherValue", new double[] { 0.0 }) .set("value", "george").build() }).build(); A4 notEqual = new AnnotationBuilder<A4>(A4.class).set("arrays", new A3[] { new AnnotationBuilder<A3>(A3.class).set("otherValue", new double[] { 0.4, 0.2 }).build(), new AnnotationBuilder<A3>(A3.class).set("otherValue", new double[] { 0.0, 2.3 }) .set("value", "bob").build() }).build(); Assert.assertEquals(A4.class, equal.annotationType()); Assert.assertEquals(A4.class, notEqual.annotationType()); Assert.assertTrue(equal.equals(jvmA4a1)); Assert.assertTrue(jvmA4a1.equals(equal)); Assert.assertEquals(jvmA4a1.hashCode(), equal.hashCode()); Assert.assertFalse(notEqual.equals(jvmA4a1)); Assert.assertFalse(jvmA4a1.equals(notEqual)); Assert.assertFalse(jvmA4a1.hashCode() == notEqual.hashCode()); } private static final A1 jvmA1a1; private static final A2 jvmA2a1; private static final A3 jvmA3a1; private static final A4 jvmA4a1; static { try { jvmA1a1 = AP.class. getMethod("a1").getAnnotation(A1.class); jvmA2a1 = AP.class.getMethod("a1").getAnnotation(A2.class); jvmA3a1 = AP.class.getMethod("a1").getAnnotation(A3.class); jvmA4a1 = AP.class.getMethod("a1").getAnnotation(A4.class); } catch(Exception e) { throw new RuntimeException(e); } } public static class AP { @A1 @A2(4) @A3(otherValue={ 1.0, 2.0 }, value="world") @A4(arrays={ @A3(otherValue=0.5), @A3(otherValue=0.0, value="george") }) public void a1() { } } @Retention(RetentionPolicy.RUNTIME) public static @interface A1 { } @Retention(RetentionPolicy.RUNTIME) public static @interface A2 { int value(); } @Retention(RetentionPolicy.RUNTIME) public static @interface A3 { double[] otherValue(); String value() default "hello"; } @Retention(RetentionPolicy.RUNTIME) public static @interface A4 { A3[] arrays(); } @Retention(RetentionPolicy.RUNTIME) public static @interface A5 { int value() default 0; RestrictionType type() default RestrictionType.NONE; } public enum RestrictionType { NONE, LENGTH, FRACTION_DIGIT } @Retention(RetentionPolicy.RUNTIME) public static @interface A6 { Class value() default Class.class; } @Retention(RetentionPolicy.RUNTIME) public static @interface Types { byte v1(); short v2(); int v3(); long v4(); char v5(); float v6(); double v7(); String v8(); byte[] v9(); short[] v10(); int[] v11(); long[] v12(); char[] v13(); float[] v14(); double[] v15(); String[] v16(); A2 v17(); A2[] v18(); boolean v19(); boolean[] v20(); A5 v21(); A6 v22(); } }