View Javadoc
1   package net.sourceforge.jenesis4java.impl;
2   
3   /*
4    * #%L
5    * Jenesis 4 Java Code Generator
6    * %%
7    * Copyright (C) 2000 - 2016 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  import net.sourceforge.jenesis4java.*;
26  import net.sourceforge.jenesis4java.util.DeclarationBaseTest;
27  import net.sourceforge.jenesis4java.util.InstanceReplacingVisitor;
28  import net.sourceforge.jenesis4java.util.StatementTestBase;
29  import net.sourceforge.jenesis4java.util.WithVmAndPackageClass;
30  import org.junit.Before;
31  import org.junit.Test;
32  import org.junit.experimental.runners.Enclosed;
33  import org.junit.runner.RunWith;
34  
35  import java.util.Arrays;
36  import java.util.Collections;
37  
38  import static net.sourceforge.jenesis4java.Constructor.ForwardingTarget.SUPER;
39  import static net.sourceforge.jenesis4java.Constructor.ForwardingTarget.THIS;
40  import static net.sourceforge.jenesis4java.impl.CommentsTest.MultiLineComment.DEFAULT_MULTILINE_COMMENT;
41  import static net.sourceforge.jenesis4java.util.CodeGenerationAssertions.*;
42  import static net.sourceforge.jenesis4java.util.Shortcuts.dummyClass;
43  import static net.sourceforge.jenesis4java.util.TestHelper.LS;
44  import static org.junit.Assert.assertEquals;
45  import static org.junit.Assert.assertNull;
46  import static org.junit.Assert.assertSame;
47  
48  @RunWith(Enclosed.class)
49  public class ConstructorTest {
50  
51      public static class BasicSyntax extends WithVmAndPackageClass {
52  
53          @Test
54          public void emptyConstructor() {
55              assertEqualsIgnoreLineBreaks("Dummy() {}", packageClass.newConstructor().toString());
56          }
57  
58          @Test
59          public void accessModifier() {
60              Constructor constructor = packageClass.newConstructor();
61              constructor.setAccess(Access.PUBLIC);
62              assertEqualsIgnoreLineBreaks("public Dummy() {}", constructor.toString());
63          }
64  
65          @Test
66          public void singleParameter() {
67              Constructor constructor = packageClass.newConstructor();
68              constructor.addParameter(String.class, "name");
69              assertEqualsIgnoreLineBreaks("Dummy(String name) {}", constructor.toString());
70          }
71  
72          @Test
73          public void multipleParameters() {
74              Constructor constructor = packageClass.newConstructor();
75              constructor.addParameter(String.class, "name");
76              constructor.addParameter(vm.type_int(), "size");
77              assertEqualsIgnoreLineBreaks("Dummy(String name, int size) {}", constructor.toString());
78          }
79  
80          @Test
81          public void singleException() {
82              Constructor constructor = packageClass.newConstructor();
83              constructor.addThrows("Exception");
84              assertEqualsIgnoreLineBreaks("Dummy() throws Exception {}", constructor.toString());
85          }
86  
87          @Test
88          public void multipleExceptions() {
89              Constructor constructor = packageClass.newConstructor();
90              constructor.addThrows("IOException");
91              constructor.addThrows("OwnException");
92              assertEqualsIgnoreLineBreaks("Dummy() throws IOException, OwnException {}", constructor.toString());
93          }
94      }
95  
96      public static class Getters extends WithVmAndPackageClass {
97  
98          @Test
99          public void nothingSet() {
100             Constructor constructor = packageClass.newConstructor();
101             assertEquals(Collections.emptyList(), constructor.getParameters());
102             assertEquals(Collections.emptyList(), constructor.getThrows());
103         }
104 
105         @Test
106         public void setParameters() {
107             Constructor constructor = packageClass.newConstructor();
108             FormalParameter formalParameter1 = constructor.addParameter(String.class, "1");
109             FormalParameter formalParameter2 = constructor.addParameter(String.class, "2");
110             assertEquals(Arrays.asList(formalParameter1, formalParameter2), constructor.getParameters());
111             assertEquals(Collections.emptyList(), constructor.getThrows());
112         }
113 
114         @Test
115         public void setThrows() {
116             Constructor constructor = packageClass.newConstructor();
117             constructor.addThrows("X").addThrows("Y");
118             assertEquals(Collections.emptyList(), constructor.getParameters());
119             assertEquals(Arrays.asList("X", "Y"), constructor.getThrows());
120         }
121     }
122 
123     public static class InheritedFunctionality extends DeclarationBaseTest {
124 
125         @Override
126         public Declaration getInstance() {
127             return dummyClass().newConstructor();
128         }
129     }
130 
131     public static class TestConstructorForwarding {
132 
133         private Constructor constructor;
134 
135         private VirtualMachine vm;
136 
137         @Before
138         public void setUp() {
139             vm = VirtualMachine.getVirtualMachine();
140             constructor = dummyClass().newConstructor();
141         }
142 
143         @Test
144         public void superNoArgs() {
145             constructor.forwardCall(SUPER);
146             assertInsideBlock("super();", constructor);
147         }
148 
149         @Test
150         public void thisNoArgs() {
151             constructor.forwardCall(THIS);
152             assertInsideBlock("this();", constructor);
153         }
154 
155         @Test
156         public void thisOverwritesSuper() {
157             constructor.forwardCall(SUPER);
158             constructor.forwardCall(THIS);
159             assertInsideBlock("this();", constructor);
160         }
161 
162         @Test
163         public void superOverwritesThis() {
164             constructor.forwardCall(THIS);
165             constructor.forwardCall(SUPER);
166             assertInsideBlock("super();", constructor);
167         }
168 
169         @Test
170         public void thisBeforeOtherStatements() {
171             Statement stmt = constructor.newStmt(vm.newFree("expression"));
172             constructor.forwardCall(SUPER);
173             assertInsideBlock("super();" + LS + stmt.toString(), constructor);
174         }
175 
176         @Test
177         public void nullOverwritesForwarding() {
178             String constructorWithoutAnyForwarding = constructor.toString();
179             constructor.forwardCall(THIS);
180 
181             ConstructorForwarding constructorForwarding = constructor.forwardCall(null);
182             assertNull(constructorForwarding);
183             assertEquals(constructorWithoutAnyForwarding, constructor.toString());
184         }
185 
186         @Test
187         public void withTrailingComment() {
188             assertThatTrailingCommentIsOnSameLine(constructor.forwardCall(THIS));
189         }
190 
191         @Test
192         public void withBlockComment() {
193             ConstructorForwarding thisForwarding = constructor.forwardCall(THIS);
194             String withoutComment = thisForwarding.toString();
195             thisForwarding.setComment(Comment.MULTI_LINE, "comment");
196             assertEquals(DEFAULT_MULTILINE_COMMENT + withoutComment, thisForwarding.toString());
197         }
198 
199         @Test
200         public void oneArgument() {
201             ConstructorForwarding thisForwarding = constructor.forwardCall(THIS);
202             ConstructorForwarding returned = thisForwarding.addVariableArg("var");
203             assertEquals("this(var);", thisForwarding.toString());
204             assertSame(thisForwarding, returned);
205         }
206 
207         @Test
208         public void severalArgumentsWithChaining() {
209             ConstructorForwarding superForwarding = constructor.forwardCall(SUPER);
210             ConstructorForwarding returned = //
211                     superForwarding.addArg(true) //
212                             .addArg(0.1d) //
213                             .addArg(vm.newFree("free")) //
214                             .addArg(1.23f) //
215                             .addArg(123) //
216                             .addArg(456L) //
217                             .addArg("string");
218 
219             assertEquals(7, superForwarding.getArgs().size());
220             assertEquals("super(true, 0.1D, free, 1.23F, 123, 456L, \"string\");", superForwarding.toString());
221             assertSame(superForwarding, returned);
222         }
223 
224         @Test
225         public void removeArg() {
226             ConstructorForwarding superForwarding = constructor.forwardCall(SUPER);
227             String beforeAddRemove = superForwarding.toString();
228             superForwarding.addArg(true).removeArg(0);
229             String afterAddRemove = superForwarding.toString();
230             assertEquals(beforeAddRemove, afterAddRemove);
231         }
232 
233         @Test(expected = IllegalArgumentException.class)
234         public void removeArgTooBig() {
235             ConstructorForwarding superForwarding = constructor.forwardCall(SUPER);
236             superForwarding.addArg("1");
237             superForwarding.removeArg(1);
238         }
239 
240         @Test(expected = IllegalArgumentException.class)
241         public void removeArgTooSmall() {
242             ConstructorForwarding superForwarding = constructor.forwardCall(SUPER);
243             superForwarding.removeArg(-1);
244         }
245 
246         @Test
247         public void getForwardingTarget() {
248             assertEquals(SUPER, constructor.forwardCall(SUPER).getTarget());
249             assertEquals(THIS, constructor.forwardCall(THIS).getTarget());
250         }
251 
252         @Test
253         public void useQualifier() {
254             ConstructorForwarding superForwarding = constructor.forwardCall(THIS);
255             superForwarding.setQualifier("Outer");
256             assertEquals("Outer.this();", superForwarding.toString());
257         }
258 
259         @Test
260         public void setAndGetQualifier() {
261             ConstructorForwarding superForwarding = constructor.forwardCall(THIS);
262             superForwarding.setQualifier("Outer");
263             assertEquals(vm.newClassLiteral("Outer").toString(), superForwarding.getQualifier().toString());
264             // FIXME: toString-hack should be replaced with equals
265         }
266 
267         @Test
268         public void noQualifier() {
269             ConstructorForwarding superForwarding = constructor.forwardCall(THIS);
270             assertNull(superForwarding.getQualifier());
271         }
272     }
273 
274     public static class ConstructorForwardingInheritedFunctionality extends StatementTestBase {
275 
276         @Override
277         public Statement getInstance() {
278             return dummyClass().newConstructor().forwardCall(THIS);
279         }
280     }
281 
282     public static class Visitor extends WithVmAndPackageClass {
283 
284         @Test
285         public void replaceForwarding() {
286             Constructor constructor = packageClass.newConstructor();
287             ConstructorForwarding superForward = constructor.forwardCall(SUPER);
288             ConstructorForwarding thisForward = constructor.forwardCall(THIS);
289             constructor.visit(new InstanceReplacingVisitor(thisForward, superForward));
290             assertInsideBlock("super();", constructor);
291         }
292 
293         @Test
294         public void replaceArgInConstructorForwarding() {
295             Constructor constructor = packageClass.newConstructor();
296             ConstructorForwarding superForward = constructor.forwardCall(SUPER);
297             Expression original = vm.newFree("original");
298             superForward.addArg(original);
299 
300             Expression replacement = vm.newFree("replacement");
301             superForward.visit(new InstanceReplacingVisitor(original, replacement));
302             assertEquals(Collections.singletonList(replacement), superForward.getArgs());
303         }
304 
305     }
306 }