• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.gapic.protoparser;
16 
17 import static org.junit.Assert.assertEquals;
18 import static org.junit.Assert.assertTrue;
19 
20 import com.google.api.generator.engine.ast.TypeNode;
21 import com.google.api.generator.engine.ast.VaporReference;
22 import com.google.api.generator.gapic.model.Field;
23 import com.google.api.generator.gapic.model.MethodArgument;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.function.BiFunction;
29 import java.util.function.Function;
30 import java.util.stream.Collectors;
31 import org.junit.Test;
32 
33 public class MethodSignatureParserTest {
34 
35   @Test
flattenMethodSignatures_basic()36   public void flattenMethodSignatures_basic() {
37     String fooName = "fooName";
38     TypeNode fooTypeOne =
39         TypeNode.withReference(
40             VaporReference.builder().setName("FooName").setPakkage("com.google.foobar").build());
41     TypeNode fooTypeTwo =
42         TypeNode.withReference(
43             VaporReference.builder().setName("FooTwoName").setPakkage("com.google.foobar").build());
44 
45     List<String> argumentNames = Arrays.asList(fooName);
46 
47     BiFunction<String, TypeNode, MethodArgument> methodArgFn =
48         (name, type) ->
49             MethodArgument.builder()
50                 .setName(name)
51                 .setType(type)
52                 .setField(Field.builder().setName(name).setType(type).build())
53                 .build();
54     List<MethodArgument> fooArgs =
55         Arrays.asList(TypeNode.STRING, fooTypeOne, fooTypeTwo).stream()
56             .map(t -> methodArgFn.apply(fooName, t))
57             .collect(Collectors.toList());
58     Map<String, List<MethodArgument>> argumentNameToOverloads = new HashMap<>();
59     argumentNameToOverloads.put(fooName, fooArgs);
60 
61     List<List<MethodArgument>> flattenedSignatures =
62         MethodSignatureParser.flattenMethodSignatureVariants(
63             argumentNames, argumentNameToOverloads);
64 
65     assertEquals(3, flattenedSignatures.size());
66 
67     assertTrue(containsTypes(flattenedSignatures, Arrays.asList(TypeNode.STRING)));
68     assertTrue(containsTypes(flattenedSignatures, Arrays.asList(fooTypeOne)));
69     assertTrue(containsTypes(flattenedSignatures, Arrays.asList(fooTypeTwo)));
70   }
71 
72   @Test
flattenMethodSignatures_oneToMany()73   public void flattenMethodSignatures_oneToMany() {
74     String fooName = "fooName";
75     String anInt = "anInt";
76 
77     TypeNode fooTypeOne =
78         TypeNode.withReference(
79             VaporReference.builder().setName("FooName").setPakkage("com.google.foobar").build());
80     TypeNode fooTypeTwo =
81         TypeNode.withReference(
82             VaporReference.builder().setName("FooTwoName").setPakkage("com.google.foobar").build());
83 
84     List<String> argumentNames = Arrays.asList(anInt, fooName);
85 
86     BiFunction<String, TypeNode, MethodArgument> methodArgFn =
87         (name, type) ->
88             MethodArgument.builder()
89                 .setName(name)
90                 .setType(type)
91                 .setField(Field.builder().setName(name).setType(type).build())
92                 .build();
93     List<MethodArgument> fooArgs =
94         Arrays.asList(TypeNode.STRING, fooTypeOne, fooTypeTwo).stream()
95             .map(t -> methodArgFn.apply(fooName, t))
96             .collect(Collectors.toList());
97     Map<String, List<MethodArgument>> argumentNameToOverloads = new HashMap<>();
98     argumentNameToOverloads.put(fooName, fooArgs);
99     argumentNameToOverloads.put(anInt, Arrays.asList(methodArgFn.apply(anInt, TypeNode.INT)));
100 
101     List<List<MethodArgument>> flattenedSignatures =
102         MethodSignatureParser.flattenMethodSignatureVariants(
103             argumentNames, argumentNameToOverloads);
104 
105     assertEquals(3, flattenedSignatures.size());
106 
107     assertTrue(containsTypes(flattenedSignatures, Arrays.asList(TypeNode.INT, TypeNode.STRING)));
108     assertTrue(containsTypes(flattenedSignatures, Arrays.asList(TypeNode.INT, fooTypeOne)));
109     assertTrue(containsTypes(flattenedSignatures, Arrays.asList(TypeNode.INT, fooTypeTwo)));
110   }
111 
112   @Test
flattenMethodSignatures_manyToOne()113   public void flattenMethodSignatures_manyToOne() {
114     String fooName = "fooName";
115     String anInt = "anInt";
116 
117     TypeNode fooTypeOne =
118         TypeNode.withReference(
119             VaporReference.builder().setName("FooName").setPakkage("com.google.foobar").build());
120     TypeNode fooTypeTwo =
121         TypeNode.withReference(
122             VaporReference.builder().setName("FooTwoName").setPakkage("com.google.foobar").build());
123 
124     List<String> argumentNames = Arrays.asList(fooName, anInt);
125 
126     BiFunction<String, TypeNode, MethodArgument> methodArgFn =
127         (name, type) ->
128             MethodArgument.builder()
129                 .setName(name)
130                 .setType(type)
131                 .setField(Field.builder().setName(name).setType(type).build())
132                 .build();
133     List<MethodArgument> fooArgs =
134         Arrays.asList(TypeNode.STRING, fooTypeOne, fooTypeTwo).stream()
135             .map(t -> methodArgFn.apply(fooName, t))
136             .collect(Collectors.toList());
137     Map<String, List<MethodArgument>> argumentNameToOverloads = new HashMap<>();
138     argumentNameToOverloads.put(fooName, fooArgs);
139     argumentNameToOverloads.put(anInt, Arrays.asList(methodArgFn.apply(anInt, TypeNode.INT)));
140 
141     List<List<MethodArgument>> flattenedSignatures =
142         MethodSignatureParser.flattenMethodSignatureVariants(
143             argumentNames, argumentNameToOverloads);
144 
145     assertEquals(3, flattenedSignatures.size());
146     assertTrue(containsTypes(flattenedSignatures, Arrays.asList(TypeNode.STRING, TypeNode.INT)));
147     assertTrue(containsTypes(flattenedSignatures, Arrays.asList(fooTypeOne, TypeNode.INT)));
148 
149     assertTrue(containsTypes(flattenedSignatures, Arrays.asList(fooTypeTwo, TypeNode.INT)));
150   }
151 
152   @Test
flattenMethodSignatures_manyToMany()153   public void flattenMethodSignatures_manyToMany() {
154     String fooName = "fooName";
155     String barName = "barName";
156     String anInt = "anInt";
157     String anotherInt = "anotherInt";
158 
159     TypeNode fooTypeOne =
160         TypeNode.withReference(
161             VaporReference.builder().setName("FooName").setPakkage("com.google.foobar").build());
162     TypeNode fooTypeTwo =
163         TypeNode.withReference(
164             VaporReference.builder().setName("FooTwoName").setPakkage("com.google.foobar").build());
165     TypeNode barTypeOne =
166         TypeNode.withReference(
167             VaporReference.builder().setName("BarName").setPakkage("com.google.foobar").build());
168     TypeNode barTypeTwo =
169         TypeNode.withReference(
170             VaporReference.builder().setName("BarTwoName").setPakkage("com.google.foobar").build());
171     TypeNode barTypeThree =
172         TypeNode.withReference(
173             VaporReference.builder().setName("BarCarName").setPakkage("com.google.foobar").build());
174 
175     List<String> argumentNames = Arrays.asList(fooName, anInt, barName, anotherInt);
176 
177     BiFunction<String, TypeNode, MethodArgument> methodArgFn =
178         (name, type) ->
179             MethodArgument.builder()
180                 .setName(name)
181                 .setType(type)
182                 .setField(Field.builder().setName(name).setType(type).build())
183                 .build();
184     List<MethodArgument> fooArgs =
185         Arrays.asList(TypeNode.STRING, fooTypeOne, fooTypeTwo).stream()
186             .map(t -> methodArgFn.apply(fooName, t))
187             .collect(Collectors.toList());
188     List<MethodArgument> barArgs =
189         Arrays.asList(TypeNode.STRING, barTypeOne, barTypeTwo, barTypeThree).stream()
190             .map(t -> methodArgFn.apply(barName, t))
191             .collect(Collectors.toList());
192     Map<String, List<MethodArgument>> argumentNameToOverloads = new HashMap<>();
193     argumentNameToOverloads.put(fooName, fooArgs);
194     argumentNameToOverloads.put(anInt, Arrays.asList(methodArgFn.apply(anInt, TypeNode.INT)));
195     argumentNameToOverloads.put(barName, barArgs);
196     argumentNameToOverloads.put(
197         anotherInt, Arrays.asList(methodArgFn.apply(anotherInt, TypeNode.INT)));
198 
199     List<List<MethodArgument>> flattenedSignatures =
200         MethodSignatureParser.flattenMethodSignatureVariants(
201             argumentNames, argumentNameToOverloads);
202 
203     assertEquals(12, flattenedSignatures.size());
204 
205     // Types 0 - 4: String, int, {String, BarName, BarTwoName, BarCarName}, int.
206     assertTrue(
207         containsTypes(
208             flattenedSignatures,
209             Arrays.asList(TypeNode.STRING, TypeNode.INT, TypeNode.STRING, TypeNode.INT)));
210     assertTrue(
211         containsTypes(
212             flattenedSignatures,
213             Arrays.asList(TypeNode.STRING, TypeNode.INT, barTypeOne, TypeNode.INT)));
214     assertTrue(
215         containsTypes(
216             flattenedSignatures,
217             Arrays.asList(TypeNode.STRING, TypeNode.INT, barTypeTwo, TypeNode.INT)));
218     assertTrue(
219         containsTypes(
220             flattenedSignatures,
221             Arrays.asList(TypeNode.STRING, TypeNode.INT, barTypeThree, TypeNode.INT)));
222 
223     // Types 5 - 8: FooName, int, {String, BarName, BarTwoName, BarCarName}, int.
224     assertTrue(
225         containsTypes(
226             flattenedSignatures,
227             Arrays.asList(fooTypeOne, TypeNode.INT, TypeNode.STRING, TypeNode.INT)));
228     assertTrue(
229         containsTypes(
230             flattenedSignatures,
231             Arrays.asList(fooTypeOne, TypeNode.INT, barTypeOne, TypeNode.INT)));
232     assertTrue(
233         containsTypes(
234             flattenedSignatures,
235             Arrays.asList(fooTypeOne, TypeNode.INT, barTypeTwo, TypeNode.INT)));
236     assertTrue(
237         containsTypes(
238             flattenedSignatures,
239             Arrays.asList(fooTypeOne, TypeNode.INT, barTypeThree, TypeNode.INT)));
240 
241     // Types 9 - 12: FooTwoName, int, {String, BarName, BarTwoName, BarCarName}, int.
242     assertTrue(
243         containsTypes(
244             flattenedSignatures,
245             Arrays.asList(fooTypeTwo, TypeNode.INT, TypeNode.STRING, TypeNode.INT)));
246     assertTrue(
247         containsTypes(
248             flattenedSignatures,
249             Arrays.asList(fooTypeTwo, TypeNode.INT, barTypeOne, TypeNode.INT)));
250     assertTrue(
251         containsTypes(
252             flattenedSignatures,
253             Arrays.asList(fooTypeTwo, TypeNode.INT, barTypeTwo, TypeNode.INT)));
254     assertTrue(
255         containsTypes(
256             flattenedSignatures,
257             Arrays.asList(fooTypeTwo, TypeNode.INT, barTypeThree, TypeNode.INT)));
258   }
259 
containsTypes( List<List<MethodArgument>> flattenedSignatures, List<TypeNode> types)260   private static boolean containsTypes(
261       List<List<MethodArgument>> flattenedSignatures, List<TypeNode> types) {
262     // Brute-force search. Feel free to improve this if you've got cycles ��.
263     Function<List<MethodArgument>, List<TypeNode>> typeExtractorFn =
264         methodArgs -> methodArgs.stream().map(m -> m.type()).collect(Collectors.toList());
265     for (List<MethodArgument> args : flattenedSignatures) {
266       if (typeExtractorFn.apply(args).equals(types)) {
267         return true;
268       }
269     }
270     return false;
271   }
272 }
273