1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.google.api.generator.engine.ast;
16 
17 import static com.google.common.truth.Truth.assertThat;
18 import static org.junit.Assert.assertThrows;
19 
20 import java.util.Arrays;
21 import java.util.HashMap;
22 import org.junit.Test;
23 
24 public class VariableExprTest {
25   @Test
validVariableExpr_basic()26   public void validVariableExpr_basic() {
27     Variable variable = Variable.builder().setName("x").setType(TypeNode.INT).build();
28     VariableExpr variableExpr = VariableExpr.builder().setVariable(variable).build();
29     assertThat(variableExpr.variable()).isEqualTo(variable);
30     assertThat(variableExpr.type()).isEqualTo(TypeNode.INT);
31     assertThat(variableExpr.isDecl()).isFalse();
32     assertThat(variableExpr.isFinal()).isFalse();
33     assertThat(variableExpr.isStatic()).isFalse();
34     assertThat(variableExpr.scope()).isEqualTo(ScopeNode.LOCAL);
35   }
36 
37   @Test
validVariableExpr_staticReference()38   public void validVariableExpr_staticReference() {
39     VariableExpr.builder()
40         .setVariable(Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build())
41         .setStaticReferenceType(TypeNode.INT_OBJECT)
42         .build();
43   }
44 
45   @Test
validVariableExpr_classFieldOnStaticReference()46   public void validVariableExpr_classFieldOnStaticReference() {
47     VariableExpr.builder()
48         .setVariable(
49             Variable.builder()
50                 .setType(TypeNode.withReference(ConcreteReference.withClazz(Class.class)))
51                 .setName("class")
52                 .build())
53         .setStaticReferenceType(TypeNode.INT_OBJECT)
54         .build();
55   }
56 
57   @Test
validVariableExpr_classFieldOnExprReference()58   public void validVariableExpr_classFieldOnExprReference() {
59     VariableExpr.builder()
60         .setVariable(
61             Variable.builder()
62                 .setType(TypeNode.withReference(ConcreteReference.withClazz(Class.class)))
63                 .setName("class")
64                 .build())
65         .setExprReferenceExpr(
66             MethodInvocationExpr.builder()
67                 .setMethodName("foobar")
68                 .setReturnType(TypeNode.INT_OBJECT)
69                 .build())
70         .build();
71   }
72 
73   @Test
validVariableExpr_withFields()74   public void validVariableExpr_withFields() {
75     Variable variable = Variable.builder().setName("x").setType(TypeNode.STRING).build();
76     VariableExpr variableExpr =
77         VariableExpr.builder()
78             .setVariable(variable)
79             .setIsFinal(true)
80             .setIsStatic(true)
81             .setScope(ScopeNode.PRIVATE)
82             .build();
83     assertThat(variableExpr.variable()).isEqualTo(variable);
84     assertThat(variableExpr.type()).isEqualTo(TypeNode.STRING);
85     assertThat(variableExpr.isDecl()).isFalse();
86     assertThat(variableExpr.isFinal()).isTrue();
87     assertThat(variableExpr.isStatic()).isTrue();
88     assertThat(variableExpr.scope()).isEqualTo(ScopeNode.PRIVATE);
89   }
90 
91   @Test
validVariableExpr_declaration()92   public void validVariableExpr_declaration() {
93     Variable variable = Variable.builder().setName("x").setType(TypeNode.BOOLEAN).build();
94     VariableExpr variableExpr =
95         VariableExpr.builder().setVariable(variable).setIsDecl(true).build();
96     assertThat(variableExpr.variable()).isEqualTo(variable);
97     assertThat(variableExpr.type()).isEqualTo(TypeNode.VOID);
98     assertThat(variableExpr.isDecl()).isTrue();
99   }
100 
101   @Test
validVariableExpr_volatileDeclaration()102   public void validVariableExpr_volatileDeclaration() {
103     Variable variable = Variable.builder().setName("x").setType(TypeNode.BOOLEAN).build();
104     VariableExpr variableExpr =
105         VariableExpr.builder()
106             .setVariable(variable)
107             .setIsDecl(true)
108             .setIsVolatile(true)
109             .setIsStatic(true)
110             .setIsFinal(true)
111             .build();
112     assertThat(variableExpr.variable()).isEqualTo(variable);
113     assertThat(variableExpr.type()).isEqualTo(TypeNode.VOID);
114     assertThat(variableExpr.isDecl()).isTrue();
115     assertThat(variableExpr.isStatic()).isTrue();
116     assertThat(variableExpr.isFinal()).isTrue();
117     assertThat(variableExpr.isVolatile()).isTrue();
118   }
119 
120   @Test
validVariableExpr_reference()121   public void validVariableExpr_reference() {
122     Variable variable = Variable.builder().setName("x").setType(TypeNode.STRING_ARRAY).build();
123     VariableExpr variableExpr = VariableExpr.builder().setVariable(variable).build();
124 
125     Variable subVariable = Variable.builder().setName("length").setType(TypeNode.INT).build();
126     VariableExpr.builder().setVariable(subVariable).setExprReferenceExpr(variableExpr).build();
127     // No exception thrown, we're good.
128   }
129 
130   @Test
validVariableExpr_referenceWithModifiersSet()131   public void validVariableExpr_referenceWithModifiersSet() {
132     Variable variable = Variable.builder().setName("x").setType(TypeNode.STRING_ARRAY).build();
133     VariableExpr variableExpr = VariableExpr.builder().setVariable(variable).build();
134 
135     Variable subVariable = Variable.builder().setName("length").setType(TypeNode.INT).build();
136     VariableExpr.builder()
137         .setVariable(subVariable)
138         .setExprReferenceExpr(variableExpr)
139         .setIsStatic(true)
140         .setIsFinal(true)
141         .setScope(ScopeNode.PUBLIC)
142         .build();
143     // No exception thrown, we're good.
144   }
145 
146   @Test
validVariableExpr_templatedArgInMethod()147   public void validVariableExpr_templatedArgInMethod() {
148     Variable variable =
149         Variable.builder()
150             .setName("x")
151             .setType(TypeNode.withReference(ConcreteReference.withClazz(HashMap.class)))
152             .build();
153     VariableExpr.builder()
154         .setVariable(variable)
155         .setTemplateObjects(Arrays.asList("RequestT", "ResponseT"))
156         .build();
157     // No exception thrown, we're good.
158   }
159 
160   @Test
validVariableExpr_templatedArgNameAndTypeInMethod()161   public void validVariableExpr_templatedArgNameAndTypeInMethod() {
162     Variable variable =
163         Variable.builder()
164             .setName("x")
165             .setType(TypeNode.withReference(ConcreteReference.withClazz(HashMap.class)))
166             .build();
167     VariableExpr varExpr =
168         VariableExpr.builder()
169             .setVariable(variable)
170             .setTemplateObjects(Arrays.asList("RequestT", TypeNode.STRING))
171             .build();
172     assertThat(varExpr.templateNodes())
173         .containsExactly(IdentifierNode.withName("RequestT"), TypeNode.STRING);
174   }
175 
176   @Test
validVariableExpr_declarationWithAnnotations()177   public void validVariableExpr_declarationWithAnnotations() {
178     Variable variable = Variable.builder().setName("x").setType(TypeNode.BOOLEAN).build();
179     VariableExpr variableExpr =
180         VariableExpr.builder()
181             .setVariable(variable)
182             .setIsDecl(true)
183             .setAnnotations(
184                 Arrays.asList(
185                     AnnotationNode.withSuppressWarnings("all"),
186                     AnnotationNode.DEPRECATED,
187                     AnnotationNode.DEPRECATED))
188             .build();
189     assertThat(variableExpr.variable()).isEqualTo(variable);
190     assertThat(variableExpr.type()).isEqualTo(TypeNode.VOID);
191     assertThat(variableExpr.isDecl()).isTrue();
192     assertThat(variableExpr.annotations())
193         .containsExactly(AnnotationNode.withSuppressWarnings("all"), AnnotationNode.DEPRECATED);
194   }
195 
196   @Test
invalidVariableExpr_templatedArgInMethodHasNonStringNonTypeNodeObject()197   public void invalidVariableExpr_templatedArgInMethodHasNonStringNonTypeNodeObject() {
198     Variable variable =
199         Variable.builder()
200             .setName("x")
201             .setType(TypeNode.withReference(ConcreteReference.withClazz(HashMap.class)))
202             .build();
203     assertThrows(
204         IllegalStateException.class,
205         () ->
206             VariableExpr.builder()
207                 .setVariable(variable)
208                 .setTemplateObjects(Arrays.asList("RequestT", new Integer(123), TypeNode.STRING))
209                 .build());
210   }
211 
212   @Test
invalidVariableExpr_badTemplateName()213   public void invalidVariableExpr_badTemplateName() {
214     Variable variable = Variable.builder().setName("x").setType(TypeNode.STRING_ARRAY).build();
215     assertThrows(
216         IdentifierNode.InvalidIdentifierException.class,
217         () ->
218             VariableExpr.builder()
219                 .setVariable(variable)
220                 .setTemplateObjects(Arrays.asList("RequestT", "123T"))
221                 .build());
222   }
223 
224   @Test
invalidVariableExpr_referencePrimitiveType()225   public void invalidVariableExpr_referencePrimitiveType() {
226     Variable variable = Variable.builder().setName("x").setType(TypeNode.INT).build();
227     VariableExpr variableExpr = VariableExpr.builder().setVariable(variable).build();
228 
229     Variable subVariable = Variable.builder().setName("length").setType(TypeNode.INT).build();
230     assertThrows(
231         IllegalStateException.class,
232         () ->
233             VariableExpr.builder()
234                 .setVariable(subVariable)
235                 .setExprReferenceExpr(variableExpr)
236                 .build());
237   }
238 
239   @Test
invalidVariableExpr_referenceAndDecl()240   public void invalidVariableExpr_referenceAndDecl() {
241     Variable variable = Variable.builder().setName("x").setType(TypeNode.STRING_ARRAY).build();
242     VariableExpr variableExpr = VariableExpr.builder().setVariable(variable).build();
243 
244     Variable subVariable = Variable.builder().setName("length").setType(TypeNode.INT).build();
245     assertThrows(
246         IllegalStateException.class,
247         () ->
248             VariableExpr.builder()
249                 .setVariable(subVariable)
250                 .setIsDecl(true)
251                 .setExprReferenceExpr(variableExpr)
252                 .build());
253   }
254 
255   @Test
invalidVariableExpr_exprAndStaticReference()256   public void invalidVariableExpr_exprAndStaticReference() {
257     Variable refVariable = Variable.builder().setName("x").setType(TypeNode.STRING_ARRAY).build();
258     assertThrows(
259         IllegalStateException.class,
260         () ->
261             VariableExpr.builder()
262                 .setVariable(Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build())
263                 .setExprReferenceExpr(VariableExpr.withVariable(refVariable))
264                 .setStaticReferenceType(TypeNode.INT_OBJECT)
265                 .build());
266   }
267 
268   @Test
invalidVariableExpr_primitiveStaticReference()269   public void invalidVariableExpr_primitiveStaticReference() {
270     assertThrows(
271         IllegalStateException.class,
272         () ->
273             VariableExpr.builder()
274                 .setVariable(Variable.builder().setType(TypeNode.INT).setName("MAX_VALUE").build())
275                 .setStaticReferenceType(TypeNode.INT)
276                 .build());
277   }
278 
279   @Test
invalidVariableExpr_standaloneClassField()280   public void invalidVariableExpr_standaloneClassField() {
281     assertThrows(
282         IllegalStateException.class,
283         () ->
284             VariableExpr.builder()
285                 .setVariable(
286                     Variable.builder()
287                         .setType(TypeNode.withReference(ConcreteReference.withClazz(Class.class)))
288                         .setName("class")
289                         .build())
290                 .build());
291   }
292 
293   @Test
invalidVariableExpr_classFieldOnPrimitiveType()294   public void invalidVariableExpr_classFieldOnPrimitiveType() {
295     assertThrows(
296         IllegalStateException.class,
297         () ->
298             VariableExpr.builder()
299                 .setVariable(
300                     Variable.builder()
301                         .setType(TypeNode.withReference(ConcreteReference.withClazz(Class.class)))
302                         .setName("class")
303                         .build())
304                 .setExprReferenceExpr(
305                     MethodInvocationExpr.builder()
306                         .setMethodName("foobar")
307                         .setReturnType(TypeNode.INT)
308                         .build())
309                 .build());
310   }
311 
312   @Test
invalidVariableExpr_annotationNoDeclaration()313   public void invalidVariableExpr_annotationNoDeclaration() {
314     Variable variable = Variable.builder().setName("x").setType(TypeNode.BOOLEAN).build();
315     VariableExpr.Builder variableExprBuilder =
316         VariableExpr.builder()
317             .setVariable(variable)
318             .setIsDecl(false)
319             .setAnnotations(Arrays.asList(AnnotationNode.DEPRECATED));
320     assertThrows(IllegalStateException.class, () -> variableExprBuilder.build());
321   }
322 }
323