View Javadoc
1   package net.sourceforge.jenesis4java.impl;
2   
3   /*
4    * #%L
5    * Jenesis 4 Java Code Generator
6    * %%
7    * Copyright (C) 2000 - 2015 jenesis4java
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * #L%
23   */
24  
25  /**
26   * Copyright (C) 2008 Richard van Nieuwenhoven - ritchie [at] gmx [dot] at This
27   * program is free software; you can redistribute it and/or modify it under the
28   * terms of the GNU Lesser General Public License as published by the Free
29   * Software Foundation; either version 2 of the License, or (at your option) any
30   * later version. This program is distributed in the hope that it will be
31   * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
32   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
33   * General Public License for more details. You should have received a copy of
34   * the GNU Lesser General Public License along with this program; if not, write
35   * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
36   * MA 02111-1307, USA.
37   */
38  
39  import net.sourceforge.jenesis4java.*;
40  import net.sourceforge.jenesis4java.util.VmInTempFolder;
41  import org.junit.Before;
42  import org.junit.Ignore;
43  import org.junit.Rule;
44  import org.junit.Test;
45  import org.junit.experimental.runners.Enclosed;
46  import org.junit.runner.RunWith;
47  
48  import java.io.IOException;
49  import java.lang.annotation.Target;
50  import java.util.Arrays;
51  import java.util.List;
52  
53  import static org.junit.Assert.*;
54  
55  @RunWith(Enclosed.class)
56  public class AnnotationTest {
57  
58      public static class IntegrationTests {
59  
60          @Rule
61          public VmInTempFolder vmInTmpDirectory = new VmInTempFolder();
62  
63          @Test
64          public void test() throws IOException {
65              VirtualMachine vm = vmInTmpDirectory.getVm();
66              CompilationUnit unit = vmInTmpDirectory.newCompilationUnit();
67              PackageClass cls = unit.newClass("HelloWorld");
68              cls.setAccess(Access.PUBLIC);
69  
70              ClassMethod method = cls.newMethod(vm.newType(Type.VOID), "main");
71              method.setAccess(Access.PUBLIC);
72              method.isStatic(true);
73              method.addParameter(vm.newArray("String", 1), "argv");
74  
75              cls.addAnnotation("Simple(annotation=\"test\")");
76              Annotation simple2 = cls.addAnnotation("Simple2");
77              simple2.addAnnotationAttribute("annotation2", vm.newString("test2"));
78  
79              Annotation ann3 = cls.addAnnotation("Simple3");
80  
81              ann3.addAnnotationAttribute("annotation3", vm.newString("test3"));
82              ann3.addAnnotationAttribute("annotation3a", vm.newString("test3a"));
83              cls.addAnnotation("NamedQueries");
84  
85              for (Annotation annotation : cls.getAnnotations()) {
86                  if ("NamedQueries".equals(annotation.getEffectiveName())) {
87                      AnnotationAttribute valueAttribute = annotation.addAnnotationAttribute((String) null);
88                      Annotation innerValue1 = vm.newAnnotation("NamedQuery");
89                      innerValue1.addDefaultValueAttribute(vm.newString("text1"));
90                      Annotation innerValue2 = vm.newAnnotation("NamedQuery");
91                      innerValue2.addDefaultValueAttribute(vm.newString("text2"));
92                      valueAttribute.addValueAnnotation(innerValue1);
93                      valueAttribute.addValueAnnotation(innerValue2);
94                  }
95              }
96  
97              String unitJavaCode = unit.toString();
98              int index = unitJavaCode.indexOf("@Simple");
99              assertTrue(unitJavaCode.indexOf("HelloWorld") > index && index > 0);
100             index = unitJavaCode.indexOf("@Simple3");
101             assertTrue(unitJavaCode.indexOf("HelloWorld") > index && index > 0);
102             index = unitJavaCode.indexOf("@NamedQueries");
103             assertTrue(unitJavaCode.indexOf("HelloWorld") > index && index > 0);
104             index = unitJavaCode.indexOf("@NamedQuery");
105             assertTrue(unitJavaCode.indexOf("@NamedQueries") < index && index > 0);
106         }
107     }
108 
109     public static class InstantiationAndCodeGeneration {
110 
111         private VirtualMachine vm;
112 
113         @Before
114         public void setUp() {
115             this.vm = VirtualMachine.getVirtualMachine();
116         }
117 
118         @Test
119         public void annotationWithoutParametersFromClass() {
120             Annotation override = vm.newAnnotation(Override.class);
121             assertEquals("@Override", override.toString());
122         }
123 
124         @Test
125         public void annotationWithoutParametersFromString() {
126             Annotation override = vm.newAnnotation("Override");
127             assertEquals("@Override", override.toString());
128         }
129 
130         @Test
131         public void annotationWithDefaultText() {
132             Annotation annotation = vm.newAnnotation(SuppressWarnings.class);
133             annotation.addAnnotationAttribute("", vm.newString("explanation"));
134             assertEquals("@SuppressWarnings(\"explanation\")", annotation.toString());
135         }
136 
137         @Test
138         public void annotationWithSingleParameter() {
139             Annotation annotation = vm.newAnnotation(Test.class);
140             annotation.addAnnotationAttribute("expected", vm.newClassLiteral(vm.newType(Exception.class)));
141             assertEquals("@Test(expected = java.lang.Exception.class)", annotation.toString());
142         }
143 
144         @Test
145         public void annotationWithMultipleParameters() {
146             Annotation annotation = vm.newAnnotation(Test.class);
147             annotation.addAnnotationAttribute("expected", vm.newClassLiteral(vm.newType(Exception.class)));
148             annotation.addAnnotationAttribute("timeout", vm.newLong(500));
149             assertEquals("@Test(expected = java.lang.Exception.class, timeout = 500L)", annotation.toString());
150         }
151 
152         @Test
153         public void annotationParameterWithoutValueGetsIgnored() {
154             Annotation annotation = vm.newAnnotation(Test.class);
155             annotation.addAnnotationAttribute("expected", vm.newClassLiteral(vm.newType(Exception.class)));
156             annotation.addAnnotationAttribute("timeout", null);
157             assertEquals("@Test(expected = java.lang.Exception.class)", annotation.toString());
158         }
159 
160         @Test
161         public void annotationValueArrayWithEmptyKey() {
162             Annotation annotation = vm.newAnnotation(Test.class);
163             AnnotationAttribute attribute = annotation.addAnnotationAttribute("");
164             attribute.addValue(vm.newClassLiteral(vm.newType(String.class)));
165             attribute.addValue(vm.newClassLiteral(vm.newType(Integer.class)));
166             String expectedAnnotation = "@Test({\n" //
167                     + "    java.lang.String.class, java.lang.Integer.class\n" //
168                     + "})";
169             assertEquals(expectedAnnotation, annotation.toString());
170         }
171 
172         @Test
173         public void annotationParameterWithArray() {
174             Annotation annotation = vm.newAnnotation(Target.class);
175             AnnotationAttribute value = annotation.addAnnotationAttribute("value");
176             value.addValue(vm.newClassLiteral("ElementType.FIELD"));
177             value.addValue(vm.newClassLiteral("ElementType.METHOD"));
178 
179             String expectedAnnotation = "@Target(value = {\n" //
180                     + "    ElementType.FIELD.class, ElementType.METHOD.class\n" //
181                     + "})";
182 
183             assertEquals(expectedAnnotation, annotation.toString());
184         }
185 
186         @Test(expected = IllegalArgumentException.class)
187         // should be illegal, but requires cleaning up text/name confusion first
188         public void annotationNameStartsWithAt() {
189             vm.newAnnotation("@Name");
190         }
191 
192         @Test
193         public void annotationParameterWithoutKey() {
194             Annotation annotation = vm.newAnnotation("Name");
195             AnnotationAttribute value = annotation.addAnnotationAttribute((String) null);
196             value.addValue(vm.newInt(100));
197 
198             assertEquals("@Name(100)", annotation.toString());
199         }
200 
201         @Test
202         public void annotationsInAnnotation() {
203             Annotation annotation = vm.newAnnotation("Name");
204             AnnotationAttribute value = annotation.addAnnotationAttribute((String) null);
205             AnnotationAttribute valueAttribute = annotation.addAnnotationAttribute((String) null);
206             Annotation innerValue1 = vm.newAnnotation("InnerAnnotation");
207             innerValue1.addDefaultValueAttribute(vm.newString("text1"));
208             value.addValueAnnotation(innerValue1);
209             Annotation innerValue2 = vm.newAnnotation("InnerAnnotation");
210             innerValue2.addDefaultValueAttribute(vm.newString("text2"));
211             value.addValueAnnotation(innerValue2);
212 
213             String expectedAnnotation = "@Name({\n" //
214                     + "    @InnerAnnotation(\"text1\"), \n" //
215                     + "    @InnerAnnotation(\"text2\")\n" //
216                     + "})";
217 
218             assertEquals(expectedAnnotation, annotation.toString());
219         }
220 
221         @Test
222         public void setCompleteAnnotationAsText() {
223             Annotation annotation = vm.newAnnotation("Test(expected = RuntimeException.class)");
224             assertEquals("@Test(expected = RuntimeException.class)", annotation.toString());
225         }
226 
227         @Test
228         @Ignore
229         // broken -- figure out what the desired behavior is
230         public void annotationSetAnotherName() {
231             Annotation annotation = vm.newAnnotation(Override.class);
232             annotation.setName("Test");
233             assertEquals("@Test", annotation.toString());
234         }
235 
236         @Test
237         public void annotationSetClassAndText() {
238             Annotation annotation = vm.newAnnotation(Override.class);
239             annotation.setText("Annotation");
240             // text overwrites previously set class
241             assertEquals("@Annotation", annotation.toString());
242         }
243 
244         @Test
245         public void effectiveNameIfOnlyTextIsSet() {
246             Annotation annotation = vm.newAnnotation("Annotation");
247             assertEquals("Annotation", annotation.getEffectiveName());
248         }
249 
250         @Test
251         public void vmCreateAnnotationAttribute() {
252             AnnotationAttribute createdAttribute = vm.newAnnotationAttribute("key", vm.newString("value"));
253             assertEquals("key = \"value\"", createdAttribute.toString());
254         }
255 
256         @Test
257         public void vmCreateAnnotationWithSeveralAttributes() {
258             AnnotationAttribute createdAttribute = vm.newAnnotationAttribute("key", vm.newString("v1"), vm.newString("v2"), vm.newString("v3"));
259             String expected = "key = {\n" //
260                     + "    \"v1\", \"v2\", \"v3\"\n" //
261                     + "}";
262             assertEquals(expected, createdAttribute.toString());
263         }
264     }
265 
266     public static class AttributesAndText {
267 
268         private VirtualMachine vm;
269 
270         @Before
271         public void setUp() {
272             this.vm = VirtualMachine.getVirtualMachine();
273         }
274 
275         @Test
276         public void annotationAttribute() {
277             Annotation annotation = vm.newAnnotation("Name");
278             annotation.addAnnotationAttribute("key", vm.newString("value"));
279             assertEquals("@Name(key = \"value\")", annotation.toString());
280         }
281 
282         @Test
283         public void getRegularAttributeName() {
284             Annotation annotation = vm.newAnnotation("Name");
285             AnnotationAttribute actualAttribute = annotation.addAnnotationAttribute("attribute", vm.newInt(123));
286 
287             AnnotationAttribute returnedAttribute = annotation.getAnnotationAttribute("attribute");
288             assertEquals(actualAttribute, returnedAttribute);
289             assertEquals("attribute", returnedAttribute.getName());
290         }
291 
292         @Test
293         @Ignore
294         // produces illegal code
295         public void severalKeylessAttributes() {
296             Annotation annotation = vm.newAnnotation("Name");
297             annotation.addAnnotationAttribute("", vm.newString("value1"));
298             annotation.addAnnotationAttribute("", vm.newString("value2"));
299             // should we throw an Exception in this case?
300             assertEquals("@Name(key = \"value\")", annotation.toString());
301         }
302 
303         @Test
304         public void addDefaultAttributeWithOneValue() {
305             Annotation annotation = vm.newAnnotation("Name");
306             AnnotationAttribute attribute = annotation.addDefaultValueAttribute(vm.newString("value"));
307 
308             assertEquals("", attribute.getName());
309             assertEquals("@Name(\"value\")", annotation.toString());
310         }
311 
312         @Test
313         public void addDefaultAttributeWithoutValue() {
314             Annotation annotation = vm.newAnnotation("Name");
315             AnnotationAttribute attribute = annotation.addDefaultValueAttribute();
316 
317             assertEquals("", attribute.getName());
318             assertEquals("@Name", annotation.toString());
319         }
320 
321         @Test
322         public void addDefaultAttributeWithSeveralValues() {
323             Annotation annotation = vm.newAnnotation("Name");
324             AnnotationAttribute attribute = annotation.addDefaultValueAttribute(vm.newInt(1), vm.newInt(2), vm.newInt(4));
325 
326             assertEquals("", attribute.getName());
327             String expectedAnnotation = "" + //
328                     "@Name({\n" + //
329                     "    1, 2, 4\n" + //
330                     "})";
331             assertEquals(expectedAnnotation, annotation.toString());
332         }
333 
334         @Test
335         public void getDefaultValueAttributeName() {
336             Annotation annotation = vm.newAnnotation("Name");
337             AnnotationAttribute actualAttribute = annotation.addDefaultValueAttribute(vm.newInt(1));
338 
339             AnnotationAttribute returnedAttribute = annotation.getAnnotationAttribute("");
340             assertEquals(actualAttribute, returnedAttribute);
341             assertEquals("", returnedAttribute.getName());
342             assertTrue(returnedAttribute.isDefaultValueAttribute());
343         }
344 
345         @Test
346         public void changeNameOfDefaultValue() {
347             // TODO is this sensible, or should name be immutable?
348             Annotation annotation = vm.newAnnotation("Name");
349             AnnotationAttribute actualAttribute = annotation.addDefaultValueAttribute(vm.newInt(1));
350             AnnotationAttribute returnedAttribute = actualAttribute.setName("newName");
351             assertFalse(returnedAttribute.isDefaultValueAttribute());
352         }
353 
354         @Test
355         public void nullNameIsDefaultValue() {
356             Annotation annotation = vm.newAnnotation("Name");
357             AnnotationAttribute actualAttribute = annotation.addAnnotationAttribute(null, vm.newInt(876));
358 
359             AnnotationAttribute returnedAttribute = annotation.getAnnotationAttribute("");
360             assertEquals(actualAttribute, returnedAttribute);
361             assertEquals("", returnedAttribute.getName());
362             assertTrue(returnedAttribute.isDefaultValueAttribute());
363         }
364 
365         @Test
366         public void setName() {
367             Annotation annotation = vm.newAnnotation("Name");
368             AnnotationAttribute actualAttribute = annotation.addAnnotationAttribute(null, vm.newInt(876));
369 
370             String returnedName = actualAttribute.setName("foobar").getName();
371             assertEquals("foobar", returnedName);
372 
373             AnnotationAttribute returnedAttribute = annotation.getAnnotationAttribute("foobar");
374             assertEquals(actualAttribute, returnedAttribute);
375             assertFalse(returnedAttribute.isDefaultValueAttribute());
376         }
377 
378         @Test
379         public void addAndGetValuesCopy() {
380             Annotation annotation = vm.newAnnotation("Name");
381             Expression int0 = vm.newInt(0);
382             Expression int1 = vm.newInt(1);
383             Expression int2 = vm.newInt(2);
384 
385             AnnotationAttribute attribute = annotation.addAnnotationAttribute("key", int0);
386 
387             Iterable<Expression> values = Arrays.asList(int1, int2);
388             attribute.addValues(values);
389 
390             List<Expression> expectedValues = Arrays.asList(int0, int1, int2);
391             assertEquals(expectedValues, attribute.getValuesCopy());
392         }
393     }
394 
395 }