View Javadoc

1   /*
2    * Grapht, an open source dependency injector.
3    * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
4    * Copyright 2010-2014 Regents of the University of Minnesota
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation; either version 2.1 of the
9    * License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14   * details.
15   *
16   * You should have received a copy of the GNU General Public License along with
17   * this program; if not, write to the Free Software Foundation, Inc., 51
18   * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19   */
20  package org.grouplens.grapht.util;
21  
22  import com.sun.tools.javac.code.Attribute;
23  import org.grouplens.grapht.annotation.AnnotationBuilder;
24  import org.grouplens.grapht.reflect.internal.types.InterfaceA;
25  import org.junit.Assert;
26  import org.junit.Test;
27  
28  import java.lang.annotation.Retention;
29  import java.lang.annotation.RetentionPolicy;
30  
31  
32  public class AnnotationBuilderTest {
33      @Test
34      public void testArrayCloned() {
35          // verify that array values are clones of the original
36          // to prevent contamination, and that returned values are also
37          // clones to prevent post-contamination
38          
39          double[] original = new double[] { 4.0 };
40          A3 built = new AnnotationBuilder<A3>(A3.class).set("otherValue", original).build();
41          double[] fromAnnot = built.otherValue();
42  
43          original[0] = 5.0;
44          Assert.assertEquals(4.0, fromAnnot[0], 0.00001);
45          
46          fromAnnot[0] = 6.0;
47          Assert.assertEquals(4.0, built.otherValue()[0], 0.00001);
48      }
49      
50      @Test
51      public void testDefaultValue() {
52          // verify that a default value is returned when nothing was assigned to it
53          A3 built = new AnnotationBuilder<A3>(A3.class).set("otherValue", new double[0]).build();
54          
55          Assert.assertEquals("hello", built.value());
56      }
57      
58      @Test(expected=IllegalArgumentException.class)
59      public void testUnknownAttribute() {
60          // verify that an attribute name not defined in the 
61          // annotation fails
62          new AnnotationBuilder<A3>(A3.class).set("notPresent", 4).build();
63      }
64      
65      @Test(expected=IllegalArgumentException.class)
66      public void testWrongSetter() {
67          // verify that an attribute called with the wrong argument
68          // type fails
69          new AnnotationBuilder<A2>(A2.class).set("value", 6.0).build();
70      }
71      
72      @Test(expected=IllegalStateException.class)
73      public void testNoValueAssignedForRequiredAttribute() {
74          // verify that not assigning a required fails at build time
75          new AnnotationBuilder<A2>(A2.class).build();
76      }
77      
78      @Test
79      public void testSetValues() {
80          // verify that all setters set the expected values
81          Types t = new AnnotationBuilder<Types>(Types.class)
82              .set("v1", (byte) 1)
83              .set("v2", (short) 2)
84              .set("v3", 3)
85              .set("v4", 4L)
86              .set("v5", '5')
87              .set("v6", 6f)
88              .set("v7", 7.0)
89              .set("v8", "8")
90              .set("v9", new byte[] { 9 })
91              .set("v10", new short[] { 10 })
92              .set("v11", new int[] { 11 })
93              .set("v12", new long[] { 12 })
94              .set("v13", new char[] { 't' })
95              .set("v14", new float[] { 14f })
96              .set("v15", new double[] { 15.0 })
97              .set("v16", new String[] { "16" })
98              .set("v17", new AnnotationBuilder<A2>(A2.class).set("value", 17).build())
99              .set("v18", new A2[] { new AnnotationBuilder<A2>(A2.class).set("value", 18).build() })
100             .set("v19", true)
101             .set("v20", new boolean[]{true, false})
102             .set("v21", new AnnotationBuilder<A5>(A5.class).set("value", 0).build())
103             .set("v22", new AnnotationBuilder<A6>(A6.class).set("value", Class.class).build())
104             .build();
105 
106         Assert.assertEquals((byte) 1, t.v1());
107         Assert.assertEquals((short) 2, t.v2());
108         Assert.assertEquals(3, t.v3());
109         Assert.assertEquals(4L, t.v4());
110         Assert.assertEquals('5', t.v5());
111         Assert.assertEquals(6f, t.v6(), 0.00001f);
112         Assert.assertEquals(7.0, t.v7(), 0.00001);
113         Assert.assertEquals("8", t.v8());
114         
115         Assert.assertEquals(1, t.v9().length);
116         Assert.assertEquals((byte) 9, t.v9()[0]);
117         
118         Assert.assertEquals(1, t.v10().length);
119         Assert.assertEquals((short) 10, t.v10()[0]);
120         
121         Assert.assertEquals(1, t.v11().length);
122         Assert.assertEquals(11, t.v11()[0]);
123         
124         Assert.assertEquals(1, t.v12().length);
125         Assert.assertEquals(12L, t.v12()[0]);
126         
127         Assert.assertEquals(1, t.v13().length);
128         Assert.assertEquals('t', t.v13()[0]);
129         
130         Assert.assertEquals(1, t.v14().length);
131         Assert.assertEquals(14f, t.v14()[0], 0.00001f);
132         
133         Assert.assertEquals(1, t.v15().length);
134         Assert.assertEquals(15.0, t.v15()[0], 0.00001);
135         
136         Assert.assertEquals(1, t.v16().length);
137         Assert.assertEquals("16", t.v16()[0]);
138         
139         Assert.assertEquals(17, t.v17().value());
140         
141         Assert.assertEquals(1, t.v18().length);
142         Assert.assertEquals(18, t.v18()[0].value());
143         
144         Assert.assertTrue(t.v19());
145         
146         Assert.assertEquals(2, t.v20().length);
147         Assert.assertTrue(t.v20()[0]);
148         Assert.assertFalse(t.v20()[1]);
149 
150         Assert.assertEquals(RestrictionType.NONE, t.v21().type());
151 
152         Assert.assertEquals(Class.class, t.v22().value());
153 
154     }
155     
156     @Test
157     public void testNoAttributes() {
158         // verify that a no attribute annotation implements
159         // the annotation type, hashCode, and equals properly
160         A1 built = new AnnotationBuilder<A1>(A1.class).build();
161         
162         Assert.assertEquals(A1.class, built.annotationType());
163         Assert.assertTrue(built.equals(jvmA1a1));
164         Assert.assertTrue(jvmA1a1.equals(built));
165         Assert.assertEquals(jvmA1a1.hashCode(), built.hashCode());
166     }
167     
168     @Test
169     public void testSingleAttribute() {
170         // verify that a single attribute correctly implements
171         // the annotation type, hashCode, and equals properly
172         A2 equal = new AnnotationBuilder<A2>(A2.class).set("value", 4).build();
173         A2 notEqual = new AnnotationBuilder<A2>(A2.class).set("value", 0).build();
174 
175         Assert.assertEquals(A2.class, equal.annotationType());
176         Assert.assertEquals(A2.class, notEqual.annotationType());
177         Assert.assertTrue(equal.equals(jvmA2a1));
178         Assert.assertTrue(jvmA2a1.equals(equal));
179         Assert.assertEquals(jvmA2a1.hashCode(), equal.hashCode());
180         
181         Assert.assertFalse(notEqual.equals(jvmA2a1));
182         Assert.assertFalse(jvmA2a1.equals(notEqual));
183         Assert.assertFalse(jvmA2a1.hashCode() == notEqual.hashCode());
184     }
185     
186     @Test
187     public void testMultipleAttribute() {
188         // verify that multiple attributes correctly implements
189         // the annotation type, hashCode, and equals properly
190         A3 equal = new AnnotationBuilder<A3>(A3.class).set("value", "world")
191                                                       .set("otherValue", new double[] { 1.0, 2.0 })
192                                                       .build();
193         A3 notEqual = new AnnotationBuilder<A3>(A3.class).set("value", "hoopla")
194                                                          .set("otherValue", new double[] { 1.0, 2.0 })
195                                                          .build();
196 
197         Assert.assertEquals(A3.class, equal.annotationType());
198         Assert.assertEquals(A3.class, notEqual.annotationType());
199         Assert.assertTrue(equal.equals(jvmA3a1));
200         Assert.assertTrue(jvmA3a1.equals(equal));
201         Assert.assertEquals(jvmA3a1.hashCode(), equal.hashCode());
202         
203         Assert.assertFalse(notEqual.equals(jvmA3a1));
204         Assert.assertFalse(jvmA3a1.equals(notEqual));
205         Assert.assertFalse(jvmA3a1.hashCode() == notEqual.hashCode());
206     }
207     
208     @Test
209     public void testAnnotationArrayAttribute() {
210         // verify that an annotation with annotation arrays implements
211         // the annotation type, hashCode, and equals properly
212         A4 equal = new AnnotationBuilder<A4>(A4.class).set("arrays", new A3[] {
213             new AnnotationBuilder<A3>(A3.class).set("otherValue", new double[] { 0.5 }).build(),
214             new AnnotationBuilder<A3>(A3.class).set("otherValue", new double[] { 0.0 })
215                                                .set("value", "george").build()
216         }).build();
217         A4 notEqual = new AnnotationBuilder<A4>(A4.class).set("arrays", new A3[] {
218             new AnnotationBuilder<A3>(A3.class).set("otherValue", new double[] { 0.4, 0.2 }).build(),
219             new AnnotationBuilder<A3>(A3.class).set("otherValue", new double[] { 0.0, 2.3 })
220                                                .set("value", "bob").build()
221         }).build();
222 
223         Assert.assertEquals(A4.class, equal.annotationType());
224         Assert.assertEquals(A4.class, notEqual.annotationType());
225         Assert.assertTrue(equal.equals(jvmA4a1));
226         Assert.assertTrue(jvmA4a1.equals(equal));
227         Assert.assertEquals(jvmA4a1.hashCode(), equal.hashCode());
228         
229         Assert.assertFalse(notEqual.equals(jvmA4a1));
230         Assert.assertFalse(jvmA4a1.equals(notEqual));
231         Assert.assertFalse(jvmA4a1.hashCode() == notEqual.hashCode());
232     }
233     
234     private static final A1 jvmA1a1;
235     private static final A2 jvmA2a1;
236     private static final A3 jvmA3a1;
237     private static final A4 jvmA4a1;
238     
239     static {
240         try {
241             jvmA1a1 = AP.class.
242                                       getMethod("a1").getAnnotation(A1.class);
243             jvmA2a1 = AP.class.getMethod("a1").getAnnotation(A2.class);
244             jvmA3a1 = AP.class.getMethod("a1").getAnnotation(A3.class);
245             jvmA4a1 = AP.class.getMethod("a1").getAnnotation(A4.class);
246         } catch(Exception e) {
247             throw new RuntimeException(e);
248         }
249     }
250     
251     public static class AP {
252         @A1 
253         @A2(4)
254         @A3(otherValue={ 1.0, 2.0 }, value="world")
255         @A4(arrays={ @A3(otherValue=0.5), @A3(otherValue=0.0, value="george") })
256         public void a1() { }
257     }
258 
259     @Retention(RetentionPolicy.RUNTIME)
260     public static @interface A1 { }
261     
262     @Retention(RetentionPolicy.RUNTIME)
263     public static @interface A2 {
264         int value();
265     }
266 
267     @Retention(RetentionPolicy.RUNTIME)
268     public static @interface A3 {
269         double[] otherValue();
270         String value() default "hello";
271     }
272     
273     @Retention(RetentionPolicy.RUNTIME)
274     public static @interface A4 {
275         A3[] arrays();
276     }
277 
278     @Retention(RetentionPolicy.RUNTIME)
279     public static @interface A5 {
280         int value() default 0;
281         RestrictionType type() default RestrictionType.NONE;
282     }
283 
284     public enum RestrictionType {
285         NONE, LENGTH, FRACTION_DIGIT
286     }
287 
288     @Retention(RetentionPolicy.RUNTIME)
289     public static @interface A6 {
290         Class value() default  Class.class;
291     }
292 
293     @Retention(RetentionPolicy.RUNTIME)
294     public static @interface Types {
295         byte v1();
296         short v2();
297         int v3();
298         long v4();
299         char v5();
300         float v6();
301         double v7();
302         String v8();
303         byte[] v9();
304         short[] v10();
305         int[] v11();
306         long[] v12();
307         char[] v13();
308         float[] v14();
309         double[] v15();
310         String[] v16();
311         A2 v17();
312         A2[] v18();
313         boolean v19();
314         boolean[] v20();
315         A5 v21();
316         A6 v22();
317     }
318 }