Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4272dbc

Browse files
authored
feat: support non-slash resnames in tests and resname helper classes (#450)
1 parent 4313d14 commit 4272dbc

File tree

8 files changed

+849
-41
lines changed

8 files changed

+849
-41
lines changed

src/main/java/com/google/api/generator/gapic/composer/ResourceNameTokenizer.java

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import com.google.api.pathtemplate.PathTemplate;
1818
import com.google.common.base.Preconditions;
1919
import java.util.ArrayList;
20-
import java.util.Arrays;
2120
import java.util.List;
2221
import java.util.Set;
2322
import java.util.stream.Collectors;
@@ -31,50 +30,51 @@ public class ResourceNameTokenizer {
3130
private static final String EQUALS_WILDCARD = "=*";
3231
private static final String EQUALS_PATH_WILDCARD = "=**";
3332

34-
static List<List<String>> parseTokenHierarchy(List<String> patterns) {
35-
List<String> nonSlashSepStrings = Arrays.asList("}_{", "}-{", "}.{", "}~{");
33+
private static final String NON_SLASH_SEP_REGEX = "\\}(_|\\-|\\.|~)\\{";
3634

35+
static List<List<String>> parseTokenHierarchy(List<String> patterns) {
3736
List<List<String>> tokenHierachies = new ArrayList<>();
3837
for (String pattern : patterns) {
3938
List<String> hierarchy = new ArrayList<>();
4039
Set<String> vars = PathTemplate.create(pattern).vars();
41-
String[] patternTokens = pattern.split(SLASH);
42-
for (String patternToken : patternTokens) {
43-
if (patternToken.startsWith(LEFT_BRACE) && patternToken.endsWith(RIGHT_BRACE)) {
44-
String processedPatternToken =
45-
// Replacement order matters - ensure the first is not a subcomponent of the second.
46-
patternToken.replace(EQUALS_PATH_WILDCARD, EMPTY).replace(EQUALS_WILDCARD, EMPTY);
40+
String[] rawPatternTokens = pattern.split(SLASH);
41+
List<String> patternTokens = new ArrayList<>();
4742

48-
// Handle non-slash separators.
49-
if (nonSlashSepStrings.stream().anyMatch(s -> patternToken.contains(s))) {
50-
for (String str : nonSlashSepStrings) {
51-
processedPatternToken = processedPatternToken.replace(str, "_");
52-
}
53-
} else {
54-
final int processedPatternTokenLength = processedPatternToken.length();
55-
// Handles wildcards.
56-
List<String> candidateVars =
57-
vars.stream()
58-
// Check that the token size is within ~3 of the var, to avoid mismatching on
59-
// variables with same-named subcomponents.
60-
// Otherwise, "customer_client_link" will match with "customer".
61-
.filter(
62-
v ->
63-
patternToken.contains(v)
64-
// Accounting for braces.
65-
&& processedPatternTokenLength - v.length() < 3)
66-
.collect(Collectors.toList());
67-
Preconditions.checkState(
68-
!candidateVars.isEmpty(),
69-
String.format(
70-
"No variable candidates found for token %s in pattern %s",
71-
processedPatternToken, pattern));
72-
processedPatternToken = candidateVars.get(0);
43+
// Process variables.
44+
for (String rawPatternToken : rawPatternTokens) {
45+
if (!rawPatternToken.startsWith(LEFT_BRACE) || !rawPatternToken.endsWith(RIGHT_BRACE)) {
46+
continue;
47+
}
48+
// Add any non-slash separated tokens in the order that they're seen.
49+
for (String subToken : rawPatternToken.split(NON_SLASH_SEP_REGEX)) {
50+
String processedSubToken =
51+
subToken.replace(LEFT_BRACE, EMPTY).replace(RIGHT_BRACE, EMPTY);
52+
if (!patternTokens.contains(processedSubToken)) {
53+
patternTokens.add(processedSubToken);
7354
}
74-
hierarchy.add(
75-
processedPatternToken.replace(LEFT_BRACE, EMPTY).replace(RIGHT_BRACE, EMPTY));
7655
}
7756
}
57+
58+
for (String patternToken : patternTokens) {
59+
// Handle wildcards.
60+
final String processedPatternToken =
61+
// Replacement order matters - ensure the first is not a subcomponent of the second.
62+
patternToken.replace(EQUALS_PATH_WILDCARD, EMPTY).replace(EQUALS_WILDCARD, EMPTY);
63+
64+
List<String> candidateVars =
65+
vars.stream()
66+
// Check that the token matches the variable exactly, to avoid mismatching on
67+
// variables with same-named subcomponents.
68+
// Otherwise, "customer_client_link" will match with "customer".
69+
.filter(v -> processedPatternToken.equals(v))
70+
.collect(Collectors.toList());
71+
Preconditions.checkState(
72+
!candidateVars.isEmpty(),
73+
String.format(
74+
"No variable candidates found for token %s in pattern %s among variables %s",
75+
processedPatternToken, pattern, vars));
76+
hierarchy.add(processedPatternToken);
77+
}
7878
tokenHierachies.add(hierarchy);
7979
}
8080
return tokenHierachies;

src/test/java/com/google/api/generator/gapic/composer/ResourceNameHelperClassComposerTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,33 @@ public void generateResourceNameClass_testingSessionOnePattern() {
187187
Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "SessionName.golden");
188188
Assert.assertCodeEquals(goldenFilePath, visitor.write());
189189
}
190+
191+
@Test
192+
public void generateResourceNameClass_testingBlueprintPatternWithNonSlashSeparator() {
193+
FileDescriptor testingFileDescriptor = TestingOuterClass.getDescriptor();
194+
ServiceDescriptor testingService = testingFileDescriptor.getServices().get(0);
195+
assertEquals(testingService.getName(), "Testing");
196+
197+
Map<String, Message> messageTypes = Parser.parseMessages(testingFileDescriptor);
198+
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(testingFileDescriptor);
199+
Set<ResourceName> outputResourceNames = new HashSet<>();
200+
List<Service> services =
201+
Parser.parseService(
202+
testingFileDescriptor,
203+
messageTypes,
204+
resourceNames,
205+
Optional.empty(),
206+
outputResourceNames);
207+
208+
ResourceName testResname = resourceNames.get("showcase.googleapis.com/Test");
209+
assertThat(outputResourceNames).contains(testResname);
210+
211+
GapicClass clazz = ResourceNameHelperClassComposer.instance().generate(testResname);
212+
213+
JavaWriterVisitor visitor = new JavaWriterVisitor();
214+
clazz.classDefinition().accept(visitor);
215+
Utils.saveCodegenToFile(this.getClass(), "TestName.golden", visitor.write());
216+
Path goldenFilePath = Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "TestName.golden");
217+
Assert.assertCodeEquals(goldenFilePath, visitor.write());
218+
}
190219
}

src/test/java/com/google/api/generator/gapic/composer/ResourceNameTokenizerTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,12 @@ public void parseTokenHierarchy_singletonCollectionAndNonSlashSeparators() {
101101

102102
List<List<String>> tokenHierarchies = ResourceNameTokenizer.parseTokenHierarchy(patterns);
103103
assertEquals(6, tokenHierarchies.size());
104-
assertThat(tokenHierarchies.get(0)).containsExactly("user", "legacy_user_blurb");
104+
assertThat(tokenHierarchies.get(0)).containsExactly("user", "legacy_user", "blurb");
105105
assertThat(tokenHierarchies.get(1)).containsExactly("user", "blurb");
106106
assertThat(tokenHierarchies.get(2)).containsExactly("room", "blurb");
107-
assertThat(tokenHierarchies.get(3)).containsExactly("user", "legacy_document_blurb");
108-
assertThat(tokenHierarchies.get(4)).containsExactly("user", "legacy_book_blurb");
109-
assertThat(tokenHierarchies.get(5)).containsExactly("room", "legacy_room_blurb");
107+
assertThat(tokenHierarchies.get(3)).containsExactly("user", "legacy_document", "blurb");
108+
assertThat(tokenHierarchies.get(4)).containsExactly("user", "legacy_book", "blurb");
109+
assertThat(tokenHierarchies.get(5)).containsExactly("room", "legacy_room", "blurb");
110110
}
111111

112112
@Test

src/test/java/com/google/api/generator/gapic/composer/ServiceClientTestClassComposerTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.google.protobuf.Descriptors.ServiceDescriptor;
3333
import com.google.pubsub.v1.PubsubProto;
3434
import com.google.showcase.v1beta1.EchoOuterClass;
35+
import com.google.showcase.v1beta1.TestingOuterClass;
3536
import google.cloud.CommonResources;
3637
import java.nio.file.Path;
3738
import java.nio.file.Paths;
@@ -71,6 +72,36 @@ public void generateClientTest_echoClient() {
7172
assertCodeEquals(goldenFilePath, visitor.write());
7273
}
7374

75+
@Test
76+
public void generateClientTest_testingClientResnameWithOnePatternWithNonSlashSepNames() {
77+
FileDescriptor testingFileDescriptor = TestingOuterClass.getDescriptor();
78+
ServiceDescriptor testingService = testingFileDescriptor.getServices().get(0);
79+
assertEquals(testingService.getName(), "Testing");
80+
81+
Map<String, Message> messageTypes = Parser.parseMessages(testingFileDescriptor);
82+
Map<String, ResourceName> resourceNames = Parser.parseResourceNames(testingFileDescriptor);
83+
Set<ResourceName> outputResourceNames = new HashSet<>();
84+
List<Service> services =
85+
Parser.parseService(
86+
testingFileDescriptor,
87+
messageTypes,
88+
resourceNames,
89+
Optional.empty(),
90+
outputResourceNames);
91+
92+
Service testingProtoService = services.get(0);
93+
GapicClass clazz =
94+
ServiceClientTestClassComposer.instance()
95+
.generate(testingProtoService, resourceNames, messageTypes);
96+
97+
JavaWriterVisitor visitor = new JavaWriterVisitor();
98+
clazz.classDefinition().accept(visitor);
99+
Utils.saveCodegenToFile(this.getClass(), "TestingClientTest.golden", visitor.write());
100+
Path goldenFilePath =
101+
Paths.get(ComposerConstants.GOLDENFILES_DIRECTORY, "TestingClientTest.golden");
102+
assertCodeEquals(goldenFilePath, visitor.write());
103+
}
104+
74105
@Test
75106
public void generateClientTest_pubSubPublisherClient() {
76107
FileDescriptor serviceFileDescriptor = PubsubProto.getDescriptor();

src/test/java/com/google/api/generator/gapic/composer/goldens/GrpcTestingStub.golden

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ import com.google.showcase.v1beta1.CreateSessionRequest;
1717
import com.google.showcase.v1beta1.DeleteSessionRequest;
1818
import com.google.showcase.v1beta1.DeleteTestRequest;
1919
import com.google.showcase.v1beta1.GetSessionRequest;
20+
import com.google.showcase.v1beta1.GetTestRequest;
2021
import com.google.showcase.v1beta1.ListSessionsRequest;
2122
import com.google.showcase.v1beta1.ListSessionsResponse;
2223
import com.google.showcase.v1beta1.ListTestsRequest;
2324
import com.google.showcase.v1beta1.ListTestsResponse;
2425
import com.google.showcase.v1beta1.ReportSessionRequest;
2526
import com.google.showcase.v1beta1.ReportSessionResponse;
2627
import com.google.showcase.v1beta1.Session;
28+
import com.google.showcase.v1beta1.Test;
2729
import com.google.showcase.v1beta1.VerifyTestRequest;
2830
import com.google.showcase.v1beta1.VerifyTestResponse;
2931
import io.grpc.MethodDescriptor;
@@ -88,6 +90,14 @@ public class GrpcTestingStub extends TestingStub {
8890
ProtoUtils.marshaller(ReportSessionResponse.getDefaultInstance()))
8991
.build();
9092

93+
private static final MethodDescriptor<GetTestRequest, Test> getTestMethodDescriptor =
94+
MethodDescriptor.<GetTestRequest, Test>newBuilder()
95+
.setType(MethodDescriptor.MethodType.UNARY)
96+
.setFullMethodName("google.showcase.v1beta1.Testing/GetTest")
97+
.setRequestMarshaller(ProtoUtils.marshaller(GetTestRequest.getDefaultInstance()))
98+
.setResponseMarshaller(ProtoUtils.marshaller(Test.getDefaultInstance()))
99+
.build();
100+
91101
private static final MethodDescriptor<ListTestsRequest, ListTestsResponse>
92102
listTestsMethodDescriptor =
93103
MethodDescriptor.<ListTestsRequest, ListTestsResponse>newBuilder()
@@ -121,6 +131,7 @@ public class GrpcTestingStub extends TestingStub {
121131
listSessionsPagedCallable;
122132
private final UnaryCallable<DeleteSessionRequest, Empty> deleteSessionCallable;
123133
private final UnaryCallable<ReportSessionRequest, ReportSessionResponse> reportSessionCallable;
134+
private final UnaryCallable<GetTestRequest, Test> getTestCallable;
124135
private final UnaryCallable<ListTestsRequest, ListTestsResponse> listTestsCallable;
125136
private final UnaryCallable<ListTestsRequest, ListTestsPagedResponse> listTestsPagedCallable;
126137
private final UnaryCallable<DeleteTestRequest, Empty> deleteTestCallable;
@@ -204,6 +215,19 @@ public class GrpcTestingStub extends TestingStub {
204215
}
205216
})
206217
.build();
218+
GrpcCallSettings<GetTestRequest, Test> getTestTransportSettings =
219+
GrpcCallSettings.<GetTestRequest, Test>newBuilder()
220+
.setMethodDescriptor(getTestMethodDescriptor)
221+
.setParamsExtractor(
222+
new RequestParamsExtractor<GetTestRequest>() {
223+
@Override
224+
public Map<String, String> extract(GetTestRequest request) {
225+
ImmutableMap.Builder<String, String> params = ImmutableMap.builder();
226+
params.put("name", String.valueOf(request.getName()));
227+
return params.build();
228+
}
229+
})
230+
.build();
207231
GrpcCallSettings<ListTestsRequest, ListTestsResponse> listTestsTransportSettings =
208232
GrpcCallSettings.<ListTestsRequest, ListTestsResponse>newBuilder()
209233
.setMethodDescriptor(listTestsMethodDescriptor)
@@ -262,6 +286,9 @@ public class GrpcTestingStub extends TestingStub {
262286
this.reportSessionCallable =
263287
callableFactory.createUnaryCallable(
264288
reportSessionTransportSettings, settings.reportSessionSettings(), clientContext);
289+
this.getTestCallable =
290+
callableFactory.createUnaryCallable(
291+
getTestTransportSettings, settings.getTestSettings(), clientContext);
265292
this.listTestsCallable =
266293
callableFactory.createUnaryCallable(
267294
listTestsTransportSettings, settings.listTestsSettings(), clientContext);
@@ -307,6 +334,10 @@ public class GrpcTestingStub extends TestingStub {
307334
return reportSessionCallable;
308335
}
309336

337+
public UnaryCallable<GetTestRequest, Test> getTestCallable() {
338+
return getTestCallable;
339+
}
340+
310341
public UnaryCallable<ListTestsRequest, ListTestsResponse> listTestsCallable() {
311342
return listTestsCallable;
312343
}

0 commit comments

Comments
 (0)